summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-12-07 20:54:15 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-12-07 20:54:15 +0000
commit727b3c755d6db784cedc1d334d4a70ce72543d0d (patch)
tree120a7864b5dd2a28845c2fee7c9b9f57fc0130d3
parent2412484207346815cb2a1a7ef3c3aa8e6e093fba (diff)
downloadmailutils-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--ChangeLog27
-rw-r--r--NEWS40
-rw-r--r--TODO5
-rw-r--r--examples/Makefile.am1
-rw-r--r--examples/aclck.c243
-rw-r--r--include/mailutils/Makefile.am3
-rw-r--r--include/mailutils/acl.h72
-rw-r--r--include/mailutils/kwd.h37
-rw-r--r--include/mailutils/mailutils.h3
-rw-r--r--include/mailutils/types.hin1
-rw-r--r--include/mailutils/vartab.h36
-rw-r--r--mailbox/Makefile.am3
-rw-r--r--mailbox/acl.c665
-rw-r--r--mailbox/cfg_parser.y7
-rw-r--r--mailbox/kwd.c92
-rw-r--r--mailbox/list.c3
-rw-r--r--mailbox/mailbox.c2
-rw-r--r--mailbox/syslog.c51
-rw-r--r--mailbox/vartab.c317
19 files changed, 1562 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index b7d170d4c..5356e3b2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/NEWS b/NEWS
index 312214b20..b9505d835 100644
--- a/NEWS
+++ b/NEWS
@@ -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:
diff --git a/TODO b/TODO
index 52e39cee1..01b987335 100644
--- a/TODO
+++ b/TODO
@@ -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