diff options
Diffstat (limited to 'src/acl.c')
-rw-r--r-- | src/acl.c | 164 |
1 files changed, 121 insertions, 43 deletions
@@ -30,19 +30,27 @@ struct pies_sockaddr { unsigned netmask; int salen; struct sockaddr sa; }; +enum name_match + { + match_none, + match_user_name, + match_group_name + }; + struct acl_entry { grecs_locus_t locus; int allow; int authenticated; pies_acl_t acl; - struct grecs_list *groups; + enum name_match name_match; + char **names; struct grecs_list *sockaddrs; }; struct pies_acl { char *name; @@ -50,27 +58,75 @@ struct pies_acl struct grecs_list *list; }; /* 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); +} pies_acl_t pies_acl_create (const char *name, grecs_locus_t *locus) { pies_acl_t acl = xmalloc (sizeof (acl[0])); 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; } void pies_acl_free (pies_acl_t acl) { free (acl->name); + grecs_locus_free (&acl->locus); grecs_list_free (acl->list); free (acl); } static struct pies_sockaddr * create_acl_sockaddr (int family, int len) @@ -193,12 +249,18 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value) sptr->netmask = 0xfffffffful; } grecs_list_append (entry->sockaddrs, sptr); return 0; } +static void +sockaddr_free (void *p) +{ + free (p); +} + static int _parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv) { if (argc == 0) return 0; else if (argv[0]->type == GRECS_TYPE_LIST) @@ -220,12 +282,13 @@ _parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv) grecs_error (&entry->locus, 0, _("unexpected end of statement after `from'")); return 1; } entry->sockaddrs = grecs_list_create (); + entry->sockaddrs->free_entry = sockaddr_free; if (argv[0]->type == GRECS_TYPE_STRING) { if (_parse_sockaddr (entry, argv[0])) return 1; } else @@ -285,28 +348,44 @@ _parse_sub_acl (struct acl_entry *entry, size_t argc, grecs_value_t **argv) } static int _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) { argc--; argv++; if (argc == 0) { grecs_error (&entry->locus, 0, - _("expected group list, but found end of statement")); + _("expected identity list, but found end of statement")); return 1; } if (argv[0]->type == GRECS_TYPE_STRING) { - 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--; argv++; } return _parse_sub_acl (entry, argc, argv); } @@ -324,35 +403,36 @@ _parse_acl (struct acl_entry *entry, size_t argc, grecs_value_t **argv) int parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl, grecs_value_t *value) { struct acl_entry *entry = xzalloc (sizeof (*entry)); - 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); return 0; } #define ACL_TAG_NONE 0 #define ACL_TAG_IGNORE 1 @@ -477,18 +557,18 @@ deny_cb (enum grecs_callback_command cmd, parse_acl_line (locus, 0, acl, value); return 0; } 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"), grecs_type_string, GRECS_MULT, NULL, 0, allow_cb }, /* 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"), grecs_type_string, GRECS_MULT, NULL, 0, deny_cb }, { NULL } }; @@ -531,38 +611,36 @@ _check_sockaddr (struct pies_sockaddr *sptr, struct acl_input *input) } } return 0; } 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) { int result = 1; if (ent->authenticated) { - result = input->user != NULL; + result = input->identity != NULL; if (!result) return result; } - 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) return result; } result = pies_acl_check (ent->acl, input, 1); if (!result) @@ -643,13 +721,13 @@ acl_copy (void *a, void *b) memcpy (a, b, sizeof (struct pies_acl)); memset (b, 0, sizeof (struct pies_acl)); return 0; } static void -acl_free_entry (void *p) +acl_free (void *p) { pies_acl_free (p); } pies_acl_t pies_acl_install (pies_acl_t acl) @@ -661,13 +739,13 @@ pies_acl_install (pies_acl_t acl) { acl_table = grecs_symtab_create(sizeof (struct pies_acl), acl_hasher, acl_compare, acl_copy, NULL, - acl_free_entry); + acl_free); if (!acl_table) xalloc_die (); } ret = grecs_symtab_lookup_or_install (acl_table, acl, &install); |