+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>
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
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
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:
# 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:
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@` || :
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@` || :
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 \
#
# 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@
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
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
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
-# 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,
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
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 \
$(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
$(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
$(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 \
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) \
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CRYPTLIBS = @CRYPTLIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
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@
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 \
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
# 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)
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 \
#
# 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
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
$(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)
$(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)
$(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)
$(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)
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)
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@
@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@
@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
! -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
@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
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*) \
*.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
.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 \
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 \
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 \
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 \
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
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
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
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
-# 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,
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.
]
)
-# 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,
[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
])
# 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,
# 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,
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,
# 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,
# 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,
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,
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,
# 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,
# 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,
# 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,
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,
# 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,
# 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,
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,
_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,
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,
# 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,
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
}
.\" <!-- 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
.\" -----------------------------------------------------------------
.\" <!-- 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
.\" -----------------------------------------------------------------
.\" <!-- 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
.\" -----------------------------------------------------------------
.\" <!-- 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
.\" -----------------------------------------------------------------
.\" <!-- 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
.\" -----------------------------------------------------------------
.\" <!-- 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
.\" -----------------------------------------------------------------
.\" <!-- 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
.\" -----------------------------------------------------------------
.\" <!-- 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
.\" -----------------------------------------------------------------
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
--- /dev/null
+/*
+** 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> ¶meters)
+{
+ 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> ¶meters)
+{
+
+ 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);
+}
--- /dev/null
+#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> ¶meters);
+
+ static std::string
+ parse_custom_query(const std::string &s,
+ const std::string &login,
+ const std::string &defdomain,
+ std::map<std::string,
+ std::string> ¶meters);
+};
+
+template<>
+bool config_file::config(const char *name,
+ std::string &value,
+ bool required,
+ const char *default_value) const;
+
+#if 0
+{
+ {
+#endif
+ }
+}
+
+#endif
#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,
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,
/*
-** Copyright 2000-2008 Double Precision, Inc. See COPYING for
+** Copyright 2000-2018 Double Precision, Inc. See COPYING for
** distribution information.
*/
#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>
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);
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;
p = fullname;
while (*p != ',' && *p != '\0')
p++;
- *p=0;
+ *p=0;
retval = writeenvval(fd, "NAME", fullname);
free(fullname);
if(retval)
struct authstaticinfolist *l;
ei.fd=fd;
+ ei.buf_ptr=ei.buffer;
ei.buf_left=0;
for (l=modulelist; l; l=l->next)
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");
}
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);
-}
--- /dev/null
+/*
+** 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);
+}
-##VERSION: $Id: 7b218a8185f424046f3ef3322a37443983e443e3-20150228120722$
+##VERSION: $Id: 7b218a8185f424046f3ef3322a37443983e443e3-20160104202005$
#
# Copyright 2000-2005 Double Precision, Inc. See COPYING for
# distribution information.
+++ /dev/null
-/*
-** 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;
-}
#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 *),
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 *),
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,
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
+++ /dev/null
-/*
- * 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],"a, 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);
- }
-}
--- /dev/null
+/*
+** 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
+}
-##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
# 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
##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
##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
#
# 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,
##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.
# 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.
.\" <!-- 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
.\" -----------------------------------------------------------------
#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);
}
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);
auth_mysql_enumerate};
-struct authstaticinfo *courier_authmysql_init()
-{
- return &authmysql_info;
+extern "C" {
+ struct authstaticinfo *courier_authmysql_init()
+ {
+ return &authmysql_info;
+ }
}
#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
+++ /dev/null
-/*
-** 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);
-}
--- /dev/null
+/*
+** 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 "
+