diff options
Diffstat (limited to 'contrib/sendmail/src')
29 files changed, 2586 insertions, 888 deletions
diff --git a/contrib/sendmail/src/README b/contrib/sendmail/src/README index c437b1e..fddce9d 100644 --- a/contrib/sendmail/src/README +++ b/contrib/sendmail/src/README @@ -189,10 +189,11 @@ replies are text based and encoded as netstrings. The socket map uses the same syntax as milters the specify the remote endpoint, e.g.: -Ksocket mySocketMap inet:12345@127.0.0.1 +KmySocketMap socket inet:12345@127.0.0.1 See doc/op/op.me for details. + +---------------+ | COMPILE FLAGS | +---------------+ @@ -630,8 +631,7 @@ EGD Define this if your system has EGD installed, see http://egd.sourceforge.net/ . It should be used to seed the PRNG for STARTTLS if HASURANDOMDEV is not defined. STARTTLS Enables SMTP STARTTLS (RFC 2487). This requires OpenSSL - (http://www.OpenSSL.org/); use OpenSSL 0.9.5a or later - (if compatible with this version), do not use 0.9.3. + (http://www.OpenSSL.org/); use OpenSSL 0.9.8zc or later. See STARTTLS COMPILATION AND CONFIGURATION for further information. TLS_NO_RSA Turn off support for RSA algorithms in STARTTLS. @@ -653,6 +653,9 @@ REQUIRES_DIR_FSYNC Turn on support for file systems that require to chattr +S on Linux. DBMMODE The default file permissions to use when creating new database files for maps and aliases. Defaults to 0640. +IPV6_FULL Use uncompressed IPv6 addresses (set by default). This + permits a zero subnet to have a more specific match, + such as different map entries for IPv6:0:0 vs IPv6:0. Generic notice: If you enable a compile time option that needs libraries or include files that don't come with sendmail or are @@ -1733,6 +1736,7 @@ Fedora Core 5, 64 bit version Problem noted by Daniel Krones, solution suggested by Anthony Howe. + +--------------+ | MANUAL PAGES | +--------------+ diff --git a/contrib/sendmail/src/TRACEFLAGS b/contrib/sendmail/src/TRACEFLAGS index e73ed10..06efaa9 100644 --- a/contrib/sendmail/src/TRACEFLAGS +++ b/contrib/sendmail/src/TRACEFLAGS @@ -87,11 +87,17 @@ 71,>99 milter.c quarantine on errors 73 queue.c shared memory updates 74,>99 map.c LDAP map defer +#if _FFR_XCNCT +75 debug FFR_XC* +#endif /* _FFR_XCNCT */ 80 content length 81 sun remote mode 83 collect.c timeout 84 deliver.c timeout 85 map.c dprintf map +#if _FFR_PROXY +87 srvrsmtp.c proxy mode +#endif 89 conf.c >=8 use sm_dprintf() instead of syslog() 91 mci.c syslogging of MCI cache information 93,>99 * Prevent daemon connection fork for profiling/debugging diff --git a/contrib/sendmail/src/TUNING b/contrib/sendmail/src/TUNING index 77c3f64..8df5803 100644 --- a/contrib/sendmail/src/TUNING +++ b/contrib/sendmail/src/TUNING @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2003 Proofpoint, Inc. and its suppliers. +# Copyright (c) 2001-2003, 2014 Proofpoint, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set @@ -135,6 +135,17 @@ to send e-mail then either the -G option should be used or should be added to the .mc file. +Note: starting with 8.15, sendmail will not ignore temporary map +lookup failures during header rewriting, which means that DNS lookup +problems even for headers will cause messages to stay in the queue. +Hence it is strongly suggested to use the nocanonify feature; +at least turning it on for the MTA, but maybe disabling it for the +MSA, i.e., use Modifiers for DaemonPortOptions accordingly. +As a last resort, it is possible to override the host map to ignore +temporary failures, e.g., +Khost host -t +However, this can cause inconsistent header rewriting. + * Mailing Lists and Large Aliases (1-n Mailing) ----------------------------------------------- diff --git a/contrib/sendmail/src/bf.c b/contrib/sendmail/src/bf.c index 7d90856..0f2c9c0 100644 --- a/contrib/sendmail/src/bf.c +++ b/contrib/sendmail/src/bf.c @@ -695,7 +695,8 @@ sm_bfcommit(fp) sm_dprintf("bfcommit(%s): to disk\n", bfp->bf_filename); if (tTd(58, 32)) sm_dprintf("bfcommit(): filemode %o flags %ld\n", - bfp->bf_filemode, bfp->bf_flags); + (unsigned int) bfp->bf_filemode, + bfp->bf_flags); } if (stat(bfp->bf_filename, &st) == 0) diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c index 8d90acb..5f090b2 100644 --- a/contrib/sendmail/src/collect.c +++ b/contrib/sendmail/src/collect.c @@ -59,7 +59,7 @@ collect_eoh(e, numhdrs, hdrslen) sm_dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n", hnum, hsize); (void) rscheck("check_eoh", hnum, hsize, e, RSF_UNSTRUCTURED|RSF_COUNT, - 3, NULL, e->e_id, NULL); + 3, NULL, e->e_id, NULL, NULL); /* ** Process the header, @@ -297,6 +297,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize) int hdrslen; int numhdrs; int afd; + int old_rd_tmo; unsigned char *pbp; unsigned char peekbuf[8]; char bufbuf[MAXLINE]; @@ -311,7 +312,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize) dbto = smtpmode ? ((int) TimeOuts.to_datablock * 1000) : SM_TIME_FOREVER; sm_io_setinfo(fp, SM_IO_WHAT_TIMEOUT, &dbto); - set_tls_rd_tmo(TimeOuts.to_datablock); + old_rd_tmo = set_tls_rd_tmo(TimeOuts.to_datablock); c = SM_IO_EOF; inputerr = false; headeronly = hdrp != NULL; @@ -720,7 +721,7 @@ readerr: } if (headeronly) - return; + goto end; if (mstate != MS_BODY) { @@ -940,6 +941,9 @@ readerr: + e->e_nrcpts * WkRecipFact; markstats(e, (ADDRESS *) NULL, STATS_NORMAL); } + + end: + (void) set_tls_rd_tmo(old_rd_tmo); } /* @@ -1026,8 +1030,8 @@ dferror(df, msg, e) #endif /* 0 */ } else - syserr("421 4.3.0 collect: Cannot write %s (%s, uid=%d, gid=%d)", - dfname, msg, (int) geteuid(), (int) getegid()); + syserr("421 4.3.0 collect: Cannot write %s (%s, uid=%ld, gid=%ld)", + dfname, msg, (long) geteuid(), (long) getegid()); if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL, SM_IO_WRONLY, NULL, df) == NULL) sm_syslog(LOG_ERR, e->e_id, diff --git a/contrib/sendmail/src/conf.c b/contrib/sendmail/src/conf.c index b64f3c7..c73334e 100644 --- a/contrib/sendmail/src/conf.c +++ b/contrib/sendmail/src/conf.c @@ -13,7 +13,7 @@ #include <sendmail.h> -SM_RCSID("@(#)$Id: conf.c,v 8.1191 2014-01-08 17:03:14 ca Exp $") +SM_RCSID("@(#)$Id: conf.c,v 8.1192 2014-01-27 18:23:21 ca Exp $") #include <sm/sendmail.h> #include <sendmail/pathnames.h> @@ -229,10 +229,8 @@ struct dbsval DontBlameSendmailValues[] = { "worldwritableforwardfile", DBS_WORLDWRITABLEFORWARDFILE }, { "worldwritableincludefile", DBS_WORLDWRITABLEINCLUDEFILE }, { "groupreadablekeyfile", DBS_GROUPREADABLEKEYFILE }, -#if _FFR_GROUPREADABLEAUTHINFOFILE - { "groupreadableadefaultauthinfofile", + { "groupreadabledefaultauthinfofile", DBS_GROUPREADABLEAUTHINFOFILE }, -#endif /* _FFR_GROUPREADABLEAUTHINFOFILE */ { NULL, 0 } }; @@ -304,9 +302,9 @@ setdefaults(e) } TrustedUid = 0; if (tTd(37, 4)) - sm_dprintf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%d\n", + sm_dprintf("setdefaults: DefUser=%s, DefUid=%ld, DefGid=%ld\n", DefUser != NULL ? DefUser : "<1:1>", - (int) DefUid, (int) DefGid); + (long) DefUid, (long) DefGid); CheckpointInterval = 10; /* option C */ MaxHopCount = 25; /* option h */ set_delivery_mode(SM_FORK, e); /* option d */ @@ -365,6 +363,8 @@ setdefaults(e) #endif /* SASL */ #if STARTTLS TLS_Srv_Opts = TLS_I_SRV; + if (NULL == EVP_digest) + EVP_digest = EVP_md5(); #endif /* STARTTLS */ #ifdef HESIOD_INIT HesiodContext = NULL; @@ -379,6 +379,9 @@ setdefaults(e) } else InetMode = AF_INET; +#if !IPV6_FULL + UseCompressedIPv6Addresses = true; +#endif #else /* NETINET6 */ InetMode = AF_INET; #endif /* NETINET6 */ @@ -399,6 +402,9 @@ setdefaults(e) BadRcptThrottleDelay = 1; #endif /* _FFR_RCPTTHROTDELAY */ ConnectionRateWindowSize = 60; +#if _FFR_BOUNCE_QUEUE + BounceQueue = NOQGRP; +#endif /* _FFR_BOUNCE_QUEUE */ setupmaps(); setupqueues(); setupmailers(); @@ -423,8 +429,8 @@ setdefuser() ? "nobody" : defpwent->pw_name, sizeof(defuserbuf)); if (tTd(37, 4)) - sm_dprintf("setdefuser: DefUid=%d, DefUser=%s\n", - (int) DefUid, DefUser); + sm_dprintf("setdefuser: DefUid=%ld, DefUser=%s\n", + (long) DefUid, DefUser); } /* ** SETUPQUEUES -- initialize default queues @@ -665,12 +671,10 @@ setupmaps() dequote_init, null_map_open, null_map_close, arith_map_lookup, null_map_store); -#if _FFR_ARPA_MAP /* "arpa" map -- IP -> arpa */ MAPDEF("arpa", NULL, 0, dequote_init, null_map_open, null_map_close, arpa_map_lookup, null_map_store); -#endif /* _FFR_ARPA_MAP */ #if SOCKETMAP /* arbitrary daemons */ @@ -2299,7 +2303,7 @@ refuseconnections(e, dn, active) # define D_MSG_LA "delaying connections on daemon %s: load average=%d >= %d" /* sleep to flatten out connection load */ sm_setproctitle(true, e, D_MSG_LA, Daemons[dn].d_name, - CurrentLA, limit); + CurrentLA, limit); if (LogLevel > 8 && (now = curtime()) > log_delay) { sm_syslog(LOG_INFO, NOQID, D_MSG_LA, @@ -2780,7 +2784,7 @@ reapchild(sig) return SIGFUNC_RETURN; } /* -** GETDTABLESIZE -- return number of file descriptors +** GETDTSIZE -- return number of file descriptors ** ** Only on non-BSD systems ** @@ -3601,8 +3605,8 @@ lockfile(fd, filename, ext, type) uid_t euid = geteuid(); errno = save_errno; - syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", - filename, ext, fd, type, omode, euid); + syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)", + filename, ext, fd, type, omode, (long) euid); dumpfd(fd, true, true); } # else /* !HASFLOCK */ @@ -3631,8 +3635,8 @@ lockfile(fd, filename, ext, type) uid_t euid = geteuid(); errno = save_errno; - syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", - filename, ext, fd, type, omode, euid); + syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)", + filename, ext, fd, type, omode, (long) euid); dumpfd(fd, true, true); } # endif /* !HASFLOCK */ @@ -4009,8 +4013,8 @@ validate_connection(sap, hostname, e) hostname, anynet_ntoa(sap)); connection_rate_check(sap, e); - if (rscheck("check_relay", hostname, anynet_ntoa(sap), - e, RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID, NULL) != EX_OK) + if (rscheck("check_relay", hostname, anynet_ntoa(sap), e, + RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID, NULL, NULL) != EX_OK) { static char reject[BUFSIZ*2]; extern char MsgBuf[]; @@ -5406,7 +5410,7 @@ sm_syslog(level, id, fmt, va_alist) SM_VA_START(ap, fmt); n = sm_vsnprintf(buf, bufsize, fmt, ap); SM_VA_END(ap); - SM_ASSERT(n > 0); + SM_ASSERT(n >= 0); if (n < bufsize) break; @@ -5736,148 +5740,155 @@ char *CompileOptions[] = { #if ALLOW_255 "ALLOW_255", -#endif /* ALLOW_255 */ +#endif #if NAMED_BIND # if DNSMAP "DNSMAP", -# endif /* DNSMAP */ -#endif /* NAMED_BIND */ +# endif +#endif #if EGD "EGD", -#endif /* EGD */ +#endif #if HESIOD "HESIOD", -#endif /* HESIOD */ +#endif +#if HESIOD_ALLOW_NUMERIC_LOGIN + "HESIOD_ALLOW_NUMERIC_LOGIN", +#endif #if HES_GETMAILHOST "HES_GETMAILHOST", -#endif /* HES_GETMAILHOST */ +#endif +#if IPV6_FULL + /* Use uncompressed IPv6 address format (no "::") by default */ + "IPV6_FULL", +#endif #if LDAPMAP "LDAPMAP", -#endif /* LDAPMAP */ +#endif #if LDAP_REFERRALS "LDAP_REFERRALS", -#endif /* LDAP_REFERRALS */ +#endif #if LOG "LOG", -#endif /* LOG */ +#endif #if MAP_NSD "MAP_NSD", -#endif /* MAP_NSD */ +#endif #if MAP_REGEX "MAP_REGEX", -#endif /* MAP_REGEX */ +#endif #if MATCHGECOS "MATCHGECOS", -#endif /* MATCHGECOS */ +#endif #if MILTER "MILTER", -#endif /* MILTER */ +#endif #if MIME7TO8 "MIME7TO8", -#endif /* MIME7TO8 */ +#endif #if MIME7TO8_OLD "MIME7TO8_OLD", -#endif /* MIME7TO8_OLD */ +#endif #if MIME8TO7 "MIME8TO7", -#endif /* MIME8TO7 */ +#endif #if NAMED_BIND "NAMED_BIND", -#endif /* NAMED_BIND */ +#endif #if NDBM "NDBM", -#endif /* NDBM */ +#endif #if NETINET "NETINET", -#endif /* NETINET */ +#endif #if NETINET6 "NETINET6", -#endif /* NETINET6 */ +#endif #if NETINFO "NETINFO", -#endif /* NETINFO */ +#endif #if NETISO "NETISO", -#endif /* NETISO */ +#endif #if NETNS "NETNS", -#endif /* NETNS */ +#endif #if NETUNIX "NETUNIX", -#endif /* NETUNIX */ +#endif #if NETX25 "NETX25", -#endif /* NETX25 */ +#endif #if NEWDB "NEWDB", -#endif /* NEWDB */ +#endif #if NIS "NIS", -#endif /* NIS */ +#endif #if NISPLUS "NISPLUS", -#endif /* NISPLUS */ +#endif #if NO_DH "NO_DH", -#endif /* NO_DH */ +#endif #if PH_MAP "PH_MAP", -#endif /* PH_MAP */ +#endif #ifdef PICKY_HELO_CHECK "PICKY_HELO_CHECK", -#endif /* PICKY_HELO_CHECK */ +#endif #if PIPELINING "PIPELINING", -#endif /* PIPELINING */ +#endif #if SASL # if SASL >= 20000 "SASLv2", # else /* SASL >= 20000 */ "SASL", -# endif /* SASL >= 20000 */ -#endif /* SASL */ +# endif +#endif #if SCANF "SCANF", -#endif /* SCANF */ +#endif #if SM_LDAP_ERROR_ON_MISSING_ARGS "SM_LDAP_ERROR_ON_MISSING_ARGS", -#endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ +#endif #if SMTPDEBUG "SMTPDEBUG", -#endif /* SMTPDEBUG */ +#endif #if SOCKETMAP "SOCKETMAP", -#endif /* SOCKETMAP */ +#endif #if STARTTLS "STARTTLS", -#endif /* STARTTLS */ +#endif #if SUID_ROOT_FILES_OK "SUID_ROOT_FILES_OK", -#endif /* SUID_ROOT_FILES_OK */ +#endif #if TCPWRAPPERS "TCPWRAPPERS", -#endif /* TCPWRAPPERS */ +#endif #if TLS_NO_RSA "TLS_NO_RSA", -#endif /* TLS_NO_RSA */ +#endif #if TLS_VRFY_PER_CTX "TLS_VRFY_PER_CTX", -#endif /* TLS_VRFY_PER_CTX */ +#endif #if USERDB "USERDB", -#endif /* USERDB */ +#endif #if USE_LDAP_INIT "USE_LDAP_INIT", -#endif /* USE_LDAP_INIT */ +#endif #if USE_TTYPATH "USE_TTYPATH", -#endif /* USE_TTYPATH */ +#endif #if XDEBUG "XDEBUG", -#endif /* XDEBUG */ +#endif #if XLA "XLA", -#endif /* XLA */ +#endif NULL }; @@ -5890,169 +5901,169 @@ char *OsCompileOptions[] = { #if ADDRCONFIG_IS_BROKEN "ADDRCONFIG_IS_BROKEN", -#endif /* ADDRCONFIG_IS_BROKEN */ +#endif #ifdef AUTO_NETINFO_HOSTS "AUTO_NETINFO_HOSTS", -#endif /* AUTO_NETINFO_HOSTS */ +#endif #ifdef AUTO_NIS_ALIASES "AUTO_NIS_ALIASES", -#endif /* AUTO_NIS_ALIASES */ +#endif #if BROKEN_RES_SEARCH "BROKEN_RES_SEARCH", -#endif /* BROKEN_RES_SEARCH */ +#endif #ifdef BSD4_4_SOCKADDR "BSD4_4_SOCKADDR", -#endif /* BSD4_4_SOCKADDR */ +#endif #if BOGUS_O_EXCL "BOGUS_O_EXCL", -#endif /* BOGUS_O_EXCL */ +#endif #if DEC_OSF_BROKEN_GETPWENT "DEC_OSF_BROKEN_GETPWENT", -#endif /* DEC_OSF_BROKEN_GETPWENT */ +#endif #if FAST_PID_RECYCLE "FAST_PID_RECYCLE", -#endif /* FAST_PID_RECYCLE */ +#endif #if HASCLOSEFROM "HASCLOSEFROM", -#endif /* HASCLOSEFROM */ +#endif #if HASFCHOWN "HASFCHOWN", -#endif /* HASFCHOWN */ +#endif #if HASFCHMOD "HASFCHMOD", -#endif /* HASFCHMOD */ +#endif #if HASFDWALK "HASFDWALK", -#endif /* HASFDWALK */ +#endif #if HASFLOCK "HASFLOCK", -#endif /* HASFLOCK */ +#endif #if HASGETDTABLESIZE "HASGETDTABLESIZE", -#endif /* HASGETDTABLESIZE */ +#endif #if HASGETUSERSHELL "HASGETUSERSHELL", -#endif /* HASGETUSERSHELL */ +#endif #if HASINITGROUPS "HASINITGROUPS", -#endif /* HASINITGROUPS */ +#endif #if HASLDAPGETALIASBYNAME "HASLDAPGETALIASBYNAME", -#endif /* HASLDAPGETALIASBYNAME */ +#endif #if HASLSTAT "HASLSTAT", -#endif /* HASLSTAT */ +#endif #if HASNICE "HASNICE", -#endif /* HASNICE */ +#endif #if HASRANDOM "HASRANDOM", -#endif /* HASRANDOM */ +#endif #if HASRRESVPORT "HASRRESVPORT", -#endif /* HASRRESVPORT */ +#endif #if HASSETEGID "HASSETEGID", -#endif /* HASSETEGID */ +#endif #if HASSETLOGIN "HASSETLOGIN", -#endif /* HASSETLOGIN */ +#endif #if HASSETREGID "HASSETREGID", -#endif /* HASSETREGID */ +#endif #if HASSETRESGID "HASSETRESGID", -#endif /* HASSETRESGID */ +#endif #if HASSETREUID "HASSETREUID", -#endif /* HASSETREUID */ +#endif #if HASSETRLIMIT "HASSETRLIMIT", -#endif /* HASSETRLIMIT */ +#endif #if HASSETSID "HASSETSID", -#endif /* HASSETSID */ +#endif #if HASSETUSERCONTEXT "HASSETUSERCONTEXT", -#endif /* HASSETUSERCONTEXT */ +#endif #if HASSETVBUF "HASSETVBUF", -#endif /* HASSETVBUF */ +#endif #if HAS_ST_GEN "HAS_ST_GEN", -#endif /* HAS_ST_GEN */ +#endif #if HASSRANDOMDEV "HASSRANDOMDEV", -#endif /* HASSRANDOMDEV */ +#endif #if HASURANDOMDEV "HASURANDOMDEV", -#endif /* HASURANDOMDEV */ +#endif #if HASSTRERROR "HASSTRERROR", -#endif /* HASSTRERROR */ +#endif #if HASULIMIT "HASULIMIT", -#endif /* HASULIMIT */ +#endif #if HASUNAME "HASUNAME", -#endif /* HASUNAME */ +#endif #if HASUNSETENV "HASUNSETENV", -#endif /* HASUNSETENV */ +#endif #if HASWAITPID "HASWAITPID", -#endif /* HASWAITPID */ +#endif #if HAVE_NANOSLEEP "HAVE_NANOSLEEP", -#endif /* HAVE_NANOSLEEP */ +#endif #if IDENTPROTO "IDENTPROTO", -#endif /* IDENTPROTO */ +#endif #if IP_SRCROUTE "IP_SRCROUTE", -#endif /* IP_SRCROUTE */ +#endif #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL "LOCK_ON_OPEN", -#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ +#endif #if MILTER_NO_NAGLE "MILTER_NO_NAGLE ", -#endif /* MILTER_NO_NAGLE */ +#endif #if NEEDFSYNC "NEEDFSYNC", -#endif /* NEEDFSYNC */ +#endif #if NEEDLINK "NEEDLINK", -#endif /* NEEDLINK */ +#endif #if NEEDLOCAL_HOSTNAME_LENGTH "NEEDLOCAL_HOSTNAME_LENGTH", -#endif /* NEEDLOCAL_HOSTNAME_LENGTH */ +#endif #if NEEDSGETIPNODE "NEEDSGETIPNODE", -#endif /* NEEDSGETIPNODE */ +#endif #if NEEDSTRSTR "NEEDSTRSTR", -#endif /* NEEDSTRSTR */ +#endif #if NEEDSTRTOL "NEEDSTRTOL", -#endif /* NEEDSTRTOL */ +#endif #ifdef NO_GETSERVBYNAME "NO_GETSERVBYNAME", -#endif /* NO_GETSERVBYNAME */ +#endif #if NOFTRUNCATE "NOFTRUNCATE", -#endif /* NOFTRUNCATE */ +#endif #if REQUIRES_DIR_FSYNC "REQUIRES_DIR_FSYNC", -#endif /* REQUIRES_DIR_FSYNC */ +#endif #if RLIMIT_NEEDS_SYS_TIME_H "RLIMIT_NEEDS_SYS_TIME_H", -#endif /* RLIMIT_NEEDS_SYS_TIME_H */ +#endif #if SAFENFSPATHCONF "SAFENFSPATHCONF", -#endif /* SAFENFSPATHCONF */ +#endif #if SECUREWARE "SECUREWARE", -#endif /* SECUREWARE */ +#endif #if SFS_TYPE == SFS_4ARGS "SFS_4ARGS", #elif SFS_TYPE == SFS_MOUNT @@ -6072,55 +6083,55 @@ char *OsCompileOptions[] = #endif #if SHARE_V1 "SHARE_V1", -#endif /* SHARE_V1 */ +#endif #if SIOCGIFCONF_IS_BROKEN "SIOCGIFCONF_IS_BROKEN", -#endif /* SIOCGIFCONF_IS_BROKEN */ +#endif #if SIOCGIFNUM_IS_BROKEN "SIOCGIFNUM_IS_BROKEN", -#endif /* SIOCGIFNUM_IS_BROKEN */ +#endif #if SNPRINTF_IS_BROKEN "SNPRINTF_IS_BROKEN", -#endif /* SNPRINTF_IS_BROKEN */ +#endif #if SO_REUSEADDR_IS_BROKEN "SO_REUSEADDR_IS_BROKEN", -#endif /* SO_REUSEADDR_IS_BROKEN */ +#endif #if SYS5SETPGRP "SYS5SETPGRP", -#endif /* SYS5SETPGRP */ +#endif #if SYSTEM5 "SYSTEM5", -#endif /* SYSTEM5 */ +#endif #if USE_DOUBLE_FORK "USE_DOUBLE_FORK", -#endif /* USE_DOUBLE_FORK */ +#endif #if USE_ENVIRON "USE_ENVIRON", -#endif /* USE_ENVIRON */ +#endif #if USE_SA_SIGACTION "USE_SA_SIGACTION", -#endif /* USE_SA_SIGACTION */ +#endif #if USE_SIGLONGJMP "USE_SIGLONGJMP", -#endif /* USE_SIGLONGJMP */ +#endif #if USEGETCONFATTR "USEGETCONFATTR", -#endif /* USEGETCONFATTR */ +#endif #if USESETEUID "USESETEUID", -#endif /* USESETEUID */ +#endif #ifdef USESYSCTL "USESYSCTL", -#endif /* USESYSCTL */ +#endif #if USE_OPENSSL_ENGINE "USE_OPENSSL_ENGINE", -#endif /* USE_OPENSSL_ENGINE */ +#endif #if USING_NETSCAPE_LDAP "USING_NETSCAPE_LDAP", -#endif /* USING_NETSCAPE_LDAP */ +#endif #ifdef WAITUNION "WAITUNION", -#endif /* WAITUNION */ +#endif NULL }; @@ -6130,77 +6141,73 @@ char *OsCompileOptions[] = char *FFRCompileOptions[] = { +#if _FFR_ADD_BCC + "_FFR_ADD_BCC", +#endif #if _FFR_ADDR_TYPE_MODES /* more info in {addr_type}, requires m4 changes! */ "_FFR_ADDR_TYPE_MODES", -#endif /* _FFR_ADDR_TYPE_MODES */ +#endif +#if _FFR_ALIAS_DETAIL + /* try to handle +detail for aliases */ + "_FFR_ALIAS_DETAIL", +#endif #if _FFR_ALLOW_SASLINFO /* DefaultAuthInfo can be specified by user. */ /* DefaultAuthInfo doesn't really work in 8.13 anymore. */ "_FFR_ALLOW_SASLINFO", -#endif /* _FFR_ALLOW_SASLINFO */ -#if _FFR_ARPA_MAP - /* arpa map to reverse an IPv(4,6) address */ - "_FFR_ARPA_MAP", -#endif /* _FFR_ARPA_MAP */ +#endif #if _FFR_BADRCPT_SHUTDOWN /* shut down connection (421) if there are too many bad RCPTs */ "_FFR_BADRCPT_SHUTDOWN", -#endif /* _FFR_BADRCPT_SHUTDOWN */ +#endif #if _FFR_BESTMX_BETTER_TRUNCATION /* Better truncation of list of MX records for dns map. */ "_FFR_BESTMX_BETTER_TRUNCATION", -#endif /* _FFR_BESTMX_BETTER_TRUNCATION */ +#endif +#if _FFR_BOUNCE_QUEUE + /* Separate, unprocessed queue for DSNs */ + /* John Gardiner Myers of Proofpoint */ + "_FFR_BOUNCE_QUEUE", +#endif #if _FFR_CATCH_BROKEN_MTAS /* Deal with MTAs that send a reply during the DATA phase. */ "_FFR_CATCH_BROKEN_MTAS", -#endif /* _FFR_CATCH_BROKEN_MTAS */ -#if _FFR_CHECKCONFIG - /* New OpMode to check the configuration file */ - "_FFR_CHECKCONFIG", -#endif /* _FFR_CHECKCONFIG */ +#endif #if _FFR_CHK_QUEUE /* Stricter checks about queue directory permissions. */ "_FFR_CHK_QUEUE", -#endif /* _FFR_CHK_QUEUE */ +#endif #if _FFR_CLIENT_SIZE /* Don't try to send mail if its size exceeds SIZE= of server. */ "_FFR_CLIENT_SIZE", -#endif /* _FFR_CLIENT_SIZE */ +#endif #if _FFR_CRLPATH /* CRLPath; needs documentation; Al Smith */ "_FFR_CRLPATH", -#endif /* _FFR_CRLPATH */ -#if _FFR_DAEMON_NETUNIX - /* Allow local (not just TCP) socket connection to server. */ - "_FFR_DAEMON_NETUNIX", -#endif /* _FFR_DAEMON_NETUNIX */ -#if _FFR_DEPRECATE_MAILER_FLAG_I - /* What it says :-) */ - "_FFR_DEPRECATE_MAILER_FLAG_I", -#endif /* _FFR_DEPRECATE_MAILER_FLAG_I */ +#endif #if _FFR_DM_ONE /* deliver first TA in background, then queue */ "_FFR_DM_ONE", -#endif /* _FFR_DM_ONE */ +#endif #if _FFR_DIGUNIX_SAFECHOWN /* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */ /* Problem noted by Anne Bennett of Concordia University */ "_FFR_DIGUNIX_SAFECHOWN", -#endif /* _FFR_DIGUNIX_SAFECHOWN */ +#endif #if _FFR_DNSMAP_ALIASABLE /* Allow dns map type to be used for aliases. */ /* Don Lewis of TDK */ "_FFR_DNSMAP_ALIASABLE", -#endif /* _FFR_DNSMAP_ALIASABLE */ +#endif #if _FFR_DONTLOCKFILESFORREAD_OPTION /* Enable DontLockFilesForRead option. */ "_FFR_DONTLOCKFILESFORREAD_OPTION", -#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ +#endif #if _FFR_DOTTED_USERNAMES /* Allow usernames with '.' */ "_FFR_DOTTED_USERNAMES", -#endif /* _FFR_DOTTED_USERNAMES */ +#endif #if _FFR_DPO_CS /* ** Make DaemonPortOptions case sensitive. @@ -6215,11 +6222,11 @@ char *FFRCompileOptions[] = */ "_FFR_DPO_CS", -#endif /* _FFR_DPO_CS */ +#endif #if _FFR_DPRINTF_MAP /* dprintf map for logging */ "_FFR_DPRINTF_MAP", -#endif /* _FFR_DPRINTF_MAP */ +#endif #if _FFR_DROP_TRUSTUSER_WARNING /* ** Don't issue this warning: @@ -6228,24 +6235,20 @@ char *FFRCompileOptions[] = */ "_FFR_DROP_TRUSTUSER_WARNING", -#endif /* _FFR_DROP_TRUSTUSER_WARNING */ +#endif #if _FFR_EIGHT_BIT_ADDR_OK /* EightBitAddrOK: allow 8-bit e-mail addresses */ "_FFR_EIGHT_BIT_ADDR_OK", -#endif /* _FFR_EIGHT_BIT_ADDR_OK */ -#if _FFR_EXPDELAY - /* exponential queue delay */ - "_FFR_EXPDELAY", -#endif /* _FFR_EXPDELAY */ +#endif #if _FFR_EXTRA_MAP_CHECK /* perform extra checks on $( $) in R lines */ "_FFR_EXTRA_MAP_CHECK", -#endif /* _FFR_EXTRA_MAP_CHECK */ +#endif #if _FFR_GETHBN_ExFILE /* ** According to Motonori Nakamura some gethostbyname() ** implementations (TurboLinux?) may (temporarily) fail - ** due to a lack of file discriptors. Enabling this FFR + ** due to a lack of file descriptors. Enabling this FFR ** will check errno for EMFILE and ENFILE and in case of a match ** cause a temporary error instead of a permanent error. ** The right solution is of course to file a bug against those @@ -6253,11 +6256,11 @@ char *FFRCompileOptions[] = */ "_FFR_GETHBN_ExFILE", -#endif /* _FFR_GETHBN_ExFILE */ +#endif #if _FFR_FIPSMODE /* FIPSMode (if supported by OpenSSL library) */ "_FFR_FIPSMODE", -#endif /* _FFR_FIPSMODE */ +#endif #if _FFR_FIX_DASHT /* ** If using -t, force not sending to argv recipients, even @@ -6265,55 +6268,66 @@ char *FFRCompileOptions[] = */ "_FFR_FIX_DASHT", -#endif /* _FFR_FIX_DASHT */ +#endif #if _FFR_FORWARD_SYSERR /* Cause a "syserr" if forward file isn't "safe". */ "_FFR_FORWARD_SYSERR", -#endif /* _FFR_FORWARD_SYSERR */ +#endif #if _FFR_GEN_ORCPT /* Generate a ORCPT DSN arg if not already provided */ "_FFR_GEN_ORCPT", -#endif /* _FFR_GEN_ORCPT */ -#if _FFR_GROUPREADABLEAUTHINFOFILE - /* Allow group readable DefaultAuthInfo file. */ - "_FFR_GROUPREADABLEAUTHINFOFILE", -#endif /* _FFR_GROUPREADABLEAUTHINFOFILE */ +#endif #if _FFR_HANDLE_ISO8859_GECOS /* ** Allow ISO 8859 characters in GECOS field: replace them - ** ith ASCII "equivalent". + ** with ASCII "equivalent". */ /* Peter Eriksson of Linkopings universitet */ "_FFR_HANDLE_ISO8859_GECOS", -#endif /* _FFR_HANDLE_ISO8859_GECOS */ +#endif +#if _FFR_HANDLE_HDR_RW_TEMPFAIL + /* + ** Temporary header rewriting problems from remotename() etc + ** are not "sticky" for mci (e.g., during queue runs). + */ + + "_FFR_HANDLE_HDR_RW_TEMPFAIL", +#endif #if _FFR_HPUX_NSSWITCH /* Use nsswitch on HP-UX */ "_FFR_HPUX_NSSWITCH", -#endif /* _FFR_HPUX_NSSWITCH */ +#endif #if _FFR_IGNORE_BOGUS_ADDR /* Ignore addresses for which prescan() failed */ "_FFR_IGNORE_BOGUS_ADDR", -#endif /* _FFR_IGNORE_BOGUS_ADDR */ +#endif #if _FFR_IGNORE_EXT_ON_HELO /* Ignore extensions offered in response to HELO */ "_FFR_IGNORE_EXT_ON_HELO", -#endif /* _FFR_IGNORE_EXT_ON_HELO */ -#if _FFR_IPV6_FULL - /* Use uncompressed IPv6 address format (no "::") */ - "_FFR_IPV6_FULL", -#endif /* _FFR_IPV6_FULL */ +#endif #if _FFR_LINUX_MHNL /* Set MAXHOSTNAMELEN to 256 (Linux) */ "_FFR_LINUX_MHNL", -#endif /* _FFR_LINUX_MHNL */ +#endif #if _FFR_LOCAL_DAEMON /* Local daemon mode (-bl) which only accepts loopback connections */ "_FFR_LOCAL_DAEMON", -#endif /* _FFR_LOCAL_DAEMON */ +#endif +#if _FFR_LOG_MORE1 + /* log some TLS/AUTH info in from= too */ + "_FFR_LOG_MORE1", +#endif +#if _FFR_LOG_MORE2 + /* log some TLS info in to= too */ + "_FFR_LOG_MORE2", +#endif +#if _FFR_LOGREPLY + "_FFR_LOGREPLY", +#endif #if _FFR_MAIL_MACRO "_FFR_MAIL_MACRO", -#endif /* _FFR_MAIL_MACRO */ +#endif #if _FFR_MAXDATASIZE /* ** It is possible that a header is larger than MILTER_CHUNK_SIZE, @@ -6323,28 +6337,33 @@ char *FFRCompileOptions[] = */ "_FFR_MAXDATASIZE", -#endif /* _FFR_MAXDATASIZE */ +#endif #if _FFR_MAX_FORWARD_ENTRIES /* Try to limit number of .forward entries */ /* (doesn't work) */ /* Randall S. Winchester of the University of Maryland */ "_FFR_MAX_FORWARD_ENTRIES", -#endif /* _FFR_MAX_FORWARD_ENTRIES */ +#endif #if _FFR_MAX_SLEEP_TIME /* Limit sleep(2) time in libsm/clock.c */ "_FFR_MAX_SLEEP_TIME", -#endif /* _FFR_MAX_SLEEP_TIME */ +#endif #if _FFR_MDS_NEGOTIATE /* MaxDataSize negotation with libmilter */ "_FFR_MDS_NEGOTIATE", -#endif /* _FFR_MDS_NEGOTIATE */ +#endif #if _FFR_MEMSTAT /* Check free memory */ "_FFR_MEMSTAT", -#endif /* _FFR_MEMSTAT */ +#endif #if _FFR_MILTER_CHECK "_FFR_MILTER_CHECK", -#endif /* _FFR_MILTER_CHECK */ +#endif +#if _FFR_MILTER_CONNECT_REPLYCODE + /* milter: propagate replycode returned by connect commands */ + /* John Gardiner Myers of Proofpoint */ + "_FFR_MILTER_CONNECT_REPLYCODE ", +#endif #if _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF /* ** milter_body() uses the same conversion algorithm as putbody() @@ -6362,7 +6381,7 @@ char *FFRCompileOptions[] = */ "_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF", -#endif /* _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF */ +#endif #if _FFR_MILTER_CHECK_REJECTIONS_TOO /* ** Also send RCPTs that are rejected by check_rcpt to a milter @@ -6370,68 +6389,71 @@ char *FFRCompileOptions[] = */ "_FFR_MILTER_CHECK_REJECTIONS_TOO", -#endif /* _FFR_MILTER_CHECK_REJECTIONS_TOO */ +#endif #if _FFR_MILTER_ENHSC /* extract enhanced status code from milter replies for dsn= logging */ "_FFR_MILTER_ENHSC", -#endif /* _FFR_MILTER_ENHSC */ +#endif #if _FFR_MIME7TO8_OLD /* Old mime7to8 code, the new is broken for at least one example. */ "_FFR_MIME7TO8_OLD", -#endif /* _FFR_MAX_SLEEP_TIME */ +#endif #if _FFR_MORE_MACROS /* allow more long macro names ("unprintable" characters). */ "_FFR_MORE_MACROS", -#endif /* _FFR_MORE_MACROS */ +#endif #if _FFR_MSG_ACCEPT /* allow to override "Message accepted for delivery" */ "_FFR_MSG_ACCEPT", -#endif /* _FFR_MSG_ACCEPT */ +#endif #if _FFR_NODELAYDSN_ON_HOLD /* Do not issue a DELAY DSN for mailers that use the hold flag. */ /* Steven Pitzl */ "_FFR_NODELAYDSN_ON_HOLD", -#endif /* _FFR_NODELAYDSN_ON_HOLD */ +#endif #if _FFR_NO_PIPE /* Disable PIPELINING, delay client if used. */ "_FFR_NO_PIPE", -#endif /* _FFR_NO_PIPE */ +#endif #if _FFR_LDAP_NETWORK_TIMEOUT /* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */ "_FFR_LDAP_NETWORK_TIMEOUT", -#endif /* _FFR_LDAP_NETWORK_TIMEOUT */ +#endif #if _FFR_LOG_NTRIES /* log ntries=, from Nik Clayton of FreeBSD */ "_FFR_LOG_NTRIES", -#endif /* _FFR_LOG_NTRIES */ +#endif +#if _FFR_PROXY + /* "proxy" (synchronous) delivery mode */ + "_FFR_PROXY", +#endif #if _FFR_QF_PARANOIA "_FFR_QF_PARANOIA", -#endif /* _FFR_QF_PARANOIA */ -#if _FFR_QUEUEDELAY - /* Exponential queue delay; disabled in 8.13 since it isn't used. */ - "_FFR_QUEUEDELAY", -#endif /* _FFR_QUEUEDELAY */ +#endif #if _FFR_QUEUE_GROUP_SORTORDER /* Allow QueueSortOrder per queue group. */ /* XXX: Still need to actually use qgrp->qg_sortorder */ "_FFR_QUEUE_GROUP_SORTORDER", -#endif /* _FFR_QUEUE_GROUP_SORTORDER */ +#endif #if _FFR_QUEUE_MACRO /* Define {queue} macro. */ "_FFR_QUEUE_MACRO", -#endif /* _FFR_QUEUE_MACRO */ +#endif #if _FFR_QUEUE_RUN_PARANOIA /* Additional checks when doing queue runs; interval of checks */ "_FFR_QUEUE_RUN_PARANOIA", -#endif /* _FFR_QUEUE_RUN_PARANOIA */ +#endif #if _FFR_QUEUE_SCHED_DBG /* Debug output for the queue scheduler. */ "_FFR_QUEUE_SCHED_DBG", -#endif /* _FFR_QUEUE_SCHED_DBG */ +#endif +#if _FFR_RCPTFLAGS + "_FFR_RCPTFLAGS", +#endif #if _FFR_RCPTTHROTDELAY /* configurable delay for BadRcptThrottle */ "_FFR_RCPTTHROTDELAY", -#endif /* _FFR_RCPTTHROTDELAY */ +#endif #if _FFR_REDIRECTEMPTY /* ** envelope <> can't be sent to mailing lists, only owner- @@ -6440,19 +6462,19 @@ char *FFRCompileOptions[] = */ "_FFR_REDIRECTEMPTY", -#endif /* _FFR_REDIRECTEMPTY */ +#endif #if _FFR_REJECT_NUL_BYTE /* reject NUL bytes in body */ "_FFR_REJECT_NUL_BYTE", -#endif /* _FFR_REJECT_NUL_BYTE */ +#endif #if _FFR_RESET_MACRO_GLOBALS /* Allow macro 'j' to be set dynamically via rulesets. */ "_FFR_RESET_MACRO_GLOBALS", -#endif /* _FFR_RESET_MACRO_GLOBALS */ +#endif #if _FFR_RHS /* Random shuffle for queue sorting. */ "_FFR_RHS", -#endif /* _FFR_RHS */ +#endif #if _FFR_RUNPQG /* ** allow -qGqueue_group -qp to work, i.e., @@ -6460,15 +6482,15 @@ char *FFRCompileOptions[] = */ "_FFR_RUNPQG", -#endif /* _FFR_RUNPQG */ +#endif #if _FFR_SESSID /* session id (for logging) */ "_FFR_SESSID", -#endif /* _FFR_SESSID */ +#endif #if _FFR_SHM_STATUS /* Donated code (unused). */ "_FFR_SHM_STATUS", -#endif /* _FFR_SHM_STATUS */ +#endif #if _FFR_LDAP_SINGLEDN /* ** The LDAP database map code in Sendmail 8.12.10, when @@ -6487,15 +6509,15 @@ char *FFRCompileOptions[] = */ "_FFR_LDAP_SINGLEDN", -#endif /* _FFR_LDAP_SINGLEDN */ +#endif #if _FFR_SKIP_DOMAINS /* process every N'th domain instead of every N'th message */ "_FFR_SKIP_DOMAINS", -#endif /* _FFR_SKIP_DOMAINS */ +#endif #if _FFR_SLEEP_USE_SELECT /* Use select(2) in libsm/clock.c to emulate sleep(2) */ "_FFR_SLEEP_USE_SELECT ", -#endif /* _FFR_SLEEP_USE_SELECT */ +#endif #if _FFR_SPT_ALIGN /* ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64 @@ -6507,26 +6529,34 @@ char *FFRCompileOptions[] = /* Chris Adams of HiWAAY Informations Services */ "_FFR_SPT_ALIGN", -#endif /* _FFR_SPT_ALIGN */ +#endif #if _FFR_SS_PER_DAEMON /* SuperSafe per DaemonPortOptions: 'T' (better letter?) */ "_FFR_SS_PER_DAEMON", -#endif /* _FFR_SS_PER_DAEMON */ +#endif #if _FFR_TESTS /* enable some test code */ "_FFR_TESTS", -#endif /* _FFR_TESTS */ +#endif #if _FFR_TIMERS /* Donated code (unused). */ "_FFR_TIMERS", -#endif /* _FFR_TIMERS */ -#if _FFR_TLS_1 - /* More STARTTLS options, e.g., secondary certs. */ - "_FFR_TLS_1", -#endif /* _FFR_TLS_1 */ +#endif #if _FFR_TLS_EC "_FFR_TLS_EC", -#endif /* _FFR_TLS_EC */ +#endif +#if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE + /* + ** Use SSL_CTX_use_certificate_chain_file() + ** instead of SSL_CTX_use_certificate_file() + */ + + "_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE", +#endif +#if _FFR_TLS_SE_OPTS + /* TLS session options */ + "_FFR_TLS_SE_OPTS", +#endif #if _FFR_TRUSTED_QF /* ** If we don't own the file mark it as unsafe. @@ -6535,7 +6565,7 @@ char *FFRCompileOptions[] = */ "_FFR_TRUSTED_QF", -#endif /* _FFR_TRUSTED_QF */ +#endif #if _FFR_USE_GETPWNAM_ERRNO /* ** See libsm/mbdb.c: only enable this on OSs @@ -6545,15 +6575,18 @@ char *FFRCompileOptions[] = */ "_FFR_USE_GETPWNAM_ERRNO", -#endif /* _FFR_USE_GETPWNAM_ERRNO */ +#endif #if _FFR_USE_SEM_LOCKING "_FFR_USE_SEM_LOCKING", -#endif /* _FFR_USE_SEM_LOCKING */ +#endif #if _FFR_USE_SETLOGIN /* Use setlogin() */ /* Peter Philipp */ "_FFR_USE_SETLOGIN", -#endif /* _FFR_USE_SETLOGIN */ +#endif +#if _FFR_XCNCT + "_FFR_XCNCT", +#endif NULL }; diff --git a/contrib/sendmail/src/daemon.c b/contrib/sendmail/src/daemon.c index d6b3f49..4288365 100644 --- a/contrib/sendmail/src/daemon.c +++ b/contrib/sendmail/src/daemon.c @@ -32,7 +32,7 @@ SM_RCSID("@(#)$Id: daemon.c,v 8.698 2013-11-22 20:51:55 ca Exp $") #endif /* defined(USE_SOCK_STREAM) */ #if STARTTLS -# include <openssl/rand.h> +# include <openssl/rand.h> #endif /* STARTTLS */ #include <sm/time.h> @@ -517,14 +517,12 @@ getrequests(e) macdefine(&BlankEnvelope.e_macro, A_PERM, macid("{daemon_family}"), "unspec"); break; -#if _FFR_DAEMON_NETUNIX -# if NETUNIX +#if NETUNIX case AF_UNIX: macdefine(&BlankEnvelope.e_macro, A_PERM, macid("{daemon_family}"), "local"); break; -# endif /* NETUNIX */ -#endif /* _FFR_DAEMON_NETUNIX */ +#endif /* NETUNIX */ #if NETINET case AF_INET: macdefine(&BlankEnvelope.e_macro, A_PERM, @@ -827,6 +825,17 @@ getrequests(e) OutChannel = outchannel; DisConnected = false; +#if _FFR_XCNCT + t = xconnect(inchannel); + if (t <= 0) + { + clrbitn(D_XCNCT, Daemons[curdaemon].d_flags); + clrbitn(D_XCNCT_M, Daemons[curdaemon].d_flags); + } + else + setbitn(t, Daemons[curdaemon].d_flags); + +#endif /* _FFR_XCNCT */ #if XLA if (!xla_host_ok(RealHostName)) @@ -1060,8 +1069,7 @@ opendaemonsocket(d, firsttime) (void) sleep(5); if (firsttime || d->d_socket < 0) { -#if _FFR_DAEMON_NETUNIX -# if NETUNIX +#if NETUNIX if (d->d_addr.sa.sa_family == AF_UNIX) { int rval; @@ -1084,8 +1092,7 @@ opendaemonsocket(d, firsttime) /* Don't try to overtake an existing socket */ (void) unlink(d->d_addr.sunix.sun_path); } -# endif /* NETUNIX */ -#endif /* _FFR_DOMAIN_NETUNIX */ +#endif /* NETUNIX */ d->d_socket = socket(d->d_addr.sa.sa_family, SOCK_STREAM, 0); if (d->d_socket < 0) @@ -1113,7 +1120,7 @@ opendaemonsocket(d, firsttime) continue; } - if (SM_FD_SETSIZE > 0 && d->d_socket >= SM_FD_SETSIZE) + if (!SM_FD_OK_SELECT(d->d_socket)) { save_errno = EINVAL; syserr("opendaemonsocket: daemon %s: server SMTP socket (%d) too large", @@ -1168,13 +1175,11 @@ opendaemonsocket(d, firsttime) switch (d->d_addr.sa.sa_family) { -#if _FFR_DAEMON_NETUNIX -# ifdef NETUNIX +#ifdef NETUNIX case AF_UNIX: socksize = sizeof(d->d_addr.sunix); break; -# endif /* NETUNIX */ -#endif /* _FFR_DAEMON_NETUNIX */ +#endif /* NETUNIX */ #if NETINET case AF_INET: socksize = sizeof(d->d_addr.sin); @@ -1493,6 +1498,9 @@ setsockaddroptions(p, d) case SM_DEFER: case SM_DELIVER: case SM_FORK: +#if _FFR_PROXY + case SM_PROXY_REQ: +#endif /* _FFR_PROXY */ d->d_dm = *v; break; default: @@ -1512,13 +1520,11 @@ setsockaddroptions(p, d) #endif /* !_FFR_DPO_CS */ if (isascii(*v) && isdigit(*v)) d->d_addr.sa.sa_family = atoi(v); -#if _FFR_DAEMON_NETUNIX -# ifdef NETUNIX +#ifdef NETUNIX else if (sm_strcasecmp(v, "unix") == 0 || sm_strcasecmp(v, "local") == 0) d->d_addr.sa.sa_family = AF_UNIX; -# endif /* NETUNIX */ -#endif /* _FFR_DAEMON_NETUNIX */ +#endif /* NETUNIX */ #if NETINET else if (sm_strcasecmp(v, "inet") == 0) d->d_addr.sa.sa_family = AF_INET; @@ -1628,14 +1634,14 @@ setsockaddroptions(p, d) { switch (d->d_addr.sa.sa_family) { -#if _FFR_DAEMON_NETUNIX -# if NETUNIX +#if NETUNIX case AF_UNIX: if (strlen(addr) >= sizeof(d->d_addr.sunix.sun_path)) { errno = ENAMETOOLONG; - syserr("setsockaddroptions: domain socket name too long: %s > %d", - addr, sizeof(d->d_addr.sunix.sun_path)); + syserr("setsockaddroptions: domain socket name too long: %s > %ld", + addr, + (long) sizeof(d->d_addr.sunix.sun_path)); break; } @@ -1646,8 +1652,7 @@ setsockaddroptions(p, d) addr, sizeof(d->d_addr.sunix.sun_path)); break; -# endif /* NETUNIX */ -#endif /* _FFR_DAEMON_NETUNIX */ +#endif /* NETUNIX */ #if NETINET case AF_INET: if (!isascii(*addr) || !isdigit(*addr) || @@ -1998,16 +2003,14 @@ addr_family(addr) return AF_INET6; } #endif /* NETINET6 */ -#if _FFR_DAEMON_NETUNIX -# if NETUNIX +#if NETUNIX if (*addr == '/') { if (tTd(16, 9)) sm_dprintf("addr_family(%s): LOCAL\n", addr); return AF_UNIX; } -# endif /* NETUNIX */ -#endif /* _FFR_DAEMON_NETUNIX */ +#endif /* NETUNIX */ if (tTd(16, 9)) sm_dprintf("addr_family(%s): UNSPEC\n", addr); return AF_UNSPEC; @@ -2045,7 +2048,7 @@ chkclientmodifiers(flag) #if MILTER /* -** SETUP_DAEMON_FILTERS -- Parse per-socket filters +** SETUP_DAEMON_MILTERS -- Parse per-socket filters ** ** Parameters: ** none @@ -3047,8 +3050,7 @@ shutdown_daemon() (void) close(Daemons[i].d_socket); Daemons[i].d_socket = -1; -#if _FFR_DAEMON_NETUNIX -# if NETUNIX +#if NETUNIX /* Remove named sockets */ if (Daemons[i].d_addr.sa.sa_family == AF_UNIX) { @@ -3070,8 +3072,7 @@ shutdown_daemon() sm_errstring(errno)); } } -# endif /* NETUNIX */ -#endif /* _FFR_DAEMON_NETUNIX */ +#endif /* NETUNIX */ } } @@ -3413,7 +3414,7 @@ getauthinfo(fd, may_be_forged) char ibuf[MAXNAME + 1]; static char hbuf[MAXNAME + MAXAUTHINFO + 11]; - *may_be_forged = false; + *may_be_forged = true; falen = sizeof(RealHostAddr); if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || falen <= 0 || RealHostAddr.sa.sa_family == 0) @@ -3430,6 +3431,8 @@ getauthinfo(fd, may_be_forged) return NULL; errno = 0; } + + *may_be_forged = false; (void) sm_strlcpyn(hbuf, sizeof(hbuf), 2, RealUserName, "@localhost"); if (tTd(9, 1)) @@ -3446,8 +3449,10 @@ getauthinfo(fd, may_be_forged) } /* cross check RealHostName with forward DNS lookup */ - if (anynet_ntoa(&RealHostAddr)[0] != '[' && - RealHostName[0] != '[') + if (anynet_ntoa(&RealHostAddr)[0] == '[' || + RealHostName[0] == '[') + *may_be_forged = false; + else { int family; @@ -3473,19 +3478,16 @@ getauthinfo(fd, may_be_forged) /* try to match the reverse against the forward lookup */ hp = sm_gethostbyname(RealHostName, family); - if (hp == NULL) - { - /* XXX: Could be a temporary error on forward lookup */ - *may_be_forged = true; - } - else + if (hp != NULL) { for (ha = hp->h_addr_list; *ha != NULL; ha++) { if (addrcmp(hp, *ha, &RealHostAddr) == 0) + { + *may_be_forged = false; break; + } } - *may_be_forged = *ha == NULL; #if NETINET6 freehostent(hp); hp = NULL; @@ -4259,12 +4261,10 @@ anynet_ntop(s6a, dst, dst_len) return NULL; dst += sz; dst_len -= sz; -# if _FFR_IPV6_FULL - ap = sm_inet6_ntop(s6a, dst, dst_len); -# else /* _FFR_IPV6_FULL */ - ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); -# endif /* _FFR_IPV6_FULL */ - + if (UseCompressedIPv6Addresses) + ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); + else + ap = sm_inet6_ntop(s6a, dst, dst_len); /* Restore pointer to beginning of string */ if (ap != NULL) ap = d; diff --git a/contrib/sendmail/src/deliver.c b/contrib/sendmail/src/deliver.c index 39c484c..62d02b1 100644 --- a/contrib/sendmail/src/deliver.c +++ b/contrib/sendmail/src/deliver.c @@ -37,7 +37,7 @@ static void sendenvelope __P((ENVELOPE *, int)); static int coloncmp __P((const char *, const char *)); #if STARTTLS -# include <openssl/err.h> +# include <openssl/err.h> static int starttls __P((MAILER *, MCI *, ENVELOPE *)); static int endtlsclt __P((MCI *)); #endif /* STARTTLS */ @@ -1223,6 +1223,7 @@ should_try_fbsh(e, tried_fallbacksmarthost, hostbuf, hbsz, status) } return false; } + /* ** DELIVER -- Deliver a message to a list of addresses. ** @@ -1392,6 +1393,8 @@ deliver(e, firstto) else p = e->e_from.q_paddr; rpath = remotename(p, m, RF_SENDERADDR|RF_CANONICAL, &rcode, e); + if (rcode != EX_OK && bitnset(M_xSMTP, m->m_flags)) + goto cleanup; if (strlen(rpath) > MAXNAME) { rpath = shortenstring(rpath, MAXSHORTSTR); @@ -1468,6 +1471,7 @@ deliver(e, firstto) /* running LMTP or SMTP */ clever = true; *pvp = NULL; + setbitn(M_xSMTP, m->m_flags); } else if (bitnset(M_LMTP, m->m_flags)) { @@ -1600,7 +1604,7 @@ deliver(e, firstto) quarantine = (e->e_quarmsg != NULL); rcode = rscheck("check_compat", e->e_from.q_paddr, to->q_paddr, e, RSF_RMCOMM|RSF_COUNT, 3, NULL, - e->e_id, NULL); + e->e_id, NULL, NULL); if (rcode == EX_OK) { /* do in-code checking if not discarding */ @@ -2465,8 +2469,8 @@ tryhost: ctladdr->q_gid) == -1 && suidwarn) { - syserr("openmailer: initgroups(%s, %d) failed", - user, ctladdr->q_gid); + syserr("openmailer: initgroups(%s, %ld) failed", + user, (long) ctladdr->q_gid); exit(EX_TEMPFAIL); } } @@ -2492,8 +2496,8 @@ tryhost: if (initgroups(DefUser, DefGid) == -1 && suidwarn) { - syserr("openmailer: initgroups(%s, %d) failed", - DefUser, DefGid); + syserr("openmailer: initgroups(%s, %ld) failed", + DefUser, (long) DefGid); exit(EX_TEMPFAIL); } } @@ -2522,9 +2526,9 @@ tryhost: new_gid != getegid()) { /* Only root can change the gid */ - syserr("openmailer: insufficient privileges to change gid, RunAsUid=%d, new_gid=%d, gid=%d, egid=%d", - (int) RunAsUid, (int) new_gid, - (int) getgid(), (int) getegid()); + syserr("openmailer: insufficient privileges to change gid, RunAsUid=%ld, new_gid=%ld, gid=%ld, egid=%ld", + (long) RunAsUid, (long) new_gid, + (long) getgid(), (long) getegid()); exit(EX_TEMPFAIL); } @@ -2619,8 +2623,8 @@ tryhost: if (RunAsUid != 0 && new_euid != RunAsUid) { /* Only root can change the uid */ - syserr("openmailer: insufficient privileges to change uid, new_euid=%d, RunAsUid=%d", - (int) new_euid, (int) RunAsUid); + syserr("openmailer: insufficient privileges to change uid, new_euid=%ld, RunAsUid=%ld", + (long) new_euid, (long) RunAsUid); exit(EX_TEMPFAIL); } @@ -2662,9 +2666,9 @@ tryhost: } if (tTd(11, 2)) - sm_dprintf("openmailer: running as r/euid=%d/%d, r/egid=%d/%d\n", - (int) getuid(), (int) geteuid(), - (int) getgid(), (int) getegid()); + sm_dprintf("openmailer: running as r/euid=%ld/%ld, r/egid=%ld/%ld\n", + (long) getuid(), (long) geteuid(), + (long) getgid(), (long) getegid()); /* move into some "safe" directory */ if (m->m_execdir != NULL) @@ -2964,8 +2968,8 @@ reconnect: /* after switching to an encrypted connection */ QuickAbort = false; SuprErrs = true; if (rscheck("try_tls", host, NULL, e, - RSF_RMCOMM, 7, host, NOQID, NULL) - != EX_OK + RSF_RMCOMM, 7, host, NOQID, NULL, + NULL) != EX_OK || Errors > olderrors) { usetls = false; @@ -3039,7 +3043,7 @@ reconnect: /* after switching to an encrypted connection */ if (rscheck("tls_server", macvalue(macid("{verify}"), e), NULL, e, RSF_RMCOMM|RSF_COUNT, 5, - host, NOQID, NULL) != EX_OK || + host, NOQID, NULL, NULL) != EX_OK || Errors > olderrors || rcode == EX_SOFTWARE) { @@ -3364,7 +3368,7 @@ do_transfer: # if STARTTLS i = rscheck("tls_rcpt", to->q_user, NULL, e, RSF_RMCOMM|RSF_COUNT, 3, - mci->mci_host, e->e_id, NULL); + mci->mci_host, e->e_id, NULL, NULL); if (i != EX_OK) { markfailure(e, to, mci, i, false); @@ -3590,7 +3594,7 @@ do_transfer: if (tobuf[0] != '\0') { - giveresponse(rcode, NULL, m, mci, ctladdr, xstart, e, tochain); + giveresponse(rcode, NULL, m, mci, ctladdr, xstart, e, NULL); #if 0 /* ** This code is disabled for now because I am not @@ -4166,14 +4170,13 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) /* ** Final cleanup. - ** Log a record of the transaction. Compute the new - ** ExitStat -- if we already had an error, stick with - ** that. + ** Log a record of the transaction. Compute the new ExitStat + ** -- if we already had an error, stick with that. */ if (OpMode != MD_VERIFY && !bitset(EF_VRFYONLY, e->e_flags) && LogLevel > ((status == EX_TEMPFAIL) ? 8 : (status == EX_OK) ? 7 : 6)) - logdelivery(m, mci, dsn, statmsg + off, ctladdr, xstart, e); + logdelivery(m, mci, dsn, statmsg + off, ctladdr, xstart, e, to, status); if (tTd(11, 2)) sm_dprintf("giveresponse: status=%d, dsn=%s, e->e_message=%s, errnum=%d\n", @@ -4215,6 +4218,8 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) ** xstart -- the transaction start time, used for ** computing transaction delay. ** e -- the current envelope. +** to -- the current recipient (NULL if none). +** rcode -- status code ** ** Returns: ** none @@ -4224,7 +4229,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) */ void -logdelivery(m, mci, dsn, status, ctladdr, xstart, e) +logdelivery(m, mci, dsn, status, ctladdr, xstart, e, to, rcode) MAILER *m; register MCI *mci; char *dsn; @@ -4232,6 +4237,8 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e) ADDRESS *ctladdr; time_t xstart; register ENVELOPE *e; + ADDRESS *to; + int rcode; { register char *bp; register char *p; @@ -4276,6 +4283,16 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e) bp += strlen(bp); } +# if _FFR_LOG_MORE2 +# if STARTTLS + p = macvalue(macid("{verify}"), e); + if (p == NULL || *p == '\0') + p = "NONE"; + (void) sm_snprintf(bp, SPACELEFT(buf, bp), ", tls_verify=%.20s", p); + bp += strlen(bp); +# endif /* STARTTLS */ +# endif /* _FFR_LOG_MORE2 */ + /* pri: changes with each delivery attempt */ (void) sm_snprintf(bp, SPACELEFT(buf, bp), ", pri=%ld", PRT_NONNEGL(e->e_msgpriority)); @@ -4342,6 +4359,43 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e) # define STATLEN 203 # endif /* (STATLEN) > 203 */ +#if _FFR_LOGREPLY + /* + ** Notes: + ** per-rcpt status: to->q_rstatus + ** global status: e->e_text + ** + ** We (re)use STATLEN here, is that a good choice? + ** + ** stat=Deferred: ... + ** has sometimes the same text? + ** + ** Note: this doesn't show the stage at which the error happened. + ** can/should we log that? + ** XS_* in reply() basically encodes the state. + */ + + /* only show errors */ + if (rcode != EX_OK && to != NULL && to->q_rstatus != NULL && + *to->q_rstatus != '\0') + { + (void) sm_snprintf(bp, SPACELEFT(buf, bp), + ", reply=%s", + shortenstring(to->q_rstatus, STATLEN)); + bp += strlen(bp); + } + else if (rcode != EX_OK && e->e_text != NULL) + { + (void) sm_snprintf(bp, SPACELEFT(buf, bp), + ", reply=%d %s%s%s", + e->e_rcode, + e->e_renhsc, + (e->e_renhsc[0] != '\0') ? " " : "", + shortenstring(e->e_text, STATLEN)); + bp += strlen(bp); + } +#endif + /* stat: max 210 bytes */ if ((bp - buf) > (sizeof(buf) - ((STATLEN) + 20))) { @@ -4368,6 +4422,7 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e) for (q = p + l; q > p; q--) { + /* XXX a comma in an address will break this! */ if (*q == ',') break; } @@ -5327,8 +5382,8 @@ mailfile(filename, mailer, ctladdr, sfflags, e) if (RunAsUid != 0 && RealUid != RunAsUid) { /* Only root can change the uid */ - syserr("mailfile: insufficient privileges to change uid, RunAsUid=%d, RealUid=%d", - (int) RunAsUid, (int) RealUid); + syserr("mailfile: insufficient privileges to change uid, RunAsUid=%ld, RealUid=%ld", + (long) RunAsUid, (long) RealUid); RETURN(EX_TEMPFAIL); } } @@ -5368,9 +5423,9 @@ mailfile(filename, mailer, ctladdr, sfflags, e) RealGid != getegid())) { /* Only root can change the gid */ - syserr("mailfile: insufficient privileges to change gid, RealGid=%d, RunAsUid=%d, gid=%d, egid=%d", - (int) RealGid, (int) RunAsUid, - (int) getgid(), (int) getegid()); + syserr("mailfile: insufficient privileges to change gid, RealGid=%ld, RunAsUid=%ld, gid=%ld, egid=%ld", + (long) RealGid, (long) RunAsUid, + (long) getgid(), (long) getegid()); RETURN(EX_TEMPFAIL); } } @@ -5411,8 +5466,8 @@ mailfile(filename, mailer, ctladdr, sfflags, e) { if (initgroups(RealUserName, RealGid) == -1 && suidwarn) { - syserr("mailfile: initgroups(%s, %d) failed", - RealUserName, RealGid); + syserr("mailfile: initgroups(%s, %ld) failed", + RealUserName, (long) RealGid); RETURN(EX_TEMPFAIL); } } @@ -5474,9 +5529,9 @@ mailfile(filename, mailer, ctladdr, sfflags, e) } if (tTd(11, 2)) - sm_dprintf("mailfile: running as r/euid=%d/%d, r/egid=%d/%d\n", - (int) getuid(), (int) geteuid(), - (int) getgid(), (int) getegid()); + sm_dprintf("mailfile: running as r/euid=%ld/%ld, r/egid=%ld/%ld\n", + (long) getuid(), (long) geteuid(), + (long) getgid(), (long) getegid()); /* move into some "safe" directory */ @@ -6163,11 +6218,18 @@ starttls(m, mci, e) } return EX_SOFTWARE; } + /* SSL_clear(clt_ssl); ? */ + + if (get_tls_se_options(e, clt_ssl, false) != 0) + { + sm_syslog(LOG_ERR, NOQID, + "STARTTLS=client, get_tls_se_options=fail"); + return EX_SOFTWARE; + } rfd = sm_io_getinfo(mci->mci_in, SM_IO_WHAT_FD, NULL); wfd = sm_io_getinfo(mci->mci_out, SM_IO_WHAT_FD, NULL); - /* SSL_clear(clt_ssl); ? */ if (rfd < 0 || wfd < 0 || (result = SSL_set_rfd(clt_ssl, rfd)) != 1 || (result = SSL_set_wfd(clt_ssl, wfd)) != 1) @@ -6189,6 +6251,7 @@ ssl_retry: if ((result = SSL_connect(clt_ssl)) <= 0) { int i, ssl_err; + int save_errno = errno; ssl_err = SSL_get_error(clt_ssl, result); i = tls_retry(clt_ssl, rfd, wfd, tlsstart, @@ -6206,7 +6269,7 @@ ssl_retry: sm_syslog(LOG_WARNING, NOQID, "STARTTLS=client, error: connect failed=%d, reason=%s, SSL_error=%d, errno=%d, retry=%d", result, sr == NULL ? "unknown" : sr, ssl_err, - errno, i); + save_errno, i); if (LogLevel > 9) tlslogerr(LOG_WARNING, "client"); } diff --git a/contrib/sendmail/src/envelope.c b/contrib/sendmail/src/envelope.c index df6c5c7..bae6b00 100644 --- a/contrib/sendmail/src/envelope.c +++ b/contrib/sendmail/src/envelope.c @@ -42,11 +42,9 @@ clrsessenvelope(e) macdefine(&e->e_macro, A_PERM, macid("{cipher}"), ""); macdefine(&e->e_macro, A_PERM, macid("{tls_version}"), ""); macdefine(&e->e_macro, A_PERM, macid("{verify}"), ""); -# if _FFR_TLS_1 macdefine(&e->e_macro, A_PERM, macid("{alg_bits}"), ""); macdefine(&e->e_macro, A_PERM, macid("{cn_issuer}"), ""); macdefine(&e->e_macro, A_PERM, macid("{cn_subject}"), ""); -# endif /* _FFR_TLS_1 */ #endif /* STARTTLS */ } @@ -246,6 +244,16 @@ dropenvelope(e, fulldrop, split) e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; } +#if _FFR_PROXY + if (tTd(87, 2)) + { + q = e->e_sendqueue; + sm_dprintf("dropenvelope: mode=%c, e=%p, sibling=%p, nrcpts=%d, sendqueue=%p, next=%p, state=%d\n", + e->e_sendmode, e, e->e_sibling, e->e_nrcpts, q, + (q == NULL) ? (void *)0 : q->q_next, + (q == NULL) ? -1 : q->q_state); + } +#endif /* _FFR_PROXY */ e->e_flags &= ~EF_QUEUERUN; for (q = e->e_sendqueue; q != NULL; q = q->q_next) @@ -253,6 +261,10 @@ dropenvelope(e, fulldrop, split) if (QS_IS_UNDELIVERED(q->q_state)) queueit = true; +#if _FFR_PROXY + if (queueit && e->e_sendmode == SM_PROXY) + queueit = false; +#endif /* _FFR_PROXY */ /* see if a notification is needed */ if (bitset(QPINGONFAILURE, q->q_flags) && @@ -577,9 +589,9 @@ simpledrop: if (!split_by_recipient(e) && bitset(EF_FATALERRS, e->e_flags)) { - syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d", + syserr("!dropenvelope(%s): cannot commit data file %s, uid=%ld", e->e_id, queuename(e, DATAFL_LETTER), - (int) geteuid()); + (long) geteuid()); } for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling) queueup(ee, false, true); diff --git a/contrib/sendmail/src/err.c b/contrib/sendmail/src/err.c index 835fa4b..0594eb9 100644 --- a/contrib/sendmail/src/err.c +++ b/contrib/sendmail/src/err.c @@ -94,7 +94,7 @@ fatal_error(exc) ** reply code defaults to 451 or 554, depending on errno. ** ** Parameters: -** fmt -- the format string. An optional '!' or '@', +** fmt -- the format string. An optional '!', '@', or '+', ** followed by an optional three-digit SMTP ** reply code, followed by message text. ** (others) -- parameters @@ -127,8 +127,7 @@ syserr(fmt, va_alist) { register char *p; int save_errno = errno; - bool panic; - bool exiting; + bool panic, exiting, keep; char *user; char *enhsc; char *errtxt; @@ -136,21 +135,22 @@ syserr(fmt, va_alist) char ubuf[80]; SM_VA_LOCAL_DECL + panic = exiting = keep = false; switch (*fmt) { case '!': ++fmt; - panic = true; - exiting = true; + panic = exiting = true; break; case '@': ++fmt; - panic = false; exiting = true; break; + case '+': + ++fmt; + keep = true; + break; default: - panic = false; - exiting = false; break; } @@ -182,7 +182,7 @@ syserr(fmt, va_alist) puterrmsg(MsgBuf); /* save this message for mailq printing */ - if (!panic && CurEnv != NULL) + if (!panic && CurEnv != NULL && (!keep || CurEnv->e_message == NULL)) { char *nmsg = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); @@ -479,6 +479,108 @@ message(msg, va_alist) } } +#if _FFR_PROXY +/* +** EMESSAGE -- print message (not necessarily an error) +** (same as message() but requires reply code and enhanced status code) +** +** Parameters: +** replycode -- SMTP reply code. +** enhsc -- enhanced status code. +** msg -- the message (sm_io_printf fmt) -- it can begin with +** an SMTP reply code. If not, 050 is assumed. +** (others) -- sm_io_printf arguments +** +** Returns: +** none +** +** Side Effects: +** none. +*/ + +/*VARARGS3*/ +void +# ifdef __STDC__ +emessage(const char *replycode, const char *enhsc, const char *msg, ...) +# else /* __STDC__ */ +emessage(replycode, enhsc, msg, va_alist) + const char *replycode; + const char *enhsc; + const char *msg; + va_dcl +# endif /* __STDC__ */ +{ + char *errtxt; + SM_VA_LOCAL_DECL + + errno = 0; + SM_VA_START(ap, msg); + errtxt = fmtmsg(MsgBuf, CurEnv->e_to, replycode, enhsc, 0, msg, ap); + SM_VA_END(ap); + putoutmsg(MsgBuf, false, false); + + /* save this message for mailq printing */ + switch (MsgBuf[0]) + { + case '4': + case '8': + if (CurEnv->e_message != NULL) + break; + /* FALLTHROUGH */ + + case '5': + if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) + sm_free(CurEnv->e_message); + CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); + break; + } +} + +/* +** EXTSC -- check and extract a status codes +** +** Parameters: +** msg -- string with possible enhanced status code. +** delim -- delim for enhanced status code. +** replycode -- pointer to storage for SMTP reply code; +** must be != NULL and have space for at least +** 4 characters. +** enhsc -- pointer to storage for enhanced status code; +** must be != NULL and have space for at least +** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3}) +** +** Returns: +** -1 -- no SMTP reply code. +** >=3 -- offset of error text in msg. +** (<=4 -- no enhanced status code) +*/ + +int +extsc(msg, delim, replycode, enhsc) + const char *msg; + int delim; + char *replycode; + char *enhsc; +{ + int offset; + + SM_REQUIRE(replycode != NULL); + SM_REQUIRE(enhsc != NULL); + replycode[0] = '\0'; + enhsc[0] = '\0'; + if (msg == NULL) + return -1; + if (!ISSMTPREPLY(msg)) + return -1; + sm_strlcpy(replycode, msg, 4); + if (msg[3] == '\0') + return 3; + offset = 4; + if (isenhsc(msg + 4, delim)) + offset = extenhsc(msg + 4, delim, enhsc) + 4; + return offset; +} +#endif /* _FFR_PROXY */ /* ** NMESSAGE -- print message (not necessarily an error) @@ -1138,7 +1240,7 @@ sm_errstring(errnum) } #if LDAPMAP - if (errnum >= E_LDAPBASE) + if (errnum >= E_LDAPBASE - E_LDAP_SHIM) return ldap_err2string(errnum - E_LDAPBASE); #endif /* LDAPMAP */ diff --git a/contrib/sendmail/src/headers.c b/contrib/sendmail/src/headers.c index 3c59a40..0af7243 100644 --- a/contrib/sendmail/src/headers.c +++ b/contrib/sendmail/src/headers.c @@ -360,7 +360,7 @@ hse: macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "h"); (void) rscheck(rs, fvalue, NULL, e, rscheckflags, 3, - NULL, e->e_id, NULL); + NULL, e->e_id, NULL, NULL); } } @@ -415,7 +415,7 @@ hse: ** the RCPT mailer. */ - if (bitnset(M_NOMHHACK, + if (bitnset(M_NOMHHACK, e->e_from.q_mailer->m_flags)) { h->h_flags &= ~H_CHECK; @@ -1194,6 +1194,22 @@ logsender(e, msgid) ", daemon=%.20s", p); sbp += strlen(sbp); } +# if _FFR_LOG_MORE1 +# if STARTTLS + p = macvalue(macid("{verify}"), e); + if (p == NULL || *p == '\0') + p = "NONE"; + (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), ", tls_verify=%.20s", p); + sbp += strlen(sbp); +# endif /* STARTTLS */ +# if SASL + p = macvalue(macid("{auth_type}"), e); + if (p == NULL || *p == '\0') + p = "NONE"; + (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), ", auth=%.20s", p); + sbp += strlen(sbp); +# endif /* SASL */ +# endif /* _FFR_LOG_MORE1 */ sm_syslog(LOG_INFO, e->e_id, "%.850s, relay=%s", sbuf, name); #else /* (SYSLOG_BUFSIZE) >= 256 */ @@ -1892,8 +1908,10 @@ putheader(mci, hdr, e, flags) if (bitset(H_FROM, h->h_flags)) oldstyle = false; - commaize(h, p, oldstyle, mci, e, - PXLF_HEADER | PXLF_STRIPMQUOTE); + if (!commaize(h, p, oldstyle, mci, e, + PXLF_HEADER | PXLF_STRIPMQUOTE) + && bitnset(M_xSMTP, mci->mci_mailer->m_flags)) + goto writeerr; } else { @@ -2169,6 +2187,12 @@ commaize(h, p, oldstyle, mci, e, putflags) #endif /* USERDB */ status = EX_OK; name = remotename(name, mci->mci_mailer, flags, &status, e); + if (status != EX_OK && bitnset(M_xSMTP, mci->mci_mailer->m_flags)) + { + if (status == EX_TEMPFAIL) + mci->mci_flags |= MCIF_NOTSTICKY; + goto writeerr; + } if (*name == '\0') { *p = savechar; diff --git a/contrib/sendmail/src/main.c b/contrib/sendmail/src/main.c index 511eb02..38eebbf 100644 --- a/contrib/sendmail/src/main.c +++ b/contrib/sendmail/src/main.c @@ -406,9 +406,7 @@ main(argc, argv, envp) case MD_HOSTSTAT: case MD_PURGESTAT: case MD_ARPAFTP: -#if _FFR_CHECKCONFIG case MD_CHECKCONFIG: -#endif /* _FFR_CHECKCONFIG */ OpMode = j; break; @@ -645,6 +643,17 @@ main(argc, argv, envp) sm_printoptions(FFRCompileOptions); } +#if STARTTLS + if (tTd(0, 14)) + { + /* exit(EX_CONFIG) if different? */ + sm_dprintf(" OpenSSL: compiled 0x%08x\n", + (uint) OPENSSL_VERSION_NUMBER); + sm_dprintf(" OpenSSL: linked 0x%08x\n", + (uint) SSLeay()); + } +#endif /* STARTTLS */ + /* clear sendmail's environment */ ExternalEnviron = environ; emptyenviron[0] = NULL; @@ -2566,6 +2575,38 @@ main(argc, argv, envp) ** Set _ macro in BlankEnvelope before calling newenvelope(). */ +#if _FFR_XCNCT + if (bitnset(D_XCNCT, *p_flags) || bitnset(D_XCNCT_M, *p_flags)) + { + /* copied from getauthinfo() */ + if (RealHostName == NULL) + { + RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); + if (strlen(RealHostName) > MAXNAME) + RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */ + } + snprintf(buf, sizeof(buf), "%s [%s]", + RealHostName, anynet_ntoa(&RealHostAddr)); + + forged = bitnset(D_XCNCT_M, *p_flags); + if (forged) + { + (void) sm_strlcat(buf, " (may be forged)", + sizeof(buf)); + macdefine(&BlankEnvelope.e_macro, A_PERM, + macid("{client_resolve}"), "FORGED"); + } + + /* HACK! variable used only two times right below */ + authinfo = buf; + if (tTd(75, 9)) + sm_syslog(LOG_INFO, NOQID, + "main: where=not_calling_getauthinfo, RealHostAddr=%s", + anynet_ntoa(&RealHostAddr)); + } + else + /* WARNING: "non-braced" else */ +#endif /* _FFR_XCNCT */ authinfo = getauthinfo(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL), &forged); macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo); @@ -2622,13 +2663,13 @@ main(argc, argv, envp) #if NETINET case AF_INET: (void) sm_snprintf(pbuf, sizeof(pbuf), "%d", - RealHostAddr.sin.sin_port); + ntohs(RealHostAddr.sin.sin_port)); break; #endif /* NETINET */ #if NETINET6 case AF_INET6: (void) sm_snprintf(pbuf, sizeof(pbuf), "%d", - RealHostAddr.sin6.sin6_port); + ntohs(RealHostAddr.sin6.sin6_port)); break; #endif /* NETINET6 */ default: @@ -3696,12 +3737,12 @@ drop_privileges(to_real_uid) GIDSET_T emptygidset[1]; if (tTd(47, 1)) - sm_dprintf("drop_privileges(%d): Real[UG]id=%d:%d, get[ug]id=%d:%d, gete[ug]id=%d:%d, RunAs[UG]id=%d:%d\n", + sm_dprintf("drop_privileges(%d): Real[UG]id=%ld:%ld, get[ug]id=%ld:%ld, gete[ug]id=%ld:%ld, RunAs[UG]id=%ld:%ld\n", (int) to_real_uid, - (int) RealUid, (int) RealGid, - (int) getuid(), (int) getgid(), - (int) geteuid(), (int) getegid(), - (int) RunAsUid, (int) RunAsGid); + (long) RealUid, (long) RealGid, + (long) getuid(), (long) getgid(), + (long) geteuid(), (long) getegid(), + (long) RunAsUid, (long) RunAsGid); if (to_real_uid) { @@ -3776,15 +3817,15 @@ drop_privileges(to_real_uid) { if (setgid(RunAsGid) < 0 && (!UseMSP || getegid() != RunAsGid)) { - syserr("drop_privileges: setgid(%d) failed", - (int) RunAsGid); + syserr("drop_privileges: setgid(%ld) failed", + (long) RunAsGid); rval = EX_OSERR; } errno = 0; if (rval == EX_OK && getegid() != RunAsGid) { - syserr("drop_privileges: Unable to set effective gid=%d to RunAsGid=%d", - (int) getegid(), (int) RunAsGid); + syserr("drop_privileges: Unable to set effective gid=%ld to RunAsGid=%ld", + (long) getegid(), (long) RunAsGid); rval = EX_OSERR; } } diff --git a/contrib/sendmail/src/map.c b/contrib/sendmail/src/map.c index b79f591..2cc283e 100644 --- a/contrib/sendmail/src/map.c +++ b/contrib/sendmail/src/map.c @@ -204,6 +204,20 @@ map_parseargs(map, ap) map->map_app = ++p; break; + case 'd': + { + char *h; + + ++p; + h = strchr(p, ' '); + if (h != NULL) + *h = '\0'; + map->map_timeout = convtime(p, 's'); + if (h != NULL) + *h = ' '; + } + break; + case 'T': map->map_tapp = ++p; break; @@ -1826,7 +1840,7 @@ ndbm_map_store(map, lhs, rhs) data.dptr = buf; if (tTd(38, 9)) sm_dprintf("ndbm_map_store append=%s\n", - data.dptr); + (char *)data.dptr); } } status = dbm_store((DBM *) map->map_db1, @@ -7366,7 +7380,6 @@ arith_map_lookup(map, name, av, statp) return NULL; } -#if _FFR_ARPA_MAP char * arpa_map_lookup(map, name, av, statp) MAP *map; @@ -7419,7 +7432,7 @@ arpa_map_lookup(map, name, av, statp) { struct in_addr in_addr; - r = anynet_pton(AF_INET, name, &in_addr); + r = inet_pton(AF_INET, name, &in_addr); if (r == 1) { unsigned char *src; @@ -7445,7 +7458,6 @@ arpa_map_lookup(map, name, av, statp) } return rval; } -#endif /* _FFR_ARPA_MAP */ #if SOCKETMAP @@ -7466,6 +7478,7 @@ socket_map_open(map, mode) { STAB *s; int sock = 0; + int tmo; SOCKADDR_LEN_T addrlen = 0; int addrno = 0; int save_errno; @@ -7865,6 +7878,13 @@ socket_map_open(map, mode) return false; } + tmo = map->map_timeout; + if (tmo == 0) + tmo = 30000; /* default: 30s */ + else + tmo *= 1000; /* s -> ms */ + sm_io_setinfo(map->map_db1, SM_IO_WHAT_TIMEOUT, &tmo); + /* Save connection for reuse */ s->s_socketmap = map; return true; @@ -7999,8 +8019,16 @@ socket_map_lookup(map, name, av, statp) if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1) { - syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply", - map->map_mname); + if (errno == EAGAIN) + { + syserr("451 4.3.0 socket_map_lookup(%s): read timeout", + map->map_mname); + } + else + { + syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply %d", + map->map_mname, errno); + } *statp = EX_TEMPFAIL; goto errcl; } diff --git a/contrib/sendmail/src/mci.c b/contrib/sendmail/src/mci.c index 773eb16..c3f925f 100644 --- a/contrib/sendmail/src/mci.c +++ b/contrib/sendmail/src/mci.c @@ -352,6 +352,7 @@ mci_get(host, m) #if PIPELINING mci->mci_okrcpts = 0; #endif /* PIPELINING */ + mci->mci_flags &= ~MCIF_NOTSTICKY; if (mci->mci_rpool == NULL) mci->mci_rpool = sm_rpool_new_x(NULL); diff --git a/contrib/sendmail/src/milter.c b/contrib/sendmail/src/milter.c index cbc4d35..9b3667d 100644 --- a/contrib/sendmail/src/milter.c +++ b/contrib/sendmail/src/milter.c @@ -204,7 +204,7 @@ static size_t MilterMaxDataSize = MILTER_MAX_DATA_SIZE; fd_set fds; \ struct timeval tv; \ \ - if (SM_FD_SETSIZE > 0 && m->mf_sock >= SM_FD_SETSIZE) \ + if (!SM_FD_OK_SELECT(m->mf_sock)) \ { \ if (tTd(64, 5)) \ sm_dprintf("milter_%s(%s): socket %d is larger than FD_SETSIZE %d\n", \ @@ -1642,8 +1642,8 @@ milter_set_option(name, val, sticky) MilterMaxDataSize != MILTER_MDS_1M) { sm_syslog(LOG_WARNING, NOQID, - "WARNING: Milter.%s=%d, allowed are only %d, %d, and %d", - name, MilterMaxDataSize, + "WARNING: Milter.%s=%lu, allowed are only %d, %d, and %d", + name, (unsigned long) MilterMaxDataSize, MILTER_MDS_64K, MILTER_MDS_256K, MILTER_MDS_1M); if (MilterMaxDataSize < MILTER_MDS_64K) @@ -2317,6 +2317,8 @@ milter_getsymlist(m, buf, rlen, offset) offset += MILTER_LEN_BYTES; macros = NULL; +#define SM_M_MACRO_NAME(i) (((i) < SM_ARRAY_SIZE(MilterOptTab) && (i) >= 0) \ + ? MilterOptTab[i].mo_name : "?") switch (i) { case SMFIM_CONNECT: @@ -2330,23 +2332,23 @@ milter_getsymlist(m, buf, rlen, offset) macros = MilterMacros[i][m->mf_idx]; m->mf_lflags |= MI_LFLAGS_SYM(i); len = strlen(buf + offset); - if (len > 0) + if (len >= 0) { r = milter_set_macros(m->mf_name, macros, buf + offset, nummac); if (r >= 0) nummac = r; if (tTd(64, 5)) - sm_dprintf("milter_getsymlist(%s, %s)=%d\n", - m->mf_name, buf + offset, r); + sm_dprintf("milter_getsymlist(%s, %s, \"%s\")=%d\n", + m->mf_name, + SM_M_MACRO_NAME(i), + buf + offset, r); } break; default: return -1; } - if (len == 0) - return -1; offset += len + 1; } @@ -2421,7 +2423,9 @@ milter_negotiate(m, e, milters) if (tTd(64, 5)) sm_dprintf("milter_negotiate(%s): send: version %lu, fflags 0x%lx, pflags 0x%lx\n", - m->mf_name, ntohl(fvers), ntohl(fflags), ntohl(pflags)); + m->mf_name, (unsigned long) ntohl(fvers), + (unsigned long) ntohl(fflags), + (unsigned long) ntohl(pflags)); response = milter_read(m, &rcmd, &rlen, m->mf_timeout[SMFTO_READ], e, "negotiate"); @@ -2526,8 +2530,9 @@ milter_negotiate(m, e, milters) { /* this should not happen... */ sm_syslog(LOG_WARNING, NOQID, - "WARNING: Milter.maxdatasize: configured=%d, set by libmilter=%d", - MilterMaxDataSize, MILTER_MDS_1M); + "WARNING: Milter.maxdatasize: configured=%lu, set by libmilter=%d", + (unsigned long) MilterMaxDataSize, + MILTER_MDS_1M); MilterMaxDataSize = MILTER_MDS_1M; } } @@ -2536,16 +2541,18 @@ milter_negotiate(m, e, milters) if (MilterMaxDataSize != MILTER_MDS_256K) { sm_syslog(LOG_WARNING, NOQID, - "WARNING: Milter.maxdatasize: configured=%d, set by libmilter=%d", - MilterMaxDataSize, MILTER_MDS_256K); + "WARNING: Milter.maxdatasize: configured=%lu, set by libmilter=%d", + (unsigned long) MilterMaxDataSize, + MILTER_MDS_256K); MilterMaxDataSize = MILTER_MDS_256K; } } else if (MilterMaxDataSize != MILTER_MDS_64K) { sm_syslog(LOG_WARNING, NOQID, - "WARNING: Milter.maxdatasize: configured=%d, set by libmilter=%d", - MilterMaxDataSize, MILTER_MDS_64K); + "WARNING: Milter.maxdatasize: configured=%lu, set by libmilter=%d", + (unsigned long) MilterMaxDataSize, + MILTER_MDS_64K); MilterMaxDataSize = MILTER_MDS_64K; } m->mf_pflags &= ~SMFI_INTERNAL; @@ -3976,6 +3983,7 @@ milter_connect(hostname, addr, e, state) else milter_per_connection_check(e); +#if !_FFR_MILTER_CONNECT_REPLYCODE /* ** SMFIR_REPLYCODE can't work with connect due to ** the requirements of SMTP. Therefore, ignore the @@ -4000,6 +4008,7 @@ milter_connect(hostname, addr, e, state) response = NULL; } } +#endif /* !_FFR_MILTER_CONNECT_REPLYCODE */ return response; } diff --git a/contrib/sendmail/src/parseaddr.c b/contrib/sendmail/src/parseaddr.c index 4c78720..2adb39c 100644 --- a/contrib/sendmail/src/parseaddr.c +++ b/contrib/sendmail/src/parseaddr.c @@ -2204,8 +2204,9 @@ badaddr: ** use entire pvp. ** buf -- buffer to build the string into. ** sz -- size of buf. -** spacesub -- the space separator character; if '\0', -** use SpaceSub. +** spacesub -- the space separator character; +** '\0': SpaceSub. +** NOSPACESEP: no separator ** external -- convert to external form? ** (no metacharacters; METAQUOTEs removed, see below) ** @@ -2268,7 +2269,7 @@ cataddr(pvp, evp, buf, sz, spacesub, external) char *q; natomtok = (IntTokenTab[**pvp & 0xff] == ATM); - if (oatomtok && natomtok) + if (oatomtok && natomtok && spacesub != NOSPACESEP) { *p++ = spacesub; if (--sz <= 0) @@ -2362,6 +2363,10 @@ sameaddr(a, b) if (strcmp(a->q_user, b->q_user) != 0) return false; + /* do the required flags match? */ + if (!ADDR_FLAGS_MATCH(a, b)) + return false; + /* if we have good uids for both but they differ, these are different */ if (a->q_mailer == ProgMailer) { @@ -2409,6 +2414,7 @@ struct qflags unsigned long qf_bit; }; +/* :'a,.s;^#define \(Q[A-Z]*\) .*; { "\1", \1 },; */ static struct qflags AddressFlags[] = { { "QGOODUID", QGOODUID }, @@ -2426,6 +2432,12 @@ static struct qflags AddressFlags[] = { "QDELIVERED", QDELIVERED }, { "QDELAYED", QDELAYED }, { "QTHISPASS", QTHISPASS }, + { "QALIAS", QALIAS }, + { "QBYTRACE", QBYTRACE }, + { "QBYNDELAY", QBYNDELAY }, + { "QBYNRELAY", QBYNRELAY }, + { "QINTBCC", QINTBCC }, + { "QDYNMAILER", QDYNMAILER }, { "QRCPTOK", QRCPTOK }, { NULL, 0 } }; @@ -2789,7 +2801,7 @@ remotename(name, m, flags, pstat, e) { sm_dprintf("remotename => `"); xputs(sm_debug_file(), buf); - sm_dprintf("'\n"); + sm_dprintf("', stat=%d\n", *pstat); } return buf; } @@ -3060,6 +3072,8 @@ dequote_map(map, name, av, statp) ** logid -- id for sm_syslog. ** addr -- if not NULL and ruleset returns $#error: ** store mailer triple here. +** addrstr -- if not NULL and ruleset does not return $#: +** address string ** ** Returns: ** EX_OK -- if the rwset doesn't resolve to $#error @@ -3067,7 +3081,7 @@ dequote_map(map, name, av, statp) */ int -rscheck(rwset, p1, p2, e, flags, logl, host, logid, addr) +rscheck(rwset, p1, p2, e, flags, logl, host, logid, addr, addrstr) char *rwset; char *p1; char *p2; @@ -3077,6 +3091,7 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid, addr) char *host; char *logid; ADDRESS *addr; + char **addrstr; { char *volatile buf; size_t bufsize; @@ -3150,6 +3165,17 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid, addr) (void) REWRITE(pvp, rsno, e); if (bitset(RSF_UNSTRUCTURED, flags)) SuprErrs = saveSuprErrs; + + if (pvp[0] != NULL && (pvp[0][0] & 0377) != CANONNET && + bitset(RSF_ADDR, flags) && addrstr != NULL) + { + cataddr(&(pvp[0]), NULL, ubuf, sizeof(ubuf), + bitset(RSF_STRING, flags) ? NOSPACESEP : ' ', + true); + *addrstr = sm_rpool_strdup_x(e->e_rpool, ubuf); + goto finis; + } + if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET || pvp[1] == NULL || (strcmp(pvp[1], "error") != 0 && strcmp(pvp[1], "discard") != 0)) diff --git a/contrib/sendmail/src/queue.c b/contrib/sendmail/src/queue.c index db339f2..a323301 100644 --- a/contrib/sendmail/src/queue.c +++ b/contrib/sendmail/src/queue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2009, 2011, 2012 Proofpoint, Inc. and its suppliers. + * Copyright (c) 1998-2009, 2011, 2012, 2014 Proofpoint, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -125,13 +125,6 @@ static SM_DEBUG_T DebugLeakQ = SM_DEBUG_INITIALIZER("leak_q", "@(#)$Debug: leak_q - trace memory leaks during queue processing $"); #endif /* SM_HEAP_CHECK */ -/* -** We use EmptyString instead of "" to avoid -** 'zero-length format string' warnings from gcc -*/ - -static const char EmptyString[] = ""; - static void grow_wlist __P((int, int)); static int multiqueue_cache __P((char *, int, QUEUEGRP *, int, unsigned int *)); static int gatherq __P((int, int, bool, bool *, bool *, int *)); @@ -304,7 +297,7 @@ hash_q(p, h) ** d data file directory name (added in 8.12) ** E error recipient ** F flag bits -** G free (was: queue delay algorithm if _FFR_QUEUEDELAY) +** G free ** H header ** I data file's inode number ** K time of last delivery attempt @@ -320,7 +313,7 @@ hash_q(p, h) ** T init time ** V queue file version ** X free (was: character set if _FFR_SAVE_CHARSET) -** Y free (was: current delay if _FFR_QUEUEDELAY) +** Y free ** Z original envelope id from ESMTP ** ! deliver by (added in 8.12) ** $ define macro @@ -404,8 +397,8 @@ queueup(e, announce, msync) printopenfds(true); errno = save_errno; - syserr("!queueup: cannot create queue file %s, euid=%d, fd=%d, fp=%p", - tf, (int) geteuid(), tfd, tfp); + syserr("!queueup: cannot create queue file %s, euid=%ld, fd=%d, fp=%p", + tf, (long) geteuid(), tfd, tfp); /* NOTREACHED */ } e->e_lockfp = tfp; @@ -427,8 +420,8 @@ queueup(e, announce, msync) break; if (LogLevel > 0 && (i % 32) == 0) sm_syslog(LOG_ALERT, e->e_id, - "queueup: cannot create %s, euid=%d: %s", - tf, (int) geteuid(), + "queueup: cannot create %s, euid=%ld: %s", + tf, (long) geteuid(), sm_errstring(errno)); } #if SM_OPEN_EXLOCK @@ -473,8 +466,8 @@ queueup(e, announce, msync) printopenfds(true); errno = save_errno; - syserr("!queueup: cannot create queue temp file %s, uid=%d", - tf, (int) geteuid()); + syserr("!queueup: cannot create queue temp file %s, uid=%ld", + tf, (long) geteuid()); } } @@ -518,8 +511,8 @@ queueup(e, announce, msync) sm_io_setinfo(e->e_dfp, SM_BF_COMMIT, NULL) < 0 && errno != EINVAL) { - syserr("!queueup: cannot commit data file %s, uid=%d", - queuename(e, DATAFL_LETTER), (int) geteuid()); + syserr("!queueup: cannot commit data file %s, uid=%ld", + queuename(e, DATAFL_LETTER), (long) geteuid()); } if (e->e_dfp != NULL && SuperSafe == SAFE_INTERACTIVE && msync) @@ -560,8 +553,8 @@ queueup(e, announce, msync) if (dfd < 0 || (dfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, (void *) &dfd, SM_IO_WRONLY_B, NULL)) == NULL) - syserr("!queueup: cannot create data temp file %s, uid=%d", - df, (int) geteuid()); + syserr("!queueup: cannot create data temp file %s, uid=%ld", + df, (long) geteuid()); if (fstat(dfd, &stbuf) < 0) e->e_dfino = -1; else @@ -595,8 +588,8 @@ queueup(e, announce, msync) } if (sm_io_close(dfp, SM_TIME_DEFAULT) < 0) - syserr("!queueup: cannot save data temp file %s, uid=%d", - df, (int) geteuid()); + syserr("!queueup: cannot save data temp file %s, uid=%ld", + df, (long) geteuid()); e->e_putbody = putbody; } @@ -733,9 +726,15 @@ queueup(e, announce, msync) (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'F'); if (bitset(QPINGONDELAY, q->q_flags)) (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'D'); + if (bitset(QINTBCC, q->q_flags)) + (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'B'); if (q->q_alias != NULL && bitset(QALIAS, q->q_alias->q_flags)) (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'A'); + + /* _FFR_RCPTFLAGS */ + if (bitset(QDYNMAILER, q->q_flags)) + (void) sm_io_putc(tfp, SM_TIME_DEFAULT, QDYNMAILFLG); (void) sm_io_putc(tfp, SM_TIME_DEFAULT, ':'); (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s\n", denlstring(q->q_paddr, true, false)); @@ -747,10 +746,10 @@ queueup(e, announce, msync) tag = "quarantined"; e->e_to = q->q_paddr; - message(tag); + message("%s", tag); if (LogLevel > 8) logdelivery(q->q_mailer, NULL, q->q_status, - tag, NULL, (time_t) 0, e); + tag, NULL, (time_t) 0, e, q, EX_OK); e->e_to = NULL; } if (tTd(40, 1)) @@ -888,8 +887,8 @@ queueup(e, announce, msync) (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER), sizeof(qf)); if (rename(tf, qf) < 0) - syserr("cannot rename(%s, %s), uid=%d", - tf, qf, (int) geteuid()); + syserr("cannot rename(%s, %s), uid=%ld", + tf, qf, (long) geteuid()); else { /* @@ -1785,7 +1784,7 @@ runner_work(e, sequenceno, didfork, skip, njobs) if (shouldqueue(w->w_pri, w->w_ctime)) { if (Verbose) - message(EmptyString); + message("%s", ""); if (QueueSortOrder == QSO_BYPRIORITY) { if (Verbose) @@ -1813,7 +1812,7 @@ runner_work(e, sequenceno, didfork, skip, njobs) { if (Verbose) { - message(EmptyString); + message("%s", ""); message("Running %s/%s (sequence %d of %d)", qid_printqueue(w->w_qgrp, w->w_qdir), w->w_name + 2, sequenceno, njobs); @@ -2042,9 +2041,7 @@ run_work_group(wgrp, flags) { IgnoreHostStatus = true; MinQueueAge = 0; -#if _FFR_EXPDELAY MaxQueueAge = 0; -#endif /* _FFR_EXPDELAY */ } /* @@ -2871,7 +2868,6 @@ gatherq(qgrp, qdir, doall, full, more, pnentries) break; case 'K': -#if _FFR_EXPDELAY if (MaxQueueAge > 0) { time_t lasttry, delay; @@ -2884,7 +2880,6 @@ gatherq(qgrp, qdir, doall, full, more, pnentries) w->w_tooyoung = true; break; } -#endif /* _FFR_EXPDELAY */ age = curtime() - (time_t) atol(&lbuf[1]); if (age >= 0 && MinQueueAge > 0 && @@ -4096,8 +4091,9 @@ readqf(e, openonly) if (LogLevel > 0) { sm_syslog(LOG_ALERT, e->e_id, - "bogus queue file, uid=%d, gid=%d, mode=%o", - st.st_uid, st.st_gid, st.st_mode); + "bogus queue file, uid=%ld, gid=%ld, mode=%o", + (long) st.st_uid, (long) st.st_gid, + (unsigned int) st.st_mode); } if (tTd(40, 8)) sm_dprintf("readqf(%s): bogus file\n", qf); @@ -4418,6 +4414,14 @@ readqf(e, openonly) ctladdr->q_flags |= QALIAS; break; + case 'B': + qflags |= QINTBCC; + break; + + case QDYNMAILFLG: + qflags |= QDYNMAILER; + break; + default: /* ignore or complain? */ break; } @@ -4426,7 +4430,7 @@ readqf(e, openonly) else qflags |= QPRIMARY; macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), - "e r"); + ((qflags & QINTBCC) != 0) ? "e b" : "e r"); if (*p != '\0') q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e, true); @@ -4443,6 +4447,10 @@ readqf(e, openonly) q->q_flags |= qflags; q->q_finalrcpt = frcpt; q->q_orcpt = orcpt; +#if _FFR_RCPTFLAGS + if (bitset(QDYNMAILER, qflags)) + newmodmailer(q, QDYNMAILFLG); +#endif (void) recipient(q, &e->e_sendqueue, 0, e); } frcpt = NULL; @@ -4500,24 +4508,6 @@ readqf(e, openonly) nomore = true; break; -#if _FFR_QUEUEDELAY - case 'G': - case 'Y': - - /* - ** Maintain backward compatibility for - ** users who defined _FFR_QUEUEDELAY in - ** previous releases. Remove this - ** code in 8.14 or 8.15. - */ - - if (qfver == 5 || qfver == 7) - break; - - /* If not qfver 5 or 7, then 'G' or 'Y' is invalid */ - /* FALLTHROUGH */ -#endif /* _FFR_QUEUEDELAY */ - default: syserr("readqf: %s: line %d: bad line \"%s\"", qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); @@ -4635,6 +4625,14 @@ readqf(e, openonly) static void prtstr __P((char *, int)); +#if _FFR_BOUNCE_QUEUE +# define SKIP_BOUNCE_QUEUE \ + if (i == BounceQueue) \ + continue; +#else +# define SKIP_BOUNCE_QUEUE +#endif + static void prtstr(s, ml) char *s; @@ -4698,6 +4696,7 @@ printnqe(out, prefix) { int j; + SKIP_BOUNCE_QUEUE k++; for (j = 0; j < Queue[i]->qg_numqueues; j++) { @@ -5643,8 +5642,8 @@ loseqfile(e, why) { p = queuename(e, LOSEQF_LETTER); if (rename(buf, p) < 0) - syserr("cannot rename(%s, %s), uid=%d", - buf, p, (int) geteuid()); + syserr("cannot rename(%s, %s), uid=%ld", + buf, p, (long) geteuid()); else if (LogLevel > 0) sm_syslog(LOG_ALERT, e->e_id, "Losing %s: %s", buf, why); @@ -6656,8 +6655,8 @@ init_sem(owner) r = sm_semsetowner(SemId, RunAsUid, RunAsGid, 0660); if (r != 0) sm_syslog(LOG_ERR, NOQID, - "key=%ld, sm_semsetowner=%d, RunAsUid=%d, RunAsGid=%d", - (long) SemKey, r, RunAsUid, RunAsGid); + "key=%ld, sm_semsetowner=%d, RunAsUid=%ld, RunAsGid=%ld", + (long) SemKey, r, (long) RunAsUid, (long) RunAsGid); } #endif /* SM_CONF_SEM */ #endif /* _FFR_USE_SEM_LOCKING */ @@ -6734,11 +6733,12 @@ upd_qs(e, count, space, where) if (QSHM_ENTRIES(idx) >= 0 && count != 0) { # if _FFR_USE_SEM_LOCKING - r = sm_sem_acq(SemId, 0, 1); + if (SemId >= 0) + r = sm_sem_acq(SemId, 0, 1); # endif /* _FFR_USE_SEM_LOCKING */ QSHM_ENTRIES(idx) += count; # if _FFR_USE_SEM_LOCKING - if (r >= 0) + if (SemId >= 0 && r >= 0) r = sm_sem_rel(SemId, 0, 1); # endif /* _FFR_USE_SEM_LOCKING */ } @@ -6815,8 +6815,8 @@ write_key_file(keypath, key) int err = errno; sm_syslog(LOG_ALERT, NOQID, - "ownership change on %s to %d failed: %s", - keypath, RunAsUid, sm_errstring(err)); + "ownership change on %s to %ld failed: %s", + keypath, (long) RunAsUid, sm_errstring(err)); } # endif /* HASFCHOWN */ } @@ -6966,8 +6966,8 @@ init_shm(qn, owner, hash) i = sm_shmsetowner(ShmId, RunAsUid, RunAsGid, 0660); if (i != 0) sm_syslog(LOG_ERR, NOQID, - "key=%ld, sm_shmsetowner=%d, RunAsUid=%d, RunAsGid=%d", - (long) ShmKey, i, RunAsUid, RunAsGid); + "key=%ld, sm_shmsetowner=%d, RunAsUid=%ld, RunAsGid=%ld", + (long) ShmKey, i, (long) RunAsUid, (long) RunAsGid); } p = (int *) Pshm; if (owner) @@ -7155,19 +7155,19 @@ setup_queues(owner) safefile(" ", RunAsUid, RunAsGid, RunAsUserName, sff, QueueFileMode, NULL) != 0) { - syserr("can not write to queue directory %s (RunAsGid=%d, required=%d)", - basedir, (int) RunAsGid, (int) st.st_gid); + syserr("can not write to queue directory %s (RunAsGid=%ld, required=%ld)", + basedir, (long) RunAsGid, (long) st.st_gid); } if (bitset(S_IWOTH|S_IXOTH, st.st_mode)) { #if _FFR_MSP_PARANOIA syserr("dangerous permissions=%o on queue directory %s", - (int) st.st_mode, basedir); + (unsigned int) st.st_mode, basedir); #else /* _FFR_MSP_PARANOIA */ if (LogLevel > 0) sm_syslog(LOG_ERR, NOQID, "dangerous permissions=%o on queue directory %s", - (int) st.st_mode, basedir); + (unsigned int) st.st_mode, basedir); #endif /* _FFR_MSP_PARANOIA */ } #if _FFR_MSP_PARANOIA @@ -7619,7 +7619,7 @@ cmpidx(a, b) } /* -** MAKEWORKGROUP -- balance queue groups into work groups per MaxQueueChildren +** MAKEWORKGROUPS -- balance queue groups into work groups per MaxQueueChildren ** ** Take the now defined queue groups and assign them to work groups. ** This is done to balance out the number of concurrently active @@ -7691,6 +7691,7 @@ makeworkgroups() NumWorkGroups = 0; for (i = 0; i < NumQueue; i++) { + SKIP_BOUNCE_QUEUE total_runners += si[i].sg_maxqrun; if (MaxQueueChildren <= 0 || total_runners <= MaxQueueChildren) NumWorkGroups++; @@ -7716,6 +7717,8 @@ makeworkgroups() dir = 1; for (i = 0; i < NumQueue; i++) { + SKIP_BOUNCE_QUEUE + /* a to-and-fro packing scheme, continue from last position */ if (j >= NumWorkGroups) { diff --git a/contrib/sendmail/src/readcf.c b/contrib/sendmail/src/readcf.c index fc3bb90..2b0fbf7 100644 --- a/contrib/sendmail/src/readcf.c +++ b/contrib/sendmail/src/readcf.c @@ -33,6 +33,51 @@ static void toomany __P((int, int)); static char *extrquotstr __P((char *, char **, char *, bool *)); static void parse_class_words __P((int, char *)); + +#if _FFR_BOUNCE_QUEUE +static char *bouncequeue = NULL; +static void initbouncequeue __P((void)); + +/* +** INITBOUNCEQUEUE -- determine BounceQueue if option is set. +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** sets BounceQueue +*/ + +static void +initbouncequeue() +{ + STAB *s; + + BounceQueue = NOQGRP; + if (bouncequeue == NULL || bouncequeue[0] == '\0') + return; + + s = stab(bouncequeue, ST_QUEUE, ST_FIND); + if (s == NULL) + { + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "Warning: option BounceQueue: unknown queue group %s\n", + bouncequeue); + } + else + BounceQueue = s->s_quegrp->qg_index; +} +#endif /* _FFR_BOUNCE_QUEUE */ + +#if _FFR_RCPTFLAGS +void setupdynmailers __P((void)); +#else +#define setupdynmailers() +#endif + /* ** READCF -- read configuration file. ** @@ -117,12 +162,12 @@ readcf(cfname, safe, e) #if STARTTLS Srv_SSL_Options = SSL_OP_ALL; Clt_SSL_Options = SSL_OP_ALL -#ifdef SSL_OP_NO_SSLv2 +# ifdef SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv2 -#endif -#ifdef SSL_OP_NO_TICKET +# endif +# ifdef SSL_OP_NO_TICKET | SSL_OP_NO_TICKET -#endif +# endif ; # ifdef SSL_OP_TLSEXT_PADDING /* SSL_OP_TLSEXT_PADDING breaks compatibility with some sites */ @@ -730,6 +775,10 @@ readcf(cfname, safe, e) (void) sm_io_close(cf, SM_TIME_DEFAULT); FileName = NULL; +#if _FFR_BOUNCE_QUEUE + initbouncequeue(); +#endif + /* initialize host maps from local service tables */ inithostmaps(); @@ -756,6 +805,7 @@ readcf(cfname, safe, e) } } } + setupdynmailers(); } /* @@ -1175,6 +1225,125 @@ fileclass(class, filename, fmt, ismap, safe, optional) if (pid > 0) (void) waitfor(pid); } + +#if _FFR_RCPTFLAGS +/* first character for dynamically created mailers */ +static char dynmailerp = ' '; + +/* list of first characters for cf defined mailers */ +static char frst[MAXMAILERS + 1]; + +/* +** SETUPDYNMAILERS -- find a char that isn't used as first element of any +** mailer name. +** +** Parameters: +** none +** +** Returns: +** none +** +** Note: space is not valid in cf defined mailers hence the function +** will always find a char. It's not nice, but this is for +** internal names only. +*/ + +void +setupdynmailers() +{ + int i; + char pp[] = "YXZ0123456789ABCDEFGHIJKLMNOPQRSTUVWyxzabcfghijkmnoqtuvw "; + + frst[MAXMAILERS] = '\0'; + for (i = 0; i < strlen(pp); i++) + { + if (strchr(frst, pp[i]) == NULL) + { + dynmailerp = pp[i]; + if (tTd(25, 8)) + sm_dprintf("dynmailerp=%c\n", dynmailerp); + return; + } + } + + /* NOTREACHED */ + SM_ASSERT(0); +} + +/* +** NEWMODMAILER -- Create a new mailer with modifications +** +** Parameters: +** rcpt -- current RCPT +** fl -- flag to set +** +** Returns: +** true iff successful. +** +** Note: this creates a copy of the mailer for the rcpt and +** modifies exactly one flag. It does not work +** for multiple flags! +*/ + +bool +newmodmailer(rcpt, fl) + ADDRESS *rcpt; + int fl; +{ + int idx; + struct mailer *m; + STAB *s; + char mname[256]; + + SM_REQUIRE(rcpt != NULL); + if (rcpt->q_mailer == NULL) + return false; + if (tTd(25, 8)) + sm_dprintf("newmodmailer: rcpt=%s\n", rcpt->q_paddr); + SM_REQUIRE(rcpt->q_mailer->m_name != NULL); + SM_REQUIRE(rcpt->q_mailer->m_name[0] != '\0'); + sm_strlcpy(mname, rcpt->q_mailer->m_name, sizeof(mname)); + mname[0] = dynmailerp; + if (tTd(25, 8)) + sm_dprintf("newmodmailer: name=%s\n", mname); + s = stab(mname, ST_MAILER, ST_ENTER); + if (s->s_mailer != NULL) + { + idx = s->s_mailer->m_mno; + if (tTd(25, 6)) + sm_dprintf("newmodmailer: found idx=%d\n", idx); + } + else + { + idx = rcpt->q_mailer->m_mno; + idx += MAXMAILERS; + if (tTd(25, 6)) + sm_dprintf("newmodmailer: idx=%d\n", idx); + if (idx > SM_ARRAY_SIZE(Mailer)) + return false; + } + + m = Mailer[idx]; + if (m == NULL) + m = (struct mailer *) xalloc(sizeof(*m)); + memset((char *) m, '\0', sizeof(*m)); + STRUCTCOPY(*rcpt->q_mailer, *m); + Mailer[idx] = m; + + /* "modify" the mailer */ + setbitn(bitidx(fl), m->m_flags); + rcpt->q_mailer = m; + m->m_mno = idx; + m->m_name = newstr(mname); + if (tTd(25, 1)) + sm_dprintf("newmodmailer: mailer[%d]=%s %p\n", + idx, Mailer[idx]->m_name, Mailer[idx]); + + return true; +} + +#endif /* _FFR_RCPTFLAGS */ + /* ** MAKEMAILER -- define a new mailer. ** @@ -1208,6 +1377,7 @@ fileclass(class, filename, fmt, ismap, safe, optional) ** enters the mailer into the mailer table. */ + void makemailer(line) char *line; @@ -1238,6 +1408,9 @@ makemailer(line) return; } m->m_name = newstr(line); +#if _FFR_RCPTFLAGS + frst[nextmailer] = line[0]; +#endif m->m_qgrp = NOQGRP; m->m_uid = NO_UID; m->m_gid = NO_GID; @@ -1279,12 +1452,10 @@ makemailer(line) { if (!(isascii(*p) && isspace(*p))) { -#if _FFR_DEPRECATE_MAILER_FLAG_I if (*p == M_INTERNAL) sm_syslog(LOG_WARNING, NOQID, "WARNING: mailer=%s, flag=%c deprecated", m->m_name, *p); -#endif /* _FFR_DEPRECATE_MAILER_FLAG_I */ setbitn(bitidx(*p), m->m_flags); } } @@ -1416,7 +1587,11 @@ makemailer(line) struct passwd *pw; while (*p != '\0' && isascii(*p) && +# if _FFR_DOTTED_USERNAMES + (isalnum(*p) || strchr(SM_PWN_CHARS, *p) != NULL)) +# else /* _FFR_DOTTED_USERNAMES */ (isalnum(*p) || strchr("-_", *p) != NULL)) +# endif /* _FFR_DOTTED_USERNAMES */ p++; while (isascii(*p) && isspace(*p)) *p++ = '\0'; @@ -1460,7 +1635,8 @@ makemailer(line) char *q = p; struct group *gr; - while (isascii(*p) && isalnum(*p)) + while (isascii(*p) && + (isalnum(*p) || strchr(SM_PWN_CHARS, *p) != NULL)) p++; *p++ = '\0'; if (*q == '\0') @@ -1939,6 +2115,439 @@ printmailer(fp, m) } (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "\n"); } + +#if STARTTLS +static struct ssl_options +{ + const char *sslopt_name; /* name of the flag */ + long sslopt_bits; /* bits to set/clear */ +} SSL_Option[] = +{ +/* Workaround for bugs are turned on by default (as well as some others) */ +#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG + { "SSL_OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG }, +#endif +#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG + { "SSL_OP_NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG }, +#endif +#ifdef SSL_OP_LEGACY_SERVER_CONNECT + { "SSL_OP_LEGACY_SERVER_CONNECT", SSL_OP_LEGACY_SERVER_CONNECT }, +#endif +#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + { "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG }, +#endif +#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG + { "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG }, +#endif +#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER + { "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER }, +#endif +#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING + { "SSL_OP_MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING }, +#endif +#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG + { "SSL_OP_SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG }, +#endif +#ifdef SSL_OP_TLS_D5_BUG + { "SSL_OP_TLS_D5_BUG", SSL_OP_TLS_D5_BUG }, +#endif +#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG + { "SSL_OP_TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG }, +#endif +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + { "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS }, +#endif +#ifdef SSL_OP_ALL + { "SSL_OP_ALL", SSL_OP_ALL }, +#endif +#ifdef SSL_OP_NO_QUERY_MTU + { "SSL_OP_NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU }, +#endif +#ifdef SSL_OP_COOKIE_EXCHANGE + { "SSL_OP_COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE }, +#endif +#ifdef SSL_OP_NO_TICKET + { "SSL_OP_NO_TICKET", SSL_OP_NO_TICKET }, +#endif +#ifdef SSL_OP_CISCO_ANYCONNECT + { "SSL_OP_CISCO_ANYCONNECT", SSL_OP_CISCO_ANYCONNECT }, +#endif +#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + { "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION }, +#endif +#ifdef SSL_OP_NO_COMPRESSION + { "SSL_OP_NO_COMPRESSION", SSL_OP_NO_COMPRESSION }, +#endif +#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION + { "SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION }, +#endif +#ifdef SSL_OP_SINGLE_ECDH_USE + { "SSL_OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE }, +#endif +#ifdef SSL_OP_SINGLE_DH_USE + { "SSL_OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE }, +#endif +#ifdef SSL_OP_EPHEMERAL_RSA + { "SSL_OP_EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA }, +#endif +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE + { "SSL_OP_CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE }, +#endif +#ifdef SSL_OP_TLS_ROLLBACK_BUG + { "SSL_OP_TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG }, +#endif +#ifdef SSL_OP_NO_SSLv2 + { "SSL_OP_NO_SSLv2", SSL_OP_NO_SSLv2 }, +#endif +#ifdef SSL_OP_NO_SSLv3 + { "SSL_OP_NO_SSLv3", SSL_OP_NO_SSLv3 }, +#endif +#ifdef SSL_OP_NO_TLSv1 + { "SSL_OP_NO_TLSv1", SSL_OP_NO_TLSv1 }, +#endif +#ifdef SSL_OP_NO_TLSv1_2 + { "SSL_OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2 }, +#endif +#ifdef SSL_OP_NO_TLSv1_1 + { "SSL_OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1 }, +#endif +#ifdef SSL_OP_PKCS1_CHECK_1 + { "SSL_OP_PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 }, +#endif +#ifdef SSL_OP_PKCS1_CHECK_2 + { "SSL_OP_PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 }, +#endif +#ifdef SSL_OP_NETSCAPE_CA_DN_BUG + { "SSL_OP_NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG }, +#endif +#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG + { "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG }, +#endif +#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG + { "SSL_OP_CRYPTOPRO_TLSEXT_BUG", SSL_OP_CRYPTOPRO_TLSEXT_BUG }, +#endif +#ifdef SSL_OP_TLSEXT_PADDING + { "SSL_OP_TLSEXT_PADDING", SSL_OP_TLSEXT_PADDING }, +#endif + { NULL, 0 } +}; + +/* +** READSSLOPTIONS -- read SSL_OP_* values +** +** Parameters: +** opt -- name of option (can be NULL) +** val -- string with SSL_OP_* values or hex value +** delim -- end of string (e.g., '\0' or ';') +** pssloptions -- return value (output) +** +** Returns: +** 0 on success. +*/ + +#define SSLOPERR_NAN 1 +#define SSLOPERR_NOTFOUND 2 +#define SM_ISSPACE(c) (isascii(c) && isspace(c)) + +static int +readssloptions(opt, val, pssloptions, delim) + char *opt; + char *val; + unsigned long *pssloptions; + int delim; +{ + char *p; + int ret; + + ret = 0; + for (p = val; *p != '\0' && *p != delim; ) + { + bool clearmode; + char *q; + unsigned long sslopt_val; + struct ssl_options *sslopts; + + while (*p == ' ') + p++; + if (*p == '\0') + break; + clearmode = false; + if (*p == '-' || *p == '+') + clearmode = *p++ == '-'; + q = p; + while (*p != '\0' && !(SM_ISSPACE(*p)) && *p != ',') + p++; + if (*p != '\0') + *p++ = '\0'; + sslopt_val = 0; + if (isdigit(*q)) + { + char *end; + + sslopt_val = strtoul(q, &end, 0); + + /* not a complete "syntax" check but good enough */ + if (end == q) + { + errno = 0; + ret = SSLOPERR_NAN; + if (opt != NULL) + syserr("readcf: %s option value %s not a number", + opt, q); + sslopt_val = 0; + } + } + else + { + for (sslopts = SSL_Option; + sslopts->sslopt_name != NULL; sslopts++) + { + if (sm_strcasecmp(q, sslopts->sslopt_name) == 0) + { + sslopt_val = sslopts->sslopt_bits; + break; + } + } + if (sslopts->sslopt_name == NULL) + { + errno = 0; + ret = SSLOPERR_NOTFOUND; + if (opt != NULL) + syserr("readcf: %s option value %s unrecognized", + opt, q); + } + } + if (sslopt_val != 0) + { + if (clearmode) + *pssloptions &= ~sslopt_val; + else + *pssloptions |= sslopt_val; + } + } + return ret; +} + +# if _FFR_TLS_SE_OPTS +/* +** GET_TLS_SE_OPTIONS -- get TLS session options (from ruleset) +** +** Parameters: +** e -- envelope +** ssl -- TLS session context +** srv -- server? +** +** Returns: +** 0 on success. +*/ + +int +get_tls_se_options(e, ssl, srv) + ENVELOPE *e; + SSL *ssl; + bool srv; +{ + bool saveQuickAbort, saveSuprErrs, ok; + char *optionlist, *opt, *val; + char *keyfile, *certfile; + size_t len, i; + int ret; + +# define who (srv ? "server" : "client") +# define NAME_C_S macvalue(macid(srv ? "{client_name}" : "{server_name}"), e) +# define ADDR_C_S macvalue(macid(srv ? "{client_addr}" : "{server_addr}"), e) +# define WHICH srv ? "srv" : "clt" + + ret = 0; + keyfile = certfile = opt = val = NULL; + saveQuickAbort = QuickAbort; + saveSuprErrs = SuprErrs; + SuprErrs = true; + QuickAbort = false; + + optionlist = NULL; + ok = rscheck(srv ? "tls_srv_features" : "tls_clt_features", + NAME_C_S, ADDR_C_S, e, + RSF_RMCOMM|RSF_ADDR|RSF_STRING, + 5, NULL, NOQID, NULL, &optionlist) == EX_OK; + if (!ok && LogLevel > 8) + { + sm_syslog(LOG_NOTICE, NOQID, + "rscheck(tls_%s_features)=failed, relay=%s [%s], errors=%d", + WHICH, NAME_C_S, ADDR_C_S, + Errors); + } + QuickAbort = saveQuickAbort; + SuprErrs = saveSuprErrs; + if (ok && LogLevel > 9) + { + sm_syslog(LOG_INFO, NOQID, + "tls_%s_features=%s, relay=%s [%s]", + WHICH, optionlist, NAME_C_S, ADDR_C_S); + } + if (!ok || optionlist == NULL || (len = strlen(optionlist)) < 2) + { + if (LogLevel > 9) + sm_syslog(LOG_INFO, NOQID, + "tls_%s_features=empty, relay=%s [%s]", + WHICH, NAME_C_S, ADDR_C_S); + + return ok ? 0 : 1; + } + + i = 0; + if (optionlist[0] == '"' && optionlist[len - 1] == '"') + { + optionlist[0] = ' '; + optionlist[--len] = '\0'; + if (len <= 2) + { + if (LogLevel > 9 && len > 1) + sm_syslog(LOG_INFO, NOQID, + "tls_%s_features=too_short, relay=%s [%s]", + WHICH, NAME_C_S, ADDR_C_S); + + /* this is not treated as error! */ + return 0; + } + i = 1; + } + +# define INVALIDSYNTAX \ + do { \ + if (LogLevel > 7) \ + sm_syslog(LOG_INFO, NOQID, \ + "tls_%s_features=invalid_syntax, opt=%s, relay=%s [%s]", \ + WHICH, opt, NAME_C_S, ADDR_C_S); \ + return -1; \ + } while (0) + +# define CHECKLEN \ + do { \ + if (i >= len) \ + INVALIDSYNTAX; \ + } while (0) + +# define SKIPWS \ + do { \ + while (i < len && SM_ISSPACE(optionlist[i])) \ + ++i; \ + CHECKLEN; \ + } while (0) + + /* parse and handle opt=val; */ + do { + char sep; + + SKIPWS; + opt = optionlist + i; + sep = '='; + while (i < len && optionlist[i] != sep + && optionlist[i] != '\0' && !SM_ISSPACE(optionlist[i])) + ++i; + CHECKLEN; + while (i < len && SM_ISSPACE(optionlist[i])) + optionlist[i++] = '\0'; + CHECKLEN; + if (optionlist[i] != sep) + INVALIDSYNTAX; + optionlist[i++] = '\0'; + + SKIPWS; + val = optionlist + i; + sep = ';'; + while (i < len && optionlist[i] != sep && optionlist[i] != '\0') + ++i; + if (optionlist[i] != '\0') + { + CHECKLEN; + optionlist[i++] = '\0'; + } + + if (LogLevel > 13) + sm_syslog(LOG_DEBUG, NOQID, + "tls_%s_features=parsed, %s=%s, relay=%s [%s]", + WHICH, opt, val, NAME_C_S, ADDR_C_S); + + if (sm_strcasecmp(opt, "options") == 0) + { + unsigned long ssloptions; + + ssloptions = 0; + ret = readssloptions(NULL, val, &ssloptions, ';'); + if (ret == 0) + (void) SSL_set_options(ssl, (long) ssloptions); + else if (LogLevel > 8) + { + sm_syslog(LOG_WARNING, NOQID, + "tls_%s_features=%s, error=%s, relay=%s [%s]", + WHICH, val, + (ret == SSLOPERR_NAN) ? "not a number" : + ((ret == SSLOPERR_NOTFOUND) ? "SSL_OP not found" : + "unknown"), + NAME_C_S, ADDR_C_S); + } + } + else if (sm_strcasecmp(opt, "cipherlist") == 0) + { + if (SSL_set_cipher_list(ssl, val) <= 0) + { + ret = 1; + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_set_cipher_list(%s) failed", + who, val); + + if (LogLevel > 9) + tlslogerr(LOG_WARNING, who); + } + } + } + else if (sm_strcasecmp(opt, "keyfile") == 0) + keyfile = val; + else if (sm_strcasecmp(opt, "certfile") == 0) + certfile = val; + else + { + ret = 1; + if (LogLevel > 7) + { + sm_syslog(LOG_INFO, NOQID, + "tls_%s_features=unknown_option, opt=%s, relay=%s [%s]", + WHICH, opt, NAME_C_S, ADDR_C_S); + } + } + + } while (optionlist[i] != '\0' && i < len); + + /* need cert and key before we can use the options */ + /* does not implement the "," hack for 2nd cert/key pair */ + if (keyfile != NULL && certfile != NULL) + { + load_certkey(ssl, srv, certfile, keyfile); + keyfile = certfile = NULL; + } + else if (keyfile != NULL || certfile != NULL) + { + ret = 1; + if (LogLevel > 7) + { + sm_syslog(LOG_INFO, NOQID, + "tls_%s_features=only_one_of_CertFile/KeyFile_specified, relay=%s [%s]", + WHICH, NAME_C_S, ADDR_C_S); + } + } + + return ret; +# undef who +# undef NAME_C_S +# undef ADDR_C_S +# undef WHICH +} +# endif /* _FFR_TLS_SE_OPTS */ +#endif /* STARTTLS */ + /* ** SETOPTION -- set global processing option ** @@ -2180,12 +2789,10 @@ static struct optioninfo { "AuthOptions", O_SASLOPTS, OI_NONE }, #define O_QUEUE_FILE_MODE 0xbe { "QueueFileMode", O_QUEUE_FILE_MODE, OI_NONE }, -#if _FFR_TLS_1 -# define O_DHPARAMS5 0xbf - { "DHParameters512", O_DHPARAMS5, OI_NONE }, -# define O_CIPHERLIST 0xc0 +#define O_DIG_ALG 0xbf + { "CertFingerprintAlgorithm", O_DIG_ALG, OI_NONE }, +#define O_CIPHERLIST 0xc0 { "CipherList", O_CIPHERLIST, OI_NONE }, -#endif /* _FFR_TLS_1 */ #define O_RANDFILE 0xc1 { "RandFile", O_RANDFILE, OI_NONE }, #define O_TLS_SRV_OPTS 0xc2 @@ -2271,16 +2878,12 @@ static struct optioninfo # define O_RCPTSHUTDG 0xe2 { "BadRcptShutdownGood", O_RCPTSHUTDG, OI_SAFE }, #endif /* _FFR_BADRCPT_SHUTDOWN */ -#if STARTTLS && _FFR_TLS_1 -# define O_SRV_SSL_OPTIONS 0xe3 +#define O_SRV_SSL_OPTIONS 0xe3 { "ServerSSLOptions", O_SRV_SSL_OPTIONS, OI_NONE }, -# define O_CLT_SSL_OPTIONS 0xe4 +#define O_CLT_SSL_OPTIONS 0xe4 { "ClientSSLOptions", O_CLT_SSL_OPTIONS, OI_NONE }, -#endif /* STARTTLS && _FFR_TLS_1 */ -#if _FFR_EXPDELAY -# define O_MAX_QUEUE_AGE 0xe5 +#define O_MAX_QUEUE_AGE 0xe5 { "MaxQueueAge", O_MAX_QUEUE_AGE, OI_NONE }, -#endif /* _FFR_EXPDELAY */ #if _FFR_RCPTTHROTDELAY # define O_RCPTTHROTDELAY 0xe6 { "BadRcptThrottleDelay", O_RCPTTHROTDELAY, OI_SAFE }, @@ -2297,128 +2900,20 @@ static struct optioninfo # define O_REJECTNUL 0xe9 { "RejectNUL", O_REJECTNUL, OI_SAFE }, #endif /* _FFR_REJECT_NUL_BYTE */ +#if _FFR_BOUNCE_QUEUE +# define O_BOUNCEQUEUE 0xea + { "BounceQueue", O_BOUNCEQUEUE, OI_NONE }, +#endif /* _FFR_BOUNCE_QUEUE */ +#if _FFR_ADD_BCC +# define O_ADDBCC 0xeb + { "AddBcc", O_ADDBCC, OI_NONE }, +#endif +#define O_USECOMPRESSEDIPV6ADDRESSES 0xec + { "UseCompressedIPv6Addresses", O_USECOMPRESSEDIPV6ADDRESSES, OI_NONE }, { NULL, '\0', OI_NONE } }; -#if STARTTLS && _FFR_TLS_1 -static struct ssl_options -{ - const char *sslopt_name; /* name of the flag */ - long sslopt_bits; /* bits to set/clear */ -} SSL_Option[] = -{ -/* Workaround for bugs are turned on by default (as well as some others) */ -#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG - { "SSL_OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG }, -#endif -#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG - { "SSL_OP_NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG }, -#endif -#ifdef SSL_OP_LEGACY_SERVER_CONNECT - { "SSL_OP_LEGACY_SERVER_CONNECT", SSL_OP_LEGACY_SERVER_CONNECT }, -#endif -#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG - { "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG }, -#endif -#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG - { "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG }, -#endif -#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER - { "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER }, -#endif -#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING - { "SSL_OP_MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING }, -#endif -#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG - { "SSL_OP_SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG }, -#endif -#ifdef SSL_OP_TLS_D5_BUG - { "SSL_OP_TLS_D5_BUG", SSL_OP_TLS_D5_BUG }, -#endif -#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG - { "SSL_OP_TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG }, -#endif -#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS - { "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS }, -#endif -#ifdef SSL_OP_ALL - { "SSL_OP_ALL", SSL_OP_ALL }, -#endif -#ifdef SSL_OP_NO_QUERY_MTU - { "SSL_OP_NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU }, -#endif -#ifdef SSL_OP_COOKIE_EXCHANGE - { "SSL_OP_COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE }, -#endif -#ifdef SSL_OP_NO_TICKET - { "SSL_OP_NO_TICKET", SSL_OP_NO_TICKET }, -#endif -#ifdef SSL_OP_CISCO_ANYCONNECT - { "SSL_OP_CISCO_ANYCONNECT", SSL_OP_CISCO_ANYCONNECT }, -#endif -#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION - { "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION }, -#endif -#ifdef SSL_OP_NO_COMPRESSION - { "SSL_OP_NO_COMPRESSION", SSL_OP_NO_COMPRESSION }, -#endif -#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION - { "SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION }, -#endif -#ifdef SSL_OP_SINGLE_ECDH_USE - { "SSL_OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE }, -#endif -#ifdef SSL_OP_SINGLE_DH_USE - { "SSL_OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE }, -#endif -#ifdef SSL_OP_EPHEMERAL_RSA - { "SSL_OP_EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA }, -#endif -#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE - { "SSL_OP_CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE }, -#endif -#ifdef SSL_OP_TLS_ROLLBACK_BUG - { "SSL_OP_TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG }, -#endif -#ifdef SSL_OP_NO_SSLv2 - { "SSL_OP_NO_SSLv2", SSL_OP_NO_SSLv2 }, -#endif -#ifdef SSL_OP_NO_SSLv3 - { "SSL_OP_NO_SSLv3", SSL_OP_NO_SSLv3 }, -#endif -#ifdef SSL_OP_NO_TLSv1 - { "SSL_OP_NO_TLSv1", SSL_OP_NO_TLSv1 }, -#endif -#ifdef SSL_OP_NO_TLSv1_2 - { "SSL_OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2 }, -#endif -#ifdef SSL_OP_NO_TLSv1_1 - { "SSL_OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1 }, -#endif -#ifdef SSL_OP_PKCS1_CHECK_1 - { "SSL_OP_PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 }, -#endif -#ifdef SSL_OP_PKCS1_CHECK_2 - { "SSL_OP_PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 }, -#endif -#ifdef SSL_OP_NETSCAPE_CA_DN_BUG - { "SSL_OP_NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG }, -#endif -#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG - { "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG }, -#endif -#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG - { "SSL_OP_CRYPTOPRO_TLSEXT_BUG", SSL_OP_CRYPTOPRO_TLSEXT_BUG }, -#endif -#ifdef SSL_OP_TLSEXT_PADDING - { "SSL_OP_TLSEXT_PADDING", SSL_OP_TLSEXT_PADDING }, -#endif - { NULL, 0 } -}; -#endif /* STARTTLS && _FFR_TLS_1 */ - - # define CANONIFY(val) # define SET_OPT_DEFAULT(opt, val) opt = val @@ -2459,9 +2954,9 @@ setoption(opt, val, safe, sticky, e) char *newval; char exbuf[MAXLINE]; #endif /* STARTTLS || SM_CONF_SHM */ -#if STARTTLS && _FFR_TLS_1 - long *pssloptions = NULL; -#endif /* STARTTLS && _FFR_TLS_1 */ +#if STARTTLS + unsigned long *pssloptions = NULL; +#endif errno = 0; if (opt == ' ') @@ -2706,6 +3201,11 @@ setoption(opt, val, safe, sticky, e) set_delivery_mode(*val, e); break; +#if _FFR_PROXY + case SM_PROXY_REQ: + set_delivery_mode(*val, e); + break; +#endif /* _FFR_PROXY */ default: syserr("Unknown delivery mode %c", *val); @@ -3159,11 +3659,9 @@ setoption(opt, val, safe, sticky, e) MinQueueAge = convtime(val, 'm'); break; -#if _FFR_EXPDELAY case O_MAX_QUEUE_AGE: MaxQueueAge = convtime(val, 'm'); break; -#endif /* _FFR_EXPDELAY */ case O_DEFCHARSET: /* default character set for mimefying */ DefaultCharSet = newstr(denlstring(val, true, true)); @@ -3378,9 +3876,9 @@ setoption(opt, val, safe, sticky, e) RunAsGid = pw->pw_gid; else if (UseMSP && *p == '\0') (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, - "WARNING: RunAsUser for MSP ignored, check group ids (egid=%d, want=%d)\n", - (int) EffGid, - (int) pw->pw_gid); + "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", + (long) EffGid, + (long) pw->pw_gid); } # ifdef UID_MAX if (RunAsUid > UID_MAX) @@ -3402,9 +3900,9 @@ setoption(opt, val, safe, sticky, e) else if (UseMSP) (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, - "WARNING: RunAsUser for MSP ignored, check group ids (egid=%d, want=%d)\n", - (int) EffGid, - (int) runasgid); + "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", + (long) EffGid, + (long) runasgid); } else { @@ -3419,9 +3917,9 @@ setoption(opt, val, safe, sticky, e) else if (UseMSP) (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, - "WARNING: RunAsUser for MSP ignored, check group ids (egid=%d, want=%d)\n", - (int) EffGid, - (int) gr->gr_gid); + "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", + (long) EffGid, + (long) gr->gr_gid); } } if (tTd(47, 5)) @@ -3749,56 +4247,22 @@ setoption(opt, val, safe, sticky, e) SET_STRING_EXP(CACertPath); case O_DHPARAMS: SET_STRING_EXP(DHParams); -# if _FFR_TLS_1 - case O_DHPARAMS5: - SET_STRING_EXP(DHParams5); case O_CIPHERLIST: SET_STRING_EXP(CipherList); + case O_DIG_ALG: + SET_STRING_EXP(CertFingerprintAlgorithm); case O_SRV_SSL_OPTIONS: pssloptions = &Srv_SSL_Options; case O_CLT_SSL_OPTIONS: if (pssloptions == NULL) pssloptions = &Clt_SSL_Options; - for (p = val; *p != 0; ) - { - bool clearmode; - char *q; - struct ssl_options *sslopts; + (void) readssloptions(o->o_name, val, pssloptions, '\0'); + if (tTd(37, 8)) + sm_dprintf("ssloptions=%#lx\n", *pssloptions); - while (*p == ' ') - p++; - if (*p == '\0') - break; - clearmode = false; - if (*p == '-' || *p == '+') - clearmode = *p++ == '-'; - q = p; - while (*p != '\0' && !(isascii(*p) && isspace(*p))) - p++; - if (*p != '\0') - *p++ = '\0'; - for (sslopts = SSL_Option; - sslopts->sslopt_name != NULL; sslopts++) - { - if (sm_strcasecmp(q, sslopts->sslopt_name) == 0) - break; - } - if (sslopts->sslopt_name == NULL) - { - errno = 0; - syserr("readcf: %s option value %s unrecognized", - o->o_name, q); - } - else if (clearmode) - *pssloptions &= ~sslopts->sslopt_bits; - else - *pssloptions |= sslopts->sslopt_bits; - } pssloptions = NULL; break; -# endif /* _FFR_TLS_1 */ - case O_CRLFILE: # if OPENSSL_VERSION_NUMBER > 0x00907000L SET_STRING_EXP(CRLFile); @@ -3839,7 +4303,6 @@ setoption(opt, val, safe, sticky, e) case 'V': TLS_Srv_Opts |= TLS_I_NO_VRFY; break; -# if _FFR_TLS_1 /* ** Server without a cert? That works only if ** AnonDH is enabled as cipher, which is not in the @@ -3851,7 +4314,6 @@ setoption(opt, val, safe, sticky, e) case 'C': TLS_Srv_Opts &= ~TLS_I_SRV_CERT; break; -# endif /* _FFR_TLS_1 */ case ' ': /* ignore */ case '\t': /* ignore */ case ',': /* ignore */ @@ -3884,10 +4346,9 @@ setoption(opt, val, safe, sticky, e) case O_CACERTFILE: case O_CACERTPATH: case O_DHPARAMS: -# if _FFR_TLS_1 - case O_DHPARAMS5: + case O_SRV_SSL_OPTIONS: + case O_CLT_SSL_OPTIONS: case O_CIPHERLIST: -# endif /* _FFR_TLS_1 */ case O_CRLFILE: # if _FFR_CRLPATH case O_CRLPATH: @@ -4064,6 +4525,21 @@ setoption(opt, val, safe, sticky, e) break; #endif /* _FFR_REJECT_NUL_BYTE */ +#if _FFR_BOUNCE_QUEUE + case O_BOUNCEQUEUE: + bouncequeue = newstr(val); + break; +#endif /* _FFR_BOUNCE_QUEUE */ + +#if _FFR_ADD_BCC + case O_ADDBCC: + AddBcc = atobool(val); + break; +#endif + case O_USECOMPRESSEDIPV6ADDRESSES: + UseCompressedIPv6Addresses = atobool(val); + break; + default: if (tTd(37, 1)) { diff --git a/contrib/sendmail/src/recipient.c b/contrib/sendmail/src/recipient.c index ff3a3b9..3fad957 100644 --- a/contrib/sendmail/src/recipient.c +++ b/contrib/sendmail/src/recipient.c @@ -667,8 +667,8 @@ recipient(new, sendq, aliaslevel, e) new->q_status = "5.7.1"; if (new->q_alias->q_ruser == NULL) usrerrenh(new->q_status, - "550 UID %d is an unknown user: cannot mail to programs", - new->q_alias->q_uid); + "550 UID %ld is an unknown user: cannot mail to programs", + (long) new->q_alias->q_uid); else usrerrenh(new->q_status, "550 User %s@%s doesn't have a valid shell for mailing to programs", @@ -890,8 +890,8 @@ recipient(new, sendq, aliaslevel, e) new->q_status = "5.7.1"; if (new->q_alias->q_ruser == NULL) usrerrenh(new->q_status, - "550 UID %d is an unknown user: cannot mail to files", - new->q_alias->q_uid); + "550 UID %ld is an unknown user: cannot mail to files", + (long) new->q_alias->q_uid); else usrerrenh(new->q_status, "550 User %s@%s doesn't have a valid shell for mailing to files", @@ -1174,7 +1174,7 @@ finduser(name, fuzzyp, user) *fuzzyp = false; -#if HESIOD +#if HESIOD && !HESIOD_ALLOW_NUMERIC_LOGIN /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */ for (p = name; *p != '\0'; p++) if (!isascii(*p) || !isdigit(*p)) @@ -1185,7 +1185,7 @@ finduser(name, fuzzyp, user) sm_dprintf("failed (numeric input)\n"); return EX_NOUSER; } -#endif /* HESIOD */ +#endif /* HESIOD && !HESIOD_ALLOW_NUMERIC_LOGIN */ /* look up this login name using fast path */ status = sm_mbdb_lookup(name, user); @@ -1446,8 +1446,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) if (tTd(27, 2)) sm_dprintf("include(%s)\n", fname); if (tTd(27, 4)) - sm_dprintf(" ruid=%d euid=%d\n", - (int) getuid(), (int) geteuid()); + sm_dprintf(" ruid=%ld euid=%ld\n", + (long) getuid(), (long) geteuid()); if (tTd(27, 14)) { sm_dprintf("ctladdr "); @@ -1455,8 +1455,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) } if (tTd(27, 9)) - sm_dprintf("include: old uid = %d/%d\n", - (int) getuid(), (int) geteuid()); + sm_dprintf("include: old uid = %ld/%ld\n", + (long) getuid(), (long) geteuid()); if (forwarding) { @@ -1483,8 +1483,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) !bitnset(DBS_NONROOTSAFEADDR, DontBlameSendmail)) { if (tTd(27, 4)) - sm_dprintf("include: not safe (euid=%d, RunAsUid=%d)\n", - (int) geteuid(), (int) RunAsUid); + sm_dprintf("include: not safe (euid=%ld, RunAsUid=%ld)\n", + (long) geteuid(), (long) RunAsUid); ctladdr->q_flags |= QUNSAFEADDR; } @@ -1512,8 +1512,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) if (initgroups(user, gid) == -1) { rval = EAGAIN; - syserr("include: initgroups(%s, %d) failed", - user, gid); + syserr("include: initgroups(%s, %ld) failed", + user, (long) gid); goto resetuid; } } @@ -1533,7 +1533,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) if (gid != 0 && setgid(gid) < -1) { rval = EAGAIN; - syserr("setgid(%d) failure", gid); + syserr("setgid(%ld) failure", (long) gid); goto resetuid; } if (uid != 0) @@ -1542,8 +1542,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) if (seteuid(uid) < 0) { rval = EAGAIN; - syserr("seteuid(%d) failure (real=%d, eff=%d)", - uid, (int) getuid(), (int) geteuid()); + syserr("seteuid(%ld) failure (real=%ld, eff=%ld)", + (long) uid, (long) getuid(), (long) geteuid()); goto resetuid; } # endif /* MAILER_SETUID_METHOD == USE_SETEUID */ @@ -1551,8 +1551,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) if (setreuid(0, uid) < 0) { rval = EAGAIN; - syserr("setreuid(0, %d) failure (real=%d, eff=%d)", - uid, (int) getuid(), (int) geteuid()); + syserr("setreuid(0, %ld) failure (real=%ld, eff=%ld)", + (long) uid, (long) getuid(), (long) geteuid()); goto resetuid; } # endif /* MAILER_SETUID_METHOD == USE_SETREUID */ @@ -1561,8 +1561,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) #endif /* MAILER_SETUID_METHOD != USE_SETUID */ if (tTd(27, 9)) - sm_dprintf("include: new uid = %d/%d\n", - (int) getuid(), (int) geteuid()); + sm_dprintf("include: new uid = %ld/%ld\n", + (long) getuid(), (long) geteuid()); /* ** If home directory is remote mounted but server is down, @@ -1655,8 +1655,8 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) { /* don't use this :include: file */ if (tTd(27, 4)) - sm_dprintf("include: not safe (uid=%d): %s\n", - (int) uid, sm_errstring(rval)); + sm_dprintf("include: not safe (uid=%ld): %s\n", + (long) uid, sm_errstring(rval)); } else if ((fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, fname, SM_IO_RDONLY, NULL)) == NULL) @@ -1683,28 +1683,28 @@ resetuid: { # if USESETEUID if (seteuid(0) < 0) - syserr("!seteuid(0) failure (real=%d, eff=%d)", - (int) getuid(), (int) geteuid()); + syserr("!seteuid(0) failure (real=%ld, eff=%ld)", + (long) getuid(), (long) geteuid()); # else /* USESETEUID */ if (setreuid(-1, 0) < 0) - syserr("!setreuid(-1, 0) failure (real=%d, eff=%d)", - (int) getuid(), (int) geteuid()); + syserr("!setreuid(-1, 0) failure (real=%ld, eff=%ld)", + (long) getuid(), (long) geteuid()); if (setreuid(RealUid, 0) < 0) - syserr("!setreuid(%d, 0) failure (real=%d, eff=%d)", - (int) RealUid, (int) getuid(), - (int) geteuid()); + syserr("!setreuid(%ld, 0) failure (real=%ld, eff=%ld)", + (long) RealUid, (long) getuid(), + (long) geteuid()); # endif /* USESETEUID */ } if (setgid(savedgid) < 0) - syserr("!setgid(%d) failure (real=%d eff=%d)", - (int) savedgid, (int) getgid(), - (int) getegid()); + syserr("!setgid(%ld) failure (real=%ld eff=%ld)", + (long) savedgid, (long) getgid(), + (long) getegid()); } #endif /* HASSETREUID || USESETEUID */ if (tTd(27, 9)) - sm_dprintf("include: reset uid = %d/%d\n", - (int) getuid(), (int) geteuid()); + sm_dprintf("include: reset uid = %ld/%ld\n", + (long) getuid(), (long) geteuid()); if (rval == E_SM_OPENTIMEOUT) usrerr("451 4.4.1 open timeout on %s", fname); diff --git a/contrib/sendmail/src/savemail.c b/contrib/sendmail/src/savemail.c index 07c3c90..6de8f2f 100644 --- a/contrib/sendmail/src/savemail.c +++ b/contrib/sendmail/src/savemail.c @@ -581,6 +581,10 @@ returntosender(msg, returnq, flags, e) else ee->e_flags |= EF_NO_BODY_RETN; +#if _FFR_BOUNCE_QUEUE + if (BounceQueue != NOQGRP) + ee->e_qgrp = ee->e_dfqgrp = BounceQueue; +#endif /* _FFR_BOUNCE_QUEUE */ if (!setnewqueue(ee)) { syserr("554 5.3.0 returntosender: cannot select queue for %s", @@ -702,8 +706,15 @@ returntosender(msg, returnq, flags, e) /* mark statistics */ markstats(ee, NULLADDR, STATS_NORMAL); - /* actually deliver the error message */ - sendall(ee, SM_DELIVER); +#if _FFR_BOUNCE_QUEUE + if (BounceQueue == NOQGRP) + { +#endif + /* actually deliver the error message */ + sendall(ee, SM_DELIVER); +#if _FFR_BOUNCE_QUEUE + } +#endif (void) dropenvelope(ee, true, false); /* check for delivery errors */ diff --git a/contrib/sendmail/src/sendmail.8 b/contrib/sendmail/src/sendmail.8 index a6c47fe..f525c3e 100644 --- a/contrib/sendmail/src/sendmail.8 +++ b/contrib/sendmail/src/sendmail.8 @@ -92,6 +92,9 @@ Also, the ``From:'' and ``Sender:'' fields are examined for the name of the sender. .TP +.B \-bC +Check the configuration file. +.TP .B \-bd Run as a daemon. .B Sendmail diff --git a/contrib/sendmail/src/sendmail.h b/contrib/sendmail/src/sendmail.h index 07a58e9..b2d0211 100644 --- a/contrib/sendmail/src/sendmail.h +++ b/contrib/sendmail/src/sendmail.h @@ -122,7 +122,7 @@ SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1104 2013-11-22 20:5 # endif /* HESIOD */ #if STARTTLS -# include <openssl/ssl.h> +# include <openssl/ssl.h> # if !TLS_NO_RSA # if _FFR_FIPSMODE # define RSA_KEYLENGTH 1024 @@ -199,10 +199,19 @@ typedef int (*sasl_callback_ft)(void); # define INADDR_NONE 0xffffffff #endif /* ! INADDR_NONE */ +/* By default use uncompressed IPv6 address format (no "::") */ +#ifndef IPV6_FULL +# define IPV6_FULL 1 +#endif /* (f)open() modes for queue files */ -# define QF_O_EXTRA 0 +#define QF_O_EXTRA 0 + +#if _FFR_PROXY || _FFR_LOGREPLY +# define _FFR_ERRCODE 1 +#endif +#define SM_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) /* ** An 'argument class' describes the storage allocation status @@ -283,11 +292,23 @@ typedef struct address ADDRESS; #define QBYTRACE 0x00008000 /* DeliverBy: trace */ #define QBYNDELAY 0x00010000 /* DeliverBy: notify, delay */ #define QBYNRELAY 0x00020000 /* DeliverBy: notify, relayed */ +#define QINTBCC 0x00040000 /* internal Bcc */ +#define QDYNMAILER 0x00080000 /* "dynamic mailer" */ #define QTHISPASS 0x40000000 /* temp: address set this pass */ #define QRCPTOK 0x80000000 /* recipient() processed address */ +#define QDYNMAILFLG 'Y' + #define Q_PINGFLAGS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY) +#if _FFR_RCPTFLAGS +# define QMATCHFLAGS (QINTBCC|QDYNMAILER) +# define QMATCH_FLAG(a) ((a)->q_flags & QMATCHFLAGS) +# define ADDR_FLAGS_MATCH(a, b) (QMATCH_FLAG(a) == QMATCH_FLAG(b)) +#else +# define ADDR_FLAGS_MATCH(a, b) true +#endif + /* values for q_state */ #define QS_OK 0 /* address ok (for now)/not yet tried */ #define QS_SENT 1 /* good address, delivery complete */ @@ -342,6 +363,9 @@ typedef struct address ADDRESS; extern ADDRESS NullAddress; /* a null (template) address [main.c] */ +/* for cataddr() */ +#define NOSPACESEP 256 + /* functions */ extern void cataddr __P((char **, char **, char *, int, int, bool)); extern char *crackaddr __P((char *, ENVELOPE *)); @@ -422,6 +446,7 @@ struct mailer }; /* bits for m_flags */ +#define M_xSMTP 0x01 /* internal: {ES,S,L}MTP */ #define M_ESMTP 'a' /* run Extended SMTP */ #define M_ALIASABLE 'A' /* user can be LHS of an alias */ #define M_BLANKEND 'b' /* ensure blank line at end of message */ @@ -449,6 +474,7 @@ struct mailer #define M_NHDR 'n' /* don't insert From line */ #define M_MANYSTATUS 'N' /* MAIL11V3: DATA returns multi-status */ #define M_RUNASRCPT 'o' /* always run mailer as recipient */ + /* 'O' free? */ #define M_FROMPATH 'p' /* use reverse-path in MAIL FROM: */ /* 'P' CF: include Return-Path: */ #define M_VRFY250 'q' /* VRFY command returns 250 instead of 252 */ @@ -464,11 +490,14 @@ struct mailer #define M_NOHOSTSTAT 'W' /* ignore long term host status information */ /* 'x' CF: include Full-Name: */ #define M_XDOT 'X' /* use hidden-dot algorithm */ + /* 'y' free? */ + /* 'Y' free? */ #define M_LMTP 'z' /* run Local Mail Transport Protocol */ #define M_DIALDELAY 'Z' /* apply dial delay sleeptime */ #define M_NOMX '0' /* turn off MX lookups */ #define M_NONULLS '1' /* don't send null bytes */ #define M_FSMTP '2' /* force SMTP (no ESMTP even if offered) */ + /* '4' free? */ #define M_EBCDIC '3' /* extend Q-P encoding for EBCDIC */ #define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */ #define M_7BITHDRS '6' /* strip headers to 7 bits even in 8 bit path */ @@ -498,7 +527,11 @@ EXTERN MAILER *FileMailer; /* ptr to *file* mailer */ EXTERN MAILER *InclMailer; /* ptr to *include* mailer */ EXTERN MAILER *LocalMailer; /* ptr to local mailer */ EXTERN MAILER *ProgMailer; /* ptr to program mailer */ +#if _FFR_RCPTFLAGS +EXTERN MAILER *Mailer[MAXMAILERS * 2 + 1]; +#else EXTERN MAILER *Mailer[MAXMAILERS + 1]; +#endif /* ** Queue group definition structure. @@ -742,6 +775,12 @@ MCI #define MCIF_INLONGLINE 0x01000000 /* in the middle of a long line */ #define MCIF_AUTH2 0x02000000 /* got 2 AUTH lines */ #define MCIF_ONLY_EHLO 0x10000000 /* use only EHLO in smtpinit */ +#if _FFR_HANDLE_HDR_RW_TEMPFAIL +/* an error is not sticky (if put{header,body}() etc fail) */ +# define MCIF_NOTSTICKY 0x20000000 +#else +# define MCIF_NOTSTICKY 0 +#endif #define MCIF_EXTENS (MCIF_EXPN | MCIF_SIZE | MCIF_8BITMIME | MCIF_DSN | MCIF_8BITOK | MCIF_AUTH | MCIF_ENHSTAT | MCIF_TLS | MCIF_AUTH2) @@ -945,10 +984,16 @@ struct envelope int e_dlvr_flag; /* deliver by flag */ SM_RPOOL_T *e_rpool; /* resource pool for this envelope */ unsigned int e_features; /* server features */ -#if _FFR_MILTER_ENHSC #define ENHSC_LEN 11 +#if _FFR_MILTER_ENHSC char e_enhsc[ENHSC_LEN]; /* enhanced status code */ #endif /* _FFR_MILTER_ENHSC */ +#if _FFR_ERRCODE + /* smtp error codes during delivery */ + int e_rcode; /* reply code */ + char e_renhsc[ENHSC_LEN]; /* enhanced status code */ + char *e_text; /* reply text */ +#endif /* _FFR_ERRCODE */ }; #define PRT_NONNEGL(v) ((v) < 0 ? LONG_MAX : (v)) @@ -1141,7 +1186,7 @@ extern int macid_parse __P((char *, char **)); #define macid(name) macid_parse(name, NULL) extern char *macname __P((int)); extern char *macvalue __P((int, ENVELOPE *)); -extern int rscheck __P((char *, char *, char *, ENVELOPE *, int, int, char *, char *, ADDRESS *)); +extern int rscheck __P((char *, char *, char *, ENVELOPE *, int, int, char *, char *, ADDRESS *, char **)); extern int rscap __P((char *, char *, char *, ENVELOPE *, char ***, char *, int)); extern void setclass __P((int, char *)); extern int strtorwset __P((char *, char **, int)); @@ -1305,15 +1350,6 @@ MAP #define MA_UNAVAIL 1 /* member map is not available */ #define MA_TRYAGAIN 2 /* member map returns temp failure */ -/* macros to handle MapTempFail */ -#define BIT_IS_MTP 0x01 /* temp.failure occurred */ -#define BIT_ASK_MTP 0x02 /* do we care about MapTempFail? */ -#define RESET_MAPTEMPFAIL MapTempFail = 0 -#define INIT_MAPTEMPFAIL MapTempFail = BIT_ASK_MTP -#define SET_MAPTEMPFAIL MapTempFail |= BIT_IS_MTP -#define IS_MAPTEMPFAIL bitset(BIT_IS_MTP, MapTempFail) -#define ASK_MAPTEMPFAIL bitset(BIT_ASK_MTP, MapTempFail) - /* ** The class of a map -- essentially the functions to call */ @@ -1633,6 +1669,10 @@ EXTERN bool V6LoopbackAddrFound; /* found an IPv6 loopback address */ /* values for e_sendmode -- send modes */ #define SM_DELIVER 'i' /* interactive delivery */ +#if _FFR_PROXY +#define SM_PROXY_REQ 's' /* synchronous mode requested */ +#define SM_PROXY 'S' /* synchronous mode activated */ +#endif /* _FFR_PROXY */ #define SM_FORK 'b' /* deliver in background */ #if _FFR_DM_ONE #define SM_DM_ONE 'o' /* deliver first TA in background, then queue */ @@ -1641,7 +1681,11 @@ EXTERN bool V6LoopbackAddrFound; /* found an IPv6 loopback address */ #define SM_DEFER 'd' /* defer map lookups as well as queue */ #define SM_VERIFY 'v' /* verify only (used internally) */ #define DM_NOTSET (-1) /* DeliveryMode (per daemon) option not set */ +#if _FFR_PROXY +# define SM_IS_INTERACTIVE(m) ((m) == SM_DELIVER || (m) == SM_PROXY_REQ || (m) == SM_PROXY) +#else /* _FFR_PROXY */ # define SM_IS_INTERACTIVE(m) ((m) == SM_DELIVER) +#endif /* _FFR_PROXY */ #define WILL_BE_QUEUED(m) ((m) == SM_QUEUE || (m) == SM_DEFER) @@ -1736,6 +1780,8 @@ EXTERN unsigned long PrivacyFlags; /* privacy flags */ #define RSF_RMCOMM 0x0001 /* strip comments */ #define RSF_UNSTRUCTURED 0x0002 /* unstructured, ignore syntax errors */ #define RSF_COUNT 0x0004 /* count rejections (statistics)? */ +#define RSF_ADDR 0x0008 /* reassemble address */ +#define RSF_STRING 0x0010 /* reassemble address as string */ /* ** Flags passed to mime8to7 and putheader. @@ -1893,6 +1939,10 @@ struct termescape #define D_OPTIONAL 'O' /* optional socket */ #define D_DISABLE ((char)0x02) /* optional socket disabled */ #define D_ISSET ((char)0x03) /* this client struct is set */ +#if _FFR_XCNCT +#define D_XCNCT ((char)0x04) /* X-Connect was used */ +#define D_XCNCT_M ((char)0x05) /* X-Connect was used + "forged" */ +#endif /* _FFR_XCNCT */ #if STARTTLS /* @@ -1926,6 +1976,7 @@ struct termescape #define TLS_I_KEY_OUNR 0x00400000 /* Key must be other unreadable */ #define TLS_I_CRLF_EX 0x00800000 /* CRL file must exist */ #define TLS_I_CRLF_UNR 0x01000000 /* CRL file must be g/o unreadable */ +#define TLS_I_DHFIXED 0x02000000 /* use fixed DH param */ /* require server cert */ #define TLS_I_SRV_CERT (TLS_I_CERT_EX | TLS_I_KEY_EX | \ @@ -1935,8 +1986,7 @@ struct termescape /* server requirements */ #define TLS_I_SRV (TLS_I_SRV_CERT | TLS_I_RSA_TMP | TLS_I_VRFY_PATH | \ - TLS_I_VRFY_LOC | TLS_I_TRY_DH | TLS_I_DH1024 | \ - TLS_I_CACHE) + TLS_I_VRFY_LOC | TLS_I_TRY_DH | TLS_I_CACHE) /* client requirements */ #define TLS_I_CLT (TLS_I_KEY_UNR | TLS_I_KEY_OUNR) @@ -1947,7 +1997,7 @@ struct termescape /* functions */ extern bool init_tls_library __P((bool _fipsmode)); -extern bool inittls __P((SSL_CTX **, unsigned long, long, bool, char *, char *, char *, char *, char *)); +extern bool inittls __P((SSL_CTX **, unsigned long, unsigned long, bool, char *, char *, char *, char *, char *)); extern bool initclttls __P((bool)); extern void setclttls __P((bool)); extern bool initsrvtls __P((bool)); @@ -1960,10 +2010,9 @@ EXTERN char *CACertPath; /* path to CA certificates (dir. with hashes) */ EXTERN char *CACertFile; /* file with CA certificate */ EXTERN char *CltCertFile; /* file with client certificate */ EXTERN char *CltKeyFile; /* file with client private key */ -# if _FFR_TLS_1 EXTERN char *CipherList; /* list of ciphers */ -EXTERN char *DHParams5; /* file with DH parameters (512) */ -# endif /* _FFR_TLS_1 */ +EXTERN char *CertFingerprintAlgorithm; /* name of fingerprint alg */ +EXTERN const EVP_MD *EVP_digest; /* digest for cert fp */ EXTERN char *DHParams; /* file with DH parameters */ EXTERN char *RandFile; /* source of random data */ EXTERN char *SrvCertFile; /* file with server certificate */ @@ -1973,7 +2022,7 @@ EXTERN char *CRLFile; /* file CRLs */ EXTERN char *CRLPath; /* path to CRLs (dir. with hashes) */ #endif /* _FFR_CRLPATH */ EXTERN unsigned long TLS_Srv_Opts; /* TLS server options */ -EXTERN long Srv_SSL_Options, Clt_SSL_Options; /* SSL options */ +EXTERN unsigned long Srv_SSL_Options, Clt_SSL_Options; /* SSL options */ #endif /* STARTTLS */ /* @@ -2054,9 +2103,7 @@ EXTERN int QueueFileMode; /* mode on files in mail queue */ EXTERN int QueueMode; /* which queue items to act upon */ EXTERN int QueueSortOrder; /* queue sorting order algorithm */ EXTERN time_t MinQueueAge; /* min delivery interval */ -#if _FFR_EXPDELAY EXTERN time_t MaxQueueAge; /* max delivery interval */ -#endif /* _FFR_EXPDELAY */ EXTERN time_t QueueIntvl; /* intervals between running the queue */ EXTERN char *QueueDir; /* location of queue directory */ EXTERN QUEUE_CHAR *QueueLimitId; /* limit queue run to id */ @@ -2064,6 +2111,9 @@ EXTERN QUEUE_CHAR *QueueLimitQuarantine; /* limit queue run to quarantine reason EXTERN QUEUE_CHAR *QueueLimitRecipient; /* limit queue run to rcpt */ EXTERN QUEUE_CHAR *QueueLimitSender; /* limit queue run to sender */ EXTERN QUEUEGRP *Queue[MAXQUEUEGROUPS + 1]; /* queue groups */ +#if _FFR_BOUNCE_QUEUE +EXTERN int BounceQueue; +#endif /* functions */ extern void assign_queueid __P((ENVELOPE *)); @@ -2265,7 +2315,7 @@ extern unsigned char tTdvect[100]; /* trace vector */ } while (0) /* reply types (text in SmtpMsgBuffer) */ -#define XS_DEFAULT 0 +#define XS_DEFAULT 0 /* other commands, e.g., RSET */ #define XS_STARTTLS 1 #define XS_AUTH 2 #define XS_GREET 3 @@ -2274,14 +2324,16 @@ extern unsigned char tTdvect[100]; /* trace vector */ #define XS_RCPT 6 #define XS_DATA 7 #define XS_EOM 8 -#define XS_DATA2 9 -#define XS_RCPT2 10 -#define XS_QUIT 15 +#define XS_DATA2 9 /* LMTP */ +#define XS_QUIT 10 /* ** Global variables. */ +#if _FFR_ADD_BCC +EXTERN bool AddBcc; +#endif #if _FFR_ADDR_TYPE_MODES EXTERN bool AddrTypeModes; /* addr_type: extra "mode" information */ #endif /* _FFR_ADDR_TYPE_MODES */ @@ -2337,6 +2389,7 @@ EXTERN bool UseMSP; /* mail submission: group writable queue ok? */ EXTERN bool WorkAroundBrokenAAAA; /* some nameservers return SERVFAIL on AAAA queries */ EXTERN bool UseErrorsTo; /* use Errors-To: header (back compat) */ EXTERN bool UseNameServer; /* using DNS -- interpret h_errno & MX RRs */ +EXTERN bool UseCompressedIPv6Addresses; /* for more specific zero-subnet matches */ EXTERN char InetMode; /* default network for daemon mode */ EXTERN char OpMode; /* operation mode, see below */ EXTERN char SpaceSub; /* substitution for <lwsp> */ @@ -2504,6 +2557,10 @@ extern void buffer_errors __P((void)); extern void flush_errors __P((bool)); extern void PRINTFLIKE(1, 2) message __P((const char *, ...)); extern void PRINTFLIKE(1, 2) nmessage __P((const char *, ...)); +#if _FFR_PROXY +extern void PRINTFLIKE(3, 4) emessage __P((const char *, const char *, const char *, ...)); +extern int extsc __P((const char *, int, char *, char *)); +#endif /* _FFR_PROXY */ extern void PRINTFLIKE(1, 2) syserr __P((const char *, ...)); extern void PRINTFLIKE(2, 3) usrerrenh __P((char *, const char *, ...)); extern void PRINTFLIKE(1, 2) usrerr __P((const char *, ...)); @@ -2519,7 +2576,7 @@ extern bool rebuildaliases __P((MAP *, bool)); extern void setalias __P((char *)); /* logging */ -extern void logdelivery __P((MAILER *, MCI *, char *, const char *, ADDRESS *, time_t, ENVELOPE *)); +extern void logdelivery __P((MAILER *, MCI *, char *, const char *, ADDRESS *, time_t, ENVELOPE *, ADDRESS *, int)); extern void logsender __P((ENVELOPE *, char *)); extern void PRINTFLIKE(3, 4) sm_syslog __P((int, const char *, const char *, ...)); @@ -2656,6 +2713,14 @@ extern int getla __P((void)); extern char *getmodifiers __P((char *, BITMAP256)); extern BITMAP256 *getrequests __P((ENVELOPE *)); extern char *getvendor __P((int)); +#if _FFR_TLS_SE_OPTS && STARTTLS +# ifndef TLS_VRFY_PER_CTX +# define TLS_VRFY_PER_CTX 1 +# endif +extern int get_tls_se_options __P((ENVELOPE *, SSL *, bool)); +#else +# define get_tls_se_options(e, s, w) 0 +#endif extern void help __P((char *, ENVELOPE *)); extern void init_md __P((int, char **)); extern void initdaemon __P((void)); @@ -2666,6 +2731,9 @@ extern void init_vendor_macros __P((ENVELOPE *)); extern SIGFUNC_DECL intsig __P((int)); extern bool isatom __P((const char *)); extern bool isloopback __P((SOCKADDR sa)); +#if _FFR_TLS_SE_OPTS && STARTTLS +extern bool load_certkey __P((SSL *, bool, char *, char *)); +#endif extern void load_if_names __P((void)); extern bool lockfile __P((int, char *, char *, int)); extern void log_sendmail_pid __P((ENVELOPE *)); @@ -2719,10 +2787,10 @@ extern sigfunc_t setsignal __P((int, sigfunc_t)); extern void sm_setuserenv __P((const char *, const char *)); extern void settime __P((ENVELOPE *)); #if STARTTLS -extern void set_tls_rd_tmo __P((int)); -#else /* STARTTLS */ -#define set_tls_rd_tmo(rd_tmo) -#endif /* STARTTLS */ +extern int set_tls_rd_tmo __P((int)); +#else +# define set_tls_rd_tmo(rd_tmo) 0 +#endif extern char *sfgets __P((char *, int, SM_FILE_T *, time_t, char *)); extern char *shortenstring __P((const char *, size_t)); extern char *shorten_hostname __P((char [])); @@ -2774,16 +2842,22 @@ extern int waitfor __P((pid_t)); extern bool writable __P((char *, ADDRESS *, long)); #if SM_HEAP_CHECK # define xalloc(size) xalloc_tagged(size, __FILE__, __LINE__) -extern char *xalloc_tagged __P((int, char*, int)); +extern char *xalloc_tagged __P((int, char *, int)); #else /* SM_HEAP_CHECK */ extern char *xalloc __P((int)); #endif /* SM_HEAP_CHECK */ +#if _FFR_XCNCT +extern int xconnect __P((SM_FILE_T *)); +#endif /* _FFR_XCNCT */ extern void xputs __P((SM_FILE_T *, const char *)); extern char *xtextify __P((char *, char *)); extern bool xtextok __P((char *)); extern int xunlink __P((char *)); extern char *xuntextify __P((char *)); +#if _FFR_RCPTFLAGS +extern bool newmodmailer __P((ADDRESS *, int)); +#endif #undef EXTERN #endif /* ! _SENDMAIL_H */ diff --git a/contrib/sendmail/src/sfsasl.c b/contrib/sendmail/src/sfsasl.c index 0593a25..5209dfa 100644 --- a/contrib/sendmail/src/sfsasl.c +++ b/contrib/sendmail/src/sfsasl.c @@ -13,6 +13,7 @@ SM_RCSID("@(#)$Id: sfsasl.c,v 8.121 2013-11-22 20:51:56 ca Exp $") #include <stdlib.h> #include <sendmail.h> #include <sm/time.h> +#include <sm/fdset.h> #include <errno.h> /* allow to disable error handling code just in case... */ @@ -415,7 +416,7 @@ sfdcsasl(fin, fout, conn, tmo) #if STARTTLS # include "sfsasl.h" -# include <openssl/err.h> +# include <openssl/err.h> /* Structure used by the "tls" file type */ struct tls_obj @@ -618,17 +619,16 @@ tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where) where, rfd, wfd, err); } - if (FD_SETSIZE > 0 && - ((err == SSL_ERROR_WANT_READ && rfd >= FD_SETSIZE) || - (err == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE))) + if ((err == SSL_ERROR_WANT_READ && !SM_FD_OK_SELECT(rfd)) || + (err == SSL_ERROR_WANT_WRITE && !SM_FD_OK_SELECT(wfd))) { if (LogLevel > 5) { sm_syslog(LOG_ERR, NOQID, "STARTTLS=%s, error: fd %d/%d too large", where, rfd, wfd); - if (LogLevel > 8) - tlslogerr(LOG_WARNING, where); + if (LogLevel > 8) + tlslogerr(LOG_WARNING, where); } errno = EINVAL; } @@ -685,17 +685,21 @@ tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where) ** rd_tmo -- read timeout ** ** Results: -** none +** previous read timeout ** This is a hack: there is no way to pass it in */ static int tls_rd_tmo = -1; -void +int set_tls_rd_tmo(rd_tmo) int rd_tmo; { + int old_rd_tmo; + + old_rd_tmo = tls_rd_tmo; tls_rd_tmo = rd_tmo; + return old_rd_tmo; } /* @@ -820,7 +824,7 @@ tls_read(fp, buf, size) } else if (LogLevel > 7) sm_syslog(LOG_WARNING, NOQID, - "STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d", + "STARTTLS: read error=%s (%d), errno=%d, retry=%d, ssl_err=%d", err, r, errno, try, ssl_err); errno = save_errno; } diff --git a/contrib/sendmail/src/sm_resolve.c b/contrib/sendmail/src/sm_resolve.c index 662eaa5..8ec2cb6 100644 --- a/contrib/sendmail/src/sm_resolve.c +++ b/contrib/sendmail/src/sm_resolve.c @@ -235,7 +235,7 @@ parse_dns_reply(data, len) if (LogLevel > 5) sm_syslog(LOG_WARNING, NOQID, "ERROR: DNS RDLENGTH=%d > data len=%d", - size, len - (p - data)); + size, len - (int)(p - data)); dns_free_data(r); return NULL; } diff --git a/contrib/sendmail/src/srvrsmtp.c b/contrib/sendmail/src/srvrsmtp.c index 1a53567..b05348d 100644 --- a/contrib/sendmail/src/srvrsmtp.c +++ b/contrib/sendmail/src/srvrsmtp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2010, 2012, 2013 Proofpoint, Inc. and its suppliers. + * Copyright (c) 1998-2010, 2012-2014 Proofpoint, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -30,7 +30,7 @@ SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.1016 2013-11-22 20:51:56 ca Exp $") static int saslmechs __P((sasl_conn_t *, char **)); #endif /* SASL */ #if STARTTLS -# include <openssl/err.h> +# include <openssl/err.h> # include <sysexits.h> static SSL_CTX *srv_ctx = NULL; /* TLS server context */ @@ -204,6 +204,174 @@ parse_esmtp_args(e, addr_st, p, delimptr, which, args, esmtp_args) args[argno] = NULL; } +#if _FFR_ADD_BCC + +/* +** ADDRCPT -- Add a rcpt to sendq list +** +** Parameters: +** rcpt -- rcpt +** sendq -- a pointer to the head of a queue to put +** these people into. +** e -- the envelope in which to add these recipients. +** +** Returns: +** The number of addresses added to the list. +*/ + +static int +addrcpt(rcpt, sendq, e) + char *rcpt; + ADDRESS **sendq; + ENVELOPE *e; +{ + int r; + char *oldto; + ADDRESS *a; + + SM_REQUIRE(rcpt != NULL); + SM_REQUIRE(sendq != NULL); + SM_REQUIRE(e != NULL); + oldto = e->e_to; + if (tTd(25, 1)) + sm_dprintf("addrcpt: rcpt=%s\n", rcpt); + r = Errors; + a = NULL; + SM_TRY + { + macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e b"); + a = parseaddr(rcpt, NULLADDR, RF_COPYALL, ' ', NULL, e, true); + if (a == NULL) + return 0; + + a->q_flags &= ~Q_PINGFLAGS; + a->q_flags |= QINTBCC; + a->q_owner = "<>"; + + /* disable alias expansion? */ + a = recipient(a, sendq, 0, e); + } + SM_FINALLY + { + e->e_to = oldto; + macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); + } + SM_END_TRY + if (tTd(25, 1)) + sm_dprintf("addrcpt: rcpt=%s, flags=%#lx\n", rcpt, + a != NULL ? a->q_flags : 0); + Errors = r; + return 1; +} + +/* +** ADDBCC -- Maybe create a copy of an e-mail +** +** Parameters: +** a -- current RCPT +** e -- the envelope. +** +** Returns: +** nothing +** +** Side Effects: +** rscheck() can trigger an "exception" +*/ + +static void +addbcc(a, e) + ADDRESS *a; + ENVELOPE *e; +{ + int nobcc; + char *newrcpt, empty[1]; + + if (!AddBcc) + return; + + nobcc = false; + empty[0] = '\0'; + newrcpt = empty; + + nobcc = rscheck("bcc", a->q_paddr, NULL, e, RSF_ADDR, 12, NULL, NOQID, + NULL, &newrcpt); + if (tTd(25, 1)) + sm_dprintf("addbcc: nobcc=%d, Errors=%d, newrcpt=<%s>\n", nobcc, Errors, newrcpt); + if (nobcc != EX_OK || Errors > 0 || *newrcpt == '\0') + return; + + (void) addrcpt(newrcpt, &e->e_sendqueue, e); + return; +} +#else /* _FFR_ADD_BCC */ +# define addbcc(a, e) +#endif /* _FFR_ADD_BCC */ + +#if _FFR_RCPTFLAGS +/* +** RCPTMODS -- Perform rcpt modifications if requested +** +** Parameters: +** rcpt -- current RCPT +** e -- the envelope. +** +** Returns: +** nothing. +*/ + +void +rcptmods(rcpt, e) + ADDRESS *rcpt; + ENVELOPE *e; +{ + char *fl; + + SM_REQUIRE(rcpt != NULL); + SM_REQUIRE(e != NULL); + + fl = macvalue(macid("{rcpt_flags}"), e); + if (fl == NULL || *fl == '\0') + return; + if (tTd(25, 1)) + sm_dprintf("rcptmods: rcpt=%s, flags=%s\n", rcpt->q_paddr, fl); + + /* parse flags */ + for ( ; *fl != '\0'; ++fl) + { + switch (*fl) + { + case 'n': + rcpt->q_flags &= ~Q_PINGFLAGS; + rcpt->q_flags |= QINTBCC; + rcpt->q_owner = "<>"; + break; + + case 'N': + rcpt->q_flags &= ~Q_PINGFLAGS; + rcpt->q_owner = "<>"; + break; + + case QDYNMAILFLG: + rcpt->q_flags |= QDYNMAILER; + newmodmailer(rcpt, *fl); + break; + + default: + sm_syslog(LOG_INFO, e->e_id, + "rcpt=%s, rcpt_flags=%s, status=unknown", + rcpt->q_paddr, fl); + break; + } + } + + /* reset macro to avoid confusion later on */ + macdefine(&e->e_macro, A_PERM, macid("{rcpt_flags}"), NULL); + +} +#else /* _FFR_RCPTFLAGS */ +# define rcptmods(a, e) +#endif /* _FFR_RCPTFLAGS */ + /* ** SMTP -- run the SMTP protocol. ** @@ -541,6 +709,24 @@ do \ qid_printname(e), CurSmtpClient, inp); \ } +/* +** Determine the correct protocol keyword to use in the +** Received: header, following RFC 3848. +*/ + +#if !STARTTLS +# define tls_active false +#endif +#if SASL +# define auth_active (authenticating == SASL_IS_AUTH) +#else +# define auth_active false +#endif +#define GET_PROTOCOL() \ + (auth_active \ + ? (tls_active ? "ESMTPSA" : "ESMTPA") \ + : (tls_active ? "ESMTPS" : "ESMTP")) + static bool SevenBitInput_Saved; /* saved version of SevenBitInput */ void @@ -577,6 +763,7 @@ smtp(nullserver, d_flags, e) SMTP_T smtp; char *addr; char *greetcode = "220"; + const char *greetmsg = "not accepting messages"; char *hostname; /* my hostname ($j) */ QUEUE_CHAR *new; char *args[MAXSMTPARGS]; @@ -907,11 +1094,7 @@ smtp(nullserver, d_flags, e) } #endif /* SASL */ -#if STARTTLS - - - set_tls_rd_tmo(TimeOuts.to_nextcommand); -#endif /* STARTTLS */ + (void) set_tls_rd_tmo(TimeOuts.to_nextcommand); #if MILTER if (smtp.sm_milterize) @@ -968,7 +1151,73 @@ smtp(nullserver, d_flags, e) response = milter_connect(q, RealHostAddr, e, &state); switch (state) { +#if _FFR_MILTER_CONNECT_REPLYCODE + case SMFIR_REPLYCODE: + if (*response == '5') + { + if (MilterLogLevel > 3) + sm_syslog(LOG_INFO, e->e_id, + "Milter: connect: host=%s, addr=%s, reject=%s", + peerhostname, + anynet_ntoa(&RealHostAddr), + response); + greetcode = "554"; /* Required by 2821 3.1 */ + nullserver = newstr(response); + if (strlen(nullserver) > 4) + { + int skip; + + greetmsg = nullserver + 4; + + /* skip over enhanced status code */ + skip = isenhsc(greetmsg, ' '); + if (skip > 0) + greetmsg += skip + 1; + } + smtp.sm_milterize = false; + break; + } + else if (strncmp(response, "421 ", 4) == 0) + { + int skip; + const char *msg = response + 4; + + if (MilterLogLevel > 3) + sm_syslog(LOG_INFO, e->e_id, + "Milter: connect: host=%s, addr=%s, shutdown=%s", + peerhostname, + anynet_ntoa(&RealHostAddr), + response); + tempfail = true; + smtp.sm_milterize = false; + + /* skip over enhanced status code */ + skip = isenhsc(msg, ' '); + if (skip > 0) + msg += skip + 1; + message("421 %s %s", MyHostName, msg); + + /* arrange to ignore send list */ + e->e_sendqueue = NULL; + goto doquit; + } + else + { + if (MilterLogLevel > 3) + sm_syslog(LOG_INFO, e->e_id, + "Milter: connect: host=%s, addr=%s, temp failing commands=%s", + peerhostname, + anynet_ntoa(&RealHostAddr), + response); + /*tempfail = true;*/ + smtp.sm_milterize = false; + nullserver = newstr(response); + break; + } + +#else /* _FFR_MILTER_CONNECT_REPLYCODE */ case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */ +#endif /* _FFR_MILTER_CONNECT_REPLYCODE */ case SMFIR_REJECT: if (MilterLogLevel > 3) sm_syslog(LOG_INFO, e->e_id, @@ -1006,7 +1255,7 @@ smtp(nullserver, d_flags, e) goto doquit; } if (response != NULL) - sm_free(response); /* XXX */ + sm_free(response); } #endif /* MILTER */ @@ -1097,8 +1346,8 @@ smtp(nullserver, d_flags, e) /* output the first line, inserting "ESMTP" as second word */ if (*greetcode == '5') - (void) sm_snprintf(inp, sizeof(inp), - "%s not accepting messages", hostname); + (void) sm_snprintf(inp, sizeof(inp), "%s %s", hostname, + greetmsg); else expand(SmtpGreeting, inp, sizeof(inp), e); @@ -1400,6 +1649,8 @@ smtp(nullserver, d_flags, e) *ssf); } + protocol = GET_PROTOCOL(); + /* ** Only switch to encrypted connection ** if a security layer has been negotiated @@ -1868,6 +2119,14 @@ smtp(nullserver, d_flags, e) goto tls_done; } + if (get_tls_se_options(e, srv_ssl, true) != 0) + { + message("454 4.3.3 TLS not available: error setting options"); + SSL_free(srv_ssl); + srv_ssl = NULL; + goto tls_done; + } + # if !TLS_VRFY_PER_CTX /* ** this could be used if it were possible to set @@ -1898,13 +2157,12 @@ smtp(nullserver, d_flags, e) SSL_set_accept_state(srv_ssl); -# define SSL_ACC(s) SSL_accept(s) - tlsstart = curtime(); ssl_retry: - if ((r = SSL_ACC(srv_ssl)) <= 0) + if ((r = SSL_accept(srv_ssl)) <= 0) { int i, ssl_err; + int save_errno = errno; ssl_err = SSL_get_error(srv_ssl, r); i = tls_retry(srv_ssl, rfd, wfd, tlsstart, @@ -1924,7 +2182,7 @@ smtp(nullserver, d_flags, e) "STARTTLS=server, error: accept failed=%d, reason=%s, SSL_error=%d, errno=%d, retry=%d, relay=%.100s", r, sr == NULL ? "unknown" : sr, - ssl_err, errno, i, + ssl_err, save_errno, i, CurSmtpClient); if (LogLevel > 9) tlslogerr(LOG_WARNING, "server"); @@ -1962,7 +2220,7 @@ smtp(nullserver, d_flags, e) macvalue(macid("{verify}"), e), "STARTTLS", e, RSF_RMCOMM|RSF_COUNT, - 5, NULL, NOQID, NULL) != EX_OK || + 5, NULL, NOQID, NULL, NULL) != EX_OK || Errors > 0) { extern char MsgBuf[]; @@ -2052,7 +2310,7 @@ smtp(nullserver, d_flags, e) DELAY_CONN("EHLO"); if (c->cmd_code == CMDEHLO) { - protocol = "ESMTP"; + protocol = GET_PROTOCOL(); SmtpPhase = "server EHLO"; } else @@ -2468,7 +2726,7 @@ smtp(nullserver, d_flags, e) #endif /* _FFR_MAIL_MACRO */ if (rscheck("check_mail", addr, NULL, e, RSF_RMCOMM|RSF_COUNT, 3, - NULL, e->e_id, NULL) != EX_OK || + NULL, e->e_id, NULL, NULL) != EX_OK || Errors > 0) sm_exc_raisenew_x(&EtypeQuickAbort, 1); macdefine(&e->e_macro, A_PERM, @@ -2731,7 +2989,7 @@ smtp(nullserver, d_flags, e) macid("{addr_type}"), "e r"); if (rscheck("check_rcpt", addr, NULL, e, RSF_RMCOMM|RSF_COUNT, 3, - NULL, e->e_id, p_addr_st) != EX_OK || + NULL, e->e_id, p_addr_st, NULL) != EX_OK || Errors > 0) goto rcpt_done; macdefine(&e->e_macro, A_PERM, @@ -2744,6 +3002,9 @@ smtp(nullserver, d_flags, e) milter_cmd_safe = true; #endif + addbcc(a, e); + rcptmods(a, e); + /* save in recipient list after ESMTP mods */ a = recipient(a, &e->e_sendqueue, 0, e); /* may trigger exception... */ @@ -2821,6 +3082,7 @@ smtp(nullserver, d_flags, e) #if !MILTER rcpt_done: #endif /* !MILTER */ + macdefine(&e->e_macro, A_PERM, macid("{rcpt_mailer}"), NULL); macdefine(&e->e_macro, A_PERM, @@ -2974,8 +3236,8 @@ smtp(nullserver, d_flags, e) { /* do config file checking of the address */ if (rscheck(vrfy ? "check_vrfy" : "check_expn", - p, NULL, e, RSF_RMCOMM, - 3, NULL, NOQID, NULL) != EX_OK || + p, NULL, e, RSF_RMCOMM, 3, NULL, + NOQID, NULL, NULL) != EX_OK || Errors > 0) sm_exc_raisenew_x(&EtypeQuickAbort, 1); (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e); @@ -3070,9 +3332,8 @@ smtp(nullserver, d_flags, e) ** available to make a decision. */ - if (rscheck("check_etrn", p, NULL, e, - RSF_RMCOMM, 3, NULL, NOQID, NULL) - != EX_OK || + if (rscheck("check_etrn", p, NULL, e, RSF_RMCOMM, 3, + NULL, NOQID, NULL, NULL) != EX_OK || Errors > 0) break; @@ -3371,7 +3632,7 @@ smtp_data(smtp, e) (void) sm_snprintf(buf, sizeof(buf), "%u", smtp->sm_nrcpts); if (rscheck("check_data", buf, NULL, e, RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL, - e->e_id, NULL) != EX_OK) + e->e_id, NULL, NULL) != EX_OK) return true; #if MILTER && SMFI_VERSION > 3 @@ -3494,7 +3755,7 @@ smtp_data(smtp, e) /* rscheck() will set Errors or EF_DISCARD if it trips */ (void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT, - 3, NULL, e->e_id, NULL); + 3, NULL, e->e_id, NULL, NULL); #if MILTER milteraccept = true; @@ -3735,6 +3996,38 @@ smtp_data(smtp, e) _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; #endif /* NAMED_BIND */ +#if _FFR_PROXY + if (SM_PROXY_REQ == e->e_sendmode) + { + /* is proxy mode possible? */ + if (e->e_sibling == NULL && e->e_nrcpts == 1 + && smtp->sm_nrcpts == 1 + && (a = e->e_sendqueue) != NULL && a->q_next == NULL) + { + a->q_flags &= ~(QPINGONFAILURE|QPINGONSUCCESS| + QPINGONDELAY); + e->e_errormode = EM_QUIET; + e->e_sendmode = SM_PROXY; + } + else + { + if (tTd(87, 2)) + { + a = e->e_sendqueue; + sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, sm_nrcpts=%d, sendqueue=%p, next=%p\n", + e->e_sendmode, e, e->e_sibling, e->e_nrcpts, + smtp->sm_nrcpts, a, + (a == NULL) ? (void *)0 : a->q_next); + } + + /* switch to interactive mode */ + e->e_sendmode = SM_DELIVER; + if (LogLevel > 9) + sm_syslog(LOG_DEBUG, e->e_id, + "proxy mode requested but not possible"); + } + } +#endif /* _FFR_PROXY */ for (ee = e; ee != NULL; ee = ee->e_sibling) { @@ -3779,6 +4072,84 @@ smtp_data(smtp, e) oldid = CurEnv->e_id; CurEnv->e_id = id; +#if _FFR_PROXY + a = e->e_sendqueue; + if (tTd(87, 1)) + { + sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, msg=%s, sendqueue=%p, next=%p, state=%d, SmtpError=%s, rcode=%d, renhsc=%s, text=%s\n", + e->e_sendmode, e, e->e_sibling, e->e_nrcpts, e->e_message, a, + (a == NULL) ? (void *)0 : a->q_next, + (a == NULL) ? -1 : a->q_state, SmtpError, e->e_rcode, + e->e_renhsc, e->e_text); + } + + if (SM_PROXY == e->e_sendmode && a->q_state != QS_SENT && + a->q_state != QS_VERIFIED) /* discarded! */ + { + char *m, *errtext; + char replycode[4]; + char enhsc[10]; + int offset; + +#define NN_MSG(e) (((e)->e_message != NULL) ? (e)->e_message : "") + m = e->e_message; +#define SM_MSG_DEFERRED "Deferred: " + if (m != NULL && strncmp(SM_MSG_DEFERRED, m, + sizeof(SM_MSG_DEFERRED) - 1) == 0) + m += sizeof(SM_MSG_DEFERRED) - 1; + offset = extsc(m, ' ', replycode, enhsc); + + if (tTd(87, 2)) + { + sm_dprintf("srv: SmtpError=%s, rcode=%d, renhsc=%s, replycode=%s, enhsc=%s, offset=%d\n", + SmtpError, e->e_rcode, e->e_renhsc, + replycode, enhsc, offset); + } + +#define DIG2CHAR(d) ((d) + '0') + if (e->e_rcode != 0 && (replycode[0] == '\0' || + replycode[0] == DIG2CHAR(REPLYTYPE(e->e_rcode)))) + { + replycode[0] = DIG2CHAR(REPLYTYPE(e->e_rcode)); + replycode[1] = DIG2CHAR(REPLYCLASS(e->e_rcode)); + replycode[2] = DIG2CHAR(REPLYMINOR(e->e_rcode)); + replycode[3] = '\0'; + if (e->e_renhsc[0] == replycode[0]) + sm_strlcpy(enhsc, e->e_renhsc, sizeof(enhsc)); + if (offset < 0) + offset = 0; + } + if (e->e_text != NULL) + { + (void) strreplnonprt(e->e_text, '_'); + errtext = e->e_text; + } + else + errtext = m + offset; + + if (replycode[0] != '\0' && enhsc[0] != '\0') + emessage(replycode, enhsc, "%s", errtext); + else if (replycode[0] != '\0') + emessage(replycode, smtptodsn(atoi(replycode)), + "%s", errtext); + else if (QS_IS_TEMPFAIL(a->q_state)) + { + if (m != NULL) + message("450 4.5.1 %s", m); + else + message("450 4.5.1 Temporary error"); + } + else + { + if (m != NULL) + message("550 5.5.1 %s", m); + else + message("550 5.0.0 Permanent error"); + } + } + else + { +#endif /* _FFR_PROXY */ /* issue success message */ #if _FFR_MSG_ACCEPT if (MessageAccept != NULL && *MessageAccept != '\0') @@ -3791,6 +4162,9 @@ smtp_data(smtp, e) else #endif /* _FFR_MSG_ACCEPT */ message("250 2.0.0 %s Message accepted for delivery", id); +#if _FFR_PROXY + } +#endif /* _FFR_PROXY */ CurEnv->e_id = oldid; /* if we just queued, poke it */ @@ -3937,7 +4311,7 @@ logundelrcpts(e, msg, level, all) ? e->e_enhsc : #endif /* _FFR_MILTER_ENHSC */ a->q_status, - msg, NULL, (time_t) 0, e); + msg, NULL, (time_t) 0, e, a, EX_OK /* ??? */); } e->e_to = NULL; } @@ -4339,8 +4713,8 @@ mail_esmtp_args(a, kp, vp, e) SuprErrs = true; QuickAbort = false; if (strcmp(auth_param, "<>") != 0 && - (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM, - 9, NULL, NOQID, NULL) != EX_OK || Errors > 0)) + (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM, 9, + NULL, NOQID, NULL, NULL) != EX_OK || Errors > 0)) { if (tTd(95, 8)) { diff --git a/contrib/sendmail/src/tls.c b/contrib/sendmail/src/tls.c index ca93ee8..6b0ea25 100644 --- a/contrib/sendmail/src/tls.c +++ b/contrib/sendmail/src/tls.c @@ -13,21 +13,21 @@ SM_RCSID("@(#)$Id: tls.c,v 8.127 2013-11-27 02:51:11 gshapiro Exp $") #if STARTTLS -# include <openssl/err.h> -# include <openssl/bio.h> -# include <openssl/pem.h> -# ifndef HASURANDOMDEV -# include <openssl/rand.h> -# endif /* ! HASURANDOMDEV */ +# include <openssl/err.h> +# include <openssl/bio.h> +# include <openssl/pem.h> +# ifndef HASURANDOMDEV +# include <openssl/rand.h> +# endif /* ! HASURANDOMDEV */ # if !TLS_NO_RSA static RSA *rsa_tmp = NULL; /* temporary RSA key */ static RSA *tmp_rsa_key __P((SSL *, int, int)); # endif /* !TLS_NO_RSA */ -# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L +# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L static int tls_verify_cb __P((X509_STORE_CTX *)); -# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ static int tls_verify_cb __P((X509_STORE_CTX *, void *)); -# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ +# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */ # if OPENSSL_VERSION_NUMBER > 0x00907000L static int x509_verify_cb __P((int, X509_STORE_CTX *)); @@ -41,7 +41,7 @@ static int x509_verify_cb __P((int, X509_STORE_CTX *)); static void apps_ssl_info_cb __P((CONST097 SSL *, int , int)); static bool tls_ok_f __P((char *, char *, int)); static bool tls_safe_f __P((char *, long, bool)); -static int tls_verify_log __P((int, X509_STORE_CTX *, char *)); +static int tls_verify_log __P((int, X509_STORE_CTX *, const char *)); # if !NO_DH static DH *get_dh512 __P((void)); @@ -73,6 +73,62 @@ get_dh512() return NULL; return dh; } + +# if 0 + +This is the data from which the C code has been generated: + +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEArDcgcLpxEksQHPlolRKCUJ2szKRziseWV9cUSQNZGxoGw7KkROz4 +HF9QSbg5axyNIG+QbZYtx0jp3l6/GWq1dLOj27yZkgYgaYgFrvKPiZ2jJ5xETQVH +UpZwbjRcyjyWkWYJVsx1aF4F/iY4kT0n/+iGEoimI3C9V3KXTJ2S6jIkyJ6M/CrN +EtrDynMlUMGlc7S1ouXVOTrtKeqy3S2L9eBLxVI+sChEijGIfELupdVeXihK006p +MgnABPDbkTx6OOtYmSZaGQX+OLW2FPmwvcrzgCz9t9cAsuUcBZv1LeHEqZZttyLU +oK0jjSXgFyeU4/NfyA+zuNeWzUL6bHmigwIBAg== +-----END DH PARAMETERS----- +# endif /* 0 */ + +static DH * +get_dh2048() +{ + static unsigned char dh2048_p[]={ + 0xAC,0x37,0x20,0x70,0xBA,0x71,0x12,0x4B,0x10,0x1C,0xF9,0x68, + 0x95,0x12,0x82,0x50,0x9D,0xAC,0xCC,0xA4,0x73,0x8A,0xC7,0x96, + 0x57,0xD7,0x14,0x49,0x03,0x59,0x1B,0x1A,0x06,0xC3,0xB2,0xA4, + 0x44,0xEC,0xF8,0x1C,0x5F,0x50,0x49,0xB8,0x39,0x6B,0x1C,0x8D, + 0x20,0x6F,0x90,0x6D,0x96,0x2D,0xC7,0x48,0xE9,0xDE,0x5E,0xBF, + 0x19,0x6A,0xB5,0x74,0xB3,0xA3,0xDB,0xBC,0x99,0x92,0x06,0x20, + 0x69,0x88,0x05,0xAE,0xF2,0x8F,0x89,0x9D,0xA3,0x27,0x9C,0x44, + 0x4D,0x05,0x47,0x52,0x96,0x70,0x6E,0x34,0x5C,0xCA,0x3C,0x96, + 0x91,0x66,0x09,0x56,0xCC,0x75,0x68,0x5E,0x05,0xFE,0x26,0x38, + 0x91,0x3D,0x27,0xFF,0xE8,0x86,0x12,0x88,0xA6,0x23,0x70,0xBD, + 0x57,0x72,0x97,0x4C,0x9D,0x92,0xEA,0x32,0x24,0xC8,0x9E,0x8C, + 0xFC,0x2A,0xCD,0x12,0xDA,0xC3,0xCA,0x73,0x25,0x50,0xC1,0xA5, + 0x73,0xB4,0xB5,0xA2,0xE5,0xD5,0x39,0x3A,0xED,0x29,0xEA,0xB2, + 0xDD,0x2D,0x8B,0xF5,0xE0,0x4B,0xC5,0x52,0x3E,0xB0,0x28,0x44, + 0x8A,0x31,0x88,0x7C,0x42,0xEE,0xA5,0xD5,0x5E,0x5E,0x28,0x4A, + 0xD3,0x4E,0xA9,0x32,0x09,0xC0,0x04,0xF0,0xDB,0x91,0x3C,0x7A, + 0x38,0xEB,0x58,0x99,0x26,0x5A,0x19,0x05,0xFE,0x38,0xB5,0xB6, + 0x14,0xF9,0xB0,0xBD,0xCA,0xF3,0x80,0x2C,0xFD,0xB7,0xD7,0x00, + 0xB2,0xE5,0x1C,0x05,0x9B,0xF5,0x2D,0xE1,0xC4,0xA9,0x96,0x6D, + 0xB7,0x22,0xD4,0xA0,0xAD,0x23,0x8D,0x25,0xE0,0x17,0x27,0x94, + 0xE3,0xF3,0x5F,0xC8,0x0F,0xB3,0xB8,0xD7,0x96,0xCD,0x42,0xFA, + 0x6C,0x79,0xA2,0x83, + }; + static unsigned char dh2048_g[]={ 0x02, }; + DH *dh; + + if ((dh=DH_new()) == NULL) + return(NULL); + dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL); + dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL); + if ((dh->p == NULL) || (dh->g == NULL)) + { + DH_free(dh); + return(NULL); + } + return(dh); +} # endif /* !NO_DH */ @@ -311,15 +367,32 @@ init_tls_library(fipsmode) } } #endif /* _FFR_FIPSMODE */ + if (bv && CertFingerprintAlgorithm != NULL) + { + const EVP_MD *md; + + md = EVP_get_digestbyname(CertFingerprintAlgorithm); + if (NULL == md) + { + bv = false; + if (LogLevel > 0) + sm_syslog(LOG_ERR, NOQID, + "STARTTLS=init, CertFingerprintAlgorithm=%s, status=invalid" + , CertFingerprintAlgorithm); + } + else + EVP_digest = md; + } return bv; } + /* ** TLS_SET_VERIFY -- request client certificate? ** ** Parameters: ** ctx -- TLS context ** ssl -- TLS structure -** vrfy -- require certificate? +** vrfy -- request certificate? ** ** Returns: ** none. @@ -369,12 +442,10 @@ tls_set_verify(ctx, ssl, vrfy) # define TLS_S_CRLF_EX 0x00000100 /* CRL file exists */ # define TLS_S_CRLF_OK 0x00000200 /* CRL file is ok */ -# if _FFR_TLS_1 -# define TLS_S_CERT2_EX 0x00001000 /* 2nd cert file exists */ -# define TLS_S_CERT2_OK 0x00002000 /* 2nd cert file is ok */ -# define TLS_S_KEY2_EX 0x00004000 /* 2nd key file exists */ -# define TLS_S_KEY2_OK 0x00008000 /* 2nd key file is ok */ -# endif /* _FFR_TLS_1 */ +# define TLS_S_CERT2_EX 0x00001000 /* 2nd cert file exists */ +# define TLS_S_CERT2_OK 0x00002000 /* 2nd cert file is ok */ +# define TLS_S_KEY2_EX 0x00004000 /* 2nd key file exists */ +# define TLS_S_KEY2_OK 0x00008000 /* 2nd key file is ok */ # define TLS_S_DH_OK 0x00200000 /* DH cert is ok */ # define TLS_S_DHPAR_EX 0x00400000 /* DH param file exists */ @@ -507,6 +578,109 @@ tls_safe_f(var, sff, srv) ok = false; \ } +# if _FFR_TLS_SE_OPTS +/* +** LOAD_CERTKEY -- load cert/key for TLS session +** +** Parameters: +** ssl -- TLS session context +** certfile -- filename of certificate +** keyfile -- filename of private key +** +** Returns: +** succeeded? +*/ + +bool +load_certkey(ssl, srv, certfile, keyfile) + SSL *ssl; + bool srv; + char *certfile; + char *keyfile; +{ + bool ok; + int r; + long sff, status; + unsigned long req; + char *who; + + ok = true; + who = srv ? "server" : "client"; + status = TLS_S_NONE; + req = TLS_I_CERT_EX|TLS_I_KEY_EX; + TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req), + TLS_S_CERT_EX, srv ? TLS_T_SRV : TLS_T_CLT); + TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req), + TLS_S_KEY_EX, srv ? TLS_T_SRV : TLS_T_CLT); + + /* certfile etc. must be "safe". */ + sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK + | SFF_NOGWFILES | SFF_NOWWFILES + | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT; + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + + TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req), + bitset(TLS_I_CERT_EX, req), + bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK, srv); + TLS_SAFE_F(keyfile, sff | TLS_KEYSFF(req), + bitset(TLS_I_KEY_EX, req), + bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK, srv); + +# define SSL_use_cert(ssl, certfile) \ + SSL_use_certificate_file(ssl, certfile, SSL_FILETYPE_PEM) +# define SSL_USE_CERT "SSL_use_certificate_file" + + if (bitset(TLS_S_CERT_OK, status) && + SSL_use_cert(ssl, certfile) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: %s(%s) failed", + who, SSL_USE_CERT, certfile); + if (LogLevel > 9) + tlslogerr(LOG_WARNING, who); + } + if (bitset(TLS_I_USE_CERT, req)) + return false; + } + if (bitset(TLS_S_KEY_OK, status) && + SSL_use_PrivateKey_file(ssl, keyfile, SSL_FILETYPE_PEM) <= 0) + { + if (LogLevel > 7) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_use_PrivateKey_file(%s) failed", + who, keyfile); + if (LogLevel > 9) + tlslogerr(LOG_WARNING, who); + } + if (bitset(TLS_I_USE_KEY, req)) + return false; + } + + /* check the private key */ + if (bitset(TLS_S_KEY_OK, status) && + (r = SSL_check_private_key(ssl)) <= 0) + { + /* Private key does not match the certificate public key */ + if (LogLevel > 5) + { + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS=%s, error: SSL_check_private_key failed(%s): %d", + who, keyfile, r); + if (LogLevel > 9) + tlslogerr(LOG_WARNING, who); + } + if (bitset(TLS_I_USE_KEY, req)) + return false; + } + + return true; +} +# endif /* _FFR_TLS_SE_OPTS */ + /* ** INITTLS -- initialize TLS ** @@ -545,7 +719,7 @@ bool inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhparam) SSL_CTX **ctx; unsigned long req; - long options; + unsigned long options; bool srv; char *certfile, *keyfile, *cacertpath, *cacertfile, *dhparam; { @@ -556,12 +730,10 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar bool ok; long sff, status; char *who; -# if _FFR_TLS_1 char *cf2, *kf2; -# endif /* _FFR_TLS_1 */ -# if SM_CONF_SHM +# if SM_CONF_SHM extern int ShmId; -# endif /* SM_CONF_SHM */ +# endif /* SM_CONF_SHM */ # if OPENSSL_VERSION_NUMBER > 0x00907000L BIO *crl_file; X509_CRL *crl; @@ -586,7 +758,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar return true; ok = true; -# if _FFR_TLS_1 /* ** look for a second filename: it must be separated by a ',' ** no blanks allowed (they won't be skipped). @@ -605,7 +776,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar if (keyfile != NULL && (kf2 = strchr(keyfile, ',')) != NULL) *kf2++ = '\0'; } -# endif /* _FFR_TLS_1 */ /* ** Check whether files/paths are defined @@ -625,7 +795,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar TLS_S_CRLF_EX, TLS_T_OTHER); # endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ -# if _FFR_TLS_1 /* ** if the second file is specified it must exist ** XXX: it is possible here to define only one of those files @@ -641,18 +810,23 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar TLS_OK_F(kf2, "KeyFile", bitset(TLS_I_KEY_EX, req), TLS_S_KEY2_EX, srv ? TLS_T_SRV : TLS_T_CLT); } -# endif /* _FFR_TLS_1 */ /* ** valid values for dhparam are (only the first char is checked) ** none no parameters: don't use DH + ** i use precomputed 2048 bit parameters ** 512 use precomputed 512 bit parameters ** 1024 generate 1024 bit parameters ** 2048 generate 2048 bit parameters ** /file/name read parameters from /file/name - ** default is: 1024 */ +#define SET_DH_DFL \ + do { \ + dhparam = "I"; \ + req |= TLS_I_DHFIXED; \ + } while (0) + if (bitset(TLS_I_TRY_DH, req)) { if (dhparam != NULL) @@ -661,24 +835,25 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar if (c == '1') req |= TLS_I_DH1024; + else if (c == 'I' || c == 'i') + req |= TLS_I_DHFIXED; else if (c == '2') req |= TLS_I_DH2048; else if (c == '5') req |= TLS_I_DH512; - else if (c != 'n' && c != 'N' && c != '/') + else if (c == 'n' || c == 'N') + req &= ~TLS_I_TRY_DH; + else if (c != '/') { if (LogLevel > 12) sm_syslog(LOG_WARNING, NOQID, - "STARTTLS=%s, error: illegal value '%s' for DHParam", + "STARTTLS=%s, error: illegal value '%s' for DHParameters", who, dhparam); dhparam = NULL; } } if (dhparam == NULL) - { - dhparam = "1"; - req |= TLS_I_DH1024; - } + SET_DH_DFL; else if (*dhparam == '/') { TLS_OK_F(dhparam, "DHParameters", @@ -705,9 +880,14 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar TLS_SAFE_F(cacertfile, sff | TLS_UNR(TLS_I_CERTF_UNR, req), bitset(TLS_I_CERTF_EX, req), bitset(TLS_S_CERTF_EX, status), TLS_S_CERTF_OK, srv); - TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req), - bitset(TLS_I_DHPAR_EX, req), - bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv); + if (dhparam != NULL && *dhparam == '/') + { + TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req), + bitset(TLS_I_DHPAR_EX, req), + bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv); + if (!bitset(TLS_S_DHPAR_OK, status)) + SET_DH_DFL; + } # if OPENSSL_VERSION_NUMBER > 0x00907000L TLS_SAFE_F(CRLFile, sff | TLS_UNR(TLS_I_CRLF_UNR, req), bitset(TLS_I_CRLF_EX, req), @@ -715,7 +895,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar # endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ if (!ok) return ok; -# if _FFR_TLS_1 if (cf2 != NULL) { TLS_SAFE_F(cf2, sff | TLS_UNR(TLS_I_CERT_UNR, req), @@ -728,7 +907,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar bitset(TLS_I_KEY_EX, req), bitset(TLS_S_KEY2_EX, status), TLS_S_KEY2_OK, srv); } -# endif /* _FFR_TLS_1 */ /* create a method and a new context */ if ((*ctx = SSL_CTX_new(srv ? SSLv23_server_method() : @@ -823,13 +1001,13 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar */ if (bitset(TLS_I_RSA_TMP, req) -# if SM_CONF_SHM +# if SM_CONF_SHM && ShmId != SM_SHM_NO_ID && (rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL, NULL)) == NULL -# else /* SM_CONF_SHM */ +# else /* SM_CONF_SHM */ && 0 /* no shared memory: no need to generate key now */ -# endif /* SM_CONF_SHM */ +# endif /* SM_CONF_SHM */ ) { if (LogLevel > 7) @@ -865,16 +1043,25 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar return false; } +#if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE +# define SSL_CTX_use_cert(ssl_ctx, certfile) \ + SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile) +# define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_chain_file" +#else +# define SSL_CTX_use_cert(ssl_ctx, certfile) \ + SSL_CTX_use_certificate_file(ssl_ctx, certfile, SSL_FILETYPE_PEM) +# define SSL_CTX_USE_CERT "SSL_CTX_use_certificate_file" +#endif + /* get the certificate file */ if (bitset(TLS_S_CERT_OK, status) && - SSL_CTX_use_certificate_file(*ctx, certfile, - SSL_FILETYPE_PEM) <= 0) + SSL_CTX_use_cert(*ctx, certfile) <= 0) { if (LogLevel > 7) { sm_syslog(LOG_WARNING, NOQID, - "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed", - who, certfile); + "STARTTLS=%s, error: %s(%s) failed", + who, SSL_CTX_USE_CERT, certfile); if (LogLevel > 9) tlslogerr(LOG_WARNING, who); } @@ -899,7 +1086,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar return false; } -# if _FFR_TLS_1 /* XXX this code is pretty much duplicated from above! */ /* load private key */ @@ -918,13 +1104,13 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar /* get the certificate file */ if (bitset(TLS_S_CERT2_OK, status) && - SSL_CTX_use_certificate_file(*ctx, cf2, SSL_FILETYPE_PEM) <= 0) + SSL_CTX_use_cert(*ctx, cf2) <= 0) { if (LogLevel > 7) { sm_syslog(LOG_WARNING, NOQID, - "STARTTLS=%s, error: SSL_CTX_use_certificate_file(%s) failed", - who, cf2); + "STARTTLS=%s, error: %s(%s) failed", + who, SSL_CTX_USE_CERT, cf2); if (LogLevel > 9) tlslogerr(LOG_WARNING, who); } @@ -944,7 +1130,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar tlslogerr(LOG_WARNING, who); } } -# endif /* _FFR_TLS_1 */ /* SSL_CTX_set_quiet_shutdown(*ctx, 1); violation of standard? */ @@ -968,7 +1153,7 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar options &= ~SSL_OP_TLS_BLOCK_PADDING_BUG; } #endif - SSL_CTX_set_options(*ctx, options); + SSL_CTX_set_options(*ctx, (long) options); # if !NO_DH /* Diffie-Hellman initialization */ @@ -977,6 +1162,10 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar #if _FFR_TLS_EC EC_KEY *ecdh; #endif /* _FFR_TLS_EC */ + + if (tTd(96, 8)) + sm_dprintf("inittls: req=%#lx, status=%#lx\n", + req, status); if (bitset(TLS_S_DHPAR_OK, status)) { BIO *bio; @@ -996,6 +1185,7 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar ERR_error_string(err, NULL)); if (LogLevel > 9) tlslogerr(LOG_WARNING, who); + SET_DH_DFL; } } else @@ -1025,8 +1215,13 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar dh = DSA_dup_DH(dsa); DSA_free(dsa); } - else - if (dh == NULL && bitset(TLS_I_DH512, req)) + else if (dh == NULL && bitset(TLS_I_DHFIXED, req)) + { + if (tTd(96, 2)) + sm_dprintf("inittls: Using precomputed 2048 bit DH parameters\n"); + dh = get_dh2048(); + } + else if (dh == NULL && bitset(TLS_I_DH512, req)) { if (tTd(96, 2)) sm_dprintf("inittls: Using precomputed 512 bit DH parameters\n"); @@ -1153,7 +1348,6 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar if (tTd(96, 9)) SSL_CTX_set_info_callback(*ctx, apps_ssl_info_cb); -# if _FFR_TLS_1 /* install our own cipher list */ if (CipherList != NULL && *CipherList != '\0') { @@ -1171,29 +1365,73 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar /* failure if setting to this list is required? */ } } -# endif /* _FFR_TLS_1 */ + if (LogLevel > 12) sm_syslog(LOG_INFO, NOQID, "STARTTLS=%s, init=%d", who, ok); -# if _FFR_TLS_1 -# if 0 +# if 0 /* ** this label is required if we want to have a "clean" exit ** see the comments above at the initialization of cf2 */ endinittls: -# endif /* 0 */ +# endif /* 0 */ /* undo damage to global variables */ if (cf2 != NULL) *--cf2 = ','; if (kf2 != NULL) *--kf2 = ','; -# endif /* _FFR_TLS_1 */ return ok; } + +/* +** CERT_FP -- get cert fingerprint +** +** Parameters: +** cert -- TLS cert +** mac -- macro storage +** macro -- where to store cert fp +** +** Returns: +** <=0: cert fp calculation failed +** >0: cert fp calculation ok +*/ + +static int +cert_fp(cert, evp_digest, mac, macro) + X509 *cert; + const EVP_MD *evp_digest; + MACROS_T *mac; + char *macro; +{ + unsigned int n; + int r; + unsigned char md[EVP_MAX_MD_SIZE]; + char md5h[EVP_MAX_MD_SIZE * 3]; + static const char hexcodes[] = "0123456789ABCDEF"; + + n = 0; + if (X509_digest(cert, EVP_digest, md, &n) == 0 || n <= 0) + { + macdefine(mac, A_TEMP, macid(macro), ""); + return 0; + } + + SM_ASSERT((n * 3) + 2 < sizeof(md5h)); + for (r = 0; r < (int) n; r++) + { + md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4]; + md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)]; + md5h[(r * 3) + 2] = ':'; + } + md5h[(n * 3) - 1] = '\0'; + macdefine(mac, A_TEMP, macid(macro), md5h); + return 1; +} + /* ** TLS_GET_INFO -- get information about TLS connection ** @@ -1208,9 +1446,7 @@ inittls(ctx, req, options, srv, certfile, keyfile, cacertpath, cacertfile, dhpar ** result of authentication. ** ** Side Effects: -** sets macros: {cipher}, {tls_version}, {verify}, -** {cipher_bits}, {alg_bits}, {cert}, {cert_subject}, -** {cert_issuer}, {cn_subject}, {cn_issuer} +** sets various TLS related macros. */ int @@ -1238,7 +1474,7 @@ tls_get_info(ssl, srv, host, mac, certreq) macdefine(mac, A_TEMP, macid("{cipher_bits}"), bitstr); (void) sm_snprintf(bitstr, sizeof(bitstr), "%d", r); macdefine(mac, A_TEMP, macid("{alg_bits}"), bitstr); - s = SSL_CIPHER_get_version(c); + s = (char *) SSL_get_version(ssl); if (s == NULL) s = "UNKNOWN"; macdefine(mac, A_TEMP, macid("{tls_version}"), s); @@ -1252,9 +1488,7 @@ tls_get_info(ssl, srv, host, mac, certreq) who, verifyok, (unsigned long) cert); if (cert != NULL) { - unsigned int n; X509_NAME *subj, *issuer; - unsigned char md[EVP_MAX_MD_SIZE]; char buf[MAXNAME]; subj = X509_get_subject_name(cert); @@ -1268,6 +1502,8 @@ tls_get_info(ssl, srv, host, mac, certreq) # define LL_BADCERT 8 +#define CERTFPMACRO (CertFingerprintAlgorithm != NULL ? "{cert_fp}" : "{cert_md5}") + #define CHECK_X509_NAME(which) \ do { \ if (r == -1) \ @@ -1313,24 +1549,7 @@ tls_get_info(ssl, srv, host, mac, certreq) CHECK_X509_NAME("cn_issuer"); macdefine(mac, A_TEMP, macid("{cn_issuer}"), xtextify(buf, "<>\")")); - n = 0; - if (X509_digest(cert, EVP_md5(), md, &n) != 0 && n > 0) - { - char md5h[EVP_MAX_MD_SIZE * 3]; - static const char hexcodes[] = "0123456789ABCDEF"; - - SM_ASSERT((n * 3) + 2 < sizeof(md5h)); - for (r = 0; r < (int) n; r++) - { - md5h[r * 3] = hexcodes[(md[r] & 0xf0) >> 4]; - md5h[(r * 3) + 1] = hexcodes[(md[r] & 0x0f)]; - md5h[(r * 3) + 2] = ':'; - } - md5h[(n * 3) - 1] = '\0'; - macdefine(mac, A_TEMP, macid("{cert_md5}"), md5h); - } - else - macdefine(mac, A_TEMP, macid("{cert_md5}"), ""); + (void) cert_fp(cert, EVP_digest, mac, CERTFPMACRO); } else { @@ -1338,7 +1557,7 @@ tls_get_info(ssl, srv, host, mac, certreq) macdefine(mac, A_PERM, macid("{cert_issuer}"), ""); macdefine(mac, A_PERM, macid("{cn_subject}"), ""); macdefine(mac, A_PERM, macid("{cn_issuer}"), ""); - macdefine(mac, A_TEMP, macid("{cert_md5}"), ""); + macdefine(mac, A_TEMP, macid(CERTFPMACRO), ""); } switch (verifyok) { @@ -1633,9 +1852,9 @@ apps_ssl_info_cb(s, where, ret) ** Parameters: ** ok -- verify ok? ** ctx -- x509 context +** name -- from where is this called? ** ** Returns: -** 0 -- fatal error ** 1 -- ok */ @@ -1643,9 +1862,8 @@ static int tls_verify_log(ok, ctx, name) int ok; X509_STORE_CTX *ctx; - char *name; + const char *name; { - SSL *ssl; X509 *cert; int reason, depth; char buf[512]; @@ -1653,17 +1871,6 @@ tls_verify_log(ok, ctx, name) cert = X509_STORE_CTX_get_current_cert(ctx); reason = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); - ssl = (SSL *) X509_STORE_CTX_get_ex_data(ctx, - SSL_get_ex_data_X509_STORE_CTX_idx()); - - if (ssl == NULL) - { - /* internal error */ - sm_syslog(LOG_ERR, NOQID, - "STARTTLS: internal error: tls_verify_cb: ssl == NULL"); - return 0; - } - X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); sm_syslog(LOG_INFO, NOQID, "STARTTLS: %s cert verify: depth=%d %s, state=%d, reason=%s", @@ -1729,10 +1936,10 @@ tlslogerr(level, who) unsigned long es; char *file, *data; char buf[256]; -# define CP (const char **) es = CRYPTO_thread_id(); - while ((l = ERR_get_error_line_data(CP &file, &line, CP &data, &flags)) + while ((l = ERR_get_error_line_data((const char **) &file, &line, + (const char **) &data, &flags)) != 0) { sm_syslog(level, NOQID, diff --git a/contrib/sendmail/src/usersmtp.c b/contrib/sendmail/src/usersmtp.c index f3ddcf2..24d38ee 100644 --- a/contrib/sendmail/src/usersmtp.c +++ b/contrib/sendmail/src/usersmtp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2006, 2008-2010 Proofpoint, Inc. and its suppliers. + * Copyright (c) 1998-2006, 2008-2010, 2014 Proofpoint, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -92,6 +92,11 @@ smtpinit(m, mci, e, onlyhelo) CurHostName = MyHostName; SmtpNeedIntro = true; state = mci->mci_state; +#if _FFR_ERRCODE + e->e_rcode = 0; + e->e_renhsc[0] = '\0'; + e->e_text = NULL; +#endif /* _FFR_ERRCODE */ switch (state) { case MCIS_MAIL: @@ -227,10 +232,7 @@ tryhelo: */ if ((UseMSP && Verbose && bitset(MCIF_VERB, mci->mci_flags)) -# if !_FFR_DEPRECATE_MAILER_FLAG_I - || bitnset(M_INTERNAL, m->m_flags) -# endif /* !_FFR_DEPRECATE_MAILER_FLAG_I */ - ) + || bitnset(M_INTERNAL, m->m_flags)) { /* tell it to be verbose */ smtpmessage("VERB", m, mci); @@ -768,9 +770,7 @@ readauth(filename, safe, sai, rpool) pid = -1; sff = SFF_REGONLY|SFF_SAFEDIRPATH|SFF_NOWLINK |SFF_NOGWFILES|SFF_NOWWFILES|SFF_NOWRFILES; -# if _FFR_GROUPREADABLEAUTHINFOFILE if (!bitnset(DBS_GROUPREADABLEAUTHINFOFILE, DontBlameSendmail)) -# endif /* _FFR_GROUPREADABLEAUTHINFOFILE */ sff |= SFF_NOGRFILES; if (DontLockReadFiles) sff |= SFF_NOLOCK; @@ -2770,7 +2770,10 @@ smtpdata(m, mci, e, ctladdr, xstart) writeerr: mci->mci_errno = errno; mci->mci_state = MCIS_ERROR; - mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL); + mci_setstat(mci, bitset(MCIF_NOTSTICKY, mci->mci_flags) + ? EX_NOTSTICKY: EX_TEMPFAIL, + "4.4.2", NULL); + mci->mci_flags &= ~MCIF_NOTSTICKY; /* ** If putbody() couldn't finish due to a timeout, @@ -2782,7 +2785,7 @@ smtpdata(m, mci, e, ctladdr, xstart) (void) bfrewind(e->e_dfp); errno = mci->mci_errno; - syserr("451 4.4.1 timeout writing message to %s", CurHostName); + syserr("+451 4.4.1 timeout writing message to %s", CurHostName); smtpquit(m, mci, e); return EX_TEMPFAIL; } @@ -3085,7 +3088,7 @@ reply(m, mci, e, timeout, pfunc, enhstat, rtype) */ bufp = SmtpReplyBuffer; - set_tls_rd_tmo(timeout); + (void) set_tls_rd_tmo(timeout); for (;;) { register char *p; @@ -3247,6 +3250,48 @@ reply(m, mci, e, timeout, pfunc, enhstat, rtype) firstline = false; continue; } +#if _FFR_ERRCODE +# if _FFR_PROXY + if ((e->e_rcode == 0 || REPLYTYPE(e->e_rcode) < 5) + && REPLYTYPE(r) > 3 && firstline) +# endif +# if _FFR_LOGREPLY + if (REPLYTYPE(r) > 3 && firstline) +# endif + { + int o = -1; +# if PIPELINING + /* + ** ignore error iff: DATA, 5xy error, but we had + ** "retryable" recipients. XREF: smtpdata() + */ + + if (!(rtype == XS_DATA && REPLYTYPE(r) == 5 && + mci->mci_okrcpts <= 0 && mci->mci_retryrcpt)) +# endif /* PIPELINING */ + { + o = extenhsc(bufp + 4, ' ', enhstatcode); + if (o > 0) + { + sm_strlcpy(e->e_renhsc, enhstatcode, + sizeof(e->e_renhsc)); + + /* skip SMTP reply code, delimiters */ + o += 5; + } + else + o = 4; + e->e_rcode = r; + e->e_text = sm_rpool_strdup_x(e->e_rpool, + bufp + o); + } + if (tTd(87, 2)) + { + sm_dprintf("user: offset=%d, bufp=%s, rcode=%d, enhstat=%s, text=%s\n", + o, bufp, r, e->e_renhsc, e->e_text); + } + } +#endif /* _FFR_ERRCODE */ firstline = false; diff --git a/contrib/sendmail/src/util.c b/contrib/sendmail/src/util.c index 02e8ec2..9775915 100644 --- a/contrib/sendmail/src/util.c +++ b/contrib/sendmail/src/util.c @@ -1833,7 +1833,7 @@ dumpfd(fd, printclosed, logit) } (void) sm_snprintf(p, SPACELEFT(buf, p), "mode=%o: ", - (int) st.st_mode); + (unsigned int) st.st_mode); p += strlen(p); switch (st.st_mode & S_IFMT) { @@ -1936,11 +1936,11 @@ dumpfd(fd, printclosed, logit) default: defprint: (void) sm_snprintf(p, SPACELEFT(buf, p), - "dev=%d/%d, ino=%llu, nlink=%d, u/gid=%d/%d, ", - major(st.st_dev), minor(st.st_dev), + "dev=%ld/%ld, ino=%llu, nlink=%d, u/gid=%ld/%ld, ", + (long) major(st.st_dev), (long) minor(st.st_dev), (ULONGLONG_T) st.st_ino, - (int) st.st_nlink, (int) st.st_uid, - (int) st.st_gid); + (int) st.st_nlink, (long) st.st_uid, + (long) st.st_gid); p += strlen(p); (void) sm_snprintf(p, SPACELEFT(buf, p), "size=%llu", (ULONGLONG_T) st.st_size); @@ -2866,3 +2866,139 @@ count_open_connections(hostaddr) return n; } +#if _FFR_XCNCT +/* +** XCONNECT -- get X-CONNECT info +** +** Parameters: +** inchannel -- FILE to check +** +** Returns: +** -1 on error +** 0 if X-CONNECT was not given +** >0 if X-CONNECT was used successfully (D_XCNCT*) +*/ + +int +xconnect(inchannel) + SM_FILE_T *inchannel; +{ + int r, i; + char *p, *b, delim, inp[MAXINPLINE]; + SOCKADDR addr; + char **pvp; + char pvpbuf[PSBUFSIZE]; + char *peerhostname; /* name of SMTP peer or "localhost" */ + extern ENVELOPE BlankEnvelope; + +#define XCONNECT "X-CONNECT " +#define XCNNCTLEN (sizeof(XCONNECT) - 1) + + /* Ask the ruleset whether to use x-connect */ + pvp = NULL; + peerhostname = RealHostName; + if (peerhostname == NULL) + peerhostname = "localhost"; + r = rscap("x_connect", peerhostname, + anynet_ntoa(&RealHostAddr), &BlankEnvelope, + &pvp, pvpbuf, sizeof(pvpbuf)); + if (tTd(75, 8)) + sm_syslog(LOG_INFO, NOQID, "x-connect: rscap=%d", r); + if (r == EX_UNAVAILABLE) + return 0; + if (r != EX_OK) + { + /* ruleset error */ + sm_syslog(LOG_INFO, NOQID, "x-connect: rscap=%d", r); + return 0; + } + if (pvp != NULL && pvp[0] != NULL && (pvp[0][0] & 0377) == CANONNET) + { + /* $#: no x-connect */ + if (tTd(75, 7)) + sm_syslog(LOG_INFO, NOQID, "x-connect: nope"); + return 0; + } + + p = sfgets(inp, sizeof(inp), InChannel, TimeOuts.to_nextcommand, "pre"); + if (tTd(75, 6)) + sm_syslog(LOG_INFO, NOQID, "x-connect: input=%s", p); + if (p == NULL || strncasecmp(p, XCONNECT, XCNNCTLEN) != 0) + return -1; + p += XCNNCTLEN; + while (isascii(*p) && isspace(*p)) + p++; + + /* parameters: IPAddress [Hostname[ M]] */ + b = p; + while (*p != '\0' && isascii(*p) && + (isalnum(*p) || *p == '.' || *p== ':')) + p++; + delim = *p; + *p = '\0'; + + memset(&addr, '\0', sizeof(addr)); + addr.sin.sin_addr.s_addr = inet_addr(b); + if (addr.sin.sin_addr.s_addr != INADDR_NONE) + { + addr.sa.sa_family = AF_INET; + memcpy(&RealHostAddr, &addr, sizeof(addr)); + if (tTd(75, 2)) + sm_syslog(LOG_INFO, NOQID, "x-connect: addr=%s", + anynet_ntoa(&RealHostAddr)); + } +# if NETINET6 + else if ((r = inet_pton(AF_INET6, b, &addr.sin6.sin6_addr)) == 1) + { + addr.sa.sa_family = AF_INET6; + memcpy(&RealHostAddr, &addr, sizeof(addr)); + } +# endif /* NETINET6 */ + else + return -1; + + /* more parameters? */ + if (delim != ' ') + return D_XCNCT; + while (*p != '\0' && isascii(*p) && isspace(*p)) + p++; + + for (b = ++p, i = 0; + *p != '\0' && isascii(*p) && (isalnum(*p) || *p == '.' || *p == '-'); + p++, i++) + ; + if (i == 0) + return D_XCNCT; + delim = *p; + if (i > MAXNAME) + b[MAXNAME] = '\0'; + else + b[i] = '\0'; + SM_FREE_CLR(RealHostName); + RealHostName = newstr(b); + if (tTd(75, 2)) + sm_syslog(LOG_INFO, NOQID, "x-connect: host=%s", b); + *p = delim; + + b = p; + if (*p != ' ') + return D_XCNCT; + + while (*p != '\0' && isascii(*p) && isspace(*p)) + p++; + + if (tTd(75, 4)) + { + char *e; + + e = strpbrk(p, "\r\n"); + if (e != NULL) + *e = '\0'; + sm_syslog(LOG_INFO, NOQID, "x-connect: rest=%s", p); + } + if (*p == 'M') + return D_XCNCT_M; + + return D_XCNCT; +} +#endif /* _FFR_XCNCT */ diff --git a/contrib/sendmail/src/version.c b/contrib/sendmail/src/version.c index 1476778..7145ce2 100644 --- a/contrib/sendmail/src/version.c +++ b/contrib/sendmail/src/version.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2014 Proofpoint, Inc. and its suppliers. + * Copyright (c) 1998-2015 Proofpoint, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,6 +13,6 @@ #include <sm/gen.h> -SM_RCSID("@(#)$Id: version.c,v 8.249 2013-11-27 00:38:50 ca Exp $") +SM_RCSID("@(#)$Id: version.c,v 8.250 2014-01-27 12:55:16 ca Exp $") -char Version[] = "8.14.9"; +char Version[] = "8.15.2"; |