[Dovecot] Configuration of LMTP Reject Code

Petter Urkedal urkedal at nbi.dk
Thu Mar 17 15:16:47 EET 2011


On 2011-02-22, Timo Sirainen wrote:
> On Tue, 2011-02-22 at 11:02 +0100, Petter Urkedal wrote:
> >     userdb {
> >       driver = passwd
> >       args = home=/srv/mail/nbi.ku.dk/%1n/%n mail=maildir:~/Maildir
> >     }
> 
> The problem with passwd is that it can't separate "user doesn't exist"
> from "temporary error". http://wiki2.dovecot.org/UserDatabase/NSS can
> separate these, but it hasn't been tested much..
> 
> > > > We use Postfix on the front-end, which is very configurable in this
> > > > respect.  I don't see a way to override the error code from LMTP,
> > > > though, but suggestions are welcome.
> > > 
> > > I don't really like adding settings that have very few users..
> > 
> > I understand, it's really a workaround.  A global directive to turn all
> > permanent errors into temporary ones, would do as well, since any error
> > from LMTP is a potential issue we want to know about.  I'm not sure
> > whether that's any nicer from your point of view.
> 
> Well, there aren't really any other permanent errors.. Quota already has
> quota_full_tempfail setting.

I think there is a better solution.  It seems that getpwnam_r is POSIX
and does the right thing.  The attached patch adds a feature-check for
getpwnam_r and, if present, uses it in userdb-passwd.c in place of the
problematic getpwnam.  I've not some light testing on a non-production
server.
-------------- next part --------------
diff -r 26d5351649ac configure.in
--- a/configure.in	Wed Mar 16 19:49:27 2011 +0200
+++ b/configure.in	Thu Mar 17 13:54:55 2011 +0100
@@ -379,7 +379,8 @@
 	       setrlimit setproctitle seteuid setreuid setegid setresgid \
 	       strtoull strtoll strtouq strtoq \
 	       setpriority quotactl getmntent kqueue kevent backtrace_symbols \
-	       walkcontext dirfd clearenv malloc_usable_size glob fallocate)
+	       walkcontext dirfd clearenv malloc_usable_size glob fallocate \
+	       getpwnam_r)
 
 AC_CHECK_LIB(rt, clock_gettime, [
   AC_DEFINE(HAVE_CLOCK_GETTIME,, Define if you have the clock_gettime function)
diff -r 26d5351649ac src/auth/userdb-passwd.c
--- a/src/auth/userdb-passwd.c	Wed Mar 16 19:49:27 2011 +0200
+++ b/src/auth/userdb-passwd.c	Thu Mar 17 13:54:55 2011 +0100
@@ -9,12 +9,18 @@
 #include "userdb-static.h"
 
 #include <pwd.h>
+#include <unistd.h>
 
 #define USER_CACHE_KEY "%u"
 
 struct passwd_userdb_module {
 	struct userdb_module module;
 	struct userdb_static_template *tmpl;
+
+#ifdef HAVE_GETPWNAM_R
+	char *buf;
+	size_t bufsize;
+#endif
 };
 
 struct passwd_userdb_iterate_context {
@@ -33,15 +39,35 @@
 	struct passwd_userdb_module *module =
 		(struct passwd_userdb_module *)_module;
 	struct passwd *pw;
+#ifdef HAVE_GETPWNAM_R
+	struct passwd pw_data;
+	int err;
+#endif
 
 	auth_request_log_debug(auth_request, "passwd", "lookup");
 
+#ifdef HAVE_GETPWNAM_R
+	err = getpwnam_r(auth_request->user, &pw_data,
+			 module->buf, module->bufsize, &pw);
+	if (pw == NULL) {
+		if (err) {
+		    auth_request_log_error(auth_request, "passwd", "%s",
+					   strerror(err));
+		    callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
+		    return;
+		}
+		auth_request_log_info(auth_request, "passwd", "unknown user");
+		callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
+		return;
+	}
+#else
 	pw = getpwnam(auth_request->user);
 	if (pw == NULL) {
 		auth_request_log_info(auth_request, "passwd", "unknown user");
 		callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
 		return;
 	}
+#endif
 
 	auth_request_set_field(auth_request, "user", pw->pw_name, NULL);
 
@@ -151,6 +177,13 @@
 	module->module.cache_key = USER_CACHE_KEY;
 	module->tmpl = userdb_static_template_build(pool, "passwd", args);
 
+#ifdef HAVE_GETPWNAM_R
+	module->bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+	if (module->bufsize == (size_t)-1)
+	    module->bufsize = 16384;
+	module->buf = p_malloc(pool, module->bufsize);
+#endif
+
 	if (userdb_static_template_remove(module->tmpl, "blocking",
 					  &value)) {
 		module->module.blocking = value == NULL ||


More information about the dovecot mailing list