Import Upstream version 0.69.0 upstream upstream/0.69.0
authorClinton Ebadi <clinton@unknownlamer.org>
Sun, 16 Feb 2020 03:12:26 +0000 (22:12 -0500)
committerClinton Ebadi <clinton@unknownlamer.org>
Sun, 16 Feb 2020 03:12:26 +0000 (22:12 -0500)
106 files changed:
ChangeLog
Makefile.am
Makefile.in
README_authlib.html.in
aclocal.m4
auth.h
auth_enumerate.3
auth_generic.3
auth_getoption.3
auth_getuserinfo.3
auth_login.3
auth_mkhomedir.3
auth_passwd.3
auth_sasl.3
authconfigfile.cpp [new file with mode: 0644]
authconfigfile.h [new file with mode: 0644]
authcustom.c
authdaemond.c
authdaemondcpp.cpp [new file with mode: 0644]
authdaemonrc.in
authgetconfig.c [deleted file]
authldap.c
authldap.h
authldaplib.c [deleted file]
authldaplib.cpp [new file with mode: 0644]
authldaprc
authlib.3.in
authmysql.cpp [moved from authmysql.c with 60% similarity]
authmysql.h
authmysqllib.c [deleted file]
authmysqllib.cpp [new file with mode: 0644]
authmysqlrc
authpasswd.1
authpgsql.c
authpgsql.h
authpgsqllib.c [deleted file]
authpgsqllib.cpp [new file with mode: 0644]
authpgsqlrc
authsasl.c
authsaslclient.h
authsqlite.cpp [moved from authsqlite.c with 56% similarity]
authsqlite.h
authsqlitelib.c [deleted file]
authsqlitelib.cpp [new file with mode: 0644]
authsqliterc
authtest.1
authuserdb.c
authuserdbpwd.c
checkpassword.c
compile
config.guess
config.sub
configure
configure.ac
courier-authlib.lpspec
courier-authlib.spec
courier-authlib.spec.in
courier_auth_config.h
courier_auth_config.h.in
courierauth.h
cramlib.c
cramlib.h [deleted file]
cryptpassword.c
depcomp
liblog/Makefile.in
liblog/aclocal.m4
libs/bdbobj/Makefile.in
libs/bdbobj/aclocal.m4
libs/gdbmobj/Makefile.in
libs/gdbmobj/aclocal.m4
libs/libhmac/Makefile.in
libs/libhmac/aclocal.m4
libs/liblock/Makefile.am
libs/liblock/Makefile.in
libs/liblock/aclocal.m4
libs/liblock/lockmail.1
libs/makedat/Makefile.in
libs/makedat/aclocal.m4
libs/makedat/makedat.in
libs/md5/Makefile.in
libs/md5/aclocal.m4
libs/numlib/Makefile.in
libs/numlib/aclocal.m4
libs/random128/Makefile.in
libs/random128/aclocal.m4
libs/rfc822/Makefile.am
libs/rfc822/Makefile.in
libs/rfc822/aclocal.m4
libs/rfc822/configure
libs/rfc822/configure.ac
libs/rfc822/rfc2047.c
libs/rfc822/rfc2047u.c
libs/sha1/Makefile.in
libs/sha1/aclocal.m4
ltmain.sh
missing
preauthmysql.c [deleted file]
preauthmysql.cpp [new file with mode: 0644]
preauthpgsql.c [deleted file]
preauthsqlite.c [deleted file]
userdb/Makefile.in
userdb/aclocal.m4
userdb/makeuserdb.8.in
userdb/userdb.8.in
userdb/userdbpw.8.in
userdb/userdbpw.c

index 85a02a6..4d32c65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,68 @@
+0.69.0
+
+2018-08-16  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * authdaemond.c: set FD_CLOEXEC on socket file descriptors, to avoid
+       leaks to child processes.
+
+2018-05-25  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * authldaplib.cpp: improve automatic reconnection logic to the LDAP
+       server.
+
+2017-11-27  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * rpm packaging fixes.
+
+2017-09-08  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * courier-authlib.spec.in: Fix several problems with the package
+       scripts. Remove 'authdaemond stop' from %preun. Add explicit
+       systemctl daemon-reload to %post and %postun
+
+2017-07-23  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * authsaslclient.h (SASL_LIST): Reorder SASL methods, strongest
+       first.
+
+0.68.0
+
+2017-03-16  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * configure.ac: Rebuild against updated courier-unicode API.
+
+0.67.0
+
+2017-01-27  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * courierauth.h: Move declarations from cramlib.h into courierauth.h,
+       exporting them as part of the public API.
+
+2016-09-04  Giovanni Bechis <giovanni@paclan.it>
+
+       * userdb/userdbpw.c (main): Use bcrypt_gensalt() on OpenBSD
+
+2016-05-07  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * authsqlite, authmysql, authpgsql: Rewrite these modules in
+       modern C++. Autodetect and automatically reload the configuration
+       file when it's changed, no server restart is needed.
+
+2016-03-20  Giovanni Bechis <giovanni@openbsd.org>
+
+       * checkpassword.c (do_authcheckpassword): Check for a null return
+       value from crypt().
+
+2016-01-17  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * authldaplib.cpp (operator): Fix compilation warning.
+
+2016-01-04  Sam Varshavchik  <mrsam@courier-mta.com>
+
+       * authldaplib.cpp: Rewrite authldap in modern C++. Autodetect
+       and automatically reload authldaprc when it is changed. No server
+       restart is required.
+
 0.66.4
 
 2015-11-14 "Hanno Böck" <hanno@hboeck.de>
index 7f4c09b..4e11ae8 100644 (file)
@@ -17,8 +17,8 @@ pkglibexecdir=$(libexecdir)/courier-authlib
 pkglibexec_SCRIPTS=authsystem.passwd
 
 pkglib_LTLIBRARIES=libcourierauth.la \
-       libcourierauthsasl.la libcourierauthsaslclient.la \
-       libcourierauthcommon.la $(modules)
+       libcourierauthcommon.la libcourierauthsasl.la libcourierauthsaslclient.la \
+       $(modules)
 sbin_SCRIPTS=authdaemond
 sbin_PROGRAMS=authtest authenumerate authpasswd
 bin_PROGRAMS=courierauthconfig
@@ -48,13 +48,14 @@ commonlibadd=libcourierauthcommon.la
 libcourierauthcommon_t=@CRYPTLIBS@
 libcourierauthcommon_la_SOURCES= \
        auth.h courierauth.h \
-       authgetconfig.c \
+       authconfigfile.cpp \
+       authconfigfile.h \
        authpwdenumerate.c \
        authsaslfrombase64.c authsasltobase64.c \
        courierauthstaticlist.h \
        authsyschangepwd.c authsyscommon.c \
        authldapescape.c \
-       cramlib.c cramlib.h \
+       cramlib.c \
        checkpassword.c cryptpassword.c \
        checkpasswordmd5.c checkpasswordsha1.c
 
@@ -108,13 +109,11 @@ libauthshadow_la_LDFLAGS=$(commonldflags)
 
 libauthpgsql_t=@PGSQL_LIBS@ @LIBM@ @NETLIBS@
 
-libauthpgsql_la_SOURCES=authpgsql.c preauthpgsql.c authpgsqllib.c authpgsql.h
+libauthpgsql_la_SOURCES=authpgsql.c authpgsqllib.cpp authpgsql.h
 libauthpgsql_la_DEPENDENCIES=$(commonlibdep)
 libauthpgsql_la_LIBADD=$(commonlibadd) $(libauthpgsql_t)
 libauthpgsql_la_LDFLAGS=$(commonldflags)
 
-authpgsqllib.lo: authpgsqllib.c authpgsqlrc.h
-
 if HAVE_AUTHPGSQL
 
 install-authpgsqlrc:
@@ -143,13 +142,11 @@ authpgsqlrc.h:
 # The authldap module
 
 libauthldap_t=@LDAPLIBS@ @NETLIBS@
-libauthldap_la_SOURCES=authldap.c preauthldap.c authldaplib.c authldap.h
+libauthldap_la_SOURCES=authldap.c preauthldap.c authldaplib.cpp authldap.h
 libauthldap_la_DEPENDENCIES=$(commonlibdep)
 libauthldap_la_LIBADD=$(commonlibadd) $(libauthldap_t)
 libauthldap_la_LDFLAGS=$(commonldflags)
 
-authldaplib.lo: authldaplib.c authldaprc.h
-
 if HAVE_LDAP
 
 install-authldaprc:
@@ -177,13 +174,11 @@ authldaprc.h:
 
 libauthmysql_t=@MYSQL_LIBS@ @LIBM@ @NETLIBS@
 
-libauthmysql_la_SOURCES=authmysql.c preauthmysql.c authmysqllib.c authmysql.h
+libauthmysql_la_SOURCES=authmysql.cpp preauthmysql.cpp authmysqllib.cpp authmysql.h
 libauthmysql_la_DEPENDENCIES=$(commonlibdep)
 libauthmysql_la_LIBADD=$(commonlibadd) $(libauthmysql_t)
 libauthmysql_la_LDFLAGS=$(commonldflags)
 
-authmysqllib.lo: authmysqllib.c authmysqlrc.h
-
 if HAVE_AUTHMYSQL
 install-authmysqlrc:
        $(mkinstalldirs) $(DESTDIR)`dirname @authmysqlrc@` || :
@@ -210,13 +205,11 @@ authmysqlrc.h:
 
 libauthsqlite_t=@SQLITE_LIBS@ @NETLIBS@
 
-libauthsqlite_la_SOURCES=authsqlite.c preauthsqlite.c authsqlitelib.c authsqlite.h
+libauthsqlite_la_SOURCES=authsqlite.cpp authsqlitelib.cpp authsqlite.h
 libauthsqlite_la_DEPENDENCIES=$(commonlibdep)
 libauthsqlite_la_LIBADD=$(commonlibadd) $(libauthsqlite_t)
 libauthsqlite_la_LDFLAGS=$(commonldflags)
 
-authsqlitelib.lo: authsqlitelib.c authsqliterc.h
-
 if HAVE_AUTHSQLITE
 install-authsqliterc:
        $(mkinstalldirs) $(DESTDIR)`dirname @authsqliterc@` || :
@@ -287,10 +280,20 @@ authdaemonrc.h:
 HTMLFILES=README.html NEWS.html INSTALL.html \
        README.authsqlite.html README.authmysql.html README.authpostgres.html
 
+
+if HAVE_SGML
+
+GITFILES=authldaprc authmysqlrc authpgsqlrc authsqliterc authdaemonrc.in
+
+$(GITFILES): %: %.git
+       perl -p -e 's/\$$Id:[^\$$]*/\$$Id: '"`git log --pretty=format:\"%H\" -n 1 -- $<`-`date +%Y%m%d%H%M%S`/" <$< >$@.tmp
+       mv -f $@.tmp $@
+endif
+
 EXTRA_DIST=$(HTMLFILES) sysconftool COPYING COPYING.GPL\
        authldap.schema \
        authldap.ldif \
-       authldaprc authmysqlrc authpgsqlrc authsqliterc README.ldap \
+       $(GITFILES) README.ldap \
        README.authmysql.myownquery \
        README.authdebug.html.in \
        courier-authlib.spec \
@@ -357,12 +360,14 @@ authenumerate_LDFLAGS=
 #
 # The main daemon.
 
-authdaemondprog_SOURCES=authdaemond.c
+authdaemondprog_SOURCES=authdaemond.c authdaemondcpp.cpp
+
 authdaemondprog_DEPENDENCIES=libcourierauthcommon.la \
+       libcourierauth.la \
        libs/liblock/liblock.la $(modules) \
        libs/libhmac/libhmac.la libs/md5/libmd5.la libs/sha1/libsha1.la \
        libs/rfc822/libencode.la libs/numlib/libnumlib.la
-authdaemondprog_LDADD=$(LIBLTDL) libcourierauthcommon.la libs/liblock/liblock.la \
+authdaemondprog_LDADD=$(LIBLTDL) libcourierauthcommon.la libcourierauth.la libs/liblock/liblock.la \
        libs/libhmac/libhmac.la libs/md5/libmd5.la libs/sha1/libsha1.la \
        libs/rfc822/libencode.la libs/numlib/libnumlib.la
 authdaemondprog_LDFLAGS=-export-dynamic $(modules:%=-dlopen %) @NETLIBS@
@@ -386,7 +391,8 @@ BUILT1=authlib.html authldaprc.h authmysqlrc.h authpgsqlrc.h authpiperc.h \
        authchangepwdir.h sbindir.h \
        pkglibdir.h pkgincludedir.h mailusergroup.h \
        README_authlib.html
-BUILT_SOURCES=$(BUILT1) $(man3:%.3=%.html) $(man1:%.1=%.html)
+BUILT_SOURCES=$(BUILT1) $(GITFILES) $(man3:%.3=%.html) $(man1:%.1=%.html) \
+       authsqliterc.h authmysqlrc.h authpgsqlrc.h authldaprc.h
 
 authchangepwdir.h: config.status
        echo '#define AUTHCHANGEPWDIR "$(pkglibexecdir)"' >authchangepwdir.h
@@ -462,14 +468,6 @@ authlib.3: authlib.3.in
 
 if HAVE_SGML
 
-GITFILES=authdaemonrc.in
-
-BUILT_SOURCES += $(GITFILES)
-
-$(GITFILES): %: %.git
-       perl -p -e 's/\$$Id:[^\$$]*/\$$Id: '"`git log --pretty=format:\"%H\" -n 1 -- $<`-`date +%Y%m%d%H%M%S`/" <$< >$@.tmp
-       mv -f $@.tmp $@
-
 authpasswd.html: authpasswd.sgml libs/docbook/sgml2html
        libs/docbook/sgml2html authpasswd.sgml authpasswd.html
 
@@ -652,15 +650,13 @@ bump.rpm.release: @PACKAGE@.spec @PACKAGE@.lpspec
        mv @PACKAGE@.lpspec.new @PACKAGE@.lpspec
 
 upload-beta:
-       test -z "$(SFPASSWD)" && exit 1; exit 0
        rm -f @PACKAGE@-@VERSION@.tar.bz2.sig; gpg --detach-sign --default-key mrsam@courier-mta.com @PACKAGE@-@VERSION@.tar.bz2; test -f @PACKAGE@-@VERSION@.tar.bz2.sig || exit 1
-       ~/src/sftools/release.pl mrsam $(SFPASSWD) courier authlib-devel `echo @VERSION@|sed 's/.*\(........\)/\1/'` @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
+       ~/src/sftools/release.pl mrsam courier authlib-devel `echo @VERSION@|sed 's/.*\(........\)/\1/'` @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
 
 upload-dist:
-       test -z "$(SFPASSWD)" && exit 1; exit 0
        rm -f @PACKAGE@-@VERSION@.tar.bz2.sig; gpg --detach-sign --default-key mrsam@courier-mta.com @PACKAGE@-@VERSION@.tar.bz2; test -f @PACKAGE@-@VERSION@.tar.bz2.sig || exit 1
        set -e; v="@PACKAGE@/@VERSION@/`date +%Y%m%d%H%M%S`"; git tag -s $$v -m 'Tag version @VERSION@'; cd libs; git tag -s $$v -m 'Tag version @VERSION@'
-       socksify ~/src/sftools/release.pl mrsam $(SFPASSWD) courier authlib @VERSION@ @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
+       socksify ~/src/sftools/release.pl mrsam courier authlib @VERSION@ @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
 
 HTMLDOCFILES=$(HTMLFILES) README.authdebug.html README_authlib.html \
        $(man3:%.3=%.html) $(man1:%.1=%.html) userdb/userdb.html userdb/makeuserdb.html userdb/userdbpw.html
index 4b08cf3..f14452b 100644 (file)
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.15 from Makefile.am.
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
 # @configure_input@
 
-# Copyright (C) 1994-2014 Free Software Foundation, Inc.
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
 
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -100,7 +100,6 @@ sbin_PROGRAMS = authtest$(EXEEXT) authenumerate$(EXEEXT) \
 bin_PROGRAMS = courierauthconfig$(EXEEXT)
 noinst_PROGRAMS = authdaemontest$(EXEEXT) authmksock$(EXEEXT) \
        authdaemondprog$(EXEEXT)
-@HAVE_SGML_TRUE@am__append_1 = $(GITFILES)
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
@@ -163,29 +162,28 @@ libauthcustom_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 am__DEPENDENCIES_1 =
 am_libauthldap_la_OBJECTS = authldap.lo preauthldap.lo authldaplib.lo
 libauthldap_la_OBJECTS = $(am_libauthldap_la_OBJECTS)
-libauthldap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-       $(AM_CFLAGS) $(CFLAGS) $(libauthldap_la_LDFLAGS) $(LDFLAGS) -o \
-       $@
+libauthldap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(libauthldap_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
 am_libauthmysql_la_OBJECTS = authmysql.lo preauthmysql.lo \
        authmysqllib.lo
 libauthmysql_la_OBJECTS = $(am_libauthmysql_la_OBJECTS)
-libauthmysql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-       $(AM_CFLAGS) $(CFLAGS) $(libauthmysql_la_LDFLAGS) $(LDFLAGS) \
-       -o $@
+libauthmysql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(libauthmysql_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
 am_libauthpam_la_OBJECTS = authpam.lo preauthpam.lo
 libauthpam_la_OBJECTS = $(am_libauthpam_la_OBJECTS)
 libauthpam_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
        $(libauthpam_la_LDFLAGS) $(LDFLAGS) -o $@
-am_libauthpgsql_la_OBJECTS = authpgsql.lo preauthpgsql.lo \
-       authpgsqllib.lo
+am_libauthpgsql_la_OBJECTS = authpgsql.lo authpgsqllib.lo
 libauthpgsql_la_OBJECTS = $(am_libauthpgsql_la_OBJECTS)
-libauthpgsql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-       $(AM_CFLAGS) $(CFLAGS) $(libauthpgsql_la_LDFLAGS) $(LDFLAGS) \
-       -o $@
+libauthpgsql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(libauthpgsql_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
 am_libauthpipe_la_OBJECTS = authpipe.lo authpipelib.lo
 libauthpipe_la_OBJECTS = $(am_libauthpipe_la_OBJECTS)
 libauthpipe_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@@ -203,13 +201,12 @@ libauthshadow_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
        $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
        $(AM_CFLAGS) $(CFLAGS) $(libauthshadow_la_LDFLAGS) $(LDFLAGS) \
        -o $@
-am_libauthsqlite_la_OBJECTS = authsqlite.lo preauthsqlite.lo \
-       authsqlitelib.lo
+am_libauthsqlite_la_OBJECTS = authsqlite.lo authsqlitelib.lo
 libauthsqlite_la_OBJECTS = $(am_libauthsqlite_la_OBJECTS)
-libauthsqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-       $(AM_CFLAGS) $(CFLAGS) $(libauthsqlite_la_LDFLAGS) $(LDFLAGS) \
-       -o $@
+libauthsqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(libauthsqlite_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
 am__DEPENDENCIES_2 = userdb/libuserdb.la
 am_libauthuserdb_la_OBJECTS = authuserdb.lo preauthuserdb.lo \
        preauthuserdbcommon.lo authuserdbpwd.lo
@@ -230,16 +227,16 @@ libcourierauth_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
        $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
        $(AM_CFLAGS) $(CFLAGS) $(libcourierauth_la_LDFLAGS) $(LDFLAGS) \
        -o $@
-am_libcourierauthcommon_la_OBJECTS = authgetconfig.lo \
+am_libcourierauthcommon_la_OBJECTS = authconfigfile.lo \
        authpwdenumerate.lo authsaslfrombase64.lo authsasltobase64.lo \
        authsyschangepwd.lo authsyscommon.lo authldapescape.lo \
        cramlib.lo checkpassword.lo cryptpassword.lo \
        checkpasswordmd5.lo checkpasswordsha1.lo
 libcourierauthcommon_la_OBJECTS =  \
        $(am_libcourierauthcommon_la_OBJECTS)
-libcourierauthcommon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-       $(AM_CFLAGS) $(CFLAGS) $(libcourierauthcommon_la_LDFLAGS) \
+libcourierauthcommon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(libcourierauthcommon_la_LDFLAGS) \
        $(LDFLAGS) -o $@
 libcourierauthsasl_la_DEPENDENCIES = libcourierauthcommon.la \
        libcourierauth.la
@@ -264,12 +261,13 @@ libcourierauthsaslclient_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
        $(AM_CFLAGS) $(CFLAGS) $(libcourierauthsaslclient_la_LDFLAGS) \
        $(LDFLAGS) -o $@
 PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(sbin_PROGRAMS)
-am_authdaemondprog_OBJECTS = authdaemond.$(OBJEXT)
+am_authdaemondprog_OBJECTS = authdaemond.$(OBJEXT) \
+       authdaemondcpp.$(OBJEXT)
 authdaemondprog_OBJECTS = $(am_authdaemondprog_OBJECTS)
-authdaemondprog_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-       $(AM_CFLAGS) $(CFLAGS) $(authdaemondprog_LDFLAGS) $(LDFLAGS) \
-       -o $@
+authdaemondprog_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(authdaemondprog_LDFLAGS) \
+       $(LDFLAGS) -o $@
 am_authdaemontest_OBJECTS = authdaemontest.$(OBJEXT)
 authdaemontest_OBJECTS = $(am_authdaemontest_OBJECTS)
 authdaemontest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@@ -329,6 +327,24 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo "  CXX     " $@;
+am__v_CXX_1 = 
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+       $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo "  CXXLD   " $@;
+am__v_CXXLD_1 = 
 SOURCES = $(libauthcustom_la_SOURCES) $(libauthldap_la_SOURCES) \
        $(libauthmysql_la_SOURCES) $(libauthpam_la_SOURCES) \
        $(libauthpgsql_la_SOURCES) $(libauthpipe_la_SOURCES) \
@@ -475,6 +491,10 @@ COURIERCONFIG = @COURIERCONFIG@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CRYPTLIBS = @CRYPTLIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -574,6 +594,7 @@ abs_top_builddir = @abs_top_builddir@
 abs_top_srcdir = @abs_top_srcdir@
 ac_ct_AR = @ac_ct_AR@
 ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
@@ -645,8 +666,8 @@ modules = @LIBAUTHUSERDB@ \
 
 pkglibexec_SCRIPTS = authsystem.passwd
 pkglib_LTLIBRARIES = libcourierauth.la \
-       libcourierauthsasl.la libcourierauthsaslclient.la \
-       libcourierauthcommon.la $(modules)
+       libcourierauthcommon.la libcourierauthsasl.la libcourierauthsaslclient.la \
+       $(modules)
 
 sbin_SCRIPTS = authdaemond
 EXTRA_LTLIBRARIES = libauthuserdb.la \
@@ -672,13 +693,14 @@ commonlibadd = libcourierauthcommon.la
 libcourierauthcommon_t = @CRYPTLIBS@
 libcourierauthcommon_la_SOURCES = \
        auth.h courierauth.h \
-       authgetconfig.c \
+       authconfigfile.cpp \
+       authconfigfile.h \
        authpwdenumerate.c \
        authsaslfrombase64.c authsasltobase64.c \
        courierauthstaticlist.h \
        authsyschangepwd.c authsyscommon.c \
        authldapescape.c \
-       cramlib.c cramlib.h \
+       cramlib.c \
        checkpassword.c cryptpassword.c \
        checkpasswordmd5.c checkpasswordsha1.c
 
@@ -726,28 +748,28 @@ libauthshadow_la_LDFLAGS = $(commonldflags)
 
 # The authpgsql module
 libauthpgsql_t = @PGSQL_LIBS@ @LIBM@ @NETLIBS@
-libauthpgsql_la_SOURCES = authpgsql.c preauthpgsql.c authpgsqllib.c authpgsql.h
+libauthpgsql_la_SOURCES = authpgsql.c authpgsqllib.cpp authpgsql.h
 libauthpgsql_la_DEPENDENCIES = $(commonlibdep)
 libauthpgsql_la_LIBADD = $(commonlibadd) $(libauthpgsql_t)
 libauthpgsql_la_LDFLAGS = $(commonldflags)
 
 # The authldap module
 libauthldap_t = @LDAPLIBS@ @NETLIBS@
-libauthldap_la_SOURCES = authldap.c preauthldap.c authldaplib.c authldap.h
+libauthldap_la_SOURCES = authldap.c preauthldap.c authldaplib.cpp authldap.h
 libauthldap_la_DEPENDENCIES = $(commonlibdep)
 libauthldap_la_LIBADD = $(commonlibadd) $(libauthldap_t)
 libauthldap_la_LDFLAGS = $(commonldflags)
 
 # The authmysql module
 libauthmysql_t = @MYSQL_LIBS@ @LIBM@ @NETLIBS@
-libauthmysql_la_SOURCES = authmysql.c preauthmysql.c authmysqllib.c authmysql.h
+libauthmysql_la_SOURCES = authmysql.cpp preauthmysql.cpp authmysqllib.cpp authmysql.h
 libauthmysql_la_DEPENDENCIES = $(commonlibdep)
 libauthmysql_la_LIBADD = $(commonlibadd) $(libauthmysql_t)
 libauthmysql_la_LDFLAGS = $(commonldflags)
 
 # The authsqlite module
 libauthsqlite_t = @SQLITE_LIBS@ @NETLIBS@
-libauthsqlite_la_SOURCES = authsqlite.c preauthsqlite.c authsqlitelib.c authsqlite.h
+libauthsqlite_la_SOURCES = authsqlite.cpp authsqlitelib.cpp authsqlite.h
 libauthsqlite_la_DEPENDENCIES = $(commonlibdep)
 libauthsqlite_la_LIBADD = $(commonlibadd) $(libauthsqlite_t)
 libauthsqlite_la_LDFLAGS = $(commonldflags)
@@ -766,10 +788,11 @@ libauthpipe_la_LDFLAGS = $(commonldflags)
 HTMLFILES = README.html NEWS.html INSTALL.html \
        README.authsqlite.html README.authmysql.html README.authpostgres.html
 
+@HAVE_SGML_TRUE@GITFILES = authldaprc authmysqlrc authpgsqlrc authsqliterc authdaemonrc.in
 EXTRA_DIST = $(HTMLFILES) sysconftool COPYING COPYING.GPL\
        authldap.schema \
        authldap.ldif \
-       authldaprc authmysqlrc authpgsqlrc authsqliterc README.ldap \
+       $(GITFILES) README.ldap \
        README.authmysql.myownquery \
        README.authdebug.html.in \
        courier-authlib.spec \
@@ -826,13 +849,14 @@ authenumerate_LDFLAGS =
 
 #
 # The main daemon.
-authdaemondprog_SOURCES = authdaemond.c
+authdaemondprog_SOURCES = authdaemond.c authdaemondcpp.cpp
 authdaemondprog_DEPENDENCIES = libcourierauthcommon.la \
+       libcourierauth.la \
        libs/liblock/liblock.la $(modules) \
        libs/libhmac/libhmac.la libs/md5/libmd5.la libs/sha1/libsha1.la \
        libs/rfc822/libencode.la libs/numlib/libnumlib.la
 
-authdaemondprog_LDADD = $(LIBLTDL) libcourierauthcommon.la libs/liblock/liblock.la \
+authdaemondprog_LDADD = $(LIBLTDL) libcourierauthcommon.la libcourierauth.la libs/liblock/liblock.la \
        libs/libhmac/libhmac.la libs/md5/libmd5.la libs/sha1/libsha1.la \
        libs/rfc822/libencode.la libs/numlib/libnumlib.la
 
@@ -854,10 +878,10 @@ BUILT1 = authlib.html authldaprc.h authmysqlrc.h authpgsqlrc.h authpiperc.h \
        pkglibdir.h pkgincludedir.h mailusergroup.h \
        README_authlib.html
 
-BUILT_SOURCES = $(BUILT1) $(man3:%.3=%.html) $(man1:%.1=%.html) \
-       $(am__append_1)
+BUILT_SOURCES = $(BUILT1) $(GITFILES) $(man3:%.3=%.html) $(man1:%.1=%.html) \
+       authsqliterc.h authmysqlrc.h authpgsqlrc.h authldaprc.h
+
 noinst_DATA = $(BUILT_SOURCES)
-@HAVE_SGML_TRUE@GITFILES = authdaemonrc.in
 HTMLDOCFILES = $(HTMLFILES) README.authdebug.html README_authlib.html \
        $(man3:%.3=%.html) $(man1:%.1=%.html) userdb/userdb.html userdb/makeuserdb.html userdb/userdbpw.html
 
@@ -865,7 +889,7 @@ all: $(BUILT_SOURCES) courier_auth_config.h
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
 .SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
+.SUFFIXES: .c .cpp .lo .o .obj
 am--refresh: Makefile
        @:
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
@@ -978,16 +1002,16 @@ libauthcustom.la: $(libauthcustom_la_OBJECTS) $(libauthcustom_la_DEPENDENCIES) $
        $(AM_V_CCLD)$(libauthcustom_la_LINK)  $(libauthcustom_la_OBJECTS) $(libauthcustom_la_LIBADD) $(LIBS)
 
 libauthldap.la: $(libauthldap_la_OBJECTS) $(libauthldap_la_DEPENDENCIES) $(EXTRA_libauthldap_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(libauthldap_la_LINK)  $(libauthldap_la_OBJECTS) $(libauthldap_la_LIBADD) $(LIBS)
+       $(AM_V_CXXLD)$(libauthldap_la_LINK)  $(libauthldap_la_OBJECTS) $(libauthldap_la_LIBADD) $(LIBS)
 
 libauthmysql.la: $(libauthmysql_la_OBJECTS) $(libauthmysql_la_DEPENDENCIES) $(EXTRA_libauthmysql_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(libauthmysql_la_LINK)  $(libauthmysql_la_OBJECTS) $(libauthmysql_la_LIBADD) $(LIBS)
+       $(AM_V_CXXLD)$(libauthmysql_la_LINK)  $(libauthmysql_la_OBJECTS) $(libauthmysql_la_LIBADD) $(LIBS)
 
 libauthpam.la: $(libauthpam_la_OBJECTS) $(libauthpam_la_DEPENDENCIES) $(EXTRA_libauthpam_la_DEPENDENCIES) 
        $(AM_V_CCLD)$(libauthpam_la_LINK)  $(libauthpam_la_OBJECTS) $(libauthpam_la_LIBADD) $(LIBS)
 
 libauthpgsql.la: $(libauthpgsql_la_OBJECTS) $(libauthpgsql_la_DEPENDENCIES) $(EXTRA_libauthpgsql_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(libauthpgsql_la_LINK)  $(libauthpgsql_la_OBJECTS) $(libauthpgsql_la_LIBADD) $(LIBS)
+       $(AM_V_CXXLD)$(libauthpgsql_la_LINK)  $(libauthpgsql_la_OBJECTS) $(libauthpgsql_la_LIBADD) $(LIBS)
 
 libauthpipe.la: $(libauthpipe_la_OBJECTS) $(libauthpipe_la_DEPENDENCIES) $(EXTRA_libauthpipe_la_DEPENDENCIES) 
        $(AM_V_CCLD)$(libauthpipe_la_LINK)  $(libauthpipe_la_OBJECTS) $(libauthpipe_la_LIBADD) $(LIBS)
@@ -999,7 +1023,7 @@ libauthshadow.la: $(libauthshadow_la_OBJECTS) $(libauthshadow_la_DEPENDENCIES) $
        $(AM_V_CCLD)$(libauthshadow_la_LINK)  $(libauthshadow_la_OBJECTS) $(libauthshadow_la_LIBADD) $(LIBS)
 
 libauthsqlite.la: $(libauthsqlite_la_OBJECTS) $(libauthsqlite_la_DEPENDENCIES) $(EXTRA_libauthsqlite_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(libauthsqlite_la_LINK)  $(libauthsqlite_la_OBJECTS) $(libauthsqlite_la_LIBADD) $(LIBS)
+       $(AM_V_CXXLD)$(libauthsqlite_la_LINK)  $(libauthsqlite_la_OBJECTS) $(libauthsqlite_la_LIBADD) $(LIBS)
 
 libauthuserdb.la: $(libauthuserdb_la_OBJECTS) $(libauthuserdb_la_DEPENDENCIES) $(EXTRA_libauthuserdb_la_DEPENDENCIES) 
        $(AM_V_CCLD)$(libauthuserdb_la_LINK)  $(libauthuserdb_la_OBJECTS) $(libauthuserdb_la_LIBADD) $(LIBS)
@@ -1008,7 +1032,7 @@ libcourierauth.la: $(libcourierauth_la_OBJECTS) $(libcourierauth_la_DEPENDENCIES
        $(AM_V_CCLD)$(libcourierauth_la_LINK) -rpath $(pkglibdir) $(libcourierauth_la_OBJECTS) $(libcourierauth_la_LIBADD) $(LIBS)
 
 libcourierauthcommon.la: $(libcourierauthcommon_la_OBJECTS) $(libcourierauthcommon_la_DEPENDENCIES) $(EXTRA_libcourierauthcommon_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(libcourierauthcommon_la_LINK) -rpath $(pkglibdir) $(libcourierauthcommon_la_OBJECTS) $(libcourierauthcommon_la_LIBADD) $(LIBS)
+       $(AM_V_CXXLD)$(libcourierauthcommon_la_LINK) -rpath $(pkglibdir) $(libcourierauthcommon_la_OBJECTS) $(libcourierauthcommon_la_LIBADD) $(LIBS)
 
 libcourierauthsasl.la: $(libcourierauthsasl_la_OBJECTS) $(libcourierauthsasl_la_DEPENDENCIES) $(EXTRA_libcourierauthsasl_la_DEPENDENCIES) 
        $(AM_V_CCLD)$(libcourierauthsasl_la_LINK) -rpath $(pkglibdir) $(libcourierauthsasl_la_OBJECTS) $(libcourierauthsasl_la_LIBADD) $(LIBS)
@@ -1125,7 +1149,7 @@ clean-sbinPROGRAMS:
 
 authdaemondprog$(EXEEXT): $(authdaemondprog_OBJECTS) $(authdaemondprog_DEPENDENCIES) $(EXTRA_authdaemondprog_DEPENDENCIES) 
        @rm -f authdaemondprog$(EXEEXT)
-       $(AM_V_CCLD)$(authdaemondprog_LINK) $(authdaemondprog_OBJECTS) $(authdaemondprog_LDADD) $(LIBS)
+       $(AM_V_CXXLD)$(authdaemondprog_LINK) $(authdaemondprog_OBJECTS) $(authdaemondprog_LDADD) $(LIBS)
 
 authdaemontest$(EXEEXT): $(authdaemontest_OBJECTS) $(authdaemontest_DEPENDENCIES) $(EXTRA_authdaemontest_DEPENDENCIES) 
        @rm -f authdaemontest$(EXEEXT)
@@ -1227,13 +1251,14 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authconfigfile.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authcustom.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authdaemon.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authdaemond.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authdaemondcpp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authdaemonlib.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authdaemontest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authenumerate.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authgetconfig.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authinfo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authldap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authldapescape.Plo@am__quote@
@@ -1284,10 +1309,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthldap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthmysql.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthpam.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthpgsql.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthpwd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthshadow.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthsqlite.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthuserdb.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preauthuserdbcommon.Plo@am__quote@
 
@@ -1312,6 +1335,27 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
+.cpp.o:
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
 mostlyclean-libtool:
        -rm -f *.lo
 
@@ -1602,7 +1646,7 @@ distdir: $(DISTFILES)
          ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
        || chmod -R a+r "$(distdir)"
 dist-gzip: distdir
-       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
        $(am__post_remove_distdir)
 dist-bzip2: distdir
        tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
@@ -1627,7 +1671,7 @@ dist-shar: distdir
        @echo WARNING: "Support for shar distribution archives is" \
                       "deprecated." >&2
        @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
-       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
        $(am__post_remove_distdir)
 
 dist-zip: distdir
@@ -1645,7 +1689,7 @@ dist dist-all:
 distcheck: dist
        case '$(DIST_ARCHIVES)' in \
        *.tar.gz*) \
-         GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+         eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
        *.tar.bz2*) \
          bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
        *.tar.lz*) \
@@ -1655,7 +1699,7 @@ distcheck: dist
        *.tar.Z*) \
          uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
        *.shar.gz*) \
-         GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+         eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
        *.zip*) \
          unzip $(distdir).zip ;;\
        esac
@@ -1886,8 +1930,6 @@ uninstall-man: uninstall-man1 uninstall-man3
 .PRECIOUS: Makefile
 
 
-authpgsqllib.lo: authpgsqllib.c authpgsqlrc.h
-
 @HAVE_AUTHPGSQL_TRUE@install-authpgsqlrc:
 @HAVE_AUTHPGSQL_TRUE@  $(mkinstalldirs) $(DESTDIR)`dirname @authpgsqlrc@` || :
 @HAVE_AUTHPGSQL_TRUE@  $(INSTALL_DATA) -m 660 $(srcdir)/authpgsqlrc \
@@ -1907,8 +1949,6 @@ authpgsqllib.lo: authpgsqllib.c authpgsqlrc.h
 authpgsqlrc.h:
        echo "#define AUTHPGSQLRC \"@authpgsqlrc@\"" >authpgsqlrc.h
 
-authldaplib.lo: authldaplib.c authldaprc.h
-
 @HAVE_LDAP_TRUE@install-authldaprc:
 @HAVE_LDAP_TRUE@       $(mkinstalldirs) $(DESTDIR)`dirname @authldaprc@` || :
 @HAVE_LDAP_TRUE@       $(INSTALL_DATA) -m 660 $(srcdir)/authldaprc \
@@ -1928,8 +1968,6 @@ authldaplib.lo: authldaplib.c authldaprc.h
 authldaprc.h:
        echo "#define AUTHLDAPRC \"@authldaprc@\"" >authldaprc.h
 
-authmysqllib.lo: authmysqllib.c authmysqlrc.h
-
 @HAVE_AUTHMYSQL_TRUE@install-authmysqlrc:
 @HAVE_AUTHMYSQL_TRUE@  $(mkinstalldirs) $(DESTDIR)`dirname @authmysqlrc@` || :
 @HAVE_AUTHMYSQL_TRUE@  $(INSTALL_DATA) -m 660 $(srcdir)/authmysqlrc \
@@ -1949,8 +1987,6 @@ authmysqllib.lo: authmysqllib.c authmysqlrc.h
 authmysqlrc.h:
        echo "#define AUTHMYSQLRC \"@authmysqlrc@\"" >authmysqlrc.h
 
-authsqlitelib.lo: authsqlitelib.c authsqliterc.h
-
 @HAVE_AUTHSQLITE_TRUE@install-authsqliterc:
 @HAVE_AUTHSQLITE_TRUE@ $(mkinstalldirs) $(DESTDIR)`dirname @authsqliterc@` || :
 @HAVE_AUTHSQLITE_TRUE@ $(INSTALL_DATA) -m 660 $(srcdir)/authsqliterc \
@@ -1993,6 +2029,10 @@ authdaemonrc.h:
        echo "#define AUTHDAEMONSOCK AUTHDAEMONVAR \"/socket\"" >>authdaemonrc.h
        echo "#define AUTHDAEMONLOCK AUTHDAEMONVAR \"/lock\"" >>authdaemonrc.h
 
+@HAVE_SGML_TRUE@$(GITFILES): %: %.git
+@HAVE_SGML_TRUE@       perl -p -e 's/\$$Id:[^\$$]*/\$$Id: '"`git log --pretty=format:\"%H\" -n 1 -- $<`-`date +%Y%m%d%H%M%S`/" <$< >$@.tmp
+@HAVE_SGML_TRUE@       mv -f $@.tmp $@
+
 README: README.html
        links -dump -no-references README.html >README
 
@@ -2072,10 +2112,6 @@ authlib.html: authlib.html.in
 authlib.3: authlib.3.in
        $(SHELL) ./config.status --file=authlib.3
 
-@HAVE_SGML_TRUE@$(GITFILES): %: %.git
-@HAVE_SGML_TRUE@       perl -p -e 's/\$$Id:[^\$$]*/\$$Id: '"`git log --pretty=format:\"%H\" -n 1 -- $<`-`date +%Y%m%d%H%M%S`/" <$< >$@.tmp
-@HAVE_SGML_TRUE@       mv -f $@.tmp $@
-
 @HAVE_SGML_TRUE@authpasswd.html: authpasswd.sgml libs/docbook/sgml2html
 @HAVE_SGML_TRUE@       libs/docbook/sgml2html authpasswd.sgml authpasswd.html
 
@@ -2255,15 +2291,13 @@ bump.rpm.release: @PACKAGE@.spec @PACKAGE@.lpspec
        mv @PACKAGE@.lpspec.new @PACKAGE@.lpspec
 
 upload-beta:
-       test -z "$(SFPASSWD)" && exit 1; exit 0
        rm -f @PACKAGE@-@VERSION@.tar.bz2.sig; gpg --detach-sign --default-key mrsam@courier-mta.com @PACKAGE@-@VERSION@.tar.bz2; test -f @PACKAGE@-@VERSION@.tar.bz2.sig || exit 1
-       ~/src/sftools/release.pl mrsam $(SFPASSWD) courier authlib-devel `echo @VERSION@|sed 's/.*\(........\)/\1/'` @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
+       ~/src/sftools/release.pl mrsam courier authlib-devel `echo @VERSION@|sed 's/.*\(........\)/\1/'` @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
 
 upload-dist:
-       test -z "$(SFPASSWD)" && exit 1; exit 0
        rm -f @PACKAGE@-@VERSION@.tar.bz2.sig; gpg --detach-sign --default-key mrsam@courier-mta.com @PACKAGE@-@VERSION@.tar.bz2; test -f @PACKAGE@-@VERSION@.tar.bz2.sig || exit 1
        set -e; v="@PACKAGE@/@VERSION@/`date +%Y%m%d%H%M%S`"; git tag -s $$v -m 'Tag version @VERSION@'; cd libs; git tag -s $$v -m 'Tag version @VERSION@'
-       socksify ~/src/sftools/release.pl mrsam $(SFPASSWD) courier authlib @VERSION@ @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
+       socksify ~/src/sftools/release.pl mrsam courier authlib @VERSION@ @PACKAGE@-@VERSION@.tar.bz2 @PACKAGE@-@VERSION@.tar.bz2.sig
 
 htmldoc: $(HTMLDOCFILES)
        for f in $^; do d=`basename $$f`; test "$$d" = "README.html" && d="index.html"; tidy -i -q --tidy-mark no --doctype transitional --input-encoding utf8 --output-encoding utf8 -asxml <$$f >$$f.tmp ; xsltproc --nonet $$HOME/www/www.courier-mta.org/xsl/authlib.xsl $$f.tmp | perl -ne 's~\$(id):.*\$$~\$(id):'"$$h"'\$$~; print' >$$HOME/www/www.courier-mta.org/authlib/$$d; rm -f $$f.tmp; done
index 85c772b..91220fe 100644 (file)
@@ -439,8 +439,9 @@ This module reads
 the list of mail accounts and passwords from an LDAP directory.
 The <code class="filename">@authldaprc@</code> configuration file defines the
 particular details regarding the LDAP directory layout.</p><p>
-A suggested LDAP schema can be found in the file
-<code class="filename">authldap.schema</code>,
+A suggested LDAP schema can be found in the files
+<code class="filename">authldap.schema</code> and
+<code class="filename">authldap.ldif</code>,
 which is included in Courier authentication library's source code, and
 may be installed on your system.</p></div><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authcustom" shape="rect"> </a><code class="literal">authcustom</code></h2></div></div></div><p>
 This is a do-nothing module where custom authentication code
index 6379c8b..8a0d7e7 100644 (file)
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.15 -*- Autoconf -*-
+# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
 
-# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -20,6 +20,83 @@ You have another version of autoconf.  It may work, but is not guaranteed to.
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically 'autoreconf'.])])
 
+dnl Sets the COURIER_UNICODE_CXXFLAGS variable to any additional compiler
+dnl flags needed to build the courier-unicode package and packages that
+dnl use the courier-unicode package.
+
+AC_DEFUN([AX_COURIER_UNICODE_CXXFLAGS],[
+
+save_FLAGS="$CXXFLAGS"
+
+AC_LANG_PUSH([C++])
+
+AC_TRY_COMPILE([
+#include <string>
+], [
+     std::u32string s;
+     char32_t c;
+     ],
+     [
+     ],
+     [
+
+COURIER_UNICODE_CXXFLAGS="-std=c++11"
+CXXFLAGS="$save_CFLAGS $COURIER_UNICODE_CXXFLAGS"
+
+AC_TRY_COMPILE([
+#include <string>
+], [
+     std::u32string s;
+     char32_t c;
+     ],
+     [
+     ],
+     [
+
+COURIER_UNICODE_CXXFLAGS="-std=c++0x"
+CXXFLAGS="$save_CFLAGS $COURIER_UNICODE_CXXFLAGS"
+
+AC_TRY_COMPILE([
+#include <string>
+], [
+     std::u32string s;
+     char32_t c;
+     ],
+     [
+     ],
+     [
+AC_MSG_ERROR([*** A compiler with C++11 Unicode support was not found])
+])
+])
+])
+CXXFLAGS="$save_FLAGS"
+AC_LANG_POP([C++])
+])
+
+AC_DEFUN([AX_COURIER_UNICODE_VERSION],[
+
+AC_MSG_CHECKING(courier-unicode library and version)
+
+AC_TRY_COMPILE([
+#include <courier-unicode.h>
+#ifndef COURIER_UNICODE_VERSION
+#define COURIER_UNICODE_VERSION 0
+#endif
+
+#if COURIER_UNICODE_VERSION < 210
+#error "courier-unicode 2.1 library is required"
+#endif
+
+],[],[],
+AC_MSG_ERROR([
+ERROR: The Courier Unicode Library 2.1 header files appear not to be installed.
+You may need to upgrade the library or install a separate development
+subpackage in addition to the main package.])
+)
+
+AC_MSG_RESULT([ok])
+])
+
 # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
 #
 #   Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
@@ -10075,7 +10152,7 @@ AC_DEFUN([AC_PROG_SYSCONFTOOL],
 ]
 )
 
-# Copyright (C) 2002-2014 Free Software Foundation, Inc.
+# Copyright (C) 2002-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10090,7 +10167,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
 [am__api_version='1.15'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.15], [],
+m4_if([$1], [1.15.1], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -10106,14 +10183,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.15])dnl
+[AM_AUTOMAKE_VERSION([1.15.1])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
 
 # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
 
-# Copyright (C) 2001-2014 Free Software Foundation, Inc.
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10165,7 +10242,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
 
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
-# Copyright (C) 1997-2014 Free Software Foundation, Inc.
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10196,7 +10273,7 @@ AC_CONFIG_COMMANDS_PRE(
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
-# Copyright (C) 1999-2014 Free Software Foundation, Inc.
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10387,7 +10464,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
 
 # Generate code to set up dependency tracking.              -*- Autoconf -*-
 
-# Copyright (C) 1999-2014 Free Software Foundation, Inc.
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10463,7 +10540,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
 
 # Do all the work for Automake.                             -*- Autoconf -*-
 
-# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10660,7 +10737,7 @@ for _am_header in $config_headers :; do
 done
 echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
 
-# Copyright (C) 2001-2014 Free Software Foundation, Inc.
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10681,7 +10758,7 @@ if test x"${install_sh+set}" != xset; then
 fi
 AC_SUBST([install_sh])])
 
-# Copyright (C) 2003-2014 Free Software Foundation, Inc.
+# Copyright (C) 2003-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10702,7 +10779,7 @@ AC_SUBST([am__leading_dot])])
 
 # Check to see how 'make' treats includes.                 -*- Autoconf -*-
 
-# Copyright (C) 2001-2014 Free Software Foundation, Inc.
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10752,7 +10829,7 @@ rm -f confinc confmf
 
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
-# Copyright (C) 1997-2014 Free Software Foundation, Inc.
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10791,7 +10868,7 @@ fi
 
 # Helper functions for option handling.                     -*- Autoconf -*-
 
-# Copyright (C) 2001-2014 Free Software Foundation, Inc.
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10820,7 +10897,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
 AC_DEFUN([_AM_IF_OPTION],
 [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
 
-# Copyright (C) 1999-2014 Free Software Foundation, Inc.
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10867,7 +10944,7 @@ AC_LANG_POP([C])])
 # For backward compatibility.
 AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
 
-# Copyright (C) 2001-2014 Free Software Foundation, Inc.
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10886,7 +10963,7 @@ AC_DEFUN([AM_RUN_LOG],
 
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
-# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -10967,7 +11044,7 @@ AC_CONFIG_COMMANDS_PRE(
 rm -f conftest.file
 ])
 
-# Copyright (C) 2009-2014 Free Software Foundation, Inc.
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -11027,7 +11104,7 @@ AC_SUBST([AM_BACKSLASH])dnl
 _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
 ])
 
-# Copyright (C) 2001-2014 Free Software Foundation, Inc.
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -11055,7 +11132,7 @@ fi
 INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
 AC_SUBST([INSTALL_STRIP_PROGRAM])])
 
-# Copyright (C) 2006-2014 Free Software Foundation, Inc.
+# Copyright (C) 2006-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -11074,7 +11151,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
 
 # Check how to create a tarball.                            -*- Autoconf -*-
 
-# Copyright (C) 2004-2014 Free Software Foundation, Inc.
+# Copyright (C) 2004-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/auth.h b/auth.h
index 837eb41..316495c 100644 (file)
--- a/auth.h
+++ b/auth.h
@@ -47,17 +47,6 @@ int auth_sys_common( int (*auth_pre_func)(const char *,
                     int (*callback_func)(struct authinfo *, void *),
                     void *callback_arg);
 
-const char *authgetconfig(const char *filename, const char *env);
-
-char *auth_parse_select_clause (char *(*escape_func)(const char *, size_t),
-                               const char *clause, const char *username,
-                               const char *defdomain,
-                               const char *service);
-
-char *auth_parse_chpass_clause (char *(*escape_func)(const char *, size_t),
-                               const char *clause, const char *username,
-                               const char *defdomain, const char *newpass,
-                               const char *newpass_crypt);
 
 #ifdef __cplusplus
 }
index 9b8bbf8..3a40fd3 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_enumerate
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 06/20/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_ENUMERATE" "3" "06/20/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_ENUMERATE" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index f6020c2..b566adf 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_generic
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 06/20/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_GENERIC" "3" "06/20/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_GENERIC" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index f5dcc11..bbd88bc 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_getoption
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 06/20/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_GETOPTION" "3" "06/20/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_GETOPTION" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index 16f4c47..57150c4 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_getuserinfo
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 06/20/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_GETUSERINFO" "3" "06/20/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_GETUSERINFO" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index d617d53..b2bccc5 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_login
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 06/20/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_LOGIN" "3" "06/20/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_LOGIN" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index 314e931..ed0155c 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2015 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_mkhomedir
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 11/04/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_MKHOMEDIR" "3" "11/04/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_MKHOMEDIR" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index 33e6d3a..573e32b 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_passwd
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 06/20/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_PASSWD" "3" "06/20/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_PASSWD" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index 705157c..4c59c8e 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004-2008 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: auth_sasl
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 06/20/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTH_SASL" "3" "06/20/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTH_SASL" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -136,7 +136,8 @@ conversation\&.
 is a version of
 \fBauth_sasl\fR
 that recognizes the
-EXTERNALSASL
+EXTERNAL
+SASL
 method\&. It takes an extra parameter,
 \fIexternalauth\fR\&. This parameter should be set to indicate an login that was authenticated via some other means, such as, perhaps, an
 SSL
diff --git a/authconfigfile.cpp b/authconfigfile.cpp
new file mode 100644 (file)
index 0000000..0a79c5b
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+** Copyright 2016 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "courier_auth_config.h"
+#endif
+
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+extern "C" {
+#include "authldap.h"
+#include "auth.h"
+#include "authldaprc.h"
+#include "courierauthdebug.h"
+};
+
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+
+#include "authconfigfile.h"
+
+courier::auth::config_file::config_file(const char *filenameArg)
+       : filename(filenameArg), loaded(false)
+{
+}
+
+bool courier::auth::config_file::load(bool reload)
+{
+       struct stat stat_buf;
+
+       if (stat(filename, &stat_buf) < 0)
+       {
+               courier_auth_err("stat(%s) failed", filename);
+               return false;
+       }
+
+       if (loaded)
+       {
+               if (stat_buf.st_mtime != config_timestamp)
+                       do_reload();
+               return true;
+       }
+
+       loaded=open_and_load_file(reload);
+
+       if (loaded)
+               config_timestamp=stat_buf.st_mtime;
+       return loaded;
+}
+
+class courier::auth::config_file::isspace {
+
+public:
+
+       bool operator()(char c)
+       {
+               return std::isspace(c);
+       }
+};
+
+class courier::auth::config_file::not_isspace : public isspace {
+
+public:
+
+       bool operator()(char c)
+       {
+               return !isspace::operator()(c);
+       }
+};
+
+
+bool courier::auth::config_file::open_and_load_file(bool reload)
+{
+       std::ifstream f(filename);
+
+       if (!f.is_open())
+       {
+               courier_auth_err("Cannot open %s", filename);
+
+               return false;
+       }
+
+       std::string s;
+
+       bool seen_marker=false;
+
+       while (s.clear(), !std::getline(f, s).eof() || !s.empty())
+       {
+               std::string::iterator e=s.end();
+
+               std::string::iterator p=
+                       std::find_if(s.begin(), e, not_isspace());
+
+               if (p == s.end() || *p == '#')
+               {
+                       static const char marker[]="##NAME: MARKER:";
+
+                       if (s.substr(0, sizeof(marker)-1) == marker)
+                               seen_marker=true;
+                       continue;
+               }
+
+               std::string::iterator q=std::find_if(p, e, isspace());
+
+               std::string name(p, q);
+               std::string setting;
+
+               while (1)
+               {
+                       q=std::find_if(q, e, not_isspace());
+
+                       while (q != e && isspace()(e[-1]))
+                               --e;
+
+                       if (q == e)
+                               break;
+
+                       bool continuing=false;
+
+                       if (e[-1] == '\\')
+                       {
+                               continuing=true;
+                               e[-1]=' ';
+                       }
+
+                       setting.insert(setting.end(), q, e);
+
+                       if (!continuing)
+                               break;
+
+                       std::getline(f, s);
+
+                       q=s.begin();
+                       e=s.end();
+               }
+
+               parsed_config.insert(std::make_pair(name, setting));
+       }
+
+       if (!seen_marker)
+       {
+               courier_auth_err((reload
+                                 ? "marker line not found in %s will try again later"
+                                 : "marker line not found in %s (probably forgot to run sysconftool after an upgrade)"), filename);
+               return false;
+       }
+
+       return do_load();
+}
+
+bool courier::auth::config_file::getconfig(const char *name,
+                                          std::string &value,
+                                          bool required,
+                                          const char *default_value) const
+{
+       std::map<std::string, std::string>::const_iterator
+               iter=parsed_config.find(name);
+
+       if (iter != parsed_config.end())
+       {
+               value=iter->second;
+               return true;
+       }
+
+       if (required)
+       {
+               courier_auth_err("%s not found in %s",
+                                name, filename);
+               return false;
+       }
+
+       value.clear();
+       if (default_value)
+               value=default_value;
+       return true;
+}
+
+template<>
+bool courier::auth::config_file::config(const char *name,
+                                       std::string &value,
+                                       bool required,
+                                       const char *default_value) const
+{
+       return getconfig(name, value, required, default_value);
+}
+
+std::string courier::auth::config_file::config(const char *name) const
+{
+       return config(name, 0);
+}
+
+std::string courier::auth::config_file::config(const char *name,
+                                              const char *default_value) const
+{
+       std::string retval;
+
+       config(name, retval, false, default_value);
+
+       return retval;
+}
+
+std::string
+courier::auth::config_file::expand_string(const std::string &s,
+                                         const std::map<std::string,
+                                         std::string> &parameters)
+{
+       std::ostringstream o;
+
+       std::string::const_iterator b=s.begin(), e=s.end(), p;
+       std::map<std::string, std::string>::const_iterator p_iter;
+
+       while (b != e)
+       {
+               p=std::find(b, e, '$');
+
+               o << std::string(b, p);
+
+               b=p;
+
+               if (b == e)
+                       continue;
+
+               if (*++b != '(')
+               {
+                       o << '$';
+                       continue;
+               }
+
+               p=std::find(++b, e, ')');
+
+               p_iter=parameters.find(std::string(b, p));
+               b=p;
+               if (b != e)
+                       ++b;
+
+               if (p_iter != parameters.end())
+                       o << p_iter->second;
+       }
+       return o.str();
+}
+
+std::string
+courier::auth::config_file::parse_custom_query(const std::string &s,
+                                              const std::string &login,
+                                              const std::string &defdomain,
+                                              std::map<std::string,
+                                              std::string> &parameters)
+{
+
+       std::string::const_iterator b=login.begin(),
+               e=login.end(),
+               p=std::find(b, e, '@');
+
+       parameters["local_part"]=std::string(b, p);
+       parameters["domain"]=p == e ? defdomain:std::string(p+1, e);
+
+       return expand_string(s, parameters);
+}
diff --git a/authconfigfile.h b/authconfigfile.h
new file mode 100644 (file)
index 0000000..e87258c
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef authconfigfile_h
+#define authconfigfile_h
+
+#if HAVE_CONFIG_H
+#include "courier_auth_config.h"
+#endif
+
+#include <time.h>
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <string>
+#include <sstream>
+#include <map>
+
+namespace courier {
+       namespace auth {
+#if 0
+       }
+}
+#endif
+
+class config_file {
+
+protected:
+       const char *filename;
+
+       std::map<std::string, std::string> parsed_config;
+private:
+       bool loaded;
+       time_t config_timestamp;
+
+public:
+       config_file(const char *filenameArg);
+       bool load(bool reload=false);
+
+private:
+       virtual bool do_load()=0;
+       virtual void do_reload()=0;
+
+       class isspace;
+       class not_isspace;
+
+       bool open_and_load_file(bool reload);
+
+ public:
+
+
+       template<typename value_type>
+               bool config(const char *name,
+                           value_type &value,
+                           bool required,
+                           const char *default_value=0)
+               const
+       {
+               std::string string_value;
+
+               if (!getconfig(name, string_value, required, default_value))
+                       return false;
+
+               std::istringstream i(string_value);
+
+               i >> value;
+               return true;
+       }
+
+       std::string config(const char *name) const;
+       std::string config(const char *name, const char *default_value) const;
+
+       bool getconfig(const char *name,
+                      std::string &value,
+                      bool required,
+                      const char *default_value=0) const;
+
+       static std::string expand_string(const std::string &s,
+                                        const std::map<std::string,
+                                        std::string> &parameters);
+
+       static std::string
+               parse_custom_query(const std::string &s,
+                                  const std::string &login,
+                                  const std::string &defdomain,
+                                  std::map<std::string,
+                                  std::string> &parameters);
+};
+
+template<>
+bool config_file::config(const char *name,
+                            std::string &value,
+                            bool required,
+                            const char *default_value) const;
+
+#if 0
+{
+       {
+#endif
+       }
+}
+
+#endif
index ff16979..48329cd 100644 (file)
@@ -14,7 +14,9 @@
 
 #include       "auth.h"
 #include       "authcustom.h"
+#include       "courierauth.h"
 #include       "courierauthstaticlist.h"
+#include       "libhmac/hmac.h"
 
 
 static int auth_custom_login(const char *service, char *authdata,
@@ -33,9 +35,6 @@ static int auth_custom_login(const char *service, char *authdata,
        return authcustomcommon(user, pass, callback_func, callback_arg);
 }
 
-#include       "libhmac/hmac.h"
-#include       "cramlib.h"
-
 static int auth_custom_cram(const char *service,
                            const char *authtype,
                            char *authdata,
index 44ad65e..3000907 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright 2000-2008 Double Precision, Inc.  See COPYING for
+** Copyright 2000-2018 Double Precision, Inc.  See COPYING for
 ** distribution information.
 */
 
@@ -23,9 +23,9 @@
 #include       "authdaemonrc.h"
 #include       "courierauthdebug.h"
 #include       "pkglibdir.h"
+#include       "courierauth.h"
 #include       "courierauthstaticlist.h"
 #include        "libhmac/hmac.h"
-#include        "cramlib.h"
 #include       <ltdl.h>
 
 
@@ -56,10 +56,11 @@ struct      sockaddr_un skun;
        strcat(skun.sun_path, ".tmp");
        unlink(skun.sun_path);
        if (bind(fd, (const struct sockaddr *)&skun, sizeof(skun)) ||
-               listen(fd, SOMAXCONN) ||
-               chmod(skun.sun_path, 0777) ||
-               rename(skun.sun_path, AUTHDAEMONSOCK) ||
-               fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+           listen(fd, SOMAXCONN) ||
+           chmod(skun.sun_path, 0777) ||
+           rename(skun.sun_path, AUTHDAEMONSOCK) ||
+           fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 ||
+           fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
        {
                perror(AUTHDAEMONSOCK);
                close(fd);
@@ -440,9 +441,9 @@ static int printauth(struct authinfo *authinfo, void *vp)
                        return (1);
        if (authinfo->fullname)
        {
-               /* 
-                * Only the first field of the comma-seperated GECOS field is the 
-                * full username. 
+               /*
+                * Only the first field of the comma-seperated GECOS field is the
+                * full username.
                 */
                char *fullname;
                char *p;
@@ -458,7 +459,7 @@ static int printauth(struct authinfo *authinfo, void *vp)
                p = fullname;
                while (*p != ',' && *p != '\0')
                        p++;
-               *p=0; 
+               *p=0;
                retval = writeenvval(fd, "NAME", fullname);
                free(fullname);
                if(retval)
@@ -614,6 +615,7 @@ static void enumerate(int fd)
        struct authstaticinfolist *l;
 
        ei.fd=fd;
+       ei.buf_ptr=ei.buffer;
        ei.buf_left=0;
 
        for (l=modulelist; l; l=l->next)
@@ -1023,7 +1025,8 @@ int start()
                saddr_len=sizeof(saddr);
                if ((fd=accept(s, &saddr, &saddr_len)) < 0)
                        continue;
-               if (fcntl(fd, F_SETFL, 0) < 0)
+               if (fcntl(fd, F_SETFL, 0) < 0 ||
+                   fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
                {
                        perror("CRIT: fcntl() failed");
                }
@@ -1032,18 +1035,3 @@ int start()
                close(fd);
        }
 }
-
-int main(int argc, char **argv)
-{
-       courier_authdebug_login_init();
-
-       if (argc > 1)
-       {
-               fprintf(stderr, "Error: authdaemond no longer handles its own daemonizing.\n"
-                       "Use new startup script.\n");
-               exit(1);
-       }
-
-       start();
-       return (0);
-}
diff --git a/authdaemondcpp.cpp b/authdaemondcpp.cpp
new file mode 100644 (file)
index 0000000..4d7f8d7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+** Copyright 2016 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#include <iostream>
+#include <stdlib.h>
+
+extern "C" {
+
+#include "courierauthdebug.h"
+
+       int start();
+};
+
+int main(int argc, char **argv)
+{
+       courier_authdebug_login_init();
+
+       if (argc > 1)
+       {
+               std::cerr <<
+                       "Error: authdaemond no longer handles its own daemonizing."
+                         << std::endl
+                         << "Use new startup script." << std::endl;
+               exit(1);
+       }
+
+       start();
+       return (0);
+}
index 7d81ef4..19e8506 100644 (file)
@@ -1,4 +1,4 @@
-##VERSION: $Id: 7b218a8185f424046f3ef3322a37443983e443e3-20150228120722$
+##VERSION: $Id: 7b218a8185f424046f3ef3322a37443983e443e3-20160104202005$
 #
 # Copyright 2000-2005 Double Precision, Inc.  See COPYING for
 # distribution information.
diff --git a/authgetconfig.c b/authgetconfig.c
deleted file mode 100644 (file)
index 0156797..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
-** Copyright 2012-2015 Double Precision, Inc.  See COPYING for
-** distribution information.
-*/
-
-#if    HAVE_CONFIG_H
-#include       "courier_auth_config.h"
-#endif
-#include       "auth.h"
-#include       "courierauthdebug.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-static const char *configfilename=0;
-static char *configauth=0;
-static size_t configauth_size=0;
-
-#define err courier_auth_err
-
-const char *authgetconfig(const char *filename, const char *env)
-{
-       size_t  i;
-       char    *p=0;
-       int     l=strlen(env);
-
-       if (configfilename && strcmp(filename, configfilename))
-       {
-               if (configauth)
-                       free(configauth);
-               configauth=0;
-               configauth_size=0;
-       }
-
-       configfilename=filename;
-
-       if (!configauth)
-       {
-               FILE    *f=fopen(filename, "r");
-               struct  stat    buf;
-
-               if (!f) return (0);
-               if (fstat(fileno(f), &buf) ||
-                       (configauth=malloc(buf.st_size+2)) == 0)
-               {
-                       fclose(f);
-                       return (0);
-               }
-               if (fread(configauth, buf.st_size, 1, f) != 1)
-               {
-                       free(configauth);
-                       configauth=0;
-                       fclose(f);
-                       return (0);
-               }
-               configauth[configauth_size=buf.st_size]=0;
-
-               for (i=0; i<configauth_size; i++)
-                       if (configauth[i] == '\n')
-                       {       /* siefca@pld.org.pl */
-                               if (!i || configauth[i-1] != '\\')
-                               {
-                                       configauth[i]='\0';
-                               }
-                               else
-                               {
-                                       configauth[i]=configauth[i-1]= ' ';
-                               }
-                       }
-               fclose(f);
-       }
-
-       for (i=0; i<configauth_size; )
-       {
-               p=configauth+i;
-               if (strncmp(p, env, l) == 0 &&
-                       isspace((int)(unsigned char)p[l]))
-               {
-                       p += l;
-                       while (*p && *p != '\n' &&
-                               isspace((int)(unsigned char)*p))
-                               ++p;
-                       break;
-               }
-
-               while (i < configauth_size)
-                       if (configauth[i++] == 0)       break;
-       }
-
-       if (i < configauth_size)
-               return (p);
-       return (0);
-}
-
-/* siefca@pld.org.pl */
-#define                MAX_SUBSTITUTION_LEN    32
-#define                SV_BEGIN_MARK           "$("
-#define                SV_END_MARK             ")"
-#define                SV_BEGIN_LEN            ((sizeof(SV_BEGIN_MARK))-1)
-#define                SV_END_LEN              ((sizeof(SV_END_MARK))-1)
-
-/* siefca@pld.org.pl */
-struct var_data {
-       const char *name;
-       const char *value;
-       const size_t size;
-       size_t value_length;
-       } ;
-
-/* siefca@pld.org.pl */
-typedef int (*parsefunc)(const char *, size_t, void *);
-
-/* siefca@pld.org.pl */
-static struct var_data *get_variable (const char *begin, size_t len,
-                                     struct var_data *vdt)
-{
-struct var_data *vdp;
-
-       if (!begin || !vdt) /* should never happend */
-       {
-               err("get_variable: critical error while "
-                                "parsing substitution variable");
-               return NULL;
-       }
-       if (len < 1)
-       {
-               err("get_variable: unknown empty substitution "
-                                "variable - aborting");
-               return NULL;
-       }
-       if (len > MAX_SUBSTITUTION_LEN)
-       {
-               err("get_variable: variable name too long "
-                                "while parsing substitution. "
-                                "name begins with "
-                                SV_BEGIN_MARK
-                                "%.*s...", MAX_SUBSTITUTION_LEN, begin);
-               return NULL;
-       }
-
-       for (vdp=vdt; vdp->name; vdp++)
-               if (vdp->size == len+1 &&
-                   !strncmp(begin, vdp->name, len))
-               {
-                       if (!vdp->value)
-                               vdp->value = "";
-                       if (!vdp->value_length)         /* length cache */
-                               vdp->value_length = strlen (vdp->value);
-                       return vdp;
-               }
-
-       err("get_variable: unknown substitution variable "
-                        SV_BEGIN_MARK
-                        "%.*s"
-                        SV_END_MARK
-                        , (int)len, begin);
-
-       return NULL;
-}
-
-/* siefca@pld.org.pl */
-static int ParsePlugin_counter (const char *p, size_t length, void *vp)
-{
-       if (!p || !vp || length < 0)
-       {
-               err("get_variable: bad arguments while counting "
-                                "query string");
-               return -1;
-       }
-
-       *((size_t *)vp) += length;
-
-       return 0;
-}
-
-/* siefca@pld.org.pl */
-static int ParsePlugin_builder (const char *p, size_t length, void *vp)
-{
-char   **strptr = (char **) vp;
-
-       if (!p || !vp || length < 0)
-       {
-               err("get_variable: bad arguments while building "
-                                "query string");
-               return -1;
-       }
-
-       if (!length) return 0;
-       memcpy ((void *) *strptr, (void *) p, length);
-       *strptr += length;
-
-       return 0;
-}
-
-/* siefca@pld.org.pl */
-static int parse_core  (const char *source, struct var_data *vdt,
-                       parsefunc outfn, void *result)
-{
-size_t v_size          = 0,
-       t_size          = 0;
-const char     *p, *q, *e,
-               *v_begin, *v_end,
-               *t_begin, *t_end;
-struct var_data        *v_ptr;
-
-       if (!source)
-               source = "";
-       if (!result)
-       {
-               err("auth_parse: no memory allocated for result "
-                                "while parser core was invoked");
-               return -1;
-       }
-       if (!vdt)
-       {
-               err("auth_parse: no substitution table found "
-                                "while parser core was invoked");
-               return -1;
-       }
-
-       q = source;
-       while ( (p=strstr(q, SV_BEGIN_MARK)) )
-       {
-               e = strstr (p, SV_END_MARK);
-               if (!e)
-               {
-                       err("auth_parse: syntax error in "
-                                        "substitution "
-                                        "- no closing symbol found! "
-                                        "bad variable begins with:"
-                                        "%.*s...", MAX_SUBSTITUTION_LEN, p);
-                       return -1;
-               }
-
-               /*
-                **
-                **          __________sometext$(variable_name)_________
-                **                    |      |  |           |
-                **             t_begin' t_end'  `v_begin    `v_end
-                **
-                 */
-
-               v_begin = p+SV_BEGIN_LEN; /* variable field ptr             */
-               v_end   = e-SV_END_LEN;   /* variable field last character  */
-               v_size  = v_end-v_begin+1;/* variable field length          */
-
-               t_begin = q;              /* text field ptr                 */
-               t_end   = p-1;            /* text field last character      */
-               t_size  = t_end-t_begin+1;/* text field length              */
-
-               /* work on text */
-               if ( (outfn (t_begin, t_size, result)) == -1 )
-                       return -1;
-
-               /* work on variable */
-               v_ptr = get_variable (v_begin, v_size, vdt);
-               if (!v_ptr) return -1;
-
-               if ( (outfn (v_ptr->value, v_ptr->value_length, result)) == -1 )
-                       return -1;
-
-               q = e + 1;
-       }
-
-       /* work on last part of text if any */
-       if (*q != '\0')
-               if ( (outfn (q, strlen(q), result)) == -1 )
-                       return -1;
-
-       return 0;
-}
-
-/* siefca@pld.org.pl */
-static char *parse_string (const char *source, struct var_data *vdt)
-{
-struct var_data *vdp   = NULL;
-char   *output_buf     = NULL,
-       *pass_buf       = NULL;
-size_t buf_size        = 2;
-
-       if (source == NULL || *source == '\0' ||
-           vdt == NULL    || vdt[0].name == NULL)
-       {
-               err("auth_parse: source clause is empty "
-                      "- this is critical error");
-               return NULL;
-       }
-
-       /* zero var_data length cache - important! */
-       for (vdp=vdt; vdp->name; vdp++)
-               vdp->value_length = 0;
-
-
-       /* phase 1 - count and validate string */
-       if ( (parse_core (source, vdt, &ParsePlugin_counter, &buf_size)) != 0)
-               return NULL;
-
-       /* phase 2 - allocate memory */
-       output_buf = malloc (buf_size);
-       if (!output_buf)
-       {
-               perror ("malloc");
-               return NULL;
-       }
-       pass_buf = output_buf;
-
-       /* phase 3 - build the output string */
-       if ( (parse_core (source, vdt, &ParsePlugin_builder, &pass_buf)) != 0)
-       {
-               free (output_buf);
-               return NULL;
-       }
-       *pass_buf = '\0';
-
-       return output_buf;
-}
-
-static char *local_part_escaped(const char *username,
-                               char *(*escape_func)(const char *, size_t))
-{
-       const char *p=strchr(username, '@');
-       size_t n=p ? p-username:strlen(username);
-
-       return escape_func(username, n);
-}
-
-static char *domain_part_escaped(const char *username,
-                                const char *defdomain,
-                                char *(*escape_func)(const char *, size_t))
-{
-       const char *p=strchr(username, '@');
-       size_t n;
-
-       if (p)
-               ++p;
-       else
-               p=defdomain;
-
-       n=strlen(p);
-
-       return escape_func(p, n);
-}
-
-static int local_and_domain_part_escaped(char *(*escape_func)(const char *, size_t),
-                                        const char *username,
-                                        const char *defdomain,
-                                        char **local_ret,
-                                        char **domain_ret)
-{
-       if ((*local_ret=local_part_escaped(username, escape_func)) == NULL)
-               return 0;
-
-       if ((*domain_ret=domain_part_escaped(username, defdomain,
-                                            escape_func)) == NULL)
-       {
-               free(*local_ret);
-               return 0;
-       }
-
-       return 1;
-}
-
-/* siefca@pld.org.pl */
-char *auth_parse_select_clause (char *(*escape_func)(const char *, size_t),
-                               const char *clause, const char *username,
-                               const char *defdomain,
-                               const char *service)
-{
-       char *str;
-
-       static struct var_data vd[]={
-               {"local_part",  NULL,   sizeof("local_part"),   0},
-               {"domain",              NULL,   sizeof("domain"),       0},
-               {"service",             NULL,   sizeof("service"),      0},
-               {NULL,          NULL,   0,                      0}};
-
-       char *l_part;
-       char *d_part;
-
-       if (clause == NULL || *clause == '\0' ||
-           !username || *username == '\0')
-               return NULL;
-
-       if (!local_and_domain_part_escaped(escape_func,
-                                          username, defdomain,
-                                          &l_part, &d_part))
-               return NULL;
-
-       vd[0].value=l_part;
-       vd[1].value=d_part;
-       vd[2].value     = service;
-
-       str=parse_string (clause, vd);
-       free(l_part);
-       free(d_part);
-       return str;
-}
-
-/* siefca@pld.org.pl */
-char *auth_parse_chpass_clause (char *(*escape_func)(const char *, size_t),
-                               const char *clause, const char *username,
-                               const char *defdomain, const char *newpass,
-                               const char *newpass_crypt)
-{
-       char *str;
-
-       static struct var_data vd[]={
-               {"local_part",  NULL,   sizeof("local_part"),           0},
-               {"domain",      NULL,   sizeof("domain"),               0},
-               {"newpass",     NULL,   sizeof("newpass"),              0},
-               {"newpass_crypt", NULL, sizeof("newpass_crypt"),        0},
-               {NULL,          NULL,   0,                              0}};
-       char *l_part;
-       char *d_part;
-
-       if (clause == NULL || *clause == '\0'           ||
-           !username || *username == '\0'              ||
-           !newpass || *newpass == '\0'                ||
-           !newpass_crypt || *newpass_crypt == '\0')   return NULL;
-
-       if (!local_and_domain_part_escaped(escape_func,
-                                          username, defdomain,
-                                          &l_part, &d_part))
-               return NULL;
-
-       vd[0].value=l_part;
-       vd[1].value=d_part;
-       vd[2].value     = newpass;
-       vd[3].value     = newpass_crypt;
-
-       if (!vd[0].value || !vd[1].value ||
-           !vd[2].value || !vd[3].value)
-       {
-               free(l_part);
-               free(d_part);
-               return NULL;
-       }
-
-       str=parse_string (clause, vd);
-       free(l_part);
-       free(d_part);
-       return str;
-}
index 37323f0..d69cde1 100644 (file)
 
 #include       "auth.h"
 #include       "authldap.h"
+#include       "courierauth.h"
 #include       "courierauthstaticlist.h"
 #include       "courierauthdebug.h"
-
-
-extern void auth_ldap_enumerate( void(*cb_func)(const char *name,
-                                               uid_t uid,
-                                               gid_t gid,
-                                               const char *homedir,
-                                               const char *maildir,
-                                               const char *options,
-                                               void *void_arg),
-                                void *void_arg);
+#include       "libhmac/hmac.h"
 
 static int auth_ldap_login(const char *service, char *authdata,
                           int (*callback_func)(struct authinfo *, void *),
@@ -45,9 +37,6 @@ static int auth_ldap_login(const char *service, char *authdata,
                              callback_arg);
 }
 
-#include       "libhmac/hmac.h"
-#include       "cramlib.h"
-
 static int auth_ldap_cram(const char *service,
                          const char *authtype, char *authdata,
                          int (*callback_func)(struct authinfo *, void *),
@@ -81,9 +70,6 @@ extern int auth_ldap_pre(const char *userid, const char *service,
         int (*callback)(struct authinfo *, void *),
                  void *arg);
 
-extern int auth_ldap_changepw(const char *, const char *, const char *,
-                             const char *);
-
 static struct authstaticinfo authldap_info={
        "authldap",
        auth_ldap,
index 534f8d4..ba18b48 100644 (file)
@@ -21,4 +21,17 @@ int authldapcommon(const char *, const char *,
 
 void authldapclose();
 
+void auth_ldap_enumerate( void(*cb_func)(const char *name,
+                                        uid_t uid,
+                                        gid_t gid,
+                                        const char *homedir,
+                                        const char *maildir,
+                                        const char *options,
+                                               void *void_arg),
+                         void *void_arg);
+
+int auth_ldap_changepw(const char *, const char *, const char *,
+                      const char *);
+
+
 #endif
diff --git a/authldaplib.c b/authldaplib.c
deleted file mode 100644 (file)
index 39b0245..0000000
+++ /dev/null
@@ -1,2067 +0,0 @@
-/*
- * authldap.c - 
- *
- * courier-imap - 
- * 
- * Copyright 1999 Luc Saillard <luc.saillard@alcove.fr>.
- *
- * This module use a server LDAP to authenticate user.
- * See the README.ldap
- *
- * This program 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 2
- * of the License, 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; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301, USA.
- */
-
-/*
- * Modified 28/11/2001 Iustin Pop <iusty@intensit.de>
- * There was a bug regarding the LDAP_TLS option: if both LDAP_TLS
- * and was LDAP_AUTHBIND were enabled, the ldap_start_tls function
- * was called only for the first connection, resulting in the fact
- * that the bind for checking the password was done without TLS,
- * sending the password in clear text over the network. Detected 
- * when using OpenLDAP with "security ssf=128" (which disalows any 
- * clear-text communication).
-*/
-
-/*
-   Modified 01/21/2000 James Golovich <james@wwnet.net>
-
-1. If LDAP_AUTHBIND is set in the config file, then the ldap server will
-handle passwords via authenticated binds, instead of checking these
-internally.
-2. Changed paramaters for authldap_get to include pass.
-
-*/
-
-/*
-   Modified 12/31/99 Sam Varshavchik:
-
-1. read_env reads from a configuration file, instead of the environment
-2. read_config appropriately modified.
-3. If 'user' contains the @ character, domain from config is NOT appended.
-4. added 'homeDir' attribute.  Use 'homeDir' instead of mailDir, and put
-   mailDir into MAILDIR=
-5. read_config renamed to authldap_read_config
-6. get_user_info renamed to authldap_get
-7. Added authldap_free_config, to clean up all the allocated memory
-   (required for preauthldap).
-8. Output LDAP attributes are defined in the configuration file as well.
-9. Allow both plaintext and crypted passwords to be read from LDAP.
-10. Added GLOB_UID GLOB_GID, as well as UID and GID params.
-
-2/19/2000 Sam.
-
-Rewrite to allow this code to be used in a long-running authentication daemon
-(for Courier).  authldap_get renamed to authldapcommon, will initialize and
-maintain a persistent connection.  Password checking moved entirely to
-authldap.c.  authldapclose() will unbind and close the connection.
-
-connection gets closed and reopened automatically after a protocol error.
-
-error return from authldapcommon will indicate whether this is a transient,
-or a permanent failure.
-
-authldap_free_config removed - no longer required.
-
-*/
-
-#if HAVE_CONFIG_H
-#include "courier_auth_config.h"
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <time.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_LBER_H
-#include <lber.h>
-#endif
-#if HAVE_LDAP_H
-#include <ldap.h>
-#if LDAP_VENDOR_VERSION > 20000
-#define OPENLDAPV2
-#endif
-#endif
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#include "authldap.h"
-#include "auth.h"
-#include "authldaprc.h"
-#include "courierauthdebug.h"
-
-#define err courier_auth_err
-
-#ifndef DEBUG_LDAP
-#define DEBUG_LDAP 0
-#endif
-
-#ifndef        LDAP_OPT_SUCCESS
-#define LDAP_OPT_SUCCESS LDAP_SUCCESS
-#endif
-
-static char **l_get_values(LDAP *ld, LDAPMessage *entry, const char *attribut)
-{
-       struct berval **p=ldap_get_values_len(ld, entry, attribut);
-       int i, n;
-       char **a;
-
-       if (!p)
-               return NULL;
-
-       n=ldap_count_values_len(p);
-
-
-       a=malloc((n + 1) * sizeof(char *));
-
-       if (!a)
-       {
-               DPRINTF("malloc failed");
-               ldap_value_free_len(p);
-               return NULL;
-       }
-
-       for (i=0; i<n; i++)
-       {
-               if ((a[i]=malloc(p[i]->bv_len+1)) == NULL)
-               {
-                       DPRINTF("malloc failed");
-                       while (i--)
-                       {
-                               free(a[i]);
-                       }
-                       free(a);
-                       ldap_value_free_len(p);
-                       return NULL;
-               }
-
-               memcpy(a[i], p[i]->bv_val, p[i]->bv_len);
-               a[i][p[i]->bv_len]=0;
-       }
-
-       ldap_value_free_len(p);
-       a[i]=NULL;
-       return a;
-}
-
-static void l_value_free(char **p)
-{
-       int i;
-
-       for (i=0; p[i]; ++i)
-               free(p[i]);
-       free(p);
-}
-
-static int l_count_values(char **p)
-{
-       int i;
-
-       for (i=0; p[i]; ++i)
-               ;
-       return i;
-}
-
-static int l_unbind(LDAP *ld)
-{
-       return ldap_unbind_ext(ld, NULL, NULL);
-}
-
-static int l_simple_bind_s(LDAP *ld,
-                          const char *who,
-                          const char *passwd)
-{
-       struct berval cred;
-
-       cred.bv_len=passwd ? strlen(passwd):0;
-       cred.bv_val=(char *)passwd;
-
-       return ldap_sasl_bind_s(ld, who, NULL, &cred, NULL, NULL, NULL);
-}
-
-static int l_search_st(LDAP *ld,
-                      const char *base,
-                      int scope,
-                      const char *filter,
-                      char **attrs,
-                      int attrsonly,
-                      struct timeval *timeout,
-                      LDAPMessage **res)
-{
-       return ldap_search_ext_s(ld, base, scope, filter, attrs,
-                                attrsonly,
-                                NULL, NULL,
-                                timeout,
-                                100,
-                                res);
-}
-
-static int l_modify_s(LDAP *ld,
-                     const char *dn,
-                     LDAPMod **mods)
-{
-       return ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
-}
-
-static int l_search(LDAP *ld,
-                   const char *base,
-                   int scope,
-                   const char *filter,
-                   char **attrs,
-                   int attrsonly)
-{
-       struct timeval tv;
-       int msgid;
-
-       tv.tv_sec=60*60;
-       tv.tv_usec=0;
-
-       if (ldap_search_ext(ld, base, scope, filter, attrs, attrsonly,
-                           NULL, NULL, &tv, 1000000, &msgid) !=
-           LDAP_SUCCESS)
-               return -1;
-
-       return msgid;
-}
-
-struct ldap_info
-{
-       const char *uri;
-       const char *binddn;
-       const char *bindpw;
-       const char *basedn;
-       const char *mail;
-        const char *filter;
-        const char *enumerate_filter;
-       const char *domain;
-
-       uid_t uid;
-       gid_t gid;
-       int   timeout;
-       int   authbind;
-        int   initbind;
-       int   deref;
-       int   protocol_version;
-       int   tls;
-
-       const char *mailroot;
-
-       char **auxoptions;
-       char **auxnames;
-       const char **attrlist;
-
-       /* Optional emailmap to handle */
-
-       const char *emailmap;
-       const char *emailmap_basedn;
-       const char *emailmap_handle;
-       const char *emailmap_handle_lookup;
-};
-
-/*
-** There's a memory leak in OpenLDAP 1.2.11, presumably in earlier versions
-** too.  See http://www.OpenLDAP.org/its/index.cgi?findid=864 for more
-** information.  To work around the bug, the first time a connection fails
-** we stop trying for 60 seconds.  After 60 seconds we kill the process,
-** and let the parent process restart it.
-**
-** We'll control this behavior via LDAP_MEMORY_LEAK.  Set it to ZERO to turn
-** off this behavior (whenever OpenLDAP gets fixed).
-*/
-
-static time_t ldapfailflag=0;
-
-static void ldapconnfailure()
-{
-       const char *p=getenv("LDAP_MEMORY_LEAK");
-
-       if (!p)
-       {
-#ifdef LDAP_VENDOR_NAME
-#ifdef LDAP_VENDOR_VERSION
-#define DO_OPENLDAP_CHECK
-#endif
-#endif
-
-#ifdef DO_OPENLDAP_CHECK
-
-               /* It's supposed to be fixed in 20019 */
-
-               if (strcmp(LDAP_VENDOR_NAME, "OpenLDAP") == 0 &&
-                   LDAP_VENDOR_VERSION < 20019)
-                       p="1";
-               else
-                       p="0";
-#else
-               p="0";
-#endif
-       }
-
-       if (atoi(p) && !ldapfailflag)
-       {
-               time(&ldapfailflag);
-               ldapfailflag += 60;
-       }
-}
-
-static int ldapconncheck()
-{
-       time_t t;
-
-       if (!ldapfailflag)
-               return (0);
-
-       time(&t);
-
-       if (t >= ldapfailflag)
-               exit(0);
-       return (1);
-}
-
-static int read_env(const char *env, const char **copy,
-       const char *errstr, int needit, const char *value_default);
-static void copy_value(LDAP *ld, LDAPMessage *entry, const char *attribut,
-       char **copy, const char *username);
-
-/*
- * Function: read_env
- * Copy the environnement $env and copy to $copy if not null
- * if needit is false, and env doesn't exist, copy $value_default to $copy
- * INPUT:
- *   $env: pointer to the environnement name
- *   $copy: where the value go
- *   $err: print a nice message when $env not_found and $needit is true
- *   $needit: if $needit is true and $value not found, return a error
- *   $value_default: the default value when $needit is false and $env doesn't exists
- * OUTPUT:
- *   boolean
- */
-static int read_env(const char *env, const char **copy,
-       const char *errstr, int needit, const char *value_default)
-{
-static char *ldapauth=0;
-static size_t ldapauth_size=0;
-size_t i;
-char   *p=0;
-int    l=strlen(env);
-
-       if (!ldapauth)
-       {
-       FILE    *f=fopen(AUTHLDAPRC, "r");
-       struct  stat    buf;
-
-               if (!f) return (0);
-               if (fstat(fileno(f), &buf) ||
-                       (ldapauth=malloc(buf.st_size+2)) == 0)
-               {
-                       fclose(f);
-                       return (0);
-               }
-               if (fread(ldapauth, buf.st_size, 1, f) != 1)
-               {
-                       free(ldapauth);
-                       ldapauth=0;
-                       fclose(f);
-                       return (0);
-               }
-               ldapauth[ldapauth_size=buf.st_size]=0;
-
-               for (i=0; i<ldapauth_size; i++)
-                       if (ldapauth[i] == '\n')
-                               ldapauth[i]=0;
-               fclose(f);
-       }
-
-       for (i=0; i<ldapauth_size; )
-       {
-               p=ldapauth+i;
-               if (memcmp(p, env, l) == 0 &&
-                       isspace((int)(unsigned char)p[l]))
-               {
-                       p += l;
-                       while (*p && *p != '\n' &&
-                               isspace((int)(unsigned char)*p))
-                               ++p;
-                       break;
-               }
-
-               while (i < ldapauth_size)
-                       if (ldapauth[i++] == 0) break;
-       }
-
-       if (i < ldapauth_size)
-       {
-               *copy= p;
-               return (1);
-       }
-
-       if (needit)
-       {
-               err("%s", errstr);
-               return 0;
-       }
-
-       *copy=0;
-       if (value_default)
-               *copy=value_default;
-
-       return 1;
-}
-
-/*
- * Function: authldap_read_config
- *   Read Configuration from the environnement table
- * INPUT:
- *   $ldap: a structure where we place information
- * OUTPUT:
- *   boolean
- */
-static int authldap_read_config(struct ldap_info *ldap)
-{
-       struct passwd *pwent;
-       struct group  *grent;
-       const char *p;
-       size_t i, pass;
-
-       for (i=0; ldap->auxoptions && ldap->auxoptions[i]; i++)
-               free(ldap->auxoptions[i]);
-       for (i=0; ldap->auxnames && ldap->auxnames[i]; i++)
-               free(ldap->auxnames[i]);
-
-       if (ldap->attrlist)
-               free(ldap->attrlist);
-       if (ldap->auxnames)
-               free(ldap->auxnames);
-       if (ldap->auxoptions)
-               free(ldap->auxoptions);
-
-       memset(ldap,0,sizeof(struct ldap_info));
-       
-       if (!read_env("LDAP_URI",&ldap->uri,
-                     "You need to specify LDAP_URI in config file",1,NULL))
-               return 0;
-
-       if (!read_env("LDAP_AUTHBIND", &p, "", 0, ""))
-               return (0);
-
-       if (p)
-               sscanf(p,"%d",&ldap->authbind);
-
-       if (!read_env("LDAP_INITBIND", &p, "", 0, "1"))
-               return (0);
-
-       if (p)
-               sscanf(p,"%d",&ldap->initbind);
-
-       if (!read_env("LDAP_BASEDN",&ldap->basedn,
-                     "You need to specify a basedn in config file",1,NULL))
-               return 0;
-       if (!read_env("LDAP_BINDDN",&ldap->binddn,
-                     "You need to specify a BINDDN in config file",0,NULL))
-               return 0;
-       if (!read_env("LDAP_BINDPW",&ldap->bindpw,
-                     "You need to specify a password for the BINDDN in config file",0,NULL))
-               return 0;
-       if (!read_env("LDAP_MAIL",&ldap->mail,
-                     "You need to specify a attribute for mail in config file",0,"mail"))
-               return 0;
-       if (!read_env("LDAP_DOMAIN",&ldap->domain,
-                     "You need to specify a domain for mail in config file",0,""))
-               return 0;
-
-       p=0;
-       ldap->uid=0;
-       if (!read_env("LDAP_GLOB_UID", &p, "", 0, ""))
-               return (0);
-
-       if (p && *p)
-       {
-               unsigned long n;
-
-               if (sscanf(p, "%lu", &n) == 1)
-                       ldap->uid=(uid_t)n;
-               else
-               {
-                       pwent=getpwnam(p);
-                       if (!pwent)
-                       {
-                               err("authldap: INVALID LDAP_GLOB_UID");
-                               return (0);
-                       }
-                       ldap->uid=pwent->pw_uid;
-               }
-       }
-
-       ldap->gid=0;
-       p=0;
-       if (!read_env("LDAP_GLOB_GID", &p, "", 0, ""))
-               return (0);
-
-       if (p && *p)
-       {
-               unsigned long n;
-
-               if (sscanf(p, "%lu", &n) == 1)
-                       ldap->gid=(gid_t)n;
-               else
-               {
-                       grent=getgrnam(p);
-                       if (!grent)
-                       {
-                               err("authldap: INVALID LDAP_GLOB_GID");
-                               return (0);
-                       }
-                       ldap->gid=grent->gr_gid;
-               }
-       }
-
-       ldap->timeout=5;
-       p=0;
-       if (read_env("LDAP_TIMEOUT", &p, "", 0, "") && p)
-       {
-               sscanf(p,"%d",&ldap->timeout);
-       }
-
-       ldap->tls=0;
-       p=0;
-       if (read_env("LDAP_TLS", &p, "", 0, "") && p)
-       {
-               ldap->tls=atoi(p);
-       }
-
-       ldap->filter=0;
-       p=0;
-       if (read_env("LDAP_FILTER", &p, "", 0, "") && p && strlen (p))
-       {
-               ldap->filter=p;
-       }
-
-       ldap->enumerate_filter=0;
-       p=0;
-       if (read_env("LDAP_ENUMERATE_FILTER", &p, "", 0, "") && p && strlen (p))
-       {
-               ldap->enumerate_filter=p;
-       }
-       else if (ldap->filter)
-       {
-               ldap->enumerate_filter=ldap->filter;
-       }
-       else
-       {
-               ldap->enumerate_filter = malloc(strlen(ldap->mail)+3);
-               if (!ldap->enumerate_filter)
-               {
-                       perror("CRIT: authldap: malloc failed");
-                       return 0;
-               }
-               sprintf((char *)ldap->enumerate_filter, "%s=*", ldap->mail);
-       }
-
-       ldap->deref = LDAP_DEREF_NEVER; 
-       ldap->protocol_version = 0;     /* use API default */
-       p=0;
-       if (!read_env("LDAP_DEREF", &p, "", 0, ""))
-               return (0);
-       if (p)
-       {
-#ifndef LDAP_OPT_DEREF
-               err("authldaplib: LDAP_OPT_DEREF not available, ignored");
-#endif
-               if (!strcasecmp (p, "never"))
-                       ldap->deref = LDAP_DEREF_NEVER;
-               else if (!strcasecmp (p, "searching"))
-                       ldap->deref = LDAP_DEREF_SEARCHING;
-               else if (!strcasecmp (p, "finding"))
-                       ldap->deref = LDAP_DEREF_FINDING;
-               else if (!strcasecmp (p, "always"))
-                       ldap->deref = LDAP_DEREF_ALWAYS; 
-       }
-
-       if (!read_env("LDAP_PROTOCOL_VERSION", &p, 0, 0, 0))
-               return (0);
-       if (p)
-       {
-       int lpv = atoi(p);
-#ifndef LDAP_OPT_PROTOCOL_VERSION
-               err("authldaplib: LDAP_OPT_PROTOCOL_VERSION not available, ignored");
-#endif
-               if (lpv == 0
-#ifdef LDAP_VERSION_MIN
-                       || lpv < LDAP_VERSION_MIN
-#endif
-#ifdef LDAP_VERSION_MAX
-                       || lpv > LDAP_VERSION_MAX
-#endif
-               )
-                       err("authldaplib: illegal protocol version ignored");
-               else
-                       ldap->protocol_version = lpv;
-       }
-
-       if (!read_env("LDAP_MAILROOT",&ldap->mailroot,"",0,NULL)
-           || ldap->mailroot == NULL || ldap->mailroot[0] == 0)
-               ldap->mailroot=NULL;
-
-       if (!read_env("LDAP_EMAILMAP", &ldap->emailmap, "", 0, "") ||
-           !read_env("LDAP_EMAILMAP_BASEDN", &ldap->emailmap_basedn, "", 0, "") ||
-           !read_env("LDAP_EMAILMAP_ATTRIBUTE", &ldap->emailmap_handle, "", 0, "")||
-           !read_env("LDAP_EMAILMAP_MAIL",
-                     &ldap->emailmap_handle_lookup, "", 0, ""))
-               return (0);
-
-
-       for (pass=0; pass<2; pass++)
-       {
-               if (pass)
-               {
-                       if ((ldap->auxnames=malloc((i+1)*sizeof(char *)))
-                           == NULL ||
-                           (ldap->auxoptions=malloc((i+1)*sizeof(char *)))
-                           == NULL)
-                       {
-                               perror("CRIT: authldap: malloc failed");
-                               if (ldap->auxnames)
-                                       ldap->auxnames[0]=0;
-                               return 0;
-                       }
-               }
-               i=0;
-
-               if (pass)
-               {
-                       ldap->auxnames[0]=NULL;
-                       ldap->auxoptions[0]=NULL;
-               }
-
-               if (!read_env("LDAP_AUXOPTIONS", &p, "", 0, NULL)
-                   || p == NULL || *p == 0)
-                       p=NULL;
-
-               while (p && *p)
-               {
-                       size_t n;
-
-                       if (*p == ',')
-                       {
-                               ++p;
-                               continue;
-                       }
-
-                       for (n=0; p[n] && p[n] != ',' && p[n] != '='; n++)
-                               ;
-
-                       if (pass)
-                       {
-                               if ((ldap->auxoptions[i]=malloc(n+1)) == NULL)
-                               {
-                                       perror("CRIT: authldap: malloc failed");
-                                       return 0;
-                               }
-
-                               memcpy(ldap->auxoptions[i], p, n);
-                               ldap->auxoptions[i][n]=0;
-                               ldap->auxoptions[i+1]=NULL;
-                       }
-
-                       p += n;
-
-                       if (*p == '=') ++p;
-
-                       for (n=0; p[n] && p[n] != ','; n++)
-                               ;
-
-                       if (pass)
-                       {
-                               if (n == 0)
-                               {
-                                       if ((ldap->auxnames[i]=
-                                            strdup(ldap->auxoptions[i]))
-                                           == NULL)
-                                       {
-                                               perror("CRIT: authldap: malloc failed");
-                                               return 0;
-                                       }
-                               }
-                               else if ((ldap->auxnames[i]=malloc(n+1)) == NULL)
-                               {
-                                       perror("CRIT: authldap: malloc failed");
-                                       return 0;
-                               }
-                               else
-                               {
-                                       memcpy(ldap->auxnames[i], p, n);
-                                       ldap->auxnames[i][n]=0;
-                                       ldap->auxnames[i+1]=NULL;
-                               }
-                       }
-                       p += n;
-                       ++i;
-               }
-       }
-
-       if ((ldap->attrlist=malloc((i+20)*sizeof(const char *))) == NULL)
-       {
-               perror("CRIT: authldap: malloc failed");
-               return 0;
-       }
-
-       return 1;
-}
-
-static void get_error(LDAP *ld, LDAPMessage *entry,
-                     const char *func,
-                     const char *attribut)
-{
-#if HAVE_LDAP_PARSE_RESULT
-
-       int errcode;
-       char *nmatched;
-       char *errmsg;
-               
-
-       if (ldap_parse_result(ld, entry, &errcode, &nmatched,
-                             &errmsg, NULL, NULL, 0)
-           != LDAP_SUCCESS)
-       {
-               DPRINTF("ldap_parseresult failed");
-       }
-       else
-       {
-               if (errcode && errcode != LDAP_DECODING_ERROR &&
-                   errcode != LDAP_NO_RESULTS_RETURNED)
-               {
-                       DPRINTF("get_values attribute %s: %s",
-                               attribut,
-                               errmsg ? errmsg:"unknown error");
-               }
-
-               if (errmsg)
-                       ldap_memfree(errmsg);
-               if (nmatched)
-                       ldap_memfree(nmatched);
-       }
-#else
-#if HAVE_LDAP_RESULT2ERROR
-       int ld_errno = ldap_result2error(ld,entry,0);
-       if (ld_errno && ld_errno != LDAP_DECODING_ERROR
-           && ld_errno != LDAP_NO_RESULTS_RETURNED)
-       {
-               DPRINTF("get_values attribute %s: %s", attribut,
-                       ldap_err2string(ld_errno));
-       }
-#else
-       if (ld->ld_errno != LDAP_DECODING_ERROR
-           && ld->ld_errno != LDAP_NO_RESULTS_RETURNED)
-       {
-               DPRINTF("get_values attribute %s: %s", attribut,
-                       ldap_err2string(ld->ld_errno));
-       }
-#endif
-#endif
-}
-
-static char **get_values(LDAP *ld, LDAPMessage *entry, const char *attribut)
-{
-       char ** values;
-       values=l_get_values(ld,entry, (char *)attribut);
-
-       if (values==NULL)
-       {
-               get_error(ld, entry, "get_values", attribut);
-       }
-
-       return values;
-}
-
-
-
-/*
- * Function: copy_value
- *   Copy value from a LDAP attribute to $copy
- * INPUT:
- *   $ld:       the connection with the LDAP server
- *   $entry:    the entry who contains attributes
- *   $attribut: this attribut
- *   $copy:     where data can go
- * OUTPUT:
- *   void
- */
-static void copy_value(LDAP *ld, LDAPMessage *entry, const char *attribut,
-                      char **copy, const char *username)
-{
-       char ** values;
-       values=l_get_values(ld,entry, attribut);
-
-       if (values==NULL)
-       {
-               get_error(ld, entry, "copy_value ", attribut);
-               *copy=NULL;
-               return;
-       }
-  /* We accept only attribute with one value */
-       else if (l_count_values(values)>1)
-        {
-                *copy=strdup(values[0]);
-                fprintf(stderr, "WARN: authldaplib: duplicate attribute %s for %s\n",
-                       attribut,
-                       username);
-                *copy=NULL;
-        }
-  /* We accept only attribute with one value */
-       else if (l_count_values(values)!=1)
-        {
-                *copy=NULL;
-        }
-  else
-        {
-                *copy=strdup(values[0]);
-        }
-#if DEBUG_LDAP
-  DPRINTF("copy_value %s: %s",attribut,values[0]);
-#endif
-  l_value_free(values);
-}
-
-static struct ldap_info my_ldap;
-static LDAP *my_ldap_fp=0;
-static LDAP *bindp=0;  /* for checking passwords with AUTHBIND */
-
-void authldapclose()
-{
-       if (my_ldap_fp)
-       {
-               l_unbind(my_ldap_fp);
-               my_ldap_fp=0;
-       }
-       if (bindp)
-       {
-               l_unbind(bindp);
-               bindp=0;
-       }
-}
-
-static int ldaperror(int rc)
-{
-#ifdef OPENLDAPV2
-       if (rc && !LDAP_NAME_ERROR(rc))
-#else
-       if (rc && !NAME_ERROR(rc))
-#endif
-       {
-               /* If there was a protocol error, close the connection */
-               authldapclose();
-               ldapconnfailure();
-       }
-       return (rc);
-}
-
-/* This function takes a ldap connection and 
- * tries to enable TLS on it.
-*/
-static int enable_tls_on(LDAP *conn) {
-#if HAVE_LDAP_TLS
-       int version;
-       int ldrc;
-
-       if (ldaperror(ldrc=ldap_get_option (conn,
-                                   LDAP_OPT_PROTOCOL_VERSION,
-                                   &version))
-           != LDAP_SUCCESS)
-       {
-               const char *s=ldap_err2string(ldrc);
-
-               err("ldap_get_option failed: %s", s);
-               return (-1);
-       }
-
-       if (version < LDAP_VERSION3)
-       {
-               version = LDAP_VERSION3;
-               (void)ldap_set_option (conn,
-                                      LDAP_OPT_PROTOCOL_VERSION,
-                                      &version);
-       }
-
-       if (ldaperror(ldrc=ldap_start_tls_s(conn, NULL, NULL))
-           != LDAP_SUCCESS)
-       {
-               const char *s=ldap_err2string(ldrc);
-
-               err("ldap_start_tls_s failed: %s", s);
-               return (-1);
-       }
-       return 0;
-#else
-       err("authldaplib: TLS not available");
-       return (-1);
-#endif
-}
-
-static LDAP *ldapconnect()
-{
-LDAP   *p=NULL;
-
-#if DEBUG_LDAP
-       DPRINTF("URI:      %s",my_ldap.uri);
-       DPRINTF("UID:      %d",my_ldap.uid);
-       DPRINTF("GID:      %d",my_ldap.gid);
-#endif
-
-       if (ldapconncheck())
-       {
-               DPRINTF("authldaplib: timing out after failed connection");
-               return (NULL);
-       }
-
-       ldap_initialize(&p, my_ldap.uri);
-
-       if (p==NULL)
-       {
-               err("cannot connect to LDAP server (%s): %s",
-                       my_ldap.uri, strerror(errno));
-               ldapconnfailure();
-       }
-#ifdef LDAP_OPT_NETWORK_TIMEOUT
-       if (my_ldap.timeout > 0)
-               ldap_set_option (p, LDAP_OPT_NETWORK_TIMEOUT, &my_ldap.timeout);
-#endif
-#if DEBUG_LDAP
-       DPRINTF("ldapconnect end");
-#endif
-       return (p);
-}
-
-static int ldapopen()
-{
-int     ldrc;
-
-       if (my_ldap_fp) return (0);
-
-       if (authldap_read_config(&my_ldap) == 0)
-       {
-               err("authldaplib: error in LDAP configuration file, aborting");
-               return (1);
-       }
-
-       my_ldap_fp=ldapconnect();
-
-       if (!my_ldap_fp)
-       {
-               return (1);
-       }
-
-#ifdef LDAP_OPT_PROTOCOL_VERSION
-
-       /* Set protocol version if selected */
-       if (my_ldap.protocol_version &&
-               ldaperror(ldrc = ldap_set_option(my_ldap_fp, LDAP_OPT_PROTOCOL_VERSION,
-               (void *) & my_ldap.protocol_version)) != LDAP_SUCCESS)
-         {
-               const char *s=ldap_err2string(ldrc);
-
-               err("ldap_set_option(PROTOCOL_VERSION %d) failed: %s",
-                       my_ldap.protocol_version, s);
-               authldapclose();
-               ldapconnfailure();
-               return (-1);
-         }
-       if (my_ldap.protocol_version)
-       {
-               DPRINTF("selected ldap protocol version %d", my_ldap.protocol_version);
-       }
-#endif
-
-       if (my_ldap.tls && enable_tls_on(my_ldap_fp))
-       {
-               authldapclose();
-               ldapconnfailure();
-               return (-1);
-       }
-
-#ifdef LDAP_OPT_DEREF
-
-       /* Set dereferencing mode */
-       if (ldaperror(ldrc = ldap_set_option(my_ldap_fp, LDAP_OPT_DEREF,
-                                        (void *) & my_ldap.deref)) != LDAP_SUCCESS)
-       {
-               const char *s=ldap_err2string(ldrc);
-
-               err("ldap_set_option(DEREF) failed: %s", s);
-               authldapclose();
-               ldapconnfailure();
-               return (-1);
-       }
-#endif
-
-       if(my_ldap.initbind)
-       {
-               /* Bind to server */
-               if (courier_authdebug_login_level >= 2)
-               {
-                       DPRINTF("binding to LDAP server as DN '%s', password '%s'",
-                               my_ldap.binddn ? my_ldap.binddn : "<null>",
-                               my_ldap.bindpw ? my_ldap.bindpw : "<null>");
-               }
-               else
-               {
-                       DPRINTF("binding to LDAP server as DN '%s'",
-                               my_ldap.binddn ? my_ldap.binddn : "<null>");
-               }
-
-               if (ldaperror(ldrc = l_simple_bind_s(my_ldap_fp,
-                                                    my_ldap.binddn,
-                                                    my_ldap.bindpw))
-                   != LDAP_SUCCESS)
-               {
-                       const char *s=ldap_err2string(ldrc);
-
-                       err("ldap_simple_bind_s failed: %s", s);
-                       authldapclose();
-                       ldapconnfailure();
-                       return (-1);
-               }
-       }
-       return (0);
-}
-
-static int auth_ldap_do(const char *, const char *, const char *,
-                       int (*)(struct authinfo *, void *),
-                        void *arg, const char *);
-
-int auth_ldap_changepw(const char *dummy, const char *user,
-                      const char *pass,
-                      const char *newpass)
-{
-       return auth_ldap_do("authlib", user, pass, NULL, NULL, newpass);
-}
-
-/*
- * Function: authldapcommon
- *   Get information from the LDAP server ($ldap) for this $user
- * INPUT:
- *   $user: the login name
- *   $pass: the login password (NULL if we don't want to check the pw)
- *   callback - callback function with filled in authentication info
- *   arg - extra argument for the callback function.
- * OUTPUT:
- *   < 0 - authentication failure
- *   > 0 - temporary failure
- *   else return code from the callback function.
- */
-
-int authldapcommon(const char *service,
-                  const char *user, const char *pass,
-                  int (*callback)(struct authinfo *, void *),
-                  void *arg)
-{
-       return (auth_ldap_do(service, user, pass, callback, arg, NULL));
-}
-
-static int auth_ldap_do2(const char *service,
-                        const char *user, const char *pass,
-                       int (*callback)(struct authinfo *, void *),
-                        void *arg, const char *newpass);
-
-static int auth_ldap_retry(const char *service,
-                          const char *user, const char *pass,
-                          int (*callback)(struct authinfo *, void *),
-                          void *arg, const char *newpass);
-
-static int auth_ldap_do(const char *service,
-                       const char *user, const char *pass,
-                       int (*callback)(struct authinfo *, void *),
-                        void *arg, const char *newpass)
-{
-       int rc=auth_ldap_retry(service, user, pass, callback, arg, newpass);
-
-       if (rc > 0)
-               rc=auth_ldap_retry(service, user, pass, callback, arg,
-                                  newpass);
-
-       return rc;
-}
-
-static int auth_ldap_retry(const char *service,
-                          const char *user, const char *pass,
-                          int (*callback)(struct authinfo *, void *),
-                          void *arg, const char *newpass)
-{
-       char *q;
-       int i;
-
-       q=courier_auth_ldap_escape(user);
-
-       if (!q)
-       {
-               perror("malloc");
-               return 1;
-       }
-
-       i=auth_ldap_do2(service, q, pass, callback, arg, newpass);
-       free(q);
-       return (i);
-}
-
-
-static int auth_ldap_do3(const char *service,
-                        const char *attrname,
-                        const char *user, const char *pass,
-                        int (*callback)(struct authinfo *, void *),
-                        void *arg, const char *newpass, const char *authaddr);
-
-static char *emailmap_get_search_string(const char *str, const char *email);
-
-static int auth_ldap_do2(const char *service,
-                        const char *user, const char *pass,
-                        int (*callback)(struct authinfo *, void *),
-                        void *arg, const char *newpass)
-{
-       char *srch;
-       struct timeval tv;
-       const char *attributes[2];
-       LDAPMessage *result, *entry;
-       int cnt;
-       char *v;
-       const char *aname;
-
-       if (ldapopen()) return (-1);
-
-       if (my_ldap.emailmap[0] == 0 || strchr(user, '@') == NULL)
-               return (auth_ldap_do3(service, my_ldap.mail,
-                                     user, pass, callback, arg, newpass,
-                                     user));
-       /* Mapping is not enabled */
-
-       srch=emailmap_get_search_string(my_ldap.emailmap, user);
-
-       if (!srch)
-       {
-               perror("CRIT: authldaplib: malloc");
-               exit(1);
-       }
-       DPRINTF("using emailmap search: %s", srch);
-
-       tv.tv_sec=my_ldap.timeout;
-       tv.tv_usec=0;
-
-       attributes[0]=my_ldap.emailmap_handle;
-
-       if (!attributes[0][0])
-               attributes[0]="handle";
-       attributes[1]=NULL;
-
-       if (ldaperror(l_search_st(my_ldap_fp,
-                                 (char *)(my_ldap.emailmap_basedn[0] ?
-                                          my_ldap.emailmap_basedn
-                                          :my_ldap.basedn),
-                                 LDAP_SCOPE_SUBTREE,
-                                 srch, (char **)attributes, 0,
-                                 &tv, &result))
-           != LDAP_SUCCESS)
-       {
-               free(srch);
-
-               DPRINTF("ldap_search_st failed");
-               if (my_ldap_fp) return (-1);
-               return (1);
-       }
-
-       if ((cnt=ldap_count_entries(my_ldap_fp, result)) != 1)
-       {
-               if (cnt)
-                       err("emailmap: %d entries returned from search %s (but we need exactly 1)",
-                              cnt, srch);
-               free(srch);
-               ldap_msgfree(result);
-               return -1;
-       }
-       free(srch);
-
-       entry=ldap_first_entry(my_ldap_fp, result);
-
-       if (!entry)
-       {
-               ldap_msgfree(result);
-
-               err("authldap: unexpected NULL from ldap_first_entry");
-               return -1;
-       }
-
-       copy_value(my_ldap_fp, entry, attributes[0], &v, user);
-
-       if (!v)
-       {
-               DPRINTF("emailmap: empty attribute");
-               ldap_msgfree(result);
-               return (-1);
-       }
-
-       aname=my_ldap.emailmap_handle_lookup;
-       if (aname[0] == 0)
-               aname=my_ldap.mail;
-
-       DPRINTF("emailmap results: aname=%s, handle=%s", aname, v);
-
-       cnt=auth_ldap_do3(service,
-                         aname, v, pass, callback, arg, newpass, user);
-
-       ldap_msgfree(result);
-       free(v);
-       return (cnt);
-}
-
-static int auth_ldap_do3(const char *service,
-                        const char *attrname,
-                        const char *user, const char *pass,
-                        int (*callback)(struct authinfo *, void *),
-                        void *arg, const char *newpass,
-                        const char *authaddr)
-{
-       char *newpass_crypt=0;
-       const char *attributes[10];
-       struct timeval timeout;
-
-       LDAPMessage *result;
-       LDAPMessage *entry;
-       char *filter, *dn;
-       int i, j;
-
-       struct authinfo auth;
-       char *homeDir=0;
-       char *mailDir=0;
-       char *userPassword=0;
-       char *cryptPassword=0;
-       char *options=0;
-       char *cn=0;
-       uid_t au;
-       gid_t ag;
-       int rc;
-       char *quota=0;
-        int additionalFilter = 0;
-        int hasAdditionalFilter = 0;
-
-        hasAdditionalFilter = my_ldap.filter != 0;
-
-       memset(&auth, 0, sizeof(auth));
-
-        if (hasAdditionalFilter)
-        {
-            /* To add the additional filter, we need to add on the
-             * additional size for "(&)" and the other filter.  So
-             * filter+3
-             */
-            additionalFilter = strlen(my_ldap.filter) + 3;
-        }
-
-       if ((filter=malloc(additionalFilter+strlen(attrname)+strlen(user)+
-                          (my_ldap.domain ? strlen(my_ldap.domain):0)+
-                          sizeof ("(=@)"))) == 0)
-       {
-               perror("malloc");
-               return 1;
-       }
-        strcpy(filter, "\0");
-
-        if (hasAdditionalFilter)
-        {
-            strcat(filter, "(&");
-            strcat(filter, my_ldap.filter);
-        }
-
-        strcat(strcat(strcat(strcat(filter, "("), attrname), "="), user);
-       if ( my_ldap.domain && my_ldap.domain[0] && strchr(user, '@') == 0 )
-               strcat(strcat(filter, "@"), my_ldap.domain);
-       strcat(filter, ")");
-        
-        if (hasAdditionalFilter)
-        {
-            strcat(filter, ")");
-        }
-
-       DPRINTF("using search filter: %s", filter);
-
-       timeout.tv_sec=my_ldap.timeout;
-       timeout.tv_usec=0;
-
-       read_env("LDAP_HOMEDIR", &attributes[0], "", 0, "homeDir");
-       read_env(service && strcmp(service, "courier") == 0
-                ? "LDAP_DEFAULTDELIVERY":"LDAP_MAILDIR",
-                &attributes[1], "", 0, 0);
-       read_env("LDAP_FULLNAME", &attributes[2], "", 0, "cn");
-       read_env("LDAP_CLEARPW", &attributes[3], "", 0, 0);
-       read_env("LDAP_CRYPTPW", &attributes[4], "", 0, 0);
-       read_env("LDAP_UID", &attributes[5], "", 0, 0);
-       read_env("LDAP_GID", &attributes[6], "", 0, 0);
-       attributes[7]=my_ldap.mail;
-       read_env("LDAP_MAILDIRQUOTA", &attributes[8], "", 0, 0);
-
-       j=0;
-       for (i=0; i<9; i++)
-       {
-               if (attributes[i])
-                       my_ldap.attrlist[j++]=attributes[i];
-       }
-
-       for (i=0; my_ldap.auxoptions[i]; i++)
-               my_ldap.attrlist[j++]=my_ldap.auxoptions[i];
-
-       my_ldap.attrlist[j]=0;
-
-       if (ldaperror(l_search_st(my_ldap_fp,
-                                 (char *)my_ldap.basedn,LDAP_SCOPE_SUBTREE,
-                                 filter, (char **)my_ldap.attrlist, 0,
-                                 &timeout, &result))
-                     != LDAP_SUCCESS)
-       {
-               DPRINTF("ldap_search_st() failed");
-               free(filter);
-
-               if (my_ldap_fp) return (-1);
-               return (1);
-       }
-
-       free(filter);
-
-       /* If we are more than one result, reject */
-       if (ldap_count_entries(my_ldap_fp,result)!=1)
-       {
-               DPRINTF("number of entries returned: %d (but we need exactly 1)",
-                       ldap_count_entries(my_ldap_fp,result));
-               ldap_msgfree(result);
-               return -1;
-       }
-
-       dn = ldap_get_dn(my_ldap_fp, result);
-
-       DPRINTF("one entry returned, DN: %s", dn ? dn : "<null>");
-
-       if (dn == NULL) 
-       {
-               DPRINTF("ldap_get_dn failed");
-               return -1;
-       }
-
-       /* Get the pointer on this result */
-       entry=ldap_first_entry(my_ldap_fp,result);
-       if (entry==NULL)
-       {
-               DPRINTF("ldap_first_entry failed");
-               free(dn);
-               return -1;
-       }
-
-#if DEBUG_LDAP
-       DPRINTF("after ldap_first_entry");
-#endif
-
-       /* print all the raw attributes */
-       if (courier_authdebug_login_level >= 2)
-       {
-       char *attr;
-       BerElement *berptr = 0;
-
-               attr = ldap_first_attribute(my_ldap_fp, entry, &berptr);
-               if (attr)
-               {
-                       DPRINTF("raw ldap entry returned:");
-               }
-
-               while (attr)
-               {
-               char **av, **ap;
-               
-                       av = l_get_values(my_ldap_fp, entry, attr);
-                       ap = av;
-                       if (av)
-                       {
-                               while(*ap)
-                               {
-                                       DPRINTF("| %s: %s", attr, *ap);
-                                       ap++;
-                               }
-                               l_value_free(av);
-                       }
-                       ldap_memfree(attr);
-                       attr = ldap_next_attribute(my_ldap_fp, entry, berptr);
-               }
-               
-               ber_free(berptr, 0);
-       }
-
-       /* Copy the directory and the password into struct */
-       copy_value(my_ldap_fp,entry,attributes[0],&homeDir, user);
-       if (attributes[1])
-               copy_value(my_ldap_fp,entry,attributes[1],&mailDir, user);
-       copy_value(my_ldap_fp,entry,attributes[2],&cn, user);
-       if (attributes[3])
-               copy_value(my_ldap_fp,entry,attributes[3],&userPassword, user);
-       if (attributes[4])
-               copy_value(my_ldap_fp,entry,attributes[4],&cryptPassword, user);
-
-       au=my_ldap.uid;
-       ag=my_ldap.gid;
-       if (attributes[5])
-       {
-               char *p=0;
-               unsigned long n;
-
-               copy_value(my_ldap_fp, entry, attributes[5], &p, user);
-               if (p) {
-                       if (sscanf(p, "%lu", &n) > 0)
-                               au= (uid_t)n;
-                       free(p);
-               }
-#if DEBUG_LDAP
-               DPRINTF("au= %d",au);
-#endif
-       }
-
-       if (attributes[6])
-       {
-               char *p=0;
-               unsigned long n;
-
-               copy_value(my_ldap_fp, entry, attributes[6], &p, user);
-               if (p) {
-                       if (sscanf(p, "%lu", &n) > 0)
-                               ag= (gid_t)n;
-                       free(p);
-               }
-#if DEBUG_LDAP
-               DPRINTF("ag= %d",ag);
-#endif
-       }
-
-       if (attributes[8])
-               copy_value(my_ldap_fp,entry,attributes[8],&quota, user);
-
-       if (homeDir != 0 && my_ldap.mailroot != 0 && *my_ldap.mailroot)
-       {
-               char *new_mailroot=malloc(strlen(homeDir)+
-                                         strlen(my_ldap.mailroot)+2);
-
-               if (!new_mailroot)
-               {
-                       perror("CRIT: authldap: malloc failed");
-                       rc= -1;
-               }
-               else
-               {
-                       strcat(strcat(strcpy(new_mailroot, my_ldap.mailroot),
-                                     "/"), homeDir);
-                       free(homeDir);
-                       homeDir=new_mailroot;
-               }
-       }
-
-       j=1;
-
-       for (i=0; my_ldap.auxoptions[i]; i++)
-       {
-               char *val;
-
-               copy_value(my_ldap_fp, entry, my_ldap.auxoptions[i], &val,
-                          user);
-
-               if (!val)
-                       continue;
-
-               j += 2 + strlen(my_ldap.auxnames[i]) +
-                       strlen(val);
-               free(val);
-       }
-
-       options=malloc(j);
-
-       if (!options)
-       {
-               perror("CRIT: authldap: malloc failed");
-               rc= -1;
-       }
-       else
-       {
-               *options=0;
-
-               for (i=0; my_ldap.auxoptions[i]; i++)
-               {
-                       char *val;
-
-                       copy_value(my_ldap_fp, entry, my_ldap.auxoptions[i],
-                                  &val,
-                                  user);
-
-                       if (!val)
-                               continue;
-
-                       if (*options)
-                               strcat(options, ",");
-                       strcat(options, my_ldap.auxnames[i]);
-                       strcat(options, "=");
-                       strcat(options, val);
-                       free(val);
-               }
-       }
-
-
-       auth.sysuserid= &au;
-       auth.sysgroupid= ag;
-       auth.homedir=homeDir;
-       auth.address=authaddr;
-       auth.fullname=cn;
-       auth.maildir=mailDir;
-       auth.clearpasswd=userPassword;
-       auth.passwd=cryptPassword;
-       auth.quota=quota;
-       auth.options=options && *options ? options:NULL;
-
-       if (homeDir == 0)
-               auth.homedir="";
-
-       rc=0;
-
-       if (au == 0 || ag == 0)
-       {
-               err("authldaplib: refuse to authenticate %s: uid=%d, gid=%d (zero uid or gid not permitted)",
-                      user, au, ag);
-               rc= 1;
-       }
-
-       courier_authdebug_authinfo("DEBUG: authldaplib: ", &auth,
-               userPassword, cryptPassword);
-
-       if (pass)
-       {
-               if (my_ldap.authbind) 
-               {
-                       if (!bindp)
-                       {
-                               bindp=ldapconnect();
-
-                               if (!bindp)
-                               {
-                                       DPRINTF("ldapconnect failed");
-                                       rc=1;
-                               }
-                               else
-#ifdef LDAP_OPT_PROTOCOL_VERSION
-                               /* Set protocol version */
-                               if (my_ldap.protocol_version &&
-                                       ldap_set_option(bindp, LDAP_OPT_PROTOCOL_VERSION,
-                                       (void *) & my_ldap.protocol_version) != LDAP_OPT_SUCCESS)
-                                 {
-                                       err("ldap_set_option(PROTOCOL_VERSION %d) failed",
-                                               my_ldap.protocol_version);
-                                       rc = 1;
-                                 }
-                               else
-#endif
-                               if(my_ldap.tls && enable_tls_on(bindp)) {
-                                       err("authldaplib: LDAP_TLS enabled but I'm unable to start tls, check your config");
-                                       rc = 1;
-                               }
-                       }
-
-                       if (bindp)
-                       {
-                               if (rc == 0)
-                               {
-                               int ldrc;
-                                       DPRINTF("rebinding with DN '%s' to validate password", dn);
-                                       ldrc = l_simple_bind_s(bindp, dn, pass);
-                                       switch (ldrc)
-                                       {
-                                       case LDAP_SUCCESS:
-                                               DPRINTF("authentication bind successful");
-                                               break;
-                                       case LDAP_INVALID_CREDENTIALS:
-                                               DPRINTF("authentication bind failed, invalid credentials");
-                                               rc = -1;
-                                               break;
-                                       default:
-                                               DPRINTF("authentication bind failed, some other problem: %s",
-                                                       ldap_err2string(ldrc));
-                                               rc = 1;
-                                               break;
-                                       }
-                               }
-                               /* Drop the connection if there was a fatal
-                                  error or if we are using historic LDAP v2,
-                                  which didn't support rebinding on same conn */
-                               if (rc > 0 || my_ldap.protocol_version == 2)
-                               {
-                                       l_unbind(bindp);
-                                       bindp=0;
-                               }
-                       }
-
-                       if (rc == 0 && newpass)
-                       {
-                               if ((newpass_crypt=authcryptpasswd(newpass,
-                                                                  auth.passwd)
-                                    ) == 0)
-                                       rc= -1;
-                       }
-               }
-               else
-               {
-                       if (auth.clearpasswd)
-                       {
-                               if (strcmp(pass,auth.clearpasswd))
-                               {
-                                       if (courier_authdebug_login_level >= 2)
-                                       {
-                                               DPRINTF("supplied password '%s' does not match clearpasswd '%s'",
-                                                       pass, auth.clearpasswd);
-                                       }
-                                       else
-                                       {
-                                               DPRINTF("supplied password does not match clearpasswd");
-                                       }
-                                       rc= -1;
-                               }
-                       }
-                       else
-                       {
-                               const char *p=auth.passwd;
-
-                               if (!p)
-                               {
-                                       DPRINTF("no password to compare against!");
-                                       rc= -1;
-                               }
-                               else if (authcheckpassword(pass, p))
-                                       rc= -1;
-                       }
-
-                       if (rc == 0 && newpass && auth.passwd)
-                       {
-                               if ((newpass_crypt=authcryptpasswd(newpass,
-                                                                  auth.passwd)
-                                    ) == 0)
-                                       rc= -1;
-                       }
-               }
-        }
-
-       if (rc == 0 && newpass)
-       {
-               LDAPMod *mods[3];
-               int mod_index=0;
-
-               LDAPMod mod_clear, mod_crypt;
-               char *mod_clear_vals[2], *mod_crypt_vals[2];
-
-               if (attributes[3])
-               {
-                       mods[mod_index]= &mod_clear;
-                       mod_clear.mod_op=LDAP_MOD_REPLACE;
-                       mod_clear.mod_type=(char *)attributes[3];
-                       mod_clear.mod_values=mod_clear_vals;
-
-                       mod_clear_vals[0]=(char *)newpass;
-                       mod_clear_vals[1]=NULL;
-                       ++mod_index;
-               }
-
-               if (attributes[4] && newpass_crypt)
-               {
-                       mods[mod_index]= &mod_crypt;
-                       mod_crypt.mod_op=LDAP_MOD_REPLACE;
-                       mod_crypt.mod_type=(char *)attributes[4];
-                       mod_crypt.mod_values=mod_crypt_vals;
-
-                       mod_crypt_vals[0]=newpass_crypt;
-                       mod_crypt_vals[1]=NULL;
-                       ++mod_index;
-               }
-               if (mod_index == 0)
-                       rc= -1;
-               else
-               {
-                       int ld_errno;
-                       mods[mod_index]=0;
-
-                       /* On a system which uses LDAP_AUTHBIND, we probably
-                          want to use the user's credentials (bindp) rather
-                          than the search credentials (my_ldap_fp) for
-                          performing the password update. (May not always be
-                          true, ideally it would be configurable) */
-                       ld_errno = l_modify_s(bindp? bindp:my_ldap_fp, dn, mods);
-                       if (ld_errno != LDAP_SUCCESS)
-                       {
-                               rc= -1;
-                               DPRINTF("LDAP modify failed: %s",
-                                       ldap_err2string(ld_errno));
-                       }
-               }
-       }
-
-       if (newpass_crypt)
-               free(newpass_crypt);
-       free (dn);
-#if DEBUG_LDAP
-       DPRINTF("before callback rc=%d",rc);
-#endif
-
-       if (rc == 0 && callback)
-       {
-               if (!auth.clearpasswd)
-                       auth.clearpasswd=pass;
-               rc= (*callback)(&auth, arg);
-#if DEBUG_LDAP
-               DPRINTF("after callback rc=%d",rc);
-#endif
-       }
-
-       ldap_msgfree(result);
-       if (options)    free(options);
-       if (homeDir)    free(homeDir);
-       if (mailDir)    free(mailDir);
-       if (userPassword)       free(userPassword);
-       if (cryptPassword)      free(cryptPassword);
-       if (cn)         free(cn);
-       if (quota)      free(quota);
-       return (rc);
-}
-
-/**
- ** Create an emailmap search string.  I'm going to wrap this into an external
- ** variable, so I'll use generic coding here.
- */
-
-struct varlist {
-       const char *varname;
-       int varname_len;
-       const char *varvalue;
-       int varvalue_len;
-} ;
-
-static char *var_expand(const char *, const struct varlist *);
-
-static char *emailmap_get_search_string(const char *str, const char *email)
-{
-       struct varlist vl[3];
-       const char *realmptr=strrchr(email, '@');/* Guaranteed nonNULL */
-
-       static const char userid[]="user";
-       static const char realm[]="realm";
-
-       vl[0].varname=userid;
-       vl[0].varname_len=sizeof(userid)-1;
-       vl[0].varvalue=email;
-       vl[0].varvalue_len=realmptr - email;
-       vl[1].varname=realm;
-       vl[1].varname_len=sizeof(realm)-1;
-       vl[1].varvalue=realmptr+1;
-       vl[1].varvalue_len=strlen(vl[1].varvalue);
-       vl[2].varname=NULL;
-
-       return (var_expand(str, vl));
-}
-
-static char *var_expand(const char *str, const struct varlist *vl)
-{
-       const char *p;
-       int cnt;
-       int pass;
-       char *q, *r;
-
-       cnt=0;
-       q=NULL;
-
-       /*
-       ** Pass 1 - count expanded string length, allocate buffer,
-       ** Pass 2 - generate the string.
-       */
-
-       for (pass=0; pass<2; pass++)
-       {
-               if (pass)
-               {
-                       if ((q=malloc(cnt)) == NULL)
-                               return (NULL);
-               }
-               r=q;
-               cnt=1;
-
-               p=str;
-
-               while (*p)
-               {
-                       if (*p == '@')
-                       {
-                               int j;
-
-                               for (j=0; vl[j].varname; j++)
-                               {
-                                       if (memcmp(vl[j].varname, p+1,
-                                                  vl[j].varname_len) == 0
-                                           && p[vl[j].varname_len+1] == '@')
-                                               break;
-                               }
-
-                               if (vl[j].varname)
-                               {
-                                       p += vl[j].varname_len+2;
-
-                                       if (r)
-                                       {
-                                               memcpy(r, vl[j].varvalue,
-                                                      vl[j].varvalue_len);
-                                               r += vl[j].varvalue_len;
-                                       }
-                                       cnt += vl[j].varvalue_len;
-                                       continue;
-                               }
-                       }
-
-                       if (r)
-                               *r++ = *p;
-                       ++p;
-                       ++cnt;
-               }
-               if (r)
-                       *r=0;
-       }
-
-       return (q);
-}
-
-void auth_ldap_enumerate( void(*cb_func)(const char *name,
-                                        uid_t uid,
-                                        gid_t gid,
-                                        const char *homedir,
-                                        const char *maildir,
-                                        const char *options,
-                                        void *void_arg),
-                          void *void_arg)
-{
-       const char *attributes[5];
-
-       int i, j;
-       int msgid;
-
-       if (ldapopen())
-       {
-               (*cb_func)(NULL, 0, 0, NULL, NULL, NULL, void_arg);
-               return;
-       }
-
-       read_env("LDAP_MAIL", &attributes[0], "", 0, "mail");
-       read_env("LDAP_UID", &attributes[1], "", 0, 0);
-       read_env("LDAP_GID", &attributes[2], "", 0, 0);
-       read_env("LDAP_HOMEDIR", &attributes[3], "", 0, "homeDir");
-       read_env("LDAP_MAILDIR", &attributes[4], "", 0, 0);
-
-       j=0;
-       for (i=0; i<5; i++)
-       {
-               if (attributes[i])
-                       my_ldap.attrlist[j++]=attributes[i];
-       }
-
-       for (i=0; my_ldap.auxoptions[i]; i++)
-               my_ldap.attrlist[j++]=my_ldap.auxoptions[i];
-
-       my_ldap.attrlist[j]=0;
-
-       DPRINTF("ldap_search: basedn='%s', filter='%s'",
-               my_ldap.basedn, my_ldap.enumerate_filter);
-       if ((msgid = l_search(my_ldap_fp, (char *)my_ldap.basedn,LDAP_SCOPE_SUBTREE,
-                             my_ldap.enumerate_filter,
-                             (char **)my_ldap.attrlist, 0)) < 0)
-       {
-               DPRINTF("ldap_search failed");
-               return;
-       }
-
-       while(1) /* process results as they come in */
-       {
-               struct timeval timeout;
-               LDAPMessage *result;
-               LDAPMessage *entry;
-               int ldrc;
-
-               timeout.tv_sec=my_ldap.timeout;
-               timeout.tv_usec=0;
-               ldrc = ldap_result(my_ldap_fp, msgid, 0, &timeout, &result);
-               switch (ldrc)
-               {
-               case -1:
-                       DPRINTF("error in ldap_result");
-                       ldap_msgfree(result);
-                       return;
-               case 0:
-                       DPRINTF("timeout waiting for search result");
-                       ldap_msgfree(result);
-                       return;
-               case LDAP_RES_SEARCH_ENTRY:
-                       break; /* deal with below */
-               case LDAP_RES_SEARCH_RESULT:
-                       if (ldap_parse_result(my_ldap_fp, result, &ldrc,
-                               NULL, NULL, NULL, NULL, 0) != LDAP_SUCCESS)
-                       {
-                               DPRINTF("ldap_parse_result failed");
-                               ldap_msgfree(result);
-                               return;
-                       }
-                       ldap_msgfree(result);
-                       if (ldrc != LDAP_SUCCESS)
-                       {
-                               DPRINTF("ldap search failure result: %s",
-                                       ldap_err2string(ldrc));
-                               return;
-                       }
-                       /* Search successfully completed */
-                       (*cb_func)(NULL, 0, 0, NULL, NULL, NULL, void_arg);
-                       return;
-               default:
-                       DPRINTF("ldap result type 0x%02X ignored", ldrc);
-                       ldap_msgfree(result);
-                       continue;
-               }
-
-               entry = ldap_first_entry(my_ldap_fp, result);
-               while (entry)
-               {
-                       char **names = get_values(my_ldap_fp, entry, attributes[0]);
-                       int n;
-
-                       if (names == NULL)
-                       {
-                               entry = ldap_next_entry(my_ldap_fp, entry);
-                               continue;
-                       }
-
-                       n=l_count_values(names);
-                       if (n > 0)
-                       {
-                               const char *name = names[0] ? names[0] : "<null>";
-                               int i,j;
-                               char *uid_s=NULL;
-                               char *gid_s=NULL;
-                               char *homedir;
-                               char *maildir;
-                               char *options;
-                               uid_t uid=my_ldap.uid;
-                               gid_t gid=my_ldap.gid;
-
-                               if (attributes[1])
-                               {
-                                       copy_value(my_ldap_fp, entry, attributes[1],
-                                                  &uid_s,
-                                                  name);
-                               }
-
-                               if (attributes[2])
-                               {
-                                       copy_value(my_ldap_fp, entry, attributes[2],
-                                                  &gid_s, name);
-                               }
-
-                               copy_value(my_ldap_fp, entry, attributes[3],
-                                          &homedir, name);
-                               copy_value(my_ldap_fp, entry, attributes[4],
-                                          &maildir, name);
-
-                               if (uid_s)
-                                       uid=atol(uid_s);
-                               if (gid_s)
-                                       gid=atol(gid_s);
-
-                               j=1;
-
-                               for (i=0; my_ldap.auxoptions[i]; i++)
-                               {
-                                       char *val;
-
-                                       copy_value(my_ldap_fp, entry, my_ldap.auxoptions[i],
-                                                  &val, name);
-
-                                       if (!val)
-                                               continue;
-
-                                       j += 2 + strlen(my_ldap.auxnames[i]) +
-                                               strlen(val);
-                                       free(val);
-                               }
-
-                               options=malloc(j);
-
-                               if (!options)
-                               {
-                                       l_value_free(names);
-                                       perror("CRIT: auth_ldap_enumerate: malloc failed");
-                                       return;
-                               }
-                               *options=0;
-
-                               for (i=0; my_ldap.auxoptions[i]; i++)
-                               {
-                                       char *val;
-
-                                       copy_value(my_ldap_fp, entry, my_ldap.auxoptions[i],
-                                                  &val, name);
-
-                                       if (!val)
-                                               continue;
-
-                                       if (*options)
-                                               strcat(options, ",");
-                                       strcat(options, my_ldap.auxnames[i]);
-                                       strcat(options, "=");
-                                       strcat(options, val);
-                                       free(val);
-                               }
-
-                               for (j = 0; j < n; j++)
-                               {
-                                       name=names[j];
-
-                                       if (name && homedir)
-                                               (*cb_func)(name, uid, gid, homedir,
-                                                          maildir, options, void_arg);
-                               }
-
-                               if (uid_s)
-                                       free(uid_s);
-                               if (gid_s)
-                                       free(gid_s);
-                               if (homedir)
-                                       free(homedir);
-                               if (maildir)
-                                       free(maildir);
-                               if (options)
-                                       free(options);
-                       }
-                       l_value_free(names);
-
-                       entry = ldap_next_entry(my_ldap_fp, entry);
-               }
-
-               ldap_msgfree(result);
-       }
-}
diff --git a/authldaplib.cpp b/authldaplib.cpp
new file mode 100644 (file)
index 0000000..d5b71a7
--- /dev/null
@@ -0,0 +1,1660 @@
+/*
+** Copyright 2016 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "courier_auth_config.h"
+#endif
+#include <string>
+#include <sstream>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <cctype>
+
+#if HAVE_LBER_H
+#include <lber.h>
+#endif
+#if HAVE_LDAP_H
+#include <ldap.h>
+#endif
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <time.h>
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+extern "C" {
+#include "authldap.h"
+#include "auth.h"
+#include "authldaprc.h"
+#include "courierauthdebug.h"
+};
+
+#include "authconfigfile.h"
+#include <stdio.h>
+
+#ifndef        LDAP_OPT_SUCCESS
+#define LDAP_OPT_SUCCESS LDAP_SUCCESS
+#endif
+
+/*
+** Main connection to the LDAP server, and a separate connection for the
+** LDAP_AUTHBIND option.
+*/
+
+class ldap_connection {
+
+public:
+       LDAP *connection;
+
+       ldap_connection() : connection(0) {}
+       ~ldap_connection() { disconnect(); }
+
+       bool connected() const { return connection != 0; }
+
+       bool connect();
+       void disconnect();
+       void close();
+
+private:
+       bool enable_tls();
+
+public:
+
+       static bool ok(const char *method, int rc)
+       {
+               if (rc == 0 || LDAP_NAME_ERROR(rc))
+                       return true;
+
+               courier_auth_err("%s failed: %s", method,
+                                ldap_err2string(rc));
+               return false;
+       }
+
+       bool bind(const std::string &userid,
+                 const std::string &password)
+       {
+               std::vector<char> buffer(password.begin(), password.end());
+               struct berval cred;
+
+               cred.bv_len=buffer.size();
+               cred.bv_val=&buffer[0];
+
+               if (connect() &&
+                   ok("ldap_sasl_bind_s",
+                      ldap_sasl_bind_s(connection, userid.c_str(),
+                                       NULL, &cred,
+                                       NULL, NULL, NULL)))
+                       return true;
+
+               disconnect();
+               return connect() &&
+                       ok("ldap_sasl_bind_s",
+                          ldap_sasl_bind_s(connection, userid.c_str(),
+                                           NULL, &cred,
+                                           NULL, NULL, NULL));
+       }
+};
+
+ldap_connection main_connection, bind_connection;
+
+
+// Loaded and parsed authldaprc configuration file.
+
+class authldaprc_file : public courier::auth::config_file {
+
+public:
+
+       int protocol_version;
+       int timeout;
+       int authbind;
+       int initbind;
+       int tls;
+       uid_t uid;
+       gid_t gid;
+
+       std::string ldap_uri, ldap_binddn, ldap_bindpw, ldap_basedn;
+       int ldap_deref;
+
+       std::vector<std::string> auxoptions, auxnames;
+
+       authldaprc_file();
+
+private:
+       bool do_load();
+       void do_reload();
+public:
+};
+
+/*
+** There's a memory leak in OpenLDAP 1.2.11, presumably in earlier versions
+** too.  See http://www.OpenLDAP.org/its/index.cgi?findid=864 for more
+** information.  To work around the bug, the first time a connection fails
+** we stop trying for 60 seconds.  After 60 seconds we kill the process,
+** and let the parent process restart it.
+**
+** We'll control this behavior via LDAP_MEMORY_LEAK.  Set it to ZERO to turn
+** off this behavior (whenever OpenLDAP gets fixed).
+*/
+
+static time_t ldapfailflag=0;
+
+static void ldapconnfailure()
+{
+       const char *p=getenv("LDAP_MEMORY_LEAK");
+
+       if (!p)
+       {
+#ifdef LDAP_VENDOR_NAME
+#ifdef LDAP_VENDOR_VERSION
+#define DO_OPENLDAP_CHECK
+#endif
+#endif
+
+#ifdef DO_OPENLDAP_CHECK
+
+               /* It's supposed to be fixed in 20019 */
+
+               if (strcmp(LDAP_VENDOR_NAME, "OpenLDAP") == 0 &&
+                   LDAP_VENDOR_VERSION < 20019)
+                       p="1";
+               else
+                       p="0";
+#else
+               p="0";
+#endif
+       }
+
+       if (atoi(p) && !ldapfailflag)
+       {
+               time(&ldapfailflag);
+               ldapfailflag += 60;
+       }
+}
+
+static int ldapconncheck()
+{
+       time_t t;
+
+       if (!ldapfailflag)
+               return (0);
+
+       time(&t);
+
+       if (t >= ldapfailflag)
+               exit(0);
+       return (1);
+}
+
+authldaprc_file::authldaprc_file()
+       : config_file(AUTHLDAPRC)
+{
+}
+
+bool authldaprc_file::do_load()
+{
+       bool loaded=true;
+
+       // Frequently-accessed variables.
+
+       if (!config("LDAP_TIMEOUT", timeout, false, "5") ||
+           !config("LDAP_TLS", tls, false, "0"))
+       {
+               loaded=false;
+       }
+
+       if (!config("LDAP_URI", ldap_uri, true))
+       {
+               loaded=false;
+       }
+
+       ldap_deref=0;
+
+       std::string deref_setting;
+
+       config("LDAP_DEREF", deref_setting, false, "");
+
+       for (std::string::iterator p=deref_setting.begin();
+            p != deref_setting.end(); ++p)
+               *p=std::tolower(*p);
+
+#ifdef LDAP_OPT_DEREF
+
+       ldap_deref=LDAP_DEREF_NEVER;
+
+       if (deref_setting == "never")
+               ldap_deref = LDAP_DEREF_NEVER;
+       else if (deref_setting == "searching")
+               ldap_deref = LDAP_DEREF_SEARCHING;
+       else if (deref_setting == "finding")
+               ldap_deref = LDAP_DEREF_FINDING;
+       else if (deref_setting == "always")
+               ldap_deref = LDAP_DEREF_ALWAYS;
+       else if (deref_setting != "")
+       {
+               loaded=false;
+               courier_auth_err("authldap: INVALID LDAP_OPT_DEREF");
+       }
+#endif
+       uid=0;
+       gid=0;
+
+       std::string uid_str, gid_str;
+
+       config("LDAP_GLOB_UID", uid_str, false);
+       config("LDAP_GLOB_GID", gid_str, false);
+
+       if (!uid_str.empty())
+       {
+               std::istringstream i(uid_str);
+
+               i >> uid;
+
+               if (i.fail())
+               {
+                       struct passwd *pwent=getpwnam(uid_str.c_str());
+
+                       if (!pwent)
+                       {
+                               courier_auth_err("authldap: INVALID LDAP_GLOB_UID");
+                               loaded=false;
+                       }
+                       else
+                       {
+                               uid=pwent->pw_uid;
+                       }
+               }
+       }
+
+       if (!gid_str.empty())
+       {
+               std::istringstream i(uid_str);
+
+               i >> gid;
+
+               if (i.fail())
+               {
+                       struct group  *grent=getgrnam(gid_str.c_str());
+
+                       if (!grent)
+                       {
+                               courier_auth_err("authldap: INVALID LDAP_GLOB_GID");
+                               loaded=false;
+                       }
+                       else
+                       {
+                               gid=grent->gr_gid;
+                       }
+               }
+       }
+
+       if (!config("LDAP_AUTHBIND", authbind, false, "0")
+           || !config("LDAP_INITBIND", initbind, false, "0")
+           || !config("LDAP_BASEDN", ldap_basedn, true))
+               loaded=false;
+
+       if (initbind)
+       {
+               if (!config("LDAP_BINDDN", ldap_binddn, true) ||
+                   !config("LDAP_BINDPW", ldap_bindpw, true))
+                       loaded=false;
+       }
+
+       if (!config("LDAP_PROTOCOL_VERSION", protocol_version, false, "0"))
+               loaded=false;
+
+       if (protocol_version)
+       {
+#ifndef LDAP_OPT_PROTOCOL_VERSION
+               courier_auth_err("authldaplib: LDAP_OPT_PROTOCOL_VERSION ignored");
+               loaded=false;
+#endif
+               if (0
+#ifdef LDAP_VERSION_MIN
+                       || protocol_version < LDAP_VERSION_MIN
+#endif
+#ifdef LDAP_VERSION_MAX
+                       || protocol_version > LDAP_VERSION_MAX
+#endif
+               )
+               {
+                       protocol_version=0;
+                       courier_auth_err("authldaplib: LDAP_PROTOCOL_VERSION not supported");
+                       loaded=false;
+               }
+       }
+
+       std::string auxoptions_str;
+
+       config("LDAP_AUXOPTIONS", auxoptions_str, "");
+
+       std::string::iterator p=auxoptions_str.begin();
+
+       while (p != auxoptions_str.end())
+       {
+               if (*p == ',')
+               {
+                       ++p;
+                       continue;
+               }
+
+               std::string::iterator q=p;
+
+               p=std::find(p, auxoptions_str.end(), ',');
+
+               std::string auxoption(q, p);
+               std::string auxname;
+
+               q=std::find(auxoption.begin(), auxoption.end(), '=');
+
+               if (q != auxoption.end())
+               {
+                       auxname=std::string(q+1, auxoption.end());
+                       auxoption=std::string(auxoption.begin(), q);
+               }
+
+               auxoptions.push_back(auxoption);
+               auxnames.push_back(auxname);
+       }
+
+       return loaded;
+}
+
+void authldaprc_file::do_reload()
+{
+       // File changed, try to load it again.
+
+       authldaprc_file new_file;
+
+       if (new_file.load(true))
+       {
+               *this=new_file;
+               DPRINTF("authldap: reloaded %s", filename);
+
+               // If we reloaded the file, close the
+               // connections, so they can be reopened using
+               // the new config.
+
+               main_connection.close();
+               bind_connection.close();
+       }
+}
+
+static authldaprc_file authldaprc;
+
+#if HAVE_LDAP_TLS
+bool ldap_connection::enable_tls()
+{
+       int version;
+
+       if (!ok("ldap_get_option",
+               ldap_get_option(connection, LDAP_OPT_PROTOCOL_VERSION,
+                               &version)))
+               return false;
+
+       if (version < LDAP_VERSION3)
+       {
+               version = LDAP_VERSION3;
+               (void)ldap_set_option (connection,
+                                      LDAP_OPT_PROTOCOL_VERSION,
+                                      &version);
+       }
+
+       if (!ok("ldap_start_tls_s",
+               ldap_start_tls_s(connection, NULL, NULL)))
+               return false;
+
+       return true;
+}
+
+#else
+
+bool ldap_connection::enable_tls()
+{
+       courier_auth_err("authldaplib: TLS not available");
+       return (-1);
+}
+#endif
+
+bool ldap_connection::connect()
+{
+       if (connected()) return true;
+
+       DPRINTF("authldaplib: connecting to %s", authldaprc.ldap_uri.c_str());
+
+       if (ldapconncheck())
+       {
+               DPRINTF("authldaplib: timing out after failed connection");
+               return (false);
+       }
+
+       ldap_initialize(&connection, authldaprc.ldap_uri.c_str());
+
+       if (connection==NULL)
+       {
+               courier_auth_err("cannot connect to LDAP server (%s): %s",
+                                authldaprc.ldap_uri.c_str(), strerror(errno));
+               ldapconnfailure();
+       }
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+       else if (authldaprc.timeout > 0)
+       {
+               DPRINTF("timeout set to %d", authldaprc.timeout);
+               ldap_set_option (connection, LDAP_OPT_NETWORK_TIMEOUT, &authldaprc.timeout);
+#endif
+       }
+
+#ifdef LDAP_OPT_PROTOCOL_VERSION
+
+       if (authldaprc.protocol_version &&
+           !ok("ldap_set_option",
+               ldap_set_option(connection,
+                               LDAP_OPT_PROTOCOL_VERSION,
+                               (void *) &authldaprc.protocol_version)))
+       {
+               disconnect();
+               return false;
+       }
+
+       if (authldaprc.protocol_version)
+       {
+               DPRINTF("selected ldap protocol version %d", authldaprc.protocol_version);
+       }
+#endif
+
+       if (authldaprc.tls && !enable_tls())
+       {
+               disconnect();
+               return false;
+       }
+
+#ifdef LDAP_OPT_DEREF
+       if (!ok("ldap_set_option",
+               ldap_set_option(connection, LDAP_OPT_DEREF,
+                               (void *)&authldaprc.ldap_deref)))
+       {
+               disconnect();
+               return (false);
+       }
+#else
+       if (!deref_setting.empty())
+       {
+               courier_auth_err("authldaplib: LDAP_OPT_DEREF not available, ignored");
+       }
+#endif
+
+       return true;
+}
+
+void ldap_connection::disconnect()
+{
+       close();
+       ldapconnfailure();
+}
+
+void ldap_connection::close()
+{
+       if (connection == NULL)
+               return;
+
+       ldap_unbind_ext(connection, 0, 0);
+       connection=NULL;
+}
+
+static int ldapopen()
+{
+       if (main_connection.connected()) return 0;
+
+       if (!main_connection.connect())
+               return 1;
+
+       if (authldaprc.initbind)
+       {
+               /* Bind to server */
+               if (courier_authdebug_login_level >= 2)
+               {
+                       DPRINTF("binding to LDAP server as DN '%s', password '%s'",
+                               authldaprc.ldap_binddn.empty() ? "<null>"
+                               : authldaprc.ldap_binddn.c_str(),
+                               authldaprc.ldap_bindpw.empty() ? "<null>"
+                               : authldaprc.ldap_bindpw.c_str());
+               }
+               else
+               {
+                       DPRINTF("binding to LDAP server as DN '%s'",
+                               authldaprc.ldap_binddn.empty() ? "<null>"
+                               : authldaprc.ldap_binddn.c_str());
+               }
+
+               if (!main_connection.bind(authldaprc.ldap_binddn,
+                                         authldaprc.ldap_bindpw))
+               {
+                       authldapclose();
+                       ldapconnfailure();
+                       return (-1);
+               }
+       }
+       return (0);
+}
+
+class authldaprc_attributes {
+
+public:
+
+       std::map<std::string, std::string *> attributes;
+
+       std::string attribute(const char *name,
+                             const char *default_value,
+                             std::string &return_value)
+       {
+               std::string value;
+
+               authldaprc.config(name, value, false, default_value);
+
+               if (!value.empty())
+                       attributes[value]=&return_value;
+               return value;
+       }
+};
+
+class authldaprc_attribute_vector : public std::vector<std::string> {
+
+public:
+
+       authldaprc_attribute_vector(const std::map<std::string, std::string *>
+                                   &attributes)
+       {
+               for (std::map<std::string, std::string *>::const_iterator
+                            p=attributes.begin(); p != attributes.end(); ++p)
+               {
+                       push_back(p->first);
+               }
+       }
+};
+
+class authldaprc_search_attributes {
+
+       std::vector<std::string> copy_buffer;
+
+public:
+
+       std::vector<char *> all_attributes_ptr;
+
+       authldaprc_search_attributes(const std::vector<std::string> &attributes)
+               : copy_buffer(attributes)
+       {
+               for (std::vector<std::string>::iterator
+                            p=copy_buffer.begin();
+                    p != copy_buffer.end(); ++p)
+               {
+                       if (p->empty())
+                               continue;
+
+                       p->push_back(0);
+                       all_attributes_ptr.push_back(& (*p)[0]);
+               }
+
+               all_attributes_ptr.push_back(0);
+       }
+
+       char **search_attributes()
+       {
+               return &all_attributes_ptr[0];
+       }
+};
+
+class authldaprc_search_result : authldaprc_search_attributes {
+
+public:
+
+       LDAPMessage *ptr;
+       bool finished;
+
+       authldaprc_search_result(ldap_connection &conn,
+                                const std::string &basedn,
+                                const std::string &query,
+                                const std::vector<std::string> &attributes,
+                                const struct timeval &timeout)
+               : authldaprc_search_attributes(attributes),
+                 ptr(NULL), finished(false)
+       {
+               struct timeval timeout_copy=timeout;
+
+               if (!conn.connect() ||
+                   !conn.ok("ldap_search_ext_s",
+                            ldap_search_ext_s(conn.connection,
+                                              basedn.c_str(),
+                                              LDAP_SCOPE_SUBTREE,
+                                              query.c_str(),
+                                              search_attributes(),
+                                              0,
+                                              NULL, NULL,
+                                              &timeout_copy,
+                                              100, &ptr)))
+               {
+                       ptr=NULL;
+                       conn.disconnect();
+                       if (!conn.connect()
+                           || !conn.ok("ldap_search_ext_s",
+                                    ldap_search_ext_s(conn.connection,
+                                                      basedn.c_str(),
+                                                      LDAP_SCOPE_SUBTREE,
+                                                      query.c_str(),
+                                                      search_attributes(),
+                                                      0,
+                                                      NULL, NULL,
+                                                      &timeout_copy,
+                                                      100, &ptr)))
+                       {
+                               ptr=NULL;
+                       }
+               }
+       }
+
+       authldaprc_search_result(ldap_connection &conn,
+                                int msgid,
+                                bool all,
+                                const struct timeval &timeout)
+               :authldaprc_search_attributes(std::vector<std::string>()),
+                ptr(NULL), finished(false)
+       {
+               while (1)
+               {
+                       struct timeval timeout_copy=timeout;
+
+                       int rc=ldap_result(conn.connection, msgid, all ? 1:0,
+                                          &timeout_copy,
+                                          &ptr);
+
+                       switch (rc)
+                       {
+                       case -1:
+                               DPRINTF("ldap_result() failed");
+                               ldap_msgfree(ptr);
+                               ptr=NULL;
+                               return;
+                       case 0:
+                               DPRINTF("ldap_result() timed out");
+                               ldap_msgfree(ptr);
+                               ptr=NULL;
+                               return;
+                       case LDAP_RES_SEARCH_ENTRY:
+                               break; /* deal with below */
+                       case LDAP_RES_SEARCH_RESULT:
+                               if (ldap_parse_result(conn.connection, ptr,
+                                                     &rc,
+                                                     NULL, NULL, NULL, NULL,
+                                                     0) != LDAP_SUCCESS)
+                               {
+                                       DPRINTF("ldap_parse_result failed");
+                                       ldap_msgfree(ptr);
+                                       ptr=NULL;
+                                       return;
+                               }
+                               ldap_msgfree(ptr);
+                               ptr=NULL;
+                               if (rc != LDAP_SUCCESS)
+                               {
+                                       DPRINTF("search failed: %s",
+                                               ldap_err2string(rc));
+                                       return;
+                               }
+                               finished=true;
+                               return;
+                       default:
+                               DPRINTF("ldap_result(): ignored 0x%02X status",
+                                       rc);
+                               ldap_msgfree(ptr);
+                               ptr=NULL;
+                               continue;
+                       }
+                       break;
+               }
+       }
+
+       bool operator!() const
+       {
+               return ptr == NULL;
+       }
+
+       operator bool() const
+       {
+               return ptr != NULL;
+       }
+
+       ~authldaprc_search_result()
+       {
+               if (ptr)
+                       ldap_msgfree(ptr);
+       }
+};
+
+static std::vector<std::string>
+authldap_entry_values(LDAP *connection, LDAPMessage *msg,
+                     const std::string &attrname)
+{
+       std::vector<std::string> values;
+
+       struct berval **p=ldap_get_values_len(connection, msg,
+                                             attrname.c_str());
+
+       if (p)
+       {
+
+               size_t n=ldap_count_values_len(p);
+
+               values.reserve(n);
+
+               for (size_t i=0; i<n; i++)
+               {
+                       const char *ptr=
+                               reinterpret_cast<const char *>(p[i]->bv_val);
+
+                       values.push_back(std::string(ptr, ptr+p[i]->bv_len));
+               }
+
+               ldap_value_free_len(p);
+       }
+       return values;
+}
+
+class authldap_get_values {
+
+       LDAP *connection;
+       LDAPMessage *entry;
+       std::string context;
+
+public:
+
+       authldap_get_values(LDAP *connectionArg,
+                           LDAPMessage *entryArg,
+                           const std::string &contextArg)
+               : connection(connectionArg),
+                 entry(entryArg),
+                 context(contextArg)
+       {
+       }
+
+       bool operator()(const std::string &attrname,
+                       std::string &value)
+       {
+               std::vector<std::string> values=
+                       authldap_entry_values(connection, entry, attrname);
+
+               if (values.empty())
+                       return false;
+
+               if (values.size() > 1)
+               {
+                       fprintf(stderr,
+                               "WARN: authldaplib: duplicate attribute %s for %s\n",
+                               attrname.c_str(),
+                               context.c_str());
+               }
+
+               value=values[0];
+               return true;
+       }
+
+       std::string options()
+       {
+               size_t i;
+
+               std::ostringstream options;
+               const char *options_sep="";
+
+               for (i=0; i<authldaprc.auxoptions.size(); ++i)
+               {
+                       std::string value;
+
+                       if (operator()(authldaprc.auxoptions[i], value)
+                           && !value.empty())
+                       {
+                               options << options_sep
+                                       << authldaprc.auxnames[i]
+                                       << "="
+                                       << value;
+                               options_sep=",";
+                       }
+               }
+               return options.str();
+       }
+};
+
+static void cpp_auth_ldap_enumerate( void(*cb_func)(const char *name,
+                                                   uid_t uid,
+                                                   gid_t gid,
+                                                   const char *homedir,
+                                                   const char *maildir,
+                                                   const char *options,
+                                                   void *void_arg),
+                                    void *void_arg)
+{
+       int msgid;
+
+       if (ldapopen())
+       {
+               (*cb_func)(NULL, 0, 0, NULL, NULL, NULL, void_arg);
+               return;
+       }
+
+       std::string mail_field, uid_field, gid_field,
+               homedir_field, maildir_field;
+
+       authldaprc.config("LDAP_MAIL", mail_field, false, "mail");
+       authldaprc.config("LDAP_UID", uid_field, false);
+       authldaprc.config("LDAP_GID", gid_field, false);
+       authldaprc.config("LDAP_HOMEDIR", homedir_field, false, "homeDir");
+       authldaprc.config("LDAP_MAILDIR", maildir_field, false);
+
+       std::vector<std::string> attribute_vector;
+
+       attribute_vector.push_back(mail_field);
+       attribute_vector.push_back(uid_field);
+       attribute_vector.push_back(gid_field);
+       attribute_vector.push_back(homedir_field);
+       attribute_vector.push_back(maildir_field);
+
+       for (size_t i=0; i<authldaprc.auxoptions.size(); i++)
+       {
+               attribute_vector.push_back(authldaprc.auxoptions[i]);
+       }
+
+       std::string enumerate_filter;
+
+       authldaprc.config("LDAP_ENUMERATE_FILTER", enumerate_filter, false);
+
+       if (enumerate_filter.empty())
+       {
+               std::string filter;
+
+               authldaprc.config("LDAP_FILTER", filter, false);
+
+               if (!filter.empty())
+               {
+                       enumerate_filter=filter;
+               }
+               else
+               {
+                       std::string s;
+
+                       authldaprc.config("LDAP_MAIL", s, false);
+
+                       enumerate_filter = s + "=*";
+               }
+       }
+
+       DPRINTF("ldap_search: basedn='%s', filter='%s'",
+               authldaprc.ldap_basedn.c_str(), enumerate_filter.c_str());
+
+       authldaprc_search_attributes search_attributes(attribute_vector);
+
+       struct timeval tv;
+       tv.tv_sec=60*60;
+       tv.tv_usec=0;
+
+       if (ldap_search_ext(main_connection.connection,
+                           authldaprc.ldap_basedn.c_str(),
+                           LDAP_SCOPE_SUBTREE,
+                           enumerate_filter.c_str(),
+                           search_attributes.search_attributes(),
+                           0,
+                           NULL, NULL, &tv, 1000000, &msgid) < 0)
+       {
+               DPRINTF("ldap_search_ext failed");
+               return;
+       }
+
+       /* Process results */
+
+       while (1)
+       {
+               struct timeval timeout;
+               LDAPMessage *entry;
+
+               timeout.tv_sec=authldaprc.timeout;
+               timeout.tv_usec=0;
+
+               authldaprc_search_result search_result(main_connection,
+                                                      msgid,
+                                                      false,
+                                                      timeout);
+
+               if (search_result.finished)
+                       break;
+
+               if (!search_result)
+                       return;
+
+               entry = ldap_first_entry(main_connection.connection, search_result.ptr);
+
+               while (entry)
+               {
+                       std::vector<std::string>
+                               names=authldap_entry_values(main_connection.connection,
+                                                           entry,
+                                                           mail_field);
+
+                       if (names.empty())
+                       {
+                               entry = ldap_next_entry(main_connection.connection, entry);
+                               continue;
+                       }
+
+                       size_t n=names.size();
+
+                       if (n > 0)
+                       {
+                               std::string uid_s, gid_s, homedir, maildir;
+                               uid_t uid=authldaprc.uid;
+                               gid_t gid=authldaprc.gid;
+
+                               authldap_get_values
+                                       get_value(main_connection.connection, entry,
+                                                 names[0]);
+
+                               if (!uid_field.empty())
+                                       get_value(uid_field, uid_s);
+
+                               if (!gid_field.empty())
+                               {
+                                       get_value(gid_field, gid_s);
+                               }
+
+                               get_value(homedir_field, homedir);
+                               get_value(maildir_field, maildir);
+
+                               if (!uid_s.empty())
+                                       std::istringstream(uid_s)
+                                               >> uid;
+
+                               if (!gid_s.empty())
+                                       std::istringstream(gid_s)
+                                               >> gid;
+
+                               std::string options=get_value.options();
+
+                               for (size_t j=0; j < n; j++)
+                               {
+                                       if (!homedir.empty())
+                                               (*cb_func)(names[j].c_str(),
+                                                          uid, gid,
+                                                          homedir.c_str(),
+                                                          maildir.empty()
+                                                          ? 0:maildir.c_str(),
+                                                          options.empty()
+                                                          ? 0:options.c_str(),
+                                                          void_arg);
+                               }
+                       }
+
+                       entry = ldap_next_entry(main_connection.connection, entry);
+               }
+       }
+
+       /* Success */
+       (*cb_func)(NULL, 0, 0, NULL, NULL, NULL, void_arg);
+}
+
+static void cpp_authldapclose()
+{
+       main_connection.disconnect();
+       bind_connection.disconnect();
+}
+
+class authldap_lookup : private authldaprc_attributes {
+
+       struct authinfo auth;
+       const char *service;
+       std::string attrname;
+       std::string user;
+       const char *pass;
+       const char *newpass;
+       const char *authaddr;
+
+public:
+       authldap_lookup(const char *serviceArg,
+                       const std::string &attrnameArg,
+                       const std::string &userArg,
+                       const char *passArg,
+                       const char *newpassArg,
+                       const char *authaddrArg);
+
+       int operator()(int (*callback)(struct authinfo *, void *), void *arg);
+
+private:
+       int verify_password(const std::string &dn);
+       int verify_password_myself(const std::string &dn);
+       int verify_password_authbind(const std::string &dn);
+};
+
+authldap_lookup::authldap_lookup(const char *serviceArg,
+                                const std::string &attrnameArg,
+                                const std::string &userArg,
+                                const char *passArg,
+                                const char *newpassArg,
+                                const char *authaddrArg)
+       : service(serviceArg),
+         attrname(attrnameArg),
+         user(userArg),
+         pass(passArg),
+         newpass(newpassArg),
+         authaddr(authaddrArg)
+{
+}
+
+int authldap_lookup::operator()(int (*callback)(struct authinfo *, void *),
+                               void *arg)
+{
+       struct timeval timeout;
+
+       LDAPMessage *entry;
+
+       std::string dn;
+
+       std::string homeDir, mailDir, userPassword,
+               cryptPassword,
+               cn,
+               uidNumber,
+               gidNumber, quota;
+
+       uid_t au;
+       gid_t ag;
+       int rc;
+
+       std::ostringstream query;
+
+       std::string filter;
+
+       authldaprc.config("LDAP_FILTER", filter, false);
+
+       if (!filter.empty())
+       {
+               query << "(&" << filter;
+       }
+
+       query << "(" << attrname << "=" << user;
+
+       std::string domain;
+
+       authldaprc.config("LDAP_DOMAIN", domain, false);
+
+       if (!domain.empty() &&
+            std::find(user.begin(), user.end(), '@') == user.end())
+               query << "@" << domain;
+       query << ")";
+
+       if (!filter.empty())
+               query << ")";
+
+       std::string query_str=query.str();
+
+       DPRINTF("Query: %s", query_str.c_str());
+
+       timeout.tv_sec=authldaprc.timeout;
+       timeout.tv_usec=0;
+
+       attribute("LDAP_HOMEDIR", "homeDir", homeDir);
+       attribute(service && strcmp(service, "courier") == 0
+                 ? "LDAP_DEFAULTDELIVERY":"LDAP_MAILDIR", 0, mailDir);
+       attribute("LDAP_FULLNAME", 0, cn);
+       std::string clearpw_value=attribute("LDAP_CLEARPW", 0, userPassword);
+       std::string cryptpw_value=attribute("LDAP_CRYPTPW", 0, cryptPassword);
+       attribute("LDAP_UID", 0, uidNumber);
+       attribute("LDAP_GID", 0, gidNumber);
+       attribute("LDAP_MAILDIRQUOTA", 0, quota);
+
+       authldaprc_attribute_vector all_attributes(attributes);
+
+       for (size_t i=0; i<authldaprc.auxoptions.size(); i++)
+       {
+               all_attributes.push_back(authldaprc.auxoptions[i]);
+       }
+
+       authldaprc_search_result result(main_connection,
+                                       authldaprc.ldap_basedn,
+                                       query_str,
+                                       all_attributes,
+                                       timeout);
+
+       int n_entries=ldap_count_entries(main_connection.connection, result.ptr);
+
+       if (n_entries != 1)
+       {
+               if (n_entries == 0)
+               {
+                       DPRINTF("Not found");
+               }
+               else
+               {
+                       DPRINTF("Returned multiple entries (%d)", n_entries);
+               }
+               return -1;
+       }
+
+       char *dn_p = ldap_get_dn(main_connection.connection, result.ptr);
+
+       DPRINTF("Returned DN: %s", dn_p ? dn_p : "<null>");
+
+       if (dn_p == NULL)
+       {
+               DPRINTF("ldap_get_dn failed");
+               return -1;
+       }
+
+       dn=dn_p;
+       free(dn_p);
+
+       /* Get the pointer on this result */
+       entry=ldap_first_entry(main_connection.connection, result.ptr);
+       if (entry==NULL)
+       {
+               DPRINTF("ldap_first_entry failed");
+               return -1;
+       }
+
+       /* print all the raw attributes */
+       if (courier_authdebug_login_level >= 2)
+       {
+               BerElement *berptr = 0;
+               char *attr=
+                       ldap_first_attribute(main_connection.connection, entry, &berptr);
+
+               while (attr)
+               {
+                       std::vector<std::string>
+                               values=authldap_entry_values(main_connection.connection,
+                                                            entry,
+                                                            attr);
+                       for (size_t i=0; i<values.size(); ++i)
+                               DPRINTF("    %s: %s", attr, values[i].c_str());
+
+                       ldap_memfree(attr);
+                       attr = ldap_next_attribute(main_connection.connection, entry,
+                                                  berptr);
+               }
+
+               ber_free(berptr, 0);
+       }
+
+       authldap_get_values get_value(main_connection.connection, entry, dn.c_str());
+
+       for (std::map<std::string, std::string *>::iterator
+                    p=attributes.begin(); p != attributes.end(); ++p)
+       {
+               get_value(p->first, *p->second);
+       }
+
+       au=authldaprc.uid;
+       ag=authldaprc.gid;
+       if (!uidNumber.empty())
+       {
+               std::istringstream(uidNumber) >> au;
+       }
+
+       if (!gidNumber.empty())
+       {
+               std::istringstream(gidNumber) >> ag;
+       }
+
+       std::string mailroot;
+
+       authldaprc.config("LDAP_MAILROOT", mailroot, false);
+
+       if (!homeDir.empty() && !mailroot.empty())
+       {
+               homeDir = mailroot + "/" + homeDir;
+       }
+
+       std::string options=get_value.options();
+
+       memset(&auth, 0, sizeof(auth));
+
+       auth.sysuserid= &au;
+       auth.sysgroupid= ag;
+       auth.homedir=homeDir.c_str();
+       auth.address=authaddr;
+       auth.fullname=cn.c_str();
+
+       if (!mailDir.empty())
+               auth.maildir=mailDir.c_str();
+
+       if (!userPassword.empty())
+               auth.clearpasswd=userPassword.c_str();
+
+       if (!cryptPassword.empty())
+               auth.passwd=cryptPassword.c_str();
+
+       if (!quota.empty())
+               auth.quota=quota.c_str();
+
+       if (!options.empty())
+               auth.options=options.c_str();
+
+       rc=0;
+
+       if (au == 0 || ag == 0)
+       {
+               courier_auth_err("authldaplib: refuse to authenticate %s: uid=%d, gid=%d (zero uid or gid not permitted)",
+                                user.c_str(), au, ag);
+               rc= 1;
+       }
+
+       courier_authdebug_authinfo("DEBUG: authldaplib: ", &auth,
+                                  userPassword.c_str(),
+                                  cryptPassword.c_str());
+
+       if (rc == 0)
+               rc=verify_password(dn);
+
+       std::string newpass_crypt;
+
+       if (rc == 0 && newpass)
+       {
+               char *p=authcryptpasswd(newpass, auth.passwd);
+
+               if (!p)
+                       rc=-1;
+               else
+               {
+                       newpass_crypt=p;
+                       free(p);
+               }
+
+               LDAPMod *mods[3];
+               int mod_index=0;
+
+               LDAPMod mod_clear, mod_crypt;
+               char *mod_clear_vals[2], *mod_crypt_vals[2];
+
+               std::vector<char> clearpw_buffer, cryptpw_buffer;
+
+               if (!clearpw_value.empty() && auth.clearpasswd)
+               {
+                       clearpw_buffer.insert(clearpw_buffer.end(),
+                                             clearpw_value.begin(),
+                                             clearpw_value.end());
+
+                       clearpw_buffer.push_back(0);
+
+                       mods[mod_index]= &mod_clear;
+                       mod_clear.mod_op=LDAP_MOD_REPLACE;
+                       mod_clear.mod_type=&clearpw_buffer[0];
+                       mod_clear.mod_values=mod_clear_vals;
+
+                       DPRINTF("Modify: %s", mod_clear.mod_type);
+
+                       mod_clear_vals[0]=(char *)newpass;
+                       mod_clear_vals[1]=NULL;
+                       ++mod_index;
+               }
+
+               if (!cryptpw_value.empty() &&
+                   !newpass_crypt.empty() && auth.passwd)
+               {
+                       cryptpw_buffer.insert(cryptpw_buffer.end(),
+                                             cryptpw_value.begin(),
+                                             cryptpw_value.end());
+
+                       cryptpw_buffer.push_back(0);
+
+                       mods[mod_index]= &mod_crypt;
+                       mod_crypt.mod_op=LDAP_MOD_REPLACE;
+                       mod_crypt.mod_type=&cryptpw_buffer[0];
+                       mod_crypt.mod_values=mod_crypt_vals;
+
+                       DPRINTF("Modify: %s", mod_crypt.mod_type);
+
+                       newpass_crypt.push_back(0);
+                       mod_crypt_vals[0]=&newpass_crypt[0];
+                       mod_crypt_vals[1]=NULL;
+                       ++mod_index;
+               }
+               if (mod_index == 0)
+                       rc= -1;
+               else
+               {
+                       mods[mod_index]=0;
+
+                       /*
+                       ** Use the user connection for updating the password.
+                       */
+
+                       int ld_errno=
+                               ldap_modify_ext_s(bind_connection.connected()
+                                                 ? bind_connection.connection
+                                                 : main_connection.connection,
+                                                 dn.c_str(), mods,
+                                                 NULL, NULL);
+
+                       if (ld_errno != LDAP_SUCCESS)
+                       {
+                               rc= -1;
+                               DPRINTF("Password update failed: %s",
+                                       ldap_err2string(ld_errno));
+                       }
+               }
+       }
+
+       if (rc == 0 && callback)
+       {
+               if (!auth.clearpasswd)
+                       auth.clearpasswd=pass;
+               rc= (*callback)(&auth, arg);
+       }
+
+       return (rc);
+}
+
+int authldap_lookup::verify_password(const std::string &dn)
+{
+       if (!pass)
+               return 0;
+
+       if (authldaprc.authbind)
+               return verify_password_authbind(dn);
+
+       return verify_password_myself(dn);
+}
+
+int authldap_lookup::verify_password_authbind(const std::string &dn)
+{
+       if (!bind_connection.connect())
+               return 1;
+
+       if (!bind_connection.bind(dn, pass))
+       {
+               bind_connection.close();
+               return 1;
+       }
+
+       if (authldaprc.protocol_version == 2)
+       {
+               // protocol version 2 does not allow rebinds.
+
+               bind_connection.close();
+       }
+
+       return 0;
+}
+
+int authldap_lookup::verify_password_myself(const std::string &dn)
+{
+       if (auth.clearpasswd)
+       {
+               if (strcmp(pass, auth.clearpasswd))
+               {
+                       if (courier_authdebug_login_level >= 2)
+                       {
+                               DPRINTF("Password for %s: '%s' does not match clearpasswd '%s'",
+                                       dn.c_str(), pass, auth.clearpasswd);
+                       }
+                       else
+                       {
+                               DPRINTF("Password for %s does not match",
+                                       dn.c_str());
+                       }
+                       return -1;
+               }
+       }
+       else
+       {
+               const char *p=auth.passwd;
+
+               if (!p)
+               {
+                       DPRINTF("Missing password in LDAP!");
+                       return -1;
+               }
+
+               if (authcheckpassword(pass, p))
+               {
+                       DPRINTF("Password for %s does not match",
+                               dn.c_str());
+                       return -1;
+               }
+        }
+
+       return 0;
+}
+
+/*
+** Replace keywords in the emailmap string.
+*/
+
+static std::string emailmap_replace(const char *str,
+                                   const std::string &user_value,
+                                   const std::string &realm_value)
+{
+       std::ostringstream o;
+
+       while (*str)
+       {
+               const char *p=str;
+
+               while (*str && *str != '@')
+                       ++str;
+
+               o << std::string(p, str);
+
+               if (*str != '@')
+                       continue;
+
+               ++str;
+
+               p=str;
+               while (*str && *str != '@')
+                       ++str;
+
+               std::string key(p, str);
+
+               if (*str)
+                       ++str;
+
+               if (key == "user")
+                       o << user_value;
+               else if (key == "realm")
+                       o << realm_value;
+       }
+
+       return o.str();
+}
+
+static int auth_ldap_try(const char *service,
+                        const char *unquoted_user, const char *pass,
+                        int (*callback)(struct authinfo *, void *),
+                        void *arg, const char *newpass)
+{
+       std::string user;
+
+       {
+               char *q=courier_auth_ldap_escape(unquoted_user);
+
+               user=q;
+               free(q);
+       }
+
+       if (ldapopen()) return (-1);
+
+       std::string::iterator at=std::find(user.begin(), user.end(), '@');
+
+       std::string emailmap;
+
+       authldaprc.config("LDAP_EMAILMAP", emailmap, false);
+
+       std::string mail;
+
+       if (!authldaprc.config("LDAP_MAIL", mail, false, "mail"))
+               return -1;
+
+       if (emailmap.empty() || at == user.end())
+       {
+               authldap_lookup real_lookup(service, mail, user, pass,
+                                           newpass, user.c_str());
+
+               return real_lookup(callback, arg);
+       }
+
+       std::string user_value(user.begin(), at);
+       std::string realm_value(++at, user.end());
+
+       std::string query=
+               emailmap_replace(emailmap.c_str(), user_value, realm_value);
+
+       DPRINTF("using emailmap search: %s", query.c_str());
+
+       struct timeval tv;
+
+       tv.tv_sec=authldaprc.timeout;
+       tv.tv_usec=0;
+
+       std::vector<std::string> attributes;
+
+       attributes.push_back("");
+
+       authldaprc.config("LDAP_EMAILMAP_ATTRIBUTE", attributes[0], false);
+
+       if (attributes[0].empty())
+               attributes[0]="handle";
+
+       std::string basedn;
+
+       if (!authldaprc.config("LDAP_EMAILMAP_BASEDN", basedn, true))
+               return -1;
+
+       authldaprc_search_result
+               lookup(main_connection,
+                      basedn,
+                      query,
+                      attributes,
+                      tv);
+
+       if (!lookup)
+       {
+               if (main_connection.connection) return (-1);
+               return (1);
+       }
+
+       int cnt=ldap_count_entries(main_connection.connection, lookup.ptr);
+
+       if (cnt != 1)
+       {
+               courier_auth_err("emailmap: %d entries returned from search %s (but we need exactly 1)",
+                   cnt, query.c_str());
+               return -1;
+       }
+
+       LDAPMessage *entry=ldap_first_entry(main_connection.connection, lookup.ptr);
+
+       if (!entry)
+       {
+               courier_auth_err("authldap: unexpected NULL from ldap_first_entry");
+               return -1;
+       }
+
+       authldap_get_values get_value(main_connection.connection, entry, query);
+
+       std::string v;
+
+       get_value(attributes[0], v);
+
+       if (v.empty())
+       {
+               DPRINTF("emailmap: empty attribute");
+               return (-1);
+       }
+
+
+       std::string attrname;
+
+       authldaprc.config("LDAP_EMAILMAP_MAIL", attrname, false);
+
+       if (attrname.empty())
+       {
+               attrname=mail;
+       }
+
+       DPRINTF("emailmap: attribute=%s, value=%s", attrname.c_str(),
+               v.c_str());
+
+       authldap_lookup real_lookup(service, attrname, v.c_str(), pass,
+                                   newpass, user.c_str());
+
+       return real_lookup(callback, arg);
+}
+
+// Try the query once. If there's a connection-level error, try again.
+
+static int auth_ldap_retry(const char *service,
+                          const char *unquoted_user,
+                          const char *pass,
+                          int (*callback)(struct authinfo *, void *),
+                          void *arg, const char *newpass)
+{
+       int rc=auth_ldap_try(service, unquoted_user, pass, callback, arg,
+                            newpass);
+
+       if (rc > 0)
+               rc=auth_ldap_try(service, unquoted_user, pass, callback, arg,
+                                  newpass);
+
+       return rc;
+}
+
+extern "C" {
+
+#if 0
+};
+#endif
+
+int auth_ldap_changepw(const char *dummy, const char *user,
+                      const char *pass,
+                      const char *newpass)
+{
+       if (!authldaprc.load())
+               return 1;
+
+       return auth_ldap_retry("authlib", user, pass, NULL, NULL, newpass);
+}
+
+int authldapcommon(const char *service,
+                  const char *user, const char *pass,
+                  int (*callback)(struct authinfo *, void *),
+                  void *arg)
+{
+       if (!authldaprc.load())
+               return 1;
+       return (auth_ldap_retry(service, user, pass, callback, arg, NULL));
+}
+
+void authldapclose()
+{
+       cpp_authldapclose();
+}
+
+void auth_ldap_enumerate( void(*cb_func)(const char *name,
+                                        uid_t uid,
+                                        gid_t gid,
+                                        const char *homedir,
+                                        const char *maildir,
+                                        const char *options,
+                                        void *void_arg),
+                          void *void_arg)
+{
+       if (!authldaprc.load())
+               return;
+
+       cpp_auth_ldap_enumerate(cb_func, void_arg);
+}
+
+#if 0
+{
+#endif
+}
index 812c6f9..77131a8 100644 (file)
@@ -1,6 +1,6 @@
-##VERSION: $Id: authldaprc 265 2013-02-25 03:49:33Z mrsam $
+##VERSION: $Id: 7ee49247d1dbf52d4bb8e0b1a180f2411aa3628a-20160107214650$
 #
-# Copyright 2000-2004 Double Precision, Inc.  See COPYING for
+# Copyright 2000-2016 Double Precision, Inc.  See COPYING for
 # distribution information.
 #
 # Do not alter lines that begin with ##, they are used when upgrading
@@ -20,6 +20,8 @@
 # That is, the name of the field, followed by spaces or tabs, followed by
 # field value.  No trailing spaces.
 #
+# Changes to this file take effect immediately.
+#
 # Here are the fields:
 
 ##NAME: LOCATION:1
@@ -69,11 +71,11 @@ LDAP_TIMEOUT                5
 
 ##NAME: LDAP_INITBIND:1
 #
-# Define this to do an initial bind to the adminstrator DN set in LDAP_BINDDN. 
+# Define this to do an initial bind to the adminstrator DN set in LDAP_BINDDN.
 # If your LDAP server allows access without a bind, or you want to authenticate
 # using a rebind (and have set LDAP_AUTHBIND to 1, you can set this to 0 and
 # need not write the LDAP-Admin passwort into this file.
-# 
+#
 LDAP_INITBIND          1
 
 ##NAME: LDAP_MAIL:0
@@ -93,7 +95,7 @@ LDAP_MAIL             mail
 
 ##NAME: LDAP_DOMAIN:0
 #
-# The following default domain will be appended, if not explicitly specified. 
+# The following default domain will be appended, if not explicitly specified.
 #
 # LDAP_DOMAIN          example.com
 
@@ -176,7 +178,7 @@ LDAP_CRYPTPW                userPassword
 #
 # Auxiliary options.  The LDAP_AUXOPTIONS setting should contain a list of
 # comma-separated "ATTRIBUTE=NAME" pairs.  These names are additional
-# attributes that define various per-account "options", as given in 
+# attributes that define various per-account "options", as given in
 # INSTALL's description of the OPTIONS setting.
 #
 # Each ATTRIBUTE specifies an LDAP attribute name.  If it is present,
@@ -198,7 +200,6 @@ LDAP_CRYPTPW                userPassword
 
 ##NAME: LDAP_ENUMERATE_FILTER:0
 #
-# {EXPERIMENTAL}
 # Optional custom filter used when enumerating accounts for authenumerate,
 # in order to compile a list of accounts for shared folders. If present,
 # this filter will be used instead of LDAP_FILTER.
@@ -280,3 +281,8 @@ LDAP_TLS            0
 # LDAP_BASEDN, but will key against LDAP_EMAILMAP_MAIL instead of LDAP_MAIL.
 #
 # LDAP_EMAILMAP_MAIL mail
+
+##NAME: MARKER:0
+#
+# Do not remove this section from this configuration file. This section
+# must be present at the end of this file.
index 4de8780..01580c0 100644 (file)
@@ -2,14 +2,14 @@
 .\"  <!-- Copyright 2004-2015 Double Precision, Inc.  See COPYING for -->
 .\"  <!-- distribution information. -->
 .\"     Title: authlib
-.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 11/04/2015
+.\"    Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author]
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\"      Date: 09/08/2017
 .\"    Manual: Double Precision, Inc.
 .\"    Source: Double Precision, Inc.
 .\"  Language: English
 .\"
-.TH "AUTHLIB" "3" "11/04/2015" "Double Precision, Inc." "Double Precision, Inc."
+.TH "AUTHLIB" "3" "09/08/2017" "Double Precision, Inc." "Double Precision, Inc."
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
similarity index 60%
rename from authmysql.c
rename to authmysql.cpp
index d7e6269..362930d 100644 (file)
 #if    HAVE_UNISTD_H
 #include       <unistd.h>
 #endif
+#include <iostream>
 
-#include       "auth.h"
 #include       "authmysql.h"
+extern "C" {
+#include       "auth.h"
 #include       "courierauthstaticlist.h"
 #include       "courierauthdebug.h"
-#include       "libhmac/hmac.h"
-#include       "cramlib.h"
-
-
-extern void auth_mysql_enumerate( void(*cb_func)(const char *name,
-                                                uid_t uid,
-                                                gid_t gid,
-                                                const char *homedir,
-                                                const char *maildir,
-                                                const char *options,
-                                                void *void_arg),
-                                 void *void_arg);
+#include       "courierauth.h"
+}
 
-static int auth_mysql_login(const char *service, char *authdata,
-                           int (*callback_func)(struct authinfo *, void *),
-                           void *callback_arg)
+static bool verify(const authmysqluserinfo &authinfo,
+                  const char *user,
+                  const char *pass)
 {
-       char *user, *pass;
-       struct authmysqluserinfo *authinfo;
-       struct  authinfo        aa;
-
-
-       if ((user=strtok(authdata, "\n")) == 0 ||
-               (pass=strtok(0, "\n")) == 0)
+       if (authinfo.home.size() == 0)  /* User not found */
        {
                errno=EPERM;
-               return (-1);
+               return false;           /* Username not found */
        }
 
-       authinfo=auth_mysql_getuserinfo(user, service);
-
-       if (!authinfo)          /* Fatal error - such as MySQL being down */
+       if (authinfo.cryptpw.size())
        {
-               errno=EACCES;
-               return (-1);
-       }
-
-       if (authinfo->cryptpw)
-       {
-               if (authcheckpassword(pass,authinfo->cryptpw))
+               if (authcheckpassword(pass,authinfo.cryptpw.c_str()))
                {
                        errno=EPERM;
-                       return (-1);    /* User/Password not found. */
+                       return false;   /* User/Password not found. */
                }
        }
-       else if (authinfo->clearpw)
+       else if (authinfo.clearpw.size())
        {
-               if (strcmp(pass, authinfo->clearpw))
+               if (authinfo.clearpw != pass)
                {
                        if (courier_authdebug_login_level >= 2)
                        {
                                DPRINTF("supplied password '%s' does not match clearpasswd '%s'",
-                                       pass, authinfo->clearpw);
+                                       pass, authinfo.clearpw.c_str());
                        }
                        else
                        {
                                DPRINTF("supplied password does not match clearpasswd");
                        }
                        errno=EPERM;
-                       return (-1);
+                       return false;
                }
        }
        else
        {
-               DPRINTF("no password available to compare");
+               DPRINTF("no password available to compare for '%s'", user);
                errno=EPERM;
-               return (-1);            /* Username not found */
+               return false;           /* Username not found */
        }
+       return true;
+}
+
+static int auth_mysql_login(const char *service, char *authdata,
+                           int (*callback_func)(struct authinfo *, void *),
+                           void *callback_arg)
+{
+       char *user, *pass;
+       struct  authinfo        aa;
+
+       if ((user=strtok(authdata, "\n")) == 0 ||
+               (pass=strtok(0, "\n")) == 0)
+       {
+               errno=EPERM;
+               return (-1);
+       }
+
+       authmysqluserinfo authinfo;
+
+       if (!auth_mysql_getuserinfo(user, service, authinfo))
+               /* Fatal error - such as MySQL being down */
+       {
+               errno=EACCES;
+               return (-1);
+       }
+
+       if (!verify(authinfo, user, pass))
+               return -1;
 
        memset(&aa, 0, sizeof(aa));
 
-       aa.sysuserid= &authinfo->uid;
-       aa.sysgroupid= authinfo->gid;
-       aa.homedir=authinfo->home;
-       aa.maildir=authinfo->maildir && authinfo->maildir[0] ?
-               authinfo->maildir:0;
-       aa.address=authinfo->username;
-       aa.quota=authinfo->quota && authinfo->quota[0] ?
-               authinfo->quota:0;
-       aa.fullname=authinfo->fullname;
-       aa.options=authinfo->options;
+       aa.sysuserid= &authinfo.uid;
+       aa.sysgroupid= authinfo.gid;
+       aa.homedir=authinfo.home.c_str();
+
+#define STR(z) (authinfo.z.size() ? authinfo.z.c_str():0)
+
+       aa.maildir=STR(maildir);
+       aa.address=STR(username);
+       aa.quota=STR(quota);
+       aa.fullname=STR(fullname);
+       aa.options=STR(options);
        aa.clearpasswd=pass;
-       aa.passwd=authinfo->cryptpw;
+       aa.passwd=STR(cryptpw);
        courier_authdebug_authinfo("DEBUG: authmysql: ", &aa,
-                           authinfo->clearpw, authinfo->cryptpw);
+                                  aa.clearpasswd, aa.passwd);
 
        return (*callback_func)(&aa, callback_arg);
 }
@@ -111,39 +118,20 @@ static int auth_mysql_changepw(const char *service, const char *user,
                               const char *pass,
                               const char *newpass)
 {
-       struct authmysqluserinfo *authinfo;
-
-       authinfo=auth_mysql_getuserinfo(user, service);
+       authmysqluserinfo authinfo;
 
-       if (!authinfo)
+       if (!auth_mysql_getuserinfo(user, service, authinfo))
        {
                errno=ENOENT;
                return (-1);
        }
 
-       if (authinfo->cryptpw)
+       if (!verify(authinfo, user, pass))
        {
-               if (authcheckpassword(pass,authinfo->cryptpw))
-               {
-                       errno=EPERM;
-                       return (-1);    /* User/Password not found. */
-               }
-       }
-       else if (authinfo->clearpw)
-       {
-               if (strcmp(pass, authinfo->clearpw))
-               {
-                       errno=EPERM;
-                       return (-1);
-               }
-       }
-       else
-       {
-               errno=EPERM;
                return (-1);
        }
 
-       if (auth_mysql_setpass(user, newpass, authinfo->cryptpw))
+       if (!auth_mysql_setpass(user, newpass, authinfo.cryptpw.c_str()))
        {
                errno=EPERM;
                return (-1);
@@ -193,7 +181,9 @@ static struct authstaticinfo authmysql_info={
        auth_mysql_enumerate};
 
 
-struct authstaticinfo *courier_authmysql_init()
-{
-       return &authmysql_info;
+extern "C" {
+       struct authstaticinfo *courier_authmysql_init()
+       {
+               return &authmysql_info;
+       }
 }
index 01bf6cf..3cade40 100644 (file)
@@ -3,33 +3,47 @@
 
 #include       "courier_auth_config.h"
 #include       <stdlib.h>
-#include       <string.h>
 #include       <sys/types.h>
 #include       <mysql.h>
 #include       <errmsg.h>
 
-struct authmysqluserinfo {
-       char *username;
-       char *fullname;
-       char *cryptpw;
-       char *clearpw;
-       char *home;
-       char *maildir;
-       char *quota;
-       char *options;
+#include        <string>
+
+class authmysqluserinfo {
+ public:
+       std::string username;
+       std::string fullname;
+       std::string cryptpw;
+       std::string clearpw;
+       std::string home;
+       std::string maildir;
+       std::string quota;
+       std::string options;
        uid_t uid;
        gid_t gid;
-       } ;
+};
+
+bool auth_mysql_getuserinfo(const char *username,
+                           const char *service,
+                           authmysqluserinfo &uiret);
 
-extern struct authmysqluserinfo *auth_mysql_getuserinfo(const char *,
-                                                       const char *);
 extern void auth_mysql_cleanup();
 
-extern int auth_mysql_setpass(const char *, const char *, const char *);
+extern bool auth_mysql_setpass(const char *, const char *, const char *);
 
 struct authinfo;
 
 extern int auth_mysql_pre(const char *, const char *,
                 int (*)(struct authinfo *, void *), void *arg);
 
+extern void auth_mysql_enumerate( void(*cb_func)(const char *name,
+                                                uid_t uid,
+                                                gid_t gid,
+                                                const char *homedir,
+                                                const char *maildir,
+                                                const char *options,
+                                                void *void_arg),
+                                 void *void_arg);
+
+
 #endif
diff --git a/authmysqllib.c b/authmysqllib.c
deleted file mode 100644 (file)
index 08ebdee..0000000
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
-** Copyright 2000-2010 Double Precision, Inc.  See COPYING for
-** distribution information.
-*/
-
-#include       <stdio.h>
-#include       <stdlib.h>
-#include       <string.h>
-#include       <unistd.h>
-#include       <ctype.h>
-#include       <sys/types.h>
-#include       <sys/stat.h>
-#include       <mysql.h>
-#include       <time.h>
-
-#include       "authmysql.h"
-#include       "authmysqlrc.h"
-#include       "auth.h"
-#include       "courierauthdebug.h"
-
-#define err courier_auth_err
-
-static const char *read_env(const char *env)
-{
-       return authgetconfig(AUTHMYSQLRC, env);
-}
-
-static MYSQL mysql_buf;
-
-static MYSQL *mysql=0;
-
-static char *escape_str(const char *c, size_t n)
-{
-       char *buf=malloc(n*2+1);
-
-       if (!buf)
-       {
-               perror("malloc");
-               return NULL;
-       }
-
-       mysql_real_escape_string(mysql, buf, c, n);
-       return buf;
-}
-
-static void set_session_options(void)
-/*
-* session variables can be set once for the whole session
-*/
-{
-/* Anton Dobkin <anton@viansib.ru>, VIAN, Ltd. */
-#if MYSQL_VERSION_ID >= 41000    
-       const char *character_set=read_env("MYSQL_CHARACTER_SET"), *check;
-    
-        if(character_set){
-
-            /*
-            * This function works like the SET NAMES statement, but also sets
-            * the value of mysql->charset, and thus affects the character set
-            * used by mysql_real_escape_string()
-            *
-            * (return value apparently work the opposite of what is documented)
-            */
-            mysql_set_character_set(mysql, character_set);
-            check = mysql_character_set_name(mysql);
-            if (strcmp(character_set, check) != 0)
-            {
-                err("Cannot set MySQL character set \"%s\", working with \"%s\"\n",
-                    character_set, check);
-            }
-            else
-            {
-                DPRINTF("Install of a character set for MySQL: %s", character_set);
-            }
-        }
-#endif /* 41000 */
-}
-
-static int do_connect()
-{
-const  char *server;
-const  char *userid;
-const  char *password;
-const  char *database;
-const  char *server_socket=0;
-unsigned int server_port=0;
-unsigned int server_opt=0;
-const  char *p;
-
-const  char *sslkey;
-const  char *sslcert;
-const  char *sslcacert;
-const  char *sslcapath;
-const  char *sslcipher;
-unsigned int  use_ssl=0;
-
-/*
-** Periodically detect dead connections.
-*/
-       if (mysql)
-       {
-               static time_t last_time=0;
-               time_t t_check;
-
-               time(&t_check);
-
-               if (t_check < last_time)
-                       last_time=t_check;      /* System clock changed */
-
-               if (t_check < last_time + 60)
-                       return (0);
-
-               last_time=t_check;
-                       
-               if (mysql_ping(mysql) == 0) return (0);
-
-               DPRINTF("authmysqllib: mysql_ping failed, connection lost");
-               mysql_close(mysql);
-               mysql=0;
-       }
-
-       server=read_env("MYSQL_SERVER");
-       userid=read_env("MYSQL_USERNAME");
-       password=read_env("MYSQL_PASSWORD");
-       database=read_env("MYSQL_DATABASE");
-
-#if MYSQL_VERSION_ID >= 32200
-       sslkey=read_env("MYSQL_SSL_KEY");
-       sslcert=read_env("MYSQL_SSL_CERT");
-       sslcacert=read_env("MYSQL_SSL_CACERT");
-       sslcapath=read_env("MYSQL_SSL_CAPATH");
-       sslcipher=read_env("MYSQL_SSL_CIPHER");
-
-       if ((sslcert != NULL) && ((sslcacert != NULL) || (sslcapath != NULL)))
-       {
-               use_ssl=1;
-       }
-#endif
-
-       server_socket=(char *) read_env("MYSQL_SOCKET");
-
-       if ((p=read_env("MYSQL_PORT")) != 0)
-       {
-               server_port=(unsigned int) atoi(p);
-       }
-
-       if ((p=read_env("MYSQL_OPT")) != 0)
-       {
-               server_opt=(unsigned int) atol(p);
-       }
-
-       if (!server && !server_socket)
-       {
-               err("authmysql: MYSQL_SERVER nor MYSQL_SOCKET set in"
-                       AUTHMYSQLRC ".");
-               return (-1);
-       }
-
-       if (!userid)
-       {
-               err("authmysql: MYSQL_USERNAME not set in "
-                       AUTHMYSQLRC ".");
-               return (-1);
-       }
-
-       if (!database)
-       {
-               err("authmysql: MYSQL_DATABASE not set in "
-                       AUTHMYSQLRC ".");
-               return (-1);
-       }
-
-#if MYSQL_VERSION_ID >= 32200
-       mysql_init(&mysql_buf);
-       if (use_ssl)
-       {
-               mysql_ssl_set(&mysql_buf, sslkey, sslcert, sslcacert,
-                             sslcapath, sslcipher);
-       }
-       mysql=mysql_real_connect(&mysql_buf, server, userid, password,
-                                NULL,
-                                server_port,
-                                server_socket,
-                                server_opt);
-#else
-       mysql=mysql_connect(&mysql_buf, server, userid, password);
-#endif
-       if (!mysql)
-       {
-               err("failed to connect to mysql server (server=%s, userid=%s): %s",
-                       server ? server : "<null>",
-                       userid ? userid : "<null>",
-                       mysql_error(&mysql_buf));
-               return (-1);
-       }
-
-       if (mysql_select_db(mysql, database))
-       {
-               err("authmysql: mysql_select_db(%s) error: %s",
-                       database, mysql_error(mysql));
-               mysql_close(mysql);
-               mysql=0;
-               return (-1);
-       }
-       
-       DPRINTF("authmysqllib: connected. Versions: "
-               "header %lu, "
-               "client %lu, "
-               "server %lu",
-               (long)MYSQL_VERSION_ID,
-               mysql_get_client_version(),
-               mysql_get_server_version(mysql));
-
-       set_session_options();  
-       return (0);
-}
-
-void auth_mysql_cleanup()
-{
-       if (mysql)
-       {
-               mysql_close(mysql);
-               mysql=0;
-       }
-}
-
-static struct authmysqluserinfo ui={0, 0, 0, 0, 0, 0, 0, 0};
-
-static void initui()
-{
-
-       if (ui.username)
-               free(ui.username);
-       if (ui.cryptpw)
-               free(ui.cryptpw);
-       if (ui.clearpw)
-               free(ui.clearpw);
-       if (ui.home)
-               free(ui.home);
-       if (ui.maildir)
-               free(ui.maildir);
-       if (ui.quota)
-               free(ui.quota);
-       if (ui.fullname)
-               free(ui.fullname);
-       if (ui.options)
-               free(ui.options);
-       memset(&ui, 0, sizeof(ui));
-}
-
-struct authmysqluserinfo *auth_mysql_getuserinfo(const char *username,
-                                                const char *service)
-{
-const char *defdomain  =NULL;
-char   *querybuf;
-MYSQL_ROW      row;
-MYSQL_RES      *result;
-int            num_fields;
-char           *endp;
-
-const char     *select_clause; /* siefca@pld.org.pl */
-
-#define DEFAULT_SELECT_QUERY "SELECT %s, %s, %s, %s, %s, %s, %s, %s, %s, %s FROM %s WHERE %s = '%s%s%s' %s%s%s", \
-               login_field, crypt_field, clear_field, uid_field,\
-               gid_field, home_field, maildir_field, quota_field,\
-               name_field, options_field, user_table, login_field,\
-               username_escaped,\
-               has_domain || !*defdomain ? "":"@", has_domain ? "":defdomain, \
-               *where_clause ? " AND (":"", where_clause,\
-               *where_clause ? ")":""
-
-       if (do_connect())       return (0);
-
-       initui();
-
-       select_clause=read_env("MYSQL_SELECT_CLAUSE");
-       defdomain=read_env("DEFAULT_DOMAIN");   
-       if (!defdomain) defdomain="";
-       
-       if (!select_clause) /* siefca@pld.org.pl */
-       {
-               const char      *user_table,
-                               *crypt_field,
-                               *clear_field,
-                               *name_field,
-                               *uid_field,
-                               *gid_field,
-                               *login_field,
-                               *home_field,
-                               *maildir_field,
-                               *quota_field,
-                               *options_field,
-                               *where_clause;
-               char            *username_escaped;
-               size_t  query_size;
-               char dummy_buf[1];
-               int has_domain;
-
-               user_table=read_env("MYSQL_USER_TABLE");
-
-               if (!user_table)
-               {
-                       err("authmysql: MYSQL_USER_TABLE not set in "
-                               AUTHMYSQLRC ".");
-                       return (0);
-               }
-
-               crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
-               clear_field=read_env("MYSQL_CLEAR_PWFIELD");
-               name_field=read_env("MYSQL_NAME_FIELD");
-
-               if (!crypt_field && !clear_field)
-               {
-                       err("authmysql: MYSQL_CRYPT_PWFIELD and "
-                               "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC ".");
-                       return (0);
-               }
-               if (!crypt_field) crypt_field="\"\"";
-               if (!clear_field) clear_field="\"\"";
-               if (!name_field) name_field="\"\"";
-
-               uid_field = read_env("MYSQL_UID_FIELD");
-               if (!uid_field) uid_field = "uid";
-
-               gid_field = read_env("MYSQL_GID_FIELD");
-               if (!gid_field) gid_field = "gid";
-
-               login_field = read_env("MYSQL_LOGIN_FIELD");
-               if (!login_field) login_field = "id";
-
-               home_field = read_env("MYSQL_HOME_FIELD");
-               if (!home_field) home_field = "home";
-
-               maildir_field=read_env(service && strcmp(service, "courier")==0
-                                      ? "MYSQL_DEFAULTDELIVERY"
-                                      : "MYSQL_MAILDIR_FIELD");
-               if (!maildir_field) maildir_field="\"\"";
-
-               quota_field=read_env("MYSQL_QUOTA_FIELD");
-               if (!quota_field) quota_field="\"\""; 
-
-               options_field=read_env("MYSQL_AUXOPTIONS_FIELD");
-               if (!options_field) options_field="\"\"";
-
-               where_clause=read_env("MYSQL_WHERE_CLAUSE");
-               if (!where_clause) where_clause = "";
-
-               username_escaped=malloc(strlen(username)*2+1);
-
-               if (!username_escaped)
-               {
-                       perror("malloc");
-                       return (0);
-               }
-
-               mysql_real_escape_string(mysql, username_escaped,
-                                        username, strlen(username));
-
-               has_domain=strchr(username, '@') != NULL;
-
-               query_size=snprintf(dummy_buf, 1, DEFAULT_SELECT_QUERY);
-
-               querybuf=malloc(query_size+1);
-
-               if (!querybuf)
-               {
-                       free(username_escaped);
-                       perror("malloc");
-                       return(0);
-               }
-
-               snprintf(querybuf, query_size+1, DEFAULT_SELECT_QUERY);
-               free(username_escaped);
-
-       }
-       else
-       {
-               /* siefca@pld.org.pl */
-               querybuf=auth_parse_select_clause (escape_str,
-                                                  select_clause, username,
-                                                  defdomain, service);
-               if (!querybuf)
-               {
-                       DPRINTF("parse_select_clause failed (DEFAULT_DOMAIN not set?)");
-                       return 0;
-               }
-       }
-
-       DPRINTF("SQL query: %s", querybuf);
-       if (mysql_query (mysql, querybuf))
-       {
-               /* <o.blasnik@nextra.de> */
-
-               DPRINTF("mysql_query failed, reconnecting: %s", mysql_error(mysql));
-               auth_mysql_cleanup();
-
-               if (do_connect())
-               {
-                       free(querybuf);
-                       return (0);
-               }
-
-               if (mysql_query (mysql, querybuf))
-               {
-                       DPRINTF("mysql_query failed second time, giving up: %s", mysql_error(mysql));
-                       free(querybuf);
-                       auth_mysql_cleanup();
-                       /* Server went down, that's OK,
-                       ** try again next time.
-                       */
-                       return (0);
-               }
-       }
-       free(querybuf);
-
-       result = mysql_store_result (mysql);       
-       if (result)
-       {
-               if (mysql_num_rows(result))
-               {
-                       row = mysql_fetch_row (result);
-                       num_fields = mysql_num_fields (result);
-
-                       if (num_fields < 6)
-                       {
-                               DPRINTF("incomplete row, only %d fields returned",
-                                       num_fields);
-                               mysql_free_result(result);
-                               return(0);
-                       }
-
-                       if (row[0] && row[0][0])
-                               ui.username=strdup(row[0]);
-                       if (row[1] && row[1][0])
-                               ui.cryptpw=strdup(row[1]);
-                       if (row[2] && row[2][0])
-                               ui.clearpw=strdup(row[2]);
-                       /* perhaps authmysql needs a glob_uid/glob_gid feature
-                          like authldap? */
-                       if (!row[3] || !row[3][0] ||
-                          (ui.uid=strtol(row[3], &endp, 10), endp[0] != '\0'))
-                       {
-                               DPRINTF("invalid value for uid: '%s'",
-                                       row[3] ? row[3] : "<null>");
-                               mysql_free_result(result);
-                               return 0;
-                       }
-                       if (!row[4] || !row[4][0] ||
-                          (ui.gid=strtol(row[4], &endp, 10), endp[0] != '\0'))
-                       {
-                               DPRINTF("invalid value for gid: '%s'",
-                                       row[4] ? row[4] : "<null>");
-                               mysql_free_result(result);
-                               return 0;
-                       }
-                       if (row[5] && row[5][0])
-                               ui.home=strdup(row[5]);
-                       else
-                       {
-                               DPRINTF("required value for 'home' (column 6) is missing");
-                               mysql_free_result(result);
-                               return(0);
-                       }
-                       if (num_fields > 6 && row[6] && row[6][0])
-                               ui.maildir=strdup(row[6]);
-                       if (num_fields > 7 && row[7] && row[7][0])
-                               ui.quota=strdup(row[7]);
-                       if (num_fields > 8 && row[8] && row[8][0])
-                               ui.fullname=strdup(row[8]);
-                       if (num_fields > 9 && row[9] && row[9][0])
-                               ui.options=strdup(row[9]);
-               }
-               else
-               {
-                       DPRINTF("zero rows returned");
-                       mysql_free_result(result);
-                       return (&ui); /* User not found */
-               }
-       }
-       else
-       {
-               DPRINTF("mysql_store_result failed");
-               return (0);
-       }
-       mysql_free_result(result);
-       return (&ui);
-}
-
-int auth_mysql_setpass(const char *user, const char *pass,
-                      const char *oldpass)
-{
-       char *newpass_crypt;
-       char *sql_buf;
-       int rc=0;
-
-       char *clear_escaped;
-       char *crypt_escaped;
-
-       const char  *clear_field        =NULL,
-                   *crypt_field        =NULL,
-                   *defdomain          =NULL,
-                   *where_clause       =NULL,
-                   *user_table         =NULL,
-                   *login_field        =NULL,
-                   *chpass_clause      =NULL; /* siefca@pld.org.pl */
-
-       if (do_connect())       return (-1);
-
-       if (!(newpass_crypt=authcryptpasswd(pass, oldpass)))
-               return (-1);
-
-       clear_escaped=malloc(strlen(pass)*2+1);
-
-       if (!clear_escaped)
-       {
-               perror("malloc");
-               free(newpass_crypt);
-               return -1;
-       }
-
-       crypt_escaped=malloc(strlen(newpass_crypt)*2+1);
-
-       if (!crypt_escaped)
-       {
-               perror("malloc");
-               free(clear_escaped);
-               free(newpass_crypt);
-               return -1;
-       }
-
-       mysql_real_escape_string(mysql, clear_escaped, pass, strlen(pass));
-       mysql_real_escape_string(mysql, crypt_escaped,
-                                newpass_crypt, strlen(newpass_crypt));
-
-       /* siefca@pld.org.pl */
-       chpass_clause=read_env("MYSQL_CHPASS_CLAUSE");
-       defdomain=read_env("DEFAULT_DOMAIN");
-       user_table=read_env("MYSQL_USER_TABLE");
-       if (!chpass_clause)
-       {
-               int has_domain=strchr(user, '@') != NULL;
-               char *username_escaped;
-               char dummy_buf[1];
-               size_t sql_buf_size;
-
-               username_escaped=malloc(strlen(user)*2+1);
-
-               if (!username_escaped)
-               {
-                       perror("malloc");
-                       free(clear_escaped);
-                       free(crypt_escaped);
-                       free(newpass_crypt);
-                       return -1;
-               }
-
-               mysql_real_escape_string(mysql, username_escaped,
-                                        user, strlen(user));
-
-               login_field = read_env("MYSQL_LOGIN_FIELD");
-               if (!login_field) login_field = "id";
-               crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
-               clear_field=read_env("MYSQL_CLEAR_PWFIELD");
-               where_clause=read_env("MYSQL_WHERE_CLAUSE");
-
-               if (!where_clause)
-                       where_clause="";
-
-               if (!crypt_field)
-                       crypt_field="";
-
-               if (!clear_field)
-                       clear_field="";
-
-               if (!defdomain)
-                       defdomain="";
-
-#define DEFAULT_SETPASS_UPDATE \
-               "UPDATE %s SET %s%s%s%s %s %s%s%s%s WHERE %s='%s%s%s' %s%s%s", \
-                       user_table,                                     \
-                       *clear_field ? clear_field:"",                  \
-                       *clear_field ? "='":"",                         \
-                       *clear_field ? clear_escaped:"",                \
-                       *clear_field ? "'":"",                          \
-                                                                       \
-                       *clear_field && *crypt_field ? ",":"",          \
-                                                                       \
-                       *crypt_field ? crypt_field:"",                  \
-                       *crypt_field ? "='":"",                         \
-                       *crypt_field ? crypt_escaped:"",                \
-                       *crypt_field ? "'":"",                          \
-                       login_field,                                    \
-                       username_escaped,                               \
-                       has_domain || !*defdomain ? "":"@",             \
-                       has_domain ? "":defdomain,                      \
-                       *where_clause ? " AND (":"", where_clause,      \
-                       *where_clause ? ")":""
-
-
-               sql_buf_size=snprintf(dummy_buf, 1, DEFAULT_SETPASS_UPDATE);
-
-               sql_buf=malloc(sql_buf_size+1);
-
-               if (sql_buf)
-                       snprintf(sql_buf, sql_buf_size+1,
-                                DEFAULT_SETPASS_UPDATE);
-
-               free(username_escaped);
-       }
-       else
-       {
-               sql_buf=auth_parse_chpass_clause(escape_str,
-                                                chpass_clause,
-                                                user,
-                                                defdomain,
-                                                clear_escaped,
-                                                crypt_escaped);
-       }
-       
-       free(clear_escaped);
-       free(crypt_escaped);
-       free(newpass_crypt);
-
-       if (courier_authdebug_login_level >= 2)
-       {
-               DPRINTF("setpass SQL: %s", sql_buf);
-       }
-       if (mysql_query (mysql, sql_buf))
-       {
-               DPRINTF("setpass SQL failed");
-               rc= -1;
-               auth_mysql_cleanup();
-       }
-       free(sql_buf);
-       return (rc);
-}
-
-void auth_mysql_enumerate( void(*cb_func)(const char *name,
-                                         uid_t uid,
-                                         gid_t gid,
-                                         const char *homedir,
-                                         const char *maildir,
-                                         const char *options,
-                                         void *void_arg),
-                          void *void_arg)
-{
-       const char *defdomain, *select_clause;
-       char    *querybuf;
-       MYSQL_ROW       row;
-       MYSQL_RES       *result;
-
-       if (do_connect())
-       {
-               (*cb_func)(NULL, 0, 0, NULL, NULL, NULL, void_arg);
-               return;
-       }
-
-       initui();
-
-       select_clause=read_env("MYSQL_ENUMERATE_CLAUSE");
-       defdomain=read_env("DEFAULT_DOMAIN");
-       if (!defdomain || !defdomain[0])
-               defdomain="*"; /* otherwise parse_select_clause fails */
-       
-       if (!select_clause)
-       {
-               const char      *user_table,
-                               *uid_field,
-                               *gid_field,
-                               *login_field,
-                               *home_field,
-                               *maildir_field,
-                               *options_field,
-                               *where_clause;
-               char dummy_buf[1];
-               size_t query_len;
-
-               user_table=read_env("MYSQL_USER_TABLE");
-
-               if (!user_table)
-               {
-                       err("authmysql: MYSQL_USER_TABLE not set in "
-                               AUTHMYSQLRC ".");
-                       return;
-               }
-
-               uid_field = read_env("MYSQL_UID_FIELD");
-               if (!uid_field) uid_field = "uid";
-
-               gid_field = read_env("MYSQL_GID_FIELD");
-               if (!gid_field) gid_field = "gid";
-
-               login_field = read_env("MYSQL_LOGIN_FIELD");
-               if (!login_field) login_field = "id";
-
-               home_field = read_env("MYSQL_HOME_FIELD");
-               if (!home_field) home_field = "home";
-
-               maildir_field=read_env("MYSQL_MAILDIR_FIELD");
-               if (!maildir_field) maildir_field="\"\"";
-
-               options_field=read_env("MYSQL_AUXOPTIONS_FIELD");
-               if (!options_field) options_field="\"\"";
-
-               where_clause=read_env("MYSQL_WHERE_CLAUSE");
-               if (!where_clause) where_clause = "";
-
-
-#define DEFAULT_ENUMERATE_QUERY \
-               "SELECT %s, %s, %s, %s, %s, %s FROM %s %s%s",\
-                       login_field, uid_field, gid_field,              \
-                       home_field, maildir_field,                      \
-                       options_field, user_table,                      \
-                       *where_clause ? " WHERE ":"",                   \
-                       where_clause
-
-               query_len=snprintf(dummy_buf, 1, DEFAULT_ENUMERATE_QUERY);
-
-               querybuf=malloc(query_len+1);
-
-               if (!querybuf)
-               {
-                       perror("malloc");
-                       return;
-               }
-
-               snprintf(querybuf, query_len+1, DEFAULT_ENUMERATE_QUERY);
-       }
-       else
-       {
-               /* siefca@pld.org.pl */
-               querybuf=auth_parse_select_clause (escape_str,
-                                                  select_clause, "*",
-                                                  defdomain, "enumerate");
-               if (!querybuf)
-               {
-                       DPRINTF("authmysql: parse_select_clause failed");
-                       return;
-               }
-       }
-       DPRINTF("authmysql: enumerate query: %s", querybuf);
-
-       if (mysql_query (mysql, querybuf))
-       {
-               DPRINTF("mysql_query failed, reconnecting: %s", mysql_error(mysql));
-               /* <o.blasnik@nextra.de> */
-
-               auth_mysql_cleanup();
-
-               if (do_connect())
-               {
-                       free(querybuf);
-                       return;
-               }
-
-               if (mysql_query (mysql, querybuf))
-               {
-                       DPRINTF("mysql_query failed second time, giving up: %s", mysql_error(mysql));
-                       free(querybuf);
-                       auth_mysql_cleanup();
-                       return;
-               }
-       }
-       free(querybuf);
-
-       result = mysql_use_result (mysql);
-       if (result)
-       {
-               const char *username;
-               uid_t uid;
-               gid_t gid;
-               const char *homedir;
-               const char *maildir;
-               const char *options;
-
-               while ((row = mysql_fetch_row (result)) != NULL)
-               {
-                       if(!row[0] || !row[0][0]
-                          || !row[1] || !row[1][0]
-                          || !row[2] || !row[2][0]
-                          || !row[3] || !row[3][0])
-                       {
-                               continue;
-                       }
-
-                       username=row[0];
-                       uid=atol(row[1]); /* FIXME use strtol to validate */
-                       gid=atol(row[2]);
-                       homedir=row[3];
-                       maildir=row[4];
-                       options=row[5];
-
-                       if (maildir && !*maildir)
-                               maildir=NULL;
-
-                       (*cb_func)(username, uid, gid, homedir,
-                                  maildir, options, void_arg);
-               }
-       }
-       /* NULL row could indicate end of result or an error */
-       if (mysql_errno(mysql))
-       {
-               DPRINTF("mysql error during enumeration: %s", mysql_error(mysql));
-       }
-       else
-               (*cb_func)(NULL, 0, 0, NULL, NULL, NULL, void_arg);
-
-       if (result) mysql_free_result(result);
-}
diff --git a/authmysqllib.cpp b/authmysqllib.cpp
new file mode 100644 (file)
index 0000000..0e8f00a
--- /dev/null
@@ -0,0 +1,810 @@
+/*
+** Copyright 2000-2016 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <unistd.h>
+#include       <ctype.h>
+#include       <sys/types.h>
+#include       <sys/stat.h>
+#include       <mysql.h>
+#include       <time.h>
+
+#include       "authmysql.h"
+
+extern "C" {
+#include       "authmysqlrc.h"
+#include       "auth.h"
+#include       "courierauthdebug.h"
+};
+
+#include <map>
+#include <sstream>
+#include <algorithm>
+
+#define err courier_auth_err
+
+#include "authconfigfile.h"
+
+class authmysql_connection {
+
+public:
+       MYSQL *mysql;
+       time_t last_time;
+
+       class authmysqlrc_vars {
+       public:
+               std::string server, server_socket, userid, password, database,
+                       character_set,
+                       sslkey, sslcert, sslcacert,
+                       sslcapath, sslcipher,
+
+                       defdomain, user_table,
+                       uid_field,
+                       gid_field,
+                       name_field,
+                       crypt_field, clear_field,
+                       login_field,
+                       home_field,
+                       maildir_field,
+                       defaultdelivery_field,
+                       quota_field,
+                       options_field,
+                       where_clause,
+                       select_clause,
+                       enumerate_clause,
+                       chpass_clause;
+
+               unsigned int server_port;
+               unsigned int server_opt;
+
+               authmysqlrc_vars()
+                       : server_port(0), server_opt(0) {}
+       };
+
+       class authmysqlrc_file : public courier::auth::config_file,
+                                public authmysqlrc_vars {
+
+               authmysql_connection &conn;
+
+       public:
+
+               authmysqlrc_file &operator=(const authmysqlrc_file &o)
+               {
+                       courier::auth::config_file::operator=(o);
+                       authmysqlrc_vars::operator=(o);
+                       return *this;
+               }
+
+               authmysqlrc_file(authmysql_connection &connArg)
+                       : courier::auth::config_file(AUTHMYSQLRC),
+                         conn(connArg)
+               {
+               }
+
+               bool do_load()
+               {
+                       server=config("MYSQL_SERVER");
+                       userid=config("MYSQL_USERNAME");
+                       password=config("MYSQL_PASSWORD");
+                       database=config("MYSQL_DATABASE");
+                       character_set=config("MYSQL_CHARACTER_SET");
+
+                       sslkey=config("MYSQL_SSL_KEY");
+                       sslcert=config("MYSQL_SSL_CERT");
+                       sslcacert=config("MYSQL_SSL_CACERT");
+                       sslcapath=config("MYSQL_SSL_CAPATH");
+                       sslcipher=config("MYSQL_SSL_CIPHER");
+
+                       if ((std::istringstream(config("MYSQL_PORT"))
+                            >> server_port).fail())
+                       {
+                               err("authmysql: cannot parse the MYSQL_PORT "
+                                   "setting");
+                               return false;
+                       }
+
+                       if ((std::istringstream(config("MYSQL_OPT"))
+                            >> server_opt).fail())
+                       {
+                               err("authmysql: cannot parse the MYSQL_OPT "
+                                   "setting");
+                               return false;
+                       }
+                       server_socket=config("MYSQL_SOCKET");
+
+                       if (!server.size() && !server_socket.size())
+                       {
+                               err("authmysql: MYSQL_SERVER nor MYSQL_SOCKET set in"
+                                   AUTHMYSQLRC ".");
+                               return false;
+                       }
+
+                       if (!userid.size())
+                       {
+                               err("authmysql: MYSQL_USERNAME not set in "
+                                   AUTHMYSQLRC ".");
+                               return false;
+                       }
+
+                       if (!database.size())
+                       {
+                               err("authmysql: MYSQL_DATABASE not set in "
+                                   AUTHMYSQLRC ".");
+                               return false;
+                       }
+
+                       defdomain=config("DEFAULT_DOMAIN");
+                       user_table=config("MYSQL_USER_TABLE");
+
+                       if (!user_table.size())
+                       {
+                               err("authmysql: MYSQL_USER_TABLE not set in "
+