aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-12-16 14:58:07 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-12-16 14:58:07 +0200
commit6bb908898b833ec69c66e918de732af5bad68934 (patch)
treedd715a052f67849d38aedaa25eafa93241e938df /src
parent9cb7455b12462a3679ed5208540793d802570481 (diff)
downloadpies-6bb908898b833ec69c66e918de732af5bad68934.tar.gz
pies-6bb908898b833ec69c66e918de732af5bad68934.tar.bz2
Implement authentication on control socket.
* Makefile.am (SUBDIRS): Add src. * configure.ac: Check for crypt.h and PAM Build ident/Makefile * grecs: Update. * ident/Makefile.am: New file. * ident/ident.c: New file. * ident/ident.h: New file. * ident/identity.h: New file. * ident/pam.c: New file. * ident/provider.c: New file. * ident/system.c: New file. * lib/Makefile.am: Add arraymember.c * lib/arraymember.c: New file. * lib/libpies.h (is_array_member): New proto. * src/Makefile.am (LDADD): Add libident.a and @PAM_LIBS@ * src/acl.c (acl_entry): Remove groups. Add new members: names and name_match. (pies_acl_create): Deep copy the locus. Set free_entry function for the list. (pies_acl_free): Free locus. (_parse_from): Set free_entry function for the list. (_parse_group): Parse the "user" construct. (parse_acl_line): Deep copy the locus. Allow for null value. (acl_keywords): Update docstrings. (_acl_check): Rewrite identity checks. * src/acl.h (acl_input)<user,groups>: Remove. <identity>: New member. (pies_acl_free): New proto. * src/ctl.c (identity): New global. (cmdtab): New command: auth (ctlio) <addr,addrlen>: New members. (ctlio_create): Start from authenticated state only if no identity_providers are configured. (cmd_auth): New function. (cmd_help): Print only commands that are available in the current state. (ctl_accept): Initialize io->addr and io->addrlen. * src/inetd-bi.c: Change call to check_acl * src/pies.c: Include identity.h (control_keywords): New statement "identity-acl" (pies_keywords): New statement "identity-provider" (config_init): Register identity mechanisms. (config_parse): New function. (config_help): Print help on identity-provider statements. (main): Use config_parse to parse grecs-style configurations. * src/pies.h: Include identity.h (check_acl): Change argument list. All callers changed. (control): Remove acl. Add conn_acl and id_acl instead. * src/progman.c (check_acl): Change argument list. Take identity as the 3rd argument.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/acl.c164
-rw-r--r--src/acl.h4
-rw-r--r--src/ctl.c68
-rw-r--r--src/inetd-bi.c2
-rw-r--r--src/pies.c63
-rw-r--r--src/pies.h7
-rw-r--r--src/progman.c10
8 files changed, 248 insertions, 75 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 04634c7..ab4546f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,2 +62,3 @@ cmdline.h: cmdline.opt
LDADD = \
+ ../ident/libident.a\
../lib/libpies.a\
@@ -65,3 +66,4 @@ LDADD = \
../gnu/libgnu.a\
- $(MF_PROCTITLE_LIBS)
+ $(MF_PROCTITLE_LIBS)\
+ @PAM_LIBS@
@@ -71,2 +73,3 @@ AM_CPPFLAGS=\
-I$(top_srcdir)/lib\
+ -I$(top_srcdir)/ident\
-I$(top_srcdir)/gnu\
diff --git a/src/acl.c b/src/acl.c
index 301f56f..fb6adfb 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -35,2 +35,9 @@ struct pies_sockaddr
+enum name_match
+ {
+ match_none,
+ match_user_name,
+ match_group_name
+ };
+
struct acl_entry
@@ -41,3 +48,4 @@ struct acl_entry
pies_acl_t acl;
- struct grecs_list *groups;
+ enum name_match name_match;
+ char **names;
struct grecs_list *sockaddrs;
@@ -55,2 +63,48 @@ struct pies_acl
/* ACL creation */
+void
+grecs_locus_point_copy (struct grecs_locus_point *dst,
+ struct grecs_locus_point *src)
+{
+ dst->file = grecs_strdup (src->file);
+ dst->line = src->line;
+ dst->col = src->col;
+}
+
+void
+grecs_locus_copy (struct grecs_locus *dst, struct grecs_locus *src)
+{
+ grecs_locus_point_copy (&dst->beg, &src->beg);
+ grecs_locus_point_copy (&dst->end, &src->end);
+}
+
+void
+grecs_locus_point_free (struct grecs_locus_point *p)
+{
+ grecs_free (p->file);
+}
+
+void
+grecs_locus_free (struct grecs_locus *loc)
+{
+ grecs_locus_point_free (&loc->beg);
+ grecs_locus_point_free (&loc->end);
+}
+
+static void
+acl_free_entry (void *p)
+{
+ struct acl_entry *ent = p;
+ pies_acl_free (ent->acl);
+ grecs_locus_free (&ent->locus);
+ grecs_list_free (ent->sockaddrs);
+ if (ent->names)
+ {
+ size_t i;
+
+ for (i = 0; ent->names[i]; i++)
+ free (ent->names[i]);
+ free (ent->names);
+ }
+ free (ent);
+}
@@ -61,4 +115,5 @@ pies_acl_create (const char *name, grecs_locus_t *locus)
acl->name = name ? xstrdup (name) : NULL;
- acl->locus = *locus;
+ grecs_locus_copy (&acl->locus, locus);
acl->list = grecs_list_create ();
+ acl->list->free_entry = acl_free_entry;
return acl;
@@ -70,2 +125,3 @@ pies_acl_free (pies_acl_t acl)
free (acl->name);
+ grecs_locus_free (&acl->locus);
grecs_list_free (acl->list);
@@ -198,2 +254,8 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value)
+static void
+sockaddr_free (void *p)
+{
+ free (p);
+}
+
static int
@@ -225,2 +287,3 @@ _parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
entry->sockaddrs = grecs_list_create ();
+ entry->sockaddrs->free_entry = sockaddr_free;
if (argv[0]->type == GRECS_TYPE_STRING)
@@ -290,2 +353,9 @@ _parse_group (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
if (strcmp (argv[0]->v.string, "group") == 0)
+ entry->name_match = match_group_name;
+ else if (strcmp (argv[0]->v.string, "user") == 0)
+ entry->name_match = match_user_name;
+ else
+ entry->name_match = match_none;
+
+ if (entry->name_match != match_none)
{
@@ -296,3 +366,3 @@ _parse_group (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
grecs_error (&entry->locus, 0,
- _("expected group list, but found end of statement"));
+ _("expected identity list, but found end of statement"));
return 1;
@@ -301,7 +371,16 @@ _parse_group (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
{
- entry->groups = grecs_list_create ();
- grecs_list_append (entry->groups, xstrdup (argv[0]->v.string));
+ entry->names = xcalloc (2, sizeof (entry->names[0]));
+ entry->names[0] = xstrdup (argv[0]->v.string);
+ entry->names[1] = NULL;
}
else
- entry->groups = argv[0]->v.list;
+ {
+ size_t i;
+ struct grecs_list_entry *ep;
+ entry->names = xcalloc (argv[0]->v.list->count + 1,
+ sizeof (entry->names[0]));
+ for (i = 0, ep = argv[0]->v.list->head; ep; ep = ep->next, ++i)
+ entry->names[i] = xstrdup (ep->data);
+ entry->names[i] = NULL;
+ }
argc--;
@@ -329,25 +408,26 @@ parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl,
- entry->locus = *locus;
+ grecs_locus_copy (&entry->locus, locus);
entry->allow = allow;
- switch (value->type)
- {
- case GRECS_TYPE_STRING:
- if (_parse_token (entry, value))
- {
- grecs_error (&entry->locus, 0, _("unknown word `%s'"),
- value->v.string);
+ if (value)
+ switch (value->type)
+ {
+ case GRECS_TYPE_STRING:
+ if (_parse_token (entry, value))
+ {
+ grecs_error (&entry->locus, 0, _("unknown word `%s'"),
+ value->v.string);
+ return 1;
+ }
+ break;
+
+ case GRECS_TYPE_ARRAY:
+ if (_parse_acl (entry, value->v.arg.c, value->v.arg.v))
return 1;
- }
- break;
-
- case GRECS_TYPE_ARRAY:
- if (_parse_acl (entry, value->v.arg.c, value->v.arg.v))
+ break;
+
+ case GRECS_TYPE_LIST:
+ grecs_error (locus, 0, _("unexpected list"));
return 1;
- break;
-
- case GRECS_TYPE_LIST:
- grecs_error (locus, 0, _("unexpected list"));
- return 1;
- }
+ }
grecs_list_append (acl->list, entry);
@@ -482,3 +562,3 @@ struct grecs_keyword acl_keywords[] = {
/* TRANSLATORS: only words within angle brackets are translatable */
- { "allow", N_("[all|authenticated|group <grp: list>] [from <addr: list>]"),
+ { "allow", N_("[all|authenticated|user <usr: list>|group <grp: list>] [from <addr: list>]"),
N_("Allow access"),
@@ -487,3 +567,3 @@ struct grecs_keyword acl_keywords[] = {
/* TRANSLATORS: only words within angle brackets are translatable */
- { "deny", N_("[all|authenticated|group <grp: list>] [from <addr: list>]"),
+ { "deny", N_("[all|authenticated|user <usr: list>|group <grp: list>] [from <addr: list>]"),
N_("Deny access"),
@@ -536,11 +616,2 @@ _check_sockaddr (struct pies_sockaddr *sptr, struct acl_input *input)
static int
-match_group (const char **groups, const char *arg)
-{
- for (; *groups; groups++)
- if (strcmp (*groups, arg) == 0)
- return 1;
- return 0;
-}
-
-static int
_acl_check (struct acl_entry *ent, struct acl_input *input)
@@ -551,3 +622,3 @@ _acl_check (struct acl_entry *ent, struct acl_input *input)
{
- result = input->user != NULL;
+ result = input->identity != NULL;
if (!result)
@@ -556,8 +627,15 @@ _acl_check (struct acl_entry *ent, struct acl_input *input)
- if (ent->groups)
+ switch (ent->name_match)
{
- struct grecs_list_entry *ep;
+ case match_none:
+ break;
- for (ep = ent->groups->head; result && ep; ep = ep->next)
- result = match_group (input->groups, ep->data);
+ case match_user_name:
+ result = pies_identity_is_user (input->identity, ent->names);
+ if (!result)
+ return result;
+ break;
+
+ case match_group_name:
+ result = pies_identity_is_group_member (input->identity, ent->names);
if (!result)
@@ -648,3 +726,3 @@ acl_copy (void *a, void *b)
static void
-acl_free_entry (void *p)
+acl_free (void *p)
{
@@ -666,3 +744,3 @@ pies_acl_install (pies_acl_t acl)
NULL,
- acl_free_entry);
+ acl_free);
if (!acl_table)
diff --git a/src/acl.h b/src/acl.h
index dc09d7b..757104d 100644
--- a/src/acl.h
+++ b/src/acl.h
@@ -23,4 +23,3 @@ struct acl_input
socklen_t addrlen;
- const char *user;
- const char **groups;
+ pies_identity_t identity;
};
@@ -28,2 +27,3 @@ struct acl_input
pies_acl_t pies_acl_create (const char *name, grecs_locus_t *locus);
+void pies_acl_free (pies_acl_t acl);
int pies_acl_check (pies_acl_t acl, struct acl_input *input, int result);
diff --git a/src/ctl.c b/src/ctl.c
index f9f2d76..20c16e1 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -19,2 +19,3 @@
#include "xvasprintf.h"
+#include "identity.h"
@@ -24,2 +25,4 @@ struct control control;
+pies_identity_t identity;
+
@@ -109,2 +112,3 @@ struct ctlio;
+static void cmd_auth (struct ctlio *, size_t, char **);
static void cmd_quit (struct ctlio *, size_t, char **);
@@ -131,2 +135,4 @@ struct ctlio_command
static struct ctlio_command cmdtab[] = {
+ { "auth", "authenticate",
+ CTL_INITIAL_STATE, 3, 3, cmd_auth },
{ "noop", "no operation",
@@ -169,2 +175,4 @@ struct ctlio
{
+ union pies_sockaddr_storage addr;
+ socklen_t addrlen;
int state;
@@ -183,3 +191,4 @@ ctlio_create (void)
io = xmalloc (sizeof (*io));
- io->state = CTL_AUTHENTICATED_STATE; //FIXME CTL_INITIAL_STATE;
+ io->state = identity_provider_list
+ ? CTL_INITIAL_STATE : CTL_AUTHENTICATED_STATE;
io->action = ACTION_CONT;
@@ -310,3 +319,2 @@ ctlio_initial_reply (struct ctlio *io)
ctlio_printf (io, "220 %s", instance);
- ctlio_printf (io, " <%s>", "foobarbaz");
//FIXME: auth mechanisms
@@ -316,2 +324,47 @@ ctlio_initial_reply (struct ctlio *io)
static void
+cmd_auth (struct ctlio *io, size_t argc, char **argv)
+{
+ struct grecs_list_entry *ep;
+ pies_identity_t id = pies_identity_create (argv[1]);
+ int auth = 0;
+
+ for (ep = identity_provider_list->head; ep; ep = ep->next)
+ {
+ pies_identity_provider_t provider = ep->data;
+ char const *pname = pies_identity_provider_name (provider);
+
+ debug(1, ("trying %s...", pname));
+ if (pies_authenticate (provider, id, argv[2]) == 0)
+ {
+ if (check_acl (control.id_acl,
+ (struct sockaddr *)&io->addr, io->addrlen, id))
+ {
+ logmsg (LOG_AUTH, "%s authenticated via %s, but failed ACL check",
+ argv[1], pname);
+ auth = 0;
+ }
+ else
+ {
+ logmsg (LOG_AUTH, "%s authenticated via %s",
+ argv[1], pname);
+ auth = 1;
+ }
+ break;
+ }
+ }
+
+ if (auth)
+ {
+ ctlio_reply (io, "230", "authentication successful");
+ identity = id;
+ io->state = CTL_AUTHENTICATED_STATE;
+ }
+ else
+ {
+ pies_identity_destroy (id);
+ ctlio_reply (io, "531", "access denied");
+ }
+}
+
+static void
cmd_noop (struct ctlio *io, size_t argc, char **argv)
@@ -349,4 +402,7 @@ cmd_help (struct ctlio *io, size_t argc, char **argv)
{
- ctlio_printf (io, "%-9s%s", cp->verb, cp->descr);
- ctlio_eol (io);
+ if (cp->states & io->state)
+ {
+ ctlio_printf (io, "%-9s%s", cp->verb, cp->descr);
+ ctlio_eol (io);
+ }
}
@@ -1002,3 +1058,3 @@ ctl_accept (int socket, void *data)
- if (check_acl (control.acl, (struct sockaddr *)&addr, addrlen))
+ if (check_acl (control.conn_acl, (struct sockaddr *)&addr, addrlen, NULL))
{
@@ -1010,2 +1066,4 @@ ctl_accept (int socket, void *data)
io = ctlio_create ();
+ io->addr = addr;
+ io->addrlen = addrlen;
ctlio_initial_reply (io);
diff --git a/src/inetd-bi.c b/src/inetd-bi.c
index e472390..de9cfa0 100644
--- a/src/inetd-bi.c
+++ b/src/inetd-bi.c
@@ -359,3 +359,3 @@ tcpmux (int fd, struct component const *comp)
- if (check_acl (comp->acl, (struct sockaddr *) &sa, salen))
+ if (check_acl (comp->acl, (struct sockaddr *) &sa, salen, NULL))
{
diff --git a/src/pies.c b/src/pies.c
index 696e9f0..9f5f174 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -20,2 +20,3 @@
#include "meta1lex.h"
+#include "identity.h"
@@ -1543,5 +1544,11 @@ struct grecs_keyword control_keywords[] = {
N_("name: string"),
- N_("Set ACL."),
+ N_("Set connection ACL."),
+ grecs_type_section, GRECS_DFLT,
+ &control.conn_acl, 0,
+ acl_section_parser, NULL, acl_keywords},
+ {"identity-acl",
+ N_("name: string"),
+ N_("Set identity ACL."),
grecs_type_section, GRECS_DFLT,
- &control.acl, 0,
+ &control.id_acl, 0,
acl_section_parser, NULL, acl_keywords},
@@ -1762,2 +1769,4 @@ struct grecs_keyword pies_keywords[] = {
},
+ { "identity-provider", "name: string", "Configure identity provider",
+ grecs_type_section, GRECS_INAC | GRECS_HIDDEN },
{NULL}
@@ -1777,2 +1786,35 @@ config_init ()
}
+ pies_identity_mechanism_register (&system_identity_mechanism);
+#ifdef WITH_PAM
+ pies_identity_mechanism_register (&pam_identity_mechanism);
+#endif
+}
+
+static void
+config_error ()
+{
+ if (!init_process)
+ exit (EX_CONFIG);
+}
+
+void
+config_parse (char const *name)
+{
+ struct grecs_node *node;
+ struct grecs_node *tree = grecs_parse (name);
+ if (!tree)
+ config_error ();
+
+ for (node = tree; node; node = node->next)
+ {
+ node = grecs_find_node (node, "identity-provider");
+ if (!node)
+ break;
+ pies_config_provider (node);
+ }
+
+ if (grecs_tree_process (tree, pies_keywords))
+ config_error ();
+
+ grecs_tree_free (tree);
}
@@ -1788,2 +1830,3 @@ config_help ()
grecs_print_statement_array (pies_keywords, 1, 0, stdout);
+ pies_config_identity_mechanisms_help ();
}
@@ -2243,9 +2286,2 @@ set_state_file_names (const char *base)
-static void
-config_error ()
-{
- if (!init_process)
- exit (EX_CONFIG);
-}
-
int
@@ -2369,9 +2405,4 @@ main (int argc, char **argv)
case CONF_PIES:
- {
- struct grecs_node *tree = grecs_parse (file->name);
- if (!tree || grecs_tree_process (tree, pies_keywords))
- config_error ();
- grecs_tree_free (tree);
- break;
- }
+ config_parse (file->name);
+ break;
diff --git a/src/pies.h b/src/pies.h
index 82ffddb..3919703 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -60,2 +60,3 @@
+#include "identity.h"
#include "acl.h"
@@ -340,3 +341,4 @@ void fd_report (int fd, const char *msg);
-int check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen);
+int check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
+ pies_identity_t identity);
@@ -563,3 +565,4 @@ struct control
struct pies_url *url;
- pies_acl_t acl;
+ pies_acl_t conn_acl;
+ pies_acl_t id_acl;
unsigned int idle_timeout;
diff --git a/src/progman.c b/src/progman.c
index 12969ab..1ec5a8d 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -1303,3 +1303,4 @@ prog_start (struct prog *prog)
int
-check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen)
+check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
+ pies_identity_t identity)
{
@@ -1313,4 +1314,3 @@ check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen)
input.addrlen = salen;
- input.user = NULL;
- input.groups = NULL;
+ input.identity = identity;
@@ -1376,4 +1376,4 @@ _prog_accept (struct prog *p)
- if (check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen)
- || check_acl (pies_acl, (struct sockaddr *)&addr, addrlen))
+ if (check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen, NULL)
+ || check_acl (pies_acl, (struct sockaddr *)&addr, addrlen, NULL))
{

Return to:

Send suggestions and report system problems to the System administrator.