This patch fixes an important reliability fix when Sendmail performs local

mail delivery with non local NSS passwd source, such as LDAP.

Stock LDAP uses getpwnam(3) to lookup recipients. As mandated by SUSv2,
getpwnam(3) does not set errno, so Sendmail has no way of distinguishing
a non existing user and an error with a remote NSS source. Therefore,
when the LDAP server goes down, Sendmail bounces mail to valid recipients.

A first workround is to remove F=w from Mlocal in sendmail.cf. This will
inhibit local recipient lookups, but it has a two drawbacks
- ~/.forward do not work anymore
- For multi-recipient mails with a single inexistent user, mail.local
cause a DSN reporting an error for all users, whereas all valid users
do get the message.

A better workaround is this patch, which calls getpwnam_r(3). This newer
API do set errno and do return an error code. Sendmail is therefore able
to detect that it had a transcient error in NSS, and it will react by
queuing the message. This is what you really want to happen when LDAP
is down.

I have not been able to get any feedback from Sendmail developers about
this patch.
This commit is contained in:
manu 2009-03-09 21:24:00 +00:00
parent 22f990c1cc
commit d2931fd38a
3 changed files with 64 additions and 3 deletions

View file

@ -1,7 +1,7 @@
# $NetBSD: Makefile,v 1.104 2008/08/13 15:41:29 manu Exp $
# $NetBSD: Makefile,v 1.105 2009/03/09 21:24:00 manu Exp $
PKGNAME= sendmail-${DIST_VERS}
PKGREVISION= 1
PKGREVISION= 2
COMMENT= The well known Mail Transport Agent
CONFLICTS+= courier-mta-[0-9]* fastforward>=0.51nb2 postfix-[0-9]*

View file

@ -1,4 +1,4 @@
$NetBSD: distinfo,v 1.37 2008/06/14 08:58:06 tron Exp $
$NetBSD: distinfo,v 1.38 2009/03/09 21:24:00 manu Exp $
SHA1 (sendmail.8.14.3.tar.gz) = 814c54c3917aa6b0981b5ea99fb34e0c02f31489
RMD160 (sendmail.8.14.3.tar.gz) = 5423360ce908c985827cf6524a6de87e3451c27a
@ -15,3 +15,4 @@ SHA1 (patch-ai) = aca71358618e8c1dc785a8b2dc049b97232b8795
SHA1 (patch-aj) = e65e6fe44380de2f9c397c1a97677eb4ad285433
SHA1 (patch-al) = f5d8cef8c4abba5d5ae813b754c16037190a7ef1
SHA1 (patch-am) = d84eedbff0f037c1db341255dc9e1877866f12c7
SHA1 (patch-ba) = 640e476e923e8a44286f0b3febd521ad87053c60

View file

@ -0,0 +1,60 @@
$NetBSD: patch-ba,v 1.1 2009/03/09 21:24:00 manu Exp $
--- devtools/OS/NetBSD.orig 2008-11-09 16:26:18.000000000 +0100
+++ devtools/OS/NetBSD 2008-11-09 16:28:06.000000000 +0100
@@ -7,3 +7,3 @@
define(`confLIBS', `-lutil')
-define(`confENVDEF', ` -DNETISO')
+define(`confENVDEF', ` -DNETISO -D_FFR_GETPWNAM_R')
define(`confDEPEND_TYPE', `CC-M')
--- libsm/mbdb.c.orig 2003-12-10 04:19:07.000000000 +0100
+++ libsm/mbdb.c 2008-11-09 17:02:31.000000000 +0100
@@ -313,8 +313,12 @@
char *name;
SM_MBDB_T *user;
{
struct passwd *pw;
+#ifdef _FFR_GETPWNAM_R
+ struct passwd pwres;
+ char pwbuf[1024];
+#endif
#ifdef HESIOD
/* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
{
@@ -327,31 +331,16 @@
return EX_NOUSER;
}
#endif /* HESIOD */
- errno = 0;
+#ifdef _FFR_GETPWNAM_R
+ if (getpwnam_r(name, &pwres, pwbuf, sizeof(pwbuf), &pw) != 0)
+ return EX_TEMPFAIL;
+#else
pw = getpwnam(name);
+#endif
if (pw == NULL)
- {
-#if 0
- /*
- ** getpwnam() isn't advertised as setting errno.
- ** In fact, under FreeBSD, non-root getpwnam() on
- ** non-existant users returns NULL with errno = EPERM.
- ** This test won't work.
- */
- switch (errno)
- {
- case 0:
- return EX_NOUSER;
- case EIO:
- return EX_OSERR;
- default:
- return EX_TEMPFAIL;
- }
-#endif /* 0 */
return EX_NOUSER;
- }
sm_mbdb_frompw(user, pw);
return EX_OK;
}