Commit 1721cf28 1721cf2809d3c1d07cdf63eabf155972abc0db2c by Sergey Poznyakoff

* configure.ac, NEWS: Add LDAP support.

* auth/Makefile.am (libmuauth_la_SOURCES): Add ldap.c.
* auth/ldap.c: New file.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add ldap.h.
* include/mailutils/ldap.h: New file.
* include/mailutils/libcfg.h (mu_ldap_cfg_capa): New extern.
* include/mailutils/mu_auth.h (mu_auth_ldap_module): New extern.
(MU_AUTH_REGISTER_ALL_MODULES): Register ldap.
* libcfg/Makefile.am (libmucfg_la_SOURCES): Add ldap.
* libcfg/ldap.c: New file.
* libcfg/init.c (cfg_capa_table): Add ldap.
* mailbox/gocs.c (mu_gocs_logging_init): Initialize log_facility
to default if not specified otherwise. Need to revise this later.
* mailbox/version.c (mu_conf_option): Reveal ldap, if supported.

* mailbox/mu_auth.c (mu_auth_data_alloc): Add safety
checks. Provide reasonable defaults for missing arguments.
* mailbox/mutil.c (mutil_parse_field_map): Bugfix - increment by 2
on each loop.

* libargp/mu_argp.c (mu_build_argp): Do not bail out if an unknown
capability is requested.

* include/mailutils/assoc.h (mu_assoc_count): New function.
* mailbox/assoc.c: Likewise.

* auth/radius.c (_expand_query): Static

* mailbox/cfg_lexer.c: Fixed memory management during cloning.
1 parent fdbd31f1
2007-11-26 Sergey Poznyakoff <gray@gnu.org.ua>
* configure.ac, NEWS: Add LDAP support.
* auth/Makefile.am (libmuauth_la_SOURCES): Add ldap.c.
* auth/ldap.c: New file.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add ldap.h.
* include/mailutils/ldap.h: New file.
* include/mailutils/libcfg.h (mu_ldap_cfg_capa): New extern.
* include/mailutils/mu_auth.h (mu_auth_ldap_module): New extern.
(MU_AUTH_REGISTER_ALL_MODULES): Register ldap.
* libcfg/Makefile.am (libmucfg_la_SOURCES): Add ldap.
* libcfg/ldap.c: New file.
* libcfg/init.c (cfg_capa_table): Add ldap.
* mailbox/gocs.c (mu_gocs_logging_init): Initialize log_facility
to default if not specified otherwise. Need to revise this later.
* mailbox/version.c (mu_conf_option): Reveal ldap, if supported.
* mailbox/mu_auth.c (mu_auth_data_alloc): Add safety
checks. Provide reasonable defaults for missing arguments.
* mailbox/mutil.c (mutil_parse_field_map): Bugfix - increment by 2
on each loop.
* libargp/mu_argp.c (mu_build_argp): Do not bail out if an unknown
capability is requested.
* include/mailutils/assoc.h (mu_assoc_count): New function.
* mailbox/assoc.c: Likewise.
* auth/radius.c (_expand_query): Static
* mailbox/cfg_lexer.c: Fixed memory management during cloning.
2007-11-24 Sergey Poznyakoff <gray@gnu.org.ua>
Improve debugging.
......
GNU mailutils NEWS -- history of user-visible changes. 2007-11-19
GNU mailutils NEWS -- history of user-visible changes. 2007-11-26
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
See the end of file for copying conditions.
......@@ -92,6 +92,8 @@ Previous versions incorrectly understood such an URL as `a/b'
* Support for new protocols: POPS (pops://) and IMAPS (imaps://),
* LDAP support (authentication and authorization).
* Fixed APOP handling.
* Remove v0.6 compatibility layer.
......
......@@ -27,6 +27,7 @@ libmuauth_la_SOURCES = \
gsasl.c\
lbuf.c\
lbuf.h\
ldap.c\
pam.c\
radius.c\
sql.c\
......
This diff is collapsed. Click to expand it.
......@@ -199,7 +199,7 @@ mu_radius_module_init (void *data)
return 0;
}
char *
static char *
_expand_query (const char *query, const char *ustr, const char *passwd)
{
char *p, *q, *res;
......@@ -274,7 +274,7 @@ _expand_query (const char *query, const char *ustr, const char *passwd)
else
{
*q++ = '%';
*q++ = 'u';
*q++ = 'p';
}
p++;
break;
......
......@@ -74,6 +74,7 @@ status_dbm=no
status_gsasl=no
status_mysql=no
status_pgsql=no
status_ldap=no
dnl Internationalization macros.
AM_GNU_GETTEXT([external], [need-ngettext])
......@@ -678,7 +679,28 @@ if test -n "$SQL_MODULES"; then
fi
dnl Virtual domain support
# LDAP support
AC_ARG_WITH(ldap,
AC_HELP_STRING([--with-ldap],
[Configure to work with OpenLDAP]),
[case $withval in
yes) status_ldap=maybe
;;
no) status_ldap=no
;;
esac],
[status_ldap=maybe])
if test $status_ldap = maybe; then
AC_CHECK_LIB(ldap, ldap_bind,[
status_ldap=yes
AC_DEFINE(WITH_LDAP, 1, [Define to 1 if you want to use -lldap])
MU_AUTHLIBS="$MU_AUTHLIBS -lldap"],
[status_ldap=no])
fi
# Virtual domain support
MU_ENABLE_SUPPORT(virtual-domains)
AC_SUBST(SITE_VIRTUAL_PWDDIR)
AC_ARG_WITH([virtual-pwddir],
......@@ -709,6 +731,7 @@ MU_ENABLE_SUPPORT(mh,
BUILD_MH_EXEC_HOOK=mh_finish_install])
MU_ENABLE_SUPPORT(maildir)
# FIXME: Should be --with-radius
MU_ENABLE_SUPPORT(radius,
[AC_CHECK_HEADERS([radius/radius.h],,
[mu_cv_enable_radius=no])
......@@ -1051,6 +1074,7 @@ Pthread support................ $status_pthread
Readline support............... $status_readline
MySQL support.................. $status_mysql
PostgreSQL support............. $status_pgsql
LDAP support................... $status_ldap
Radius support................. $status_radius
Support for virtual domains.... $status_virtual_domains
......@@ -1075,6 +1099,7 @@ EOF
[status_pam=$status_pam
status_ltdl=$status_ltdl
status_dbm="$status_dbm"
status_ldap=$status_ldap
status_gnutls=$WITH_GNUTLS
status_gsasl=$status_gsasl
status_gssapi=$WITH_GSSAPI
......
......@@ -48,6 +48,7 @@ pkginclude_HEADERS = \
guile.h\
header.h\
iterator.h\
ldap.h\
libargp.h\
libcfg.h\
libsieve.h\
......
......@@ -40,6 +40,7 @@ int mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator);
int mu_assoc_remove_ref (mu_assoc_t assoc, void *data);
int mu_assoc_remove (mu_assoc_t assoc, const char *name);
int mu_assoc_set_free (mu_assoc_t assoc, mu_assoc_free_fn fn);
int mu_assoc_count (mu_assoc_t assoc, size_t *pcount);
#ifdef __cplusplus
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005, 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, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifndef _MAILUTILS_LDAP_H
#define _MAILUTILS_LDAP_H
#ifdef __cplusplus
extern "C" {
#endif
struct mu_ldap_module_config
{
int enable;
char *url;
char *base;
char *binddn;
char *passwd;
int tls;
/* FIXME: sasl */
int debug;
char *getpwnam_filter;
char *getpwuid_filter;
mu_assoc_t field_map;
};
#ifdef __cplusplus
}
#endif
#endif
......@@ -95,6 +95,7 @@ extern struct mu_cfg_capa mu_virtdomain_cfg_capa;
extern struct mu_cfg_capa mu_sieve_cfg_capa;
extern struct mu_cfg_capa mu_daemon_cfg_capa;
extern struct mu_cfg_capa mu_auth_cfg_capa;
extern struct mu_cfg_capa mu_ldap_cfg_capa;
#ifdef __cplusplus
}
......
......@@ -137,6 +137,7 @@ extern struct mu_auth_module mu_auth_pam_module;
extern struct mu_auth_module mu_auth_sql_module;
extern struct mu_auth_module mu_auth_virtual_module;
extern struct mu_auth_module mu_auth_radius_module;
extern struct mu_auth_module mu_auth_ldap_module;
#define MU_AUTH_REGISTER_ALL_MODULES() do {\
mu_auth_register_module (&mu_auth_generic_module); \
......@@ -145,6 +146,7 @@ extern struct mu_auth_module mu_auth_radius_module;
mu_auth_register_module (&mu_auth_sql_module);\
mu_auth_register_module (&mu_auth_virtual_module);\
mu_auth_register_module (&mu_auth_radius_module);\
mu_auth_register_module (&mu_auth_ldap_module);\
} while (0)
#endif
......
......@@ -113,17 +113,12 @@ mu_build_argp (const struct argp *template, const char *capa[])
for (n = 0; capa && capa[n]; n++)
{
struct argp_capa *cp = find_capa (capa[n]);
if (!cp)
if (cp)
{
mu_error (_("INTERNAL ERROR: requested unknown argp "
"capability %s (please report)"),
capa[n]);
abort ();
}
ap[nchild] = *cp->child;
ap[nchild].group = group++;
nchild++;
}
}
ap[nchild].argp = NULL;
......
......@@ -26,6 +26,7 @@ libmucfg_la_SOURCES=\
common.c\
init.c\
gsasl.c\
ldap.c\
pam.c\
radius.c\
sieve.c\
......
......@@ -38,6 +38,7 @@ struct mu_cfg_capa *cfg_capa_table[] = {
S (virtdomain),
S (sieve),
S (daemon),
S (ldap),
NULL
};
......
/* This file is part of GNU Mailutils
Copyright (C) 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "mailutils/libcfg.h"
#include "mailutils/mutil.h"
#include "mailutils/ldap.h"
static struct mu_ldap_module_config ldap_settings;
static int
cb_field_map (mu_cfg_locus_t *locus, void *data, char *arg)
{
int err;
int rc = mutil_parse_field_map (arg, &ldap_settings.field_map, &err);
if (rc)
mu_error (_("%s:%d: Error near element %d: %s"),
locus->file, locus->line, err, mu_strerror (rc));
return 0;
}
static struct mu_cfg_param mu_ldap_param[] = {
{ "enable", mu_cfg_bool, &ldap_settings.enable },
{ "url", mu_cfg_string, &ldap_settings.url },
{ "base", mu_cfg_string, &ldap_settings.base },
{ "binddn", mu_cfg_string, &ldap_settings.binddn },
{ "passwd", mu_cfg_string, &ldap_settings.passwd },
{ "tls", mu_cfg_bool, &ldap_settings.tls },
{ "debug", mu_cfg_int, &ldap_settings.debug },
{ "field-map", mu_cfg_callback, NULL, cb_field_map },
{ "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter },
{ "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter },
{ NULL }
};
int
mu_ldap_section_parser
(enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
void *section_data, void *call_data)
{
switch (stage)
{
case mu_cfg_section_start:
ldap_settings.enable = 1;
break;
case mu_cfg_section_end:
mu_gocs_store ("ldap", &ldap_settings);
}
return 0;
}
struct mu_cfg_capa mu_ldap_cfg_capa = {
"ldap", mu_ldap_param, mu_ldap_section_parser
};
......@@ -488,3 +488,26 @@ mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator)
*piterator = iterator;
return 0;
}
int
mu_assoc_count (mu_assoc_t assoc, size_t *pcount)
{
mu_iterator_t itr;
int rc;
size_t count;
if (!assoc || !pcount)
return EINVAL;
rc = mu_assoc_get_iterator (assoc, &itr);
if (rc)
return rc;
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
count++;
mu_iterator_destroy (&itr);
*pcount = count;
return 0;
}
......
......@@ -308,18 +308,12 @@ mu_config_create_container (struct mu_cfg_cont **pcont,
}
#define DUP_SHALLOW 0
#define DUP_DEEP 1
struct dup_data
{
int duptype;
struct mu_cfg_cont *cont;
struct mu_cfg_section **endsect;
};
static int dup_container (struct mu_cfg_cont **pcont,
struct mu_cfg_section **endsect);
static int dup_container (struct mu_cfg_cont **pcont);
static int
_dup_section_action (void *item, void *cbdata)
......@@ -328,17 +322,10 @@ _dup_section_action (void *item, void *cbdata)
struct mu_cfg_cont *cont = item;
struct dup_data *pdd = cbdata;
switch (pdd->duptype)
{
case DUP_DEEP:
rc = dup_container (&cont, pdd->endsect);
rc = dup_container (&cont);
if (rc)
return rc;
break;
case DUP_SHALLOW:
break;
}
if (!pdd->cont->v.section.subsec)
{
int rc = mu_list_create (&pdd->cont->v.section.subsec);
......@@ -354,7 +341,7 @@ _dup_param_action (void *item, void *cbdata)
int rc;
struct mu_cfg_cont *cont = item;
struct dup_data *pdd = cbdata;
rc = dup_container (&cont, pdd->endsect);
rc = dup_container (&cont);
if (rc)
return rc;
if (!pdd->cont->v.section.param)
......@@ -367,7 +354,7 @@ _dup_param_action (void *item, void *cbdata)
}
static int
dup_container (struct mu_cfg_cont **pcont, struct mu_cfg_section **endsect)
dup_container (struct mu_cfg_cont **pcont)
{
int rc;
struct mu_cfg_cont *newcont, *oldcont = *pcont;
......@@ -378,7 +365,6 @@ dup_container (struct mu_cfg_cont **pcont, struct mu_cfg_section **endsect)
return rc;
dd.cont = newcont;
dd.endsect = endsect;
switch (oldcont->type)
{
case mu_cfg_cont_section:
......@@ -387,14 +373,8 @@ dup_container (struct mu_cfg_cont **pcont, struct mu_cfg_section **endsect)
newcont->v.section.data = oldcont->v.section.data;
newcont->v.section.subsec = NULL;
newcont->v.section.param = NULL;
if (endsect && &oldcont->v.section == *endsect)
dd.duptype = DUP_SHALLOW;
else
dd.duptype = DUP_DEEP;
mu_list_do (oldcont->v.section.subsec, _dup_section_action, &dd);
mu_list_do (oldcont->v.section.param, _dup_param_action, &dd);
if (dd.duptype == DUP_SHALLOW)
*endsect = &newcont->v.section;
break;
case mu_cfg_cont_param:
......@@ -406,12 +386,29 @@ dup_container (struct mu_cfg_cont **pcont, struct mu_cfg_section **endsect)
}
static int
_destroy_container_action (void *item, void *cbdata)
static void
destroy_list (mu_list_t *plist)
{
struct mu_cfg_cont *cont = item;
mu_config_destroy_container (&cont);
return 0;
mu_list_t list = *plist;
mu_iterator_t itr = NULL;
if (!list)
return;
mu_list_get_iterator (list, &itr);
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
struct mu_cfg_cont *cont, *p;
mu_iterator_current (itr, (void**)&cont);
p = cont;
mu_config_destroy_container (&p);
if (!p)
mu_list_remove (list, cont);
}
mu_iterator_destroy (&itr);
if (mu_list_is_empty (list))
mu_list_destroy (plist);
}
void
......@@ -419,13 +416,12 @@ mu_config_destroy_container (struct mu_cfg_cont **pcont)
{
struct mu_cfg_cont *cont = *pcont;
unsigned refcount = mu_refcount_dec (cont->refcount);
/* printf ("destr %p-%s: %d\n", cont, cont->v.section.ident, refcount); */
switch (cont->type)
{
case mu_cfg_cont_section:
mu_list_do (cont->v.section.subsec, _destroy_container_action, NULL);
mu_list_destroy (&cont->v.section.subsec);
mu_list_do (cont->v.section.param, _destroy_container_action, NULL);
mu_list_destroy (&cont->v.section.param);
destroy_list (&cont->v.section.subsec);
destroy_list (&cont->v.section.param);
break;
case mu_cfg_cont_param:
......@@ -471,7 +467,8 @@ _clone_action (void *item, void *cbdata)
int
mu_config_clone_container (struct mu_cfg_cont *cont)
{
mu_refcount_inc (cont->refcount);
int n = mu_refcount_inc (cont->refcount);
/* printf("clone %p-%s: %d\n", cont, cont->v.section.ident, n); */
switch (cont->type)
{
case mu_cfg_cont_section:
......@@ -520,9 +517,19 @@ _mu_config_register_section (struct mu_cfg_cont **proot,
if (mu_refcount_value ((*proot)->refcount) > 1)
{
/* It is a clone, do copy-on-write */
rc = dup_container (proot, &parent);
rc = dup_container (proot);
if (rc)
return rc;
root_section = &(*proot)->v.section;
if (parent_path)
{
if (mu_cfg_find_section (root_section, parent_path, &parent))
return MU_ERR_NOENT;
}
else
parent = root_section;
}
if (ident)
......@@ -730,12 +737,11 @@ _mu_parse_config (char *file, char *progname,
static struct mu_cfg_param empty_param = { NULL };
if (!progparam)
progparam = &empty_param;
_mu_config_register_section (&cont, NULL, "program", prog_parser,
progname,
progparam, &prog_sect);
mu_config_clone_container (old_root);
if (old_root->v.section.subsec)
{
if (!prog_sect->subsec)
......@@ -744,9 +750,9 @@ _mu_parse_config (char *file, char *progname,
for (mu_iterator_first (iter); !mu_iterator_is_done (iter);
mu_iterator_next (iter))
{
struct mu_cfg_section *s;
mu_iterator_current (iter, (void**)&s);
mu_list_append (prog_sect->subsec, s);
struct mu_cfg_cont *c;
mu_iterator_current (iter, (void**)&c);
mu_list_append (prog_sect->subsec, c);
}
mu_iterator_destroy (&iter);
}
......@@ -759,9 +765,9 @@ _mu_parse_config (char *file, char *progname,
for (mu_iterator_first (iter); !mu_iterator_is_done (iter);
mu_iterator_next (iter))
{
struct mu_cfg_param *p;
mu_iterator_current (iter, (void**)&p);
mu_list_append (prog_sect->param, p);
struct mu_cfg_cont *c;
mu_iterator_current (iter, (void**)&c);
mu_list_append (prog_sect->param, c);
}
mu_iterator_destroy (&iter);
}
......
......@@ -212,7 +212,11 @@ mu_gocs_logging_init (void *data)
mu_debug_default_printer = mu_debug_syslog_printer;
}
else
{
log_facility = LOG_FACILITY;
mu_debug_default_printer = mu_debug_stderr_printer;
}
/* FIXME: Tag */
return 0;
}
......
......@@ -122,14 +122,35 @@ mu_auth_data_alloc (struct mu_auth_data **ptr,
const char *mailbox,
int change_uid)
{
size_t size = sizeof (**ptr) +
size_t size;
char *p;
char *tmp_mailbox_name = NULL;
if (!name)
return EINVAL;
if (!passwd)
passwd = "x";
if (!gecos)
gecos = "";
if (!dir)
dir = "/nonexisting";
if (!shell)
shell = "/dev/null";
if (!mailbox)
{
rc = mu_construct_user_mailbox_url (&tmp_mailbox_name, name);
if (rc)
return rc;
mailbox_name = tmp_mailbox_name;
}
size = = sizeof (**ptr) +
strlen (name) + 1 +
strlen (passwd) + 1 +
strlen (gecos) + 1 +
strlen (dir) + 1 +
strlen (shell) + 1 +
strlen (mailbox) + 1;
char *p;
*ptr = calloc (1, size);
if (!*ptr)
......@@ -151,6 +172,8 @@ mu_auth_data_alloc (struct mu_auth_data **ptr,
(*ptr)->uid = uid;
(*ptr)->gid = gid;
(*ptr)->change_uid = change_uid;
free (tmp_mailbox_name);
return 0;
}
......
......@@ -1449,7 +1449,7 @@ mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, int *perr)
return rc;
}
for (i = 0; i < argc; i++)
for (i = 0; i < argc; i += 2)
{
char *tok = argv[i];
char *p = strchr (tok, '=');
......
......@@ -86,6 +86,9 @@ static char *mu_conf_option[] = {
#ifdef HAVE_PGSQL
"HAVE_PGSQL",
#endif
#ifdef WITH_LDAP
"WITH_LDAP",
#endif
#ifdef ENABLE_VIRTUAL_DOMAINS
"ENABLE_VIRTUAL_DOMAINS",
#endif
......