diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-12-07 20:54:15 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-12-07 20:54:15 +0000 |
commit | 727b3c755d6db784cedc1d334d4a70ce72543d0d (patch) | |
tree | 120a7864b5dd2a28845c2fee7c9b9f57fc0130d3 | |
parent | 2412484207346815cb2a1a7ef3c3aa8e6e093fba (diff) | |
download | mailutils-727b3c755d6db784cedc1d334d4a70ce72543d0d.tar.gz mailutils-727b3c755d6db784cedc1d334d4a70ce72543d0d.tar.bz2 |
* NEWS, TODO: Update.
* examples/Makefile.am: Add aclck
* examples/aclck.c: New file. Test program for ACLs.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add acl.h,
kwd.h and vartab.h.
* include/mailutils/acl.h: New file. ACL declarations.
* include/mailutils/kwd.h: New file. Declarations for simple
string to token conversion.
* include/mailutils/vartab.h: New file. Declarations of functions
for variable expansion.
* include/mailutils/mailutils.h: Include acl.h, kwd.h and
vartab.h.
* include/mailutils/types.hin: Define mu_vartab_t
* mailbox/Makefile.am (libmailutils_la_SOURCES): Add acl.c, kwd.c,
and vartab.c.
* mailbox/acl.c: New file.
* mailbox/kwd.c: New file.
* mailbox/vartab.c: New file.
* mailbox/cfg_parser.y (parse_cidr): Fix typo.
* mailbox/list.c: Fix indentation.
* mailbox/mailbox.c (_create_mailbox): Fix type of level.
* mailbox/syslog.c: Use mu_kwd_* functions.
-rw-r--r-- | ChangeLog | 27 | ||||
-rw-r--r-- | NEWS | 40 | ||||
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | examples/Makefile.am | 1 | ||||
-rw-r--r-- | examples/aclck.c | 243 | ||||
-rw-r--r-- | include/mailutils/Makefile.am | 3 | ||||
-rw-r--r-- | include/mailutils/acl.h | 72 | ||||
-rw-r--r-- | include/mailutils/kwd.h | 37 | ||||
-rw-r--r-- | include/mailutils/mailutils.h | 3 | ||||
-rw-r--r-- | include/mailutils/types.hin | 1 | ||||
-rw-r--r-- | include/mailutils/vartab.h | 36 | ||||
-rw-r--r-- | mailbox/Makefile.am | 3 | ||||
-rw-r--r-- | mailbox/acl.c | 665 | ||||
-rw-r--r-- | mailbox/cfg_parser.y | 7 | ||||
-rw-r--r-- | mailbox/kwd.c | 92 | ||||
-rw-r--r-- | mailbox/list.c | 3 | ||||
-rw-r--r-- | mailbox/mailbox.c | 2 | ||||
-rw-r--r-- | mailbox/syslog.c | 51 | ||||
-rw-r--r-- | mailbox/vartab.c | 317 |
19 files changed, 1562 insertions, 46 deletions
@@ -1,3 +1,30 @@ +2007-12-07 Sergey Poznyakoff <gray@gnu.org.ua> + + * NEWS, TODO: Update. + * examples/Makefile.am: Add aclck + * examples/aclck.c: New file. Test program for ACLs. + * include/mailutils/Makefile.am (pkginclude_HEADERS): Add acl.h, + kwd.h and vartab.h. + * include/mailutils/acl.h: New file. ACL declarations. + * include/mailutils/kwd.h: New file. Declarations for simple + string to token conversion. + * include/mailutils/vartab.h: New file. Declarations of functions + for variable expansion. + * include/mailutils/mailutils.h: Include acl.h, kwd.h and + vartab.h. + * include/mailutils/types.hin: Define mu_vartab_t + + * mailbox/Makefile.am (libmailutils_la_SOURCES): Add acl.c, kwd.c, + and vartab.c. + * mailbox/acl.c: New file. + * mailbox/kwd.c: New file. + * mailbox/vartab.c: New file. + + * mailbox/cfg_parser.y (parse_cidr): Fix typo. + * mailbox/list.c: Fix indentation. + * mailbox/mailbox.c (_create_mailbox): Fix type of level. + * mailbox/syslog.c: Use mu_kwd_* functions. + 2007-12-05 Sergey Poznyakoff <gray@gnu.org.ua> * configure.ac: Add TCP wrappers support. @@ -1,4 +1,4 @@ -GNU mailutils NEWS -- history of user-visible changes. 2007-12-05 +GNU mailutils NEWS -- history of user-visible changes. 2007-12-07 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. See the end of file for copying conditions. @@ -151,12 +151,12 @@ functions: New type of event, MU_EVT_MESSAGE_APPEND, is signalled whenever a new message is appended to the mailbox. -* Quick access to a message +** Quick access to a message A set of functions are provided for so-called `quick access' to mail messages. FIXME: describe it. -* New `aget' and `sget' accessors for mu_url_t +** New `aget' and `sget' accessors for mu_url_t The following new accessors are provided: @@ -181,20 +181,48 @@ extern int mu_url_aget_path (const mu_url_t, char **); extern int mu_url_sget_query (const mu_url_t, const char **); extern int mu_url_aget_query (const mu_url_t, char **); -* Incompatible change in mu_url_get_.* return value +** ACL + +A set of functions implements general-purpose access control lists. +They are declared in the header file mailutils/acl.h. Currently, +these functions support IPv4 and UNIX address families. Support for +more address families, in particular IPv6, will be added in future. +The following actions can be defined in ACLs: + + 1. mu_acl_accept - Accept connection. + 2. mu_acl_deny - Deny connection. + 3. mu_acl_log - Issue a log message, using mu_diag.* + diagnostics functions. + 4. mu_acl_exec - Execute an external program. + 5. mu_acl_ifexec - Execute an external program and accept or + deny connection depending on its exit code. + +** KWD + +A set of functions is provided for translating string values to +integer tokens and vice-versa using simple translation tables. +These functions are declared in the header file mailutils/kwd.h. + +** Vartab + +A set of functions is provided for performing variable expansion in +strings. These functions are declared in the header file +mailutils/vartab.h. + +** Incompatible change in mu_url_get_.* return value Any mu_url_get_.* accessors return MU_ERR_ENOENT if the corresponding field is not present in the object. Previous versions in that case returned 0 and stored empty string in the output buffer. -* Fixed parsing of URLs similar to file:///a/b. +** Fixed parsing of URLs similar to file:///a/b. It is parsed as an absolute file name `/a/b'. Previous versions incorrectly understood such an URL as `a/b' (relative file name). -* Remove v0.6 compatibility layer. +** Remove v0.6 compatibility layer. Version 1.2: @@ -1,9 +1,12 @@ -GNU mailutils TODO list. 2007-11-30 +GNU mailutils TODO list. 2007-12-07 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. * Documentation +* Review the code and use mu_vartab_* and mu_kwd_* functions where +necessary. + * mailbox ** Generic search interface diff --git a/examples/Makefile.am b/examples/Makefile.am index 86872611d..144224cda 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -20,6 +20,7 @@ SUBDIRS = config cpp scheme noinst_PROGRAMS = \ + aclck\ addr\ argcv\ base64\ diff --git a/examples/aclck.c b/examples/aclck.c new file mode 100644 index 000000000..68502a47f --- /dev/null +++ b/examples/aclck.c @@ -0,0 +1,243 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999, 2000, 2001, 2002, 2005, + 2007 Free Software Foundation, Inc. + + GNU Mailutils 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. + + GNU Mailutils is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Mailutils; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA */ + +#include <mailutils/mailutils.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> +#include <arpa/inet.h> + +#include <stdlib.h> +#include <string.h> + +struct sockaddr *target_sa; +int target_salen; +mu_acl_t acl; + +struct sockaddr * +parse_address (int *psalen, char *str) +{ + struct sockaddr_in in; + struct sockaddr *sa; + + in.sin_family = AF_INET; + if (inet_aton (str, &in.sin_addr) == 0) + { + mu_error ("Invalid IPv4: %s", str); + exit (1); + } + in.sin_port = 0; + *psalen = sizeof (in); + sa = malloc (*psalen); + if (!sa) + { + mu_error ("%s", mu_strerror (errno)); + exit (1); + } + + memcpy (sa, &in, sizeof (in)); + return sa; +} + +void +read_rules (FILE *fp) +{ + char buf[512]; + int line = 0; + int argc = 0; + char **argv; + int rc; + + rc = mu_acl_create (&acl); + if (rc) + { + mu_error ("cannot create acl: %s", mu_strerror (rc)); + exit (1); + } + + while (fgets (buf, sizeof buf, fp)) + { + unsigned long netmask; + int salen; + struct sockaddr *sa; + mu_acl_action_t action; + void *data = NULL; + char *p; + + int len = strlen (buf); + if (len == 0) + continue; + if (buf[len-1] != '\n') + { + mu_error ("%d: line too long", line); + continue; + } + buf[len-1] = 0; + line++; + if (buf[0] == '#') + continue; + + if (argc) + mu_argcv_free (argc, argv); + + mu_argcv_get (buf, " \t", "#", &argc, &argv); + if (argc < 2) + { + mu_error ("%d: invalid input", line); + continue; + } + + p = strchr (argv[1], '/'); + if (p) + { + char *q; + unsigned netlen; + + *p++ = 0; + netlen = strtoul (p, &q, 10); + if (*q == 0) + { + if (netlen == 0) + netmask = 0; + else + { + netmask = 0xfffffffful >> (32 - netlen); + netmask <<= (32 - netlen); + netmask = htonl (netmask); + } + } + else if (*q == '.') + { + struct in_addr addr; + + if (inet_aton (p, &addr) == 0) + { + mu_error ("%d: invalid netmask", line); + continue; + } + netmask = addr.s_addr; + } + else + { + mu_error ("%d: invalid netmask", line); + continue; + } + } + else + netmask = 0xfffffffful; + + sa = parse_address (&salen, argv[1]); + + /* accept addr + deny addr + log addr [rest ...] + exec addr [rest ...] + execif addr rest ....] + */ + if (mu_acl_string_to_action (argv[0], &action)) + { + mu_error ("%d: invalid command", line); + continue; + } + + switch (action) + { + case mu_acl_accept: + case mu_acl_deny: + break; + + case mu_acl_log: + case mu_acl_exec: + case mu_acl_ifexec: + data = strdup (argv[2]); + } + + rc = mu_acl_append (acl, action, data, sa, salen, netmask); + if (rc) + mu_error ("%d: cannot append acl entry: %s", line, + mu_strerror (rc)); + } +} + +int +main (int argc, char **argv) +{ + int rc; + FILE *file = NULL; + mu_acl_result_t result; + + mu_set_program_name (argv[0]); + while ((rc = getopt (argc, argv, "Dd:a:f:")) != EOF) + { + switch (rc) + { + case 'D': + mu_debug_line_info = 1; + break; + + case 'd': + mu_global_debug_from_string (optarg, "command line"); + break; + + case 'a': + target_sa = parse_address (&target_salen, optarg); + break; + + case 'f': + file = fopen (optarg, "r"); + if (file == 0) + { + mu_error ("cannot open file %s: %s", optarg, + mu_strerror (errno)); + exit (1); + } + break; + + default: + exit (1); + } + } + + argv += optind; + argc -= optind; + + read_rules (file ? file : stdin); + rc = mu_acl_check_sockaddr (acl, target_sa, target_salen, &result); + if (rc) + { + mu_error ("mu_acl_check_sockaddr failed: %s", mu_strerror (rc)); + exit (1); + } + switch (result) + { + case mu_acl_result_undefined: + puts ("undefined"); + break; + + case mu_acl_result_accept: + puts ("accept"); + break; + + case mu_acl_result_deny: + puts ("deny"); + break; + } + exit (0); +} diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am index d14b9e9ad..f81ef693a 100644 --- a/include/mailutils/Makefile.am +++ b/include/mailutils/Makefile.am @@ -32,6 +32,7 @@ DISTCLEANFILES = types.h pkginclude_DATA = types.h pkginclude_HEADERS = \ + acl.h\ address.h\ argcv.h\ assoc.h\ @@ -52,6 +53,7 @@ pkginclude_HEADERS = \ guile.h\ header.h\ iterator.h\ + kwd.h\ ldap.h\ libargp.h\ libcfg.h\ @@ -84,6 +86,7 @@ pkginclude_HEADERS = \ sql.h\ tls.h\ url.h\ + vartab.h\ version.h nobase_pkginclude_HEADERS = \ diff --git a/include/mailutils/acl.h b/include/mailutils/acl.h new file mode 100644 index 000000000..ab136ee85 --- /dev/null +++ b/include/mailutils/acl.h @@ -0,0 +1,72 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2007 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _MAILUTILS_ACL_H +#define _MAILUTILS_ACL_H + +#include <mailutils/types.h> +#include <mailutils/iterator.h> + +typedef struct _mu_acl *mu_acl_t; + +typedef enum mu_acl_action + { + mu_acl_accept, + mu_acl_deny, + mu_acl_log, + mu_acl_exec, + mu_acl_ifexec + } +mu_acl_action_t; + +typedef enum mu_acl_result + { + mu_acl_result_undefined, + mu_acl_result_accept, + mu_acl_result_deny + } +mu_acl_result_t; + +struct sockaddr; +struct in_addr; + +int mu_acl_create (mu_acl_t *acl); +int mu_acl_destroy (mu_acl_t *acl); +int mu_acl_count (mu_acl_t acl, size_t *pcount); +int mu_acl_get_debug (mu_acl_t acl, mu_debug_t *pdebug); +int mu_acl_set_debug (mu_acl_t acl, mu_debug_t debug); +int mu_acl_get_iterator (mu_acl_t acl, mu_iterator_t *pitr); +int mu_acl_append (mu_acl_t acl, mu_acl_action_t act, void *data, + struct sockaddr *sa, int salen, + unsigned long netmask); +int mu_acl_prepend (mu_acl_t acl, mu_acl_action_t act, void *data, + struct sockaddr *sa, int salen, unsigned long netmask); +int mu_acl_insert (mu_acl_t acl, size_t pos, int before, + mu_acl_action_t act, void *data, + struct sockaddr *sa, int salen, unsigned long netmask); + +int mu_acl_check_ipv4 (mu_acl_t acl, unsigned int addr, mu_acl_result_t *pres); +int mu_acl_check_inaddr (mu_acl_t acl, struct in_addr *inp, + mu_acl_result_t *pres); +int mu_acl_check_sockaddr (mu_acl_t acl, struct sockaddr *sa, int salen, + mu_acl_result_t *pres); +int mu_acl_check_fd (mu_acl_t acl, int fd, mu_acl_result_t *pres); + +int mu_acl_action_to_string (mu_acl_action_t act, const char **pstr); +int mu_acl_string_to_action (const char *str, mu_acl_action_t *pres); + +#endif diff --git a/include/mailutils/kwd.h b/include/mailutils/kwd.h new file mode 100644 index 000000000..da7036dd9 --- /dev/null +++ b/include/mailutils/kwd.h @@ -0,0 +1,37 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2007 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _MAILUTILS_KWD_H +#define _MAILUTILS_KWD_H + +typedef struct mu_kwd mu_kwd_t; + +struct mu_kwd +{ + char *name; + int tok; +}; + +int mu_kwd_xlat_name (mu_kwd_t *kwtab, const char *str, int *pres); +int mu_kwd_xlat_name_ci (mu_kwd_t *kwtab, const char *str, int *pres); +int mu_kwd_xlat_name_len (mu_kwd_t *kwtab, const char *str, size_t len, + int *pres); +int mu_kwd_xlat_name_len_ci (mu_kwd_t *kwtab, const char *str, size_t len, + int *pres); +int mu_kwd_xlat_tok (mu_kwd_t *kwtab, int tok, const char **pres); + +#endif diff --git a/include/mailutils/mailutils.h b/include/mailutils/mailutils.h index 770149327..4c68710ac 100644 --- a/include/mailutils/mailutils.h +++ b/include/mailutils/mailutils.h @@ -17,6 +17,7 @@ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <mailutils/acl.h> #include <mailutils/address.h> #include <mailutils/argcv.h> #include <mailutils/attribute.h> @@ -30,6 +31,7 @@ #include <mailutils/folder.h> #include <mailutils/header.h> #include <mailutils/iterator.h> +#include <mailutils/kwd.h> #include <mailutils/libsieve.h> #include <mailutils/list.h> #include <mailutils/locker.h> @@ -54,6 +56,7 @@ #include <mailutils/url.h> #include <mailutils/gocs.h> #include <mailutils/version.h> +#include <mailutils/vartab.h> #ifdef MU_COMPAT # error "Version 0.6 is no longer supported. Please, update your program." diff --git a/include/mailutils/types.hin b/include/mailutils/types.hin index b2a26ce7f..b0c1558a2 100644 --- a/include/mailutils/types.hin +++ b/include/mailutils/types.hin @@ -96,6 +96,7 @@ typedef struct _mu_record *mu_record_t; typedef struct _mu_stream *mu_stream_t; typedef struct _mu_ticket *mu_ticket_t; typedef struct _mu_url *mu_url_t; +typedef struct _mu_vartab *mu_vartab_t; typedef struct _mu_wicket *mu_wicket_t; typedef void *mu_transport_t; typedef struct _mu_assoc *mu_assoc_t; diff --git a/include/mailutils/vartab.h b/include/mailutils/vartab.h new file mode 100644 index 000000000..6a9b82805 --- /dev/null +++ b/include/mailutils/vartab.h @@ -0,0 +1,36 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2007 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _MAILUTILS_VARTAB_H +#define _MAILUTILS_VARTAB_H + +#include <mailutils/types.h> + +typedef int (*mu_var_expansion_fp) (const char *name, void *data, char **p); +typedef void (*mu_var_free_fp) (void *data, char *value); + +int mu_vartab_create (mu_vartab_t *pvar); +int mu_vartab_destroy (mu_vartab_t *pvar); +int mu_vartab_define (mu_vartab_t var, const char *name, const char *value, + int isstatic); +int mu_vartab_define_exp (mu_vartab_t var, const char *name, + mu_var_expansion_fp fun, mu_var_free_fp free, + void *data); +int mu_vartab_count (mu_vartab_t vt, size_t *pcount); +int mu_vartab_getvar (mu_vartab_t vt, const char *name, const char **pvalue); +int mu_vartab_expand (mu_vartab_t vt, const char *str, char **pres); +#endif diff --git a/mailbox/Makefile.am b/mailbox/Makefile.am index c7035ece0..5ab84c884 100644 --- a/mailbox/Makefile.am +++ b/mailbox/Makefile.am @@ -36,6 +36,7 @@ AM_CPPFLAGS = \ EXTRA_DIST = errors muerrno.cin parsedate.y fgetpwent.c cfg_parser.y cfg_parser.h inttostr.c inttostr.h libmailutils_la_SOURCES = \ + acl.c\ address.c\ amd.c\ argcv.c\ @@ -65,6 +66,7 @@ libmailutils_la_SOURCES = \ gocs.c\ header.c\ iterator.c\ + kwd.c\ list.c\ locale.c\ locker.c\ @@ -102,6 +104,7 @@ libmailutils_la_SOURCES = \ tcp.c\ ticket.c\ url.c\ + vartab.c\ version.c\ wicket.c\ imaxtostr.c offtostr.c umaxtostr.c intprops.h diff --git a/mailbox/acl.c b/mailbox/acl.c new file mode 100644 index 000000000..0b1dcfb6c --- /dev/null +++ b/mailbox/acl.c @@ -0,0 +1,665 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2007 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; If not, see + <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> +#include <arpa/inet.h> + +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <mailutils/acl.h> +#include <mailutils/argcv.h> +#include <mailutils/list.h> +#include <mailutils/debug.h> +#include <mailutils/error.h> +#include <mailutils/errno.h> +#include <mailutils/kwd.h> +#include <mailutils/vartab.h> +#include <mu_umaxtostr.h> + +struct _mu_acl_entry +{ + mu_acl_action_t action; + void *arg; + unsigned netmask; + int salen; + struct sockaddr sa[1]; +}; + +struct _mu_acl +{ + mu_debug_t debug; + mu_list_t aclist; +}; + + +static void +_destroy_acl_entry (void *item) +{ + struct _mu_acl_entry *p = item; + free (p); + /* FIXME: free arg? */ +} + +static size_t +mu_acl_entry_size (int salen) +{ + return sizeof (struct _mu_acl_entry) + salen - sizeof (struct sockaddr); +} + +static int +prepare_sa (struct sockaddr *sa) +{ + switch (sa->sa_family) + { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + sin->sin_addr.s_addr = ntohl (sin->sin_addr.s_addr); + break; + } + + case AF_UNIX: + break; + + default: + return 1; + } + return 0; +} + +int +mu_acl_entry_create (struct _mu_acl_entry **pent, + mu_acl_action_t action, void *data, + struct sockaddr *sa, int salen, unsigned long netmask) +{ + struct _mu_acl_entry *p = malloc (mu_acl_entry_size (salen)); + if (!p) + return EINVAL; + + p->action = action; + p->arg = data; + p->netmask = ntohl (netmask); + p->salen = salen; + memcpy (p->sa, sa, salen); + if (prepare_sa (p->sa)) + { + free (p); + return EINVAL; + } + *pent = p; + return 0; +} + + +int +mu_acl_create (mu_acl_t *pacl) +{ + int rc; + mu_acl_t acl; + mu_log_level_t level; + + acl = calloc (1, sizeof (*acl)); + if (!acl) + return errno; + rc = mu_list_create (&acl->aclist); + if (rc) + free (acl); + else + *pacl = acl; + mu_list_set_destroy_item (acl->aclist, _destroy_acl_entry); + + level = mu_global_debug_level ("acl"); + if (level) + { + int status = mu_debug_create (&acl->debug, NULL); + if (status == 0) + mu_debug_set_level (acl->debug, level); + } + + return rc; +} + +int +mu_acl_count (mu_acl_t acl, size_t *pcount) +{ + if (!acl) + return EINVAL; + return mu_list_count (acl->aclist, pcount); +} + +int +mu_acl_destroy (mu_acl_t *pacl) +{ + mu_acl_t acl; + if (!pacl || !*pacl) + return EINVAL; + acl = *pacl; + mu_list_destroy (&acl->aclist); + mu_debug_destroy (&acl->debug, NULL); + free (acl); + *pacl = acl; + return 0; +} + +int +mu_acl_get_debug (mu_acl_t acl, mu_debug_t *pdebug) +{ + if (!acl) + return EINVAL; + if (!pdebug) + return MU_ERR_OUT_NULL; + *pdebug = acl->debug; + return 0; +} + +int +mu_acl_set_debug (mu_acl_t acl, mu_debug_t debug) +{ + if (!acl) + return EINVAL; + acl->debug = debug; + return 0; +} + +int +mu_acl_get_iterator (mu_acl_t acl, mu_iterator_t *pitr) +{ + if (!acl) + return EINVAL; + return mu_list_get_iterator (acl->aclist, pitr); +} + +int +mu_acl_append (mu_acl_t acl, mu_acl_action_t act, + void *data, struct sockaddr *sa, int salen, + unsigned long netmask) +{ + int rc; + struct _mu_acl_entry *ent; + + if (!acl) + return EINVAL; + rc = mu_acl_entry_create (&ent, act, data, sa, salen, netmask); + if (rc) + { + MU_DEBUG1 (acl->debug, MU_DEBUG_ERROR, "Cannot allocate ACL entry: %s", + mu_strerror (rc)); + return ENOMEM; + } + + rc = mu_list_append (acl->aclist, ent); + if (rc) + { + MU_DEBUG1 (acl->debug, MU_DEBUG_ERROR, "Cannot append ACL entry: %s", + mu_strerror (rc)); + free (ent); + } + return rc; +} + +int +mu_acl_prepend (mu_acl_t acl, mu_acl_action_t act, void *data, + struct sockaddr *sa, int salen, unsigned long netmask) +{ + int rc; + struct _mu_acl_entry *ent; + + if (!acl) + return EINVAL; + rc = mu_acl_entry_create (&ent, act, data, sa, salen, netmask); + if (rc) + { + MU_DEBUG1 (acl->debug, MU_DEBUG_ERROR, "Cannot allocate ACL entry: %s", + mu_strerror (rc)); + return ENOMEM; + } + rc = mu_list_prepend (acl->aclist, ent); + if (rc) + { + MU_DEBUG1 (acl->debug, MU_DEBUG_ERROR, "Cannot prepend ACL entry: %s", + mu_strerror (rc)); + free (ent); + } + return rc; +} + +int +mu_acl_insert (mu_acl_t acl, size_t pos, int before, + mu_acl_action_t act, void *data, + struct sockaddr *sa, int salen, unsigned long netmask) +{ + int rc; + void *ptr; + struct _mu_acl_entry *ent; + + if (!acl) + return EINVAL; + + rc = mu_list_get (acl->aclist, pos, &ptr); + if (rc) + { + MU_DEBUG1 (acl->debug, MU_DEBUG_ERROR, "No such entry %lu", + (unsigned long) pos); + return rc; + } + rc = mu_acl_entry_create (&ent, act, data, sa, salen, netmask); + if (!ent) + { + MU_DEBUG1 (acl->debug, MU_DEBUG_ERROR, "Cannot allocate ACL entry: %s", + mu_strerror (rc)); + return ENOMEM; + } + rc = mu_list_insert (acl->aclist, ptr, ent, before); + if (rc) + { + MU_DEBUG1 (acl->debug, MU_DEBUG_ERROR, "Cannot insert ACL entry: %s", + mu_strerror (rc)); + free (ent); + } + return rc; +} + + +static mu_kwd_t action_tab[] = { + { "accept", mu_acl_accept }, + { "deny", mu_acl_deny }, + { "log", mu_acl_log }, + { "exec", mu_acl_exec }, + { "ifexec", mu_acl_ifexec }, + { NULL } +}; + +int +mu_acl_action_to_string (mu_acl_action_t act, const char **pstr) +{ + return mu_kwd_xlat_tok (action_tab, act, pstr); +} + +int +mu_acl_string_to_action (const char *str, mu_acl_action_t *pres) +{ + int x; + int rc = mu_kwd_xlat_name (action_tab, str, &x); + if (rc == 0) + *pres = x; + return rc; +} + +void +debug_sockaddr (mu_debug_t dbg, mu_log_level_t lvl, struct sockaddr *sa) +{ + switch (sa->sa_family) + { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + mu_debug_printf (dbg, lvl, "{AF_INET %s:%d}", + inet_ntoa (sin->sin_addr), ntohs (sin->sin_port)); + break; + } + + case AF_UNIX: + { + struct sockaddr_un *sun = (struct sockaddr_un *)sa; + mu_debug_printf (dbg, lvl, "{AF_UNIX %s}", sun->sun_path); + break; + } + + default: + mu_debug_printf (dbg, lvl, "{Unsupported family: %d}", sa->sa_family); + } +} + +int +_acl_match (mu_debug_t debug, struct _mu_acl_entry *ent, struct sockaddr *sa) +{ +#define RESMATCH(word) \ + if (mu_debug_check_level (debug, MU_DEBUG_TRACE0)) \ + mu_debug_printf (debug, MU_DEBUG_TRACE0, "%s; ", word); + + if (mu_debug_check_level (debug, MU_DEBUG_TRACE0)) + { + struct in_addr a; + + __MU_DEBUG1 (debug, MU_DEBUG_TRACE0, "%s", "Does "); + debug_sockaddr (debug, MU_DEBUG_TRACE0, sa); + mu_debug_printf (debug, MU_DEBUG_TRACE0, " match "); + debug_sockaddr (debug, MU_DEBU |