From 0441d265f2bb9da249c7abf333f0f771fadb4ab5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 19:36:47 +0200 Subject: Adding upstream version 1:2.3.21+dfsg1. Signed-off-by: Daniel Baumann --- pigeonhole/src/managesieve-login/Makefile.am | 43 + pigeonhole/src/managesieve-login/Makefile.in | 931 +++++++++++++++++++++ .../src/managesieve-login/client-authenticate.c | 308 +++++++ .../src/managesieve-login/client-authenticate.h | 21 + pigeonhole/src/managesieve-login/client.c | 574 +++++++++++++ pigeonhole/src/managesieve-login/client.h | 76 ++ .../managesieve-login-settings-plugin.c | 223 +++++ .../managesieve-login-settings-plugin.h | 9 + .../managesieve-login/managesieve-login-settings.c | 104 +++ .../managesieve-login/managesieve-login-settings.h | 17 + .../src/managesieve-login/managesieve-proxy.c | 686 +++++++++++++++ .../src/managesieve-login/managesieve-proxy.h | 12 + 12 files changed, 3004 insertions(+) create mode 100644 pigeonhole/src/managesieve-login/Makefile.am create mode 100644 pigeonhole/src/managesieve-login/Makefile.in create mode 100644 pigeonhole/src/managesieve-login/client-authenticate.c create mode 100644 pigeonhole/src/managesieve-login/client-authenticate.h create mode 100644 pigeonhole/src/managesieve-login/client.c create mode 100644 pigeonhole/src/managesieve-login/client.h create mode 100644 pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.c create mode 100644 pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.h create mode 100644 pigeonhole/src/managesieve-login/managesieve-login-settings.c create mode 100644 pigeonhole/src/managesieve-login/managesieve-login-settings.h create mode 100644 pigeonhole/src/managesieve-login/managesieve-proxy.c create mode 100644 pigeonhole/src/managesieve-login/managesieve-proxy.h (limited to 'pigeonhole/src/managesieve-login') diff --git a/pigeonhole/src/managesieve-login/Makefile.am b/pigeonhole/src/managesieve-login/Makefile.am new file mode 100644 index 0000000..3bfbc75 --- /dev/null +++ b/pigeonhole/src/managesieve-login/Makefile.am @@ -0,0 +1,43 @@ +settingsdir = $(dovecot_moduledir)/settings + +dovecot_pkglibexec_PROGRAMS = managesieve-login + +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + $(LIBDOVECOT_LOGIN_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-managesieve + +libmanagesieve_login_settings_la_LDFLAGS = -module -avoid-version + +settings_LTLIBRARIES = \ + libmanagesieve_login_settings.la + +libmanagesieve_login_settings_la_SOURCES = \ + managesieve-login-settings.c \ + managesieve-login-settings-plugin.c + +libmanagesieve_login_settings_la_CFLAGS = \ + $(AM_CFLAGS) $(LIBDOVECOT_CONFIG_INCLUDE) -DPKG_LIBEXECDIR=\""$(dovecot_pkglibexecdir)"\" + +libs = \ + $(top_builddir)/src/lib-managesieve/libmanagesieve.la + +managesieve_login_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +managesieve_login_LDFLAGS = $(BINARY_LDFLAGS) +managesieve_login_LDADD = $(libs) $(LIBDOVECOT_LOGIN) $(LIBDOVECOT) +managesieve_login_DEPENDENCIES = $(libs) $(LIBDOVECOT_LOGIN_DEPS) $(LIBDOVECOT_DEPS) + +managesieve_login_SOURCES = \ + client.c \ + client-authenticate.c \ + managesieve-login-settings.c \ + managesieve-proxy.c + +noinst_HEADERS = \ + client.h \ + client-authenticate.h \ + managesieve-login-settings.h \ + managesieve-login-settings-plugin.h \ + managesieve-proxy.h diff --git a/pigeonhole/src/managesieve-login/Makefile.in b/pigeonhole/src/managesieve-login/Makefile.in new file mode 100644 index 0000000..14d7b78 --- /dev/null +++ b/pigeonhole/src/managesieve-login/Makefile.in @@ -0,0 +1,931 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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@ +dovecot_pkglibexec_PROGRAMS = managesieve-login$(EXEEXT) +subdir = src/managesieve-login +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__installdirs = "$(DESTDIR)$(dovecot_pkglibexecdir)" \ + "$(DESTDIR)$(settingsdir)" +PROGRAMS = $(dovecot_pkglibexec_PROGRAMS) +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; }; \ + } +LTLIBRARIES = $(settings_LTLIBRARIES) +libmanagesieve_login_settings_la_LIBADD = +am_libmanagesieve_login_settings_la_OBJECTS = libmanagesieve_login_settings_la-managesieve-login-settings.lo \ + libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo +libmanagesieve_login_settings_la_OBJECTS = \ + $(am_libmanagesieve_login_settings_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 = +libmanagesieve_login_settings_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) \ + $(libmanagesieve_login_settings_la_LDFLAGS) $(LDFLAGS) -o $@ +am_managesieve_login_OBJECTS = managesieve_login-client.$(OBJEXT) \ + managesieve_login-client-authenticate.$(OBJEXT) \ + managesieve_login-managesieve-login-settings.$(OBJEXT) \ + managesieve_login-managesieve-proxy.$(OBJEXT) +managesieve_login_OBJECTS = $(am_managesieve_login_OBJECTS) +am__DEPENDENCIES_1 = +managesieve_login_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(managesieve_login_LDFLAGS) $(LDFLAGS) \ + -o $@ +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)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo \ + ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo \ + ./$(DEPDIR)/managesieve_login-client-authenticate.Po \ + ./$(DEPDIR)/managesieve_login-client.Po \ + ./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po \ + ./$(DEPDIR)/managesieve_login-managesieve-proxy.Po +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 = $(libmanagesieve_login_settings_la_SOURCES) \ + $(managesieve_login_SOURCES) +DIST_SOURCES = $(libmanagesieve_login_settings_la_SOURCES) \ + $(managesieve_login_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@ +settingsdir = $(dovecot_moduledir)/settings +AM_CPPFLAGS = \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_SERVICE_INCLUDE) \ + $(LIBDOVECOT_LOGIN_INCLUDE) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/lib-managesieve + +libmanagesieve_login_settings_la_LDFLAGS = -module -avoid-version +settings_LTLIBRARIES = \ + libmanagesieve_login_settings.la + +libmanagesieve_login_settings_la_SOURCES = \ + managesieve-login-settings.c \ + managesieve-login-settings-plugin.c + +libmanagesieve_login_settings_la_CFLAGS = \ + $(AM_CFLAGS) $(LIBDOVECOT_CONFIG_INCLUDE) -DPKG_LIBEXECDIR=\""$(dovecot_pkglibexecdir)"\" + +libs = \ + $(top_builddir)/src/lib-managesieve/libmanagesieve.la + +managesieve_login_CPPFLAGS = $(AM_CPPFLAGS) $(BINARY_CFLAGS) +managesieve_login_LDFLAGS = $(BINARY_LDFLAGS) +managesieve_login_LDADD = $(libs) $(LIBDOVECOT_LOGIN) $(LIBDOVECOT) +managesieve_login_DEPENDENCIES = $(libs) $(LIBDOVECOT_LOGIN_DEPS) $(LIBDOVECOT_DEPS) +managesieve_login_SOURCES = \ + client.c \ + client-authenticate.c \ + managesieve-login-settings.c \ + managesieve-proxy.c + +noinst_HEADERS = \ + client.h \ + client-authenticate.h \ + managesieve-login-settings.h \ + managesieve-login-settings-plugin.h \ + managesieve-proxy.h + +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/managesieve-login/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/managesieve-login/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): +install-dovecot_pkglibexecPROGRAMS: $(dovecot_pkglibexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$(dovecot_pkglibexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(dovecot_pkglibexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dovecot_pkglibexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(dovecot_pkglibexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(dovecot_pkglibexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-dovecot_pkglibexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$(dovecot_pkglibexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(dovecot_pkglibexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(dovecot_pkglibexecdir)" && rm -f $$files + +clean-dovecot_pkglibexecPROGRAMS: + @list='$(dovecot_pkglibexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +install-settingsLTLIBRARIES: $(settings_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || 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)$(settingsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(settingsdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(settingsdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(settingsdir)"; \ + } + +uninstall-settingsLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(settings_LTLIBRARIES)'; test -n "$(settingsdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(settingsdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(settingsdir)/$$f"; \ + done + +clean-settingsLTLIBRARIES: + -test -z "$(settings_LTLIBRARIES)" || rm -f $(settings_LTLIBRARIES) + @list='$(settings_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}; \ + } + +libmanagesieve_login_settings.la: $(libmanagesieve_login_settings_la_OBJECTS) $(libmanagesieve_login_settings_la_DEPENDENCIES) $(EXTRA_libmanagesieve_login_settings_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmanagesieve_login_settings_la_LINK) -rpath $(settingsdir) $(libmanagesieve_login_settings_la_OBJECTS) $(libmanagesieve_login_settings_la_LIBADD) $(LIBS) + +managesieve-login$(EXEEXT): $(managesieve_login_OBJECTS) $(managesieve_login_DEPENDENCIES) $(EXTRA_managesieve_login_DEPENDENCIES) + @rm -f managesieve-login$(EXEEXT) + $(AM_V_CCLD)$(managesieve_login_LINK) $(managesieve_login_OBJECTS) $(managesieve_login_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-client-authenticate.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/managesieve_login-managesieve-proxy.Po@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 $@ $< + +libmanagesieve_login_settings_la-managesieve-login-settings.lo: managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -MT libmanagesieve_login_settings_la-managesieve-login-settings.lo -MD -MP -MF $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Tpo -c -o libmanagesieve_login_settings_la-managesieve-login-settings.lo `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Tpo $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings.c' object='libmanagesieve_login_settings_la-managesieve-login-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) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -c -o libmanagesieve_login_settings_la-managesieve-login-settings.lo `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c + +libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo: managesieve-login-settings-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -MT libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo -MD -MP -MF $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Tpo -c -o libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo `test -f 'managesieve-login-settings-plugin.c' || echo '$(srcdir)/'`managesieve-login-settings-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Tpo $(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings-plugin.c' object='libmanagesieve_login_settings_la-managesieve-login-settings-plugin.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmanagesieve_login_settings_la_CFLAGS) $(CFLAGS) -c -o libmanagesieve_login_settings_la-managesieve-login-settings-plugin.lo `test -f 'managesieve-login-settings-plugin.c' || echo '$(srcdir)/'`managesieve-login-settings-plugin.c + +managesieve_login-client.o: client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client.o -MD -MP -MF $(DEPDIR)/managesieve_login-client.Tpo -c -o managesieve_login-client.o `test -f 'client.c' || echo '$(srcdir)/'`client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client.Tpo $(DEPDIR)/managesieve_login-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='managesieve_login-client.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client.o `test -f 'client.c' || echo '$(srcdir)/'`client.c + +managesieve_login-client.obj: client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client.obj -MD -MP -MF $(DEPDIR)/managesieve_login-client.Tpo -c -o managesieve_login-client.obj `if test -f 'client.c'; then $(CYGPATH_W) 'client.c'; else $(CYGPATH_W) '$(srcdir)/client.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client.Tpo $(DEPDIR)/managesieve_login-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='managesieve_login-client.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client.obj `if test -f 'client.c'; then $(CYGPATH_W) 'client.c'; else $(CYGPATH_W) '$(srcdir)/client.c'; fi` + +managesieve_login-client-authenticate.o: client-authenticate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client-authenticate.o -MD -MP -MF $(DEPDIR)/managesieve_login-client-authenticate.Tpo -c -o managesieve_login-client-authenticate.o `test -f 'client-authenticate.c' || echo '$(srcdir)/'`client-authenticate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client-authenticate.Tpo $(DEPDIR)/managesieve_login-client-authenticate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client-authenticate.c' object='managesieve_login-client-authenticate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client-authenticate.o `test -f 'client-authenticate.c' || echo '$(srcdir)/'`client-authenticate.c + +managesieve_login-client-authenticate.obj: client-authenticate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-client-authenticate.obj -MD -MP -MF $(DEPDIR)/managesieve_login-client-authenticate.Tpo -c -o managesieve_login-client-authenticate.obj `if test -f 'client-authenticate.c'; then $(CYGPATH_W) 'client-authenticate.c'; else $(CYGPATH_W) '$(srcdir)/client-authenticate.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-client-authenticate.Tpo $(DEPDIR)/managesieve_login-client-authenticate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client-authenticate.c' object='managesieve_login-client-authenticate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-client-authenticate.obj `if test -f 'client-authenticate.c'; then $(CYGPATH_W) 'client-authenticate.c'; else $(CYGPATH_W) '$(srcdir)/client-authenticate.c'; fi` + +managesieve_login-managesieve-login-settings.o: managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-login-settings.o -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo -c -o managesieve_login-managesieve-login-settings.o `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo $(DEPDIR)/managesieve_login-managesieve-login-settings.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings.c' object='managesieve_login-managesieve-login-settings.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-login-settings.o `test -f 'managesieve-login-settings.c' || echo '$(srcdir)/'`managesieve-login-settings.c + +managesieve_login-managesieve-login-settings.obj: managesieve-login-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-login-settings.obj -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo -c -o managesieve_login-managesieve-login-settings.obj `if test -f 'managesieve-login-settings.c'; then $(CYGPATH_W) 'managesieve-login-settings.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-login-settings.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-login-settings.Tpo $(DEPDIR)/managesieve_login-managesieve-login-settings.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-login-settings.c' object='managesieve_login-managesieve-login-settings.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-login-settings.obj `if test -f 'managesieve-login-settings.c'; then $(CYGPATH_W) 'managesieve-login-settings.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-login-settings.c'; fi` + +managesieve_login-managesieve-proxy.o: managesieve-proxy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-proxy.o -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo -c -o managesieve_login-managesieve-proxy.o `test -f 'managesieve-proxy.c' || echo '$(srcdir)/'`managesieve-proxy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo $(DEPDIR)/managesieve_login-managesieve-proxy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-proxy.c' object='managesieve_login-managesieve-proxy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-proxy.o `test -f 'managesieve-proxy.c' || echo '$(srcdir)/'`managesieve-proxy.c + +managesieve_login-managesieve-proxy.obj: managesieve-proxy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT managesieve_login-managesieve-proxy.obj -MD -MP -MF $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo -c -o managesieve_login-managesieve-proxy.obj `if test -f 'managesieve-proxy.c'; then $(CYGPATH_W) 'managesieve-proxy.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-proxy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/managesieve_login-managesieve-proxy.Tpo $(DEPDIR)/managesieve_login-managesieve-proxy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='managesieve-proxy.c' object='managesieve_login-managesieve-proxy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(managesieve_login_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o managesieve_login-managesieve-proxy.obj `if test -f 'managesieve-proxy.c'; then $(CYGPATH_W) 'managesieve-proxy.c'; else $(CYGPATH_W) '$(srcdir)/managesieve-proxy.c'; fi` + +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 $(PROGRAMS) $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(dovecot_pkglibexecdir)" "$(DESTDIR)$(settingsdir)"; 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-dovecot_pkglibexecPROGRAMS clean-generic clean-libtool \ + clean-settingsLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo + -rm -f ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo + -rm -f ./$(DEPDIR)/managesieve_login-client-authenticate.Po + -rm -f ./$(DEPDIR)/managesieve_login-client.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-proxy.Po + -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-settingsLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-dovecot_pkglibexecPROGRAMS + +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)/libmanagesieve_login_settings_la-managesieve-login-settings-plugin.Plo + -rm -f ./$(DEPDIR)/libmanagesieve_login_settings_la-managesieve-login-settings.Plo + -rm -f ./$(DEPDIR)/managesieve_login-client-authenticate.Po + -rm -f ./$(DEPDIR)/managesieve_login-client.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-login-settings.Po + -rm -f ./$(DEPDIR)/managesieve_login-managesieve-proxy.Po + -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-dovecot_pkglibexecPROGRAMS \ + uninstall-settingsLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-dovecot_pkglibexecPROGRAMS clean-generic clean-libtool \ + clean-settingsLTLIBRARIES 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-dovecot_pkglibexecPROGRAMS 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-settingsLTLIBRARIES 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-dovecot_pkglibexecPROGRAMS \ + uninstall-settingsLTLIBRARIES + +.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/managesieve-login/client-authenticate.c b/pigeonhole/src/managesieve-login/client-authenticate.c new file mode 100644 index 0000000..b186f84 --- /dev/null +++ b/pigeonhole/src/managesieve-login/client-authenticate.c @@ -0,0 +1,308 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "login-common.h" +#include "base64.h" +#include "buffer.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "safe-memset.h" +#include "str.h" +#include "str-sanitize.h" +#include "auth-client.h" + +#include "managesieve-parser.h" +#include "managesieve-quote.h" +#include "client.h" + +#include "client-authenticate.h" +#include "managesieve-proxy.h" + + +const char *client_authenticate_get_capabilities +(struct client *client) +{ + const struct auth_mech_desc *mech; + unsigned int i, count; + string_t *str; + + str = t_str_new(128); + mech = sasl_server_get_advertised_mechs(client, &count); + + for (i = 0; i < count; i++) { + if (i > 0) + str_append_c(str, ' '); + str_append(str, mech[i].name); + } + + return str_c(str); +} + +void managesieve_client_auth_result(struct client *client, + enum client_auth_result result, + const struct client_auth_reply *reply, const char *text) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + string_t *referral; + + switch (result) { + case CLIENT_AUTH_RESULT_SUCCESS: + /* nothing to be done for IMAP */ + break; + case CLIENT_AUTH_RESULT_REFERRAL_SUCCESS: + case CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN: + /* MANAGESIEVE referral + + [nologin] referral host=.. [port=..] [destuser=..] + [reason=..] + + NO [REFERRAL sieve://user;AUTH=mech@host:port/] "Can't login." + OK [...] "Logged in, but you should use this server instead." + .. [REFERRAL ..] Reason from auth server + */ + referral = t_str_new(128); + str_printfa(referral, "REFERRAL sieve://%s;AUTH=%s@%s", + reply->destuser, client->auth_mech_name, reply->host); + if ( reply->port != 4190 ) + str_printfa(referral, ":%u", reply->port); + + if ( result == CLIENT_AUTH_RESULT_REFERRAL_SUCCESS ) { + client_send_okresp(client, str_c(referral), text);; + } else { + client_send_noresp(client, str_c(referral), text); + } + break; + case CLIENT_AUTH_RESULT_ABORTED: + case CLIENT_AUTH_RESULT_AUTHFAILED_REASON: + case CLIENT_AUTH_RESULT_AUTHZFAILED: + client_send_no(client, text); + break; + case CLIENT_AUTH_RESULT_TEMPFAIL: + client_send_noresp(client, "TRYLATER", text); + break; + case CLIENT_AUTH_RESULT_SSL_REQUIRED: + client_send_noresp(client, "ENCRYPT-NEEDED", text); + break; + case CLIENT_AUTH_RESULT_AUTHFAILED: + default: + client_send_no(client, text); + break; + } + + msieve_client->auth_response_input = NULL; + managesieve_parser_reset(msieve_client->parser); +} + +void managesieve_client_auth_send_challenge +(struct client *client, const char *data) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *) client; + + T_BEGIN { + string_t *str = t_str_new(256); + + managesieve_quote_append_string(str, data, TRUE); + str_append(str, "\r\n"); + + client_send_raw_data(client, str_c(str), str_len(str)); + } T_END; + + msieve_client->auth_response_input = NULL; + managesieve_parser_reset(msieve_client->parser); +} + +static int managesieve_client_auth_read_response +(struct managesieve_client *msieve_client, bool initial, const char **error_r) +{ + struct client *client = &msieve_client->common; + const struct managesieve_arg *args; + const char *error; + bool fatal; + const unsigned char *data; + size_t size; + uoff_t resp_size; + int ret; + + *error_r = NULL; + + if ( i_stream_read(client->input) == -1 ) { + /* disconnected */ + client_destroy_iostream_error(client); + return -1; + } + + if ( msieve_client->auth_response_input == NULL ) { + + if ( msieve_client->skip_line ) { + if ( i_stream_next_line(client->input) == NULL ) + return 0; + + msieve_client->skip_line = FALSE; + } + + switch ( managesieve_parser_read_args(msieve_client->parser, 0, + MANAGESIEVE_PARSE_FLAG_STRING_STREAM, &args) ) { + case -1: + error = managesieve_parser_get_error(msieve_client->parser, &fatal); + if (fatal) { + client_send_bye(client, error); + client_destroy(client, t_strconcat( + "parse error during auth: ", error, NULL)); + } else { + *error_r = error; + } + msieve_client->skip_line = TRUE; + return -1; + + case -2: + /* not enough data */ + return 0; + + default: + break; + } + + if ( MANAGESIEVE_ARG_IS_EOL(&args[0]) ) { + if (!initial) { + *error_r = "Received empty AUTHENTICATE client response line."; + msieve_client->skip_line = TRUE; + return -1; + } + msieve_client->skip_line = TRUE; + return 1; + } + + if ( !managesieve_arg_get_string_stream + (&args[0], &msieve_client->auth_response_input) + || !MANAGESIEVE_ARG_IS_EOL(&args[1]) ) { + if ( !initial ) + *error_r = "Invalid AUTHENTICATE client response."; + else + *error_r = "Invalid AUTHENTICATE initial response."; + msieve_client->skip_line = TRUE; + return -1; + } + + if ( i_stream_get_size + (msieve_client->auth_response_input, FALSE, &resp_size) <= 0 ) + resp_size = 0; + + if (client->auth_response == NULL) + client->auth_response = str_new(default_pool, I_MAX(resp_size+1, 256)); + } + + while ( (ret=i_stream_read_more + (msieve_client->auth_response_input, &data, &size) ) > 0 ) { + + if (str_len(client->auth_response) + size > LOGIN_MAX_AUTH_BUF_SIZE) { + client_destroy(client, "Authentication response too large"); + return -1; + } + + str_append_data(client->auth_response, data, size); + i_stream_skip(msieve_client->auth_response_input, size); + } + + if ( ret == 0 ) return 0; + + if ( msieve_client->auth_response_input->stream_errno != 0 ) { + if ( !client->input->eof && + msieve_client->auth_response_input->stream_errno == EINVAL ) { + msieve_client->skip_line = TRUE; + *error_r = t_strconcat + ("Error in AUTHENTICATE response string: ", + i_stream_get_error(msieve_client->auth_response_input), NULL); + return -1; + } + + client_destroy_iostream_error(client); + return -1; + } + + if ( i_stream_next_line(client->input) == NULL ) + return 0; + + return 1; +} + +void managesieve_client_auth_parse_response(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *) client; + const char *error = NULL; + int ret; + + if ( (ret=managesieve_client_auth_read_response(msieve_client, FALSE, &error)) + < 0 ) { + if ( error != NULL ) + client_auth_fail(client, error); + return; + } + + if ( ret == 0 ) return; + + if ( strcmp(str_c(client->auth_response), "*") == 0 ) { + client_auth_abort(client); + return; + } + + client_auth_respond(client, str_c(client->auth_response)); + + memset(str_c_modifiable(client->auth_response), 0, + str_len(client->auth_response)); +} + +int cmd_authenticate +(struct managesieve_client *msieve_client, const struct managesieve_arg *args) +{ + /* NOTE: This command's input is handled specially because the + SASL-IR can be large. */ + struct client *client = &msieve_client->common; + const char *mech_name, *init_response; + const char *error; + int ret; + + if (!msieve_client->auth_mech_name_parsed) { + i_assert(args != NULL); + + /* one mandatory argument: authentication mechanism name */ + if ( !managesieve_arg_get_string(&args[0], &mech_name) ) + return -1; + + if (*mech_name == '\0') + return -1; + + i_free(client->auth_mech_name); + client->auth_mech_name = i_strdup(mech_name); + msieve_client->auth_mech_name_parsed = TRUE; + + msieve_client->auth_response_input = NULL; + managesieve_parser_reset(msieve_client->parser); + } + + msieve_client->skip_line = FALSE; + if ( (ret=managesieve_client_auth_read_response(msieve_client, TRUE, &error)) + < 0 ) { + msieve_client->auth_mech_name_parsed = FALSE; + if ( error != NULL ) { + client_send_no(client, error); + } + return 1; + } + + if ( ret == 0 ) return 0; + + init_response = ( client->auth_response == NULL ? NULL : + t_strdup(str_c(client->auth_response)) ); + msieve_client->auth_mech_name_parsed = FALSE; + if ( (ret=client_auth_begin + (client, t_strdup(client->auth_mech_name), init_response)) < 0 ) + return ret; + + msieve_client->cmd_finished = TRUE; + return 0; +} + diff --git a/pigeonhole/src/managesieve-login/client-authenticate.h b/pigeonhole/src/managesieve-login/client-authenticate.h new file mode 100644 index 0000000..1280ad5 --- /dev/null +++ b/pigeonhole/src/managesieve-login/client-authenticate.h @@ -0,0 +1,21 @@ +#ifndef CLIENT_AUTHENTICATE_H +#define CLIENT_AUTHENTICATE_H + +struct managesieve_arg; + +const char *client_authenticate_get_capabilities + (struct client *client); + +void managesieve_client_auth_result + (struct client *client, enum client_auth_result result, + const struct client_auth_reply *reply, const char *text); + +void managesieve_client_auth_send_challenge + (struct client *client, const char *data); +void managesieve_client_auth_parse_response + (struct client *client); + +int cmd_authenticate + (struct managesieve_client *client, const struct managesieve_arg *args); + +#endif diff --git a/pigeonhole/src/managesieve-login/client.c b/pigeonhole/src/managesieve-login/client.c new file mode 100644 index 0000000..fe8acff --- /dev/null +++ b/pigeonhole/src/managesieve-login/client.c @@ -0,0 +1,574 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "login-common.h" +#include "buffer.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "safe-memset.h" +#include "str.h" +#include "strescape.h" +#include "base64.h" +#include "master-service.h" +#include "master-auth.h" +#include "auth-client.h" + +#include "managesieve-parser.h" +#include "managesieve-quote.h" + +#include "client.h" +#include "client-authenticate.h" + +#include "managesieve-login-settings.h" +#include "managesieve-proxy.h" + +/* Disconnect client when it sends too many bad commands */ +#define CLIENT_MAX_BAD_COMMANDS 3 + +struct managesieve_command { + const char *name; + int (*func)(struct managesieve_client *client, + const struct managesieve_arg *args); + int preparsed_args; +}; + +/* Skip incoming data until newline is found, + returns TRUE if newline was found. */ +bool client_skip_line(struct managesieve_client *client) +{ + const unsigned char *data; + size_t i, data_size; + + data = i_stream_get_data(client->common.input, &data_size); + + for (i = 0; i < data_size; i++) { + if (data[i] == '\n') { + i_stream_skip(client->common.input, i+1); + return TRUE; + } + } + + return FALSE; +} + +static void client_send_capabilities(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + const char *saslcap; + + T_BEGIN { + saslcap = client_authenticate_get_capabilities(client); + + /* Default capabilities */ + client_send_raw(client, t_strconcat( + "\"IMPLEMENTATION\" \"", + msieve_client->set->managesieve_implementation_string, + "\"\r\n", NULL)); + client_send_raw(client, t_strconcat( + "\"SIEVE\" \"", + msieve_client->set->managesieve_sieve_capability, + "\"\r\n", NULL)); + if (msieve_client->set->managesieve_notify_capability != NULL) { + client_send_raw(client, t_strconcat( + "\"NOTIFY\" \"", + msieve_client->set->managesieve_notify_capability, + "\"\r\n", NULL)); + } + client_send_raw(client, t_strconcat("\"SASL\" \"", saslcap, + "\"\r\n", NULL)); + + /* STARTTLS */ + if (login_ssl_initialized && !client->tls) + client_send_raw(client, "\"STARTTLS\"\r\n"); + + /* Protocol version */ + client_send_raw(client, "\"VERSION\" \"1.0\"\r\n"); + + /* XCLIENT */ + if (client->trusted) + client_send_raw(client, "\"XCLIENT\"\r\n"); + } T_END; +} + +static int +cmd_capability(struct managesieve_client *client, + const struct managesieve_arg *args ATTR_UNUSED) +{ + o_stream_cork(client->common.output); + + client_send_capabilities(&client->common); + client_send_ok(&client->common, "Capability completed."); + + o_stream_uncork(client->common.output); + + return 1; +} + +static int +cmd_starttls(struct managesieve_client *client, + const struct managesieve_arg *args ATTR_UNUSED) +{ + client_cmd_starttls(&client->common); + return 1; +} + +static void +managesieve_client_notify_starttls(struct client *client, bool success, + const char *text) +{ + if (success) + client_send_ok(client, text); + else + client_send_no(client, text); +} + +static int +cmd_noop(struct managesieve_client *client, const struct managesieve_arg *args) +{ + const char *text; + string_t *resp_code; + + if (MANAGESIEVE_ARG_IS_EOL(&args[0])) { + client_send_ok(&client->common, "NOOP Completed"); + return 1; + } + if (!MANAGESIEVE_ARG_IS_EOL(&args[1])) + return -1; + if (!managesieve_arg_get_string(&args[0], &text)) { + client_send_no(&client->common, "Invalid echo tag."); + return 1; + } + + resp_code = t_str_new(256); + str_append(resp_code, "TAG "); + managesieve_quote_append_string(resp_code, text, FALSE); + + client_send_okresp(&client->common, str_c(resp_code), "Done"); + return 1; +} + +static int +cmd_logout(struct managesieve_client *client, + const struct managesieve_arg *args ATTR_UNUSED) +{ + client_send_ok(&client->common, "Logout completed."); + client_destroy(&client->common, CLIENT_UNAUTHENTICATED_LOGOUT_MSG); + return 1; +} + +static int +cmd_xclient_parse_forward(struct managesieve_client *client, const char *value) +{ + size_t value_len = strlen(value); + + if (client->common.forward_fields != NULL) + str_truncate(client->common.forward_fields, 0); + else { + client->common.forward_fields = str_new( + client->common.preproxy_pool, + MAX_BASE64_DECODED_SIZE(value_len)); + } + + if (base64_decode(value, value_len, NULL, + client->common.forward_fields) < 0) + return -1; + + return 0; +} + +static int +cmd_xclient(struct managesieve_client *client, + const struct managesieve_arg *args) +{ + const char *arg; + bool args_ok = TRUE; + + if (!client->common.trusted) { + client_send_no(&client->common, "You are not from trusted IP"); + return 1; + } + while (!MANAGESIEVE_ARG_IS_EOL(&args[0]) && + managesieve_arg_get_atom(&args[0], &arg)) { + if (strncasecmp(arg, "ADDR=", 5) == 0) { + if (net_addr2ip(arg + 5, &client->common.ip) < 0) + args_ok = FALSE; + } else if (strncasecmp(arg, "FORWARD=", 8) == 0) { + if (cmd_xclient_parse_forward(client, arg + 8) < 0) + args_ok = FALSE; + } else if (strncasecmp(arg, "PORT=", 5) == 0) { + if (net_str2port(arg + 5, + &client->common.remote_port) < 0) + args_ok = FALSE; + } else if (strncasecmp(arg, "SESSION=", 8) == 0) { + const char *value = arg + 8; + + if (strlen(value) <= LOGIN_MAX_SESSION_ID_LEN) { + client->common.session_id = + p_strdup(client->common.pool, value); + } + } else if (strncasecmp(arg, "TTL=", 4) == 0) { + if (str_to_uint(arg + 4, &client->common.proxy_ttl) < 0) + args_ok = FALSE; + } + args++; + } + if (!args_ok || !MANAGESIEVE_ARG_IS_EOL(&args[0])) + return -1; + + client_send_ok(&client->common, "Updated"); + return 1; +} + +static struct managesieve_command commands[] = { + { "AUTHENTICATE", cmd_authenticate, 1 }, + { "CAPABILITY", cmd_capability, -1 }, + { "STARTTLS", cmd_starttls, -1 }, + { "NOOP", cmd_noop, 0 }, + { "LOGOUT", cmd_logout, -1 }, + { "XCLIENT", cmd_xclient, 0 }, + { NULL, NULL, 0 } +}; + +static bool client_handle_input(struct managesieve_client *client) +{ + i_assert(!client->common.authenticating); + + if (client->cmd_finished) { + /* Clear the previous command from memory */ + client->cmd_name = NULL; + client->cmd_parsed_args = FALSE; + client->cmd = NULL; + managesieve_parser_reset(client->parser); + + /* Remove \r\n */ + if (client->skip_line) { + if (!client_skip_line(client)) + return FALSE; + client->skip_line = FALSE; + } + + client->cmd_finished = FALSE; + } + + if (client->cmd == NULL) { + struct managesieve_command *cmd; + const char *cmd_name; + + client->cmd_name = managesieve_parser_read_word(client->parser); + if (client->cmd_name == NULL) + return FALSE; /* Need more data */ + + cmd_name = t_str_ucase(client->cmd_name); + cmd = commands; + while (cmd->name != NULL) { + if (strcmp(cmd->name, cmd_name) == 0) + break; + cmd++; + } + + if (cmd->name != NULL) + client->cmd = cmd; + else + client->skip_line = TRUE; + } + return client->common.v.input_next_cmd(&client->common); +} + +static bool managesieve_client_input_next_cmd(struct client *_client) +{ + struct managesieve_client *client = + (struct managesieve_client *)_client; + const struct managesieve_arg *args = NULL; + const char *msg; + int ret = 1; + bool fatal; + + if (client->cmd == NULL) { + /* Unknown command */ + ret = -1; + } else if (!client->cmd_parsed_args) { + unsigned int arg_count = + (client->cmd->preparsed_args > 0 ? + client->cmd->preparsed_args : 0); + + switch (managesieve_parser_read_args(client->parser, arg_count, + 0, &args)) { + case -1: + /* Error */ + msg = managesieve_parser_get_error(client->parser, + &fatal); + if (fatal) { + client_send_bye(&client->common, msg); + client_destroy(&client->common, msg); + return FALSE; + } + client_send_no(&client->common, msg); + client->cmd_finished = TRUE; + client->skip_line = TRUE; + return TRUE; + case -2: + /* Not enough data */ + return FALSE; + } + i_assert(args != NULL); + + if (arg_count == 0) { + /* We read the entire line - skip over the CRLF */ + if (!client_skip_line(client)) + i_unreached(); + } else { + /* Get rid of it later */ + client->skip_line = TRUE; + } + + client->cmd_parsed_args = TRUE; + + if (client->cmd->preparsed_args == -1) { + /* Check absence of arguments */ + if (args[0].type != MANAGESIEVE_ARG_EOL) + ret = -1; + } + } + if (ret > 0) { + i_assert(client->cmd != NULL); + ret = client->cmd->func(client, args); + } + + if (ret != 0) + client->cmd_finished = TRUE; + if (ret < 0) { + if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { + client_send_bye(&client->common, + "Too many invalid MANAGESIEVE commands."); + client_destroy(&client->common, + "Too many invalid commands."); + return FALSE; + } + client_send_no(&client->common, + "Error in MANAGESIEVE command received by server."); + } + + return ret != 0 && !client->common.destroyed; +} + +static void managesieve_client_input(struct client *client) +{ + struct managesieve_client *managesieve_client = + (struct managesieve_client *)client; + + if (!client_read(client)) + return; + + client_ref(client); + o_stream_cork(managesieve_client->common.output); + for (;;) { + if (!auth_client_is_connected(auth_client)) { + /* We're not currently connected to auth process - + don't allow any commands */ + /* FIXME: Can't do untagged responses with managesieve. + Any other ways? + client_send_ok(client, AUTH_SERVER_WAITING_MSG); + */ + timeout_remove(&client->to_auth_waiting); + + client->input_blocked = TRUE; + break; + } else { + if (!client_handle_input(managesieve_client)) + break; + } + } + o_stream_uncork(managesieve_client->common.output); + client_unref(&client); +} + +static struct client *managesieve_client_alloc(pool_t pool) +{ + struct managesieve_client *msieve_client; + + msieve_client = p_new(pool, struct managesieve_client, 1); + return &msieve_client->common; +} + +static void managesieve_client_create(struct client *client, void **other_sets) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + msieve_client->set = other_sets[0]; + msieve_client->parser = managesieve_parser_create( + msieve_client->common.input, MAX_MANAGESIEVE_LINE); + client->io = io_add(client->fd, IO_READ, client_input, client); +} + +static void managesieve_client_destroy(struct client *client) +{ + struct managesieve_client *managesieve_client = + (struct managesieve_client *)client; + + managesieve_parser_destroy(&managesieve_client->parser); +} + +static void managesieve_client_notify_auth_ready(struct client *client) +{ + /* Cork the stream to send the capability data as a single tcp frame + Some naive clients break if we don't. + */ + o_stream_cork(client->output); + + /* Send initial capabilities */ + client_send_capabilities(client); + client_send_ok(client, client->set->login_greeting); + + o_stream_uncork(client->output); + + client->banner_sent = TRUE; +} + +static void managesieve_client_starttls(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + managesieve_parser_destroy(&msieve_client->parser); + msieve_client->parser = managesieve_parser_create( + msieve_client->common.input, MAX_MANAGESIEVE_LINE); + + /* CRLF is lost from buffer when streams are reopened. */ + msieve_client->skip_line = FALSE; + + /* Cork the stream to send the capability data as a single tcp frame + Some naive clients break if we don't. + */ + o_stream_cork(client->output); + + client_send_capabilities(client); + client_send_ok(client, "TLS negotiation successful."); + + o_stream_uncork(client->output); +} + +static void +client_send_reply_raw(struct client *client, const char *prefix, + const char *resp_code, const char *text) +{ + T_BEGIN { + string_t *line = t_str_new(256); + + str_append(line, prefix); + + if (resp_code != NULL) { + str_append(line, " ("); + str_append(line, resp_code); + str_append_c(line, ')'); + } + + if (text != NULL) { + str_append_c(line, ' '); + managesieve_quote_append_string(line, text, TRUE); + } + + str_append(line, "\r\n"); + + client_send_raw_data(client, str_data(line), str_len(line)); + } T_END; +} + +void client_send_reply_code(struct client *client, + enum managesieve_cmd_reply reply, + const char *resp_code, const char *text) +{ + const char *prefix = "NO"; + + switch (reply) { + case MANAGESIEVE_CMD_REPLY_OK: + prefix = "OK"; + break; + case MANAGESIEVE_CMD_REPLY_NO: + break; + case MANAGESIEVE_CMD_REPLY_BYE: + prefix = "BYE"; + break; + } + + client_send_reply_raw(client, prefix, resp_code, text); +} + +void client_send_reply(struct client *client, enum managesieve_cmd_reply reply, + const char *text) +{ + client_send_reply_code(client, reply, NULL, text); +} + +static void +managesieve_client_notify_disconnect(struct client *client, + enum client_disconnect_reason reason, + const char *text) +{ + if (reason == CLIENT_DISCONNECT_SYSTEM_SHUTDOWN) { + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_BYE, + "TRYLATER", text); + } else { + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_BYE, + NULL, text); + } +} + +static void managesieve_login_preinit(void) +{ + login_set_roots = managesieve_login_settings_set_roots; +} + +static void managesieve_login_init(void) +{ +} + +static void managesieve_login_deinit(void) +{ + clients_destroy_all(); +} + +static struct client_vfuncs managesieve_client_vfuncs = { + .alloc = managesieve_client_alloc, + .create = managesieve_client_create, + .destroy = managesieve_client_destroy, + .notify_auth_ready = managesieve_client_notify_auth_ready, + .notify_disconnect = managesieve_client_notify_disconnect, + .notify_starttls = managesieve_client_notify_starttls, + .starttls = managesieve_client_starttls, + .input = managesieve_client_input, + .auth_send_challenge = managesieve_client_auth_send_challenge, + .auth_parse_response = managesieve_client_auth_parse_response, + .auth_result = managesieve_client_auth_result, + .proxy_reset = managesieve_proxy_reset, + .proxy_parse_line = managesieve_proxy_parse_line, + .proxy_failed = managesieve_proxy_failed, + .proxy_get_state = managesieve_proxy_get_state, + .send_raw_data = client_common_send_raw_data, + .input_next_cmd = managesieve_client_input_next_cmd, + .free = client_common_default_free, +}; + +static struct login_binary managesieve_login_binary = { + .protocol = "sieve", + .process_name = "managesieve-login", + .default_port = 4190, + + .event_category = { + .name = "managesieve", + }, + + .client_vfuncs = &managesieve_client_vfuncs, + .preinit = managesieve_login_preinit, + .init = managesieve_login_init, + .deinit = managesieve_login_deinit, + + .anonymous_login_acceptable = FALSE, +}; + +int main(int argc, char *argv[]) +{ + return login_binary_run(&managesieve_login_binary, argc, argv); +} diff --git a/pigeonhole/src/managesieve-login/client.h b/pigeonhole/src/managesieve-login/client.h new file mode 100644 index 0000000..a04190d --- /dev/null +++ b/pigeonhole/src/managesieve-login/client.h @@ -0,0 +1,76 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include "net.h" +#include "client-common.h" + +/* maximum length for managesieve command line. */ +#define MAX_MANAGESIEVE_LINE 8192 + +enum managesieve_proxy_state { + MSIEVE_PROXY_STATE_NONE, + MSIEVE_PROXY_STATE_TLS_START, + MSIEVE_PROXY_STATE_TLS_READY, + MSIEVE_PROXY_STATE_XCLIENT, + MSIEVE_PROXY_STATE_AUTH, + + MSIEVE_PROXY_STATE_COUNT +}; +struct managesieve_command; + +struct managesieve_client { + struct client common; + + const struct managesieve_login_settings *set; + struct managesieve_parser *parser; + + enum managesieve_proxy_state proxy_state; + + const char *cmd_name; + struct managesieve_command *cmd; + + struct istream *auth_response_input; + + bool cmd_finished:1; + bool cmd_parsed_args:1; + bool skip_line:1; + bool auth_mech_name_parsed:1; + + bool proxy_starttls:1; + bool proxy_sasl:1; + bool proxy_xclient:1; +}; + +bool client_skip_line(struct managesieve_client *client); + +enum managesieve_cmd_reply { + MANAGESIEVE_CMD_REPLY_OK, + MANAGESIEVE_CMD_REPLY_NO, + MANAGESIEVE_CMD_REPLY_BYE +}; + +void client_send_reply(struct client *client, enum managesieve_cmd_reply reply, + const char *text); + +void client_send_reply_code(struct client *client, + enum managesieve_cmd_reply reply, + const char *resp_code, const char *text); + +#define client_send_ok(client, text) \ + client_send_reply(client, MANAGESIEVE_CMD_REPLY_OK, text) +#define client_send_no(client, text) \ + client_send_reply(client, MANAGESIEVE_CMD_REPLY_NO, text) +#define client_send_bye(client, text) \ + client_send_reply(client, MANAGESIEVE_CMD_REPLY_BYE, text) + +#define client_send_okresp(client, resp_code, text) \ + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_OK, \ + resp_code, text) +#define client_send_noresp(client, resp_code, text) \ + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, \ + resp_code, text) +#define client_send_byeresp(client, resp_code, text) \ + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_BYE, \ + resp_code, text) + +#endif diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.c b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.c new file mode 100644 index 0000000..12515cd --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.c @@ -0,0 +1,223 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "buffer.h" +#include "env-util.h" +#include "execv-const.h" +#include "master-service.h" +#include "settings-parser.h" +#include "config-parser-private.h" +#include "managesieve-login-settings-plugin.h" + +#include +#include +#include +#include + +typedef enum { CAP_SIEVE, CAP_NOTIFY } capability_type_t; + +bool capability_dumped = FALSE; +static char *capability_sieve = NULL; +static char *capability_notify = NULL; + +static void (*next_hook_config_parser_begin)(struct config_parser_context *ctx) = NULL; + +static void managesieve_login_config_parser_begin(struct config_parser_context *ctx); + +const char *managesieve_login_settings_version = DOVECOT_ABI_VERSION; + +void managesieve_login_settings_init(struct module *module ATTR_UNUSED) +{ + next_hook_config_parser_begin = hook_config_parser_begin; + hook_config_parser_begin = managesieve_login_config_parser_begin; +} + +void managesieve_login_settings_deinit(void) +{ + hook_config_parser_begin = next_hook_config_parser_begin; + + if ( capability_sieve != NULL ) + i_free(capability_sieve); + + if ( capability_notify != NULL ) + i_free(capability_notify); +} + +static void capability_store(capability_type_t cap_type, const char *value) +{ + switch ( cap_type ) { + case CAP_SIEVE: + capability_sieve = i_strdup(value); + break; + case CAP_NOTIFY: + capability_notify = i_strdup(value); + break; + } +} + +static void capability_parse(const char *cap_string) +{ + capability_type_t cap_type = CAP_SIEVE; + const char *p = cap_string; + string_t *part = t_str_new(256); + + if ( cap_string == NULL || *cap_string == '\0' ) { + i_warning("managesieve-login: capability string is empty."); + return; + } + + while ( *p != '\0' ) { + if ( *p == '\\' ) { + p++; + if ( *p != '\0' ) { + str_append_c(part, *p); + p++; + } else break; + } else if ( *p == ':' ) { + if ( strcasecmp(str_c(part), "SIEVE") == 0 ) + cap_type = CAP_SIEVE; + else if ( strcasecmp(str_c(part), "NOTIFY") == 0 ) + cap_type = CAP_NOTIFY; + else + i_warning("managesieve-login: unknown capability '%s' listed in " + "capability string (ignored).", str_c(part)); + str_truncate(part, 0); + } else if ( *p == ',' ) { + capability_store(cap_type, str_c(part)); + str_truncate(part, 0); + } else { + /* Append character, but omit leading spaces */ + if ( str_len(part) > 0 || *p != ' ' ) + str_append_c(part, *p); + } + p++; + } + + if ( str_len(part) > 0 ) { + capability_store(cap_type, str_c(part)); + } +} + +static bool capability_dump(void) +{ + char buf[4096]; + int fd[2], status = 0; + ssize_t ret; + unsigned int pos; + pid_t pid; + + if ( getenv("DUMP_CAPABILITY") != NULL ) + return TRUE; + + if ( pipe(fd) < 0 ) { + i_error("managesieve-login: dump-capability pipe() failed: %m"); + return FALSE; + } + fd_close_on_exec(fd[0], TRUE); + fd_close_on_exec(fd[1], TRUE); + + if ( (pid = fork()) == (pid_t)-1 ) { + (void)close(fd[0]); (void)close(fd[1]); + i_error("managesieve-login: dump-capability fork() failed: %m"); + return FALSE; + } + + if ( pid == 0 ) { + const char *argv[5]; + + /* Child */ + (void)close(fd[0]); + + if (dup2(fd[1], STDOUT_FILENO) < 0) + i_fatal("managesieve-login: dump-capability dup2() failed: %m"); + + env_put("DUMP_CAPABILITY", "1"); + + argv[0] = PKG_LIBEXECDIR"/managesieve"; + argv[1] = "-k"; + argv[2] = "-c"; + argv[3] = master_service_get_config_path(master_service); + argv[4] = NULL; + execv_const(argv[0], argv); + + i_fatal("managesieve-login: dump-capability execv(%s) failed: %m", argv[0]); + } + + (void)close(fd[1]); + + alarm(60); + if (wait(&status) == -1) { + i_error("managesieve-login: dump-capability failed: process %d got stuck", + (int)pid); + return FALSE; + } + alarm(0); + + if (status != 0) { + (void)close(fd[0]); + if (WIFSIGNALED(status)) { + i_error("managesieve-login: dump-capability process " + "killed with signal %d", WTERMSIG(status)); + } else { + i_error("managesieve-login: dump-capability process returned %d", + WIFEXITED(status) ? WEXITSTATUS(status) : status); + } + return FALSE; + } + + pos = 0; + while ((ret = read(fd[0], buf + pos, sizeof(buf) - pos)) > 0) + pos += ret; + + if (ret < 0) { + i_error("managesieve-login: read(dump-capability process) failed: %m"); + (void)close(fd[0]); + return FALSE; + } + (void)close(fd[0]); + + if (pos == 0 || buf[pos-1] != '\n') { + i_error("managesieve-login: dump-capability: Couldn't read capability " + "(got %u bytes)", pos); + return FALSE; + } + buf[pos-1] = '\0'; + + capability_parse(buf); + + return TRUE; +} + +static void managesieve_login_config_set +(struct config_parser_context *ctx, const char *key, const char *value) +{ + config_apply_line(ctx, key, t_strdup_printf("%s=%s", key, value), NULL); +} + +static void managesieve_login_config_parser_begin(struct config_parser_context *ctx) +{ + const char *const *module = ctx->modules; + + if ( module != NULL && *module != NULL ) { + while ( *module != NULL ) { + if ( strcmp(*module, "managesieve-login") == 0 ) + break; + module++; + } + if ( *module == NULL ) + return; + } + + if ( !capability_dumped ) { + (void)capability_dump(); + capability_dumped = TRUE; + } + + if ( capability_sieve != NULL ) + managesieve_login_config_set(ctx, "managesieve_sieve_capability", capability_sieve); + + if ( capability_notify != NULL ) + managesieve_login_config_set(ctx, "managesieve_notify_capability", capability_notify); +} diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.h b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.h new file mode 100644 index 0000000..ebefe1a --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings-plugin.h @@ -0,0 +1,9 @@ +#ifndef MANAGESIEVE_LOGIN_SETTINGS_PLUGIN_H +#define MANAGESIEVE_LOGIN_SETTINGS_PLUGIN_H + +#include "lib.h" + +void managesieve_login_settings_init(struct module *module); +void managesieve_login_settings_deinit(void); + +#endif diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings.c b/pigeonhole/src/managesieve-login/managesieve-login-settings.c new file mode 100644 index 0000000..9146d03 --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "buffer.h" +#include "env-util.h" +#include "execv-const.h" +#include "settings-parser.h" +#include "service-settings.h" +#include "login-settings.h" + +#include "pigeonhole-config.h" + +#include "managesieve-login-settings.h" + +#include +#include +#include +#include + +/* */ + +static struct inet_listener_settings managesieve_login_inet_listeners_array[] = { + { .name = "sieve", .address = "", .port = 4190 }, +}; +static struct inet_listener_settings *managesieve_login_inet_listeners[] = { + &managesieve_login_inet_listeners_array[0] +}; +static buffer_t managesieve_login_inet_listeners_buf = { + { { managesieve_login_inet_listeners, + sizeof(managesieve_login_inet_listeners) } } +}; +/* */ + +struct service_settings managesieve_login_settings_service_settings = { + .name = "managesieve-login", + .protocol = "sieve", + .type = "login", + .executable = "managesieve-login", + .user = "$default_login_user", + .group = "", + .privileged_group = "", + .extra_groups = "", + .chroot = "login", + + .drop_priv_before_exec = FALSE, + + .process_min_avail = 0, + .process_limit = 0, + .client_limit = 0, + .service_count = 1, + .idle_kill = 0, + .vsz_limit = (uoff_t)-1, + + .unix_listeners = ARRAY_INIT, + .fifo_listeners = ARRAY_INIT, + .inet_listeners = { { &managesieve_login_inet_listeners_buf, + sizeof(managesieve_login_inet_listeners[0]) } } +}; + +#undef DEF +#define DEF(type, name) \ + SETTING_DEFINE_STRUCT_##type(#name, name, struct managesieve_login_settings) + +static const struct setting_define managesieve_login_setting_defines[] = { + DEF(STR, managesieve_implementation_string), + DEF(STR, managesieve_sieve_capability), + DEF(STR, managesieve_notify_capability), + + SETTING_DEFINE_LIST_END +}; + +static const struct managesieve_login_settings managesieve_login_default_settings = { + .managesieve_implementation_string = DOVECOT_NAME " " PIGEONHOLE_NAME, + .managesieve_sieve_capability = "", + .managesieve_notify_capability = NULL +}; + +static const struct setting_parser_info *managesieve_login_setting_dependencies[] = { + &login_setting_parser_info, + NULL +}; + +static const struct setting_parser_info managesieve_login_setting_parser_info = { + .module_name = "managesieve-login", + .defines = managesieve_login_setting_defines, + .defaults = &managesieve_login_default_settings, + + .type_offset = (size_t)-1, + .struct_size = sizeof(struct managesieve_login_settings), + + .parent_offset = (size_t)-1, + .parent = NULL, + + .dependencies = managesieve_login_setting_dependencies +}; + +const struct setting_parser_info *managesieve_login_settings_set_roots[] = { + &login_setting_parser_info, + &managesieve_login_setting_parser_info, + NULL +}; + diff --git a/pigeonhole/src/managesieve-login/managesieve-login-settings.h b/pigeonhole/src/managesieve-login/managesieve-login-settings.h new file mode 100644 index 0000000..c6f4826 --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-login-settings.h @@ -0,0 +1,17 @@ +#ifndef MANAGESIEVE_LOGIN_SETTINGS_H +#define MANAGESIEVE_LOGIN_SETTINGS_H + +struct managesieve_login_settings { + const char *managesieve_implementation_string; + const char *managesieve_sieve_capability; + const char *managesieve_notify_capability; +}; + +extern const struct setting_parser_info *managesieve_login_settings_set_roots[]; + +#ifdef _CONFIG_PLUGIN +void managesieve_login_settings_init(void); +void managesieve_login_settings_deinit(void); +#endif + +#endif diff --git a/pigeonhole/src/managesieve-login/managesieve-proxy.c b/pigeonhole/src/managesieve-login/managesieve-proxy.c new file mode 100644 index 0000000..50e31ae --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-proxy.c @@ -0,0 +1,686 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include +#include "login-common.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "str.h" +#include "str-sanitize.h" +#include "strescape.h" +#include "safe-memset.h" +#include "buffer.h" +#include "base64.h" +#include "dsasl-client.h" + +#include "client.h" +#include "client-authenticate.h" + +#include "managesieve-quote.h" +#include "managesieve-proxy.h" +#include "managesieve-parser.h" + +typedef enum { + MANAGESIEVE_RESPONSE_NONE, + MANAGESIEVE_RESPONSE_OK, + MANAGESIEVE_RESPONSE_NO, + MANAGESIEVE_RESPONSE_BYE +} managesieve_response_t; + +static const char *managesieve_proxy_state_names[MSIEVE_PROXY_STATE_COUNT] = { + "none", "tls-start", "tls-ready", "xclient", "auth" +}; + +static string_t * +proxy_compose_xclient_forward(struct managesieve_client *client) +{ + const char *const *arg; + string_t *str; + + if (*client->common.auth_passdb_args == NULL) + return NULL; + + str = t_str_new(128); + for (arg = client->common.auth_passdb_args; *arg != NULL; arg++) { + if (strncasecmp(*arg, "forward_", 8) == 0) { + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append_tabescaped(str, (*arg)+8); + } + } + if (str_len(str) == 0) + return NULL; + + return str; +} + +static void +proxy_write_xclient(struct managesieve_client *client, string_t *str) +{ + string_t *fwd = proxy_compose_xclient_forward(client); + + str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u", + net_ip2addr(&client->common.ip), client->common.remote_port, + client_get_session_id(&client->common), + client->common.proxy_ttl - 1); + if (fwd != NULL) { + str_append(str, " FORWARD="); + base64_encode(str_data(fwd), str_len(fwd), str); + } + str_append(str, "\r\n"); +} + +static void +proxy_write_auth_data(const unsigned char *data, unsigned int data_len, + string_t *str) +{ + if (data_len == 0) + str_append(str, "\"\""); + else { + string_t *data_str = t_str_new(128); + base64_encode(data, data_len, data_str); + managesieve_quote_append_string(str, str_c(data_str), FALSE); + } +} + +static int +proxy_write_auth(struct managesieve_client *client, string_t *str) +{ + struct dsasl_client_settings sasl_set; + const unsigned char *output; + size_t len; + const char *mech_name, *error; + + i_assert(client->common.proxy_ttl > 1); + + if (!client->proxy_sasl) { + /* Prevent sending credentials to a server that has login + disabled; i.e., due to the lack of TLS */ + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG, + "Server has disabled authentication (TLS required?)"); + return -1; + } + + if (client->common.proxy_mech == NULL) + client->common.proxy_mech = &dsasl_client_mech_plain; + + i_assert(client->common.proxy_sasl_client == NULL); + i_zero(&sasl_set); + sasl_set.authid = (client->common.proxy_master_user != NULL ? + client->common.proxy_master_user : + client->common.proxy_user); + sasl_set.authzid = client->common.proxy_user; + sasl_set.password = client->common.proxy_password; + client->common.proxy_sasl_client = + dsasl_client_new(client->common.proxy_mech, &sasl_set); + mech_name = dsasl_client_mech_get_name(client->common.proxy_mech); + + str_append(str, "AUTHENTICATE "); + managesieve_quote_append_string(str, mech_name, FALSE); + if (dsasl_client_output(client->common.proxy_sasl_client, + &output, &len, &error) < 0) { + const char *reason = t_strdup_printf( + "SASL mechanism %s init failed: %s", + mech_name, error); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_INTERNAL, reason); + return -1; + } + if (len > 0) { + str_append_c(str, ' '); + proxy_write_auth_data(output, len, str); + } + str_append(str, "\r\n"); + return 0; +} + +static int +proxy_input_auth_challenge(struct managesieve_client *client, const char *line, + const char **challenge_r) +{ + struct istream *input; + struct managesieve_parser *parser; + const struct managesieve_arg *args; + const char *challenge; + bool fatal = FALSE; + int ret; + + i_assert(client->common.proxy_sasl_client != NULL); + *challenge_r = NULL; + + /* Build an input stream for the managesieve parser. + FIXME: Ugly, see proxy_input_capability(). + */ + line = t_strconcat(line, "\r\n", NULL); + input = i_stream_create_from_data(line, strlen(line)); + parser = managesieve_parser_create(input, MAX_MANAGESIEVE_LINE); + managesieve_parser_reset(parser); + + (void)i_stream_read(input); + ret = managesieve_parser_read_args(parser, 1, 0, &args); + + if (ret >= 0) { + if (ret > 0 && + managesieve_arg_get_string(&args[0], &challenge)) { + *challenge_r = t_strdup(challenge); + } else { + const char *reason = t_strdup_printf( + "Server sent invalid SASL challenge line: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + } else if (ret == -2) { + /* Parser needs more data (not possible on mem stream) */ + i_unreached(); + + } else { + const char *error_str = + managesieve_parser_get_error(parser, &fatal); + error_str = (error_str != NULL ? error_str : "unknown (bug)"); + + /* Do not accept faulty server */ + const char *reason = t_strdup_printf( + "Protocol parse error(%d) int SASL challenge line: %s " + "(line=`%s')", ret, error_str, line); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + + /* Cleanup parser */ + managesieve_parser_destroy(&parser); + i_stream_destroy(&input); + + /* Time to exit if greeting was not accepted */ + if (fatal) + return -1; + return 0; +} + +static int +proxy_write_auth_response(struct managesieve_client *client, + const char *challenge, string_t *str) +{ + const unsigned char *data; + size_t data_len; + const char *error; + int ret; + + if (base64_decode(challenge, strlen(challenge), NULL, str) < 0) { + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + "Server sent invalid base64 data in AUTHENTICATE response"); + return -1; + } + ret = dsasl_client_input(client->common.proxy_sasl_client, + str_data(str), str_len(str), &error); + if (ret == 0) { + ret = dsasl_client_output(client->common.proxy_sasl_client, + &data, &data_len, &error); + } + if (ret < 0) { + const char *reason = t_strdup_printf( + "Server sent invalid authentication data: %s", error); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + return -1; + } + i_assert(ret == 0); + + str_truncate(str, 0); + proxy_write_auth_data(data, data_len, str); + str_append(str, "\r\n"); + return 0; +} + +static managesieve_response_t +proxy_read_response(const struct managesieve_arg *args) +{ + const char *response; + + if (managesieve_arg_get_atom(&args[0], &response)) { + if (strcasecmp(response, "OK") == 0) { + /* Received OK response; greeting is finished */ + return MANAGESIEVE_RESPONSE_OK; + + } else if (strcasecmp(response, "NO") == 0) { + /* Received OK response; greeting is finished */ + return MANAGESIEVE_RESPONSE_NO; + + } else if (strcasecmp(response, "BYE") == 0) { + /* Received OK response; greeting is finished */ + return MANAGESIEVE_RESPONSE_BYE; + } + } + return MANAGESIEVE_RESPONSE_NONE; +} + +static int +proxy_input_capability(struct managesieve_client *client, const char *line, + managesieve_response_t *resp_r) +{ + struct istream *input; + struct managesieve_parser *parser; + const struct managesieve_arg *args; + const char *capability; + int ret; + bool fatal = FALSE; + + *resp_r = MANAGESIEVE_RESPONSE_NONE; + + /* Build an input stream for the managesieve parser + + FIXME: It would be nice if the line-wise parsing could be substituded + by something similar to the command line interpreter. However, + the current login_proxy structure does not make streams known + until inside proxy_input handler. + */ + line = t_strconcat(line, "\r\n", NULL); + input = i_stream_create_from_data(line, strlen(line)); + parser = managesieve_parser_create(input, MAX_MANAGESIEVE_LINE); + managesieve_parser_reset(parser); + + /* Parse input + + FIXME: Theoretically the OK response could include a response code + which could be rejected by the parser. + */ + (void)i_stream_read(input); + ret = managesieve_parser_read_args(parser, 2, 0, &args); + + if (ret == 0) { + const char *reason = t_strdup_printf( + "Remote returned with invalid capability/greeting line: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } else if (ret > 0) { + if (args[0].type == MANAGESIEVE_ARG_ATOM) { + *resp_r = proxy_read_response(args); + + if (*resp_r == MANAGESIEVE_RESPONSE_NONE) { + const char *reason = t_strdup_printf( + "Remote sent invalid response: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + reason); + + fatal = TRUE; + } + } else if (managesieve_arg_get_string(&args[0], &capability)) { + if (strcasecmp(capability, "SASL") == 0) { + const char *sasl_mechs; + + /* Check whether the server supports the SASL mechanism + we are going to use (currently only PLAIN supported). + */ + if (ret == 2 && + managesieve_arg_get_string(&args[1], &sasl_mechs)) { + const char *const *mechs = t_strsplit(sasl_mechs, " "); + + if (*mechs != NULL) { + /* At least one SASL mechanism is supported */ + client->proxy_sasl = TRUE; + } + + } else { + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + "Server returned erroneous SASL capability"); + fatal = TRUE; + } + + } else if (strcasecmp(capability, "STARTTLS") == 0) { + client->proxy_starttls = TRUE; + } else if (strcasecmp(capability, "XCLIENT") == 0) { + client->proxy_xclient = TRUE; + } + + } else { + /* Do not accept faulty server */ + const char *reason = t_strdup_printf( + "Remote returned with invalid capability/greeting line: %s", + str_sanitize(line,160)); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + } else if (ret == -2) { + /* Parser needs more data (not possible on mem stream) */ + i_unreached(); + + } else { + const char *error_str = + managesieve_parser_get_error(parser, &fatal); + error_str = (error_str != NULL ? error_str : "unknown (bug)"); + + /* Do not accept faulty server */ + const char *reason = t_strdup_printf( + "Protocol parse error(%d) in capability/greeting line: %s " + "(line=`%s')", ret, error_str, line); + login_proxy_failed(client->common.login_proxy, + login_proxy_get_event(client->common.login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, reason); + fatal = TRUE; + } + + /* Cleanup parser */ + managesieve_parser_destroy(&parser); + i_stream_destroy(&input); + + /* Time to exit if greeting was not accepted */ + if (fatal) + return -1; + + /* Wait until greeting is received completely */ + if (*resp_r == MANAGESIEVE_RESPONSE_NONE) + return 1; + + return 0; +} + +static void +managesieve_proxy_parse_auth_reply(const char *line, + const char **reason_r, bool *trylater_r) +{ + struct managesieve_parser *parser; + const struct managesieve_arg *args; + struct istream *input; + const char *reason; + int ret; + + *trylater_r = FALSE; + + if (strncasecmp(line, "NO ", 3) != 0) { + *reason_r = line; + return; + } + line += 3; + *reason_r = line; + + if (line[0] == '(') { + /* Parse optional resp-code. FIXME: The current + managesieve-parser can't really handle this properly, so + we'll just assume that there aren't any strings with ')' + in them. */ + if (strncasecmp(line, "(TRYLATER) ", 11) == 0) { + *trylater_r = TRUE; + line += 11; + } else { + line = strstr(line, ") "); + if (line == NULL) + return; + line += 2; + } + } + + /* Parse the string */ + input = i_stream_create_from_data(line, strlen(line)); + parser = managesieve_parser_create(input, (size_t)-1); + (void)i_stream_read(input); + ret = managesieve_parser_finish_line(parser, 0, 0, &args); + if (ret == 1 && managesieve_arg_get_string(&args[0], &reason)) + *reason_r = t_strdup(reason); + managesieve_parser_destroy(&parser); + i_stream_destroy(&input); +} + +int managesieve_proxy_parse_line(struct client *client, const char *line) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + struct ostream *output; + enum login_proxy_ssl_flags ssl_flags; + managesieve_response_t response = MANAGESIEVE_RESPONSE_NONE; + string_t *command; + int ret = 0; + + i_assert(!client->destroyed); + + output = login_proxy_get_ostream(client->login_proxy); + switch (msieve_client->proxy_state) { + case MSIEVE_PROXY_STATE_NONE: + ret = proxy_input_capability(msieve_client, line, &response); + if (ret < 0) + return -1; + if (ret == 0) { + if (response != MANAGESIEVE_RESPONSE_OK) { + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_PROTOCOL, + "Remote sent unexpected NO/BYE instead of capability response"); + return -1; + } + + command = t_str_new(128); + + ssl_flags = login_proxy_get_ssl_flags(client->login_proxy); + if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) { + if (!msieve_client->proxy_starttls) { + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG, + "Remote doesn't support STARTTLS"); + return -1; + } + + str_append(command, "STARTTLS\r\n"); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_TLS_START; + } else if (msieve_client->proxy_xclient) { + proxy_write_xclient(msieve_client, command); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_XCLIENT; + } else { + if (proxy_write_auth(msieve_client, command) < 0) + return -1; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH; + } + + o_stream_nsend(output, str_data(command), str_len(command)); + } + return 0; + case MSIEVE_PROXY_STATE_TLS_START: + if (strncasecmp(line, "OK", 2) == 0 && + (strlen(line) == 2 || line[2] == ' ')) { + /* STARTTLS successful, begin TLS negotiation. */ + if (login_proxy_starttls(client->login_proxy) < 0) + return -1; + + msieve_client->proxy_sasl = FALSE; + msieve_client->proxy_xclient = FALSE; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_TLS_READY; + return 1; + } + + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE, + "Remote refused STARTTLS command"); + return -1; + case MSIEVE_PROXY_STATE_TLS_READY: + ret = proxy_input_capability(msieve_client, line, &response); + if (ret < 0) + return -1; + if (ret == 0) { + if (response != MANAGESIEVE_RESPONSE_OK) { + /* STARTTLS failed */ + const char *reason = t_strdup_printf( + "Remote STARTTLS failed: %s", + str_sanitize(line, 160)); + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE, reason); + return -1; + } + + command = t_str_new(128); + if (msieve_client->proxy_xclient) { + proxy_write_xclient(msieve_client, command); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_XCLIENT; + } else { + if (proxy_write_auth(msieve_client, command) < 0) + return -1; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH; + } + o_stream_nsend(output, str_data(command), str_len(command)); + } + return 0; + case MSIEVE_PROXY_STATE_XCLIENT: + if (strncasecmp(line, "OK", 2) == 0 && + (strlen(line) == 2 || line[2] == ' ')) { + command = t_str_new(128); + if (proxy_write_auth(msieve_client, command) < 0) + return -1; + o_stream_nsend(output, str_data(command), str_len(command)); + msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH; + return 0; + } + + const char *reason = t_strdup_printf( + "Remote XCLIENT failed: %s", + str_sanitize(line, 160)); + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + LOGIN_PROXY_FAILURE_TYPE_REMOTE, reason); + return -1; + case MSIEVE_PROXY_STATE_AUTH: + /* Challenge? */ + if (*line == '"') { + const char *challenge; + + if (proxy_input_auth_challenge(msieve_client, line, + &challenge) < 0) + return -1; + command = t_str_new(128); + if (proxy_write_auth_response(msieve_client, challenge, + command) < 0) + return -1; + o_stream_nsend(output, str_data(command), + str_len(command)); + return 0; + } + + /* Check login status */ + if (strncasecmp(line, "OK", 2) == 0 && + (strlen(line) == 2 || line[2] == ' ')) { + string_t *str = t_str_new(128); + + /* Login successful */ + + /* FIXME: Some SASL mechanisms cause a capability + response to be sent. + */ + + /* Send this line to client. */ + str_append(str, line); + str_append(str, "\r\n"); + o_stream_nsend(client->output, str_data(str), + str_len(str)); + + client_proxy_finish_destroy_client(client); + return 1; + } + + /* Authentication failed */ + bool try_later; + (void)managesieve_proxy_parse_auth_reply(line, &reason, + &try_later); + + /* Login failed. Send our own failure reply so client can't + figure out if user exists or not just by looking at the reply + string. + */ + enum login_proxy_failure_type failure_type; + if (try_later) + failure_type = LOGIN_PROXY_FAILURE_TYPE_AUTH_TEMPFAIL; + else { + failure_type = LOGIN_PROXY_FAILURE_TYPE_AUTH; + client_send_no(client, AUTH_FAILED_MSG); + } + + login_proxy_failed(client->login_proxy, + login_proxy_get_event(client->login_proxy), + failure_type, reason); + return -1; + default: + /* Not supposed to happen */ + break; + } + + i_unreached(); + return -1; +} + +void managesieve_proxy_reset(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + msieve_client->proxy_starttls = FALSE; + msieve_client->proxy_sasl = FALSE; + msieve_client->proxy_xclient = FALSE; + msieve_client->proxy_state = MSIEVE_PROXY_STATE_NONE; +} + +static void +managesieve_proxy_send_failure_reply(struct client *client, + enum login_proxy_failure_type type, + const char *reason) +{ + switch (type) { + case LOGIN_PROXY_FAILURE_TYPE_CONNECT: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE: + case LOGIN_PROXY_FAILURE_TYPE_PROTOCOL: + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, + "TRYLATER", LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL_CONFIG: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG: + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, + NULL, LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH_TEMPFAIL: + client_send_reply_code(client, MANAGESIEVE_CMD_REPLY_NO, + "TRYLATER", reason); + break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH: + /* reply was already sent */ + break; + } +} + +void managesieve_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting) +{ + if (!reconnecting) + managesieve_proxy_send_failure_reply(client, type, reason); + client_common_proxy_failed(client, type, reason, reconnecting); +} + +const char *managesieve_proxy_get_state(struct client *client) +{ + struct managesieve_client *msieve_client = + (struct managesieve_client *)client; + + return managesieve_proxy_state_names[msieve_client->proxy_state]; +} diff --git a/pigeonhole/src/managesieve-login/managesieve-proxy.h b/pigeonhole/src/managesieve-login/managesieve-proxy.h new file mode 100644 index 0000000..946f074 --- /dev/null +++ b/pigeonhole/src/managesieve-login/managesieve-proxy.h @@ -0,0 +1,12 @@ +#ifndef MANAGESIEVE_PROXY_H +#define MANAGESIEVE_PROXY_H + +void managesieve_proxy_reset(struct client *client); +int managesieve_proxy_parse_line(struct client *client, const char *line); + +void managesieve_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); +const char *managesieve_proxy_get_state(struct client *client); + +#endif -- cgit v1.2.3