diff -ruN ../dovecot-1.0.rc8/src/auth/Makefile.am ./src/auth/Makefile.am --- ../dovecot-1.0.rc8/src/auth/Makefile.am 2006-06-18 11:44:10.000000000 +0200 +++ ./src/auth/Makefile.am 2006-09-29 23:14:46.000000000 +0200 @@ -2,7 +2,7 @@ pkglibexecdir = $(libexecdir)/dovecot -pkglibexec_PROGRAMS = dovecot-auth checkpassword-reply +pkglibexec_PROGRAMS = dovecot-auth checkpassword-reply vmailmgrwrapper vmailmgr-reply AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ @@ -112,5 +112,14 @@ checkpassword_reply_LDADD = \ ../lib/liblib.a -checkpassword_reply_sources = \ +checkpassword_reply_SOURCES = \ checkpassword-reply.c + +vmailmgr_reply_LDADD = \ + ../lib/liblib.a + +vmailmgr_reply_SOURCES = \ + vmailmgr-reply.c + +vmailmgrwrapper_SOURCES = \ + vmailmgrwrapper.c diff -ruN ../dovecot-1.0.rc8/src/auth/Makefile.in ./src/auth/Makefile.in --- ../dovecot-1.0.rc8/src/auth/Makefile.in 2006-08-18 00:16:03.000000000 +0200 +++ ./src/auth/Makefile.in 2006-09-29 23:15:29.000000000 +0200 @@ -39,7 +39,8 @@ build_triplet = @build@ host_triplet = @host@ pkglibexec_PROGRAMS = dovecot-auth$(EXEEXT) \ - checkpassword-reply$(EXEEXT) + checkpassword-reply$(EXEEXT) vmailmgrwrapper$(EXEEXT) \ + vmailmgr-reply$(EXEEXT) subdir = src/auth DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in @@ -62,8 +63,8 @@ am__installdirs = "$(DESTDIR)$(pkglibexecdir)" pkglibexecPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(pkglibexec_PROGRAMS) -checkpassword_reply_SOURCES = checkpassword-reply.c -checkpassword_reply_OBJECTS = checkpassword-reply.$(OBJEXT) +am_checkpassword_reply_OBJECTS = checkpassword-reply.$(OBJEXT) +checkpassword_reply_OBJECTS = $(am_checkpassword_reply_OBJECTS) checkpassword_reply_DEPENDENCIES = ../lib/liblib.a am_dovecot_auth_OBJECTS = auth.$(OBJEXT) auth-cache.$(OBJEXT) \ auth-client-connection.$(OBJEXT) \ @@ -94,6 +95,12 @@ ../lib-settings/libsettings.a ../lib-ntlm/libntlm.a \ ../lib-sql/libsql.a ../lib/liblib.a $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_vmailmgr_reply_OBJECTS = vmailmgr-reply.$(OBJEXT) +vmailmgr_reply_OBJECTS = $(am_vmailmgr_reply_OBJECTS) +vmailmgr_reply_DEPENDENCIES = ../lib/liblib.a +am_vmailmgrwrapper_OBJECTS = vmailmgrwrapper.$(OBJEXT) +vmailmgrwrapper_OBJECTS = $(am_vmailmgrwrapper_OBJECTS) +vmailmgrwrapper_LDADD = $(LDADD) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -105,10 +112,12 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(libpassword_a_SOURCES) checkpassword-reply.c \ - $(dovecot_auth_SOURCES) -DIST_SOURCES = $(libpassword_a_SOURCES) checkpassword-reply.c \ - $(dovecot_auth_SOURCES) +SOURCES = $(libpassword_a_SOURCES) $(checkpassword_reply_SOURCES) \ + $(dovecot_auth_SOURCES) $(vmailmgr_reply_SOURCES) \ + $(vmailmgrwrapper_SOURCES) +DIST_SOURCES = $(libpassword_a_SOURCES) $(checkpassword_reply_SOURCES) \ + $(dovecot_auth_SOURCES) $(vmailmgr_reply_SOURCES) \ + $(vmailmgrwrapper_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags @@ -353,9 +362,18 @@ checkpassword_reply_LDADD = \ ../lib/liblib.a -checkpassword_reply_sources = \ +checkpassword_reply_SOURCES = \ checkpassword-reply.c +vmailmgr_reply_LDADD = \ + ../lib/liblib.a + +vmailmgr_reply_SOURCES = \ + vmailmgr-reply.c + +vmailmgrwrapper_SOURCES = \ + vmailmgrwrapper.c + all: all-am .SUFFIXES: @@ -430,6 +448,12 @@ dovecot-auth$(EXEEXT): $(dovecot_auth_OBJECTS) $(dovecot_auth_DEPENDENCIES) @rm -f dovecot-auth$(EXEEXT) $(LINK) $(dovecot_auth_LDFLAGS) $(dovecot_auth_OBJECTS) $(dovecot_auth_LDADD) $(LIBS) +vmailmgr-reply$(EXEEXT): $(vmailmgr_reply_OBJECTS) $(vmailmgr_reply_DEPENDENCIES) + @rm -f vmailmgr-reply$(EXEEXT) + $(LINK) $(vmailmgr_reply_LDFLAGS) $(vmailmgr_reply_OBJECTS) $(vmailmgr_reply_LDADD) $(LIBS) +vmailmgrwrapper$(EXEEXT): $(vmailmgrwrapper_OBJECTS) $(vmailmgrwrapper_DEPENDENCIES) + @rm -f vmailmgrwrapper$(EXEEXT) + $(LINK) $(vmailmgrwrapper_LDFLAGS) $(vmailmgrwrapper_OBJECTS) $(vmailmgrwrapper_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -490,6 +514,8 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/userdb-static.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/userdb-vpopmail.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/userdb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmailmgr-reply.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmailmgrwrapper.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ diff -ruN ../dovecot-1.0.rc8/src/auth/passdb-checkpassword.c ./src/auth/passdb-checkpassword.c --- ../dovecot-1.0.rc8/src/auth/passdb-checkpassword.c 2006-08-17 21:47:56.000000000 +0200 +++ ./src/auth/passdb-checkpassword.c 2006-09-29 23:14:46.000000000 +0200 @@ -375,17 +375,48 @@ hash_insert(module->clients, POINTER_CAST(pid), chkpw_auth_request); } +static int +checkpassword_parse_args(struct auth_passdb *auth_passdb, struct checkpassword_passdb_module *mod, const char *args) { + const char *start; + size_t i = 1; + + if (args[0] != '/' || args[0] == ',') return -1; /* bad format */ + if (strchr(args, ',') != strrchr(args, ',')) return -1; /* too many commas ',' */ + + /* first token always expected */ + start = args; + while (args[i] != '\0' && args[i] != ',') i++; + mod->checkpassword_path = p_strdup_until(auth_passdb->auth->pool, start, start+i); + if (args[i] == '\0') { + mod->checkpassword_reply_path = PKG_LIBEXECDIR"/checkpassword-reply"; + return 0; + } + + /* second token */ + i++; + start = args + i; + while (args[i] != '\0' && (args[i] != ',' || args[i-1] == '\\')) i++; + if (args[i] != '\0') return -1; /* more than 2 tokens given */ + mod->checkpassword_reply_path = p_strdup_until(auth_passdb->auth->pool, start, start+i); + + return 0; +} + static struct passdb_module * checkpassword_preinit(struct auth_passdb *auth_passdb, const char *args) { struct checkpassword_passdb_module *module; + int ret; module = p_new(auth_passdb->auth->pool, struct checkpassword_passdb_module, 1); - module->checkpassword_path = p_strdup(auth_passdb->auth->pool, args); - module->checkpassword_reply_path = - PKG_LIBEXECDIR"/checkpassword-reply"; - + ret = checkpassword_parse_args(auth_passdb, module, args); + if (ret != 0) { + i_error("Invalid format for args config opt. Fallback to defaults -- %d", ret); + module->checkpassword_path = "/usr/local/bin/checkpassword"; + module->checkpassword_reply_path = PKG_LIBEXECDIR"/checkpassword-reply"; + } + module->clients = hash_create(default_pool, default_pool, 0, NULL, NULL); diff -ruN ../dovecot-1.0.rc8/src/auth/vmailmgr-reply.c ./src/auth/vmailmgr-reply.c --- ../dovecot-1.0.rc8/src/auth/vmailmgr-reply.c 1970-01-01 01:00:00.000000000 +0100 +++ ./src/auth/vmailmgr-reply.c 2006-09-29 23:14:46.000000000 +0200 @@ -0,0 +1,90 @@ +/* simple checkpassword wrapper to send userdb data back to dovecot-auth */ + +#include "lib.h" +#include "str.h" +#include "write-full.h" + +#include +#include +#include + +#ifndef PATH_MAX +/* _POSIX_PATH_MAX is 256 */ +#warning "PATH_MAX not available on your system. Defaulting to 256 chars" +#define PATH_MAX 256 +#endif + +int main(int argc, char *argv[]) +{ + string_t *str; + const char *extra_env, *value, *const *tmp; + char mdirpath[PATH_MAX]; + + + if (argc < 2) { + i_error("Unable to get maildir path. You need to put a \"maildir\" argument after me for me to get this information."); + return 1; + } + + if (argv[1][0] == '/') { /* absolute path given */ + size_t wsz; + + wsz = snprintf(mdirpath, PATH_MAX, "%s", argv[1]); + if (wsz >= PATH_MAX) { /* overflow */ + i_error("PATH_MAX (%d) is not enough for holding the whole maildir path (%d).", PATH_MAX, wsz); + return 1; + } + } else if (argv[1][0] == '.' && argv[1][1] == '/') { /* relative path */ + size_t wsz; + + if (getcwd(mdirpath, PATH_MAX) == NULL) { + i_error("Could not get working directory: %m"); + return 1; + } + wsz = snprintf(mdirpath, PATH_MAX, "%s/%s", mdirpath, argv[1]+2); + if (wsz >= PATH_MAX) { /* overflow */ + i_error("PATH_MAX (%d) is not enough for holding the whole maildir path (%d).", PATH_MAX, wsz); + return 1; + } + } else { /* ?? */ + i_error("The argument I got in place of the maildir path is unusable: %s", argv[1]); + return 1; + } + + lib_init(); + str = t_str_new(1024); + + if (strchr(getenv("USER"), '\t') != NULL) { + i_error("USER contains TAB"); + return 1; + } + + if (strchr(mdirpath, '\t') != NULL) { + i_error("Mail dir path contains TAB"); + return 1; + } + + str_printfa(str, "userdb_user=%s\t" + "userdb_home=%s\t" + "userdb_uid=%s\t" + "userdb_gid=%s\t", + getenv("USER"), mdirpath, + dec2str(getuid()), dec2str(getgid())); + + extra_env = getenv("EXTRA"); + if (extra_env != NULL) { + for (tmp = t_strsplit(extra_env, " "); *tmp != NULL; tmp++) { + value = getenv(*tmp); + if (value != NULL) { + str_printfa(str, "%s=%s\t", + t_str_lcase(*tmp), value); + } + } + } + + if (write_full(4, str_data(str), str_len(str)) < 0) { + i_error("write_full() failed: %m"); + exit(111); + } + return 0; +} diff -ruN ../dovecot-1.0.rc8/src/auth/vmailmgrwrapper.c ./src/auth/vmailmgrwrapper.c --- ../dovecot-1.0.rc8/src/auth/vmailmgrwrapper.c 1970-01-01 01:00:00.000000000 +0100 +++ ./src/auth/vmailmgrwrapper.c 2006-09-29 23:14:46.000000000 +0200 @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include +#include + +#define CHECKVPW "/usr/local/bin/checkvpw" +#define EXTRAARG "maildir" + +int main(int argc, char *argv[]) { + if (argc != 2) { + syslog(LOG_ERR, "I want 1 argument: program to be executed, not %d.", argc-1); + exit(111); + } + + execl(CHECKVPW, CHECKVPW, argv[1], EXTRAARG, NULL); + syslog(LOG_ERR, "Unable to execute " CHECKVPW ": %s", strerror(errno)); + + return 111; +} + diff -ruN ../dovecot-1.0.rc8/src/lib-storage/index/maildir/maildir-storage.c ./src/lib-storage/index/maildir/maildir-storage.c --- ../dovecot-1.0.rc8/src/lib-storage/index/maildir/maildir-storage.c 2006-08-10 22:35:11.000000000 +0200 +++ ./src/lib-storage/index/maildir/maildir-storage.c 2006-09-29 23:14:46.000000000 +0200 @@ -56,6 +56,19 @@ (void)rename(oldpath, path); } +/* string for setting inboxes */ +#define INBOXSTR ":INBOX=" +#define INBOXLEN 7 + +/* string for setting indexes */ +#define INDEXSTR ":INDEX=" +#define INDEXLEN 7 + +/* string for setting control */ +#define CONTROLSTR ":CONTROL=" +#define CONTROLLEN 9 + + static struct mail_storage * maildir_create(const char *data, const char *user, enum mail_storage_flags flags, @@ -99,26 +112,50 @@ root_dir = "/"; } } else { + const char *p_inbox, *p_index, *p_control; + /* [:INBOX=] [:INDEX=] [:CONTROL=] */ - if (debug) - i_info("maildir: data=%s", data); - p = strchr(data, ':'); - if (p == NULL) - root_dir = data; - else { - root_dir = t_strdup_until(data, p); + if (debug) + i_info("maildir: data=%s", data); - do { - p++; - if (strncmp(p, "INBOX=", 6) == 0) - inbox_dir = t_strcut(p+6, ':'); - else if (strncmp(p, "INDEX=", 6) == 0) - index_dir = t_strcut(p+6, ':'); - else if (strncmp(p, "CONTROL=", 8) == 0) - control_dir = t_strcut(p+8, ':'); - p = strchr(p, ':'); - } while (p != NULL); - } + /* expecting INBOX, INDEX, CONTROL in order */ + p_inbox = strstr(data, INBOXSTR); + p_index = strstr(data, INDEXSTR); + p_control = strstr(data, CONTROLSTR); + + /* safety check p_inbox < p_index < p_control */ + if (p_control != NULL && !(p_control > p_index && p_control > p_inbox)) { + i_error("inbox/index/control args in config do not appear in the order required."); + return NULL; + } + if (p_index != NULL && !(p_index > p_inbox)) { + i_error("inbox/index/control args in config do not appear in the order required."); + return NULL; + } + + /* set root_dir */ + if ((p = p_inbox) != NULL || (p = p_index) != NULL || (p = p_control) != NULL) { + /* p is where the first option begin */ + root_dir = t_strdup_until(data, p); + if (p_inbox != NULL) { /* set ":INBOX=" if available */ + if ((p = p_index) != NULL || (p = p_control) != NULL) { + /* p holds the next arg */ + inbox_dir = t_strdup_until(p_inbox + INBOXLEN, p); + } else { + inbox_dir = t_strdup(p_inbox + INBOXLEN); + } + } + if (p_index != NULL) { /* set ":INDEX=" if available */ + if (p_control != NULL) index_dir = t_strdup_until(p_index + INDEXLEN, p_control); + else index_dir = t_strdup(p_index + INDEXLEN); + } + if (p_control != NULL) { /* set ":INDEX=" if available */ + control_dir = t_strdup(p_control + CONTROLLEN); + } + } else { + /* no options set */ + root_dir = data; + } } if (root_dir == NULL) {