diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /pigeonhole/src/lib-sieve/storage/ldap | |
parent | Initial commit. (diff) | |
download | dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole/src/lib-sieve/storage/ldap')
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/Makefile.am | 32 | ||||
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/Makefile.in | 843 | ||||
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.c | 1378 | ||||
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.h | 140 | ||||
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c | 369 | ||||
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c | 169 | ||||
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.c | 230 | ||||
-rw-r--r-- | pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.h | 108 |
8 files changed, 3269 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/storage/ldap/Makefile.am b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.am new file mode 100644 index 0000000..86df92c --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.am @@ -0,0 +1,32 @@ +noinst_LTLIBRARIES = libsieve_storage_ldap.la + +sieve_plugindir = $(dovecot_moduledir)/sieve +sieve_plugin_LTLIBRARIES = + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +ldap_sources = \ + sieve-ldap-db.c \ + sieve-ldap-script.c \ + sieve-ldap-storage.c \ + sieve-ldap-storage-settings.c + +libsieve_storage_ldap_la_SOURCES = $(ldap_sources) +libsieve_storage_ldap_la_LIBADD = $(LDAP_LIBS) + +noinst_HEADERS = \ + sieve-ldap-db.h \ + sieve-ldap-storage.h + +if LDAP_PLUGIN +sieve_plugin_LTLIBRARIES += lib10_sieve_storage_ldap_plugin.la + +lib10_sieve_storage_ldap_plugin_la_LDFLAGS = -module -avoid-version +lib10_sieve_storage_ldap_plugin_la_LIBADD = $(LDAP_LIBS) +lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES = $(LDAP_LIBS) +lib10_sieve_storage_ldap_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DPLUGIN_BUILD +lib10_sieve_storage_ldap_plugin_la_SOURCES = $(ldap_sources) +endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/Makefile.in b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.in new file mode 100644 index 0000000..82a8ac1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/Makefile.in @@ -0,0 +1,843 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@LDAP_PLUGIN_TRUE@am__append_1 = lib10_sieve_storage_ldap_plugin.la +subdir = src/lib-sieve/storage/ldap +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(sieve_plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(sieve_plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +am__lib10_sieve_storage_ldap_plugin_la_SOURCES_DIST = sieve-ldap-db.c \ + sieve-ldap-script.c sieve-ldap-storage.c \ + sieve-ldap-storage-settings.c +am__objects_1 = lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo \ + lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo \ + lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo \ + lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo +@LDAP_PLUGIN_TRUE@am_lib10_sieve_storage_ldap_plugin_la_OBJECTS = \ +@LDAP_PLUGIN_TRUE@ $(am__objects_1) +lib10_sieve_storage_ldap_plugin_la_OBJECTS = \ + $(am_lib10_sieve_storage_ldap_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib10_sieve_storage_ldap_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(lib10_sieve_storage_ldap_plugin_la_LDFLAGS) $(LDFLAGS) -o $@ +@LDAP_PLUGIN_TRUE@am_lib10_sieve_storage_ldap_plugin_la_rpath = \ +@LDAP_PLUGIN_TRUE@ -rpath $(sieve_plugindir) +libsieve_storage_ldap_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__objects_2 = sieve-ldap-db.lo sieve-ldap-script.lo \ + sieve-ldap-storage.lo sieve-ldap-storage-settings.lo +am_libsieve_storage_ldap_la_OBJECTS = $(am__objects_2) +libsieve_storage_ldap_la_OBJECTS = \ + $(am_libsieve_storage_ldap_la_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo \ + ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo \ + ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo \ + ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo \ + ./$(DEPDIR)/sieve-ldap-db.Plo \ + ./$(DEPDIR)/sieve-ldap-script.Plo \ + ./$(DEPDIR)/sieve-ldap-storage-settings.Plo \ + ./$(DEPDIR)/sieve-ldap-storage.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib10_sieve_storage_ldap_plugin_la_SOURCES) \ + $(libsieve_storage_ldap_la_SOURCES) +DIST_SOURCES = $(am__lib10_sieve_storage_ldap_plugin_la_SOURCES_DIST) \ + $(libsieve_storage_ldap_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libsieve_storage_ldap.la +sieve_plugindir = $(dovecot_moduledir)/sieve +sieve_plugin_LTLIBRARIES = $(am__append_1) +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-sieve + +ldap_sources = \ + sieve-ldap-db.c \ + sieve-ldap-script.c \ + sieve-ldap-storage.c \ + sieve-ldap-storage-settings.c + +libsieve_storage_ldap_la_SOURCES = $(ldap_sources) +libsieve_storage_ldap_la_LIBADD = $(LDAP_LIBS) +noinst_HEADERS = \ + sieve-ldap-db.h \ + sieve-ldap-storage.h + +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_LDFLAGS = -module -avoid-version +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_LIBADD = $(LDAP_LIBS) +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES = $(LDAP_LIBS) +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DPLUGIN_BUILD +@LDAP_PLUGIN_TRUE@lib10_sieve_storage_ldap_plugin_la_SOURCES = $(ldap_sources) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-sieve/storage/ldap/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/storage/ldap/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-sieve_pluginLTLIBRARIES: $(sieve_plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(sieve_plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sieve_plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(sieve_plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(sieve_plugindir)"; \ + } + +uninstall-sieve_pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(sieve_plugin_LTLIBRARIES)'; test -n "$(sieve_plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(sieve_plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(sieve_plugindir)/$$f"; \ + done + +clean-sieve_pluginLTLIBRARIES: + -test -z "$(sieve_plugin_LTLIBRARIES)" || rm -f $(sieve_plugin_LTLIBRARIES) + @list='$(sieve_plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib10_sieve_storage_ldap_plugin.la: $(lib10_sieve_storage_ldap_plugin_la_OBJECTS) $(lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES) $(EXTRA_lib10_sieve_storage_ldap_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib10_sieve_storage_ldap_plugin_la_LINK) $(am_lib10_sieve_storage_ldap_plugin_la_rpath) $(lib10_sieve_storage_ldap_plugin_la_OBJECTS) $(lib10_sieve_storage_ldap_plugin_la_LIBADD) $(LIBS) + +libsieve_storage_ldap.la: $(libsieve_storage_ldap_la_OBJECTS) $(libsieve_storage_ldap_la_DEPENDENCIES) $(EXTRA_libsieve_storage_ldap_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_storage_ldap_la_OBJECTS) $(libsieve_storage_ldap_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-db.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-script.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-storage-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sieve-ldap-storage.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo: sieve-ldap-db.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo `test -f 'sieve-ldap-db.c' || echo '$(srcdir)/'`sieve-ldap-db.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-db.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.lo `test -f 'sieve-ldap-db.c' || echo '$(srcdir)/'`sieve-ldap-db.c + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo: sieve-ldap-script.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo `test -f 'sieve-ldap-script.c' || echo '$(srcdir)/'`sieve-ldap-script.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-script.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.lo `test -f 'sieve-ldap-script.c' || echo '$(srcdir)/'`sieve-ldap-script.c + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo: sieve-ldap-storage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo `test -f 'sieve-ldap-storage.c' || echo '$(srcdir)/'`sieve-ldap-storage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-storage.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.lo `test -f 'sieve-ldap-storage.c' || echo '$(srcdir)/'`sieve-ldap-storage.c + +lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo: sieve-ldap-storage-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo -MD -MP -MF $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Tpo -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo `test -f 'sieve-ldap-storage-settings.c' || echo '$(srcdir)/'`sieve-ldap-storage-settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Tpo $(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sieve-ldap-storage-settings.c' object='lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib10_sieve_storage_ldap_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.lo `test -f 'sieve-ldap-storage-settings.c' || echo '$(srcdir)/'`sieve-ldap-storage-settings.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(sieve_plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-sieve_pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-sieve_pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/lib10_sieve_storage_ldap_plugin_la-sieve-ldap-storage.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-db.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-script.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage-settings.Plo + -rm -f ./$(DEPDIR)/sieve-ldap-storage.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-sieve_pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-sieve_pluginLTLIBRARIES cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-sieve_pluginLTLIBRARIES \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-sieve_pluginLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.c new file mode 100644 index 0000000..0a7b440 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.c @@ -0,0 +1,1378 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-ldap-storage.h" + +/* FIXME: Imported this from Dovecot auth for now. We're working on a proper + lib-ldap, but, until then, some code is duplicated here. */ + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "net.h" +#include "ioloop.h" +#include "array.h" +#include "hash.h" +#include "aqueue.h" +#include "str.h" +#include "time-util.h" +#include "env-util.h" +#include "var-expand.h" +#include "istream.h" + +#include <stddef.h> +#include <unistd.h> + +struct db_ldap_result { + int refcount; + LDAPMessage *msg; +}; + +struct db_ldap_result_iterate_context { + pool_t pool; + + struct auth_request *auth_request; + const ARRAY_TYPE(ldap_field) *attr_map; + unsigned int attr_idx; + + /* attribute name => value */ + HASH_TABLE(char *, struct db_ldap_value *) ldap_attrs; + + const char *val_1_arr[2]; + string_t *var, *debug; + + bool skip_null_values; + bool iter_dn_values; +}; + +struct db_ldap_sasl_bind_context { + const char *authcid; + const char *passwd; + const char *realm; + const char *authzid; +}; + +static struct ldap_connection *ldap_connections = NULL; + +static int db_ldap_bind(struct ldap_connection *conn); +static void db_ldap_conn_close(struct ldap_connection *conn); + +int ldap_deref_from_str(const char *str, int *deref_r) +{ + if (strcasecmp(str, "never") == 0) + *deref_r = LDAP_DEREF_NEVER; + else if (strcasecmp(str, "searching") == 0) + *deref_r = LDAP_DEREF_SEARCHING; + else if (strcasecmp(str, "finding") == 0) + *deref_r = LDAP_DEREF_FINDING; + else if (strcasecmp(str, "always") == 0) + *deref_r = LDAP_DEREF_ALWAYS; + else + return -1; + return 0; +} + +int ldap_scope_from_str(const char *str, int *scope_r) +{ + if (strcasecmp(str, "base") == 0) + *scope_r = LDAP_SCOPE_BASE; + else if (strcasecmp(str, "onelevel") == 0) + *scope_r = LDAP_SCOPE_ONELEVEL; + else if (strcasecmp(str, "subtree") == 0) + *scope_r = LDAP_SCOPE_SUBTREE; + else + return -1; + return 0; +} + +#ifdef OPENLDAP_TLS_OPTIONS +int ldap_tls_require_cert_from_str(const char *str, int *opt_x_tls_r) +{ + if (strcasecmp(str, "never") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_NEVER; + else if (strcasecmp(str, "hard") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_HARD; + else if (strcasecmp(str, "demand") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_DEMAND; + else if (strcasecmp(str, "allow") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_ALLOW; + else if (strcasecmp(str, "try") == 0) + *opt_x_tls_r = LDAP_OPT_X_TLS_TRY; + else + return -1; + return 0; +} +#endif + + +static int ldap_get_errno(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret, err; + + ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err); + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: " + "Can't get error number: %s", + ldap_err2string(ret)); + return LDAP_UNAVAILABLE; + } + + return err; +} + +const char *ldap_get_error(struct ldap_connection *conn) +{ + const char *ret; + char *str = NULL; + + ret = ldap_err2string(ldap_get_errno(conn)); + + ldap_get_option(conn->ld, LDAP_OPT_ERROR_STRING, (void *)&str); + if (str != NULL) { + ret = t_strconcat(ret, ", ", str, NULL); + ldap_memfree(str); + } + ldap_set_option(conn->ld, LDAP_OPT_ERROR_STRING, NULL); + return ret; +} + +static void ldap_conn_reconnect(struct ldap_connection *conn) +{ + db_ldap_conn_close(conn); + if (sieve_ldap_db_connect(conn) < 0) + db_ldap_conn_close(conn); +} + +static int ldap_handle_error(struct ldap_connection *conn) +{ + int err = ldap_get_errno(conn); + + switch (err) { + case LDAP_SUCCESS: + i_unreached(); + case LDAP_SIZELIMIT_EXCEEDED: + case LDAP_TIMELIMIT_EXCEEDED: + case LDAP_NO_SUCH_ATTRIBUTE: + case LDAP_UNDEFINED_TYPE: + case LDAP_INAPPROPRIATE_MATCHING: + case LDAP_CONSTRAINT_VIOLATION: + case LDAP_TYPE_OR_VALUE_EXISTS: + case LDAP_INVALID_SYNTAX: + case LDAP_NO_SUCH_OBJECT: + case LDAP_ALIAS_PROBLEM: + case LDAP_INVALID_DN_SYNTAX: + case LDAP_IS_LEAF: + case LDAP_ALIAS_DEREF_PROBLEM: + case LDAP_FILTER_ERROR: + /* invalid input */ + return -1; + case LDAP_SERVER_DOWN: + case LDAP_TIMEOUT: + case LDAP_UNAVAILABLE: + case LDAP_BUSY: +#ifdef LDAP_CONNECT_ERROR + case LDAP_CONNECT_ERROR: +#endif + case LDAP_LOCAL_ERROR: + case LDAP_INVALID_CREDENTIALS: + case LDAP_OPERATIONS_ERROR: + default: + /* connection problems */ + ldap_conn_reconnect(conn); + return 0; + } +} + +static int db_ldap_request_search(struct ldap_connection *conn, + struct ldap_request *request) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + + i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND); + i_assert(request->msgid == -1); + + request->msgid = + ldap_search(conn->ld, *request->base == '\0' ? NULL : + request->base, request->scope, + request->filter, request->attributes, 0); + if (request->msgid == -1) { + e_error(storage->event, "db: " + "ldap_search(%s) parsing failed: %s", + request->filter, ldap_get_error(conn)); + if (ldap_handle_error(conn) < 0) { + /* broken request, remove it */ + return 0; + } + return -1; + } + return 1; +} + +static bool db_ldap_request_queue_next(struct ldap_connection *conn) +{ + struct ldap_request *const *requestp, *request; + int ret = -1; + + /* connecting may call db_ldap_connect_finish(), which gets us back + here. so do the connection before checking the request queue. */ + if (sieve_ldap_db_connect(conn) < 0) + return FALSE; + + if (conn->pending_count == aqueue_count(conn->request_queue)) { + /* no non-pending requests */ + return FALSE; + } + if (conn->pending_count > DB_LDAP_MAX_PENDING_REQUESTS) { + /* wait until server has replied to some requests */ + return FALSE; + } + + requestp = array_idx(&conn->request_array, + aqueue_idx(conn->request_queue, + conn->pending_count)); + request = *requestp; + + switch (conn->conn_state) { + case LDAP_CONN_STATE_DISCONNECTED: + case LDAP_CONN_STATE_BINDING: + /* wait until we're in bound state */ + return FALSE; + case LDAP_CONN_STATE_BOUND: + /* we can do anything in this state */ + break; + } + + ret = db_ldap_request_search(conn, request); + if (ret > 0) { + /* success */ + i_assert(request->msgid != -1); + conn->pending_count++; + return TRUE; + } else if (ret < 0) { + /* disconnected */ + return FALSE; + } else { + /* broken request, remove from queue */ + aqueue_delete_tail(conn->request_queue); + request->callback(conn, request, NULL); + return TRUE; + } +} + +static bool +db_ldap_check_limits(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ldap_request *const *first_requestp; + unsigned int count; + time_t secs_diff; + + count = aqueue_count(conn->request_queue); + if (count == 0) + return TRUE; + + first_requestp = array_idx(&conn->request_array, + aqueue_idx(conn->request_queue, 0)); + secs_diff = ioloop_time - (*first_requestp)->create_time; + if (secs_diff > DB_LDAP_REQUEST_LOST_TIMEOUT_SECS) { + e_error(storage->event, "db: " + "Connection appears to be hanging, reconnecting"); + ldap_conn_reconnect(conn); + return TRUE; + } + return TRUE; +} + +void db_ldap_request(struct ldap_connection *conn, + struct ldap_request *request) +{ + request->msgid = -1; + request->create_time = ioloop_time; + + if (!db_ldap_check_limits(conn)) { + request->callback(conn, request, NULL); + return; + } + + aqueue_append(conn->request_queue, &request); + (void)db_ldap_request_queue_next(conn); +} + +static int db_ldap_connect_finish(struct ldap_connection *conn, int ret) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + + if (ret == LDAP_SERVER_DOWN) { + e_error(storage->event, "db: " + "Can't connect to server: %s", + set->uris != NULL ? + set->uris : set->hosts); + return -1; + } + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: " + "binding failed (dn %s): %s", + set->dn == NULL ? "(none)" : set->dn, + ldap_get_error(conn)); + return -1; + } + + timeout_remove(&conn->to); + conn->conn_state = LDAP_CONN_STATE_BOUND; + e_debug(storage->event, "db: " + "Successfully bound (dn %s)", + set->dn == NULL ? "(none)" : set->dn); + while (db_ldap_request_queue_next(conn)) + ; + return 0; +} + +static void db_ldap_default_bind_finished(struct ldap_connection *conn, + struct db_ldap_result *res) +{ + int ret; + + i_assert(conn->pending_count == 0); + conn->default_bind_msgid = -1; + + ret = ldap_result2error(conn->ld, res->msg, FALSE); + if (db_ldap_connect_finish(conn, ret) < 0) { + /* lost connection, close it */ + db_ldap_conn_close(conn); + } +} + +static void db_ldap_abort_requests(struct ldap_connection *conn, + unsigned int max_count, + unsigned int timeout_secs, + bool error, const char *reason) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ldap_request *const *requestp, *request; + time_t diff; + + while (aqueue_count(conn->request_queue) > 0 && max_count > 0) { + requestp = array_idx(&conn->request_array, + aqueue_idx(conn->request_queue, 0)); + request = *requestp; + + diff = ioloop_time - request->create_time; + if (diff < (time_t)timeout_secs) + break; + + /* timed out, abort */ + aqueue_delete_tail(conn->request_queue); + + if (request->msgid != -1) { + i_assert(conn->pending_count > 0); + conn->pending_count--; + } + if (error) + e_error(storage->event, "db: %s", reason); + else + e_debug(storage->event, "db: %s", reason); + request->callback(conn, request, NULL); + max_count--; + } +} + +static struct ldap_request * +db_ldap_find_request(struct ldap_connection *conn, int msgid, + unsigned int *idx_r) +{ + struct ldap_request *const *requests, *request = NULL; + unsigned int i, count; + + count = aqueue_count(conn->request_queue); + if (count == 0) + return NULL; + + requests = array_idx(&conn->request_array, 0); + for (i = 0; i < count; i++) { + request = requests[aqueue_idx(conn->request_queue, i)]; + if (request->msgid == msgid) { + *idx_r = i; + return request; + } + if (request->msgid == -1) + break; + } + return NULL; +} + +static bool +db_ldap_handle_request_result(struct ldap_connection *conn, + struct ldap_request *request, unsigned int idx, + struct db_ldap_result *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret; + bool final_result; + + i_assert(conn->pending_count > 0); + + switch (ldap_msgtype(res->msg)) { + case LDAP_RES_SEARCH_ENTRY: + case LDAP_RES_SEARCH_RESULT: + break; + case LDAP_RES_SEARCH_REFERENCE: + /* we're going to ignore this */ + return FALSE; + default: + e_error(storage->event, "db: Reply with unexpected type %d", + ldap_msgtype(res->msg)); + return TRUE; + } + + if (ldap_msgtype(res->msg) == LDAP_RES_SEARCH_ENTRY) { + ret = LDAP_SUCCESS; + final_result = FALSE; + } else { + final_result = TRUE; + ret = ldap_result2error(conn->ld, res->msg, 0); + } + if (ret != LDAP_SUCCESS) { + /* handle search failures here */ + e_error(storage->event, "db: " + "ldap_search(base=%s filter=%s) failed: %s", + request->base, request->filter, + ldap_err2string(ret)); + res = NULL; + } else { + if (!final_result && storage->svinst->debug) { + e_debug(storage->event, + "db: ldap_search(base=%s filter=%s) returned entry: %s", + request->base, request->filter, + ldap_get_dn(conn->ld, res->msg)); + } + } + if (res == NULL && !final_result) { + /* wait for the final reply */ + request->failed = TRUE; + return TRUE; + } + if (request->failed) + res = NULL; + if (final_result) { + conn->pending_count--; + aqueue_delete(conn->request_queue, idx); + } + + T_BEGIN { + request->callback(conn, request, res == NULL ? NULL : res->msg); + } T_END; + + if (idx > 0) { + /* see if there are timed out requests */ + db_ldap_abort_requests(conn, idx, + DB_LDAP_REQUEST_LOST_TIMEOUT_SECS, + TRUE, "Request lost"); + } + return TRUE; +} + +static void db_ldap_result_unref(struct db_ldap_result **_res) +{ + struct db_ldap_result *res = *_res; + + *_res = NULL; + i_assert(res->refcount > 0); + if (--res->refcount == 0) { + ldap_msgfree(res->msg); + i_free(res); + } +} + +static void +db_ldap_request_free(struct ldap_request *request) +{ + if (request->result != NULL) + db_ldap_result_unref(&request->result); +} + +static void +db_ldap_handle_result(struct ldap_connection *conn, struct db_ldap_result *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ldap_request *request; + unsigned int idx; + int msgid; + + msgid = ldap_msgid(res->msg); + if (msgid == conn->default_bind_msgid) { + db_ldap_default_bind_finished(conn, res); + return; + } + + request = db_ldap_find_request(conn, msgid, &idx); + if (request == NULL) { + e_error(storage->event, + "db: Reply with unknown msgid %d", msgid); + return; + } + + if (db_ldap_handle_request_result(conn, request, idx, res)) + db_ldap_request_free(request); +} + +static void ldap_input(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct timeval timeout; + struct db_ldap_result *res; + LDAPMessage *msg; + time_t prev_reply_diff; + int ret; + + do { + if (conn->ld == NULL) + return; + + i_zero(&timeout); + ret = ldap_result(conn->ld, LDAP_RES_ANY, 0, &timeout, &msg); +#ifdef OPENLDAP_ASYNC_WORKAROUND + if (ret == 0) { + /* try again, there may be another in buffer */ + ret = ldap_result(conn->ld, LDAP_RES_ANY, 0, + &timeout, &msg); + } +#endif + if (ret <= 0) + break; + + res = i_new(struct db_ldap_result, 1); + res->refcount = 1; + res->msg = msg; + db_ldap_handle_result(conn, res); + db_ldap_result_unref(&res); + } while (conn->io != NULL); + + prev_reply_diff = ioloop_time - conn->last_reply_stamp; + conn->last_reply_stamp = ioloop_time; + + if (ret > 0) { + /* input disabled, continue once it's enabled */ + i_assert(conn->io == NULL); + } else if (ret == 0) { + /* send more requests */ + while (db_ldap_request_queue_next(conn)) + ; + } else if (ldap_get_errno(conn) != LDAP_SERVER_DOWN) { + e_error(storage->event, "db: ldap_result() failed: %s", + ldap_get_error(conn)); + ldap_conn_reconnect(conn); + } else if (aqueue_count(conn->request_queue) > 0 || + prev_reply_diff < DB_LDAP_IDLE_RECONNECT_SECS) { + e_error(storage->event, + "db: Connection lost to LDAP server, reconnecting"); + ldap_conn_reconnect(conn); + } else { + /* server probably disconnected an idle connection. don't + reconnect until the next request comes. */ + db_ldap_conn_close(conn); + } +} + +#ifdef HAVE_LDAP_SASL +static int +sasl_interact(LDAP *ld ATTR_UNUSED, unsigned flags ATTR_UNUSED, + void *defaults, void *interact) +{ + struct db_ldap_sasl_bind_context *context = defaults; + sasl_interact_t *in; + const char *str; + + for (in = interact; in->id != SASL_CB_LIST_END; in++) { + switch (in->id) { + case SASL_CB_GETREALM: + str = context->realm; + break; + case SASL_CB_AUTHNAME: + str = context->authcid; + break; + case SASL_CB_USER: + str = context->authzid; + break; + case SASL_CB_PASS: + str = context->passwd; + break; + default: + str = NULL; + break; + } + if (str != NULL) { + in->len = strlen(str); + in->result = str; + } + + } + return LDAP_SUCCESS; +} +#endif + +static void ldap_connection_timeout(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + i_assert(conn->conn_state == LDAP_CONN_STATE_BINDING); + + e_error(storage->event, "db: Initial binding to LDAP server timed out"); + db_ldap_conn_close(conn); +} + +static int db_ldap_bind(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + int msgid; + + i_assert(conn->conn_state != LDAP_CONN_STATE_BINDING); + i_assert(conn->default_bind_msgid == -1); + i_assert(conn->pending_count == 0); + + msgid = ldap_bind(conn->ld, set->dn, set->dnpass, + LDAP_AUTH_SIMPLE); + if (msgid == -1) { + i_assert(ldap_get_errno(conn) != LDAP_SUCCESS); + if (db_ldap_connect_finish(conn, ldap_get_errno(conn)) < 0) { + /* lost connection, close it */ + db_ldap_conn_close(conn); + } + return -1; + } + + conn->conn_state = LDAP_CONN_STATE_BINDING; + conn->default_bind_msgid = msgid; + + timeout_remove(&conn->to); + conn->to = timeout_add(DB_LDAP_REQUEST_LOST_TIMEOUT_SECS*1000, + ldap_connection_timeout, conn); + return 0; +} + +static int db_ldap_get_fd(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret; + + /* get the connection's fd */ + ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *)&conn->fd); + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: Can't get connection fd: %s", + ldap_err2string(ret)); + return -1; + } + if (conn->fd <= STDERR_FILENO) { + /* Solaris LDAP library seems to be broken */ + e_error(storage->event, + "db: Buggy LDAP library returned wrong fd: %d", + conn->fd); + return -1; + } + i_assert(conn->fd != -1); + net_set_nonblock(conn->fd, TRUE); + return 0; +} + +static int +db_ldap_set_opt(struct ldap_connection *conn, int opt, const void *value, + const char *optname, const char *value_str) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + int ret; + + ret = ldap_set_option(conn->ld, opt, value); + if (ret != LDAP_SUCCESS) { + e_error(storage->event, "db: Can't set option %s to %s: %s", + optname, value_str, ldap_err2string(ret)); + return -1; + } + return 0; +} + +static int +db_ldap_set_opt_str(struct ldap_connection *conn, int opt, const char *value, + const char *optname) +{ + if (value != NULL) + return db_ldap_set_opt(conn, opt, value, optname, value); + return 0; +} + +static int db_ldap_set_tls_options(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + + if (!set->tls) + return 0; + +#ifdef OPENLDAP_TLS_OPTIONS + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CACERTFILE, + set->tls_ca_cert_file, "tls_ca_cert_file") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CACERTDIR, + set->tls_ca_cert_dir, "tls_ca_cert_dir") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CERTFILE, + set->tls_cert_file, "tls_cert_file") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_KEYFILE, + set->tls_key_file, "tls_key_file") < 0) + return -1; + if (db_ldap_set_opt_str(conn, LDAP_OPT_X_TLS_CIPHER_SUITE, + set->tls_cipher_suite, "tls_cipher_suite") < 0) + return -1; + if (set->tls_require_cert != NULL) { + if (db_ldap_set_opt(conn, LDAP_OPT_X_TLS_REQUIRE_CERT, + &set->ldap_tls_require_cert, + "tls_require_cert", set->tls_require_cert) < 0) + return -1; + } +#else + if (set->tls_ca_cert_file != NULL || + set->tls_ca_cert_dir != NULL || + set->tls_cert_file != NULL || + set->tls_key_file != NULL || + set->tls_cipher_suite != NULL) { + e_warning(&conn->lstorage->storage, "db: " + "tls_* settings ignored, " + "your LDAP library doesn't seem to support them"); + } +#endif + return 0; +} + +static int db_ldap_set_options(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + unsigned int ldap_version; + int value; + + if (db_ldap_set_opt(conn, LDAP_OPT_DEREF, &set->ldap_deref, + "deref", set->deref) < 0) + return -1; +#ifdef LDAP_OPT_DEBUG_LEVEL + if (str_to_int(set->debug_level, &value) >= 0 && value != 0) { + if (db_ldap_set_opt(conn, LDAP_OPT_DEBUG_LEVEL, &value, + "debug_level", set->debug_level) < 0) + return -1; + } +#endif + + if (set->ldap_version < 3) { + if (set->sasl_bind) { + e_error(storage->event, + "db: sasl_bind=yes requires ldap_version=3"); + return -1; + } + if (set->tls) { + e_error(storage->event, + "db: tls=yes requires ldap_version=3"); + return -1; + } + } + + ldap_version = set->ldap_version; + if (db_ldap_set_opt(conn, LDAP_OPT_PROTOCOL_VERSION, &ldap_version, + "protocol_version", dec2str(ldap_version)) < 0) + return -1; + if (db_ldap_set_tls_options(conn) < 0) + return -1; + return 0; +} + +int sieve_ldap_db_connect(struct ldap_connection *conn) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + struct timeval start, end; + int debug_level; + bool debug; +#if defined(HAVE_LDAP_SASL) || defined(LDAP_HAVE_START_TLS_S) + int ret; +#endif + + if (conn->conn_state != LDAP_CONN_STATE_DISCONNECTED) + return 0; + + debug = FALSE; + if (str_to_int(set->debug_level, &debug_level) >= 0) + debug = debug_level > 0; + + if (debug) + i_gettimeofday(&start); + i_assert(conn->pending_count == 0); + if (conn->ld == NULL) { + if (set->uris != NULL) { +#ifdef LDAP_HAVE_INITIALIZE + if (ldap_initialize(&conn->ld, set->uris) != LDAP_SUCCESS) + conn->ld = NULL; +#else + e_error(storage->event, "db: " + "Your LDAP library doesn't support " + "'uris' setting, use 'hosts' instead."); + return -1; +#endif + } else + conn->ld = ldap_init(set->hosts, LDAP_PORT); + + if (conn->ld == NULL) { + e_error(storage->event, "db: " + "ldap_init() failed with hosts: %s", set->hosts); + return -1; + } + + if (db_ldap_set_options(conn) < 0) + return -1; + } + + if (set->tls) { +#ifdef LDAP_HAVE_START_TLS_S + ret = ldap_start_tls_s(conn->ld, NULL, NULL); + if (ret != LDAP_SUCCESS) { + if (ret == LDAP_OPERATIONS_ERROR && + set->uris != NULL && + str_begins(set->uris, "ldaps:")) { + e_error(storage->event, "db: " + "Don't use both tls=yes and ldaps URI"); + } + e_error(storage->event, "db: " + "ldap_start_tls_s() failed: %s", + ldap_err2string(ret)); + return -1; + } +#else + e_error(storage->event, "db: " + "Your LDAP library doesn't support TLS"); + return -1; +#endif + } + + if (set->sasl_bind) { +#ifdef HAVE_LDAP_SASL + struct db_ldap_sasl_bind_context context; + + i_zero(&context); + context.authcid = set->dn; + context.passwd = set->dnpass; + context.realm = set->sasl_realm; + context.authzid = set->sasl_authz_id; + + /* There doesn't seem to be a way to do SASL binding + asynchronously.. */ + ret = ldap_sasl_interactive_bind_s(conn->ld, NULL, + set->sasl_mech, + NULL, NULL, LDAP_SASL_QUIET, + sasl_interact, &context); + if (db_ldap_connect_finish(conn, ret) < 0) + return -1; +#else + e_error(storage->event, "db: " + "sasl_bind=yes but no SASL support compiled in"); + return -1; +#endif + conn->conn_state = LDAP_CONN_STATE_BOUND; + } else { + if (db_ldap_bind(conn) < 0) + return -1; + } + if (debug) { + i_gettimeofday(&end); + int msecs = timeval_diff_msecs(&end, &start); + e_debug(storage->event, "db: " + "Initialization took %d msecs", msecs); + } + + if (db_ldap_get_fd(conn) < 0) + return -1; + conn->io = io_add(conn->fd, IO_READ, ldap_input, conn); + return 0; +} + +void db_ldap_enable_input(struct ldap_connection *conn, bool enable) +{ + if (!enable) { + io_remove(&conn->io); + } else { + if (conn->io == NULL && conn->fd != -1) { + conn->io = io_add(conn->fd, IO_READ, ldap_input, conn); + ldap_input(conn); + } + } +} + +static void db_ldap_disconnect_timeout(struct ldap_connection *conn) +{ + db_ldap_abort_requests(conn, UINT_MAX, + DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS, FALSE, + "Aborting (timeout), we're not connected to LDAP server"); + + if (aqueue_count(conn->request_queue) == 0) { + /* no requests left, remove this timeout handler */ + timeout_remove(&conn->to); + } +} + +static void db_ldap_conn_close(struct ldap_connection *conn) +{ + struct ldap_request *const *requests, *request; + unsigned int i; + + conn->conn_state = LDAP_CONN_STATE_DISCONNECTED; + conn->default_bind_msgid = -1; + + timeout_remove(&conn->to); + + if (conn->pending_count != 0) { + requests = array_idx(&conn->request_array, 0); + for (i = 0; i < conn->pending_count; i++) { + request = requests[aqueue_idx(conn->request_queue, i)]; + + i_assert(request->msgid != -1); + request->msgid = -1; + } + conn->pending_count = 0; + } + + if (conn->ld != NULL) { + ldap_unbind(conn->ld); + conn->ld = NULL; + } + conn->fd = -1; + + /* the fd may have already been closed before ldap_unbind(), + so we'll have to use io_remove_closed(). */ + io_remove_closed(&conn->io); + + if (aqueue_count(conn->request_queue) > 0) { + conn->to = timeout_add(DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS * + 1000/2, db_ldap_disconnect_timeout, conn); + } +} + +struct ldap_field_find_context { + ARRAY_TYPE(string) attr_names; + pool_t pool; +}; + +#define IS_LDAP_ESCAPED_CHAR(c) \ + ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\') + +const char *ldap_escape(const char *str) +{ + const char *p; + string_t *ret; + + for (p = str; *p != '\0'; p++) { + if (IS_LDAP_ESCAPED_CHAR(*p)) + break; + } + + if (*p == '\0') + return str; + + ret = t_str_new((size_t) (p - str) + 64); + str_append_data(ret, str, (size_t) (p - str)); + + for (; *p != '\0'; p++) { + if (IS_LDAP_ESCAPED_CHAR(*p)) + str_append_c(ret, '\\'); + str_append_c(ret, *p); + } + return str_c(ret); +} + +struct ldap_connection * +sieve_ldap_db_init(struct sieve_ldap_storage *lstorage) +{ + struct ldap_connection *conn; + pool_t pool; + + pool = pool_alloconly_create("ldap_connection", 1024); + conn = p_new(pool, struct ldap_connection, 1); + conn->pool = pool; + conn->refcount = 1; + conn->lstorage = lstorage; + + conn->conn_state = LDAP_CONN_STATE_DISCONNECTED; + conn->default_bind_msgid = -1; + conn->fd = -1; + + i_array_init(&conn->request_array, 512); + conn->request_queue = aqueue_init(&conn->request_array.arr); + + conn->next = ldap_connections; + ldap_connections = conn; + return conn; +} + +void sieve_ldap_db_unref(struct ldap_connection **_conn) +{ + struct ldap_connection *conn = *_conn; + struct ldap_connection **p; + + *_conn = NULL; + i_assert(conn->refcount >= 0); + if (--conn->refcount > 0) + return; + + for (p = &ldap_connections; *p != NULL; p = &(*p)->next) { + if (*p == conn) { + *p = conn->next; + break; + } + } + + db_ldap_abort_requests(conn, UINT_MAX, 0, FALSE, "Shutting down"); + i_assert(conn->pending_count == 0); + db_ldap_conn_close(conn); + i_assert(conn->to == NULL); + + array_free(&conn->request_array); + aqueue_deinit(&conn->request_queue); + + pool_unref(&conn->pool); +} + +static void db_ldap_switch_ioloop(struct ldap_connection *conn) +{ + if (conn->to != NULL) + conn->to = io_loop_move_timeout(&conn->to); + if (conn->io != NULL) + conn->io = io_loop_move_io(&conn->io); +} + +static void db_ldap_wait(struct ldap_connection *conn) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct ioloop *prev_ioloop = current_ioloop; + + i_assert(conn->ioloop == NULL); + + if (aqueue_count(conn->request_queue) == 0) + return; + + conn->ioloop = io_loop_create(); + db_ldap_switch_ioloop(conn); + /* either we're waiting for network I/O or we're getting out of a + callback using timeout_add_short(0) */ + i_assert(io_loop_have_ios(conn->ioloop) || + io_loop_have_immediate_timeouts(conn->ioloop)); + + do { + e_debug(storage->event, "db: " + "Waiting for %d requests to finish", + aqueue_count(conn->request_queue) ); + io_loop_run(conn->ioloop); + } while (aqueue_count(conn->request_queue) > 0); + + e_debug(storage->event, "db: All requests finished"); + + current_ioloop = prev_ioloop; + db_ldap_switch_ioloop(conn); + current_ioloop = conn->ioloop; + io_loop_destroy(&conn->ioloop); +} + +static void sieve_ldap_db_script_free(unsigned char *script) +{ + i_free(script); +} + +static int +sieve_ldap_db_get_script_modattr(struct ldap_connection *conn, + LDAPMessage *entry, pool_t pool, const char **modattr_r) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + char *attr, **vals; + BerElement *ber; + + *modattr_r = NULL; + + attr = ldap_first_attribute(conn->ld, entry, &ber); + while (attr != NULL) { + if (strcmp(attr, set->sieve_ldap_mod_attr) == 0) { + vals = ldap_get_values(conn->ld, entry, attr); + if (vals == NULL || vals[0] == NULL) + return 0; + + if (vals[1] != NULL) { + e_warning(storage->event, "db: " + "Search returned more than one Sieve modified attribute `%s'; " + "using only the first one.", set->sieve_ldap_mod_attr); + } + + *modattr_r = p_strdup(pool, vals[0]); + + ldap_value_free(vals); + ldap_memfree(attr); + return 1; + } + ldap_memfree(attr); + attr = ldap_next_attribute(conn->ld, entry, ber); + } + ber_free(ber, 0); + + return 0; +} + +static int +sieve_ldap_db_get_script(struct ldap_connection *conn, + LDAPMessage *entry, struct istream **script_r) +{ + const struct sieve_ldap_storage_settings *set = &conn->lstorage->set; + struct sieve_storage *storage = &conn->lstorage->storage; + char *attr; + unsigned char *data; + size_t size; + struct berval **vals; + BerElement *ber; + + attr = ldap_first_attribute(conn->ld, entry, &ber); + while (attr != NULL) { + if (strcmp(attr, set->sieve_ldap_script_attr) == 0) { + vals = ldap_get_values_len(conn->ld, entry, attr); + if (vals == NULL || vals[0] == NULL) + return 0; + + if (vals[1] != NULL) { + e_warning(storage->event, "db: " + "Search returned more than one Sieve script attribute `%s'; " + "using only the first one.", set->sieve_ldap_script_attr); + } + + size = vals[0]->bv_len; + data = i_malloc(size); + + e_debug(storage->event, "db: " + "Found script with length %zu", size); + + memcpy(data, vals[0]->bv_val, size); + + ldap_value_free_len(vals); + ldap_memfree(attr); + + *script_r = i_stream_create_from_data(data, size); + i_stream_add_destroy_callback + (*script_r, sieve_ldap_db_script_free, data); + return 1; + } + ldap_memfree(attr); + attr = ldap_next_attribute(conn->ld, entry, ber); + } + ber_free(ber, 0); + + return 0; +} + +const struct var_expand_table +auth_request_var_expand_static_tab[] = { + { 'u', NULL, "user" }, + { 'n', NULL, "username" }, + { 'd', NULL, "domain" }, + { 'h', NULL, "home" }, + { '\0', NULL, "name" }, + { '\0', NULL, NULL } +}; + +static const struct var_expand_table * +db_ldap_get_var_expand_table(struct ldap_connection *conn, + const char *name) +{ + struct sieve_ldap_storage *lstorage = conn->lstorage; + struct sieve_instance *svinst = lstorage->storage.svinst; + const unsigned int auth_count = + N_ELEMENTS(auth_request_var_expand_static_tab); + struct var_expand_table *tab; + + /* keep the extra fields at the beginning. the last static_tab field + contains the ending NULL-fields. */ + tab = t_malloc_no0((auth_count) * sizeof(*tab)); + + memcpy(tab, auth_request_var_expand_static_tab, + auth_count * sizeof(*tab)); + + tab[0].value = ldap_escape(lstorage->username); + tab[1].value = ldap_escape(t_strcut(lstorage->username, '@')); + tab[2].value = strchr(lstorage->username, '@'); + if (tab[2].value != NULL) + tab[2].value = ldap_escape(tab[2].value+1); + tab[3].value = ldap_escape(svinst->home_dir); + tab[4].value = ldap_escape(name); + return tab; +} + +struct sieve_ldap_script_lookup_request { + struct ldap_request request; + + unsigned int entries; + const char *result_dn; + const char *result_modattr; +}; + +static void +sieve_ldap_lookup_script_callback(struct ldap_connection *conn, + struct ldap_request *request, LDAPMessage *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct sieve_ldap_script_lookup_request *srequest = + (struct sieve_ldap_script_lookup_request *)request; + + if (res == NULL) { + io_loop_stop(conn->ioloop); + return; + } + + if (ldap_msgtype(res) != LDAP_RES_SEARCH_RESULT) { + if (srequest->result_dn == NULL) { + srequest->result_dn = p_strdup + (request->pool, ldap_get_dn(conn->ld, res)); + (void)sieve_ldap_db_get_script_modattr + (conn, res, request->pool, &srequest->result_modattr); + } else if (srequest->entries++ == 0) { + e_warning(storage->event, "db: " + "Search returned more than one entry for Sieve script; " + "using only the first one."); + } + } else { + io_loop_stop(conn->ioloop); + return; + } +} + +int sieve_ldap_db_lookup_script(struct ldap_connection *conn, + const char *name, const char **dn_r, const char **modattr_r) +{ + struct sieve_ldap_storage *lstorage = conn->lstorage; + struct sieve_storage *storage = &lstorage->storage; + const struct sieve_ldap_storage_settings *set = &lstorage->set; + struct sieve_ldap_script_lookup_request *request; + const struct var_expand_table *tab; + char **attr_names; + const char *error; + string_t *str; + + pool_t pool = pool_alloconly_create + ("sieve_ldap_script_lookup_request", 512); + request = p_new(pool, struct sieve_ldap_script_lookup_request, 1); + request->request.pool = pool; + + tab = db_ldap_get_var_expand_table(conn, name); + + str = t_str_new(512); + if (var_expand(str, set->base, tab, &error) <= 0) { + e_error(storage->event, "db: " + "Failed to expand base=%s: %s", + set->base, error); + return -1; + } + request->request.base = p_strdup(pool, str_c(str)); + + attr_names = p_new(pool, char *, 3); + attr_names[0] = p_strdup(pool, set->sieve_ldap_mod_attr); + + str_truncate(str, 0); + if (var_expand(str, set->sieve_ldap_filter, tab, &error) <= 0) { + e_error(storage->event, "db: " + "Failed to expand sieve_ldap_filter=%s: %s", + set->sieve_ldap_filter, error); + return -1; + } + + request->request.scope = lstorage->set.ldap_scope; + request->request.filter = p_strdup(pool, str_c(str)); + request->request.attributes = attr_names; + + e_debug(storage->event, "base=%s scope=%s filter=%s fields=%s", + request->request.base, lstorage->set.scope, + request->request.filter, + t_strarray_join((const char **)attr_names, ",")); + + request->request.callback = sieve_ldap_lookup_script_callback; + db_ldap_request(conn, &request->request); + db_ldap_wait(conn); + + *dn_r = t_strdup(request->result_dn); + *modattr_r = t_strdup(request->result_modattr); + pool_unref(&request->request.pool); + return (*dn_r == NULL ? 0 : 1); +} + +struct sieve_ldap_script_read_request { + struct ldap_request request; + + unsigned int entries; + struct istream *result; +}; + +static void +sieve_ldap_read_script_callback(struct ldap_connection *conn, + struct ldap_request *request, LDAPMessage *res) +{ + struct sieve_storage *storage = &conn->lstorage->storage; + struct sieve_ldap_script_read_request *srequest = + (struct sieve_ldap_script_read_request *)request; + + if (res == NULL) { + io_loop_stop(conn->ioloop); + return; + } + + if (ldap_msgtype(res) != LDAP_RES_SEARCH_RESULT) { + + if (srequest->result == NULL) { + (void)sieve_ldap_db_get_script(conn, res, &srequest->result); + } else { + e_error(storage->event, "db: " + "Search returned more than one entry for Sieve script DN"); + i_stream_unref(&srequest->result); + } + + } else { + io_loop_stop(conn->ioloop); + return; + } +} + +int sieve_ldap_db_read_script(struct ldap_connection *conn, + const char *dn, struct istream **script_r) +{ + struct sieve_ldap_storage *lstorage = conn->lstorage; + struct sieve_storage *storage = &lstorage->storage; + const struct sieve_ldap_storage_settings *set = &lstorage->set; + struct sieve_ldap_script_read_request *request; + char **attr_names; + + pool_t pool = pool_alloconly_create + ("sieve_ldap_script_read_request", 512); + request = p_new(pool, struct sieve_ldap_script_read_request, 1); + request->request.pool = pool; + request->request.base = p_strdup(pool, dn); + + attr_names = p_new(pool, char *, 3); + attr_names[0] = p_strdup(pool, set->sieve_ldap_script_attr); + + request->request.scope = LDAP_SCOPE_BASE; + request->request.filter = "(objectClass=*)"; + request->request.attributes = attr_names; + + e_debug(storage->event, "base=%s scope=base filter=%s fields=%s", + request->request.base, request->request.filter, + t_strarray_join((const char **)attr_names, ",")); + + request->request.callback = sieve_ldap_read_script_callback; + db_ldap_request(conn, &request->request); + db_ldap_wait(conn); + + *script_r = request->result; + pool_unref(&request->request.pool); + return (*script_r == NULL ? 0 : 1); +} + + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.h b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.h new file mode 100644 index 0000000..d213026 --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-db.h @@ -0,0 +1,140 @@ +#ifndef DB_LDAP_H +#define DB_LDAP_H + +/* Functions like ldap_bind() have been deprecated in OpenLDAP 2.3 + This define enables them until the code here can be refactored */ +#define LDAP_DEPRECATED 1 + +/* Maximum number of pending requests before delaying new requests. */ +#define DB_LDAP_MAX_PENDING_REQUESTS 8 +/* If LDAP connection is down, fail requests after waiting for this long. */ +#define DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS 4 +/* If request is still in queue after this many seconds and other requests + have been replied, assume the request was lost and abort it. */ +#define DB_LDAP_REQUEST_LOST_TIMEOUT_SECS 60 +/* If server disconnects us, don't reconnect if no requests have been sent + for this many seconds. */ +#define DB_LDAP_IDLE_RECONNECT_SECS 60 + +#include <ldap.h> + +#define HAVE_LDAP_SASL +#ifdef HAVE_SASL_SASL_H +# include <sasl/sasl.h> +#elif defined (HAVE_SASL_H) +# include <sasl.h> +#else +# undef HAVE_LDAP_SASL +#endif +#ifdef LDAP_OPT_X_TLS +# define OPENLDAP_TLS_OPTIONS +#endif +#if !defined(SASL_VERSION_MAJOR) || SASL_VERSION_MAJOR < 2 +# undef HAVE_LDAP_SASL +#endif + +#ifndef LDAP_SASL_QUIET +# define LDAP_SASL_QUIET 0 /* Doesn't exist in Solaris LDAP */ +#endif + +/* Older versions may require calling ldap_result() twice */ +#if LDAP_VENDOR_VERSION <= 20112 +# define OPENLDAP_ASYNC_WORKAROUND +#endif + +/* Solaris LDAP library doesn't have LDAP_OPT_SUCCESS */ +#ifndef LDAP_OPT_SUCCESS +# define LDAP_OPT_SUCCESS LDAP_SUCCESS +#endif + +struct ldap_connection; +struct ldap_request; + +typedef void db_search_callback_t(struct ldap_connection *conn, + struct ldap_request *request, + LDAPMessage *res); +struct ldap_request { + pool_t pool; + + /* msgid for sent requests, -1 if not sent */ + int msgid; + /* timestamp when request was created */ + time_t create_time; + + bool failed; + + db_search_callback_t *callback; + + const char *base; + const char *filter; + int scope; + char **attributes; + + struct db_ldap_result *result; +}; + +enum ldap_connection_state { + /* Not connected */ + LDAP_CONN_STATE_DISCONNECTED, + /* Binding - either to default dn or doing auth bind */ + LDAP_CONN_STATE_BINDING, + /* Bound */ + LDAP_CONN_STATE_BOUND +}; + +struct ldap_connection { + struct ldap_connection *next; + + struct sieve_ldap_storage *lstorage; + + pool_t pool; + int refcount; + + LDAP *ld; + enum ldap_connection_state conn_state; + int default_bind_msgid; + + int fd; + struct io *io; + struct timeout *to; + struct ioloop *ioloop; + + /* Request queue contains sent requests at tail (msgid != -1) and + queued requests at head (msgid == -1). */ + struct aqueue *request_queue; + ARRAY(struct ldap_request *) request_array; + /* Number of messages in queue with msgid != -1 */ + unsigned int pending_count; + + /* Timestamp when we last received a reply */ + time_t last_reply_stamp; +}; + + +int ldap_deref_from_str(const char *str, int *deref_r); +int ldap_scope_from_str(const char *str, int *scope_r); +#ifdef OPENLDAP_TLS_OPTIONS +int ldap_tls_require_cert_from_str(const char *str, int *opt_x_tls_r); +#endif + +/* Send/queue request */ +void db_ldap_request(struct ldap_connection *conn, + struct ldap_request *request); + +void db_ldap_enable_input(struct ldap_connection *conn, bool enable); + +const char *ldap_escape(const char *str); +const char *ldap_get_error(struct ldap_connection *conn); + +int sieve_ldap_db_connect(struct ldap_connection *conn); + +struct ldap_connection * +sieve_ldap_db_init(struct sieve_ldap_storage *lstorage); +void sieve_ldap_db_unref(struct ldap_connection **conn); + +int sieve_ldap_db_lookup_script(struct ldap_connection *conn, + const char *name, const char **dn_r, const char **modattr_r); +int sieve_ldap_db_read_script(struct ldap_connection *conn, + const char *dn, struct istream **script_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c new file mode 100644 index 0000000..1c732db --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c @@ -0,0 +1,369 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "time-util.h" +#include "istream.h" + +#include "sieve-ldap-storage.h" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "str.h" +#include "strfuncs.h" + +#include "sieve-error.h" +#include "sieve-dump.h" +#include "sieve-binary.h" + +/* + * Script file implementation + */ + +static struct sieve_ldap_script *sieve_ldap_script_alloc(void) +{ + struct sieve_ldap_script *lscript; + pool_t pool; + + pool = pool_alloconly_create("sieve_ldap_script", 1024); + lscript = p_new(pool, struct sieve_ldap_script, 1); + lscript->script = sieve_ldap_script; + lscript->script.pool = pool; + + return lscript; +} + +struct sieve_ldap_script *sieve_ldap_script_init +(struct sieve_ldap_storage *lstorage, const char *name) +{ + struct sieve_storage *storage = &lstorage->storage; + struct sieve_ldap_script *lscript = NULL; + const char *location; + + if ( name == NULL ) { + name = SIEVE_LDAP_SCRIPT_DEFAULT; + location = storage->location; + } else { + location = t_strconcat + (storage->location, ";name=", name, NULL); + } + + lscript = sieve_ldap_script_alloc(); + sieve_script_init(&lscript->script, + storage, &sieve_ldap_script, location, name); + return lscript; +} + +static int sieve_ldap_script_open +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + struct sieve_storage *storage = script->storage; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + int ret; + + if ( sieve_ldap_db_connect(lstorage->conn) < 0 ) { + sieve_storage_set_critical(storage, + "Failed to connect to LDAP database"); + *error_r = storage->error_code; + return -1; + } + + if ( (ret=sieve_ldap_db_lookup_script(lstorage->conn, + script->name, &lscript->dn, &lscript->modattr)) <= 0 ) { + if ( ret == 0 ) { + e_debug(script->event, "Script entry not found"); + sieve_script_set_error(script, + SIEVE_ERROR_NOT_FOUND, + "Sieve script not found"); + } else { + sieve_script_set_internal_error(script); + } + *error_r = script->storage->error_code; + return -1; + } + + return 0; +} + +static int sieve_ldap_script_get_stream +(struct sieve_script *script, struct istream **stream_r, + enum sieve_error *error_r) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + struct sieve_storage *storage = script->storage; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + int ret; + + i_assert(lscript->dn != NULL); + + if ( (ret=sieve_ldap_db_read_script( + lstorage->conn, lscript->dn, stream_r)) <= 0 ) { + if ( ret == 0 ) { + e_debug(script->event, "Script attribute not found"); + sieve_script_set_error(script, + SIEVE_ERROR_NOT_FOUND, + "Sieve script not found"); + } else { + sieve_script_set_internal_error(script); + } + *error_r = script->storage->error_code; + return -1; + } + return 0; +} + +static int sieve_ldap_script_binary_read_metadata +(struct sieve_script *script, struct sieve_binary_block *sblock, + sieve_size_t *offset) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + struct sieve_instance *svinst = script->storage->svinst; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)script->storage; + struct sieve_binary *sbin = + sieve_binary_block_get_binary(sblock); + time_t bmtime = sieve_binary_mtime(sbin); + string_t *dn, *modattr; + + /* config file changed? */ + if ( bmtime <= lstorage->set_mtime ) { + if ( svinst->debug ) { + e_debug(script->event, + "Sieve binary `%s' is not newer " + "than the LDAP configuration `%s' (%s <= %s)", + sieve_binary_path(sbin), lstorage->config_file, + t_strflocaltime("%Y-%m-%d %H:%M:%S", bmtime), + t_strflocaltime("%Y-%m-%d %H:%M:%S", lstorage->set_mtime)); + } + return 0; + } + + /* open script if not open already */ + if ( lscript->dn == NULL && + sieve_script_open(script, NULL) < 0 ) + return 0; + + /* if modattr not found, recompile always */ + if ( lscript->modattr == NULL || *lscript->modattr == '\0' ) { + e_error(script->event, + "LDAP entry for script `%s' " + "has no modified attribute `%s'", + sieve_script_location(script), + lstorage->set.sieve_ldap_mod_attr); + return 0; + } + + /* compare DN in binary and from search result */ + if ( !sieve_binary_read_string(sblock, offset, &dn) ) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s': " + "Invalid DN", + sieve_binary_path(sbin), sieve_script_location(script)); + return -1; + } + i_assert( lscript->dn != NULL ); + if ( strcmp(str_c(dn), lscript->dn) != 0 ) { + e_debug(script->event, + "Binary `%s' reports different LDAP DN for script `%s' " + "(`%s' rather than `%s')", + sieve_binary_path(sbin), sieve_script_location(script), + str_c(dn), lscript->dn); + return 0; + } + + /* compare modattr in binary and from search result */ + if ( !sieve_binary_read_string(sblock, offset, &modattr) ) { + e_error(script->event, + "Binary `%s' has invalid metadata for script `%s': " + "Invalid modified attribute", + sieve_binary_path(sbin), sieve_script_location(script)); + return -1; + } + if ( strcmp(str_c(modattr), lscript->modattr) != 0 ) { + e_debug(script->event, + "Binary `%s' reports different modified attribute content " + "for script `%s' (`%s' rather than `%s')", + sieve_binary_path(sbin), sieve_script_location(script), + str_c(modattr), lscript->modattr); + return 0; + } + return 1; +} + +static void sieve_ldap_script_binary_write_metadata +(struct sieve_script *script, struct sieve_binary_block *sblock) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + + sieve_binary_emit_cstring(sblock, lscript->dn); + if (lscript->modattr == NULL) + sieve_binary_emit_cstring(sblock, ""); + else + sieve_binary_emit_cstring(sblock, lscript->modattr); +} + +static bool sieve_ldap_script_binary_dump_metadata +(struct sieve_script *script ATTR_UNUSED, struct sieve_dumptime_env *denv, + struct sieve_binary_block *sblock, sieve_size_t *offset) +{ + string_t *dn, *modattr; + + if ( !sieve_binary_read_string(sblock, offset, &dn) ) + return FALSE; + sieve_binary_dumpf(denv, "ldap.dn = %s\n", str_c(dn)); + + if ( !sieve_binary_read_string(sblock, offset, &modattr) ) + return FALSE; + sieve_binary_dumpf(denv, "ldap.mod_attr = %s\n", str_c(modattr)); + + return TRUE; +} + +static const char *sieve_ldap_script_get_binpath +(struct sieve_ldap_script *lscript) +{ + struct sieve_script *script = &lscript->script; + struct sieve_storage *storage = script->storage; + + if ( lscript->binpath == NULL ) { + if ( storage->bin_dir == NULL ) + return NULL; + lscript->binpath = p_strconcat(script->pool, + storage->bin_dir, "/", + sieve_binfile_from_name(script->name), NULL); + } + + return lscript->binpath; +} + +static struct sieve_binary *sieve_ldap_script_binary_load +(struct sieve_script *script, enum sieve_error *error_r) +{ + struct sieve_storage *storage = script->storage; + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + + if ( sieve_ldap_script_get_binpath(lscript) == NULL ) + return NULL; + + return sieve_binary_open(storage->svinst, + lscript->binpath, script, error_r); +} + +static int sieve_ldap_script_binary_save +(struct sieve_script *script, struct sieve_binary *sbin, bool update, + enum sieve_error *error_r) +{ + struct sieve_ldap_script *lscript = + (struct sieve_ldap_script *)script; + + if ( sieve_ldap_script_get_binpath(lscript) == NULL ) + return 0; + + if ( sieve_storage_setup_bindir(script->storage, 0700) < 0 ) + return -1; + + return sieve_binary_save + (sbin, lscript->binpath, update, 0600, error_r); +} + +static bool sieve_ldap_script_equals +(const struct sieve_script *script, const struct sieve_script *other) +{ + struct sieve_storage *storage = script->storage; + struct sieve_storage *sother = other->storage; + + if ( strcmp(storage->location, sother->location) != 0 ) + return FALSE; + + i_assert( script->name != NULL && other->name != NULL ); + + return ( strcmp(script->name, other->name) == 0 ); +} + +const struct sieve_script sieve_ldap_script = { + .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME, + .v = { + .open = sieve_ldap_script_open, + + .get_stream = sieve_ldap_script_get_stream, + + .binary_read_metadata = sieve_ldap_script_binary_read_metadata, + .binary_write_metadata = sieve_ldap_script_binary_write_metadata, + .binary_dump_metadata = sieve_ldap_script_binary_dump_metadata, + .binary_load = sieve_ldap_script_binary_load, + .binary_save = sieve_ldap_script_binary_save, + + .equals = sieve_ldap_script_equals + } +}; + +/* + * Script sequence + */ + +struct sieve_ldap_script_sequence { + struct sieve_script_sequence seq; + + bool done:1; +}; + +struct sieve_script_sequence *sieve_ldap_storage_get_script_sequence +(struct sieve_storage *storage, enum sieve_error *error_r) +{ + struct sieve_ldap_script_sequence *lsec = NULL; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + + /* Create sequence object */ + lsec = i_new(struct sieve_ldap_script_sequence, 1); + sieve_script_sequence_init(&lsec->seq, storage); + + return &lsec->seq; +} + +struct sieve_script *sieve_ldap_script_sequence_next +(struct sieve_script_sequence *seq, enum sieve_error *error_r) +{ + struct sieve_ldap_script_sequence *lsec = + (struct sieve_ldap_script_sequence *)seq; + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)seq->storage; + struct sieve_ldap_script *lscript; + + if ( error_r != NULL ) + *error_r = SIEVE_ERROR_NONE; + + if ( lsec->done ) + return NULL; + lsec->done = TRUE; + + lscript = sieve_ldap_script_init + (lstorage, seq->storage->script_name); + if ( sieve_script_open(&lscript->script, error_r) < 0 ) { + struct sieve_script *script = &lscript->script; + sieve_script_unref(&script); + return NULL; + } + + return &lscript->script; +} + +void sieve_ldap_script_sequence_destroy +(struct sieve_script_sequence *seq) +{ + struct sieve_ldap_script_sequence *lsec = + (struct sieve_ldap_script_sequence *)seq; + i_free(lsec); +} + + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c new file mode 100644 index 0000000..35fe5cb --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c @@ -0,0 +1,169 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "env-util.h" +#include "settings.h" + +#include "sieve-common.h" + +#include "sieve-ldap-storage.h" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "sieve-error.h" + +#include "sieve-ldap-db.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#define DEF_STR(name) DEF_STRUCT_STR(name, sieve_ldap_storage_settings) +#define DEF_INT(name) DEF_STRUCT_INT(name, sieve_ldap_storage_settings) +#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, sieve_ldap_storage_settings) + +static struct setting_def setting_defs[] = { + DEF_STR(hosts), + DEF_STR(uris), + DEF_STR(dn), + DEF_STR(dnpass), + DEF_BOOL(tls), + DEF_BOOL(sasl_bind), + DEF_STR(sasl_mech), + DEF_STR(sasl_realm), + DEF_STR(sasl_authz_id), + DEF_STR(tls_ca_cert_file), + DEF_STR(tls_ca_cert_dir), + DEF_STR(tls_cert_file), + DEF_STR(tls_key_file), + DEF_STR(tls_cipher_suite), + DEF_STR(tls_require_cert), + DEF_STR(deref), + DEF_STR(scope), + DEF_STR(base), + DEF_INT(ldap_version), + DEF_STR(debug_level), + DEF_STR(ldaprc_path), + DEF_STR(sieve_ldap_script_attr), + DEF_STR(sieve_ldap_mod_attr), + DEF_STR(sieve_ldap_filter), + + { 0, NULL, 0 } +}; + +static struct sieve_ldap_storage_settings default_settings = { + .hosts = NULL, + .uris = NULL, + .dn = NULL, + .dnpass = NULL, + .tls = FALSE, + .sasl_bind = FALSE, + .sasl_mech = NULL, + .sasl_realm = NULL, + .sasl_authz_id = NULL, + .tls_ca_cert_file = NULL, + .tls_ca_cert_dir = NULL, + .tls_cert_file = NULL, + .tls_key_file = NULL, + .tls_cipher_suite = NULL, + .tls_require_cert = NULL, + .deref = "never", + .scope = "subtree", + .base = NULL, + .ldap_version = 3, + .debug_level = "0", + .ldaprc_path = "", + .sieve_ldap_script_attr = "mailSieveRuleSource", + .sieve_ldap_mod_attr = "modifyTimestamp", + .sieve_ldap_filter = "(&(objectClass=posixAccount)(uid=%u))", +}; + +static const char *parse_setting(const char *key, const char *value, + struct sieve_ldap_storage *lstorage) +{ + return parse_setting_from_defs + (lstorage->storage.pool, setting_defs, &lstorage->set, key, value); +} + +int sieve_ldap_storage_read_settings +(struct sieve_ldap_storage *lstorage, const char *config_path) +{ + struct sieve_storage *storage = &lstorage->storage; + const char *str, *error; + struct stat st; + + if ( stat(config_path, &st) < 0 ) { + e_error(storage->event, + "Failed to read LDAP storage config: " + "stat(%s) failed: %m", config_path); + return -1; + } + + lstorage->set = default_settings; + lstorage->set_mtime = st.st_mtime; + + if (!settings_read_nosection + (config_path, parse_setting, lstorage, &error)) { + sieve_storage_set_critical(storage, + "Failed to read LDAP storage config `%s': %s", + config_path, error); + return -1; + } + + if (lstorage->set.base == NULL) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "No search base given", config_path); + return -1; + } + + if (lstorage->set.uris == NULL && lstorage->set.hosts == NULL) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "No uris or hosts set", config_path); + return -1; + } + + if (*lstorage->set.ldaprc_path != '\0') { + str = getenv("LDAPRC"); + if (str != NULL && strcmp(str, lstorage->set.ldaprc_path) != 0) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Multiple different ldaprc_path settings not allowed " + "(%s and %s)", config_path, str, lstorage->set.ldaprc_path); + return -1; + } + env_put("LDAPRC", lstorage->set.ldaprc_path); + } + + if ( ldap_deref_from_str + (lstorage->set.deref, &lstorage->set.ldap_deref) < 0 ) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Invalid deref option `%s'", + config_path, lstorage->set.deref);; + } + + if ( ldap_scope_from_str + (lstorage->set.scope, &lstorage->set.ldap_scope) < 0 ) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Invalid scope option `%s'", + config_path, lstorage->set.scope);; + } + +#ifdef OPENLDAP_TLS_OPTIONS + if ( lstorage->set.tls_require_cert != NULL && + ldap_tls_require_cert_from_str(lstorage->set.tls_require_cert, + &lstorage->set.ldap_tls_require_cert) < 0) { + sieve_storage_set_critical(storage, + "Invalid LDAP storage config `%s': " + "Invalid tls_require_cert option `%s'", + config_path, lstorage->set.tls_require_cert); + } +#endif + return 0; +} + +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.c new file mode 100644 index 0000000..1f7922a --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.c @@ -0,0 +1,230 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +//#include "ldap.h" + +#include "sieve-common.h" + +#include "sieve-ldap-storage.h" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "sieve-error.h" + +#ifndef PLUGIN_BUILD +const struct sieve_storage sieve_ldap_storage; +#else +const struct sieve_storage sieve_ldap_storage_plugin; +#endif + +/* + * Storage class + */ + +static struct sieve_storage *sieve_ldap_storage_alloc(void) +{ + struct sieve_ldap_storage *lstorage; + pool_t pool; + + pool = pool_alloconly_create("sieve_ldap_storage", 1024); + lstorage = p_new(pool, struct sieve_ldap_storage, 1); +#ifndef PLUGIN_BUILD + lstorage->storage = sieve_ldap_storage; +#else + lstorage->storage = sieve_ldap_storage_plugin; +#endif + lstorage->storage.pool = pool; + + return &lstorage->storage; +} + +static int sieve_ldap_storage_init +(struct sieve_storage *storage, const char *const *options, + enum sieve_error *error_r) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + struct sieve_instance *svinst = storage->svinst; + const char *username = NULL; + + if ( options != NULL ) { + while ( *options != NULL ) { + const char *option = *options; + + if ( strncasecmp(option, "user=", 5) == 0 && option[5] != '\0' ) { + username = option+5; + } else { + sieve_storage_set_critical(storage, + "Invalid option `%s'", option); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + + options++; + } + } + + if ( username == NULL ) { + if ( svinst->username == NULL ) { + sieve_storage_set_critical(storage, + "No username specified"); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + return -1; + } + username = svinst->username; + } + + e_debug(storage->event, "user=%s, config=%s", + username, storage->location); + + if ( sieve_ldap_storage_read_settings(lstorage, storage->location) < 0 ) + return -1; + + lstorage->username = p_strdup(storage->pool, username); + lstorage->config_file = p_strdup(storage->pool, storage->location); + lstorage->conn = sieve_ldap_db_init(lstorage); + + storage->location = p_strconcat(storage->pool, + SIEVE_LDAP_STORAGE_DRIVER_NAME, ":", storage->location, + ";user=", username, NULL); + + return 0; +} + +static void sieve_ldap_storage_destroy +(struct sieve_storage *storage) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + + if ( lstorage->conn != NULL ) + sieve_ldap_db_unref(&lstorage->conn); +} + +/* + * Script access + */ + +static struct sieve_script *sieve_ldap_storage_get_script +(struct sieve_storage *storage, const char *name) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + struct sieve_ldap_script *lscript; + + T_BEGIN { + lscript = sieve_ldap_script_init(lstorage, name); + } T_END; + + return &lscript->script; +} + +/* + * Active script + */ + +struct sieve_script *sieve_ldap_storage_active_script_open +(struct sieve_storage *storage) +{ + struct sieve_ldap_storage *lstorage = + (struct sieve_ldap_storage *)storage; + struct sieve_ldap_script *lscript; + + lscript = sieve_ldap_script_init + (lstorage, storage->script_name); + if ( sieve_script_open(&lscript->script, NULL) < 0 ) { + struct sieve_script *script = &lscript->script; + sieve_script_unref(&script); + return NULL; + } + + return &lscript->script; +} + +int sieve_ldap_storage_active_script_get_name +(struct sieve_storage *storage, const char **name_r) +{ + if ( storage->script_name != NULL ) + *name_r = storage->script_name; + else + *name_r = SIEVE_LDAP_SCRIPT_DEFAULT; + return 0; +} + +/* + * Driver definition + */ + +#ifndef PLUGIN_BUILD +const struct sieve_storage sieve_ldap_storage = { +#else +const struct sieve_storage sieve_ldap_storage_plugin = { +#endif + .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME, + .version = 0, + .v = { + .alloc = sieve_ldap_storage_alloc, + .init = sieve_ldap_storage_init, + .destroy = sieve_ldap_storage_destroy, + + .get_script = sieve_ldap_storage_get_script, + + .get_script_sequence = sieve_ldap_storage_get_script_sequence, + .script_sequence_next = sieve_ldap_script_sequence_next, + .script_sequence_destroy = sieve_ldap_script_sequence_destroy, + + .active_script_get_name = sieve_ldap_storage_active_script_get_name, + .active_script_open = sieve_ldap_storage_active_script_open, + + // FIXME: impement management interface + } +}; + +#ifndef SIEVE_BUILTIN_LDAP +/* Building a plugin */ + +const char *sieve_storage_ldap_plugin_version = PIGEONHOLE_ABI_VERSION; + +void sieve_storage_ldap_plugin_load +(struct sieve_instance *svinst, void **context); +void sieve_storage_ldap_plugin_unload +(struct sieve_instance *svinst, void *context); +void sieve_storage_ldap_plugin_init(void); +void sieve_storage_ldap_plugin_deinit(void); + +void sieve_storage_ldap_plugin_load +(struct sieve_instance *svinst, void **context ATTR_UNUSED) +{ + sieve_storage_class_register + (svinst, &sieve_ldap_storage_plugin); + + e_debug(svinst->event, + "Sieve LDAP storage plugin for %s version %s loaded", + PIGEONHOLE_NAME, PIGEONHOLE_VERSION_FULL); +} + +void sieve_storage_ldap_plugin_unload +(struct sieve_instance *svinst ATTR_UNUSED, + void *context ATTR_UNUSED) +{ + sieve_storage_class_unregister + (svinst, &sieve_ldap_storage_plugin); +} + +void sieve_storage_ldap_plugin_init(void) +{ + /* Nothing */ +} + +void sieve_storage_ldap_plugin_deinit(void) +{ + /* Nothing */ +} +#endif + +#else /* !defined(SIEVE_BUILTIN_LDAP) && !defined(PLUGIN_BUILD) */ +const struct sieve_storage sieve_ldap_storage = { + .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME +}; +#endif diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.h b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.h new file mode 100644 index 0000000..f97ceba --- /dev/null +++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-storage.h @@ -0,0 +1,108 @@ +#ifndef SIEVE_LDAP_STORAGE_H +#define SIEVE_LDAP_STORAGE_H + +#include "sieve.h" +#include "sieve-script-private.h" +#include "sieve-storage-private.h" + +#define SIEVE_LDAP_SCRIPT_DEFAULT "default" + +#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD) + +#include "sieve-ldap-db.h" + +struct sieve_ldap_storage; + +/* + * LDAP settings + */ + +struct sieve_ldap_storage_settings { + const char *hosts; + const char *uris; + const char *dn; + const char *dnpass; + + bool tls; + bool sasl_bind; + const char *sasl_mech; + const char *sasl_realm; + const char *sasl_authz_id; + + const char *tls_ca_cert_file; + const char *tls_ca_cert_dir; + const char *tls_cert_file; + const char *tls_key_file; + const char *tls_cipher_suite; + const char *tls_require_cert; + + const char *deref; + const char *scope; + const char *base; + unsigned int ldap_version; + + const char *ldaprc_path; + const char *debug_level; + + const char *sieve_ldap_script_attr; + const char *sieve_ldap_mod_attr; + const char *sieve_ldap_filter; + + /* ... */ + int ldap_deref, ldap_scope, ldap_tls_require_cert; +}; + +int sieve_ldap_storage_read_settings + (struct sieve_ldap_storage *lstorage, const char *config_path); + +/* + * Storage class + */ + +struct sieve_ldap_storage { + struct sieve_storage storage; + + struct sieve_ldap_storage_settings set; + time_t set_mtime; + + const char *config_file; + const char *username; // FIXME: needed? + + struct ldap_connection *conn; +}; + +struct sieve_script *sieve_ldap_storage_active_script_open + (struct sieve_storage *storage); +int sieve_ldap_storage_active_script_get_name + (struct sieve_storage *storage, const char **name_r); + +/* + * Script class + */ + +struct sieve_ldap_script { + struct sieve_script script; + + const char *dn; + const char *modattr; + + const char *binpath; +}; + +struct sieve_ldap_script *sieve_ldap_script_init + (struct sieve_ldap_storage *lstorage, const char *name); + +/* + * Script sequence + */ + +struct sieve_script_sequence *sieve_ldap_storage_get_script_sequence + (struct sieve_storage *storage, enum sieve_error *error_r); + +struct sieve_script *sieve_ldap_script_sequence_next + (struct sieve_script_sequence *seq, enum sieve_error *error_r); +void sieve_ldap_script_sequence_destroy(struct sieve_script_sequence *seq); + +#endif + +#endif |