1 /* 2 * Copyright (c) 1998-2013 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 16 SM_RCSID("@(#)$Id: conf.c,v 8.1192 2014-01-27 18:23:21 ca Exp $") 17 18 #include <sm/sendmail.h> 19 #include <sendmail/pathnames.h> 20 #if NEWDB 21 # include "sm/bdb.h" 22 #endif /* NEWDB */ 23 24 #include <daemon.h> 25 #include "map.h" 26 27 #ifdef DEC 28 # if NETINET6 29 /* for the IPv6 device lookup */ 30 # define _SOCKADDR_LEN 31 # include <macros.h> 32 # endif /* NETINET6 */ 33 #endif /* DEC */ 34 35 # include <sys/ioctl.h> 36 # include <sys/param.h> 37 38 #include <limits.h> 39 #if NETINET || NETINET6 40 # include <arpa/inet.h> 41 #endif /* NETINET || NETINET6 */ 42 #if HASULIMIT && defined(HPUX11) 43 # include <ulimit.h> 44 #endif /* HASULIMIT && defined(HPUX11) */ 45 46 static void setupmaps __P((void)); 47 static void setupmailers __P((void)); 48 static void setupqueues __P((void)); 49 static int get_num_procs_online __P((void)); 50 static int add_hostnames __P((SOCKADDR *)); 51 52 #if NETINET6 && NEEDSGETIPNODE 53 static struct hostent *sm_getipnodebyname __P((const char *, int, int, int *)); 54 static struct hostent *sm_getipnodebyaddr __P((const void *, size_t, int, int *)); 55 #else /* NETINET6 && NEEDSGETIPNODE */ 56 #define sm_getipnodebyname getipnodebyname 57 #define sm_getipnodebyaddr getipnodebyaddr 58 #endif /* NETINET6 && NEEDSGETIPNODE */ 59 60 61 /* 62 ** CONF.C -- Sendmail Configuration Tables. 63 ** 64 ** Defines the configuration of this installation. 65 ** 66 ** Configuration Variables: 67 ** HdrInfo -- a table describing well-known header fields. 68 ** Each entry has the field name and some flags, 69 ** which are described in sendmail.h. 70 ** 71 ** Notes: 72 ** I have tried to put almost all the reasonable 73 ** configuration information into the configuration 74 ** file read at runtime. My intent is that anything 75 ** here is a function of the version of UNIX you 76 ** are running, or is really static -- for example 77 ** the headers are a superset of widely used 78 ** protocols. If you find yourself playing with 79 ** this file too much, you may be making a mistake! 80 */ 81 82 83 /* 84 ** Header info table 85 ** Final (null) entry contains the flags used for any other field. 86 ** 87 ** Not all of these are actually handled specially by sendmail 88 ** at this time. They are included as placeholders, to let 89 ** you know that "someday" I intend to have sendmail do 90 ** something with them. 91 */ 92 93 struct hdrinfo HdrInfo[] = 94 { 95 /* originator fields, most to least significant */ 96 { "resent-sender", H_FROM|H_RESENT, NULL }, 97 { "resent-from", H_FROM|H_RESENT, NULL }, 98 { "resent-reply-to", H_FROM|H_RESENT, NULL }, 99 { "sender", H_FROM, NULL }, 100 { "from", H_FROM, NULL }, 101 { "reply-to", H_FROM, NULL }, 102 { "errors-to", H_FROM|H_ERRORSTO, NULL }, 103 { "full-name", H_ACHECK, NULL }, 104 { "return-receipt-to", H_RECEIPTTO, NULL }, 105 { "delivery-receipt-to", H_RECEIPTTO, NULL }, 106 { "disposition-notification-to", H_FROM, NULL }, 107 108 /* destination fields */ 109 { "to", H_RCPT, NULL }, 110 { "resent-to", H_RCPT|H_RESENT, NULL }, 111 { "cc", H_RCPT, NULL }, 112 { "resent-cc", H_RCPT|H_RESENT, NULL }, 113 { "bcc", H_RCPT|H_BCC, NULL }, 114 { "resent-bcc", H_RCPT|H_BCC|H_RESENT, NULL }, 115 { "apparently-to", H_RCPT, NULL }, 116 117 /* message identification and control */ 118 { "message-id", 0, NULL }, 119 { "resent-message-id", H_RESENT, NULL }, 120 { "message", H_EOH, NULL }, 121 { "text", H_EOH, NULL }, 122 123 /* date fields */ 124 { "date", 0, NULL }, 125 { "resent-date", H_RESENT, NULL }, 126 127 /* trace fields */ 128 { "received", H_TRACE|H_FORCE, NULL }, 129 { "x400-received", H_TRACE|H_FORCE, NULL }, 130 { "via", H_TRACE|H_FORCE, NULL }, 131 { "mail-from", H_TRACE|H_FORCE, NULL }, 132 133 /* miscellaneous fields */ 134 { "comments", H_FORCE|H_ENCODABLE, NULL }, 135 { "return-path", H_FORCE|H_ACHECK|H_BINDLATE, NULL }, 136 { "content-transfer-encoding", H_CTE, NULL }, 137 { "content-type", H_CTYPE, NULL }, 138 { "content-length", H_ACHECK, NULL }, 139 { "subject", H_ENCODABLE, NULL }, 140 { "x-authentication-warning", H_FORCE, NULL }, 141 142 { NULL, 0, NULL } 143 }; 144 145 146 147 /* 148 ** Privacy values 149 */ 150 151 struct prival PrivacyValues[] = 152 { 153 { "public", PRIV_PUBLIC }, 154 { "needmailhelo", PRIV_NEEDMAILHELO }, 155 { "needexpnhelo", PRIV_NEEDEXPNHELO }, 156 { "needvrfyhelo", PRIV_NEEDVRFYHELO }, 157 { "noexpn", PRIV_NOEXPN }, 158 { "novrfy", PRIV_NOVRFY }, 159 { "restrictexpand", PRIV_RESTRICTEXPAND }, 160 { "restrictmailq", PRIV_RESTRICTMAILQ }, 161 { "restrictqrun", PRIV_RESTRICTQRUN }, 162 { "noetrn", PRIV_NOETRN }, 163 { "noverb", PRIV_NOVERB }, 164 { "authwarnings", PRIV_AUTHWARNINGS }, 165 { "noreceipts", PRIV_NORECEIPTS }, 166 { "nobodyreturn", PRIV_NOBODYRETN }, 167 { "goaway", PRIV_GOAWAY }, 168 { "noactualrecipient", PRIV_NOACTUALRECIPIENT }, 169 { NULL, 0 } 170 }; 171 172 /* 173 ** DontBlameSendmail values 174 */ 175 176 struct dbsval DontBlameSendmailValues[] = 177 { 178 { "safe", DBS_SAFE }, 179 { "assumesafechown", DBS_ASSUMESAFECHOWN }, 180 { "groupwritabledirpathsafe", DBS_GROUPWRITABLEDIRPATHSAFE }, 181 { "groupwritableforwardfilesafe", 182 DBS_GROUPWRITABLEFORWARDFILESAFE }, 183 { "groupwritableincludefilesafe", 184 DBS_GROUPWRITABLEINCLUDEFILESAFE }, 185 { "groupwritablealiasfile", DBS_GROUPWRITABLEALIASFILE }, 186 { "worldwritablealiasfile", DBS_WORLDWRITABLEALIASFILE }, 187 { "forwardfileinunsafedirpath", DBS_FORWARDFILEINUNSAFEDIRPATH }, 188 { "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH }, 189 { "mapinunsafedirpath", DBS_MAPINUNSAFEDIRPATH }, 190 { "linkedaliasfileinwritabledir", 191 DBS_LINKEDALIASFILEINWRITABLEDIR }, 192 { "linkedclassfileinwritabledir", 193 DBS_LINKEDCLASSFILEINWRITABLEDIR }, 194 { "linkedforwardfileinwritabledir", 195 DBS_LINKEDFORWARDFILEINWRITABLEDIR }, 196 { "linkedincludefileinwritabledir", 197 DBS_LINKEDINCLUDEFILEINWRITABLEDIR }, 198 { "linkedmapinwritabledir", DBS_LINKEDMAPINWRITABLEDIR }, 199 { "linkedserviceswitchfileinwritabledir", 200 DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR }, 201 { "filedeliverytohardlink", DBS_FILEDELIVERYTOHARDLINK }, 202 { "filedeliverytosymlink", DBS_FILEDELIVERYTOSYMLINK }, 203 { "writemaptohardlink", DBS_WRITEMAPTOHARDLINK }, 204 { "writemaptosymlink", DBS_WRITEMAPTOSYMLINK }, 205 { "writestatstohardlink", DBS_WRITESTATSTOHARDLINK }, 206 { "writestatstosymlink", DBS_WRITESTATSTOSYMLINK }, 207 { "forwardfileingroupwritabledirpath", 208 DBS_FORWARDFILEINGROUPWRITABLEDIRPATH }, 209 { "includefileingroupwritabledirpath", 210 DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH }, 211 { "classfileinunsafedirpath", DBS_CLASSFILEINUNSAFEDIRPATH }, 212 { "errorheaderinunsafedirpath", DBS_ERRORHEADERINUNSAFEDIRPATH }, 213 { "helpfileinunsafedirpath", DBS_HELPFILEINUNSAFEDIRPATH }, 214 { "forwardfileinunsafedirpathsafe", 215 DBS_FORWARDFILEINUNSAFEDIRPATHSAFE }, 216 { "includefileinunsafedirpathsafe", 217 DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE }, 218 { "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH }, 219 { "runwritableprogram", DBS_RUNWRITABLEPROGRAM }, 220 { "nonrootsafeaddr", DBS_NONROOTSAFEADDR }, 221 { "truststickybit", DBS_TRUSTSTICKYBIT }, 222 { "dontwarnforwardfileinunsafedirpath", 223 DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH }, 224 { "insufficiententropy", DBS_INSUFFICIENTENTROPY }, 225 { "groupreadablesasldbfile", DBS_GROUPREADABLESASLDBFILE }, 226 { "groupwritablesasldbfile", DBS_GROUPWRITABLESASLDBFILE }, 227 { "groupwritableforwardfile", DBS_GROUPWRITABLEFORWARDFILE }, 228 { "groupwritableincludefile", DBS_GROUPWRITABLEINCLUDEFILE }, 229 { "worldwritableforwardfile", DBS_WORLDWRITABLEFORWARDFILE }, 230 { "worldwritableincludefile", DBS_WORLDWRITABLEINCLUDEFILE }, 231 { "groupreadablekeyfile", DBS_GROUPREADABLEKEYFILE }, 232 { "groupreadabledefaultauthinfofile", 233 DBS_GROUPREADABLEAUTHINFOFILE }, 234 { NULL, 0 } 235 }; 236 237 /* 238 ** Miscellaneous stuff. 239 */ 240 241 int DtableSize = 50; /* max open files; reset in 4.2bsd */ 242 /* 243 ** SETDEFAULTS -- set default values 244 ** 245 ** Some of these must be initialized using direct code since they 246 ** depend on run-time values. So let's do all of them this way. 247 ** 248 ** Parameters: 249 ** e -- the default envelope. 250 ** 251 ** Returns: 252 ** none. 253 ** 254 ** Side Effects: 255 ** Initializes a bunch of global variables to their 256 ** default values. 257 */ 258 259 #define MINUTES * 60 260 #define HOURS * 60 MINUTES 261 #define DAYS * 24 HOURS 262 263 #ifndef MAXRULERECURSION 264 # define MAXRULERECURSION 50 /* max ruleset recursion depth */ 265 #endif /* ! MAXRULERECURSION */ 266 267 void 268 setdefaults(e) 269 register ENVELOPE *e; 270 { 271 int i; 272 int numprocs; 273 struct passwd *pw; 274 275 numprocs = get_num_procs_online(); 276 SpaceSub = ' '; /* option B */ 277 QueueLA = 8 * numprocs; /* option x */ 278 RefuseLA = 12 * numprocs; /* option X */ 279 WkRecipFact = 30000L; /* option y */ 280 WkClassFact = 1800L; /* option z */ 281 WkTimeFact = 90000L; /* option Z */ 282 QueueFactor = WkRecipFact * 20; /* option q */ 283 QueueMode = QM_NORMAL; /* what queue items to act upon */ 284 FileMode = (RealUid != geteuid()) ? 0644 : 0600; 285 /* option F */ 286 QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600; 287 /* option QueueFileMode */ 288 289 if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) || 290 ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) || 291 ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0)) 292 { 293 DefUid = pw->pw_uid; /* option u */ 294 DefGid = pw->pw_gid; /* option g */ 295 DefUser = newstr(pw->pw_name); 296 } 297 else 298 { 299 DefUid = 1; /* option u */ 300 DefGid = 1; /* option g */ 301 setdefuser(); 302 } 303 TrustedUid = 0; 304 if (tTd(37, 4)) 305 sm_dprintf("setdefaults: DefUser=%s, DefUid=%ld, DefGid=%ld\n", 306 DefUser != NULL ? DefUser : "<1:1>", 307 (long) DefUid, (long) DefGid); 308 CheckpointInterval = 10; /* option C */ 309 MaxHopCount = 25; /* option h */ 310 set_delivery_mode(SM_FORK, e); /* option d */ 311 e->e_errormode = EM_PRINT; /* option e */ 312 e->e_qgrp = NOQGRP; 313 e->e_qdir = NOQDIR; 314 e->e_xfqgrp = NOQGRP; 315 e->e_xfqdir = NOQDIR; 316 e->e_ctime = curtime(); 317 SevenBitInput = false; /* option 7 */ 318 MaxMciCache = 1; /* option k */ 319 MciCacheTimeout = 5 MINUTES; /* option K */ 320 LogLevel = 9; /* option L */ 321 #if MILTER 322 MilterLogLevel = -1; 323 #endif /* MILTER */ 324 inittimeouts(NULL, false); /* option r */ 325 PrivacyFlags = PRIV_PUBLIC; /* option p */ 326 MeToo = true; /* option m */ 327 SendMIMEErrors = true; /* option f */ 328 SuperSafe = SAFE_REALLY; /* option s */ 329 clrbitmap(DontBlameSendmail); /* DontBlameSendmail option */ 330 #if MIME8TO7 331 MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */ 332 #else /* MIME8TO7 */ 333 MimeMode = MM_PASS8BIT; 334 #endif /* MIME8TO7 */ 335 for (i = 0; i < MAXTOCLASS; i++) 336 { 337 TimeOuts.to_q_return[i] = 5 DAYS; /* option T */ 338 TimeOuts.to_q_warning[i] = 0; /* option T */ 339 } 340 ServiceSwitchFile = "/etc/mail/service.switch"; 341 ServiceCacheMaxAge = (time_t) 10; 342 HostsFile = _PATH_HOSTS; 343 PidFile = newstr(_PATH_SENDMAILPID); 344 MustQuoteChars = "@,;:\\()[].'"; 345 MciInfoTimeout = 30 MINUTES; 346 MaxRuleRecursion = MAXRULERECURSION; 347 MaxAliasRecursion = 10; 348 MaxMacroRecursion = 10; 349 ColonOkInAddr = true; 350 DontLockReadFiles = true; 351 DontProbeInterfaces = DPI_PROBEALL; 352 DoubleBounceAddr = "postmaster"; 353 MaxHeadersLength = MAXHDRSLEN; 354 MaxMimeHeaderLength = MAXLINE; 355 MaxMimeFieldLength = MaxMimeHeaderLength / 2; 356 MaxForwardEntries = 0; 357 FastSplit = 1; 358 MaxNOOPCommands = MAXNOOPCOMMANDS; 359 #if SASL 360 AuthMechanisms = newstr(AUTH_MECHANISMS); 361 AuthRealm = NULL; 362 MaxSLBits = INT_MAX; 363 #endif /* SASL */ 364 #if STARTTLS 365 TLS_Srv_Opts = TLS_I_SRV; 366 if (NULL == EVP_digest) 367 EVP_digest = EVP_md5(); 368 Srv_SSL_Options = SSL_OP_ALL; 369 Clt_SSL_Options = SSL_OP_ALL 370 # ifdef SSL_OP_NO_SSLv2 371 | SSL_OP_NO_SSLv2 372 # endif 373 # ifdef SSL_OP_NO_TICKET 374 | SSL_OP_NO_TICKET 375 # endif 376 ; 377 # ifdef SSL_OP_TLSEXT_PADDING 378 /* SSL_OP_TLSEXT_PADDING breaks compatibility with some sites */ 379 Srv_SSL_Options &= ~SSL_OP_TLSEXT_PADDING; 380 Clt_SSL_Options &= ~SSL_OP_TLSEXT_PADDING; 381 # endif /* SSL_OP_TLSEXT_PADDING */ 382 #endif /* STARTTLS */ 383 #ifdef HESIOD_INIT 384 HesiodContext = NULL; 385 #endif /* HESIOD_INIT */ 386 #if NETINET6 387 /* Detect if IPv6 is available at run time */ 388 i = socket(AF_INET6, SOCK_STREAM, 0); 389 if (i >= 0) 390 { 391 InetMode = AF_INET6; 392 (void) close(i); 393 } 394 else 395 InetMode = AF_INET; 396 #if !IPV6_FULL 397 UseCompressedIPv6Addresses = true; 398 #endif 399 #else /* NETINET6 */ 400 InetMode = AF_INET; 401 #endif /* NETINET6 */ 402 ControlSocketName = NULL; 403 memset(&ConnectOnlyTo, '\0', sizeof(ConnectOnlyTo)); 404 DataFileBufferSize = 4096; 405 XscriptFileBufferSize = 4096; 406 for (i = 0; i < MAXRWSETS; i++) 407 RuleSetNames[i] = NULL; 408 #if MILTER 409 InputFilters[0] = NULL; 410 #endif /* MILTER */ 411 RejectLogInterval = 3 HOURS; 412 #if REQUIRES_DIR_FSYNC 413 RequiresDirfsync = true; 414 #endif /* REQUIRES_DIR_FSYNC */ 415 #if _FFR_RCPTTHROTDELAY 416 BadRcptThrottleDelay = 1; 417 #endif /* _FFR_RCPTTHROTDELAY */ 418 ConnectionRateWindowSize = 60; 419 #if _FFR_BOUNCE_QUEUE 420 BounceQueue = NOQGRP; 421 #endif /* _FFR_BOUNCE_QUEUE */ 422 setupmaps(); 423 setupqueues(); 424 setupmailers(); 425 setupheaders(); 426 } 427 428 429 /* 430 ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 431 */ 432 433 void 434 setdefuser() 435 { 436 struct passwd *defpwent; 437 static char defuserbuf[40]; 438 439 DefUser = defuserbuf; 440 defpwent = sm_getpwuid(DefUid); 441 (void) sm_strlcpy(defuserbuf, 442 (defpwent == NULL || defpwent->pw_name == NULL) 443 ? "nobody" : defpwent->pw_name, 444 sizeof(defuserbuf)); 445 if (tTd(37, 4)) 446 sm_dprintf("setdefuser: DefUid=%ld, DefUser=%s\n", 447 (long) DefUid, DefUser); 448 } 449 /* 450 ** SETUPQUEUES -- initialize default queues 451 ** 452 ** The mqueue QUEUE structure gets filled in after readcf() but 453 ** we need something to point to now for the mailer setup, 454 ** which use "mqueue" as default queue. 455 */ 456 457 static void 458 setupqueues() 459 { 460 char buf[100]; 461 462 MaxRunnersPerQueue = 1; 463 (void) sm_strlcpy(buf, "mqueue, P=/var/spool/mqueue", sizeof(buf)); 464 makequeue(buf, false); 465 } 466 /* 467 ** SETUPMAILERS -- initialize default mailers 468 */ 469 470 static void 471 setupmailers() 472 { 473 char buf[100]; 474 475 (void) sm_strlcpy(buf, "prog, P=/bin/sh, F=lsouDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u", 476 sizeof(buf)); 477 makemailer(buf); 478 479 (void) sm_strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE \201u", 480 sizeof(buf)); 481 makemailer(buf); 482 483 (void) sm_strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u", 484 sizeof(buf)); 485 makemailer(buf); 486 initerrmailers(); 487 } 488 /* 489 ** SETUPMAPS -- set up map classes 490 */ 491 492 #define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \ 493 { \ 494 extern bool parse __P((MAP *, char *)); \ 495 extern bool open __P((MAP *, int)); \ 496 extern void close __P((MAP *)); \ 497 extern char *lookup __P((MAP *, char *, char **, int *)); \ 498 extern void store __P((MAP *, char *, char *)); \ 499 s = stab(name, ST_MAPCLASS, ST_ENTER); \ 500 s->s_mapclass.map_cname = name; \ 501 s->s_mapclass.map_ext = ext; \ 502 s->s_mapclass.map_cflags = flags; \ 503 s->s_mapclass.map_parse = parse; \ 504 s->s_mapclass.map_open = open; \ 505 s->s_mapclass.map_close = close; \ 506 s->s_mapclass.map_lookup = lookup; \ 507 s->s_mapclass.map_store = store; \ 508 } 509 510 static void 511 setupmaps() 512 { 513 register STAB *s; 514 515 #if NEWDB 516 # if DB_VERSION_MAJOR > 1 517 int major_v, minor_v, patch_v; 518 519 (void) db_version(&major_v, &minor_v, &patch_v); 520 if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR) 521 { 522 errno = 0; 523 syserr("Berkeley DB version mismatch: compiled against %d.%d.%d, run-time linked against %d.%d.%d", 524 DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, 525 major_v, minor_v, patch_v); 526 } 527 # endif /* DB_VERSION_MAJOR > 1 */ 528 529 MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 530 map_parseargs, hash_map_open, db_map_close, 531 db_map_lookup, db_map_store); 532 533 MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 534 map_parseargs, bt_map_open, db_map_close, 535 db_map_lookup, db_map_store); 536 #endif /* NEWDB */ 537 538 #if NDBM 539 MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE, 540 map_parseargs, ndbm_map_open, ndbm_map_close, 541 ndbm_map_lookup, ndbm_map_store); 542 #endif /* NDBM */ 543 544 #if NIS 545 MAPDEF("nis", NULL, MCF_ALIASOK, 546 map_parseargs, nis_map_open, null_map_close, 547 nis_map_lookup, null_map_store); 548 #endif /* NIS */ 549 550 #if NISPLUS 551 MAPDEF("nisplus", NULL, MCF_ALIASOK, 552 map_parseargs, nisplus_map_open, null_map_close, 553 nisplus_map_lookup, null_map_store); 554 #endif /* NISPLUS */ 555 556 #if LDAPMAP 557 MAPDEF("ldap", NULL, MCF_ALIASOK|MCF_NOTPERSIST, 558 ldapmap_parseargs, ldapmap_open, ldapmap_close, 559 ldapmap_lookup, null_map_store); 560 #endif /* LDAPMAP */ 561 562 #if PH_MAP 563 MAPDEF("ph", NULL, MCF_NOTPERSIST, 564 ph_map_parseargs, ph_map_open, ph_map_close, 565 ph_map_lookup, null_map_store); 566 #endif /* PH_MAP */ 567 568 #if MAP_NSD 569 /* IRIX 6.5 nsd support */ 570 MAPDEF("nsd", NULL, MCF_ALIASOK, 571 map_parseargs, null_map_open, null_map_close, 572 nsd_map_lookup, null_map_store); 573 #endif /* MAP_NSD */ 574 575 #if HESIOD 576 MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY, 577 map_parseargs, hes_map_open, hes_map_close, 578 hes_map_lookup, null_map_store); 579 #endif /* HESIOD */ 580 581 #if NETINFO 582 MAPDEF("netinfo", NULL, MCF_ALIASOK, 583 map_parseargs, ni_map_open, null_map_close, 584 ni_map_lookup, null_map_store); 585 #endif /* NETINFO */ 586 587 #if 0 588 MAPDEF("dns", NULL, 0, 589 dns_map_init, null_map_open, null_map_close, 590 dns_map_lookup, null_map_store); 591 #endif /* 0 */ 592 593 #if NAMED_BIND 594 # if DNSMAP 595 # if _FFR_DNSMAP_ALIASABLE 596 MAPDEF("dns", NULL, MCF_ALIASOK, 597 dns_map_parseargs, dns_map_open, null_map_close, 598 dns_map_lookup, null_map_store); 599 # else /* _FFR_DNSMAP_ALIASABLE */ 600 MAPDEF("dns", NULL, 0, 601 dns_map_parseargs, dns_map_open, null_map_close, 602 dns_map_lookup, null_map_store); 603 # endif /* _FFR_DNSMAP_ALIASABLE */ 604 # endif /* DNSMAP */ 605 #endif /* NAMED_BIND */ 606 607 #if NAMED_BIND 608 /* best MX DNS lookup */ 609 MAPDEF("bestmx", NULL, MCF_OPTFILE, 610 map_parseargs, null_map_open, null_map_close, 611 bestmx_map_lookup, null_map_store); 612 #endif /* NAMED_BIND */ 613 614 MAPDEF("host", NULL, 0, 615 host_map_init, null_map_open, null_map_close, 616 host_map_lookup, null_map_store); 617 618 MAPDEF("text", NULL, MCF_ALIASOK, 619 map_parseargs, text_map_open, null_map_close, 620 text_map_lookup, null_map_store); 621 622 MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY, 623 map_parseargs, stab_map_open, null_map_close, 624 stab_map_lookup, stab_map_store); 625 626 MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE, 627 map_parseargs, impl_map_open, impl_map_close, 628 impl_map_lookup, impl_map_store); 629 630 /* access to system passwd file */ 631 MAPDEF("user", NULL, MCF_OPTFILE, 632 map_parseargs, user_map_open, null_map_close, 633 user_map_lookup, null_map_store); 634 635 /* dequote map */ 636 MAPDEF("dequote", NULL, 0, 637 dequote_init, null_map_open, null_map_close, 638 dequote_map, null_map_store); 639 640 #if MAP_REGEX 641 MAPDEF("regex", NULL, 0, 642 regex_map_init, null_map_open, null_map_close, 643 regex_map_lookup, null_map_store); 644 #endif /* MAP_REGEX */ 645 646 #if USERDB 647 /* user database */ 648 MAPDEF("userdb", ".db", 0, 649 map_parseargs, null_map_open, null_map_close, 650 udb_map_lookup, null_map_store); 651 #endif /* USERDB */ 652 653 /* arbitrary programs */ 654 MAPDEF("program", NULL, MCF_ALIASOK, 655 map_parseargs, null_map_open, null_map_close, 656 prog_map_lookup, null_map_store); 657 658 /* sequenced maps */ 659 MAPDEF("sequence", NULL, MCF_ALIASOK, 660 seq_map_parse, null_map_open, null_map_close, 661 seq_map_lookup, seq_map_store); 662 663 /* switched interface to sequenced maps */ 664 MAPDEF("switch", NULL, MCF_ALIASOK, 665 map_parseargs, switch_map_open, null_map_close, 666 seq_map_lookup, seq_map_store); 667 668 /* null map lookup -- really for internal use only */ 669 MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE, 670 map_parseargs, null_map_open, null_map_close, 671 null_map_lookup, null_map_store); 672 673 /* syslog map -- logs information to syslog */ 674 MAPDEF("syslog", NULL, 0, 675 syslog_map_parseargs, null_map_open, null_map_close, 676 syslog_map_lookup, null_map_store); 677 678 /* macro storage map -- rulesets can set macros */ 679 MAPDEF("macro", NULL, 0, 680 dequote_init, null_map_open, null_map_close, 681 macro_map_lookup, null_map_store); 682 683 /* arithmetic map -- add/subtract/compare */ 684 MAPDEF("arith", NULL, 0, 685 dequote_init, null_map_open, null_map_close, 686 arith_map_lookup, null_map_store); 687 688 /* "arpa" map -- IP -> arpa */ 689 MAPDEF("arpa", NULL, 0, 690 dequote_init, null_map_open, null_map_close, 691 arpa_map_lookup, null_map_store); 692 693 #if SOCKETMAP 694 /* arbitrary daemons */ 695 MAPDEF("socket", NULL, MCF_ALIASOK, 696 map_parseargs, socket_map_open, socket_map_close, 697 socket_map_lookup, null_map_store); 698 #endif /* SOCKETMAP */ 699 700 #if _FFR_DPRINTF_MAP 701 /* dprintf map -- logs information to syslog */ 702 MAPDEF("dprintf", NULL, 0, 703 dprintf_map_parseargs, null_map_open, null_map_close, 704 dprintf_map_lookup, null_map_store); 705 #endif /* _FFR_DPRINTF_MAP */ 706 707 if (tTd(38, 2)) 708 { 709 /* bogus map -- always return tempfail */ 710 MAPDEF("bogus", NULL, MCF_ALIASOK|MCF_OPTFILE, 711 map_parseargs, null_map_open, null_map_close, 712 bogus_map_lookup, null_map_store); 713 } 714 } 715 716 #undef MAPDEF 717 /* 718 ** INITHOSTMAPS -- initial host-dependent maps 719 ** 720 ** This should act as an interface to any local service switch 721 ** provided by the host operating system. 722 ** 723 ** Parameters: 724 ** none 725 ** 726 ** Returns: 727 ** none 728 ** 729 ** Side Effects: 730 ** Should define maps "host" and "users" as necessary 731 ** for this OS. If they are not defined, they will get 732 ** a default value later. It should check to make sure 733 ** they are not defined first, since it's possible that 734 ** the config file has provided an override. 735 */ 736 737 void 738 inithostmaps() 739 { 740 register int i; 741 int nmaps; 742 char *maptype[MAXMAPSTACK]; 743 short mapreturn[MAXMAPACTIONS]; 744 char buf[MAXLINE]; 745 746 /* 747 ** Make sure we have a host map. 748 */ 749 750 if (stab("host", ST_MAP, ST_FIND) == NULL) 751 { 752 /* user didn't initialize: set up host map */ 753 (void) sm_strlcpy(buf, "host host", sizeof(buf)); 754 #if NAMED_BIND 755 if (ConfigLevel >= 2) 756 (void) sm_strlcat(buf, " -a. -D", sizeof(buf)); 757 #endif /* NAMED_BIND */ 758 (void) makemapentry(buf); 759 } 760 761 /* 762 ** Set up default aliases maps 763 */ 764 765 nmaps = switch_map_find("aliases", maptype, mapreturn); 766 for (i = 0; i < nmaps; i++) 767 { 768 if (strcmp(maptype[i], "files") == 0 && 769 stab("aliases.files", ST_MAP, ST_FIND) == NULL) 770 { 771 (void) sm_strlcpy(buf, "aliases.files null", 772 sizeof(buf)); 773 (void) makemapentry(buf); 774 } 775 #if NISPLUS 776 else if (strcmp(maptype[i], "nisplus") == 0 && 777 stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL) 778 { 779 (void) sm_strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir", 780 sizeof(buf)); 781 (void) makemapentry(buf); 782 } 783 #endif /* NISPLUS */ 784 #if NIS 785 else if (strcmp(maptype[i], "nis") == 0 && 786 stab("aliases.nis", ST_MAP, ST_FIND) == NULL) 787 { 788 (void) sm_strlcpy(buf, "aliases.nis nis mail.aliases", 789 sizeof(buf)); 790 (void) makemapentry(buf); 791 } 792 #endif /* NIS */ 793 #if NETINFO 794 else if (strcmp(maptype[i], "netinfo") == 0 && 795 stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL) 796 { 797 (void) sm_strlcpy(buf, "aliases.netinfo netinfo -z, /aliases", 798 sizeof(buf)); 799 (void) makemapentry(buf); 800 } 801 #endif /* NETINFO */ 802 #if HESIOD 803 else if (strcmp(maptype[i], "hesiod") == 0 && 804 stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL) 805 { 806 (void) sm_strlcpy(buf, "aliases.hesiod hesiod aliases", 807 sizeof(buf)); 808 (void) makemapentry(buf); 809 } 810 #endif /* HESIOD */ 811 #if LDAPMAP && defined(SUN_EXTENSIONS) && \ 812 defined(SUN_SIMPLIFIED_LDAP) && HASLDAPGETALIASBYNAME 813 else if (strcmp(maptype[i], "ldap") == 0 && 814 stab("aliases.ldap", ST_MAP, ST_FIND) == NULL) 815 { 816 (void) sm_strlcpy(buf, "aliases.ldap ldap -b . -h localhost -k mail=%0 -v mailgroup", 817 sizeof buf); 818 (void) makemapentry(buf); 819 } 820 #endif /* LDAPMAP && defined(SUN_EXTENSIONS) && ... */ 821 } 822 if (stab("aliases", ST_MAP, ST_FIND) == NULL) 823 { 824 (void) sm_strlcpy(buf, "aliases switch aliases", sizeof(buf)); 825 (void) makemapentry(buf); 826 } 827 } 828 829 /* 830 ** SWITCH_MAP_FIND -- find the list of types associated with a map 831 ** 832 ** This is the system-dependent interface to the service switch. 833 ** 834 ** Parameters: 835 ** service -- the name of the service of interest. 836 ** maptype -- an out-array of strings containing the types 837 ** of access to use for this service. There can 838 ** be at most MAXMAPSTACK types for a single service. 839 ** mapreturn -- an out-array of return information bitmaps 840 ** for the map. 841 ** 842 ** Returns: 843 ** The number of map types filled in, or -1 for failure. 844 ** 845 ** Side effects: 846 ** Preserves errno so nothing in the routine clobbers it. 847 */ 848 849 #if defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) 850 # define _USE_SUN_NSSWITCH_ 851 #endif /* defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) */ 852 853 #if _FFR_HPUX_NSSWITCH 854 # ifdef __hpux 855 # define _USE_SUN_NSSWITCH_ 856 # endif /* __hpux */ 857 #endif /* _FFR_HPUX_NSSWITCH */ 858 859 #ifdef _USE_SUN_NSSWITCH_ 860 # include <nsswitch.h> 861 #endif /* _USE_SUN_NSSWITCH_ */ 862 863 #if defined(ultrix) || (defined(__osf__) && defined(__alpha)) 864 # define _USE_DEC_SVC_CONF_ 865 #endif /* defined(ultrix) || (defined(__osf__) && defined(__alpha)) */ 866 867 #ifdef _USE_DEC_SVC_CONF_ 868 # include <sys/svcinfo.h> 869 #endif /* _USE_DEC_SVC_CONF_ */ 870 871 int 872 switch_map_find(service, maptype, mapreturn) 873 char *service; 874 char *maptype[MAXMAPSTACK]; 875 short mapreturn[MAXMAPACTIONS]; 876 { 877 int svcno = 0; 878 int save_errno = errno; 879 880 #ifdef _USE_SUN_NSSWITCH_ 881 struct __nsw_switchconfig *nsw_conf; 882 enum __nsw_parse_err pserr; 883 struct __nsw_lookup *lk; 884 static struct __nsw_lookup lkp0 = 885 { "files", {1, 0, 0, 0}, NULL, NULL }; 886 static struct __nsw_switchconfig lkp_default = 887 { 0, "sendmail", 3, &lkp0 }; 888 889 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 890 mapreturn[svcno] = 0; 891 892 if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL) 893 lk = lkp_default.lookups; 894 else 895 lk = nsw_conf->lookups; 896 svcno = 0; 897 while (lk != NULL && svcno < MAXMAPSTACK) 898 { 899 maptype[svcno] = lk->service_name; 900 if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN) 901 mapreturn[MA_NOTFOUND] |= 1 << svcno; 902 if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN) 903 mapreturn[MA_TRYAGAIN] |= 1 << svcno; 904 if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN) 905 mapreturn[MA_TRYAGAIN] |= 1 << svcno; 906 svcno++; 907 lk = lk->next; 908 } 909 errno = save_errno; 910 return svcno; 911 #endif /* _USE_SUN_NSSWITCH_ */ 912 913 #ifdef _USE_DEC_SVC_CONF_ 914 struct svcinfo *svcinfo; 915 int svc; 916 917 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 918 mapreturn[svcno] = 0; 919 920 svcinfo = getsvc(); 921 if (svcinfo == NULL) 922 goto punt; 923 if (strcmp(service, "hosts") == 0) 924 svc = SVC_HOSTS; 925 else if (strcmp(service, "aliases") == 0) 926 svc = SVC_ALIASES; 927 else if (strcmp(service, "passwd") == 0) 928 svc = SVC_PASSWD; 929 else 930 { 931 errno = save_errno; 932 return -1; 933 } 934 for (svcno = 0; svcno < SVC_PATHSIZE && svcno < MAXMAPSTACK; svcno++) 935 { 936 switch (svcinfo->svcpath[svc][svcno]) 937 { 938 case SVC_LOCAL: 939 maptype[svcno] = "files"; 940 break; 941 942 case SVC_YP: 943 maptype[svcno] = "nis"; 944 break; 945 946 case SVC_BIND: 947 maptype[svcno] = "dns"; 948 break; 949 950 # ifdef SVC_HESIOD 951 case SVC_HESIOD: 952 maptype[svcno] = "hesiod"; 953 break; 954 # endif /* SVC_HESIOD */ 955 956 case SVC_LAST: 957 errno = save_errno; 958 return svcno; 959 } 960 } 961 errno = save_errno; 962 return svcno; 963 #endif /* _USE_DEC_SVC_CONF_ */ 964 965 #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) 966 /* 967 ** Fall-back mechanism. 968 */ 969 970 STAB *st; 971 static time_t servicecachetime; /* time service switch was cached */ 972 time_t now = curtime(); 973 974 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 975 mapreturn[svcno] = 0; 976 977 if ((now - servicecachetime) > (time_t) ServiceCacheMaxAge) 978 { 979 /* (re)read service switch */ 980 register SM_FILE_T *fp; 981 long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK; 982 983 if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR, 984 DontBlameSendmail)) 985 sff |= SFF_NOWLINK; 986 987 if (ConfigFileRead) 988 servicecachetime = now; 989 fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff); 990 if (fp != NULL) 991 { 992 char buf[MAXLINE]; 993 994 while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf, 995 sizeof(buf)) >= 0) 996 { 997 register char *p; 998 999 p = strpbrk(buf, "#\n"); 1000 if (p != NULL) 1001 *p = '\0'; 1002 #ifndef SM_NSSWITCH_DELIMS 1003 # define SM_NSSWITCH_DELIMS " \t" 1004 #endif /* SM_NSSWITCH_DELIMS */ 1005 p = strpbrk(buf, SM_NSSWITCH_DELIMS); 1006 if (p != NULL) 1007 *p++ = '\0'; 1008 if (buf[0] == '\0') 1009 continue; 1010 if (p == NULL) 1011 { 1012 sm_syslog(LOG_ERR, NOQID, 1013 "Bad line on %.100s: %.100s", 1014 ServiceSwitchFile, 1015 buf); 1016 continue; 1017 } 1018 while (isascii(*p) && isspace(*p)) 1019 p++; 1020 if (*p == '\0') 1021 continue; 1022 1023 /* 1024 ** Find/allocate space for this service entry. 1025 ** Space for all of the service strings 1026 ** are allocated at once. This means 1027 ** that we only have to free the first 1028 ** one to free all of them. 1029 */ 1030 1031 st = stab(buf, ST_SERVICE, ST_ENTER); 1032 if (st->s_service[0] != NULL) 1033 sm_free((void *) st->s_service[0]); /* XXX */ 1034 p = newstr(p); 1035 for (svcno = 0; svcno < MAXMAPSTACK; ) 1036 { 1037 if (*p == '\0') 1038 break; 1039 st->s_service[svcno++] = p; 1040 p = strpbrk(p, " \t"); 1041 if (p == NULL) 1042 break; 1043 *p++ = '\0'; 1044 while (isascii(*p) && isspace(*p)) 1045 p++; 1046 } 1047 if (svcno < MAXMAPSTACK) 1048 st->s_service[svcno] = NULL; 1049 } 1050 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1051 } 1052 } 1053 1054 /* look up entry in cache */ 1055 st = stab(service, ST_SERVICE, ST_FIND); 1056 if (st != NULL && st->s_service[0] != NULL) 1057 { 1058 /* extract data */ 1059 svcno = 0; 1060 while (svcno < MAXMAPSTACK) 1061 { 1062 maptype[svcno] = st->s_service[svcno]; 1063 if (maptype[svcno++] == NULL) 1064 break; 1065 } 1066 errno = save_errno; 1067 return --svcno; 1068 } 1069 #endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */ 1070 1071 #if !defined(_USE_SUN_NSSWITCH_) 1072 /* if the service file doesn't work, use an absolute fallback */ 1073 # ifdef _USE_DEC_SVC_CONF_ 1074 punt: 1075 # endif /* _USE_DEC_SVC_CONF_ */ 1076 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 1077 mapreturn[svcno] = 0; 1078 svcno = 0; 1079 if (strcmp(service, "aliases") == 0) 1080 { 1081 maptype[svcno++] = "files"; 1082 # if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) 1083 maptype[svcno++] = "netinfo"; 1084 # endif /* defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) */ 1085 # ifdef AUTO_NIS_ALIASES 1086 # if NISPLUS 1087 maptype[svcno++] = "nisplus"; 1088 # endif /* NISPLUS */ 1089 # if NIS 1090 maptype[svcno++] = "nis"; 1091 # endif /* NIS */ 1092 # endif /* AUTO_NIS_ALIASES */ 1093 errno = save_errno; 1094 return svcno; 1095 } 1096 if (strcmp(service, "hosts") == 0) 1097 { 1098 # if NAMED_BIND 1099 maptype[svcno++] = "dns"; 1100 # else /* NAMED_BIND */ 1101 # if defined(sun) && !defined(BSD) 1102 /* SunOS */ 1103 maptype[svcno++] = "nis"; 1104 # endif /* defined(sun) && !defined(BSD) */ 1105 # endif /* NAMED_BIND */ 1106 # if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) 1107 maptype[svcno++] = "netinfo"; 1108 # endif /* defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) */ 1109 maptype[svcno++] = "files"; 1110 errno = save_errno; 1111 return svcno; 1112 } 1113 errno = save_errno; 1114 return -1; 1115 #endif /* !defined(_USE_SUN_NSSWITCH_) */ 1116 } 1117 /* 1118 ** USERNAME -- return the user id of the logged in user. 1119 ** 1120 ** Parameters: 1121 ** none. 1122 ** 1123 ** Returns: 1124 ** The login name of the logged in user. 1125 ** 1126 ** Side Effects: 1127 ** none. 1128 ** 1129 ** Notes: 1130 ** The return value is statically allocated. 1131 */ 1132 1133 char * 1134 username() 1135 { 1136 static char *myname = NULL; 1137 extern char *getlogin(); 1138 register struct passwd *pw; 1139 1140 /* cache the result */ 1141 if (myname == NULL) 1142 { 1143 myname = getlogin(); 1144 if (myname == NULL || myname[0] == '\0') 1145 { 1146 pw = sm_getpwuid(RealUid); 1147 if (pw != NULL) 1148 myname = pw->pw_name; 1149 } 1150 else 1151 { 1152 uid_t uid = RealUid; 1153 1154 if ((pw = sm_getpwnam(myname)) == NULL || 1155 (uid != 0 && uid != pw->pw_uid)) 1156 { 1157 pw = sm_getpwuid(uid); 1158 if (pw != NULL) 1159 myname = pw->pw_name; 1160 } 1161 } 1162 if (myname == NULL || myname[0] == '\0') 1163 { 1164 syserr("554 5.3.0 Who are you?"); 1165 myname = "postmaster"; 1166 } 1167 else if (strpbrk(myname, ",;:/|\"\\") != NULL) 1168 myname = addquotes(myname, NULL); 1169 else 1170 myname = sm_pstrdup_x(myname); 1171 } 1172 return myname; 1173 } 1174 /* 1175 ** TTYPATH -- Get the path of the user's tty 1176 ** 1177 ** Returns the pathname of the user's tty. Returns NULL if 1178 ** the user is not logged in or if s/he has write permission 1179 ** denied. 1180 ** 1181 ** Parameters: 1182 ** none 1183 ** 1184 ** Returns: 1185 ** pathname of the user's tty. 1186 ** NULL if not logged in or write permission denied. 1187 ** 1188 ** Side Effects: 1189 ** none. 1190 ** 1191 ** WARNING: 1192 ** Return value is in a local buffer. 1193 ** 1194 ** Called By: 1195 ** savemail 1196 */ 1197 1198 char * 1199 ttypath() 1200 { 1201 struct stat stbuf; 1202 register char *pathn; 1203 extern char *ttyname(); 1204 extern char *getlogin(); 1205 1206 /* compute the pathname of the controlling tty */ 1207 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 1208 (pathn = ttyname(0)) == NULL) 1209 { 1210 errno = 0; 1211 return NULL; 1212 } 1213 1214 /* see if we have write permission */ 1215 if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode)) 1216 { 1217 errno = 0; 1218 return NULL; 1219 } 1220 1221 /* see if the user is logged in */ 1222 if (getlogin() == NULL) 1223 return NULL; 1224 1225 /* looks good */ 1226 return pathn; 1227 } 1228 /* 1229 ** CHECKCOMPAT -- check for From and To person compatible. 1230 ** 1231 ** This routine can be supplied on a per-installation basis 1232 ** to determine whether a person is allowed to send a message. 1233 ** This allows restriction of certain types of internet 1234 ** forwarding or registration of users. 1235 ** 1236 ** If the hosts are found to be incompatible, an error 1237 ** message should be given using "usrerr" and an EX_ code 1238 ** should be returned. You can also set to->q_status to 1239 ** a DSN-style status code. 1240 ** 1241 ** EF_NO_BODY_RETN can be set in e->e_flags to suppress the 1242 ** body during the return-to-sender function; this should be done 1243 ** on huge messages. This bit may already be set by the ESMTP 1244 ** protocol. 1245 ** 1246 ** Parameters: 1247 ** to -- the person being sent to. 1248 ** 1249 ** Returns: 1250 ** an exit status 1251 ** 1252 ** Side Effects: 1253 ** none (unless you include the usrerr stuff) 1254 */ 1255 1256 int 1257 checkcompat(to, e) 1258 register ADDRESS *to; 1259 register ENVELOPE *e; 1260 { 1261 if (tTd(49, 1)) 1262 sm_dprintf("checkcompat(to=%s, from=%s)\n", 1263 to->q_paddr, e->e_from.q_paddr); 1264 1265 #ifdef EXAMPLE_CODE 1266 /* this code is intended as an example only */ 1267 register STAB *s; 1268 1269 s = stab("arpa", ST_MAILER, ST_FIND); 1270 if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 && 1271 to->q_mailer == s->s_mailer) 1272 { 1273 usrerr("553 No ARPA mail through this machine: see your system administration"); 1274 /* e->e_flags |= EF_NO_BODY_RETN; to suppress body on return */ 1275 to->q_status = "5.7.1"; 1276 return EX_UNAVAILABLE; 1277 } 1278 #endif /* EXAMPLE_CODE */ 1279 return EX_OK; 1280 } 1281 1282 #ifdef SUN_EXTENSIONS 1283 static void 1284 init_md_sun() 1285 { 1286 struct stat sbuf; 1287 1288 /* Check for large file descriptor */ 1289 if (fstat(fileno(stdin), &sbuf) < 0) 1290 { 1291 if (errno == EOVERFLOW) 1292 { 1293 perror("stdin"); 1294 exit(EX_NOINPUT); 1295 } 1296 } 1297 } 1298 #endif /* SUN_EXTENSIONS */ 1299 1300 /* 1301 ** INIT_MD -- do machine dependent initializations 1302 ** 1303 ** Systems that have global modes that should be set should do 1304 ** them here rather than in main. 1305 */ 1306 1307 #ifdef _AUX_SOURCE 1308 # include <compat.h> 1309 #endif /* _AUX_SOURCE */ 1310 1311 #if SHARE_V1 1312 # include <shares.h> 1313 #endif /* SHARE_V1 */ 1314 1315 void 1316 init_md(argc, argv) 1317 int argc; 1318 char **argv; 1319 { 1320 #ifdef _AUX_SOURCE 1321 setcompat(getcompat() | COMPAT_BSDPROT); 1322 #endif /* _AUX_SOURCE */ 1323 1324 #ifdef SUN_EXTENSIONS 1325 init_md_sun(); 1326 #endif /* SUN_EXTENSIONS */ 1327 1328 #if _CONVEX_SOURCE 1329 /* keep gethostby*() from stripping the local domain name */ 1330 set_domain_trim_off(); 1331 #endif /* _CONVEX_SOURCE */ 1332 #if defined(__QNX__) && !defined(__QNXNTO__) 1333 /* 1334 ** Due to QNX's network distributed nature, you can target a tcpip 1335 ** stack on a different node in the qnx network; this patch lets 1336 ** this feature work. The __sock_locate() must be done before the 1337 ** environment is clear. 1338 */ 1339 __sock_locate(); 1340 #endif /* __QNX__ */ 1341 #if SECUREWARE || defined(_SCO_unix_) 1342 set_auth_parameters(argc, argv); 1343 1344 # ifdef _SCO_unix_ 1345 /* 1346 ** This is required for highest security levels (the kernel 1347 ** won't let it call set*uid() or run setuid binaries without 1348 ** it). It may be necessary on other SECUREWARE systems. 1349 */ 1350 1351 if (getluid() == -1) 1352 setluid(0); 1353 # endif /* _SCO_unix_ */ 1354 #endif /* SECUREWARE || defined(_SCO_unix_) */ 1355 1356 1357 #ifdef VENDOR_DEFAULT 1358 VendorCode = VENDOR_DEFAULT; 1359 #else /* VENDOR_DEFAULT */ 1360 VendorCode = VENDOR_BERKELEY; 1361 #endif /* VENDOR_DEFAULT */ 1362 } 1363 /* 1364 ** INIT_VENDOR_MACROS -- vendor-dependent macro initializations 1365 ** 1366 ** Called once, on startup. 1367 ** 1368 ** Parameters: 1369 ** e -- the global envelope. 1370 ** 1371 ** Returns: 1372 ** none. 1373 ** 1374 ** Side Effects: 1375 ** vendor-dependent. 1376 */ 1377 1378 void 1379 init_vendor_macros(e) 1380 register ENVELOPE *e; 1381 { 1382 } 1383 /* 1384 ** GETLA -- get the current load average 1385 ** 1386 ** This code stolen from la.c. 1387 ** 1388 ** Parameters: 1389 ** none. 1390 ** 1391 ** Returns: 1392 ** The current load average as an integer. 1393 ** 1394 ** Side Effects: 1395 ** none. 1396 */ 1397 1398 /* try to guess what style of load average we have */ 1399 #define LA_ZERO 1 /* always return load average as zero */ 1400 #define LA_INT 2 /* read kmem for avenrun; interpret as long */ 1401 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 1402 #define LA_SUBR 4 /* call getloadavg */ 1403 #define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */ 1404 #define LA_SHORT 6 /* read kmem for avenrun; interpret as short */ 1405 #define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */ 1406 #define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */ 1407 #define LA_DGUX 9 /* special DGUX implementation */ 1408 #define LA_HPUX 10 /* special HPUX implementation */ 1409 #define LA_IRIX6 11 /* special IRIX 6.2 implementation */ 1410 #define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */ 1411 #define LA_DEVSHORT 13 /* read short from a device */ 1412 #define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */ 1413 #define LA_PSET 15 /* Solaris per-processor-set load average */ 1414 #define LA_LONGLONG 17 /* read kmem for avenrun; interpret as long long */ 1415 1416 /* do guesses based on general OS type */ 1417 #ifndef LA_TYPE 1418 # define LA_TYPE LA_ZERO 1419 #endif /* ! LA_TYPE */ 1420 1421 #ifndef FSHIFT 1422 # if defined(unixpc) 1423 # define FSHIFT 5 1424 # endif /* defined(unixpc) */ 1425 1426 # if defined(__alpha) || defined(IRIX) 1427 # define FSHIFT 10 1428 # endif /* defined(__alpha) || defined(IRIX) */ 1429 1430 #endif /* ! FSHIFT */ 1431 1432 #ifndef FSHIFT 1433 # define FSHIFT 8 1434 #endif /* ! FSHIFT */ 1435 1436 #ifndef FSCALE 1437 # define FSCALE (1 << FSHIFT) 1438 #endif /* ! FSCALE */ 1439 1440 #ifndef LA_AVENRUN 1441 # ifdef SYSTEM5 1442 # define LA_AVENRUN "avenrun" 1443 # else /* SYSTEM5 */ 1444 # define LA_AVENRUN "_avenrun" 1445 # endif /* SYSTEM5 */ 1446 #endif /* ! LA_AVENRUN */ 1447 1448 /* _PATH_KMEM should be defined in <paths.h> */ 1449 #ifndef _PATH_KMEM 1450 # define _PATH_KMEM "/dev/kmem" 1451 #endif /* ! _PATH_KMEM */ 1452 1453 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) 1454 1455 # include <nlist.h> 1456 1457 /* _PATH_UNIX should be defined in <paths.h> */ 1458 # ifndef _PATH_UNIX 1459 # if defined(SYSTEM5) 1460 # define _PATH_UNIX "/unix" 1461 # else /* defined(SYSTEM5) */ 1462 # define _PATH_UNIX "/vmunix" 1463 # endif /* defined(SYSTEM5) */ 1464 # endif /* ! _PATH_UNIX */ 1465 1466 # ifdef _AUX_SOURCE 1467 struct nlist Nl[2]; 1468 # else /* _AUX_SOURCE */ 1469 struct nlist Nl[] = 1470 { 1471 { LA_AVENRUN }, 1472 { 0 }, 1473 }; 1474 # endif /* _AUX_SOURCE */ 1475 # define X_AVENRUN 0 1476 1477 int 1478 getla() 1479 { 1480 int j; 1481 static int kmem = -1; 1482 # if LA_TYPE == LA_INT 1483 long avenrun[3]; 1484 # else /* LA_TYPE == LA_INT */ 1485 # if LA_TYPE == LA_SHORT 1486 short avenrun[3]; 1487 # else 1488 # if LA_TYPE == LA_LONGLONG 1489 long long avenrun[3]; 1490 # else /* LA_TYPE == LA_LONGLONG */ 1491 double avenrun[3]; 1492 # endif /* LA_TYPE == LA_LONGLONG */ 1493 # endif /* LA_TYPE == LA_SHORT */ 1494 # endif /* LA_TYPE == LA_INT */ 1495 extern off_t lseek(); 1496 1497 if (kmem < 0) 1498 { 1499 # ifdef _AUX_SOURCE 1500 (void) sm_strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN, 1501 sizeof(Nl[X_AVENRUN].n_name)); 1502 Nl[1].n_name[0] = '\0'; 1503 # endif /* _AUX_SOURCE */ 1504 1505 # if defined(_AIX3) || defined(_AIX4) 1506 if (knlist(Nl, 1, sizeof(Nl[0])) < 0) 1507 # else /* defined(_AIX3) || defined(_AIX4) */ 1508 if (nlist(_PATH_UNIX, Nl) < 0) 1509 # endif /* defined(_AIX3) || defined(_AIX4) */ 1510 { 1511 if (tTd(3, 1)) 1512 sm_dprintf("getla: nlist(%s): %s\n", _PATH_UNIX, 1513 sm_errstring(errno)); 1514 return -1; 1515 } 1516 if (Nl[X_AVENRUN].n_value == 0) 1517 { 1518 if (tTd(3, 1)) 1519 sm_dprintf("getla: nlist(%s, %s) ==> 0\n", 1520 _PATH_UNIX, LA_AVENRUN); 1521 return -1; 1522 } 1523 # ifdef NAMELISTMASK 1524 Nl[X_AVENRUN].n_value &= NAMELISTMASK; 1525 # endif /* NAMELISTMASK */ 1526 1527 kmem = open(_PATH_KMEM, 0, 0); 1528 if (kmem < 0) 1529 { 1530 if (tTd(3, 1)) 1531 sm_dprintf("getla: open(/dev/kmem): %s\n", 1532 sm_errstring(errno)); 1533 return -1; 1534 } 1535 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1536 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1537 { 1538 if (tTd(3, 1)) 1539 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1540 sm_errstring(errno)); 1541 (void) close(kmem); 1542 kmem = -1; 1543 return -1; 1544 } 1545 } 1546 if (tTd(3, 20)) 1547 sm_dprintf("getla: symbol address = %#lx\n", 1548 (unsigned long) Nl[X_AVENRUN].n_value); 1549 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 || 1550 read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun)) 1551 { 1552 /* thank you Ian */ 1553 if (tTd(3, 1)) 1554 sm_dprintf("getla: lseek or read: %s\n", 1555 sm_errstring(errno)); 1556 return -1; 1557 } 1558 # if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) 1559 if (tTd(3, 5)) 1560 { 1561 # if LA_TYPE == LA_SHORT 1562 sm_dprintf("getla: avenrun = %d", avenrun[0]); 1563 if (tTd(3, 15)) 1564 sm_dprintf(", %d, %d", avenrun[1], avenrun[2]); 1565 # else /* LA_TYPE == LA_SHORT */ 1566 # if LA_TYPE == LA_LONGLONG 1567 sm_dprintf("getla: avenrun = %lld", avenrun[0]); 1568 if (tTd(3, 15)) 1569 sm_dprintf(", %lld, %lld", avenrun[1], avenrun[2]); 1570 # else /* LA_TYPE == LA_LONGLONG */ 1571 sm_dprintf("getla: avenrun = %ld", avenrun[0]); 1572 if (tTd(3, 15)) 1573 sm_dprintf(", %ld, %ld", avenrun[1], avenrun[2]); 1574 # endif /* LA_TYPE == LA_LONGLONG */ 1575 # endif /* LA_TYPE == LA_SHORT */ 1576 sm_dprintf("\n"); 1577 } 1578 if (tTd(3, 1)) 1579 sm_dprintf("getla: %d\n", 1580 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1581 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1582 # else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */ 1583 if (tTd(3, 5)) 1584 { 1585 sm_dprintf("getla: avenrun = %g", avenrun[0]); 1586 if (tTd(3, 15)) 1587 sm_dprintf(", %g, %g", avenrun[1], avenrun[2]); 1588 sm_dprintf("\n"); 1589 } 1590 if (tTd(3, 1)) 1591 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 1592 return ((int) (avenrun[0] + 0.5)); 1593 # endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */ 1594 } 1595 1596 #endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */ 1597 1598 #if LA_TYPE == LA_READKSYM 1599 1600 # include <sys/ksym.h> 1601 1602 int 1603 getla() 1604 { 1605 int j; 1606 static int kmem = -1; 1607 long avenrun[3]; 1608 struct mioc_rksym mirk; 1609 1610 if (kmem < 0) 1611 { 1612 kmem = open("/dev/kmem", 0, 0); 1613 if (kmem < 0) 1614 { 1615 if (tTd(3, 1)) 1616 sm_dprintf("getla: open(/dev/kmem): %s\n", 1617 sm_errstring(errno)); 1618 return -1; 1619 } 1620 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1621 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1622 { 1623 if (tTd(3, 1)) 1624 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1625 sm_errstring(errno)); 1626 (void) close(kmem); 1627 kmem = -1; 1628 return -1; 1629 } 1630 } 1631 mirk.mirk_symname = LA_AVENRUN; 1632 mirk.mirk_buf = avenrun; 1633 mirk.mirk_buflen = sizeof(avenrun); 1634 if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0) 1635 { 1636 if (tTd(3, 1)) 1637 sm_dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n", 1638 sm_errstring(errno)); 1639 return -1; 1640 } 1641 if (tTd(3, 5)) 1642 { 1643 sm_dprintf("getla: avenrun = %d", avenrun[0]); 1644 if (tTd(3, 15)) 1645 sm_dprintf(", %d, %d", avenrun[1], avenrun[2]); 1646 sm_dprintf("\n"); 1647 } 1648 if (tTd(3, 1)) 1649 sm_dprintf("getla: %d\n", 1650 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1651 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1652 } 1653 1654 #endif /* LA_TYPE == LA_READKSYM */ 1655 1656 #if LA_TYPE == LA_DGUX 1657 1658 # include <sys/dg_sys_info.h> 1659 1660 int 1661 getla() 1662 { 1663 struct dg_sys_info_load_info load_info; 1664 1665 dg_sys_info((long *)&load_info, 1666 DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); 1667 1668 if (tTd(3, 1)) 1669 sm_dprintf("getla: %d\n", (int) (load_info.one_minute + 0.5)); 1670 1671 return ((int) (load_info.one_minute + 0.5)); 1672 } 1673 1674 #endif /* LA_TYPE == LA_DGUX */ 1675 1676 #if LA_TYPE == LA_HPUX 1677 1678 /* forward declarations to keep gcc from complaining */ 1679 struct pst_dynamic; 1680 struct pst_status; 1681 struct pst_static; 1682 struct pst_vminfo; 1683 struct pst_diskinfo; 1684 struct pst_processor; 1685 struct pst_lv; 1686 struct pst_swapinfo; 1687 1688 # include <sys/param.h> 1689 # include <sys/pstat.h> 1690 1691 int 1692 getla() 1693 { 1694 struct pst_dynamic pstd; 1695 1696 if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic), 1697 (size_t) 1, 0) == -1) 1698 return 0; 1699 1700 if (tTd(3, 1)) 1701 sm_dprintf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); 1702 1703 return (int) (pstd.psd_avg_1_min + 0.5); 1704 } 1705 1706 #endif /* LA_TYPE == LA_HPUX */ 1707 1708 #if LA_TYPE == LA_SUBR 1709 1710 int 1711 getla() 1712 { 1713 double avenrun[3]; 1714 1715 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 1716 { 1717 if (tTd(3, 1)) 1718 sm_dprintf("getla: getloadavg failed: %s", 1719 sm_errstring(errno)); 1720 return -1; 1721 } 1722 if (tTd(3, 1)) 1723 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 1724 return ((int) (avenrun[0] + 0.5)); 1725 } 1726 1727 #endif /* LA_TYPE == LA_SUBR */ 1728 1729 #if LA_TYPE == LA_MACH 1730 1731 /* 1732 ** This has been tested on NEXTSTEP release 2.1/3.X. 1733 */ 1734 1735 # if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 1736 # include <mach/mach.h> 1737 # else /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ 1738 # include <mach.h> 1739 # endif /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ 1740 1741 int 1742 getla() 1743 { 1744 processor_set_t default_set; 1745 kern_return_t error; 1746 unsigned int info_count; 1747 struct processor_set_basic_info info; 1748 host_t host; 1749 1750 error = processor_set_default(host_self(), &default_set); 1751 if (error != KERN_SUCCESS) 1752 { 1753 if (tTd(3, 1)) 1754 sm_dprintf("getla: processor_set_default failed: %s", 1755 sm_errstring(errno)); 1756 return -1; 1757 } 1758 info_count = PROCESSOR_SET_BASIC_INFO_COUNT; 1759 if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, 1760 &host, (processor_set_info_t)&info, 1761 &info_count) != KERN_SUCCESS) 1762 { 1763 if (tTd(3, 1)) 1764 sm_dprintf("getla: processor_set_info failed: %s", 1765 sm_errstring(errno)); 1766 return -1; 1767 } 1768 if (tTd(3, 1)) 1769 sm_dprintf("getla: %d\n", 1770 (int) ((info.load_average + (LOAD_SCALE / 2)) / 1771 LOAD_SCALE)); 1772 return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE; 1773 } 1774 1775 #endif /* LA_TYPE == LA_MACH */ 1776 1777 #if LA_TYPE == LA_PROCSTR 1778 # if SM_CONF_BROKEN_STRTOD 1779 ERROR: This OS has most likely a broken strtod() implemenentation. 1780 ERROR: The function is required for getla(). 1781 ERROR: Check the compilation options _LA_PROCSTR and 1782 ERROR: _SM_CONF_BROKEN_STRTOD (without the leading _). 1783 # endif /* SM_CONF_BROKEN_STRTOD */ 1784 1785 /* 1786 ** Read /proc/loadavg for the load average. This is assumed to be 1787 ** in a format like "0.15 0.12 0.06". 1788 ** 1789 ** Initially intended for Linux. This has been in the kernel 1790 ** since at least 0.99.15. 1791 */ 1792 1793 # ifndef _PATH_LOADAVG 1794 # define _PATH_LOADAVG "/proc/loadavg" 1795 # endif /* ! _PATH_LOADAVG */ 1796 1797 int 1798 getla() 1799 { 1800 double avenrun; 1801 register int result; 1802 SM_FILE_T *fp; 1803 1804 fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_LOADAVG, SM_IO_RDONLY, 1805 NULL); 1806 if (fp == NULL) 1807 { 1808 if (tTd(3, 1)) 1809 sm_dprintf("getla: sm_io_open(%s): %s\n", 1810 _PATH_LOADAVG, sm_errstring(errno)); 1811 return -1; 1812 } 1813 result = sm_io_fscanf(fp, SM_TIME_DEFAULT, "%lf", &avenrun); 1814 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1815 if (result != 1) 1816 { 1817 if (tTd(3, 1)) 1818 sm_dprintf("getla: sm_io_fscanf() = %d: %s\n", 1819 result, sm_errstring(errno)); 1820 return -1; 1821 } 1822 1823 if (tTd(3, 1)) 1824 sm_dprintf("getla(): %.2f\n", avenrun); 1825 1826 return ((int) (avenrun + 0.5)); 1827 } 1828 1829 #endif /* LA_TYPE == LA_PROCSTR */ 1830 1831 #if LA_TYPE == LA_IRIX6 1832 1833 # include <sys/sysmp.h> 1834 1835 # ifdef _UNICOSMP 1836 # define CAST_SYSMP(x) (x) 1837 # else /* _UNICOSMP */ 1838 # define CAST_SYSMP(x) ((x) & 0x7fffffff) 1839 # endif /* _UNICOSMP */ 1840 1841 int 1842 getla(void) 1843 { 1844 int j; 1845 static int kmem = -1; 1846 int avenrun[3]; 1847 1848 if (kmem < 0) 1849 { 1850 kmem = open(_PATH_KMEM, 0, 0); 1851 if (kmem < 0) 1852 { 1853 if (tTd(3, 1)) 1854 sm_dprintf("getla: open(%s): %s\n", _PATH_KMEM, 1855 sm_errstring(errno)); 1856 return -1; 1857 } 1858 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1859 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1860 { 1861 if (tTd(3, 1)) 1862 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1863 sm_errstring(errno)); 1864 (void) close(kmem); 1865 kmem = -1; 1866 return -1; 1867 } 1868 } 1869 1870 if (lseek(kmem, CAST_SYSMP(sysmp(MP_KERNADDR, MPKA_AVENRUN)), SEEK_SET) 1871 == -1 || 1872 read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun)) 1873 { 1874 if (tTd(3, 1)) 1875 sm_dprintf("getla: lseek or read: %s\n", 1876 sm_errstring(errno)); 1877 return -1; 1878 } 1879 if (tTd(3, 5)) 1880 { 1881 sm_dprintf("getla: avenrun = %ld", (long int) avenrun[0]); 1882 if (tTd(3, 15)) 1883 sm_dprintf(", %ld, %ld", 1884 (long int) avenrun[1], (long int) avenrun[2]); 1885 sm_dprintf("\n"); 1886 } 1887 1888 if (tTd(3, 1)) 1889 sm_dprintf("getla: %d\n", 1890 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1891 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1892 1893 } 1894 #endif /* LA_TYPE == LA_IRIX6 */ 1895 1896 #if LA_TYPE == LA_KSTAT 1897 1898 # include <kstat.h> 1899 1900 int 1901 getla() 1902 { 1903 static kstat_ctl_t *kc = NULL; 1904 static kstat_t *ksp = NULL; 1905 kstat_named_t *ksn; 1906 int la; 1907 1908 if (kc == NULL) /* if not initialized before */ 1909 kc = kstat_open(); 1910 if (kc == NULL) 1911 { 1912 if (tTd(3, 1)) 1913 sm_dprintf("getla: kstat_open(): %s\n", 1914 sm_errstring(errno)); 1915 return -1; 1916 } 1917 if (ksp == NULL) 1918 ksp = kstat_lookup(kc, "unix", 0, "system_misc"); 1919 if (ksp == NULL) 1920 { 1921 if (tTd(3, 1)) 1922 sm_dprintf("getla: kstat_lookup(): %s\n", 1923 sm_errstring(errno)); 1924 return -1; 1925 } 1926 if (kstat_read(kc, ksp, NULL) < 0) 1927 { 1928 if (tTd(3, 1)) 1929 sm_dprintf("getla: kstat_read(): %s\n", 1930 sm_errstring(errno)); 1931 return -1; 1932 } 1933 ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min"); 1934 la = ((double) ksn->value.ul + FSCALE/2) / FSCALE; 1935 /* kstat_close(kc); /o do not close for fast access */ 1936 return la; 1937 } 1938 1939 #endif /* LA_TYPE == LA_KSTAT */ 1940 1941 #if LA_TYPE == LA_DEVSHORT 1942 1943 /* 1944 ** Read /dev/table/avenrun for the load average. This should contain 1945 ** three shorts for the 1, 5, and 15 minute loads. We only read the 1946 ** first, since that's all we care about. 1947 ** 1948 ** Intended for SCO OpenServer 5. 1949 */ 1950 1951 # ifndef _PATH_AVENRUN 1952 # define _PATH_AVENRUN "/dev/table/avenrun" 1953 # endif /* ! _PATH_AVENRUN */ 1954 1955 int 1956 getla() 1957 { 1958 static int afd = -1; 1959 short avenrun; 1960 int loadav; 1961 int r; 1962 1963 errno = EBADF; 1964 1965 if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1) 1966 { 1967 if (errno != EBADF) 1968 return -1; 1969 afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC); 1970 if (afd < 0) 1971 { 1972 sm_syslog(LOG_ERR, NOQID, 1973 "can't open %s: %s", 1974 _PATH_AVENRUN, sm_errstring(errno)); 1975 return -1; 1976 } 1977 } 1978 1979 r = read(afd, &avenrun, sizeof(avenrun)); 1980 if (r != sizeof(avenrun)) 1981 { 1982 sm_syslog(LOG_ERR, NOQID, 1983 "can't read %s: %s", _PATH_AVENRUN, 1984 r == -1 ? sm_errstring(errno) : "short read"); 1985 return -1; 1986 } 1987 1988 if (tTd(3, 5)) 1989 sm_dprintf("getla: avenrun = %d\n", avenrun); 1990 loadav = (int) (avenrun + FSCALE/2) >> FSHIFT; 1991 if (tTd(3, 1)) 1992 sm_dprintf("getla: %d\n", loadav); 1993 return loadav; 1994 } 1995 1996 #endif /* LA_TYPE == LA_DEVSHORT */ 1997 1998 #if LA_TYPE == LA_ALPHAOSF 1999 struct rtentry; 2000 struct mbuf; 2001 # include <sys/table.h> 2002 2003 int 2004 getla() 2005 { 2006 int ave = 0; 2007 struct tbl_loadavg tab; 2008 2009 if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1) 2010 { 2011 if (tTd(3, 1)) 2012 sm_dprintf("getla: table %s\n", sm_errstring(errno)); 2013 return -1; 2014 } 2015 2016 if (tTd(3, 1)) 2017 sm_dprintf("getla: scale = %d\n", tab.tl_lscale); 2018 2019 if (tab.tl_lscale) 2020 ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) / 2021 tab.tl_lscale); 2022 else 2023 ave = (int) (tab.tl_avenrun.d[2] + 0.5); 2024 2025 if (tTd(3, 1)) 2026 sm_dprintf("getla: %d\n", ave); 2027 2028 return ave; 2029 } 2030 2031 #endif /* LA_TYPE == LA_ALPHAOSF */ 2032 2033 #if LA_TYPE == LA_PSET 2034 2035 int 2036 getla() 2037 { 2038 double avenrun[3]; 2039 2040 if (pset_getloadavg(PS_MYID, avenrun, 2041 sizeof(avenrun) / sizeof(avenrun[0])) < 0) 2042 { 2043 if (tTd(3, 1)) 2044 sm_dprintf("getla: pset_getloadavg failed: %s", 2045 sm_errstring(errno)); 2046 return -1; 2047 } 2048 if (tTd(3, 1)) 2049 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 2050 return ((int) (avenrun[0] + 0.5)); 2051 } 2052 2053 #endif /* LA_TYPE == LA_PSET */ 2054 2055 #if LA_TYPE == LA_ZERO 2056 2057 int 2058 getla() 2059 { 2060 if (tTd(3, 1)) 2061 sm_dprintf("getla: ZERO\n"); 2062 return 0; 2063 } 2064 2065 #endif /* LA_TYPE == LA_ZERO */ 2066 2067 /* 2068 * Copyright 1989 Massachusetts Institute of Technology 2069 * 2070 * Permission to use, copy, modify, distribute, and sell this software and its 2071 * documentation for any purpose is hereby granted without fee, provided that 2072 * the above copyright notice appear in all copies and that both that 2073 * copyright notice and this permission notice appear in supporting 2074 * documentation, and that the name of M.I.T. not be used in advertising or 2075 * publicity pertaining to distribution of the software without specific, 2076 * written prior permission. M.I.T. makes no representations about the 2077 * suitability of this software for any purpose. It is provided "as is" 2078 * without express or implied warranty. 2079 * 2080 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 2081 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. 2082 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 2083 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 2084 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 2085 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2086 * 2087 * Authors: Many and varied... 2088 */ 2089 2090 /* Non Apollo stuff removed by Don Lewis 11/15/93 */ 2091 #ifndef lint 2092 SM_UNUSED(static char rcsid[]) = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; 2093 #endif /* ! lint */ 2094 2095 #ifdef apollo 2096 # undef volatile 2097 # include <apollo/base.h> 2098 2099 /* ARGSUSED */ 2100 int getloadavg( call_data ) 2101 caddr_t call_data; /* pointer to (double) return value */ 2102 { 2103 double *avenrun = (double *) call_data; 2104 int i; 2105 status_$t st; 2106 long loadav[3]; 2107 2108 proc1_$get_loadav(loadav, &st); 2109 *avenrun = loadav[0] / (double) (1 << 16); 2110 return 0; 2111 } 2112 #endif /* apollo */ 2113 /* 2114 ** SM_GETLA -- get the current load average 2115 ** 2116 ** Parameters: 2117 ** none 2118 ** 2119 ** Returns: 2120 ** none 2121 ** 2122 ** Side Effects: 2123 ** Set CurrentLA to the current load average. 2124 ** Set {load_avg} in GlobalMacros to the current load average. 2125 */ 2126 2127 void 2128 sm_getla() 2129 { 2130 char labuf[8]; 2131 2132 CurrentLA = getla(); 2133 (void) sm_snprintf(labuf, sizeof(labuf), "%d", CurrentLA); 2134 macdefine(&GlobalMacros, A_TEMP, macid("{load_avg}"), labuf); 2135 } 2136 /* 2137 ** SHOULDQUEUE -- should this message be queued or sent? 2138 ** 2139 ** Compares the message cost to the load average to decide. 2140 ** 2141 ** Note: Do NOT change this API! It is documented in op.me 2142 ** and theoretically the user can change this function... 2143 ** 2144 ** Parameters: 2145 ** pri -- the priority of the message in question. 2146 ** ct -- the message creation time (unused, but see above). 2147 ** 2148 ** Returns: 2149 ** true -- if this message should be queued up for the 2150 ** time being. 2151 ** false -- if the load is low enough to send this message. 2152 ** 2153 ** Side Effects: 2154 ** none. 2155 */ 2156 2157 /* ARGSUSED1 */ 2158 bool 2159 shouldqueue(pri, ct) 2160 long pri; 2161 time_t ct; 2162 { 2163 bool rval; 2164 #if _FFR_MEMSTAT 2165 long memfree; 2166 #endif /* _FFR_MEMSTAT */ 2167 2168 if (tTd(3, 30)) 2169 sm_dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ", 2170 CurrentLA, pri); 2171 2172 #if _FFR_MEMSTAT 2173 if (QueueLowMem > 0 && 2174 sm_memstat_get(MemoryResource, &memfree) >= 0 && 2175 memfree < QueueLowMem) 2176 { 2177 if (tTd(3, 30)) 2178 sm_dprintf("true (memfree=%ld < QueueLowMem=%ld)\n", 2179 memfree, QueueLowMem); 2180 return true; 2181 } 2182 #endif /* _FFR_MEMSTAT */ 2183 if (CurrentLA < QueueLA) 2184 { 2185 if (tTd(3, 30)) 2186 sm_dprintf("false (CurrentLA < QueueLA)\n"); 2187 return false; 2188 } 2189 rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); 2190 if (tTd(3, 30)) 2191 sm_dprintf("%s (by calculation)\n", rval ? "true" : "false"); 2192 return rval; 2193 } 2194 2195 /* 2196 ** REFUSECONNECTIONS -- decide if connections should be refused 2197 ** 2198 ** Parameters: 2199 ** e -- the current envelope. 2200 ** dn -- number of daemon. 2201 ** active -- was this daemon actually active? 2202 ** 2203 ** Returns: 2204 ** true if incoming SMTP connections should be refused 2205 ** (for now). 2206 ** false if we should accept new work. 2207 ** 2208 ** Side Effects: 2209 ** Sets process title when it is rejecting connections. 2210 */ 2211 2212 bool 2213 refuseconnections(e, dn, active) 2214 ENVELOPE *e; 2215 int dn; 2216 bool active; 2217 { 2218 static time_t lastconn[MAXDAEMONS]; 2219 static int conncnt[MAXDAEMONS]; 2220 static time_t firstrejtime[MAXDAEMONS]; 2221 static time_t nextlogtime[MAXDAEMONS]; 2222 int limit; 2223 #if _FFR_MEMSTAT 2224 long memfree; 2225 #endif /* _FFR_MEMSTAT */ 2226 2227 #if XLA 2228 if (!xla_smtp_ok()) 2229 return true; 2230 #endif /* XLA */ 2231 2232 SM_ASSERT(dn >= 0); 2233 SM_ASSERT(dn < MAXDAEMONS); 2234 if (ConnRateThrottle > 0) 2235 { 2236 time_t now; 2237 2238 now = curtime(); 2239 if (active) 2240 { 2241 if (now != lastconn[dn]) 2242 { 2243 lastconn[dn] = now; 2244 conncnt[dn] = 1; 2245 } 2246 else if (conncnt[dn]++ > ConnRateThrottle) 2247 { 2248 #define D_MSG_CRT "deferring connections on daemon %s: %d per second" 2249 /* sleep to flatten out connection load */ 2250 sm_setproctitle(true, e, D_MSG_CRT, 2251 Daemons[dn].d_name, 2252 ConnRateThrottle); 2253 if (LogLevel > 8) 2254 sm_syslog(LOG_INFO, NOQID, D_MSG_CRT, 2255 Daemons[dn].d_name, 2256 ConnRateThrottle); 2257 (void) sleep(1); 2258 } 2259 } 2260 else if (now != lastconn[dn]) 2261 conncnt[dn] = 0; 2262 } 2263 2264 2265 #if _FFR_MEMSTAT 2266 if (RefuseLowMem > 0 && 2267 sm_memstat_get(MemoryResource, &memfree) >= 0 && 2268 memfree < RefuseLowMem) 2269 { 2270 # define R_MSG_LM "rejecting connections on daemon %s: free memory: %ld" 2271 sm_setproctitle(true, e, R_MSG_LM, Daemons[dn].d_name, memfree); 2272 if (LogLevel > 8) 2273 sm_syslog(LOG_NOTICE, NOQID, R_MSG_LM, 2274 Daemons[dn].d_name, memfree); 2275 return true; 2276 } 2277 #endif /* _FFR_MEMSTAT */ 2278 sm_getla(); 2279 limit = (Daemons[dn].d_refuseLA != DPO_NOTSET) ? 2280 Daemons[dn].d_refuseLA : RefuseLA; 2281 if (limit > 0 && CurrentLA >= limit) 2282 { 2283 time_t now; 2284 2285 # define R_MSG_LA "rejecting connections on daemon %s: load average: %d" 2286 # define R2_MSG_LA "have been rejecting connections on daemon %s for %s" 2287 sm_setproctitle(true, e, R_MSG_LA, Daemons[dn].d_name, 2288 CurrentLA); 2289 if (LogLevel > 8) 2290 sm_syslog(LOG_NOTICE, NOQID, R_MSG_LA, 2291 Daemons[dn].d_name, CurrentLA); 2292 now = curtime(); 2293 if (firstrejtime[dn] == 0) 2294 { 2295 firstrejtime[dn] = now; 2296 nextlogtime[dn] = now + RejectLogInterval; 2297 } 2298 else if (nextlogtime[dn] < now) 2299 { 2300 sm_syslog(LOG_ERR, NOQID, R2_MSG_LA, Daemons[dn].d_name, 2301 pintvl(now - firstrejtime[dn], true)); 2302 nextlogtime[dn] = now + RejectLogInterval; 2303 } 2304 return true; 2305 } 2306 else 2307 firstrejtime[dn] = 0; 2308 2309 limit = (Daemons[dn].d_delayLA != DPO_NOTSET) ? 2310 Daemons[dn].d_delayLA : DelayLA; 2311 if (limit > 0 && CurrentLA >= limit) 2312 { 2313 time_t now; 2314 static time_t log_delay = (time_t) 0; 2315 2316 # define MIN_DELAY_LOG 90 /* wait before logging this again */ 2317 # define D_MSG_LA "delaying connections on daemon %s: load average=%d >= %d" 2318 /* sleep to flatten out connection load */ 2319 sm_setproctitle(true, e, D_MSG_LA, Daemons[dn].d_name, 2320 CurrentLA, limit); 2321 if (LogLevel > 8 && (now = curtime()) > log_delay) 2322 { 2323 sm_syslog(LOG_INFO, NOQID, D_MSG_LA, 2324 Daemons[dn].d_name, CurrentLA, limit); 2325 log_delay = now + MIN_DELAY_LOG; 2326 } 2327 (void) sleep(1); 2328 } 2329 2330 limit = (Daemons[dn].d_maxchildren != DPO_NOTSET) ? 2331 Daemons[dn].d_maxchildren : MaxChildren; 2332 if (limit > 0 && CurChildren >= limit) 2333 { 2334 proc_list_probe(); 2335 if (CurChildren >= limit) 2336 { 2337 #define R_MSG_CHILD "rejecting connections on daemon %s: %d children, max %d" 2338 sm_setproctitle(true, e, R_MSG_CHILD, 2339 Daemons[dn].d_name, CurChildren, 2340 limit); 2341 if (LogLevel > 8) 2342 sm_syslog(LOG_INFO, NOQID, R_MSG_CHILD, 2343 Daemons[dn].d_name, CurChildren, 2344 limit); 2345 return true; 2346 } 2347 } 2348 return false; 2349 } 2350 2351 /* 2352 ** SETPROCTITLE -- set process title for ps 2353 ** 2354 ** Parameters: 2355 ** fmt -- a printf style format string. 2356 ** a, b, c -- possible parameters to fmt. 2357 ** 2358 ** Returns: 2359 ** none. 2360 ** 2361 ** Side Effects: 2362 ** Clobbers argv of our main procedure so ps(1) will 2363 ** display the title. 2364 */ 2365 2366 #define SPT_NONE 0 /* don't use it at all */ 2367 #define SPT_REUSEARGV 1 /* cover argv with title information */ 2368 #define SPT_BUILTIN 2 /* use libc builtin */ 2369 #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ 2370 #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ 2371 #define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */ 2372 #define SPT_SCO 6 /* write kernel u. area */ 2373 #define SPT_CHANGEARGV 7 /* write our own strings into argv[] */ 2374 2375 #ifndef SPT_TYPE 2376 # define SPT_TYPE SPT_REUSEARGV 2377 #endif /* ! SPT_TYPE */ 2378 2379 2380 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN 2381 2382 # if SPT_TYPE == SPT_PSTAT 2383 # include <sys/pstat.h> 2384 # endif /* SPT_TYPE == SPT_PSTAT */ 2385 # if SPT_TYPE == SPT_PSSTRINGS 2386 # include <machine/vmparam.h> 2387 # include <sys/exec.h> 2388 # ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ 2389 # undef SPT_TYPE 2390 # define SPT_TYPE SPT_REUSEARGV 2391 # else /* ! PS_STRINGS */ 2392 # ifndef NKPDE /* FreeBSD 2.0 */ 2393 # define NKPDE 63 2394 typedef unsigned int *pt_entry_t; 2395 # endif /* ! NKPDE */ 2396 # endif /* ! PS_STRINGS */ 2397 # endif /* SPT_TYPE == SPT_PSSTRINGS */ 2398 2399 # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV 2400 # define SETPROC_STATIC static 2401 # else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ 2402 # define SETPROC_STATIC 2403 # endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ 2404 2405 # if SPT_TYPE == SPT_SYSMIPS 2406 # include <sys/sysmips.h> 2407 # include <sys/sysnews.h> 2408 # endif /* SPT_TYPE == SPT_SYSMIPS */ 2409 2410 # if SPT_TYPE == SPT_SCO 2411 # include <sys/immu.h> 2412 # include <sys/dir.h> 2413 # include <sys/user.h> 2414 # include <sys/fs/s5param.h> 2415 # if PSARGSZ > MAXLINE 2416 # define SPT_BUFSIZE PSARGSZ 2417 # endif /* PSARGSZ > MAXLINE */ 2418 # endif /* SPT_TYPE == SPT_SCO */ 2419 2420 # ifndef SPT_PADCHAR 2421 # define SPT_PADCHAR ' ' 2422 # endif /* ! SPT_PADCHAR */ 2423 2424 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ 2425 2426 #ifndef SPT_BUFSIZE 2427 # define SPT_BUFSIZE MAXLINE 2428 #endif /* ! SPT_BUFSIZE */ 2429 2430 #if _FFR_SPT_ALIGN 2431 2432 /* 2433 ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 2434 ** 64 bit alignment, so unless each piece of argv and envp is a multiple 2435 ** of 8 bytes (including terminating NULL), initsetproctitle() won't use 2436 ** any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE if 2437 ** you use this FFR. 2438 */ 2439 2440 # ifdef SPT_ALIGN_SIZE 2441 # define SPT_ALIGN(x, align) (((((x) + SPT_ALIGN_SIZE) >> (align)) << (align)) - 1) 2442 # else /* SPT_ALIGN_SIZE */ 2443 # define SPT_ALIGN(x, align) (x) 2444 # endif /* SPT_ALIGN_SIZE */ 2445 #else /* _FFR_SPT_ALIGN */ 2446 # define SPT_ALIGN(x, align) (x) 2447 #endif /* _FFR_SPT_ALIGN */ 2448 2449 /* 2450 ** Pointers for setproctitle. 2451 ** This allows "ps" listings to give more useful information. 2452 */ 2453 2454 static char **Argv = NULL; /* pointer to argument vector */ 2455 static char *LastArgv = NULL; /* end of argv */ 2456 #if SPT_TYPE != SPT_BUILTIN 2457 static void setproctitle __P((const char *, ...)); 2458 #endif /* SPT_TYPE != SPT_BUILTIN */ 2459 2460 void 2461 initsetproctitle(argc, argv, envp) 2462 int argc; 2463 char **argv; 2464 char **envp; 2465 { 2466 register int i; 2467 int align; 2468 extern char **environ; 2469 2470 /* 2471 ** Move the environment so setproctitle can use the space at 2472 ** the top of memory. 2473 */ 2474 2475 if (envp != NULL) 2476 { 2477 for (i = 0; envp[i] != NULL; i++) 2478 continue; 2479 environ = (char **) xalloc(sizeof(char *) * (i + 1)); 2480 for (i = 0; envp[i] != NULL; i++) 2481 environ[i] = newstr(envp[i]); 2482 environ[i] = NULL; 2483 } 2484 2485 /* 2486 ** Save start and extent of argv for setproctitle. 2487 */ 2488 2489 Argv = argv; 2490 2491 /* 2492 ** Determine how much space we can use for setproctitle. 2493 ** Use all contiguous argv and envp pointers starting at argv[0] 2494 */ 2495 2496 align = -1; 2497 # if _FFR_SPT_ALIGN 2498 # ifdef SPT_ALIGN_SIZE 2499 for (i = SPT_ALIGN_SIZE; i > 0; i >>= 1) 2500 align++; 2501 # endif /* SPT_ALIGN_SIZE */ 2502 # endif /* _FFR_SPT_ALIGN */ 2503 2504 for (i = 0; i < argc; i++) 2505 { 2506 if (i == 0 || LastArgv + 1 == argv[i]) 2507 LastArgv = argv[i] + SPT_ALIGN(strlen(argv[i]), align); 2508 } 2509 for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++) 2510 { 2511 if (LastArgv + 1 == envp[i]) 2512 LastArgv = envp[i] + SPT_ALIGN(strlen(envp[i]), align); 2513 } 2514 } 2515 2516 #if SPT_TYPE != SPT_BUILTIN 2517 2518 /*VARARGS1*/ 2519 static void 2520 # ifdef __STDC__ 2521 setproctitle(const char *fmt, ...) 2522 # else /* __STDC__ */ 2523 setproctitle(fmt, va_alist) 2524 const char *fmt; 2525 va_dcl 2526 # endif /* __STDC__ */ 2527 { 2528 # if SPT_TYPE != SPT_NONE 2529 register int i; 2530 register char *p; 2531 SETPROC_STATIC char buf[SPT_BUFSIZE]; 2532 SM_VA_LOCAL_DECL 2533 # if SPT_TYPE == SPT_PSTAT 2534 union pstun pst; 2535 # endif /* SPT_TYPE == SPT_PSTAT */ 2536 # if SPT_TYPE == SPT_SCO 2537 int j; 2538 off_t seek_off; 2539 static int kmem = -1; 2540 static pid_t kmempid = -1; 2541 struct user u; 2542 # endif /* SPT_TYPE == SPT_SCO */ 2543 2544 p = buf; 2545 2546 /* print sendmail: heading for grep */ 2547 (void) sm_strlcpy(p, "sendmail: ", SPACELEFT(buf, p)); 2548 p += strlen(p); 2549 2550 /* print the argument string */ 2551 SM_VA_START(ap, fmt); 2552 (void) sm_vsnprintf(p, SPACELEFT(buf, p), fmt, ap); 2553 SM_VA_END(ap); 2554 2555 i = (int) strlen(buf); 2556 if (i < 0) 2557 return; 2558 2559 # if SPT_TYPE == SPT_PSTAT 2560 pst.pst_command = buf; 2561 pstat(PSTAT_SETCMD, pst, i, 0, 0); 2562 # endif /* SPT_TYPE == SPT_PSTAT */ 2563 # if SPT_TYPE == SPT_PSSTRINGS 2564 PS_STRINGS->ps_nargvstr = 1; 2565 PS_STRINGS->ps_argvstr = buf; 2566 # endif /* SPT_TYPE == SPT_PSSTRINGS */ 2567 # if SPT_TYPE == SPT_SYSMIPS 2568 sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf); 2569 # endif /* SPT_TYPE == SPT_SYSMIPS */ 2570 # if SPT_TYPE == SPT_SCO 2571 if (kmem < 0 || kmempid != CurrentPid) 2572 { 2573 if (kmem >= 0) 2574 (void) close(kmem); 2575 kmem = open(_PATH_KMEM, O_RDWR, 0); 2576 if (kmem < 0) 2577 return; 2578 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 2579 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 2580 { 2581 (void) close(kmem); 2582 kmem = -1; 2583 return; 2584 } 2585 kmempid = CurrentPid; 2586 } 2587 buf[PSARGSZ - 1] = '\0'; 2588 seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u; 2589 if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off) 2590 (void) write(kmem, buf, PSARGSZ); 2591 # endif /* SPT_TYPE == SPT_SCO */ 2592 # if SPT_TYPE == SPT_REUSEARGV 2593 if (LastArgv == NULL) 2594 return; 2595 2596 if (i > LastArgv - Argv[0] - 2) 2597 { 2598 i = LastArgv - Argv[0] - 2; 2599 buf[i] = '\0'; 2600 } 2601 (void) sm_strlcpy(Argv[0], buf, i + 1); 2602 p = &Argv[0][i]; 2603 while (p < LastArgv) 2604 *p++ = SPT_PADCHAR; 2605 Argv[1] = NULL; 2606 # endif /* SPT_TYPE == SPT_REUSEARGV */ 2607 # if SPT_TYPE == SPT_CHANGEARGV 2608 Argv[0] = buf; 2609 Argv[1] = 0; 2610 # endif /* SPT_TYPE == SPT_CHANGEARGV */ 2611 # endif /* SPT_TYPE != SPT_NONE */ 2612 } 2613 2614 #endif /* SPT_TYPE != SPT_BUILTIN */ 2615 /* 2616 ** SM_SETPROCTITLE -- set process task and set process title for ps 2617 ** 2618 ** Possibly set process status and call setproctitle() to 2619 ** change the ps display. 2620 ** 2621 ** Parameters: 2622 ** status -- whether or not to store as process status 2623 ** e -- the current envelope. 2624 ** fmt -- a printf style format string. 2625 ** a, b, c -- possible parameters to fmt. 2626 ** 2627 ** Returns: 2628 ** none. 2629 */ 2630 2631 /*VARARGS3*/ 2632 void 2633 #ifdef __STDC__ 2634 sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...) 2635 #else /* __STDC__ */ 2636 sm_setproctitle(status, e, fmt, va_alist) 2637 bool status; 2638 ENVELOPE *e; 2639 const char *fmt; 2640 va_dcl 2641 #endif /* __STDC__ */ 2642 { 2643 char buf[SPT_BUFSIZE]; 2644 SM_VA_LOCAL_DECL 2645 2646 /* print the argument string */ 2647 SM_VA_START(ap, fmt); 2648 (void) sm_vsnprintf(buf, sizeof(buf), fmt, ap); 2649 SM_VA_END(ap); 2650 2651 if (status) 2652 proc_list_set(CurrentPid, buf); 2653 2654 if (ProcTitlePrefix != NULL) 2655 { 2656 char prefix[SPT_BUFSIZE]; 2657 2658 expand(ProcTitlePrefix, prefix, sizeof(prefix), e); 2659 setproctitle("%s: %s", prefix, buf); 2660 } 2661 else 2662 setproctitle("%s", buf); 2663 } 2664 /* 2665 ** WAITFOR -- wait for a particular process id. 2666 ** 2667 ** Parameters: 2668 ** pid -- process id to wait for. 2669 ** 2670 ** Returns: 2671 ** status of pid. 2672 ** -1 if pid never shows up. 2673 ** 2674 ** Side Effects: 2675 ** none. 2676 */ 2677 2678 int 2679 waitfor(pid) 2680 pid_t pid; 2681 { 2682 int st; 2683 pid_t i; 2684 2685 do 2686 { 2687 errno = 0; 2688 i = sm_wait(&st); 2689 if (i > 0) 2690 proc_list_drop(i, st, NULL); 2691 } while ((i >= 0 || errno == EINTR) && i != pid); 2692 if (i < 0) 2693 return -1; 2694 return st; 2695 } 2696 /* 2697 ** SM_WAIT -- wait 2698 ** 2699 ** Parameters: 2700 ** status -- pointer to status (return value) 2701 ** 2702 ** Returns: 2703 ** pid 2704 */ 2705 2706 pid_t 2707 sm_wait(status) 2708 int *status; 2709 { 2710 # ifdef WAITUNION 2711 union wait st; 2712 # else /* WAITUNION */ 2713 auto int st; 2714 # endif /* WAITUNION */ 2715 pid_t i; 2716 # if defined(ISC_UNIX) || defined(_SCO_unix_) 2717 int savesig; 2718 # endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ 2719 2720 # if defined(ISC_UNIX) || defined(_SCO_unix_) 2721 savesig = sm_releasesignal(SIGCHLD); 2722 # endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ 2723 i = wait(&st); 2724 # if defined(ISC_UNIX) || defined(_SCO_unix_) 2725 if (savesig > 0) 2726 sm_blocksignal(SIGCHLD); 2727 # endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ 2728 # ifdef WAITUNION 2729 *status = st.w_status; 2730 # else /* WAITUNION */ 2731 *status = st; 2732 # endif /* WAITUNION */ 2733 return i; 2734 } 2735 /* 2736 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 2737 ** 2738 ** Parameters: 2739 ** sig -- the signal that got us here (unused). 2740 ** 2741 ** Returns: 2742 ** none. 2743 ** 2744 ** Side Effects: 2745 ** Picks up extant zombies. 2746 ** Control socket exits may restart/shutdown daemon. 2747 ** 2748 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2749 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2750 ** DOING. 2751 */ 2752 2753 /* ARGSUSED0 */ 2754 SIGFUNC_DECL 2755 reapchild(sig) 2756 int sig; 2757 { 2758 int save_errno = errno; 2759 int st; 2760 pid_t pid; 2761 # if HASWAITPID 2762 auto int status; 2763 int count; 2764 2765 count = 0; 2766 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) 2767 { 2768 st = status; 2769 if (count++ > 1000) 2770 break; 2771 # else /* HASWAITPID */ 2772 # ifdef WNOHANG 2773 union wait status; 2774 2775 while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) 2776 { 2777 st = status.w_status; 2778 # else /* WNOHANG */ 2779 auto int status; 2780 2781 /* 2782 ** Catch one zombie -- we will be re-invoked (we hope) if there 2783 ** are more. Unreliable signals probably break this, but this 2784 ** is the "old system" situation -- waitpid or wait3 are to be 2785 ** strongly preferred. 2786 */ 2787 2788 if ((pid = wait(&status)) > 0) 2789 { 2790 st = status; 2791 # endif /* WNOHANG */ 2792 # endif /* HASWAITPID */ 2793 /* Drop PID and check if it was a control socket child */ 2794 proc_list_drop(pid, st, NULL); 2795 } 2796 FIX_SYSV_SIGNAL(sig, reapchild); 2797 errno = save_errno; 2798 return SIGFUNC_RETURN; 2799 } 2800 /* 2801 ** GETDTSIZE -- return number of file descriptors 2802 ** 2803 ** Only on non-BSD systems 2804 ** 2805 ** Parameters: 2806 ** none 2807 ** 2808 ** Returns: 2809 ** size of file descriptor table 2810 ** 2811 ** Side Effects: 2812 ** none 2813 */ 2814 2815 #ifdef SOLARIS 2816 # include <sys/resource.h> 2817 #endif /* SOLARIS */ 2818 2819 int 2820 getdtsize() 2821 { 2822 # ifdef RLIMIT_NOFILE 2823 struct rlimit rl; 2824 2825 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) 2826 return rl.rlim_cur; 2827 # endif /* RLIMIT_NOFILE */ 2828 2829 # if HASGETDTABLESIZE 2830 return getdtablesize(); 2831 # else /* HASGETDTABLESIZE */ 2832 # ifdef _SC_OPEN_MAX 2833 return sysconf(_SC_OPEN_MAX); 2834 # else /* _SC_OPEN_MAX */ 2835 return NOFILE; 2836 # endif /* _SC_OPEN_MAX */ 2837 # endif /* HASGETDTABLESIZE */ 2838 } 2839 /* 2840 ** UNAME -- get the UUCP name of this system. 2841 */ 2842 2843 #if !HASUNAME 2844 2845 int 2846 uname(name) 2847 struct utsname *name; 2848 { 2849 SM_FILE_T *file; 2850 char *n; 2851 2852 name->nodename[0] = '\0'; 2853 2854 /* try /etc/whoami -- one line with the node name */ 2855 if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, "/etc/whoami", 2856 SM_IO_RDONLY, NULL)) != NULL) 2857 { 2858 (void) sm_io_fgets(file, SM_TIME_DEFAULT, name->nodename, 2859 NODE_LENGTH + 1); 2860 (void) sm_io_close(file, SM_TIME_DEFAULT); 2861 n = strchr(name->nodename, '\n'); 2862 if (n != NULL) 2863 *n = '\0'; 2864 if (name->nodename[0] != '\0') 2865 return 0; 2866 } 2867 2868 /* try /usr/include/whoami.h -- has a #define somewhere */ 2869 if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, 2870 "/usr/include/whoami.h", SM_IO_RDONLY, NULL)) 2871 != NULL) 2872 { 2873 char buf[MAXLINE]; 2874 2875 while (sm_io_fgets(file, SM_TIME_DEFAULT, 2876 buf, sizeof(buf)) >= 0) 2877 { 2878 if (sm_io_sscanf(buf, "#define sysname \"%*[^\"]\"", 2879 NODE_LENGTH, name->nodename) > 0) 2880 break; 2881 } 2882 (void) sm_io_close(file, SM_TIME_DEFAULT); 2883 if (name->nodename[0] != '\0') 2884 return 0; 2885 } 2886 2887 return -1; 2888 } 2889 #endif /* !HASUNAME */ 2890 /* 2891 ** INITGROUPS -- initialize groups 2892 ** 2893 ** Stub implementation for System V style systems 2894 */ 2895 2896 #if !HASINITGROUPS 2897 2898 initgroups(name, basegid) 2899 char *name; 2900 int basegid; 2901 { 2902 return 0; 2903 } 2904 2905 #endif /* !HASINITGROUPS */ 2906 /* 2907 ** SETGROUPS -- set group list 2908 ** 2909 ** Stub implementation for systems that don't have group lists 2910 */ 2911 2912 #ifndef NGROUPS_MAX 2913 2914 int 2915 setgroups(ngroups, grouplist) 2916 int ngroups; 2917 GIDSET_T grouplist[]; 2918 { 2919 return 0; 2920 } 2921 2922 #endif /* ! NGROUPS_MAX */ 2923 /* 2924 ** SETSID -- set session id (for non-POSIX systems) 2925 */ 2926 2927 #if !HASSETSID 2928 2929 pid_t 2930 setsid __P ((void)) 2931 { 2932 # ifdef TIOCNOTTY 2933 int fd; 2934 2935 fd = open("/dev/tty", O_RDWR, 0); 2936 if (fd >= 0) 2937 { 2938 (void) ioctl(fd, TIOCNOTTY, (char *) 0); 2939 (void) close(fd); 2940 } 2941 # endif /* TIOCNOTTY */ 2942 # ifdef SYS5SETPGRP 2943 return setpgrp(); 2944 # else /* SYS5SETPGRP */ 2945 return setpgid(0, CurrentPid); 2946 # endif /* SYS5SETPGRP */ 2947 } 2948 2949 #endif /* !HASSETSID */ 2950 /* 2951 ** FSYNC -- dummy fsync 2952 */ 2953 2954 #if NEEDFSYNC 2955 2956 fsync(fd) 2957 int fd; 2958 { 2959 # ifdef O_SYNC 2960 return fcntl(fd, F_SETFL, O_SYNC); 2961 # else /* O_SYNC */ 2962 /* nothing we can do */ 2963 return 0; 2964 # endif /* O_SYNC */ 2965 } 2966 2967 #endif /* NEEDFSYNC */ 2968 /* 2969 ** DGUX_INET_ADDR -- inet_addr for DG/UX 2970 ** 2971 ** Data General DG/UX version of inet_addr returns a struct in_addr 2972 ** instead of a long. This patches things. Only needed on versions 2973 ** prior to 5.4.3. 2974 */ 2975 2976 #ifdef DGUX_5_4_2 2977 2978 # undef inet_addr 2979 2980 long 2981 dgux_inet_addr(host) 2982 char *host; 2983 { 2984 struct in_addr haddr; 2985 2986 haddr = inet_addr(host); 2987 return haddr.s_addr; 2988 } 2989 2990 #endif /* DGUX_5_4_2 */ 2991 /* 2992 ** GETOPT -- for old systems or systems with bogus implementations 2993 */ 2994 2995 #if !SM_CONF_GETOPT 2996 2997 /* 2998 * Copyright (c) 1985 Regents of the University of California. 2999 * All rights reserved. The Berkeley software License Agreement 3000 * specifies the terms and conditions for redistribution. 3001 */ 3002 3003 3004 /* 3005 ** this version hacked to add `atend' flag to allow state machine 3006 ** to reset if invoked by the program to scan args for a 2nd time 3007 */ 3008 3009 # if defined(LIBC_SCCS) && !defined(lint) 3010 static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86"; 3011 # endif /* defined(LIBC_SCCS) && !defined(lint) */ 3012 3013 /* 3014 ** get option letter from argument vector 3015 */ 3016 # ifdef _CONVEX_SOURCE 3017 extern int optind, opterr, optopt; 3018 extern char *optarg; 3019 # else /* _CONVEX_SOURCE */ 3020 int opterr = 1; /* if error message should be printed */ 3021 int optind = 1; /* index into parent argv vector */ 3022 int optopt = 0; /* character checked for validity */ 3023 char *optarg = NULL; /* argument associated with option */ 3024 # endif /* _CONVEX_SOURCE */ 3025 3026 # define BADCH (int)'?' 3027 # define EMSG "" 3028 # define tell(s) if (opterr) \ 3029 {sm_io_fputs(smioerr, SM_TIME_DEFAULT, *nargv); \ 3030 (void) sm_io_fputs(smioerr, SM_TIME_DEFAULT, s); \ 3031 (void) sm_io_putc(smioerr, SM_TIME_DEFAULT, optopt); \ 3032 (void) sm_io_putc(smioerr, SM_TIME_DEFAULT, '\n'); \ 3033 return BADCH;} 3034 3035 int 3036 getopt(nargc,nargv,ostr) 3037 int nargc; 3038 char *const *nargv; 3039 const char *ostr; 3040 { 3041 static char *place = EMSG; /* option letter processing */ 3042 static char atend = 0; 3043 register char *oli = NULL; /* option letter list index */ 3044 3045 if (atend) { 3046 atend = 0; 3047 place = EMSG; 3048 } 3049 if(!*place) { /* update scanning pointer */ 3050 if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) { 3051 atend++; 3052 return -1; 3053 } 3054 if (*place == '-') { /* found "--" */ 3055 ++optind; 3056 atend++; 3057 return -1; 3058 } 3059 } /* option letter okay? */ 3060 if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) { 3061 if (!*place) ++optind; 3062 tell(": illegal option -- "); 3063 } 3064 if (oli && *++oli != ':') { /* don't need argument */ 3065 optarg = NULL; 3066 if (!*place) ++optind; 3067 } 3068 else { /* need an argument */ 3069 if (*place) optarg = place; /* no white space */ 3070 else if (nargc <= ++optind) { /* no arg */ 3071 place = EMSG; 3072 tell(": option requires an argument -- "); 3073 } 3074 else optarg = nargv[optind]; /* white space */ 3075 place = EMSG; 3076 ++optind; 3077 } 3078 return optopt; /* dump back option letter */ 3079 } 3080 3081 #endif /* !SM_CONF_GETOPT */ 3082 /* 3083 ** USERSHELLOK -- tell if a user's shell is ok for unrestricted use 3084 ** 3085 ** Parameters: 3086 ** user -- the name of the user we are checking. 3087 ** shell -- the user's shell from /etc/passwd 3088 ** 3089 ** Returns: 3090 ** true -- if it is ok to use this for unrestricted access. 3091 ** false -- if the shell is restricted. 3092 */ 3093 3094 #if !HASGETUSERSHELL 3095 3096 # ifndef _PATH_SHELLS 3097 # define _PATH_SHELLS "/etc/shells" 3098 # endif /* ! _PATH_SHELLS */ 3099 3100 # if defined(_AIX3) || defined(_AIX4) 3101 # include <userconf.h> 3102 # if _AIX4 >= 40200 3103 # include <userpw.h> 3104 # endif /* _AIX4 >= 40200 */ 3105 # include <usersec.h> 3106 # endif /* defined(_AIX3) || defined(_AIX4) */ 3107 3108 static char *DefaultUserShells[] = 3109 { 3110 "/bin/sh", /* standard shell */ 3111 # ifdef MPE 3112 "/SYS/PUB/CI", 3113 # else /* MPE */ 3114 "/usr/bin/sh", 3115 "/bin/csh", /* C shell */ 3116 "/usr/bin/csh", 3117 # endif /* MPE */ 3118 # ifdef __hpux 3119 # ifdef V4FS 3120 "/usr/bin/rsh", /* restricted Bourne shell */ 3121 "/usr/bin/ksh", /* Korn shell */ 3122 "/usr/bin/rksh", /* restricted Korn shell */ 3123 "/usr/bin/pam", 3124 "/usr/bin/keysh", /* key shell (extended Korn shell) */ 3125 "/usr/bin/posix/sh", 3126 # else /* V4FS */ 3127 "/bin/rsh", /* restricted Bourne shell */ 3128 "/bin/ksh", /* Korn shell */ 3129 "/bin/rksh", /* restricted Korn shell */ 3130 "/bin/pam", 3131 "/usr/bin/keysh", /* key shell (extended Korn shell) */ 3132 "/bin/posix/sh", 3133 "/sbin/sh", 3134 # endif /* V4FS */ 3135 # endif /* __hpux */ 3136 # if defined(_AIX3) || defined(_AIX4) 3137 "/bin/ksh", /* Korn shell */ 3138 "/usr/bin/ksh", 3139 "/bin/tsh", /* trusted shell */ 3140 "/usr/bin/tsh", 3141 "/bin/bsh", /* Bourne shell */ 3142 "/usr/bin/bsh", 3143 # endif /* defined(_AIX3) || defined(_AIX4) */ 3144 # if defined(__svr4__) || defined(__svr5__) 3145 "/bin/ksh", /* Korn shell */ 3146 "/usr/bin/ksh", 3147 # endif /* defined(__svr4__) || defined(__svr5__) */ 3148 # ifdef sgi 3149 "/sbin/sh", /* SGI's shells really live in /sbin */ 3150 "/usr/bin/sh", 3151 "/sbin/bsh", /* classic Bourne shell */ 3152 "/bin/bsh", 3153 "/usr/bin/bsh", 3154 "/sbin/csh", /* standard csh */ 3155 "/bin/csh", 3156 "/usr/bin/csh", 3157 "/sbin/jsh", /* classic Bourne shell w/ job control*/ 3158 "/bin/jsh", 3159 "/usr/bin/jsh", 3160 "/bin/ksh", /* Korn shell */ 3161 "/sbin/ksh", 3162 "/usr/bin/ksh", 3163 "/sbin/tcsh", /* Extended csh */ 3164 "/bin/tcsh", 3165 "/usr/bin/tcsh", 3166 # endif /* sgi */ 3167 NULL 3168 }; 3169 3170 #endif /* !HASGETUSERSHELL */ 3171 3172 #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/" 3173 3174 bool 3175 usershellok(user, shell) 3176 char *user; 3177 char *shell; 3178 { 3179 # if HASGETUSERSHELL 3180 register char *p; 3181 extern char *getusershell(); 3182 3183 if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') || 3184 ConfigLevel <= 1) 3185 return true; 3186 3187 setusershell(); 3188 while ((p = getusershell()) != NULL) 3189 if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0) 3190 break; 3191 endusershell(); 3192 return p != NULL; 3193 # else /* HASGETUSERSHELL */ 3194 # if USEGETCONFATTR 3195 auto char *v; 3196 # endif /* USEGETCONFATTR */ 3197 register SM_FILE_T *shellf; 3198 char buf[MAXLINE]; 3199 3200 if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') || 3201 ConfigLevel <= 1) 3202 return true; 3203 3204 # if USEGETCONFATTR 3205 /* 3206 ** Naturally IBM has a "better" idea..... 3207 ** 3208 ** What a crock. This interface isn't documented, it is 3209 ** considered part of the security library (-ls), and it 3210 ** only works if you are running as root (since the list 3211 ** of valid shells is obviously a source of great concern). 3212 ** I recommend that you do NOT define USEGETCONFATTR, 3213 ** especially since you are going to have to set up an 3214 ** /etc/shells anyhow to handle the cases where getconfattr 3215 ** fails. 3216 */ 3217 3218 if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL) 3219 { 3220 while (*v != '\0') 3221 { 3222 if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0) 3223 return true; 3224 v += strlen(v) + 1; 3225 } 3226 return false; 3227 } 3228 # endif /* USEGETCONFATTR */ 3229 3230 shellf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_SHELLS, 3231 SM_IO_RDONLY, NULL); 3232 if (shellf == NULL) 3233 { 3234 /* no /etc/shells; see if it is one of the std shells */ 3235 char **d; 3236 3237 if (errno != ENOENT && LogLevel > 3) 3238 sm_syslog(LOG_ERR, NOQID, 3239 "usershellok: cannot open %s: %s", 3240 _PATH_SHELLS, sm_errstring(errno)); 3241 3242 for (d = DefaultUserShells; *d != NULL; d++) 3243 { 3244 if (strcmp(shell, *d) == 0) 3245 return true; 3246 } 3247 return false; 3248 } 3249 3250 while (sm_io_fgets(shellf, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0) 3251 { 3252 register char *p, *q; 3253 3254 p = buf; 3255 while (*p != '\0' && *p != '#' && *p != '/') 3256 p++; 3257 if (*p == '#' || *p == '\0') 3258 continue; 3259 q = p; 3260 while (*p != '\0' && *p != '#' && !(isascii(*p) && isspace(*p))) 3261 p++; 3262 *p = '\0'; 3263 if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0) 3264 { 3265 (void) sm_io_close(shellf, SM_TIME_DEFAULT); 3266 return true; 3267 } 3268 } 3269 (void) sm_io_close(shellf, SM_TIME_DEFAULT); 3270 return false; 3271 # endif /* HASGETUSERSHELL */ 3272 } 3273 /* 3274 ** FREEDISKSPACE -- see how much free space is on the queue filesystem 3275 ** 3276 ** Only implemented if you have statfs. 3277 ** 3278 ** Parameters: 3279 ** dir -- the directory in question. 3280 ** bsize -- a variable into which the filesystem 3281 ** block size is stored. 3282 ** 3283 ** Returns: 3284 ** The number of blocks free on the queue filesystem. 3285 ** -1 if the statfs call fails. 3286 ** 3287 ** Side effects: 3288 ** Puts the filesystem block size into bsize. 3289 */ 3290 3291 /* statfs types */ 3292 # define SFS_NONE 0 /* no statfs implementation */ 3293 # define SFS_USTAT 1 /* use ustat */ 3294 # define SFS_4ARGS 2 /* use four-argument statfs call */ 3295 # define SFS_VFS 3 /* use <sys/vfs.h> implementation */ 3296 # define SFS_MOUNT 4 /* use <sys/mount.h> implementation */ 3297 # define SFS_STATFS 5 /* use <sys/statfs.h> implementation */ 3298 # define SFS_STATVFS 6 /* use <sys/statvfs.h> implementation */ 3299 3300 # ifndef SFS_TYPE 3301 # define SFS_TYPE SFS_NONE 3302 # endif /* ! SFS_TYPE */ 3303 3304 # if SFS_TYPE == SFS_USTAT 3305 # include <ustat.h> 3306 # endif /* SFS_TYPE == SFS_USTAT */ 3307 # if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS 3308 # include <sys/statfs.h> 3309 # endif /* SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS */ 3310 # if SFS_TYPE == SFS_VFS 3311 # include <sys/vfs.h> 3312 # endif /* SFS_TYPE == SFS_VFS */ 3313 # if SFS_TYPE == SFS_MOUNT 3314 # include <sys/mount.h> 3315 # endif /* SFS_TYPE == SFS_MOUNT */ 3316 # if SFS_TYPE == SFS_STATVFS 3317 # include <sys/statvfs.h> 3318 # endif /* SFS_TYPE == SFS_STATVFS */ 3319 3320 long 3321 freediskspace(dir, bsize) 3322 const char *dir; 3323 long *bsize; 3324 { 3325 # if SFS_TYPE == SFS_NONE 3326 if (bsize != NULL) 3327 *bsize = 4096L; 3328 3329 /* assume free space is plentiful */ 3330 return (long) LONG_MAX; 3331 # else /* SFS_TYPE == SFS_NONE */ 3332 # if SFS_TYPE == SFS_USTAT 3333 struct ustat fs; 3334 struct stat statbuf; 3335 # define FSBLOCKSIZE DEV_BSIZE 3336 # define SFS_BAVAIL f_tfree 3337 # else /* SFS_TYPE == SFS_USTAT */ 3338 # if defined(ultrix) 3339 struct fs_data fs; 3340 # define SFS_BAVAIL fd_bfreen 3341 # define FSBLOCKSIZE 1024L 3342 # else /* defined(ultrix) */ 3343 # if SFS_TYPE == SFS_STATVFS 3344 struct statvfs fs; 3345 # define FSBLOCKSIZE fs.f_frsize 3346 # else /* SFS_TYPE == SFS_STATVFS */ 3347 struct statfs fs; 3348 # define FSBLOCKSIZE fs.f_bsize 3349 # endif /* SFS_TYPE == SFS_STATVFS */ 3350 # endif /* defined(ultrix) */ 3351 # endif /* SFS_TYPE == SFS_USTAT */ 3352 # ifndef SFS_BAVAIL 3353 # define SFS_BAVAIL f_bavail 3354 # endif /* ! SFS_BAVAIL */ 3355 3356 # if SFS_TYPE == SFS_USTAT 3357 if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) 3358 # else /* SFS_TYPE == SFS_USTAT */ 3359 # if SFS_TYPE == SFS_4ARGS 3360 if (statfs(dir, &fs, sizeof(fs), 0) == 0) 3361 # else /* SFS_TYPE == SFS_4ARGS */ 3362 # if SFS_TYPE == SFS_STATVFS 3363 if (statvfs(dir, &fs) == 0) 3364 # else /* SFS_TYPE == SFS_STATVFS */ 3365 # if defined(ultrix) 3366 if (statfs(dir, &fs) > 0) 3367 # else /* defined(ultrix) */ 3368 if (statfs(dir, &fs) == 0) 3369 # endif /* defined(ultrix) */ 3370 # endif /* SFS_TYPE == SFS_STATVFS */ 3371 # endif /* SFS_TYPE == SFS_4ARGS */ 3372 # endif /* SFS_TYPE == SFS_USTAT */ 3373 { 3374 if (bsize != NULL) 3375 *bsize = FSBLOCKSIZE; 3376 if (fs.SFS_BAVAIL <= 0) 3377 return 0; 3378 else if (fs.SFS_BAVAIL > LONG_MAX) 3379 return (long) LONG_MAX; 3380 else 3381 return (long) fs.SFS_BAVAIL; 3382 } 3383 return -1; 3384 # endif /* SFS_TYPE == SFS_NONE */ 3385 } 3386 /* 3387 ** ENOUGHDISKSPACE -- is there enough free space on the queue file systems? 3388 ** 3389 ** Parameters: 3390 ** msize -- the size to check against. If zero, we don't yet 3391 ** know how big the message will be, so just check for 3392 ** a "reasonable" amount. 3393 ** e -- envelope, or NULL -- controls logging 3394 ** 3395 ** Returns: 3396 ** true if in every queue group there is at least one 3397 ** queue directory whose file system contains enough free space. 3398 ** false otherwise. 3399 ** 3400 ** Side Effects: 3401 ** If there is not enough disk space and e != NULL 3402 ** then sm_syslog is called. 3403 */ 3404 3405 bool 3406 enoughdiskspace(msize, e) 3407 long msize; 3408 ENVELOPE *e; 3409 { 3410 int i; 3411 3412 #if _FFR_TESTS 3413 if (tTd(4, 101)) 3414 return false; 3415 #endif /* _FFR_TESTS */ 3416 if (MinBlocksFree <= 0 && msize <= 0) 3417 { 3418 if (tTd(4, 80)) 3419 sm_dprintf("enoughdiskspace: no threshold\n"); 3420 return true; 3421 } 3422 3423 filesys_update(); 3424 for (i = 0; i < NumQueue; ++i) 3425 { 3426 if (pickqdir(Queue[i], msize, e) < 0) 3427 return false; 3428 } 3429 return true; 3430 } 3431 /* 3432 ** TRANSIENTERROR -- tell if an error code indicates a transient failure 3433 ** 3434 ** This looks at an errno value and tells if this is likely to 3435 ** go away if retried later. 3436 ** 3437 ** Parameters: 3438 ** err -- the errno code to classify. 3439 ** 3440 ** Returns: 3441 ** true if this is probably transient. 3442 ** false otherwise. 3443 */ 3444 3445 bool 3446 transienterror(err) 3447 int err; 3448 { 3449 switch (err) 3450 { 3451 case EIO: /* I/O error */ 3452 case ENXIO: /* Device not configured */ 3453 case EAGAIN: /* Resource temporarily unavailable */ 3454 case ENOMEM: /* Cannot allocate memory */ 3455 case ENODEV: /* Operation not supported by device */ 3456 case ENFILE: /* Too many open files in system */ 3457 case EMFILE: /* Too many open files */ 3458 case ENOSPC: /* No space left on device */ 3459 case ETIMEDOUT: /* Connection timed out */ 3460 #ifdef ESTALE 3461 case ESTALE: /* Stale NFS file handle */ 3462 #endif /* ESTALE */ 3463 #ifdef ENETDOWN 3464 case ENETDOWN: /* Network is down */ 3465 #endif /* ENETDOWN */ 3466 #ifdef ENETUNREACH 3467 case ENETUNREACH: /* Network is unreachable */ 3468 #endif /* ENETUNREACH */ 3469 #ifdef ENETRESET 3470 case ENETRESET: /* Network dropped connection on reset */ 3471 #endif /* ENETRESET */ 3472 #ifdef ECONNABORTED 3473 case ECONNABORTED: /* Software caused connection abort */ 3474 #endif /* ECONNABORTED */ 3475 #ifdef ECONNRESET 3476 case ECONNRESET: /* Connection reset by peer */ 3477 #endif /* ECONNRESET */ 3478 #ifdef ENOBUFS 3479 case ENOBUFS: /* No buffer space available */ 3480 #endif /* ENOBUFS */ 3481 #ifdef ESHUTDOWN 3482 case ESHUTDOWN: /* Can't send after socket shutdown */ 3483 #endif /* ESHUTDOWN */ 3484 #ifdef ECONNREFUSED 3485 case ECONNREFUSED: /* Connection refused */ 3486 #endif /* ECONNREFUSED */ 3487 #ifdef EHOSTDOWN 3488 case EHOSTDOWN: /* Host is down */ 3489 #endif /* EHOSTDOWN */ 3490 #ifdef EHOSTUNREACH 3491 case EHOSTUNREACH: /* No route to host */ 3492 #endif /* EHOSTUNREACH */ 3493 #ifdef EDQUOT 3494 case EDQUOT: /* Disc quota exceeded */ 3495 #endif /* EDQUOT */ 3496 #ifdef EPROCLIM 3497 case EPROCLIM: /* Too many processes */ 3498 #endif /* EPROCLIM */ 3499 #ifdef EUSERS 3500 case EUSERS: /* Too many users */ 3501 #endif /* EUSERS */ 3502 #ifdef EDEADLK 3503 case EDEADLK: /* Resource deadlock avoided */ 3504 #endif /* EDEADLK */ 3505 #ifdef EISCONN 3506 case EISCONN: /* Socket already connected */ 3507 #endif /* EISCONN */ 3508 #ifdef EINPROGRESS 3509 case EINPROGRESS: /* Operation now in progress */ 3510 #endif /* EINPROGRESS */ 3511 #ifdef EALREADY 3512 case EALREADY: /* Operation already in progress */ 3513 #endif /* EALREADY */ 3514 #ifdef EADDRINUSE 3515 case EADDRINUSE: /* Address already in use */ 3516 #endif /* EADDRINUSE */ 3517 #ifdef EADDRNOTAVAIL 3518 case EADDRNOTAVAIL: /* Can't assign requested address */ 3519 #endif /* EADDRNOTAVAIL */ 3520 #ifdef ETXTBSY 3521 case ETXTBSY: /* (Apollo) file locked */ 3522 #endif /* ETXTBSY */ 3523 #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) 3524 case ENOSR: /* Out of streams resources */ 3525 #endif /* defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) */ 3526 #ifdef ENOLCK 3527 case ENOLCK: /* No locks available */ 3528 #endif /* ENOLCK */ 3529 case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */ 3530 return true; 3531 } 3532 3533 /* nope, must be permanent */ 3534 return false; 3535 } 3536 /* 3537 ** LOCKFILE -- lock a file using flock or (shudder) fcntl locking 3538 ** 3539 ** Parameters: 3540 ** fd -- the file descriptor of the file. 3541 ** filename -- the file name (for error messages). 3542 ** ext -- the filename extension. 3543 ** type -- type of the lock. Bits can be: 3544 ** LOCK_EX -- exclusive lock. 3545 ** LOCK_NB -- non-blocking. 3546 ** LOCK_UN -- unlock. 3547 ** 3548 ** Returns: 3549 ** true if the lock was acquired. 3550 ** false otherwise. 3551 */ 3552 3553 bool 3554 lockfile(fd, filename, ext, type) 3555 int fd; 3556 char *filename; 3557 char *ext; 3558 int type; 3559 { 3560 int i; 3561 int save_errno; 3562 # if !HASFLOCK 3563 int action; 3564 struct flock lfd; 3565 3566 if (ext == NULL) 3567 ext = ""; 3568 3569 memset(&lfd, '\0', sizeof(lfd)); 3570 if (bitset(LOCK_UN, type)) 3571 lfd.l_type = F_UNLCK; 3572 else if (bitset(LOCK_EX, type)) 3573 lfd.l_type = F_WRLCK; 3574 else 3575 lfd.l_type = F_RDLCK; 3576 3577 if (bitset(LOCK_NB, type)) 3578 action = F_SETLK; 3579 else 3580 action = F_SETLKW; 3581 3582 if (tTd(55, 60)) 3583 sm_dprintf("lockfile(%s%s, action=%d, type=%d): ", 3584 filename, ext, action, lfd.l_type); 3585 3586 while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR) 3587 continue; 3588 if (i >= 0) 3589 { 3590 if (tTd(55, 60)) 3591 sm_dprintf("SUCCESS\n"); 3592 return true; 3593 } 3594 save_errno = errno; 3595 3596 if (tTd(55, 60)) 3597 sm_dprintf("(%s) ", sm_errstring(save_errno)); 3598 3599 /* 3600 ** On SunOS, if you are testing using -oQ/tmp/mqueue or 3601 ** -oA/tmp/aliases or anything like that, and /tmp is mounted 3602 ** as type "tmp" (that is, served from swap space), the 3603 ** previous fcntl will fail with "Invalid argument" errors. 3604 ** Since this is fairly common during testing, we will assume 3605 ** that this indicates that the lock is successfully grabbed. 3606 */ 3607 3608 if (save_errno == EINVAL) 3609 { 3610 if (tTd(55, 60)) 3611 sm_dprintf("SUCCESS\n"); 3612 return true; 3613 } 3614 3615 if (!bitset(LOCK_NB, type) || 3616 (save_errno != EACCES && save_errno != EAGAIN)) 3617 { 3618 int omode = fcntl(fd, F_GETFL, 0); 3619 uid_t euid = geteuid(); 3620 3621 errno = save_errno; 3622 syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)", 3623 filename, ext, fd, type, omode, (long) euid); 3624 dumpfd(fd, true, true); 3625 } 3626 # else /* !HASFLOCK */ 3627 if (ext == NULL) 3628 ext = ""; 3629 3630 if (tTd(55, 60)) 3631 sm_dprintf("lockfile(%s%s, type=%o): ", filename, ext, type); 3632 3633 while ((i = flock(fd, type)) < 0 && errno == EINTR) 3634 continue; 3635 if (i >= 0) 3636 { 3637 if (tTd(55, 60)) 3638 sm_dprintf("SUCCESS\n"); 3639 return true; 3640 } 3641 save_errno = errno; 3642 3643 if (tTd(55, 60)) 3644 sm_dprintf("(%s) ", sm_errstring(save_errno)); 3645 3646 if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK) 3647 { 3648 int omode = fcntl(fd, F_GETFL, 0); 3649 uid_t euid = geteuid(); 3650 3651 errno = save_errno; 3652 syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)", 3653 filename, ext, fd, type, omode, (long) euid); 3654 dumpfd(fd, true, true); 3655 } 3656 # endif /* !HASFLOCK */ 3657 if (tTd(55, 60)) 3658 sm_dprintf("FAIL\n"); 3659 errno = save_errno; 3660 return false; 3661 } 3662 /* 3663 ** CHOWNSAFE -- tell if chown is "safe" (executable only by root) 3664 ** 3665 ** Unfortunately, given that we can't predict other systems on which 3666 ** a remote mounted (NFS) filesystem will be mounted, the answer is 3667 ** almost always that this is unsafe. 3668 ** 3669 ** Note also that many operating systems have non-compliant 3670 ** implementations of the _POSIX_CHOWN_RESTRICTED variable and the 3671 ** fpathconf() routine. According to IEEE 1003.1-1990, if 3672 ** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then 3673 ** no non-root process can give away the file. However, vendors 3674 ** don't take NFS into account, so a comfortable value of 3675 ** _POSIX_CHOWN_RESTRICTED tells us nothing. 3676 ** 3677 ** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf() 3678 ** even on files where chown is not restricted. Many systems get 3679 ** this wrong on NFS-based filesystems (that is, they say that chown 3680 ** is restricted [safe] on NFS filesystems where it may not be, since 3681 ** other systems can access the same filesystem and do file giveaway; 3682 ** only the NFS server knows for sure!) Hence, it is important to 3683 ** get the value of SAFENFSPATHCONF correct -- it should be defined 3684 ** _only_ after testing (see test/t_pathconf.c) a system on an unsafe 3685 ** NFS-based filesystem to ensure that you can get meaningful results. 3686 ** If in doubt, assume unsafe! 3687 ** 3688 ** You may also need to tweak IS_SAFE_CHOWN -- it should be a 3689 ** condition indicating whether the return from pathconf indicates 3690 ** that chown is safe (typically either > 0 or >= 0 -- there isn't 3691 ** even any agreement about whether a zero return means that a file 3692 ** is or is not safe). It defaults to "> 0". 3693 ** 3694 ** If the parent directory is safe (writable only by owner back 3695 ** to the root) then we can relax slightly and trust fpathconf 3696 ** in more circumstances. This is really a crock -- if this is an 3697 ** NFS mounted filesystem then we really know nothing about the 3698 ** underlying implementation. However, most systems pessimize and 3699 ** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which 3700 ** we interpret as unsafe, as we should. Thus, this heuristic gets 3701 ** us into a possible problem only on systems that have a broken 3702 ** pathconf implementation and which are also poorly configured 3703 ** (have :include: files in group- or world-writable directories). 3704 ** 3705 ** Parameters: 3706 ** fd -- the file descriptor to check. 3707 ** safedir -- set if the parent directory is safe. 3708 ** 3709 ** Returns: 3710 ** true -- if the chown(2) operation is "safe" -- that is, 3711 ** only root can chown the file to an arbitrary user. 3712 ** false -- if an arbitrary user can give away a file. 3713 */ 3714 3715 #ifndef IS_SAFE_CHOWN 3716 # define IS_SAFE_CHOWN > 0 3717 #endif /* ! IS_SAFE_CHOWN */ 3718 3719 bool 3720 chownsafe(fd, safedir) 3721 int fd; 3722 bool safedir; 3723 { 3724 # if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ 3725 (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H)) 3726 int rval; 3727 3728 /* give the system administrator a chance to override */ 3729 if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail)) 3730 return true; 3731 3732 /* 3733 ** Some systems (e.g., SunOS) seem to have the call and the 3734 ** #define _PC_CHOWN_RESTRICTED, but don't actually implement 3735 ** the call. This heuristic checks for that. 3736 */ 3737 3738 errno = 0; 3739 rval = fpathconf(fd, _PC_CHOWN_RESTRICTED); 3740 # if SAFENFSPATHCONF 3741 return errno == 0 && rval IS_SAFE_CHOWN; 3742 # else /* SAFENFSPATHCONF */ 3743 return safedir && errno == 0 && rval IS_SAFE_CHOWN; 3744 # endif /* SAFENFSPATHCONF */ 3745 # else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */ 3746 return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail); 3747 # endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */ 3748 } 3749 /* 3750 ** RESETLIMITS -- reset system controlled resource limits 3751 ** 3752 ** This is to avoid denial-of-service attacks 3753 ** 3754 ** Parameters: 3755 ** none 3756 ** 3757 ** Returns: 3758 ** none 3759 */ 3760 3761 #if HASSETRLIMIT 3762 # ifdef RLIMIT_NEEDS_SYS_TIME_H 3763 # include <sm/time.h> 3764 # endif /* RLIMIT_NEEDS_SYS_TIME_H */ 3765 # include <sys/resource.h> 3766 #endif /* HASSETRLIMIT */ 3767 3768 void 3769 resetlimits() 3770 { 3771 #if HASSETRLIMIT 3772 struct rlimit lim; 3773 3774 lim.rlim_cur = lim.rlim_max = RLIM_INFINITY; 3775 (void) setrlimit(RLIMIT_CPU, &lim); 3776 (void) setrlimit(RLIMIT_FSIZE, &lim); 3777 # ifdef RLIMIT_NOFILE 3778 lim.rlim_cur = lim.rlim_max = FD_SETSIZE; 3779 (void) setrlimit(RLIMIT_NOFILE, &lim); 3780 # endif /* RLIMIT_NOFILE */ 3781 #else /* HASSETRLIMIT */ 3782 # if HASULIMIT 3783 (void) ulimit(2, 0x3fffff); 3784 (void) ulimit(4, FD_SETSIZE); 3785 # endif /* HASULIMIT */ 3786 #endif /* HASSETRLIMIT */ 3787 errno = 0; 3788 } 3789 /* 3790 ** SETVENDOR -- process vendor code from V configuration line 3791 ** 3792 ** Parameters: 3793 ** vendor -- string representation of vendor. 3794 ** 3795 ** Returns: 3796 ** true -- if ok. 3797 ** false -- if vendor code could not be processed. 3798 ** 3799 ** Side Effects: 3800 ** It is reasonable to set mode flags here to tweak 3801 ** processing in other parts of the code if necessary. 3802 ** For example, if you are a vendor that uses $%y to 3803 ** indicate YP lookups, you could enable that here. 3804 */ 3805 3806 bool 3807 setvendor(vendor) 3808 char *vendor; 3809 { 3810 if (sm_strcasecmp(vendor, "Berkeley") == 0) 3811 { 3812 VendorCode = VENDOR_BERKELEY; 3813 return true; 3814 } 3815 3816 /* add vendor extensions here */ 3817 3818 #ifdef SUN_EXTENSIONS 3819 if (sm_strcasecmp(vendor, "Sun") == 0) 3820 { 3821 VendorCode = VENDOR_SUN; 3822 return true; 3823 } 3824 #endif /* SUN_EXTENSIONS */ 3825 #ifdef DEC 3826 if (sm_strcasecmp(vendor, "Digital") == 0) 3827 { 3828 VendorCode = VENDOR_DEC; 3829 return true; 3830 } 3831 #endif /* DEC */ 3832 3833 #if defined(VENDOR_NAME) && defined(VENDOR_CODE) 3834 if (sm_strcasecmp(vendor, VENDOR_NAME) == 0) 3835 { 3836 VendorCode = VENDOR_CODE; 3837 return true; 3838 } 3839 #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ 3840 3841 return false; 3842 } 3843 /* 3844 ** GETVENDOR -- return vendor name based on vendor code 3845 ** 3846 ** Parameters: 3847 ** vendorcode -- numeric representation of vendor. 3848 ** 3849 ** Returns: 3850 ** string containing vendor name. 3851 */ 3852 3853 char * 3854 getvendor(vendorcode) 3855 int vendorcode; 3856 { 3857 #if defined(VENDOR_NAME) && defined(VENDOR_CODE) 3858 /* 3859 ** Can't have the same switch case twice so need to 3860 ** handle VENDOR_CODE outside of switch. It might 3861 ** match one of the existing VENDOR_* codes. 3862 */ 3863 3864 if (vendorcode == VENDOR_CODE) 3865 return VENDOR_NAME; 3866 #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ 3867 3868 switch (vendorcode) 3869 { 3870 case VENDOR_BERKELEY: 3871 return "Berkeley"; 3872 3873 case VENDOR_SUN: 3874 return "Sun"; 3875 3876 case VENDOR_HP: 3877 return "HP"; 3878 3879 case VENDOR_IBM: 3880 return "IBM"; 3881 3882 case VENDOR_SENDMAIL: 3883 return "Sendmail"; 3884 3885 default: 3886 return "Unknown"; 3887 } 3888 } 3889 /* 3890 ** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults 3891 ** 3892 ** Vendor_pre_defaults is called before reading the configuration 3893 ** file; vendor_post_defaults is called immediately after. 3894 ** 3895 ** Parameters: 3896 ** e -- the global environment to initialize. 3897 ** 3898 ** Returns: 3899 ** none. 3900 */ 3901 3902 #if SHARE_V1 3903 int DefShareUid; /* default share uid to run as -- unused??? */ 3904 #endif /* SHARE_V1 */ 3905 3906 void 3907 vendor_pre_defaults(e) 3908 ENVELOPE *e; 3909 { 3910 #if SHARE_V1 3911 /* OTHERUID is defined in shares.h, do not be alarmed */ 3912 DefShareUid = OTHERUID; 3913 #endif /* SHARE_V1 */ 3914 #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) 3915 sun_pre_defaults(e); 3916 #endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ 3917 #ifdef apollo 3918 /* 3919 ** stupid domain/os can't even open 3920 ** /etc/mail/sendmail.cf without this 3921 */ 3922 3923 sm_setuserenv("ISP", NULL); 3924 sm_setuserenv("SYSTYPE", NULL); 3925 #endif /* apollo */ 3926 } 3927 3928 3929 void 3930 vendor_post_defaults(e) 3931 ENVELOPE *e; 3932 { 3933 #ifdef __QNX__ 3934 /* Makes sure the SOCK environment variable remains */ 3935 sm_setuserenv("SOCK", NULL); 3936 #endif /* __QNX__ */ 3937 #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) 3938 sun_post_defaults(e); 3939 #endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ 3940 } 3941 /* 3942 ** VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode 3943 */ 3944 3945 void 3946 vendor_daemon_setup(e) 3947 ENVELOPE *e; 3948 { 3949 #if HASSETLOGIN 3950 (void) setlogin(RunAsUserName); 3951 #endif /* HASSETLOGIN */ 3952 #if SECUREWARE 3953 if (getluid() != -1) 3954 { 3955 usrerr("Daemon cannot have LUID"); 3956 finis(false, true, EX_USAGE); 3957 } 3958 #endif /* SECUREWARE */ 3959 } 3960 /* 3961 ** VENDOR_SET_UID -- do setup for setting a user id 3962 ** 3963 ** This is called when we are still root. 3964 ** 3965 ** Parameters: 3966 ** uid -- the uid we are about to become. 3967 ** 3968 ** Returns: 3969 ** none. 3970 */ 3971 3972 void 3973 vendor_set_uid(uid) 3974 UID_T uid; 3975 { 3976 /* 3977 ** We need to setup the share groups (lnodes) 3978 ** and add auditing information (luid's) 3979 ** before we loose our ``root''ness. 3980 */ 3981 #if SHARE_V1 3982 if (setupshares(uid, syserr) != 0) 3983 syserr("Unable to set up shares"); 3984 #endif /* SHARE_V1 */ 3985 #if SECUREWARE 3986 (void) setup_secure(uid); 3987 #endif /* SECUREWARE */ 3988 } 3989 /* 3990 ** VALIDATE_CONNECTION -- check connection for rationality 3991 ** 3992 ** If the connection is rejected, this routine should log an 3993 ** appropriate message -- but should never issue any SMTP protocol. 3994 ** 3995 ** Parameters: 3996 ** sap -- a pointer to a SOCKADDR naming the peer. 3997 ** hostname -- the name corresponding to sap. 3998 ** e -- the current envelope. 3999 ** 4000 ** Returns: 4001 ** error message from rejection. 4002 ** NULL if not rejected. 4003 */ 4004 4005 #if TCPWRAPPERS 4006 # include <tcpd.h> 4007 4008 /* tcpwrappers does no logging, but you still have to declare these -- ugh */ 4009 int allow_severity = LOG_INFO; 4010 int deny_severity = LOG_NOTICE; 4011 #endif /* TCPWRAPPERS */ 4012 4013 char * 4014 validate_connection(sap, hostname, e) 4015 SOCKADDR *sap; 4016 char *hostname; 4017 ENVELOPE *e; 4018 { 4019 #if TCPWRAPPERS 4020 char *host; 4021 char *addr; 4022 extern int hosts_ctl(); 4023 #endif /* TCPWRAPPERS */ 4024 4025 if (tTd(48, 3)) 4026 sm_dprintf("validate_connection(%s, %s)\n", 4027 hostname, anynet_ntoa(sap)); 4028 4029 connection_rate_check(sap, e); 4030 if (rscheck("check_relay", hostname, anynet_ntoa(sap), e, 4031 RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID, NULL, NULL) != EX_OK) 4032 { 4033 static char reject[BUFSIZ*2]; 4034 extern char MsgBuf[]; 4035 4036 if (tTd(48, 4)) 4037 sm_dprintf(" ... validate_connection: BAD (rscheck)\n"); 4038 4039 if (strlen(MsgBuf) >= 3) 4040 (void) sm_strlcpy(reject, MsgBuf, sizeof(reject)); 4041 else 4042 (void) sm_strlcpy(reject, "Access denied", sizeof(reject)); 4043 4044 return reject; 4045 } 4046 4047 #if TCPWRAPPERS 4048 if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']') 4049 host = "unknown"; 4050 else 4051 host = hostname; 4052 addr = anynet_ntoa(sap); 4053 4054 # if NETINET6 4055 /* TCP/Wrappers don't want the IPv6: protocol label */ 4056 if (addr != NULL && sm_strncasecmp(addr, "IPv6:", 5) == 0) 4057 addr += 5; 4058 # endif /* NETINET6 */ 4059 4060 if (!hosts_ctl("sendmail", host, addr, STRING_UNKNOWN)) 4061 { 4062 if (tTd(48, 4)) 4063 sm_dprintf(" ... validate_connection: BAD (tcpwrappers)\n"); 4064 if (LogLevel > 3) 4065 sm_syslog(LOG_NOTICE, e->e_id, 4066 "tcpwrappers (%s, %s) rejection", 4067 host, addr); 4068 return "Access denied"; 4069 } 4070 #endif /* TCPWRAPPERS */ 4071 if (tTd(48, 4)) 4072 sm_dprintf(" ... validate_connection: OK\n"); 4073 return NULL; 4074 } 4075 4076 /* 4077 ** STRTOL -- convert string to long integer 4078 ** 4079 ** For systems that don't have it in the C library. 4080 ** 4081 ** This is taken verbatim from the 4.4-Lite C library. 4082 */ 4083 4084 #if NEEDSTRTOL 4085 4086 # if defined(LIBC_SCCS) && !defined(lint) 4087 static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; 4088 # endif /* defined(LIBC_SCCS) && !defined(lint) */ 4089 4090 /* 4091 ** Convert a string to a long integer. 4092 ** 4093 ** Ignores `locale' stuff. Assumes that the upper and lower case 4094 ** alphabets and digits are each contiguous. 4095 */ 4096 4097 long 4098 strtol(nptr, endptr, base) 4099 const char *nptr; 4100 char **endptr; 4101 register int base; 4102 { 4103 register const char *s = nptr; 4104 register unsigned long acc; 4105 register int c; 4106 register unsigned long cutoff; 4107 register int neg = 0, any, cutlim; 4108 4109 /* 4110 ** Skip white space and pick up leading +/- sign if any. 4111 ** If base is 0, allow 0x for hex and 0 for octal, else 4112 ** assume decimal; if base is already 16, allow 0x. 4113 */ 4114 do { 4115 c = *s++; 4116 } while (isascii(c) && isspace(c)); 4117 if (c == '-') { 4118 neg = 1; 4119 c = *s++; 4120 } else if (c == '+') 4121 c = *s++; 4122 if ((base == 0 || base == 16) && 4123 c == '0' && (*s == 'x' || *s == 'X')) { 4124 c = s[1]; 4125 s += 2; 4126 base = 16; 4127 } 4128 if (base == 0) 4129 base = c == '0' ? 8 : 10; 4130 4131 /* 4132 ** Compute the cutoff value between legal numbers and illegal 4133 ** numbers. That is the largest legal value, divided by the 4134 ** base. An input number that is greater than this value, if 4135 ** followed by a legal input character, is too big. One that 4136 ** is equal to this value may be valid or not; the limit 4137 ** between valid and invalid numbers is then based on the last 4138 ** digit. For instance, if the range for longs is 4139 ** [-2147483648..2147483647] and the input base is 10, 4140 ** cutoff will be set to 214748364 and cutlim to either 4141 ** 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 4142 ** a value > 214748364, or equal but the next digit is > 7 (or 8), 4143 ** the number is too big, and we will return a range error. 4144 ** 4145 ** Set any if any `digits' consumed; make it negative to indicate 4146 ** overflow. 4147 */ 4148 cutoff = neg ? -(unsigned long) LONG_MIN : LONG_MAX; 4149 cutlim = cutoff % (unsigned long) base; 4150 cutoff /= (unsigned long) base; 4151 for (acc = 0, any = 0;; c = *s++) { 4152 if (isascii(c) && isdigit(c)) 4153 c -= '0'; 4154 else if (isascii(c) && isalpha(c)) 4155 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 4156 else 4157 break; 4158 if (c >= base) 4159 break; 4160 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 4161 any = -1; 4162 else { 4163 any = 1; 4164 acc *= base; 4165 acc += c; 4166 } 4167 } 4168 if (any < 0) { 4169 acc = neg ? LONG_MIN : LONG_MAX; 4170 errno = ERANGE; 4171 } else if (neg) 4172 acc = -acc; 4173 if (endptr != 0) 4174 *endptr = (char *)(any ? s - 1 : nptr); 4175 return acc; 4176 } 4177 4178 #endif /* NEEDSTRTOL */ 4179 /* 4180 ** STRSTR -- find first substring in string 4181 ** 4182 ** Parameters: 4183 ** big -- the big (full) string. 4184 ** little -- the little (sub) string. 4185 ** 4186 ** Returns: 4187 ** A pointer to the first instance of little in big. 4188 ** big if little is the null string. 4189 ** NULL if little is not contained in big. 4190 */ 4191 4192 #if NEEDSTRSTR 4193 4194 char * 4195 strstr(big, little) 4196 char *big; 4197 char *little; 4198 { 4199 register char *p = big; 4200 int l; 4201 4202 if (*little == '\0') 4203 return big; 4204 l = strlen(little); 4205 4206 while ((p = strchr(p, *little)) != NULL) 4207 { 4208 if (strncmp(p, little, l) == 0) 4209 return p; 4210 p++; 4211 } 4212 return NULL; 4213 } 4214 4215 #endif /* NEEDSTRSTR */ 4216 /* 4217 ** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX 4218 ** 4219 ** Some operating systems have weird problems with the gethostbyXXX 4220 ** routines. For example, Solaris versions at least through 2.3 4221 ** don't properly deliver a canonical h_name field. This tries to 4222 ** work around these problems. 4223 ** 4224 ** Support IPv6 as well as IPv4. 4225 */ 4226 4227 #if NETINET6 && NEEDSGETIPNODE 4228 4229 # ifndef AI_DEFAULT 4230 # define AI_DEFAULT 0 /* dummy */ 4231 # endif /* ! AI_DEFAULT */ 4232 # ifndef AI_ADDRCONFIG 4233 # define AI_ADDRCONFIG 0 /* dummy */ 4234 # endif /* ! AI_ADDRCONFIG */ 4235 # ifndef AI_V4MAPPED 4236 # define AI_V4MAPPED 0 /* dummy */ 4237 # endif /* ! AI_V4MAPPED */ 4238 # ifndef AI_ALL 4239 # define AI_ALL 0 /* dummy */ 4240 # endif /* ! AI_ALL */ 4241 4242 static struct hostent * 4243 sm_getipnodebyname(name, family, flags, err) 4244 const char *name; 4245 int family; 4246 int flags; 4247 int *err; 4248 { 4249 struct hostent *h; 4250 # if HAS_GETHOSTBYNAME2 4251 4252 h = gethostbyname2(name, family); 4253 if (h == NULL) 4254 *err = h_errno; 4255 return h; 4256 4257 # else /* HAS_GETHOSTBYNAME2 */ 4258 bool resv6 = true; 4259 4260 if (family == AF_INET6) 4261 { 4262 /* From RFC2133, section 6.1 */ 4263 resv6 = bitset(RES_USE_INET6, _res.options); 4264 _res.options |= RES_USE_INET6; 4265 } 4266 SM_SET_H_ERRNO(0); 4267 h = gethostbyname(name); 4268 if (!resv6) 4269 _res.options &= ~RES_USE_INET6; 4270 4271 /* the function is supposed to return only the requested family */ 4272 if (h != NULL && h->h_addrtype != family) 4273 { 4274 # if NETINET6 4275 freehostent(h); 4276 # endif /* NETINET6 */ 4277 h = NULL; 4278 *err = NO_DATA; 4279 } 4280 else 4281 *err = h_errno; 4282 return h; 4283 # endif /* HAS_GETHOSTBYNAME2 */ 4284 } 4285 4286 static struct hostent * 4287 sm_getipnodebyaddr(addr, len, family, err) 4288 const void *addr; 4289 size_t len; 4290 int family; 4291 int *err; 4292 { 4293 struct hostent *h; 4294 4295 SM_SET_H_ERRNO(0); 4296 h = gethostbyaddr(addr, len, family); 4297 *err = h_errno; 4298 return h; 4299 } 4300 4301 void 4302 freehostent(h) 4303 struct hostent *h; 4304 { 4305 /* 4306 ** Stub routine -- if they don't have getipnodeby*(), 4307 ** they probably don't have the free routine either. 4308 */ 4309 4310 return; 4311 } 4312 #endif /* NETINET6 && NEEDSGETIPNODE */ 4313 4314 struct hostent * 4315 sm_gethostbyname(name, family) 4316 char *name; 4317 int family; 4318 { 4319 int save_errno; 4320 struct hostent *h = NULL; 4321 #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) 4322 # if SOLARIS == 20300 || SOLARIS == 203 4323 static struct hostent hp; 4324 static char buf[1000]; 4325 extern struct hostent *_switch_gethostbyname_r(); 4326 4327 if (tTd(61, 10)) 4328 sm_dprintf("_switch_gethostbyname_r(%s)... ", name); 4329 h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); 4330 save_errno = errno; 4331 # else /* SOLARIS == 20300 || SOLARIS == 203 */ 4332 extern struct hostent *__switch_gethostbyname(); 4333 4334 if (tTd(61, 10)) 4335 sm_dprintf("__switch_gethostbyname(%s)... ", name); 4336 h = __switch_gethostbyname(name); 4337 save_errno = errno; 4338 # endif /* SOLARIS == 20300 || SOLARIS == 203 */ 4339 #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ 4340 int nmaps; 4341 # if NETINET6 4342 # ifndef SM_IPNODEBYNAME_FLAGS 4343 /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */ 4344 # define SM_IPNODEBYNAME_FLAGS AI_ADDRCONFIG 4345 # endif /* SM_IPNODEBYNAME_FLAGS */ 4346 4347 int flags = SM_IPNODEBYNAME_FLAGS; 4348 int err; 4349 # endif /* NETINET6 */ 4350 char *maptype[MAXMAPSTACK]; 4351 short mapreturn[MAXMAPACTIONS]; 4352 char hbuf[MAXNAME]; 4353 4354 if (tTd(61, 10)) 4355 sm_dprintf("sm_gethostbyname(%s, %d)... ", name, family); 4356 4357 # if NETINET6 4358 # if ADDRCONFIG_IS_BROKEN 4359 flags &= ~AI_ADDRCONFIG; 4360 # endif /* ADDRCONFIG_IS_BROKEN */ 4361 h = sm_getipnodebyname(name, family, flags, &err); 4362 SM_SET_H_ERRNO(err); 4363 # else /* NETINET6 */ 4364 h = gethostbyname(name); 4365 # endif /* NETINET6 */ 4366 4367 save_errno = errno; 4368 if (h == NULL) 4369 { 4370 if (tTd(61, 10)) 4371 sm_dprintf("failure\n"); 4372 4373 nmaps = switch_map_find("hosts", maptype, mapreturn); 4374 while (--nmaps >= 0) 4375 { 4376 if (strcmp(maptype[nmaps], "nis") == 0 || 4377 strcmp(maptype[nmaps], "files") == 0) 4378 break; 4379 } 4380 4381 if (nmaps >= 0) 4382 { 4383 /* try short name */ 4384 if (strlen(name) > sizeof(hbuf) - 1) 4385 { 4386 errno = save_errno; 4387 return NULL; 4388 } 4389 (void) sm_strlcpy(hbuf, name, sizeof(hbuf)); 4390 (void) shorten_hostname(hbuf); 4391 4392 /* if it hasn't been shortened, there's no point */ 4393 if (strcmp(hbuf, name) != 0) 4394 { 4395 if (tTd(61, 10)) 4396 sm_dprintf("sm_gethostbyname(%s, %d)... ", 4397 hbuf, family); 4398 4399 # if NETINET6 4400 h = sm_getipnodebyname(hbuf, family, flags, &err); 4401 SM_SET_H_ERRNO(err); 4402 save_errno = errno; 4403 # else /* NETINET6 */ 4404 h = gethostbyname(hbuf); 4405 save_errno = errno; 4406 # endif /* NETINET6 */ 4407 } 4408 } 4409 } 4410 #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ 4411 4412 /* the function is supposed to return only the requested family */ 4413 if (h != NULL && h->h_addrtype != family) 4414 { 4415 # if NETINET6 4416 freehostent(h); 4417 # endif /* NETINET6 */ 4418 h = NULL; 4419 SM_SET_H_ERRNO(NO_DATA); 4420 } 4421 4422 if (tTd(61, 10)) 4423 { 4424 if (h == NULL) 4425 sm_dprintf("failure\n"); 4426 else 4427 { 4428 sm_dprintf("%s\n", h->h_name); 4429 if (tTd(61, 11)) 4430 { 4431 struct in_addr ia; 4432 size_t i; 4433 #if NETINET6 4434 struct in6_addr ia6; 4435 char buf6[INET6_ADDRSTRLEN]; 4436 #endif /* NETINET6 */ 4437 4438 if (h->h_aliases != NULL) 4439 for (i = 0; h->h_aliases[i] != NULL; 4440 i++) 4441 sm_dprintf("\talias: %s\n", 4442 h->h_aliases[i]); 4443 for (i = 0; h->h_addr_list[i] != NULL; i++) 4444 { 4445 char *addr; 4446 4447 addr = NULL; 4448 #if NETINET6 4449 if (h->h_addrtype == AF_INET6) 4450 { 4451 memmove(&ia6, h->h_addr_list[i], 4452 IN6ADDRSZ); 4453 addr = anynet_ntop(&ia6, 4454 buf6, sizeof(buf6)); 4455 } 4456 else 4457 #endif /* NETINET6 */ 4458 /* "else" in #if code above */ 4459 { 4460 memmove(&ia, h->h_addr_list[i], 4461 INADDRSZ); 4462 addr = (char *) inet_ntoa(ia); 4463 } 4464 if (addr != NULL) 4465 sm_dprintf("\taddr: %s\n", addr); 4466 } 4467 } 4468 } 4469 } 4470 errno = save_errno; 4471 return h; 4472 } 4473 4474 struct hostent * 4475 sm_gethostbyaddr(addr, len, type) 4476 char *addr; 4477 int len; 4478 int type; 4479 { 4480 struct hostent *hp; 4481 4482 #if NETINET6 4483 if (type == AF_INET6 && 4484 IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *) addr)) 4485 { 4486 /* Avoid reverse lookup for IPv6 unspecified address */ 4487 SM_SET_H_ERRNO(HOST_NOT_FOUND); 4488 return NULL; 4489 } 4490 #endif /* NETINET6 */ 4491 4492 #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) 4493 # if SOLARIS == 20300 || SOLARIS == 203 4494 { 4495 static struct hostent he; 4496 static char buf[1000]; 4497 extern struct hostent *_switch_gethostbyaddr_r(); 4498 4499 hp = _switch_gethostbyaddr_r(addr, len, type, &he, 4500 buf, sizeof(buf), &h_errno); 4501 } 4502 # else /* SOLARIS == 20300 || SOLARIS == 203 */ 4503 { 4504 extern struct hostent *__switch_gethostbyaddr(); 4505 4506 hp = __switch_gethostbyaddr(addr, len, type); 4507 } 4508 # endif /* SOLARIS == 20300 || SOLARIS == 203 */ 4509 #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ 4510 # if NETINET6 4511 { 4512 int err; 4513 4514 hp = sm_getipnodebyaddr(addr, len, type, &err); 4515 SM_SET_H_ERRNO(err); 4516 } 4517 # else /* NETINET6 */ 4518 hp = gethostbyaddr(addr, len, type); 4519 # endif /* NETINET6 */ 4520 #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ 4521 return hp; 4522 } 4523 /* 4524 ** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid 4525 */ 4526 4527 struct passwd * 4528 sm_getpwnam(user) 4529 char *user; 4530 { 4531 #ifdef _AIX4 4532 extern struct passwd *_getpwnam_shadow(const char *, const int); 4533 4534 return _getpwnam_shadow(user, 0); 4535 #else /* _AIX4 */ 4536 return getpwnam(user); 4537 #endif /* _AIX4 */ 4538 } 4539 4540 struct passwd * 4541 sm_getpwuid(uid) 4542 UID_T uid; 4543 { 4544 #if defined(_AIX4) && 0 4545 extern struct passwd *_getpwuid_shadow(const int, const int); 4546 4547 return _getpwuid_shadow(uid,0); 4548 #else /* defined(_AIX4) && 0 */ 4549 return getpwuid(uid); 4550 #endif /* defined(_AIX4) && 0 */ 4551 } 4552 /* 4553 ** SECUREWARE_SETUP_SECURE -- Convex SecureWare setup 4554 ** 4555 ** Set up the trusted computing environment for C2 level security 4556 ** under SecureWare. 4557 ** 4558 ** Parameters: 4559 ** uid -- uid of the user to initialize in the TCB 4560 ** 4561 ** Returns: 4562 ** none 4563 ** 4564 ** Side Effects: 4565 ** Initialized the user in the trusted computing base 4566 */ 4567 4568 #if SECUREWARE 4569 4570 # include <sys/security.h> 4571 # include <prot.h> 4572 4573 void 4574 secureware_setup_secure(uid) 4575 UID_T uid; 4576 { 4577 int rc; 4578 4579 if (getluid() != -1) 4580 return; 4581 4582 if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN) 4583 { 4584 switch (rc) 4585 { 4586 case SSI_NO_PRPW_ENTRY: 4587 syserr("No protected passwd entry, uid = %d", 4588 (int) uid); 4589 break; 4590 4591 case SSI_LOCKED: 4592 syserr("Account has been disabled, uid = %d", 4593 (int) uid); 4594 break; 4595 4596 case SSI_RETIRED: 4597 syserr("Account has been retired, uid = %d", 4598 (int) uid); 4599 break; 4600 4601 case SSI_BAD_SET_LUID: 4602 syserr("Could not set LUID, uid = %d", (int) uid); 4603 break; 4604 4605 case SSI_BAD_SET_PRIVS: 4606 syserr("Could not set kernel privs, uid = %d", 4607 (int) uid); 4608 4609 default: 4610 syserr("Unknown return code (%d) from set_secure_info(%d)", 4611 rc, (int) uid); 4612 break; 4613 } 4614 finis(false, true, EX_NOPERM); 4615 } 4616 } 4617 #endif /* SECUREWARE */ 4618 /* 4619 ** ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address 4620 ** 4621 ** Add hostnames to class 'w' based on the IP address read from 4622 ** the network interface. 4623 ** 4624 ** Parameters: 4625 ** sa -- a pointer to a SOCKADDR containing the address 4626 ** 4627 ** Returns: 4628 ** 0 if successful, -1 if host lookup fails. 4629 */ 4630 4631 static int 4632 add_hostnames(sa) 4633 SOCKADDR *sa; 4634 { 4635 struct hostent *hp; 4636 char **ha; 4637 char hnb[MAXHOSTNAMELEN]; 4638 4639 /* lookup name with IP address */ 4640 switch (sa->sa.sa_family) 4641 { 4642 #if NETINET 4643 case AF_INET: 4644 hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr, 4645 sizeof(sa->sin.sin_addr), 4646 sa->sa.sa_family); 4647 break; 4648 #endif /* NETINET */ 4649 4650 #if NETINET6 4651 case AF_INET6: 4652 hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr, 4653 sizeof(sa->sin6.sin6_addr), 4654 sa->sa.sa_family); 4655 break; 4656 #endif /* NETINET6 */ 4657 4658 default: 4659 /* Give warning about unsupported family */ 4660 if (LogLevel > 3) 4661 sm_syslog(LOG_WARNING, NOQID, 4662 "Unsupported address family %d: %.100s", 4663 sa->sa.sa_family, anynet_ntoa(sa)); 4664 return -1; 4665 } 4666 4667 if (hp == NULL) 4668 { 4669 int save_errno = errno; 4670 4671 if (LogLevel > 3 && 4672 #if NETINET && defined(IN_LINKLOCAL) 4673 !(sa->sa.sa_family == AF_INET && 4674 IN_LINKLOCAL(ntohl(sa->sin.sin_addr.s_addr))) && 4675 #endif /* NETINET && defined(IN_LINKLOCAL) */ 4676 #if NETINET6 4677 !(sa->sa.sa_family == AF_INET6 && 4678 IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) && 4679 #endif /* NETINET6 */ 4680 true) 4681 sm_syslog(LOG_WARNING, NOQID, 4682 "gethostbyaddr(%.100s) failed: %d", 4683 anynet_ntoa(sa), 4684 #if NAMED_BIND 4685 h_errno 4686 #else /* NAMED_BIND */ 4687 -1 4688 #endif /* NAMED_BIND */ 4689 ); 4690 errno = save_errno; 4691 return -1; 4692 } 4693 4694 /* save its cname */ 4695 if (!wordinclass((char *) hp->h_name, 'w')) 4696 { 4697 setclass('w', (char *) hp->h_name); 4698 if (tTd(0, 4)) 4699 sm_dprintf("\ta.k.a.: %s\n", hp->h_name); 4700 4701 if (sm_snprintf(hnb, sizeof(hnb), "[%s]", hp->h_name) < 4702 sizeof(hnb) 4703 && !wordinclass((char *) hnb, 'w')) 4704 setclass('w', hnb); 4705 } 4706 else 4707 { 4708 if (tTd(0, 43)) 4709 sm_dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name); 4710 } 4711 4712 /* save all it aliases name */ 4713 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 4714 { 4715 if (!wordinclass(*ha, 'w')) 4716 { 4717 setclass('w', *ha); 4718 if (tTd(0, 4)) 4719 sm_dprintf("\ta.k.a.: %s\n", *ha); 4720 if (sm_snprintf(hnb, sizeof(hnb), 4721 "[%s]", *ha) < sizeof(hnb) && 4722 !wordinclass((char *) hnb, 'w')) 4723 setclass('w', hnb); 4724 } 4725 else 4726 { 4727 if (tTd(0, 43)) 4728 sm_dprintf("\ta.k.a.: %s (already in $=w)\n", 4729 *ha); 4730 } 4731 } 4732 #if NETINET6 4733 freehostent(hp); 4734 #endif /* NETINET6 */ 4735 return 0; 4736 } 4737 /* 4738 ** LOAD_IF_NAMES -- load interface-specific names into $=w 4739 ** 4740 ** Parameters: 4741 ** none. 4742 ** 4743 ** Returns: 4744 ** none. 4745 ** 4746 ** Side Effects: 4747 ** Loads $=w with the names of all the interfaces. 4748 */ 4749 4750 #if !NETINET 4751 # define SIOCGIFCONF_IS_BROKEN 1 /* XXX */ 4752 #endif /* !NETINET */ 4753 4754 #if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN 4755 struct rtentry; 4756 struct mbuf; 4757 # ifndef SUNOS403 4758 # include <sm/time.h> 4759 # endif /* ! SUNOS403 */ 4760 # if (_AIX4 >= 40300) && !defined(_NET_IF_H) 4761 # undef __P 4762 # endif /* (_AIX4 >= 40300) && !defined(_NET_IF_H) */ 4763 # include <net/if.h> 4764 #endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ 4765 4766 void 4767 load_if_names() 4768 { 4769 # if NETINET6 && defined(SIOCGLIFCONF) 4770 # ifdef __hpux 4771 4772 /* 4773 ** Unfortunately, HP has changed all of the structures, 4774 ** making life difficult for implementors. 4775 */ 4776 4777 # define lifconf if_laddrconf 4778 # define lifc_len iflc_len 4779 # define lifc_buf iflc_buf 4780 # define lifreq if_laddrreq 4781 # define lifr_addr iflr_addr 4782 # define lifr_name iflr_name 4783 # define lifr_flags iflr_flags 4784 # define ss_family sa_family 4785 # undef SIOCGLIFNUM 4786 # endif /* __hpux */ 4787 4788 int s; 4789 int i; 4790 size_t len; 4791 int numifs; 4792 char *buf; 4793 struct lifconf lifc; 4794 # ifdef SIOCGLIFNUM 4795 struct lifnum lifn; 4796 # endif /* SIOCGLIFNUM */ 4797 4798 s = socket(InetMode, SOCK_DGRAM, 0); 4799 if (s == -1) 4800 return; 4801 4802 /* get the list of known IP address from the kernel */ 4803 # ifdef __hpux 4804 i = ioctl(s, SIOCGIFNUM, (char *) &numifs); 4805 # endif /* __hpux */ 4806 # ifdef SIOCGLIFNUM 4807 lifn.lifn_family = AF_UNSPEC; 4808 lifn.lifn_flags = 0; 4809 i = ioctl(s, SIOCGLIFNUM, (char *)&lifn); 4810 numifs = lifn.lifn_count; 4811 # endif /* SIOCGLIFNUM */ 4812 4813 # if defined(__hpux) || defined(SIOCGLIFNUM) 4814 if (i < 0) 4815 { 4816 /* can't get number of interfaces -- fall back */ 4817 if (tTd(0, 4)) 4818 sm_dprintf("SIOCGLIFNUM failed: %s\n", 4819 sm_errstring(errno)); 4820 numifs = -1; 4821 } 4822 else if (tTd(0, 42)) 4823 sm_dprintf("system has %d interfaces\n", numifs); 4824 if (numifs < 0) 4825 # endif /* defined(__hpux) || defined(SIOCGLIFNUM) */ 4826 numifs = MAXINTERFACES; 4827 4828 if (numifs <= 0) 4829 { 4830 (void) close(s); 4831 return; 4832 } 4833 4834 len = lifc.lifc_len = numifs * sizeof(struct lifreq); 4835 buf = lifc.lifc_buf = xalloc(lifc.lifc_len); 4836 # ifndef __hpux 4837 lifc.lifc_family = AF_UNSPEC; 4838 lifc.lifc_flags = 0; 4839 # endif /* ! __hpux */ 4840 if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) 4841 { 4842 if (tTd(0, 4)) 4843 sm_dprintf("SIOCGLIFCONF failed: %s\n", 4844 sm_errstring(errno)); 4845 (void) close(s); 4846 sm_free(buf); 4847 return; 4848 } 4849 4850 /* scan the list of IP address */ 4851 if (tTd(0, 40)) 4852 sm_dprintf("scanning for interface specific names, lifc_len=%ld\n", 4853 (long) len); 4854 4855 for (i = 0; i < len && i >= 0; ) 4856 { 4857 int flags; 4858 struct lifreq *ifr = (struct lifreq *)&buf[i]; 4859 SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr; 4860 int af = ifr->lifr_addr.ss_family; 4861 char *addr; 4862 char *name; 4863 struct in6_addr ia6; 4864 struct in_addr ia; 4865 # ifdef SIOCGLIFFLAGS 4866 struct lifreq ifrf; 4867 # endif /* SIOCGLIFFLAGS */ 4868 char ip_addr[256]; 4869 char buf6[INET6_ADDRSTRLEN]; 4870 4871 /* 4872 ** We must close and recreate the socket each time 4873 ** since we don't know what type of socket it is now 4874 ** (each status function may change it). 4875 */ 4876 4877 (void) close(s); 4878 4879 s = socket(af, SOCK_DGRAM, 0); 4880 if (s == -1) 4881 { 4882 sm_free(buf); /* XXX */ 4883 return; 4884 } 4885 4886 /* 4887 ** If we don't have a complete ifr structure, 4888 ** don't try to use it. 4889 */ 4890 4891 if ((len - i) < sizeof(*ifr)) 4892 break; 4893 4894 # ifdef BSD4_4_SOCKADDR 4895 if (sa->sa.sa_len > sizeof(ifr->lifr_addr)) 4896 i += sizeof(ifr->lifr_name) + sa->sa.sa_len; 4897 else 4898 # endif /* BSD4_4_SOCKADDR */ 4899 # ifdef DEC 4900 /* fix for IPv6 size differences */ 4901 i += sizeof(ifr->ifr_name) + 4902 max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len); 4903 # else /* DEC */ 4904 i += sizeof(*ifr); 4905 # endif /* DEC */ 4906 4907 if (tTd(0, 20)) 4908 sm_dprintf("%s\n", anynet_ntoa(sa)); 4909 4910 if (af != AF_INET && af != AF_INET6) 4911 continue; 4912 4913 # ifdef SIOCGLIFFLAGS 4914 memset(&ifrf, '\0', sizeof(struct lifreq)); 4915 (void) sm_strlcpy(ifrf.lifr_name, ifr->lifr_name, 4916 sizeof(ifrf.lifr_name)); 4917 if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0) 4918 { 4919 if (tTd(0, 4)) 4920 sm_dprintf("SIOCGLIFFLAGS failed: %s\n", 4921 sm_errstring(errno)); 4922 continue; 4923 } 4924 4925 name = ifr->lifr_name; 4926 flags = ifrf.lifr_flags; 4927 4928 if (tTd(0, 41)) 4929 sm_dprintf("\tflags: %lx\n", (unsigned long) flags); 4930 4931 if (!bitset(IFF_UP, flags)) 4932 continue; 4933 # endif /* SIOCGLIFFLAGS */ 4934 4935 ip_addr[0] = '\0'; 4936 4937 /* extract IP address from the list*/ 4938 switch (af) 4939 { 4940 case AF_INET6: 4941 SETV6LOOPBACKADDRFOUND(*sa); 4942 # ifdef __KAME__ 4943 /* convert into proper scoped address */ 4944 if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || 4945 IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && 4946 sa->sin6.sin6_scope_id == 0) 4947 { 4948 struct in6_addr *ia6p; 4949 4950 ia6p = &sa->sin6.sin6_addr; 4951 sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | 4952 ((unsigned int)ia6p->s6_addr[2] << 8)); 4953 ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; 4954 } 4955 # endif /* __KAME__ */ 4956 ia6 = sa->sin6.sin6_addr; 4957 if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) 4958 { 4959 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 4960 message("WARNING: interface %s is UP with %s address", 4961 name, addr == NULL ? "(NULL)" : addr); 4962 continue; 4963 } 4964 4965 /* save IP address in text from */ 4966 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 4967 if (addr != NULL) 4968 (void) sm_snprintf(ip_addr, sizeof(ip_addr), 4969 "[%.*s]", 4970 (int) sizeof(ip_addr) - 3, 4971 addr); 4972 break; 4973 4974 case AF_INET: 4975 ia = sa->sin.sin_addr; 4976 if (ia.s_addr == INADDR_ANY || 4977 ia.s_addr == INADDR_NONE) 4978 { 4979 message("WARNING: interface %s is UP with %s address", 4980 name, inet_ntoa(ia)); 4981 continue; 4982 } 4983 4984 /* save IP address in text from */ 4985 (void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]", 4986 (int) sizeof(ip_addr) - 3, inet_ntoa(ia)); 4987 break; 4988 } 4989 4990 if (*ip_addr == '\0') 4991 continue; 4992 4993 if (!wordinclass(ip_addr, 'w')) 4994 { 4995 setclass('w', ip_addr); 4996 if (tTd(0, 4)) 4997 sm_dprintf("\ta.k.a.: %s\n", ip_addr); 4998 } 4999 5000 # ifdef SIOCGLIFFLAGS 5001 /* skip "loopback" interface "lo" */ 5002 if (DontProbeInterfaces == DPI_SKIPLOOPBACK && 5003 bitset(IFF_LOOPBACK, flags)) 5004 continue; 5005 # endif /* SIOCGLIFFLAGS */ 5006 (void) add_hostnames(sa); 5007 } 5008 sm_free(buf); /* XXX */ 5009 (void) close(s); 5010 # else /* NETINET6 && defined(SIOCGLIFCONF) */ 5011 # if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN 5012 int s; 5013 int i; 5014 struct ifconf ifc; 5015 int numifs; 5016 5017 s = socket(AF_INET, SOCK_DGRAM, 0); 5018 if (s == -1) 5019 return; 5020 5021 /* get the list of known IP address from the kernel */ 5022 # if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN 5023 if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) 5024 { 5025 /* can't get number of interfaces -- fall back */ 5026 if (tTd(0, 4)) 5027 sm_dprintf("SIOCGIFNUM failed: %s\n", 5028 sm_errstring(errno)); 5029 numifs = -1; 5030 } 5031 else if (tTd(0, 42)) 5032 sm_dprintf("system has %d interfaces\n", numifs); 5033 if (numifs < 0) 5034 # endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */ 5035 numifs = MAXINTERFACES; 5036 5037 if (numifs <= 0) 5038 { 5039 (void) close(s); 5040 return; 5041 } 5042 ifc.ifc_len = numifs * sizeof(struct ifreq); 5043 ifc.ifc_buf = xalloc(ifc.ifc_len); 5044 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 5045 { 5046 if (tTd(0, 4)) 5047 sm_dprintf("SIOCGIFCONF failed: %s\n", 5048 sm_errstring(errno)); 5049 (void) close(s); 5050 return; 5051 } 5052 5053 /* scan the list of IP address */ 5054 if (tTd(0, 40)) 5055 sm_dprintf("scanning for interface specific names, ifc_len=%d\n", 5056 ifc.ifc_len); 5057 5058 for (i = 0; i < ifc.ifc_len && i >= 0; ) 5059 { 5060 int af; 5061 struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i]; 5062 SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr; 5063 # if NETINET6 5064 char *addr; 5065 struct in6_addr ia6; 5066 # endif /* NETINET6 */ 5067 struct in_addr ia; 5068 # ifdef SIOCGIFFLAGS 5069 struct ifreq ifrf; 5070 # endif /* SIOCGIFFLAGS */ 5071 char ip_addr[256]; 5072 # if NETINET6 5073 char buf6[INET6_ADDRSTRLEN]; 5074 # endif /* NETINET6 */ 5075 5076 /* 5077 ** If we don't have a complete ifr structure, 5078 ** don't try to use it. 5079 */ 5080 5081 if ((ifc.ifc_len - i) < sizeof(*ifr)) 5082 break; 5083 5084 # ifdef BSD4_4_SOCKADDR 5085 if (sa->sa.sa_len > sizeof(ifr->ifr_addr)) 5086 i += sizeof(ifr->ifr_name) + sa->sa.sa_len; 5087 else 5088 # endif /* BSD4_4_SOCKADDR */ 5089 i += sizeof(*ifr); 5090 5091 if (tTd(0, 20)) 5092 sm_dprintf("%s\n", anynet_ntoa(sa)); 5093 5094 af = ifr->ifr_addr.sa_family; 5095 if (af != AF_INET 5096 # if NETINET6 5097 && af != AF_INET6 5098 # endif /* NETINET6 */ 5099 ) 5100 continue; 5101 5102 # ifdef SIOCGIFFLAGS 5103 memset(&ifrf, '\0', sizeof(struct ifreq)); 5104 (void) sm_strlcpy(ifrf.ifr_name, ifr->ifr_name, 5105 sizeof(ifrf.ifr_name)); 5106 (void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf); 5107 if (tTd(0, 41)) 5108 sm_dprintf("\tflags: %lx\n", 5109 (unsigned long) ifrf.ifr_flags); 5110 # define IFRFREF ifrf 5111 # else /* SIOCGIFFLAGS */ 5112 # define IFRFREF (*ifr) 5113 # endif /* SIOCGIFFLAGS */ 5114 5115 if (!bitset(IFF_UP, IFRFREF.ifr_flags)) 5116 continue; 5117 5118 ip_addr[0] = '\0'; 5119 5120 /* extract IP address from the list*/ 5121 switch (af) 5122 { 5123 case AF_INET: 5124 ia = sa->sin.sin_addr; 5125 if (ia.s_addr == INADDR_ANY || 5126 ia.s_addr == INADDR_NONE) 5127 { 5128 message("WARNING: interface %s is UP with %s address", 5129 ifr->ifr_name, inet_ntoa(ia)); 5130 continue; 5131 } 5132 5133 /* save IP address in text from */ 5134 (void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]", 5135 (int) sizeof(ip_addr) - 3, 5136 inet_ntoa(ia)); 5137 break; 5138 5139 # if NETINET6 5140 case AF_INET6: 5141 SETV6LOOPBACKADDRFOUND(*sa); 5142 # ifdef __KAME__ 5143 /* convert into proper scoped address */ 5144 if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || 5145 IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && 5146 sa->sin6.sin6_scope_id == 0) 5147 { 5148 struct in6_addr *ia6p; 5149 5150 ia6p = &sa->sin6.sin6_addr; 5151 sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | 5152 ((unsigned int)ia6p->s6_addr[2] << 8)); 5153 ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; 5154 } 5155 # endif /* __KAME__ */ 5156 ia6 = sa->sin6.sin6_addr; 5157 if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) 5158 { 5159 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 5160 message("WARNING: interface %s is UP with %s address", 5161 ifr->ifr_name, 5162 addr == NULL ? "(NULL)" : addr); 5163 continue; 5164 } 5165 5166 /* save IP address in text from */ 5167 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 5168 if (addr != NULL) 5169 (void) sm_snprintf(ip_addr, sizeof(ip_addr), 5170 "[%.*s]", 5171 (int) sizeof(ip_addr) - 3, 5172 addr); 5173 break; 5174 5175 # endif /* NETINET6 */ 5176 } 5177 5178 if (ip_addr[0] == '\0') 5179 continue; 5180 5181 if (!wordinclass(ip_addr, 'w')) 5182 { 5183 setclass('w', ip_addr); 5184 if (tTd(0, 4)) 5185 sm_dprintf("\ta.k.a.: %s\n", ip_addr); 5186 } 5187 5188 /* skip "loopback" interface "lo" */ 5189 if (DontProbeInterfaces == DPI_SKIPLOOPBACK && 5190 bitset(IFF_LOOPBACK, IFRFREF.ifr_flags)) 5191 continue; 5192 5193 (void) add_hostnames(sa); 5194 } 5195 sm_free(ifc.ifc_buf); /* XXX */ 5196 (void) close(s); 5197 # undef IFRFREF 5198 # endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ 5199 # endif /* NETINET6 && defined(SIOCGLIFCONF) */ 5200 } 5201 /* 5202 ** ISLOOPBACK -- is socket address in the loopback net? 5203 ** 5204 ** Parameters: 5205 ** sa -- socket address. 5206 ** 5207 ** Returns: 5208 ** true -- is socket address in the loopback net? 5209 ** false -- otherwise 5210 ** 5211 */ 5212 5213 bool 5214 isloopback(sa) 5215 SOCKADDR sa; 5216 { 5217 #if NETINET6 5218 if (IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr)) 5219 return true; 5220 #else /* NETINET6 */ 5221 /* XXX how to correctly extract IN_LOOPBACKNET part? */ 5222 if (((ntohl(sa.sin.sin_addr.s_addr) & IN_CLASSA_NET) 5223 >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 5224 return true; 5225 #endif /* NETINET6 */ 5226 return false; 5227 } 5228 /* 5229 ** GET_NUM_PROCS_ONLINE -- return the number of processors currently online 5230 ** 5231 ** Parameters: 5232 ** none. 5233 ** 5234 ** Returns: 5235 ** The number of processors online. 5236 */ 5237 5238 static int 5239 get_num_procs_online() 5240 { 5241 int nproc = 0; 5242 5243 #ifdef USESYSCTL 5244 # if defined(CTL_HW) && defined(HW_NCPU) 5245 size_t sz; 5246 int mib[2]; 5247 5248 mib[0] = CTL_HW; 5249 mib[1] = HW_NCPU; 5250 sz = (size_t) sizeof(nproc); 5251 (void) sysctl(mib, 2, &nproc, &sz, NULL, 0); 5252 # endif /* defined(CTL_HW) && defined(HW_NCPU) */ 5253 #else /* USESYSCTL */ 5254 # ifdef _SC_NPROCESSORS_ONLN 5255 nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); 5256 # else /* _SC_NPROCESSORS_ONLN */ 5257 # ifdef __hpux 5258 # include <sys/pstat.h> 5259 struct pst_dynamic psd; 5260 5261 if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) 5262 nproc = psd.psd_proc_cnt; 5263 # endif /* __hpux */ 5264 # endif /* _SC_NPROCESSORS_ONLN */ 5265 #endif /* USESYSCTL */ 5266 5267 if (nproc <= 0) 5268 nproc = 1; 5269 return nproc; 5270 } 5271 /* 5272 ** SM_CLOSEFROM -- close file descriptors 5273 ** 5274 ** Parameters: 5275 ** lowest -- first fd to close 5276 ** highest -- last fd + 1 to close 5277 ** 5278 ** Returns: 5279 ** none 5280 */ 5281 5282 void 5283 sm_closefrom(lowest, highest) 5284 int lowest, highest; 5285 { 5286 #if HASCLOSEFROM 5287 closefrom(lowest); 5288 #else /* HASCLOSEFROM */ 5289 int i; 5290 5291 for (i = lowest; i < highest; i++) 5292 (void) close(i); 5293 #endif /* HASCLOSEFROM */ 5294 } 5295 #if HASFDWALK 5296 /* 5297 ** CLOSEFD_WALK -- walk fd's arranging to close them 5298 ** Callback for fdwalk() 5299 ** 5300 ** Parameters: 5301 ** lowest -- first fd to arrange to be closed 5302 ** fd -- fd to arrange to be closed 5303 ** 5304 ** Returns: 5305 ** zero 5306 */ 5307 5308 static int 5309 closefd_walk(lowest, fd) 5310 void *lowest; 5311 int fd; 5312 { 5313 if (fd >= *(int *)lowest) 5314 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 5315 return 0; 5316 } 5317 #endif /* HASFDWALK */ 5318 /* 5319 ** SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed 5320 ** 5321 ** Parameters: 5322 ** lowest -- first fd to arrange to be closed 5323 ** highest -- last fd + 1 to arrange to be closed 5324 ** 5325 ** Returns: 5326 ** none 5327 */ 5328 5329 void 5330 sm_close_on_exec(lowest, highest) 5331 int lowest, highest; 5332 { 5333 #if HASFDWALK 5334 (void) fdwalk(closefd_walk, &lowest); 5335 #else /* HASFDWALK */ 5336 int i, j; 5337 5338 for (i = lowest; i < highest; i++) 5339 { 5340 if ((j = fcntl(i, F_GETFD, 0)) != -1) 5341 (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 5342 } 5343 #endif /* HASFDWALK */ 5344 } 5345 /* 5346 ** SEED_RANDOM -- seed the random number generator 5347 ** 5348 ** Parameters: 5349 ** none 5350 ** 5351 ** Returns: 5352 ** none 5353 */ 5354 5355 void 5356 seed_random() 5357 { 5358 #if HASSRANDOMDEV 5359 srandomdev(); 5360 #else /* HASSRANDOMDEV */ 5361 long seed; 5362 struct timeval t; 5363 5364 seed = (long) CurrentPid; 5365 if (gettimeofday(&t, NULL) >= 0) 5366 seed += t.tv_sec + t.tv_usec; 5367 5368 # if HASRANDOM 5369 (void) srandom(seed); 5370 # else /* HASRANDOM */ 5371 (void) srand((unsigned int) seed); 5372 # endif /* HASRANDOM */ 5373 #endif /* HASSRANDOMDEV */ 5374 } 5375 /* 5376 ** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE 5377 ** 5378 ** Parameters: 5379 ** level -- syslog level 5380 ** id -- envelope ID or NULL (NOQUEUE) 5381 ** fmt -- format string 5382 ** arg... -- arguments as implied by fmt. 5383 ** 5384 ** Returns: 5385 ** none 5386 */ 5387 5388 /* VARARGS3 */ 5389 void 5390 #ifdef __STDC__ 5391 sm_syslog(int level, const char *id, const char *fmt, ...) 5392 #else /* __STDC__ */ 5393 sm_syslog(level, id, fmt, va_alist) 5394 int level; 5395 const char *id; 5396 const char *fmt; 5397 va_dcl 5398 #endif /* __STDC__ */ 5399 { 5400 char *buf; 5401 size_t bufsize; 5402 char *begin, *end; 5403 int save_errno; 5404 int seq = 1; 5405 int idlen; 5406 char buf0[MAXLINE]; 5407 char *newstring; 5408 extern int SyslogPrefixLen; 5409 SM_VA_LOCAL_DECL 5410 5411 save_errno = errno; 5412 if (id == NULL) 5413 id = "NOQUEUE"; 5414 idlen = strlen(id) + SyslogPrefixLen; 5415 5416 buf = buf0; 5417 bufsize = sizeof(buf0); 5418 5419 for (;;) 5420 { 5421 int n; 5422 5423 /* print log message into buf */ 5424 SM_VA_START(ap, fmt); 5425 n = sm_vsnprintf(buf, bufsize, fmt, ap); 5426 SM_VA_END(ap); 5427 SM_ASSERT(n >= 0); 5428 if (n < bufsize) 5429 break; 5430 5431 /* String too small, redo with correct size */ 5432 bufsize = n + 1; 5433 if (buf != buf0) 5434 { 5435 sm_free(buf); 5436 buf = NULL; 5437 } 5438 buf = sm_malloc_x(bufsize); 5439 } 5440 5441 /* clean up buf after it has been expanded with args */ 5442 newstring = str2prt(buf); 5443 if ((strlen(newstring) + idlen + 1) < SYSLOG_BUFSIZE) 5444 { 5445 #if LOG 5446 if (*id == '\0') 5447 { 5448 if (tTd(89, 10)) 5449 { 5450 struct timeval tv; 5451 5452 gettimeofday(&tv, NULL); 5453 sm_dprintf("%ld.%06ld %s\n", (long) tv.tv_sec, 5454 (long) tv.tv_usec, newstring); 5455 } 5456 else if (tTd(89, 8)) 5457 sm_dprintf("%s\n", newstring); 5458 else 5459 syslog(level, "%s", newstring); 5460 } 5461 else 5462 { 5463 if (tTd(89, 10)) 5464 { 5465 struct timeval tv; 5466 5467 gettimeofday(&tv, NULL); 5468 sm_dprintf("%ld.%06ld %s: %s\n", (long) tv.tv_sec, 5469 (long) tv.tv_usec, id, newstring); 5470 } 5471 else if (tTd(89, 8)) 5472 sm_dprintf("%s: %s\n", id, newstring); 5473 else 5474 syslog(level, "%s: %s", id, newstring); 5475 } 5476 #else /* LOG */ 5477 /*XXX should do something more sensible */ 5478 if (*id == '\0') 5479 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", 5480 newstring); 5481 else 5482 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5483 "%s: %s\n", id, newstring); 5484 #endif /* LOG */ 5485 if (buf != buf0) 5486 sm_free(buf); 5487 errno = save_errno; 5488 return; 5489 } 5490 5491 /* 5492 ** additional length for splitting: " ..." + 3, where 3 is magic to 5493 ** have some data for the next entry. 5494 */ 5495 5496 #define SL_SPLIT 7 5497 5498 begin = newstring; 5499 idlen += 5; /* strlen("[999]"), see below */ 5500 while (*begin != '\0' && 5501 (strlen(begin) + idlen) > SYSLOG_BUFSIZE) 5502 { 5503 char save; 5504 5505 if (seq >= 999) 5506 { 5507 /* Too many messages */ 5508 break; 5509 } 5510 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5511 while (end > begin) 5512 { 5513 /* Break on comma or space */ 5514 if (*end == ',' || *end == ' ') 5515 { 5516 end++; /* Include separator */ 5517 break; 5518 } 5519 end--; 5520 } 5521 /* No separator, break midstring... */ 5522 if (end == begin) 5523 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5524 save = *end; 5525 *end = 0; 5526 #if LOG 5527 if (tTd(89, 8)) 5528 sm_dprintf("%s[%d]: %s ...\n", id, seq++, begin); 5529 else 5530 syslog(level, "%s[%d]: %s ...", id, seq++, begin); 5531 #else /* LOG */ 5532 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5533 "%s[%d]: %s ...\n", id, seq++, begin); 5534 #endif /* LOG */ 5535 *end = save; 5536 begin = end; 5537 } 5538 if (seq >= 999) 5539 { 5540 #if LOG 5541 if (tTd(89, 8)) 5542 sm_dprintf("%s[%d]: log terminated, too many parts\n", 5543 id, seq); 5544 else 5545 syslog(level, "%s[%d]: log terminated, too many parts", 5546 id, seq); 5547 #else /* LOG */ 5548 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5549 "%s[%d]: log terminated, too many parts\n", id, seq); 5550 #endif /* LOG */ 5551 } 5552 else if (*begin != '\0') 5553 { 5554 #if LOG 5555 if (tTd(89, 8)) 5556 sm_dprintf("%s[%d]: %s\n", id, seq, begin); 5557 else 5558 syslog(level, "%s[%d]: %s", id, seq, begin); 5559 #else /* LOG */ 5560 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5561 "%s[%d]: %s\n", id, seq, begin); 5562 #endif /* LOG */ 5563 } 5564 if (buf != buf0) 5565 sm_free(buf); 5566 errno = save_errno; 5567 } 5568 /* 5569 ** HARD_SYSLOG -- call syslog repeatedly until it works 5570 ** 5571 ** Needed on HP-UX, which apparently doesn't guarantee that 5572 ** syslog succeeds during interrupt handlers. 5573 */ 5574 5575 #if defined(__hpux) && !defined(HPUX11) 5576 5577 # define MAXSYSLOGTRIES 100 5578 # undef syslog 5579 # ifdef V4FS 5580 # define XCNST const 5581 # define CAST (const char *) 5582 # else /* V4FS */ 5583 # define XCNST 5584 # define CAST 5585 # endif /* V4FS */ 5586 5587 void 5588 # ifdef __STDC__ 5589 hard_syslog(int pri, XCNST char *msg, ...) 5590 # else /* __STDC__ */ 5591 hard_syslog(pri, msg, va_alist) 5592 int pri; 5593 XCNST char *msg; 5594 va_dcl 5595 # endif /* __STDC__ */ 5596 { 5597 int i; 5598 char buf[SYSLOG_BUFSIZE]; 5599 SM_VA_LOCAL_DECL 5600 5601 SM_VA_START(ap, msg); 5602 (void) sm_vsnprintf(buf, sizeof(buf), msg, ap); 5603 SM_VA_END(ap); 5604 5605 for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; ) 5606 continue; 5607 } 5608 5609 # undef CAST 5610 #endif /* defined(__hpux) && !defined(HPUX11) */ 5611 #if NEEDLOCAL_HOSTNAME_LENGTH 5612 /* 5613 ** LOCAL_HOSTNAME_LENGTH 5614 ** 5615 ** This is required to get sendmail to compile against BIND 4.9.x 5616 ** on Ultrix. 5617 ** 5618 ** Unfortunately, a Compaq Y2K patch kit provides it without 5619 ** bumping __RES in /usr/include/resolv.h so we can't automatically 5620 ** figure out whether it is needed. 5621 */ 5622 5623 int 5624 local_hostname_length(hostname) 5625 char *hostname; 5626 { 5627 size_t len_host, len_domain; 5628 5629 if (!*_res.defdname) 5630 res_init(); 5631 len_host = strlen(hostname); 5632 len_domain = strlen(_res.defdname); 5633 if (len_host > len_domain && 5634 (sm_strcasecmp(hostname + len_host - len_domain, 5635 _res.defdname) == 0) && 5636 hostname[len_host - len_domain - 1] == '.') 5637 return len_host - len_domain - 1; 5638 else 5639 return 0; 5640 } 5641 #endif /* NEEDLOCAL_HOSTNAME_LENGTH */ 5642 5643 #if NEEDLINK 5644 /* 5645 ** LINK -- clone a file 5646 ** 5647 ** Some OS's lacks link() and hard links. Since sendmail is using 5648 ** link() as an efficient way to clone files, this implementation 5649 ** will simply do a file copy. 5650 ** 5651 ** NOTE: This link() replacement is not a generic replacement as it 5652 ** does not handle all of the semantics of the real link(2). 5653 ** 5654 ** Parameters: 5655 ** source -- pathname of existing file. 5656 ** target -- pathname of link (clone) to be created. 5657 ** 5658 ** Returns: 5659 ** 0 -- success. 5660 ** -1 -- failure, see errno for details. 5661 */ 5662 5663 int 5664 link(source, target) 5665 const char *source; 5666 const char *target; 5667 { 5668 int save_errno; 5669 int sff; 5670 int src = -1, dst = -1; 5671 ssize_t readlen; 5672 ssize_t writelen; 5673 char buf[BUFSIZ]; 5674 struct stat st; 5675 5676 sff = SFF_REGONLY|SFF_OPENASROOT; 5677 if (DontLockReadFiles) 5678 sff |= SFF_NOLOCK; 5679 5680 /* Open the original file */ 5681 src = safeopen((char *)source, O_RDONLY, 0, sff); 5682 if (src < 0) 5683 goto fail; 5684 5685 /* Obtain the size and the mode */ 5686 if (fstat(src, &st) < 0) 5687 goto fail; 5688 5689 /* Create the duplicate copy */ 5690 sff &= ~SFF_NOLOCK; 5691 sff |= SFF_CREAT; 5692 dst = safeopen((char *)target, O_CREAT|O_EXCL|O_WRONLY, 5693 st.st_mode, sff); 5694 if (dst < 0) 5695 goto fail; 5696 5697 /* Copy all of the bytes one buffer at a time */ 5698 while ((readlen = read(src, &buf, sizeof(buf))) > 0) 5699 { 5700 ssize_t left = readlen; 5701 char *p = buf; 5702 5703 while (left > 0 && 5704 (writelen = write(dst, p, (size_t) left)) >= 0) 5705 { 5706 left -= writelen; 5707 p += writelen; 5708 } 5709 if (writelen < 0) 5710 break; 5711 } 5712 5713 /* Any trouble reading? */ 5714 if (readlen < 0 || writelen < 0) 5715 goto fail; 5716 5717 /* Close the input file */ 5718 if (close(src) < 0) 5719 { 5720 src = -1; 5721 goto fail; 5722 } 5723 src = -1; 5724 5725 /* Close the output file */ 5726 if (close(dst) < 0) 5727 { 5728 /* don't set dst = -1 here so we unlink the file */ 5729 goto fail; 5730 } 5731 5732 /* Success */ 5733 return 0; 5734 5735 fail: 5736 save_errno = errno; 5737 if (src >= 0) 5738 (void) close(src); 5739 if (dst >= 0) 5740 { 5741 (void) unlink(target); 5742 (void) close(dst); 5743 } 5744 errno = save_errno; 5745 return -1; 5746 } 5747 #endif /* NEEDLINK */ 5748 5749 /* 5750 ** Compile-Time options 5751 */ 5752 5753 char *CompileOptions[] = 5754 { 5755 #if ALLOW_255 5756 "ALLOW_255", 5757 #endif 5758 #if NAMED_BIND 5759 # if DNSMAP 5760 "DNSMAP", 5761 # endif 5762 #endif 5763 #if EGD 5764 "EGD", 5765 #endif 5766 #if HESIOD 5767 "HESIOD", 5768 #endif 5769 #if HESIOD_ALLOW_NUMERIC_LOGIN 5770 "HESIOD_ALLOW_NUMERIC_LOGIN", 5771 #endif 5772 #if HES_GETMAILHOST 5773 "HES_GETMAILHOST", 5774 #endif 5775 #if IPV6_FULL 5776 /* Use uncompressed IPv6 address format (no "::") by default */ 5777 "IPV6_FULL", 5778 #endif 5779 #if LDAPMAP 5780 "LDAPMAP", 5781 #endif 5782 #if LDAP_REFERRALS 5783 "LDAP_REFERRALS", 5784 #endif 5785 #if LOG 5786 "LOG", 5787 #endif 5788 #if MAP_NSD 5789 "MAP_NSD", 5790 #endif 5791 #if MAP_REGEX 5792 "MAP_REGEX", 5793 #endif 5794 #if MATCHGECOS 5795 "MATCHGECOS", 5796 #endif 5797 #if MILTER 5798 "MILTER", 5799 #endif 5800 #if MIME7TO8 5801 "MIME7TO8", 5802 #endif 5803 #if MIME7TO8_OLD 5804 "MIME7TO8_OLD", 5805 #endif 5806 #if MIME8TO7 5807 "MIME8TO7", 5808 #endif 5809 #if NAMED_BIND 5810 "NAMED_BIND", 5811 #endif 5812 #if NDBM 5813 "NDBM", 5814 #endif 5815 #if NETINET 5816 "NETINET", 5817 #endif 5818 #if NETINET6 5819 "NETINET6", 5820 #endif 5821 #if NETINFO 5822 "NETINFO", 5823 #endif 5824 #if NETISO 5825 "NETISO", 5826 #endif 5827 #if NETNS 5828 "NETNS", 5829 #endif 5830 #if NETUNIX 5831 "NETUNIX", 5832 #endif 5833 #if NETX25 5834 "NETX25", 5835 #endif 5836 #if NEWDB 5837 "NEWDB", 5838 #endif 5839 #if NIS 5840 "NIS", 5841 #endif 5842 #if NISPLUS 5843 "NISPLUS", 5844 #endif 5845 #if NO_DH 5846 "NO_DH", 5847 #endif 5848 #if PH_MAP 5849 "PH_MAP", 5850 #endif 5851 #ifdef PICKY_HELO_CHECK 5852 "PICKY_HELO_CHECK", 5853 #endif 5854 #if PIPELINING 5855 "PIPELINING", 5856 #endif 5857 #if SASL 5858 # if SASL >= 20000 5859 "SASLv2", 5860 # else /* SASL >= 20000 */ 5861 "SASL", 5862 # endif 5863 #endif 5864 #if SCANF 5865 "SCANF", 5866 #endif 5867 #if SM_LDAP_ERROR_ON_MISSING_ARGS 5868 "SM_LDAP_ERROR_ON_MISSING_ARGS", 5869 #endif 5870 #if SMTPDEBUG 5871 "SMTPDEBUG", 5872 #endif 5873 #if SOCKETMAP 5874 "SOCKETMAP", 5875 #endif 5876 #if STARTTLS 5877 "STARTTLS", 5878 #endif 5879 #if SUID_ROOT_FILES_OK 5880 "SUID_ROOT_FILES_OK", 5881 #endif 5882 #if TCPWRAPPERS 5883 "TCPWRAPPERS", 5884 #endif 5885 #if TLS_NO_RSA 5886 "TLS_NO_RSA", 5887 #endif 5888 #if TLS_VRFY_PER_CTX 5889 "TLS_VRFY_PER_CTX", 5890 #endif 5891 #if USERDB 5892 "USERDB", 5893 #endif 5894 #if USE_LDAP_INIT 5895 "USE_LDAP_INIT", 5896 #endif 5897 #if USE_TTYPATH 5898 "USE_TTYPATH", 5899 #endif 5900 #if XDEBUG 5901 "XDEBUG", 5902 #endif 5903 #if XLA 5904 "XLA", 5905 #endif 5906 NULL 5907 }; 5908 5909 5910 /* 5911 ** OS compile options. 5912 */ 5913 5914 char *OsCompileOptions[] = 5915 { 5916 #if ADDRCONFIG_IS_BROKEN 5917 "ADDRCONFIG_IS_BROKEN", 5918 #endif 5919 #ifdef AUTO_NETINFO_HOSTS 5920 "AUTO_NETINFO_HOSTS", 5921 #endif 5922 #ifdef AUTO_NIS_ALIASES 5923 "AUTO_NIS_ALIASES", 5924 #endif 5925 #if BROKEN_RES_SEARCH 5926 "BROKEN_RES_SEARCH", 5927 #endif 5928 #ifdef BSD4_4_SOCKADDR 5929 "BSD4_4_SOCKADDR", 5930 #endif 5931 #if BOGUS_O_EXCL 5932 "BOGUS_O_EXCL", 5933 #endif 5934 #if DEC_OSF_BROKEN_GETPWENT 5935 "DEC_OSF_BROKEN_GETPWENT", 5936 #endif 5937 #if FAST_PID_RECYCLE 5938 "FAST_PID_RECYCLE", 5939 #endif 5940 #if HASCLOSEFROM 5941 "HASCLOSEFROM", 5942 #endif 5943 #if HASFCHOWN 5944 "HASFCHOWN", 5945 #endif 5946 #if HASFCHMOD 5947 "HASFCHMOD", 5948 #endif 5949 #if HASFDWALK 5950 "HASFDWALK", 5951 #endif 5952 #if HASFLOCK 5953 "HASFLOCK", 5954 #endif 5955 #if HASGETDTABLESIZE 5956 "HASGETDTABLESIZE", 5957 #endif 5958 #if HASGETUSERSHELL 5959 "HASGETUSERSHELL", 5960 #endif 5961 #if HASINITGROUPS 5962 "HASINITGROUPS", 5963 #endif 5964 #if HASLDAPGETALIASBYNAME 5965 "HASLDAPGETALIASBYNAME", 5966 #endif 5967 #if HASLSTAT 5968 "HASLSTAT", 5969 #endif 5970 #if HASNICE 5971 "HASNICE", 5972 #endif 5973 #if HASRANDOM 5974 "HASRANDOM", 5975 #endif 5976 #if HASRRESVPORT 5977 "HASRRESVPORT", 5978 #endif 5979 #if HASSETEGID 5980 "HASSETEGID", 5981 #endif 5982 #if HASSETLOGIN 5983 "HASSETLOGIN", 5984 #endif 5985 #if HASSETREGID 5986 "HASSETREGID", 5987 #endif 5988 #if HASSETRESGID 5989 "HASSETRESGID", 5990 #endif 5991 #if HASSETREUID 5992 "HASSETREUID", 5993 #endif 5994 #if HASSETRLIMIT 5995 "HASSETRLIMIT", 5996 #endif 5997 #if HASSETSID 5998 "HASSETSID", 5999 #endif 6000 #if HASSETUSERCONTEXT 6001 "HASSETUSERCONTEXT", 6002 #endif 6003 #if HASSETVBUF 6004 "HASSETVBUF", 6005 #endif 6006 #if HAS_ST_GEN 6007 "HAS_ST_GEN", 6008 #endif 6009 #if HASSRANDOMDEV 6010 "HASSRANDOMDEV", 6011 #endif 6012 #if HASURANDOMDEV 6013 "HASURANDOMDEV", 6014 #endif 6015 #if HASSTRERROR 6016 "HASSTRERROR", 6017 #endif 6018 #if HASULIMIT 6019 "HASULIMIT", 6020 #endif 6021 #if HASUNAME 6022 "HASUNAME", 6023 #endif 6024 #if HASUNSETENV 6025 "HASUNSETENV", 6026 #endif 6027 #if HASWAITPID 6028 "HASWAITPID", 6029 #endif 6030 #if HAVE_NANOSLEEP 6031 "HAVE_NANOSLEEP", 6032 #endif 6033 #if IDENTPROTO 6034 "IDENTPROTO", 6035 #endif 6036 #if IP_SRCROUTE 6037 "IP_SRCROUTE", 6038 #endif 6039 #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 6040 "LOCK_ON_OPEN", 6041 #endif 6042 #if MILTER_NO_NAGLE 6043 "MILTER_NO_NAGLE ", 6044 #endif 6045 #if NEEDFSYNC 6046 "NEEDFSYNC", 6047 #endif 6048 #if NEEDLINK 6049 "NEEDLINK", 6050 #endif 6051 #if NEEDLOCAL_HOSTNAME_LENGTH 6052 "NEEDLOCAL_HOSTNAME_LENGTH", 6053 #endif 6054 #if NEEDSGETIPNODE 6055 "NEEDSGETIPNODE", 6056 #endif 6057 #if NEEDSTRSTR 6058 "NEEDSTRSTR", 6059 #endif 6060 #if NEEDSTRTOL 6061 "NEEDSTRTOL", 6062 #endif 6063 #ifdef NO_GETSERVBYNAME 6064 "NO_GETSERVBYNAME", 6065 #endif 6066 #if NOFTRUNCATE 6067 "NOFTRUNCATE", 6068 #endif 6069 #if REQUIRES_DIR_FSYNC 6070 "REQUIRES_DIR_FSYNC", 6071 #endif 6072 #if RLIMIT_NEEDS_SYS_TIME_H 6073 "RLIMIT_NEEDS_SYS_TIME_H", 6074 #endif 6075 #if SAFENFSPATHCONF 6076 "SAFENFSPATHCONF", 6077 #endif 6078 #if SECUREWARE 6079 "SECUREWARE", 6080 #endif 6081 #if SFS_TYPE == SFS_4ARGS 6082 "SFS_4ARGS", 6083 #elif SFS_TYPE == SFS_MOUNT 6084 "SFS_MOUNT", 6085 #elif SFS_TYPE == SFS_NONE 6086 "SFS_NONE", 6087 #elif SFS_TYPE == SFS_NT 6088 "SFS_NT", 6089 #elif SFS_TYPE == SFS_STATFS 6090 "SFS_STATFS", 6091 #elif SFS_TYPE == SFS_STATVFS 6092 "SFS_STATVFS", 6093 #elif SFS_TYPE == SFS_USTAT 6094 "SFS_USTAT", 6095 #elif SFS_TYPE == SFS_VFS 6096 "SFS_VFS", 6097 #endif 6098 #if SHARE_V1 6099 "SHARE_V1", 6100 #endif 6101 #if SIOCGIFCONF_IS_BROKEN 6102 "SIOCGIFCONF_IS_BROKEN", 6103 #endif 6104 #if SIOCGIFNUM_IS_BROKEN 6105 "SIOCGIFNUM_IS_BROKEN", 6106 #endif 6107 #if SNPRINTF_IS_BROKEN 6108 "SNPRINTF_IS_BROKEN", 6109 #endif 6110 #if SO_REUSEADDR_IS_BROKEN 6111 "SO_REUSEADDR_IS_BROKEN", 6112 #endif 6113 #if SYS5SETPGRP 6114 "SYS5SETPGRP", 6115 #endif 6116 #if SYSTEM5 6117 "SYSTEM5", 6118 #endif 6119 #if USE_DOUBLE_FORK 6120 "USE_DOUBLE_FORK", 6121 #endif 6122 #if USE_ENVIRON 6123 "USE_ENVIRON", 6124 #endif 6125 #if USE_SA_SIGACTION 6126 "USE_SA_SIGACTION", 6127 #endif 6128 #if USE_SIGLONGJMP 6129 "USE_SIGLONGJMP", 6130 #endif 6131 #if USEGETCONFATTR 6132 "USEGETCONFATTR", 6133 #endif 6134 #if USESETEUID 6135 "USESETEUID", 6136 #endif 6137 #ifdef USESYSCTL 6138 "USESYSCTL", 6139 #endif 6140 #if USE_OPENSSL_ENGINE 6141 "USE_OPENSSL_ENGINE", 6142 #endif 6143 #if USING_NETSCAPE_LDAP 6144 "USING_NETSCAPE_LDAP", 6145 #endif 6146 #ifdef WAITUNION 6147 "WAITUNION", 6148 #endif 6149 NULL 6150 }; 6151 6152 /* 6153 ** FFR compile options. 6154 */ 6155 6156 char *FFRCompileOptions[] = 6157 { 6158 #if _FFR_ADD_BCC 6159 "_FFR_ADD_BCC", 6160 #endif 6161 #if _FFR_ADDR_TYPE_MODES 6162 /* more info in {addr_type}, requires m4 changes! */ 6163 "_FFR_ADDR_TYPE_MODES", 6164 #endif 6165 #if _FFR_ALIAS_DETAIL 6166 /* try to handle +detail for aliases */ 6167 "_FFR_ALIAS_DETAIL", 6168 #endif 6169 #if _FFR_ALLOW_SASLINFO 6170 /* DefaultAuthInfo can be specified by user. */ 6171 /* DefaultAuthInfo doesn't really work in 8.13 anymore. */ 6172 "_FFR_ALLOW_SASLINFO", 6173 #endif 6174 #if _FFR_BADRCPT_SHUTDOWN 6175 /* shut down connection (421) if there are too many bad RCPTs */ 6176 "_FFR_BADRCPT_SHUTDOWN", 6177 #endif 6178 #if _FFR_BESTMX_BETTER_TRUNCATION 6179 /* Better truncation of list of MX records for dns map. */ 6180 "_FFR_BESTMX_BETTER_TRUNCATION", 6181 #endif 6182 #if _FFR_BOUNCE_QUEUE 6183 /* Separate, unprocessed queue for DSNs */ 6184 /* John Gardiner Myers of Proofpoint */ 6185 "_FFR_BOUNCE_QUEUE", 6186 #endif 6187 #if _FFR_CATCH_BROKEN_MTAS 6188 /* Deal with MTAs that send a reply during the DATA phase. */ 6189 "_FFR_CATCH_BROKEN_MTAS", 6190 #endif 6191 #if _FFR_CHK_QUEUE 6192 /* Stricter checks about queue directory permissions. */ 6193 "_FFR_CHK_QUEUE", 6194 #endif 6195 #if _FFR_CLIENT_SIZE 6196 /* Don't try to send mail if its size exceeds SIZE= of server. */ 6197 "_FFR_CLIENT_SIZE", 6198 #endif 6199 #if _FFR_CRLPATH 6200 /* CRLPath; needs documentation; Al Smith */ 6201 "_FFR_CRLPATH", 6202 #endif 6203 #if _FFR_DM_ONE 6204 /* deliver first TA in background, then queue */ 6205 "_FFR_DM_ONE", 6206 #endif 6207 #if _FFR_DIGUNIX_SAFECHOWN 6208 /* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */ 6209 /* Problem noted by Anne Bennett of Concordia University */ 6210 "_FFR_DIGUNIX_SAFECHOWN", 6211 #endif 6212 #if _FFR_DNSMAP_ALIASABLE 6213 /* Allow dns map type to be used for aliases. */ 6214 /* Don Lewis of TDK */ 6215 "_FFR_DNSMAP_ALIASABLE", 6216 #endif 6217 #if _FFR_DONTLOCKFILESFORREAD_OPTION 6218 /* Enable DontLockFilesForRead option. */ 6219 "_FFR_DONTLOCKFILESFORREAD_OPTION", 6220 #endif 6221 #if _FFR_DOTTED_USERNAMES 6222 /* Allow usernames with '.' */ 6223 "_FFR_DOTTED_USERNAMES", 6224 #endif 6225 #if _FFR_DPO_CS 6226 /* 6227 ** Make DaemonPortOptions case sensitive. 6228 ** For some unknown reasons the code converted every option 6229 ** to uppercase (first letter only, as that's the only one that 6230 ** is actually checked). This prevented all new lower case options 6231 ** from working... 6232 ** The documentation doesn't say anything about case (in)sensitivity, 6233 ** which means it should be case sensitive by default, 6234 ** but it's not a good idea to change this within a patch release, 6235 ** so let's delay this to 8.15. 6236 */ 6237 6238 "_FFR_DPO_CS", 6239 #endif 6240 #if _FFR_DPRINTF_MAP 6241 /* dprintf map for logging */ 6242 "_FFR_DPRINTF_MAP", 6243 #endif 6244 #if _FFR_DROP_TRUSTUSER_WARNING 6245 /* 6246 ** Don't issue this warning: 6247 ** "readcf: option TrustedUser may cause problems on systems 6248 ** which do not support fchown() if UseMSP is not set. 6249 */ 6250 6251 "_FFR_DROP_TRUSTUSER_WARNING", 6252 #endif 6253 #if _FFR_EIGHT_BIT_ADDR_OK 6254 /* EightBitAddrOK: allow 8-bit e-mail addresses */ 6255 "_FFR_EIGHT_BIT_ADDR_OK", 6256 #endif 6257 #if _FFR_EXTRA_MAP_CHECK 6258 /* perform extra checks on $( $) in R lines */ 6259 "_FFR_EXTRA_MAP_CHECK", 6260 #endif 6261 #if _FFR_GETHBN_ExFILE 6262 /* 6263 ** According to Motonori Nakamura some gethostbyname() 6264 ** implementations (TurboLinux?) may (temporarily) fail 6265 ** due to a lack of file descriptors. Enabling this FFR 6266 ** will check errno for EMFILE and ENFILE and in case of a match 6267 ** cause a temporary error instead of a permanent error. 6268 ** The right solution is of course to file a bug against those 6269 ** systems such that they actually set h_errno = TRY_AGAIN. 6270 */ 6271 6272 "_FFR_GETHBN_ExFILE", 6273 #endif 6274 #if _FFR_FIPSMODE 6275 /* FIPSMode (if supported by OpenSSL library) */ 6276 "_FFR_FIPSMODE", 6277 #endif 6278 #if _FFR_FIX_DASHT 6279 /* 6280 ** If using -t, force not sending to argv recipients, even 6281 ** if they are mentioned in the headers. 6282 */ 6283 6284 "_FFR_FIX_DASHT", 6285 #endif 6286 #if _FFR_FORWARD_SYSERR 6287 /* Cause a "syserr" if forward file isn't "safe". */ 6288 "_FFR_FORWARD_SYSERR", 6289 #endif 6290 #if _FFR_GEN_ORCPT 6291 /* Generate a ORCPT DSN arg if not already provided */ 6292 "_FFR_GEN_ORCPT", 6293 #endif 6294 #if _FFR_HANDLE_ISO8859_GECOS 6295 /* 6296 ** Allow ISO 8859 characters in GECOS field: replace them 6297 ** with ASCII "equivalent". 6298 */ 6299 6300 /* Peter Eriksson of Linkopings universitet */ 6301 "_FFR_HANDLE_ISO8859_GECOS", 6302 #endif 6303 #if _FFR_HANDLE_HDR_RW_TEMPFAIL 6304 /* 6305 ** Temporary header rewriting problems from remotename() etc 6306 ** are not "sticky" for mci (e.g., during queue runs). 6307 */ 6308 6309 "_FFR_HANDLE_HDR_RW_TEMPFAIL", 6310 #endif 6311 #if _FFR_HPUX_NSSWITCH 6312 /* Use nsswitch on HP-UX */ 6313 "_FFR_HPUX_NSSWITCH", 6314 #endif 6315 #if _FFR_IGNORE_BOGUS_ADDR 6316 /* Ignore addresses for which prescan() failed */ 6317 "_FFR_IGNORE_BOGUS_ADDR", 6318 #endif 6319 #if _FFR_IGNORE_EXT_ON_HELO 6320 /* Ignore extensions offered in response to HELO */ 6321 "_FFR_IGNORE_EXT_ON_HELO", 6322 #endif 6323 #if _FFR_LINUX_MHNL 6324 /* Set MAXHOSTNAMELEN to 256 (Linux) */ 6325 "_FFR_LINUX_MHNL", 6326 #endif 6327 #if _FFR_LOCAL_DAEMON 6328 /* Local daemon mode (-bl) which only accepts loopback connections */ 6329 "_FFR_LOCAL_DAEMON", 6330 #endif 6331 #if _FFR_LOG_MORE1 6332 /* log some TLS/AUTH info in from= too */ 6333 "_FFR_LOG_MORE1", 6334 #endif 6335 #if _FFR_LOG_MORE2 6336 /* log some TLS info in to= too */ 6337 "_FFR_LOG_MORE2", 6338 #endif 6339 #if _FFR_LOGREPLY 6340 "_FFR_LOGREPLY", 6341 #endif 6342 #if _FFR_MAIL_MACRO 6343 "_FFR_MAIL_MACRO", 6344 #endif 6345 #if _FFR_MAXDATASIZE 6346 /* 6347 ** It is possible that a header is larger than MILTER_CHUNK_SIZE, 6348 ** hence this shouldn't be used as limit for milter communication. 6349 ** see also libmilter/comm.c 6350 ** Gurusamy Sarathy of ActiveState 6351 */ 6352 6353 "_FFR_MAXDATASIZE", 6354 #endif 6355 #if _FFR_MAX_FORWARD_ENTRIES 6356 /* Try to limit number of .forward entries */ 6357 /* (doesn't work) */ 6358 /* Randall S. Winchester of the University of Maryland */ 6359 "_FFR_MAX_FORWARD_ENTRIES", 6360 #endif 6361 #if _FFR_MAX_SLEEP_TIME 6362 /* Limit sleep(2) time in libsm/clock.c */ 6363 "_FFR_MAX_SLEEP_TIME", 6364 #endif 6365 #if _FFR_MDS_NEGOTIATE 6366 /* MaxDataSize negotation with libmilter */ 6367 "_FFR_MDS_NEGOTIATE", 6368 #endif 6369 #if _FFR_MEMSTAT 6370 /* Check free memory */ 6371 "_FFR_MEMSTAT", 6372 #endif 6373 #if _FFR_MILTER_CHECK 6374 "_FFR_MILTER_CHECK", 6375 #endif 6376 #if _FFR_MILTER_CONNECT_REPLYCODE 6377 /* milter: propagate replycode returned by connect commands */ 6378 /* John Gardiner Myers of Proofpoint */ 6379 "_FFR_MILTER_CONNECT_REPLYCODE ", 6380 #endif 6381 #if _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF 6382 /* 6383 ** milter_body() uses the same conversion algorithm as putbody() 6384 ** to translate the "local" df format (\n) to SMTP format (\r\n). 6385 ** However, putbody() and mime8to7() use different conversion 6386 ** algorithms. 6387 ** If the input date does not follow the SMTP standard 6388 ** (e.g., if it has "naked \r"s), then the output from putbody() 6389 ** and mime8to7() will most likely be different. 6390 ** By turning on this FFR milter_body() will try to "imitate" 6391 ** mime8to7(). 6392 ** Note: there is no (simple) way to deal with both conversions 6393 ** in a consistent manner. Moreover, as the "GiGo" principle applies, 6394 ** it's not really worth to fix it. 6395 */ 6396 6397 "_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF", 6398 #endif 6399 #if _FFR_MILTER_CHECK_REJECTIONS_TOO 6400 /* 6401 ** Also send RCPTs that are rejected by check_rcpt to a milter 6402 ** (if requested during option negotiation). 6403 */ 6404 6405 "_FFR_MILTER_CHECK_REJECTIONS_TOO", 6406 #endif 6407 #if _FFR_MILTER_ENHSC 6408 /* extract enhanced status code from milter replies for dsn= logging */ 6409 "_FFR_MILTER_ENHSC", 6410 #endif 6411 #if _FFR_MIME7TO8_OLD 6412 /* Old mime7to8 code, the new is broken for at least one example. */ 6413 "_FFR_MIME7TO8_OLD", 6414 #endif 6415 #if _FFR_MORE_MACROS 6416 /* allow more long macro names ("unprintable" characters). */ 6417 "_FFR_MORE_MACROS", 6418 #endif 6419 #if _FFR_MSG_ACCEPT 6420 /* allow to override "Message accepted for delivery" */ 6421 "_FFR_MSG_ACCEPT", 6422 #endif 6423 #if _FFR_NODELAYDSN_ON_HOLD 6424 /* Do not issue a DELAY DSN for mailers that use the hold flag. */ 6425 /* Steven Pitzl */ 6426 "_FFR_NODELAYDSN_ON_HOLD", 6427 #endif 6428 #if _FFR_NO_PIPE 6429 /* Disable PIPELINING, delay client if used. */ 6430 "_FFR_NO_PIPE", 6431 #endif 6432 #if _FFR_LDAP_NETWORK_TIMEOUT 6433 /* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */ 6434 "_FFR_LDAP_NETWORK_TIMEOUT", 6435 #endif 6436 #if _FFR_LOG_NTRIES 6437 /* log ntries=, from Nik Clayton of FreeBSD */ 6438 "_FFR_LOG_NTRIES", 6439 #endif 6440 #if _FFR_PROXY 6441 /* "proxy" (synchronous) delivery mode */ 6442 "_FFR_PROXY", 6443 #endif 6444 #if _FFR_QF_PARANOIA 6445 "_FFR_QF_PARANOIA", 6446 #endif 6447 #if _FFR_QUEUE_GROUP_SORTORDER 6448 /* Allow QueueSortOrder per queue group. */ 6449 /* XXX: Still need to actually use qgrp->qg_sortorder */ 6450 "_FFR_QUEUE_GROUP_SORTORDER", 6451 #endif 6452 #if _FFR_QUEUE_MACRO 6453 /* Define {queue} macro. */ 6454 "_FFR_QUEUE_MACRO", 6455 #endif 6456 #if _FFR_QUEUE_RUN_PARANOIA 6457 /* Additional checks when doing queue runs; interval of checks */ 6458 "_FFR_QUEUE_RUN_PARANOIA", 6459 #endif 6460 #if _FFR_QUEUE_SCHED_DBG 6461 /* Debug output for the queue scheduler. */ 6462 "_FFR_QUEUE_SCHED_DBG", 6463 #endif 6464 #if _FFR_RCPTFLAGS 6465 "_FFR_RCPTFLAGS", 6466 #endif 6467 #if _FFR_RCPTTHROTDELAY 6468 /* configurable delay for BadRcptThrottle */ 6469 "_FFR_RCPTTHROTDELAY", 6470 #endif 6471 #if _FFR_REDIRECTEMPTY 6472 /* 6473 ** envelope <> can't be sent to mailing lists, only owner- 6474 ** send spam of this type to owner- of the list 6475 ** ---- to stop spam from going to mailing lists. 6476 */ 6477 6478 "_FFR_REDIRECTEMPTY", 6479 #endif 6480 #if _FFR_REJECT_NUL_BYTE 6481 /* reject NUL bytes in body */ 6482 "_FFR_REJECT_NUL_BYTE", 6483 #endif 6484 #if _FFR_RESET_MACRO_GLOBALS 6485 /* Allow macro 'j' to be set dynamically via rulesets. */ 6486 "_FFR_RESET_MACRO_GLOBALS", 6487 #endif 6488 #if _FFR_RHS 6489 /* Random shuffle for queue sorting. */ 6490 "_FFR_RHS", 6491 #endif 6492 #if _FFR_RUNPQG 6493 /* 6494 ** allow -qGqueue_group -qp to work, i.e., 6495 ** restrict a persistent queue runner to a queue group. 6496 */ 6497 6498 "_FFR_RUNPQG", 6499 #endif 6500 #if _FFR_SESSID 6501 /* session id (for logging) */ 6502 "_FFR_SESSID", 6503 #endif 6504 #if _FFR_SHM_STATUS 6505 /* Donated code (unused). */ 6506 "_FFR_SHM_STATUS", 6507 #endif 6508 #if _FFR_LDAP_SINGLEDN 6509 /* 6510 ** The LDAP database map code in Sendmail 8.12.10, when 6511 ** given the -1 switch, would match only a single DN, 6512 ** but was able to return multiple attributes for that 6513 ** DN. In Sendmail 8.13 this "bug" was corrected to 6514 ** only return if exactly one attribute matched. 6515 ** 6516 ** Unfortunately, our configuration uses the former 6517 ** behaviour. Attached is a relatively simple patch 6518 ** to 8.13.4 which adds a -2 switch (for lack of a 6519 ** better option) which returns the single dn/multiple 6520 ** attributes. 6521 ** 6522 ** Jeffrey T. Eaton, Carnegie-Mellon University 6523 */ 6524 6525 "_FFR_LDAP_SINGLEDN", 6526 #endif 6527 #if _FFR_SKIP_DOMAINS 6528 /* process every N'th domain instead of every N'th message */ 6529 "_FFR_SKIP_DOMAINS", 6530 #endif 6531 #if _FFR_SLEEP_USE_SELECT 6532 /* Use select(2) in libsm/clock.c to emulate sleep(2) */ 6533 "_FFR_SLEEP_USE_SELECT ", 6534 #endif 6535 #if _FFR_SPT_ALIGN 6536 /* 6537 ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64 6538 ** bit alignment, so unless each piece of argv and envp is a multiple 6539 ** of 8 bytes (including terminating NULL), initsetproctitle() won't 6540 ** use any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE 6541 ** if you use this FFR. 6542 */ 6543 6544 /* Chris Adams of HiWAAY Informations Services */ 6545 "_FFR_SPT_ALIGN", 6546 #endif 6547 #if _FFR_SS_PER_DAEMON 6548 /* SuperSafe per DaemonPortOptions: 'T' (better letter?) */ 6549 "_FFR_SS_PER_DAEMON", 6550 #endif 6551 #if _FFR_TESTS 6552 /* enable some test code */ 6553 "_FFR_TESTS", 6554 #endif 6555 #if _FFR_TIMERS 6556 /* Donated code (unused). */ 6557 "_FFR_TIMERS", 6558 #endif 6559 #if _FFR_TLS_EC 6560 "_FFR_TLS_EC", 6561 #endif 6562 #if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE 6563 /* 6564 ** Use SSL_CTX_use_certificate_chain_file() 6565 ** instead of SSL_CTX_use_certificate_file() 6566 */ 6567 6568 "_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE", 6569 #endif 6570 #if _FFR_TLS_SE_OPTS 6571 /* TLS session options */ 6572 "_FFR_TLS_SE_OPTS", 6573 #endif 6574 #if _FFR_TRUSTED_QF 6575 /* 6576 ** If we don't own the file mark it as unsafe. 6577 ** However, allow TrustedUser to own it as well 6578 ** in case TrustedUser manipulates the queue. 6579 */ 6580 6581 "_FFR_TRUSTED_QF", 6582 #endif 6583 #if _FFR_USE_GETPWNAM_ERRNO 6584 /* 6585 ** See libsm/mbdb.c: only enable this on OSs 6586 ** that implement the correct (POSIX) semantics. 6587 ** This will need to become an OS-specific #if enabled 6588 ** in one of the headers files under include/sm/os/ . 6589 */ 6590 6591 "_FFR_USE_GETPWNAM_ERRNO", 6592 #endif 6593 #if _FFR_USE_SEM_LOCKING 6594 "_FFR_USE_SEM_LOCKING", 6595 #endif 6596 #if _FFR_USE_SETLOGIN 6597 /* Use setlogin() */ 6598 /* Peter Philipp */ 6599 "_FFR_USE_SETLOGIN", 6600 #endif 6601 #if _FFR_XCNCT 6602 "_FFR_XCNCT", 6603 #endif 6604 NULL 6605 }; 6606 6607