aboutsummaryrefslogtreecommitdiff
path: root/src/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/acl.c')
-rw-r--r--src/acl.c206
1 files changed, 112 insertions, 94 deletions
diff --git a/src/acl.c b/src/acl.c
index a0ee85e..dc459f5 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -1,8 +1,8 @@
/* This file is part of GNU Pies
- Copyright (C) 2009, 2010 Sergey Poznyakoff
+ Copyright (C) 2009, 2010, 2011 Sergey Poznyakoff
GNU Pies is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
@@ -22,13 +22,12 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <hash.h>
struct pies_sockaddr
{
unsigned netmask;
int salen;
struct sockaddr sa;
@@ -37,41 +36,45 @@ struct pies_sockaddr
struct acl_entry
{
grecs_locus_t locus;
int allow;
int authenticated;
pies_acl_t acl;
- gl_list_t groups;
- gl_list_t sockaddrs;
+ struct grecs_list *groups;
+ struct grecs_list *sockaddrs;
};
struct pies_acl
{
char *name;
grecs_locus_t locus;
- gl_list_t list;
+ struct grecs_list *list;
};
/* ACL creation */
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;
- acl->list = gl_list_create_empty(&gl_linked_list_implementation,
- NULL,
- NULL,
- NULL,
- false);
+ acl->list = grecs_list_create ();
return acl;
}
+void
+pies_acl_free (pies_acl_t acl)
+{
+ free (acl->name);
+ grecs_list_free (acl->list);
+ free (acl);
+}
+
static struct pies_sockaddr *
create_acl_sockaddr (int family, int len)
{
struct pies_sockaddr *p = xzalloc (sizeof (*p));
p->salen = len;
p->sa.sa_family = family;
@@ -186,60 +189,55 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value)
return 1;
}
}
else
sptr->netmask = 0xfffffffful;
}
- gl_list_add_last (entry->sockaddrs, sptr);
+ grecs_list_append (entry->sockaddrs, sptr);
return 0;
}
static int
-_parse_from (struct acl_entry *entry, size_t argc, const grecs_value_t *argv)
+_parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
{
if (argc == 0)
return 0;
- else if (argv->type == GRECS_TYPE_LIST)
+ else if (argv[0]->type == GRECS_TYPE_LIST)
{
grecs_error (&entry->locus, 0, _("expected `from', but found list"));
return 1;
}
- else if (strcmp (argv->v.string, "from"))
+ else if (strcmp (argv[0]->v.string, "from"))
{
grecs_error (&entry->locus, 0, _("expected `from', but found `%s'"),
- argv->v.string);
+ argv[0]->v.string);
return 1;
}
argc--;
argv++;
if (argc == 0)
{
grecs_error (&entry->locus, 0,
_("unexpected end of statement after `from'"));
return 1;
}
- entry->sockaddrs = gl_list_create_empty(&gl_linked_list_implementation,
- NULL,
- NULL,
- NULL,
- false);
- if (argv->type == GRECS_TYPE_STRING)
+ entry->sockaddrs = grecs_list_create ();
+ if (argv[0]->type == GRECS_TYPE_STRING)
{
- if (_parse_sockaddr (entry, argv))
+ if (_parse_sockaddr (entry, argv[0]))
return 1;
}
else
{
- gl_list_iterator_t itr = gl_list_iterator (argv->v.list);
- const void *p;
int rc = 0;
- while (gl_list_iterator_next (&itr, &p, NULL))
- rc += _parse_sockaddr (entry, (const grecs_value_t*) p);
- gl_list_iterator_free (&itr);
+ struct grecs_list_entry *ep;
+
+ for (ep = argv[0]->v.list->head; ep; ep = ep->next)
+ rc += _parse_sockaddr (entry, (const grecs_value_t*) ep->data);
if (rc)
return rc;
}
if (argc - 1)
{
@@ -247,84 +245,80 @@ _parse_from (struct acl_entry *entry, size_t argc, const grecs_value_t *argv)
return 1;
}
return 0;
}
static int
-_parse_sub_acl (struct acl_entry *entry, size_t argc, grecs_value_t *argv)
+_parse_sub_acl (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
{
if (argc == 0)
return 0;
- if (strcmp (argv->v.string, "acl") == 0)
+ if (strcmp (argv[0]->v.string, "acl") == 0)
{
argc--;
argv++;
if (argc == 0)
{
grecs_error (&entry->locus, 0,
_("expected ACL name, but found end of statement"));
return 1;
}
- if (argv->type != GRECS_TYPE_STRING)
+ if (argv[0]->type != GRECS_TYPE_STRING)
{
grecs_error (&entry->locus, 0,
_("expected string, but found list"));
return 1;
}
- entry->acl = pies_acl_lookup (argv->v.string);
+ entry->acl = pies_acl_lookup (argv[0]->v.string);
if (!entry->acl)
{
grecs_error (&entry->locus, 0, _("ACL not defined: `%s'"),
- argv->v.string);
+ argv[0]->v.string);
return 1;
}
argc--;
argv++;
}
return _parse_from (entry, argc, argv);
}
static int
-_parse_group (struct acl_entry *entry, size_t argc, grecs_value_t * argv)
+_parse_group (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
{
- if (strcmp (argv->v.string, "group") == 0)
+ if (strcmp (argv[0]->v.string, "group") == 0)
{
argc--;
argv++;
if (argc == 0)
{
grecs_error (&entry->locus, 0,
_("expected group list, but found end of statement"));
return 1;
}
- if (argv->type == GRECS_TYPE_STRING)
+ if (argv[0]->type == GRECS_TYPE_STRING)
{
- entry->groups = gl_list_create_empty(&gl_linked_list_implementation,
- NULL,
- NULL,
- NULL,
- false);
- gl_list_add_last (entry->groups, (void *) argv->v.string);
+ entry->groups = grecs_list_create ();
+ grecs_list_append (entry->groups, xstrdup (argv[0]->v.string));
}
else
- entry->groups = argv->v.list;
+ entry->groups = argv[0]->v.list;
argc--;
argv++;
}
return _parse_sub_acl (entry, argc, argv);
}
static int
-_parse_acl (struct acl_entry *entry, size_t argc, grecs_value_t *argv)
+_parse_acl (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
{
- if (assert_grecs_value_type (&entry->locus, argv, GRECS_TYPE_STRING))
+ if (assert_grecs_value_type (&entry->locus, argv[0], GRECS_TYPE_STRING))
return 1;
- else if (_parse_token (entry, argv) == 0)
+ else if (_parse_token (entry, argv[0]) == 0)
return _parse_sub_acl (entry, argc - 1, argv + 1);
else
return _parse_group (entry, argc, argv);
}
int
@@ -353,13 +347,13 @@ parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl,
break;
case GRECS_TYPE_LIST:
grecs_error (locus, 0, _("unexpected list"));
return 1;
}
- gl_list_add_last (acl->list, entry);
+ grecs_list_append (acl->list, entry);
return 0;
}
#define ACL_TAG_NONE 0
#define ACL_TAG_IGNORE 1
#define ACL_TAG_OPTIONAL 2
@@ -370,13 +364,12 @@ _acl_common_section_parser (enum grecs_callback_command cmd,
grecs_locus_t *locus,
grecs_value_t *value,
pies_acl_t *pacl,
int flag)
{
pies_acl_t acl;
- grecs_locus_t defn_loc;
const char *tag = NULL;
int has_value = 0;
switch (cmd)
{
case grecs_callback_section_begin:
@@ -409,21 +402,14 @@ _acl_common_section_parser (enum grecs_callback_command cmd,
else if (flag == ACL_TAG_REQUIRED)
{
grecs_error (locus, 0, _("missing ACL name"));
return 1;
}
acl = pies_acl_create (tag, locus);
- if (tag && pies_acl_install (acl, &defn_loc))
- {
- grecs_error (locus, 0,
- _("redefinition of ACL %s"),
- value->v.string);
- grecs_error (&defn_loc, 0,
- _("location of the previous definition"));
- return 1;
- }
+ if (tag && (acl = pies_acl_install (acl)) == NULL)
+ return 1;
if (pacl)
*pacl = acl;
break;
case grecs_callback_section_end:
case grecs_callback_set_value:
@@ -567,47 +553,45 @@ _acl_check (struct acl_entry *ent, struct acl_input *input)
if (!result)
return result;
}
if (ent->groups)
{
- const void *p;
- gl_list_iterator_t itr = gl_list_iterator (ent->groups);
- while (result && gl_list_iterator_next (&itr, &p, NULL))
- result = match_group (input->groups, p);
- gl_list_iterator_free (&itr);
+ struct grecs_list_entry *ep;
+
+ for (ep = ent->groups->head; result && ep; ep = ep->next)
+ result = match_group (input->groups, ep->data);
if (!result)
return result;
}
result = pies_acl_check (ent->acl, input, 1);
if (!result)
return result;
if (ent->sockaddrs)
{
- const void *p;
- gl_list_iterator_t itr = gl_list_iterator (ent->sockaddrs);
+ struct grecs_list_entry *ep;
+
result = 0;
- while (gl_list_iterator_next (&itr, &p, NULL))
+ for (ep = ent->sockaddrs->head; ep; ep = ep->next)
{
- result = _check_sockaddr ((struct pies_sockaddr *)p, input);
+ result = _check_sockaddr ((struct pies_sockaddr *)ep->data, input);
if (result)
break;
}
- gl_list_iterator_free (&itr);
}
return result;
}
static int
_acl_check_cb (struct acl_entry *ent, struct acl_input *input, int *pres)
{
int result = _acl_check (ent, input);
- debug (1, ("%s:%d: %s", ent->locus.file, ent->locus.line,
+ debug (1, ("%s:%d: %s", ent->locus.beg.file, ent->locus.beg.line,
/* TRANSLATORS: `MATCHES' is the verb `match' in 2nd person.
E.g., in French: CONCORD AVEC */
result ? _("MATCHES") : _("does not match")));
if (result)
{
@@ -619,67 +603,101 @@ _acl_check_cb (struct acl_entry *ent, struct acl_input *input, int *pres)
int
pies_acl_check (pies_acl_t acl, struct acl_input *input, int result)
{
if (acl)
{
- const void *p;
- gl_list_iterator_t itr = gl_list_iterator (acl->list);
- while (gl_list_iterator_next (&itr, &p, NULL)
- && !_acl_check_cb ((struct acl_entry *)p, input, &result))
- ;
- gl_list_iterator_free (&itr);
+ struct grecs_list_entry *ep;
+
+ for (ep = acl->list->head; ep; ep = ep->next)
+ if (_acl_check_cb ((struct acl_entry *)ep->data, input, &result))
+ break;
}
return result;
}
/* Hash table */
-static Hash_table *acl_table;
+static struct grecs_symtab *acl_table;
/* Calculate the hash of a string. */
-static size_t
-acl_hasher (void const *data, size_t n_buckets)
+static unsigned
+acl_hasher (void *data, unsigned long n_buckets)
{
const struct pies_acl *p = data;
- return hash_string (p->name, n_buckets);
+ return grecs_hash_string (p->name, n_buckets);
}
/* Compare two strings for equality. */
-static bool
+static int
acl_compare (void const *data1, void const *data2)
{
const struct pies_acl *p1 = data1;
const struct pies_acl *p2 = data2;
- return strcasecmp (p1->name, p2->name) == 0;
+ return strcasecmp (p1->name, p2->name);
}
-int
-pies_acl_install (pies_acl_t acl, grecs_locus_t * locus)
+static int
+acl_copy (void *a, void *b)
+{
+ const struct pies_acl *pb = b;
+
+ memcpy (a, b, sizeof (struct pies_acl));
+ memset (b, 0, sizeof (struct pies_acl));
+ return 0;
+}
+
+static void
+acl_free_entry (void *p)
+{
+ pies_acl_free (p);
+}
+
+pies_acl_t
+pies_acl_install (pies_acl_t acl)
{
pies_acl_t ret;
- if (!((acl_table
- || (acl_table = hash_initialize (0, 0,
- acl_hasher,
- acl_compare, 0)))
- && (ret = hash_insert (acl_table, acl))))
- xalloc_die ();
-
- if (ret != acl)
+ int install = 1;
+
+ if (!acl_table)
{
- if (locus)
- *locus = ret->locus;
- return 1;
+ acl_table = grecs_symtab_create(sizeof (struct pies_acl),
+ acl_hasher,
+ acl_compare,
+ acl_copy,
+ NULL,
+ acl_free_entry);
+ if (!acl_table)
+ xalloc_die ();
}
- return 0;
+
+ ret = grecs_symtab_lookup_or_install (acl_table, acl, &install);
+
+ if (!ret)
+ {
+ logmsg (LOG_ERR, _("cannot install acl: %s"), strerror (errno));
+ exit (1);
+ }
+
+ if (!install)
+ {
+ grecs_error (&acl->locus, 0,
+ _("redefinition of ACL %s"),
+ ret->name);
+ grecs_error (&ret->locus, 0,
+ _("location of the previous definition"));
+ ret = NULL;
+ }
+ pies_acl_free (acl);
+ return ret;
}
pies_acl_t
pies_acl_lookup (const char *name)
{
struct pies_acl samp;
if (!acl_table)
return NULL;
samp.name = (char *) name;
- return hash_lookup (acl_table, &samp);
+ return grecs_symtab_lookup_or_install (acl_table, &samp, NULL);
}

Return to:

Send suggestions and report system problems to the System administrator.