aboutsummaryrefslogtreecommitdiff
path: root/src/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/acl.c')
-rw-r--r--src/acl.c70
1 files changed, 66 insertions, 4 deletions
diff --git a/src/acl.c b/src/acl.c
index a96eb77..e7523f5 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -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);
+}

Return to:

Send suggestions and report system problems to the System administrator.