diff options
Diffstat (limited to 'contrib/sendmail/mail.local/mail.local.c')
-rw-r--r-- | contrib/sendmail/mail.local/mail.local.c | 618 |
1 files changed, 301 insertions, 317 deletions
diff --git a/contrib/sendmail/mail.local/mail.local.c b/contrib/sendmail/mail.local/mail.local.c index 5eca2e4..cd13f44 100644 --- a/contrib/sendmail/mail.local/mail.local.c +++ b/contrib/sendmail/mail.local/mail.local.c @@ -10,234 +10,113 @@ * */ -#ifndef lint -static char copyright[] = +#include <sm/gen.h> + +SM_IDSTR(copyright, "@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ All rights reserved.\n\ Copyright (c) 1990, 1993, 1994\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* ! lint */ + The Regents of the University of California. All rights reserved.\n") + +SM_IDSTR(id, "@(#)$Id: mail.local.c,v 8.235 2001/12/30 04:59:39 gshapiro Exp $") -#ifndef lint -static char id[] = "@(#)$Id: mail.local.c,v 8.143.4.58 2001/06/01 05:33:31 gshapiro Exp $"; -#endif /* ! lint */ +#include <stdlib.h> +#include <sm/errstring.h> +#include <sm/io.h> +#include <sm/limits.h> +# include <unistd.h> +# ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +# endif /* EX_OK */ +#include <sm/mbdb.h> +#include <sm/sysexits.h> /* $FreeBSD$ */ /* ** This is not intended to work on System V derived systems ** such as Solaris or HP-UX, since they use a totally different -** approach to mailboxes (essentially, they have a setgid program -** rather than setuid, and they rely on the ability to "give away" +** approach to mailboxes (essentially, they have a set-group-ID program +** rather than set-user-ID, and they rely on the ability to "give away" ** files to do their work). IT IS NOT A BUG that this doesn't ** work on such architectures. */ -/* additional mode for open() */ -# define EXTRA_MODE 0 - -# include <sys/types.h> -# include <sys/param.h> -# include <sys/stat.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <time.h> +#include <stdlib.h> # include <sys/socket.h> # include <sys/file.h> - # include <netinet/in.h> # include <arpa/nameser.h> - -# include <fcntl.h> # include <netdb.h> -# include <pwd.h> -# include <stdio.h> -# include <stdlib.h> -# include <string.h> -# include <syslog.h> -# include <time.h> -# include <unistd.h> -# ifdef EX_OK -# undef EX_OK /* unistd.h may have another use for this */ -# endif /* EX_OK */ -# include <sysexits.h> -# include <ctype.h> +# include <pwd.h> -# ifndef __P -# include "sendmail/cdefs.h" -# endif /* ! __P */ -# include "sendmail/useful.h" - -extern size_t strlcpy __P((char *, const char *, size_t)); -extern size_t strlcat __P((char *, const char *, size_t)); - -# if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) -# ifndef HASSTRERROR -# define HASSTRERROR 1 -# endif /* ! HASSTRERROR */ -# endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ - -# include "sendmail/errstring.h" - -# ifndef LOCKTO_RM -# define LOCKTO_RM 300 /* timeout for stale lockfile removal */ -# endif /* ! LOCKTO_RM */ -# ifndef LOCKTO_GLOB -# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ -# endif /* ! LOCKTO_GLOB */ - -# ifdef __STDC__ -# include <stdarg.h> -# define REALLOC(ptr, size) realloc(ptr, size) -# else /* __STDC__ */ -# include <varargs.h> -/* define a realloc() which works for NULL pointers */ -# define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size)) -# endif /* __STDC__ */ - -# if (defined(sun) && defined(__svr4__)) || defined(__SVR4) -# define USE_LOCKF 1 -# define USE_SETEUID 1 -# define _PATH_MAILDIR "/var/mail" -# endif /* (defined(sun) && defined(__svr4__)) || defined(__SVR4) */ - -# ifdef NCR_MP_RAS3 -# define USE_LOCKF 1 -# define HASSNPRINTF 1 -# define _PATH_MAILDIR "/var/mail" -# endif /* NCR_MP_RAS3 */ - -# if defined(_AIX) -# define USE_LOCKF 1 -# define USE_SETEUID 1 -# endif /* defined(_AIX) */ - -# if defined(__hpux) -# define USE_LOCKF 1 -# define USE_SETRESUID 1 -# endif /* defined(__hpux) */ - -# ifdef DGUX -# define HASSNPRINTF 1 -# define USE_LOCKF 1 -# endif /* DGUX */ - -# if defined(_CRAY) -# if !defined(MAXPATHLEN) -# define MAXPATHLEN PATHSIZE -# endif /* !defined(MAXPATHLEN) */ -# define _PATH_MAILDIR "/usr/spool/mail" -# endif /* defined(_CRAY) */ - -# if defined(NeXT) && !defined(__APPLE__) -# include <libc.h> -# define _PATH_MAILDIR "/usr/spool/mail" -# define S_IRUSR S_IREAD -# define S_IWUSR S_IWRITE -# endif /* defined(NeXT) && !defined(__APPLE__) */ - -# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) -# include <paths.h> -# endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ +#include <sm/string.h> +#include <syslog.h> +#include <ctype.h> -/* - * If you don't have flock, you could try using lockf instead. - */ +#include <sm/conf.h> +#include <sendmail/pathnames.h> -# ifdef USE_LOCKF -# define flock(a, b) lockf(a, b, 0) -# ifdef LOCK_EX -# undef LOCK_EX -# endif /* LOCK_EX */ -# define LOCK_EX F_LOCK -# endif /* USE_LOCKF */ - -# ifndef LOCK_EX -# include <sys/file.h> -# endif /* ! LOCK_EX */ - -# if defined(BSD4_4) || defined(__GLIBC__) -# include <paths.h> -# define _PATH_LOCTMP "/var/tmp/local.XXXXXX" -# endif /* defined(BSD4_4) || defined(__GLIBC__) */ - -# ifdef BSD4_4 -# define HAS_ST_GEN 1 -# else /* BSD4_4 */ -# ifndef _BSD_VA_LIST_ -# define _BSD_VA_LIST_ va_list -# endif /* ! _BSD_VA_LIST_ */ -# endif /* BSD4_4 */ - -# if defined(BSD4_4) || defined(linux) -# define HASSNPRINTF 1 -# else /* defined(BSD4_4) || defined(linux) */ -# ifndef ultrix -extern FILE *fdopen __P((int, const char *)); -# endif /* ! ultrix */ -# endif /* defined(BSD4_4) || defined(linux) */ - -# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) -# define CONTENTLENGTH 1 /* Needs the Content-Length header */ -# endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ - -# if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) -# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ -# endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ - -# ifdef HPUX11 -# define HASSNPRINTF 1 /* has snprintf starting in 11.X */ -# endif /* HPUX11 */ - -# if _AIX4 >= 40300 -# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */ -# endif /* _AIX4 >= 40300 */ - -# if !HASSNPRINTF && !SFIO -extern int snprintf __P((char *, size_t, const char *, ...)); -# ifndef _CRAY -extern int vsnprintf __P((char *, size_t, const char *, ...)); -# endif /* ! _CRAY */ -# endif /* !HASSNPRINTF && !SFIO */ -/* -** If you don't have setreuid, and you have saved uids, and you have -** a seteuid() call that doesn't try to emulate using setuid(), then -** you can try defining USE_SETEUID. -*/ +/* additional mode for open() */ +# define EXTRA_MODE 0 + -# ifdef USE_SETEUID -# define setreuid(r, e) seteuid(e) -# endif /* USE_SETEUID */ +#ifndef LOCKTO_RM +# define LOCKTO_RM 300 /* timeout for stale lockfile removal */ +#endif /* ! LOCKTO_RM */ +#ifndef LOCKTO_GLOB +# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ +#endif /* ! LOCKTO_GLOB */ + +/* define a realloc() which works for NULL pointers */ +#define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size)) /* -** And of course on hpux you have setresuid() +** If you don't have flock, you could try using lockf instead. */ -# ifdef USE_SETRESUID -# define setreuid(r, e) setresuid(-1, e, -1) -# endif /* USE_SETRESUID */ +#ifdef LDA_USE_LOCKF +# define flock(a, b) lockf(a, b, 0) +# ifdef LOCK_EX +# undef LOCK_EX +# endif /* LOCK_EX */ +# define LOCK_EX F_LOCK +#endif /* LDA_USE_LOCKF */ -# ifndef _PATH_LOCTMP -# define _PATH_LOCTMP "/var/tmp/local.XXXXXX" -# endif /* ! _PATH_LOCTMP */ -# ifndef _PATH_MAILDIR -# define _PATH_MAILDIR "/var/spool/mail" -# endif /* ! _PATH_MAILDIR */ +#ifndef LOCK_EX +# include <sys/file.h> +#endif /* ! LOCK_EX */ -# ifndef S_ISREG -# define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) -# endif /* ! S_ISREG */ +/* +** If you don't have setreuid, and you have saved uids, and you have +** a seteuid() call that doesn't try to emulate using setuid(), then +** you can try defining LDA_USE_SETEUID. +*/ -# ifdef MAILLOCK -# include <maillock.h> -# endif /* MAILLOCK */ +#ifdef LDA_USE_SETEUID +# define setreuid(r, e) seteuid(e) +#endif /* LDA_USE_SETEUID */ -# define U_UID pw->pw_uid -# define U_GID pw->pw_gid +#ifdef LDA_CONTENTLENGTH +# define CONTENTLENGTH 1 +#endif /* LDA_CONTENTLENGTH */ #ifndef INADDRSZ # define INADDRSZ 4 /* size of an IPv4 address in bytes */ #endif /* ! INADDRSZ */ +#ifdef MAILLOCK +# include <maillock.h> +#endif /* MAILLOCK */ + #ifndef MAILER_DAEMON # define MAILER_DAEMON "MAILER-DAEMON" #endif /* ! MAILER_DAEMON */ @@ -248,19 +127,20 @@ off_t HeaderLength; off_t BodyLength; #endif /* CONTENTLENGTH */ -bool EightBitMime = TRUE; /* advertise 8BITMIME in LMTP */ +bool EightBitMime = true; /* advertise 8BITMIME in LMTP */ char ErrBuf[10240]; /* error buffer */ int ExitVal = EX_OK; /* sysexits.h error value. */ -bool HoldErrs = FALSE; /* Hold errors in ErrBuf */ -bool LMTPMode = FALSE; -bool BounceQuota = FALSE; /* permanent error when over quota */ -bool nobiff = FALSE; -bool nofsync = FALSE; +bool nobiff = false; +bool nofsync = false; +bool HoldErrs = false; /* Hold errors in ErrBuf */ +bool LMTPMode = false; +bool BounceQuota = false; /* permanent error when over quota */ +char *HomeMailFile = NULL; /* store mail in homedir */ void deliver __P((int, char *)); int e_to_sys __P((int)); void notifybiff __P((char *)); -int store __P((char *, int, bool *)); +int store __P((char *, bool *)); void usage __P((void)); int lockmbox __P((char *)); void unlockmbox __P((void)); @@ -277,6 +157,8 @@ main(argc, argv) int ch, fd; uid_t uid; char *from; + char *mbdbname = "pw"; + int err; extern char *optarg; extern int optind; @@ -295,12 +177,12 @@ main(argc, argv) # endif /* LOG_MAIL */ from = NULL; - while ((ch = getopt(argc, argv, "7Bbdf:r:ls")) != -1) + while ((ch = getopt(argc, argv, "7BbdD:f:h:r:ls")) != -1) { switch(ch) { case '7': /* Do not advertise 8BITMIME */ - EightBitMime = FALSE; + EightBitMime = false; break; case 'B': @@ -308,12 +190,16 @@ main(argc, argv) break; case 'b': /* bounce mail when over quota. */ - BounceQuota = TRUE; + BounceQuota = true; break; case 'd': /* Backward compatible. */ break; + case 'D': /* mailbox database type */ + mbdbname = optarg; + break; + case 'f': case 'r': /* Backward compatible. */ if (from != NULL) @@ -324,8 +210,18 @@ main(argc, argv) from = optarg; break; + case 'h': + if (optarg != NULL || *optarg != '\0') + HomeMailFile = optarg; + else + { + mailerr(NULL, "-h: missing filename"); + usage(); + } + break; + case 'l': - LMTPMode = TRUE; + LMTPMode = true; break; case 's': @@ -344,6 +240,19 @@ main(argc, argv) if (!nobiff) notifybiff(NULL); + err = sm_mbdb_initialize(mbdbname); + if (err != EX_OK) + { + char *errcode = "521"; + + if (err == EX_TEMPFAIL) + errcode = "421"; + + mailerr(errcode, "Can not open mailbox database %s: %s", + mbdbname, sm_strexit(err)); + exit(err); + } + if (LMTPMode) { extern void dolmtp __P((void)); @@ -370,7 +279,6 @@ main(argc, argv) */ uid = getuid(); - if (from == NULL && ((from = getlogin()) == NULL || (pw = getpwnam(from)) == NULL || pw->pw_uid != uid)) @@ -386,9 +294,9 @@ main(argc, argv) ** at the expense of repeated failures and multiple deliveries. */ - HoldErrs = TRUE; - fd = store(from, 0, NULL); - HoldErrs = FALSE; + HoldErrs = true; + fd = store(from, NULL); + HoldErrs = false; if (fd < 0) { flush_error(); @@ -480,6 +388,8 @@ parseaddr(s, rcpt) s = MAILER_DAEMON; l = strlen(s) + 1; + if (l < 0) + return NULL; p = malloc(l); if (p == NULL) { @@ -487,7 +397,7 @@ parseaddr(s, rcpt) exit(EX_TEMPFAIL); } - (void) strlcpy(p, s, l); + (void) sm_strlcpy(p, s, l); return p; } @@ -495,9 +405,22 @@ char * process_recipient(addr) char *addr; { - if (getpwnam(addr) == NULL) + SM_MBDB_T user; + + switch (sm_mbdb_lookup(addr, &user)) + { + case EX_OK: + return NULL; + + case EX_NOUSER: return "550 5.1.1 User unknown"; - return NULL; + + case EX_TEMPFAIL: + return "451 4.3.0 User database failure; retry later"; + + default: + return "550 5.3.0 User database failure"; + } } #define RCPT_GROW 30 @@ -509,7 +432,7 @@ dolmtp() char **rcpt_addr = NULL; int rcpt_num = 0; int rcpt_alloc = 0; - bool gotlhlo = FALSE; + bool gotlhlo = false; char *err; int msgfd; char *p; @@ -520,7 +443,7 @@ dolmtp() memset(myhostname, '\0', sizeof myhostname); (void) gethostname(myhostname, sizeof myhostname - 1); if (myhostname[0] == '\0') - strlcpy(myhostname, "localhost", sizeof myhostname); + sm_strlcpy(myhostname, "localhost", sizeof myhostname); printf("220 %s LMTP ready\r\n", myhostname); for (;;) @@ -538,18 +461,18 @@ dolmtp() { case 'd': case 'D': - if (strcasecmp(buf, "data") == 0) + if (sm_strcasecmp(buf, "data") == 0) { - bool inbody = FALSE; + bool inbody = false; if (rcpt_num == 0) { mailerr("503 5.5.1", "No recipients"); continue; } - HoldErrs = TRUE; - msgfd = store(return_path, rcpt_num, &inbody); - HoldErrs = FALSE; + HoldErrs = true; + msgfd = store(return_path, &inbody); + HoldErrs = false; if (msgfd < 0 && !inbody) { flush_error(); @@ -579,7 +502,7 @@ dolmtp() case 'l': case 'L': - if (strncasecmp(buf, "lhlo ", 5) == 0) + if (sm_strncasecmp(buf, "lhlo ", 5) == 0) { /* check for duplicate per RFC 1651 4.2 */ if (gotlhlo) @@ -588,7 +511,7 @@ dolmtp() myhostname); continue; } - gotlhlo = TRUE; + gotlhlo = true; printf("250-%s\r\n", myhostname); if (EightBitMime) printf("250-8BITMIME\r\n"); @@ -602,7 +525,7 @@ dolmtp() case 'm': case 'M': - if (strncasecmp(buf, "mail ", 5) == 0) + if (sm_strncasecmp(buf, "mail ", 5) == 0) { if (return_path != NULL) { @@ -610,9 +533,9 @@ dolmtp() "Nested MAIL command"); continue; } - if (strncasecmp(buf+5, "from:", 5) != 0 || + if (sm_strncasecmp(buf+5, "from:", 5) != 0 || ((return_path = parseaddr(buf + 10, - FALSE)) == NULL)) + false)) == NULL)) { mailerr("501 5.5.4", "Syntax error in parameters"); @@ -627,7 +550,7 @@ dolmtp() case 'n': case 'N': - if (strcasecmp(buf, "noop") == 0) + if (sm_strcasecmp(buf, "noop") == 0) { printf("250 2.0.0 Ok\r\n"); continue; @@ -638,7 +561,7 @@ dolmtp() case 'q': case 'Q': - if (strcasecmp(buf, "quit") == 0) + if (sm_strcasecmp(buf, "quit") == 0) { printf("221 2.0.0 Bye\r\n"); exit(EX_OK); @@ -649,7 +572,7 @@ dolmtp() case 'r': case 'R': - if (strncasecmp(buf, "rcpt ", 5) == 0) + if (sm_strncasecmp(buf, "rcpt ", 5) == 0) { if (return_path == NULL) { @@ -671,9 +594,9 @@ dolmtp() exit(EX_TEMPFAIL); } } - if (strncasecmp(buf + 5, "to:", 3) != 0 || + if (sm_strncasecmp(buf + 5, "to:", 3) != 0 || ((rcpt_addr[rcpt_num] = parseaddr(buf + 8, - TRUE)) == NULL)) + true)) == NULL)) { mailerr("501 5.5.4", "Syntax error in parameters"); @@ -689,7 +612,7 @@ dolmtp() printf("250 2.1.5 Ok\r\n"); continue; } - else if (strcasecmp(buf, "rset") == 0) + else if (sm_strcasecmp(buf, "rset") == 0) { printf("250 2.0.0 Ok\r\n"); @@ -707,7 +630,7 @@ rset: case 'v': case 'V': - if (strncasecmp(buf, "vrfy ", 5) == 0) + if (sm_strncasecmp(buf, "vrfy ", 5) == 0) { printf("252 2.3.3 Try RCPT to attempt delivery\r\n"); continue; @@ -727,25 +650,24 @@ rset: } int -store(from, lmtprcpts, inbody) +store(from, inbody) char *from; - int lmtprcpts; bool *inbody; { FILE *fp = NULL; time_t tval; - bool eline; - bool fullline = TRUE; /* current line is terminated */ + bool eline; /* previous line was empty */ + bool fullline = true; /* current line is terminated */ bool prevfl; /* previous line was terminated */ char line[2048]; int fd; char tmpbuf[sizeof _PATH_LOCTMP + 1]; if (inbody != NULL) - *inbody = FALSE; + *inbody = false; (void) umask(0077); - (void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf); + (void) sm_strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf); if ((fd = mkstemp(tmpbuf)) < 0 || (fp = fdopen(fd, "w+")) == NULL) { mailerr("451 4.3.0", "Unable to open temporary file"); @@ -759,7 +681,7 @@ store(from, lmtprcpts, inbody) (void) fflush(stdout); } if (inbody != NULL) - *inbody = TRUE; + *inbody = true; (void) time(&tval); (void) fprintf(fp, "From %s %s", from, ctime(&tval)); @@ -770,7 +692,7 @@ store(from, lmtprcpts, inbody) #endif /* CONTENTLENGTH */ line[0] = '\0'; - eline = TRUE; + eline = true; while (fgets(line, sizeof(line), stdin) != (char *) NULL) { size_t line_len = 0; @@ -792,7 +714,7 @@ store(from, lmtprcpts, inbody) } /* Check to see if we have the full line from fgets() */ - fullline = FALSE; + fullline = false; if (line_len > 0) { if (line[line_len - 1] == '\n') @@ -804,7 +726,7 @@ store(from, lmtprcpts, inbody) line[line_len - 1] = '\0'; line_len--; } - fullline = TRUE; + fullline = true; } else if (line[line_len - 1] == '\r') { @@ -813,19 +735,19 @@ store(from, lmtprcpts, inbody) if (peek == '\n') { line[line_len - 1] = '\n'; - fullline = TRUE; + fullline = true; } else (void) ungetc(peek, stdin); } } else - fullline = TRUE; + fullline = true; #ifdef CONTENTLENGTH if (prevfl && line[0] == '\n' && HeaderLength == 0) { - eline = FALSE; + eline = false; if (fp != NULL) HeaderLength = ftell(fp); if (HeaderLength <= 0) @@ -840,7 +762,7 @@ store(from, lmtprcpts, inbody) } #else /* CONTENTLENGTH */ if (prevfl && line[0] == '\n') - eline = TRUE; + eline = true; #endif /* CONTENTLENGTH */ else { @@ -848,12 +770,12 @@ store(from, lmtprcpts, inbody) fp != NULL && !memcmp(line, "From ", 5)) (void) putc('>', fp); - eline = FALSE; + eline = false; #ifdef CONTENTLENGTH /* discard existing "Content-Length:" headers */ if (prevfl && HeaderLength == 0 && (line[0] == 'C' || line[0] == 'c') && - strncasecmp(line, ContentHdr, 15) == 0) + sm_strncasecmp(line, ContentHdr, 15) == 0) { /* ** be paranoid: clear the line @@ -908,15 +830,10 @@ store(from, lmtprcpts, inbody) if (HeaderLength > 0 && BodyLength >= 0) { - extern char *quad_to_string(); - - if (sizeof BodyLength > sizeof(long)) - snprintf(line, sizeof line, "%s\n", - quad_to_string(BodyLength)); - else - snprintf(line, sizeof line, "%ld\n", - (long) BodyLength); - strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16); + (void) sm_snprintf(line, sizeof line, "%lld\n", + (LONGLONG_T) BodyLength); + (void) sm_strlcpy(&ContentHdr[16], line, + sizeof(ContentHdr) - 16); } else BodyLength = -1; /* Something is wrong here */ @@ -943,9 +860,9 @@ deliver(fd, name) { struct stat fsb; struct stat sb; - struct passwd *pw; char path[MAXPATHLEN]; int mbfd = -1, nr = 0, nw, off; + int exitval; char *p; char *errcode; off_t curoff; @@ -954,26 +871,42 @@ deliver(fd, name) int readamount; #endif /* CONTENTLENGTH */ char biffmsg[100], buf[8*1024]; - extern char *quad_to_string(); - + SM_MBDB_T user; /* ** Disallow delivery to unknown names -- special mailboxes can be ** handled in the sendmail aliases file. */ - if ((pw = getpwnam(name)) == NULL) + exitval = sm_mbdb_lookup(name, &user); + switch (exitval) { - if (ExitVal == EX_TEMPFAIL) - errcode = "451 4.3.0"; - else - { - ExitVal = EX_UNAVAILABLE; - errcode = "550 5.1.1"; - } - mailerr(errcode, "Unknown name: %s", name); + case EX_OK: + break; + + case EX_NOUSER: + exitval = EX_UNAVAILABLE; + mailerr("550 5.1.1", "%s: User unknown", name); + break; + + case EX_TEMPFAIL: + mailerr("451 4.3.0", "%s: User database failure; retry later", + name); + break; + + default: + exitval = EX_UNAVAILABLE; + mailerr("550 5.3.0", "%s: User database failure", name); + break; + } + + if (exitval != EX_OK) + { + if (ExitVal != EX_TEMPFAIL) + ExitVal = exitval; return; } + endpwent(); /* @@ -995,7 +928,29 @@ deliver(fd, name) } - (void) snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name); + if (HomeMailFile == NULL) + { + if (sm_snprintf(path, sizeof(path), "%s/%s", + _PATH_MAILDIR, name) >= sizeof(path)) + { + exitval = EX_UNAVAILABLE; + mailerr("550 5.1.1", "%s: Invalid mailbox path", name); + return; + } + } + else if (*user.mbdb_homedir == '\0') + { + exitval = EX_UNAVAILABLE; + mailerr("550 5.1.1", "%s: User missing home directory", name); + return; + } + else if (sm_snprintf(path, sizeof(path), "%s/%s", + user.mbdb_homedir, HomeMailFile) >= sizeof(path)) + { + exitval = EX_UNAVAILABLE; + mailerr("550 5.1.1", "%s: Invalid mailbox path", name); + return; + } /* @@ -1037,7 +992,7 @@ tryagain: errcode = "551 5.3.0"; mailerr(errcode, "lockmailbox %s failed; error code %d %s", - p, off, errno > 0 ? errstring(errno) : ""); + p, off, errno > 0 ? sm_errstring(errno) : ""); return; } @@ -1045,7 +1000,7 @@ tryagain: { int save_errno; int mode = S_IRUSR|S_IWUSR; - gid_t gid = U_GID; + gid_t gid = user.mbdb_gid; #ifdef MAILGID (void) umask(0007); @@ -1071,13 +1026,13 @@ tryagain: /* open failed, don't try again */ mailerr("450 4.2.0", "%s: %s", path, - errstring(save_errno)); + sm_errstring(save_errno)); goto err0; } - else if (fchown(mbfd, U_UID, gid) < 0) + else if (fchown(mbfd, user.mbdb_uid, gid) < 0) { mailerr("451 4.3.0", "chown %u.%u: %s", - U_UID, gid, name); + user.mbdb_uid, gid, name); goto err1; } else @@ -1089,7 +1044,7 @@ tryagain: ** is no longer valid; better safe than sorry. */ - sb.st_uid = U_UID; + sb.st_uid = user.mbdb_uid; (void) close(mbfd); mbfd = -1; } @@ -1099,28 +1054,29 @@ tryagain: mailerr("550 5.2.0", "%s: irregular file", path); goto err0; } - else if (sb.st_uid != U_UID) + else if (sb.st_uid != user.mbdb_uid) { ExitVal = EX_CANTCREAT; mailerr("550 5.2.0", "%s: wrong ownership (%d)", - path, sb.st_uid); + path, (int) sb.st_uid); goto err0; } /* change UID for quota checks */ - if (setreuid(0, U_UID) < 0) + if (setreuid(0, user.mbdb_uid) < 0) { mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)", - U_UID, errstring(errno), getuid(), geteuid()); + (int) user.mbdb_uid, sm_errstring(errno), + (int) getuid(), (int) geteuid()); goto err1; } #ifdef DEBUG - fprintf(stderr, "new euid = %d\n", geteuid()); + fprintf(stderr, "new euid = %d\n", (int) geteuid()); #endif /* DEBUG */ mbfd = open(path, O_APPEND|O_WRONLY|EXTRA_MODE, 0); if (mbfd < 0) { - mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + mailerr("450 4.2.0", "%s: %s", path, sm_errstring(errno)); goto err0; } else if (fstat(mbfd, &fsb) < 0 || @@ -1140,11 +1096,48 @@ tryagain: goto err1; } +#if 0 + /* + ** This code could be reused if we decide to add a + ** per-user quota field to the sm_mbdb interface. + */ + + /* + ** Fail if the user has a quota specified, and delivery of this + ** message would exceed that quota. We bounce such failures using + ** EX_UNAVAILABLE, unless there were internal problems, since + ** storing immense messages for later retries can cause queueing + ** issues. + */ + + if (ui.quota > 0) + { + struct stat dsb; + + if (fstat(fd, &dsb) < 0) + { + ExitVal = EX_TEMPFAIL; + mailerr("451 4.3.0", + "%s: fstat: can't stat temporary storage: %s", + ui.mailspool, sm_errstring(errno)); + goto err1; + } + + if (dsb.st_size + sb.st_size + 1 > ui.quota) + { + ExitVal = EX_UNAVAILABLE; + mailerr("551 5.2.2", + "%s: Mailbox full or quota exceeded", + ui.mailspool); + goto err1; + } + } +#endif /* 0 */ /* Wait until we can get a lock on the file. */ if (flock(mbfd, LOCK_EX) < 0) { - mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + mailerr("450 4.2.0", "%s: %s", path, sm_errstring(errno)); goto err1; } @@ -1152,23 +1145,19 @@ tryagain: { /* Get the starting offset of the new message for biff. */ curoff = lseek(mbfd, (off_t) 0, SEEK_END); - if (sizeof curoff > sizeof(long)) - (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n", - name, quad_to_string(curoff)); - else - (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\n", - name, (long) curoff); + (void) sm_snprintf(biffmsg, sizeof(biffmsg), "%s@%lld\n", + name, (LONGLONG_T) curoff); } /* Copy the message into the file. */ if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1) { mailerr("450 4.2.0", "Temporary file: %s", - errstring(errno)); + sm_errstring(errno)); goto err1; } #ifdef DEBUG - fprintf(stderr, "before writing: euid = %d\n", geteuid()); + fprintf(stderr, "before writing: euid = %d\n", (int) geteuid()); #endif /* DEBUG */ #ifdef CONTENTLENGTH headerbytes = (BodyLength >= 0) ? HeaderLength : -1 ; @@ -1176,7 +1165,7 @@ tryagain: { if (headerbytes == 0) { - snprintf(buf, sizeof buf, "%s", ContentHdr); + (void) sm_snprintf(buf, sizeof buf, "%s", ContentHdr); nr = strlen(buf); headerbytes = -1; readamount = 0; @@ -1206,7 +1195,7 @@ tryagain: errcode = "552 5.2.2"; #endif /* EDQUOT */ mailerr(errcode, "%s: %s", - path, errstring(errno)); + path, sm_errstring(errno)); goto err3; } } @@ -1214,18 +1203,18 @@ tryagain: if (nr < 0) { mailerr("450 4.2.0", "Temporary file: %s", - errstring(errno)); + sm_errstring(errno)); goto err3; } /* Flush to disk, don't wait for update. */ if (!nofsync && fsync(mbfd) < 0) { - mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + mailerr("450 4.2.0", "%s: %s", path, sm_errstring(errno)); err3: (void) setreuid(0, 0); #ifdef DEBUG - fprintf(stderr, "reset euid = %d\n", geteuid()); + fprintf(stderr, "reset euid = %d\n", (int) geteuid()); #endif /* DEBUG */ (void) ftruncate(mbfd, curoff); err1: if (mbfd >= 0) @@ -1242,7 +1231,7 @@ err0: unlockmbox(); if (errno == EDQUOT && BounceQuota) errcode = "552 5.2.2"; #endif /* EDQUOT */ - mailerr(errcode, "%s: %s", path, errstring(errno)); + mailerr(errcode, "%s: %s", path, sm_errstring(errno)); (void) truncate(path, curoff); } else if (!nobiff) @@ -1251,11 +1240,11 @@ err0: unlockmbox(); if (setreuid(0, 0) < 0) { mailerr("450 4.2.0", "setreuid(0, 0): %s", - errstring(errno)); + sm_errstring(errno)); goto err0; } #ifdef DEBUG - fprintf(stderr, "reset euid = %d\n", geteuid()); + fprintf(stderr, "reset euid = %d\n", (int) geteuid()); #endif /* DEBUG */ unlockmbox(); if (LMTPMode) @@ -1269,7 +1258,7 @@ err0: unlockmbox(); ** EPA 11/94. */ -bool Locked = FALSE; +bool Locked = false; #ifdef MAILLOCK int @@ -1282,7 +1271,7 @@ lockmbox(name) return 0; if ((r = maillock(name, 15)) == L_SUCCESS) { - Locked = TRUE; + Locked = true; return 0; } switch (r) @@ -1309,7 +1298,7 @@ unlockmbox() { if (Locked) mailunlock(); - Locked = FALSE; + Locked = false; } #else /* MAILLOCK */ @@ -1326,7 +1315,7 @@ lockmbox(path) return 0; if (strlen(path) + 6 > sizeof LockName) return EX_SOFTWARE; - (void) snprintf(LockName, sizeof LockName, "%s.lock", path); + (void) sm_snprintf(LockName, sizeof LockName, "%s.lock", path); (void) time(&start); for (; ; sleep(5)) { @@ -1346,7 +1335,7 @@ lockmbox(path) { /* defeat lock checking programs which test pid */ (void) write(fd, "0", 2); - Locked = TRUE; + Locked = true; (void) close(fd); return 0; } @@ -1376,7 +1365,7 @@ unlockmbox() if (!Locked) return; (void) unlink(LockName); - Locked = FALSE; + Locked = false; } #endif /* MAILLOCK */ @@ -1384,7 +1373,7 @@ void notifybiff(msg) char *msg; { - static bool initialized = FALSE; + static bool initialized = false; static int f = -1; struct hostent *hp; struct servent *sp; @@ -1393,7 +1382,7 @@ notifybiff(msg) if (!initialized) { - initialized = TRUE; + initialized = true; /* Be silent if biff service not available. */ if ((sp = getservbyname("biff", "udp")) == NULL || @@ -1424,11 +1413,12 @@ void usage() { ExitVal = EX_USAGE; - mailerr(NULL, "usage: mail.local [-7] [-B] [-b] [-l] [-f from] [-s] user ..."); + mailerr(NULL, "usage: mail.local [-7] [-B] [-b] [-d] [-l] [-s] [-f from|-r from] [-h filename] user ..."); exit(ExitVal); } void +/*VARARGS2*/ #ifdef __STDC__ mailerr(const char *hdr, const char *fmt, ...) #else /* __STDC__ */ @@ -1439,25 +1429,19 @@ mailerr(hdr, fmt, va_alist) #endif /* __STDC__ */ { size_t len = 0; - va_list ap; + SM_VA_LOCAL_DECL (void) e_to_sys(errno); -#ifdef __STDC__ - va_start(ap, fmt); -#else /* __STDC__ */ - va_start(ap); -#endif /* __STDC__ */ + SM_VA_START(ap, fmt); - if (LMTPMode) + if (LMTPMode && hdr != NULL) { - if (hdr != NULL) - { - snprintf(ErrBuf, sizeof ErrBuf, "%s ", hdr); - len = strlen(ErrBuf); - } + sm_snprintf(ErrBuf, sizeof ErrBuf, "%s ", hdr); + len = strlen(ErrBuf); } - (void) vsnprintf(&ErrBuf[len], sizeof ErrBuf - len, fmt, ap); + (void) sm_vsnprintf(&ErrBuf[len], sizeof ErrBuf - len, fmt, ap); + SM_VA_END(ap); if (!HoldErrs) flush_error(); @@ -1646,7 +1630,7 @@ _gettemp(path, doopen) extern int errno; register char *start, *trv; struct stat sbuf; - u_int pid; + unsigned int pid; pid = getpid(); for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ |