aboutsummaryrefslogtreecommitdiff
path: root/src/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/acl.c')
-rw-r--r--src/acl.c128
1 files changed, 103 insertions, 25 deletions
diff --git a/src/acl.c b/src/acl.c
index 301f56f..fb6adfb 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -33,13 +33,21 @@ struct pies_sockaddr
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;
};
@@ -53,14 +61,61 @@ 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);
+}
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;
}
@@ -68,6 +123,7 @@ void
pies_acl_free (pies_acl_t acl)
{
free (acl->name);
+ grecs_locus_free (&acl->locus);
grecs_list_free (acl->list);
free (acl);
}
@@ -196,6 +252,12 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value)
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)
{
@@ -223,6 +285,7 @@ _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)
{
if (_parse_sockaddr (entry, argv[0]))
@@ -288,22 +351,38 @@ 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++;
}
@@ -327,9 +406,10 @@ parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl,
{
struct acl_entry *entry = xzalloc (sizeof (*entry));
- entry->locus = *locus;
+ grecs_locus_copy (&entry->locus, locus);
entry->allow = allow;
+ if (value)
switch (value->type)
{
case GRECS_TYPE_STRING:
@@ -480,12 +560,12 @@ deny_cb (enum grecs_callback_command cmd,
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 },
@@ -534,32 +614,30 @@ _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)
{
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;
+
+ case match_user_name:
+ result = pies_identity_is_user (input->identity, ent->names);
+ if (!result)
+ return result;
+ break;
- for (ep = ent->groups->head; result && ep; ep = ep->next)
- result = match_group (input->groups, ep->data);
+ case match_group_name:
+ result = pies_identity_is_group_member (input->identity, ent->names);
if (!result)
return result;
}
@@ -646,7 +724,7 @@ acl_copy (void *a, void *b)
}
static void
-acl_free_entry (void *p)
+acl_free (void *p)
{
pies_acl_free (p);
}
@@ -664,7 +742,7 @@ pies_acl_install (pies_acl_t acl)
acl_compare,
acl_copy,
NULL,
- acl_free_entry);
+ acl_free);
if (!acl_table)
xalloc_die ();
}

Return to:

Send suggestions and report system problems to the System administrator.