diff options
Diffstat (limited to 'src/acl.c')
-rw-r--r-- | src/acl.c | 70 |
1 files changed, 66 insertions, 4 deletions
@@ -119,16 +119,19 @@ pies_acl_create (const char *name, grecs_locus_t *locus) 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); + if (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) { struct pies_sockaddr *p = grecs_zalloc (sizeof (*p)); @@ -249,12 +252,25 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value) sptr->netmask = 0xfffffffful; } grecs_list_append (entry->sockaddrs, sptr); return 0; } +static int +sockaddr_cmp (void const *a, void const *b) +{ + struct pies_sockaddr const *ap = a; + struct pies_sockaddr const *bp = b; + + if (ap->netmask != bp->netmask) + return 1; + if (ap->salen != bp->salen) + return 1; + return memcmp (&ap->sa, &bp->sa, ap->salen); +} + static void sockaddr_free (void *p) { free (p); } @@ -282,12 +298,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->cmp = sockaddr_cmp; entry->sockaddrs->free_entry = sockaddr_free; if (argv[0]->type == GRECS_TYPE_STRING) { if (_parse_sockaddr (entry, argv[0])) return 1; } @@ -430,13 +447,43 @@ parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl, grecs_error (locus, 0, _("unexpected list")); return 1; } grecs_list_append (acl->list, entry); return 0; } + +static int +acl_entry_cmp (void const *a, void const *b) +{ + struct acl_entry const *ap = a; + struct acl_entry const *bp = b; + size_t i; + + if (ap->allow != bp->allow) + return 1; + if (ap->authenticated != bp->authenticated) + return 1; + if (pies_acl_cmp (ap->acl, bp->acl)) + return 1; + if (ap->name_match != bp->name_match) + return 1; + if (ap->names && bp->names) + { + for (i = 0; ap->names[i]; i++) + if (!bp->names[i] || strcmp (ap->names[i], bp->names[i])) + return 1; + if (bp->names[i]) + return 1; + } + else if (ap->names || bp->names) + return 1; + + return grecs_list_compare (ap->sockaddrs, bp->sockaddrs); +} + #define ACL_TAG_NONE 0 #define ACL_TAG_IGNORE 1 #define ACL_TAG_OPTIONAL 2 #define ACL_TAG_REQUIRED 3 int @@ -489,12 +536,17 @@ _acl_common_section_parser (enum grecs_callback_command cmd, return 1; if (pacl) *pacl = acl; break; case grecs_callback_section_end: + acl = *pacl; + if (acl->list) + acl->list->cmp = acl_entry_cmp; + break; + case grecs_callback_set_value: break; } return 0; } @@ -772,6 +824,16 @@ pies_acl_lookup (const char *name) struct pies_acl samp; if (!acl_table) return NULL; samp.name = (char *) name; return grecs_symtab_lookup_or_install (acl_table, &samp, NULL); } + +int +pies_acl_cmp (struct pies_acl *a, struct pies_acl *b) +{ + if (!a) + return !!b; + else + return 1; + return grecs_list_compare (a->list, b->list); +} |