138032Speter/* 2261194Sgshapiro * Copyright (c) 1998-2006, 2008-2010, 2013 Proofpoint, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 538032Speter * Copyright (c) 1988, 1993 638032Speter * The Regents of the University of California. All rights reserved. 738032Speter * 838032Speter * By using this file, you agree to the terms and conditions set 938032Speter * forth in the LICENSE file which can be found at the top level of 1038032Speter * the sendmail distribution. 1138032Speter * 1238032Speter */ 1338032Speter 1464562Sgshapiro#include <sendmail.h> 15168515Sgshapiro#include <sm/sendmail.h> 16363466Sgshapiro#if STARTTLS 17363466Sgshapiro# include <tls.h> 18363466Sgshapiro#endif 19363466Sgshapiro#if DNSSEC_TEST 20363466Sgshapiro# include <sm_resolve.h> 21363466Sgshapiro#endif 2238032Speter 23266527SgshapiroSM_RCSID("@(#)$Id: readcf.c,v 8.692 2013-11-22 20:51:56 ca Exp $") 2464562Sgshapiro 2564562Sgshapiro#if NETINET || NETINET6 2664562Sgshapiro# include <arpa/inet.h> 27363466Sgshapiro#endif 2864562Sgshapiro 29223067Sgshapiro 3064562Sgshapiro#define SECONDS 3164562Sgshapiro#define MINUTES * 60 3264562Sgshapiro#define HOUR * 3600 3364562Sgshapiro#define HOURS HOUR 3464562Sgshapiro 3594334Sgshapirostatic void fileclass __P((int, char *, char *, bool, bool, bool)); 3664562Sgshapirostatic char **makeargv __P((char *)); 3764562Sgshapirostatic void settimeout __P((char *, char *, bool)); 3864562Sgshapirostatic void toomany __P((int, int)); 3990792Sgshapirostatic char *extrquotstr __P((char *, char **, char *, bool *)); 40141858Sgshapirostatic void parse_class_words __P((int, char *)); 4164562Sgshapiro 42285229Sgshapiro 43285229Sgshapiro#if _FFR_BOUNCE_QUEUE 44285229Sgshapirostatic char *bouncequeue = NULL; 45285229Sgshapirostatic void initbouncequeue __P((void)); 46285229Sgshapiro 4738032Speter/* 48285229Sgshapiro** INITBOUNCEQUEUE -- determine BounceQueue if option is set. 49285229Sgshapiro** 50285229Sgshapiro** Parameters: 51285229Sgshapiro** none. 52285229Sgshapiro** 53285229Sgshapiro** Returns: 54285229Sgshapiro** none. 55285229Sgshapiro** 56285229Sgshapiro** Side Effects: 57285229Sgshapiro** sets BounceQueue 58285229Sgshapiro*/ 59285229Sgshapiro 60285229Sgshapirostatic void 61285229Sgshapiroinitbouncequeue() 62285229Sgshapiro{ 63285229Sgshapiro STAB *s; 64285229Sgshapiro 65285229Sgshapiro BounceQueue = NOQGRP; 66285229Sgshapiro if (bouncequeue == NULL || bouncequeue[0] == '\0') 67285229Sgshapiro return; 68285229Sgshapiro 69285229Sgshapiro s = stab(bouncequeue, ST_QUEUE, ST_FIND); 70285229Sgshapiro if (s == NULL) 71285229Sgshapiro { 72285229Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 73285229Sgshapiro "Warning: option BounceQueue: unknown queue group %s\n", 74285229Sgshapiro bouncequeue); 75285229Sgshapiro } 76285229Sgshapiro else 77285229Sgshapiro BounceQueue = s->s_quegrp->qg_index; 78285229Sgshapiro} 79285229Sgshapiro#endif /* _FFR_BOUNCE_QUEUE */ 80285229Sgshapiro 81285229Sgshapiro#if _FFR_RCPTFLAGS 82285229Sgshapirovoid setupdynmailers __P((void)); 83285229Sgshapiro#else 84285229Sgshapiro#define setupdynmailers() 85285229Sgshapiro#endif 86285229Sgshapiro 87285229Sgshapiro/* 8838032Speter** READCF -- read configuration file. 8938032Speter** 9038032Speter** This routine reads the configuration file and builds the internal 9138032Speter** form. 9238032Speter** 9338032Speter** The file is formatted as a sequence of lines, each taken 9438032Speter** atomically. The first character of each line describes how 9538032Speter** the line is to be interpreted. The lines are: 9638032Speter** Dxval Define macro x to have value val. 9738032Speter** Cxword Put word into class x. 9838032Speter** Fxfile [fmt] Read file for lines to put into 9938032Speter** class x. Use scanf string 'fmt' 10038032Speter** or "%s" if not present. Fmt should 10138032Speter** only produce one string-valued result. 10238032Speter** Hname: value Define header with field-name 'name' 10338032Speter** and value as specified; this will be 10438032Speter** macro expanded immediately before 10538032Speter** use. 10638032Speter** Sn Use rewriting set n. 10738032Speter** Rlhs rhs Rewrite addresses that match lhs to 10838032Speter** be rhs. 10938032Speter** Mn arg=val... Define mailer. n is the internal name. 11038032Speter** Args specify mailer parameters. 11138032Speter** Oxvalue Set option x to value. 11290792Sgshapiro** O option value Set option (long name) to value. 11338032Speter** Pname=value Set precedence name to value. 11490792Sgshapiro** Qn arg=val... Define queue groups. n is the internal name. 11590792Sgshapiro** Args specify queue parameters. 11638032Speter** Vversioncode[/vendorcode] 11738032Speter** Version level/vendor name of 11838032Speter** configuration syntax. 11938032Speter** Kmapname mapclass arguments.... 12038032Speter** Define keyed lookup of a given class. 12138032Speter** Arguments are class dependent. 12238032Speter** Eenvar=value Set the environment value to the given value. 12338032Speter** 12438032Speter** Parameters: 12538032Speter** cfname -- configuration file name. 12690792Sgshapiro** safe -- true if this is the system config file; 12790792Sgshapiro** false otherwise. 12838032Speter** e -- the main envelope. 12938032Speter** 13038032Speter** Returns: 13138032Speter** none. 13238032Speter** 13338032Speter** Side Effects: 13438032Speter** Builds several internal tables. 13538032Speter*/ 13638032Speter 13738032Spetervoid 13838032Speterreadcf(cfname, safe, e) 13938032Speter char *cfname; 14038032Speter bool safe; 14138032Speter register ENVELOPE *e; 14238032Speter{ 14390792Sgshapiro SM_FILE_T *cf; 14464562Sgshapiro int ruleset = -1; 14538032Speter char *q; 14638032Speter struct rewrite *rwp = NULL; 14738032Speter char *bp; 14838032Speter auto char *ep; 14938032Speter int nfuzzy; 15038032Speter char *file; 15138032Speter bool optional; 15290792Sgshapiro bool ok; 15394334Sgshapiro bool ismap; 15438032Speter int mid; 15538032Speter register char *p; 15664562Sgshapiro long sff = SFF_OPENASROOT; 15738032Speter struct stat statb; 15838032Speter char buf[MAXLINE]; 159168515Sgshapiro int bufsize; 16038032Speter char exbuf[MAXLINE]; 16138032Speter char pvpbuf[MAXLINE + MAXATOM]; 16238032Speter static char *null_list[1] = { NULL }; 16390792Sgshapiro extern unsigned char TokTypeNoC[]; 16438032Speter 16538032Speter FileName = cfname; 16638032Speter LineNumber = 0; 16738032Speter 16838032Speter if (DontLockReadFiles) 16938032Speter sff |= SFF_NOLOCK; 17038032Speter cf = safefopen(cfname, O_RDONLY, 0444, sff); 17138032Speter if (cf == NULL) 17238032Speter { 17338032Speter syserr("cannot open"); 17490792Sgshapiro finis(false, true, EX_OSFILE); 17538032Speter } 17638032Speter 17790792Sgshapiro if (fstat(sm_io_getinfo(cf, SM_IO_WHAT_FD, NULL), &statb) < 0) 17838032Speter { 17938032Speter syserr("cannot fstat"); 18090792Sgshapiro finis(false, true, EX_OSFILE); 18138032Speter } 18238032Speter 18338032Speter if (!S_ISREG(statb.st_mode)) 18438032Speter { 18538032Speter syserr("not a plain file"); 18690792Sgshapiro finis(false, true, EX_OSFILE); 18738032Speter } 18838032Speter 18938032Speter if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode)) 19038032Speter { 191203004Sgshapiro if (OpMode == MD_DAEMON || OpMode == MD_INITALIAS || OpMode == MD_CHECKCONFIG) 19290792Sgshapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 19390792Sgshapiro "%s: WARNING: dangerous write permissions\n", 19490792Sgshapiro FileName); 19538032Speter if (LogLevel > 0) 19638032Speter sm_syslog(LOG_CRIT, NOQID, 19764562Sgshapiro "%s: WARNING: dangerous write permissions", 19864562Sgshapiro FileName); 19938032Speter } 20038032Speter 20190792Sgshapiro#if XLA 20238032Speter xla_zero(); 203363466Sgshapiro#endif 20438032Speter 205168515Sgshapiro while (bufsize = sizeof(buf), 206168515Sgshapiro (bp = fgetfolded(buf, &bufsize, cf)) != NULL) 20738032Speter { 208168515Sgshapiro char *nbp; 209168515Sgshapiro 21038032Speter if (bp[0] == '#') 21138032Speter { 21238032Speter if (bp != buf) 21390792Sgshapiro sm_free(bp); /* XXX */ 21438032Speter continue; 21538032Speter } 21638032Speter 21738032Speter /* do macro expansion mappings */ 218168515Sgshapiro nbp = translate_dollars(bp, bp, &bufsize); 219168515Sgshapiro if (nbp != bp && bp != buf) 220168515Sgshapiro sm_free(bp); 221168515Sgshapiro bp = nbp; 22238032Speter 22338032Speter /* interpret this line */ 22438032Speter errno = 0; 22538032Speter switch (bp[0]) 22638032Speter { 22738032Speter case '\0': 22838032Speter case '#': /* comment */ 22938032Speter break; 23038032Speter 23138032Speter case 'R': /* rewriting rule */ 23264562Sgshapiro if (ruleset < 0) 23364562Sgshapiro { 23464562Sgshapiro syserr("missing valid ruleset for \"%s\"", bp); 23564562Sgshapiro break; 23664562Sgshapiro } 23738032Speter for (p = &bp[1]; *p != '\0' && *p != '\t'; p++) 23838032Speter continue; 23938032Speter 24038032Speter if (*p == '\0') 24138032Speter { 24238032Speter syserr("invalid rewrite line \"%s\" (tab expected)", bp); 24338032Speter break; 24438032Speter } 24538032Speter 24638032Speter /* allocate space for the rule header */ 24738032Speter if (rwp == NULL) 24838032Speter { 24938032Speter RewriteRules[ruleset] = rwp = 250168515Sgshapiro (struct rewrite *) xalloc(sizeof(*rwp)); 25138032Speter } 25238032Speter else 25338032Speter { 254168515Sgshapiro rwp->r_next = (struct rewrite *) xalloc(sizeof(*rwp)); 25538032Speter rwp = rwp->r_next; 25638032Speter } 25738032Speter rwp->r_next = NULL; 25838032Speter 25938032Speter /* expand and save the LHS */ 26038032Speter *p = '\0'; 261168515Sgshapiro expand(&bp[1], exbuf, sizeof(exbuf), e); 26238032Speter rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, 263168515Sgshapiro sizeof(pvpbuf), NULL, 264168515Sgshapiro ConfigLevel >= 9 ? TokTypeNoC : IntTokenTab, 265132943Sgshapiro true); 26638032Speter nfuzzy = 0; 26738032Speter if (rwp->r_lhs != NULL) 26838032Speter { 26938032Speter register char **ap; 27038032Speter 27190792Sgshapiro rwp->r_lhs = copyplist(rwp->r_lhs, true, NULL); 27238032Speter 27338032Speter /* count the number of fuzzy matches in LHS */ 27438032Speter for (ap = rwp->r_lhs; *ap != NULL; ap++) 27538032Speter { 27638032Speter char *botch; 27738032Speter 27838032Speter botch = NULL; 279168515Sgshapiro switch (ap[0][0] & 0377) 28038032Speter { 28138032Speter case MATCHZANY: 28238032Speter case MATCHANY: 28338032Speter case MATCHONE: 28438032Speter case MATCHCLASS: 28538032Speter case MATCHNCLASS: 28638032Speter nfuzzy++; 28738032Speter break; 28838032Speter 28938032Speter case MATCHREPL: 290168515Sgshapiro botch = "$1-$9"; 29138032Speter break; 29238032Speter 29338032Speter case CANONUSER: 29438032Speter botch = "$:"; 29538032Speter break; 29638032Speter 29738032Speter case CALLSUBR: 29838032Speter botch = "$>"; 29938032Speter break; 30038032Speter 30138032Speter case CONDIF: 30238032Speter botch = "$?"; 30338032Speter break; 30438032Speter 30538032Speter case CONDFI: 30638032Speter botch = "$."; 30738032Speter break; 30838032Speter 30938032Speter case HOSTBEGIN: 31038032Speter botch = "$["; 31138032Speter break; 31238032Speter 31338032Speter case HOSTEND: 31438032Speter botch = "$]"; 31538032Speter break; 31638032Speter 31738032Speter case LOOKUPBEGIN: 31838032Speter botch = "$("; 31938032Speter break; 32038032Speter 32138032Speter case LOOKUPEND: 32238032Speter botch = "$)"; 32338032Speter break; 32438032Speter } 32538032Speter if (botch != NULL) 32638032Speter syserr("Inappropriate use of %s on LHS", 32738032Speter botch); 32838032Speter } 32964562Sgshapiro rwp->r_line = LineNumber; 33038032Speter } 33138032Speter else 33238032Speter { 33338032Speter syserr("R line: null LHS"); 33438032Speter rwp->r_lhs = null_list; 33538032Speter } 33682017Sgshapiro if (nfuzzy > MAXMATCH) 33782017Sgshapiro { 33882017Sgshapiro syserr("R line: too many wildcards"); 33982017Sgshapiro rwp->r_lhs = null_list; 34082017Sgshapiro } 34138032Speter 34238032Speter /* expand and save the RHS */ 34338032Speter while (*++p == '\t') 34438032Speter continue; 34538032Speter q = p; 34638032Speter while (*p != '\0' && *p != '\t') 34738032Speter p++; 34838032Speter *p = '\0'; 349168515Sgshapiro expand(q, exbuf, sizeof(exbuf), e); 35038032Speter rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, 351168515Sgshapiro sizeof(pvpbuf), NULL, 352168515Sgshapiro ConfigLevel >= 9 ? TokTypeNoC : IntTokenTab, 353132943Sgshapiro true); 35438032Speter if (rwp->r_rhs != NULL) 35538032Speter { 35638032Speter register char **ap; 357120256Sgshapiro int args, endtoken; 358120256Sgshapiro#if _FFR_EXTRA_MAP_CHECK 359120256Sgshapiro int nexttoken; 360363466Sgshapiro#endif 361120256Sgshapiro bool inmap; 36238032Speter 36390792Sgshapiro rwp->r_rhs = copyplist(rwp->r_rhs, true, NULL); 36438032Speter 36538032Speter /* check no out-of-bounds replacements */ 36638032Speter nfuzzy += '0'; 367120256Sgshapiro inmap = false; 368120256Sgshapiro args = 0; 369120256Sgshapiro endtoken = 0; 37038032Speter for (ap = rwp->r_rhs; *ap != NULL; ap++) 37138032Speter { 37238032Speter char *botch; 37338032Speter 37438032Speter botch = NULL; 375168515Sgshapiro switch (ap[0][0] & 0377) 37638032Speter { 37738032Speter case MATCHREPL: 378168515Sgshapiro if (ap[0][1] <= '0' || 379168515Sgshapiro ap[0][1] > nfuzzy) 38038032Speter { 38138032Speter syserr("replacement $%c out of bounds", 382168515Sgshapiro ap[0][1]); 38338032Speter } 38438032Speter break; 38538032Speter 38638032Speter case MATCHZANY: 38738032Speter botch = "$*"; 38838032Speter break; 38938032Speter 39038032Speter case MATCHANY: 39138032Speter botch = "$+"; 39238032Speter break; 39338032Speter 39438032Speter case MATCHONE: 39538032Speter botch = "$-"; 39638032Speter break; 39738032Speter 39838032Speter case MATCHCLASS: 39938032Speter botch = "$="; 40038032Speter break; 40138032Speter 40238032Speter case MATCHNCLASS: 40338032Speter botch = "$~"; 40438032Speter break; 40590792Sgshapiro 406120256Sgshapiro case CANONHOST: 407120256Sgshapiro if (!inmap) 408120256Sgshapiro break; 409120256Sgshapiro if (++args >= MAX_MAP_ARGS) 410120256Sgshapiro syserr("too many arguments for map lookup"); 411120256Sgshapiro break; 412120256Sgshapiro 413120256Sgshapiro case HOSTBEGIN: 414120256Sgshapiro endtoken = HOSTEND; 415120256Sgshapiro /* FALLTHROUGH */ 416120256Sgshapiro case LOOKUPBEGIN: 417120256Sgshapiro /* see above... */ 418168515Sgshapiro if ((ap[0][0] & 0377) == LOOKUPBEGIN) 419120256Sgshapiro endtoken = LOOKUPEND; 420120256Sgshapiro if (inmap) 421120256Sgshapiro syserr("cannot nest map lookups"); 422120256Sgshapiro inmap = true; 423120256Sgshapiro args = 0; 424120256Sgshapiro#if _FFR_EXTRA_MAP_CHECK 425168515Sgshapiro if (ap[1] == NULL) 426120256Sgshapiro { 427120256Sgshapiro syserr("syntax error in map lookup"); 428120256Sgshapiro break; 429120256Sgshapiro } 430168515Sgshapiro nexttoken = ap[1][0] & 0377; 431120256Sgshapiro if (nexttoken == CANONHOST || 432120256Sgshapiro nexttoken == CANONUSER || 433363466Sgshapiro nexttoken == endtoken) 434120256Sgshapiro { 435120256Sgshapiro syserr("missing map name for lookup"); 436120256Sgshapiro break; 437120256Sgshapiro } 438168515Sgshapiro if (ap[2] == NULL) 439120256Sgshapiro { 440120256Sgshapiro syserr("syntax error in map lookup"); 441120256Sgshapiro break; 442120256Sgshapiro } 443363466Sgshapiro if ((unsigned char) ap[0][0] == HOSTBEGIN) 444120256Sgshapiro break; 445168515Sgshapiro nexttoken = ap[2][0] & 0377; 446120256Sgshapiro if (nexttoken == CANONHOST || 447120256Sgshapiro nexttoken == CANONUSER || 448120256Sgshapiro nexttoken == endtoken) 449120256Sgshapiro { 450120256Sgshapiro syserr("missing key name for lookup"); 451120256Sgshapiro break; 452120256Sgshapiro } 453120256Sgshapiro#endif /* _FFR_EXTRA_MAP_CHECK */ 454120256Sgshapiro break; 455120256Sgshapiro 456120256Sgshapiro case HOSTEND: 457120256Sgshapiro case LOOKUPEND: 458168515Sgshapiro if ((ap[0][0] & 0377) != endtoken) 459120256Sgshapiro break; 460120256Sgshapiro inmap = false; 461120256Sgshapiro endtoken = 0; 462120256Sgshapiro break; 463120256Sgshapiro 464120256Sgshapiro 46590792Sgshapiro#if 0 46690792Sgshapiro/* 46790792Sgshapiro** This doesn't work yet as there are maps defined *after* the cf 46890792Sgshapiro** is read such as host, user, and alias. So for now, it's removed. 46990792Sgshapiro** When it comes back, the RELEASE_NOTES entry will be: 47090792Sgshapiro** Emit warnings for unknown maps when reading the .cf file. Based on 47190792Sgshapiro** patch from Robert Harker of Harker Systems. 47290792Sgshapiro*/ 47390792Sgshapiro 47490792Sgshapiro case LOOKUPBEGIN: 47590792Sgshapiro /* 47690792Sgshapiro ** Got a database lookup, 47790792Sgshapiro ** check if map is defined. 47890792Sgshapiro */ 47990792Sgshapiro 480168515Sgshapiro ep = ap[1]; 481168515Sgshapiro if ((ep[0] & 0377) != MACRODEXPAND && 482168515Sgshapiro stab(ep, ST_MAP, ST_FIND) == NULL) 48390792Sgshapiro { 48490792Sgshapiro (void) sm_io_fprintf(smioout, 48590792Sgshapiro SM_TIME_DEFAULT, 48690792Sgshapiro "Warning: %s: line %d: map %s not found\n", 48790792Sgshapiro FileName, 48890792Sgshapiro LineNumber, 48990792Sgshapiro ep); 49090792Sgshapiro } 49190792Sgshapiro break; 49290792Sgshapiro#endif /* 0 */ 49338032Speter } 49438032Speter if (botch != NULL) 49538032Speter syserr("Inappropriate use of %s on RHS", 49638032Speter botch); 49738032Speter } 498120256Sgshapiro if (inmap) 499120256Sgshapiro syserr("missing map closing token"); 50038032Speter } 50138032Speter else 50238032Speter { 50338032Speter syserr("R line: null RHS"); 50438032Speter rwp->r_rhs = null_list; 50538032Speter } 50638032Speter break; 50738032Speter 50838032Speter case 'S': /* select rewriting set */ 509168515Sgshapiro expand(&bp[1], exbuf, sizeof(exbuf), e); 51038032Speter ruleset = strtorwset(exbuf, NULL, ST_ENTER); 51138032Speter if (ruleset < 0) 51238032Speter break; 51364562Sgshapiro 51438032Speter rwp = RewriteRules[ruleset]; 51538032Speter if (rwp != NULL) 51638032Speter { 517203004Sgshapiro if (OpMode == MD_TEST || OpMode == MD_CHECKCONFIG) 51890792Sgshapiro (void) sm_io_fprintf(smioout, 51990792Sgshapiro SM_TIME_DEFAULT, 52090792Sgshapiro "WARNING: Ruleset %s has multiple definitions\n", 52190792Sgshapiro &bp[1]); 52264562Sgshapiro if (tTd(37, 1)) 52390792Sgshapiro sm_dprintf("WARNING: Ruleset %s has multiple definitions\n", 52490792Sgshapiro &bp[1]); 52538032Speter while (rwp->r_next != NULL) 52638032Speter rwp = rwp->r_next; 52738032Speter } 52838032Speter break; 52938032Speter 53038032Speter case 'D': /* macro definition */ 53190792Sgshapiro mid = macid_parse(&bp[1], &ep); 53271345Sgshapiro if (mid == 0) 53371345Sgshapiro break; 53438032Speter p = munchstring(ep, NULL, '\0'); 53590792Sgshapiro macdefine(&e->e_macro, A_TEMP, mid, p); 53638032Speter break; 53738032Speter 53838032Speter case 'H': /* required header line */ 53964562Sgshapiro (void) chompheader(&bp[1], CHHDR_DEF, NULL, e); 54038032Speter break; 54138032Speter 54238032Speter case 'C': /* word class */ 54338032Speter case 'T': /* trusted user (set class `t') */ 54438032Speter if (bp[0] == 'C') 54538032Speter { 54690792Sgshapiro mid = macid_parse(&bp[1], &ep); 54771345Sgshapiro if (mid == 0) 54871345Sgshapiro break; 549168515Sgshapiro expand(ep, exbuf, sizeof(exbuf), e); 55038032Speter p = exbuf; 55138032Speter } 55238032Speter else 55338032Speter { 55438032Speter mid = 't'; 55538032Speter p = &bp[1]; 55638032Speter } 55738032Speter while (*p != '\0') 55838032Speter { 55938032Speter register char *wd; 56038032Speter char delim; 56138032Speter 562363466Sgshapiro while (*p != '\0' && SM_ISSPACE(*p)) 56338032Speter p++; 56438032Speter wd = p; 565363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 56638032Speter p++; 56738032Speter delim = *p; 56838032Speter *p = '\0'; 56938032Speter if (wd[0] != '\0') 57038032Speter setclass(mid, wd); 57138032Speter *p = delim; 57238032Speter } 57338032Speter break; 57438032Speter 57538032Speter case 'F': /* word class from file */ 57690792Sgshapiro mid = macid_parse(&bp[1], &ep); 57771345Sgshapiro if (mid == 0) 57871345Sgshapiro break; 579363466Sgshapiro for (p = ep; SM_ISSPACE(*p); ) 58038032Speter p++; 58138032Speter if (p[0] == '-' && p[1] == 'o') 58238032Speter { 58390792Sgshapiro optional = true; 58490792Sgshapiro while (*p != '\0' && 585363466Sgshapiro !(SM_ISSPACE(*p))) 58638032Speter p++; 587363466Sgshapiro while (SM_ISSPACE(*p)) 58838032Speter p++; 58938032Speter } 59038032Speter else 59190792Sgshapiro optional = false; 59264562Sgshapiro 59394334Sgshapiro /* check if [key]@map:spec */ 59494334Sgshapiro ismap = false; 59594334Sgshapiro if (!SM_IS_DIR_DELIM(*p) && 59694334Sgshapiro *p != '|' && 59794334Sgshapiro (q = strchr(p, '@')) != NULL) 59890792Sgshapiro { 59994334Sgshapiro q++; 60094334Sgshapiro 60194334Sgshapiro /* look for @LDAP or @map: in string */ 60294334Sgshapiro if (strcmp(q, "LDAP") == 0 || 60394334Sgshapiro (*q != ':' && 60494334Sgshapiro strchr(q, ':') != NULL)) 60594334Sgshapiro ismap = true; 60694334Sgshapiro } 60794334Sgshapiro 60894334Sgshapiro if (ismap) 60994334Sgshapiro { 61090792Sgshapiro /* use entire spec */ 61190792Sgshapiro file = p; 61290792Sgshapiro } 61390792Sgshapiro else 61490792Sgshapiro { 61590792Sgshapiro file = extrquotstr(p, &q, " ", &ok); 61690792Sgshapiro if (!ok) 61790792Sgshapiro { 61890792Sgshapiro syserr("illegal filename '%s'", p); 61990792Sgshapiro break; 62090792Sgshapiro } 62190792Sgshapiro } 62290792Sgshapiro 62394334Sgshapiro if (*file == '|' || ismap) 62438032Speter p = "%s"; 62538032Speter else 62638032Speter { 62764562Sgshapiro p = q; 62838032Speter if (*p == '\0') 62938032Speter p = "%s"; 63038032Speter else 63138032Speter { 63238032Speter *p = '\0'; 63338032Speter while (isascii(*++p) && isspace(*p)) 63438032Speter continue; 63538032Speter } 63638032Speter } 63794334Sgshapiro fileclass(mid, file, p, ismap, safe, optional); 63838032Speter break; 63938032Speter 64090792Sgshapiro#if XLA 64138032Speter case 'L': /* extended load average description */ 64238032Speter xla_init(&bp[1]); 64338032Speter break; 644363466Sgshapiro#endif 64538032Speter 64638032Speter#if defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) 64738032Speter case 'L': /* lookup macro */ 64838032Speter case 'G': /* lookup class */ 64938032Speter /* reserved for Sun -- NIS+ database lookup */ 65038032Speter if (VendorCode != VENDOR_SUN) 65138032Speter goto badline; 65238032Speter sun_lg_config_line(bp, e); 65338032Speter break; 65464562Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) */ 65538032Speter 65638032Speter case 'M': /* define mailer */ 65738032Speter makemailer(&bp[1]); 65838032Speter break; 65938032Speter 66038032Speter case 'O': /* set option */ 66190792Sgshapiro setoption(bp[1], &bp[2], safe, false, e); 66238032Speter break; 66338032Speter 66438032Speter case 'P': /* set precedence */ 66538032Speter if (NumPriorities >= MAXPRIORITIES) 66638032Speter { 66738032Speter toomany('P', MAXPRIORITIES); 66838032Speter break; 66938032Speter } 67038032Speter for (p = &bp[1]; *p != '\0' && *p != '='; p++) 67138032Speter continue; 67238032Speter if (*p == '\0') 67338032Speter goto badline; 67438032Speter *p = '\0'; 67538032Speter Priorities[NumPriorities].pri_name = newstr(&bp[1]); 67638032Speter Priorities[NumPriorities].pri_val = atoi(++p); 67738032Speter NumPriorities++; 67838032Speter break; 67938032Speter 68090792Sgshapiro case 'Q': /* define queue */ 68190792Sgshapiro makequeue(&bp[1], true); 68290792Sgshapiro break; 68390792Sgshapiro 68438032Speter case 'V': /* configuration syntax version */ 685363466Sgshapiro for (p = &bp[1]; SM_ISSPACE(*p); p++) 68638032Speter continue; 68738032Speter if (!isascii(*p) || !isdigit(*p)) 68838032Speter { 68964562Sgshapiro syserr("invalid argument to V line: \"%.20s\"", 69038032Speter &bp[1]); 69138032Speter break; 69238032Speter } 69338032Speter ConfigLevel = strtol(p, &ep, 10); 69438032Speter 69538032Speter /* 69638032Speter ** Do heuristic tweaking for back compatibility. 69738032Speter */ 69838032Speter 69938032Speter if (ConfigLevel >= 5) 70038032Speter { 70138032Speter /* level 5 configs have short name in $w */ 70238032Speter p = macvalue('w', e); 70338032Speter if (p != NULL && (p = strchr(p, '.')) != NULL) 70490792Sgshapiro { 70538032Speter *p = '\0'; 70690792Sgshapiro macdefine(&e->e_macro, A_TEMP, 'w', 70790792Sgshapiro macvalue('w', e)); 70890792Sgshapiro } 70938032Speter } 71038032Speter if (ConfigLevel >= 6) 71138032Speter { 71290792Sgshapiro ColonOkInAddr = false; 71338032Speter } 71438032Speter 71538032Speter /* 71638032Speter ** Look for vendor code. 71738032Speter */ 71838032Speter 71938032Speter if (*ep++ == '/') 72038032Speter { 72138032Speter /* extract vendor code */ 72238032Speter for (p = ep; isascii(*p) && isalpha(*p); ) 72338032Speter p++; 72438032Speter *p = '\0'; 72538032Speter 72638032Speter if (!setvendor(ep)) 72738032Speter syserr("invalid V line vendor code: \"%s\"", 72838032Speter ep); 72938032Speter } 73038032Speter break; 73138032Speter 73238032Speter case 'K': 733168515Sgshapiro expand(&bp[1], exbuf, sizeof(exbuf), e); 73438032Speter (void) makemapentry(exbuf); 73538032Speter break; 73638032Speter 73738032Speter case 'E': 73838032Speter p = strchr(bp, '='); 73938032Speter if (p != NULL) 74038032Speter *p++ = '\0'; 741157001Sgshapiro sm_setuserenv(&bp[1], p); 74238032Speter break; 74338032Speter 74464562Sgshapiro case 'X': /* mail filter */ 74590792Sgshapiro#if MILTER 74664562Sgshapiro milter_setup(&bp[1]); 74790792Sgshapiro#else /* MILTER */ 74890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 74990792Sgshapiro "Warning: Filter usage ('X') requires Milter support (-DMILTER)\n"); 75090792Sgshapiro#endif /* MILTER */ 75164562Sgshapiro break; 75264562Sgshapiro 75338032Speter default: 75438032Speter badline: 75538032Speter syserr("unknown configuration line \"%s\"", bp); 75638032Speter } 75738032Speter if (bp != buf) 75890792Sgshapiro sm_free(bp); /* XXX */ 75938032Speter } 76090792Sgshapiro if (sm_io_error(cf)) 76138032Speter { 76238032Speter syserr("I/O read error"); 76390792Sgshapiro finis(false, true, EX_OSFILE); 76438032Speter } 76590792Sgshapiro (void) sm_io_close(cf, SM_TIME_DEFAULT); 76638032Speter FileName = NULL; 76738032Speter 768285229Sgshapiro#if _FFR_BOUNCE_QUEUE 769285229Sgshapiro initbouncequeue(); 770285229Sgshapiro#endif 771285229Sgshapiro 77238032Speter /* initialize host maps from local service tables */ 77338032Speter inithostmaps(); 77438032Speter 77564562Sgshapiro /* initialize daemon (if not defined yet) */ 77664562Sgshapiro initdaemon(); 77764562Sgshapiro 77838032Speter /* determine if we need to do special name-server frotz */ 77938032Speter { 78038032Speter int nmaps; 78138032Speter char *maptype[MAXMAPSTACK]; 78238032Speter short mapreturn[MAXMAPACTIONS]; 78338032Speter 78438032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 78590792Sgshapiro UseNameServer = false; 78638032Speter if (nmaps > 0 && nmaps <= MAXMAPSTACK) 78738032Speter { 78838032Speter register int mapno; 78938032Speter 79090792Sgshapiro for (mapno = 0; mapno < nmaps && !UseNameServer; 79190792Sgshapiro mapno++) 79238032Speter { 79338032Speter if (strcmp(maptype[mapno], "dns") == 0) 79490792Sgshapiro UseNameServer = true; 79538032Speter } 79638032Speter } 79738032Speter } 798285229Sgshapiro setupdynmailers(); 79938032Speter} 800168515Sgshapiro 80190792Sgshapiro/* 80238032Speter** TRANSLATE_DOLLARS -- convert $x into internal form 80338032Speter** 80438032Speter** Actually does all appropriate pre-processing of a config line 80538032Speter** to turn it into internal form. 80638032Speter** 80738032Speter** Parameters: 808168515Sgshapiro** ibp -- the buffer to translate. 809168515Sgshapiro** obp -- where to put the translation; may be the same as obp 810168515Sgshapiro** bsp -- a pointer to the size of obp; will be updated if 811168515Sgshapiro** the buffer needs to be replaced. 81238032Speter** 81338032Speter** Returns: 814168515Sgshapiro** The buffer pointer; may differ from obp if the expansion 815168515Sgshapiro** is larger then *bsp, in which case this will point to 816168515Sgshapiro** malloc()ed memory which must be free()d by the caller. 81738032Speter*/ 81838032Speter 819168515Sgshapirochar * 820168515Sgshapirotranslate_dollars(ibp, obp, bsp) 821168515Sgshapiro char *ibp; 822168515Sgshapiro char *obp; 823168515Sgshapiro int *bsp; 82438032Speter{ 82538032Speter register char *p; 82638032Speter auto char *ep; 827168515Sgshapiro char *bp; 82838032Speter 829168515Sgshapiro if (tTd(37, 53)) 830168515Sgshapiro { 831168515Sgshapiro sm_dprintf("translate_dollars("); 832168515Sgshapiro xputs(sm_debug_file(), ibp); 833168515Sgshapiro sm_dprintf(")\n"); 834168515Sgshapiro } 835168515Sgshapiro 836168515Sgshapiro bp = quote_internal_chars(ibp, obp, bsp); 837168515Sgshapiro 83838032Speter for (p = bp; *p != '\0'; p++) 83938032Speter { 84038032Speter if (*p == '#' && p > bp && ConfigLevel >= 3) 84138032Speter { 84238032Speter register char *e; 84338032Speter 84438032Speter switch (*--p & 0377) 84538032Speter { 84638032Speter case MACROEXPAND: 84738032Speter /* it's from $# -- let it go through */ 84838032Speter p++; 84938032Speter break; 85038032Speter 85138032Speter case '\\': 85238032Speter /* it's backslash escaped */ 85390792Sgshapiro (void) sm_strlcpy(p, p + 1, strlen(p)); 85438032Speter break; 85538032Speter 85638032Speter default: 85764562Sgshapiro /* delete leading white space */ 858363466Sgshapiro while (SM_ISSPACE(*p) && 85938032Speter *p != '\n' && p > bp) 860168515Sgshapiro { 86138032Speter p--; 862168515Sgshapiro } 86338032Speter if ((e = strchr(++p, '\n')) != NULL) 86490792Sgshapiro (void) sm_strlcpy(p, e, strlen(p)); 86538032Speter else 86638032Speter *p-- = '\0'; 86738032Speter break; 86838032Speter } 86938032Speter continue; 87038032Speter } 87138032Speter 87238032Speter if (*p != '$' || p[1] == '\0') 87338032Speter continue; 87438032Speter 87538032Speter if (p[1] == '$') 87638032Speter { 87738032Speter /* actual dollar sign.... */ 87890792Sgshapiro (void) sm_strlcpy(p, p + 1, strlen(p)); 87938032Speter continue; 88038032Speter } 88138032Speter 88238032Speter /* convert to macro expansion character */ 88338032Speter *p++ = MACROEXPAND; 88438032Speter 88538032Speter /* special handling for $=, $~, $&, and $? */ 88638032Speter if (*p == '=' || *p == '~' || *p == '&' || *p == '?') 88738032Speter p++; 88838032Speter 88938032Speter /* convert macro name to code */ 89090792Sgshapiro *p = macid_parse(p, &ep); 89164562Sgshapiro if (ep != p + 1) 89290792Sgshapiro (void) sm_strlcpy(p + 1, ep, strlen(p + 1)); 89338032Speter } 89438032Speter 89538032Speter /* strip trailing white space from the line */ 896363466Sgshapiro while (--p > bp && SM_ISSPACE(*p)) 89738032Speter *p = '\0'; 898168515Sgshapiro 899168515Sgshapiro if (tTd(37, 53)) 900168515Sgshapiro { 901168515Sgshapiro sm_dprintf(" translate_dollars => "); 902168515Sgshapiro xputs(sm_debug_file(), bp); 903168515Sgshapiro sm_dprintf("\n"); 904168515Sgshapiro } 905168515Sgshapiro 906168515Sgshapiro return bp; 90738032Speter} 90890792Sgshapiro/* 90938032Speter** TOOMANY -- signal too many of some option 91038032Speter** 91138032Speter** Parameters: 91238032Speter** id -- the id of the error line 91338032Speter** maxcnt -- the maximum possible values 91438032Speter** 91538032Speter** Returns: 91638032Speter** none. 91738032Speter** 91838032Speter** Side Effects: 91938032Speter** gives a syserr. 92038032Speter*/ 92138032Speter 92264562Sgshapirostatic void 92338032Spetertoomany(id, maxcnt) 92438032Speter int id; 92538032Speter int maxcnt; 92638032Speter{ 92738032Speter syserr("too many %c lines, %d max", id, maxcnt); 92838032Speter} 92990792Sgshapiro/* 93038032Speter** FILECLASS -- read members of a class from a file 93138032Speter** 93238032Speter** Parameters: 93338032Speter** class -- class to define. 93438032Speter** filename -- name of file to read. 93538032Speter** fmt -- scanf string to use for match. 93694334Sgshapiro** ismap -- if set, this is a map lookup. 93738032Speter** safe -- if set, this is a safe read. 93838032Speter** optional -- if set, it is not an error for the file to 93938032Speter** not exist. 94038032Speter** 94138032Speter** Returns: 94238032Speter** none 94338032Speter** 94438032Speter** Side Effects: 94538032Speter** puts all lines in filename that match a scanf into 94638032Speter** the named class. 94738032Speter*/ 94838032Speter 94990792Sgshapiro/* 95090792Sgshapiro** Break up the match into words and add to class. 95190792Sgshapiro*/ 95290792Sgshapiro 95364562Sgshapirostatic void 95490792Sgshapiroparse_class_words(class, line) 95590792Sgshapiro int class; 95690792Sgshapiro char *line; 95790792Sgshapiro{ 95890792Sgshapiro while (line != NULL && *line != '\0') 95990792Sgshapiro { 96090792Sgshapiro register char *q; 96190792Sgshapiro 96290792Sgshapiro /* strip leading spaces */ 963363466Sgshapiro while (SM_ISSPACE(*line)) 96490792Sgshapiro line++; 96590792Sgshapiro if (*line == '\0') 96690792Sgshapiro break; 96790792Sgshapiro 96890792Sgshapiro /* find the end of the word */ 96990792Sgshapiro q = line; 970363466Sgshapiro while (*line != '\0' && !(SM_ISSPACE(*line))) 97190792Sgshapiro line++; 97290792Sgshapiro if (*line != '\0') 97390792Sgshapiro *line++ = '\0'; 97490792Sgshapiro 97590792Sgshapiro /* enter the word in the symbol table */ 97690792Sgshapiro setclass(class, q); 97790792Sgshapiro } 97890792Sgshapiro} 97990792Sgshapiro 98090792Sgshapirostatic void 98194334Sgshapirofileclass(class, filename, fmt, ismap, safe, optional) 98238032Speter int class; 98338032Speter char *filename; 98438032Speter char *fmt; 98594334Sgshapiro bool ismap; 98638032Speter bool safe; 98738032Speter bool optional; 98838032Speter{ 98990792Sgshapiro SM_FILE_T *f; 99064562Sgshapiro long sff; 99138032Speter pid_t pid; 99238032Speter register char *p; 99338032Speter char buf[MAXLINE]; 99438032Speter 99538032Speter if (tTd(37, 2)) 99690792Sgshapiro sm_dprintf("fileclass(%s, fmt=%s)\n", filename, fmt); 99738032Speter 99890792Sgshapiro if (*filename == '\0') 99938032Speter { 100090792Sgshapiro syserr("fileclass: missing file name"); 100190792Sgshapiro return; 100290792Sgshapiro } 100394334Sgshapiro else if (ismap) 100490792Sgshapiro { 100590792Sgshapiro int status = 0; 100690792Sgshapiro char *key; 100790792Sgshapiro char *mn; 100890792Sgshapiro char *cl, *spec; 100990792Sgshapiro STAB *mapclass; 101090792Sgshapiro MAP map; 101190792Sgshapiro 101290792Sgshapiro mn = newstr(macname(class)); 101390792Sgshapiro 101490792Sgshapiro key = filename; 101590792Sgshapiro 101694334Sgshapiro /* skip past key */ 101794334Sgshapiro if ((p = strchr(filename, '@')) == NULL) 101894334Sgshapiro { 101994334Sgshapiro /* should not happen */ 102094334Sgshapiro syserr("fileclass: bogus map specification"); 102194334Sgshapiro sm_free(mn); 102294334Sgshapiro return; 102394334Sgshapiro } 102494334Sgshapiro 102590792Sgshapiro /* skip past '@' */ 102690792Sgshapiro *p++ = '\0'; 102790792Sgshapiro cl = p; 102890792Sgshapiro 1029120256Sgshapiro#if LDAPMAP 103090792Sgshapiro if (strcmp(cl, "LDAP") == 0) 103190792Sgshapiro { 103290792Sgshapiro int n; 103390792Sgshapiro char *lc; 103490792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 103590792Sgshapiro char lcbuf[MAXLINE]; 103690792Sgshapiro 103790792Sgshapiro /* Get $j */ 1038168515Sgshapiro expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope); 103990792Sgshapiro if (jbuf[0] == '\0') 104090792Sgshapiro { 104190792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 1042168515Sgshapiro sizeof(jbuf)); 104390792Sgshapiro } 104490792Sgshapiro 104590792Sgshapiro /* impose the default schema */ 104690792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 104790792Sgshapiro if (lc == NULL) 104890792Sgshapiro lc = ""; 104990792Sgshapiro else 105090792Sgshapiro { 1051168515Sgshapiro expand(lc, lcbuf, sizeof(lcbuf), CurEnv); 105290792Sgshapiro lc = lcbuf; 105390792Sgshapiro } 105490792Sgshapiro 105590792Sgshapiro cl = "ldap"; 1056168515Sgshapiro n = sm_snprintf(buf, sizeof(buf), 1057132943Sgshapiro "-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=%s)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))) -v sendmailMTAClassValue,sendmailMTAClassSearch:FILTER:sendmailMTAClass,sendmailMTAClassURL:URL:sendmailMTAClass", 105890792Sgshapiro mn, lc, jbuf); 1059168515Sgshapiro if (n >= sizeof(buf)) 106090792Sgshapiro { 106190792Sgshapiro syserr("fileclass: F{%s}: Default LDAP string too long", 106290792Sgshapiro mn); 106390792Sgshapiro sm_free(mn); 106490792Sgshapiro return; 106590792Sgshapiro } 106690792Sgshapiro spec = buf; 106790792Sgshapiro } 106890792Sgshapiro else 1069120256Sgshapiro#endif /* LDAPMAP */ 107090792Sgshapiro { 107190792Sgshapiro if ((spec = strchr(cl, ':')) == NULL) 107290792Sgshapiro { 107390792Sgshapiro syserr("fileclass: F{%s}: missing map class", 107490792Sgshapiro mn); 107590792Sgshapiro sm_free(mn); 107690792Sgshapiro return; 107790792Sgshapiro } 107890792Sgshapiro *spec++ ='\0'; 107990792Sgshapiro } 108090792Sgshapiro 108190792Sgshapiro /* set up map structure */ 108290792Sgshapiro mapclass = stab(cl, ST_MAPCLASS, ST_FIND); 108390792Sgshapiro if (mapclass == NULL) 108490792Sgshapiro { 108590792Sgshapiro syserr("fileclass: F{%s}: class %s not available", 108690792Sgshapiro mn, cl); 108790792Sgshapiro sm_free(mn); 108890792Sgshapiro return; 108990792Sgshapiro } 1090168515Sgshapiro memset(&map, '\0', sizeof(map)); 109190792Sgshapiro map.map_class = &mapclass->s_mapclass; 109290792Sgshapiro map.map_mname = mn; 109390792Sgshapiro map.map_mflags |= MF_FILECLASS; 109490792Sgshapiro 109594334Sgshapiro if (tTd(37, 5)) 109694334Sgshapiro sm_dprintf("fileclass: F{%s}: map class %s, key %s, spec %s\n", 109794334Sgshapiro mn, cl, key, spec); 109894334Sgshapiro 109994334Sgshapiro 110090792Sgshapiro /* parse map spec */ 110190792Sgshapiro if (!map.map_class->map_parse(&map, spec)) 110290792Sgshapiro { 110390792Sgshapiro /* map_parse() showed the error already */ 110490792Sgshapiro sm_free(mn); 110590792Sgshapiro return; 110690792Sgshapiro } 110790792Sgshapiro map.map_mflags |= MF_VALID; 110890792Sgshapiro 110990792Sgshapiro /* open map */ 111090792Sgshapiro if (map.map_class->map_open(&map, O_RDONLY)) 111190792Sgshapiro { 111290792Sgshapiro map.map_mflags |= MF_OPEN; 111390792Sgshapiro map.map_pid = getpid(); 111490792Sgshapiro } 111590792Sgshapiro else 111690792Sgshapiro { 111790792Sgshapiro if (!optional && 111890792Sgshapiro !bitset(MF_OPTIONAL, map.map_mflags)) 111990792Sgshapiro syserr("fileclass: F{%s}: map open failed", 112090792Sgshapiro mn); 112190792Sgshapiro sm_free(mn); 112290792Sgshapiro return; 112390792Sgshapiro } 112490792Sgshapiro 112590792Sgshapiro /* lookup */ 112690792Sgshapiro p = (*map.map_class->map_lookup)(&map, key, NULL, &status); 112790792Sgshapiro if (status != EX_OK && status != EX_NOTFOUND) 112890792Sgshapiro { 112990792Sgshapiro if (!optional) 113090792Sgshapiro syserr("fileclass: F{%s}: map lookup failed", 113190792Sgshapiro mn); 113290792Sgshapiro p = NULL; 113390792Sgshapiro } 113490792Sgshapiro 113590792Sgshapiro /* use the results */ 113690792Sgshapiro if (p != NULL) 113790792Sgshapiro parse_class_words(class, p); 113890792Sgshapiro 113990792Sgshapiro /* close map */ 114090792Sgshapiro map.map_mflags |= MF_CLOSING; 114190792Sgshapiro map.map_class->map_close(&map); 114290792Sgshapiro map.map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 114390792Sgshapiro sm_free(mn); 114490792Sgshapiro return; 114590792Sgshapiro } 114690792Sgshapiro else if (filename[0] == '|') 114790792Sgshapiro { 114838032Speter auto int fd; 114938032Speter int i; 115038032Speter char *argv[MAXPV + 1]; 115138032Speter 115238032Speter i = 0; 115390792Sgshapiro for (p = strtok(&filename[1], " \t"); 115490792Sgshapiro p != NULL && i < MAXPV; 115590792Sgshapiro p = strtok(NULL, " \t")) 115638032Speter argv[i++] = p; 115738032Speter argv[i] = NULL; 115838032Speter pid = prog_open(argv, &fd, CurEnv); 115938032Speter if (pid < 0) 116038032Speter f = NULL; 116138032Speter else 116290792Sgshapiro f = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 116390792Sgshapiro (void *) &fd, SM_IO_RDONLY, NULL); 116438032Speter } 116538032Speter else 116638032Speter { 116738032Speter pid = -1; 116838032Speter sff = SFF_REGONLY; 116964562Sgshapiro if (!bitnset(DBS_CLASSFILEINUNSAFEDIRPATH, DontBlameSendmail)) 117038032Speter sff |= SFF_SAFEDIRPATH; 117164562Sgshapiro if (!bitnset(DBS_LINKEDCLASSFILEINWRITABLEDIR, 117264562Sgshapiro DontBlameSendmail)) 117338032Speter sff |= SFF_NOWLINK; 117438032Speter if (safe) 117538032Speter sff |= SFF_OPENASROOT; 117690792Sgshapiro else if (RealUid == 0) 117790792Sgshapiro sff |= SFF_ROOTOK; 117838032Speter if (DontLockReadFiles) 117938032Speter sff |= SFF_NOLOCK; 118038032Speter f = safefopen(filename, O_RDONLY, 0, sff); 118138032Speter } 118238032Speter if (f == NULL) 118338032Speter { 118438032Speter if (!optional) 118564562Sgshapiro syserr("fileclass: cannot open '%s'", filename); 118638032Speter return; 118738032Speter } 118838032Speter 1189249729Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0) 119038032Speter { 119164562Sgshapiro#if SCANF 119238032Speter char wordbuf[MAXLINE + 1]; 1193363466Sgshapiro#endif 119438032Speter 119538032Speter if (buf[0] == '#') 119638032Speter continue; 119764562Sgshapiro#if SCANF 119890792Sgshapiro if (sm_io_sscanf(buf, fmt, wordbuf) != 1) 119938032Speter continue; 120038032Speter p = wordbuf; 120164562Sgshapiro#else /* SCANF */ 120238032Speter p = buf; 120364562Sgshapiro#endif /* SCANF */ 120438032Speter 120590792Sgshapiro parse_class_words(class, p); 120690792Sgshapiro 120738032Speter /* 120890792Sgshapiro ** If anything else is added here, 120990792Sgshapiro ** check if the '@' map case above 121090792Sgshapiro ** needs the code as well. 121138032Speter */ 121238032Speter } 121338032Speter 121490792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 121538032Speter if (pid > 0) 121638032Speter (void) waitfor(pid); 121738032Speter} 1218285229Sgshapiro 1219285229Sgshapiro#if _FFR_RCPTFLAGS 1220285229Sgshapiro/* first character for dynamically created mailers */ 1221285229Sgshapirostatic char dynmailerp = ' '; 1222285229Sgshapiro 1223285229Sgshapiro/* list of first characters for cf defined mailers */ 1224285229Sgshapirostatic char frst[MAXMAILERS + 1]; 1225285229Sgshapiro 122690792Sgshapiro/* 1227285229Sgshapiro** SETUPDYNMAILERS -- find a char that isn't used as first element of any 1228285229Sgshapiro** mailer name. 1229285229Sgshapiro** 1230285229Sgshapiro** Parameters: 1231285229Sgshapiro** none 1232285229Sgshapiro** 1233285229Sgshapiro** Returns: 1234285229Sgshapiro** none 1235363466Sgshapiro** 1236285229Sgshapiro** Note: space is not valid in cf defined mailers hence the function 1237285229Sgshapiro** will always find a char. It's not nice, but this is for 1238285229Sgshapiro** internal names only. 1239285229Sgshapiro*/ 1240285229Sgshapiro 1241285229Sgshapirovoid 1242285229Sgshapirosetupdynmailers() 1243285229Sgshapiro{ 1244285229Sgshapiro int i; 1245285229Sgshapiro char pp[] = "YXZ0123456789ABCDEFGHIJKLMNOPQRSTUVWyxzabcfghijkmnoqtuvw "; 1246285229Sgshapiro 1247285229Sgshapiro frst[MAXMAILERS] = '\0'; 1248285229Sgshapiro for (i = 0; i < strlen(pp); i++) 1249285229Sgshapiro { 1250285229Sgshapiro if (strchr(frst, pp[i]) == NULL) 1251285229Sgshapiro { 1252285229Sgshapiro dynmailerp = pp[i]; 1253285229Sgshapiro if (tTd(25, 8)) 1254285229Sgshapiro sm_dprintf("dynmailerp=%c\n", dynmailerp); 1255285229Sgshapiro return; 1256285229Sgshapiro } 1257285229Sgshapiro } 1258285229Sgshapiro 1259285229Sgshapiro /* NOTREACHED */ 1260285229Sgshapiro SM_ASSERT(0); 1261285229Sgshapiro} 1262285229Sgshapiro 1263285229Sgshapiro/* 1264285229Sgshapiro** NEWMODMAILER -- Create a new mailer with modifications 1265285229Sgshapiro** 1266285229Sgshapiro** Parameters: 1267285229Sgshapiro** rcpt -- current RCPT 1268285229Sgshapiro** fl -- flag to set 1269285229Sgshapiro** 1270285229Sgshapiro** Returns: 1271285229Sgshapiro** true iff successful. 1272285229Sgshapiro** 1273285229Sgshapiro** Note: this creates a copy of the mailer for the rcpt and 1274285229Sgshapiro** modifies exactly one flag. It does not work 1275285229Sgshapiro** for multiple flags! 1276285229Sgshapiro*/ 1277285229Sgshapiro 1278285229Sgshapirobool 1279285229Sgshapironewmodmailer(rcpt, fl) 1280285229Sgshapiro ADDRESS *rcpt; 1281285229Sgshapiro int fl; 1282285229Sgshapiro{ 1283285229Sgshapiro int idx; 1284285229Sgshapiro struct mailer *m; 1285285229Sgshapiro STAB *s; 1286285229Sgshapiro char mname[256]; 1287285229Sgshapiro 1288285229Sgshapiro SM_REQUIRE(rcpt != NULL); 1289285229Sgshapiro if (rcpt->q_mailer == NULL) 1290285229Sgshapiro return false; 1291285229Sgshapiro if (tTd(25, 8)) 1292285229Sgshapiro sm_dprintf("newmodmailer: rcpt=%s\n", rcpt->q_paddr); 1293285229Sgshapiro SM_REQUIRE(rcpt->q_mailer->m_name != NULL); 1294285229Sgshapiro SM_REQUIRE(rcpt->q_mailer->m_name[0] != '\0'); 1295285229Sgshapiro sm_strlcpy(mname, rcpt->q_mailer->m_name, sizeof(mname)); 1296285229Sgshapiro mname[0] = dynmailerp; 1297285229Sgshapiro if (tTd(25, 8)) 1298285229Sgshapiro sm_dprintf("newmodmailer: name=%s\n", mname); 1299285229Sgshapiro s = stab(mname, ST_MAILER, ST_ENTER); 1300285229Sgshapiro if (s->s_mailer != NULL) 1301285229Sgshapiro { 1302285229Sgshapiro idx = s->s_mailer->m_mno; 1303285229Sgshapiro if (tTd(25, 6)) 1304285229Sgshapiro sm_dprintf("newmodmailer: found idx=%d\n", idx); 1305285229Sgshapiro } 1306285229Sgshapiro else 1307285229Sgshapiro { 1308285229Sgshapiro idx = rcpt->q_mailer->m_mno; 1309285229Sgshapiro idx += MAXMAILERS; 1310285229Sgshapiro if (tTd(25, 6)) 1311285229Sgshapiro sm_dprintf("newmodmailer: idx=%d\n", idx); 1312285229Sgshapiro if (idx > SM_ARRAY_SIZE(Mailer)) 1313285229Sgshapiro return false; 1314285229Sgshapiro } 1315285229Sgshapiro 1316285229Sgshapiro m = Mailer[idx]; 1317285229Sgshapiro if (m == NULL) 1318285229Sgshapiro m = (struct mailer *) xalloc(sizeof(*m)); 1319285229Sgshapiro memset((char *) m, '\0', sizeof(*m)); 1320285229Sgshapiro STRUCTCOPY(*rcpt->q_mailer, *m); 1321285229Sgshapiro Mailer[idx] = m; 1322285229Sgshapiro 1323285229Sgshapiro /* "modify" the mailer */ 1324285229Sgshapiro setbitn(bitidx(fl), m->m_flags); 1325285229Sgshapiro rcpt->q_mailer = m; 1326285229Sgshapiro m->m_mno = idx; 1327285229Sgshapiro m->m_name = newstr(mname); 1328285229Sgshapiro if (tTd(25, 1)) 1329285229Sgshapiro sm_dprintf("newmodmailer: mailer[%d]=%s %p\n", 1330285229Sgshapiro idx, Mailer[idx]->m_name, Mailer[idx]); 1331285229Sgshapiro 1332285229Sgshapiro return true; 1333285229Sgshapiro} 1334285229Sgshapiro 1335285229Sgshapiro#endif /* _FFR_RCPTFLAGS */ 1336285229Sgshapiro 1337285229Sgshapiro/* 133838032Speter** MAKEMAILER -- define a new mailer. 133938032Speter** 134038032Speter** Parameters: 134138032Speter** line -- description of mailer. This is in labeled 134238032Speter** fields. The fields are: 134338032Speter** A -- the argv for this mailer 134438032Speter** C -- the character set for MIME conversions 134538032Speter** D -- the directory to run in 134638032Speter** E -- the eol string 134738032Speter** F -- the flags associated with the mailer 134838032Speter** L -- the maximum line length 134938032Speter** M -- the maximum message size 135038032Speter** N -- the niceness at which to run 135138032Speter** P -- the path to the mailer 135290792Sgshapiro** Q -- the queue group for the mailer 135338032Speter** R -- the recipient rewriting set 135438032Speter** S -- the sender rewriting set 135538032Speter** T -- the mailer type (for DSNs) 135638032Speter** U -- the uid to run as 135764562Sgshapiro** W -- the time to wait at the end 135873188Sgshapiro** m -- maximum messages per connection 135990792Sgshapiro** r -- maximum number of recipients per message 136073188Sgshapiro** / -- new root directory 136138032Speter** The first word is the canonical name of the mailer. 136238032Speter** 136338032Speter** Returns: 136438032Speter** none. 136538032Speter** 136638032Speter** Side Effects: 136738032Speter** enters the mailer into the mailer table. 136838032Speter*/ 136938032Speter 1370285229Sgshapiro 137138032Spetervoid 137238032Spetermakemailer(line) 137338032Speter char *line; 137438032Speter{ 137538032Speter register char *p; 137638032Speter register struct mailer *m; 137738032Speter register STAB *s; 137838032Speter int i; 137938032Speter char fcode; 138038032Speter auto char *endp; 138190792Sgshapiro static int nextmailer = 0; /* "free" index into Mailer struct */ 138238032Speter 138338032Speter /* allocate a mailer and set up defaults */ 1384168515Sgshapiro m = (struct mailer *) xalloc(sizeof(*m)); 1385168515Sgshapiro memset((char *) m, '\0', sizeof(*m)); 138690792Sgshapiro errno = 0; /* avoid bogus error text */ 138738032Speter 138838032Speter /* collect the mailer name */ 138990792Sgshapiro for (p = line; 1390363466Sgshapiro *p != '\0' && *p != ',' && !(SM_ISSPACE(*p)); 139190792Sgshapiro p++) 139238032Speter continue; 139338032Speter if (*p != '\0') 139438032Speter *p++ = '\0'; 139538032Speter if (line[0] == '\0') 139671345Sgshapiro { 139738032Speter syserr("name required for mailer"); 139871345Sgshapiro return; 139971345Sgshapiro } 140038032Speter m->m_name = newstr(line); 1401285229Sgshapiro#if _FFR_RCPTFLAGS 1402285229Sgshapiro frst[nextmailer] = line[0]; 1403285229Sgshapiro#endif 140494334Sgshapiro m->m_qgrp = NOQGRP; 1405132943Sgshapiro m->m_uid = NO_UID; 1406132943Sgshapiro m->m_gid = NO_GID; 140738032Speter 140838032Speter /* now scan through and assign info from the fields */ 140938032Speter while (*p != '\0') 141038032Speter { 141138032Speter auto char *delimptr; 141238032Speter 141390792Sgshapiro while (*p != '\0' && 1414363466Sgshapiro (*p == ',' || (SM_ISSPACE(*p)))) 141538032Speter p++; 141638032Speter 141738032Speter /* p now points to field code */ 141838032Speter fcode = *p; 141938032Speter while (*p != '\0' && *p != '=' && *p != ',') 142038032Speter p++; 142138032Speter if (*p++ != '=') 142238032Speter { 142338032Speter syserr("mailer %s: `=' expected", m->m_name); 142438032Speter return; 142538032Speter } 1426363466Sgshapiro while (SM_ISSPACE(*p)) 142738032Speter p++; 142838032Speter 142938032Speter /* p now points to the field body */ 143038032Speter p = munchstring(p, &delimptr, ','); 143138032Speter 143238032Speter /* install the field into the mailer struct */ 143338032Speter switch (fcode) 143438032Speter { 143538032Speter case 'P': /* pathname */ 143690792Sgshapiro if (*p != '\0') /* error is issued below */ 143771345Sgshapiro m->m_mailer = newstr(p); 143838032Speter break; 143938032Speter 144038032Speter case 'F': /* flags */ 144138032Speter for (; *p != '\0'; p++) 144290792Sgshapiro { 1443363466Sgshapiro if (!(SM_ISSPACE(*p))) 144490792Sgshapiro { 144590792Sgshapiro if (*p == M_INTERNAL) 144690792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 144790792Sgshapiro "WARNING: mailer=%s, flag=%c deprecated", 144890792Sgshapiro m->m_name, *p); 144971345Sgshapiro setbitn(bitidx(*p), m->m_flags); 145090792Sgshapiro } 145190792Sgshapiro } 145238032Speter break; 145338032Speter 145438032Speter case 'S': /* sender rewriting ruleset */ 145538032Speter case 'R': /* recipient rewriting ruleset */ 145638032Speter i = strtorwset(p, &endp, ST_ENTER); 145738032Speter if (i < 0) 145838032Speter return; 145938032Speter if (fcode == 'S') 146038032Speter m->m_sh_rwset = m->m_se_rwset = i; 146138032Speter else 146238032Speter m->m_rh_rwset = m->m_re_rwset = i; 146338032Speter 146438032Speter p = endp; 146538032Speter if (*p++ == '/') 146638032Speter { 146738032Speter i = strtorwset(p, NULL, ST_ENTER); 146838032Speter if (i < 0) 146938032Speter return; 147038032Speter if (fcode == 'S') 147138032Speter m->m_sh_rwset = i; 147238032Speter else 147338032Speter m->m_rh_rwset = i; 147438032Speter } 147538032Speter break; 147638032Speter 147738032Speter case 'E': /* end of line string */ 147838032Speter if (*p == '\0') 147938032Speter syserr("mailer %s: null end-of-line string", 148038032Speter m->m_name); 148171345Sgshapiro else 148271345Sgshapiro m->m_eol = newstr(p); 148338032Speter break; 148438032Speter 148538032Speter case 'A': /* argument vector */ 148690792Sgshapiro if (*p != '\0') /* error is issued below */ 148771345Sgshapiro m->m_argv = makeargv(p); 148838032Speter break; 148938032Speter 149038032Speter case 'M': /* maximum message size */ 149138032Speter m->m_maxsize = atol(p); 149238032Speter break; 149338032Speter 149464562Sgshapiro case 'm': /* maximum messages per connection */ 149564562Sgshapiro m->m_maxdeliveries = atoi(p); 149664562Sgshapiro break; 149764562Sgshapiro 149864562Sgshapiro case 'r': /* max recipient per envelope */ 149964562Sgshapiro m->m_maxrcpt = atoi(p); 150064562Sgshapiro break; 150164562Sgshapiro 150238032Speter case 'L': /* maximum line length */ 150338032Speter m->m_linelimit = atoi(p); 150438032Speter if (m->m_linelimit < 0) 150538032Speter m->m_linelimit = 0; 150638032Speter break; 150738032Speter 150838032Speter case 'N': /* run niceness */ 150938032Speter m->m_nice = atoi(p); 151038032Speter break; 151138032Speter 151238032Speter case 'D': /* working directory */ 151338032Speter if (*p == '\0') 151438032Speter syserr("mailer %s: null working directory", 151538032Speter m->m_name); 151671345Sgshapiro else 151771345Sgshapiro m->m_execdir = newstr(p); 151838032Speter break; 151938032Speter 152038032Speter case 'C': /* default charset */ 152138032Speter if (*p == '\0') 152238032Speter syserr("mailer %s: null charset", m->m_name); 152371345Sgshapiro else 152471345Sgshapiro m->m_defcharset = newstr(p); 152538032Speter break; 152638032Speter 152790792Sgshapiro case 'Q': /* queue for this mailer */ 152890792Sgshapiro if (*p == '\0') 152990792Sgshapiro { 153090792Sgshapiro syserr("mailer %s: null queue", m->m_name); 153190792Sgshapiro break; 153290792Sgshapiro } 153390792Sgshapiro s = stab(p, ST_QUEUE, ST_FIND); 153490792Sgshapiro if (s == NULL) 153590792Sgshapiro syserr("mailer %s: unknown queue %s", 153690792Sgshapiro m->m_name, p); 153790792Sgshapiro else 153890792Sgshapiro m->m_qgrp = s->s_quegrp->qg_index; 153990792Sgshapiro break; 154090792Sgshapiro 154138032Speter case 'T': /* MTA-Name/Address/Diagnostic types */ 154238032Speter /* extract MTA name type; default to "dns" */ 154338032Speter m->m_mtatype = newstr(p); 154438032Speter p = strchr(m->m_mtatype, '/'); 154538032Speter if (p != NULL) 154638032Speter { 154738032Speter *p++ = '\0'; 154838032Speter if (*p == '\0') 154938032Speter p = NULL; 155038032Speter } 155138032Speter if (*m->m_mtatype == '\0') 155238032Speter m->m_mtatype = "dns"; 155338032Speter 155438032Speter /* extract address type; default to "rfc822" */ 155538032Speter m->m_addrtype = p; 155638032Speter if (p != NULL) 155738032Speter p = strchr(p, '/'); 155838032Speter if (p != NULL) 155938032Speter { 156038032Speter *p++ = '\0'; 156138032Speter if (*p == '\0') 156238032Speter p = NULL; 156338032Speter } 156438032Speter if (m->m_addrtype == NULL || *m->m_addrtype == '\0') 156538032Speter m->m_addrtype = "rfc822"; 156638032Speter 156738032Speter /* extract diagnostic type; default to "smtp" */ 156838032Speter m->m_diagtype = p; 156938032Speter if (m->m_diagtype == NULL || *m->m_diagtype == '\0') 157038032Speter m->m_diagtype = "smtp"; 157138032Speter break; 157238032Speter 157338032Speter case 'U': /* user id */ 157438032Speter if (isascii(*p) && !isdigit(*p)) 157538032Speter { 157638032Speter char *q = p; 157738032Speter struct passwd *pw; 157838032Speter 157938032Speter while (*p != '\0' && isascii(*p) && 1580285229Sgshapiro# if _FFR_DOTTED_USERNAMES 1581285229Sgshapiro (isalnum(*p) || strchr(SM_PWN_CHARS, *p) != NULL)) 1582363466Sgshapiro# else 158338032Speter (isalnum(*p) || strchr("-_", *p) != NULL)) 1584363466Sgshapiro# endif 158538032Speter p++; 1586363466Sgshapiro while (SM_ISSPACE(*p)) 158738032Speter *p++ = '\0'; 158838032Speter if (*p != '\0') 158938032Speter *p++ = '\0'; 159038032Speter if (*q == '\0') 159171345Sgshapiro { 159238032Speter syserr("mailer %s: null user name", 159338032Speter m->m_name); 159471345Sgshapiro break; 159571345Sgshapiro } 159638032Speter pw = sm_getpwnam(q); 159738032Speter if (pw == NULL) 159871345Sgshapiro { 159938032Speter syserr("readcf: mailer U= flag: unknown user %s", q); 160071345Sgshapiro break; 160171345Sgshapiro } 160238032Speter else 160338032Speter { 160438032Speter m->m_uid = pw->pw_uid; 160538032Speter m->m_gid = pw->pw_gid; 160638032Speter } 160738032Speter } 160838032Speter else 160938032Speter { 161038032Speter auto char *q; 161138032Speter 161238032Speter m->m_uid = strtol(p, &q, 0); 161338032Speter p = q; 1614363466Sgshapiro while (SM_ISSPACE(*p)) 161538032Speter p++; 161638032Speter if (*p != '\0') 161738032Speter p++; 161838032Speter } 1619363466Sgshapiro while (SM_ISSPACE(*p)) 162038032Speter p++; 162138032Speter if (*p == '\0') 162238032Speter break; 162338032Speter if (isascii(*p) && !isdigit(*p)) 162438032Speter { 162538032Speter char *q = p; 162638032Speter struct group *gr; 162738032Speter 1628285229Sgshapiro while (isascii(*p) && 1629285229Sgshapiro (isalnum(*p) || strchr(SM_PWN_CHARS, *p) != NULL)) 163038032Speter p++; 163138032Speter *p++ = '\0'; 163238032Speter if (*q == '\0') 163371345Sgshapiro { 163438032Speter syserr("mailer %s: null group name", 163538032Speter m->m_name); 163671345Sgshapiro break; 163771345Sgshapiro } 163838032Speter gr = getgrnam(q); 163938032Speter if (gr == NULL) 164071345Sgshapiro { 164138032Speter syserr("readcf: mailer U= flag: unknown group %s", q); 164271345Sgshapiro break; 164371345Sgshapiro } 164438032Speter else 164538032Speter m->m_gid = gr->gr_gid; 164638032Speter } 164738032Speter else 164838032Speter { 164938032Speter m->m_gid = strtol(p, NULL, 0); 165038032Speter } 165138032Speter break; 165264562Sgshapiro 165364562Sgshapiro case 'W': /* wait timeout */ 165464562Sgshapiro m->m_wait = convtime(p, 's'); 165564562Sgshapiro break; 165664562Sgshapiro 165764562Sgshapiro case '/': /* new root directory */ 165864562Sgshapiro if (*p == '\0') 165964562Sgshapiro syserr("mailer %s: null root directory", 166064562Sgshapiro m->m_name); 166164562Sgshapiro else 166264562Sgshapiro m->m_rootdir = newstr(p); 166364562Sgshapiro break; 166464562Sgshapiro 166564562Sgshapiro default: 166664562Sgshapiro syserr("M%s: unknown mailer equate %c=", 166764562Sgshapiro m->m_name, fcode); 166864562Sgshapiro break; 166938032Speter } 167038032Speter 167138032Speter p = delimptr; 167238032Speter } 167338032Speter 167490792Sgshapiro#if !HASRRESVPORT 167590792Sgshapiro if (bitnset(M_SECURE_PORT, m->m_flags)) 167690792Sgshapiro { 167790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 167890792Sgshapiro "M%s: Warning: F=%c set on system that doesn't support rresvport()\n", 167990792Sgshapiro m->m_name, M_SECURE_PORT); 168090792Sgshapiro } 168190792Sgshapiro#endif /* !HASRRESVPORT */ 168290792Sgshapiro 168390792Sgshapiro#if !HASNICE 168490792Sgshapiro if (m->m_nice != 0) 168590792Sgshapiro { 168690792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 168790792Sgshapiro "M%s: Warning: N= set on system that doesn't support nice()\n", 168890792Sgshapiro m->m_name); 168990792Sgshapiro } 169090792Sgshapiro#endif /* !HASNICE */ 169190792Sgshapiro 169238032Speter /* do some rationality checking */ 169338032Speter if (m->m_argv == NULL) 169438032Speter { 169538032Speter syserr("M%s: A= argument required", m->m_name); 169638032Speter return; 169738032Speter } 169838032Speter if (m->m_mailer == NULL) 169938032Speter { 170038032Speter syserr("M%s: P= argument required", m->m_name); 170138032Speter return; 170238032Speter } 170338032Speter 170490792Sgshapiro if (nextmailer >= MAXMAILERS) 170538032Speter { 170638032Speter syserr("too many mailers defined (%d max)", MAXMAILERS); 170738032Speter return; 170838032Speter } 170938032Speter 171064562Sgshapiro if (m->m_maxrcpt <= 0) 171164562Sgshapiro m->m_maxrcpt = DEFAULT_MAX_RCPT; 171264562Sgshapiro 171338032Speter /* do some heuristic cleanup for back compatibility */ 171438032Speter if (bitnset(M_LIMITS, m->m_flags)) 171538032Speter { 171638032Speter if (m->m_linelimit == 0) 171738032Speter m->m_linelimit = SMTPLINELIM; 171838032Speter if (ConfigLevel < 2) 171938032Speter setbitn(M_7BITS, m->m_flags); 172038032Speter } 172138032Speter 172264562Sgshapiro if (strcmp(m->m_mailer, "[TCP]") == 0) 172338032Speter { 172490792Sgshapiro syserr("M%s: P=[TCP] must be replaced by P=[IPC]", m->m_name); 172571345Sgshapiro return; 172638032Speter } 172738032Speter 172890792Sgshapiro if (strcmp(m->m_mailer, "[IPC]") == 0) 172938032Speter { 173064562Sgshapiro /* Use the second argument for host or path to socket */ 173164562Sgshapiro if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || 173264562Sgshapiro m->m_argv[1][0] == '\0') 173364562Sgshapiro { 173464562Sgshapiro syserr("M%s: too few parameters for %s mailer", 173564562Sgshapiro m->m_name, m->m_mailer); 173671345Sgshapiro return; 173764562Sgshapiro } 173866494Sgshapiro if (strcmp(m->m_argv[0], "TCP") != 0 173964562Sgshapiro#if NETUNIX 174066494Sgshapiro && strcmp(m->m_argv[0], "FILE") != 0 1741363466Sgshapiro#endif 174264562Sgshapiro ) 174364562Sgshapiro { 174490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 174590792Sgshapiro "M%s: Warning: first argument in %s mailer must be %s\n", 174690792Sgshapiro m->m_name, m->m_mailer, 174764562Sgshapiro#if NETUNIX 174890792Sgshapiro "TCP or FILE" 1749363466Sgshapiro#else 175090792Sgshapiro "TCP" 1751363466Sgshapiro#endif 175290792Sgshapiro ); 175364562Sgshapiro } 175490792Sgshapiro if (m->m_mtatype == NULL) 175590792Sgshapiro m->m_mtatype = "dns"; 175690792Sgshapiro if (m->m_addrtype == NULL) 175790792Sgshapiro m->m_addrtype = "rfc822"; 175890792Sgshapiro if (m->m_diagtype == NULL) 175990792Sgshapiro { 176090792Sgshapiro if (m->m_argv[0] != NULL && 176190792Sgshapiro strcmp(m->m_argv[0], "FILE") == 0) 176290792Sgshapiro m->m_diagtype = "x-unix"; 176390792Sgshapiro else 176490792Sgshapiro m->m_diagtype = "smtp"; 176590792Sgshapiro } 176664562Sgshapiro } 176764562Sgshapiro else if (strcmp(m->m_mailer, "[FILE]") == 0) 176864562Sgshapiro { 176938032Speter /* Use the second argument for filename */ 177038032Speter if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || 177138032Speter m->m_argv[2] != NULL) 177238032Speter { 177338032Speter syserr("M%s: too %s parameters for [FILE] mailer", 177438032Speter m->m_name, 177538032Speter (m->m_argv[0] == NULL || 177638032Speter m->m_argv[1] == NULL) ? "few" : "many"); 177771345Sgshapiro return; 177838032Speter } 177938032Speter else if (strcmp(m->m_argv[0], "FILE") != 0) 178038032Speter { 178138032Speter syserr("M%s: first argument in [FILE] mailer must be FILE", 178238032Speter m->m_name); 178371345Sgshapiro return; 178438032Speter } 178538032Speter } 178638032Speter 178738032Speter if (m->m_eol == NULL) 178838032Speter { 178938032Speter char **pp; 179038032Speter 179138032Speter /* default for SMTP is \r\n; use \n for local delivery */ 179238032Speter for (pp = m->m_argv; *pp != NULL; pp++) 179338032Speter { 179438032Speter for (p = *pp; *p != '\0'; ) 179538032Speter { 179638032Speter if ((*p++ & 0377) == MACROEXPAND && *p == 'u') 179738032Speter break; 179838032Speter } 179938032Speter if (*p != '\0') 180038032Speter break; 180138032Speter } 180238032Speter if (*pp == NULL) 180338032Speter m->m_eol = "\r\n"; 180438032Speter else 180538032Speter m->m_eol = "\n"; 180638032Speter } 180738032Speter 180838032Speter /* enter the mailer into the symbol table */ 180938032Speter s = stab(m->m_name, ST_MAILER, ST_ENTER); 181038032Speter if (s->s_mailer != NULL) 181138032Speter { 181238032Speter i = s->s_mailer->m_mno; 181390792Sgshapiro sm_free(s->s_mailer); /* XXX */ 181438032Speter } 181538032Speter else 181638032Speter { 181790792Sgshapiro i = nextmailer++; 181838032Speter } 181938032Speter Mailer[i] = s->s_mailer = m; 182038032Speter m->m_mno = i; 182138032Speter} 182290792Sgshapiro/* 182338032Speter** MUNCHSTRING -- translate a string into internal form. 182438032Speter** 182538032Speter** Parameters: 182638032Speter** p -- the string to munch. 182738032Speter** delimptr -- if non-NULL, set to the pointer of the 182838032Speter** field delimiter character. 182938032Speter** delim -- the delimiter for the field. 183038032Speter** 183138032Speter** Returns: 183238032Speter** the munched string. 183364562Sgshapiro** 183464562Sgshapiro** Side Effects: 183564562Sgshapiro** the munched string is a local static buffer. 183664562Sgshapiro** it must be copied before the function is called again. 183738032Speter*/ 183838032Speter 183938032Speterchar * 184038032Spetermunchstring(p, delimptr, delim) 184138032Speter register char *p; 184238032Speter char **delimptr; 184338032Speter int delim; 184438032Speter{ 184538032Speter register char *q; 184690792Sgshapiro bool backslash = false; 184790792Sgshapiro bool quotemode = false; 184838032Speter static char buf[MAXLINE]; 184938032Speter 1850168515Sgshapiro for (q = buf; *p != '\0' && q < &buf[sizeof(buf) - 1]; p++) 185138032Speter { 185238032Speter if (backslash) 185338032Speter { 185438032Speter /* everything is roughly literal */ 185590792Sgshapiro backslash = false; 185638032Speter switch (*p) 185738032Speter { 185838032Speter case 'r': /* carriage return */ 185938032Speter *q++ = '\r'; 186038032Speter continue; 186138032Speter 186238032Speter case 'n': /* newline */ 186338032Speter *q++ = '\n'; 186438032Speter continue; 186538032Speter 186638032Speter case 'f': /* form feed */ 186738032Speter *q++ = '\f'; 186838032Speter continue; 186938032Speter 187038032Speter case 'b': /* backspace */ 187138032Speter *q++ = '\b'; 187238032Speter continue; 187338032Speter } 187438032Speter *q++ = *p; 187538032Speter } 187638032Speter else 187738032Speter { 187838032Speter if (*p == '\\') 187990792Sgshapiro backslash = true; 188038032Speter else if (*p == '"') 188138032Speter quotemode = !quotemode; 188238032Speter else if (quotemode || *p != delim) 188338032Speter *q++ = *p; 188438032Speter else 188538032Speter break; 188638032Speter } 188738032Speter } 188838032Speter 188938032Speter if (delimptr != NULL) 189038032Speter *delimptr = p; 189138032Speter *q++ = '\0'; 189264562Sgshapiro return buf; 189338032Speter} 189490792Sgshapiro/* 189590792Sgshapiro** EXTRQUOTSTR -- extract a (quoted) string. 189690792Sgshapiro** 189790792Sgshapiro** This routine deals with quoted (") strings and escaped 189890792Sgshapiro** spaces (\\ ). 189990792Sgshapiro** 190090792Sgshapiro** Parameters: 190190792Sgshapiro** p -- source string. 190290792Sgshapiro** delimptr -- if non-NULL, set to the pointer of the 190390792Sgshapiro** field delimiter character. 190490792Sgshapiro** delimbuf -- delimiters for the field. 190590792Sgshapiro** st -- if non-NULL, store the return value (whether the 190690792Sgshapiro** string was correctly quoted) here. 190790792Sgshapiro** 190890792Sgshapiro** Returns: 190990792Sgshapiro** the extracted string. 191090792Sgshapiro** 191190792Sgshapiro** Side Effects: 191290792Sgshapiro** the returned string is a local static buffer. 191390792Sgshapiro** it must be copied before the function is called again. 191490792Sgshapiro*/ 191590792Sgshapiro 191690792Sgshapirostatic char * 191790792Sgshapiroextrquotstr(p, delimptr, delimbuf, st) 191890792Sgshapiro register char *p; 191990792Sgshapiro char **delimptr; 192090792Sgshapiro char *delimbuf; 192190792Sgshapiro bool *st; 192290792Sgshapiro{ 192390792Sgshapiro register char *q; 192490792Sgshapiro bool backslash = false; 192590792Sgshapiro bool quotemode = false; 192690792Sgshapiro static char buf[MAXLINE]; 192790792Sgshapiro 1928168515Sgshapiro for (q = buf; *p != '\0' && q < &buf[sizeof(buf) - 1]; p++) 192990792Sgshapiro { 193090792Sgshapiro if (backslash) 193190792Sgshapiro { 193290792Sgshapiro backslash = false; 193390792Sgshapiro if (*p != ' ') 193490792Sgshapiro *q++ = '\\'; 193590792Sgshapiro } 193690792Sgshapiro if (*p == '\\') 193790792Sgshapiro backslash = true; 193890792Sgshapiro else if (*p == '"') 193990792Sgshapiro quotemode = !quotemode; 194090792Sgshapiro else if (quotemode || 194190792Sgshapiro strchr(delimbuf, (int) *p) == NULL) 194290792Sgshapiro *q++ = *p; 194390792Sgshapiro else 194490792Sgshapiro break; 194590792Sgshapiro } 194690792Sgshapiro 194790792Sgshapiro if (delimptr != NULL) 194890792Sgshapiro *delimptr = p; 194990792Sgshapiro *q++ = '\0'; 195090792Sgshapiro if (st != NULL) 195190792Sgshapiro *st = !(quotemode || backslash); 195290792Sgshapiro return buf; 195390792Sgshapiro} 195490792Sgshapiro/* 195538032Speter** MAKEARGV -- break up a string into words 195638032Speter** 195738032Speter** Parameters: 195838032Speter** p -- the string to break up. 195938032Speter** 196038032Speter** Returns: 196138032Speter** a char **argv (dynamically allocated) 196238032Speter** 196338032Speter** Side Effects: 196438032Speter** munges p. 196538032Speter*/ 196638032Speter 196764562Sgshapirostatic char ** 196838032Spetermakeargv(p) 196938032Speter register char *p; 197038032Speter{ 197138032Speter char *q; 197238032Speter int i; 197338032Speter char **avp; 197438032Speter char *argv[MAXPV + 1]; 197538032Speter 197638032Speter /* take apart the words */ 197738032Speter i = 0; 197838032Speter while (*p != '\0' && i < MAXPV) 197938032Speter { 198038032Speter q = p; 1981363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 198238032Speter p++; 1983363466Sgshapiro while (SM_ISSPACE(*p)) 198438032Speter *p++ = '\0'; 198538032Speter argv[i++] = newstr(q); 198638032Speter } 198738032Speter argv[i++] = NULL; 198838032Speter 198938032Speter /* now make a copy of the argv */ 1990168515Sgshapiro avp = (char **) xalloc(sizeof(*avp) * i); 1991168515Sgshapiro memmove((char *) avp, (char *) argv, sizeof(*avp) * i); 199238032Speter 199364562Sgshapiro return avp; 199438032Speter} 199590792Sgshapiro/* 199638032Speter** PRINTRULES -- print rewrite rules (for debugging) 199738032Speter** 199838032Speter** Parameters: 199938032Speter** none. 200038032Speter** 200138032Speter** Returns: 200238032Speter** none. 200338032Speter** 200438032Speter** Side Effects: 200538032Speter** prints rewrite rules. 200638032Speter*/ 200738032Speter 200838032Spetervoid 200938032Speterprintrules() 201038032Speter{ 201138032Speter register struct rewrite *rwp; 201238032Speter register int ruleset; 201338032Speter 201438032Speter for (ruleset = 0; ruleset < 10; ruleset++) 201538032Speter { 201638032Speter if (RewriteRules[ruleset] == NULL) 201738032Speter continue; 2018132943Sgshapiro sm_dprintf("\n----Rule Set %d:", ruleset); 201938032Speter 202038032Speter for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 202138032Speter { 2022132943Sgshapiro sm_dprintf("\nLHS:"); 2023132943Sgshapiro printav(sm_debug_file(), rwp->r_lhs); 2024132943Sgshapiro sm_dprintf("RHS:"); 2025132943Sgshapiro printav(sm_debug_file(), rwp->r_rhs); 202638032Speter } 202738032Speter } 202838032Speter} 202990792Sgshapiro/* 203038032Speter** PRINTMAILER -- print mailer structure (for debugging) 203138032Speter** 203238032Speter** Parameters: 2033132943Sgshapiro** fp -- output file 203438032Speter** m -- the mailer to print 203538032Speter** 203638032Speter** Returns: 203738032Speter** none. 203838032Speter*/ 203938032Speter 204038032Spetervoid 2041132943Sgshapiroprintmailer(fp, m) 2042132943Sgshapiro SM_FILE_T *fp; 204338032Speter register MAILER *m; 204438032Speter{ 204538032Speter int j; 204638032Speter 2047132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 204890792Sgshapiro "mailer %d (%s): P=%s S=", m->m_mno, m->m_name, 204990792Sgshapiro m->m_mailer); 205064562Sgshapiro if (RuleSetNames[m->m_se_rwset] == NULL) 2051132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d/", 205290792Sgshapiro m->m_se_rwset); 205364562Sgshapiro else 2054132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s/", 205590792Sgshapiro RuleSetNames[m->m_se_rwset]); 205664562Sgshapiro if (RuleSetNames[m->m_sh_rwset] == NULL) 2057132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d R=", 205890792Sgshapiro m->m_sh_rwset); 205964562Sgshapiro else 2060132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s R=", 206190792Sgshapiro RuleSetNames[m->m_sh_rwset]); 206264562Sgshapiro if (RuleSetNames[m->m_re_rwset] == NULL) 2063132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d/", 206490792Sgshapiro m->m_re_rwset); 206564562Sgshapiro else 2066132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s/", 206790792Sgshapiro RuleSetNames[m->m_re_rwset]); 206864562Sgshapiro if (RuleSetNames[m->m_rh_rwset] == NULL) 2069132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d ", 207090792Sgshapiro m->m_rh_rwset); 207164562Sgshapiro else 2072132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s ", 207390792Sgshapiro RuleSetNames[m->m_rh_rwset]); 2074132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "M=%ld U=%d:%d F=", 207590792Sgshapiro m->m_maxsize, (int) m->m_uid, (int) m->m_gid); 207638032Speter for (j = '\0'; j <= '\177'; j++) 207738032Speter if (bitnset(j, m->m_flags)) 2078132943Sgshapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, j); 2079132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " L=%d E=", 208090792Sgshapiro m->m_linelimit); 2081132943Sgshapiro xputs(fp, m->m_eol); 208238032Speter if (m->m_defcharset != NULL) 2083132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " C=%s", 208490792Sgshapiro m->m_defcharset); 2085132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " T=%s/%s/%s", 208690792Sgshapiro m->m_mtatype == NULL 208790792Sgshapiro ? "<undefined>" : m->m_mtatype, 208890792Sgshapiro m->m_addrtype == NULL 208990792Sgshapiro ? "<undefined>" : m->m_addrtype, 209090792Sgshapiro m->m_diagtype == NULL 209190792Sgshapiro ? "<undefined>" : m->m_diagtype); 2092132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " r=%d", m->m_maxrcpt); 209338032Speter if (m->m_argv != NULL) 209438032Speter { 209538032Speter char **a = m->m_argv; 209638032Speter 2097132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " A="); 209838032Speter while (*a != NULL) 209938032Speter { 210038032Speter if (a != m->m_argv) 2101132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 210290792Sgshapiro " "); 2103132943Sgshapiro xputs(fp, *a++); 210438032Speter } 210538032Speter } 2106132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "\n"); 210738032Speter} 2108285229Sgshapiro 2109285229Sgshapiro#if STARTTLS 2110285229Sgshapirostatic struct ssl_options 2111285229Sgshapiro{ 2112285229Sgshapiro const char *sslopt_name; /* name of the flag */ 2113285229Sgshapiro long sslopt_bits; /* bits to set/clear */ 2114285229Sgshapiro} SSL_Option[] = 2115285229Sgshapiro{ 2116285229Sgshapiro/* Workaround for bugs are turned on by default (as well as some others) */ 2117285229Sgshapiro#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG 2118285229Sgshapiro { "SSL_OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG }, 2119285229Sgshapiro#endif 2120285229Sgshapiro#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG 2121285229Sgshapiro { "SSL_OP_NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG }, 2122285229Sgshapiro#endif 2123285229Sgshapiro#ifdef SSL_OP_LEGACY_SERVER_CONNECT 2124285229Sgshapiro { "SSL_OP_LEGACY_SERVER_CONNECT", SSL_OP_LEGACY_SERVER_CONNECT }, 2125285229Sgshapiro#endif 2126285229Sgshapiro#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 2127285229Sgshapiro { "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG }, 2128285229Sgshapiro#endif 2129285229Sgshapiro#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 2130285229Sgshapiro { "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG }, 2131285229Sgshapiro#endif 2132285229Sgshapiro#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 2133285229Sgshapiro { "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER }, 2134285229Sgshapiro#endif 2135285229Sgshapiro#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING 2136285229Sgshapiro { "SSL_OP_MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING }, 2137285229Sgshapiro#endif 2138285229Sgshapiro#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG 2139285229Sgshapiro { "SSL_OP_SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG }, 2140285229Sgshapiro#endif 2141285229Sgshapiro#ifdef SSL_OP_TLS_D5_BUG 2142285229Sgshapiro { "SSL_OP_TLS_D5_BUG", SSL_OP_TLS_D5_BUG }, 2143285229Sgshapiro#endif 2144285229Sgshapiro#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG 2145285229Sgshapiro { "SSL_OP_TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG }, 2146285229Sgshapiro#endif 2147285229Sgshapiro#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 2148285229Sgshapiro { "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS }, 2149285229Sgshapiro#endif 2150285229Sgshapiro#ifdef SSL_OP_ALL 2151285229Sgshapiro { "SSL_OP_ALL", SSL_OP_ALL }, 2152285229Sgshapiro#endif 2153285229Sgshapiro#ifdef SSL_OP_NO_QUERY_MTU 2154285229Sgshapiro { "SSL_OP_NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU }, 2155285229Sgshapiro#endif 2156285229Sgshapiro#ifdef SSL_OP_COOKIE_EXCHANGE 2157285229Sgshapiro { "SSL_OP_COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE }, 2158285229Sgshapiro#endif 2159285229Sgshapiro#ifdef SSL_OP_NO_TICKET 2160285229Sgshapiro { "SSL_OP_NO_TICKET", SSL_OP_NO_TICKET }, 2161285229Sgshapiro#endif 2162285229Sgshapiro#ifdef SSL_OP_CISCO_ANYCONNECT 2163285229Sgshapiro { "SSL_OP_CISCO_ANYCONNECT", SSL_OP_CISCO_ANYCONNECT }, 2164285229Sgshapiro#endif 2165285229Sgshapiro#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 2166285229Sgshapiro { "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION }, 2167285229Sgshapiro#endif 2168285229Sgshapiro#ifdef SSL_OP_NO_COMPRESSION 2169285229Sgshapiro { "SSL_OP_NO_COMPRESSION", SSL_OP_NO_COMPRESSION }, 2170285229Sgshapiro#endif 2171285229Sgshapiro#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 2172285229Sgshapiro { "SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION }, 2173285229Sgshapiro#endif 2174285229Sgshapiro#ifdef SSL_OP_SINGLE_ECDH_USE 2175285229Sgshapiro { "SSL_OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE }, 2176285229Sgshapiro#endif 2177285229Sgshapiro#ifdef SSL_OP_SINGLE_DH_USE 2178285229Sgshapiro { "SSL_OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE }, 2179285229Sgshapiro#endif 2180285229Sgshapiro#ifdef SSL_OP_EPHEMERAL_RSA 2181285229Sgshapiro { "SSL_OP_EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA }, 2182285229Sgshapiro#endif 2183285229Sgshapiro#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE 2184285229Sgshapiro { "SSL_OP_CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE }, 2185285229Sgshapiro#endif 2186285229Sgshapiro#ifdef SSL_OP_TLS_ROLLBACK_BUG 2187285229Sgshapiro { "SSL_OP_TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG }, 2188285229Sgshapiro#endif 2189285229Sgshapiro#ifdef SSL_OP_NO_SSLv2 2190285229Sgshapiro { "SSL_OP_NO_SSLv2", SSL_OP_NO_SSLv2 }, 2191285229Sgshapiro#endif 2192285229Sgshapiro#ifdef SSL_OP_NO_SSLv3 2193285229Sgshapiro { "SSL_OP_NO_SSLv3", SSL_OP_NO_SSLv3 }, 2194285229Sgshapiro#endif 2195285229Sgshapiro#ifdef SSL_OP_NO_TLSv1 2196285229Sgshapiro { "SSL_OP_NO_TLSv1", SSL_OP_NO_TLSv1 }, 2197285229Sgshapiro#endif 2198363466Sgshapiro#ifdef SSL_OP_NO_TLSv1_3 2199363466Sgshapiro { "SSL_OP_NO_TLSv1_3", SSL_OP_NO_TLSv1_3 }, 2200363466Sgshapiro#endif 2201285229Sgshapiro#ifdef SSL_OP_NO_TLSv1_2 2202285229Sgshapiro { "SSL_OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2 }, 2203285229Sgshapiro#endif 2204285229Sgshapiro#ifdef SSL_OP_NO_TLSv1_1 2205285229Sgshapiro { "SSL_OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1 }, 2206285229Sgshapiro#endif 2207285229Sgshapiro#ifdef SSL_OP_PKCS1_CHECK_1 2208285229Sgshapiro { "SSL_OP_PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 }, 2209285229Sgshapiro#endif 2210285229Sgshapiro#ifdef SSL_OP_PKCS1_CHECK_2 2211285229Sgshapiro { "SSL_OP_PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 }, 2212285229Sgshapiro#endif 2213285229Sgshapiro#ifdef SSL_OP_NETSCAPE_CA_DN_BUG 2214285229Sgshapiro { "SSL_OP_NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG }, 2215285229Sgshapiro#endif 2216285229Sgshapiro#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 2217285229Sgshapiro { "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG }, 2218285229Sgshapiro#endif 2219285229Sgshapiro#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG 2220285229Sgshapiro { "SSL_OP_CRYPTOPRO_TLSEXT_BUG", SSL_OP_CRYPTOPRO_TLSEXT_BUG }, 2221285229Sgshapiro#endif 2222285229Sgshapiro#ifdef SSL_OP_TLSEXT_PADDING 2223285229Sgshapiro { "SSL_OP_TLSEXT_PADDING", SSL_OP_TLSEXT_PADDING }, 2224285229Sgshapiro#endif 2225363466Sgshapiro#ifdef SSL_OP_NO_RENEGOTIATION 2226363466Sgshapiro { "SSL_OP_NO_RENEGOTIATION", SSL_OP_NO_RENEGOTIATION }, 2227363466Sgshapiro#endif 2228363466Sgshapiro#ifdef SSL_OP_NO_ANTI_REPLAY 2229363466Sgshapiro { "SSL_OP_NO_ANTI_REPLAY", SSL_OP_NO_ANTI_REPLAY }, 2230363466Sgshapiro#endif 2231363466Sgshapiro#ifdef SSL_OP_ALLOW_NO_DHE_KEX 2232363466Sgshapiro { "SSL_OP_ALLOW_NO_DHE_KEX", SSL_OP_ALLOW_NO_DHE_KEX }, 2233363466Sgshapiro#endif 2234363466Sgshapiro#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC 2235363466Sgshapiro { "SSL_OP_NO_ENCRYPT_THEN_MAC", SSL_OP_NO_ENCRYPT_THEN_MAC }, 2236363466Sgshapiro#endif 2237363466Sgshapiro#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT 2238363466Sgshapiro { "SSL_OP_ENABLE_MIDDLEBOX_COMPAT", SSL_OP_ENABLE_MIDDLEBOX_COMPAT }, 2239363466Sgshapiro#endif 2240363466Sgshapiro#ifdef SSL_OP_PRIORITIZE_CHACHA 2241363466Sgshapiro { "SSL_OP_PRIORITIZE_CHACHA", SSL_OP_PRIORITIZE_CHACHA }, 2242363466Sgshapiro#endif 2243285229Sgshapiro { NULL, 0 } 2244285229Sgshapiro}; 2245285229Sgshapiro 224690792Sgshapiro/* 2247285229Sgshapiro** READSSLOPTIONS -- read SSL_OP_* values 2248285229Sgshapiro** 2249285229Sgshapiro** Parameters: 2250285229Sgshapiro** opt -- name of option (can be NULL) 2251285229Sgshapiro** val -- string with SSL_OP_* values or hex value 2252285229Sgshapiro** delim -- end of string (e.g., '\0' or ';') 2253285229Sgshapiro** pssloptions -- return value (output) 2254285229Sgshapiro** 2255285229Sgshapiro** Returns: 2256285229Sgshapiro** 0 on success. 2257285229Sgshapiro*/ 2258285229Sgshapiro 2259285229Sgshapiro#define SSLOPERR_NAN 1 2260285229Sgshapiro#define SSLOPERR_NOTFOUND 2 2261285229Sgshapiro 2262363466Sgshapirostatic int readssloptions __P((char *, char *, unsigned long *, int )); 2263363466Sgshapiro 2264285229Sgshapirostatic int 2265285229Sgshapiroreadssloptions(opt, val, pssloptions, delim) 2266285229Sgshapiro char *opt; 2267285229Sgshapiro char *val; 2268285229Sgshapiro unsigned long *pssloptions; 2269285229Sgshapiro int delim; 2270285229Sgshapiro{ 2271285229Sgshapiro char *p; 2272285229Sgshapiro int ret; 2273285229Sgshapiro 2274285229Sgshapiro ret = 0; 2275285229Sgshapiro for (p = val; *p != '\0' && *p != delim; ) 2276285229Sgshapiro { 2277285229Sgshapiro bool clearmode; 2278285229Sgshapiro char *q; 2279285229Sgshapiro unsigned long sslopt_val; 2280285229Sgshapiro struct ssl_options *sslopts; 2281285229Sgshapiro 2282285229Sgshapiro while (*p == ' ') 2283285229Sgshapiro p++; 2284285229Sgshapiro if (*p == '\0') 2285285229Sgshapiro break; 2286285229Sgshapiro clearmode = false; 2287285229Sgshapiro if (*p == '-' || *p == '+') 2288285229Sgshapiro clearmode = *p++ == '-'; 2289285229Sgshapiro q = p; 2290285229Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p)) && *p != ',') 2291285229Sgshapiro p++; 2292285229Sgshapiro if (*p != '\0') 2293285229Sgshapiro *p++ = '\0'; 2294285229Sgshapiro sslopt_val = 0; 2295285229Sgshapiro if (isdigit(*q)) 2296285229Sgshapiro { 2297285229Sgshapiro char *end; 2298285229Sgshapiro 2299285229Sgshapiro sslopt_val = strtoul(q, &end, 0); 2300285229Sgshapiro 2301285229Sgshapiro /* not a complete "syntax" check but good enough */ 2302285229Sgshapiro if (end == q) 2303285229Sgshapiro { 2304285229Sgshapiro errno = 0; 2305285229Sgshapiro ret = SSLOPERR_NAN; 2306285229Sgshapiro if (opt != NULL) 2307285229Sgshapiro syserr("readcf: %s option value %s not a number", 2308285229Sgshapiro opt, q); 2309285229Sgshapiro sslopt_val = 0; 2310285229Sgshapiro } 2311285229Sgshapiro } 2312285229Sgshapiro else 2313285229Sgshapiro { 2314285229Sgshapiro for (sslopts = SSL_Option; 2315285229Sgshapiro sslopts->sslopt_name != NULL; sslopts++) 2316285229Sgshapiro { 2317285229Sgshapiro if (sm_strcasecmp(q, sslopts->sslopt_name) == 0) 2318285229Sgshapiro { 2319285229Sgshapiro sslopt_val = sslopts->sslopt_bits; 2320285229Sgshapiro break; 2321285229Sgshapiro } 2322285229Sgshapiro } 2323285229Sgshapiro if (sslopts->sslopt_name == NULL) 2324285229Sgshapiro { 2325285229Sgshapiro errno = 0; 2326285229Sgshapiro ret = SSLOPERR_NOTFOUND; 2327285229Sgshapiro if (opt != NULL) 2328285229Sgshapiro syserr("readcf: %s option value %s unrecognized", 2329285229Sgshapiro opt, q); 2330285229Sgshapiro } 2331285229Sgshapiro } 2332285229Sgshapiro if (sslopt_val != 0) 2333285229Sgshapiro { 2334285229Sgshapiro if (clearmode) 2335285229Sgshapiro *pssloptions &= ~sslopt_val; 2336285229Sgshapiro else 2337285229Sgshapiro *pssloptions |= sslopt_val; 2338285229Sgshapiro } 2339285229Sgshapiro } 2340285229Sgshapiro return ret; 2341285229Sgshapiro} 2342285229Sgshapiro 2343285229Sgshapiro/* 2344285229Sgshapiro** GET_TLS_SE_OPTIONS -- get TLS session options (from ruleset) 2345285229Sgshapiro** 2346285229Sgshapiro** Parameters: 2347285229Sgshapiro** e -- envelope 2348285229Sgshapiro** ssl -- TLS session context 2349363466Sgshapiro** tlsi_ctx -- TLS info context 2350285229Sgshapiro** srv -- server? 2351285229Sgshapiro** 2352285229Sgshapiro** Returns: 2353285229Sgshapiro** 0 on success. 2354285229Sgshapiro*/ 2355285229Sgshapiro 2356285229Sgshapiroint 2357363466Sgshapiroget_tls_se_options(e, ssl, tlsi_ctx, srv) 2358285229Sgshapiro ENVELOPE *e; 2359285229Sgshapiro SSL *ssl; 2360363466Sgshapiro tlsi_ctx_T *tlsi_ctx; 2361285229Sgshapiro bool srv; 2362285229Sgshapiro{ 2363285229Sgshapiro bool saveQuickAbort, saveSuprErrs, ok; 2364285229Sgshapiro char *optionlist, *opt, *val; 2365285229Sgshapiro char *keyfile, *certfile; 2366285229Sgshapiro size_t len, i; 2367285229Sgshapiro int ret; 2368285229Sgshapiro 2369285229Sgshapiro# define who (srv ? "server" : "client") 2370285229Sgshapiro# define NAME_C_S macvalue(macid(srv ? "{client_name}" : "{server_name}"), e) 2371285229Sgshapiro# define ADDR_C_S macvalue(macid(srv ? "{client_addr}" : "{server_addr}"), e) 2372285229Sgshapiro# define WHICH srv ? "srv" : "clt" 2373285229Sgshapiro 2374285229Sgshapiro ret = 0; 2375285229Sgshapiro keyfile = certfile = opt = val = NULL; 2376285229Sgshapiro saveQuickAbort = QuickAbort; 2377285229Sgshapiro saveSuprErrs = SuprErrs; 2378285229Sgshapiro SuprErrs = true; 2379285229Sgshapiro QuickAbort = false; 2380285229Sgshapiro 2381285229Sgshapiro optionlist = NULL; 2382285229Sgshapiro ok = rscheck(srv ? "tls_srv_features" : "tls_clt_features", 2383285229Sgshapiro NAME_C_S, ADDR_C_S, e, 2384285229Sgshapiro RSF_RMCOMM|RSF_ADDR|RSF_STRING, 2385285229Sgshapiro 5, NULL, NOQID, NULL, &optionlist) == EX_OK; 2386285229Sgshapiro if (!ok && LogLevel > 8) 2387285229Sgshapiro { 2388285229Sgshapiro sm_syslog(LOG_NOTICE, NOQID, 2389285229Sgshapiro "rscheck(tls_%s_features)=failed, relay=%s [%s], errors=%d", 2390285229Sgshapiro WHICH, NAME_C_S, ADDR_C_S, 2391285229Sgshapiro Errors); 2392285229Sgshapiro } 2393285229Sgshapiro QuickAbort = saveQuickAbort; 2394285229Sgshapiro SuprErrs = saveSuprErrs; 2395285229Sgshapiro if (ok && LogLevel > 9) 2396285229Sgshapiro { 2397285229Sgshapiro sm_syslog(LOG_INFO, NOQID, 2398285229Sgshapiro "tls_%s_features=%s, relay=%s [%s]", 2399285229Sgshapiro WHICH, optionlist, NAME_C_S, ADDR_C_S); 2400285229Sgshapiro } 2401285229Sgshapiro if (!ok || optionlist == NULL || (len = strlen(optionlist)) < 2) 2402285229Sgshapiro { 2403285229Sgshapiro if (LogLevel > 9) 2404285229Sgshapiro sm_syslog(LOG_INFO, NOQID, 2405285229Sgshapiro "tls_%s_features=empty, relay=%s [%s]", 2406363466Sgshapiro WHICH, NAME_C_S, ADDR_C_S); 2407285229Sgshapiro 2408285229Sgshapiro return ok ? 0 : 1; 2409285229Sgshapiro } 2410285229Sgshapiro 2411285229Sgshapiro i = 0; 2412285229Sgshapiro if (optionlist[0] == '"' && optionlist[len - 1] == '"') 2413285229Sgshapiro { 2414285229Sgshapiro optionlist[0] = ' '; 2415285229Sgshapiro optionlist[--len] = '\0'; 2416285229Sgshapiro if (len <= 2) 2417285229Sgshapiro { 2418285229Sgshapiro if (LogLevel > 9 && len > 1) 2419285229Sgshapiro sm_syslog(LOG_INFO, NOQID, 2420285229Sgshapiro "tls_%s_features=too_short, relay=%s [%s]", 2421363466Sgshapiro WHICH, NAME_C_S, ADDR_C_S); 2422285229Sgshapiro 2423285229Sgshapiro /* this is not treated as error! */ 2424285229Sgshapiro return 0; 2425285229Sgshapiro } 2426285229Sgshapiro i = 1; 2427285229Sgshapiro } 2428285229Sgshapiro 2429285229Sgshapiro# define INVALIDSYNTAX \ 2430285229Sgshapiro do { \ 2431285229Sgshapiro if (LogLevel > 7) \ 2432285229Sgshapiro sm_syslog(LOG_INFO, NOQID, \ 2433285229Sgshapiro "tls_%s_features=invalid_syntax, opt=%s, relay=%s [%s]", \ 2434363466Sgshapiro WHICH, opt, NAME_C_S, ADDR_C_S); \ 2435285229Sgshapiro return -1; \ 2436285229Sgshapiro } while (0) 2437285229Sgshapiro 2438285229Sgshapiro# define CHECKLEN \ 2439285229Sgshapiro do { \ 2440285229Sgshapiro if (i >= len) \ 2441285229Sgshapiro INVALIDSYNTAX; \ 2442285229Sgshapiro } while (0) 2443285229Sgshapiro 2444285229Sgshapiro# define SKIPWS \ 2445285229Sgshapiro do { \ 2446285229Sgshapiro while (i < len && SM_ISSPACE(optionlist[i])) \ 2447285229Sgshapiro ++i; \ 2448285229Sgshapiro CHECKLEN; \ 2449285229Sgshapiro } while (0) 2450285229Sgshapiro 2451285229Sgshapiro /* parse and handle opt=val; */ 2452285229Sgshapiro do { 2453285229Sgshapiro char sep; 2454285229Sgshapiro 2455285229Sgshapiro SKIPWS; 2456285229Sgshapiro opt = optionlist + i; 2457285229Sgshapiro sep = '='; 2458285229Sgshapiro while (i < len && optionlist[i] != sep 2459285229Sgshapiro && optionlist[i] != '\0' && !SM_ISSPACE(optionlist[i])) 2460285229Sgshapiro ++i; 2461285229Sgshapiro CHECKLEN; 2462285229Sgshapiro while (i < len && SM_ISSPACE(optionlist[i])) 2463285229Sgshapiro optionlist[i++] = '\0'; 2464285229Sgshapiro CHECKLEN; 2465285229Sgshapiro if (optionlist[i] != sep) 2466285229Sgshapiro INVALIDSYNTAX; 2467285229Sgshapiro optionlist[i++] = '\0'; 2468285229Sgshapiro 2469285229Sgshapiro SKIPWS; 2470285229Sgshapiro val = optionlist + i; 2471285229Sgshapiro sep = ';'; 2472285229Sgshapiro while (i < len && optionlist[i] != sep && optionlist[i] != '\0') 2473285229Sgshapiro ++i; 2474285229Sgshapiro if (optionlist[i] != '\0') 2475285229Sgshapiro { 2476285229Sgshapiro CHECKLEN; 2477285229Sgshapiro optionlist[i++] = '\0'; 2478285229Sgshapiro } 2479285229Sgshapiro 2480285229Sgshapiro if (LogLevel > 13) 2481285229Sgshapiro sm_syslog(LOG_DEBUG, NOQID, 2482285229Sgshapiro "tls_%s_features=parsed, %s=%s, relay=%s [%s]", 2483285229Sgshapiro WHICH, opt, val, NAME_C_S, ADDR_C_S); 2484285229Sgshapiro 2485285229Sgshapiro if (sm_strcasecmp(opt, "options") == 0) 2486285229Sgshapiro { 2487285229Sgshapiro unsigned long ssloptions; 2488285229Sgshapiro 2489285229Sgshapiro ssloptions = 0; 2490285229Sgshapiro ret = readssloptions(NULL, val, &ssloptions, ';'); 2491285229Sgshapiro if (ret == 0) 2492285229Sgshapiro (void) SSL_set_options(ssl, (long) ssloptions); 2493285229Sgshapiro else if (LogLevel > 8) 2494285229Sgshapiro { 2495285229Sgshapiro sm_syslog(LOG_WARNING, NOQID, 2496285229Sgshapiro "tls_%s_features=%s, error=%s, relay=%s [%s]", 2497285229Sgshapiro WHICH, val, 2498285229Sgshapiro (ret == SSLOPERR_NAN) ? "not a number" : 2499285229Sgshapiro ((ret == SSLOPERR_NOTFOUND) ? "SSL_OP not found" : 2500285229Sgshapiro "unknown"), 2501285229Sgshapiro NAME_C_S, ADDR_C_S); 2502285229Sgshapiro } 2503285229Sgshapiro } 2504285229Sgshapiro else if (sm_strcasecmp(opt, "cipherlist") == 0) 2505285229Sgshapiro { 2506285229Sgshapiro if (SSL_set_cipher_list(ssl, val) <= 0) 2507285229Sgshapiro { 2508285229Sgshapiro ret = 1; 2509285229Sgshapiro if (LogLevel > 7) 2510285229Sgshapiro { 2511285229Sgshapiro sm_syslog(LOG_WARNING, NOQID, 2512285229Sgshapiro "STARTTLS=%s, error: SSL_set_cipher_list(%s) failed", 2513285229Sgshapiro who, val); 2514285229Sgshapiro 2515363466Sgshapiro tlslogerr(LOG_WARNING, 9, who); 2516285229Sgshapiro } 2517285229Sgshapiro } 2518285229Sgshapiro } 2519363466Sgshapiro else if (sm_strcasecmp(opt, "flags") == 0) 2520363466Sgshapiro { 2521363466Sgshapiro char *p; 2522363466Sgshapiro 2523363466Sgshapiro for (p = val; *p != '\0'; p++) 2524363466Sgshapiro { 2525363466Sgshapiro if (isascii(*p) && isalnum(*p)) 2526363466Sgshapiro setbitn(bitidx(*p), tlsi_ctx->tlsi_flags); 2527363466Sgshapiro } 2528363466Sgshapiro } 2529285229Sgshapiro else if (sm_strcasecmp(opt, "keyfile") == 0) 2530285229Sgshapiro keyfile = val; 2531285229Sgshapiro else if (sm_strcasecmp(opt, "certfile") == 0) 2532285229Sgshapiro certfile = val; 2533285229Sgshapiro else 2534285229Sgshapiro { 2535285229Sgshapiro ret = 1; 2536285229Sgshapiro if (LogLevel > 7) 2537285229Sgshapiro { 2538285229Sgshapiro sm_syslog(LOG_INFO, NOQID, 2539285229Sgshapiro "tls_%s_features=unknown_option, opt=%s, relay=%s [%s]", 2540363466Sgshapiro WHICH, opt, NAME_C_S, ADDR_C_S); 2541285229Sgshapiro } 2542285229Sgshapiro } 2543285229Sgshapiro 2544285229Sgshapiro } while (optionlist[i] != '\0' && i < len); 2545285229Sgshapiro 2546285229Sgshapiro /* need cert and key before we can use the options */ 2547285229Sgshapiro /* does not implement the "," hack for 2nd cert/key pair */ 2548285229Sgshapiro if (keyfile != NULL && certfile != NULL) 2549285229Sgshapiro { 2550285229Sgshapiro load_certkey(ssl, srv, certfile, keyfile); 2551285229Sgshapiro keyfile = certfile = NULL; 2552285229Sgshapiro } 2553285229Sgshapiro else if (keyfile != NULL || certfile != NULL) 2554285229Sgshapiro { 2555285229Sgshapiro ret = 1; 2556285229Sgshapiro if (LogLevel > 7) 2557285229Sgshapiro { 2558285229Sgshapiro sm_syslog(LOG_INFO, NOQID, 2559285229Sgshapiro "tls_%s_features=only_one_of_CertFile/KeyFile_specified, relay=%s [%s]", 2560363466Sgshapiro WHICH, NAME_C_S, ADDR_C_S); 2561285229Sgshapiro } 2562285229Sgshapiro } 2563285229Sgshapiro 2564285229Sgshapiro return ret; 2565285229Sgshapiro# undef who 2566285229Sgshapiro# undef NAME_C_S 2567285229Sgshapiro# undef ADDR_C_S 2568285229Sgshapiro# undef WHICH 2569285229Sgshapiro} 2570285229Sgshapiro#endif /* STARTTLS */ 2571285229Sgshapiro 2572285229Sgshapiro/* 257338032Speter** SETOPTION -- set global processing option 257438032Speter** 257538032Speter** Parameters: 257638032Speter** opt -- option name. 257738032Speter** val -- option value (as a text string). 257838032Speter** safe -- set if this came from a configuration file. 257938032Speter** Some options (if set from the command line) will 258038032Speter** reset the user id to avoid security problems. 258138032Speter** sticky -- if set, don't let other setoptions override 258238032Speter** this value. 258338032Speter** e -- the main envelope. 258438032Speter** 258538032Speter** Returns: 258638032Speter** none. 258738032Speter** 258838032Speter** Side Effects: 258938032Speter** Sets options as implied by the arguments. 259038032Speter*/ 259138032Speter 259264562Sgshapirostatic BITMAP256 StickyOpt; /* set if option is stuck */ 259338032Speter 259438032Speter#if NAMED_BIND 259538032Speter 259664562Sgshapirostatic struct resolverflags 259738032Speter{ 259838032Speter char *rf_name; /* name of the flag */ 259938032Speter long rf_bits; /* bits to set/clear */ 260038032Speter} ResolverFlags[] = 260138032Speter{ 260238032Speter { "debug", RES_DEBUG }, 260338032Speter { "aaonly", RES_AAONLY }, 260438032Speter { "usevc", RES_USEVC }, 260538032Speter { "primary", RES_PRIMARY }, 260638032Speter { "igntc", RES_IGNTC }, 260738032Speter { "recurse", RES_RECURSE }, 260838032Speter { "defnames", RES_DEFNAMES }, 260938032Speter { "stayopen", RES_STAYOPEN }, 261038032Speter { "dnsrch", RES_DNSRCH }, 261190792Sgshapiro# ifdef RES_USE_INET6 261290792Sgshapiro { "use_inet6", RES_USE_INET6 }, 2613363466Sgshapiro# endif 2614363466Sgshapiro# ifdef RES_USE_EDNS0 2615363466Sgshapiro { "use_edns0", RES_USE_EDNS0 }, 2616363466Sgshapiro# endif 2617363466Sgshapiro# ifdef RES_USE_DNSSEC 2618363466Sgshapiro { "use_dnssec", RES_USE_DNSSEC }, 2619363466Sgshapiro# endif 2620363466Sgshapiro# if RES_TRUSTAD 2621363466Sgshapiro { "trustad", RES_TRUSTAD }, 2622363466Sgshapiro# endif 262338032Speter { "true", 0 }, /* avoid error on old syntax */ 2624363466Sgshapiro { "true", 0 }, /* avoid error on old syntax */ 262538032Speter { NULL, 0 } 262638032Speter}; 262738032Speter 262864562Sgshapiro#endif /* NAMED_BIND */ 262938032Speter 263064562Sgshapiro#define OI_NONE 0 /* no special treatment */ 263164562Sgshapiro#define OI_SAFE 0x0001 /* safe for random people to use */ 263264562Sgshapiro#define OI_SUBOPT 0x0002 /* option has suboptions */ 263364562Sgshapiro 263464562Sgshapirostatic struct optioninfo 263538032Speter{ 263690792Sgshapiro char *o_name; /* long name of option */ 263790792Sgshapiro unsigned char o_code; /* short name of option */ 263890792Sgshapiro unsigned short o_flags; /* option flags */ 263938032Speter} OptionTab[] = 264038032Speter{ 264164562Sgshapiro#if defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) 264264562Sgshapiro { "RemoteMode", '>', OI_NONE }, 2643363466Sgshapiro#endif 264464562Sgshapiro { "SevenBitInput", '7', OI_SAFE }, 264564562Sgshapiro { "EightBitMode", '8', OI_SAFE }, 264664562Sgshapiro { "AliasFile", 'A', OI_NONE }, 264764562Sgshapiro { "AliasWait", 'a', OI_NONE }, 264864562Sgshapiro { "BlankSub", 'B', OI_NONE }, 264964562Sgshapiro { "MinFreeBlocks", 'b', OI_SAFE }, 265064562Sgshapiro { "CheckpointInterval", 'C', OI_SAFE }, 265164562Sgshapiro { "HoldExpensive", 'c', OI_NONE }, 265264562Sgshapiro { "DeliveryMode", 'd', OI_SAFE }, 265364562Sgshapiro { "ErrorHeader", 'E', OI_NONE }, 265464562Sgshapiro { "ErrorMode", 'e', OI_SAFE }, 265564562Sgshapiro { "TempFileMode", 'F', OI_NONE }, 265664562Sgshapiro { "SaveFromLine", 'f', OI_NONE }, 265764562Sgshapiro { "MatchGECOS", 'G', OI_NONE }, 265890792Sgshapiro 265990792Sgshapiro /* no long name, just here to avoid problems in setoption */ 266090792Sgshapiro { "", 'g', OI_NONE }, 266164562Sgshapiro { "HelpFile", 'H', OI_NONE }, 266264562Sgshapiro { "MaxHopCount", 'h', OI_NONE }, 266364562Sgshapiro { "ResolverOptions", 'I', OI_NONE }, 266464562Sgshapiro { "IgnoreDots", 'i', OI_SAFE }, 266564562Sgshapiro { "ForwardPath", 'J', OI_NONE }, 266664562Sgshapiro { "SendMimeErrors", 'j', OI_SAFE }, 266764562Sgshapiro { "ConnectionCacheSize", 'k', OI_NONE }, 266864562Sgshapiro { "ConnectionCacheTimeout", 'K', OI_NONE }, 266964562Sgshapiro { "UseErrorsTo", 'l', OI_NONE }, 267064562Sgshapiro { "LogLevel", 'L', OI_SAFE }, 267164562Sgshapiro { "MeToo", 'm', OI_SAFE }, 267290792Sgshapiro 267390792Sgshapiro /* no long name, just here to avoid problems in setoption */ 267490792Sgshapiro { "", 'M', OI_NONE }, 267564562Sgshapiro { "CheckAliases", 'n', OI_NONE }, 267664562Sgshapiro { "OldStyleHeaders", 'o', OI_SAFE }, 267764562Sgshapiro { "DaemonPortOptions", 'O', OI_NONE }, 267864562Sgshapiro { "PrivacyOptions", 'p', OI_SAFE }, 267964562Sgshapiro { "PostmasterCopy", 'P', OI_NONE }, 268064562Sgshapiro { "QueueFactor", 'q', OI_NONE }, 268164562Sgshapiro { "QueueDirectory", 'Q', OI_NONE }, 268264562Sgshapiro { "DontPruneRoutes", 'R', OI_NONE }, 268364562Sgshapiro { "Timeout", 'r', OI_SUBOPT }, 268464562Sgshapiro { "StatusFile", 'S', OI_NONE }, 268564562Sgshapiro { "SuperSafe", 's', OI_SAFE }, 268664562Sgshapiro { "QueueTimeout", 'T', OI_NONE }, 268764562Sgshapiro { "TimeZoneSpec", 't', OI_NONE }, 268864562Sgshapiro { "UserDatabaseSpec", 'U', OI_NONE }, 268964562Sgshapiro { "DefaultUser", 'u', OI_NONE }, 269064562Sgshapiro { "FallbackMXhost", 'V', OI_NONE }, 269164562Sgshapiro { "Verbose", 'v', OI_SAFE }, 269264562Sgshapiro { "TryNullMXList", 'w', OI_NONE }, 269364562Sgshapiro { "QueueLA", 'x', OI_NONE }, 269464562Sgshapiro { "RefuseLA", 'X', OI_NONE }, 269564562Sgshapiro { "RecipientFactor", 'y', OI_NONE }, 269664562Sgshapiro { "ForkEachJob", 'Y', OI_NONE }, 269764562Sgshapiro { "ClassFactor", 'z', OI_NONE }, 269864562Sgshapiro { "RetryFactor", 'Z', OI_NONE }, 269938032Speter#define O_QUEUESORTORD 0x81 270064562Sgshapiro { "QueueSortOrder", O_QUEUESORTORD, OI_SAFE }, 270138032Speter#define O_HOSTSFILE 0x82 270264562Sgshapiro { "HostsFile", O_HOSTSFILE, OI_NONE }, 270338032Speter#define O_MQA 0x83 270464562Sgshapiro { "MinQueueAge", O_MQA, OI_SAFE }, 270538032Speter#define O_DEFCHARSET 0x85 270664562Sgshapiro { "DefaultCharSet", O_DEFCHARSET, OI_SAFE }, 270738032Speter#define O_SSFILE 0x86 270864562Sgshapiro { "ServiceSwitchFile", O_SSFILE, OI_NONE }, 270938032Speter#define O_DIALDELAY 0x87 271064562Sgshapiro { "DialDelay", O_DIALDELAY, OI_SAFE }, 271138032Speter#define O_NORCPTACTION 0x88 271264562Sgshapiro { "NoRecipientAction", O_NORCPTACTION, OI_SAFE }, 271338032Speter#define O_SAFEFILEENV 0x89 271464562Sgshapiro { "SafeFileEnvironment", O_SAFEFILEENV, OI_NONE }, 271538032Speter#define O_MAXMSGSIZE 0x8a 271664562Sgshapiro { "MaxMessageSize", O_MAXMSGSIZE, OI_NONE }, 271738032Speter#define O_COLONOKINADDR 0x8b 271864562Sgshapiro { "ColonOkInAddr", O_COLONOKINADDR, OI_SAFE }, 271938032Speter#define O_MAXQUEUERUN 0x8c 272064562Sgshapiro { "MaxQueueRunSize", O_MAXQUEUERUN, OI_SAFE }, 272138032Speter#define O_MAXCHILDREN 0x8d 272264562Sgshapiro { "MaxDaemonChildren", O_MAXCHILDREN, OI_NONE }, 272338032Speter#define O_KEEPCNAMES 0x8e 272464562Sgshapiro { "DontExpandCnames", O_KEEPCNAMES, OI_NONE }, 272538032Speter#define O_MUSTQUOTE 0x8f 272664562Sgshapiro { "MustQuoteChars", O_MUSTQUOTE, OI_NONE }, 272738032Speter#define O_SMTPGREETING 0x90 272864562Sgshapiro { "SmtpGreetingMessage", O_SMTPGREETING, OI_NONE }, 272938032Speter#define O_UNIXFROM 0x91 273064562Sgshapiro { "UnixFromLine", O_UNIXFROM, OI_NONE }, 273138032Speter#define O_OPCHARS 0x92 273264562Sgshapiro { "OperatorChars", O_OPCHARS, OI_NONE }, 273338032Speter#define O_DONTINITGRPS 0x93 273464562Sgshapiro { "DontInitGroups", O_DONTINITGRPS, OI_NONE }, 273538032Speter#define O_SLFH 0x94 273664562Sgshapiro { "SingleLineFromHeader", O_SLFH, OI_SAFE }, 273738032Speter#define O_ABH 0x95 273864562Sgshapiro { "AllowBogusHELO", O_ABH, OI_SAFE }, 273938032Speter#define O_CONNTHROT 0x97 274064562Sgshapiro { "ConnectionRateThrottle", O_CONNTHROT, OI_NONE }, 274138032Speter#define O_UGW 0x99 274264562Sgshapiro { "UnsafeGroupWrites", O_UGW, OI_NONE }, 274338032Speter#define O_DBLBOUNCE 0x9a 274464562Sgshapiro { "DoubleBounceAddress", O_DBLBOUNCE, OI_NONE }, 274538032Speter#define O_HSDIR 0x9b 274664562Sgshapiro { "HostStatusDirectory", O_HSDIR, OI_NONE }, 274738032Speter#define O_SINGTHREAD 0x9c 274864562Sgshapiro { "SingleThreadDelivery", O_SINGTHREAD, OI_NONE }, 274938032Speter#define O_RUNASUSER 0x9d 275064562Sgshapiro { "RunAsUser", O_RUNASUSER, OI_NONE }, 275138032Speter#define O_DSN_RRT 0x9e 275264562Sgshapiro { "RrtImpliesDsn", O_DSN_RRT, OI_NONE }, 275338032Speter#define O_PIDFILE 0x9f 275464562Sgshapiro { "PidFile", O_PIDFILE, OI_NONE }, 275538032Speter#define O_DONTBLAMESENDMAIL 0xa0 275664562Sgshapiro { "DontBlameSendmail", O_DONTBLAMESENDMAIL, OI_NONE }, 275738032Speter#define O_DPI 0xa1 275864562Sgshapiro { "DontProbeInterfaces", O_DPI, OI_NONE }, 275938032Speter#define O_MAXRCPT 0xa2 276064562Sgshapiro { "MaxRecipientsPerMessage", O_MAXRCPT, OI_SAFE }, 276138032Speter#define O_DEADLETTER 0xa3 276264562Sgshapiro { "DeadLetterDrop", O_DEADLETTER, OI_NONE }, 276338032Speter#if _FFR_DONTLOCKFILESFORREAD_OPTION 276464562Sgshapiro# define O_DONTLOCK 0xa4 276564562Sgshapiro { "DontLockFilesForRead", O_DONTLOCK, OI_NONE }, 2766363466Sgshapiro#endif 276738032Speter#define O_MAXALIASRCSN 0xa5 276864562Sgshapiro { "MaxAliasRecursion", O_MAXALIASRCSN, OI_NONE }, 276938032Speter#define O_CNCTONLYTO 0xa6 277064562Sgshapiro { "ConnectOnlyTo", O_CNCTONLYTO, OI_NONE }, 277142575Speter#define O_TRUSTUSER 0xa7 277264562Sgshapiro { "TrustedUser", O_TRUSTUSER, OI_NONE }, 277342575Speter#define O_MAXMIMEHDRLEN 0xa8 277464562Sgshapiro { "MaxMimeHeaderLength", O_MAXMIMEHDRLEN, OI_NONE }, 277542575Speter#define O_CONTROLSOCKET 0xa9 277664562Sgshapiro { "ControlSocketName", O_CONTROLSOCKET, OI_NONE }, 277743730Speter#define O_MAXHDRSLEN 0xaa 277864562Sgshapiro { "MaxHeadersLength", O_MAXHDRSLEN, OI_NONE }, 277964562Sgshapiro#if _FFR_MAX_FORWARD_ENTRIES 278064562Sgshapiro# define O_MAXFORWARD 0xab 278164562Sgshapiro { "MaxForwardEntries", O_MAXFORWARD, OI_NONE }, 2782363466Sgshapiro#endif 278364562Sgshapiro#define O_PROCTITLEPREFIX 0xac 278464562Sgshapiro { "ProcessTitlePrefix", O_PROCTITLEPREFIX, OI_NONE }, 278564562Sgshapiro#define O_SASLINFO 0xad 278664562Sgshapiro#if _FFR_ALLOW_SASLINFO 278764562Sgshapiro { "DefaultAuthInfo", O_SASLINFO, OI_SAFE }, 2788363466Sgshapiro#else 278964562Sgshapiro { "DefaultAuthInfo", O_SASLINFO, OI_NONE }, 2790363466Sgshapiro#endif 279164562Sgshapiro#define O_SASLMECH 0xae 279264562Sgshapiro { "AuthMechanisms", O_SASLMECH, OI_NONE }, 279364562Sgshapiro#define O_CLIENTPORT 0xaf 279464562Sgshapiro { "ClientPortOptions", O_CLIENTPORT, OI_NONE }, 279564562Sgshapiro#define O_DF_BUFSIZE 0xb0 279664562Sgshapiro { "DataFileBufferSize", O_DF_BUFSIZE, OI_NONE }, 279764562Sgshapiro#define O_XF_BUFSIZE 0xb1 279864562Sgshapiro { "XscriptFileBufferSize", O_XF_BUFSIZE, OI_NONE }, 279990792Sgshapiro#define O_LDAPDEFAULTSPEC 0xb2 280064562Sgshapiro { "LDAPDefaultSpec", O_LDAPDEFAULTSPEC, OI_NONE }, 280190792Sgshapiro#define O_SRVCERTFILE 0xb4 280264562Sgshapiro { "ServerCertFile", O_SRVCERTFILE, OI_NONE }, 280390792Sgshapiro#define O_SRVKEYFILE 0xb5 2804102528Sgshapiro { "ServerKeyFile", O_SRVKEYFILE, OI_NONE }, 280590792Sgshapiro#define O_CLTCERTFILE 0xb6 280664562Sgshapiro { "ClientCertFile", O_CLTCERTFILE, OI_NONE }, 280790792Sgshapiro#define O_CLTKEYFILE 0xb7 2808102528Sgshapiro { "ClientKeyFile", O_CLTKEYFILE, OI_NONE }, 280990792Sgshapiro#define O_CACERTFILE 0xb8 2810110560Sgshapiro { "CACertFile", O_CACERTFILE, OI_NONE }, 281190792Sgshapiro#define O_CACERTPATH 0xb9 2812110560Sgshapiro { "CACertPath", O_CACERTPATH, OI_NONE }, 281390792Sgshapiro#define O_DHPARAMS 0xba 281464562Sgshapiro { "DHParameters", O_DHPARAMS, OI_NONE }, 281564562Sgshapiro#define O_INPUTMILTER 0xbb 281664562Sgshapiro { "InputMailFilters", O_INPUTMILTER, OI_NONE }, 281764562Sgshapiro#define O_MILTER 0xbc 281864562Sgshapiro { "Milter", O_MILTER, OI_SUBOPT }, 281964562Sgshapiro#define O_SASLOPTS 0xbd 282064562Sgshapiro { "AuthOptions", O_SASLOPTS, OI_NONE }, 282164562Sgshapiro#define O_QUEUE_FILE_MODE 0xbe 282264562Sgshapiro { "QueueFileMode", O_QUEUE_FILE_MODE, OI_NONE }, 2823285229Sgshapiro#define O_DIG_ALG 0xbf 2824285229Sgshapiro { "CertFingerprintAlgorithm", O_DIG_ALG, OI_NONE }, 2825285229Sgshapiro#define O_CIPHERLIST 0xc0 282664562Sgshapiro { "CipherList", O_CIPHERLIST, OI_NONE }, 282790792Sgshapiro#define O_RANDFILE 0xc1 282864562Sgshapiro { "RandFile", O_RANDFILE, OI_NONE }, 282990792Sgshapiro#define O_TLS_SRV_OPTS 0xc2 283090792Sgshapiro { "TLSSrvOptions", O_TLS_SRV_OPTS, OI_NONE }, 283190792Sgshapiro#define O_RCPTTHROT 0xc3 283290792Sgshapiro { "BadRcptThrottle", O_RCPTTHROT, OI_SAFE }, 283390792Sgshapiro#define O_DLVR_MIN 0xc4 283490792Sgshapiro { "DeliverByMin", O_DLVR_MIN, OI_NONE }, 283590792Sgshapiro#define O_MAXQUEUECHILDREN 0xc5 283690792Sgshapiro { "MaxQueueChildren", O_MAXQUEUECHILDREN, OI_NONE }, 283790792Sgshapiro#define O_MAXRUNNERSPERQUEUE 0xc6 283890792Sgshapiro { "MaxRunnersPerQueue", O_MAXRUNNERSPERQUEUE, OI_NONE }, 283990792Sgshapiro#define O_DIRECTSUBMODIFIERS 0xc7 284090792Sgshapiro { "DirectSubmissionModifiers", O_DIRECTSUBMODIFIERS, OI_NONE }, 284190792Sgshapiro#define O_NICEQUEUERUN 0xc8 284290792Sgshapiro { "NiceQueueRun", O_NICEQUEUERUN, OI_NONE }, 284390792Sgshapiro#define O_SHMKEY 0xc9 284490792Sgshapiro { "SharedMemoryKey", O_SHMKEY, OI_NONE }, 284590792Sgshapiro#define O_SASLBITS 0xca 284690792Sgshapiro { "AuthMaxBits", O_SASLBITS, OI_NONE }, 284790792Sgshapiro#define O_MBDB 0xcb 284890792Sgshapiro { "MailboxDatabase", O_MBDB, OI_NONE }, 284990792Sgshapiro#define O_MSQ 0xcc 285090792Sgshapiro { "UseMSP", O_MSQ, OI_NONE }, 285190792Sgshapiro#define O_DELAY_LA 0xcd 285290792Sgshapiro { "DelayLA", O_DELAY_LA, OI_NONE }, 285390792Sgshapiro#define O_FASTSPLIT 0xce 285490792Sgshapiro { "FastSplit", O_FASTSPLIT, OI_NONE }, 2855168515Sgshapiro#define O_SOFTBOUNCE 0xcf 285690792Sgshapiro { "SoftBounce", O_SOFTBOUNCE, OI_NONE }, 2857168515Sgshapiro#define O_SHMKEYFILE 0xd0 285894334Sgshapiro { "SharedMemoryKeyFile", O_SHMKEYFILE, OI_NONE }, 2859132943Sgshapiro#define O_REJECTLOGINTERVAL 0xd1 2860110560Sgshapiro { "RejectLogInterval", O_REJECTLOGINTERVAL, OI_NONE }, 2861132943Sgshapiro#define O_REQUIRES_DIR_FSYNC 0xd2 2862110560Sgshapiro { "RequiresDirfsync", O_REQUIRES_DIR_FSYNC, OI_NONE }, 2863132943Sgshapiro#define O_CONNECTION_RATE_WINDOW_SIZE 0xd3 2864132943Sgshapiro { "ConnectionRateWindowSize", O_CONNECTION_RATE_WINDOW_SIZE, OI_NONE }, 2865132943Sgshapiro#define O_CRLFILE 0xd4 2866132943Sgshapiro { "CRLFile", O_CRLFILE, OI_NONE }, 2867132943Sgshapiro#define O_FALLBACKSMARTHOST 0xd5 2868132943Sgshapiro { "FallbackSmartHost", O_FALLBACKSMARTHOST, OI_NONE }, 2869132943Sgshapiro#define O_SASLREALM 0xd6 2870132943Sgshapiro { "AuthRealm", O_SASLREALM, OI_NONE }, 2871363466Sgshapiro#define O_CRLPATH 0xd7 2872132943Sgshapiro { "CRLPath", O_CRLPATH, OI_NONE }, 2873168515Sgshapiro#define O_HELONAME 0xd8 2874132943Sgshapiro { "HeloName", O_HELONAME, OI_NONE }, 2875157001Sgshapiro#if _FFR_MEMSTAT 2876157001Sgshapiro# define O_REFUSELOWMEM 0xd9 2877157001Sgshapiro { "RefuseLowMem", O_REFUSELOWMEM, OI_NONE }, 2878157001Sgshapiro# define O_QUEUELOWMEM 0xda 2879157001Sgshapiro { "QueueLowMem", O_QUEUELOWMEM, OI_NONE }, 2880157001Sgshapiro# define O_MEMRESOURCE 0xdb 2881157001Sgshapiro { "MemoryResource", O_MEMRESOURCE, OI_NONE }, 2882157001Sgshapiro#endif /* _FFR_MEMSTAT */ 2883168515Sgshapiro#define O_MAXNOOPCOMMANDS 0xdc 2884157001Sgshapiro { "MaxNOOPCommands", O_MAXNOOPCOMMANDS, OI_NONE }, 2885157001Sgshapiro#if _FFR_MSG_ACCEPT 2886157001Sgshapiro# define O_MSG_ACCEPT 0xdd 2887157001Sgshapiro { "MessageAccept", O_MSG_ACCEPT, OI_NONE }, 2888363466Sgshapiro#endif 2889157001Sgshapiro#if _FFR_QUEUE_RUN_PARANOIA 2890157001Sgshapiro# define O_CHK_Q_RUNNERS 0xde 2891157001Sgshapiro { "CheckQueueRunners", O_CHK_Q_RUNNERS, OI_NONE }, 2892363466Sgshapiro#endif 2893168515Sgshapiro#if _FFR_EIGHT_BIT_ADDR_OK 2894168515Sgshapiro# if !ALLOW_255 2895168515Sgshapiro# ERROR FFR_EIGHT_BIT_ADDR_OK requires _ALLOW_255 2896363466Sgshapiro# endif 2897168515Sgshapiro# define O_EIGHT_BIT_ADDR_OK 0xdf 2898168515Sgshapiro { "EightBitAddrOK", O_EIGHT_BIT_ADDR_OK, OI_NONE }, 2899168515Sgshapiro#endif /* _FFR_EIGHT_BIT_ADDR_OK */ 2900173340Sgshapiro#if _FFR_ADDR_TYPE_MODES 2901173340Sgshapiro# define O_ADDR_TYPE_MODES 0xe0 2902173340Sgshapiro { "AddrTypeModes", O_ADDR_TYPE_MODES, OI_NONE }, 2903363466Sgshapiro#endif 2904182352Sgshapiro#if _FFR_BADRCPT_SHUTDOWN 2905182352Sgshapiro# define O_RCPTSHUTD 0xe1 2906182352Sgshapiro { "BadRcptShutdown", O_RCPTSHUTD, OI_SAFE }, 2907182352Sgshapiro# define O_RCPTSHUTDG 0xe2 2908182352Sgshapiro { "BadRcptShutdownGood", O_RCPTSHUTDG, OI_SAFE }, 2909182352Sgshapiro#endif /* _FFR_BADRCPT_SHUTDOWN */ 2910285229Sgshapiro#define O_SRV_SSL_OPTIONS 0xe3 2911203004Sgshapiro { "ServerSSLOptions", O_SRV_SSL_OPTIONS, OI_NONE }, 2912285229Sgshapiro#define O_CLT_SSL_OPTIONS 0xe4 2913203004Sgshapiro { "ClientSSLOptions", O_CLT_SSL_OPTIONS, OI_NONE }, 2914285229Sgshapiro#define O_MAX_QUEUE_AGE 0xe5 2915203004Sgshapiro { "MaxQueueAge", O_MAX_QUEUE_AGE, OI_NONE }, 2916203004Sgshapiro#if _FFR_RCPTTHROTDELAY 2917203004Sgshapiro# define O_RCPTTHROTDELAY 0xe6 2918203004Sgshapiro { "BadRcptThrottleDelay", O_RCPTTHROTDELAY, OI_SAFE }, 2919363466Sgshapiro#endif 2920223067Sgshapiro#if 0 && _FFR_QOS && defined(SOL_IP) && defined(IP_TOS) 2921223067Sgshapiro# define O_INETQOS 0xe7 /* reserved for FFR_QOS */ 2922223067Sgshapiro { "InetQoS", O_INETQOS, OI_NONE }, 2923223067Sgshapiro#endif 2924249729Sgshapiro#if STARTTLS && _FFR_FIPSMODE 2925249729Sgshapiro# define O_FIPSMODE 0xe8 2926249729Sgshapiro { "FIPSMode", O_FIPSMODE, OI_NONE }, 2927363466Sgshapiro#endif 2928249729Sgshapiro#if _FFR_REJECT_NUL_BYTE 2929249729Sgshapiro# define O_REJECTNUL 0xe9 2930249729Sgshapiro { "RejectNUL", O_REJECTNUL, OI_SAFE }, 2931363466Sgshapiro#endif 2932285229Sgshapiro#if _FFR_BOUNCE_QUEUE 2933285229Sgshapiro# define O_BOUNCEQUEUE 0xea 2934285229Sgshapiro { "BounceQueue", O_BOUNCEQUEUE, OI_NONE }, 2935363466Sgshapiro#endif 2936285229Sgshapiro#if _FFR_ADD_BCC 2937285229Sgshapiro# define O_ADDBCC 0xeb 2938285229Sgshapiro { "AddBcc", O_ADDBCC, OI_NONE }, 2939285229Sgshapiro#endif 2940285229Sgshapiro#define O_USECOMPRESSEDIPV6ADDRESSES 0xec 2941285229Sgshapiro { "UseCompressedIPv6Addresses", O_USECOMPRESSEDIPV6ADDRESSES, OI_NONE }, 2942363466Sgshapiro#if STARTTLS 2943363466Sgshapiro# define O_SSLENGINE 0xed 2944363466Sgshapiro { "SSLEngine", O_SSLENGINE, OI_NONE }, 2945363466Sgshapiro# define O_SSLENGINEPATH 0xee 2946363466Sgshapiro { "SSLEnginePath", O_SSLENGINEPATH, OI_NONE }, 2947363466Sgshapiro# define O_TLSFB2CLEAR 0xef 2948363466Sgshapiro { "TLSFallbacktoClear", O_TLSFB2CLEAR, OI_NONE }, 2949363466Sgshapiro#endif 2950363466Sgshapiro#if DNSSEC_TEST 2951363466Sgshapiro# define O_NSPORTIP 0xf0 2952363466Sgshapiro { "NameServer", O_NSPORTIP, OI_NONE }, 2953363466Sgshapiro#endif 2954363466Sgshapiro#if DANE 2955363466Sgshapiro# define O_DANE 0xf1 2956363466Sgshapiro { "DANE", O_DANE, OI_NONE }, 2957363466Sgshapiro#endif 2958363466Sgshapiro#if DNSSEC_TEST 2959363466Sgshapiro# define O_NSSRCHLIST 0xf2 2960363466Sgshapiro { "NameSearchList", O_NSSRCHLIST, OI_NONE }, 2961363466Sgshapiro#endif 2962363466Sgshapiro#if _FFR_BLANKENV_MACV 2963363466Sgshapiro# define O_HACKS 0xf4 2964363466Sgshapiro { "Hacks", O_HACKS, OI_NONE }, 2965363466Sgshapiro#endif 2966363466Sgshapiro#if _FFR_KEEPBCC 2967363466Sgshapiro# define O_KEEPBCC 0xf3 2968363466Sgshapiro { "KeepBcc", O_KEEPBCC, OI_NONE }, 2969363466Sgshapiro#endif 2970132943Sgshapiro 2971363466Sgshapiro#if _FFR_CLIENTCA 2972363466Sgshapiro#define O_CLTCACERTFILE 0xf5 2973363466Sgshapiro { "ClientCACertFile", O_CLTCACERTFILE, OI_NONE }, 2974363466Sgshapiro#define O_CLTCACERTPATH 0xf6 2975363466Sgshapiro { "ClientCACertPath", O_CLTCACERTPATH, OI_NONE }, 2976363466Sgshapiro#endif 2977363466Sgshapiro#if _FFR_TLS_ALTNAMES 2978363466Sgshapiro# define O_CHECKALTNAMES 0xf7 2979363466Sgshapiro { "SetCertAltnames", O_CHECKALTNAMES, OI_NONE }, 2980363466Sgshapiro#endif 2981363466Sgshapiro 298264562Sgshapiro { NULL, '\0', OI_NONE } 298338032Speter}; 298438032Speter 298590792Sgshapiro# define CANONIFY(val) 298690792Sgshapiro 298790792Sgshapiro# define SET_OPT_DEFAULT(opt, val) opt = val 298890792Sgshapiro 298990792Sgshapiro/* set a string option by expanding the value and assigning it */ 299090792Sgshapiro/* WARNING this belongs ONLY into a case statement! */ 299190792Sgshapiro#define SET_STRING_EXP(str) \ 2992168515Sgshapiro expand(val, exbuf, sizeof(exbuf), e); \ 299390792Sgshapiro newval = sm_pstrdup_x(exbuf); \ 299490792Sgshapiro if (str != NULL) \ 299590792Sgshapiro sm_free(str); \ 299690792Sgshapiro CANONIFY(newval); \ 299790792Sgshapiro str = newval; \ 299890792Sgshapiro break 299990792Sgshapiro 300090792Sgshapiro#define OPTNAME o->o_name == NULL ? "<unknown>" : o->o_name 300190792Sgshapiro 300238032Spetervoid 300338032Spetersetoption(opt, val, safe, sticky, e) 300438032Speter int opt; 300538032Speter char *val; 300638032Speter bool safe; 300738032Speter bool sticky; 300838032Speter register ENVELOPE *e; 300938032Speter{ 301038032Speter register char *p; 301138032Speter register struct optioninfo *o; 301238032Speter char *subopt; 3013363466Sgshapiro int i; 301438032Speter bool can_setuid = RunAsUid == 0; 301538032Speter auto char *ep; 301638032Speter char buf[50]; 301738032Speter extern bool Warn_Q_option; 301864562Sgshapiro#if _FFR_ALLOW_SASLINFO 301990792Sgshapiro extern unsigned int SubmitMode; 3020363466Sgshapiro#endif 3021168515Sgshapiro#if STARTTLS || SM_CONF_SHM 302290792Sgshapiro char *newval; 302390792Sgshapiro char exbuf[MAXLINE]; 3024363466Sgshapiro#endif 3025285229Sgshapiro#if STARTTLS 3026285229Sgshapiro unsigned long *pssloptions = NULL; 3027285229Sgshapiro#endif 302838032Speter 302938032Speter errno = 0; 303038032Speter if (opt == ' ') 303138032Speter { 303238032Speter /* full word options */ 303338032Speter struct optioninfo *sel; 303438032Speter 303538032Speter p = strchr(val, '='); 303638032Speter if (p == NULL) 303738032Speter p = &val[strlen(val)]; 303838032Speter while (*--p == ' ') 303938032Speter continue; 304038032Speter while (*++p == ' ') 304138032Speter *p = '\0'; 304238032Speter if (p == val) 304338032Speter { 304438032Speter syserr("readcf: null option name"); 304538032Speter return; 304638032Speter } 304738032Speter if (*p == '=') 304838032Speter *p++ = '\0'; 304938032Speter while (*p == ' ') 305038032Speter p++; 305138032Speter subopt = strchr(val, '.'); 305238032Speter if (subopt != NULL) 305338032Speter *subopt++ = '\0'; 305438032Speter sel = NULL; 305538032Speter for (o = OptionTab; o->o_name != NULL; o++) 305638032Speter { 305790792Sgshapiro if (sm_strncasecmp(o->o_name, val, strlen(val)) != 0) 305838032Speter continue; 305938032Speter if (strlen(o->o_name) == strlen(val)) 306038032Speter { 306138032Speter /* completely specified -- this must be it */ 306238032Speter sel = NULL; 306338032Speter break; 306438032Speter } 306538032Speter if (sel != NULL) 306638032Speter break; 306738032Speter sel = o; 306838032Speter } 306938032Speter if (sel != NULL && o->o_name == NULL) 307038032Speter o = sel; 307138032Speter else if (o->o_name == NULL) 307238032Speter { 307338032Speter syserr("readcf: unknown option name %s", val); 307438032Speter return; 307538032Speter } 307638032Speter else if (sel != NULL) 307738032Speter { 307838032Speter syserr("readcf: ambiguous option name %s (matches %s and %s)", 307938032Speter val, sel->o_name, o->o_name); 308038032Speter return; 308138032Speter } 308238032Speter if (strlen(val) != strlen(o->o_name)) 308338032Speter { 308438032Speter int oldVerbose = Verbose; 308538032Speter 308638032Speter Verbose = 1; 308738032Speter message("Option %s used as abbreviation for %s", 308838032Speter val, o->o_name); 308938032Speter Verbose = oldVerbose; 309038032Speter } 309138032Speter opt = o->o_code; 309238032Speter val = p; 309338032Speter } 309438032Speter else 309538032Speter { 309638032Speter for (o = OptionTab; o->o_name != NULL; o++) 309738032Speter { 309838032Speter if (o->o_code == opt) 309938032Speter break; 310038032Speter } 310190792Sgshapiro if (o->o_name == NULL) 310290792Sgshapiro { 310390792Sgshapiro syserr("readcf: unknown option name 0x%x", opt & 0xff); 310490792Sgshapiro return; 310590792Sgshapiro } 310638032Speter subopt = NULL; 310738032Speter } 310838032Speter 310964562Sgshapiro if (subopt != NULL && !bitset(OI_SUBOPT, o->o_flags)) 311064562Sgshapiro { 311164562Sgshapiro if (tTd(37, 1)) 311290792Sgshapiro sm_dprintf("setoption: %s does not support suboptions, ignoring .%s\n", 311390792Sgshapiro OPTNAME, subopt); 311464562Sgshapiro subopt = NULL; 311564562Sgshapiro } 311664562Sgshapiro 311738032Speter if (tTd(37, 1)) 311838032Speter { 311990792Sgshapiro sm_dprintf(isascii(opt) && isprint(opt) ? 312090792Sgshapiro "setoption %s (%c)%s%s=" : 312190792Sgshapiro "setoption %s (0x%x)%s%s=", 312290792Sgshapiro OPTNAME, opt, subopt == NULL ? "" : ".", 312390792Sgshapiro subopt == NULL ? "" : subopt); 3124132943Sgshapiro xputs(sm_debug_file(), val); 312538032Speter } 312638032Speter 312738032Speter /* 312838032Speter ** See if this option is preset for us. 312938032Speter */ 313038032Speter 313138032Speter if (!sticky && bitnset(opt, StickyOpt)) 313238032Speter { 313338032Speter if (tTd(37, 1)) 313490792Sgshapiro sm_dprintf(" (ignored)\n"); 313538032Speter return; 313638032Speter } 313738032Speter 313838032Speter /* 313938032Speter ** Check to see if this option can be specified by this user. 314038032Speter */ 314138032Speter 314238032Speter if (!safe && RealUid == 0) 314390792Sgshapiro safe = true; 314464562Sgshapiro if (!safe && !bitset(OI_SAFE, o->o_flags)) 314538032Speter { 314638032Speter if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) 314738032Speter { 314864562Sgshapiro int dp; 314964562Sgshapiro 315038032Speter if (tTd(37, 1)) 315190792Sgshapiro sm_dprintf(" (unsafe)"); 315290792Sgshapiro dp = drop_privileges(true); 315364562Sgshapiro setstat(dp); 315438032Speter } 315538032Speter } 315638032Speter if (tTd(37, 1)) 315790792Sgshapiro sm_dprintf("\n"); 315838032Speter 315938032Speter switch (opt & 0xff) 316038032Speter { 316138032Speter case '7': /* force seven-bit input */ 316238032Speter SevenBitInput = atobool(val); 316338032Speter break; 316438032Speter 316577349Sgshapiro case '8': /* handling of 8-bit input */ 316638032Speter#if MIME8TO7 316738032Speter switch (*val) 316838032Speter { 316990792Sgshapiro case 'p': /* pass 8 bit, convert MIME */ 317090792Sgshapiro MimeMode = MM_CVTMIME|MM_PASS8BIT; 317190792Sgshapiro break; 317290792Sgshapiro 317338032Speter case 'm': /* convert 8-bit, convert MIME */ 317438032Speter MimeMode = MM_CVTMIME|MM_MIME8BIT; 317538032Speter break; 317638032Speter 317738032Speter case 's': /* strict adherence */ 317838032Speter MimeMode = MM_CVTMIME; 317938032Speter break; 318038032Speter 318164562Sgshapiro# if 0 318238032Speter case 'r': /* reject 8-bit, don't convert MIME */ 318338032Speter MimeMode = 0; 318438032Speter break; 318538032Speter 318638032Speter case 'j': /* "just send 8" */ 318738032Speter MimeMode = MM_PASS8BIT; 318838032Speter break; 318938032Speter 319038032Speter case 'a': /* encode 8 bit if available */ 319138032Speter MimeMode = MM_MIME8BIT|MM_PASS8BIT|MM_CVTMIME; 319238032Speter break; 319338032Speter 319438032Speter case 'c': /* convert 8 bit to MIME, never 7 bit */ 319538032Speter MimeMode = MM_MIME8BIT; 319638032Speter break; 319764562Sgshapiro# endif /* 0 */ 319838032Speter 319938032Speter default: 320038032Speter syserr("Unknown 8-bit mode %c", *val); 320190792Sgshapiro finis(false, true, EX_USAGE); 320238032Speter } 320377349Sgshapiro#else /* MIME8TO7 */ 320490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 320590792Sgshapiro "Warning: Option: %s requires MIME8TO7 support\n", 320690792Sgshapiro OPTNAME); 320777349Sgshapiro#endif /* MIME8TO7 */ 320838032Speter break; 320938032Speter 321038032Speter case 'A': /* set default alias file */ 321138032Speter if (val[0] == '\0') 321290792Sgshapiro { 321390792Sgshapiro char *al; 321490792Sgshapiro 321590792Sgshapiro SET_OPT_DEFAULT(al, "aliases"); 321690792Sgshapiro setalias(al); 321790792Sgshapiro } 321838032Speter else 321938032Speter setalias(val); 322038032Speter break; 322138032Speter 322238032Speter case 'a': /* look N minutes for "@:@" in alias file */ 322338032Speter if (val[0] == '\0') 322490792Sgshapiro SafeAlias = 5 MINUTES; 322538032Speter else 322638032Speter SafeAlias = convtime(val, 'm'); 322738032Speter break; 322838032Speter 322938032Speter case 'B': /* substitution for blank character */ 323038032Speter SpaceSub = val[0]; 323138032Speter if (SpaceSub == '\0') 323238032Speter SpaceSub = ' '; 323338032Speter break; 323438032Speter 323538032Speter case 'b': /* min blocks free on queue fs/max msg size */ 323638032Speter p = strchr(val, '/'); 323738032Speter if (p != NULL) 323838032Speter { 323938032Speter *p++ = '\0'; 324038032Speter MaxMessageSize = atol(p); 324138032Speter } 324238032Speter MinBlocksFree = atol(val); 324338032Speter break; 324438032Speter 324538032Speter case 'c': /* don't connect to "expensive" mailers */ 324638032Speter NoConnect = atobool(val); 324738032Speter break; 324838032Speter 324938032Speter case 'C': /* checkpoint every N addresses */ 3250132943Sgshapiro if (safe || CheckpointInterval > atoi(val)) 3251132943Sgshapiro CheckpointInterval = atoi(val); 325238032Speter break; 325338032Speter 325438032Speter case 'd': /* delivery mode */ 325538032Speter switch (*val) 325638032Speter { 325738032Speter case '\0': 325864562Sgshapiro set_delivery_mode(SM_DELIVER, e); 325938032Speter break; 326038032Speter 326138032Speter case SM_QUEUE: /* queue only */ 326238032Speter case SM_DEFER: /* queue only and defer map lookups */ 326338032Speter case SM_DELIVER: /* do everything */ 326438032Speter case SM_FORK: /* fork after verification */ 3265157001Sgshapiro#if _FFR_DM_ONE 3266157001Sgshapiro /* deliver first TA in background, then queue */ 3267157001Sgshapiro case SM_DM_ONE: 3268363466Sgshapiro#endif 326964562Sgshapiro set_delivery_mode(*val, e); 327038032Speter break; 327138032Speter 3272285229Sgshapiro#if _FFR_PROXY 3273285229Sgshapiro case SM_PROXY_REQ: 3274285229Sgshapiro set_delivery_mode(*val, e); 3275285229Sgshapiro break; 3276285229Sgshapiro#endif /* _FFR_PROXY */ 3277223067Sgshapiro 327838032Speter default: 327938032Speter syserr("Unknown delivery mode %c", *val); 328090792Sgshapiro finis(false, true, EX_USAGE); 328138032Speter } 328238032Speter break; 328338032Speter 328438032Speter case 'E': /* error message header/header file */ 328538032Speter if (*val != '\0') 328638032Speter ErrMsgFile = newstr(val); 328738032Speter break; 328838032Speter 328938032Speter case 'e': /* set error processing mode */ 329038032Speter switch (*val) 329138032Speter { 329238032Speter case EM_QUIET: /* be silent about it */ 329338032Speter case EM_MAIL: /* mail back */ 329438032Speter case EM_BERKNET: /* do berknet error processing */ 329538032Speter case EM_WRITE: /* write back (or mail) */ 329638032Speter case EM_PRINT: /* print errors normally (default) */ 329738032Speter e->e_errormode = *val; 329838032Speter break; 329938032Speter } 330038032Speter break; 330138032Speter 330238032Speter case 'F': /* file mode */ 330338032Speter FileMode = atooct(val) & 0777; 330438032Speter break; 330538032Speter 330638032Speter case 'f': /* save Unix-style From lines on front */ 330738032Speter SaveFrom = atobool(val); 330838032Speter break; 330938032Speter 331038032Speter case 'G': /* match recipients against GECOS field */ 331138032Speter MatchGecos = atobool(val); 331238032Speter break; 331338032Speter 331438032Speter case 'g': /* default gid */ 331538032Speter g_opt: 331638032Speter if (isascii(*val) && isdigit(*val)) 331738032Speter DefGid = atoi(val); 331838032Speter else 331938032Speter { 332038032Speter register struct group *gr; 332138032Speter 332238032Speter DefGid = -1; 332338032Speter gr = getgrnam(val); 332438032Speter if (gr == NULL) 332538032Speter syserr("readcf: option %c: unknown group %s", 332638032Speter opt, val); 332738032Speter else 332838032Speter DefGid = gr->gr_gid; 332938032Speter } 333038032Speter break; 333138032Speter 333238032Speter case 'H': /* help file */ 333338032Speter if (val[0] == '\0') 333490792Sgshapiro { 333590792Sgshapiro SET_OPT_DEFAULT(HelpFile, "helpfile"); 333690792Sgshapiro } 333738032Speter else 333873188Sgshapiro { 333990792Sgshapiro CANONIFY(val); 334038032Speter HelpFile = newstr(val); 334173188Sgshapiro } 334238032Speter break; 334338032Speter 334438032Speter case 'h': /* maximum hop count */ 334538032Speter MaxHopCount = atoi(val); 334638032Speter break; 334738032Speter 334838032Speter case 'I': /* use internet domain name server */ 334938032Speter#if NAMED_BIND 335038032Speter for (p = val; *p != 0; ) 335138032Speter { 335238032Speter bool clearmode; 335338032Speter char *q; 335438032Speter struct resolverflags *rfp; 335538032Speter 335638032Speter while (*p == ' ') 335738032Speter p++; 335838032Speter if (*p == '\0') 335938032Speter break; 336090792Sgshapiro clearmode = false; 336138032Speter if (*p == '-') 336290792Sgshapiro clearmode = true; 336338032Speter else if (*p != '+') 336438032Speter p--; 336538032Speter p++; 336638032Speter q = p; 3367363466Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p))) 336838032Speter p++; 336938032Speter if (*p != '\0') 337038032Speter *p++ = '\0'; 337190792Sgshapiro if (sm_strcasecmp(q, "HasWildcardMX") == 0) 337238032Speter { 337338032Speter HasWildcardMX = !clearmode; 337438032Speter continue; 337538032Speter } 337673188Sgshapiro if (sm_strcasecmp(q, "WorkAroundBrokenAAAA") == 0) 337773188Sgshapiro { 337873188Sgshapiro WorkAroundBrokenAAAA = !clearmode; 337973188Sgshapiro continue; 338073188Sgshapiro } 338138032Speter for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++) 338238032Speter { 338390792Sgshapiro if (sm_strcasecmp(q, rfp->rf_name) == 0) 338438032Speter break; 338538032Speter } 338638032Speter if (rfp->rf_name == NULL) 338738032Speter syserr("readcf: I option value %s unrecognized", q); 338838032Speter else if (clearmode) 338938032Speter _res.options &= ~rfp->rf_bits; 339038032Speter else 339138032Speter _res.options |= rfp->rf_bits; 339238032Speter } 339338032Speter if (tTd(8, 2)) 339490792Sgshapiro sm_dprintf("_res.options = %x, HasWildcardMX = %d\n", 339590792Sgshapiro (unsigned int) _res.options, HasWildcardMX); 339664562Sgshapiro#else /* NAMED_BIND */ 339738032Speter usrerr("name server (I option) specified but BIND not compiled in"); 339864562Sgshapiro#endif /* NAMED_BIND */ 339938032Speter break; 340038032Speter 340138032Speter case 'i': /* ignore dot lines in message */ 340238032Speter IgnrDot = atobool(val); 340338032Speter break; 340438032Speter 340538032Speter case 'j': /* send errors in MIME (RFC 1341) format */ 340638032Speter SendMIMEErrors = atobool(val); 340738032Speter break; 340838032Speter 340938032Speter case 'J': /* .forward search path */ 341090792Sgshapiro CANONIFY(val); 341138032Speter ForwardPath = newstr(val); 341238032Speter break; 341338032Speter 341438032Speter case 'k': /* connection cache size */ 341538032Speter MaxMciCache = atoi(val); 341638032Speter if (MaxMciCache < 0) 341738032Speter MaxMciCache = 0; 341838032Speter break; 341938032Speter 342038032Speter case 'K': /* connection cache timeout */ 342138032Speter MciCacheTimeout = convtime(val, 'm'); 342238032Speter break; 342338032Speter 342438032Speter case 'l': /* use Errors-To: header */ 342538032Speter UseErrorsTo = atobool(val); 342638032Speter break; 342738032Speter 342838032Speter case 'L': /* log level */ 342938032Speter if (safe || LogLevel < atoi(val)) 343038032Speter LogLevel = atoi(val); 343138032Speter break; 343238032Speter 343338032Speter case 'M': /* define macro */ 343490792Sgshapiro sticky = false; 3435363466Sgshapiro i = macid_parse(val, &ep); 3436363466Sgshapiro if (i == 0) 343771345Sgshapiro break; 343838032Speter p = newstr(ep); 343938032Speter if (!safe) 3440120256Sgshapiro cleanstrcpy(p, p, strlen(p) + 1); 3441363466Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, i, p); 344238032Speter break; 344338032Speter 344438032Speter case 'm': /* send to me too */ 344538032Speter MeToo = atobool(val); 344638032Speter break; 344738032Speter 344838032Speter case 'n': /* validate RHS in newaliases */ 344938032Speter CheckAliases = atobool(val); 345038032Speter break; 345138032Speter 345238032Speter /* 'N' available -- was "net name" */ 345338032Speter 345438032Speter case 'O': /* daemon options */ 345564562Sgshapiro if (!setdaemonoptions(val)) 345664562Sgshapiro syserr("too many daemons defined (%d max)", MAXDAEMONS); 345738032Speter break; 345838032Speter 345938032Speter case 'o': /* assume old style headers */ 346038032Speter if (atobool(val)) 346138032Speter CurEnv->e_flags |= EF_OLDSTYLE; 346238032Speter else 346338032Speter CurEnv->e_flags &= ~EF_OLDSTYLE; 346438032Speter break; 346538032Speter 346638032Speter case 'p': /* select privacy level */ 346738032Speter p = val; 346838032Speter for (;;) 346938032Speter { 347038032Speter register struct prival *pv; 347138032Speter extern struct prival PrivacyValues[]; 347238032Speter 347338032Speter while (isascii(*p) && (isspace(*p) || ispunct(*p))) 347438032Speter p++; 347538032Speter if (*p == '\0') 347638032Speter break; 347738032Speter val = p; 347838032Speter while (isascii(*p) && isalnum(*p)) 347938032Speter p++; 348038032Speter if (*p != '\0') 348138032Speter *p++ = '\0'; 348238032Speter 348338032Speter for (pv = PrivacyValues; pv->pv_name != NULL; pv++) 348438032Speter { 348590792Sgshapiro if (sm_strcasecmp(val, pv->pv_name) == 0) 348638032Speter break; 348738032Speter } 348838032Speter if (pv->pv_name == NULL) 348938032Speter syserr("readcf: Op line: %s unrecognized", val); 349071345Sgshapiro else 349171345Sgshapiro PrivacyFlags |= pv->pv_flag; 349238032Speter } 349390792Sgshapiro sticky = false; 349438032Speter break; 349538032Speter 349638032Speter case 'P': /* postmaster copy address for returned mail */ 349738032Speter PostMasterCopy = newstr(val); 349838032Speter break; 349938032Speter 350038032Speter case 'q': /* slope of queue only function */ 350138032Speter QueueFactor = atoi(val); 350238032Speter break; 350338032Speter 350438032Speter case 'Q': /* queue directory */ 350538032Speter if (val[0] == '\0') 350666494Sgshapiro { 350738032Speter QueueDir = "mqueue"; 350866494Sgshapiro } 350938032Speter else 351066494Sgshapiro { 351138032Speter QueueDir = newstr(val); 351266494Sgshapiro } 351338032Speter if (RealUid != 0 && !safe) 351490792Sgshapiro Warn_Q_option = true; 351538032Speter break; 351638032Speter 351738032Speter case 'R': /* don't prune routes */ 351838032Speter DontPruneRoutes = atobool(val); 351938032Speter break; 352038032Speter 352138032Speter case 'r': /* read timeout */ 352238032Speter if (subopt == NULL) 352364562Sgshapiro inittimeouts(val, sticky); 352438032Speter else 352564562Sgshapiro settimeout(subopt, val, sticky); 352638032Speter break; 352738032Speter 352838032Speter case 'S': /* status file */ 352938032Speter if (val[0] == '\0') 353090792Sgshapiro { 353190792Sgshapiro SET_OPT_DEFAULT(StatFile, "statistics"); 353290792Sgshapiro } 353338032Speter else 353473188Sgshapiro { 353590792Sgshapiro CANONIFY(val); 353638032Speter StatFile = newstr(val); 353773188Sgshapiro } 353838032Speter break; 353938032Speter 354038032Speter case 's': /* be super safe, even if expensive */ 354190792Sgshapiro if (tolower(*val) == 'i') 354290792Sgshapiro SuperSafe = SAFE_INTERACTIVE; 3543132943Sgshapiro else if (tolower(*val) == 'p') 3544132943Sgshapiro#if MILTER 3545132943Sgshapiro SuperSafe = SAFE_REALLY_POSTMILTER; 3546132943Sgshapiro#else /* MILTER */ 3547132943Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3548132943Sgshapiro "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n"); 3549132943Sgshapiro#endif /* MILTER */ 355090792Sgshapiro else 355190792Sgshapiro SuperSafe = atobool(val) ? SAFE_REALLY : SAFE_NO; 355238032Speter break; 355338032Speter 355438032Speter case 'T': /* queue timeout */ 355538032Speter p = strchr(val, '/'); 355638032Speter if (p != NULL) 355738032Speter { 355838032Speter *p++ = '\0'; 355964562Sgshapiro settimeout("queuewarn", p, sticky); 356038032Speter } 356164562Sgshapiro settimeout("queuereturn", val, sticky); 356238032Speter break; 356338032Speter 356438032Speter case 't': /* time zone name */ 356538032Speter TimeZoneSpec = newstr(val); 356638032Speter break; 356738032Speter 356838032Speter case 'U': /* location of user database */ 356938032Speter UdbSpec = newstr(val); 357038032Speter break; 357138032Speter 357238032Speter case 'u': /* set default uid */ 357338032Speter for (p = val; *p != '\0'; p++) 357438032Speter { 357594334Sgshapiro# if _FFR_DOTTED_USERNAMES 357690792Sgshapiro if (*p == '/' || *p == ':') 3577363466Sgshapiro# else 357838032Speter if (*p == '.' || *p == '/' || *p == ':') 3579363466Sgshapiro# endif 358038032Speter { 358138032Speter *p++ = '\0'; 358238032Speter break; 358338032Speter } 358438032Speter } 358538032Speter if (isascii(*val) && isdigit(*val)) 358638032Speter { 358738032Speter DefUid = atoi(val); 358838032Speter setdefuser(); 358938032Speter } 359038032Speter else 359138032Speter { 359238032Speter register struct passwd *pw; 359338032Speter 359438032Speter DefUid = -1; 359538032Speter pw = sm_getpwnam(val); 359638032Speter if (pw == NULL) 359771345Sgshapiro { 359838032Speter syserr("readcf: option u: unknown user %s", val); 359971345Sgshapiro break; 360071345Sgshapiro } 360138032Speter else 360238032Speter { 360338032Speter DefUid = pw->pw_uid; 360438032Speter DefGid = pw->pw_gid; 360538032Speter DefUser = newstr(pw->pw_name); 360638032Speter } 360738032Speter } 360838032Speter 360990792Sgshapiro# ifdef UID_MAX 361038032Speter if (DefUid > UID_MAX) 361138032Speter { 361238032Speter syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored", 361390792Sgshapiro (long)DefUid, (long)UID_MAX); 361471345Sgshapiro break; 361538032Speter } 361690792Sgshapiro# endif /* UID_MAX */ 361738032Speter 361838032Speter /* handle the group if it is there */ 361938032Speter if (*p == '\0') 362038032Speter break; 362138032Speter val = p; 362238032Speter goto g_opt; 362338032Speter 362438032Speter case 'V': /* fallback MX host */ 362538032Speter if (val[0] != '\0') 3626132943Sgshapiro FallbackMX = newstr(val); 362738032Speter break; 362838032Speter 362938032Speter case 'v': /* run in verbose mode */ 363038032Speter Verbose = atobool(val) ? 1 : 0; 363138032Speter break; 363238032Speter 363338032Speter case 'w': /* if we are best MX, try host directly */ 363438032Speter TryNullMXList = atobool(val); 363538032Speter break; 363638032Speter 363738032Speter /* 'W' available -- was wizard password */ 363838032Speter 363938032Speter case 'x': /* load avg at which to auto-queue msgs */ 364038032Speter QueueLA = atoi(val); 364138032Speter break; 364238032Speter 364390792Sgshapiro case 'X': /* load avg at which to auto-reject connections */ 364438032Speter RefuseLA = atoi(val); 364538032Speter break; 364638032Speter 364790792Sgshapiro case O_DELAY_LA: /* load avg at which to delay connections */ 364890792Sgshapiro DelayLA = atoi(val); 364990792Sgshapiro break; 365090792Sgshapiro 365138032Speter case 'y': /* work recipient factor */ 365238032Speter WkRecipFact = atoi(val); 365338032Speter break; 365438032Speter 365538032Speter case 'Y': /* fork jobs during queue runs */ 365638032Speter ForkQueueRuns = atobool(val); 365738032Speter break; 365838032Speter 365938032Speter case 'z': /* work message class factor */ 366038032Speter WkClassFact = atoi(val); 366138032Speter break; 366238032Speter 366338032Speter case 'Z': /* work time factor */ 366438032Speter WkTimeFact = atoi(val); 366538032Speter break; 366638032Speter 366764562Sgshapiro 366894334Sgshapiro#if _FFR_QUEUE_GROUP_SORTORDER 366994334Sgshapiro /* coordinate this with makequeue() */ 3670363466Sgshapiro#endif 367138032Speter case O_QUEUESORTORD: /* queue sorting order */ 367238032Speter switch (*val) 367338032Speter { 367490792Sgshapiro case 'f': /* File Name */ 367590792Sgshapiro case 'F': 367690792Sgshapiro QueueSortOrder = QSO_BYFILENAME; 367790792Sgshapiro break; 367890792Sgshapiro 367938032Speter case 'h': /* Host first */ 368038032Speter case 'H': 368164562Sgshapiro QueueSortOrder = QSO_BYHOST; 368238032Speter break; 368338032Speter 368490792Sgshapiro case 'm': /* Modification time */ 368590792Sgshapiro case 'M': 368690792Sgshapiro QueueSortOrder = QSO_BYMODTIME; 368790792Sgshapiro break; 368890792Sgshapiro 368938032Speter case 'p': /* Priority order */ 369038032Speter case 'P': 369164562Sgshapiro QueueSortOrder = QSO_BYPRIORITY; 369238032Speter break; 369338032Speter 369438032Speter case 't': /* Submission time */ 369538032Speter case 'T': 369664562Sgshapiro QueueSortOrder = QSO_BYTIME; 369738032Speter break; 369838032Speter 369990792Sgshapiro case 'r': /* Random */ 370090792Sgshapiro case 'R': 370190792Sgshapiro QueueSortOrder = QSO_RANDOM; 370264562Sgshapiro break; 370364562Sgshapiro 370490792Sgshapiro#if _FFR_RHS 370590792Sgshapiro case 's': /* Shuffled host name */ 370690792Sgshapiro case 'S': 370790792Sgshapiro QueueSortOrder = QSO_BYSHUFFLE; 370890792Sgshapiro break; 370990792Sgshapiro#endif /* _FFR_RHS */ 371090792Sgshapiro 3711132943Sgshapiro case 'n': /* none */ 3712132943Sgshapiro case 'N': 3713132943Sgshapiro QueueSortOrder = QSO_NONE; 371464562Sgshapiro break; 371564562Sgshapiro 371664562Sgshapiro default: 3717132943Sgshapiro syserr("Invalid queue sort order \"%s\"", val); 371864562Sgshapiro } 371964562Sgshapiro break; 372064562Sgshapiro 372138032Speter case O_HOSTSFILE: /* pathname of /etc/hosts file */ 372290792Sgshapiro CANONIFY(val); 372338032Speter HostsFile = newstr(val); 372438032Speter break; 372538032Speter 372638032Speter case O_MQA: /* minimum queue age between deliveries */ 372738032Speter MinQueueAge = convtime(val, 'm'); 372838032Speter break; 372938032Speter 3730203004Sgshapiro case O_MAX_QUEUE_AGE: 3731203004Sgshapiro MaxQueueAge = convtime(val, 'm'); 3732203004Sgshapiro break; 3733203004Sgshapiro 373438032Speter case O_DEFCHARSET: /* default character set for mimefying */ 373590792Sgshapiro DefaultCharSet = newstr(denlstring(val, true, true)); 373638032Speter break; 373738032Speter 373838032Speter case O_SSFILE: /* service switch file */ 373990792Sgshapiro CANONIFY(val); 374038032Speter ServiceSwitchFile = newstr(val); 374138032Speter break; 374238032Speter 374338032Speter case O_DIALDELAY: /* delay for dial-on-demand operation */ 374438032Speter DialDelay = convtime(val, 's'); 374538032Speter break; 374638032Speter 374738032Speter case O_NORCPTACTION: /* what to do if no recipient */ 374890792Sgshapiro if (sm_strcasecmp(val, "none") == 0) 374938032Speter NoRecipientAction = NRA_NO_ACTION; 375090792Sgshapiro else if (sm_strcasecmp(val, "add-to") == 0) 375138032Speter NoRecipientAction = NRA_ADD_TO; 375290792Sgshapiro else if (sm_strcasecmp(val, "add-apparently-to") == 0) 375338032Speter NoRecipientAction = NRA_ADD_APPARENTLY_TO; 375490792Sgshapiro else if (sm_strcasecmp(val, "add-bcc") == 0) 375538032Speter NoRecipientAction = NRA_ADD_BCC; 375690792Sgshapiro else if (sm_strcasecmp(val, "add-to-undisclosed") == 0) 375738032Speter NoRecipientAction = NRA_ADD_TO_UNDISCLOSED; 375838032Speter else 375938032Speter syserr("Invalid NoRecipientAction: %s", val); 376038032Speter break; 376138032Speter 376238032Speter case O_SAFEFILEENV: /* chroot() environ for writing to files */ 376394334Sgshapiro if (*val == '\0') 376494334Sgshapiro break; 376594334Sgshapiro 376694334Sgshapiro /* strip trailing slashes */ 376794334Sgshapiro p = val + strlen(val) - 1; 376894334Sgshapiro while (p >= val && *p == '/') 376994334Sgshapiro *p-- = '\0'; 377094334Sgshapiro 377194334Sgshapiro if (*val == '\0') 377294334Sgshapiro break; 377394334Sgshapiro 377438032Speter SafeFileEnv = newstr(val); 377538032Speter break; 377638032Speter 377738032Speter case O_MAXMSGSIZE: /* maximum message size */ 377838032Speter MaxMessageSize = atol(val); 377938032Speter break; 378038032Speter 378138032Speter case O_COLONOKINADDR: /* old style handling of colon addresses */ 378238032Speter ColonOkInAddr = atobool(val); 378338032Speter break; 378438032Speter 378538032Speter case O_MAXQUEUERUN: /* max # of jobs in a single queue run */ 378690792Sgshapiro MaxQueueRun = atoi(val); 378738032Speter break; 378838032Speter 378938032Speter case O_MAXCHILDREN: /* max # of children of daemon */ 379038032Speter MaxChildren = atoi(val); 379138032Speter break; 379238032Speter 379390792Sgshapiro case O_MAXQUEUECHILDREN: /* max # of children of daemon */ 379490792Sgshapiro MaxQueueChildren = atoi(val); 379590792Sgshapiro break; 379690792Sgshapiro 379790792Sgshapiro case O_MAXRUNNERSPERQUEUE: /* max # runners in a queue group */ 379890792Sgshapiro MaxRunnersPerQueue = atoi(val); 379990792Sgshapiro break; 380090792Sgshapiro 380190792Sgshapiro case O_NICEQUEUERUN: /* nice queue runs */ 380290792Sgshapiro#if !HASNICE 380390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 380490792Sgshapiro "Warning: NiceQueueRun set on system that doesn't support nice()\n"); 3805363466Sgshapiro#endif 380690792Sgshapiro 380790792Sgshapiro /* XXX do we want to check the range? > 0 ? */ 380890792Sgshapiro NiceQueueRun = atoi(val); 380990792Sgshapiro break; 381090792Sgshapiro 381194334Sgshapiro case O_SHMKEY: /* shared memory key */ 381290792Sgshapiro#if SM_CONF_SHM 381390792Sgshapiro ShmKey = atol(val); 381490792Sgshapiro#else /* SM_CONF_SHM */ 381590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 381690792Sgshapiro "Warning: Option: %s requires shared memory support (-DSM_CONF_SHM)\n", 381790792Sgshapiro OPTNAME); 381890792Sgshapiro#endif /* SM_CONF_SHM */ 381990792Sgshapiro break; 382090792Sgshapiro 382194334Sgshapiro case O_SHMKEYFILE: /* shared memory key file */ 3822168515Sgshapiro#if SM_CONF_SHM 382398841Sgshapiro SET_STRING_EXP(ShmKeyFile); 3824168515Sgshapiro#else /* SM_CONF_SHM */ 382594334Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 382694334Sgshapiro "Warning: Option: %s requires shared memory support (-DSM_CONF_SHM)\n", 382794334Sgshapiro OPTNAME); 382898841Sgshapiro break; 3829168515Sgshapiro#endif /* SM_CONF_SHM */ 383094334Sgshapiro 383164562Sgshapiro#if _FFR_MAX_FORWARD_ENTRIES 383264562Sgshapiro case O_MAXFORWARD: /* max # of forward entries */ 383364562Sgshapiro MaxForwardEntries = atoi(val); 383464562Sgshapiro break; 3835363466Sgshapiro#endif 383664562Sgshapiro 383738032Speter case O_KEEPCNAMES: /* don't expand CNAME records */ 383838032Speter DontExpandCnames = atobool(val); 383938032Speter break; 384038032Speter 384138032Speter case O_MUSTQUOTE: /* must quote these characters in phrases */ 3842168515Sgshapiro (void) sm_strlcpy(buf, "@,;:\\()[]", sizeof(buf)); 3843168515Sgshapiro if (strlen(val) < sizeof(buf) - 10) 3844168515Sgshapiro (void) sm_strlcat(buf, val, sizeof(buf)); 384564562Sgshapiro else 384690792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 384790792Sgshapiro "Warning: MustQuoteChars too long, ignored.\n"); 384838032Speter MustQuoteChars = newstr(buf); 384938032Speter break; 385038032Speter 385138032Speter case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */ 385238032Speter SmtpGreeting = newstr(munchstring(val, NULL, '\0')); 385338032Speter break; 385438032Speter 385538032Speter case O_UNIXFROM: /* UNIX From_ line (old $l macro) */ 385638032Speter UnixFromLine = newstr(munchstring(val, NULL, '\0')); 385738032Speter break; 385838032Speter 385938032Speter case O_OPCHARS: /* operator characters (old $o macro) */ 386064562Sgshapiro if (OperatorChars != NULL) 386190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 386290792Sgshapiro "Warning: OperatorChars is being redefined.\n It should only be set before ruleset definitions.\n"); 386338032Speter OperatorChars = newstr(munchstring(val, NULL, '\0')); 386438032Speter break; 386538032Speter 386638032Speter case O_DONTINITGRPS: /* don't call initgroups(3) */ 386738032Speter DontInitGroups = atobool(val); 386838032Speter break; 386938032Speter 387038032Speter case O_SLFH: /* make sure from fits on one line */ 387138032Speter SingleLineFromHeader = atobool(val); 387238032Speter break; 387338032Speter 387438032Speter case O_ABH: /* allow HELO commands with syntax errors */ 387538032Speter AllowBogusHELO = atobool(val); 387638032Speter break; 387738032Speter 387838032Speter case O_CONNTHROT: /* connection rate throttle */ 387938032Speter ConnRateThrottle = atoi(val); 388038032Speter break; 388138032Speter 388238032Speter case O_UGW: /* group writable files are unsafe */ 388338032Speter if (!atobool(val)) 388464562Sgshapiro { 388564562Sgshapiro setbitn(DBS_GROUPWRITABLEFORWARDFILESAFE, 388664562Sgshapiro DontBlameSendmail); 388764562Sgshapiro setbitn(DBS_GROUPWRITABLEINCLUDEFILESAFE, 388864562Sgshapiro DontBlameSendmail); 388964562Sgshapiro } 389038032Speter break; 389138032Speter 389238032Speter case O_DBLBOUNCE: /* address to which to send double bounces */ 389390792Sgshapiro DoubleBounceAddr = newstr(val); 389438032Speter break; 389538032Speter 389638032Speter case O_HSDIR: /* persistent host status directory */ 389738032Speter if (val[0] != '\0') 389873188Sgshapiro { 389990792Sgshapiro CANONIFY(val); 390038032Speter HostStatDir = newstr(val); 390173188Sgshapiro } 390238032Speter break; 390338032Speter 390438032Speter case O_SINGTHREAD: /* single thread deliveries (requires hsdir) */ 390538032Speter SingleThreadDelivery = atobool(val); 390638032Speter break; 390738032Speter 390838032Speter case O_RUNASUSER: /* run bulk of code as this user */ 390938032Speter for (p = val; *p != '\0'; p++) 391038032Speter { 391194334Sgshapiro# if _FFR_DOTTED_USERNAMES 391290792Sgshapiro if (*p == '/' || *p == ':') 3913363466Sgshapiro# else 391438032Speter if (*p == '.' || *p == '/' || *p == ':') 3915363466Sgshapiro# endif 391638032Speter { 391738032Speter *p++ = '\0'; 391838032Speter break; 391938032Speter } 392038032Speter } 392138032Speter if (isascii(*val) && isdigit(*val)) 392238032Speter { 392338032Speter if (can_setuid) 392438032Speter RunAsUid = atoi(val); 392538032Speter } 392638032Speter else 392738032Speter { 392838032Speter register struct passwd *pw; 392938032Speter 393038032Speter pw = sm_getpwnam(val); 393138032Speter if (pw == NULL) 393271345Sgshapiro { 393338032Speter syserr("readcf: option RunAsUser: unknown user %s", val); 393471345Sgshapiro break; 393571345Sgshapiro } 393638032Speter else if (can_setuid) 393738032Speter { 393838032Speter if (*p == '\0') 393938032Speter RunAsUserName = newstr(val); 394038032Speter RunAsUid = pw->pw_uid; 394138032Speter RunAsGid = pw->pw_gid; 394238032Speter } 394390792Sgshapiro else if (EffGid == pw->pw_gid) 394490792Sgshapiro RunAsGid = pw->pw_gid; 394590792Sgshapiro else if (UseMSP && *p == '\0') 394690792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3947285229Sgshapiro "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", 3948285229Sgshapiro (long) EffGid, 3949285229Sgshapiro (long) pw->pw_gid); 395038032Speter } 395190792Sgshapiro# ifdef UID_MAX 395238032Speter if (RunAsUid > UID_MAX) 395338032Speter { 395438032Speter syserr("readcf: option RunAsUser: uid value (%ld) > UID_MAX (%ld); ignored", 395571345Sgshapiro (long) RunAsUid, (long) UID_MAX); 395671345Sgshapiro break; 395738032Speter } 395890792Sgshapiro# endif /* UID_MAX */ 395938032Speter if (*p != '\0') 396038032Speter { 396138032Speter if (isascii(*p) && isdigit(*p)) 396238032Speter { 396390792Sgshapiro gid_t runasgid; 396490792Sgshapiro 396590792Sgshapiro runasgid = (gid_t) atoi(p); 396690792Sgshapiro if (can_setuid || EffGid == runasgid) 396790792Sgshapiro RunAsGid = runasgid; 396890792Sgshapiro else if (UseMSP) 396990792Sgshapiro (void) sm_io_fprintf(smioout, 397090792Sgshapiro SM_TIME_DEFAULT, 3971285229Sgshapiro "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", 3972285229Sgshapiro (long) EffGid, 3973285229Sgshapiro (long) runasgid); 397438032Speter } 397538032Speter else 397638032Speter { 397738032Speter register struct group *gr; 397864562Sgshapiro 397938032Speter gr = getgrnam(p); 398038032Speter if (gr == NULL) 398138032Speter syserr("readcf: option RunAsUser: unknown group %s", 398238032Speter p); 398390792Sgshapiro else if (can_setuid || EffGid == gr->gr_gid) 398438032Speter RunAsGid = gr->gr_gid; 398590792Sgshapiro else if (UseMSP) 398690792Sgshapiro (void) sm_io_fprintf(smioout, 398790792Sgshapiro SM_TIME_DEFAULT, 3988285229Sgshapiro "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", 3989285229Sgshapiro (long) EffGid, 3990285229Sgshapiro (long) gr->gr_gid); 399138032Speter } 399238032Speter } 399338032Speter if (tTd(47, 5)) 399490792Sgshapiro sm_dprintf("readcf: RunAsUser = %d:%d\n", 399590792Sgshapiro (int) RunAsUid, (int) RunAsGid); 399638032Speter break; 399738032Speter 399838032Speter case O_DSN_RRT: 399938032Speter RrtImpliesDsn = atobool(val); 400038032Speter break; 400138032Speter 400238032Speter case O_PIDFILE: 400390792Sgshapiro PSTRSET(PidFile, val); 400438032Speter break; 400538032Speter 400690792Sgshapiro case O_DONTBLAMESENDMAIL: 400738032Speter p = val; 400838032Speter for (;;) 400938032Speter { 401038032Speter register struct dbsval *dbs; 401138032Speter extern struct dbsval DontBlameSendmailValues[]; 401238032Speter 401338032Speter while (isascii(*p) && (isspace(*p) || ispunct(*p))) 401438032Speter p++; 401538032Speter if (*p == '\0') 401638032Speter break; 401738032Speter val = p; 401838032Speter while (isascii(*p) && isalnum(*p)) 401938032Speter p++; 402038032Speter if (*p != '\0') 402138032Speter *p++ = '\0'; 402238032Speter 402338032Speter for (dbs = DontBlameSendmailValues; 402438032Speter dbs->dbs_name != NULL; dbs++) 402538032Speter { 402690792Sgshapiro if (sm_strcasecmp(val, dbs->dbs_name) == 0) 402738032Speter break; 402838032Speter } 402938032Speter if (dbs->dbs_name == NULL) 403038032Speter syserr("readcf: DontBlameSendmail option: %s unrecognized", val); 403138032Speter else if (dbs->dbs_flag == DBS_SAFE) 403264562Sgshapiro clrbitmap(DontBlameSendmail); 403338032Speter else 403464562Sgshapiro setbitn(dbs->dbs_flag, DontBlameSendmail); 403538032Speter } 403690792Sgshapiro sticky = false; 403738032Speter break; 403838032Speter 403938032Speter case O_DPI: 404090792Sgshapiro if (sm_strcasecmp(val, "loopback") == 0) 404190792Sgshapiro DontProbeInterfaces = DPI_SKIPLOOPBACK; 404290792Sgshapiro else if (atobool(val)) 404390792Sgshapiro DontProbeInterfaces = DPI_PROBENONE; 404490792Sgshapiro else 404590792Sgshapiro DontProbeInterfaces = DPI_PROBEALL; 404638032Speter break; 404738032Speter 404838032Speter case O_MAXRCPT: 404938032Speter MaxRcptPerMsg = atoi(val); 405038032Speter break; 405138032Speter 405290792Sgshapiro case O_RCPTTHROT: 405390792Sgshapiro BadRcptThrottle = atoi(val); 405490792Sgshapiro break; 405590792Sgshapiro 4056203004Sgshapiro#if _FFR_RCPTTHROTDELAY 4057203004Sgshapiro case O_RCPTTHROTDELAY: 4058203004Sgshapiro BadRcptThrottleDelay = atoi(val); 4059203004Sgshapiro break; 4060363466Sgshapiro#endif 4061203004Sgshapiro 406238032Speter case O_DEADLETTER: 406390792Sgshapiro CANONIFY(val); 406490792Sgshapiro PSTRSET(DeadLetterDrop, val); 406538032Speter break; 406638032Speter 406738032Speter#if _FFR_DONTLOCKFILESFORREAD_OPTION 406838032Speter case O_DONTLOCK: 406938032Speter DontLockReadFiles = atobool(val); 407038032Speter break; 4071363466Sgshapiro#endif 407238032Speter 407338032Speter case O_MAXALIASRCSN: 407438032Speter MaxAliasRecursion = atoi(val); 407538032Speter break; 407638032Speter 407738032Speter case O_CNCTONLYTO: 407838032Speter /* XXX should probably use gethostbyname */ 407964562Sgshapiro#if NETINET || NETINET6 4080363466Sgshapiro i = 0; 4081363466Sgshapiro if ((subopt = strchr(val, '@')) != NULL) 4082363466Sgshapiro { 4083363466Sgshapiro *subopt = '\0'; 4084363466Sgshapiro i = (int) strtoul(val, NULL, 0); 4085363466Sgshapiro 4086363466Sgshapiro /* stricter checks? probably not useful. */ 4087363466Sgshapiro if (i > USHRT_MAX) 4088363466Sgshapiro { 4089363466Sgshapiro syserr("readcf: option ConnectOnlyTo: invalid port %s", 4090363466Sgshapiro val); 4091363466Sgshapiro break; 4092363466Sgshapiro } 4093363466Sgshapiro val = subopt + 1; 4094363466Sgshapiro } 409590792Sgshapiro ConnectOnlyTo.sa.sa_family = AF_UNSPEC; 409664562Sgshapiro# if NETINET6 409790792Sgshapiro if (anynet_pton(AF_INET6, val, 4098223067Sgshapiro &ConnectOnlyTo.sin6.sin6_addr) == 1) 4099363466Sgshapiro { 410064562Sgshapiro ConnectOnlyTo.sa.sa_family = AF_INET6; 4101363466Sgshapiro if (i != 0) 4102363466Sgshapiro ConnectOnlyTo.sin6.sin6_port = htons(i); 4103363466Sgshapiro } 410464562Sgshapiro else 410564562Sgshapiro# endif /* NETINET6 */ 410690792Sgshapiro# if NETINET 410764562Sgshapiro { 410864562Sgshapiro ConnectOnlyTo.sin.sin_addr.s_addr = inet_addr(val); 410990792Sgshapiro if (ConnectOnlyTo.sin.sin_addr.s_addr != INADDR_NONE) 411090792Sgshapiro ConnectOnlyTo.sa.sa_family = AF_INET; 4111363466Sgshapiro if (i != 0) 4112363466Sgshapiro ConnectOnlyTo.sin.sin_port = htons(i); 411364562Sgshapiro } 411490792Sgshapiro 411590792Sgshapiro# endif /* NETINET */ 411690792Sgshapiro if (ConnectOnlyTo.sa.sa_family == AF_UNSPEC) 411790792Sgshapiro { 411890792Sgshapiro syserr("readcf: option ConnectOnlyTo: invalid IP address %s", 411990792Sgshapiro val); 412090792Sgshapiro break; 412190792Sgshapiro } 412264562Sgshapiro#endif /* NETINET || NETINET6 */ 412338032Speter break; 412438032Speter 412542575Speter case O_TRUSTUSER: 412690792Sgshapiro# if !HASFCHOWN && !defined(_FFR_DROP_TRUSTUSER_WARNING) 412790792Sgshapiro if (!UseMSP) 412890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 412990792Sgshapiro "readcf: option TrustedUser may cause problems on systems\n which do not support fchown() if UseMSP is not set.\n"); 413090792Sgshapiro# endif /* !HASFCHOWN && !defined(_FFR_DROP_TRUSTUSER_WARNING) */ 413138032Speter if (isascii(*val) && isdigit(*val)) 413242575Speter TrustedUid = atoi(val); 413338032Speter else 413438032Speter { 413538032Speter register struct passwd *pw; 413638032Speter 413742575Speter TrustedUid = 0; 413838032Speter pw = sm_getpwnam(val); 413938032Speter if (pw == NULL) 414071345Sgshapiro { 414142575Speter syserr("readcf: option TrustedUser: unknown user %s", val); 414271345Sgshapiro break; 414371345Sgshapiro } 414438032Speter else 414542575Speter TrustedUid = pw->pw_uid; 414638032Speter } 414738032Speter 414864562Sgshapiro# ifdef UID_MAX 414942575Speter if (TrustedUid > UID_MAX) 415038032Speter { 415142575Speter syserr("readcf: option TrustedUser: uid value (%ld) > UID_MAX (%ld)", 415271345Sgshapiro (long) TrustedUid, (long) UID_MAX); 415342575Speter TrustedUid = 0; 415438032Speter } 415564562Sgshapiro# endif /* UID_MAX */ 415638032Speter break; 415738032Speter 415842575Speter case O_MAXMIMEHDRLEN: 415942575Speter p = strchr(val, '/'); 416042575Speter if (p != NULL) 416142575Speter *p++ = '\0'; 416242575Speter MaxMimeHeaderLength = atoi(val); 416342575Speter if (p != NULL && *p != '\0') 416442575Speter MaxMimeFieldLength = atoi(p); 416542575Speter else 416642575Speter MaxMimeFieldLength = MaxMimeHeaderLength / 2; 416742575Speter 4168120256Sgshapiro if (MaxMimeHeaderLength <= 0) 416942575Speter MaxMimeHeaderLength = 0; 417042575Speter else if (MaxMimeHeaderLength < 128) 417190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 417290792Sgshapiro "Warning: MaxMimeHeaderLength: header length limit set lower than 128\n"); 417342575Speter 4174120256Sgshapiro if (MaxMimeFieldLength <= 0) 417542575Speter MaxMimeFieldLength = 0; 417642575Speter else if (MaxMimeFieldLength < 40) 417790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 417890792Sgshapiro "Warning: MaxMimeHeaderLength: field length limit set lower than 40\n"); 4179168515Sgshapiro 4180168515Sgshapiro /* 4181168515Sgshapiro ** Headers field values now include leading space, so let's 4182168515Sgshapiro ** adjust the values to be "backward compatible". 4183168515Sgshapiro */ 4184168515Sgshapiro 4185168515Sgshapiro if (MaxMimeHeaderLength > 0) 4186168515Sgshapiro MaxMimeHeaderLength++; 4187168515Sgshapiro if (MaxMimeFieldLength > 0) 4188168515Sgshapiro MaxMimeFieldLength++; 418942575Speter break; 419042575Speter 419142575Speter case O_CONTROLSOCKET: 419290792Sgshapiro PSTRSET(ControlSocketName, val); 419342575Speter break; 419442575Speter 419543730Speter case O_MAXHDRSLEN: 419643730Speter MaxHeadersLength = atoi(val); 419743148Speter 419843730Speter if (MaxHeadersLength > 0 && 419943730Speter MaxHeadersLength < (MAXHDRSLEN / 2)) 420090792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 420190792Sgshapiro "Warning: MaxHeadersLength: headers length limit set lower than %d\n", 420290792Sgshapiro (MAXHDRSLEN / 2)); 420343148Speter break; 420443148Speter 420564562Sgshapiro case O_PROCTITLEPREFIX: 420690792Sgshapiro PSTRSET(ProcTitlePrefix, val); 420764562Sgshapiro break; 420864562Sgshapiro 420964562Sgshapiro#if SASL 421064562Sgshapiro case O_SASLINFO: 421190792Sgshapiro# if _FFR_ALLOW_SASLINFO 421264562Sgshapiro /* 421390792Sgshapiro ** Allow users to select their own authinfo file 421490792Sgshapiro ** under certain circumstances, otherwise just ignore 421590792Sgshapiro ** the option. If the option isn't ignored, several 421690792Sgshapiro ** commands don't work very well, e.g., mailq. 421764562Sgshapiro ** However, this is not a "perfect" solution. 421864562Sgshapiro ** If mail is queued, the authentication info 421964562Sgshapiro ** will not be used in subsequent delivery attempts. 422064562Sgshapiro ** If we really want to support this, then it has 422164562Sgshapiro ** to be stored in the queue file. 422264562Sgshapiro */ 422364562Sgshapiro if (!bitset(SUBMIT_MSA, SubmitMode) && RealUid != 0 && 422464562Sgshapiro RunAsUid != RealUid) 422564562Sgshapiro break; 422690792Sgshapiro# endif /* _FFR_ALLOW_SASLINFO */ 422790792Sgshapiro PSTRSET(SASLInfo, val); 422864562Sgshapiro break; 422964562Sgshapiro 423064562Sgshapiro case O_SASLMECH: 423164562Sgshapiro if (AuthMechanisms != NULL) 423290792Sgshapiro sm_free(AuthMechanisms); /* XXX */ 423364562Sgshapiro if (*val != '\0') 423464562Sgshapiro AuthMechanisms = newstr(val); 423564562Sgshapiro else 423664562Sgshapiro AuthMechanisms = NULL; 423764562Sgshapiro break; 423864562Sgshapiro 4239132943Sgshapiro case O_SASLREALM: 4240132943Sgshapiro if (AuthRealm != NULL) 4241132943Sgshapiro sm_free(AuthRealm); 4242132943Sgshapiro if (*val != '\0') 4243132943Sgshapiro AuthRealm = newstr(val); 4244132943Sgshapiro else 4245132943Sgshapiro AuthRealm = NULL; 4246132943Sgshapiro break; 4247132943Sgshapiro 424864562Sgshapiro case O_SASLOPTS: 424964562Sgshapiro while (val != NULL && *val != '\0') 425064562Sgshapiro { 425190792Sgshapiro switch (*val) 425264562Sgshapiro { 425364562Sgshapiro case 'A': 425464562Sgshapiro SASLOpts |= SASL_AUTH_AUTH; 425564562Sgshapiro break; 4256110560Sgshapiro 425764562Sgshapiro case 'a': 425864562Sgshapiro SASLOpts |= SASL_SEC_NOACTIVE; 425964562Sgshapiro break; 4260110560Sgshapiro 426164562Sgshapiro case 'c': 426264562Sgshapiro SASLOpts |= SASL_SEC_PASS_CREDENTIALS; 426364562Sgshapiro break; 4264110560Sgshapiro 426564562Sgshapiro case 'd': 426664562Sgshapiro SASLOpts |= SASL_SEC_NODICTIONARY; 426764562Sgshapiro break; 4268110560Sgshapiro 426964562Sgshapiro case 'f': 427064562Sgshapiro SASLOpts |= SASL_SEC_FORWARD_SECRECY; 427164562Sgshapiro break; 4272110560Sgshapiro 427398121Sgshapiro# if SASL >= 20101 427498121Sgshapiro case 'm': 427598121Sgshapiro SASLOpts |= SASL_SEC_MUTUAL_AUTH; 427698121Sgshapiro break; 427798121Sgshapiro# endif /* SASL >= 20101 */ 4278110560Sgshapiro 427964562Sgshapiro case 'p': 428064562Sgshapiro SASLOpts |= SASL_SEC_NOPLAINTEXT; 428164562Sgshapiro break; 4282110560Sgshapiro 428364562Sgshapiro case 'y': 428464562Sgshapiro SASLOpts |= SASL_SEC_NOANONYMOUS; 428564562Sgshapiro break; 4286110560Sgshapiro 428790792Sgshapiro case ' ': /* ignore */ 428890792Sgshapiro case '\t': /* ignore */ 428990792Sgshapiro case ',': /* ignore */ 429090792Sgshapiro break; 4291110560Sgshapiro 429264562Sgshapiro default: 429390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 429490792Sgshapiro "Warning: Option: %s unknown parameter '%c'\n", 429590792Sgshapiro OPTNAME, 429690792Sgshapiro (isascii(*val) && 429790792Sgshapiro isprint(*val)) 429890792Sgshapiro ? *val : '?'); 429964562Sgshapiro break; 430064562Sgshapiro } 430164562Sgshapiro ++val; 430264562Sgshapiro val = strpbrk(val, ", \t"); 430364562Sgshapiro if (val != NULL) 430464562Sgshapiro ++val; 430564562Sgshapiro } 430664562Sgshapiro break; 4307110560Sgshapiro 430890792Sgshapiro case O_SASLBITS: 430990792Sgshapiro MaxSLBits = atoi(val); 431090792Sgshapiro break; 431164562Sgshapiro 431264562Sgshapiro#else /* SASL */ 431364562Sgshapiro case O_SASLINFO: 431464562Sgshapiro case O_SASLMECH: 4315132943Sgshapiro case O_SASLREALM: 431664562Sgshapiro case O_SASLOPTS: 431790792Sgshapiro case O_SASLBITS: 431890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 431990792Sgshapiro "Warning: Option: %s requires SASL support (-DSASL)\n", 432090792Sgshapiro OPTNAME); 432164562Sgshapiro break; 432264562Sgshapiro#endif /* SASL */ 432364562Sgshapiro 432464562Sgshapiro#if STARTTLS 4325363466Sgshapiro case O_TLSFB2CLEAR: 4326363466Sgshapiro TLSFallbacktoClear = atobool(val); 4327363466Sgshapiro break; 432864562Sgshapiro case O_SRVCERTFILE: 4329110560Sgshapiro SET_STRING_EXP(SrvCertFile); 433064562Sgshapiro case O_SRVKEYFILE: 4331110560Sgshapiro SET_STRING_EXP(SrvKeyFile); 433264562Sgshapiro case O_CLTCERTFILE: 4333110560Sgshapiro SET_STRING_EXP(CltCertFile); 433464562Sgshapiro case O_CLTKEYFILE: 4335110560Sgshapiro SET_STRING_EXP(CltKeyFile); 433664562Sgshapiro case O_CACERTFILE: 4337110560Sgshapiro SET_STRING_EXP(CACertFile); 433864562Sgshapiro case O_CACERTPATH: 4339110560Sgshapiro SET_STRING_EXP(CACertPath); 4340363466Sgshapiro#if _FFR_CLIENTCA 4341363466Sgshapiro case O_CLTCACERTFILE: 4342363466Sgshapiro SET_STRING_EXP(CltCACertFile); 4343363466Sgshapiro case O_CLTCACERTPATH: 4344363466Sgshapiro SET_STRING_EXP(CltCACertPath); 4345363466Sgshapiro#endif 434664562Sgshapiro case O_DHPARAMS: 434790792Sgshapiro SET_STRING_EXP(DHParams); 434890792Sgshapiro case O_CIPHERLIST: 434990792Sgshapiro SET_STRING_EXP(CipherList); 4350285229Sgshapiro case O_DIG_ALG: 4351285229Sgshapiro SET_STRING_EXP(CertFingerprintAlgorithm); 4352363466Sgshapiro case O_SSLENGINEPATH: 4353363466Sgshapiro SET_STRING_EXP(SSLEnginePath); 4354363466Sgshapiro case O_SSLENGINE: 4355363466Sgshapiro newval = sm_pstrdup_x(val); 4356363466Sgshapiro if (SSLEngine != NULL) 4357363466Sgshapiro sm_free(SSLEngine); 4358363466Sgshapiro SSLEngine = newval; 4359363466Sgshapiro 4360363466Sgshapiro /* 4361363466Sgshapiro ** Which engines need to be initialized before fork()? 4362363466Sgshapiro ** XXX hack, should be an option? 4363363466Sgshapiro */ 4364363466Sgshapiro 4365363466Sgshapiro if (strcmp(SSLEngine, "chil") == 0) 4366363466Sgshapiro SSLEngineprefork = true; 4367363466Sgshapiro break; 4368203004Sgshapiro case O_SRV_SSL_OPTIONS: 4369203004Sgshapiro pssloptions = &Srv_SSL_Options; 4370203004Sgshapiro case O_CLT_SSL_OPTIONS: 4371203004Sgshapiro if (pssloptions == NULL) 4372203004Sgshapiro pssloptions = &Clt_SSL_Options; 4373285229Sgshapiro (void) readssloptions(o->o_name, val, pssloptions, '\0'); 4374285229Sgshapiro if (tTd(37, 8)) 4375285229Sgshapiro sm_dprintf("ssloptions=%#lx\n", *pssloptions); 4376203004Sgshapiro 4377203004Sgshapiro pssloptions = NULL; 4378203004Sgshapiro break; 4379203004Sgshapiro 4380132943Sgshapiro case O_CRLFILE: 4381132943Sgshapiro SET_STRING_EXP(CRLFile); 4382132943Sgshapiro break; 438364562Sgshapiro 4384132943Sgshapiro case O_CRLPATH: 4385132943Sgshapiro SET_STRING_EXP(CRLPath); 4386132943Sgshapiro break; 4387132943Sgshapiro 438890792Sgshapiro /* 438990792Sgshapiro ** XXX How about options per daemon/client instead of globally? 439090792Sgshapiro ** This doesn't work well for some options, e.g., no server cert, 439190792Sgshapiro ** but fine for others. 439290792Sgshapiro ** 439390792Sgshapiro ** XXX Some people may want different certs per server. 439490792Sgshapiro ** 439590792Sgshapiro ** See also srvfeatures() 439690792Sgshapiro */ 439790792Sgshapiro 439890792Sgshapiro case O_TLS_SRV_OPTS: 439990792Sgshapiro while (val != NULL && *val != '\0') 440090792Sgshapiro { 440190792Sgshapiro switch (*val) 440290792Sgshapiro { 440390792Sgshapiro case 'V': 440490792Sgshapiro TLS_Srv_Opts |= TLS_I_NO_VRFY; 440590792Sgshapiro break; 440690792Sgshapiro /* 440790792Sgshapiro ** Server without a cert? That works only if 440890792Sgshapiro ** AnonDH is enabled as cipher, which is not in the 440990792Sgshapiro ** default list. Hence the CipherList option must 441090792Sgshapiro ** be available. Moreover: which clients support this 441190792Sgshapiro ** besides sendmail with this setting? 441290792Sgshapiro */ 441390792Sgshapiro 441490792Sgshapiro case 'C': 441590792Sgshapiro TLS_Srv_Opts &= ~TLS_I_SRV_CERT; 441690792Sgshapiro break; 441790792Sgshapiro case ' ': /* ignore */ 441890792Sgshapiro case '\t': /* ignore */ 441990792Sgshapiro case ',': /* ignore */ 442090792Sgshapiro break; 442190792Sgshapiro default: 442290792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 442390792Sgshapiro "Warning: Option: %s unknown parameter '%c'\n", 442490792Sgshapiro OPTNAME, 442590792Sgshapiro (isascii(*val) && 442690792Sgshapiro isprint(*val)) 442790792Sgshapiro ? *val : '?'); 442890792Sgshapiro break; 442990792Sgshapiro } 443090792Sgshapiro ++val; 443190792Sgshapiro val = strpbrk(val, ", \t"); 443290792Sgshapiro if (val != NULL) 443390792Sgshapiro ++val; 443490792Sgshapiro } 443564562Sgshapiro break; 443664562Sgshapiro 443764562Sgshapiro case O_RANDFILE: 443890792Sgshapiro PSTRSET(RandFile, val); 443964562Sgshapiro break; 444064562Sgshapiro 444190792Sgshapiro#else /* STARTTLS */ 444264562Sgshapiro case O_SRVCERTFILE: 444364562Sgshapiro case O_SRVKEYFILE: 444464562Sgshapiro case O_CLTCERTFILE: 444564562Sgshapiro case O_CLTKEYFILE: 444664562Sgshapiro case O_CACERTFILE: 444764562Sgshapiro case O_CACERTPATH: 4448363466Sgshapiro#if _FFR_CLIENTCA 4449363466Sgshapiro case O_CLTCACERTFILE: 4450363466Sgshapiro case O_CLTCACERTPATH: 4451363466Sgshapiro#endif 445264562Sgshapiro case O_DHPARAMS: 4453285229Sgshapiro case O_SRV_SSL_OPTIONS: 4454285229Sgshapiro case O_CLT_SSL_OPTIONS: 445564562Sgshapiro case O_CIPHERLIST: 4456363466Sgshapiro case O_DIG_ALG: 4457132943Sgshapiro case O_CRLFILE: 4458132943Sgshapiro case O_CRLPATH: 445964562Sgshapiro case O_RANDFILE: 446090792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 446190792Sgshapiro "Warning: Option: %s requires TLS support\n", 446290792Sgshapiro OPTNAME); 446364562Sgshapiro break; 446464562Sgshapiro 446590792Sgshapiro#endif /* STARTTLS */ 4466249729Sgshapiro#if STARTTLS && _FFR_FIPSMODE 4467249729Sgshapiro case O_FIPSMODE: 4468249729Sgshapiro FipsMode = atobool(val); 4469249729Sgshapiro break; 4470363466Sgshapiro#endif 447164562Sgshapiro 447264562Sgshapiro case O_CLIENTPORT: 447364562Sgshapiro setclientoptions(val); 447464562Sgshapiro break; 447564562Sgshapiro 447664562Sgshapiro case O_DF_BUFSIZE: 447764562Sgshapiro DataFileBufferSize = atoi(val); 447864562Sgshapiro break; 447964562Sgshapiro 448064562Sgshapiro case O_XF_BUFSIZE: 448164562Sgshapiro XscriptFileBufferSize = atoi(val); 448264562Sgshapiro break; 448364562Sgshapiro 448464562Sgshapiro case O_LDAPDEFAULTSPEC: 448590792Sgshapiro#if LDAPMAP 448664562Sgshapiro ldapmap_set_defaults(val); 448764562Sgshapiro#else /* LDAPMAP */ 448890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 448990792Sgshapiro "Warning: Option: %s requires LDAP support (-DLDAPMAP)\n", 449090792Sgshapiro OPTNAME); 449164562Sgshapiro#endif /* LDAPMAP */ 449264562Sgshapiro break; 449364562Sgshapiro 449464562Sgshapiro case O_INPUTMILTER: 449590792Sgshapiro#if MILTER 449664562Sgshapiro InputFilterList = newstr(val); 449790792Sgshapiro#else /* MILTER */ 449890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 449990792Sgshapiro "Warning: Option: %s requires Milter support (-DMILTER)\n", 450090792Sgshapiro OPTNAME); 450190792Sgshapiro#endif /* MILTER */ 450264562Sgshapiro break; 450364562Sgshapiro 450464562Sgshapiro case O_MILTER: 450590792Sgshapiro#if MILTER 450664562Sgshapiro milter_set_option(subopt, val, sticky); 450790792Sgshapiro#else /* MILTER */ 450890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 450990792Sgshapiro "Warning: Option: %s requires Milter support (-DMILTER)\n", 451090792Sgshapiro OPTNAME); 451190792Sgshapiro#endif /* MILTER */ 451264562Sgshapiro break; 451364562Sgshapiro 451464562Sgshapiro case O_QUEUE_FILE_MODE: /* queue file mode */ 451564562Sgshapiro QueueFileMode = atooct(val) & 0777; 451664562Sgshapiro break; 451764562Sgshapiro 451890792Sgshapiro case O_DLVR_MIN: /* deliver by minimum time */ 451990792Sgshapiro DeliverByMin = convtime(val, 's'); 452090792Sgshapiro break; 452190792Sgshapiro 452290792Sgshapiro /* modifiers {daemon_flags} for direct submissions */ 452390792Sgshapiro case O_DIRECTSUBMODIFIERS: 452490792Sgshapiro { 452590792Sgshapiro BITMAP256 m; /* ignored */ 452690792Sgshapiro extern ENVELOPE BlankEnvelope; 452790792Sgshapiro 452890792Sgshapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 452990792Sgshapiro macid("{daemon_flags}"), 453090792Sgshapiro getmodifiers(val, m)); 453190792Sgshapiro } 453290792Sgshapiro break; 453390792Sgshapiro 453490792Sgshapiro case O_FASTSPLIT: 453590792Sgshapiro FastSplit = atoi(val); 453690792Sgshapiro break; 453790792Sgshapiro 453890792Sgshapiro case O_MBDB: 453990792Sgshapiro Mbdb = newstr(val); 454090792Sgshapiro break; 454190792Sgshapiro 454290792Sgshapiro case O_MSQ: 454390792Sgshapiro UseMSP = atobool(val); 454490792Sgshapiro break; 454590792Sgshapiro 454690792Sgshapiro case O_SOFTBOUNCE: 454790792Sgshapiro SoftBounce = atobool(val); 454890792Sgshapiro break; 454990792Sgshapiro 4550110560Sgshapiro case O_REJECTLOGINTERVAL: /* time btwn log msgs while refusing */ 4551110560Sgshapiro RejectLogInterval = convtime(val, 'h'); 4552110560Sgshapiro break; 4553110560Sgshapiro 4554110560Sgshapiro case O_REQUIRES_DIR_FSYNC: 4555132943Sgshapiro#if REQUIRES_DIR_FSYNC 4556110560Sgshapiro RequiresDirfsync = atobool(val); 4557363466Sgshapiro#else 4558110560Sgshapiro /* silently ignored... required for cf file option */ 4559363466Sgshapiro#endif 4560110560Sgshapiro break; 4561110560Sgshapiro 4562132943Sgshapiro case O_CONNECTION_RATE_WINDOW_SIZE: 4563132943Sgshapiro ConnectionRateWindowSize = convtime(val, 's'); 4564132943Sgshapiro break; 4565132943Sgshapiro 4566132943Sgshapiro case O_FALLBACKSMARTHOST: /* fallback smart host */ 4567132943Sgshapiro if (val[0] != '\0') 4568132943Sgshapiro FallbackSmartHost = newstr(val); 4569132943Sgshapiro break; 4570132943Sgshapiro 4571132943Sgshapiro case O_HELONAME: 4572157001Sgshapiro HeloName = newstr(val); 4573157001Sgshapiro break; 4574168515Sgshapiro 4575157001Sgshapiro#if _FFR_MEMSTAT 4576157001Sgshapiro case O_REFUSELOWMEM: 4577157001Sgshapiro RefuseLowMem = atoi(val); 4578157001Sgshapiro break; 4579157001Sgshapiro case O_QUEUELOWMEM: 4580157001Sgshapiro QueueLowMem = atoi(val); 4581157001Sgshapiro break; 4582157001Sgshapiro case O_MEMRESOURCE: 4583157001Sgshapiro MemoryResource = newstr(val); 4584157001Sgshapiro break; 4585157001Sgshapiro#endif /* _FFR_MEMSTAT */ 4586132943Sgshapiro 4587157001Sgshapiro case O_MAXNOOPCOMMANDS: 4588157001Sgshapiro MaxNOOPCommands = atoi(val); 4589157001Sgshapiro break; 4590157001Sgshapiro 4591157001Sgshapiro#if _FFR_MSG_ACCEPT 4592157001Sgshapiro case O_MSG_ACCEPT: 4593157001Sgshapiro MessageAccept = newstr(val); 4594157001Sgshapiro break; 4595363466Sgshapiro#endif 4596157001Sgshapiro 4597157001Sgshapiro#if _FFR_QUEUE_RUN_PARANOIA 4598157001Sgshapiro case O_CHK_Q_RUNNERS: 4599157001Sgshapiro CheckQueueRunners = atoi(val); 4600157001Sgshapiro break; 4601363466Sgshapiro#endif 4602157001Sgshapiro 4603168515Sgshapiro#if _FFR_EIGHT_BIT_ADDR_OK 4604168515Sgshapiro case O_EIGHT_BIT_ADDR_OK: 4605168515Sgshapiro EightBitAddrOK = atobool(val); 4606168515Sgshapiro break; 4607363466Sgshapiro#endif 4608168515Sgshapiro 4609173340Sgshapiro#if _FFR_ADDR_TYPE_MODES 4610173340Sgshapiro case O_ADDR_TYPE_MODES: 4611173340Sgshapiro AddrTypeModes = atobool(val); 4612173340Sgshapiro break; 4613363466Sgshapiro#endif 4614173340Sgshapiro 4615182352Sgshapiro#if _FFR_BADRCPT_SHUTDOWN 4616182352Sgshapiro case O_RCPTSHUTD: 4617182352Sgshapiro BadRcptShutdown = atoi(val); 4618182352Sgshapiro break; 4619182352Sgshapiro 4620182352Sgshapiro case O_RCPTSHUTDG: 4621182352Sgshapiro BadRcptShutdownGood = atoi(val); 4622182352Sgshapiro break; 4623182352Sgshapiro#endif /* _FFR_BADRCPT_SHUTDOWN */ 4624182352Sgshapiro 4625249729Sgshapiro#if _FFR_REJECT_NUL_BYTE 4626249729Sgshapiro case O_REJECTNUL: 4627249729Sgshapiro RejectNUL = atobool(val); 4628249729Sgshapiro break; 4629363466Sgshapiro#endif 4630249729Sgshapiro 4631285229Sgshapiro#if _FFR_BOUNCE_QUEUE 4632285229Sgshapiro case O_BOUNCEQUEUE: 4633285229Sgshapiro bouncequeue = newstr(val); 4634285229Sgshapiro break; 4635363466Sgshapiro#endif 4636285229Sgshapiro 4637285229Sgshapiro#if _FFR_ADD_BCC 4638285229Sgshapiro case O_ADDBCC: 4639285229Sgshapiro AddBcc = atobool(val); 4640285229Sgshapiro break; 4641285229Sgshapiro#endif 4642285229Sgshapiro case O_USECOMPRESSEDIPV6ADDRESSES: 4643285229Sgshapiro UseCompressedIPv6Addresses = atobool(val); 4644285229Sgshapiro break; 4645285229Sgshapiro 4646363466Sgshapiro#if DNSSEC_TEST 4647363466Sgshapiro case O_NSPORTIP: 4648363466Sgshapiro nsportip(val); 4649363466Sgshapiro break; 4650363466Sgshapiro case O_NSSRCHLIST: 4651363466Sgshapiro NameSearchList = sm_strdup(val); 4652363466Sgshapiro break; 4653363466Sgshapiro#endif 4654363466Sgshapiro 4655363466Sgshapiro#if DANE 4656363466Sgshapiro case O_DANE: 4657363466Sgshapiro if (sm_strcasecmp(val, "always") == 0) 4658363466Sgshapiro Dane = DANE_ALWAYS; 4659363466Sgshapiro else 4660363466Sgshapiro Dane = atobool(val) ? DANE_SECURE : DANE_NEVER; 4661363466Sgshapiro break; 4662363466Sgshapiro#endif 4663363466Sgshapiro 4664363466Sgshapiro#if _FFR_BLANKENV_MACV 4665363466Sgshapiro case O_HACKS: 4666363466Sgshapiro Hacks = (int) strtol(val, NULL, 0); 4667363466Sgshapiro break; 4668363466Sgshapiro#endif 4669363466Sgshapiro 4670363466Sgshapiro#if _FFR_KEEPBCC 4671363466Sgshapiro case O_KEEPBCC: 4672363466Sgshapiro KeepBcc = atobool(val); 4673363466Sgshapiro break; 4674363466Sgshapiro#endif 4675363466Sgshapiro 4676363466Sgshapiro# if _FFR_TLS_ALTNAMES 4677363466Sgshapiro case O_CHECKALTNAMES: 4678363466Sgshapiro SetCertAltnames = atobool(val); 4679363466Sgshapiro break; 4680363466Sgshapiro# endif 4681363466Sgshapiro 468238032Speter default: 468338032Speter if (tTd(37, 1)) 468438032Speter { 468538032Speter if (isascii(opt) && isprint(opt)) 468690792Sgshapiro sm_dprintf("Warning: option %c unknown\n", opt); 468738032Speter else 468890792Sgshapiro sm_dprintf("Warning: option 0x%x unknown\n", opt); 468938032Speter } 469038032Speter break; 469138032Speter } 469264562Sgshapiro 469364562Sgshapiro /* 469464562Sgshapiro ** Options with suboptions are responsible for taking care 469564562Sgshapiro ** of sticky-ness (e.g., that a command line setting is kept 469664562Sgshapiro ** when reading in the sendmail.cf file). This has to be done 469764562Sgshapiro ** when the suboptions are parsed since each suboption must be 469864562Sgshapiro ** sticky, not the root option. 469964562Sgshapiro */ 470064562Sgshapiro 470164562Sgshapiro if (sticky && !bitset(OI_SUBOPT, o->o_flags)) 470238032Speter setbitn(opt, StickyOpt); 470338032Speter} 470490792Sgshapiro/* 470538032Speter** SETCLASS -- set a string into a class 470638032Speter** 470738032Speter** Parameters: 470838032Speter** class -- the class to put the string in. 470938032Speter** str -- the string to enter 471038032Speter** 471138032Speter** Returns: 471238032Speter** none. 471338032Speter** 471438032Speter** Side Effects: 471538032Speter** puts the word into the symbol table. 471638032Speter*/ 471738032Speter 471838032Spetervoid 471938032Spetersetclass(class, str) 472038032Speter int class; 472138032Speter char *str; 472238032Speter{ 472338032Speter register STAB *s; 472438032Speter 4725168515Sgshapiro if ((str[0] & 0377) == MATCHCLASS) 472664562Sgshapiro { 472764562Sgshapiro int mid; 472864562Sgshapiro 472964562Sgshapiro str++; 473090792Sgshapiro mid = macid(str); 473171345Sgshapiro if (mid == 0) 473264562Sgshapiro return; 473364562Sgshapiro 473464562Sgshapiro if (tTd(37, 8)) 473590792Sgshapiro sm_dprintf("setclass(%s, $=%s)\n", 473690792Sgshapiro macname(class), macname(mid)); 473764562Sgshapiro copy_class(mid, class); 473864562Sgshapiro } 473964562Sgshapiro else 474064562Sgshapiro { 474164562Sgshapiro if (tTd(37, 8)) 474290792Sgshapiro sm_dprintf("setclass(%s, %s)\n", macname(class), str); 474364562Sgshapiro 474464562Sgshapiro s = stab(str, ST_CLASS, ST_ENTER); 474571345Sgshapiro setbitn(bitidx(class), s->s_class); 474664562Sgshapiro } 474738032Speter} 474890792Sgshapiro/* 474938032Speter** MAKEMAPENTRY -- create a map entry 475038032Speter** 475138032Speter** Parameters: 475238032Speter** line -- the config file line 475338032Speter** 475438032Speter** Returns: 475538032Speter** A pointer to the map that has been created. 475638032Speter** NULL if there was a syntax error. 475738032Speter** 475838032Speter** Side Effects: 475938032Speter** Enters the map into the dictionary. 476038032Speter*/ 476138032Speter 476238032SpeterMAP * 476338032Spetermakemapentry(line) 476438032Speter char *line; 476538032Speter{ 476638032Speter register char *p; 476738032Speter char *mapname; 476838032Speter char *classname; 476938032Speter register STAB *s; 477038032Speter STAB *class; 477138032Speter 4772363466Sgshapiro for (p = line; SM_ISSPACE(*p); p++) 477338032Speter continue; 477438032Speter if (!(isascii(*p) && isalnum(*p))) 477538032Speter { 477638032Speter syserr("readcf: config K line: no map name"); 477738032Speter return NULL; 477838032Speter } 477938032Speter 478038032Speter mapname = p; 478138032Speter while ((isascii(*++p) && isalnum(*p)) || *p == '_' || *p == '.') 478238032Speter continue; 478338032Speter if (*p != '\0') 478438032Speter *p++ = '\0'; 4785363466Sgshapiro while (SM_ISSPACE(*p)) 478638032Speter p++; 478738032Speter if (!(isascii(*p) && isalnum(*p))) 478838032Speter { 478938032Speter syserr("readcf: config K line, map %s: no map class", mapname); 479038032Speter return NULL; 479138032Speter } 479238032Speter classname = p; 479338032Speter while (isascii(*++p) && isalnum(*p)) 479438032Speter continue; 479538032Speter if (*p != '\0') 479638032Speter *p++ = '\0'; 4797363466Sgshapiro while (SM_ISSPACE(*p)) 479838032Speter p++; 479938032Speter 480038032Speter /* look up the class */ 480138032Speter class = stab(classname, ST_MAPCLASS, ST_FIND); 480238032Speter if (class == NULL) 480338032Speter { 480490792Sgshapiro syserr("readcf: map %s: class %s not available", mapname, 480590792Sgshapiro classname); 480638032Speter return NULL; 480738032Speter } 480838032Speter 480938032Speter /* enter the map */ 481038032Speter s = stab(mapname, ST_MAP, ST_ENTER); 481138032Speter s->s_map.map_class = &class->s_mapclass; 481238032Speter s->s_map.map_mname = newstr(mapname); 481338032Speter 481438032Speter if (class->s_mapclass.map_parse(&s->s_map, p)) 481538032Speter s->s_map.map_mflags |= MF_VALID; 481638032Speter 481738032Speter if (tTd(37, 5)) 481838032Speter { 481990792Sgshapiro sm_dprintf("map %s, class %s, flags %lx, file %s,\n", 482090792Sgshapiro s->s_map.map_mname, s->s_map.map_class->map_cname, 482190792Sgshapiro s->s_map.map_mflags, s->s_map.map_file); 482290792Sgshapiro sm_dprintf("\tapp %s, domain %s, rebuild %s\n", 482390792Sgshapiro s->s_map.map_app, s->s_map.map_domain, 482490792Sgshapiro s->s_map.map_rebuild); 482538032Speter } 482638032Speter return &s->s_map; 482738032Speter} 482890792Sgshapiro/* 482938032Speter** STRTORWSET -- convert string to rewriting set number 483038032Speter** 483138032Speter** Parameters: 483238032Speter** p -- the pointer to the string to decode. 483338032Speter** endp -- if set, store the trailing delimiter here. 483438032Speter** stabmode -- ST_ENTER to create this entry, ST_FIND if 483538032Speter** it must already exist. 483638032Speter** 483738032Speter** Returns: 483838032Speter** The appropriate ruleset number. 483938032Speter** -1 if it is not valid (error already printed) 484038032Speter*/ 484138032Speter 484238032Speterint 484338032Speterstrtorwset(p, endp, stabmode) 484438032Speter char *p; 484538032Speter char **endp; 484638032Speter int stabmode; 484738032Speter{ 484838032Speter int ruleset; 484938032Speter static int nextruleset = MAXRWSETS; 485038032Speter 4851363466Sgshapiro while (SM_ISSPACE(*p)) 485238032Speter p++; 485338032Speter if (!isascii(*p)) 485438032Speter { 485538032Speter syserr("invalid ruleset name: \"%.20s\"", p); 485638032Speter return -1; 485738032Speter } 485838032Speter if (isdigit(*p)) 485938032Speter { 486038032Speter ruleset = strtol(p, endp, 10); 486138032Speter if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 486238032Speter { 486338032Speter syserr("bad ruleset %d (%d max)", 486438032Speter ruleset, MAXRWSETS / 2); 486538032Speter ruleset = -1; 486638032Speter } 486738032Speter } 486838032Speter else 486938032Speter { 487038032Speter STAB *s; 487138032Speter char delim; 487264562Sgshapiro char *q = NULL; 487338032Speter 487438032Speter q = p; 4875203004Sgshapiro while (*p != '\0' && isascii(*p) && (isalnum(*p) || *p == '_')) 487638032Speter p++; 487738032Speter if (q == p || !(isascii(*q) && isalpha(*q))) 487838032Speter { 487938032Speter /* no valid characters */ 488038032Speter syserr("invalid ruleset name: \"%.20s\"", q); 488138032Speter return -1; 488238032Speter } 4883363466Sgshapiro while (SM_ISSPACE(*p)) 488438032Speter *p++ = '\0'; 488538032Speter delim = *p; 488638032Speter if (delim != '\0') 488738032Speter *p = '\0'; 488838032Speter s = stab(q, ST_RULESET, stabmode); 488938032Speter if (delim != '\0') 489038032Speter *p = delim; 489138032Speter 489238032Speter if (s == NULL) 489338032Speter return -1; 489438032Speter 489538032Speter if (stabmode == ST_ENTER && delim == '=') 489638032Speter { 489738032Speter while (isascii(*++p) && isspace(*p)) 489838032Speter continue; 489938032Speter if (!(isascii(*p) && isdigit(*p))) 490038032Speter { 490138032Speter syserr("bad ruleset definition \"%s\" (number required after `=')", q); 490238032Speter ruleset = -1; 490338032Speter } 490438032Speter else 490538032Speter { 490638032Speter ruleset = strtol(p, endp, 10); 490738032Speter if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 490838032Speter { 490938032Speter syserr("bad ruleset number %d in \"%s\" (%d max)", 491038032Speter ruleset, q, MAXRWSETS / 2); 491138032Speter ruleset = -1; 491238032Speter } 491338032Speter } 491438032Speter } 491538032Speter else 491638032Speter { 491738032Speter if (endp != NULL) 491838032Speter *endp = p; 491964562Sgshapiro if (s->s_ruleset >= 0) 492038032Speter ruleset = s->s_ruleset; 492138032Speter else if ((ruleset = --nextruleset) < MAXRWSETS / 2) 492238032Speter { 492338032Speter syserr("%s: too many named rulesets (%d max)", 492438032Speter q, MAXRWSETS / 2); 492538032Speter ruleset = -1; 492638032Speter } 492738032Speter } 492864562Sgshapiro if (s->s_ruleset >= 0 && 492964562Sgshapiro ruleset >= 0 && 493064562Sgshapiro ruleset != s->s_ruleset) 493138032Speter { 493238032Speter syserr("%s: ruleset changed value (old %d, new %d)", 493338032Speter q, s->s_ruleset, ruleset); 493438032Speter ruleset = s->s_ruleset; 493538032Speter } 493664562Sgshapiro else if (ruleset >= 0) 493738032Speter { 493838032Speter s->s_ruleset = ruleset; 493938032Speter } 494071345Sgshapiro if (stabmode == ST_ENTER && ruleset >= 0) 494164562Sgshapiro { 494264562Sgshapiro char *h = NULL; 494364562Sgshapiro 494464562Sgshapiro if (RuleSetNames[ruleset] != NULL) 494590792Sgshapiro sm_free(RuleSetNames[ruleset]); /* XXX */ 494664562Sgshapiro if (delim != '\0' && (h = strchr(q, delim)) != NULL) 494764562Sgshapiro *h = '\0'; 494864562Sgshapiro RuleSetNames[ruleset] = newstr(q); 494964562Sgshapiro if (delim == '/' && h != NULL) 495064562Sgshapiro *h = delim; /* put back delim */ 495164562Sgshapiro } 495238032Speter } 495338032Speter return ruleset; 495438032Speter} 495590792Sgshapiro/* 495664562Sgshapiro** SETTIMEOUT -- set an individual timeout 495764562Sgshapiro** 495864562Sgshapiro** Parameters: 495964562Sgshapiro** name -- the name of the timeout. 496064562Sgshapiro** val -- the value of the timeout. 496164562Sgshapiro** sticky -- if set, don't let other setoptions override 496264562Sgshapiro** this value. 496364562Sgshapiro** 496464562Sgshapiro** Returns: 496564562Sgshapiro** none. 496664562Sgshapiro*/ 496764562Sgshapiro 496864562Sgshapiro/* set if Timeout sub-option is stuck */ 496964562Sgshapirostatic BITMAP256 StickyTimeoutOpt; 497064562Sgshapiro 497164562Sgshapirostatic struct timeoutinfo 497264562Sgshapiro{ 497390792Sgshapiro char *to_name; /* long name of timeout */ 497490792Sgshapiro unsigned char to_code; /* code for option */ 497564562Sgshapiro} TimeOutTab[] = 497664562Sgshapiro{ 497764562Sgshapiro#define TO_INITIAL 0x01 497864562Sgshapiro { "initial", TO_INITIAL }, 497964562Sgshapiro#define TO_MAIL 0x02 498064562Sgshapiro { "mail", TO_MAIL }, 498164562Sgshapiro#define TO_RCPT 0x03 498264562Sgshapiro { "rcpt", TO_RCPT }, 498364562Sgshapiro#define TO_DATAINIT 0x04 498464562Sgshapiro { "datainit", TO_DATAINIT }, 498564562Sgshapiro#define TO_DATABLOCK 0x05 498664562Sgshapiro { "datablock", TO_DATABLOCK }, 498764562Sgshapiro#define TO_DATAFINAL 0x06 498864562Sgshapiro { "datafinal", TO_DATAFINAL }, 498964562Sgshapiro#define TO_COMMAND 0x07 499064562Sgshapiro { "command", TO_COMMAND }, 499164562Sgshapiro#define TO_RSET 0x08 499264562Sgshapiro { "rset", TO_RSET }, 499364562Sgshapiro#define TO_HELO 0x09 499464562Sgshapiro { "helo", TO_HELO }, 499564562Sgshapiro#define TO_QUIT 0x0A 499664562Sgshapiro { "quit", TO_QUIT }, 499764562Sgshapiro#define TO_MISC 0x0B 499864562Sgshapiro { "misc", TO_MISC }, 499964562Sgshapiro#define TO_IDENT 0x0C 500064562Sgshapiro { "ident", TO_IDENT }, 500164562Sgshapiro#define TO_FILEOPEN 0x0D 500264562Sgshapiro { "fileopen", TO_FILEOPEN }, 500364562Sgshapiro#define TO_CONNECT 0x0E 500464562Sgshapiro { "connect", TO_CONNECT }, 500564562Sgshapiro#define TO_ICONNECT 0x0F 500664562Sgshapiro { "iconnect", TO_ICONNECT }, 500764562Sgshapiro#define TO_QUEUEWARN 0x10 500864562Sgshapiro { "queuewarn", TO_QUEUEWARN }, 500964562Sgshapiro { "queuewarn.*", TO_QUEUEWARN }, 501064562Sgshapiro#define TO_QUEUEWARN_NORMAL 0x11 501164562Sgshapiro { "queuewarn.normal", TO_QUEUEWARN_NORMAL }, 501264562Sgshapiro#define TO_QUEUEWARN_URGENT 0x12 501364562Sgshapiro { "queuewarn.urgent", TO_QUEUEWARN_URGENT }, 501464562Sgshapiro#define TO_QUEUEWARN_NON_URGENT 0x13 501564562Sgshapiro { "queuewarn.non-urgent", TO_QUEUEWARN_NON_URGENT }, 501664562Sgshapiro#define TO_QUEUERETURN 0x14 501764562Sgshapiro { "queuereturn", TO_QUEUERETURN }, 501864562Sgshapiro { "queuereturn.*", TO_QUEUERETURN }, 501964562Sgshapiro#define TO_QUEUERETURN_NORMAL 0x15 502064562Sgshapiro { "queuereturn.normal", TO_QUEUERETURN_NORMAL }, 502164562Sgshapiro#define TO_QUEUERETURN_URGENT 0x16 502264562Sgshapiro { "queuereturn.urgent", TO_QUEUERETURN_URGENT }, 502364562Sgshapiro#define TO_QUEUERETURN_NON_URGENT 0x17 502464562Sgshapiro { "queuereturn.non-urgent", TO_QUEUERETURN_NON_URGENT }, 502564562Sgshapiro#define TO_HOSTSTATUS 0x18 502664562Sgshapiro { "hoststatus", TO_HOSTSTATUS }, 502764562Sgshapiro#define TO_RESOLVER_RETRANS 0x19 502864562Sgshapiro { "resolver.retrans", TO_RESOLVER_RETRANS }, 502964562Sgshapiro#define TO_RESOLVER_RETRANS_NORMAL 0x1A 503064562Sgshapiro { "resolver.retrans.normal", TO_RESOLVER_RETRANS_NORMAL }, 503164562Sgshapiro#define TO_RESOLVER_RETRANS_FIRST 0x1B 503264562Sgshapiro { "resolver.retrans.first", TO_RESOLVER_RETRANS_FIRST }, 503364562Sgshapiro#define TO_RESOLVER_RETRY 0x1C 503464562Sgshapiro { "resolver.retry", TO_RESOLVER_RETRY }, 503564562Sgshapiro#define TO_RESOLVER_RETRY_NORMAL 0x1D 503664562Sgshapiro { "resolver.retry.normal", TO_RESOLVER_RETRY_NORMAL }, 503764562Sgshapiro#define TO_RESOLVER_RETRY_FIRST 0x1E 503864562Sgshapiro { "resolver.retry.first", TO_RESOLVER_RETRY_FIRST }, 503964562Sgshapiro#define TO_CONTROL 0x1F 504064562Sgshapiro { "control", TO_CONTROL }, 504190792Sgshapiro#define TO_LHLO 0x20 504290792Sgshapiro { "lhlo", TO_LHLO }, 504390792Sgshapiro#define TO_AUTH 0x21 504490792Sgshapiro { "auth", TO_AUTH }, 504590792Sgshapiro#define TO_STARTTLS 0x22 504690792Sgshapiro { "starttls", TO_STARTTLS }, 504790792Sgshapiro#define TO_ACONNECT 0x23 504890792Sgshapiro { "aconnect", TO_ACONNECT }, 5049132943Sgshapiro#define TO_QUEUEWARN_DSN 0x24 5050112810Sgshapiro { "queuewarn.dsn", TO_QUEUEWARN_DSN }, 5051132943Sgshapiro#define TO_QUEUERETURN_DSN 0x25 5052112810Sgshapiro { "queuereturn.dsn", TO_QUEUERETURN_DSN }, 505364562Sgshapiro { NULL, 0 }, 505464562Sgshapiro}; 505564562Sgshapiro 505664562Sgshapiro 505764562Sgshapirostatic void 505864562Sgshapirosettimeout(name, val, sticky) 505964562Sgshapiro char *name; 506064562Sgshapiro char *val; 506164562Sgshapiro bool sticky; 506264562Sgshapiro{ 506364562Sgshapiro register struct timeoutinfo *to; 506490792Sgshapiro int i, addopts; 506564562Sgshapiro time_t toval; 506664562Sgshapiro 506764562Sgshapiro if (tTd(37, 2)) 506890792Sgshapiro sm_dprintf("settimeout(%s = %s)", name, val); 506964562Sgshapiro 507064562Sgshapiro for (to = TimeOutTab; to->to_name != NULL; to++) 507164562Sgshapiro { 507290792Sgshapiro if (sm_strcasecmp(to->to_name, name) == 0) 507364562Sgshapiro break; 507464562Sgshapiro } 507564562Sgshapiro 507664562Sgshapiro if (to->to_name == NULL) 507771345Sgshapiro { 507871345Sgshapiro errno = 0; /* avoid bogus error text */ 507964562Sgshapiro syserr("settimeout: invalid timeout %s", name); 508071345Sgshapiro return; 508171345Sgshapiro } 508264562Sgshapiro 508364562Sgshapiro /* 508464562Sgshapiro ** See if this option is preset for us. 508564562Sgshapiro */ 508664562Sgshapiro 508764562Sgshapiro if (!sticky && bitnset(to->to_code, StickyTimeoutOpt)) 508864562Sgshapiro { 508964562Sgshapiro if (tTd(37, 2)) 509090792Sgshapiro sm_dprintf(" (ignored)\n"); 509164562Sgshapiro return; 509264562Sgshapiro } 509364562Sgshapiro 509464562Sgshapiro if (tTd(37, 2)) 509590792Sgshapiro sm_dprintf("\n"); 509664562Sgshapiro 509764562Sgshapiro toval = convtime(val, 'm'); 509880785Sgshapiro addopts = 0; 509964562Sgshapiro 510064562Sgshapiro switch (to->to_code) 510164562Sgshapiro { 510264562Sgshapiro case TO_INITIAL: 510364562Sgshapiro TimeOuts.to_initial = toval; 510464562Sgshapiro break; 510564562Sgshapiro 510664562Sgshapiro case TO_MAIL: 510764562Sgshapiro TimeOuts.to_mail = toval; 510864562Sgshapiro break; 510964562Sgshapiro 511064562Sgshapiro case TO_RCPT: 511164562Sgshapiro TimeOuts.to_rcpt = toval; 511264562Sgshapiro break; 511364562Sgshapiro 511464562Sgshapiro case TO_DATAINIT: 511564562Sgshapiro TimeOuts.to_datainit = toval; 511664562Sgshapiro break; 511764562Sgshapiro 511864562Sgshapiro case TO_DATABLOCK: 511964562Sgshapiro TimeOuts.to_datablock = toval; 512064562Sgshapiro break; 512164562Sgshapiro 512264562Sgshapiro case TO_DATAFINAL: 512364562Sgshapiro TimeOuts.to_datafinal = toval; 512464562Sgshapiro break; 512564562Sgshapiro 512664562Sgshapiro case TO_COMMAND: 512764562Sgshapiro TimeOuts.to_nextcommand = toval; 512864562Sgshapiro break; 512964562Sgshapiro 513064562Sgshapiro case TO_RSET: 513164562Sgshapiro TimeOuts.to_rset = toval; 513264562Sgshapiro break; 513364562Sgshapiro 513464562Sgshapiro case TO_HELO: 513564562Sgshapiro TimeOuts.to_helo = toval; 513664562Sgshapiro break; 513764562Sgshapiro 513864562Sgshapiro case TO_QUIT: 513964562Sgshapiro TimeOuts.to_quit = toval; 514064562Sgshapiro break; 514164562Sgshapiro 514264562Sgshapiro case TO_MISC: 514364562Sgshapiro TimeOuts.to_miscshort = toval; 514464562Sgshapiro break; 514564562Sgshapiro 514664562Sgshapiro case TO_IDENT: 514764562Sgshapiro TimeOuts.to_ident = toval; 514864562Sgshapiro break; 514964562Sgshapiro 515064562Sgshapiro case TO_FILEOPEN: 515164562Sgshapiro TimeOuts.to_fileopen = toval; 515264562Sgshapiro break; 515364562Sgshapiro 515464562Sgshapiro case TO_CONNECT: 515564562Sgshapiro TimeOuts.to_connect = toval; 515664562Sgshapiro break; 515764562Sgshapiro 515864562Sgshapiro case TO_ICONNECT: 515964562Sgshapiro TimeOuts.to_iconnect = toval; 516064562Sgshapiro break; 516164562Sgshapiro 516290792Sgshapiro case TO_ACONNECT: 516390792Sgshapiro TimeOuts.to_aconnect = toval; 516490792Sgshapiro break; 516590792Sgshapiro 516664562Sgshapiro case TO_QUEUEWARN: 516764562Sgshapiro toval = convtime(val, 'h'); 516864562Sgshapiro TimeOuts.to_q_warning[TOC_NORMAL] = toval; 516964562Sgshapiro TimeOuts.to_q_warning[TOC_URGENT] = toval; 517064562Sgshapiro TimeOuts.to_q_warning[TOC_NONURGENT] = toval; 5171112810Sgshapiro TimeOuts.to_q_warning[TOC_DSN] = toval; 517280785Sgshapiro addopts = 2; 517364562Sgshapiro break; 517464562Sgshapiro 517564562Sgshapiro case TO_QUEUEWARN_NORMAL: 517664562Sgshapiro toval = convtime(val, 'h'); 517764562Sgshapiro TimeOuts.to_q_warning[TOC_NORMAL] = toval; 517864562Sgshapiro break; 517964562Sgshapiro 518064562Sgshapiro case TO_QUEUEWARN_URGENT: 518164562Sgshapiro toval = convtime(val, 'h'); 518264562Sgshapiro TimeOuts.to_q_warning[TOC_URGENT] = toval; 518364562Sgshapiro break; 518464562Sgshapiro 518564562Sgshapiro case TO_QUEUEWARN_NON_URGENT: 518664562Sgshapiro toval = convtime(val, 'h'); 518764562Sgshapiro TimeOuts.to_q_warning[TOC_NONURGENT] = toval; 518864562Sgshapiro break; 518964562Sgshapiro 5190112810Sgshapiro case TO_QUEUEWARN_DSN: 5191112810Sgshapiro toval = convtime(val, 'h'); 5192112810Sgshapiro TimeOuts.to_q_warning[TOC_DSN] = toval; 5193112810Sgshapiro break; 5194112810Sgshapiro 519564562Sgshapiro case TO_QUEUERETURN: 519664562Sgshapiro toval = convtime(val, 'd'); 519764562Sgshapiro TimeOuts.to_q_return[TOC_NORMAL] = toval; 519864562Sgshapiro TimeOuts.to_q_return[TOC_URGENT] = toval; 519964562Sgshapiro TimeOuts.to_q_return[TOC_NONURGENT] = toval; 5200112810Sgshapiro TimeOuts.to_q_return[TOC_DSN] = toval; 520180785Sgshapiro addopts = 2; 520264562Sgshapiro break; 520364562Sgshapiro 520464562Sgshapiro case TO_QUEUERETURN_NORMAL: 520564562Sgshapiro toval = convtime(val, 'd'); 520664562Sgshapiro TimeOuts.to_q_return[TOC_NORMAL] = toval; 520764562Sgshapiro break; 520864562Sgshapiro 520964562Sgshapiro case TO_QUEUERETURN_URGENT: 521064562Sgshapiro toval = convtime(val, 'd'); 521164562Sgshapiro TimeOuts.to_q_return[TOC_URGENT] = toval; 521264562Sgshapiro break; 521364562Sgshapiro 521464562Sgshapiro case TO_QUEUERETURN_NON_URGENT: 521564562Sgshapiro toval = convtime(val, 'd'); 521664562Sgshapiro TimeOuts.to_q_return[TOC_NONURGENT] = toval; 521764562Sgshapiro break; 521864562Sgshapiro 5219112810Sgshapiro case TO_QUEUERETURN_DSN: 5220112810Sgshapiro toval = convtime(val, 'd'); 5221112810Sgshapiro TimeOuts.to_q_return[TOC_DSN] = toval; 5222112810Sgshapiro break; 5223112810Sgshapiro 522464562Sgshapiro case TO_HOSTSTATUS: 522564562Sgshapiro MciInfoTimeout = toval; 522664562Sgshapiro break; 522764562Sgshapiro 522864562Sgshapiro case TO_RESOLVER_RETRANS: 522964562Sgshapiro toval = convtime(val, 's'); 523064562Sgshapiro TimeOuts.res_retrans[RES_TO_DEFAULT] = toval; 523164562Sgshapiro TimeOuts.res_retrans[RES_TO_FIRST] = toval; 523264562Sgshapiro TimeOuts.res_retrans[RES_TO_NORMAL] = toval; 523380785Sgshapiro addopts = 2; 523464562Sgshapiro break; 523564562Sgshapiro 523664562Sgshapiro case TO_RESOLVER_RETRY: 523764562Sgshapiro i = atoi(val); 523864562Sgshapiro TimeOuts.res_retry[RES_TO_DEFAULT] = i; 523964562Sgshapiro TimeOuts.res_retry[RES_TO_FIRST] = i; 524064562Sgshapiro TimeOuts.res_retry[RES_TO_NORMAL] = i; 524180785Sgshapiro addopts = 2; 524264562Sgshapiro break; 524364562Sgshapiro 524464562Sgshapiro case TO_RESOLVER_RETRANS_NORMAL: 524564562Sgshapiro TimeOuts.res_retrans[RES_TO_NORMAL] = convtime(val, 's'); 524664562Sgshapiro break; 524764562Sgshapiro 524864562Sgshapiro case TO_RESOLVER_RETRY_NORMAL: 524964562Sgshapiro TimeOuts.res_retry[RES_TO_NORMAL] = atoi(val); 525064562Sgshapiro break; 525164562Sgshapiro 525264562Sgshapiro case TO_RESOLVER_RETRANS_FIRST: 525364562Sgshapiro TimeOuts.res_retrans[RES_TO_FIRST] = convtime(val, 's'); 525464562Sgshapiro break; 525564562Sgshapiro 525664562Sgshapiro case TO_RESOLVER_RETRY_FIRST: 525764562Sgshapiro TimeOuts.res_retry[RES_TO_FIRST] = atoi(val); 525864562Sgshapiro break; 525964562Sgshapiro 526064562Sgshapiro case TO_CONTROL: 526164562Sgshapiro TimeOuts.to_control = toval; 526264562Sgshapiro break; 526364562Sgshapiro 526490792Sgshapiro case TO_LHLO: 526590792Sgshapiro TimeOuts.to_lhlo = toval; 526690792Sgshapiro break; 526790792Sgshapiro 526890792Sgshapiro#if SASL 526990792Sgshapiro case TO_AUTH: 527090792Sgshapiro TimeOuts.to_auth = toval; 527190792Sgshapiro break; 5272363466Sgshapiro#endif 527390792Sgshapiro 527490792Sgshapiro#if STARTTLS 527590792Sgshapiro case TO_STARTTLS: 527690792Sgshapiro TimeOuts.to_starttls = toval; 527790792Sgshapiro break; 5278363466Sgshapiro#endif 527990792Sgshapiro 528064562Sgshapiro default: 528164562Sgshapiro syserr("settimeout: invalid timeout %s", name); 528264562Sgshapiro break; 528364562Sgshapiro } 528464562Sgshapiro 528564562Sgshapiro if (sticky) 528680785Sgshapiro { 528780785Sgshapiro for (i = 0; i <= addopts; i++) 528880785Sgshapiro setbitn(to->to_code + i, StickyTimeoutOpt); 528980785Sgshapiro } 529064562Sgshapiro} 529190792Sgshapiro/* 529238032Speter** INITTIMEOUTS -- parse and set timeout values 529338032Speter** 529438032Speter** Parameters: 529538032Speter** val -- a pointer to the values. If NULL, do initial 529638032Speter** settings. 529764562Sgshapiro** sticky -- if set, don't let other setoptions override 529864562Sgshapiro** this suboption value. 529938032Speter** 530038032Speter** Returns: 530138032Speter** none. 530238032Speter** 530338032Speter** Side Effects: 530438032Speter** Initializes the TimeOuts structure 530538032Speter*/ 530638032Speter 530738032Spetervoid 530864562Sgshapiroinittimeouts(val, sticky) 530938032Speter register char *val; 531064562Sgshapiro bool sticky; 531138032Speter{ 531238032Speter register char *p; 531338032Speter 531438032Speter if (tTd(37, 2)) 531590792Sgshapiro sm_dprintf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val); 531638032Speter if (val == NULL) 531738032Speter { 531838032Speter TimeOuts.to_connect = (time_t) 0 SECONDS; 531990792Sgshapiro TimeOuts.to_aconnect = (time_t) 0 SECONDS; 532094334Sgshapiro TimeOuts.to_iconnect = (time_t) 0 SECONDS; 532138032Speter TimeOuts.to_initial = (time_t) 5 MINUTES; 532238032Speter TimeOuts.to_helo = (time_t) 5 MINUTES; 532338032Speter TimeOuts.to_mail = (time_t) 10 MINUTES; 532438032Speter TimeOuts.to_rcpt = (time_t) 1 HOUR; 532538032Speter TimeOuts.to_datainit = (time_t) 5 MINUTES; 532638032Speter TimeOuts.to_datablock = (time_t) 1 HOUR; 532738032Speter TimeOuts.to_datafinal = (time_t) 1 HOUR; 532838032Speter TimeOuts.to_rset = (time_t) 5 MINUTES; 532938032Speter TimeOuts.to_quit = (time_t) 2 MINUTES; 533038032Speter TimeOuts.to_nextcommand = (time_t) 1 HOUR; 533138032Speter TimeOuts.to_miscshort = (time_t) 2 MINUTES; 533238032Speter#if IDENTPROTO 533364562Sgshapiro TimeOuts.to_ident = (time_t) 5 SECONDS; 5334363466Sgshapiro#else 533538032Speter TimeOuts.to_ident = (time_t) 0 SECONDS; 5336363466Sgshapiro#endif 533738032Speter TimeOuts.to_fileopen = (time_t) 60 SECONDS; 533864562Sgshapiro TimeOuts.to_control = (time_t) 2 MINUTES; 533990792Sgshapiro TimeOuts.to_lhlo = (time_t) 2 MINUTES; 534090792Sgshapiro#if SASL 534190792Sgshapiro TimeOuts.to_auth = (time_t) 10 MINUTES; 5342363466Sgshapiro#endif 534390792Sgshapiro#if STARTTLS 534490792Sgshapiro TimeOuts.to_starttls = (time_t) 1 HOUR; 5345363466Sgshapiro#endif 534638032Speter if (tTd(37, 5)) 534738032Speter { 534890792Sgshapiro sm_dprintf("Timeouts:\n"); 534990792Sgshapiro sm_dprintf(" connect = %ld\n", 535090792Sgshapiro (long) TimeOuts.to_connect); 535190792Sgshapiro sm_dprintf(" aconnect = %ld\n", 535290792Sgshapiro (long) TimeOuts.to_aconnect); 535390792Sgshapiro sm_dprintf(" initial = %ld\n", 535490792Sgshapiro (long) TimeOuts.to_initial); 535590792Sgshapiro sm_dprintf(" helo = %ld\n", (long) TimeOuts.to_helo); 535690792Sgshapiro sm_dprintf(" mail = %ld\n", (long) TimeOuts.to_mail); 535790792Sgshapiro sm_dprintf(" rcpt = %ld\n", (long) TimeOuts.to_rcpt); 535890792Sgshapiro sm_dprintf(" datainit = %ld\n", 535990792Sgshapiro (long) TimeOuts.to_datainit); 536090792Sgshapiro sm_dprintf(" datablock = %ld\n", 536190792Sgshapiro (long) TimeOuts.to_datablock); 536290792Sgshapiro sm_dprintf(" datafinal = %ld\n", 536390792Sgshapiro (long) TimeOuts.to_datafinal); 536490792Sgshapiro sm_dprintf(" rset = %ld\n", (long) TimeOuts.to_rset); 536590792Sgshapiro sm_dprintf(" quit = %ld\n", (long) TimeOuts.to_quit); 536690792Sgshapiro sm_dprintf(" nextcommand = %ld\n", 536790792Sgshapiro (long) TimeOuts.to_nextcommand); 536890792Sgshapiro sm_dprintf(" miscshort = %ld\n", 536990792Sgshapiro (long) TimeOuts.to_miscshort); 537090792Sgshapiro sm_dprintf(" ident = %ld\n", (long) TimeOuts.to_ident); 537190792Sgshapiro sm_dprintf(" fileopen = %ld\n", 537290792Sgshapiro (long) TimeOuts.to_fileopen); 537390792Sgshapiro sm_dprintf(" lhlo = %ld\n", 537490792Sgshapiro (long) TimeOuts.to_lhlo); 537590792Sgshapiro sm_dprintf(" control = %ld\n", 537690792Sgshapiro (long) TimeOuts.to_control); 537738032Speter } 537838032Speter return; 537938032Speter } 538038032Speter 538138032Speter for (;; val = p) 538238032Speter { 5383363466Sgshapiro while (SM_ISSPACE(*val)) 538438032Speter val++; 538538032Speter if (*val == '\0') 538638032Speter break; 538738032Speter for (p = val; *p != '\0' && *p != ','; p++) 538838032Speter continue; 538938032Speter if (*p != '\0') 539038032Speter *p++ = '\0'; 539138032Speter 539238032Speter if (isascii(*val) && isdigit(*val)) 539338032Speter { 539438032Speter /* old syntax -- set everything */ 539538032Speter TimeOuts.to_mail = convtime(val, 'm'); 539638032Speter TimeOuts.to_rcpt = TimeOuts.to_mail; 539738032Speter TimeOuts.to_datainit = TimeOuts.to_mail; 539838032Speter TimeOuts.to_datablock = TimeOuts.to_mail; 539938032Speter TimeOuts.to_datafinal = TimeOuts.to_mail; 540038032Speter TimeOuts.to_nextcommand = TimeOuts.to_mail; 540164562Sgshapiro if (sticky) 540264562Sgshapiro { 540364562Sgshapiro setbitn(TO_MAIL, StickyTimeoutOpt); 540464562Sgshapiro setbitn(TO_RCPT, StickyTimeoutOpt); 540564562Sgshapiro setbitn(TO_DATAINIT, StickyTimeoutOpt); 540664562Sgshapiro setbitn(TO_DATABLOCK, StickyTimeoutOpt); 540764562Sgshapiro setbitn(TO_DATAFINAL, StickyTimeoutOpt); 540864562Sgshapiro setbitn(TO_COMMAND, StickyTimeoutOpt); 540964562Sgshapiro } 541038032Speter continue; 541138032Speter } 541238032Speter else 541338032Speter { 541438032Speter register char *q = strchr(val, ':'); 541538032Speter 541638032Speter if (q == NULL && (q = strchr(val, '=')) == NULL) 541738032Speter { 541838032Speter /* syntax error */ 541938032Speter continue; 542038032Speter } 542138032Speter *q++ = '\0'; 542264562Sgshapiro settimeout(val, q, sticky); 542338032Speter } 542438032Speter } 542538032Speter} 5426