Hi Sam,

RE: https://bugs.debian.org/765579

On Thu, Oct 16, 2014 at 08:09:07PM -0400, Sam Varshavchik wrote:
> I am considering it. This is not a lot of code, but for me to take
> responsibility for it, since nobody else cares about it, I'll need to slowly
> pick it apart.

Yah, I thought the upstream of patch (mr.maX) was temporary out.  So I
rebased it to the current source.  But the upstream of patch is quiet
for communication (I thought I sent message.  CCing here.) and not seem
to be actively promoting his patch to Sam.  That made me uneasy to carry
Debian-only patch.  That made me to stop applying.
 
> Furthermore, I would like to believe that if there was, indeed, any demand
> for this kind of integration, someone would surely be willing to maintain
> this integration piece. Nature abhors a vacuum, so if this is now abandoned,
> for whatever reason, someone would surely be found, to take over.

I agree.  Anytime this part of patch is maintained by an accountable
person like Sam (possibly with mr.maX), I will be happy to have this
functionality.  (I think it may be better to change dlopen instead of
linking it like now so library package dependency is optional.)

Regards,

Osamu
PS: I attach patch here for the record.

Author: mr.maX <mrmax...@maxempire.com>
Description: [Dovecot] Dovecot auth user lookup patch for maildrop
 A patch for maildrop that would allow it to perform user lookups directly
 against Dovecot in a similar way how they are done by Dovecot's LDA deliver
 depending on used version of maildrop is available at 
 http://wiki.dovecot.org/maildrop (Document)
 http://www.max.rs/ozone/maildrop-2.3.0-dovecotauth.patch.txt (This patch)
 .
 maildrop will be extended with another command line option "-t", which can be
 used to specify the location of Dovecot's master auth socket that will be used
 when performing user lookups. There's a readme file (README.dovecotauth)
 together with patch with a little bit more information regarding the use of
 this extension.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Original upstream message: Sun Apr 26 01:20:14 EEST 2009
 recently I started using maildrop as a MDA doing lightweight filtering in a 
 Postfix/Dovecot mail server combo. Only thing missing was the fact that 
 maildrop couldn't perform user lookups against a user database that was 
 already being served by Dovecot (for smtp auth in Postfix and for imap 
 access obviously) in order to easily determinate proper mailbox location and 
 home directory of my "virtual" users when delivering e-mails. I wanted to 
 avoid having another authentication daemon running (Courier Authlib) that 
 would be serving this data to maildrop, so I've spent some time to write an 
 extension for maildrop that would allow it to do user lookups directly 
 against Dovecot in a similar way how they are done by Dovecot's LDA deliver. 
 For everyone that are using maildrop in a similar setup that may be 
 interested in this extension, a patch against maildrop version 2.0.4 can be 
 downloaded from the following location: 
 http://www.max.rs/ozone/maildrop-2.0.4-dovecotauth.patch.txt
 .
 When this patch is applied, maildrop will be extended with another command 
 line option "-t", which can be used to specify the location of Dovecot's 
 master auth socket that will be used when performing user lookups. There's a 
 readme file (README.dovecotauth) together with patch with a little bit more 
 information regarding the use of this extension. I hope that some of you may 
 find my modification to maildrop useful.
 .
 --
 Best Regards,
 Marko Njezic - mr.maX @ MAX Interactive corp.
 .
 Note: 
 When importing this patch to Debian, patch to maildrop/Makefile.in is dropped
 to avoid build problem with autoreconf.  See http://bugs.debian.org/661156

--- /dev/null
+++ b/libs/maildrop/dovecotauth.c
@@ -0,0 +1,480 @@
+/*
+** Copyright 2009 Marko Njezic
+** Licensed under the same terms as Courier Authlib AND/OR Courier Maildrop.
+**
+** Partially based on authdaemonlib.c from Courier Authlib, which had the following statement:
+**
+** Copyright 2000-2006 Double Precision, Inc.  See COPYING for
+** distribution information.
+**
+** Code that was taken from authdaemonlib.c is as follows:
+**  - s_connect() function
+**  - opensock() function with modification to accept socket address
+**  - writeauth() function
+**  - readline() function with related support functions (with modification
+**    to time-out after TIMEOUT_READ seconds)
+*/
+
+#include	"dovecotauth.h"
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<string.h>
+#include	<errno.h>
+#include	<fcntl.h>
+#include	<pwd.h>
+#include	<time.h>
+#include	<unistd.h>
+#include	<sys/types.h>
+#include	<sys/socket.h>
+#include	<sys/un.h>
+#include	<sys/select.h>
+
+static const char rcsid[]="$Id$";
+
+static int TIMEOUT_SOCK=10,
+	TIMEOUT_WRITE=10,
+	TIMEOUT_READ=30;
+
+static int s_connect(int sockfd,
+		     const struct sockaddr *addr,
+		     size_t addr_s,
+		     time_t connect_timeout)
+{
+	fd_set fdr;
+	struct timeval tv;
+	int	rc;
+
+#ifdef SOL_KEEPALIVE
+	setsockopt(sockfd, SOL_SOCKET, SOL_KEEPALIVE,
+		   (const char *)&dummy, sizeof(dummy));
+#endif
+
+#ifdef  SOL_LINGER
+        {
+		struct linger l;
+
+                l.l_onoff=0;
+                l.l_linger=0;
+
+                setsockopt(sockfd, SOL_SOCKET, SOL_LINGER,
+			   (const char *)&l, sizeof(l));
+        }
+#endif
+
+        /*
+        ** If configuration says to use the kernel's timeout settings,
+        ** just call connect, and be done with it.
+        */
+
+        if (connect_timeout == 0)
+                return ( connect(sockfd, addr, addr_s));
+
+        /* Asynchronous connect with timeout. */
+
+        if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)     return (-1);
+
+        if ( connect(sockfd, addr, addr_s) == 0)
+        {
+                /* That was easy, we're done. */
+
+                if (fcntl(sockfd, F_SETFL, 0) < 0)      return (-1);
+                return (0);
+        }
+
+	if (errno != EINPROGRESS)
+		return -1;
+
+	/* Wait for the connection to go through, until the timeout expires */
+
+        FD_ZERO(&fdr);
+        FD_SET(sockfd, &fdr);
+        tv.tv_sec=connect_timeout;
+        tv.tv_usec=0;
+
+        rc=select(sockfd+1, 0, &fdr, 0, &tv);
+        if (rc < 0)     return (-1);
+
+        if (!FD_ISSET(sockfd, &fdr))
+        {
+                errno=ETIMEDOUT;
+                return (-1);
+        }
+
+	{
+		int     gserr;
+		socklen_t gslen = sizeof(gserr);
+
+		if (getsockopt(sockfd, SOL_SOCKET,
+			       SO_ERROR,
+			       (char *)&gserr, &gslen)==0)
+		{
+			if (gserr == 0)
+				return 0;
+
+			errno=gserr;
+		}
+	}
+	return (-1);
+}
+
+static int opensock(const char *addr)
+{
+	int	s=socket(PF_UNIX, SOCK_STREAM, 0);
+	struct  sockaddr_un skun;
+
+	skun.sun_family=AF_UNIX;
+	strncpy(skun.sun_path, addr, sizeof(skun.sun_path));
+
+	if (s < 0)
+	{
+		perror("CRIT: dovecotauth: socket() failed");
+		return (-1);
+	}
+
+	{
+		const char *p=getenv("TIMEOUT_SOCK");
+		int n=atoi(p ? p:"0");
+
+		if (n > 0)
+			TIMEOUT_SOCK=n;
+	}
+
+	{
+		const char *p=getenv("TIMEOUT_READ");
+		int n=atoi(p ? p:"0");
+
+		if (n > 0)
+			TIMEOUT_READ=n;
+	}
+
+	{
+		const char *p=getenv("TIMEOUT_WRITE");
+		int n=atoi(p ? p:"0");
+
+		if (n > 0)
+			TIMEOUT_WRITE=n;
+	}
+
+	if (s_connect(s, (const struct sockaddr *)&skun, sizeof(skun),
+		      TIMEOUT_SOCK))
+	{
+		perror("ERR: dovecotauth: s_connect() failed");
+		if (errno == ETIMEDOUT || errno == ECONNREFUSED)
+			fprintf(stderr, "ERR: [Hint: perhaps dovecot-auth daemon is not running?]\n");
+		close(s);
+		return (-1);
+	}
+	return (s);
+}
+
+static int writeauth(int fd, const char *p, unsigned pl)
+{
+fd_set  fds;
+struct  timeval tv;
+
+	while (pl)
+	{
+	int     n;
+
+		FD_ZERO(&fds);
+		FD_SET(fd, &fds);
+		tv.tv_sec=TIMEOUT_WRITE;
+		tv.tv_usec=0;
+		if (select(fd+1, 0, &fds, 0, &tv) <= 0 || !FD_ISSET(fd, &fds))
+			return (-1);
+		n=write(fd, p, pl);
+		if (n <= 0)     return (-1);
+		p += n;
+		pl -= n;
+	}
+	return (0);
+}
+
+struct enum_getch {
+	char buffer[BUFSIZ];
+	char *buf_ptr;
+	size_t buf_left;
+};
+
+#define getauthc(fd,eg) ((eg)->buf_left-- ? \
+			(unsigned char)*((eg)->buf_ptr)++:\
+			fillgetauthc((fd),(eg)))
+
+static int fillgetauthc(int fd, struct enum_getch *eg)
+{
+	time_t	end_time, curtime;
+
+	time(&end_time);
+	end_time += TIMEOUT_READ;
+
+	for (;;)
+	{
+		int     n;
+		fd_set  fds;
+		struct  timeval tv;
+
+		time(&curtime);
+		if (curtime >= end_time)
+			break;
+
+		FD_ZERO(&fds);
+		FD_SET(fd, &fds);
+		tv.tv_sec=end_time - curtime;
+		tv.tv_usec=0;
+		if (select(fd+1, &fds, 0, 0, &tv) <= 0 || !FD_ISSET(fd, &fds))
+			break;
+
+		n=read(fd, eg->buffer, sizeof(eg->buffer));
+		if (n <= 0)
+			break;
+
+		eg->buf_ptr=eg->buffer;
+		eg->buf_left=n;
+
+		--eg->buf_left;
+		return (unsigned char)*(eg->buf_ptr)++;
+	}
+	return EOF;
+}
+
+static int readline(int fd, struct enum_getch *eg,
+		    char *buf,
+		    size_t bufsize)
+{
+	if (bufsize == 0)
+		return EOF;
+
+	while (--bufsize)
+	{
+		int ch=getauthc(fd, eg);
+
+		if (ch == EOF)
+			return -1;
+		if (ch == '\n')
+			break;
+
+		*buf++=ch;
+	}
+	*buf=0;
+	return 0;
+}
+
+/*
+** The actual implementation of Dovecot authentication protocol handling follows.
+** Full specification of the protocol can be found at: http://wiki.dovecot.org/Authentication%20Protocol
+** We are only interested in the "master" type requests for user information.
+*/
+
+int parse_userinfo(const char *user, const char *linebuf,
+	int (*func)(struct dovecotauthinfo *, void *), void *arg)
+{
+	int return_value=1;
+	struct dovecotauthinfo a;
+	char *buf, *p;
+	uid_t u;
+
+	/* Validate input arguments */
+	if (!user || !linebuf)
+		return (1);
+
+	/* Try to allocate buffer */
+	buf = (char *)malloc(strlen(linebuf)+1);
+	if (!buf)
+		return (1);
+	strcpy(buf, linebuf);
+
+	memset(&a, 0, sizeof(a));
+	a.homedir="";
+
+	p = strtok(buf, "\t");
+	if (p)
+		a.address=p;
+	else
+		a.address=user;
+
+	/* Parse any additional parameters */
+	while ((p = strtok(0, "\t")) != 0)
+	{
+		if (strncmp(p, "uid=", 4) == 0)
+		{
+			u=atol(p+4);
+			a.sysuserid = &u;
+			if (u == 0)
+			{
+				fprintf(stderr, "ERR: dovecotauth: Received invalid uid from auth socket\n");
+				return_value=1;
+				goto cleanup_parse_userinfo;
+			}
+		}
+		else if (strncmp(p, "gid=", 4) == 0)
+		{
+			a.sysgroupid=atol(p+4);
+			if (a.sysgroupid == 0)
+			{
+				fprintf(stderr, "ERR: dovecotauth: Received invalid gid from auth socket\n");
+				return_value=1;
+				goto cleanup_parse_userinfo;
+			}
+		}
+		else if (strncmp(p, "system_user=", 12) == 0)
+		{
+			a.sysusername=p+12;
+			if (a.sysusername)
+			{
+				struct passwd *q=getpwnam(a.sysusername);
+
+				if (q && q->pw_uid == 0)
+				{
+					fprintf(stderr, "ERR: dovecotauth: Received invalid system user from auth socket\n");
+					return_value=1;
+					goto cleanup_parse_userinfo;
+				}
+			}
+		}
+		else if (strncmp(p, "home=", 5) == 0)
+		{
+			a.homedir=p+5;
+		}
+		else if (strncmp(p, "mail=", 5) == 0)
+		{
+			a.maildir=p+5;
+		}
+	}
+
+	return_value = (*func)(&a, arg);
+
+cleanup_parse_userinfo:
+	free(buf);
+	return return_value;
+}
+
+#define	DOVECOTAUTH_LINEBUFSIZE	8192
+
+int _dovecotauth_getuserinfo(int wrfd, int rdfd, const char *user,
+	int (*func)(struct dovecotauthinfo *, void *), void *arg)
+{
+	static char cmdpart1[]="VERSION\t1\t0\nUSER\t1\t";
+	static char cmdpart2[]="\tservice=maildrop\n";
+	int return_value=1, handshake=0;
+	struct enum_getch eg;
+	char *cmdbuf, *linebuf;
+
+	/* Validate input arguments */
+	if (!user)
+		return (1);
+
+	/* Try to allocate buffers */
+	cmdbuf=(char *)malloc(strlen(cmdpart1)+strlen(cmdpart2)+strlen(user)+20);
+	if (!cmdbuf)
+		return (1);
+
+	linebuf=(char *)malloc(DOVECOTAUTH_LINEBUFSIZE);
+	if (!linebuf)
+		return (1);
+
+	/* Initial handshake */
+	eg.buf_left=0;
+	while (readline(rdfd, &eg, linebuf, DOVECOTAUTH_LINEBUFSIZE) == 0)
+	{
+		if (strncmp(linebuf, "VERSION\t", 8) == 0)
+		{
+			if (strncmp(linebuf+8, "1\t", 2) != 0)
+			{
+				fprintf(stderr, "ERR: dovecotauth: Authentication protocol version mismatch\n");
+				return_value=1;
+				goto cleanup_dovecotauth_getuserinfo;
+			}
+		}
+		else if (strncmp(linebuf, "SPID\t", 5) == 0)
+		{
+			/* End of server side handshake */
+			handshake=1;
+			break;
+		}
+	}
+
+	if (!handshake)
+	{
+		fprintf(stderr, "ERR: dovecotauth: Did not receive proper server handshake from auth socket\n");
+		return_value=1;
+		goto cleanup_dovecotauth_getuserinfo;
+	}
+
+	/*
+	** Try to be helpful in case that user tries to connect to the wrong auth socket.
+	** There's a slight chance that this won't execute in case that the previously
+	** returned line ends exactly at the buffer end, but we won't handle that case,
+	** since this is just a hint to the user, and not really neccessary.
+	** Normally, if user tries to communicate with wrong auth socket,
+	** we would simply time-out, while waiting for information.
+	*/
+	if (eg.buf_left > 0 && readline(rdfd, &eg, linebuf, DOVECOTAUTH_LINEBUFSIZE) == 0)
+	{
+		if (strncmp(linebuf, "CUID\t", 5) == 0)
+		{
+			fprintf(stderr, "ERR: dovecotauth: Trying to connect to what appears to be a client auth socket, instead of a master auth socket\n");
+			return_value=1;
+			goto cleanup_dovecotauth_getuserinfo;
+		}
+	}
+
+	/* Generate our part of communication */
+	strcat(strcat(strcpy(cmdbuf, cmdpart1), user), cmdpart2);
+
+	/* Send our part of communication */
+	if (writeauth(wrfd, cmdbuf, strlen(cmdbuf)))
+	{
+		return_value=1;
+		goto cleanup_dovecotauth_getuserinfo;
+	}
+
+	/* Parse returned information */
+	eg.buf_left=0;
+	if (readline(rdfd, &eg, linebuf, DOVECOTAUTH_LINEBUFSIZE) == 0)
+	{
+		if (strncmp(linebuf, "USER\t1\t", 7) == 0)
+		{
+			/* User was found in the database and we now parse returned information */
+			return_value=parse_userinfo(user, linebuf+7, func, arg);
+			goto cleanup_dovecotauth_getuserinfo;
+		}
+		else if (strcmp(linebuf, "NOTFOUND\t1") == 0)
+		{
+			/* User was not found in the database */
+			return_value=-1; /* Negative return value means that user is not found! */
+			goto cleanup_dovecotauth_getuserinfo;
+		}
+		else if (strncmp(linebuf, "FAIL\t1", 6) == 0)
+		{
+			/* An internal error has occurred on Dovecot's end */
+			return_value=1;
+			goto cleanup_dovecotauth_getuserinfo;
+		}
+		else
+		{
+			fprintf(stderr, "ERR: dovecotauth: Received unknown input from auth socket\n");
+		}
+	}
+	else
+		fprintf(stderr, "ERR: dovecotauth: Did not receive proper input from auth socket\n");
+
+cleanup_dovecotauth_getuserinfo:
+	free(cmdbuf);
+	free(linebuf);
+	return return_value;
+}
+
+int dovecotauth_getuserinfo(const char *addr, const char *user,
+	int (*func)(struct dovecotauthinfo *, void *), void *arg)
+{
+	int	s=opensock(addr);
+	int	rc;
+
+	if (s < 0)
+	{
+		return (1);
+	}
+	rc = _dovecotauth_getuserinfo(s, s, user, func, arg);
+	close(s);
+	return rc;
+}
--- /dev/null
+++ b/libs/maildrop/dovecotauth.h
@@ -0,0 +1,59 @@
+#ifndef	dovecotauth_h
+#define	dovecotauth_h
+
+/*
+** Copyright 2009 Marko Njezic
+** Licensed under the same terms as Courier Authlib AND/OR Courier Maildrop.
+**
+** Partially based on courierauth.h from Courier Authlib, which had the following statement:
+**
+** Copyright 2004 Double Precision, Inc.  See COPYING for
+** distribution information.
+*/
+
+#include	<sys/types.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+static const char dovecotauth_h_rcsid[]="$Id$";
+
+struct dovecotauthinfo {
+	const char *address;
+	const char *sysusername;
+	const uid_t *sysuserid;
+	gid_t sysgroupid;
+	const char *homedir;
+	const char *maildir;
+	} ;
+
+/*
+	This structure is modeled after authinfo structure from Courier Authlib.
+
+	Either sysusername or sysuserid may be NULL, but not both of them.
+	They, and sysgroupid, specify the authenticated user's system
+	userid and groupid.  homedir points to the authenticated user's
+	home directory.  address and maildir, are obvious.
+
+	After populating this tructure, the lookup function calls the
+	callback function that's specified in its second argument.  The
+	callback function receives a pointer to the authinfo structure.
+
+	The callback function also receives a context pointer, which is
+	the third argument to the lookup function.
+
+	The lookup function should return a negative value if the userid
+	does not exist, a positive value if there was a temporary error
+	looking up the userid, or whatever is the return code from the
+	callback function, if the user exists.
+*/
+
+int dovecotauth_getuserinfo(const char *addr, const char *user,
+	int (*func)(struct dovecotauthinfo *, void *), void *arg);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif
--- a/libs/maildrop/main.C
+++ b/libs/maildrop/main.C
@@ -32,6 +32,16 @@
 #include	<pwd.h>
 #include	<grp.h>
 #include	"../dbobj.h"
+
+/*
+** This switch can later be moved to config.h file with appropriate
+** configure option like --with-dovecotauth or something similar
+*/
+#define	DOVECOTAUTH	1
+#if DOVECOTAUTH
+#include	"dovecotauth.h"
+#endif
+
 #if AUTHLIB
 #include	<courierauth.h>
 #endif
@@ -176,6 +186,14 @@
 	"\n"
 #endif
 #endif
+#if DOVECOTAUTH
+	"Dovecot Authentication extension enabled."
+#if CRLF_TERM
+	"\r\n"
+#else
+	"\n"
+#endif
+#endif
 #if AUTHLIB
 	"Courier Authentication Library extension enabled."
 #if CRLF_TERM
@@ -345,6 +363,98 @@
 }
 #endif
 
+#if DOVECOTAUTH
+static int callback_dovecotauth(struct dovecotauthinfo *auth,
+			    void *void_arg)
+{
+	Maildrop &maildrop=*(Maildrop *)void_arg;
+
+	if (VerboseLevel() > 1)
+	{
+		Buffer b;
+
+		b.set(auth->sysgroupid);
+		b.push(0);
+
+		merr << "maildrop: dovecotauth: groupid="
+		     << b << "\n";
+	}
+
+	setgroupid(auth->sysgroupid);
+
+	uid_t u;
+	if (auth->sysusername)
+	{
+		struct	passwd *q=getpwnam(auth->sysusername);
+
+		if (q == NULL)
+		{
+			merr << "Cannot find system user "
+			     << auth->sysusername
+			     << "\n";
+
+			nochangeuidgid();
+		}
+
+		u=q->pw_uid;
+	}
+	else
+		u=*auth->sysuserid;
+
+	if (VerboseLevel() > 1)
+	{
+		Buffer b;
+
+		b.set(u);
+		b.push(0);
+
+		merr << "maildrop: dovecotauth: userid="
+		     << b << "\n";
+	}
+
+	setuid(u);
+
+	if ( getuid() != u)
+		nochangeuidgid();
+
+	if (VerboseLevel() > 1)
+	{
+		merr << "maildrop: dovecotauth: logname="
+		     << auth->address
+		     << ", home="
+		     << auth->homedir
+		     << ", mail="
+		     << (auth->maildir ? auth->maildir:"(default)")
+		     << "\n";
+	}
+
+	maildrop.init_home=auth->homedir;
+	maildrop.init_logname=auth->address;
+	maildrop.init_shell="/bin/sh";
+	maildrop.init_default=auth->maildir ? auth->maildir:
+		GetDefaultMailbox(auth->address);
+
+	return 0;
+}
+
+int find_in_dovecotauth(const char *addr, Maildrop *maildrop, const char* user)
+{
+	int rc=dovecotauth_getuserinfo(addr,
+				user, callback_dovecotauth, maildrop);
+
+	if (rc == 0)
+		return 1;
+
+	if (rc > 0)
+	{
+		errexit=EX_TEMPFAIL;
+		throw "Temporary authentication failure.";
+	}
+
+	return 0;
+}
+#endif
+
 static void tempfail(const char *msg)
 {
 	errexit = EX_TEMPFAIL;
@@ -369,6 +479,9 @@
 const	char *numuidgid=0;
 #endif
 #endif
+#if DOVECOTAUTH
+const	char *dovecotauth_addr=0;
+#endif
 
 
 	umask( 0007 );
@@ -454,6 +567,18 @@
 		case 'a':
 			maildrop.authlib_essential=1;
 			break;
+#if DOVECOTAUTH
+		case 't':
+			if (!*optarg && argn < argc)	optarg=argv[argn++];
+			if (!*optarg)
+			{
+				mout << "You didn't specify the location of Dovecot auth socket.\n";
+				return (EX_TEMPFAIL);
+			}
+			else
+				dovecotauth_addr=optarg;
+			break;
+#endif
 		case 'h':
 			help();
 			return (EX_TEMPFAIL);
@@ -475,7 +600,17 @@
 
 		if (*deliverymode)
 		{
-			found = find_in_authlib(&maildrop, deliverymode);
+
+#if DOVECOTAUTH
+			if (dovecotauth_addr)
+			{
+				found = find_in_dovecotauth(dovecotauth_addr, &maildrop, deliverymode);
+			}
+			else
+#endif
+			{
+				found = find_in_authlib(&maildrop, deliverymode);
+			}
 
 			if ( !found )
 			{
--- a/libs/maildrop/Makefile.am
+++ b/libs/maildrop/Makefile.am
@@ -43,7 +43,7 @@
 	recipe.C recipe.h recipenode.C recipenode.h recipeparse.C reeval.C \
 	reeval.h regexpnode.h rematch.C rematch.h rematchmsg.C rematchmsg.h \
 	rematchstr.C rematchstr.h search.C search.h token.C \
-	token.h varlist.C varlist.h
+	token.h varlist.C varlist.h dovecotauth.c dovecotauth.h
 
 maildrop_DEPENDENCIES = libmdcommon.la ../maildir/maildir.libdeps
 
--- /dev/null
+++ b/README.dovecotauth
@@ -0,0 +1,46 @@
+Dovecot Authentication extension for maildrop
+=============================================
+** Copyright 2009 Marko Njezic
+** Licensed under the same terms as Courier Authlib AND/OR Courier Maildrop.
+
+When you patch maildrop to include Dovecot Authentication extension, you'll be
+able to do user database lookups against Dovecot. This extension can happily
+coexist with Courier Authlib extension if it is also compiled.
+
+In order to use it you'll need to specify additional option "-t" that will point
+to the location of Dovecot's auth master socket when starting maildrop in
+delivery mode. For example:
+
+maildrop -d USER -t /var/run/dovecot/auth-master
+
+By specifying "-t" option, maildrop will first try user lookup against Dovecot's
+database. If user is not found, maildrop will fallback to local user database
+(i.e. passwd), as usual. Lookups against Courier Authlib will not be done when
+"-t" option is specified. If you want to perform such lookup when both
+extensions are compiled, simply remove "-t" option and maildrop will behave as
+usual.
+
+One significant difference compared to Courier Authlib extension is that Dovecot
+Authentication extension will never return uid/gid that's equal to zero. If such
+value was returned from database, maildrop will exit with temporary failure.
+This was done in order to prevent accidental mistakes. If you really want to
+deliver as/to root, you'll have to start maildrop without "-t" option and let
+it directly query system user database on its own.
+
+Make sure that correct permissions are set on Dovecot's auth master socket so
+that maildrop can communicate with it. Also, depending on what type of users are
+being served from Dovecot's database, if user lookup returns local user
+accounts, you may end up with problems when maildrop tries to write mails to the
+spool directory if wrong permission are set on it, since maildrop will reset its
+permissions (uid/gid) to the values returned from user database. This behavior
+is the same as the behavior of lookups against Courier Authlib, since they also
+reset maildrop's permissions. When you want maildrop to deliver to the local
+users, it's best to let it directly query system user database on its own,
+since then it can apply its own "RESET_GID" magic, which will hopefully result
+in "correct" permissions that will allow maildrop to write to the spool
+directory.
+
+And last but not least, I hope that you'll find this extension useful.
+Especially if you already have an existing user database in Dovecot, but would
+like to use maildrop (with its powerful "xfilter" command) to deliver e-mails,
+without setting up another authentication user database, like Courier Authlib.

Reply via email to