138032Speter/* 2261363Sgshapiro * 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> 1638032Speter 17266692SgshapiroSM_RCSID("@(#)$Id: readcf.c,v 8.692 2013-11-22 20:51:56 ca Exp $") 1864562Sgshapiro 1964562Sgshapiro#if NETINET || NETINET6 2064562Sgshapiro# include <arpa/inet.h> 2164562Sgshapiro#endif /* NETINET || NETINET6 */ 2264562Sgshapiro 23223067Sgshapiro 2464562Sgshapiro#define SECONDS 2564562Sgshapiro#define MINUTES * 60 2664562Sgshapiro#define HOUR * 3600 2764562Sgshapiro#define HOURS HOUR 2864562Sgshapiro 2994334Sgshapirostatic void fileclass __P((int, char *, char *, bool, bool, bool)); 3064562Sgshapirostatic char **makeargv __P((char *)); 3164562Sgshapirostatic void settimeout __P((char *, char *, bool)); 3264562Sgshapirostatic void toomany __P((int, int)); 3390792Sgshapirostatic char *extrquotstr __P((char *, char **, char *, bool *)); 34141858Sgshapirostatic void parse_class_words __P((int, char *)); 3564562Sgshapiro 36285303Sgshapiro 37285303Sgshapiro#if _FFR_BOUNCE_QUEUE 38285303Sgshapirostatic char *bouncequeue = NULL; 39285303Sgshapirostatic void initbouncequeue __P((void)); 40285303Sgshapiro 4138032Speter/* 42285303Sgshapiro** INITBOUNCEQUEUE -- determine BounceQueue if option is set. 43285303Sgshapiro** 44285303Sgshapiro** Parameters: 45285303Sgshapiro** none. 46285303Sgshapiro** 47285303Sgshapiro** Returns: 48285303Sgshapiro** none. 49285303Sgshapiro** 50285303Sgshapiro** Side Effects: 51285303Sgshapiro** sets BounceQueue 52285303Sgshapiro*/ 53285303Sgshapiro 54285303Sgshapirostatic void 55285303Sgshapiroinitbouncequeue() 56285303Sgshapiro{ 57285303Sgshapiro STAB *s; 58285303Sgshapiro 59285303Sgshapiro BounceQueue = NOQGRP; 60285303Sgshapiro if (bouncequeue == NULL || bouncequeue[0] == '\0') 61285303Sgshapiro return; 62285303Sgshapiro 63285303Sgshapiro s = stab(bouncequeue, ST_QUEUE, ST_FIND); 64285303Sgshapiro if (s == NULL) 65285303Sgshapiro { 66285303Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 67285303Sgshapiro "Warning: option BounceQueue: unknown queue group %s\n", 68285303Sgshapiro bouncequeue); 69285303Sgshapiro } 70285303Sgshapiro else 71285303Sgshapiro BounceQueue = s->s_quegrp->qg_index; 72285303Sgshapiro} 73285303Sgshapiro#endif /* _FFR_BOUNCE_QUEUE */ 74285303Sgshapiro 75285303Sgshapiro#if _FFR_RCPTFLAGS 76285303Sgshapirovoid setupdynmailers __P((void)); 77285303Sgshapiro#else 78285303Sgshapiro#define setupdynmailers() 79285303Sgshapiro#endif 80285303Sgshapiro 81285303Sgshapiro/* 8238032Speter** READCF -- read configuration file. 8338032Speter** 8438032Speter** This routine reads the configuration file and builds the internal 8538032Speter** form. 8638032Speter** 8738032Speter** The file is formatted as a sequence of lines, each taken 8838032Speter** atomically. The first character of each line describes how 8938032Speter** the line is to be interpreted. The lines are: 9038032Speter** Dxval Define macro x to have value val. 9138032Speter** Cxword Put word into class x. 9238032Speter** Fxfile [fmt] Read file for lines to put into 9338032Speter** class x. Use scanf string 'fmt' 9438032Speter** or "%s" if not present. Fmt should 9538032Speter** only produce one string-valued result. 9638032Speter** Hname: value Define header with field-name 'name' 9738032Speter** and value as specified; this will be 9838032Speter** macro expanded immediately before 9938032Speter** use. 10038032Speter** Sn Use rewriting set n. 10138032Speter** Rlhs rhs Rewrite addresses that match lhs to 10238032Speter** be rhs. 10338032Speter** Mn arg=val... Define mailer. n is the internal name. 10438032Speter** Args specify mailer parameters. 10538032Speter** Oxvalue Set option x to value. 10690792Sgshapiro** O option value Set option (long name) to value. 10738032Speter** Pname=value Set precedence name to value. 10890792Sgshapiro** Qn arg=val... Define queue groups. n is the internal name. 10990792Sgshapiro** Args specify queue parameters. 11038032Speter** Vversioncode[/vendorcode] 11138032Speter** Version level/vendor name of 11238032Speter** configuration syntax. 11338032Speter** Kmapname mapclass arguments.... 11438032Speter** Define keyed lookup of a given class. 11538032Speter** Arguments are class dependent. 11638032Speter** Eenvar=value Set the environment value to the given value. 11738032Speter** 11838032Speter** Parameters: 11938032Speter** cfname -- configuration file name. 12090792Sgshapiro** safe -- true if this is the system config file; 12190792Sgshapiro** false otherwise. 12238032Speter** e -- the main envelope. 12338032Speter** 12438032Speter** Returns: 12538032Speter** none. 12638032Speter** 12738032Speter** Side Effects: 12838032Speter** Builds several internal tables. 12938032Speter*/ 13038032Speter 13138032Spetervoid 13238032Speterreadcf(cfname, safe, e) 13338032Speter char *cfname; 13438032Speter bool safe; 13538032Speter register ENVELOPE *e; 13638032Speter{ 13790792Sgshapiro SM_FILE_T *cf; 13864562Sgshapiro int ruleset = -1; 13938032Speter char *q; 14038032Speter struct rewrite *rwp = NULL; 14138032Speter char *bp; 14238032Speter auto char *ep; 14338032Speter int nfuzzy; 14438032Speter char *file; 14538032Speter bool optional; 14690792Sgshapiro bool ok; 14794334Sgshapiro bool ismap; 14838032Speter int mid; 14938032Speter register char *p; 15064562Sgshapiro long sff = SFF_OPENASROOT; 15138032Speter struct stat statb; 15238032Speter char buf[MAXLINE]; 153168515Sgshapiro int bufsize; 15438032Speter char exbuf[MAXLINE]; 15538032Speter char pvpbuf[MAXLINE + MAXATOM]; 15638032Speter static char *null_list[1] = { NULL }; 15790792Sgshapiro extern unsigned char TokTypeNoC[]; 15838032Speter 15938032Speter FileName = cfname; 16038032Speter LineNumber = 0; 16138032Speter 162203004Sgshapiro#if STARTTLS 163223067Sgshapiro Srv_SSL_Options = SSL_OP_ALL; 164223067Sgshapiro Clt_SSL_Options = SSL_OP_ALL 165285303Sgshapiro# ifdef SSL_OP_NO_SSLv2 166223067Sgshapiro | SSL_OP_NO_SSLv2 167285303Sgshapiro# endif 168285303Sgshapiro# ifdef SSL_OP_NO_TICKET 169223067Sgshapiro | SSL_OP_NO_TICKET 170285303Sgshapiro# endif 171223067Sgshapiro ; 172285303Sgshapiro# ifdef SSL_OP_TLSEXT_PADDING 173285303Sgshapiro /* SSL_OP_TLSEXT_PADDING breaks compatibility with some sites */ 174285303Sgshapiro Srv_SSL_Options &= ~SSL_OP_TLSEXT_PADDING; 175285303Sgshapiro Clt_SSL_Options &= ~SSL_OP_TLSEXT_PADDING; 176285303Sgshapiro# endif /* SSL_OP_TLSEXT_PADDING */ 177203004Sgshapiro#endif /* STARTTLS */ 17838032Speter if (DontLockReadFiles) 17938032Speter sff |= SFF_NOLOCK; 18038032Speter cf = safefopen(cfname, O_RDONLY, 0444, sff); 18138032Speter if (cf == NULL) 18238032Speter { 18338032Speter syserr("cannot open"); 18490792Sgshapiro finis(false, true, EX_OSFILE); 18538032Speter } 18638032Speter 18790792Sgshapiro if (fstat(sm_io_getinfo(cf, SM_IO_WHAT_FD, NULL), &statb) < 0) 18838032Speter { 18938032Speter syserr("cannot fstat"); 19090792Sgshapiro finis(false, true, EX_OSFILE); 19138032Speter } 19238032Speter 19338032Speter if (!S_ISREG(statb.st_mode)) 19438032Speter { 19538032Speter syserr("not a plain file"); 19690792Sgshapiro finis(false, true, EX_OSFILE); 19738032Speter } 19838032Speter 19938032Speter if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode)) 20038032Speter { 201203004Sgshapiro if (OpMode == MD_DAEMON || OpMode == MD_INITALIAS || OpMode == MD_CHECKCONFIG) 20290792Sgshapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 20390792Sgshapiro "%s: WARNING: dangerous write permissions\n", 20490792Sgshapiro FileName); 20538032Speter if (LogLevel > 0) 20638032Speter sm_syslog(LOG_CRIT, NOQID, 20764562Sgshapiro "%s: WARNING: dangerous write permissions", 20864562Sgshapiro FileName); 20938032Speter } 21038032Speter 21190792Sgshapiro#if XLA 21238032Speter xla_zero(); 21364562Sgshapiro#endif /* XLA */ 21438032Speter 215168515Sgshapiro while (bufsize = sizeof(buf), 216168515Sgshapiro (bp = fgetfolded(buf, &bufsize, cf)) != NULL) 21738032Speter { 218168515Sgshapiro char *nbp; 219168515Sgshapiro 22038032Speter if (bp[0] == '#') 22138032Speter { 22238032Speter if (bp != buf) 22390792Sgshapiro sm_free(bp); /* XXX */ 22438032Speter continue; 22538032Speter } 22638032Speter 22738032Speter /* do macro expansion mappings */ 228168515Sgshapiro nbp = translate_dollars(bp, bp, &bufsize); 229168515Sgshapiro if (nbp != bp && bp != buf) 230168515Sgshapiro sm_free(bp); 231168515Sgshapiro bp = nbp; 23238032Speter 23338032Speter /* interpret this line */ 23438032Speter errno = 0; 23538032Speter switch (bp[0]) 23638032Speter { 23738032Speter case '\0': 23838032Speter case '#': /* comment */ 23938032Speter break; 24038032Speter 24138032Speter case 'R': /* rewriting rule */ 24264562Sgshapiro if (ruleset < 0) 24364562Sgshapiro { 24464562Sgshapiro syserr("missing valid ruleset for \"%s\"", bp); 24564562Sgshapiro break; 24664562Sgshapiro } 24738032Speter for (p = &bp[1]; *p != '\0' && *p != '\t'; p++) 24838032Speter continue; 24938032Speter 25038032Speter if (*p == '\0') 25138032Speter { 25238032Speter syserr("invalid rewrite line \"%s\" (tab expected)", bp); 25338032Speter break; 25438032Speter } 25538032Speter 25638032Speter /* allocate space for the rule header */ 25738032Speter if (rwp == NULL) 25838032Speter { 25938032Speter RewriteRules[ruleset] = rwp = 260168515Sgshapiro (struct rewrite *) xalloc(sizeof(*rwp)); 26138032Speter } 26238032Speter else 26338032Speter { 264168515Sgshapiro rwp->r_next = (struct rewrite *) xalloc(sizeof(*rwp)); 26538032Speter rwp = rwp->r_next; 26638032Speter } 26738032Speter rwp->r_next = NULL; 26838032Speter 26938032Speter /* expand and save the LHS */ 27038032Speter *p = '\0'; 271168515Sgshapiro expand(&bp[1], exbuf, sizeof(exbuf), e); 27238032Speter rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, 273168515Sgshapiro sizeof(pvpbuf), NULL, 274168515Sgshapiro ConfigLevel >= 9 ? TokTypeNoC : IntTokenTab, 275132943Sgshapiro true); 27638032Speter nfuzzy = 0; 27738032Speter if (rwp->r_lhs != NULL) 27838032Speter { 27938032Speter register char **ap; 28038032Speter 28190792Sgshapiro rwp->r_lhs = copyplist(rwp->r_lhs, true, NULL); 28238032Speter 28338032Speter /* count the number of fuzzy matches in LHS */ 28438032Speter for (ap = rwp->r_lhs; *ap != NULL; ap++) 28538032Speter { 28638032Speter char *botch; 28738032Speter 28838032Speter botch = NULL; 289168515Sgshapiro switch (ap[0][0] & 0377) 29038032Speter { 29138032Speter case MATCHZANY: 29238032Speter case MATCHANY: 29338032Speter case MATCHONE: 29438032Speter case MATCHCLASS: 29538032Speter case MATCHNCLASS: 29638032Speter nfuzzy++; 29738032Speter break; 29838032Speter 29938032Speter case MATCHREPL: 300168515Sgshapiro botch = "$1-$9"; 30138032Speter break; 30238032Speter 30338032Speter case CANONUSER: 30438032Speter botch = "$:"; 30538032Speter break; 30638032Speter 30738032Speter case CALLSUBR: 30838032Speter botch = "$>"; 30938032Speter break; 31038032Speter 31138032Speter case CONDIF: 31238032Speter botch = "$?"; 31338032Speter break; 31438032Speter 31538032Speter case CONDFI: 31638032Speter botch = "$."; 31738032Speter break; 31838032Speter 31938032Speter case HOSTBEGIN: 32038032Speter botch = "$["; 32138032Speter break; 32238032Speter 32338032Speter case HOSTEND: 32438032Speter botch = "$]"; 32538032Speter break; 32638032Speter 32738032Speter case LOOKUPBEGIN: 32838032Speter botch = "$("; 32938032Speter break; 33038032Speter 33138032Speter case LOOKUPEND: 33238032Speter botch = "$)"; 33338032Speter break; 33438032Speter } 33538032Speter if (botch != NULL) 33638032Speter syserr("Inappropriate use of %s on LHS", 33738032Speter botch); 33838032Speter } 33964562Sgshapiro rwp->r_line = LineNumber; 34038032Speter } 34138032Speter else 34238032Speter { 34338032Speter syserr("R line: null LHS"); 34438032Speter rwp->r_lhs = null_list; 34538032Speter } 34682017Sgshapiro if (nfuzzy > MAXMATCH) 34782017Sgshapiro { 34882017Sgshapiro syserr("R line: too many wildcards"); 34982017Sgshapiro rwp->r_lhs = null_list; 35082017Sgshapiro } 35138032Speter 35238032Speter /* expand and save the RHS */ 35338032Speter while (*++p == '\t') 35438032Speter continue; 35538032Speter q = p; 35638032Speter while (*p != '\0' && *p != '\t') 35738032Speter p++; 35838032Speter *p = '\0'; 359168515Sgshapiro expand(q, exbuf, sizeof(exbuf), e); 36038032Speter rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, 361168515Sgshapiro sizeof(pvpbuf), NULL, 362168515Sgshapiro ConfigLevel >= 9 ? TokTypeNoC : IntTokenTab, 363132943Sgshapiro true); 36438032Speter if (rwp->r_rhs != NULL) 36538032Speter { 36638032Speter register char **ap; 367120256Sgshapiro int args, endtoken; 368120256Sgshapiro#if _FFR_EXTRA_MAP_CHECK 369120256Sgshapiro int nexttoken; 370120256Sgshapiro#endif /* _FFR_EXTRA_MAP_CHECK */ 371120256Sgshapiro bool inmap; 37238032Speter 37390792Sgshapiro rwp->r_rhs = copyplist(rwp->r_rhs, true, NULL); 37438032Speter 37538032Speter /* check no out-of-bounds replacements */ 37638032Speter nfuzzy += '0'; 377120256Sgshapiro inmap = false; 378120256Sgshapiro args = 0; 379120256Sgshapiro endtoken = 0; 38038032Speter for (ap = rwp->r_rhs; *ap != NULL; ap++) 38138032Speter { 38238032Speter char *botch; 38338032Speter 38438032Speter botch = NULL; 385168515Sgshapiro switch (ap[0][0] & 0377) 38638032Speter { 38738032Speter case MATCHREPL: 388168515Sgshapiro if (ap[0][1] <= '0' || 389168515Sgshapiro ap[0][1] > nfuzzy) 39038032Speter { 39138032Speter syserr("replacement $%c out of bounds", 392168515Sgshapiro ap[0][1]); 39338032Speter } 39438032Speter break; 39538032Speter 39638032Speter case MATCHZANY: 39738032Speter botch = "$*"; 39838032Speter break; 39938032Speter 40038032Speter case MATCHANY: 40138032Speter botch = "$+"; 40238032Speter break; 40338032Speter 40438032Speter case MATCHONE: 40538032Speter botch = "$-"; 40638032Speter break; 40738032Speter 40838032Speter case MATCHCLASS: 40938032Speter botch = "$="; 41038032Speter break; 41138032Speter 41238032Speter case MATCHNCLASS: 41338032Speter botch = "$~"; 41438032Speter break; 41590792Sgshapiro 416120256Sgshapiro case CANONHOST: 417120256Sgshapiro if (!inmap) 418120256Sgshapiro break; 419120256Sgshapiro if (++args >= MAX_MAP_ARGS) 420120256Sgshapiro syserr("too many arguments for map lookup"); 421120256Sgshapiro break; 422120256Sgshapiro 423120256Sgshapiro case HOSTBEGIN: 424120256Sgshapiro endtoken = HOSTEND; 425120256Sgshapiro /* FALLTHROUGH */ 426120256Sgshapiro case LOOKUPBEGIN: 427120256Sgshapiro /* see above... */ 428168515Sgshapiro if ((ap[0][0] & 0377) == LOOKUPBEGIN) 429120256Sgshapiro endtoken = LOOKUPEND; 430120256Sgshapiro if (inmap) 431120256Sgshapiro syserr("cannot nest map lookups"); 432120256Sgshapiro inmap = true; 433120256Sgshapiro args = 0; 434120256Sgshapiro#if _FFR_EXTRA_MAP_CHECK 435168515Sgshapiro if (ap[1] == NULL) 436120256Sgshapiro { 437120256Sgshapiro syserr("syntax error in map lookup"); 438120256Sgshapiro break; 439120256Sgshapiro } 440168515Sgshapiro nexttoken = ap[1][0] & 0377; 441120256Sgshapiro if (nexttoken == CANONHOST || 442120256Sgshapiro nexttoken == CANONUSER || 443168515Sgshapiro nexttoken == endtoken)) 444120256Sgshapiro { 445120256Sgshapiro syserr("missing map name for lookup"); 446120256Sgshapiro break; 447120256Sgshapiro } 448168515Sgshapiro if (ap[2] == NULL) 449120256Sgshapiro { 450120256Sgshapiro syserr("syntax error in map lookup"); 451120256Sgshapiro break; 452120256Sgshapiro } 453168515Sgshapiro if (ap[0][0] == HOSTBEGIN) 454120256Sgshapiro break; 455168515Sgshapiro nexttoken = ap[2][0] & 0377; 456120256Sgshapiro if (nexttoken == CANONHOST || 457120256Sgshapiro nexttoken == CANONUSER || 458120256Sgshapiro nexttoken == endtoken) 459120256Sgshapiro { 460120256Sgshapiro syserr("missing key name for lookup"); 461120256Sgshapiro break; 462120256Sgshapiro } 463120256Sgshapiro#endif /* _FFR_EXTRA_MAP_CHECK */ 464120256Sgshapiro break; 465120256Sgshapiro 466120256Sgshapiro case HOSTEND: 467120256Sgshapiro case LOOKUPEND: 468168515Sgshapiro if ((ap[0][0] & 0377) != endtoken) 469120256Sgshapiro break; 470120256Sgshapiro inmap = false; 471120256Sgshapiro endtoken = 0; 472120256Sgshapiro break; 473120256Sgshapiro 474120256Sgshapiro 47590792Sgshapiro#if 0 47690792Sgshapiro/* 47790792Sgshapiro** This doesn't work yet as there are maps defined *after* the cf 47890792Sgshapiro** is read such as host, user, and alias. So for now, it's removed. 47990792Sgshapiro** When it comes back, the RELEASE_NOTES entry will be: 48090792Sgshapiro** Emit warnings for unknown maps when reading the .cf file. Based on 48190792Sgshapiro** patch from Robert Harker of Harker Systems. 48290792Sgshapiro*/ 48390792Sgshapiro 48490792Sgshapiro case LOOKUPBEGIN: 48590792Sgshapiro /* 48690792Sgshapiro ** Got a database lookup, 48790792Sgshapiro ** check if map is defined. 48890792Sgshapiro */ 48990792Sgshapiro 490168515Sgshapiro ep = ap[1]; 491168515Sgshapiro if ((ep[0] & 0377) != MACRODEXPAND && 492168515Sgshapiro stab(ep, ST_MAP, ST_FIND) == NULL) 49390792Sgshapiro { 49490792Sgshapiro (void) sm_io_fprintf(smioout, 49590792Sgshapiro SM_TIME_DEFAULT, 49690792Sgshapiro "Warning: %s: line %d: map %s not found\n", 49790792Sgshapiro FileName, 49890792Sgshapiro LineNumber, 49990792Sgshapiro ep); 50090792Sgshapiro } 50190792Sgshapiro break; 50290792Sgshapiro#endif /* 0 */ 50338032Speter } 50438032Speter if (botch != NULL) 50538032Speter syserr("Inappropriate use of %s on RHS", 50638032Speter botch); 50738032Speter } 508120256Sgshapiro if (inmap) 509120256Sgshapiro syserr("missing map closing token"); 51038032Speter } 51138032Speter else 51238032Speter { 51338032Speter syserr("R line: null RHS"); 51438032Speter rwp->r_rhs = null_list; 51538032Speter } 51638032Speter break; 51738032Speter 51838032Speter case 'S': /* select rewriting set */ 519168515Sgshapiro expand(&bp[1], exbuf, sizeof(exbuf), e); 52038032Speter ruleset = strtorwset(exbuf, NULL, ST_ENTER); 52138032Speter if (ruleset < 0) 52238032Speter break; 52364562Sgshapiro 52438032Speter rwp = RewriteRules[ruleset]; 52538032Speter if (rwp != NULL) 52638032Speter { 527203004Sgshapiro if (OpMode == MD_TEST || OpMode == MD_CHECKCONFIG) 52890792Sgshapiro (void) sm_io_fprintf(smioout, 52990792Sgshapiro SM_TIME_DEFAULT, 53090792Sgshapiro "WARNING: Ruleset %s has multiple definitions\n", 53190792Sgshapiro &bp[1]); 53264562Sgshapiro if (tTd(37, 1)) 53390792Sgshapiro sm_dprintf("WARNING: Ruleset %s has multiple definitions\n", 53490792Sgshapiro &bp[1]); 53538032Speter while (rwp->r_next != NULL) 53638032Speter rwp = rwp->r_next; 53738032Speter } 53838032Speter break; 53938032Speter 54038032Speter case 'D': /* macro definition */ 54190792Sgshapiro mid = macid_parse(&bp[1], &ep); 54271345Sgshapiro if (mid == 0) 54371345Sgshapiro break; 54438032Speter p = munchstring(ep, NULL, '\0'); 54590792Sgshapiro macdefine(&e->e_macro, A_TEMP, mid, p); 54638032Speter break; 54738032Speter 54838032Speter case 'H': /* required header line */ 54964562Sgshapiro (void) chompheader(&bp[1], CHHDR_DEF, NULL, e); 55038032Speter break; 55138032Speter 55238032Speter case 'C': /* word class */ 55338032Speter case 'T': /* trusted user (set class `t') */ 55438032Speter if (bp[0] == 'C') 55538032Speter { 55690792Sgshapiro mid = macid_parse(&bp[1], &ep); 55771345Sgshapiro if (mid == 0) 55871345Sgshapiro break; 559168515Sgshapiro expand(ep, exbuf, sizeof(exbuf), e); 56038032Speter p = exbuf; 56138032Speter } 56238032Speter else 56338032Speter { 56438032Speter mid = 't'; 56538032Speter p = &bp[1]; 56638032Speter } 56738032Speter while (*p != '\0') 56838032Speter { 56938032Speter register char *wd; 57038032Speter char delim; 57138032Speter 57238032Speter while (*p != '\0' && isascii(*p) && isspace(*p)) 57338032Speter p++; 57438032Speter wd = p; 57538032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 57638032Speter p++; 57738032Speter delim = *p; 57838032Speter *p = '\0'; 57938032Speter if (wd[0] != '\0') 58038032Speter setclass(mid, wd); 58138032Speter *p = delim; 58238032Speter } 58338032Speter break; 58438032Speter 58538032Speter case 'F': /* word class from file */ 58690792Sgshapiro mid = macid_parse(&bp[1], &ep); 58771345Sgshapiro if (mid == 0) 58871345Sgshapiro break; 58938032Speter for (p = ep; isascii(*p) && isspace(*p); ) 59038032Speter p++; 59138032Speter if (p[0] == '-' && p[1] == 'o') 59238032Speter { 59390792Sgshapiro optional = true; 59490792Sgshapiro while (*p != '\0' && 59590792Sgshapiro !(isascii(*p) && isspace(*p))) 59638032Speter p++; 59738032Speter while (isascii(*p) && isspace(*p)) 59838032Speter p++; 59938032Speter } 60038032Speter else 60190792Sgshapiro optional = false; 60264562Sgshapiro 60394334Sgshapiro /* check if [key]@map:spec */ 60494334Sgshapiro ismap = false; 60594334Sgshapiro if (!SM_IS_DIR_DELIM(*p) && 60694334Sgshapiro *p != '|' && 60794334Sgshapiro (q = strchr(p, '@')) != NULL) 60890792Sgshapiro { 60994334Sgshapiro q++; 61094334Sgshapiro 61194334Sgshapiro /* look for @LDAP or @map: in string */ 61294334Sgshapiro if (strcmp(q, "LDAP") == 0 || 61394334Sgshapiro (*q != ':' && 61494334Sgshapiro strchr(q, ':') != NULL)) 61594334Sgshapiro ismap = true; 61694334Sgshapiro } 61794334Sgshapiro 61894334Sgshapiro if (ismap) 61994334Sgshapiro { 62090792Sgshapiro /* use entire spec */ 62190792Sgshapiro file = p; 62290792Sgshapiro } 62390792Sgshapiro else 62490792Sgshapiro { 62590792Sgshapiro file = extrquotstr(p, &q, " ", &ok); 62690792Sgshapiro if (!ok) 62790792Sgshapiro { 62890792Sgshapiro syserr("illegal filename '%s'", p); 62990792Sgshapiro break; 63090792Sgshapiro } 63190792Sgshapiro } 63290792Sgshapiro 63394334Sgshapiro if (*file == '|' || ismap) 63438032Speter p = "%s"; 63538032Speter else 63638032Speter { 63764562Sgshapiro p = q; 63838032Speter if (*p == '\0') 63938032Speter p = "%s"; 64038032Speter else 64138032Speter { 64238032Speter *p = '\0'; 64338032Speter while (isascii(*++p) && isspace(*p)) 64438032Speter continue; 64538032Speter } 64638032Speter } 64794334Sgshapiro fileclass(mid, file, p, ismap, safe, optional); 64838032Speter break; 64938032Speter 65090792Sgshapiro#if XLA 65138032Speter case 'L': /* extended load average description */ 65238032Speter xla_init(&bp[1]); 65338032Speter break; 65464562Sgshapiro#endif /* XLA */ 65538032Speter 65638032Speter#if defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) 65738032Speter case 'L': /* lookup macro */ 65838032Speter case 'G': /* lookup class */ 65938032Speter /* reserved for Sun -- NIS+ database lookup */ 66038032Speter if (VendorCode != VENDOR_SUN) 66138032Speter goto badline; 66238032Speter sun_lg_config_line(bp, e); 66338032Speter break; 66464562Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) */ 66538032Speter 66638032Speter case 'M': /* define mailer */ 66738032Speter makemailer(&bp[1]); 66838032Speter break; 66938032Speter 67038032Speter case 'O': /* set option */ 67190792Sgshapiro setoption(bp[1], &bp[2], safe, false, e); 67238032Speter break; 67338032Speter 67438032Speter case 'P': /* set precedence */ 67538032Speter if (NumPriorities >= MAXPRIORITIES) 67638032Speter { 67738032Speter toomany('P', MAXPRIORITIES); 67838032Speter break; 67938032Speter } 68038032Speter for (p = &bp[1]; *p != '\0' && *p != '='; p++) 68138032Speter continue; 68238032Speter if (*p == '\0') 68338032Speter goto badline; 68438032Speter *p = '\0'; 68538032Speter Priorities[NumPriorities].pri_name = newstr(&bp[1]); 68638032Speter Priorities[NumPriorities].pri_val = atoi(++p); 68738032Speter NumPriorities++; 68838032Speter break; 68938032Speter 69090792Sgshapiro case 'Q': /* define queue */ 69190792Sgshapiro makequeue(&bp[1], true); 69290792Sgshapiro break; 69390792Sgshapiro 69438032Speter case 'V': /* configuration syntax version */ 69538032Speter for (p = &bp[1]; isascii(*p) && isspace(*p); p++) 69638032Speter continue; 69738032Speter if (!isascii(*p) || !isdigit(*p)) 69838032Speter { 69964562Sgshapiro syserr("invalid argument to V line: \"%.20s\"", 70038032Speter &bp[1]); 70138032Speter break; 70238032Speter } 70338032Speter ConfigLevel = strtol(p, &ep, 10); 70438032Speter 70538032Speter /* 70638032Speter ** Do heuristic tweaking for back compatibility. 70738032Speter */ 70838032Speter 70938032Speter if (ConfigLevel >= 5) 71038032Speter { 71138032Speter /* level 5 configs have short name in $w */ 71238032Speter p = macvalue('w', e); 71338032Speter if (p != NULL && (p = strchr(p, '.')) != NULL) 71490792Sgshapiro { 71538032Speter *p = '\0'; 71690792Sgshapiro macdefine(&e->e_macro, A_TEMP, 'w', 71790792Sgshapiro macvalue('w', e)); 71890792Sgshapiro } 71938032Speter } 72038032Speter if (ConfigLevel >= 6) 72138032Speter { 72290792Sgshapiro ColonOkInAddr = false; 72338032Speter } 72438032Speter 72538032Speter /* 72638032Speter ** Look for vendor code. 72738032Speter */ 72838032Speter 72938032Speter if (*ep++ == '/') 73038032Speter { 73138032Speter /* extract vendor code */ 73238032Speter for (p = ep; isascii(*p) && isalpha(*p); ) 73338032Speter p++; 73438032Speter *p = '\0'; 73538032Speter 73638032Speter if (!setvendor(ep)) 73738032Speter syserr("invalid V line vendor code: \"%s\"", 73838032Speter ep); 73938032Speter } 74038032Speter break; 74138032Speter 74238032Speter case 'K': 743168515Sgshapiro expand(&bp[1], exbuf, sizeof(exbuf), e); 74438032Speter (void) makemapentry(exbuf); 74538032Speter break; 74638032Speter 74738032Speter case 'E': 74838032Speter p = strchr(bp, '='); 74938032Speter if (p != NULL) 75038032Speter *p++ = '\0'; 751157001Sgshapiro sm_setuserenv(&bp[1], p); 75238032Speter break; 75338032Speter 75464562Sgshapiro case 'X': /* mail filter */ 75590792Sgshapiro#if MILTER 75664562Sgshapiro milter_setup(&bp[1]); 75790792Sgshapiro#else /* MILTER */ 75890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 75990792Sgshapiro "Warning: Filter usage ('X') requires Milter support (-DMILTER)\n"); 76090792Sgshapiro#endif /* MILTER */ 76164562Sgshapiro break; 76264562Sgshapiro 76338032Speter default: 76438032Speter badline: 76538032Speter syserr("unknown configuration line \"%s\"", bp); 76638032Speter } 76738032Speter if (bp != buf) 76890792Sgshapiro sm_free(bp); /* XXX */ 76938032Speter } 77090792Sgshapiro if (sm_io_error(cf)) 77138032Speter { 77238032Speter syserr("I/O read error"); 77390792Sgshapiro finis(false, true, EX_OSFILE); 77438032Speter } 77590792Sgshapiro (void) sm_io_close(cf, SM_TIME_DEFAULT); 77638032Speter FileName = NULL; 77738032Speter 778285303Sgshapiro#if _FFR_BOUNCE_QUEUE 779285303Sgshapiro initbouncequeue(); 780285303Sgshapiro#endif 781285303Sgshapiro 78238032Speter /* initialize host maps from local service tables */ 78338032Speter inithostmaps(); 78438032Speter 78564562Sgshapiro /* initialize daemon (if not defined yet) */ 78664562Sgshapiro initdaemon(); 78764562Sgshapiro 78838032Speter /* determine if we need to do special name-server frotz */ 78938032Speter { 79038032Speter int nmaps; 79138032Speter char *maptype[MAXMAPSTACK]; 79238032Speter short mapreturn[MAXMAPACTIONS]; 79338032Speter 79438032Speter nmaps = switch_map_find("hosts", maptype, mapreturn); 79590792Sgshapiro UseNameServer = false; 79638032Speter if (nmaps > 0 && nmaps <= MAXMAPSTACK) 79738032Speter { 79838032Speter register int mapno; 79938032Speter 80090792Sgshapiro for (mapno = 0; mapno < nmaps && !UseNameServer; 80190792Sgshapiro mapno++) 80238032Speter { 80338032Speter if (strcmp(maptype[mapno], "dns") == 0) 80490792Sgshapiro UseNameServer = true; 80538032Speter } 80638032Speter } 80738032Speter } 808285303Sgshapiro setupdynmailers(); 80938032Speter} 810168515Sgshapiro 81190792Sgshapiro/* 81238032Speter** TRANSLATE_DOLLARS -- convert $x into internal form 81338032Speter** 81438032Speter** Actually does all appropriate pre-processing of a config line 81538032Speter** to turn it into internal form. 81638032Speter** 81738032Speter** Parameters: 818168515Sgshapiro** ibp -- the buffer to translate. 819168515Sgshapiro** obp -- where to put the translation; may be the same as obp 820168515Sgshapiro** bsp -- a pointer to the size of obp; will be updated if 821168515Sgshapiro** the buffer needs to be replaced. 82238032Speter** 82338032Speter** Returns: 824168515Sgshapiro** The buffer pointer; may differ from obp if the expansion 825168515Sgshapiro** is larger then *bsp, in which case this will point to 826168515Sgshapiro** malloc()ed memory which must be free()d by the caller. 82738032Speter*/ 82838032Speter 829168515Sgshapirochar * 830168515Sgshapirotranslate_dollars(ibp, obp, bsp) 831168515Sgshapiro char *ibp; 832168515Sgshapiro char *obp; 833168515Sgshapiro int *bsp; 83438032Speter{ 83538032Speter register char *p; 83638032Speter auto char *ep; 837168515Sgshapiro char *bp; 83838032Speter 839168515Sgshapiro if (tTd(37, 53)) 840168515Sgshapiro { 841168515Sgshapiro sm_dprintf("translate_dollars("); 842168515Sgshapiro xputs(sm_debug_file(), ibp); 843168515Sgshapiro sm_dprintf(")\n"); 844168515Sgshapiro } 845168515Sgshapiro 846168515Sgshapiro bp = quote_internal_chars(ibp, obp, bsp); 847168515Sgshapiro 84838032Speter for (p = bp; *p != '\0'; p++) 84938032Speter { 85038032Speter if (*p == '#' && p > bp && ConfigLevel >= 3) 85138032Speter { 85238032Speter register char *e; 85338032Speter 85438032Speter switch (*--p & 0377) 85538032Speter { 85638032Speter case MACROEXPAND: 85738032Speter /* it's from $# -- let it go through */ 85838032Speter p++; 85938032Speter break; 86038032Speter 86138032Speter case '\\': 86238032Speter /* it's backslash escaped */ 86390792Sgshapiro (void) sm_strlcpy(p, p + 1, strlen(p)); 86438032Speter break; 86538032Speter 86638032Speter default: 86764562Sgshapiro /* delete leading white space */ 86838032Speter while (isascii(*p) && isspace(*p) && 86938032Speter *p != '\n' && p > bp) 870168515Sgshapiro { 87138032Speter p--; 872168515Sgshapiro } 87338032Speter if ((e = strchr(++p, '\n')) != NULL) 87490792Sgshapiro (void) sm_strlcpy(p, e, strlen(p)); 87538032Speter else 87638032Speter *p-- = '\0'; 87738032Speter break; 87838032Speter } 87938032Speter continue; 88038032Speter } 88138032Speter 88238032Speter if (*p != '$' || p[1] == '\0') 88338032Speter continue; 88438032Speter 88538032Speter if (p[1] == '$') 88638032Speter { 88738032Speter /* actual dollar sign.... */ 88890792Sgshapiro (void) sm_strlcpy(p, p + 1, strlen(p)); 88938032Speter continue; 89038032Speter } 89138032Speter 89238032Speter /* convert to macro expansion character */ 89338032Speter *p++ = MACROEXPAND; 89438032Speter 89538032Speter /* special handling for $=, $~, $&, and $? */ 89638032Speter if (*p == '=' || *p == '~' || *p == '&' || *p == '?') 89738032Speter p++; 89838032Speter 89938032Speter /* convert macro name to code */ 90090792Sgshapiro *p = macid_parse(p, &ep); 90164562Sgshapiro if (ep != p + 1) 90290792Sgshapiro (void) sm_strlcpy(p + 1, ep, strlen(p + 1)); 90338032Speter } 90438032Speter 90538032Speter /* strip trailing white space from the line */ 90638032Speter while (--p > bp && isascii(*p) && isspace(*p)) 90738032Speter *p = '\0'; 908168515Sgshapiro 909168515Sgshapiro if (tTd(37, 53)) 910168515Sgshapiro { 911168515Sgshapiro sm_dprintf(" translate_dollars => "); 912168515Sgshapiro xputs(sm_debug_file(), bp); 913168515Sgshapiro sm_dprintf("\n"); 914168515Sgshapiro } 915168515Sgshapiro 916168515Sgshapiro return bp; 91738032Speter} 91890792Sgshapiro/* 91938032Speter** TOOMANY -- signal too many of some option 92038032Speter** 92138032Speter** Parameters: 92238032Speter** id -- the id of the error line 92338032Speter** maxcnt -- the maximum possible values 92438032Speter** 92538032Speter** Returns: 92638032Speter** none. 92738032Speter** 92838032Speter** Side Effects: 92938032Speter** gives a syserr. 93038032Speter*/ 93138032Speter 93264562Sgshapirostatic void 93338032Spetertoomany(id, maxcnt) 93438032Speter int id; 93538032Speter int maxcnt; 93638032Speter{ 93738032Speter syserr("too many %c lines, %d max", id, maxcnt); 93838032Speter} 93990792Sgshapiro/* 94038032Speter** FILECLASS -- read members of a class from a file 94138032Speter** 94238032Speter** Parameters: 94338032Speter** class -- class to define. 94438032Speter** filename -- name of file to read. 94538032Speter** fmt -- scanf string to use for match. 94694334Sgshapiro** ismap -- if set, this is a map lookup. 94738032Speter** safe -- if set, this is a safe read. 94838032Speter** optional -- if set, it is not an error for the file to 94938032Speter** not exist. 95038032Speter** 95138032Speter** Returns: 95238032Speter** none 95338032Speter** 95438032Speter** Side Effects: 95538032Speter** puts all lines in filename that match a scanf into 95638032Speter** the named class. 95738032Speter*/ 95838032Speter 95990792Sgshapiro/* 96090792Sgshapiro** Break up the match into words and add to class. 96190792Sgshapiro*/ 96290792Sgshapiro 96364562Sgshapirostatic void 96490792Sgshapiroparse_class_words(class, line) 96590792Sgshapiro int class; 96690792Sgshapiro char *line; 96790792Sgshapiro{ 96890792Sgshapiro while (line != NULL && *line != '\0') 96990792Sgshapiro { 97090792Sgshapiro register char *q; 97190792Sgshapiro 97290792Sgshapiro /* strip leading spaces */ 97390792Sgshapiro while (isascii(*line) && isspace(*line)) 97490792Sgshapiro line++; 97590792Sgshapiro if (*line == '\0') 97690792Sgshapiro break; 97790792Sgshapiro 97890792Sgshapiro /* find the end of the word */ 97990792Sgshapiro q = line; 98090792Sgshapiro while (*line != '\0' && !(isascii(*line) && isspace(*line))) 98190792Sgshapiro line++; 98290792Sgshapiro if (*line != '\0') 98390792Sgshapiro *line++ = '\0'; 98490792Sgshapiro 98590792Sgshapiro /* enter the word in the symbol table */ 98690792Sgshapiro setclass(class, q); 98790792Sgshapiro } 98890792Sgshapiro} 98990792Sgshapiro 99090792Sgshapirostatic void 99194334Sgshapirofileclass(class, filename, fmt, ismap, safe, optional) 99238032Speter int class; 99338032Speter char *filename; 99438032Speter char *fmt; 99594334Sgshapiro bool ismap; 99638032Speter bool safe; 99738032Speter bool optional; 99838032Speter{ 99990792Sgshapiro SM_FILE_T *f; 100064562Sgshapiro long sff; 100138032Speter pid_t pid; 100238032Speter register char *p; 100338032Speter char buf[MAXLINE]; 100438032Speter 100538032Speter if (tTd(37, 2)) 100690792Sgshapiro sm_dprintf("fileclass(%s, fmt=%s)\n", filename, fmt); 100738032Speter 100890792Sgshapiro if (*filename == '\0') 100938032Speter { 101090792Sgshapiro syserr("fileclass: missing file name"); 101190792Sgshapiro return; 101290792Sgshapiro } 101394334Sgshapiro else if (ismap) 101490792Sgshapiro { 101590792Sgshapiro int status = 0; 101690792Sgshapiro char *key; 101790792Sgshapiro char *mn; 101890792Sgshapiro char *cl, *spec; 101990792Sgshapiro STAB *mapclass; 102090792Sgshapiro MAP map; 102190792Sgshapiro 102290792Sgshapiro mn = newstr(macname(class)); 102390792Sgshapiro 102490792Sgshapiro key = filename; 102590792Sgshapiro 102694334Sgshapiro /* skip past key */ 102794334Sgshapiro if ((p = strchr(filename, '@')) == NULL) 102894334Sgshapiro { 102994334Sgshapiro /* should not happen */ 103094334Sgshapiro syserr("fileclass: bogus map specification"); 103194334Sgshapiro sm_free(mn); 103294334Sgshapiro return; 103394334Sgshapiro } 103494334Sgshapiro 103590792Sgshapiro /* skip past '@' */ 103690792Sgshapiro *p++ = '\0'; 103790792Sgshapiro cl = p; 103890792Sgshapiro 1039120256Sgshapiro#if LDAPMAP 104090792Sgshapiro if (strcmp(cl, "LDAP") == 0) 104190792Sgshapiro { 104290792Sgshapiro int n; 104390792Sgshapiro char *lc; 104490792Sgshapiro char jbuf[MAXHOSTNAMELEN]; 104590792Sgshapiro char lcbuf[MAXLINE]; 104690792Sgshapiro 104790792Sgshapiro /* Get $j */ 1048168515Sgshapiro expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope); 104990792Sgshapiro if (jbuf[0] == '\0') 105090792Sgshapiro { 105190792Sgshapiro (void) sm_strlcpy(jbuf, "localhost", 1052168515Sgshapiro sizeof(jbuf)); 105390792Sgshapiro } 105490792Sgshapiro 105590792Sgshapiro /* impose the default schema */ 105690792Sgshapiro lc = macvalue(macid("{sendmailMTACluster}"), CurEnv); 105790792Sgshapiro if (lc == NULL) 105890792Sgshapiro lc = ""; 105990792Sgshapiro else 106090792Sgshapiro { 1061168515Sgshapiro expand(lc, lcbuf, sizeof(lcbuf), CurEnv); 106290792Sgshapiro lc = lcbuf; 106390792Sgshapiro } 106490792Sgshapiro 106590792Sgshapiro cl = "ldap"; 1066168515Sgshapiro n = sm_snprintf(buf, sizeof(buf), 1067132943Sgshapiro "-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=%s)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))) -v sendmailMTAClassValue,sendmailMTAClassSearch:FILTER:sendmailMTAClass,sendmailMTAClassURL:URL:sendmailMTAClass", 106890792Sgshapiro mn, lc, jbuf); 1069168515Sgshapiro if (n >= sizeof(buf)) 107090792Sgshapiro { 107190792Sgshapiro syserr("fileclass: F{%s}: Default LDAP string too long", 107290792Sgshapiro mn); 107390792Sgshapiro sm_free(mn); 107490792Sgshapiro return; 107590792Sgshapiro } 107690792Sgshapiro spec = buf; 107790792Sgshapiro } 107890792Sgshapiro else 1079120256Sgshapiro#endif /* LDAPMAP */ 108090792Sgshapiro { 108190792Sgshapiro if ((spec = strchr(cl, ':')) == NULL) 108290792Sgshapiro { 108390792Sgshapiro syserr("fileclass: F{%s}: missing map class", 108490792Sgshapiro mn); 108590792Sgshapiro sm_free(mn); 108690792Sgshapiro return; 108790792Sgshapiro } 108890792Sgshapiro *spec++ ='\0'; 108990792Sgshapiro } 109090792Sgshapiro 109190792Sgshapiro /* set up map structure */ 109290792Sgshapiro mapclass = stab(cl, ST_MAPCLASS, ST_FIND); 109390792Sgshapiro if (mapclass == NULL) 109490792Sgshapiro { 109590792Sgshapiro syserr("fileclass: F{%s}: class %s not available", 109690792Sgshapiro mn, cl); 109790792Sgshapiro sm_free(mn); 109890792Sgshapiro return; 109990792Sgshapiro } 1100168515Sgshapiro memset(&map, '\0', sizeof(map)); 110190792Sgshapiro map.map_class = &mapclass->s_mapclass; 110290792Sgshapiro map.map_mname = mn; 110390792Sgshapiro map.map_mflags |= MF_FILECLASS; 110490792Sgshapiro 110594334Sgshapiro if (tTd(37, 5)) 110694334Sgshapiro sm_dprintf("fileclass: F{%s}: map class %s, key %s, spec %s\n", 110794334Sgshapiro mn, cl, key, spec); 110894334Sgshapiro 110994334Sgshapiro 111090792Sgshapiro /* parse map spec */ 111190792Sgshapiro if (!map.map_class->map_parse(&map, spec)) 111290792Sgshapiro { 111390792Sgshapiro /* map_parse() showed the error already */ 111490792Sgshapiro sm_free(mn); 111590792Sgshapiro return; 111690792Sgshapiro } 111790792Sgshapiro map.map_mflags |= MF_VALID; 111890792Sgshapiro 111990792Sgshapiro /* open map */ 112090792Sgshapiro if (map.map_class->map_open(&map, O_RDONLY)) 112190792Sgshapiro { 112290792Sgshapiro map.map_mflags |= MF_OPEN; 112390792Sgshapiro map.map_pid = getpid(); 112490792Sgshapiro } 112590792Sgshapiro else 112690792Sgshapiro { 112790792Sgshapiro if (!optional && 112890792Sgshapiro !bitset(MF_OPTIONAL, map.map_mflags)) 112990792Sgshapiro syserr("fileclass: F{%s}: map open failed", 113090792Sgshapiro mn); 113190792Sgshapiro sm_free(mn); 113290792Sgshapiro return; 113390792Sgshapiro } 113490792Sgshapiro 113590792Sgshapiro /* lookup */ 113690792Sgshapiro p = (*map.map_class->map_lookup)(&map, key, NULL, &status); 113790792Sgshapiro if (status != EX_OK && status != EX_NOTFOUND) 113890792Sgshapiro { 113990792Sgshapiro if (!optional) 114090792Sgshapiro syserr("fileclass: F{%s}: map lookup failed", 114190792Sgshapiro mn); 114290792Sgshapiro p = NULL; 114390792Sgshapiro } 114490792Sgshapiro 114590792Sgshapiro /* use the results */ 114690792Sgshapiro if (p != NULL) 114790792Sgshapiro parse_class_words(class, p); 114890792Sgshapiro 114990792Sgshapiro /* close map */ 115090792Sgshapiro map.map_mflags |= MF_CLOSING; 115190792Sgshapiro map.map_class->map_close(&map); 115290792Sgshapiro map.map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); 115390792Sgshapiro sm_free(mn); 115490792Sgshapiro return; 115590792Sgshapiro } 115690792Sgshapiro else if (filename[0] == '|') 115790792Sgshapiro { 115838032Speter auto int fd; 115938032Speter int i; 116038032Speter char *argv[MAXPV + 1]; 116138032Speter 116238032Speter i = 0; 116390792Sgshapiro for (p = strtok(&filename[1], " \t"); 116490792Sgshapiro p != NULL && i < MAXPV; 116590792Sgshapiro p = strtok(NULL, " \t")) 116638032Speter argv[i++] = p; 116738032Speter argv[i] = NULL; 116838032Speter pid = prog_open(argv, &fd, CurEnv); 116938032Speter if (pid < 0) 117038032Speter f = NULL; 117138032Speter else 117290792Sgshapiro f = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 117390792Sgshapiro (void *) &fd, SM_IO_RDONLY, NULL); 117438032Speter } 117538032Speter else 117638032Speter { 117738032Speter pid = -1; 117838032Speter sff = SFF_REGONLY; 117964562Sgshapiro if (!bitnset(DBS_CLASSFILEINUNSAFEDIRPATH, DontBlameSendmail)) 118038032Speter sff |= SFF_SAFEDIRPATH; 118164562Sgshapiro if (!bitnset(DBS_LINKEDCLASSFILEINWRITABLEDIR, 118264562Sgshapiro DontBlameSendmail)) 118338032Speter sff |= SFF_NOWLINK; 118438032Speter if (safe) 118538032Speter sff |= SFF_OPENASROOT; 118690792Sgshapiro else if (RealUid == 0) 118790792Sgshapiro sff |= SFF_ROOTOK; 118838032Speter if (DontLockReadFiles) 118938032Speter sff |= SFF_NOLOCK; 119038032Speter f = safefopen(filename, O_RDONLY, 0, sff); 119138032Speter } 119238032Speter if (f == NULL) 119338032Speter { 119438032Speter if (!optional) 119564562Sgshapiro syserr("fileclass: cannot open '%s'", filename); 119638032Speter return; 119738032Speter } 119838032Speter 1199249729Sgshapiro while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0) 120038032Speter { 120164562Sgshapiro#if SCANF 120238032Speter char wordbuf[MAXLINE + 1]; 120364562Sgshapiro#endif /* SCANF */ 120438032Speter 120538032Speter if (buf[0] == '#') 120638032Speter continue; 120764562Sgshapiro#if SCANF 120890792Sgshapiro if (sm_io_sscanf(buf, fmt, wordbuf) != 1) 120938032Speter continue; 121038032Speter p = wordbuf; 121164562Sgshapiro#else /* SCANF */ 121238032Speter p = buf; 121364562Sgshapiro#endif /* SCANF */ 121438032Speter 121590792Sgshapiro parse_class_words(class, p); 121690792Sgshapiro 121738032Speter /* 121890792Sgshapiro ** If anything else is added here, 121990792Sgshapiro ** check if the '@' map case above 122090792Sgshapiro ** needs the code as well. 122138032Speter */ 122238032Speter } 122338032Speter 122490792Sgshapiro (void) sm_io_close(f, SM_TIME_DEFAULT); 122538032Speter if (pid > 0) 122638032Speter (void) waitfor(pid); 122738032Speter} 1228285303Sgshapiro 1229285303Sgshapiro#if _FFR_RCPTFLAGS 1230285303Sgshapiro/* first character for dynamically created mailers */ 1231285303Sgshapirostatic char dynmailerp = ' '; 1232285303Sgshapiro 1233285303Sgshapiro/* list of first characters for cf defined mailers */ 1234285303Sgshapirostatic char frst[MAXMAILERS + 1]; 1235285303Sgshapiro 123690792Sgshapiro/* 1237285303Sgshapiro** SETUPDYNMAILERS -- find a char that isn't used as first element of any 1238285303Sgshapiro** mailer name. 1239285303Sgshapiro** 1240285303Sgshapiro** Parameters: 1241285303Sgshapiro** none 1242285303Sgshapiro** 1243285303Sgshapiro** Returns: 1244285303Sgshapiro** none 1245285303Sgshapiro** 1246285303Sgshapiro** Note: space is not valid in cf defined mailers hence the function 1247285303Sgshapiro** will always find a char. It's not nice, but this is for 1248285303Sgshapiro** internal names only. 1249285303Sgshapiro*/ 1250285303Sgshapiro 1251285303Sgshapirovoid 1252285303Sgshapirosetupdynmailers() 1253285303Sgshapiro{ 1254285303Sgshapiro int i; 1255285303Sgshapiro char pp[] = "YXZ0123456789ABCDEFGHIJKLMNOPQRSTUVWyxzabcfghijkmnoqtuvw "; 1256285303Sgshapiro 1257285303Sgshapiro frst[MAXMAILERS] = '\0'; 1258285303Sgshapiro for (i = 0; i < strlen(pp); i++) 1259285303Sgshapiro { 1260285303Sgshapiro if (strchr(frst, pp[i]) == NULL) 1261285303Sgshapiro { 1262285303Sgshapiro dynmailerp = pp[i]; 1263285303Sgshapiro if (tTd(25, 8)) 1264285303Sgshapiro sm_dprintf("dynmailerp=%c\n", dynmailerp); 1265285303Sgshapiro return; 1266285303Sgshapiro } 1267285303Sgshapiro } 1268285303Sgshapiro 1269285303Sgshapiro /* NOTREACHED */ 1270285303Sgshapiro SM_ASSERT(0); 1271285303Sgshapiro} 1272285303Sgshapiro 1273285303Sgshapiro/* 1274285303Sgshapiro** NEWMODMAILER -- Create a new mailer with modifications 1275285303Sgshapiro** 1276285303Sgshapiro** Parameters: 1277285303Sgshapiro** rcpt -- current RCPT 1278285303Sgshapiro** fl -- flag to set 1279285303Sgshapiro** 1280285303Sgshapiro** Returns: 1281285303Sgshapiro** true iff successful. 1282285303Sgshapiro** 1283285303Sgshapiro** Note: this creates a copy of the mailer for the rcpt and 1284285303Sgshapiro** modifies exactly one flag. It does not work 1285285303Sgshapiro** for multiple flags! 1286285303Sgshapiro*/ 1287285303Sgshapiro 1288285303Sgshapirobool 1289285303Sgshapironewmodmailer(rcpt, fl) 1290285303Sgshapiro ADDRESS *rcpt; 1291285303Sgshapiro int fl; 1292285303Sgshapiro{ 1293285303Sgshapiro int idx; 1294285303Sgshapiro struct mailer *m; 1295285303Sgshapiro STAB *s; 1296285303Sgshapiro char mname[256]; 1297285303Sgshapiro 1298285303Sgshapiro SM_REQUIRE(rcpt != NULL); 1299285303Sgshapiro if (rcpt->q_mailer == NULL) 1300285303Sgshapiro return false; 1301285303Sgshapiro if (tTd(25, 8)) 1302285303Sgshapiro sm_dprintf("newmodmailer: rcpt=%s\n", rcpt->q_paddr); 1303285303Sgshapiro SM_REQUIRE(rcpt->q_mailer->m_name != NULL); 1304285303Sgshapiro SM_REQUIRE(rcpt->q_mailer->m_name[0] != '\0'); 1305285303Sgshapiro sm_strlcpy(mname, rcpt->q_mailer->m_name, sizeof(mname)); 1306285303Sgshapiro mname[0] = dynmailerp; 1307285303Sgshapiro if (tTd(25, 8)) 1308285303Sgshapiro sm_dprintf("newmodmailer: name=%s\n", mname); 1309285303Sgshapiro s = stab(mname, ST_MAILER, ST_ENTER); 1310285303Sgshapiro if (s->s_mailer != NULL) 1311285303Sgshapiro { 1312285303Sgshapiro idx = s->s_mailer->m_mno; 1313285303Sgshapiro if (tTd(25, 6)) 1314285303Sgshapiro sm_dprintf("newmodmailer: found idx=%d\n", idx); 1315285303Sgshapiro } 1316285303Sgshapiro else 1317285303Sgshapiro { 1318285303Sgshapiro idx = rcpt->q_mailer->m_mno; 1319285303Sgshapiro idx += MAXMAILERS; 1320285303Sgshapiro if (tTd(25, 6)) 1321285303Sgshapiro sm_dprintf("newmodmailer: idx=%d\n", idx); 1322285303Sgshapiro if (idx > SM_ARRAY_SIZE(Mailer)) 1323285303Sgshapiro return false; 1324285303Sgshapiro } 1325285303Sgshapiro 1326285303Sgshapiro m = Mailer[idx]; 1327285303Sgshapiro if (m == NULL) 1328285303Sgshapiro m = (struct mailer *) xalloc(sizeof(*m)); 1329285303Sgshapiro memset((char *) m, '\0', sizeof(*m)); 1330285303Sgshapiro STRUCTCOPY(*rcpt->q_mailer, *m); 1331285303Sgshapiro Mailer[idx] = m; 1332285303Sgshapiro 1333285303Sgshapiro /* "modify" the mailer */ 1334285303Sgshapiro setbitn(bitidx(fl), m->m_flags); 1335285303Sgshapiro rcpt->q_mailer = m; 1336285303Sgshapiro m->m_mno = idx; 1337285303Sgshapiro m->m_name = newstr(mname); 1338285303Sgshapiro if (tTd(25, 1)) 1339285303Sgshapiro sm_dprintf("newmodmailer: mailer[%d]=%s %p\n", 1340285303Sgshapiro idx, Mailer[idx]->m_name, Mailer[idx]); 1341285303Sgshapiro 1342285303Sgshapiro return true; 1343285303Sgshapiro} 1344285303Sgshapiro 1345285303Sgshapiro#endif /* _FFR_RCPTFLAGS */ 1346285303Sgshapiro 1347285303Sgshapiro/* 134838032Speter** MAKEMAILER -- define a new mailer. 134938032Speter** 135038032Speter** Parameters: 135138032Speter** line -- description of mailer. This is in labeled 135238032Speter** fields. The fields are: 135338032Speter** A -- the argv for this mailer 135438032Speter** C -- the character set for MIME conversions 135538032Speter** D -- the directory to run in 135638032Speter** E -- the eol string 135738032Speter** F -- the flags associated with the mailer 135838032Speter** L -- the maximum line length 135938032Speter** M -- the maximum message size 136038032Speter** N -- the niceness at which to run 136138032Speter** P -- the path to the mailer 136290792Sgshapiro** Q -- the queue group for the mailer 136338032Speter** R -- the recipient rewriting set 136438032Speter** S -- the sender rewriting set 136538032Speter** T -- the mailer type (for DSNs) 136638032Speter** U -- the uid to run as 136764562Sgshapiro** W -- the time to wait at the end 136873188Sgshapiro** m -- maximum messages per connection 136990792Sgshapiro** r -- maximum number of recipients per message 137073188Sgshapiro** / -- new root directory 137138032Speter** The first word is the canonical name of the mailer. 137238032Speter** 137338032Speter** Returns: 137438032Speter** none. 137538032Speter** 137638032Speter** Side Effects: 137738032Speter** enters the mailer into the mailer table. 137838032Speter*/ 137938032Speter 1380285303Sgshapiro 138138032Spetervoid 138238032Spetermakemailer(line) 138338032Speter char *line; 138438032Speter{ 138538032Speter register char *p; 138638032Speter register struct mailer *m; 138738032Speter register STAB *s; 138838032Speter int i; 138938032Speter char fcode; 139038032Speter auto char *endp; 139190792Sgshapiro static int nextmailer = 0; /* "free" index into Mailer struct */ 139238032Speter 139338032Speter /* allocate a mailer and set up defaults */ 1394168515Sgshapiro m = (struct mailer *) xalloc(sizeof(*m)); 1395168515Sgshapiro memset((char *) m, '\0', sizeof(*m)); 139690792Sgshapiro errno = 0; /* avoid bogus error text */ 139738032Speter 139838032Speter /* collect the mailer name */ 139990792Sgshapiro for (p = line; 140090792Sgshapiro *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); 140190792Sgshapiro p++) 140238032Speter continue; 140338032Speter if (*p != '\0') 140438032Speter *p++ = '\0'; 140538032Speter if (line[0] == '\0') 140671345Sgshapiro { 140738032Speter syserr("name required for mailer"); 140871345Sgshapiro return; 140971345Sgshapiro } 141038032Speter m->m_name = newstr(line); 1411285303Sgshapiro#if _FFR_RCPTFLAGS 1412285303Sgshapiro frst[nextmailer] = line[0]; 1413285303Sgshapiro#endif 141494334Sgshapiro m->m_qgrp = NOQGRP; 1415132943Sgshapiro m->m_uid = NO_UID; 1416132943Sgshapiro m->m_gid = NO_GID; 141738032Speter 141838032Speter /* now scan through and assign info from the fields */ 141938032Speter while (*p != '\0') 142038032Speter { 142138032Speter auto char *delimptr; 142238032Speter 142390792Sgshapiro while (*p != '\0' && 142490792Sgshapiro (*p == ',' || (isascii(*p) && isspace(*p)))) 142538032Speter p++; 142638032Speter 142738032Speter /* p now points to field code */ 142838032Speter fcode = *p; 142938032Speter while (*p != '\0' && *p != '=' && *p != ',') 143038032Speter p++; 143138032Speter if (*p++ != '=') 143238032Speter { 143338032Speter syserr("mailer %s: `=' expected", m->m_name); 143438032Speter return; 143538032Speter } 143638032Speter while (isascii(*p) && isspace(*p)) 143738032Speter p++; 143838032Speter 143938032Speter /* p now points to the field body */ 144038032Speter p = munchstring(p, &delimptr, ','); 144138032Speter 144238032Speter /* install the field into the mailer struct */ 144338032Speter switch (fcode) 144438032Speter { 144538032Speter case 'P': /* pathname */ 144690792Sgshapiro if (*p != '\0') /* error is issued below */ 144771345Sgshapiro m->m_mailer = newstr(p); 144838032Speter break; 144938032Speter 145038032Speter case 'F': /* flags */ 145138032Speter for (; *p != '\0'; p++) 145290792Sgshapiro { 145338032Speter if (!(isascii(*p) && isspace(*p))) 145490792Sgshapiro { 145590792Sgshapiro if (*p == M_INTERNAL) 145690792Sgshapiro sm_syslog(LOG_WARNING, NOQID, 145790792Sgshapiro "WARNING: mailer=%s, flag=%c deprecated", 145890792Sgshapiro m->m_name, *p); 145971345Sgshapiro setbitn(bitidx(*p), m->m_flags); 146090792Sgshapiro } 146190792Sgshapiro } 146238032Speter break; 146338032Speter 146438032Speter case 'S': /* sender rewriting ruleset */ 146538032Speter case 'R': /* recipient rewriting ruleset */ 146638032Speter i = strtorwset(p, &endp, ST_ENTER); 146738032Speter if (i < 0) 146838032Speter return; 146938032Speter if (fcode == 'S') 147038032Speter m->m_sh_rwset = m->m_se_rwset = i; 147138032Speter else 147238032Speter m->m_rh_rwset = m->m_re_rwset = i; 147338032Speter 147438032Speter p = endp; 147538032Speter if (*p++ == '/') 147638032Speter { 147738032Speter i = strtorwset(p, NULL, ST_ENTER); 147838032Speter if (i < 0) 147938032Speter return; 148038032Speter if (fcode == 'S') 148138032Speter m->m_sh_rwset = i; 148238032Speter else 148338032Speter m->m_rh_rwset = i; 148438032Speter } 148538032Speter break; 148638032Speter 148738032Speter case 'E': /* end of line string */ 148838032Speter if (*p == '\0') 148938032Speter syserr("mailer %s: null end-of-line string", 149038032Speter m->m_name); 149171345Sgshapiro else 149271345Sgshapiro m->m_eol = newstr(p); 149338032Speter break; 149438032Speter 149538032Speter case 'A': /* argument vector */ 149690792Sgshapiro if (*p != '\0') /* error is issued below */ 149771345Sgshapiro m->m_argv = makeargv(p); 149838032Speter break; 149938032Speter 150038032Speter case 'M': /* maximum message size */ 150138032Speter m->m_maxsize = atol(p); 150238032Speter break; 150338032Speter 150464562Sgshapiro case 'm': /* maximum messages per connection */ 150564562Sgshapiro m->m_maxdeliveries = atoi(p); 150664562Sgshapiro break; 150764562Sgshapiro 150864562Sgshapiro case 'r': /* max recipient per envelope */ 150964562Sgshapiro m->m_maxrcpt = atoi(p); 151064562Sgshapiro break; 151164562Sgshapiro 151238032Speter case 'L': /* maximum line length */ 151338032Speter m->m_linelimit = atoi(p); 151438032Speter if (m->m_linelimit < 0) 151538032Speter m->m_linelimit = 0; 151638032Speter break; 151738032Speter 151838032Speter case 'N': /* run niceness */ 151938032Speter m->m_nice = atoi(p); 152038032Speter break; 152138032Speter 152238032Speter case 'D': /* working directory */ 152338032Speter if (*p == '\0') 152438032Speter syserr("mailer %s: null working directory", 152538032Speter m->m_name); 152671345Sgshapiro else 152771345Sgshapiro m->m_execdir = newstr(p); 152838032Speter break; 152938032Speter 153038032Speter case 'C': /* default charset */ 153138032Speter if (*p == '\0') 153238032Speter syserr("mailer %s: null charset", m->m_name); 153371345Sgshapiro else 153471345Sgshapiro m->m_defcharset = newstr(p); 153538032Speter break; 153638032Speter 153790792Sgshapiro case 'Q': /* queue for this mailer */ 153890792Sgshapiro if (*p == '\0') 153990792Sgshapiro { 154090792Sgshapiro syserr("mailer %s: null queue", m->m_name); 154190792Sgshapiro break; 154290792Sgshapiro } 154390792Sgshapiro s = stab(p, ST_QUEUE, ST_FIND); 154490792Sgshapiro if (s == NULL) 154590792Sgshapiro syserr("mailer %s: unknown queue %s", 154690792Sgshapiro m->m_name, p); 154790792Sgshapiro else 154890792Sgshapiro m->m_qgrp = s->s_quegrp->qg_index; 154990792Sgshapiro break; 155090792Sgshapiro 155138032Speter case 'T': /* MTA-Name/Address/Diagnostic types */ 155238032Speter /* extract MTA name type; default to "dns" */ 155338032Speter m->m_mtatype = newstr(p); 155438032Speter p = strchr(m->m_mtatype, '/'); 155538032Speter if (p != NULL) 155638032Speter { 155738032Speter *p++ = '\0'; 155838032Speter if (*p == '\0') 155938032Speter p = NULL; 156038032Speter } 156138032Speter if (*m->m_mtatype == '\0') 156238032Speter m->m_mtatype = "dns"; 156338032Speter 156438032Speter /* extract address type; default to "rfc822" */ 156538032Speter m->m_addrtype = p; 156638032Speter if (p != NULL) 156738032Speter p = strchr(p, '/'); 156838032Speter if (p != NULL) 156938032Speter { 157038032Speter *p++ = '\0'; 157138032Speter if (*p == '\0') 157238032Speter p = NULL; 157338032Speter } 157438032Speter if (m->m_addrtype == NULL || *m->m_addrtype == '\0') 157538032Speter m->m_addrtype = "rfc822"; 157638032Speter 157738032Speter /* extract diagnostic type; default to "smtp" */ 157838032Speter m->m_diagtype = p; 157938032Speter if (m->m_diagtype == NULL || *m->m_diagtype == '\0') 158038032Speter m->m_diagtype = "smtp"; 158138032Speter break; 158238032Speter 158338032Speter case 'U': /* user id */ 158438032Speter if (isascii(*p) && !isdigit(*p)) 158538032Speter { 158638032Speter char *q = p; 158738032Speter struct passwd *pw; 158838032Speter 158938032Speter while (*p != '\0' && isascii(*p) && 1590285303Sgshapiro# if _FFR_DOTTED_USERNAMES 1591285303Sgshapiro (isalnum(*p) || strchr(SM_PWN_CHARS, *p) != NULL)) 1592285303Sgshapiro# else /* _FFR_DOTTED_USERNAMES */ 159338032Speter (isalnum(*p) || strchr("-_", *p) != NULL)) 1594285303Sgshapiro# endif /* _FFR_DOTTED_USERNAMES */ 159538032Speter p++; 159638032Speter while (isascii(*p) && isspace(*p)) 159738032Speter *p++ = '\0'; 159838032Speter if (*p != '\0') 159938032Speter *p++ = '\0'; 160038032Speter if (*q == '\0') 160171345Sgshapiro { 160238032Speter syserr("mailer %s: null user name", 160338032Speter m->m_name); 160471345Sgshapiro break; 160571345Sgshapiro } 160638032Speter pw = sm_getpwnam(q); 160738032Speter if (pw == NULL) 160871345Sgshapiro { 160938032Speter syserr("readcf: mailer U= flag: unknown user %s", q); 161071345Sgshapiro break; 161171345Sgshapiro } 161238032Speter else 161338032Speter { 161438032Speter m->m_uid = pw->pw_uid; 161538032Speter m->m_gid = pw->pw_gid; 161638032Speter } 161738032Speter } 161838032Speter else 161938032Speter { 162038032Speter auto char *q; 162138032Speter 162238032Speter m->m_uid = strtol(p, &q, 0); 162338032Speter p = q; 162438032Speter while (isascii(*p) && isspace(*p)) 162538032Speter p++; 162638032Speter if (*p != '\0') 162738032Speter p++; 162838032Speter } 162938032Speter while (isascii(*p) && isspace(*p)) 163038032Speter p++; 163138032Speter if (*p == '\0') 163238032Speter break; 163338032Speter if (isascii(*p) && !isdigit(*p)) 163438032Speter { 163538032Speter char *q = p; 163638032Speter struct group *gr; 163738032Speter 1638285303Sgshapiro while (isascii(*p) && 1639285303Sgshapiro (isalnum(*p) || strchr(SM_PWN_CHARS, *p) != NULL)) 164038032Speter p++; 164138032Speter *p++ = '\0'; 164238032Speter if (*q == '\0') 164371345Sgshapiro { 164438032Speter syserr("mailer %s: null group name", 164538032Speter m->m_name); 164671345Sgshapiro break; 164771345Sgshapiro } 164838032Speter gr = getgrnam(q); 164938032Speter if (gr == NULL) 165071345Sgshapiro { 165138032Speter syserr("readcf: mailer U= flag: unknown group %s", q); 165271345Sgshapiro break; 165371345Sgshapiro } 165438032Speter else 165538032Speter m->m_gid = gr->gr_gid; 165638032Speter } 165738032Speter else 165838032Speter { 165938032Speter m->m_gid = strtol(p, NULL, 0); 166038032Speter } 166138032Speter break; 166264562Sgshapiro 166364562Sgshapiro case 'W': /* wait timeout */ 166464562Sgshapiro m->m_wait = convtime(p, 's'); 166564562Sgshapiro break; 166664562Sgshapiro 166764562Sgshapiro case '/': /* new root directory */ 166864562Sgshapiro if (*p == '\0') 166964562Sgshapiro syserr("mailer %s: null root directory", 167064562Sgshapiro m->m_name); 167164562Sgshapiro else 167264562Sgshapiro m->m_rootdir = newstr(p); 167364562Sgshapiro break; 167464562Sgshapiro 167564562Sgshapiro default: 167664562Sgshapiro syserr("M%s: unknown mailer equate %c=", 167764562Sgshapiro m->m_name, fcode); 167864562Sgshapiro break; 167938032Speter } 168038032Speter 168138032Speter p = delimptr; 168238032Speter } 168338032Speter 168490792Sgshapiro#if !HASRRESVPORT 168590792Sgshapiro if (bitnset(M_SECURE_PORT, m->m_flags)) 168690792Sgshapiro { 168790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 168890792Sgshapiro "M%s: Warning: F=%c set on system that doesn't support rresvport()\n", 168990792Sgshapiro m->m_name, M_SECURE_PORT); 169090792Sgshapiro } 169190792Sgshapiro#endif /* !HASRRESVPORT */ 169290792Sgshapiro 169390792Sgshapiro#if !HASNICE 169490792Sgshapiro if (m->m_nice != 0) 169590792Sgshapiro { 169690792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 169790792Sgshapiro "M%s: Warning: N= set on system that doesn't support nice()\n", 169890792Sgshapiro m->m_name); 169990792Sgshapiro } 170090792Sgshapiro#endif /* !HASNICE */ 170190792Sgshapiro 170238032Speter /* do some rationality checking */ 170338032Speter if (m->m_argv == NULL) 170438032Speter { 170538032Speter syserr("M%s: A= argument required", m->m_name); 170638032Speter return; 170738032Speter } 170838032Speter if (m->m_mailer == NULL) 170938032Speter { 171038032Speter syserr("M%s: P= argument required", m->m_name); 171138032Speter return; 171238032Speter } 171338032Speter 171490792Sgshapiro if (nextmailer >= MAXMAILERS) 171538032Speter { 171638032Speter syserr("too many mailers defined (%d max)", MAXMAILERS); 171738032Speter return; 171838032Speter } 171938032Speter 172064562Sgshapiro if (m->m_maxrcpt <= 0) 172164562Sgshapiro m->m_maxrcpt = DEFAULT_MAX_RCPT; 172264562Sgshapiro 172338032Speter /* do some heuristic cleanup for back compatibility */ 172438032Speter if (bitnset(M_LIMITS, m->m_flags)) 172538032Speter { 172638032Speter if (m->m_linelimit == 0) 172738032Speter m->m_linelimit = SMTPLINELIM; 172838032Speter if (ConfigLevel < 2) 172938032Speter setbitn(M_7BITS, m->m_flags); 173038032Speter } 173138032Speter 173264562Sgshapiro if (strcmp(m->m_mailer, "[TCP]") == 0) 173338032Speter { 173490792Sgshapiro syserr("M%s: P=[TCP] must be replaced by P=[IPC]", m->m_name); 173571345Sgshapiro return; 173638032Speter } 173738032Speter 173890792Sgshapiro if (strcmp(m->m_mailer, "[IPC]") == 0) 173938032Speter { 174064562Sgshapiro /* Use the second argument for host or path to socket */ 174164562Sgshapiro if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || 174264562Sgshapiro m->m_argv[1][0] == '\0') 174364562Sgshapiro { 174464562Sgshapiro syserr("M%s: too few parameters for %s mailer", 174564562Sgshapiro m->m_name, m->m_mailer); 174671345Sgshapiro return; 174764562Sgshapiro } 174866494Sgshapiro if (strcmp(m->m_argv[0], "TCP") != 0 174964562Sgshapiro#if NETUNIX 175066494Sgshapiro && strcmp(m->m_argv[0], "FILE") != 0 175164562Sgshapiro#endif /* NETUNIX */ 175264562Sgshapiro ) 175364562Sgshapiro { 175490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 175590792Sgshapiro "M%s: Warning: first argument in %s mailer must be %s\n", 175690792Sgshapiro m->m_name, m->m_mailer, 175764562Sgshapiro#if NETUNIX 175890792Sgshapiro "TCP or FILE" 175964562Sgshapiro#else /* NETUNIX */ 176090792Sgshapiro "TCP" 176164562Sgshapiro#endif /* NETUNIX */ 176290792Sgshapiro ); 176364562Sgshapiro } 176490792Sgshapiro if (m->m_mtatype == NULL) 176590792Sgshapiro m->m_mtatype = "dns"; 176690792Sgshapiro if (m->m_addrtype == NULL) 176790792Sgshapiro m->m_addrtype = "rfc822"; 176890792Sgshapiro if (m->m_diagtype == NULL) 176990792Sgshapiro { 177090792Sgshapiro if (m->m_argv[0] != NULL && 177190792Sgshapiro strcmp(m->m_argv[0], "FILE") == 0) 177290792Sgshapiro m->m_diagtype = "x-unix"; 177390792Sgshapiro else 177490792Sgshapiro m->m_diagtype = "smtp"; 177590792Sgshapiro } 177664562Sgshapiro } 177764562Sgshapiro else if (strcmp(m->m_mailer, "[FILE]") == 0) 177864562Sgshapiro { 177938032Speter /* Use the second argument for filename */ 178038032Speter if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || 178138032Speter m->m_argv[2] != NULL) 178238032Speter { 178338032Speter syserr("M%s: too %s parameters for [FILE] mailer", 178438032Speter m->m_name, 178538032Speter (m->m_argv[0] == NULL || 178638032Speter m->m_argv[1] == NULL) ? "few" : "many"); 178771345Sgshapiro return; 178838032Speter } 178938032Speter else if (strcmp(m->m_argv[0], "FILE") != 0) 179038032Speter { 179138032Speter syserr("M%s: first argument in [FILE] mailer must be FILE", 179238032Speter m->m_name); 179371345Sgshapiro return; 179438032Speter } 179538032Speter } 179638032Speter 179738032Speter if (m->m_eol == NULL) 179838032Speter { 179938032Speter char **pp; 180038032Speter 180138032Speter /* default for SMTP is \r\n; use \n for local delivery */ 180238032Speter for (pp = m->m_argv; *pp != NULL; pp++) 180338032Speter { 180438032Speter for (p = *pp; *p != '\0'; ) 180538032Speter { 180638032Speter if ((*p++ & 0377) == MACROEXPAND && *p == 'u') 180738032Speter break; 180838032Speter } 180938032Speter if (*p != '\0') 181038032Speter break; 181138032Speter } 181238032Speter if (*pp == NULL) 181338032Speter m->m_eol = "\r\n"; 181438032Speter else 181538032Speter m->m_eol = "\n"; 181638032Speter } 181738032Speter 181838032Speter /* enter the mailer into the symbol table */ 181938032Speter s = stab(m->m_name, ST_MAILER, ST_ENTER); 182038032Speter if (s->s_mailer != NULL) 182138032Speter { 182238032Speter i = s->s_mailer->m_mno; 182390792Sgshapiro sm_free(s->s_mailer); /* XXX */ 182438032Speter } 182538032Speter else 182638032Speter { 182790792Sgshapiro i = nextmailer++; 182838032Speter } 182938032Speter Mailer[i] = s->s_mailer = m; 183038032Speter m->m_mno = i; 183138032Speter} 183290792Sgshapiro/* 183338032Speter** MUNCHSTRING -- translate a string into internal form. 183438032Speter** 183538032Speter** Parameters: 183638032Speter** p -- the string to munch. 183738032Speter** delimptr -- if non-NULL, set to the pointer of the 183838032Speter** field delimiter character. 183938032Speter** delim -- the delimiter for the field. 184038032Speter** 184138032Speter** Returns: 184238032Speter** the munched string. 184364562Sgshapiro** 184464562Sgshapiro** Side Effects: 184564562Sgshapiro** the munched string is a local static buffer. 184664562Sgshapiro** it must be copied before the function is called again. 184738032Speter*/ 184838032Speter 184938032Speterchar * 185038032Spetermunchstring(p, delimptr, delim) 185138032Speter register char *p; 185238032Speter char **delimptr; 185338032Speter int delim; 185438032Speter{ 185538032Speter register char *q; 185690792Sgshapiro bool backslash = false; 185790792Sgshapiro bool quotemode = false; 185838032Speter static char buf[MAXLINE]; 185938032Speter 1860168515Sgshapiro for (q = buf; *p != '\0' && q < &buf[sizeof(buf) - 1]; p++) 186138032Speter { 186238032Speter if (backslash) 186338032Speter { 186438032Speter /* everything is roughly literal */ 186590792Sgshapiro backslash = false; 186638032Speter switch (*p) 186738032Speter { 186838032Speter case 'r': /* carriage return */ 186938032Speter *q++ = '\r'; 187038032Speter continue; 187138032Speter 187238032Speter case 'n': /* newline */ 187338032Speter *q++ = '\n'; 187438032Speter continue; 187538032Speter 187638032Speter case 'f': /* form feed */ 187738032Speter *q++ = '\f'; 187838032Speter continue; 187938032Speter 188038032Speter case 'b': /* backspace */ 188138032Speter *q++ = '\b'; 188238032Speter continue; 188338032Speter } 188438032Speter *q++ = *p; 188538032Speter } 188638032Speter else 188738032Speter { 188838032Speter if (*p == '\\') 188990792Sgshapiro backslash = true; 189038032Speter else if (*p == '"') 189138032Speter quotemode = !quotemode; 189238032Speter else if (quotemode || *p != delim) 189338032Speter *q++ = *p; 189438032Speter else 189538032Speter break; 189638032Speter } 189738032Speter } 189838032Speter 189938032Speter if (delimptr != NULL) 190038032Speter *delimptr = p; 190138032Speter *q++ = '\0'; 190264562Sgshapiro return buf; 190338032Speter} 190490792Sgshapiro/* 190590792Sgshapiro** EXTRQUOTSTR -- extract a (quoted) string. 190690792Sgshapiro** 190790792Sgshapiro** This routine deals with quoted (") strings and escaped 190890792Sgshapiro** spaces (\\ ). 190990792Sgshapiro** 191090792Sgshapiro** Parameters: 191190792Sgshapiro** p -- source string. 191290792Sgshapiro** delimptr -- if non-NULL, set to the pointer of the 191390792Sgshapiro** field delimiter character. 191490792Sgshapiro** delimbuf -- delimiters for the field. 191590792Sgshapiro** st -- if non-NULL, store the return value (whether the 191690792Sgshapiro** string was correctly quoted) here. 191790792Sgshapiro** 191890792Sgshapiro** Returns: 191990792Sgshapiro** the extracted string. 192090792Sgshapiro** 192190792Sgshapiro** Side Effects: 192290792Sgshapiro** the returned string is a local static buffer. 192390792Sgshapiro** it must be copied before the function is called again. 192490792Sgshapiro*/ 192590792Sgshapiro 192690792Sgshapirostatic char * 192790792Sgshapiroextrquotstr(p, delimptr, delimbuf, st) 192890792Sgshapiro register char *p; 192990792Sgshapiro char **delimptr; 193090792Sgshapiro char *delimbuf; 193190792Sgshapiro bool *st; 193290792Sgshapiro{ 193390792Sgshapiro register char *q; 193490792Sgshapiro bool backslash = false; 193590792Sgshapiro bool quotemode = false; 193690792Sgshapiro static char buf[MAXLINE]; 193790792Sgshapiro 1938168515Sgshapiro for (q = buf; *p != '\0' && q < &buf[sizeof(buf) - 1]; p++) 193990792Sgshapiro { 194090792Sgshapiro if (backslash) 194190792Sgshapiro { 194290792Sgshapiro backslash = false; 194390792Sgshapiro if (*p != ' ') 194490792Sgshapiro *q++ = '\\'; 194590792Sgshapiro } 194690792Sgshapiro if (*p == '\\') 194790792Sgshapiro backslash = true; 194890792Sgshapiro else if (*p == '"') 194990792Sgshapiro quotemode = !quotemode; 195090792Sgshapiro else if (quotemode || 195190792Sgshapiro strchr(delimbuf, (int) *p) == NULL) 195290792Sgshapiro *q++ = *p; 195390792Sgshapiro else 195490792Sgshapiro break; 195590792Sgshapiro } 195690792Sgshapiro 195790792Sgshapiro if (delimptr != NULL) 195890792Sgshapiro *delimptr = p; 195990792Sgshapiro *q++ = '\0'; 196090792Sgshapiro if (st != NULL) 196190792Sgshapiro *st = !(quotemode || backslash); 196290792Sgshapiro return buf; 196390792Sgshapiro} 196490792Sgshapiro/* 196538032Speter** MAKEARGV -- break up a string into words 196638032Speter** 196738032Speter** Parameters: 196838032Speter** p -- the string to break up. 196938032Speter** 197038032Speter** Returns: 197138032Speter** a char **argv (dynamically allocated) 197238032Speter** 197338032Speter** Side Effects: 197438032Speter** munges p. 197538032Speter*/ 197638032Speter 197764562Sgshapirostatic char ** 197838032Spetermakeargv(p) 197938032Speter register char *p; 198038032Speter{ 198138032Speter char *q; 198238032Speter int i; 198338032Speter char **avp; 198438032Speter char *argv[MAXPV + 1]; 198538032Speter 198638032Speter /* take apart the words */ 198738032Speter i = 0; 198838032Speter while (*p != '\0' && i < MAXPV) 198938032Speter { 199038032Speter q = p; 199138032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 199238032Speter p++; 199338032Speter while (isascii(*p) && isspace(*p)) 199438032Speter *p++ = '\0'; 199538032Speter argv[i++] = newstr(q); 199638032Speter } 199738032Speter argv[i++] = NULL; 199838032Speter 199938032Speter /* now make a copy of the argv */ 2000168515Sgshapiro avp = (char **) xalloc(sizeof(*avp) * i); 2001168515Sgshapiro memmove((char *) avp, (char *) argv, sizeof(*avp) * i); 200238032Speter 200364562Sgshapiro return avp; 200438032Speter} 200590792Sgshapiro/* 200638032Speter** PRINTRULES -- print rewrite rules (for debugging) 200738032Speter** 200838032Speter** Parameters: 200938032Speter** none. 201038032Speter** 201138032Speter** Returns: 201238032Speter** none. 201338032Speter** 201438032Speter** Side Effects: 201538032Speter** prints rewrite rules. 201638032Speter*/ 201738032Speter 201838032Spetervoid 201938032Speterprintrules() 202038032Speter{ 202138032Speter register struct rewrite *rwp; 202238032Speter register int ruleset; 202338032Speter 202438032Speter for (ruleset = 0; ruleset < 10; ruleset++) 202538032Speter { 202638032Speter if (RewriteRules[ruleset] == NULL) 202738032Speter continue; 2028132943Sgshapiro sm_dprintf("\n----Rule Set %d:", ruleset); 202938032Speter 203038032Speter for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 203138032Speter { 2032132943Sgshapiro sm_dprintf("\nLHS:"); 2033132943Sgshapiro printav(sm_debug_file(), rwp->r_lhs); 2034132943Sgshapiro sm_dprintf("RHS:"); 2035132943Sgshapiro printav(sm_debug_file(), rwp->r_rhs); 203638032Speter } 203738032Speter } 203838032Speter} 203990792Sgshapiro/* 204038032Speter** PRINTMAILER -- print mailer structure (for debugging) 204138032Speter** 204238032Speter** Parameters: 2043132943Sgshapiro** fp -- output file 204438032Speter** m -- the mailer to print 204538032Speter** 204638032Speter** Returns: 204738032Speter** none. 204838032Speter*/ 204938032Speter 205038032Spetervoid 2051132943Sgshapiroprintmailer(fp, m) 2052132943Sgshapiro SM_FILE_T *fp; 205338032Speter register MAILER *m; 205438032Speter{ 205538032Speter int j; 205638032Speter 2057132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 205890792Sgshapiro "mailer %d (%s): P=%s S=", m->m_mno, m->m_name, 205990792Sgshapiro m->m_mailer); 206064562Sgshapiro if (RuleSetNames[m->m_se_rwset] == NULL) 2061132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d/", 206290792Sgshapiro m->m_se_rwset); 206364562Sgshapiro else 2064132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s/", 206590792Sgshapiro RuleSetNames[m->m_se_rwset]); 206664562Sgshapiro if (RuleSetNames[m->m_sh_rwset] == NULL) 2067132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d R=", 206890792Sgshapiro m->m_sh_rwset); 206964562Sgshapiro else 2070132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s R=", 207190792Sgshapiro RuleSetNames[m->m_sh_rwset]); 207264562Sgshapiro if (RuleSetNames[m->m_re_rwset] == NULL) 2073132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d/", 207490792Sgshapiro m->m_re_rwset); 207564562Sgshapiro else 2076132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s/", 207790792Sgshapiro RuleSetNames[m->m_re_rwset]); 207864562Sgshapiro if (RuleSetNames[m->m_rh_rwset] == NULL) 2079132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d ", 208090792Sgshapiro m->m_rh_rwset); 208164562Sgshapiro else 2082132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s ", 208390792Sgshapiro RuleSetNames[m->m_rh_rwset]); 2084132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "M=%ld U=%d:%d F=", 208590792Sgshapiro m->m_maxsize, (int) m->m_uid, (int) m->m_gid); 208638032Speter for (j = '\0'; j <= '\177'; j++) 208738032Speter if (bitnset(j, m->m_flags)) 2088132943Sgshapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, j); 2089132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " L=%d E=", 209090792Sgshapiro m->m_linelimit); 2091132943Sgshapiro xputs(fp, m->m_eol); 209238032Speter if (m->m_defcharset != NULL) 2093132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " C=%s", 209490792Sgshapiro m->m_defcharset); 2095132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " T=%s/%s/%s", 209690792Sgshapiro m->m_mtatype == NULL 209790792Sgshapiro ? "<undefined>" : m->m_mtatype, 209890792Sgshapiro m->m_addrtype == NULL 209990792Sgshapiro ? "<undefined>" : m->m_addrtype, 210090792Sgshapiro m->m_diagtype == NULL 210190792Sgshapiro ? "<undefined>" : m->m_diagtype); 2102132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " r=%d", m->m_maxrcpt); 210338032Speter if (m->m_argv != NULL) 210438032Speter { 210538032Speter char **a = m->m_argv; 210638032Speter 2107132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " A="); 210838032Speter while (*a != NULL) 210938032Speter { 211038032Speter if (a != m->m_argv) 2111132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 211290792Sgshapiro " "); 2113132943Sgshapiro xputs(fp, *a++); 211438032Speter } 211538032Speter } 2116132943Sgshapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "\n"); 211738032Speter} 2118285303Sgshapiro 2119285303Sgshapiro#if STARTTLS 2120285303Sgshapirostatic struct ssl_options 2121285303Sgshapiro{ 2122285303Sgshapiro const char *sslopt_name; /* name of the flag */ 2123285303Sgshapiro long sslopt_bits; /* bits to set/clear */ 2124285303Sgshapiro} SSL_Option[] = 2125285303Sgshapiro{ 2126285303Sgshapiro/* Workaround for bugs are turned on by default (as well as some others) */ 2127285303Sgshapiro#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG 2128285303Sgshapiro { "SSL_OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG }, 2129285303Sgshapiro#endif 2130285303Sgshapiro#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG 2131285303Sgshapiro { "SSL_OP_NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG }, 2132285303Sgshapiro#endif 2133285303Sgshapiro#ifdef SSL_OP_LEGACY_SERVER_CONNECT 2134285303Sgshapiro { "SSL_OP_LEGACY_SERVER_CONNECT", SSL_OP_LEGACY_SERVER_CONNECT }, 2135285303Sgshapiro#endif 2136285303Sgshapiro#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 2137285303Sgshapiro { "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG }, 2138285303Sgshapiro#endif 2139285303Sgshapiro#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 2140285303Sgshapiro { "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG }, 2141285303Sgshapiro#endif 2142285303Sgshapiro#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 2143285303Sgshapiro { "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER }, 2144285303Sgshapiro#endif 2145285303Sgshapiro#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING 2146285303Sgshapiro { "SSL_OP_MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING }, 2147285303Sgshapiro#endif 2148285303Sgshapiro#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG 2149285303Sgshapiro { "SSL_OP_SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG }, 2150285303Sgshapiro#endif 2151285303Sgshapiro#ifdef SSL_OP_TLS_D5_BUG 2152285303Sgshapiro { "SSL_OP_TLS_D5_BUG", SSL_OP_TLS_D5_BUG }, 2153285303Sgshapiro#endif 2154285303Sgshapiro#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG 2155285303Sgshapiro { "SSL_OP_TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG }, 2156285303Sgshapiro#endif 2157285303Sgshapiro#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 2158285303Sgshapiro { "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS }, 2159285303Sgshapiro#endif 2160285303Sgshapiro#ifdef SSL_OP_ALL 2161285303Sgshapiro { "SSL_OP_ALL", SSL_OP_ALL }, 2162285303Sgshapiro#endif 2163285303Sgshapiro#ifdef SSL_OP_NO_QUERY_MTU 2164285303Sgshapiro { "SSL_OP_NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU }, 2165285303Sgshapiro#endif 2166285303Sgshapiro#ifdef SSL_OP_COOKIE_EXCHANGE 2167285303Sgshapiro { "SSL_OP_COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE }, 2168285303Sgshapiro#endif 2169285303Sgshapiro#ifdef SSL_OP_NO_TICKET 2170285303Sgshapiro { "SSL_OP_NO_TICKET", SSL_OP_NO_TICKET }, 2171285303Sgshapiro#endif 2172285303Sgshapiro#ifdef SSL_OP_CISCO_ANYCONNECT 2173285303Sgshapiro { "SSL_OP_CISCO_ANYCONNECT", SSL_OP_CISCO_ANYCONNECT }, 2174285303Sgshapiro#endif 2175285303Sgshapiro#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 2176285303Sgshapiro { "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION }, 2177285303Sgshapiro#endif 2178285303Sgshapiro#ifdef SSL_OP_NO_COMPRESSION 2179285303Sgshapiro { "SSL_OP_NO_COMPRESSION", SSL_OP_NO_COMPRESSION }, 2180285303Sgshapiro#endif 2181285303Sgshapiro#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 2182285303Sgshapiro { "SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION }, 2183285303Sgshapiro#endif 2184285303Sgshapiro#ifdef SSL_OP_SINGLE_ECDH_USE 2185285303Sgshapiro { "SSL_OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE }, 2186285303Sgshapiro#endif 2187285303Sgshapiro#ifdef SSL_OP_SINGLE_DH_USE 2188285303Sgshapiro { "SSL_OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE }, 2189285303Sgshapiro#endif 2190285303Sgshapiro#ifdef SSL_OP_EPHEMERAL_RSA 2191285303Sgshapiro { "SSL_OP_EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA }, 2192285303Sgshapiro#endif 2193285303Sgshapiro#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE 2194285303Sgshapiro { "SSL_OP_CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE }, 2195285303Sgshapiro#endif 2196285303Sgshapiro#ifdef SSL_OP_TLS_ROLLBACK_BUG 2197285303Sgshapiro { "SSL_OP_TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG }, 2198285303Sgshapiro#endif 2199285303Sgshapiro#ifdef SSL_OP_NO_SSLv2 2200285303Sgshapiro { "SSL_OP_NO_SSLv2", SSL_OP_NO_SSLv2 }, 2201285303Sgshapiro#endif 2202285303Sgshapiro#ifdef SSL_OP_NO_SSLv3 2203285303Sgshapiro { "SSL_OP_NO_SSLv3", SSL_OP_NO_SSLv3 }, 2204285303Sgshapiro#endif 2205285303Sgshapiro#ifdef SSL_OP_NO_TLSv1 2206285303Sgshapiro { "SSL_OP_NO_TLSv1", SSL_OP_NO_TLSv1 }, 2207285303Sgshapiro#endif 2208285303Sgshapiro#ifdef SSL_OP_NO_TLSv1_2 2209285303Sgshapiro { "SSL_OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2 }, 2210285303Sgshapiro#endif 2211285303Sgshapiro#ifdef SSL_OP_NO_TLSv1_1 2212285303Sgshapiro { "SSL_OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1 }, 2213285303Sgshapiro#endif 2214285303Sgshapiro#ifdef SSL_OP_PKCS1_CHECK_1 2215285303Sgshapiro { "SSL_OP_PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 }, 2216285303Sgshapiro#endif 2217285303Sgshapiro#ifdef SSL_OP_PKCS1_CHECK_2 2218285303Sgshapiro { "SSL_OP_PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 }, 2219285303Sgshapiro#endif 2220285303Sgshapiro#ifdef SSL_OP_NETSCAPE_CA_DN_BUG 2221285303Sgshapiro { "SSL_OP_NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG }, 2222285303Sgshapiro#endif 2223285303Sgshapiro#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 2224285303Sgshapiro { "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG }, 2225285303Sgshapiro#endif 2226285303Sgshapiro#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG 2227285303Sgshapiro { "SSL_OP_CRYPTOPRO_TLSEXT_BUG", SSL_OP_CRYPTOPRO_TLSEXT_BUG }, 2228285303Sgshapiro#endif 2229285303Sgshapiro#ifdef SSL_OP_TLSEXT_PADDING 2230285303Sgshapiro { "SSL_OP_TLSEXT_PADDING", SSL_OP_TLSEXT_PADDING }, 2231285303Sgshapiro#endif 2232285303Sgshapiro { NULL, 0 } 2233285303Sgshapiro}; 2234285303Sgshapiro 223590792Sgshapiro/* 2236285303Sgshapiro** READSSLOPTIONS -- read SSL_OP_* values 2237285303Sgshapiro** 2238285303Sgshapiro** Parameters: 2239285303Sgshapiro** opt -- name of option (can be NULL) 2240285303Sgshapiro** val -- string with SSL_OP_* values or hex value 2241285303Sgshapiro** delim -- end of string (e.g., '\0' or ';') 2242285303Sgshapiro** pssloptions -- return value (output) 2243285303Sgshapiro** 2244285303Sgshapiro** Returns: 2245285303Sgshapiro** 0 on success. 2246285303Sgshapiro*/ 2247285303Sgshapiro 2248285303Sgshapiro#define SSLOPERR_NAN 1 2249285303Sgshapiro#define SSLOPERR_NOTFOUND 2 2250285303Sgshapiro#define SM_ISSPACE(c) (isascii(c) && isspace(c)) 2251285303Sgshapiro 2252285303Sgshapirostatic int 2253285303Sgshapiroreadssloptions(opt, val, pssloptions, delim) 2254285303Sgshapiro char *opt; 2255285303Sgshapiro char *val; 2256285303Sgshapiro unsigned long *pssloptions; 2257285303Sgshapiro int delim; 2258285303Sgshapiro{ 2259285303Sgshapiro char *p; 2260285303Sgshapiro int ret; 2261285303Sgshapiro 2262285303Sgshapiro ret = 0; 2263285303Sgshapiro for (p = val; *p != '\0' && *p != delim; ) 2264285303Sgshapiro { 2265285303Sgshapiro bool clearmode; 2266285303Sgshapiro char *q; 2267285303Sgshapiro unsigned long sslopt_val; 2268285303Sgshapiro struct ssl_options *sslopts; 2269285303Sgshapiro 2270285303Sgshapiro while (*p == ' ') 2271285303Sgshapiro p++; 2272285303Sgshapiro if (*p == '\0') 2273285303Sgshapiro break; 2274285303Sgshapiro clearmode = false; 2275285303Sgshapiro if (*p == '-' || *p == '+') 2276285303Sgshapiro clearmode = *p++ == '-'; 2277285303Sgshapiro q = p; 2278285303Sgshapiro while (*p != '\0' && !(SM_ISSPACE(*p)) && *p != ',') 2279285303Sgshapiro p++; 2280285303Sgshapiro if (*p != '\0') 2281285303Sgshapiro *p++ = '\0'; 2282285303Sgshapiro sslopt_val = 0; 2283285303Sgshapiro if (isdigit(*q)) 2284285303Sgshapiro { 2285285303Sgshapiro char *end; 2286285303Sgshapiro 2287285303Sgshapiro sslopt_val = strtoul(q, &end, 0); 2288285303Sgshapiro 2289285303Sgshapiro /* not a complete "syntax" check but good enough */ 2290285303Sgshapiro if (end == q) 2291285303Sgshapiro { 2292285303Sgshapiro errno = 0; 2293285303Sgshapiro ret = SSLOPERR_NAN; 2294285303Sgshapiro if (opt != NULL) 2295285303Sgshapiro syserr("readcf: %s option value %s not a number", 2296285303Sgshapiro opt, q); 2297285303Sgshapiro sslopt_val = 0; 2298285303Sgshapiro } 2299285303Sgshapiro } 2300285303Sgshapiro else 2301285303Sgshapiro { 2302285303Sgshapiro for (sslopts = SSL_Option; 2303285303Sgshapiro sslopts->sslopt_name != NULL; sslopts++) 2304285303Sgshapiro { 2305285303Sgshapiro if (sm_strcasecmp(q, sslopts->sslopt_name) == 0) 2306285303Sgshapiro { 2307285303Sgshapiro sslopt_val = sslopts->sslopt_bits; 2308285303Sgshapiro break; 2309285303Sgshapiro } 2310285303Sgshapiro } 2311285303Sgshapiro if (sslopts->sslopt_name == NULL) 2312285303Sgshapiro { 2313285303Sgshapiro errno = 0; 2314285303Sgshapiro ret = SSLOPERR_NOTFOUND; 2315285303Sgshapiro if (opt != NULL) 2316285303Sgshapiro syserr("readcf: %s option value %s unrecognized", 2317285303Sgshapiro opt, q); 2318285303Sgshapiro } 2319285303Sgshapiro } 2320285303Sgshapiro if (sslopt_val != 0) 2321285303Sgshapiro { 2322285303Sgshapiro if (clearmode) 2323285303Sgshapiro *pssloptions &= ~sslopt_val; 2324285303Sgshapiro else 2325285303Sgshapiro *pssloptions |= sslopt_val; 2326285303Sgshapiro } 2327285303Sgshapiro } 2328285303Sgshapiro return ret; 2329285303Sgshapiro} 2330285303Sgshapiro 2331285303Sgshapiro# if _FFR_TLS_SE_OPTS 2332285303Sgshapiro/* 2333285303Sgshapiro** GET_TLS_SE_OPTIONS -- get TLS session options (from ruleset) 2334285303Sgshapiro** 2335285303Sgshapiro** Parameters: 2336285303Sgshapiro** e -- envelope 2337285303Sgshapiro** ssl -- TLS session context 2338285303Sgshapiro** srv -- server? 2339285303Sgshapiro** 2340285303Sgshapiro** Returns: 2341285303Sgshapiro** 0 on success. 2342285303Sgshapiro*/ 2343285303Sgshapiro 2344285303Sgshapiroint 2345285303Sgshapiroget_tls_se_options(e, ssl, srv) 2346285303Sgshapiro ENVELOPE *e; 2347285303Sgshapiro SSL *ssl; 2348285303Sgshapiro bool srv; 2349285303Sgshapiro{ 2350285303Sgshapiro bool saveQuickAbort, saveSuprErrs, ok; 2351285303Sgshapiro char *optionlist, *opt, *val; 2352285303Sgshapiro char *keyfile, *certfile; 2353285303Sgshapiro size_t len, i; 2354285303Sgshapiro int ret; 2355285303Sgshapiro 2356285303Sgshapiro# define who (srv ? "server" : "client") 2357285303Sgshapiro# define NAME_C_S macvalue(macid(srv ? "{client_name}" : "{server_name}"), e) 2358285303Sgshapiro# define ADDR_C_S macvalue(macid(srv ? "{client_addr}" : "{server_addr}"), e) 2359285303Sgshapiro# define WHICH srv ? "srv" : "clt" 2360285303Sgshapiro 2361285303Sgshapiro ret = 0; 2362285303Sgshapiro keyfile = certfile = opt = val = NULL; 2363285303Sgshapiro saveQuickAbort = QuickAbort; 2364285303Sgshapiro saveSuprErrs = SuprErrs; 2365285303Sgshapiro SuprErrs = true; 2366285303Sgshapiro QuickAbort = false; 2367285303Sgshapiro 2368285303Sgshapiro optionlist = NULL; 2369285303Sgshapiro ok = rscheck(srv ? "tls_srv_features" : "tls_clt_features", 2370285303Sgshapiro NAME_C_S, ADDR_C_S, e, 2371285303Sgshapiro RSF_RMCOMM|RSF_ADDR|RSF_STRING, 2372285303Sgshapiro 5, NULL, NOQID, NULL, &optionlist) == EX_OK; 2373285303Sgshapiro if (!ok && LogLevel > 8) 2374285303Sgshapiro { 2375285303Sgshapiro sm_syslog(LOG_NOTICE, NOQID, 2376285303Sgshapiro "rscheck(tls_%s_features)=failed, relay=%s [%s], errors=%d", 2377285303Sgshapiro WHICH, NAME_C_S, ADDR_C_S, 2378285303Sgshapiro Errors); 2379285303Sgshapiro } 2380285303Sgshapiro QuickAbort = saveQuickAbort; 2381285303Sgshapiro SuprErrs = saveSuprErrs; 2382285303Sgshapiro if (ok && LogLevel > 9) 2383285303Sgshapiro { 2384285303Sgshapiro sm_syslog(LOG_INFO, NOQID, 2385285303Sgshapiro "tls_%s_features=%s, relay=%s [%s]", 2386285303Sgshapiro WHICH, optionlist, NAME_C_S, ADDR_C_S); 2387285303Sgshapiro } 2388285303Sgshapiro if (!ok || optionlist == NULL || (len = strlen(optionlist)) < 2) 2389285303Sgshapiro { 2390285303Sgshapiro if (LogLevel > 9) 2391285303Sgshapiro sm_syslog(LOG_INFO, NOQID, 2392285303Sgshapiro "tls_%s_features=empty, relay=%s [%s]", 2393285303Sgshapiro WHICH, NAME_C_S, ADDR_C_S); 2394285303Sgshapiro 2395285303Sgshapiro return ok ? 0 : 1; 2396285303Sgshapiro } 2397285303Sgshapiro 2398285303Sgshapiro i = 0; 2399285303Sgshapiro if (optionlist[0] == '"' && optionlist[len - 1] == '"') 2400285303Sgshapiro { 2401285303Sgshapiro optionlist[0] = ' '; 2402285303Sgshapiro optionlist[--len] = '\0'; 2403285303Sgshapiro if (len <= 2) 2404285303Sgshapiro { 2405285303Sgshapiro if (LogLevel > 9 && len > 1) 2406285303Sgshapiro sm_syslog(LOG_INFO, NOQID, 2407285303Sgshapiro "tls_%s_features=too_short, relay=%s [%s]", 2408285303Sgshapiro WHICH, NAME_C_S, ADDR_C_S); 2409285303Sgshapiro 2410285303Sgshapiro /* this is not treated as error! */ 2411285303Sgshapiro return 0; 2412285303Sgshapiro } 2413285303Sgshapiro i = 1; 2414285303Sgshapiro } 2415285303Sgshapiro 2416285303Sgshapiro# define INVALIDSYNTAX \ 2417285303Sgshapiro do { \ 2418285303Sgshapiro if (LogLevel > 7) \ 2419285303Sgshapiro sm_syslog(LOG_INFO, NOQID, \ 2420285303Sgshapiro "tls_%s_features=invalid_syntax, opt=%s, relay=%s [%s]", \ 2421285303Sgshapiro WHICH, opt, NAME_C_S, ADDR_C_S); \ 2422285303Sgshapiro return -1; \ 2423285303Sgshapiro } while (0) 2424285303Sgshapiro 2425285303Sgshapiro# define CHECKLEN \ 2426285303Sgshapiro do { \ 2427285303Sgshapiro if (i >= len) \ 2428285303Sgshapiro INVALIDSYNTAX; \ 2429285303Sgshapiro } while (0) 2430285303Sgshapiro 2431285303Sgshapiro# define SKIPWS \ 2432285303Sgshapiro do { \ 2433285303Sgshapiro while (i < len && SM_ISSPACE(optionlist[i])) \ 2434285303Sgshapiro ++i; \ 2435285303Sgshapiro CHECKLEN; \ 2436285303Sgshapiro } while (0) 2437285303Sgshapiro 2438285303Sgshapiro /* parse and handle opt=val; */ 2439285303Sgshapiro do { 2440285303Sgshapiro char sep; 2441285303Sgshapiro 2442285303Sgshapiro SKIPWS; 2443285303Sgshapiro opt = optionlist + i; 2444285303Sgshapiro sep = '='; 2445285303Sgshapiro while (i < len && optionlist[i] != sep 2446285303Sgshapiro && optionlist[i] != '\0' && !SM_ISSPACE(optionlist[i])) 2447285303Sgshapiro ++i; 2448285303Sgshapiro CHECKLEN; 2449285303Sgshapiro while (i < len && SM_ISSPACE(optionlist[i])) 2450285303Sgshapiro optionlist[i++] = '\0'; 2451285303Sgshapiro CHECKLEN; 2452285303Sgshapiro if (optionlist[i] != sep) 2453285303Sgshapiro INVALIDSYNTAX; 2454285303Sgshapiro optionlist[i++] = '\0'; 2455285303Sgshapiro 2456285303Sgshapiro SKIPWS; 2457285303Sgshapiro val = optionlist + i; 2458285303Sgshapiro sep = ';'; 2459285303Sgshapiro while (i < len && optionlist[i] != sep && optionlist[i] != '\0') 2460285303Sgshapiro ++i; 2461285303Sgshapiro if (optionlist[i] != '\0') 2462285303Sgshapiro { 2463285303Sgshapiro CHECKLEN; 2464285303Sgshapiro optionlist[i++] = '\0'; 2465285303Sgshapiro } 2466285303Sgshapiro 2467285303Sgshapiro if (LogLevel > 13) 2468285303Sgshapiro sm_syslog(LOG_DEBUG, NOQID, 2469285303Sgshapiro "tls_%s_features=parsed, %s=%s, relay=%s [%s]", 2470285303Sgshapiro WHICH, opt, val, NAME_C_S, ADDR_C_S); 2471285303Sgshapiro 2472285303Sgshapiro if (sm_strcasecmp(opt, "options") == 0) 2473285303Sgshapiro { 2474285303Sgshapiro unsigned long ssloptions; 2475285303Sgshapiro 2476285303Sgshapiro ssloptions = 0; 2477285303Sgshapiro ret = readssloptions(NULL, val, &ssloptions, ';'); 2478285303Sgshapiro if (ret == 0) 2479285303Sgshapiro (void) SSL_set_options(ssl, (long) ssloptions); 2480285303Sgshapiro else if (LogLevel > 8) 2481285303Sgshapiro { 2482285303Sgshapiro sm_syslog(LOG_WARNING, NOQID, 2483285303Sgshapiro "tls_%s_features=%s, error=%s, relay=%s [%s]", 2484285303Sgshapiro WHICH, val, 2485285303Sgshapiro (ret == SSLOPERR_NAN) ? "not a number" : 2486285303Sgshapiro ((ret == SSLOPERR_NOTFOUND) ? "SSL_OP not found" : 2487285303Sgshapiro "unknown"), 2488285303Sgshapiro NAME_C_S, ADDR_C_S); 2489285303Sgshapiro } 2490285303Sgshapiro } 2491285303Sgshapiro else if (sm_strcasecmp(opt, "cipherlist") == 0) 2492285303Sgshapiro { 2493285303Sgshapiro if (SSL_set_cipher_list(ssl, val) <= 0) 2494285303Sgshapiro { 2495285303Sgshapiro ret = 1; 2496285303Sgshapiro if (LogLevel > 7) 2497285303Sgshapiro { 2498285303Sgshapiro sm_syslog(LOG_WARNING, NOQID, 2499285303Sgshapiro "STARTTLS=%s, error: SSL_set_cipher_list(%s) failed", 2500285303Sgshapiro who, val); 2501285303Sgshapiro 2502285303Sgshapiro if (LogLevel > 9) 2503285303Sgshapiro tlslogerr(LOG_WARNING, who); 2504285303Sgshapiro } 2505285303Sgshapiro } 2506285303Sgshapiro } 2507285303Sgshapiro else if (sm_strcasecmp(opt, "keyfile") == 0) 2508285303Sgshapiro keyfile = val; 2509285303Sgshapiro else if (sm_strcasecmp(opt, "certfile") == 0) 2510285303Sgshapiro certfile = val; 2511285303Sgshapiro else 2512285303Sgshapiro { 2513285303Sgshapiro ret = 1; 2514285303Sgshapiro if (LogLevel > 7) 2515285303Sgshapiro { 2516285303Sgshapiro sm_syslog(LOG_INFO, NOQID, 2517285303Sgshapiro "tls_%s_features=unknown_option, opt=%s, relay=%s [%s]", 2518285303Sgshapiro WHICH, opt, NAME_C_S, ADDR_C_S); 2519285303Sgshapiro } 2520285303Sgshapiro } 2521285303Sgshapiro 2522285303Sgshapiro } while (optionlist[i] != '\0' && i < len); 2523285303Sgshapiro 2524285303Sgshapiro /* need cert and key before we can use the options */ 2525285303Sgshapiro /* does not implement the "," hack for 2nd cert/key pair */ 2526285303Sgshapiro if (keyfile != NULL && certfile != NULL) 2527285303Sgshapiro { 2528285303Sgshapiro load_certkey(ssl, srv, certfile, keyfile); 2529285303Sgshapiro keyfile = certfile = NULL; 2530285303Sgshapiro } 2531285303Sgshapiro else if (keyfile != NULL || certfile != NULL) 2532285303Sgshapiro { 2533285303Sgshapiro ret = 1; 2534285303Sgshapiro if (LogLevel > 7) 2535285303Sgshapiro { 2536285303Sgshapiro sm_syslog(LOG_INFO, NOQID, 2537285303Sgshapiro "tls_%s_features=only_one_of_CertFile/KeyFile_specified, relay=%s [%s]", 2538285303Sgshapiro WHICH, NAME_C_S, ADDR_C_S); 2539285303Sgshapiro } 2540285303Sgshapiro } 2541285303Sgshapiro 2542285303Sgshapiro return ret; 2543285303Sgshapiro# undef who 2544285303Sgshapiro# undef NAME_C_S 2545285303Sgshapiro# undef ADDR_C_S 2546285303Sgshapiro# undef WHICH 2547285303Sgshapiro} 2548285303Sgshapiro# endif /* _FFR_TLS_SE_OPTS */ 2549285303Sgshapiro#endif /* STARTTLS */ 2550285303Sgshapiro 2551285303Sgshapiro/* 255238032Speter** SETOPTION -- set global processing option 255338032Speter** 255438032Speter** Parameters: 255538032Speter** opt -- option name. 255638032Speter** val -- option value (as a text string). 255738032Speter** safe -- set if this came from a configuration file. 255838032Speter** Some options (if set from the command line) will 255938032Speter** reset the user id to avoid security problems. 256038032Speter** sticky -- if set, don't let other setoptions override 256138032Speter** this value. 256238032Speter** e -- the main envelope. 256338032Speter** 256438032Speter** Returns: 256538032Speter** none. 256638032Speter** 256738032Speter** Side Effects: 256838032Speter** Sets options as implied by the arguments. 256938032Speter*/ 257038032Speter 257164562Sgshapirostatic BITMAP256 StickyOpt; /* set if option is stuck */ 257238032Speter 257338032Speter#if NAMED_BIND 257438032Speter 257564562Sgshapirostatic struct resolverflags 257638032Speter{ 257738032Speter char *rf_name; /* name of the flag */ 257838032Speter long rf_bits; /* bits to set/clear */ 257938032Speter} ResolverFlags[] = 258038032Speter{ 258138032Speter { "debug", RES_DEBUG }, 258238032Speter { "aaonly", RES_AAONLY }, 258338032Speter { "usevc", RES_USEVC }, 258438032Speter { "primary", RES_PRIMARY }, 258538032Speter { "igntc", RES_IGNTC }, 258638032Speter { "recurse", RES_RECURSE }, 258738032Speter { "defnames", RES_DEFNAMES }, 258838032Speter { "stayopen", RES_STAYOPEN }, 258938032Speter { "dnsrch", RES_DNSRCH }, 259090792Sgshapiro# ifdef RES_USE_INET6 259190792Sgshapiro { "use_inet6", RES_USE_INET6 }, 259290792Sgshapiro# endif /* RES_USE_INET6 */ 259338032Speter { "true", 0 }, /* avoid error on old syntax */ 259438032Speter { NULL, 0 } 259538032Speter}; 259638032Speter 259764562Sgshapiro#endif /* NAMED_BIND */ 259838032Speter 259964562Sgshapiro#define OI_NONE 0 /* no special treatment */ 260064562Sgshapiro#define OI_SAFE 0x0001 /* safe for random people to use */ 260164562Sgshapiro#define OI_SUBOPT 0x0002 /* option has suboptions */ 260264562Sgshapiro 260364562Sgshapirostatic struct optioninfo 260438032Speter{ 260590792Sgshapiro char *o_name; /* long name of option */ 260690792Sgshapiro unsigned char o_code; /* short name of option */ 260790792Sgshapiro unsigned short o_flags; /* option flags */ 260838032Speter} OptionTab[] = 260938032Speter{ 261064562Sgshapiro#if defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) 261164562Sgshapiro { "RemoteMode", '>', OI_NONE }, 261264562Sgshapiro#endif /* defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) */ 261364562Sgshapiro { "SevenBitInput", '7', OI_SAFE }, 261464562Sgshapiro { "EightBitMode", '8', OI_SAFE }, 261564562Sgshapiro { "AliasFile", 'A', OI_NONE }, 261664562Sgshapiro { "AliasWait", 'a', OI_NONE }, 261764562Sgshapiro { "BlankSub", 'B', OI_NONE }, 261864562Sgshapiro { "MinFreeBlocks", 'b', OI_SAFE }, 261964562Sgshapiro { "CheckpointInterval", 'C', OI_SAFE }, 262064562Sgshapiro { "HoldExpensive", 'c', OI_NONE }, 262164562Sgshapiro { "DeliveryMode", 'd', OI_SAFE }, 262264562Sgshapiro { "ErrorHeader", 'E', OI_NONE }, 262364562Sgshapiro { "ErrorMode", 'e', OI_SAFE }, 262464562Sgshapiro { "TempFileMode", 'F', OI_NONE }, 262564562Sgshapiro { "SaveFromLine", 'f', OI_NONE }, 262664562Sgshapiro { "MatchGECOS", 'G', OI_NONE }, 262790792Sgshapiro 262890792Sgshapiro /* no long name, just here to avoid problems in setoption */ 262990792Sgshapiro { "", 'g', OI_NONE }, 263064562Sgshapiro { "HelpFile", 'H', OI_NONE }, 263164562Sgshapiro { "MaxHopCount", 'h', OI_NONE }, 263264562Sgshapiro { "ResolverOptions", 'I', OI_NONE }, 263364562Sgshapiro { "IgnoreDots", 'i', OI_SAFE }, 263464562Sgshapiro { "ForwardPath", 'J', OI_NONE }, 263564562Sgshapiro { "SendMimeErrors", 'j', OI_SAFE }, 263664562Sgshapiro { "ConnectionCacheSize", 'k', OI_NONE }, 263764562Sgshapiro { "ConnectionCacheTimeout", 'K', OI_NONE }, 263864562Sgshapiro { "UseErrorsTo", 'l', OI_NONE }, 263964562Sgshapiro { "LogLevel", 'L', OI_SAFE }, 264064562Sgshapiro { "MeToo", 'm', OI_SAFE }, 264190792Sgshapiro 264290792Sgshapiro /* no long name, just here to avoid problems in setoption */ 264390792Sgshapiro { "", 'M', OI_NONE }, 264464562Sgshapiro { "CheckAliases", 'n', OI_NONE }, 264564562Sgshapiro { "OldStyleHeaders", 'o', OI_SAFE }, 264664562Sgshapiro { "DaemonPortOptions", 'O', OI_NONE }, 264764562Sgshapiro { "PrivacyOptions", 'p', OI_SAFE }, 264864562Sgshapiro { "PostmasterCopy", 'P', OI_NONE }, 264964562Sgshapiro { "QueueFactor", 'q', OI_NONE }, 265064562Sgshapiro { "QueueDirectory", 'Q', OI_NONE }, 265164562Sgshapiro { "DontPruneRoutes", 'R', OI_NONE }, 265264562Sgshapiro { "Timeout", 'r', OI_SUBOPT }, 265364562Sgshapiro { "StatusFile", 'S', OI_NONE }, 265464562Sgshapiro { "SuperSafe", 's', OI_SAFE }, 265564562Sgshapiro { "QueueTimeout", 'T', OI_NONE }, 265664562Sgshapiro { "TimeZoneSpec", 't', OI_NONE }, 265764562Sgshapiro { "UserDatabaseSpec", 'U', OI_NONE }, 265864562Sgshapiro { "DefaultUser", 'u', OI_NONE }, 265964562Sgshapiro { "FallbackMXhost", 'V', OI_NONE }, 266064562Sgshapiro { "Verbose", 'v', OI_SAFE }, 266164562Sgshapiro { "TryNullMXList", 'w', OI_NONE }, 266264562Sgshapiro { "QueueLA", 'x', OI_NONE }, 266364562Sgshapiro { "RefuseLA", 'X', OI_NONE }, 266464562Sgshapiro { "RecipientFactor", 'y', OI_NONE }, 266564562Sgshapiro { "ForkEachJob", 'Y', OI_NONE }, 266664562Sgshapiro { "ClassFactor", 'z', OI_NONE }, 266764562Sgshapiro { "RetryFactor", 'Z', OI_NONE }, 266838032Speter#define O_QUEUESORTORD 0x81 266964562Sgshapiro { "QueueSortOrder", O_QUEUESORTORD, OI_SAFE }, 267038032Speter#define O_HOSTSFILE 0x82 267164562Sgshapiro { "HostsFile", O_HOSTSFILE, OI_NONE }, 267238032Speter#define O_MQA 0x83 267364562Sgshapiro { "MinQueueAge", O_MQA, OI_SAFE }, 267438032Speter#define O_DEFCHARSET 0x85 267564562Sgshapiro { "DefaultCharSet", O_DEFCHARSET, OI_SAFE }, 267638032Speter#define O_SSFILE 0x86 267764562Sgshapiro { "ServiceSwitchFile", O_SSFILE, OI_NONE }, 267838032Speter#define O_DIALDELAY 0x87 267964562Sgshapiro { "DialDelay", O_DIALDELAY, OI_SAFE }, 268038032Speter#define O_NORCPTACTION 0x88 268164562Sgshapiro { "NoRecipientAction", O_NORCPTACTION, OI_SAFE }, 268238032Speter#define O_SAFEFILEENV 0x89 268364562Sgshapiro { "SafeFileEnvironment", O_SAFEFILEENV, OI_NONE }, 268438032Speter#define O_MAXMSGSIZE 0x8a 268564562Sgshapiro { "MaxMessageSize", O_MAXMSGSIZE, OI_NONE }, 268638032Speter#define O_COLONOKINADDR 0x8b 268764562Sgshapiro { "ColonOkInAddr", O_COLONOKINADDR, OI_SAFE }, 268838032Speter#define O_MAXQUEUERUN 0x8c 268964562Sgshapiro { "MaxQueueRunSize", O_MAXQUEUERUN, OI_SAFE }, 269038032Speter#define O_MAXCHILDREN 0x8d 269164562Sgshapiro { "MaxDaemonChildren", O_MAXCHILDREN, OI_NONE }, 269238032Speter#define O_KEEPCNAMES 0x8e 269364562Sgshapiro { "DontExpandCnames", O_KEEPCNAMES, OI_NONE }, 269438032Speter#define O_MUSTQUOTE 0x8f 269564562Sgshapiro { "MustQuoteChars", O_MUSTQUOTE, OI_NONE }, 269638032Speter#define O_SMTPGREETING 0x90 269764562Sgshapiro { "SmtpGreetingMessage", O_SMTPGREETING, OI_NONE }, 269838032Speter#define O_UNIXFROM 0x91 269964562Sgshapiro { "UnixFromLine", O_UNIXFROM, OI_NONE }, 270038032Speter#define O_OPCHARS 0x92 270164562Sgshapiro { "OperatorChars", O_OPCHARS, OI_NONE }, 270238032Speter#define O_DONTINITGRPS 0x93 270364562Sgshapiro { "DontInitGroups", O_DONTINITGRPS, OI_NONE }, 270438032Speter#define O_SLFH 0x94 270564562Sgshapiro { "SingleLineFromHeader", O_SLFH, OI_SAFE }, 270638032Speter#define O_ABH 0x95 270764562Sgshapiro { "AllowBogusHELO", O_ABH, OI_SAFE }, 270838032Speter#define O_CONNTHROT 0x97 270964562Sgshapiro { "ConnectionRateThrottle", O_CONNTHROT, OI_NONE }, 271038032Speter#define O_UGW 0x99 271164562Sgshapiro { "UnsafeGroupWrites", O_UGW, OI_NONE }, 271238032Speter#define O_DBLBOUNCE 0x9a 271364562Sgshapiro { "DoubleBounceAddress", O_DBLBOUNCE, OI_NONE }, 271438032Speter#define O_HSDIR 0x9b 271564562Sgshapiro { "HostStatusDirectory", O_HSDIR, OI_NONE }, 271638032Speter#define O_SINGTHREAD 0x9c 271764562Sgshapiro { "SingleThreadDelivery", O_SINGTHREAD, OI_NONE }, 271838032Speter#define O_RUNASUSER 0x9d 271964562Sgshapiro { "RunAsUser", O_RUNASUSER, OI_NONE }, 272038032Speter#define O_DSN_RRT 0x9e 272164562Sgshapiro { "RrtImpliesDsn", O_DSN_RRT, OI_NONE }, 272238032Speter#define O_PIDFILE 0x9f 272364562Sgshapiro { "PidFile", O_PIDFILE, OI_NONE }, 272438032Speter#define O_DONTBLAMESENDMAIL 0xa0 272564562Sgshapiro { "DontBlameSendmail", O_DONTBLAMESENDMAIL, OI_NONE }, 272638032Speter#define O_DPI 0xa1 272764562Sgshapiro { "DontProbeInterfaces", O_DPI, OI_NONE }, 272838032Speter#define O_MAXRCPT 0xa2 272964562Sgshapiro { "MaxRecipientsPerMessage", O_MAXRCPT, OI_SAFE }, 273038032Speter#define O_DEADLETTER 0xa3 273164562Sgshapiro { "DeadLetterDrop", O_DEADLETTER, OI_NONE }, 273238032Speter#if _FFR_DONTLOCKFILESFORREAD_OPTION 273364562Sgshapiro# define O_DONTLOCK 0xa4 273464562Sgshapiro { "DontLockFilesForRead", O_DONTLOCK, OI_NONE }, 273564562Sgshapiro#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ 273638032Speter#define O_MAXALIASRCSN 0xa5 273764562Sgshapiro { "MaxAliasRecursion", O_MAXALIASRCSN, OI_NONE }, 273838032Speter#define O_CNCTONLYTO 0xa6 273964562Sgshapiro { "ConnectOnlyTo", O_CNCTONLYTO, OI_NONE }, 274042575Speter#define O_TRUSTUSER 0xa7 274164562Sgshapiro { "TrustedUser", O_TRUSTUSER, OI_NONE }, 274242575Speter#define O_MAXMIMEHDRLEN 0xa8 274364562Sgshapiro { "MaxMimeHeaderLength", O_MAXMIMEHDRLEN, OI_NONE }, 274442575Speter#define O_CONTROLSOCKET 0xa9 274564562Sgshapiro { "ControlSocketName", O_CONTROLSOCKET, OI_NONE }, 274643730Speter#define O_MAXHDRSLEN 0xaa 274764562Sgshapiro { "MaxHeadersLength", O_MAXHDRSLEN, OI_NONE }, 274864562Sgshapiro#if _FFR_MAX_FORWARD_ENTRIES 274964562Sgshapiro# define O_MAXFORWARD 0xab 275064562Sgshapiro { "MaxForwardEntries", O_MAXFORWARD, OI_NONE }, 275164562Sgshapiro#endif /* _FFR_MAX_FORWARD_ENTRIES */ 275264562Sgshapiro#define O_PROCTITLEPREFIX 0xac 275364562Sgshapiro { "ProcessTitlePrefix", O_PROCTITLEPREFIX, OI_NONE }, 275464562Sgshapiro#define O_SASLINFO 0xad 275564562Sgshapiro#if _FFR_ALLOW_SASLINFO 275664562Sgshapiro { "DefaultAuthInfo", O_SASLINFO, OI_SAFE }, 275764562Sgshapiro#else /* _FFR_ALLOW_SASLINFO */ 275864562Sgshapiro { "DefaultAuthInfo", O_SASLINFO, OI_NONE }, 275964562Sgshapiro#endif /* _FFR_ALLOW_SASLINFO */ 276064562Sgshapiro#define O_SASLMECH 0xae 276164562Sgshapiro { "AuthMechanisms", O_SASLMECH, OI_NONE }, 276264562Sgshapiro#define O_CLIENTPORT 0xaf 276364562Sgshapiro { "ClientPortOptions", O_CLIENTPORT, OI_NONE }, 276464562Sgshapiro#define O_DF_BUFSIZE 0xb0 276564562Sgshapiro { "DataFileBufferSize", O_DF_BUFSIZE, OI_NONE }, 276664562Sgshapiro#define O_XF_BUFSIZE 0xb1 276764562Sgshapiro { "XscriptFileBufferSize", O_XF_BUFSIZE, OI_NONE }, 276890792Sgshapiro#define O_LDAPDEFAULTSPEC 0xb2 276964562Sgshapiro { "LDAPDefaultSpec", O_LDAPDEFAULTSPEC, OI_NONE }, 277090792Sgshapiro#define O_SRVCERTFILE 0xb4 277164562Sgshapiro { "ServerCertFile", O_SRVCERTFILE, OI_NONE }, 277290792Sgshapiro#define O_SRVKEYFILE 0xb5 2773102528Sgshapiro { "ServerKeyFile", O_SRVKEYFILE, OI_NONE }, 277490792Sgshapiro#define O_CLTCERTFILE 0xb6 277564562Sgshapiro { "ClientCertFile", O_CLTCERTFILE, OI_NONE }, 277690792Sgshapiro#define O_CLTKEYFILE 0xb7 2777102528Sgshapiro { "ClientKeyFile", O_CLTKEYFILE, OI_NONE }, 277890792Sgshapiro#define O_CACERTFILE 0xb8 2779110560Sgshapiro { "CACertFile", O_CACERTFILE, OI_NONE }, 278090792Sgshapiro#define O_CACERTPATH 0xb9 2781110560Sgshapiro { "CACertPath", O_CACERTPATH, OI_NONE }, 278290792Sgshapiro#define O_DHPARAMS 0xba 278364562Sgshapiro { "DHParameters", O_DHPARAMS, OI_NONE }, 278464562Sgshapiro#define O_INPUTMILTER 0xbb 278564562Sgshapiro { "InputMailFilters", O_INPUTMILTER, OI_NONE }, 278664562Sgshapiro#define O_MILTER 0xbc 278764562Sgshapiro { "Milter", O_MILTER, OI_SUBOPT }, 278864562Sgshapiro#define O_SASLOPTS 0xbd 278964562Sgshapiro { "AuthOptions", O_SASLOPTS, OI_NONE }, 279064562Sgshapiro#define O_QUEUE_FILE_MODE 0xbe 279164562Sgshapiro { "QueueFileMode", O_QUEUE_FILE_MODE, OI_NONE }, 2792285303Sgshapiro#define O_DIG_ALG 0xbf 2793285303Sgshapiro { "CertFingerprintAlgorithm", O_DIG_ALG, OI_NONE }, 2794285303Sgshapiro#define O_CIPHERLIST 0xc0 279564562Sgshapiro { "CipherList", O_CIPHERLIST, OI_NONE }, 279690792Sgshapiro#define O_RANDFILE 0xc1 279764562Sgshapiro { "RandFile", O_RANDFILE, OI_NONE }, 279890792Sgshapiro#define O_TLS_SRV_OPTS 0xc2 279990792Sgshapiro { "TLSSrvOptions", O_TLS_SRV_OPTS, OI_NONE }, 280090792Sgshapiro#define O_RCPTTHROT 0xc3 280190792Sgshapiro { "BadRcptThrottle", O_RCPTTHROT, OI_SAFE }, 280290792Sgshapiro#define O_DLVR_MIN 0xc4 280390792Sgshapiro { "DeliverByMin", O_DLVR_MIN, OI_NONE }, 280490792Sgshapiro#define O_MAXQUEUECHILDREN 0xc5 280590792Sgshapiro { "MaxQueueChildren", O_MAXQUEUECHILDREN, OI_NONE }, 280690792Sgshapiro#define O_MAXRUNNERSPERQUEUE 0xc6 280790792Sgshapiro { "MaxRunnersPerQueue", O_MAXRUNNERSPERQUEUE, OI_NONE }, 280890792Sgshapiro#define O_DIRECTSUBMODIFIERS 0xc7 280990792Sgshapiro { "DirectSubmissionModifiers", O_DIRECTSUBMODIFIERS, OI_NONE }, 281090792Sgshapiro#define O_NICEQUEUERUN 0xc8 281190792Sgshapiro { "NiceQueueRun", O_NICEQUEUERUN, OI_NONE }, 281290792Sgshapiro#define O_SHMKEY 0xc9 281390792Sgshapiro { "SharedMemoryKey", O_SHMKEY, OI_NONE }, 281490792Sgshapiro#define O_SASLBITS 0xca 281590792Sgshapiro { "AuthMaxBits", O_SASLBITS, OI_NONE }, 281690792Sgshapiro#define O_MBDB 0xcb 281790792Sgshapiro { "MailboxDatabase", O_MBDB, OI_NONE }, 281890792Sgshapiro#define O_MSQ 0xcc 281990792Sgshapiro { "UseMSP", O_MSQ, OI_NONE }, 282090792Sgshapiro#define O_DELAY_LA 0xcd 282190792Sgshapiro { "DelayLA", O_DELAY_LA, OI_NONE }, 282290792Sgshapiro#define O_FASTSPLIT 0xce 282390792Sgshapiro { "FastSplit", O_FASTSPLIT, OI_NONE }, 2824168515Sgshapiro#define O_SOFTBOUNCE 0xcf 282590792Sgshapiro { "SoftBounce", O_SOFTBOUNCE, OI_NONE }, 2826168515Sgshapiro#define O_SHMKEYFILE 0xd0 282794334Sgshapiro { "SharedMemoryKeyFile", O_SHMKEYFILE, OI_NONE }, 2828132943Sgshapiro#define O_REJECTLOGINTERVAL 0xd1 2829110560Sgshapiro { "RejectLogInterval", O_REJECTLOGINTERVAL, OI_NONE }, 2830132943Sgshapiro#define O_REQUIRES_DIR_FSYNC 0xd2 2831110560Sgshapiro { "RequiresDirfsync", O_REQUIRES_DIR_FSYNC, OI_NONE }, 2832132943Sgshapiro#define O_CONNECTION_RATE_WINDOW_SIZE 0xd3 2833132943Sgshapiro { "ConnectionRateWindowSize", O_CONNECTION_RATE_WINDOW_SIZE, OI_NONE }, 2834132943Sgshapiro#define O_CRLFILE 0xd4 2835132943Sgshapiro { "CRLFile", O_CRLFILE, OI_NONE }, 2836132943Sgshapiro#define O_FALLBACKSMARTHOST 0xd5 2837132943Sgshapiro { "FallbackSmartHost", O_FALLBACKSMARTHOST, OI_NONE }, 2838132943Sgshapiro#define O_SASLREALM 0xd6 2839132943Sgshapiro { "AuthRealm", O_SASLREALM, OI_NONE }, 2840132943Sgshapiro#if _FFR_CRLPATH 2841132943Sgshapiro# define O_CRLPATH 0xd7 2842132943Sgshapiro { "CRLPath", O_CRLPATH, OI_NONE }, 2843132943Sgshapiro#endif /* _FFR_CRLPATH */ 2844168515Sgshapiro#define O_HELONAME 0xd8 2845132943Sgshapiro { "HeloName", O_HELONAME, OI_NONE }, 2846157001Sgshapiro#if _FFR_MEMSTAT 2847157001Sgshapiro# define O_REFUSELOWMEM 0xd9 2848157001Sgshapiro { "RefuseLowMem", O_REFUSELOWMEM, OI_NONE }, 2849157001Sgshapiro# define O_QUEUELOWMEM 0xda 2850157001Sgshapiro { "QueueLowMem", O_QUEUELOWMEM, OI_NONE }, 2851157001Sgshapiro# define O_MEMRESOURCE 0xdb 2852157001Sgshapiro { "MemoryResource", O_MEMRESOURCE, OI_NONE }, 2853157001Sgshapiro#endif /* _FFR_MEMSTAT */ 2854168515Sgshapiro#define O_MAXNOOPCOMMANDS 0xdc 2855157001Sgshapiro { "MaxNOOPCommands", O_MAXNOOPCOMMANDS, OI_NONE }, 2856157001Sgshapiro#if _FFR_MSG_ACCEPT 2857157001Sgshapiro# define O_MSG_ACCEPT 0xdd 2858157001Sgshapiro { "MessageAccept", O_MSG_ACCEPT, OI_NONE }, 2859157001Sgshapiro#endif /* _FFR_MSG_ACCEPT */ 2860157001Sgshapiro#if _FFR_QUEUE_RUN_PARANOIA 2861157001Sgshapiro# define O_CHK_Q_RUNNERS 0xde 2862157001Sgshapiro { "CheckQueueRunners", O_CHK_Q_RUNNERS, OI_NONE }, 2863157001Sgshapiro#endif /* _FFR_QUEUE_RUN_PARANOIA */ 2864168515Sgshapiro#if _FFR_EIGHT_BIT_ADDR_OK 2865168515Sgshapiro# if !ALLOW_255 2866168515Sgshapiro# ERROR FFR_EIGHT_BIT_ADDR_OK requires _ALLOW_255 2867168515Sgshapiro# endif /* !ALLOW_255 */ 2868168515Sgshapiro# define O_EIGHT_BIT_ADDR_OK 0xdf 2869168515Sgshapiro { "EightBitAddrOK", O_EIGHT_BIT_ADDR_OK, OI_NONE }, 2870168515Sgshapiro#endif /* _FFR_EIGHT_BIT_ADDR_OK */ 2871173340Sgshapiro#if _FFR_ADDR_TYPE_MODES 2872173340Sgshapiro# define O_ADDR_TYPE_MODES 0xe0 2873173340Sgshapiro { "AddrTypeModes", O_ADDR_TYPE_MODES, OI_NONE }, 2874173340Sgshapiro#endif /* _FFR_ADDR_TYPE_MODES */ 2875182352Sgshapiro#if _FFR_BADRCPT_SHUTDOWN 2876182352Sgshapiro# define O_RCPTSHUTD 0xe1 2877182352Sgshapiro { "BadRcptShutdown", O_RCPTSHUTD, OI_SAFE }, 2878182352Sgshapiro# define O_RCPTSHUTDG 0xe2 2879182352Sgshapiro { "BadRcptShutdownGood", O_RCPTSHUTDG, OI_SAFE }, 2880182352Sgshapiro#endif /* _FFR_BADRCPT_SHUTDOWN */ 2881285303Sgshapiro#define O_SRV_SSL_OPTIONS 0xe3 2882203004Sgshapiro { "ServerSSLOptions", O_SRV_SSL_OPTIONS, OI_NONE }, 2883285303Sgshapiro#define O_CLT_SSL_OPTIONS 0xe4 2884203004Sgshapiro { "ClientSSLOptions", O_CLT_SSL_OPTIONS, OI_NONE }, 2885285303Sgshapiro#define O_MAX_QUEUE_AGE 0xe5 2886203004Sgshapiro { "MaxQueueAge", O_MAX_QUEUE_AGE, OI_NONE }, 2887203004Sgshapiro#if _FFR_RCPTTHROTDELAY 2888203004Sgshapiro# define O_RCPTTHROTDELAY 0xe6 2889203004Sgshapiro { "BadRcptThrottleDelay", O_RCPTTHROTDELAY, OI_SAFE }, 2890203004Sgshapiro#endif /* _FFR_RCPTTHROTDELAY */ 2891223067Sgshapiro#if 0 && _FFR_QOS && defined(SOL_IP) && defined(IP_TOS) 2892223067Sgshapiro# define O_INETQOS 0xe7 /* reserved for FFR_QOS */ 2893223067Sgshapiro { "InetQoS", O_INETQOS, OI_NONE }, 2894223067Sgshapiro#endif 2895249729Sgshapiro#if STARTTLS && _FFR_FIPSMODE 2896249729Sgshapiro# define O_FIPSMODE 0xe8 2897249729Sgshapiro { "FIPSMode", O_FIPSMODE, OI_NONE }, 2898249729Sgshapiro#endif /* STARTTLS && _FFR_FIPSMODE */ 2899249729Sgshapiro#if _FFR_REJECT_NUL_BYTE 2900249729Sgshapiro# define O_REJECTNUL 0xe9 2901249729Sgshapiro { "RejectNUL", O_REJECTNUL, OI_SAFE }, 2902249729Sgshapiro#endif /* _FFR_REJECT_NUL_BYTE */ 2903285303Sgshapiro#if _FFR_BOUNCE_QUEUE 2904285303Sgshapiro# define O_BOUNCEQUEUE 0xea 2905285303Sgshapiro { "BounceQueue", O_BOUNCEQUEUE, OI_NONE }, 2906285303Sgshapiro#endif /* _FFR_BOUNCE_QUEUE */ 2907285303Sgshapiro#if _FFR_ADD_BCC 2908285303Sgshapiro# define O_ADDBCC 0xeb 2909285303Sgshapiro { "AddBcc", O_ADDBCC, OI_NONE }, 2910285303Sgshapiro#endif 2911285303Sgshapiro#define O_USECOMPRESSEDIPV6ADDRESSES 0xec 2912285303Sgshapiro { "UseCompressedIPv6Addresses", O_USECOMPRESSEDIPV6ADDRESSES, OI_NONE }, 2913132943Sgshapiro 291464562Sgshapiro { NULL, '\0', OI_NONE } 291538032Speter}; 291638032Speter 291790792Sgshapiro# define CANONIFY(val) 291890792Sgshapiro 291990792Sgshapiro# define SET_OPT_DEFAULT(opt, val) opt = val 292090792Sgshapiro 292190792Sgshapiro/* set a string option by expanding the value and assigning it */ 292290792Sgshapiro/* WARNING this belongs ONLY into a case statement! */ 292390792Sgshapiro#define SET_STRING_EXP(str) \ 2924168515Sgshapiro expand(val, exbuf, sizeof(exbuf), e); \ 292590792Sgshapiro newval = sm_pstrdup_x(exbuf); \ 292690792Sgshapiro if (str != NULL) \ 292790792Sgshapiro sm_free(str); \ 292890792Sgshapiro CANONIFY(newval); \ 292990792Sgshapiro str = newval; \ 293090792Sgshapiro break 293190792Sgshapiro 293290792Sgshapiro#define OPTNAME o->o_name == NULL ? "<unknown>" : o->o_name 293390792Sgshapiro 293438032Spetervoid 293538032Spetersetoption(opt, val, safe, sticky, e) 293638032Speter int opt; 293738032Speter char *val; 293838032Speter bool safe; 293938032Speter bool sticky; 294038032Speter register ENVELOPE *e; 294138032Speter{ 294238032Speter register char *p; 294338032Speter register struct optioninfo *o; 294438032Speter char *subopt; 294538032Speter int mid; 294638032Speter bool can_setuid = RunAsUid == 0; 294738032Speter auto char *ep; 294838032Speter char buf[50]; 294938032Speter extern bool Warn_Q_option; 295064562Sgshapiro#if _FFR_ALLOW_SASLINFO 295190792Sgshapiro extern unsigned int SubmitMode; 295264562Sgshapiro#endif /* _FFR_ALLOW_SASLINFO */ 2953168515Sgshapiro#if STARTTLS || SM_CONF_SHM 295490792Sgshapiro char *newval; 295590792Sgshapiro char exbuf[MAXLINE]; 2956168515Sgshapiro#endif /* STARTTLS || SM_CONF_SHM */ 2957285303Sgshapiro#if STARTTLS 2958285303Sgshapiro unsigned long *pssloptions = NULL; 2959285303Sgshapiro#endif 296038032Speter 296138032Speter errno = 0; 296238032Speter if (opt == ' ') 296338032Speter { 296438032Speter /* full word options */ 296538032Speter struct optioninfo *sel; 296638032Speter 296738032Speter p = strchr(val, '='); 296838032Speter if (p == NULL) 296938032Speter p = &val[strlen(val)]; 297038032Speter while (*--p == ' ') 297138032Speter continue; 297238032Speter while (*++p == ' ') 297338032Speter *p = '\0'; 297438032Speter if (p == val) 297538032Speter { 297638032Speter syserr("readcf: null option name"); 297738032Speter return; 297838032Speter } 297938032Speter if (*p == '=') 298038032Speter *p++ = '\0'; 298138032Speter while (*p == ' ') 298238032Speter p++; 298338032Speter subopt = strchr(val, '.'); 298438032Speter if (subopt != NULL) 298538032Speter *subopt++ = '\0'; 298638032Speter sel = NULL; 298738032Speter for (o = OptionTab; o->o_name != NULL; o++) 298838032Speter { 298990792Sgshapiro if (sm_strncasecmp(o->o_name, val, strlen(val)) != 0) 299038032Speter continue; 299138032Speter if (strlen(o->o_name) == strlen(val)) 299238032Speter { 299338032Speter /* completely specified -- this must be it */ 299438032Speter sel = NULL; 299538032Speter break; 299638032Speter } 299738032Speter if (sel != NULL) 299838032Speter break; 299938032Speter sel = o; 300038032Speter } 300138032Speter if (sel != NULL && o->o_name == NULL) 300238032Speter o = sel; 300338032Speter else if (o->o_name == NULL) 300438032Speter { 300538032Speter syserr("readcf: unknown option name %s", val); 300638032Speter return; 300738032Speter } 300838032Speter else if (sel != NULL) 300938032Speter { 301038032Speter syserr("readcf: ambiguous option name %s (matches %s and %s)", 301138032Speter val, sel->o_name, o->o_name); 301238032Speter return; 301338032Speter } 301438032Speter if (strlen(val) != strlen(o->o_name)) 301538032Speter { 301638032Speter int oldVerbose = Verbose; 301738032Speter 301838032Speter Verbose = 1; 301938032Speter message("Option %s used as abbreviation for %s", 302038032Speter val, o->o_name); 302138032Speter Verbose = oldVerbose; 302238032Speter } 302338032Speter opt = o->o_code; 302438032Speter val = p; 302538032Speter } 302638032Speter else 302738032Speter { 302838032Speter for (o = OptionTab; o->o_name != NULL; o++) 302938032Speter { 303038032Speter if (o->o_code == opt) 303138032Speter break; 303238032Speter } 303390792Sgshapiro if (o->o_name == NULL) 303490792Sgshapiro { 303590792Sgshapiro syserr("readcf: unknown option name 0x%x", opt & 0xff); 303690792Sgshapiro return; 303790792Sgshapiro } 303838032Speter subopt = NULL; 303938032Speter } 304038032Speter 304164562Sgshapiro if (subopt != NULL && !bitset(OI_SUBOPT, o->o_flags)) 304264562Sgshapiro { 304364562Sgshapiro if (tTd(37, 1)) 304490792Sgshapiro sm_dprintf("setoption: %s does not support suboptions, ignoring .%s\n", 304590792Sgshapiro OPTNAME, subopt); 304664562Sgshapiro subopt = NULL; 304764562Sgshapiro } 304864562Sgshapiro 304938032Speter if (tTd(37, 1)) 305038032Speter { 305190792Sgshapiro sm_dprintf(isascii(opt) && isprint(opt) ? 305290792Sgshapiro "setoption %s (%c)%s%s=" : 305390792Sgshapiro "setoption %s (0x%x)%s%s=", 305490792Sgshapiro OPTNAME, opt, subopt == NULL ? "" : ".", 305590792Sgshapiro subopt == NULL ? "" : subopt); 3056132943Sgshapiro xputs(sm_debug_file(), val); 305738032Speter } 305838032Speter 305938032Speter /* 306038032Speter ** See if this option is preset for us. 306138032Speter */ 306238032Speter 306338032Speter if (!sticky && bitnset(opt, StickyOpt)) 306438032Speter { 306538032Speter if (tTd(37, 1)) 306690792Sgshapiro sm_dprintf(" (ignored)\n"); 306738032Speter return; 306838032Speter } 306938032Speter 307038032Speter /* 307138032Speter ** Check to see if this option can be specified by this user. 307238032Speter */ 307338032Speter 307438032Speter if (!safe && RealUid == 0) 307590792Sgshapiro safe = true; 307664562Sgshapiro if (!safe && !bitset(OI_SAFE, o->o_flags)) 307738032Speter { 307838032Speter if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) 307938032Speter { 308064562Sgshapiro int dp; 308164562Sgshapiro 308238032Speter if (tTd(37, 1)) 308390792Sgshapiro sm_dprintf(" (unsafe)"); 308490792Sgshapiro dp = drop_privileges(true); 308564562Sgshapiro setstat(dp); 308638032Speter } 308738032Speter } 308838032Speter if (tTd(37, 1)) 308990792Sgshapiro sm_dprintf("\n"); 309038032Speter 309138032Speter switch (opt & 0xff) 309238032Speter { 309338032Speter case '7': /* force seven-bit input */ 309438032Speter SevenBitInput = atobool(val); 309538032Speter break; 309638032Speter 309777349Sgshapiro case '8': /* handling of 8-bit input */ 309838032Speter#if MIME8TO7 309938032Speter switch (*val) 310038032Speter { 310190792Sgshapiro case 'p': /* pass 8 bit, convert MIME */ 310290792Sgshapiro MimeMode = MM_CVTMIME|MM_PASS8BIT; 310390792Sgshapiro break; 310490792Sgshapiro 310538032Speter case 'm': /* convert 8-bit, convert MIME */ 310638032Speter MimeMode = MM_CVTMIME|MM_MIME8BIT; 310738032Speter break; 310838032Speter 310938032Speter case 's': /* strict adherence */ 311038032Speter MimeMode = MM_CVTMIME; 311138032Speter break; 311238032Speter 311364562Sgshapiro# if 0 311438032Speter case 'r': /* reject 8-bit, don't convert MIME */ 311538032Speter MimeMode = 0; 311638032Speter break; 311738032Speter 311838032Speter case 'j': /* "just send 8" */ 311938032Speter MimeMode = MM_PASS8BIT; 312038032Speter break; 312138032Speter 312238032Speter case 'a': /* encode 8 bit if available */ 312338032Speter MimeMode = MM_MIME8BIT|MM_PASS8BIT|MM_CVTMIME; 312438032Speter break; 312538032Speter 312638032Speter case 'c': /* convert 8 bit to MIME, never 7 bit */ 312738032Speter MimeMode = MM_MIME8BIT; 312838032Speter break; 312964562Sgshapiro# endif /* 0 */ 313038032Speter 313138032Speter default: 313238032Speter syserr("Unknown 8-bit mode %c", *val); 313390792Sgshapiro finis(false, true, EX_USAGE); 313438032Speter } 313577349Sgshapiro#else /* MIME8TO7 */ 313690792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 313790792Sgshapiro "Warning: Option: %s requires MIME8TO7 support\n", 313890792Sgshapiro OPTNAME); 313977349Sgshapiro#endif /* MIME8TO7 */ 314038032Speter break; 314138032Speter 314238032Speter case 'A': /* set default alias file */ 314338032Speter if (val[0] == '\0') 314490792Sgshapiro { 314590792Sgshapiro char *al; 314690792Sgshapiro 314790792Sgshapiro SET_OPT_DEFAULT(al, "aliases"); 314890792Sgshapiro setalias(al); 314990792Sgshapiro } 315038032Speter else 315138032Speter setalias(val); 315238032Speter break; 315338032Speter 315438032Speter case 'a': /* look N minutes for "@:@" in alias file */ 315538032Speter if (val[0] == '\0') 315690792Sgshapiro SafeAlias = 5 MINUTES; 315738032Speter else 315838032Speter SafeAlias = convtime(val, 'm'); 315938032Speter break; 316038032Speter 316138032Speter case 'B': /* substitution for blank character */ 316238032Speter SpaceSub = val[0]; 316338032Speter if (SpaceSub == '\0') 316438032Speter SpaceSub = ' '; 316538032Speter break; 316638032Speter 316738032Speter case 'b': /* min blocks free on queue fs/max msg size */ 316838032Speter p = strchr(val, '/'); 316938032Speter if (p != NULL) 317038032Speter { 317138032Speter *p++ = '\0'; 317238032Speter MaxMessageSize = atol(p); 317338032Speter } 317438032Speter MinBlocksFree = atol(val); 317538032Speter break; 317638032Speter 317738032Speter case 'c': /* don't connect to "expensive" mailers */ 317838032Speter NoConnect = atobool(val); 317938032Speter break; 318038032Speter 318138032Speter case 'C': /* checkpoint every N addresses */ 3182132943Sgshapiro if (safe || CheckpointInterval > atoi(val)) 3183132943Sgshapiro CheckpointInterval = atoi(val); 318438032Speter break; 318538032Speter 318638032Speter case 'd': /* delivery mode */ 318738032Speter switch (*val) 318838032Speter { 318938032Speter case '\0': 319064562Sgshapiro set_delivery_mode(SM_DELIVER, e); 319138032Speter break; 319238032Speter 319338032Speter case SM_QUEUE: /* queue only */ 319438032Speter case SM_DEFER: /* queue only and defer map lookups */ 319538032Speter case SM_DELIVER: /* do everything */ 319638032Speter case SM_FORK: /* fork after verification */ 3197157001Sgshapiro#if _FFR_DM_ONE 3198157001Sgshapiro /* deliver first TA in background, then queue */ 3199157001Sgshapiro case SM_DM_ONE: 3200157001Sgshapiro#endif /* _FFR_DM_ONE */ 320164562Sgshapiro set_delivery_mode(*val, e); 320238032Speter break; 320338032Speter 3204285303Sgshapiro#if _FFR_PROXY 3205285303Sgshapiro case SM_PROXY_REQ: 3206285303Sgshapiro set_delivery_mode(*val, e); 3207285303Sgshapiro break; 3208285303Sgshapiro#endif /* _FFR_PROXY */ 3209223067Sgshapiro 321038032Speter default: 321138032Speter syserr("Unknown delivery mode %c", *val); 321290792Sgshapiro finis(false, true, EX_USAGE); 321338032Speter } 321438032Speter break; 321538032Speter 321638032Speter case 'E': /* error message header/header file */ 321738032Speter if (*val != '\0') 321838032Speter ErrMsgFile = newstr(val); 321938032Speter break; 322038032Speter 322138032Speter case 'e': /* set error processing mode */ 322238032Speter switch (*val) 322338032Speter { 322438032Speter case EM_QUIET: /* be silent about it */ 322538032Speter case EM_MAIL: /* mail back */ 322638032Speter case EM_BERKNET: /* do berknet error processing */ 322738032Speter case EM_WRITE: /* write back (or mail) */ 322838032Speter case EM_PRINT: /* print errors normally (default) */ 322938032Speter e->e_errormode = *val; 323038032Speter break; 323138032Speter } 323238032Speter break; 323338032Speter 323438032Speter case 'F': /* file mode */ 323538032Speter FileMode = atooct(val) & 0777; 323638032Speter break; 323738032Speter 323838032Speter case 'f': /* save Unix-style From lines on front */ 323938032Speter SaveFrom = atobool(val); 324038032Speter break; 324138032Speter 324238032Speter case 'G': /* match recipients against GECOS field */ 324338032Speter MatchGecos = atobool(val); 324438032Speter break; 324538032Speter 324638032Speter case 'g': /* default gid */ 324738032Speter g_opt: 324838032Speter if (isascii(*val) && isdigit(*val)) 324938032Speter DefGid = atoi(val); 325038032Speter else 325138032Speter { 325238032Speter register struct group *gr; 325338032Speter 325438032Speter DefGid = -1; 325538032Speter gr = getgrnam(val); 325638032Speter if (gr == NULL) 325738032Speter syserr("readcf: option %c: unknown group %s", 325838032Speter opt, val); 325938032Speter else 326038032Speter DefGid = gr->gr_gid; 326138032Speter } 326238032Speter break; 326338032Speter 326438032Speter case 'H': /* help file */ 326538032Speter if (val[0] == '\0') 326690792Sgshapiro { 326790792Sgshapiro SET_OPT_DEFAULT(HelpFile, "helpfile"); 326890792Sgshapiro } 326938032Speter else 327073188Sgshapiro { 327190792Sgshapiro CANONIFY(val); 327238032Speter HelpFile = newstr(val); 327373188Sgshapiro } 327438032Speter break; 327538032Speter 327638032Speter case 'h': /* maximum hop count */ 327738032Speter MaxHopCount = atoi(val); 327838032Speter break; 327938032Speter 328038032Speter case 'I': /* use internet domain name server */ 328138032Speter#if NAMED_BIND 328238032Speter for (p = val; *p != 0; ) 328338032Speter { 328438032Speter bool clearmode; 328538032Speter char *q; 328638032Speter struct resolverflags *rfp; 328738032Speter 328838032Speter while (*p == ' ') 328938032Speter p++; 329038032Speter if (*p == '\0') 329138032Speter break; 329290792Sgshapiro clearmode = false; 329338032Speter if (*p == '-') 329490792Sgshapiro clearmode = true; 329538032Speter else if (*p != '+') 329638032Speter p--; 329738032Speter p++; 329838032Speter q = p; 329938032Speter while (*p != '\0' && !(isascii(*p) && isspace(*p))) 330038032Speter p++; 330138032Speter if (*p != '\0') 330238032Speter *p++ = '\0'; 330390792Sgshapiro if (sm_strcasecmp(q, "HasWildcardMX") == 0) 330438032Speter { 330538032Speter HasWildcardMX = !clearmode; 330638032Speter continue; 330738032Speter } 330873188Sgshapiro if (sm_strcasecmp(q, "WorkAroundBrokenAAAA") == 0) 330973188Sgshapiro { 331073188Sgshapiro WorkAroundBrokenAAAA = !clearmode; 331173188Sgshapiro continue; 331273188Sgshapiro } 331338032Speter for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++) 331438032Speter { 331590792Sgshapiro if (sm_strcasecmp(q, rfp->rf_name) == 0) 331638032Speter break; 331738032Speter } 331838032Speter if (rfp->rf_name == NULL) 331938032Speter syserr("readcf: I option value %s unrecognized", q); 332038032Speter else if (clearmode) 332138032Speter _res.options &= ~rfp->rf_bits; 332238032Speter else 332338032Speter _res.options |= rfp->rf_bits; 332438032Speter } 332538032Speter if (tTd(8, 2)) 332690792Sgshapiro sm_dprintf("_res.options = %x, HasWildcardMX = %d\n", 332790792Sgshapiro (unsigned int) _res.options, HasWildcardMX); 332864562Sgshapiro#else /* NAMED_BIND */ 332938032Speter usrerr("name server (I option) specified but BIND not compiled in"); 333064562Sgshapiro#endif /* NAMED_BIND */ 333138032Speter break; 333238032Speter 333338032Speter case 'i': /* ignore dot lines in message */ 333438032Speter IgnrDot = atobool(val); 333538032Speter break; 333638032Speter 333738032Speter case 'j': /* send errors in MIME (RFC 1341) format */ 333838032Speter SendMIMEErrors = atobool(val); 333938032Speter break; 334038032Speter 334138032Speter case 'J': /* .forward search path */ 334290792Sgshapiro CANONIFY(val); 334338032Speter ForwardPath = newstr(val); 334438032Speter break; 334538032Speter 334638032Speter case 'k': /* connection cache size */ 334738032Speter MaxMciCache = atoi(val); 334838032Speter if (MaxMciCache < 0) 334938032Speter MaxMciCache = 0; 335038032Speter break; 335138032Speter 335238032Speter case 'K': /* connection cache timeout */ 335338032Speter MciCacheTimeout = convtime(val, 'm'); 335438032Speter break; 335538032Speter 335638032Speter case 'l': /* use Errors-To: header */ 335738032Speter UseErrorsTo = atobool(val); 335838032Speter break; 335938032Speter 336038032Speter case 'L': /* log level */ 336138032Speter if (safe || LogLevel < atoi(val)) 336238032Speter LogLevel = atoi(val); 336338032Speter break; 336438032Speter 336538032Speter case 'M': /* define macro */ 336690792Sgshapiro sticky = false; 336790792Sgshapiro mid = macid_parse(val, &ep); 336871345Sgshapiro if (mid == 0) 336971345Sgshapiro break; 337038032Speter p = newstr(ep); 337138032Speter if (!safe) 3372120256Sgshapiro cleanstrcpy(p, p, strlen(p) + 1); 337390792Sgshapiro macdefine(&CurEnv->e_macro, A_TEMP, mid, p); 337438032Speter break; 337538032Speter 337638032Speter case 'm': /* send to me too */ 337738032Speter MeToo = atobool(val); 337838032Speter break; 337938032Speter 338038032Speter case 'n': /* validate RHS in newaliases */ 338138032Speter CheckAliases = atobool(val); 338238032Speter break; 338338032Speter 338438032Speter /* 'N' available -- was "net name" */ 338538032Speter 338638032Speter case 'O': /* daemon options */ 338764562Sgshapiro if (!setdaemonoptions(val)) 338864562Sgshapiro syserr("too many daemons defined (%d max)", MAXDAEMONS); 338938032Speter break; 339038032Speter 339138032Speter case 'o': /* assume old style headers */ 339238032Speter if (atobool(val)) 339338032Speter CurEnv->e_flags |= EF_OLDSTYLE; 339438032Speter else 339538032Speter CurEnv->e_flags &= ~EF_OLDSTYLE; 339638032Speter break; 339738032Speter 339838032Speter case 'p': /* select privacy level */ 339938032Speter p = val; 340038032Speter for (;;) 340138032Speter { 340238032Speter register struct prival *pv; 340338032Speter extern struct prival PrivacyValues[]; 340438032Speter 340538032Speter while (isascii(*p) && (isspace(*p) || ispunct(*p))) 340638032Speter p++; 340738032Speter if (*p == '\0') 340838032Speter break; 340938032Speter val = p; 341038032Speter while (isascii(*p) && isalnum(*p)) 341138032Speter p++; 341238032Speter if (*p != '\0') 341338032Speter *p++ = '\0'; 341438032Speter 341538032Speter for (pv = PrivacyValues; pv->pv_name != NULL; pv++) 341638032Speter { 341790792Sgshapiro if (sm_strcasecmp(val, pv->pv_name) == 0) 341838032Speter break; 341938032Speter } 342038032Speter if (pv->pv_name == NULL) 342138032Speter syserr("readcf: Op line: %s unrecognized", val); 342271345Sgshapiro else 342371345Sgshapiro PrivacyFlags |= pv->pv_flag; 342438032Speter } 342590792Sgshapiro sticky = false; 342638032Speter break; 342738032Speter 342838032Speter case 'P': /* postmaster copy address for returned mail */ 342938032Speter PostMasterCopy = newstr(val); 343038032Speter break; 343138032Speter 343238032Speter case 'q': /* slope of queue only function */ 343338032Speter QueueFactor = atoi(val); 343438032Speter break; 343538032Speter 343638032Speter case 'Q': /* queue directory */ 343738032Speter if (val[0] == '\0') 343866494Sgshapiro { 343938032Speter QueueDir = "mqueue"; 344066494Sgshapiro } 344138032Speter else 344266494Sgshapiro { 344338032Speter QueueDir = newstr(val); 344466494Sgshapiro } 344538032Speter if (RealUid != 0 && !safe) 344690792Sgshapiro Warn_Q_option = true; 344738032Speter break; 344838032Speter 344938032Speter case 'R': /* don't prune routes */ 345038032Speter DontPruneRoutes = atobool(val); 345138032Speter break; 345238032Speter 345338032Speter case 'r': /* read timeout */ 345438032Speter if (subopt == NULL) 345564562Sgshapiro inittimeouts(val, sticky); 345638032Speter else 345764562Sgshapiro settimeout(subopt, val, sticky); 345838032Speter break; 345938032Speter 346038032Speter case 'S': /* status file */ 346138032Speter if (val[0] == '\0') 346290792Sgshapiro { 346390792Sgshapiro SET_OPT_DEFAULT(StatFile, "statistics"); 346490792Sgshapiro } 346538032Speter else 346673188Sgshapiro { 346790792Sgshapiro CANONIFY(val); 346838032Speter StatFile = newstr(val); 346973188Sgshapiro } 347038032Speter break; 347138032Speter 347238032Speter case 's': /* be super safe, even if expensive */ 347390792Sgshapiro if (tolower(*val) == 'i') 347490792Sgshapiro SuperSafe = SAFE_INTERACTIVE; 3475132943Sgshapiro else if (tolower(*val) == 'p') 3476132943Sgshapiro#if MILTER 3477132943Sgshapiro SuperSafe = SAFE_REALLY_POSTMILTER; 3478132943Sgshapiro#else /* MILTER */ 3479132943Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3480132943Sgshapiro "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n"); 3481132943Sgshapiro#endif /* MILTER */ 348290792Sgshapiro else 348390792Sgshapiro SuperSafe = atobool(val) ? SAFE_REALLY : SAFE_NO; 348438032Speter break; 348538032Speter 348638032Speter case 'T': /* queue timeout */ 348738032Speter p = strchr(val, '/'); 348838032Speter if (p != NULL) 348938032Speter { 349038032Speter *p++ = '\0'; 349164562Sgshapiro settimeout("queuewarn", p, sticky); 349238032Speter } 349364562Sgshapiro settimeout("queuereturn", val, sticky); 349438032Speter break; 349538032Speter 349638032Speter case 't': /* time zone name */ 349738032Speter TimeZoneSpec = newstr(val); 349838032Speter break; 349938032Speter 350038032Speter case 'U': /* location of user database */ 350138032Speter UdbSpec = newstr(val); 350238032Speter break; 350338032Speter 350438032Speter case 'u': /* set default uid */ 350538032Speter for (p = val; *p != '\0'; p++) 350638032Speter { 350794334Sgshapiro# if _FFR_DOTTED_USERNAMES 350890792Sgshapiro if (*p == '/' || *p == ':') 350994334Sgshapiro# else /* _FFR_DOTTED_USERNAMES */ 351038032Speter if (*p == '.' || *p == '/' || *p == ':') 351194334Sgshapiro# endif /* _FFR_DOTTED_USERNAMES */ 351238032Speter { 351338032Speter *p++ = '\0'; 351438032Speter break; 351538032Speter } 351638032Speter } 351738032Speter if (isascii(*val) && isdigit(*val)) 351838032Speter { 351938032Speter DefUid = atoi(val); 352038032Speter setdefuser(); 352138032Speter } 352238032Speter else 352338032Speter { 352438032Speter register struct passwd *pw; 352538032Speter 352638032Speter DefUid = -1; 352738032Speter pw = sm_getpwnam(val); 352838032Speter if (pw == NULL) 352971345Sgshapiro { 353038032Speter syserr("readcf: option u: unknown user %s", val); 353171345Sgshapiro break; 353271345Sgshapiro } 353338032Speter else 353438032Speter { 353538032Speter DefUid = pw->pw_uid; 353638032Speter DefGid = pw->pw_gid; 353738032Speter DefUser = newstr(pw->pw_name); 353838032Speter } 353938032Speter } 354038032Speter 354190792Sgshapiro# ifdef UID_MAX 354238032Speter if (DefUid > UID_MAX) 354338032Speter { 354438032Speter syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored", 354590792Sgshapiro (long)DefUid, (long)UID_MAX); 354671345Sgshapiro break; 354738032Speter } 354890792Sgshapiro# endif /* UID_MAX */ 354938032Speter 355038032Speter /* handle the group if it is there */ 355138032Speter if (*p == '\0') 355238032Speter break; 355338032Speter val = p; 355438032Speter goto g_opt; 355538032Speter 355638032Speter case 'V': /* fallback MX host */ 355738032Speter if (val[0] != '\0') 3558132943Sgshapiro FallbackMX = newstr(val); 355938032Speter break; 356038032Speter 356138032Speter case 'v': /* run in verbose mode */ 356238032Speter Verbose = atobool(val) ? 1 : 0; 356338032Speter break; 356438032Speter 356538032Speter case 'w': /* if we are best MX, try host directly */ 356638032Speter TryNullMXList = atobool(val); 356738032Speter break; 356838032Speter 356938032Speter /* 'W' available -- was wizard password */ 357038032Speter 357138032Speter case 'x': /* load avg at which to auto-queue msgs */ 357238032Speter QueueLA = atoi(val); 357338032Speter break; 357438032Speter 357590792Sgshapiro case 'X': /* load avg at which to auto-reject connections */ 357638032Speter RefuseLA = atoi(val); 357738032Speter break; 357838032Speter 357990792Sgshapiro case O_DELAY_LA: /* load avg at which to delay connections */ 358090792Sgshapiro DelayLA = atoi(val); 358190792Sgshapiro break; 358290792Sgshapiro 358338032Speter case 'y': /* work recipient factor */ 358438032Speter WkRecipFact = atoi(val); 358538032Speter break; 358638032Speter 358738032Speter case 'Y': /* fork jobs during queue runs */ 358838032Speter ForkQueueRuns = atobool(val); 358938032Speter break; 359038032Speter 359138032Speter case 'z': /* work message class factor */ 359238032Speter WkClassFact = atoi(val); 359338032Speter break; 359438032Speter 359538032Speter case 'Z': /* work time factor */ 359638032Speter WkTimeFact = atoi(val); 359738032Speter break; 359838032Speter 359964562Sgshapiro 360094334Sgshapiro#if _FFR_QUEUE_GROUP_SORTORDER 360194334Sgshapiro /* coordinate this with makequeue() */ 360294334Sgshapiro#endif /* _FFR_QUEUE_GROUP_SORTORDER */ 360338032Speter case O_QUEUESORTORD: /* queue sorting order */ 360438032Speter switch (*val) 360538032Speter { 360690792Sgshapiro case 'f': /* File Name */ 360790792Sgshapiro case 'F': 360890792Sgshapiro QueueSortOrder = QSO_BYFILENAME; 360990792Sgshapiro break; 361090792Sgshapiro 361138032Speter case 'h': /* Host first */ 361238032Speter case 'H': 361364562Sgshapiro QueueSortOrder = QSO_BYHOST; 361438032Speter break; 361538032Speter 361690792Sgshapiro case 'm': /* Modification time */ 361790792Sgshapiro case 'M': 361890792Sgshapiro QueueSortOrder = QSO_BYMODTIME; 361990792Sgshapiro break; 362090792Sgshapiro 362138032Speter case 'p': /* Priority order */ 362238032Speter case 'P': 362364562Sgshapiro QueueSortOrder = QSO_BYPRIORITY; 362438032Speter break; 362538032Speter 362638032Speter case 't': /* Submission time */ 362738032Speter case 'T': 362864562Sgshapiro QueueSortOrder = QSO_BYTIME; 362938032Speter break; 363038032Speter 363190792Sgshapiro case 'r': /* Random */ 363290792Sgshapiro case 'R': 363390792Sgshapiro QueueSortOrder = QSO_RANDOM; 363464562Sgshapiro break; 363564562Sgshapiro 363690792Sgshapiro#if _FFR_RHS 363790792Sgshapiro case 's': /* Shuffled host name */ 363890792Sgshapiro case 'S': 363990792Sgshapiro QueueSortOrder = QSO_BYSHUFFLE; 364090792Sgshapiro break; 364190792Sgshapiro#endif /* _FFR_RHS */ 364290792Sgshapiro 3643132943Sgshapiro case 'n': /* none */ 3644132943Sgshapiro case 'N': 3645132943Sgshapiro QueueSortOrder = QSO_NONE; 364664562Sgshapiro break; 364764562Sgshapiro 364864562Sgshapiro default: 3649132943Sgshapiro syserr("Invalid queue sort order \"%s\"", val); 365064562Sgshapiro } 365164562Sgshapiro break; 365264562Sgshapiro 365338032Speter case O_HOSTSFILE: /* pathname of /etc/hosts file */ 365490792Sgshapiro CANONIFY(val); 365538032Speter HostsFile = newstr(val); 365638032Speter break; 365738032Speter 365838032Speter case O_MQA: /* minimum queue age between deliveries */ 365938032Speter MinQueueAge = convtime(val, 'm'); 366038032Speter break; 366138032Speter 3662203004Sgshapiro case O_MAX_QUEUE_AGE: 3663203004Sgshapiro MaxQueueAge = convtime(val, 'm'); 3664203004Sgshapiro break; 3665203004Sgshapiro 366638032Speter case O_DEFCHARSET: /* default character set for mimefying */ 366790792Sgshapiro DefaultCharSet = newstr(denlstring(val, true, true)); 366838032Speter break; 366938032Speter 367038032Speter case O_SSFILE: /* service switch file */ 367190792Sgshapiro CANONIFY(val); 367238032Speter ServiceSwitchFile = newstr(val); 367338032Speter break; 367438032Speter 367538032Speter case O_DIALDELAY: /* delay for dial-on-demand operation */ 367638032Speter DialDelay = convtime(val, 's'); 367738032Speter break; 367838032Speter 367938032Speter case O_NORCPTACTION: /* what to do if no recipient */ 368090792Sgshapiro if (sm_strcasecmp(val, "none") == 0) 368138032Speter NoRecipientAction = NRA_NO_ACTION; 368290792Sgshapiro else if (sm_strcasecmp(val, "add-to") == 0) 368338032Speter NoRecipientAction = NRA_ADD_TO; 368490792Sgshapiro else if (sm_strcasecmp(val, "add-apparently-to") == 0) 368538032Speter NoRecipientAction = NRA_ADD_APPARENTLY_TO; 368690792Sgshapiro else if (sm_strcasecmp(val, "add-bcc") == 0) 368738032Speter NoRecipientAction = NRA_ADD_BCC; 368890792Sgshapiro else if (sm_strcasecmp(val, "add-to-undisclosed") == 0) 368938032Speter NoRecipientAction = NRA_ADD_TO_UNDISCLOSED; 369038032Speter else 369138032Speter syserr("Invalid NoRecipientAction: %s", val); 369238032Speter break; 369338032Speter 369438032Speter case O_SAFEFILEENV: /* chroot() environ for writing to files */ 369594334Sgshapiro if (*val == '\0') 369694334Sgshapiro break; 369794334Sgshapiro 369894334Sgshapiro /* strip trailing slashes */ 369994334Sgshapiro p = val + strlen(val) - 1; 370094334Sgshapiro while (p >= val && *p == '/') 370194334Sgshapiro *p-- = '\0'; 370294334Sgshapiro 370394334Sgshapiro if (*val == '\0') 370494334Sgshapiro break; 370594334Sgshapiro 370638032Speter SafeFileEnv = newstr(val); 370738032Speter break; 370838032Speter 370938032Speter case O_MAXMSGSIZE: /* maximum message size */ 371038032Speter MaxMessageSize = atol(val); 371138032Speter break; 371238032Speter 371338032Speter case O_COLONOKINADDR: /* old style handling of colon addresses */ 371438032Speter ColonOkInAddr = atobool(val); 371538032Speter break; 371638032Speter 371738032Speter case O_MAXQUEUERUN: /* max # of jobs in a single queue run */ 371890792Sgshapiro MaxQueueRun = atoi(val); 371938032Speter break; 372038032Speter 372138032Speter case O_MAXCHILDREN: /* max # of children of daemon */ 372238032Speter MaxChildren = atoi(val); 372338032Speter break; 372438032Speter 372590792Sgshapiro case O_MAXQUEUECHILDREN: /* max # of children of daemon */ 372690792Sgshapiro MaxQueueChildren = atoi(val); 372790792Sgshapiro break; 372890792Sgshapiro 372990792Sgshapiro case O_MAXRUNNERSPERQUEUE: /* max # runners in a queue group */ 373090792Sgshapiro MaxRunnersPerQueue = atoi(val); 373190792Sgshapiro break; 373290792Sgshapiro 373390792Sgshapiro case O_NICEQUEUERUN: /* nice queue runs */ 373490792Sgshapiro#if !HASNICE 373590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 373690792Sgshapiro "Warning: NiceQueueRun set on system that doesn't support nice()\n"); 373790792Sgshapiro#endif /* !HASNICE */ 373890792Sgshapiro 373990792Sgshapiro /* XXX do we want to check the range? > 0 ? */ 374090792Sgshapiro NiceQueueRun = atoi(val); 374190792Sgshapiro break; 374290792Sgshapiro 374394334Sgshapiro case O_SHMKEY: /* shared memory key */ 374490792Sgshapiro#if SM_CONF_SHM 374590792Sgshapiro ShmKey = atol(val); 374690792Sgshapiro#else /* SM_CONF_SHM */ 374790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 374890792Sgshapiro "Warning: Option: %s requires shared memory support (-DSM_CONF_SHM)\n", 374990792Sgshapiro OPTNAME); 375090792Sgshapiro#endif /* SM_CONF_SHM */ 375190792Sgshapiro break; 375290792Sgshapiro 375394334Sgshapiro case O_SHMKEYFILE: /* shared memory key file */ 3754168515Sgshapiro#if SM_CONF_SHM 375598841Sgshapiro SET_STRING_EXP(ShmKeyFile); 3756168515Sgshapiro#else /* SM_CONF_SHM */ 375794334Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 375894334Sgshapiro "Warning: Option: %s requires shared memory support (-DSM_CONF_SHM)\n", 375994334Sgshapiro OPTNAME); 376098841Sgshapiro break; 3761168515Sgshapiro#endif /* SM_CONF_SHM */ 376294334Sgshapiro 376364562Sgshapiro#if _FFR_MAX_FORWARD_ENTRIES 376464562Sgshapiro case O_MAXFORWARD: /* max # of forward entries */ 376564562Sgshapiro MaxForwardEntries = atoi(val); 376664562Sgshapiro break; 376764562Sgshapiro#endif /* _FFR_MAX_FORWARD_ENTRIES */ 376864562Sgshapiro 376938032Speter case O_KEEPCNAMES: /* don't expand CNAME records */ 377038032Speter DontExpandCnames = atobool(val); 377138032Speter break; 377238032Speter 377338032Speter case O_MUSTQUOTE: /* must quote these characters in phrases */ 3774168515Sgshapiro (void) sm_strlcpy(buf, "@,;:\\()[]", sizeof(buf)); 3775168515Sgshapiro if (strlen(val) < sizeof(buf) - 10) 3776168515Sgshapiro (void) sm_strlcat(buf, val, sizeof(buf)); 377764562Sgshapiro else 377890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 377990792Sgshapiro "Warning: MustQuoteChars too long, ignored.\n"); 378038032Speter MustQuoteChars = newstr(buf); 378138032Speter break; 378238032Speter 378338032Speter case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */ 378438032Speter SmtpGreeting = newstr(munchstring(val, NULL, '\0')); 378538032Speter break; 378638032Speter 378738032Speter case O_UNIXFROM: /* UNIX From_ line (old $l macro) */ 378838032Speter UnixFromLine = newstr(munchstring(val, NULL, '\0')); 378938032Speter break; 379038032Speter 379138032Speter case O_OPCHARS: /* operator characters (old $o macro) */ 379264562Sgshapiro if (OperatorChars != NULL) 379390792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 379490792Sgshapiro "Warning: OperatorChars is being redefined.\n It should only be set before ruleset definitions.\n"); 379538032Speter OperatorChars = newstr(munchstring(val, NULL, '\0')); 379638032Speter break; 379738032Speter 379838032Speter case O_DONTINITGRPS: /* don't call initgroups(3) */ 379938032Speter DontInitGroups = atobool(val); 380038032Speter break; 380138032Speter 380238032Speter case O_SLFH: /* make sure from fits on one line */ 380338032Speter SingleLineFromHeader = atobool(val); 380438032Speter break; 380538032Speter 380638032Speter case O_ABH: /* allow HELO commands with syntax errors */ 380738032Speter AllowBogusHELO = atobool(val); 380838032Speter break; 380938032Speter 381038032Speter case O_CONNTHROT: /* connection rate throttle */ 381138032Speter ConnRateThrottle = atoi(val); 381238032Speter break; 381338032Speter 381438032Speter case O_UGW: /* group writable files are unsafe */ 381538032Speter if (!atobool(val)) 381664562Sgshapiro { 381764562Sgshapiro setbitn(DBS_GROUPWRITABLEFORWARDFILESAFE, 381864562Sgshapiro DontBlameSendmail); 381964562Sgshapiro setbitn(DBS_GROUPWRITABLEINCLUDEFILESAFE, 382064562Sgshapiro DontBlameSendmail); 382164562Sgshapiro } 382238032Speter break; 382338032Speter 382438032Speter case O_DBLBOUNCE: /* address to which to send double bounces */ 382590792Sgshapiro DoubleBounceAddr = newstr(val); 382638032Speter break; 382738032Speter 382838032Speter case O_HSDIR: /* persistent host status directory */ 382938032Speter if (val[0] != '\0') 383073188Sgshapiro { 383190792Sgshapiro CANONIFY(val); 383238032Speter HostStatDir = newstr(val); 383373188Sgshapiro } 383438032Speter break; 383538032Speter 383638032Speter case O_SINGTHREAD: /* single thread deliveries (requires hsdir) */ 383738032Speter SingleThreadDelivery = atobool(val); 383838032Speter break; 383938032Speter 384038032Speter case O_RUNASUSER: /* run bulk of code as this user */ 384138032Speter for (p = val; *p != '\0'; p++) 384238032Speter { 384394334Sgshapiro# if _FFR_DOTTED_USERNAMES 384490792Sgshapiro if (*p == '/' || *p == ':') 384594334Sgshapiro# else /* _FFR_DOTTED_USERNAMES */ 384638032Speter if (*p == '.' || *p == '/' || *p == ':') 384794334Sgshapiro# endif /* _FFR_DOTTED_USERNAMES */ 384838032Speter { 384938032Speter *p++ = '\0'; 385038032Speter break; 385138032Speter } 385238032Speter } 385338032Speter if (isascii(*val) && isdigit(*val)) 385438032Speter { 385538032Speter if (can_setuid) 385638032Speter RunAsUid = atoi(val); 385738032Speter } 385838032Speter else 385938032Speter { 386038032Speter register struct passwd *pw; 386138032Speter 386238032Speter pw = sm_getpwnam(val); 386338032Speter if (pw == NULL) 386471345Sgshapiro { 386538032Speter syserr("readcf: option RunAsUser: unknown user %s", val); 386671345Sgshapiro break; 386771345Sgshapiro } 386838032Speter else if (can_setuid) 386938032Speter { 387038032Speter if (*p == '\0') 387138032Speter RunAsUserName = newstr(val); 387238032Speter RunAsUid = pw->pw_uid; 387338032Speter RunAsGid = pw->pw_gid; 387438032Speter } 387590792Sgshapiro else if (EffGid == pw->pw_gid) 387690792Sgshapiro RunAsGid = pw->pw_gid; 387790792Sgshapiro else if (UseMSP && *p == '\0') 387890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3879285303Sgshapiro "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", 3880285303Sgshapiro (long) EffGid, 3881285303Sgshapiro (long) pw->pw_gid); 388238032Speter } 388390792Sgshapiro# ifdef UID_MAX 388438032Speter if (RunAsUid > UID_MAX) 388538032Speter { 388638032Speter syserr("readcf: option RunAsUser: uid value (%ld) > UID_MAX (%ld); ignored", 388771345Sgshapiro (long) RunAsUid, (long) UID_MAX); 388871345Sgshapiro break; 388938032Speter } 389090792Sgshapiro# endif /* UID_MAX */ 389138032Speter if (*p != '\0') 389238032Speter { 389338032Speter if (isascii(*p) && isdigit(*p)) 389438032Speter { 389590792Sgshapiro gid_t runasgid; 389690792Sgshapiro 389790792Sgshapiro runasgid = (gid_t) atoi(p); 389890792Sgshapiro if (can_setuid || EffGid == runasgid) 389990792Sgshapiro RunAsGid = runasgid; 390090792Sgshapiro else if (UseMSP) 390190792Sgshapiro (void) sm_io_fprintf(smioout, 390290792Sgshapiro SM_TIME_DEFAULT, 3903285303Sgshapiro "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", 3904285303Sgshapiro (long) EffGid, 3905285303Sgshapiro (long) runasgid); 390638032Speter } 390738032Speter else 390838032Speter { 390938032Speter register struct group *gr; 391064562Sgshapiro 391138032Speter gr = getgrnam(p); 391238032Speter if (gr == NULL) 391338032Speter syserr("readcf: option RunAsUser: unknown group %s", 391438032Speter p); 391590792Sgshapiro else if (can_setuid || EffGid == gr->gr_gid) 391638032Speter RunAsGid = gr->gr_gid; 391790792Sgshapiro else if (UseMSP) 391890792Sgshapiro (void) sm_io_fprintf(smioout, 391990792Sgshapiro SM_TIME_DEFAULT, 3920285303Sgshapiro "WARNING: RunAsUser for MSP ignored, check group ids (egid=%ld, want=%ld)\n", 3921285303Sgshapiro (long) EffGid, 3922285303Sgshapiro (long) gr->gr_gid); 392338032Speter } 392438032Speter } 392538032Speter if (tTd(47, 5)) 392690792Sgshapiro sm_dprintf("readcf: RunAsUser = %d:%d\n", 392790792Sgshapiro (int) RunAsUid, (int) RunAsGid); 392838032Speter break; 392938032Speter 393038032Speter case O_DSN_RRT: 393138032Speter RrtImpliesDsn = atobool(val); 393238032Speter break; 393338032Speter 393438032Speter case O_PIDFILE: 393590792Sgshapiro PSTRSET(PidFile, val); 393638032Speter break; 393738032Speter 393890792Sgshapiro case O_DONTBLAMESENDMAIL: 393938032Speter p = val; 394038032Speter for (;;) 394138032Speter { 394238032Speter register struct dbsval *dbs; 394338032Speter extern struct dbsval DontBlameSendmailValues[]; 394438032Speter 394538032Speter while (isascii(*p) && (isspace(*p) || ispunct(*p))) 394638032Speter p++; 394738032Speter if (*p == '\0') 394838032Speter break; 394938032Speter val = p; 395038032Speter while (isascii(*p) && isalnum(*p)) 395138032Speter p++; 395238032Speter if (*p != '\0') 395338032Speter *p++ = '\0'; 395438032Speter 395538032Speter for (dbs = DontBlameSendmailValues; 395638032Speter dbs->dbs_name != NULL; dbs++) 395738032Speter { 395890792Sgshapiro if (sm_strcasecmp(val, dbs->dbs_name) == 0) 395938032Speter break; 396038032Speter } 396138032Speter if (dbs->dbs_name == NULL) 396238032Speter syserr("readcf: DontBlameSendmail option: %s unrecognized", val); 396338032Speter else if (dbs->dbs_flag == DBS_SAFE) 396464562Sgshapiro clrbitmap(DontBlameSendmail); 396538032Speter else 396664562Sgshapiro setbitn(dbs->dbs_flag, DontBlameSendmail); 396738032Speter } 396890792Sgshapiro sticky = false; 396938032Speter break; 397038032Speter 397138032Speter case O_DPI: 397290792Sgshapiro if (sm_strcasecmp(val, "loopback") == 0) 397390792Sgshapiro DontProbeInterfaces = DPI_SKIPLOOPBACK; 397490792Sgshapiro else if (atobool(val)) 397590792Sgshapiro DontProbeInterfaces = DPI_PROBENONE; 397690792Sgshapiro else 397790792Sgshapiro DontProbeInterfaces = DPI_PROBEALL; 397838032Speter break; 397938032Speter 398038032Speter case O_MAXRCPT: 398138032Speter MaxRcptPerMsg = atoi(val); 398238032Speter break; 398338032Speter 398490792Sgshapiro case O_RCPTTHROT: 398590792Sgshapiro BadRcptThrottle = atoi(val); 398690792Sgshapiro break; 398790792Sgshapiro 3988203004Sgshapiro#if _FFR_RCPTTHROTDELAY 3989203004Sgshapiro case O_RCPTTHROTDELAY: 3990203004Sgshapiro BadRcptThrottleDelay = atoi(val); 3991203004Sgshapiro break; 3992203004Sgshapiro#endif /* _FFR_RCPTTHROTDELAY */ 3993203004Sgshapiro 399438032Speter case O_DEADLETTER: 399590792Sgshapiro CANONIFY(val); 399690792Sgshapiro PSTRSET(DeadLetterDrop, val); 399738032Speter break; 399838032Speter 399938032Speter#if _FFR_DONTLOCKFILESFORREAD_OPTION 400038032Speter case O_DONTLOCK: 400138032Speter DontLockReadFiles = atobool(val); 400238032Speter break; 400364562Sgshapiro#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ 400438032Speter 400538032Speter case O_MAXALIASRCSN: 400638032Speter MaxAliasRecursion = atoi(val); 400738032Speter break; 400838032Speter 400938032Speter case O_CNCTONLYTO: 401038032Speter /* XXX should probably use gethostbyname */ 401164562Sgshapiro#if NETINET || NETINET6 401290792Sgshapiro ConnectOnlyTo.sa.sa_family = AF_UNSPEC; 401364562Sgshapiro# if NETINET6 401490792Sgshapiro if (anynet_pton(AF_INET6, val, 4015223067Sgshapiro &ConnectOnlyTo.sin6.sin6_addr) == 1) 401664562Sgshapiro ConnectOnlyTo.sa.sa_family = AF_INET6; 401764562Sgshapiro else 401864562Sgshapiro# endif /* NETINET6 */ 401990792Sgshapiro# if NETINET 402064562Sgshapiro { 402164562Sgshapiro ConnectOnlyTo.sin.sin_addr.s_addr = inet_addr(val); 402290792Sgshapiro if (ConnectOnlyTo.sin.sin_addr.s_addr != INADDR_NONE) 402390792Sgshapiro ConnectOnlyTo.sa.sa_family = AF_INET; 402464562Sgshapiro } 402590792Sgshapiro 402690792Sgshapiro# endif /* NETINET */ 402790792Sgshapiro if (ConnectOnlyTo.sa.sa_family == AF_UNSPEC) 402890792Sgshapiro { 402990792Sgshapiro syserr("readcf: option ConnectOnlyTo: invalid IP address %s", 403090792Sgshapiro val); 403190792Sgshapiro break; 403290792Sgshapiro } 403364562Sgshapiro#endif /* NETINET || NETINET6 */ 403438032Speter break; 403538032Speter 403642575Speter case O_TRUSTUSER: 403790792Sgshapiro# if !HASFCHOWN && !defined(_FFR_DROP_TRUSTUSER_WARNING) 403890792Sgshapiro if (!UseMSP) 403990792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 404090792Sgshapiro "readcf: option TrustedUser may cause problems on systems\n which do not support fchown() if UseMSP is not set.\n"); 404190792Sgshapiro# endif /* !HASFCHOWN && !defined(_FFR_DROP_TRUSTUSER_WARNING) */ 404238032Speter if (isascii(*val) && isdigit(*val)) 404342575Speter TrustedUid = atoi(val); 404438032Speter else 404538032Speter { 404638032Speter register struct passwd *pw; 404738032Speter 404842575Speter TrustedUid = 0; 404938032Speter pw = sm_getpwnam(val); 405038032Speter if (pw == NULL) 405171345Sgshapiro { 405242575Speter syserr("readcf: option TrustedUser: unknown user %s", val); 405371345Sgshapiro break; 405471345Sgshapiro } 405538032Speter else 405642575Speter TrustedUid = pw->pw_uid; 405738032Speter } 405838032Speter 405964562Sgshapiro# ifdef UID_MAX 406042575Speter if (TrustedUid > UID_MAX) 406138032Speter { 406242575Speter syserr("readcf: option TrustedUser: uid value (%ld) > UID_MAX (%ld)", 406371345Sgshapiro (long) TrustedUid, (long) UID_MAX); 406442575Speter TrustedUid = 0; 406538032Speter } 406664562Sgshapiro# endif /* UID_MAX */ 406738032Speter break; 406838032Speter 406942575Speter case O_MAXMIMEHDRLEN: 407042575Speter p = strchr(val, '/'); 407142575Speter if (p != NULL) 407242575Speter *p++ = '\0'; 407342575Speter MaxMimeHeaderLength = atoi(val); 407442575Speter if (p != NULL && *p != '\0') 407542575Speter MaxMimeFieldLength = atoi(p); 407642575Speter else 407742575Speter MaxMimeFieldLength = MaxMimeHeaderLength / 2; 407842575Speter 4079120256Sgshapiro if (MaxMimeHeaderLength <= 0) 408042575Speter MaxMimeHeaderLength = 0; 408142575Speter else if (MaxMimeHeaderLength < 128) 408290792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 408390792Sgshapiro "Warning: MaxMimeHeaderLength: header length limit set lower than 128\n"); 408442575Speter 4085120256Sgshapiro if (MaxMimeFieldLength <= 0) 408642575Speter MaxMimeFieldLength = 0; 408742575Speter else if (MaxMimeFieldLength < 40) 408890792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 408990792Sgshapiro "Warning: MaxMimeHeaderLength: field length limit set lower than 40\n"); 4090168515Sgshapiro 4091168515Sgshapiro /* 4092168515Sgshapiro ** Headers field values now include leading space, so let's 4093168515Sgshapiro ** adjust the values to be "backward compatible". 4094168515Sgshapiro */ 4095168515Sgshapiro 4096168515Sgshapiro if (MaxMimeHeaderLength > 0) 4097168515Sgshapiro MaxMimeHeaderLength++; 4098168515Sgshapiro if (MaxMimeFieldLength > 0) 4099168515Sgshapiro MaxMimeFieldLength++; 410042575Speter break; 410142575Speter 410242575Speter case O_CONTROLSOCKET: 410390792Sgshapiro PSTRSET(ControlSocketName, val); 410442575Speter break; 410542575Speter 410643730Speter case O_MAXHDRSLEN: 410743730Speter MaxHeadersLength = atoi(val); 410843148Speter 410943730Speter if (MaxHeadersLength > 0 && 411043730Speter MaxHeadersLength < (MAXHDRSLEN / 2)) 411190792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 411290792Sgshapiro "Warning: MaxHeadersLength: headers length limit set lower than %d\n", 411390792Sgshapiro (MAXHDRSLEN / 2)); 411443148Speter break; 411543148Speter 411664562Sgshapiro case O_PROCTITLEPREFIX: 411790792Sgshapiro PSTRSET(ProcTitlePrefix, val); 411864562Sgshapiro break; 411964562Sgshapiro 412064562Sgshapiro#if SASL 412164562Sgshapiro case O_SASLINFO: 412290792Sgshapiro# if _FFR_ALLOW_SASLINFO 412364562Sgshapiro /* 412490792Sgshapiro ** Allow users to select their own authinfo file 412590792Sgshapiro ** under certain circumstances, otherwise just ignore 412690792Sgshapiro ** the option. If the option isn't ignored, several 412790792Sgshapiro ** commands don't work very well, e.g., mailq. 412864562Sgshapiro ** However, this is not a "perfect" solution. 412964562Sgshapiro ** If mail is queued, the authentication info 413064562Sgshapiro ** will not be used in subsequent delivery attempts. 413164562Sgshapiro ** If we really want to support this, then it has 413264562Sgshapiro ** to be stored in the queue file. 413364562Sgshapiro */ 413464562Sgshapiro if (!bitset(SUBMIT_MSA, SubmitMode) && RealUid != 0 && 413564562Sgshapiro RunAsUid != RealUid) 413664562Sgshapiro break; 413790792Sgshapiro# endif /* _FFR_ALLOW_SASLINFO */ 413890792Sgshapiro PSTRSET(SASLInfo, val); 413964562Sgshapiro break; 414064562Sgshapiro 414164562Sgshapiro case O_SASLMECH: 414264562Sgshapiro if (AuthMechanisms != NULL) 414390792Sgshapiro sm_free(AuthMechanisms); /* XXX */ 414464562Sgshapiro if (*val != '\0') 414564562Sgshapiro AuthMechanisms = newstr(val); 414664562Sgshapiro else 414764562Sgshapiro AuthMechanisms = NULL; 414864562Sgshapiro break; 414964562Sgshapiro 4150132943Sgshapiro case O_SASLREALM: 4151132943Sgshapiro if (AuthRealm != NULL) 4152132943Sgshapiro sm_free(AuthRealm); 4153132943Sgshapiro if (*val != '\0') 4154132943Sgshapiro AuthRealm = newstr(val); 4155132943Sgshapiro else 4156132943Sgshapiro AuthRealm = NULL; 4157132943Sgshapiro break; 4158132943Sgshapiro 415964562Sgshapiro case O_SASLOPTS: 416064562Sgshapiro while (val != NULL && *val != '\0') 416164562Sgshapiro { 416290792Sgshapiro switch (*val) 416364562Sgshapiro { 416464562Sgshapiro case 'A': 416564562Sgshapiro SASLOpts |= SASL_AUTH_AUTH; 416664562Sgshapiro break; 4167110560Sgshapiro 416864562Sgshapiro case 'a': 416964562Sgshapiro SASLOpts |= SASL_SEC_NOACTIVE; 417064562Sgshapiro break; 4171110560Sgshapiro 417264562Sgshapiro case 'c': 417364562Sgshapiro SASLOpts |= SASL_SEC_PASS_CREDENTIALS; 417464562Sgshapiro break; 4175110560Sgshapiro 417664562Sgshapiro case 'd': 417764562Sgshapiro SASLOpts |= SASL_SEC_NODICTIONARY; 417864562Sgshapiro break; 4179110560Sgshapiro 418064562Sgshapiro case 'f': 418164562Sgshapiro SASLOpts |= SASL_SEC_FORWARD_SECRECY; 418264562Sgshapiro break; 4183110560Sgshapiro 418498121Sgshapiro# if SASL >= 20101 418598121Sgshapiro case 'm': 418698121Sgshapiro SASLOpts |= SASL_SEC_MUTUAL_AUTH; 418798121Sgshapiro break; 418898121Sgshapiro# endif /* SASL >= 20101 */ 4189110560Sgshapiro 419064562Sgshapiro case 'p': 419164562Sgshapiro SASLOpts |= SASL_SEC_NOPLAINTEXT; 419264562Sgshapiro break; 4193110560Sgshapiro 419464562Sgshapiro case 'y': 419564562Sgshapiro SASLOpts |= SASL_SEC_NOANONYMOUS; 419664562Sgshapiro break; 4197110560Sgshapiro 419890792Sgshapiro case ' ': /* ignore */ 419990792Sgshapiro case '\t': /* ignore */ 420090792Sgshapiro case ',': /* ignore */ 420190792Sgshapiro break; 4202110560Sgshapiro 420364562Sgshapiro default: 420490792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 420590792Sgshapiro "Warning: Option: %s unknown parameter '%c'\n", 420690792Sgshapiro OPTNAME, 420790792Sgshapiro (isascii(*val) && 420890792Sgshapiro isprint(*val)) 420990792Sgshapiro ? *val : '?'); 421064562Sgshapiro break; 421164562Sgshapiro } 421264562Sgshapiro ++val; 421364562Sgshapiro val = strpbrk(val, ", \t"); 421464562Sgshapiro if (val != NULL) 421564562Sgshapiro ++val; 421664562Sgshapiro } 421764562Sgshapiro break; 4218110560Sgshapiro 421990792Sgshapiro case O_SASLBITS: 422090792Sgshapiro MaxSLBits = atoi(val); 422190792Sgshapiro break; 422264562Sgshapiro 422364562Sgshapiro#else /* SASL */ 422464562Sgshapiro case O_SASLINFO: 422564562Sgshapiro case O_SASLMECH: 4226132943Sgshapiro case O_SASLREALM: 422764562Sgshapiro case O_SASLOPTS: 422890792Sgshapiro case O_SASLBITS: 422990792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 423090792Sgshapiro "Warning: Option: %s requires SASL support (-DSASL)\n", 423190792Sgshapiro OPTNAME); 423264562Sgshapiro break; 423364562Sgshapiro#endif /* SASL */ 423464562Sgshapiro 423564562Sgshapiro#if STARTTLS 423664562Sgshapiro case O_SRVCERTFILE: 4237110560Sgshapiro SET_STRING_EXP(SrvCertFile); 423864562Sgshapiro case O_SRVKEYFILE: 4239110560Sgshapiro SET_STRING_EXP(SrvKeyFile); 424064562Sgshapiro case O_CLTCERTFILE: 4241110560Sgshapiro SET_STRING_EXP(CltCertFile); 424264562Sgshapiro case O_CLTKEYFILE: 4243110560Sgshapiro SET_STRING_EXP(CltKeyFile); 424464562Sgshapiro case O_CACERTFILE: 4245110560Sgshapiro SET_STRING_EXP(CACertFile); 424664562Sgshapiro case O_CACERTPATH: 4247110560Sgshapiro SET_STRING_EXP(CACertPath); 424864562Sgshapiro case O_DHPARAMS: 424990792Sgshapiro SET_STRING_EXP(DHParams); 425090792Sgshapiro case O_CIPHERLIST: 425190792Sgshapiro SET_STRING_EXP(CipherList); 4252285303Sgshapiro case O_DIG_ALG: 4253285303Sgshapiro SET_STRING_EXP(CertFingerprintAlgorithm); 4254203004Sgshapiro case O_SRV_SSL_OPTIONS: 4255203004Sgshapiro pssloptions = &Srv_SSL_Options; 4256203004Sgshapiro case O_CLT_SSL_OPTIONS: 4257203004Sgshapiro if (pssloptions == NULL) 4258203004Sgshapiro pssloptions = &Clt_SSL_Options; 4259285303Sgshapiro (void) readssloptions(o->o_name, val, pssloptions, '\0'); 4260285303Sgshapiro if (tTd(37, 8)) 4261285303Sgshapiro sm_dprintf("ssloptions=%#lx\n", *pssloptions); 4262203004Sgshapiro 4263203004Sgshapiro pssloptions = NULL; 4264203004Sgshapiro break; 4265203004Sgshapiro 4266132943Sgshapiro case O_CRLFILE: 4267132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 4268132943Sgshapiro SET_STRING_EXP(CRLFile); 4269132943Sgshapiro# else /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 4270132943Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4271132943Sgshapiro "Warning: Option: %s requires at least OpenSSL 0.9.7\n", 4272132943Sgshapiro OPTNAME); 4273132943Sgshapiro break; 4274132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 427564562Sgshapiro 4276132943Sgshapiro# if _FFR_CRLPATH 4277132943Sgshapiro case O_CRLPATH: 4278132943Sgshapiro# if OPENSSL_VERSION_NUMBER > 0x00907000L 4279132943Sgshapiro SET_STRING_EXP(CRLPath); 4280132943Sgshapiro# else /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 4281132943Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4282132943Sgshapiro "Warning: Option: %s requires at least OpenSSL 0.9.7\n", 4283132943Sgshapiro OPTNAME); 4284132943Sgshapiro break; 4285132943Sgshapiro# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ 4286132943Sgshapiro# endif /* _FFR_CRLPATH */ 4287132943Sgshapiro 428890792Sgshapiro /* 428990792Sgshapiro ** XXX How about options per daemon/client instead of globally? 429090792Sgshapiro ** This doesn't work well for some options, e.g., no server cert, 429190792Sgshapiro ** but fine for others. 429290792Sgshapiro ** 429390792Sgshapiro ** XXX Some people may want different certs per server. 429490792Sgshapiro ** 429590792Sgshapiro ** See also srvfeatures() 429690792Sgshapiro */ 429790792Sgshapiro 429890792Sgshapiro case O_TLS_SRV_OPTS: 429990792Sgshapiro while (val != NULL && *val != '\0') 430090792Sgshapiro { 430190792Sgshapiro switch (*val) 430290792Sgshapiro { 430390792Sgshapiro case 'V': 430490792Sgshapiro TLS_Srv_Opts |= TLS_I_NO_VRFY; 430590792Sgshapiro break; 430690792Sgshapiro /* 430790792Sgshapiro ** Server without a cert? That works only if 430890792Sgshapiro ** AnonDH is enabled as cipher, which is not in the 430990792Sgshapiro ** default list. Hence the CipherList option must 431090792Sgshapiro ** be available. Moreover: which clients support this 431190792Sgshapiro ** besides sendmail with this setting? 431290792Sgshapiro */ 431390792Sgshapiro 431490792Sgshapiro case 'C': 431590792Sgshapiro TLS_Srv_Opts &= ~TLS_I_SRV_CERT; 431690792Sgshapiro break; 431790792Sgshapiro case ' ': /* ignore */ 431890792Sgshapiro case '\t': /* ignore */ 431990792Sgshapiro case ',': /* ignore */ 432090792Sgshapiro break; 432190792Sgshapiro default: 432290792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 432390792Sgshapiro "Warning: Option: %s unknown parameter '%c'\n", 432490792Sgshapiro OPTNAME, 432590792Sgshapiro (isascii(*val) && 432690792Sgshapiro isprint(*val)) 432790792Sgshapiro ? *val : '?'); 432890792Sgshapiro break; 432990792Sgshapiro } 433090792Sgshapiro ++val; 433190792Sgshapiro val = strpbrk(val, ", \t"); 433290792Sgshapiro if (val != NULL) 433390792Sgshapiro ++val; 433490792Sgshapiro } 433564562Sgshapiro break; 433664562Sgshapiro 433764562Sgshapiro case O_RANDFILE: 433890792Sgshapiro PSTRSET(RandFile, val); 433964562Sgshapiro break; 434064562Sgshapiro 434190792Sgshapiro#else /* STARTTLS */ 434264562Sgshapiro case O_SRVCERTFILE: 434364562Sgshapiro case O_SRVKEYFILE: 434464562Sgshapiro case O_CLTCERTFILE: 434564562Sgshapiro case O_CLTKEYFILE: 434664562Sgshapiro case O_CACERTFILE: 434764562Sgshapiro case O_CACERTPATH: 434864562Sgshapiro case O_DHPARAMS: 4349285303Sgshapiro case O_SRV_SSL_OPTIONS: 4350285303Sgshapiro case O_CLT_SSL_OPTIONS: 435164562Sgshapiro case O_CIPHERLIST: 4352132943Sgshapiro case O_CRLFILE: 4353132943Sgshapiro# if _FFR_CRLPATH 4354132943Sgshapiro case O_CRLPATH: 4355132943Sgshapiro# endif /* _FFR_CRLPATH */ 435664562Sgshapiro case O_RANDFILE: 435790792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 435890792Sgshapiro "Warning: Option: %s requires TLS support\n", 435990792Sgshapiro OPTNAME); 436064562Sgshapiro break; 436164562Sgshapiro 436290792Sgshapiro#endif /* STARTTLS */ 4363249729Sgshapiro#if STARTTLS && _FFR_FIPSMODE 4364249729Sgshapiro case O_FIPSMODE: 4365249729Sgshapiro FipsMode = atobool(val); 4366249729Sgshapiro break; 4367249729Sgshapiro#endif /* STARTTLS && _FFR_FIPSMODE */ 436864562Sgshapiro 436964562Sgshapiro case O_CLIENTPORT: 437064562Sgshapiro setclientoptions(val); 437164562Sgshapiro break; 437264562Sgshapiro 437364562Sgshapiro case O_DF_BUFSIZE: 437464562Sgshapiro DataFileBufferSize = atoi(val); 437564562Sgshapiro break; 437664562Sgshapiro 437764562Sgshapiro case O_XF_BUFSIZE: 437864562Sgshapiro XscriptFileBufferSize = atoi(val); 437964562Sgshapiro break; 438064562Sgshapiro 438164562Sgshapiro case O_LDAPDEFAULTSPEC: 438290792Sgshapiro#if LDAPMAP 438364562Sgshapiro ldapmap_set_defaults(val); 438464562Sgshapiro#else /* LDAPMAP */ 438590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 438690792Sgshapiro "Warning: Option: %s requires LDAP support (-DLDAPMAP)\n", 438790792Sgshapiro OPTNAME); 438864562Sgshapiro#endif /* LDAPMAP */ 438964562Sgshapiro break; 439064562Sgshapiro 439164562Sgshapiro case O_INPUTMILTER: 439290792Sgshapiro#if MILTER 439364562Sgshapiro InputFilterList = newstr(val); 439490792Sgshapiro#else /* MILTER */ 439590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 439690792Sgshapiro "Warning: Option: %s requires Milter support (-DMILTER)\n", 439790792Sgshapiro OPTNAME); 439890792Sgshapiro#endif /* MILTER */ 439964562Sgshapiro break; 440064562Sgshapiro 440164562Sgshapiro case O_MILTER: 440290792Sgshapiro#if MILTER 440364562Sgshapiro milter_set_option(subopt, val, sticky); 440490792Sgshapiro#else /* MILTER */ 440590792Sgshapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 440690792Sgshapiro "Warning: Option: %s requires Milter support (-DMILTER)\n", 440790792Sgshapiro OPTNAME); 440890792Sgshapiro#endif /* MILTER */ 440964562Sgshapiro break; 441064562Sgshapiro 441164562Sgshapiro case O_QUEUE_FILE_MODE: /* queue file mode */ 441264562Sgshapiro QueueFileMode = atooct(val) & 0777; 441364562Sgshapiro break; 441464562Sgshapiro 441590792Sgshapiro case O_DLVR_MIN: /* deliver by minimum time */ 441690792Sgshapiro DeliverByMin = convtime(val, 's'); 441790792Sgshapiro break; 441890792Sgshapiro 441990792Sgshapiro /* modifiers {daemon_flags} for direct submissions */ 442090792Sgshapiro case O_DIRECTSUBMODIFIERS: 442190792Sgshapiro { 442290792Sgshapiro BITMAP256 m; /* ignored */ 442390792Sgshapiro extern ENVELOPE BlankEnvelope; 442490792Sgshapiro 442590792Sgshapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 442690792Sgshapiro macid("{daemon_flags}"), 442790792Sgshapiro getmodifiers(val, m)); 442890792Sgshapiro } 442990792Sgshapiro break; 443090792Sgshapiro 443190792Sgshapiro case O_FASTSPLIT: 443290792Sgshapiro FastSplit = atoi(val); 443390792Sgshapiro break; 443490792Sgshapiro 443590792Sgshapiro case O_MBDB: 443690792Sgshapiro Mbdb = newstr(val); 443790792Sgshapiro break; 443890792Sgshapiro 443990792Sgshapiro case O_MSQ: 444090792Sgshapiro UseMSP = atobool(val); 444190792Sgshapiro break; 444290792Sgshapiro 444390792Sgshapiro case O_SOFTBOUNCE: 444490792Sgshapiro SoftBounce = atobool(val); 444590792Sgshapiro break; 444690792Sgshapiro 4447110560Sgshapiro case O_REJECTLOGINTERVAL: /* time btwn log msgs while refusing */ 4448110560Sgshapiro RejectLogInterval = convtime(val, 'h'); 4449110560Sgshapiro break; 4450110560Sgshapiro 4451110560Sgshapiro case O_REQUIRES_DIR_FSYNC: 4452132943Sgshapiro#if REQUIRES_DIR_FSYNC 4453110560Sgshapiro RequiresDirfsync = atobool(val); 4454132943Sgshapiro#else /* REQUIRES_DIR_FSYNC */ 4455110560Sgshapiro /* silently ignored... required for cf file option */ 4456132943Sgshapiro#endif /* REQUIRES_DIR_FSYNC */ 4457110560Sgshapiro break; 4458110560Sgshapiro 4459132943Sgshapiro case O_CONNECTION_RATE_WINDOW_SIZE: 4460132943Sgshapiro ConnectionRateWindowSize = convtime(val, 's'); 4461132943Sgshapiro break; 4462132943Sgshapiro 4463132943Sgshapiro case O_FALLBACKSMARTHOST: /* fallback smart host */ 4464132943Sgshapiro if (val[0] != '\0') 4465132943Sgshapiro FallbackSmartHost = newstr(val); 4466132943Sgshapiro break; 4467132943Sgshapiro 4468132943Sgshapiro case O_HELONAME: 4469157001Sgshapiro HeloName = newstr(val); 4470157001Sgshapiro break; 4471168515Sgshapiro 4472157001Sgshapiro#if _FFR_MEMSTAT 4473157001Sgshapiro case O_REFUSELOWMEM: 4474157001Sgshapiro RefuseLowMem = atoi(val); 4475157001Sgshapiro break; 4476157001Sgshapiro case O_QUEUELOWMEM: 4477157001Sgshapiro QueueLowMem = atoi(val); 4478157001Sgshapiro break; 4479157001Sgshapiro case O_MEMRESOURCE: 4480157001Sgshapiro MemoryResource = newstr(val); 4481157001Sgshapiro break; 4482157001Sgshapiro#endif /* _FFR_MEMSTAT */ 4483132943Sgshapiro 4484157001Sgshapiro case O_MAXNOOPCOMMANDS: 4485157001Sgshapiro MaxNOOPCommands = atoi(val); 4486157001Sgshapiro break; 4487157001Sgshapiro 4488157001Sgshapiro#if _FFR_MSG_ACCEPT 4489157001Sgshapiro case O_MSG_ACCEPT: 4490157001Sgshapiro MessageAccept = newstr(val); 4491157001Sgshapiro break; 4492157001Sgshapiro#endif /* _FFR_MSG_ACCEPT */ 4493157001Sgshapiro 4494157001Sgshapiro#if _FFR_QUEUE_RUN_PARANOIA 4495157001Sgshapiro case O_CHK_Q_RUNNERS: 4496157001Sgshapiro CheckQueueRunners = atoi(val); 4497157001Sgshapiro break; 4498157001Sgshapiro#endif /* _FFR_QUEUE_RUN_PARANOIA */ 4499157001Sgshapiro 4500168515Sgshapiro#if _FFR_EIGHT_BIT_ADDR_OK 4501168515Sgshapiro case O_EIGHT_BIT_ADDR_OK: 4502168515Sgshapiro EightBitAddrOK = atobool(val); 4503168515Sgshapiro break; 4504168515Sgshapiro#endif /* _FFR_EIGHT_BIT_ADDR_OK */ 4505168515Sgshapiro 4506173340Sgshapiro#if _FFR_ADDR_TYPE_MODES 4507173340Sgshapiro case O_ADDR_TYPE_MODES: 4508173340Sgshapiro AddrTypeModes = atobool(val); 4509173340Sgshapiro break; 4510173340Sgshapiro#endif /* _FFR_ADDR_TYPE_MODES */ 4511173340Sgshapiro 4512182352Sgshapiro#if _FFR_BADRCPT_SHUTDOWN 4513182352Sgshapiro case O_RCPTSHUTD: 4514182352Sgshapiro BadRcptShutdown = atoi(val); 4515182352Sgshapiro break; 4516182352Sgshapiro 4517182352Sgshapiro case O_RCPTSHUTDG: 4518182352Sgshapiro BadRcptShutdownGood = atoi(val); 4519182352Sgshapiro break; 4520182352Sgshapiro#endif /* _FFR_BADRCPT_SHUTDOWN */ 4521182352Sgshapiro 4522249729Sgshapiro#if _FFR_REJECT_NUL_BYTE 4523249729Sgshapiro case O_REJECTNUL: 4524249729Sgshapiro RejectNUL = atobool(val); 4525249729Sgshapiro break; 4526249729Sgshapiro#endif /* _FFR_REJECT_NUL_BYTE */ 4527249729Sgshapiro 4528285303Sgshapiro#if _FFR_BOUNCE_QUEUE 4529285303Sgshapiro case O_BOUNCEQUEUE: 4530285303Sgshapiro bouncequeue = newstr(val); 4531285303Sgshapiro break; 4532285303Sgshapiro#endif /* _FFR_BOUNCE_QUEUE */ 4533285303Sgshapiro 4534285303Sgshapiro#if _FFR_ADD_BCC 4535285303Sgshapiro case O_ADDBCC: 4536285303Sgshapiro AddBcc = atobool(val); 4537285303Sgshapiro break; 4538285303Sgshapiro#endif 4539285303Sgshapiro case O_USECOMPRESSEDIPV6ADDRESSES: 4540285303Sgshapiro UseCompressedIPv6Addresses = atobool(val); 4541285303Sgshapiro break; 4542285303Sgshapiro 454338032Speter default: 454438032Speter if (tTd(37, 1)) 454538032Speter { 454638032Speter if (isascii(opt) && isprint(opt)) 454790792Sgshapiro sm_dprintf("Warning: option %c unknown\n", opt); 454838032Speter else 454990792Sgshapiro sm_dprintf("Warning: option 0x%x unknown\n", opt); 455038032Speter } 455138032Speter break; 455238032Speter } 455364562Sgshapiro 455464562Sgshapiro /* 455564562Sgshapiro ** Options with suboptions are responsible for taking care 455664562Sgshapiro ** of sticky-ness (e.g., that a command line setting is kept 455764562Sgshapiro ** when reading in the sendmail.cf file). This has to be done 455864562Sgshapiro ** when the suboptions are parsed since each suboption must be 455964562Sgshapiro ** sticky, not the root option. 456064562Sgshapiro */ 456164562Sgshapiro 456264562Sgshapiro if (sticky && !bitset(OI_SUBOPT, o->o_flags)) 456338032Speter setbitn(opt, StickyOpt); 456438032Speter} 456590792Sgshapiro/* 456638032Speter** SETCLASS -- set a string into a class 456738032Speter** 456838032Speter** Parameters: 456938032Speter** class -- the class to put the string in. 457038032Speter** str -- the string to enter 457138032Speter** 457238032Speter** Returns: 457338032Speter** none. 457438032Speter** 457538032Speter** Side Effects: 457638032Speter** puts the word into the symbol table. 457738032Speter*/ 457838032Speter 457938032Spetervoid 458038032Spetersetclass(class, str) 458138032Speter int class; 458238032Speter char *str; 458338032Speter{ 458438032Speter register STAB *s; 458538032Speter 4586168515Sgshapiro if ((str[0] & 0377) == MATCHCLASS) 458764562Sgshapiro { 458864562Sgshapiro int mid; 458964562Sgshapiro 459064562Sgshapiro str++; 459190792Sgshapiro mid = macid(str); 459271345Sgshapiro if (mid == 0) 459364562Sgshapiro return; 459464562Sgshapiro 459564562Sgshapiro if (tTd(37, 8)) 459690792Sgshapiro sm_dprintf("setclass(%s, $=%s)\n", 459790792Sgshapiro macname(class), macname(mid)); 459864562Sgshapiro copy_class(mid, class); 459964562Sgshapiro } 460064562Sgshapiro else 460164562Sgshapiro { 460264562Sgshapiro if (tTd(37, 8)) 460390792Sgshapiro sm_dprintf("setclass(%s, %s)\n", macname(class), str); 460464562Sgshapiro 460564562Sgshapiro s = stab(str, ST_CLASS, ST_ENTER); 460671345Sgshapiro setbitn(bitidx(class), s->s_class); 460764562Sgshapiro } 460838032Speter} 460990792Sgshapiro/* 461038032Speter** MAKEMAPENTRY -- create a map entry 461138032Speter** 461238032Speter** Parameters: 461338032Speter** line -- the config file line 461438032Speter** 461538032Speter** Returns: 461638032Speter** A pointer to the map that has been created. 461738032Speter** NULL if there was a syntax error. 461838032Speter** 461938032Speter** Side Effects: 462038032Speter** Enters the map into the dictionary. 462138032Speter*/ 462238032Speter 462338032SpeterMAP * 462438032Spetermakemapentry(line) 462538032Speter char *line; 462638032Speter{ 462738032Speter register char *p; 462838032Speter char *mapname; 462938032Speter char *classname; 463038032Speter register STAB *s; 463138032Speter STAB *class; 463238032Speter 463338032Speter for (p = line; isascii(*p) && isspace(*p); p++) 463438032Speter continue; 463538032Speter if (!(isascii(*p) && isalnum(*p))) 463638032Speter { 463738032Speter syserr("readcf: config K line: no map name"); 463838032Speter return NULL; 463938032Speter } 464038032Speter 464138032Speter mapname = p; 464238032Speter while ((isascii(*++p) && isalnum(*p)) || *p == '_' || *p == '.') 464338032Speter continue; 464438032Speter if (*p != '\0') 464538032Speter *p++ = '\0'; 464638032Speter while (isascii(*p) && isspace(*p)) 464738032Speter p++; 464838032Speter if (!(isascii(*p) && isalnum(*p))) 464938032Speter { 465038032Speter syserr("readcf: config K line, map %s: no map class", mapname); 465138032Speter return NULL; 465238032Speter } 465338032Speter classname = p; 465438032Speter while (isascii(*++p) && isalnum(*p)) 465538032Speter continue; 465638032Speter if (*p != '\0') 465738032Speter *p++ = '\0'; 465838032Speter while (isascii(*p) && isspace(*p)) 465938032Speter p++; 466038032Speter 466138032Speter /* look up the class */ 466238032Speter class = stab(classname, ST_MAPCLASS, ST_FIND); 466338032Speter if (class == NULL) 466438032Speter { 466590792Sgshapiro syserr("readcf: map %s: class %s not available", mapname, 466690792Sgshapiro classname); 466738032Speter return NULL; 466838032Speter } 466938032Speter 467038032Speter /* enter the map */ 467138032Speter s = stab(mapname, ST_MAP, ST_ENTER); 467238032Speter s->s_map.map_class = &class->s_mapclass; 467338032Speter s->s_map.map_mname = newstr(mapname); 467438032Speter 467538032Speter if (class->s_mapclass.map_parse(&s->s_map, p)) 467638032Speter s->s_map.map_mflags |= MF_VALID; 467738032Speter 467838032Speter if (tTd(37, 5)) 467938032Speter { 468090792Sgshapiro sm_dprintf("map %s, class %s, flags %lx, file %s,\n", 468190792Sgshapiro s->s_map.map_mname, s->s_map.map_class->map_cname, 468290792Sgshapiro s->s_map.map_mflags, s->s_map.map_file); 468390792Sgshapiro sm_dprintf("\tapp %s, domain %s, rebuild %s\n", 468490792Sgshapiro s->s_map.map_app, s->s_map.map_domain, 468590792Sgshapiro s->s_map.map_rebuild); 468638032Speter } 468738032Speter return &s->s_map; 468838032Speter} 468990792Sgshapiro/* 469038032Speter** STRTORWSET -- convert string to rewriting set number 469138032Speter** 469238032Speter** Parameters: 469338032Speter** p -- the pointer to the string to decode. 469438032Speter** endp -- if set, store the trailing delimiter here. 469538032Speter** stabmode -- ST_ENTER to create this entry, ST_FIND if 469638032Speter** it must already exist. 469738032Speter** 469838032Speter** Returns: 469938032Speter** The appropriate ruleset number. 470038032Speter** -1 if it is not valid (error already printed) 470138032Speter*/ 470238032Speter 470338032Speterint 470438032Speterstrtorwset(p, endp, stabmode) 470538032Speter char *p; 470638032Speter char **endp; 470738032Speter int stabmode; 470838032Speter{ 470938032Speter int ruleset; 471038032Speter static int nextruleset = MAXRWSETS; 471138032Speter 471238032Speter while (isascii(*p) && isspace(*p)) 471338032Speter p++; 471438032Speter if (!isascii(*p)) 471538032Speter { 471638032Speter syserr("invalid ruleset name: \"%.20s\"", p); 471738032Speter return -1; 471838032Speter } 471938032Speter if (isdigit(*p)) 472038032Speter { 472138032Speter ruleset = strtol(p, endp, 10); 472238032Speter if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 472338032Speter { 472438032Speter syserr("bad ruleset %d (%d max)", 472538032Speter ruleset, MAXRWSETS / 2); 472638032Speter ruleset = -1; 472738032Speter } 472838032Speter } 472938032Speter else 473038032Speter { 473138032Speter STAB *s; 473238032Speter char delim; 473364562Sgshapiro char *q = NULL; 473438032Speter 473538032Speter q = p; 4736203004Sgshapiro while (*p != '\0' && isascii(*p) && (isalnum(*p) || *p == '_')) 473738032Speter p++; 473838032Speter if (q == p || !(isascii(*q) && isalpha(*q))) 473938032Speter { 474038032Speter /* no valid characters */ 474138032Speter syserr("invalid ruleset name: \"%.20s\"", q); 474238032Speter return -1; 474338032Speter } 474438032Speter while (isascii(*p) && isspace(*p)) 474538032Speter *p++ = '\0'; 474638032Speter delim = *p; 474738032Speter if (delim != '\0') 474838032Speter *p = '\0'; 474938032Speter s = stab(q, ST_RULESET, stabmode); 475038032Speter if (delim != '\0') 475138032Speter *p = delim; 475238032Speter 475338032Speter if (s == NULL) 475438032Speter return -1; 475538032Speter 475638032Speter if (stabmode == ST_ENTER && delim == '=') 475738032Speter { 475838032Speter while (isascii(*++p) && isspace(*p)) 475938032Speter continue; 476038032Speter if (!(isascii(*p) && isdigit(*p))) 476138032Speter { 476238032Speter syserr("bad ruleset definition \"%s\" (number required after `=')", q); 476338032Speter ruleset = -1; 476438032Speter } 476538032Speter else 476638032Speter { 476738032Speter ruleset = strtol(p, endp, 10); 476838032Speter if (ruleset >= MAXRWSETS / 2 || ruleset < 0) 476938032Speter { 477038032Speter syserr("bad ruleset number %d in \"%s\" (%d max)", 477138032Speter ruleset, q, MAXRWSETS / 2); 477238032Speter ruleset = -1; 477338032Speter } 477438032Speter } 477538032Speter } 477638032Speter else 477738032Speter { 477838032Speter if (endp != NULL) 477938032Speter *endp = p; 478064562Sgshapiro if (s->s_ruleset >= 0) 478138032Speter ruleset = s->s_ruleset; 478238032Speter else if ((ruleset = --nextruleset) < MAXRWSETS / 2) 478338032Speter { 478438032Speter syserr("%s: too many named rulesets (%d max)", 478538032Speter q, MAXRWSETS / 2); 478638032Speter ruleset = -1; 478738032Speter } 478838032Speter } 478964562Sgshapiro if (s->s_ruleset >= 0 && 479064562Sgshapiro ruleset >= 0 && 479164562Sgshapiro ruleset != s->s_ruleset) 479238032Speter { 479338032Speter syserr("%s: ruleset changed value (old %d, new %d)", 479438032Speter q, s->s_ruleset, ruleset); 479538032Speter ruleset = s->s_ruleset; 479638032Speter } 479764562Sgshapiro else if (ruleset >= 0) 479838032Speter { 479938032Speter s->s_ruleset = ruleset; 480038032Speter } 480171345Sgshapiro if (stabmode == ST_ENTER && ruleset >= 0) 480264562Sgshapiro { 480364562Sgshapiro char *h = NULL; 480464562Sgshapiro 480564562Sgshapiro if (RuleSetNames[ruleset] != NULL) 480690792Sgshapiro sm_free(RuleSetNames[ruleset]); /* XXX */ 480764562Sgshapiro if (delim != '\0' && (h = strchr(q, delim)) != NULL) 480864562Sgshapiro *h = '\0'; 480964562Sgshapiro RuleSetNames[ruleset] = newstr(q); 481064562Sgshapiro if (delim == '/' && h != NULL) 481164562Sgshapiro *h = delim; /* put back delim */ 481264562Sgshapiro } 481338032Speter } 481438032Speter return ruleset; 481538032Speter} 481690792Sgshapiro/* 481764562Sgshapiro** SETTIMEOUT -- set an individual timeout 481864562Sgshapiro** 481964562Sgshapiro** Parameters: 482064562Sgshapiro** name -- the name of the timeout. 482164562Sgshapiro** val -- the value of the timeout. 482264562Sgshapiro** sticky -- if set, don't let other setoptions override 482364562Sgshapiro** this value. 482464562Sgshapiro** 482564562Sgshapiro** Returns: 482664562Sgshapiro** none. 482764562Sgshapiro*/ 482864562Sgshapiro 482964562Sgshapiro/* set if Timeout sub-option is stuck */ 483064562Sgshapirostatic BITMAP256 StickyTimeoutOpt; 483164562Sgshapiro 483264562Sgshapirostatic struct timeoutinfo 483364562Sgshapiro{ 483490792Sgshapiro char *to_name; /* long name of timeout */ 483590792Sgshapiro unsigned char to_code; /* code for option */ 483664562Sgshapiro} TimeOutTab[] = 483764562Sgshapiro{ 483864562Sgshapiro#define TO_INITIAL 0x01 483964562Sgshapiro { "initial", TO_INITIAL }, 484064562Sgshapiro#define TO_MAIL 0x02 484164562Sgshapiro { "mail", TO_MAIL }, 484264562Sgshapiro#define TO_RCPT 0x03 484364562Sgshapiro { "rcpt", TO_RCPT }, 484464562Sgshapiro#define TO_DATAINIT 0x04 484564562Sgshapiro { "datainit", TO_DATAINIT }, 484664562Sgshapiro#define TO_DATABLOCK 0x05 484764562Sgshapiro { "datablock", TO_DATABLOCK }, 484864562Sgshapiro#define TO_DATAFINAL 0x06 484964562Sgshapiro { "datafinal", TO_DATAFINAL }, 485064562Sgshapiro#define TO_COMMAND 0x07 485164562Sgshapiro { "command", TO_COMMAND }, 485264562Sgshapiro#define TO_RSET 0x08 485364562Sgshapiro { "rset", TO_RSET }, 485464562Sgshapiro#define TO_HELO 0x09 485564562Sgshapiro { "helo", TO_HELO }, 485664562Sgshapiro#define TO_QUIT 0x0A 485764562Sgshapiro { "quit", TO_QUIT }, 485864562Sgshapiro#define TO_MISC 0x0B 485964562Sgshapiro { "misc", TO_MISC }, 486064562Sgshapiro#define TO_IDENT 0x0C 486164562Sgshapiro { "ident", TO_IDENT }, 486264562Sgshapiro#define TO_FILEOPEN 0x0D 486364562Sgshapiro { "fileopen", TO_FILEOPEN }, 486464562Sgshapiro#define TO_CONNECT 0x0E 486564562Sgshapiro { "connect", TO_CONNECT }, 486664562Sgshapiro#define TO_ICONNECT 0x0F 486764562Sgshapiro { "iconnect", TO_ICONNECT }, 486864562Sgshapiro#define TO_QUEUEWARN 0x10 486964562Sgshapiro { "queuewarn", TO_QUEUEWARN }, 487064562Sgshapiro { "queuewarn.*", TO_QUEUEWARN }, 487164562Sgshapiro#define TO_QUEUEWARN_NORMAL 0x11 487264562Sgshapiro { "queuewarn.normal", TO_QUEUEWARN_NORMAL }, 487364562Sgshapiro#define TO_QUEUEWARN_URGENT 0x12 487464562Sgshapiro { "queuewarn.urgent", TO_QUEUEWARN_URGENT }, 487564562Sgshapiro#define TO_QUEUEWARN_NON_URGENT 0x13 487664562Sgshapiro { "queuewarn.non-urgent", TO_QUEUEWARN_NON_URGENT }, 487764562Sgshapiro#define TO_QUEUERETURN 0x14 487864562Sgshapiro { "queuereturn", TO_QUEUERETURN }, 487964562Sgshapiro { "queuereturn.*", TO_QUEUERETURN }, 488064562Sgshapiro#define TO_QUEUERETURN_NORMAL 0x15 488164562Sgshapiro { "queuereturn.normal", TO_QUEUERETURN_NORMAL }, 488264562Sgshapiro#define TO_QUEUERETURN_URGENT 0x16 488364562Sgshapiro { "queuereturn.urgent", TO_QUEUERETURN_URGENT }, 488464562Sgshapiro#define TO_QUEUERETURN_NON_URGENT 0x17 488564562Sgshapiro { "queuereturn.non-urgent", TO_QUEUERETURN_NON_URGENT }, 488664562Sgshapiro#define TO_HOSTSTATUS 0x18 488764562Sgshapiro { "hoststatus", TO_HOSTSTATUS }, 488864562Sgshapiro#define TO_RESOLVER_RETRANS 0x19 488964562Sgshapiro { "resolver.retrans", TO_RESOLVER_RETRANS }, 489064562Sgshapiro#define TO_RESOLVER_RETRANS_NORMAL 0x1A 489164562Sgshapiro { "resolver.retrans.normal", TO_RESOLVER_RETRANS_NORMAL }, 489264562Sgshapiro#define TO_RESOLVER_RETRANS_FIRST 0x1B 489364562Sgshapiro { "resolver.retrans.first", TO_RESOLVER_RETRANS_FIRST }, 489464562Sgshapiro#define TO_RESOLVER_RETRY 0x1C 489564562Sgshapiro { "resolver.retry", TO_RESOLVER_RETRY }, 489664562Sgshapiro#define TO_RESOLVER_RETRY_NORMAL 0x1D 489764562Sgshapiro { "resolver.retry.normal", TO_RESOLVER_RETRY_NORMAL }, 489864562Sgshapiro#define TO_RESOLVER_RETRY_FIRST 0x1E 489964562Sgshapiro { "resolver.retry.first", TO_RESOLVER_RETRY_FIRST }, 490064562Sgshapiro#define TO_CONTROL 0x1F 490164562Sgshapiro { "control", TO_CONTROL }, 490290792Sgshapiro#define TO_LHLO 0x20 490390792Sgshapiro { "lhlo", TO_LHLO }, 490490792Sgshapiro#define TO_AUTH 0x21 490590792Sgshapiro { "auth", TO_AUTH }, 490690792Sgshapiro#define TO_STARTTLS 0x22 490790792Sgshapiro { "starttls", TO_STARTTLS }, 490890792Sgshapiro#define TO_ACONNECT 0x23 490990792Sgshapiro { "aconnect", TO_ACONNECT }, 4910132943Sgshapiro#define TO_QUEUEWARN_DSN 0x24 4911112810Sgshapiro { "queuewarn.dsn", TO_QUEUEWARN_DSN }, 4912132943Sgshapiro#define TO_QUEUERETURN_DSN 0x25 4913112810Sgshapiro { "queuereturn.dsn", TO_QUEUERETURN_DSN }, 491464562Sgshapiro { NULL, 0 }, 491564562Sgshapiro}; 491664562Sgshapiro 491764562Sgshapiro 491864562Sgshapirostatic void 491964562Sgshapirosettimeout(name, val, sticky) 492064562Sgshapiro char *name; 492164562Sgshapiro char *val; 492264562Sgshapiro bool sticky; 492364562Sgshapiro{ 492464562Sgshapiro register struct timeoutinfo *to; 492590792Sgshapiro int i, addopts; 492664562Sgshapiro time_t toval; 492764562Sgshapiro 492864562Sgshapiro if (tTd(37, 2)) 492990792Sgshapiro sm_dprintf("settimeout(%s = %s)", name, val); 493064562Sgshapiro 493164562Sgshapiro for (to = TimeOutTab; to->to_name != NULL; to++) 493264562Sgshapiro { 493390792Sgshapiro if (sm_strcasecmp(to->to_name, name) == 0) 493464562Sgshapiro break; 493564562Sgshapiro } 493664562Sgshapiro 493764562Sgshapiro if (to->to_name == NULL) 493871345Sgshapiro { 493971345Sgshapiro errno = 0; /* avoid bogus error text */ 494064562Sgshapiro syserr("settimeout: invalid timeout %s", name); 494171345Sgshapiro return; 494271345Sgshapiro } 494364562Sgshapiro 494464562Sgshapiro /* 494564562Sgshapiro ** See if this option is preset for us. 494664562Sgshapiro */ 494764562Sgshapiro 494864562Sgshapiro if (!sticky && bitnset(to->to_code, StickyTimeoutOpt)) 494964562Sgshapiro { 495064562Sgshapiro if (tTd(37, 2)) 495190792Sgshapiro sm_dprintf(" (ignored)\n"); 495264562Sgshapiro return; 495364562Sgshapiro } 495464562Sgshapiro 495564562Sgshapiro if (tTd(37, 2)) 495690792Sgshapiro sm_dprintf("\n"); 495764562Sgshapiro 495864562Sgshapiro toval = convtime(val, 'm'); 495980785Sgshapiro addopts = 0; 496064562Sgshapiro 496164562Sgshapiro switch (to->to_code) 496264562Sgshapiro { 496364562Sgshapiro case TO_INITIAL: 496464562Sgshapiro TimeOuts.to_initial = toval; 496564562Sgshapiro break; 496664562Sgshapiro 496764562Sgshapiro case TO_MAIL: 496864562Sgshapiro TimeOuts.to_mail = toval; 496964562Sgshapiro break; 497064562Sgshapiro 497164562Sgshapiro case TO_RCPT: 497264562Sgshapiro TimeOuts.to_rcpt = toval; 497364562Sgshapiro break; 497464562Sgshapiro 497564562Sgshapiro case TO_DATAINIT: 497664562Sgshapiro TimeOuts.to_datainit = toval; 497764562Sgshapiro break; 497864562Sgshapiro 497964562Sgshapiro case TO_DATABLOCK: 498064562Sgshapiro TimeOuts.to_datablock = toval; 498164562Sgshapiro break; 498264562Sgshapiro 498364562Sgshapiro case TO_DATAFINAL: 498464562Sgshapiro TimeOuts.to_datafinal = toval; 498564562Sgshapiro break; 498664562Sgshapiro 498764562Sgshapiro case TO_COMMAND: 498864562Sgshapiro TimeOuts.to_nextcommand = toval; 498964562Sgshapiro break; 499064562Sgshapiro 499164562Sgshapiro case TO_RSET: 499264562Sgshapiro TimeOuts.to_rset = toval; 499364562Sgshapiro break; 499464562Sgshapiro 499564562Sgshapiro case TO_HELO: 499664562Sgshapiro TimeOuts.to_helo = toval; 499764562Sgshapiro break; 499864562Sgshapiro 499964562Sgshapiro case TO_QUIT: 500064562Sgshapiro TimeOuts.to_quit = toval; 500164562Sgshapiro break; 500264562Sgshapiro 500364562Sgshapiro case TO_MISC: 500464562Sgshapiro TimeOuts.to_miscshort = toval; 500564562Sgshapiro break; 500664562Sgshapiro 500764562Sgshapiro case TO_IDENT: 500864562Sgshapiro TimeOuts.to_ident = toval; 500964562Sgshapiro break; 501064562Sgshapiro 501164562Sgshapiro case TO_FILEOPEN: 501264562Sgshapiro TimeOuts.to_fileopen = toval; 501364562Sgshapiro break; 501464562Sgshapiro 501564562Sgshapiro case TO_CONNECT: 501664562Sgshapiro TimeOuts.to_connect = toval; 501764562Sgshapiro break; 501864562Sgshapiro 501964562Sgshapiro case TO_ICONNECT: 502064562Sgshapiro TimeOuts.to_iconnect = toval; 502164562Sgshapiro break; 502264562Sgshapiro 502390792Sgshapiro case TO_ACONNECT: 502490792Sgshapiro TimeOuts.to_aconnect = toval; 502590792Sgshapiro break; 502690792Sgshapiro 502764562Sgshapiro case TO_QUEUEWARN: 502864562Sgshapiro toval = convtime(val, 'h'); 502964562Sgshapiro TimeOuts.to_q_warning[TOC_NORMAL] = toval; 503064562Sgshapiro TimeOuts.to_q_warning[TOC_URGENT] = toval; 503164562Sgshapiro TimeOuts.to_q_warning[TOC_NONURGENT] = toval; 5032112810Sgshapiro TimeOuts.to_q_warning[TOC_DSN] = toval; 503380785Sgshapiro addopts = 2; 503464562Sgshapiro break; 503564562Sgshapiro 503664562Sgshapiro case TO_QUEUEWARN_NORMAL: 503764562Sgshapiro toval = convtime(val, 'h'); 503864562Sgshapiro TimeOuts.to_q_warning[TOC_NORMAL] = toval; 503964562Sgshapiro break; 504064562Sgshapiro 504164562Sgshapiro case TO_QUEUEWARN_URGENT: 504264562Sgshapiro toval = convtime(val, 'h'); 504364562Sgshapiro TimeOuts.to_q_warning[TOC_URGENT] = toval; 504464562Sgshapiro break; 504564562Sgshapiro 504664562Sgshapiro case TO_QUEUEWARN_NON_URGENT: 504764562Sgshapiro toval = convtime(val, 'h'); 504864562Sgshapiro TimeOuts.to_q_warning[TOC_NONURGENT] = toval; 504964562Sgshapiro break; 505064562Sgshapiro 5051112810Sgshapiro case TO_QUEUEWARN_DSN: 5052112810Sgshapiro toval = convtime(val, 'h'); 5053112810Sgshapiro TimeOuts.to_q_warning[TOC_DSN] = toval; 5054112810Sgshapiro break; 5055112810Sgshapiro 505664562Sgshapiro case TO_QUEUERETURN: 505764562Sgshapiro toval = convtime(val, 'd'); 505864562Sgshapiro TimeOuts.to_q_return[TOC_NORMAL] = toval; 505964562Sgshapiro TimeOuts.to_q_return[TOC_URGENT] = toval; 506064562Sgshapiro TimeOuts.to_q_return[TOC_NONURGENT] = toval; 5061112810Sgshapiro TimeOuts.to_q_return[TOC_DSN] = toval; 506280785Sgshapiro addopts = 2; 506364562Sgshapiro break; 506464562Sgshapiro 506564562Sgshapiro case TO_QUEUERETURN_NORMAL: 506664562Sgshapiro toval = convtime(val, 'd'); 506764562Sgshapiro TimeOuts.to_q_return[TOC_NORMAL] = toval; 506864562Sgshapiro break; 506964562Sgshapiro 507064562Sgshapiro case TO_QUEUERETURN_URGENT: 507164562Sgshapiro toval = convtime(val, 'd'); 507264562Sgshapiro TimeOuts.to_q_return[TOC_URGENT] = toval; 507364562Sgshapiro break; 507464562Sgshapiro 507564562Sgshapiro case TO_QUEUERETURN_NON_URGENT: 507664562Sgshapiro toval = convtime(val, 'd'); 507764562Sgshapiro TimeOuts.to_q_return[TOC_NONURGENT] = toval; 507864562Sgshapiro break; 507964562Sgshapiro 5080112810Sgshapiro case TO_QUEUERETURN_DSN: 5081112810Sgshapiro toval = convtime(val, 'd'); 5082112810Sgshapiro TimeOuts.to_q_return[TOC_DSN] = toval; 5083112810Sgshapiro break; 5084112810Sgshapiro 508564562Sgshapiro case TO_HOSTSTATUS: 508664562Sgshapiro MciInfoTimeout = toval; 508764562Sgshapiro break; 508864562Sgshapiro 508964562Sgshapiro case TO_RESOLVER_RETRANS: 509064562Sgshapiro toval = convtime(val, 's'); 509164562Sgshapiro TimeOuts.res_retrans[RES_TO_DEFAULT] = toval; 509264562Sgshapiro TimeOuts.res_retrans[RES_TO_FIRST] = toval; 509364562Sgshapiro TimeOuts.res_retrans[RES_TO_NORMAL] = toval; 509480785Sgshapiro addopts = 2; 509564562Sgshapiro break; 509664562Sgshapiro 509764562Sgshapiro case TO_RESOLVER_RETRY: 509864562Sgshapiro i = atoi(val); 509964562Sgshapiro TimeOuts.res_retry[RES_TO_DEFAULT] = i; 510064562Sgshapiro TimeOuts.res_retry[RES_TO_FIRST] = i; 510164562Sgshapiro TimeOuts.res_retry[RES_TO_NORMAL] = i; 510280785Sgshapiro addopts = 2; 510364562Sgshapiro break; 510464562Sgshapiro 510564562Sgshapiro case TO_RESOLVER_RETRANS_NORMAL: 510664562Sgshapiro TimeOuts.res_retrans[RES_TO_NORMAL] = convtime(val, 's'); 510764562Sgshapiro break; 510864562Sgshapiro 510964562Sgshapiro case TO_RESOLVER_RETRY_NORMAL: 511064562Sgshapiro TimeOuts.res_retry[RES_TO_NORMAL] = atoi(val); 511164562Sgshapiro break; 511264562Sgshapiro 511364562Sgshapiro case TO_RESOLVER_RETRANS_FIRST: 511464562Sgshapiro TimeOuts.res_retrans[RES_TO_FIRST] = convtime(val, 's'); 511564562Sgshapiro break; 511664562Sgshapiro 511764562Sgshapiro case TO_RESOLVER_RETRY_FIRST: 511864562Sgshapiro TimeOuts.res_retry[RES_TO_FIRST] = atoi(val); 511964562Sgshapiro break; 512064562Sgshapiro 512164562Sgshapiro case TO_CONTROL: 512264562Sgshapiro TimeOuts.to_control = toval; 512364562Sgshapiro break; 512464562Sgshapiro 512590792Sgshapiro case TO_LHLO: 512690792Sgshapiro TimeOuts.to_lhlo = toval; 512790792Sgshapiro break; 512890792Sgshapiro 512990792Sgshapiro#if SASL 513090792Sgshapiro case TO_AUTH: 513190792Sgshapiro TimeOuts.to_auth = toval; 513290792Sgshapiro break; 513390792Sgshapiro#endif /* SASL */ 513490792Sgshapiro 513590792Sgshapiro#if STARTTLS 513690792Sgshapiro case TO_STARTTLS: 513790792Sgshapiro TimeOuts.to_starttls = toval; 513890792Sgshapiro break; 513990792Sgshapiro#endif /* STARTTLS */ 514090792Sgshapiro 514164562Sgshapiro default: 514264562Sgshapiro syserr("settimeout: invalid timeout %s", name); 514364562Sgshapiro break; 514464562Sgshapiro } 514564562Sgshapiro 514664562Sgshapiro if (sticky) 514780785Sgshapiro { 514880785Sgshapiro for (i = 0; i <= addopts; i++) 514980785Sgshapiro setbitn(to->to_code + i, StickyTimeoutOpt); 515080785Sgshapiro } 515164562Sgshapiro} 515290792Sgshapiro/* 515338032Speter** INITTIMEOUTS -- parse and set timeout values 515438032Speter** 515538032Speter** Parameters: 515638032Speter** val -- a pointer to the values. If NULL, do initial 515738032Speter** settings. 515864562Sgshapiro** sticky -- if set, don't let other setoptions override 515964562Sgshapiro** this suboption value. 516038032Speter** 516138032Speter** Returns: 516238032Speter** none. 516338032Speter** 516438032Speter** Side Effects: 516538032Speter** Initializes the TimeOuts structure 516638032Speter*/ 516738032Speter 516838032Spetervoid 516964562Sgshapiroinittimeouts(val, sticky) 517038032Speter register char *val; 517164562Sgshapiro bool sticky; 517238032Speter{ 517338032Speter register char *p; 517438032Speter 517538032Speter if (tTd(37, 2)) 517690792Sgshapiro sm_dprintf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val); 517738032Speter if (val == NULL) 517838032Speter { 517938032Speter TimeOuts.to_connect = (time_t) 0 SECONDS; 518090792Sgshapiro TimeOuts.to_aconnect = (time_t) 0 SECONDS; 518194334Sgshapiro TimeOuts.to_iconnect = (time_t) 0 SECONDS; 518238032Speter TimeOuts.to_initial = (time_t) 5 MINUTES; 518338032Speter TimeOuts.to_helo = (time_t) 5 MINUTES; 518438032Speter TimeOuts.to_mail = (time_t) 10 MINUTES; 518538032Speter TimeOuts.to_rcpt = (time_t) 1 HOUR; 518638032Speter TimeOuts.to_datainit = (time_t) 5 MINUTES; 518738032Speter TimeOuts.to_datablock = (time_t) 1 HOUR; 518838032Speter TimeOuts.to_datafinal = (time_t) 1 HOUR; 518938032Speter TimeOuts.to_rset = (time_t) 5 MINUTES; 519038032Speter TimeOuts.to_quit = (time_t) 2 MINUTES; 519138032Speter TimeOuts.to_nextcommand = (time_t) 1 HOUR; 519238032Speter TimeOuts.to_miscshort = (time_t) 2 MINUTES; 519338032Speter#if IDENTPROTO 519464562Sgshapiro TimeOuts.to_ident = (time_t) 5 SECONDS; 519564562Sgshapiro#else /* IDENTPROTO */ 519638032Speter TimeOuts.to_ident = (time_t) 0 SECONDS; 519764562Sgshapiro#endif /* IDENTPROTO */ 519838032Speter TimeOuts.to_fileopen = (time_t) 60 SECONDS; 519964562Sgshapiro TimeOuts.to_control = (time_t) 2 MINUTES; 520090792Sgshapiro TimeOuts.to_lhlo = (time_t) 2 MINUTES; 520190792Sgshapiro#if SASL 520290792Sgshapiro TimeOuts.to_auth = (time_t) 10 MINUTES; 520390792Sgshapiro#endif /* SASL */ 520490792Sgshapiro#if STARTTLS 520590792Sgshapiro TimeOuts.to_starttls = (time_t) 1 HOUR; 520690792Sgshapiro#endif /* STARTTLS */ 520738032Speter if (tTd(37, 5)) 520838032Speter { 520990792Sgshapiro sm_dprintf("Timeouts:\n"); 521090792Sgshapiro sm_dprintf(" connect = %ld\n", 521190792Sgshapiro (long) TimeOuts.to_connect); 521290792Sgshapiro sm_dprintf(" aconnect = %ld\n", 521390792Sgshapiro (long) TimeOuts.to_aconnect); 521490792Sgshapiro sm_dprintf(" initial = %ld\n", 521590792Sgshapiro (long) TimeOuts.to_initial); 521690792Sgshapiro sm_dprintf(" helo = %ld\n", (long) TimeOuts.to_helo); 521790792Sgshapiro sm_dprintf(" mail = %ld\n", (long) TimeOuts.to_mail); 521890792Sgshapiro sm_dprintf(" rcpt = %ld\n", (long) TimeOuts.to_rcpt); 521990792Sgshapiro sm_dprintf(" datainit = %ld\n", 522090792Sgshapiro (long) TimeOuts.to_datainit); 522190792Sgshapiro sm_dprintf(" datablock = %ld\n", 522290792Sgshapiro (long) TimeOuts.to_datablock); 522390792Sgshapiro sm_dprintf(" datafinal = %ld\n", 522490792Sgshapiro (long) TimeOuts.to_datafinal); 522590792Sgshapiro sm_dprintf(" rset = %ld\n", (long) TimeOuts.to_rset); 522690792Sgshapiro sm_dprintf(" quit = %ld\n", (long) TimeOuts.to_quit); 522790792Sgshapiro sm_dprintf(" nextcommand = %ld\n", 522890792Sgshapiro (long) TimeOuts.to_nextcommand); 522990792Sgshapiro sm_dprintf(" miscshort = %ld\n", 523090792Sgshapiro (long) TimeOuts.to_miscshort); 523190792Sgshapiro sm_dprintf(" ident = %ld\n", (long) TimeOuts.to_ident); 523290792Sgshapiro sm_dprintf(" fileopen = %ld\n", 523390792Sgshapiro (long) TimeOuts.to_fileopen); 523490792Sgshapiro sm_dprintf(" lhlo = %ld\n", 523590792Sgshapiro (long) TimeOuts.to_lhlo); 523690792Sgshapiro sm_dprintf(" control = %ld\n", 523790792Sgshapiro (long) TimeOuts.to_control); 523838032Speter } 523938032Speter return; 524038032Speter } 524138032Speter 524238032Speter for (;; val = p) 524338032Speter { 524438032Speter while (isascii(*val) && isspace(*val)) 524538032Speter val++; 524638032Speter if (*val == '\0') 524738032Speter break; 524838032Speter for (p = val; *p != '\0' && *p != ','; p++) 524938032Speter continue; 525038032Speter if (*p != '\0') 525138032Speter *p++ = '\0'; 525238032Speter 525338032Speter if (isascii(*val) && isdigit(*val)) 525438032Speter { 525538032Speter /* old syntax -- set everything */ 525638032Speter TimeOuts.to_mail = convtime(val, 'm'); 525738032Speter TimeOuts.to_rcpt = TimeOuts.to_mail; 525838032Speter TimeOuts.to_datainit = TimeOuts.to_mail; 525938032Speter TimeOuts.to_datablock = TimeOuts.to_mail; 526038032Speter TimeOuts.to_datafinal = TimeOuts.to_mail; 526138032Speter TimeOuts.to_nextcommand = TimeOuts.to_mail; 526264562Sgshapiro if (sticky) 526364562Sgshapiro { 526464562Sgshapiro setbitn(TO_MAIL, StickyTimeoutOpt); 526564562Sgshapiro setbitn(TO_RCPT, StickyTimeoutOpt); 526664562Sgshapiro setbitn(TO_DATAINIT, StickyTimeoutOpt); 526764562Sgshapiro setbitn(TO_DATABLOCK, StickyTimeoutOpt); 526864562Sgshapiro setbitn(TO_DATAFINAL, StickyTimeoutOpt); 526964562Sgshapiro setbitn(TO_COMMAND, StickyTimeoutOpt); 527064562Sgshapiro } 527138032Speter continue; 527238032Speter } 527338032Speter else 527438032Speter { 527538032Speter register char *q = strchr(val, ':'); 527638032Speter 527738032Speter if (q == NULL && (q = strchr(val, '=')) == NULL) 527838032Speter { 527938032Speter /* syntax error */ 528038032Speter continue; 528138032Speter } 528238032Speter *q++ = '\0'; 528364562Sgshapiro settimeout(val, q, sticky); 528438032Speter } 528538032Speter } 528638032Speter} 5287