diff options
Diffstat (limited to 'contrib/sendmail/mail.local/mail.local.c')
-rw-r--r-- | contrib/sendmail/mail.local/mail.local.c | 185 |
1 files changed, 181 insertions, 4 deletions
diff --git a/contrib/sendmail/mail.local/mail.local.c b/contrib/sendmail/mail.local/mail.local.c index 3b91ee43..d623ac9 100644 --- a/contrib/sendmail/mail.local/mail.local.c +++ b/contrib/sendmail/mail.local/mail.local.c @@ -20,7 +20,7 @@ SM_IDSTR(copyright, Copyright (c) 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n") -SM_IDSTR(id, "@(#)$Id: mail.local.c,v 8.239.2.11 2003/09/01 01:49:46 gshapiro Exp $") +SM_IDSTR(id, "@(#)$Id: mail.local.c,v 8.251 2003/11/03 18:38:29 ca Exp $") #include <stdlib.h> #include <sm/errstring.h> @@ -34,6 +34,13 @@ SM_IDSTR(id, "@(#)$Id: mail.local.c,v 8.239.2.11 2003/09/01 01:49:46 gshapiro Ex #include <sm/mbdb.h> #include <sm/sysexits.h> +#ifndef HASHSPOOL +# define HASHSPOOL 0 +#endif /* ! HASHSPOOL */ +#ifndef HASHSPOOLMD5 +# define HASHSPOOLMD5 0 +#endif /* ! HASHSPOOLMD5 */ + /* ** This is not intended to work on System V derived systems ** such as Solaris or HP-UX, since they use a totally different @@ -65,6 +72,15 @@ SM_IDSTR(id, "@(#)$Id: mail.local.c,v 8.239.2.11 2003/09/01 01:49:46 gshapiro Ex #include <sm/conf.h> #include <sendmail/pathnames.h> +#if HASHSPOOL +# define HASH_NONE 0 +# define HASH_USER 1 +# if HASHSPOOLMD5 +# define HASH_MD5 2 +# include <openssl/md5.h> +# endif /* HASHSPOOLMD5 */ +#endif /* HASHSPOOL */ + #ifndef LOCKTO_RM # define LOCKTO_RM 300 /* timeout for stale lockfile removal */ @@ -134,6 +150,15 @@ bool LMTPMode = false; bool BounceQuota = false; /* permanent error when over quota */ char *HomeMailFile = NULL; /* store mail in homedir */ +#if HASHSPOOL +int HashType = HASH_NONE; +int HashDepth = 0; +bool StripRcptDomain = true; +#else /* HASHSPOOL */ +# define StripRcptDomain true +#endif /* HASHSPOOL */ +char SpoolPath[MAXPATHLEN]; + void deliver __P((int, char *)); int e_to_sys __P((int)); void notifybiff __P((char *)); @@ -143,6 +168,9 @@ int lockmbox __P((char *)); void unlockmbox __P((void)); void mailerr __P((const char *, const char *, ...)); void flush_error __P((void)); +#if HASHSPOOL +const char *hashname __P((char *)); +#endif /* HASHSPOOL */ int @@ -174,7 +202,17 @@ main(argc, argv) # endif /* LOG_MAIL */ from = NULL; + if (sm_strlcpy(SpoolPath, _PATH_MAILDIR, sizeof(SpoolPath)) >= + sizeof(SpoolPath)) + { + mailerr("421", "Configuration error: _PATH_MAILDIR too large"); + exit(EX_CONFIG); + } +#if HASHSPOOL + while ((ch = getopt(argc, argv, "7BbdD:f:h:r:lH:p:ns")) != -1) +#else /* HASHSPOOL */ while ((ch = getopt(argc, argv, "7BbdD:f:h:r:ls")) != -1) +#endif /* HASHSPOOL */ { switch(ch) { @@ -225,6 +263,61 @@ main(argc, argv) nofsync++; break; +#if HASHSPOOL + case 'H': + if (optarg == NULL || *optarg == '\0') + { + mailerr(NULL, "-H: missing hashinfo"); + usage(); + } + switch(optarg[0]) + { + case 'u': + HashType = HASH_USER; + break; + +# if HASHSPOOLMD5 + case 'm': + HashType = HASH_MD5; + break; +# endif /* HASHSPOOLMD5 */ + + default: + mailerr(NULL, "-H: unknown hash type"); + usage(); + } + if (optarg[1] == '\0') + { + mailerr(NULL, "-H: invalid hash depth"); + usage(); + } + HashDepth = atoi(&optarg[1]); + if ((HashDepth <= 0) || ((HashDepth * 2) >= MAXPATHLEN)) + { + mailerr(NULL, "-H: invalid hash depth"); + usage(); + } + break; + + case 'p': + if (optarg == NULL || *optarg == '\0') + { + mailerr(NULL, "-p: missing spool path"); + usage(); + } + if (sm_strlcpy(SpoolPath, optarg, sizeof(SpoolPath)) >= + sizeof(SpoolPath)) + { + mailerr(NULL, "-p: invalid spool path"); + usage(); + } + break; + + case 'n': + StripRcptDomain = false; + break; +#endif /* HASHSPOOL */ + case '?': default: usage(); @@ -593,7 +686,7 @@ dolmtp() } if (sm_strncasecmp(buf + 5, "to:", 3) != 0 || ((rcpt_addr[rcpt_num] = parseaddr(buf + 8, - true)) == NULL)) + StripRcptDomain)) == NULL)) { mailerr("501 5.5.4", "Syntax error in parameters"); @@ -916,6 +1009,7 @@ deliver(fd, name) ** Also, clear out any bogus characters. */ +#if !HASHSPOOL if (strlen(name) > 40) name[40] = '\0'; for (p = name; *p != '\0'; p++) @@ -925,12 +1019,22 @@ deliver(fd, name) else if (!isprint(*p)) *p = '.'; } +#endif /* !HASHSPOOL */ if (HomeMailFile == NULL) { - if (sm_snprintf(path, sizeof(path), "%s/%s", - _PATH_MAILDIR, name) >= sizeof(path)) + if (sm_strlcpyn(path, sizeof(path), +#if HASHSPOOL + 4, +#else /* HASHSPOOL */ + 3, +#endif /* HASHSPOOL */ + SpoolPath, "/", +#if HASHSPOOL + hashname(name), +#endif /* HASHSPOOL */ + name) >= sizeof(path)) { exitval = EX_UNAVAILABLE; mailerr("550 5.1.1", "%s: Invalid mailbox path", name); @@ -1510,6 +1614,79 @@ flush_error() } } +#if HASHSPOOL +const char * +hashname(name) + char *name; +{ + static char p[MAXPATHLEN]; + int i; + int len; + char *str; +# if HASHSPOOLMD5 + char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; + MD5_CTX ctx; + unsigned char md5[18]; +# if MAXPATHLEN <= 24 + ERROR _MAXPATHLEN <= 24 +# endif /* MAXPATHLEN <= 24 */ + char b64[24]; + MD5_LONG bits; + int j; +# endif /* HASHSPOOLMD5 */ + + if (HashType == HASH_NONE || HashDepth * 2 >= MAXPATHLEN) + { + p[0] = '\0'; + return p; + } + + switch(HashType) + { + case HASH_USER: + str = name; + break; + +# if HASHSPOOLMD5 + case HASH_MD5: + MD5_Init(&ctx); + MD5_Update(&ctx, name, strlen(name)); + MD5_Final(md5, &ctx); + md5[16] = 0; + md5[17] = 0; + + for (i = 0; i < 6; i++) + { + bits = (unsigned) md5[(3 * i)] << 16; + bits |= (unsigned) md5[(3 * i) + 1] << 8; + bits |= (unsigned) md5[(3 * i) + 2]; + + for (j = 3; j >= 0; j--) + { + b64[(4 * i) + j] = Base64[(bits & 0x3f)]; + bits >>= 6; + } + } + b64[22] = '\0'; + str = b64; + break; +# endif /* HASHSPOOLMD5 */ + } + + len = strlen(str); + for (i = 0; i < HashDepth; i++) + { + if (i < len) + p[i * 2] = str[i]; + else + p[i * 2] = '_'; + p[(i * 2) + 1] = '/'; + } + p[HashDepth * 2] = '\0'; + return p; +} +#endif /* HASHSPOOL */ + /* * e_to_sys -- * Guess which errno's are temporary. Gag me. |