1divert(-1) 2# 3# Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. 4# All rights reserved. 5# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. 6# Copyright (c) 1988, 1993 7# The Regents of the University of California. All rights reserved. 8# 9# By using this file, you agree to the terms and conditions set 10# forth in the LICENSE file which can be found at the top level of 11# the sendmail distribution. 12# 13# 14divert(0) 15 16VERSIONID(`$Id: proto.m4,v 8.649.2.5 2002/08/15 02:39:01 ca Exp $') 17 18# level CF_LEVEL config file format 19V`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Berkeley') 20divert(-1) 21 22dnl if MAILER(`local') not defined: do it ourself; be nice 23dnl maybe we should issue a warning? 24ifdef(`_MAILER_local_',`', `MAILER(local)') 25 26# do some sanity checking 27ifdef(`__OSTYPE__',, 28 `errprint(`*** ERROR: No system type defined (use OSTYPE macro) 29')') 30 31# pick our default mailers 32ifdef(`confSMTP_MAILER',, `define(`confSMTP_MAILER', `esmtp')') 33ifdef(`confLOCAL_MAILER',, `define(`confLOCAL_MAILER', `local')') 34ifdef(`confRELAY_MAILER',, 35 `define(`confRELAY_MAILER', 36 `ifdef(`_MAILER_smtp_', `relay', 37 `ifdef(`_MAILER_uucp', `uucp-new', `unknown')')')') 38ifdef(`confUUCP_MAILER',, `define(`confUUCP_MAILER', `uucp-old')') 39define(`_SMTP_', `confSMTP_MAILER')dnl for readability only 40define(`_LOCAL_', `confLOCAL_MAILER')dnl for readability only 41define(`_RELAY_', `confRELAY_MAILER')dnl for readability only 42define(`_UUCP_', `confUUCP_MAILER')dnl for readability only 43 44# back compatibility with old config files 45ifdef(`confDEF_GROUP_ID', 46`errprint(`*** confDEF_GROUP_ID is obsolete. 47 Use confDEF_USER_ID with a colon in the value instead. 48')') 49ifdef(`confREAD_TIMEOUT', 50`errprint(`*** confREAD_TIMEOUT is obsolete. 51 Use individual confTO_<timeout> parameters instead. 52')') 53ifdef(`confMESSAGE_TIMEOUT', 54 `define(`_ARG_', index(confMESSAGE_TIMEOUT, /)) 55 ifelse(_ARG_, -1, 56 `define(`confTO_QUEUERETURN', confMESSAGE_TIMEOUT)', 57 `define(`confTO_QUEUERETURN', 58 substr(confMESSAGE_TIMEOUT, 0, _ARG_)) 59 define(`confTO_QUEUEWARN', 60 substr(confMESSAGE_TIMEOUT, eval(_ARG_+1)))')') 61ifdef(`confMIN_FREE_BLOCKS', `ifelse(index(confMIN_FREE_BLOCKS, /), -1,, 62`errprint(`*** compound confMIN_FREE_BLOCKS is obsolete. 63 Use confMAX_MESSAGE_SIZE for the second part of the value. 64')')') 65 66 67# Sanity check on ldap_routing feature 68# If the user doesn't specify a new map, they better have given as a 69# default LDAP specification which has the LDAP base (and most likely the host) 70ifdef(`confLDAP_DEFAULT_SPEC',, `ifdef(`_LDAP_ROUTING_WARN_', `errprint(` 71WARNING: Using default FEATURE(ldap_routing) map definition(s) 72without setting confLDAP_DEFAULT_SPEC option. 73')')')dnl 74 75# clean option definitions below.... 76define(`_OPTION', `ifdef(`$2', `O $1`'ifelse(defn(`$2'), `',, `=$2')', `#O $1`'ifelse(`$3', `',,`=$3')')')dnl 77 78dnl required to "rename" the check_* rulesets... 79define(`_U_',ifdef(`_DELAY_CHECKS_',`',`_')) 80dnl default relaying denied message 81ifdef(`confRELAY_MSG', `', `define(`confRELAY_MSG', 82ifdef(`_USE_AUTH_', `"550 Relaying denied. Proper authentication required."', `"550 Relaying denied"'))') 83ifdef(`confRCPTREJ_MSG', `', `define(`confRCPTREJ_MSG', `"550 Mailbox disabled for this recipient"')') 84define(`_CODE553', `553') 85divert(0)dnl 86 87# override file safeties - setting this option compromises system security, 88# addressing the actual file configuration problem is preferred 89# need to set this before any file actions are encountered in the cf file 90_OPTION(DontBlameSendmail, `confDONT_BLAME_SENDMAIL', `safe') 91 92# default LDAP map specification 93# need to set this now before any LDAP maps are defined 94_OPTION(LDAPDefaultSpec, `confLDAP_DEFAULT_SPEC', `-h localhost') 95 96################## 97# local info # 98################## 99 100# my LDAP cluster 101# need to set this before any LDAP lookups are done (including classes) 102ifdef(`confLDAP_CLUSTER', `D{sendmailMTACluster}`'confLDAP_CLUSTER', `#D{sendmailMTACluster}$m') 103 104Cwlocalhost 105ifdef(`USE_CW_FILE', 106`# file containing names of hosts for which we receive email 107Fw`'confCW_FILE', 108 `dnl') 109 110# my official domain name 111# ... `define' this only if sendmail cannot automatically determine your domain 112ifdef(`confDOMAIN_NAME', `Dj`'confDOMAIN_NAME', `#Dj$w.Foo.COM') 113 114CP. 115 116ifdef(`UUCP_RELAY', 117`# UUCP relay host 118DY`'UUCP_RELAY 119CPUUCP 120 121')dnl 122ifdef(`BITNET_RELAY', 123`# BITNET relay host 124DB`'BITNET_RELAY 125CPBITNET 126 127')dnl 128ifdef(`DECNET_RELAY', 129`define(`_USE_DECNET_SYNTAX_', 1)dnl 130# DECnet relay host 131DC`'DECNET_RELAY 132CPDECNET 133 134')dnl 135ifdef(`FAX_RELAY', 136`# FAX relay host 137DF`'FAX_RELAY 138CPFAX 139 140')dnl 141# "Smart" relay host (may be null) 142DS`'ifdef(`SMART_HOST', `SMART_HOST') 143 144ifdef(`LUSER_RELAY', `dnl 145# place to which unknown users should be forwarded 146Kuser user -m -a<> 147DL`'LUSER_RELAY', 148`dnl') 149 150# operators that cannot be in local usernames (i.e., network indicators) 151CO @ % ifdef(`_NO_UUCP_', `', `!') 152 153# a class with just dot (for identifying canonical names) 154C.. 155 156# a class with just a left bracket (for identifying domain literals) 157C[[ 158 159ifdef(`_ACCESS_TABLE_', `dnl 160# access_db acceptance class 161C{Accept}OK RELAY 162ifdef(`_DELAY_COMPAT_8_10_',`dnl 163ifdef(`_BLACKLIST_RCPT_',`dnl 164# possible access_db RHS for spam friends/haters 165C{SpamTag}SPAMFRIEND SPAMHATER')')', 166`dnl') 167 168dnl mark for "domain is ok" (resolved or accepted anyway) 169define(`_RES_OK_', `OKR')dnl 170ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',`dnl',`dnl 171# Resolve map (to check if a host exists in check_mail) 172Kresolve host -a<_RES_OK_> -T<TEMP>') 173C{ResOk}_RES_OK_ 174 175ifdef(`_NEED_MACRO_MAP_', `dnl 176ifdef(`_MACRO_MAP_', `', `# macro storage map 177define(`_MACRO_MAP_', `1')dnl 178Kmacro macro')', `dnl') 179 180ifdef(`confCR_FILE', `dnl 181# Hosts for which relaying is permitted ($=R) 182FR`'confCR_FILE', 183`dnl') 184 185define(`TLS_SRV_TAG', `"TLS_Srv"')dnl 186define(`TLS_CLT_TAG', `"TLS_Clt"')dnl 187define(`TLS_RCPT_TAG', `"TLS_Rcpt"')dnl 188define(`TLS_TRY_TAG', `"Try_TLS"')dnl 189define(`SRV_FEAT_TAG', `"Srv_Features"')dnl 190dnl this may be useful in other contexts too 191ifdef(`_ARITH_MAP_', `', `# arithmetic map 192define(`_ARITH_MAP_', `1')dnl 193Karith arith') 194ifdef(`_ACCESS_TABLE_', `dnl 195ifdef(`_MACRO_MAP_', `', `# macro storage map 196define(`_MACRO_MAP_', `1')dnl 197Kmacro macro') 198# possible values for TLS_connection in access map 199C{tls}VERIFY ENCR', `dnl') 200ifdef(`_CERT_REGEX_ISSUER_', `dnl 201# extract relevant part from cert issuer 202KCERTIssuer regex _CERT_REGEX_ISSUER_', `dnl') 203ifdef(`_CERT_REGEX_SUBJECT_', `dnl 204# extract relevant part from cert subject 205KCERTSubject regex _CERT_REGEX_SUBJECT_', `dnl') 206 207ifdef(`LOCAL_RELAY', `dnl 208# who I send unqualified names to (null means deliver locally) 209DR`'LOCAL_RELAY') 210 211ifdef(`MAIL_HUB', `dnl 212# who gets all local email traffic ($R has precedence for unqualified names) 213DH`'MAIL_HUB') 214 215# dequoting map 216Kdequote dequote`'ifdef(`confDEQUOTE_OPTS', ` confDEQUOTE_OPTS', `') 217 218divert(0)dnl # end of nullclient diversion 219# class E: names that should be exposed as from this host, even if we masquerade 220# class L: names that should be delivered locally, even if we have a relay 221# class M: domains that should be converted to $M 222# class N: domains that should not be converted to $M 223#CL root 224undivert(5)dnl 225ifdef(`_VIRTHOSTS_', `CR$={VirtHost}', `dnl') 226 227ifdef(`MASQUERADE_NAME', `dnl 228# who I masquerade as (null for no masquerading) (see also $=M) 229DM`'MASQUERADE_NAME') 230 231# my name for error messages 232ifdef(`confMAILER_NAME', `Dn`'confMAILER_NAME', `#DnMAILER-DAEMON') 233 234undivert(6)dnl LOCAL_CONFIG 235include(_CF_DIR_`m4/version.m4') 236 237############### 238# Options # 239############### 240ifdef(`confAUTO_REBUILD', 241`errprint(WARNING: `confAUTO_REBUILD' is no longer valid. 242 There was a potential for a denial of service attack if this is set. 243)')dnl 244 245# strip message body to 7 bits on input? 246_OPTION(SevenBitInput, `confSEVEN_BIT_INPUT', `False') 247 248# 8-bit data handling 249_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `pass8') 250 251# wait for alias file rebuild (default units: minutes) 252_OPTION(AliasWait, `confALIAS_WAIT', `5m') 253 254# location of alias file 255_OPTION(AliasFile, `ALIAS_FILE', `MAIL_SETTINGS_DIR`'aliases') 256 257# minimum number of free blocks on filesystem 258_OPTION(MinFreeBlocks, `confMIN_FREE_BLOCKS', `100') 259 260# maximum message size 261_OPTION(MaxMessageSize, `confMAX_MESSAGE_SIZE', `1000000') 262 263# substitution for space (blank) characters 264_OPTION(BlankSub, `confBLANK_SUB', `_') 265 266# avoid connecting to "expensive" mailers on initial submission? 267_OPTION(HoldExpensive, `confCON_EXPENSIVE', `False') 268 269# checkpoint queue runs after every N successful deliveries 270_OPTION(CheckpointInterval, `confCHECKPOINT_INTERVAL', `10') 271 272# default delivery mode 273_OPTION(DeliveryMode, `confDELIVERY_MODE', `background') 274 275# error message header/file 276_OPTION(ErrorHeader, `confERROR_MESSAGE', `MAIL_SETTINGS_DIR`'error-header') 277 278# error mode 279_OPTION(ErrorMode, `confERROR_MODE', `print') 280 281# save Unix-style "From_" lines at top of header? 282_OPTION(SaveFromLine, `confSAVE_FROM_LINES', `False') 283 284# queue file mode (qf files) 285_OPTION(QueueFileMode, `confQUEUE_FILE_MODE', `0600') 286 287# temporary file mode 288_OPTION(TempFileMode, `confTEMP_FILE_MODE', `0600') 289 290# match recipients against GECOS field? 291_OPTION(MatchGECOS, `confMATCH_GECOS', `False') 292 293# maximum hop count 294_OPTION(MaxHopCount, `confMAX_HOP', `25') 295 296# location of help file 297O HelpFile=ifdef(`HELP_FILE', HELP_FILE, `MAIL_SETTINGS_DIR`'helpfile') 298 299# ignore dots as terminators in incoming messages? 300_OPTION(IgnoreDots, `confIGNORE_DOTS', `False') 301 302# name resolver options 303_OPTION(ResolverOptions, `confBIND_OPTS', `+AAONLY') 304 305# deliver MIME-encapsulated error messages? 306_OPTION(SendMimeErrors, `confMIME_FORMAT_ERRORS', `True') 307 308# Forward file search path 309_OPTION(ForwardPath, `confFORWARD_PATH', `/var/forward/$u:$z/.forward.$w:$z/.forward') 310 311# open connection cache size 312_OPTION(ConnectionCacheSize, `confMCI_CACHE_SIZE', `2') 313 314# open connection cache timeout 315_OPTION(ConnectionCacheTimeout, `confMCI_CACHE_TIMEOUT', `5m') 316 317# persistent host status directory 318_OPTION(HostStatusDirectory, `confHOST_STATUS_DIRECTORY', `.hoststat') 319 320# single thread deliveries (requires HostStatusDirectory)? 321_OPTION(SingleThreadDelivery, `confSINGLE_THREAD_DELIVERY', `False') 322 323# use Errors-To: header? 324_OPTION(UseErrorsTo, `confUSE_ERRORS_TO', `False') 325 326# log level 327_OPTION(LogLevel, `confLOG_LEVEL', `10') 328 329# send to me too, even in an alias expansion? 330_OPTION(MeToo, `confME_TOO', `True') 331 332# verify RHS in newaliases? 333_OPTION(CheckAliases, `confCHECK_ALIASES', `False') 334 335# default messages to old style headers if no special punctuation? 336_OPTION(OldStyleHeaders, `confOLD_STYLE_HEADERS', `False') 337 338# SMTP daemon options 339ifelse(defn(`confDAEMON_OPTIONS'), `', `dnl', 340`errprint(WARNING: `confDAEMON_OPTIONS' is no longer valid. 341 Use `DAEMON_OPTIONS()'; see cf/README. 342)'dnl 343`DAEMON_OPTIONS(`confDAEMON_OPTIONS')') 344ifelse(defn(`_DPO_'), `', 345`ifdef(`_NETINET6_', `O DaemonPortOptions=Name=MTA-v4, Family=inet 346O DaemonPortOptions=Name=MTA-v6, Family=inet6',`O DaemonPortOptions=Name=MTA')', `_DPO_') 347ifdef(`_NO_MSA_', `dnl', `O DaemonPortOptions=Port=587, Name=MSA, M=E') 348 349# SMTP client options 350ifelse(defn(`confCLIENT_OPTIONS'), `', `dnl', 351`errprint(WARNING: `confCLIENT_OPTIONS' is no longer valid. See cf/README for more information. 352)'dnl 353`CLIENT_OPTIONS(`confCLIENT_OPTIONS')') 354ifelse(defn(`_CPO_'), `', 355`#O ClientPortOptions=Family=inet, Address=0.0.0.0', `_CPO_') 356 357# Modifiers to `define' {daemon_flags} for direct submissions 358_OPTION(DirectSubmissionModifiers, `confDIRECT_SUBMISSION_MODIFIERS', `') 359 360# Use as mail submission program? See sendmail/SECURITY 361_OPTION(UseMSP, `confUSE_MSP', `') 362 363# privacy flags 364_OPTION(PrivacyOptions, `confPRIVACY_FLAGS', `authwarnings') 365 366# who (if anyone) should get extra copies of error messages 367_OPTION(PostmasterCopy, `confCOPY_ERRORS_TO', `Postmaster') 368 369# slope of queue-only function 370_OPTION(QueueFactor, `confQUEUE_FACTOR', `600000') 371 372# limit on number of concurrent queue runners 373_OPTION(MaxQueueChildren, `confMAX_QUEUE_CHILDREN', `') 374 375# maximum number of queue-runners per queue-grouping with multiple queues 376_OPTION(MaxRunnersPerQueue, `confMAX_RUNNERS_PER_QUEUE', `1') 377 378# priority of queue runners (nice(3)) 379_OPTION(NiceQueueRun, `confNICE_QUEUE_RUN', `') 380 381# shall we sort the queue by hostname first? 382_OPTION(QueueSortOrder, `confQUEUE_SORT_ORDER', `priority') 383 384# minimum time in queue before retry 385_OPTION(MinQueueAge, `confMIN_QUEUE_AGE', `30m') 386 387# how many jobs can you process in the queue? 388_OPTION(MaxQueueRunSize, `confMAX_QUEUE_RUN_SIZE', `10000') 389 390# perform initial split of envelope without checking MX records 391_OPTION(FastSplit, `confFAST_SPLIT', `1') 392 393# queue directory 394O QueueDirectory=ifdef(`QUEUE_DIR', QUEUE_DIR, `/var/spool/mqueue') 395 396# key for shared memory; 0 to turn off 397_OPTION(SharedMemoryKey, `confSHARED_MEMORY_KEY', `0') 398 399ifdef(`confSHARED_MEMORY_KEY_FILE', `dnl 400# file to store key for shared memory (if SharedMemoryKey = -1) 401O SharedMemoryKeyFile=confSHARED_MEMORY_KEY_FILE') 402 403# timeouts (many of these) 404_OPTION(Timeout.initial, `confTO_INITIAL', `5m') 405_OPTION(Timeout.connect, `confTO_CONNECT', `5m') 406_OPTION(Timeout.aconnect, `confTO_ACONNECT', `0s') 407_OPTION(Timeout.iconnect, `confTO_ICONNECT', `5m') 408_OPTION(Timeout.helo, `confTO_HELO', `5m') 409_OPTION(Timeout.mail, `confTO_MAIL', `10m') 410_OPTION(Timeout.rcpt, `confTO_RCPT', `1h') 411_OPTION(Timeout.datainit, `confTO_DATAINIT', `5m') 412_OPTION(Timeout.datablock, `confTO_DATABLOCK', `1h') 413_OPTION(Timeout.datafinal, `confTO_DATAFINAL', `1h') 414_OPTION(Timeout.rset, `confTO_RSET', `5m') 415_OPTION(Timeout.quit, `confTO_QUIT', `2m') 416_OPTION(Timeout.misc, `confTO_MISC', `2m') 417_OPTION(Timeout.command, `confTO_COMMAND', `1h') 418_OPTION(Timeout.ident, `confTO_IDENT', `5s') 419_OPTION(Timeout.fileopen, `confTO_FILEOPEN', `60s') 420_OPTION(Timeout.control, `confTO_CONTROL', `2m') 421_OPTION(Timeout.queuereturn, `confTO_QUEUERETURN', `5d') 422_OPTION(Timeout.queuereturn.normal, `confTO_QUEUERETURN_NORMAL', `5d') 423_OPTION(Timeout.queuereturn.urgent, `confTO_QUEUERETURN_URGENT', `2d') 424_OPTION(Timeout.queuereturn.non-urgent, `confTO_QUEUERETURN_NONURGENT', `7d') 425_OPTION(Timeout.queuewarn, `confTO_QUEUEWARN', `4h') 426_OPTION(Timeout.queuewarn.normal, `confTO_QUEUEWARN_NORMAL', `4h') 427_OPTION(Timeout.queuewarn.urgent, `confTO_QUEUEWARN_URGENT', `1h') 428_OPTION(Timeout.queuewarn.non-urgent, `confTO_QUEUEWARN_NONURGENT', `12h') 429_OPTION(Timeout.hoststatus, `confTO_HOSTSTATUS', `30m') 430_OPTION(Timeout.resolver.retrans, `confTO_RESOLVER_RETRANS', `5s') 431_OPTION(Timeout.resolver.retrans.first, `confTO_RESOLVER_RETRANS_FIRST', `5s') 432_OPTION(Timeout.resolver.retrans.normal, `confTO_RESOLVER_RETRANS_NORMAL', `5s') 433_OPTION(Timeout.resolver.retry, `confTO_RESOLVER_RETRY', `4') 434_OPTION(Timeout.resolver.retry.first, `confTO_RESOLVER_RETRY_FIRST', `4') 435_OPTION(Timeout.resolver.retry.normal, `confTO_RESOLVER_RETRY_NORMAL', `4') 436_OPTION(Timeout.lhlo, `confTO_LHLO', `2m') 437_OPTION(Timeout.auth, `confTO_AUTH', `10m') 438_OPTION(Timeout.starttls, `confTO_STARTTLS', `1h') 439 440# time for DeliverBy; extension disabled if less than 0 441_OPTION(DeliverByMin, `confDELIVER_BY_MIN', `0') 442 443# should we not prune routes in route-addr syntax addresses? 444_OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES', `False') 445 446# queue up everything before forking? 447_OPTION(SuperSafe, `confSAFE_QUEUE', `True') 448 449# status file 450O StatusFile=ifdef(`STATUS_FILE', `STATUS_FILE', `MAIL_SETTINGS_DIR`'statistics') 451 452# time zone handling: 453# if undefined, use system default 454# if defined but null, use TZ envariable passed in 455# if defined and non-null, use that info 456ifelse(confTIME_ZONE, `USE_SYSTEM', `#O TimeZoneSpec=', 457 confTIME_ZONE, `USE_TZ', `O TimeZoneSpec=', 458 `O TimeZoneSpec=confTIME_ZONE') 459 460# default UID (can be username or userid:groupid) 461_OPTION(DefaultUser, `confDEF_USER_ID', `mailnull') 462 463# list of locations of user database file (null means no lookup) 464_OPTION(UserDatabaseSpec, `confUSERDB_SPEC', `MAIL_SETTINGS_DIR`'userdb') 465 466# fallback MX host 467_OPTION(FallbackMXhost, `confFALLBACK_MX', `fall.back.host.net') 468 469# if we are the best MX host for a site, try it directly instead of config err 470_OPTION(TryNullMXList, `confTRY_NULL_MX_LIST', `False') 471 472# load average at which we just queue messages 473_OPTION(QueueLA, `confQUEUE_LA', `8') 474 475# load average at which we refuse connections 476_OPTION(RefuseLA, `confREFUSE_LA', `12') 477 478# load average at which we delay connections; 0 means no limit 479_OPTION(DelayLA, `confDELAY_LA', `0') 480 481# maximum number of children we allow at one time 482_OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `0') 483 484# maximum number of new connections per second 485_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `0') 486 487# work recipient factor 488_OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', `30000') 489 490# deliver each queued job in a separate process? 491_OPTION(ForkEachJob, `confSEPARATE_PROC', `False') 492 493# work class factor 494_OPTION(ClassFactor, `confWORK_CLASS_FACTOR', `1800') 495 496# work time factor 497_OPTION(RetryFactor, `confWORK_TIME_FACTOR', `90000') 498 499# default character set 500_OPTION(DefaultCharSet, `confDEF_CHAR_SET', `iso-8859-1') 501 502# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others) 503_OPTION(ServiceSwitchFile, `confSERVICE_SWITCH_FILE', `MAIL_SETTINGS_DIR`'service.switch') 504 505# hosts file (normally /etc/hosts) 506_OPTION(HostsFile, `confHOSTS_FILE', `/etc/hosts') 507 508# dialup line delay on connection failure 509_OPTION(DialDelay, `confDIAL_DELAY', `10s') 510 511# action to take if there are no recipients in the message 512_OPTION(NoRecipientAction, `confNO_RCPT_ACTION', `add-to-undisclosed') 513 514# chrooted environment for writing to files 515_OPTION(SafeFileEnvironment, `confSAFE_FILE_ENV', `/arch') 516 517# are colons OK in addresses? 518_OPTION(ColonOkInAddr, `confCOLON_OK_IN_ADDR', `True') 519 520# shall I avoid expanding CNAMEs (violates protocols)? 521_OPTION(DontExpandCnames, `confDONT_EXPAND_CNAMES', `False') 522 523# SMTP initial login message (old $e macro) 524_OPTION(SmtpGreetingMessage, `confSMTP_LOGIN_MSG', `$j Sendmail $v ready at $b') 525 526# UNIX initial From header format (old $l macro) 527_OPTION(UnixFromLine, `confFROM_LINE', `From $g $d') 528 529# From: lines that have embedded newlines are unwrapped onto one line 530_OPTION(SingleLineFromHeader, `confSINGLE_LINE_FROM_HEADER', `False') 531 532# Allow HELO SMTP command that does not `include' a host name 533_OPTION(AllowBogusHELO, `confALLOW_BOGUS_HELO', `False') 534 535# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) 536_OPTION(MustQuoteChars, `confMUST_QUOTE_CHARS', `.') 537 538# delimiter (operator) characters (old $o macro) 539_OPTION(OperatorChars, `confOPERATORS', `.:@[]') 540 541# shall I avoid calling initgroups(3) because of high NIS costs? 542_OPTION(DontInitGroups, `confDONT_INIT_GROUPS', `False') 543 544# are group-writable `:include:' and .forward files (un)trustworthy? 545# True (the default) means they are not trustworthy. 546_OPTION(UnsafeGroupWrites, `confUNSAFE_GROUP_WRITES', `True') 547ifdef(`confUNSAFE_GROUP_WRITES', 548`errprint(`WARNING: confUNSAFE_GROUP_WRITES is deprecated; use confDONT_BLAME_SENDMAIL. 549')') 550 551# where do errors that occur when sending errors get sent? 552_OPTION(DoubleBounceAddress, `confDOUBLE_BOUNCE_ADDRESS', `postmaster') 553 554# where to save bounces if all else fails 555_OPTION(DeadLetterDrop, `confDEAD_LETTER_DROP', `/var/tmp/dead.letter') 556 557# what user id do we assume for the majority of the processing? 558_OPTION(RunAsUser, `confRUN_AS_USER', `sendmail') 559 560# maximum number of recipients per SMTP envelope 561_OPTION(MaxRecipientsPerMessage, `confMAX_RCPTS_PER_MESSAGE', `100') 562 563# limit the rate recipients per SMTP envelope are accepted 564# once the threshold number of recipients have been rejected 565_OPTION(BadRcptThrottle, `confBAD_RCPT_THROTTLE', `20') 566 567# shall we get local names from our installed interfaces? 568_OPTION(DontProbeInterfaces, `confDONT_PROBE_INTERFACES', `False') 569 570# Return-Receipt-To: header implies DSN request 571_OPTION(RrtImpliesDsn, `confRRT_IMPLIES_DSN', `False') 572 573# override connection address (for testing) 574_OPTION(ConnectOnlyTo, `confCONNECT_ONLY_TO', `0.0.0.0') 575 576# Trusted user for file ownership and starting the daemon 577_OPTION(TrustedUser, `confTRUSTED_USER', `root') 578 579# Control socket for daemon management 580_OPTION(ControlSocketName, `confCONTROL_SOCKET_NAME', `/var/spool/mqueue/.control') 581 582# Maximum MIME header length to protect MUAs 583_OPTION(MaxMimeHeaderLength, `confMAX_MIME_HEADER_LENGTH', `0/0') 584 585# Maximum length of the sum of all headers 586_OPTION(MaxHeadersLength, `confMAX_HEADERS_LENGTH', `32768') 587 588# Maximum depth of alias recursion 589_OPTION(MaxAliasRecursion, `confMAX_ALIAS_RECURSION', `10') 590 591# location of pid file 592_OPTION(PidFile, `confPID_FILE', `/var/run/sendmail.pid') 593 594# Prefix string for the process title shown on 'ps' listings 595_OPTION(ProcessTitlePrefix, `confPROCESS_TITLE_PREFIX', `prefix') 596 597# Data file (df) memory-buffer file maximum size 598_OPTION(DataFileBufferSize, `confDF_BUFFER_SIZE', `4096') 599 600# Transcript file (xf) memory-buffer file maximum size 601_OPTION(XscriptFileBufferSize, `confXF_BUFFER_SIZE', `4096') 602 603# lookup type to find information about local mailboxes 604_OPTION(MailboxDatabase, `confMAILBOX_DATABASE', `pw') 605 606# list of authentication mechanisms 607_OPTION(AuthMechanisms, `confAUTH_MECHANISMS', `EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5') 608 609# default authentication information for outgoing connections 610_OPTION(DefaultAuthInfo, `confDEF_AUTH_INFO', `MAIL_SETTINGS_DIR`'default-auth-info') 611 612# SMTP AUTH flags 613_OPTION(AuthOptions, `confAUTH_OPTIONS', `') 614 615# SMTP AUTH maximum encryption strength 616_OPTION(AuthMaxBits, `confAUTH_MAX_BITS', `') 617 618# SMTP STARTTLS server options 619_OPTION(TLSSrvOptions, `confTLS_SRV_OPTIONS', `') 620 621# Input mail filters 622_OPTION(InputMailFilters, `confINPUT_MAIL_FILTERS', `') 623 624ifelse(len(X`'_MAIL_FILTERS_DEF), `1', `dnl', `dnl 625# Milter options 626_OPTION(Milter.LogLevel, `confMILTER_LOG_LEVEL', `') 627_OPTION(Milter.macros.connect, `confMILTER_MACROS_CONNECT', `') 628_OPTION(Milter.macros.helo, `confMILTER_MACROS_HELO', `') 629_OPTION(Milter.macros.envfrom, `confMILTER_MACROS_ENVFROM', `') 630_OPTION(Milter.macros.envrcpt, `confMILTER_MACROS_ENVRCPT', `')') 631 632# CA directory 633_OPTION(CACERTPath, `confCACERT_PATH', `') 634# CA file 635_OPTION(CACERTFile, `confCACERT', `') 636# Server Cert 637_OPTION(ServerCertFile, `confSERVER_CERT', `') 638# Server private key 639_OPTION(ServerKeyFile, `confSERVER_KEY', `') 640# Client Cert 641_OPTION(ClientCertFile, `confCLIENT_CERT', `') 642# Client private key 643_OPTION(ClientKeyFile, `confCLIENT_KEY', `') 644# DHParameters (only required if DSA/DH is used) 645_OPTION(DHParameters, `confDH_PARAMETERS', `') 646# Random data source (required for systems without /dev/urandom under OpenSSL) 647_OPTION(RandFile, `confRAND_FILE', `') 648 649############################ 650`# QUEUE GROUP DEFINITIONS #' 651############################ 652_QUEUE_GROUP_ 653 654########################### 655# Message precedences # 656########################### 657 658Pfirst-class=0 659Pspecial-delivery=100 660Plist=-30 661Pbulk=-60 662Pjunk=-100 663 664##################### 665# Trusted users # 666##################### 667 668# this is equivalent to setting class "t" 669ifdef(`_USE_CT_FILE_', `', `#')Ft`'ifdef(`confCT_FILE', confCT_FILE, `MAIL_SETTINGS_DIR`'trusted-users') 670Troot 671Tdaemon 672ifdef(`_NO_UUCP_', `dnl', `Tuucp') 673ifdef(`confTRUSTED_USERS', `T`'confTRUSTED_USERS', `dnl') 674 675######################### 676# Format of headers # 677######################### 678 679ifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `$?x$x <$g>$|$g$.')')dnl 680H?P?Return-Path: <$g> 681HReceived: confRECEIVED_HEADER 682H?D?Resent-Date: $a 683H?D?Date: $a 684H?F?Resent-From: confFROM_HEADER 685H?F?From: confFROM_HEADER 686H?x?Full-Name: $x 687# HPosted-Date: $a 688# H?l?Received-Date: $b 689H?M?Resent-Message-Id: <$t.$i@$j> 690H?M?Message-Id: <$t.$i@$j> 691 692# 693###################################################################### 694###################################################################### 695##### 696##### REWRITING RULES 697##### 698###################################################################### 699###################################################################### 700 701############################################ 702### Ruleset 3 -- Name Canonicalization ### 703############################################ 704Scanonify=3 705 706# handle null input (translate to <@> special case) 707R$@ $@ <@> 708 709# strip group: syntax (not inside angle brackets!) and trailing semicolon 710R$* $: $1 <@> mark addresses 711R$* < $* > $* <@> $: $1 < $2 > $3 unmark <addr> 712R@ $* <@> $: @ $1 unmark @host:... 713R$* [ IPv6 : $+ ] <@> $: $1 [ IPv6 : $2 ] unmark IPv6 addr 714R$* :: $* <@> $: $1 :: $2 unmark node::addr 715R:`include': $* <@> $: :`include': $1 unmark :`include':... 716R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon 717R$* : $* <@> $: $2 strip colon if marked 718R$* <@> $: $1 unmark 719R$* ; $1 strip trailing semi 720R$* < $+ :; > $* $@ $2 :; <@> catch <list:;> 721R$* < $* ; > $1 < $2 > bogus bracketed semi 722 723# null input now results from list:; syntax 724R$@ $@ :; <@> 725 726# strip angle brackets -- note RFC733 heuristic to get innermost item 727R$* $: < $1 > housekeeping <> 728R$+ < $* > < $2 > strip excess on left 729R< $* > $+ < $1 > strip excess on right 730R<> $@ < @ > MAIL FROM:<> case 731R< $+ > $: $1 remove housekeeping <> 732 733ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl 734# make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later 735R@ $+ , $+ @ $1 : $2 change all "," to ":" 736 737# localize and dispose of route-based addresses 738dnl XXX: IPv6 colon conflict 739ifdef(`NO_NETINET6', `dnl', 740`R@ [$+] : $+ $@ $>Canonify2 < @ [$1] > : $2 handle <route-addr>') 741R@ $+ : $+ $@ $>Canonify2 < @$1 > : $2 handle <route-addr> 742dnl',`dnl 743# strip route address <@a,@b,@c:user@d> -> <user@d> 744R@ $+ , $+ $2 745ifdef(`NO_NETINET6', `dnl', 746`R@ [ $* ] : $+ $2') 747R@ $+ : $+ $2 748dnl') 749 750# find focus for list syntax 751R $+ : $* ; @ $+ $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax 752R $+ : $* ; $@ $1 : $2; list syntax 753 754# find focus for @ syntax addresses 755R$+ @ $+ $: $1 < @ $2 > focus on domain 756R$+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right 757R$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical 758 759dnl This is flagged as an error in S0; no need to silently fix it here. 760dnl # do some sanity checking 761dnl R$* < @ $~[ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs 762 763ifdef(`_NO_UUCP_', `dnl', 764`# convert old-style addresses to a domain-based address 765R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names 766R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps 767R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains 768') 769ifdef(`_USE_DECNET_SYNTAX_', 770`# convert node::user addresses into a domain-based address 771R$- :: $+ $@ $>Canonify2 $2 < @ $1 .DECNET > resolve DECnet names 772R$- . $- :: $+ $@ $>Canonify2 $3 < @ $1.$2 .DECNET > numeric DECnet addr 773', 774 `dnl') 775# if we have % signs, take the rightmost one 776R$* % $* $1 @ $2 First make them all @s. 777R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. 778R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish 779 780# else we must be a local name 781R$* $@ $>Canonify2 $1 782 783 784################################################ 785### Ruleset 96 -- bottom half of ruleset 3 ### 786################################################ 787 788SCanonify2=96 789 790# handle special cases for local names 791R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all 792R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain 793ifdef(`_NO_UUCP_', `dnl', 794`R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain') 795 796# check for IPv4/IPv6 domain literal 797R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [addr] 798R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal 799R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr 800 801ifdef(`_DOMAIN_TABLE_', `dnl 802# look up domains in the domain table 803R$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3', `dnl') 804 805undivert(2)dnl LOCAL_RULE_3 806 807ifdef(`_BITDOMAIN_TABLE_', `dnl 808# handle BITNET mapping 809R$* < @ $+ .BITNET > $* $: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3', `dnl') 810 811ifdef(`_UUDOMAIN_TABLE_', `dnl 812# handle UUCP mapping 813R$* < @ $+ .UUCP > $* $: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3', `dnl') 814 815ifdef(`_NO_UUCP_', `dnl', 816`ifdef(`UUCP_RELAY', 817`# pass UUCP addresses straight through 818R$* < @ $+ . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', 819`# if really UUCP, handle it immediately 820ifdef(`_CLASS_U_', 821`R$* < @ $=U . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 822ifdef(`_CLASS_V_', 823`R$* < @ $=V . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 824ifdef(`_CLASS_W_', 825`R$* < @ $=W . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 826ifdef(`_CLASS_X_', 827`R$* < @ $=X . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 828ifdef(`_CLASS_Y_', 829`R$* < @ $=Y . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 830 831ifdef(`_NO_CANONIFY_', `dnl', `dnl 832# try UUCP traffic as a local address 833R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 834R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3') 835')') 836# hostnames ending in class P are always canonical 837R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 838dnl apply the next rule only for hostnames not in class P 839dnl this even works for phrases in class P since . is in class P 840dnl which daemon flags are set? 841R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 842dnl the other rules in this section only apply if the hostname 843dnl does not end in class P hence no further checks are done here 844dnl if this ever changes make sure the lookups are "protected" again! 845ifdef(`_NO_CANONIFY_', `dnl 846dnl do not canonify unless: 847dnl domain ends in class {Canonify} (this does not work if the intersection 848dnl with class P is non-empty) 849dnl or {daemon_flags} has c set 850# pass to name server to make hostname canonical if in class {Canonify} 851R$* $| $* < @ $* $={Canonify} > $* $: $2 < @ $[ $3 $4 $] > $5 852# pass to name server to make hostname canonical if requested 853R$* c $* $| $* < @ $* > $* $: $3 < @ $[ $4 $] > $5 854dnl trailing dot? -> do not apply _CANONIFY_HOSTS_ 855R$* $| $* < @ $+ . > $* $: $2 < @ $3 . > $4 856# add a trailing dot to qualified hostnames so other rules will work 857R$* $| $* < @ $+.$+ > $* $: $2 < @ $3.$4 . > $5 858ifdef(`_CANONIFY_HOSTS_', `dnl 859dnl this should only apply to unqualified hostnames 860dnl but if a valid character inside an unqualified hostname is an OperatorChar 861dnl then $- does not work. 862# lookup unqualified hostnames 863R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4', `dnl')', `dnl 864dnl _NO_CANONIFY_ is not set: canonify unless: 865dnl {daemon_flags} contains CC (do not canonify) 866dnl but add a trailing dot to qualified hostnames so other rules will work 867dnl should we do this for every hostname: even unqualified? 868R$* CC $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 869R$* CC $* $| $* $: $3 870ifdef(`_FFR_NOCANONIFY_HEADERS', `dnl 871# do not canonify header addresses 872R$* $| $* < @ $* $~P > $* $: $&{addr_type} $| $2 < @ $3 $4 > $5 873R$* h $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 874R$* h $* $| $* $: $3', `dnl') 875# pass to name server to make hostname canonical 876R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4') 877dnl remove {daemon_flags} for other cases 878R$* $| $* $: $2 879 880# local host aliases and pseudo-domains are always canonical 881R$* < @ $=w > $* $: $1 < @ $2 . > $3 882ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 883`R$* < @ $* $=M > $* $: $1 < @ $2 $3 . > $4', 884`R$* < @ $=M > $* $: $1 < @ $2 . > $3') 885ifdef(`_VIRTUSER_TABLE_', `dnl 886dnl virtual hosts are also canonical 887ifdef(`_VIRTUSER_ENTIRE_DOMAIN_', 888`R$* < @ $* $={VirtHost} > $* $: $1 < @ $2 $3 . > $4', 889`R$* < @ $={VirtHost} > $* $: $1 < @ $2 . > $3')', 890`dnl') 891ifdef(`_GENERICS_TABLE_', `dnl 892dnl hosts for genericstable are also canonical 893ifdef(`_GENERICS_ENTIRE_DOMAIN_', 894`R$* < @ $* $=G > $* $: $1 < @ $2 $3 . > $4', 895`R$* < @ $=G > $* $: $1 < @ $2 . > $3')', 896`dnl') 897dnl remove superfluous dots (maybe repeatedly) which may have been added 898dnl by one of the rules before 899R$* < @ $* . . > $* $1 < @ $2 . > $3 900 901 902################################################## 903### Ruleset 4 -- Final Output Post-rewriting ### 904################################################## 905Sfinal=4 906 907R$+ :; <@> $@ $1 : handle <list:;> 908R$* <@> $@ handle <> and list:; 909 910# strip trailing dot off possibly canonical name 911R$* < @ $+ . > $* $1 < @ $2 > $3 912 913# eliminate internal code 914R$* < @ *LOCAL* > $* $1 < @ $j > $2 915 916# externalize local domain info 917R$* < $+ > $* $1 $2 $3 defocus 918R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 <route-addr> canonical 919R@ $* $@ @ $1 ... and exit 920 921ifdef(`_NO_UUCP_', `dnl', 922`# UUCP must always be presented in old form 923R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u') 924 925ifdef(`_USE_DECNET_SYNTAX_', 926`# put DECnet back in :: form 927R$+ @ $+ . DECNET $2 :: $1 u@h.DECNET => h::u', 928 `dnl') 929# delete duplicate local names 930R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host 931 932 933 934############################################################## 935### Ruleset 97 -- recanonicalize and call ruleset zero ### 936### (used for recursive calls) ### 937############################################################## 938 939SRecurse=97 940R$* $: $>canonify $1 941R$* $@ $>parse $1 942 943 944###################################### 945### Ruleset 0 -- Parse Address ### 946###################################### 947 948Sparse=0 949 950R$* $: $>Parse0 $1 initial parsing 951R<@> $#_LOCAL_ $: <@> special case error msgs 952R$* $: $>ParseLocal $1 handle local hacks 953R$* $: $>Parse1 $1 final parsing 954 955# 956# Parse0 -- do initial syntax checking and eliminate local addresses. 957# This should either return with the (possibly modified) input 958# or return with a #error mailer. It should not return with a 959# #mailer other than the #error mailer. 960# 961 962SParse0 963R<@> $@ <@> special case error msgs 964R$* : $* ; <@> $#error $@ 5.1.3 $: "_CODE553 List:; syntax illegal for recipient addresses" 965R@ <@ $* > < @ $1 > catch "@@host" bogosity 966R<@ $+> $#error $@ 5.1.3 $: "_CODE553 User address required" 967R$+ <@> $#error $@ 5.1.3 $: "_CODE553 Hostname required" 968R$* $: <> $1 969dnl allow tricks like [host1]:[host2] 970R<> $* < @ [ $* ] : $+ > $* $1 < @ [ $2 ] : $3 > $4 971R<> $* < @ [ $* ] , $+ > $* $1 < @ [ $2 ] , $3 > $4 972dnl but no a@[b]c 973R<> $* < @ [ $* ] $+ > $* $#error $@ 5.1.2 $: "_CODE553 Invalid address" 974R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 975R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "_CODE553 Colon illegal in host name part" 976R<> $* $1 977R$* < @ . $* > $* $#error $@ 5.1.2 $: "_CODE553 Invalid host name" 978R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "_CODE553 Invalid host name" 979dnl no a@b@ 980R$* < @ $* @ > $* $#error $@ 5.1.2 $: "_CODE553 Invalid route address" 981dnl no a@b@c 982R$* @ $* < @ $* > $* $#error $@ 5.1.3 $: "_CODE553 Invalid route address" 983dnl comma only allowed before @; this check is not complete 984R$* , $~O $* $#error $@ 5.1.3 $: "_CODE553 Invalid route address" 985 986ifdef(`_STRICT_RFC821_', `# more RFC 821 checks 987R$* . < @ $* > $* $#error $@ 5.1.2 $: "_CODE553 Local part must not end with a dot" 988R. $* < @ $* > $* $#error $@ 5.1.2 $: "_CODE553 Local part must not begin with a dot" 989dnl', `dnl') 990 991# now delete the local info -- note $=O to find characters that cause forwarding 992R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user 993R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... 994R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here 995R< @ $+ > $#error $@ 5.1.3 $: "_CODE553 User address required" 996R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... 997R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" 998R< @ *LOCAL* > $#error $@ 5.1.3 $: "_CODE553 User address required" 999R$* $=O $* < @ *LOCAL* > 1000 $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... 1001R$* < @ *LOCAL* > $: $1 1002 1003# 1004# Parse1 -- the bottom half of ruleset 0. 1005# 1006 1007SParse1 1008ifdef(`_LDAP_ROUTING_', `dnl 1009# handle LDAP routing for hosts in $={LDAPRoute} 1010R$+ < @ $={LDAPRoute} . > $: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $2> <> 1011R$+ < @ $={LDAPRouteEquiv} . > $: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $M> <>', 1012`dnl') 1013 1014ifdef(`_MAILER_smtp_', 1015`# handle numeric address spec 1016dnl there is no check whether this is really an IP number 1017R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec 1018R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path 1019R$* < @ [ $+ ] : > $* $#_SMTP_ $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send 1020R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer 1021R$* < @ [ $+ ] : $+ > $* $#_SMTP_ $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer', 1022 `dnl') 1023 1024ifdef(`_VIRTUSER_TABLE_', `dnl 1025# handle virtual users 1026ifdef(`_VIRTUSER_STOP_ONE_LEVEL_RECURSION_',`dnl 1027dnl this is not a documented option 1028dnl it stops looping in virtusertable mapping if input and output 1029dnl are identical, i.e., if address A is mapped to A. 1030dnl it does not deal with multi-level recursion 1031# handle full domains in RHS of virtusertable 1032R$+ < @ $+ > $: $(macro {RecipientAddress} $) $1 < @ $2 > 1033R$+ < @ $+ > $: <?> $1 < @ $2 > $| $>final $1 < @ $2 > 1034R<?> $+ $| $+ $: $1 $(macro {RecipientAddress} $@ $2 $) 1035R<?> $+ $| $* $: $1', 1036`dnl') 1037R$+ $: <!> $1 Mark for lookup 1038dnl input: <!> local<@domain> 1039ifdef(`_VIRTUSER_ENTIRE_DOMAIN_', 1040`R<!> $+ < @ $* $={VirtHost} . > $: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >', 1041`R<!> $+ < @ $={VirtHost} . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >') 1042dnl input: <result-of-lookup | @> local<@domain> | <!> local<@domain> 1043R<!> $+ < @ $=w . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . > 1044dnl if <@> local<@domain>: no match but try lookup 1045dnl user+detail: try user++@domain if detail not empty 1046R<@> $+ + $+ < @ $* . > 1047 $: < $(virtuser $1 + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 1048dnl user+detail: try user+*@domain 1049R<@> $+ + $* < @ $* . > 1050 $: < $(virtuser $1 + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 1051dnl user+detail: try user@domain 1052R<@> $+ + $* < @ $* . > 1053 $: < $(virtuser $1 @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 1054dnl try default entry: @domain 1055dnl ++@domain 1056R<@> $+ + $+ < @ $+ . > $: < $(virtuser + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 1057dnl +*@domain 1058R<@> $+ + $* < @ $+ . > $: < $(virtuser + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 1059dnl @domain if +detail exists 1060dnl if no match, change marker to prevent a second @domain lookup 1061R<@> $+ + $* < @ $+ . > $: < $(virtuser @ $3 $@ $1 $@ $2 $@ +$2 $: ! $) > $1 + $2 < @ $3 . > 1062dnl without +detail 1063R<@> $+ < @ $+ . > $: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . > 1064dnl no match 1065R<@> $+ $: $1 1066dnl remove mark 1067R<!> $+ $: $1 1068R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 1069R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 1070ifdef(`_VIRTUSER_STOP_ONE_LEVEL_RECURSION_',`dnl 1071# check virtuser input address against output address, if same, skip recursion 1072R< $+ > $+ < @ $+ > $: < $1 > $2 < @ $3 > $| $1 1073# it is the same: stop now 1074R< $+ > $+ < @ $+ > $| $&{RecipientAddress} $: $>ParseLocal $>Parse0 $>canonify $1 1075R< $+ > $+ < @ $+ > $| $* $: < $1 > $2 < @ $3 > 1076dnl', `dnl') 1077dnl this is not a documented option 1078dnl it performs no looping at all for virtusertable 1079ifdef(`_NO_VIRTUSER_RECURSION_', 1080`R< $+ > $+ < @ $+ > $: $>ParseLocal $>Parse0 $>canonify $1', 1081`R< $+ > $+ < @ $+ > $: $>Recurse $1') 1082dnl', `dnl') 1083 1084# short circuit local delivery so forwarded email works 1085ifdef(`_MAILER_usenet_', `dnl 1086R$+ . USENET < @ $=w . > $#usenet $@ usenet $: $1 handle usenet specially', `dnl') 1087 1088 1089ifdef(`_STICKY_LOCAL_DOMAIN_', 1090`R$+ < @ $=w . > $: < $H > $1 < @ $2 . > first try hub 1091R< $+ > $+ < $+ > $>MailerToTriple < $1 > $2 < $3 > yep .... 1092dnl $H empty (but @$=w.) 1093R< > $+ + $* < $+ > $#_LOCAL_ $: $1 + $2 plussed name? 1094R< > $+ < $+ > $#_LOCAL_ $: @ $1 nope, local address', 1095`R$=L < @ $=w . > $#_LOCAL_ $: @ $1 special local names 1096R$+ < @ $=w . > $#_LOCAL_ $: $1 regular local name') 1097 1098ifdef(`_MAILER_TABLE_', `dnl 1099# not local -- try mailer table lookup 1100R$* <@ $+ > $* $: < $2 > $1 < @ $2 > $3 extract host name 1101R< $+ . > $* $: < $1 > $2 strip trailing dot 1102R< $+ > $* $: < $(mailertable $1 $) > $2 lookup 1103dnl it is $~[ instead of $- to avoid matches on IPv6 addresses 1104R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check -- resolved? 1105R< $+ > $* $: $>Mailertable <$1> $2 try domain', 1106`dnl') 1107undivert(4)dnl UUCP rules from `MAILER(uucp)' 1108 1109ifdef(`_NO_UUCP_', `dnl', 1110`# resolve remotely connected UUCP links (if any) 1111ifdef(`_CLASS_V_', 1112`R$* < @ $=V . UUCP . > $* $: $>MailerToTriple < $V > $1 <@$2.UUCP.> $3', 1113 `dnl') 1114ifdef(`_CLASS_W_', 1115`R$* < @ $=W . UUCP . > $* $: $>MailerToTriple < $W > $1 <@$2.UUCP.> $3', 1116 `dnl') 1117ifdef(`_CLASS_X_', 1118`R$* < @ $=X . UUCP . > $* $: $>MailerToTriple < $X > $1 <@$2.UUCP.> $3', 1119 `dnl')') 1120 1121# resolve fake top level domains by forwarding to other hosts 1122ifdef(`BITNET_RELAY', 1123`R$*<@$+.BITNET.>$* $: $>MailerToTriple < $B > $1 <@$2.BITNET.> $3 user@host.BITNET', 1124 `dnl') 1125ifdef(`DECNET_RELAY', 1126`R$*<@$+.DECNET.>$* $: $>MailerToTriple < $C > $1 <@$2.DECNET.> $3 user@host.DECNET', 1127 `dnl') 1128ifdef(`_MAILER_pop_', 1129`R$+ < @ POP. > $#pop $: $1 user@POP', 1130 `dnl') 1131ifdef(`_MAILER_fax_', 1132`R$+ < @ $+ .FAX. > $#fax $@ $2 $: $1 user@host.FAX', 1133`ifdef(`FAX_RELAY', 1134`R$*<@$+.FAX.>$* $: $>MailerToTriple < $F > $1 <@$2.FAX.> $3 user@host.FAX', 1135 `dnl')') 1136 1137ifdef(`UUCP_RELAY', 1138`# forward non-local UUCP traffic to our UUCP relay 1139R$*<@$*.UUCP.>$* $: $>MailerToTriple < $Y > $1 <@$2.UUCP.> $3 uucp mail', 1140`ifdef(`_MAILER_uucp_', 1141`# forward other UUCP traffic straight to UUCP 1142R$* < @ $+ .UUCP. > $* $#_UUCP_ $@ $2 $: $1 < @ $2 .UUCP. > $3 user@host.UUCP', 1143 `dnl')') 1144ifdef(`_MAILER_usenet_', ` 1145# addresses sent to net.group.USENET will get forwarded to a newsgroup 1146R$+ . USENET $#usenet $@ usenet $: $1', 1147 `dnl') 1148 1149ifdef(`_LOCAL_RULES_', 1150`# figure out what should stay in our local mail system 1151undivert(1)', `dnl') 1152 1153# pass names that still have a host to a smarthost (if defined) 1154R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name 1155 1156# deal with other remote names 1157ifdef(`_MAILER_smtp_', 1158`R$* < @$* > $* $#_SMTP_ $@ $2 $: $1 < @ $2 > $3 user@host.domain', 1159`R$* < @$* > $* $#error $@ 5.1.2 $: "_CODE553 Unrecognized host name " $2') 1160 1161# handle locally delivered names 1162R$=L $#_LOCAL_ $: @ $1 special local names 1163R$+ $#_LOCAL_ $: $1 regular local names 1164 1165########################################################################### 1166### Ruleset 5 -- special rewriting after aliases have been expanded ### 1167########################################################################### 1168 1169SLocal_localaddr 1170Slocaladdr=5 1171R$+ $: $1 $| $>"Local_localaddr" $1 1172R$+ $| $#ok $@ $1 no change 1173R$+ $| $#$* $#$2 1174R$+ $| $* $: $1 1175 1176ifdef(`_PRESERVE_LUSER_HOST_', `dnl 1177# Preserve rcpt_host in {Host} 1178R$+ $: $1 $| $&h $| $&{Host} check h and {Host} 1179R$+ $| $| $: $(macro {Host} $@ $) $1 no h or {Host} 1180R$+ $| $| $+ $: $1 h not set, {Host} set 1181R$+ $| +$* $| $* $: $1 h is +detail, {Host} set 1182R$+ $| $* @ $+ $| $* $: $(macro {Host} $@ @$3 $) $1 set {Host} to host in h 1183R$+ $| $+ $| $* $: $(macro {Host} $@ @$2 $) $1 set {Host} to h 1184')dnl 1185 1186ifdef(`_FFR_5_', `dnl 1187# Preserve host in a macro 1188R$+ $: $(macro {LocalAddrHost} $) $1 1189R$+ @ $+ $: $(macro {LocalAddrHost} $@ @ $2 $) $1') 1190 1191ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `', `dnl 1192# deal with plussed users so aliases work nicely 1193R$+ + * $#_LOCAL_ $@ $&h $: $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') 1194R$+ + $* $#_LOCAL_ $@ + $2 $: $1 + *`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') 1195') 1196# prepend an empty "forward host" on the front 1197R$+ $: <> $1 1198 1199ifdef(`LUSER_RELAY', `dnl 1200# send unrecognized local users to a relay host 1201ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `dnl 1202R< > $+ + $* $: < ? $L > <+ $2> $(user $1 $) look up user+ 1203R< > $+ $: < ? $L > < > $(user $1 $) look up user 1204R< ? $* > < $* > $+ <> $: < > $3 $2 found; strip $L 1205R< ? $* > < $* > $+ $: < $1 > $3 $2 not found', ` 1206R< > $+ $: < $L > $(user $1 $) look up user 1207R< $* > $+ <> $: < > $2 found; strip $L') 1208ifdef(`_PRESERVE_LUSER_HOST_', `dnl 1209R< $+ > $+ $: < $1 > $2 $&{Host}') 1210dnl') 1211 1212ifdef(`MAIL_HUB', `dnl 1213R< > $+ $: < $H > $1 try hub', `dnl') 1214ifdef(`LOCAL_RELAY', `dnl 1215R< > $+ $: < $R > $1 try relay', `dnl') 1216ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `dnl 1217R< > $+ $@ $1', `dnl 1218R< > $+ $: < > < $1 <> $&h > nope, restore +detail 1219ifdef(`_PRESERVE_LUSER_HOST_', `dnl 1220R< > < $+ @ $+ <> + $* > $: < > < $1 + $3 @ $2 > check whether +detail') 1221R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail 1222R< > < $+ <> $* > $: < > < $1 > else discard 1223R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part 1224R< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') strip the extra + 1225R< > < $+ > $@ $1 no +detail 1226R$+ $: $1 <> $&h add +detail back in 1227ifdef(`_PRESERVE_LUSER_HOST_', `dnl 1228R$+ @ $+ <> + $* $: $1 + $3 @ $2 check whether +detail') 1229R$+ <> + $* $: $1 + $2 check whether +detail 1230R$+ <> $* $: $1 else discard') 1231R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension 1232R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension 1233ifdef(`_PRESERVE_LUSER_HOST_', `dnl 1234dnl it is $~[ instead of $- to avoid matches on IPv6 addresses 1235R< $~[ : $+ > $+ @ $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $4 >') 1236R< $~[ : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > 1237ifdef(`_PRESERVE_LUSER_HOST_', `dnl 1238R< $+ > $+ @ $+ $@ $>MailerToTriple < $1 > $2 < @ $3 >') 1239R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > 1240 1241ifdef(`_MAILER_TABLE_', `dnl 1242ifdef(`_LDAP_ROUTING_', `dnl 1243################################################################### 1244### Ruleset LDAPMailertable -- mailertable lookup for LDAP ### 1245dnl input: <Domain> FullAddress 1246################################################################### 1247 1248SLDAPMailertable 1249R< $+ > $* $: < $(mailertable $1 $) > $2 lookup 1250R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check resolved? 1251R< $+ > $* $: < $1 > $>Mailertable <$1> $2 try domain 1252R< $+ > $#$* $#$2 found 1253R< $+ > $* $#_RELAY_ $@ $1 $: $2 not found, direct relay', 1254`dnl') 1255 1256################################################################### 1257### Ruleset 90 -- try domain part of mailertable entry ### 1258dnl input: LeftPartOfDomain <RightPartOfDomain> FullAddress 1259################################################################### 1260 1261SMailertable=90 1262dnl shift and check 1263dnl %2 is not documented in cf/README 1264R$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4 1265dnl it is $~[ instead of $- to avoid matches on IPv6 addresses 1266R$* <$~[ : $* > $* $>MailerToTriple < $2 : $3 > $4 check -- resolved? 1267R$* < . $+ > $* $@ $>Mailertable $1 . <$2> $3 no -- strip & try again 1268dnl is $2 always empty? 1269R$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "." 1270R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 "." found? 1271dnl return full address 1272R< $* > $* $@ $2 no mailertable match', 1273`dnl') 1274 1275################################################################### 1276### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### 1277dnl input: in general: <[mailer:]host> lp<@domain>rest 1278dnl <> address -> address 1279dnl <error:d.s.n:text> -> error 1280dnl <error:text> -> error 1281dnl <mailer:user@host> lp<@domain>rest -> mailer host user 1282dnl <mailer:host> address -> mailer host address 1283dnl <localdomain> address -> address 1284dnl <host> address -> relay host address 1285################################################################### 1286 1287SMailerToTriple=95 1288R< > $* $@ $1 strip off null relay 1289R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 1290R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 1291R< local : $* > $* $>CanonLocal < $1 > $2 1292dnl it is $~[ instead of $- to avoid matches on IPv6 addresses 1293R< $~[ : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user 1294R< $~[ : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer 1295R< $=w > $* $@ $2 delete local host 1296R< $+ > $* $#_RELAY_ $@ $1 $: $2 use unqualified mailer 1297 1298################################################################### 1299### Ruleset CanonLocal -- canonify local: syntax ### 1300dnl input: <user> address 1301dnl <x> <@host> : rest -> Recurse rest 1302dnl <x> p1 $=O p2 <@host> -> Recurse p1 $=O p2 1303dnl <> user <@host> rest -> local user@host user 1304dnl <> user -> local user user 1305dnl <user@host> lp <@domain> rest -> <user> lp <@host> [cont] 1306dnl <user> lp <@host> rest -> local lp@host user 1307dnl <user> lp -> local lp user 1308################################################################### 1309 1310SCanonLocal 1311# strip local host from routed addresses 1312R< $* > < @ $+ > : $+ $@ $>Recurse $3 1313R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 1314 1315# strip trailing dot from any host name that may appear 1316R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > 1317 1318# handle local: syntax -- use old user, either with or without host 1319R< > $* < @ $* > $* $#_LOCAL_ $@ $1@$2 $: $1 1320R< > $+ $#_LOCAL_ $@ $1 $: $1 1321 1322# handle local:user@host syntax -- ignore host part 1323R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > 1324 1325# handle local:user syntax 1326R< $+ > $* <@ $* > $* $#_LOCAL_ $@ $2@$3 $: $1 1327R< $+ > $* $#_LOCAL_ $@ $2 $: $1 1328 1329################################################################### 1330### Ruleset 93 -- convert header names to masqueraded form ### 1331################################################################### 1332 1333SMasqHdr=93 1334 1335ifdef(`_GENERICS_TABLE_', `dnl 1336# handle generics database 1337ifdef(`_GENERICS_ENTIRE_DOMAIN_', 1338dnl if generics should be applied add a @ as mark 1339`R$+ < @ $* $=G . > $: < $1@$2$3 > $1 < @ $2$3 . > @ mark', 1340`R$+ < @ $=G . > $: < $1@$2 > $1 < @ $2 . > @ mark') 1341R$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark 1342dnl workspace: either user<@domain> or <user@domain> user <@domain> @ 1343dnl ignore the first case for now 1344dnl if it has the mark lookup full address 1345dnl broken: %1 is full address not just detail 1346R< $+ > $+ < $* > @ $: < $(generics $1 $: @ $1 $) > $2 < $3 > 1347dnl workspace: ... or <match|@user@domain> user <@domain> 1348dnl no match, try user+detail@domain 1349R<@$+ + $* @ $+> $+ < @ $+ > 1350 $: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) > $4 < @ $5 > 1351R<@$+ + $* @ $+> $+ < @ $+ > 1352 $: < $(generics $1@$3 $: $) > $4 < @ $5 > 1353dnl no match, remove mark 1354R<@$+ > $+ < @ $+ > $: < > $2 < @ $3 > 1355dnl no match, try @domain for exceptions 1356R< > $+ < @ $+ . > $: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . > 1357dnl workspace: ... or <match> user <@domain> 1358dnl no match, try local part 1359R< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 > 1360R< > $+ + $* < @ $+ > $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 > 1361R< > $+ + $* < @ $+ > $: < $(generics $1 $: $) > $1 + $2 < @ $3 > 1362R< $* @ $* > $* < $* > $@ $>canonify $1 @ $2 found qualified 1363R< $+ > $* < $* > $: $>canonify $1 @ *LOCAL* found unqualified 1364R< > $* $: $1 not found', 1365`dnl') 1366 1367# do not masquerade anything in class N 1368R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > 1369 1370ifdef(`MASQUERADE_NAME', `dnl 1371# special case the users that should be exposed 1372R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed 1373ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 1374`R$=E < @ $* $=M . > $@ $1 < @ $2 $3 . >', 1375`R$=E < @ $=M . > $@ $1 < @ $2 . >') 1376ifdef(`_LIMITED_MASQUERADE_', `dnl', 1377`R$=E < @ $=w . > $@ $1 < @ $2 . >') 1378 1379# handle domain-specific masquerading 1380ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 1381`R$* < @ $* $=M . > $* $: $1 < @ $2 $3 . @ $M > $4 convert masqueraded doms', 1382`R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms') 1383ifdef(`_LIMITED_MASQUERADE_', `dnl', 1384`R$* < @ $=w . > $* $: $1 < @ $2 . @ $M > $3') 1385R$* < @ *LOCAL* > $* $: $1 < @ $j . @ $M > $2 1386R$* < @ $+ @ > $* $: $1 < @ $2 > $3 $M is null 1387R$* < @ $+ @ $+ > $* $: $1 < @ $3 . > $4 $M is not null 1388dnl', `dnl no masquerading 1389dnl just fix *LOCAL* leftovers 1390R$* < @ *LOCAL* > $@ $1 < @ $j . >') 1391 1392################################################################### 1393### Ruleset 94 -- convert envelope names to masqueraded form ### 1394################################################################### 1395 1396SMasqEnv=94 1397ifdef(`_MASQUERADE_ENVELOPE_', 1398`R$+ $@ $>MasqHdr $1', 1399`R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2') 1400 1401################################################################### 1402### Ruleset 98 -- local part of ruleset zero (can be null) ### 1403################################################################### 1404 1405SParseLocal=98 1406undivert(3)dnl LOCAL_RULE_0 1407 1408ifdef(`_LDAP_ROUTING_', `dnl 1409###################################################################### 1410### LDAPExpand: Expand address using LDAP routing 1411### 1412### Parameters: 1413### <$1> -- parsed address (user < @ domain . >) (pass through) 1414### <$2> -- RFC822 address (user @ domain) (used for lookup) 1415### <$3> -- +detail information 1416### 1417### Returns: 1418### Mailer triplet ($#mailer $@ host $: address) 1419### Parsed address (user < @ domain . >) 1420###################################################################### 1421 1422SLDAPExpand 1423# do the LDAP lookups 1424R<$+><$+><$*> $: <$(ldapmra $2 $: $)> <$(ldapmh $2 $: $)> <$1> <$2> <$3> 1425 1426# look for temporary failures (return original address, MTA will queue up) 1427R<$* <TMPF>> <$*> <$+> <$+> <$*> $@ $3 1428R<$*> <$* <TMPF>> <$+> <$+> <$*> $@ $3 1429 1430# if mailRoutingAddress and local or non-existant mailHost, 1431# return the new mailRoutingAddress 1432ifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl 1433R<$+@$+> <$=w> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 $6 @ $2 1434R<$+@$+> <> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 $5 @ $2') 1435R<$+> <$=w> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 1436R<$+> <> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 1437 1438 1439# if mailRoutingAddress and non-local mailHost, 1440# relay to mailHost with new mailRoutingAddress 1441ifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl 1442ifdef(`_MAILER_TABLE_', `dnl 1443# check mailertable for host, relay from there 1444R<$+@$+> <$+> <$+> <$+> <$*> $>LDAPMailertable <$3> $>canonify $1 $6 @ $2', 1445`R<$+@$+> <$+> <$+> <$+> <$*> $#_RELAY_ $@ $3 $: $>canonify $1 $6 @ $2')') 1446ifdef(`_MAILER_TABLE_', `dnl 1447# check mailertable for host, relay from there 1448R<$+> <$+> <$+> <$+> <$*> $>LDAPMailertable <$2> $>canonify $1', 1449`R<$+> <$+> <$+> <$+> <$*> $#_RELAY_ $@ $2 $: $>canonify $1') 1450 1451# if no mailRoutingAddress and local mailHost, 1452# return original address 1453R<> <$=w> <$+> <$+> <$*> $@ $2 1454 1455 1456# if no mailRoutingAddress and non-local mailHost, 1457# relay to mailHost with original address 1458ifdef(`_MAILER_TABLE_', `dnl 1459# check mailertable for host, relay from there 1460R<> <$+> <$+> <$+> <$*> $>LDAPMailertable <$1> $2', 1461`R<> <$+> <$+> <$+> <$*> $#_RELAY_ $@ $1 $: $2') 1462 1463ifdef(`_LDAP_ROUTE_DETAIL_', 1464`# if no mailRoutingAddress and no mailHost, 1465# try without +detail 1466R<> <> <$+> <$+ + $* @ $+> <> $@ $>LDAPExpand <$1> <$2 @ $4> <+$3>')dnl 1467 1468# if still no mailRoutingAddress and no mailHost, 1469# try @domain 1470ifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl 1471R<> <> <$+> <$+ + $* @ $+> <> $@ $>LDAPExpand <$1> <@ $4> <+$3>') 1472R<> <> <$+> <$+ @ $+> <$*> $@ $>LDAPExpand <$1> <@ $3> <$4> 1473 1474# if no mailRoutingAddress and no mailHost and this was a domain attempt, 1475ifelse(_LDAP_ROUTING_, `_MUST_EXIST_', `dnl 1476# user does not exist 1477R<> <> <$+> <@ $+> <$*> $: <?> < $&{addr_type} > < $1 > 1478# only give error for envelope recipient 1479R<?> <e r> <$+> $#error $@ nouser $: "550 User unknown" 1480R<?> <$*> <$+> $@ $2', 1481`dnl 1482# return the original address 1483R<> <> <$+> <@ $+> <$*> $@ $1')', 1484`dnl') 1485 1486ifelse(substr(confDELIVERY_MODE,0,1), `d', `errprint(`WARNING: Antispam rules not available in deferred delivery mode. 1487')') 1488ifdef(`_ACCESS_TABLE_', `dnl', `divert(-1)') 1489###################################################################### 1490### D: LookUpDomain -- search for domain in access database 1491### 1492### Parameters: 1493### <$1> -- key (domain name) 1494### <$2> -- default (what to return if not found in db) 1495dnl must not be empty 1496### <$3> -- mark (must be <(!|+) single-token>) 1497### ! does lookup only with tag 1498### + does lookup with and without tag 1499### <$4> -- passthru (additional data passed unchanged through) 1500dnl returns: <default> <passthru> 1501dnl <result> <passthru> 1502###################################################################### 1503 1504SD 1505dnl workspace <key> <default> <passthru> <mark> 1506dnl lookup with tag (in front, no delimiter here) 1507dnl 2 3 4 5 1508R<$*> <$+> <$- $-> <$*> $: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5> 1509dnl workspace <result-of-lookup|?> <key> <default> <passthru> <mark> 1510dnl lookup without tag? 1511dnl 1 2 3 4 1512R<?> <$+> <$+> <+ $-> <$*> $: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4> 1513ifdef(`_LOOKUPDOTDOMAIN_', `dnl omit first component: lookup .rest 1514dnl XXX apply this also to IP addresses? 1515dnl currently it works the wrong way round for [1.2.3.4] 1516dnl 1 2 3 4 5 6 1517R<?> <$+.$+> <$+> <$- $-> <$*> $: < $(access $5`'_TAG_DELIM_`'.$2 $: ? $) > <$1.$2> <$3> <$4 $5> <$6> 1518dnl 1 2 3 4 5 1519R<?> <$+.$+> <$+> <+ $-> <$*> $: < $(access .$2 $: ? $) > <$1.$2> <$3> <+ $4> <$5>', `dnl') 1520ifdef(`_ACCESS_SKIP_', `dnl 1521dnl found SKIP: return <default> and <passthru> 1522dnl 1 2 3 4 5 1523R<SKIP> <$+> <$+> <$- $-> <$*> $@ <$2> <$5>', `dnl') 1524dnl not found: IPv4 net (no check is done whether it is an IP number!) 1525dnl 1 2 3 4 5 6 1526R<?> <[$+.$-]> <$+> <$- $-> <$*> $@ $>D <[$1]> <$3> <$4 $5> <$6> 1527ifdef(`NO_NETINET6', `dnl', 1528`dnl not found: IPv6 net 1529dnl (could be merged with previous rule if we have a class containing .:) 1530dnl 1 2 3 4 5 6 1531R<?> <[$+::$-]> <$+> <$- $-> <$*> $: $>D <[$1]> <$3> <$4 $5> <$6> 1532R<?> <[$+:$-]> <$+> <$- $-> <$*> $: $>D <[$1]> <$3> <$4 $5> <$6>') 1533dnl not found, but subdomain: try again 1534dnl 1 2 3 4 5 6 1535R<?> <$+.$+> <$+> <$- $-> <$*> $@ $>D <$2> <$3> <$4 $5> <$6> 1536ifdef(`_FFR_LOOKUPTAG_', `dnl lookup Tag: 1537dnl 1 2 3 4 1538R<?> <$+> <$+> <! $-> <$*> $: < $(access $3`'_TAG_DELIM_ $: ? $) > <$1> <$2> <! $3> <$4>', `dnl') 1539dnl not found, no subdomain: return <default> and <passthru> 1540dnl 1 2 3 4 5 1541R<?> <$+> <$+> <$- $-> <$*> $@ <$2> <$5> 1542ifdef(`_ATMPF_', `dnl tempfail? 1543dnl 2 3 4 5 6 1544R<$* _ATMPF_> <$+> <$+> <$- $-> <$*> $@ <_ATMPF_> <$6>', `dnl') 1545dnl return <result of lookup> and <passthru> 1546dnl 2 3 4 5 6 1547R<$*> <$+> <$+> <$- $-> <$*> $@ <$1> <$6> 1548 1549###################################################################### 1550### A: LookUpAddress -- search for host address in access database 1551### 1552### Parameters: 1553### <$1> -- key (dot quadded host address) 1554### <$2> -- default (what to return if not found in db) 1555dnl must not be empty 1556### <$3> -- mark (must be <(!|+) single-token>) 1557### ! does lookup only with tag 1558### + does lookup with and without tag 1559### <$4> -- passthru (additional data passed through) 1560dnl returns: <default> <passthru> 1561dnl <result> <passthru> 1562###################################################################### 1563 1564SA 1565dnl lookup with tag 1566dnl 2 3 4 5 1567R<$+> <$+> <$- $-> <$*> $: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5> 1568dnl lookup without tag 1569dnl 1 2 3 4 1570R<?> <$+> <$+> <+ $-> <$*> $: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4> 1571dnl workspace <result-of-lookup|?> <key> <default> <mark> <passthru> 1572ifdef(`_ACCESS_SKIP_', `dnl 1573dnl found SKIP: return <default> and <passthru> 1574dnl 1 2 3 4 5 1575R<SKIP> <$+> <$+> <$- $-> <$*> $@ <$2> <$5>', `dnl') 1576ifdef(`NO_NETINET6', `dnl', 1577`dnl no match; IPv6: remove last part 1578dnl 1 2 3 4 5 6 1579R<?> <$+::$-> <$+> <$- $-> <$*> $@ $>A <$1> <$3> <$4 $5> <$6> 1580R<?> <$+:$-> <$+> <$- $-> <$*> $@ $>A <$1> <$3> <$4 $5> <$6>') 1581dnl no match; IPv4: remove last part 1582dnl 1 2 3 4 5 6 1583R<?> <$+.$-> <$+> <$- $-> <$*> $@ $>A <$1> <$3> <$4 $5> <$6> 1584dnl no match: return default 1585dnl 1 2 3 4 5 1586R<?> <$+> <$+> <$- $-> <$*> $@ <$2> <$5> 1587ifdef(`_ATMPF_', `dnl tempfail? 1588dnl 2 3 4 5 6 1589R<$* _ATMPF_> <$+> <$+> <$- $-> <$*> $@ <_ATMPF_> <$6>', `dnl') 1590dnl match: return result 1591dnl 2 3 4 5 6 1592R<$*> <$+> <$+> <$- $-> <$*> $@ <$1> <$6> 1593dnl endif _ACCESS_TABLE_ 1594divert(0) 1595###################################################################### 1596### CanonAddr -- Convert an address into a standard form for 1597### relay checking. Route address syntax is 1598### crudely converted into a %-hack address. 1599### 1600### Parameters: 1601### $1 -- full recipient address 1602### 1603### Returns: 1604### parsed address, not in source route form 1605dnl user%host%host<@domain> 1606dnl host!user<@domain> 1607###################################################################### 1608 1609SCanonAddr 1610R$* $: $>Parse0 $>canonify $1 make domain canonical 1611ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl 1612R< @ $+ > : $* @ $* < @ $1 > : $2 % $3 change @ to % in src route 1613R$* < @ $+ > : $* : $* $3 $1 < @ $2 > : $4 change to % hack. 1614R$* < @ $+ > : $* $3 $1 < @ $2 > 1615dnl') 1616 1617###################################################################### 1618### ParseRecipient -- Strip off hosts in $=R as well as possibly 1619### $* $=m or the access database. 1620### Check user portion for host separators. 1621### 1622### Parameters: 1623### $1 -- full recipient address 1624### 1625### Returns: 1626### parsed, non-local-relaying address 1627###################################################################### 1628 1629SParseRecipient 1630dnl mark and canonify address 1631R$* $: <?> $>CanonAddr $1 1632dnl workspace: <?> localpart<@domain[.]> 1633R<?> $* < @ $* . > <?> $1 < @ $2 > strip trailing dots 1634dnl workspace: <?> localpart<@domain> 1635R<?> $- < @ $* > $: <?> $(dequote $1 $) < @ $2 > dequote local part 1636 1637# if no $=O character, no host in the user portion, we are done 1638R<?> $* $=O $* < @ $* > $: <NO> $1 $2 $3 < @ $4> 1639dnl no $=O in localpart: return 1640R<?> $* $@ $1 1641 1642dnl workspace: <NO> localpart<@domain>, where localpart contains $=O 1643dnl mark everything which has an "authorized" domain with <RELAY> 1644ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 1645# if we relay, check username portion for user%host so host can be checked also 1646R<NO> $* < @ $* $=m > $: <RELAY> $1 < @ $2 $3 >', `dnl') 1647dnl workspace: <(NO|RELAY)> localpart<@domain>, where localpart contains $=O 1648dnl if mark is <NO> then change it to <RELAY> if domain is "authorized" 1649 1650dnl what if access map returns something else than RELAY? 1651dnl we are only interested in RELAY entries... 1652dnl other To: entries: blacklist recipient; generic entries? 1653dnl if it is an error we probably do not want to relay anyway 1654ifdef(`_RELAY_HOSTS_ONLY_', 1655`R<NO> $* < @ $=R > $: <RELAY> $1 < @ $2 > 1656ifdef(`_ACCESS_TABLE_', `dnl 1657R<NO> $* < @ $+ > $: <$(access To:$2 $: NO $)> $1 < @ $2 > 1658R<NO> $* < @ $+ > $: <$(access $2 $: NO $)> $1 < @ $2 >',`dnl')', 1659`R<NO> $* < @ $* $=R > $: <RELAY> $1 < @ $2 $3 > 1660ifdef(`_ACCESS_TABLE_', `dnl 1661R<NO> $* < @ $+ > $: $>D <$2> <NO> <+ To> <$1 < @ $2 >> 1662R<$+> <$+> $: <$1> $2',`dnl')') 1663 1664 1665ifdef(`_RELAY_MX_SERVED_', `dnl 1666dnl do "we" ($=w) act as backup MX server for the destination domain? 1667R<NO> $* < @ $+ > $: <MX> < : $(mxserved $2 $) : > < $1 < @$2 > > 1668R<MX> < : $* <TEMP> : > $* $#TEMP $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1 1669dnl yes: mark it as <RELAY> 1670R<MX> < $* : $=w. : $* > < $+ > $: <RELAY> $4 1671dnl no: put old <NO> mark back 1672R<MX> < : $* : > < $+ > $: <NO> $2', `dnl') 1673 1674dnl do we relay to this recipient domain? 1675R<RELAY> $* < @ $* > $@ $>ParseRecipient $1 1676dnl something else 1677R<$+> $* $@ $2 1678 1679 1680###################################################################### 1681### check_relay -- check hostname/address on SMTP startup 1682###################################################################### 1683 1684SLocal_check_relay 1685Scheck`'_U_`'relay 1686R$* $: $1 $| $>"Local_check_relay" $1 1687R$* $| $* $| $#$* $#$3 1688R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 1689 1690SBasic_check_relay 1691# check for deferred delivery mode 1692R$* $: < $&{deliveryMode} > $1 1693R< d > $* $@ deferred 1694R< $* > $* $: $2 1695 1696ifdef(`_ACCESS_TABLE_', `dnl 1697dnl workspace: {client_name} $| {client_addr} 1698R$+ $| $+ $: $>D < $1 > <?> <+ Connect> < $2 > 1699dnl workspace: <result-of-lookup> <{client_addr}> 1700R<?> <$+> $: $>A < $1 > <?> <+ Connect> <> no: another lookup 1701dnl workspace: <result-of-lookup> (<>|<{client_addr}>) 1702R<?> <$*> $: OK found nothing 1703dnl workspace: <result-of-lookup> (<>|<{client_addr}>) | OK 1704R<$={Accept}> <$*> $@ $1 return value of lookup 1705R<REJECT> <$*> $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"') 1706R<DISCARD> <$*> $#discard $: discard 1707ifdef(`_FFR_QUARANTINE', 1708`R<QUARANTINE:$+> <$*> $#error $@ quarantine $: $1', `dnl') 1709dnl error tag 1710R<ERROR:$-.$-.$-:$+> <$*> $#error $@ $1.$2.$3 $: $4 1711R<ERROR:$+> <$*> $#error $: $1 1712ifdef(`_ATMPF_', `R<$* _ATMPF_> <$*> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 1713dnl generic error from access map 1714R<$+> <$*> $#error $: $1', `dnl') 1715 1716ifdef(`_RBL_',`dnl 1717# DNS based IP address spam list 1718dnl workspace: ignored... 1719R$* $: $&{client_addr} 1720R$-.$-.$-.$- $: <?> $(host $4.$3.$2.$1._RBL_. $: OK $) 1721R<?>OK $: OKSOFAR 1722R<?>$+ $#error $@ 5.7.1 $: "550 Rejected: " $&{client_addr} " listed at _RBL_"', 1723`dnl') 1724undivert(8) 1725 1726###################################################################### 1727### check_mail -- check SMTP ``MAIL FROM:'' command argument 1728###################################################################### 1729 1730SLocal_check_mail 1731Scheck`'_U_`'mail 1732R$* $: $1 $| $>"Local_check_mail" $1 1733R$* $| $#$* $#$2 1734R$* $| $* $@ $>"Basic_check_mail" $1 1735 1736SBasic_check_mail 1737# check for deferred delivery mode 1738R$* $: < $&{deliveryMode} > $1 1739R< d > $* $@ deferred 1740R< $* > $* $: $2 1741 1742# authenticated? 1743dnl done first: we can require authentication for every mail transaction 1744dnl workspace: address as given by MAIL FROM: (sender) 1745R$* $: $1 $| $>"tls_client" $&{verify} $| MAIL 1746R$* $| $#$+ $#$2 1747dnl undo damage: remove result of tls_client call 1748R$* $| $* $: $1 1749 1750dnl workspace: address as given by MAIL FROM: 1751R<> $@ <OK> we MUST accept <> (RFC 1123) 1752ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl 1753dnl do some additional checks 1754dnl no user@host 1755dnl no user@localhost (if nonlocal sender) 1756dnl this is a pretty simple canonification, it will not catch every case 1757dnl just make sure the address has <> around it (which is required by 1758dnl the RFC anyway, maybe we should complain if they are missing...) 1759dnl dirty trick: if it is user@host, just add a dot: user@host. this will 1760dnl not be modified by host lookups. 1761R$+ $: <?> $1 1762R<?><$+> $: <@> <$1> 1763R<?>$+ $: <@> <$1> 1764dnl workspace: <@> <address> 1765dnl prepend daemon_flags 1766R$* $: $&{daemon_flags} $| $1 1767dnl workspace: ${daemon_flags} $| <@> <address> 1768dnl do not allow these at all or only from local systems? 1769R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > 1770dnl accept unqualified sender: change mark to avoid test 1771R$* u $* $| <@> < $* > $: <?> < $3 > 1772dnl workspace: ${daemon_flags} $| <@> <address> 1773dnl or: <? ${client_name} > <address> 1774dnl or: <?> <address> 1775dnl remove daemon_flags 1776R$* $| $* $: $2 1777# handle case of @localhost on address 1778R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > 1779R<@> < $* @ [127.0.0.1] > 1780 $: < ? $&{client_name} > < $1 @ [127.0.0.1] > 1781R<@> < $* @ localhost.$m > 1782 $: < ? $&{client_name} > < $1 @ localhost.$m > 1783ifdef(`_NO_UUCP_', `dnl', 1784`R<@> < $* @ localhost.UUCP > 1785 $: < ? $&{client_name} > < $1 @ localhost.UUCP >') 1786dnl workspace: < ? $&{client_name} > <user@localhost|host> 1787dnl or: <@> <address> 1788dnl or: <?> <address> (thanks to u in ${daemon_flags}) 1789R<@> $* $: $1 no localhost as domain 1790dnl workspace: < ? $&{client_name} > <user@localhost|host> 1791dnl or: <address> 1792dnl or: <?> <address> (thanks to u in ${daemon_flags}) 1793R<? $=w> $* $: $2 local client: ok 1794R<? $+> <$+> $#error $@ 5.5.4 $: "_CODE553 Real domain name required for sender address" 1795dnl remove <?> (happens only if ${client_name} == "" or u in ${daemon_flags}) 1796R<?> $* $: $1') 1797dnl workspace: address (or <address>) 1798R$* $: <?> $>CanonAddr $1 canonify sender address and mark it 1799dnl workspace: <?> CanonicalAddress (i.e. address in canonical form localpart<@host>) 1800dnl there is nothing behind the <@host> so no trailing $* needed 1801R<?> $* < @ $+ . > <?> $1 < @ $2 > strip trailing dots 1802# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) 1803R<?> $* < @ $* $=P > $: <_RES_OK_> $1 < @ $2 $3 > 1804dnl workspace <mark> CanonicalAddress where mark is ? or OK 1805dnl A sender address with my local host name ($j) is safe 1806R<?> $* < @ $j > $: <_RES_OK_> $1 < @ $j > 1807ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_', 1808`R<?> $* < @ $+ > $: <_RES_OK_> $1 < @ $2 > ... unresolvable OK', 1809`R<?> $* < @ $+ > $: <? $(resolve $2 $: $2 <PERM> $) > $1 < @ $2 > 1810R<? $* <$->> $* < @ $+ > 1811 $: <$2> $3 < @ $4 >') 1812dnl workspace <mark> CanonicalAddress where mark is ?, _RES_OK_, PERM, TEMP 1813dnl mark is ? iff the address is user (wo @domain) 1814 1815ifdef(`_ACCESS_TABLE_', `dnl 1816# check sender address: user@address, user@, address 1817dnl should we remove +ext from user? 1818dnl workspace: <mark> CanonicalAddress where mark is: ?, _RES_OK_, PERM, TEMP 1819R<$+> $+ < @ $* > $: @<$1> <$2 < @ $3 >> $| <F:$2@$3> <U:$2@> <D:$3> 1820R<$+> $+ $: @<$1> <$2> $| <U:$2@> 1821dnl workspace: @<mark> <CanonicalAddress> $| <@type:address> .... 1822dnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>> 1823dnl will only return user<@domain when "reversing" the args 1824R@ <$+> <$*> $| <$+> $: <@> <$1> <$2> $| $>SearchList <+ From> $| <$3> <> 1825dnl workspace: <@><mark> <CanonicalAddress> $| <result> 1826R<@> <$+> <$*> $| <$*> $: <$3> <$1> <$2> reverse result 1827dnl workspace: <result> <mark> <CanonicalAddress> 1828# retransform for further use 1829dnl required form: 1830dnl <ResultOfLookup|mark> CanonicalAddress 1831R<?> <$+> <$*> $: <$1> $2 no match 1832R<$+> <$+> <$*> $: <$1> $3 relevant result, keep it', `dnl') 1833dnl workspace <ResultOfLookup|mark> CanonicalAddress 1834dnl mark is ? iff the address is user (wo @domain) 1835 1836ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl 1837# handle case of no @domain on address 1838dnl prepend daemon_flags 1839R<?> $* $: $&{daemon_flags} $| <?> $1 1840dnl accept unqualified sender: change mark to avoid test 1841R$* u $* $| <?> $* $: <_RES_OK_> $3 1842dnl remove daemon_flags 1843R$* $| $* $: $2 1844R<?> $* $: < ? $&{client_name} > $1 1845R<?> $* $@ <_RES_OK_> ...local unqualed ok 1846R<? $+> $* $#error $@ 5.5.4 $: "_CODE553 Domain name required for sender address " $&f 1847 ...remote is not') 1848# check results 1849R<?> $* $: @ $1 mark address: nothing known about it 1850R<$={ResOk}> $* $@ <_RES_OK_> domain ok: stop 1851R<TEMP> $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve" 1852R<PERM> $* $#error $@ 5.1.8 $: "_CODE553 Domain of sender address " $&f " does not exist" 1853ifdef(`_ACCESS_TABLE_', `dnl 1854R<$={Accept}> $* $# $1 accept from access map 1855R<DISCARD> $* $#discard $: discard 1856ifdef(`_FFR_QUARANTINE', 1857`R<QUARANTINE:$+> $* $#error $@ quarantine $: $1', `dnl') 1858R<REJECT> $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"') 1859dnl error tag 1860R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4 1861R<ERROR:$+> $* $#error $: $1 1862ifdef(`_ATMPF_', `R<_ATMPF_> $* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 1863dnl generic error from access map 1864R<$+> $* $#error $: $1 error from access db', 1865`dnl') 1866 1867###################################################################### 1868### check_rcpt -- check SMTP ``RCPT TO:'' command argument 1869###################################################################### 1870 1871SLocal_check_rcpt 1872Scheck`'_U_`'rcpt 1873R$* $: $1 $| $>"Local_check_rcpt" $1 1874R$* $| $#$* $#$2 1875R$* $| $* $@ $>"Basic_check_rcpt" $1 1876 1877SBasic_check_rcpt 1878# empty address? 1879R<> $#error $@ nouser $: "553 User address required" 1880R$@ $#error $@ nouser $: "553 User address required" 1881# check for deferred delivery mode 1882R$* $: < $&{deliveryMode} > $1 1883R< d > $* $@ deferred 1884R< $* > $* $: $2 1885 1886ifdef(`_REQUIRE_QUAL_RCPT_', `dnl 1887dnl this code checks for user@host where host is not a FQHN. 1888dnl it is not activated. 1889dnl notice: code to check for a recipient without a domain name is 1890dnl available down below; look for the same macro. 1891dnl this check is done here because the name might be qualified by the 1892dnl canonicalization. 1893# require fully qualified domain part? 1894dnl very simple canonification: make sure the address is in < > 1895R$+ $: <?> $1 1896R<?> <$+> $: <@> <$1> 1897R<?> $+ $: <@> <$1> 1898R<@> < postmaster > $: postmaster 1899R<@> < $* @ $+ . $+ > $: < $3 @ $4 . $5 > 1900dnl prepend daemon_flags 1901R<@> $* $: $&{daemon_flags} $| <@> $1 1902dnl workspace: ${daemon_flags} $| <@> <address> 1903dnl do not allow these at all or only from local systems? 1904R$* r $* $| <@> < $* @ $* > $: < ? $&{client_name} > < $3 @ $4 > 1905R<?> < $* > $: <$1> 1906R<? $=w> < $* > $: <$1> 1907R<? $+> <$+> $#error $@ 5.5.4 $: "553 Fully qualified domain name required" 1908dnl remove daemon_flags for other cases 1909R$* $| <@> $* $: $2', `dnl') 1910 1911dnl ################################################################## 1912dnl call subroutines for recipient and relay 1913dnl possible returns from subroutines: 1914dnl $#TEMP temporary failure 1915dnl $#error permanent failure (or temporary if from access map) 1916dnl $#other stop processing 1917dnl RELAY RELAYing allowed 1918dnl other otherwise 1919###################################################################### 1920R$* $: $1 $| @ $>"Rcpt_ok" $1 1921dnl temporary failure? remove mark @ and remember 1922R$* $| @ $#TEMP $+ $: $1 $| T $2 1923dnl error or ok (stop) 1924R$* $| @ $#$* $#$2 1925ifdef(`_PROMISCUOUS_RELAY_', `divert(-1)', `dnl') 1926R$* $| @ RELAY $@ RELAY 1927dnl something else: call check sender (relay) 1928R$* $| @ $* $: O $| $>"Relay_ok" $1 1929dnl temporary failure: call check sender (relay) 1930R$* $| T $+ $: T $2 $| $>"Relay_ok" $1 1931dnl temporary failure? return that 1932R$* $| $#TEMP $+ $#error $2 1933dnl error or ok (stop) 1934R$* $| $#$* $#$2 1935R$* $| RELAY $@ RELAY 1936dnl something else: return previous temp failure 1937R T $+ $| $* $#error $1 1938# anything else is bogus 1939R$* $#error $@ 5.7.1 $: confRELAY_MSG 1940divert(0) 1941 1942###################################################################### 1943### Rcpt_ok: is the recipient ok? 1944dnl input: recipient address (RCPT TO) 1945dnl output: see explanation at call 1946###################################################################### 1947SRcpt_ok 1948ifdef(`_LOOSE_RELAY_CHECK_',`dnl 1949R$* $: $>CanonAddr $1 1950R$* < @ $* . > $1 < @ $2 > strip trailing dots', 1951`R$* $: $>ParseRecipient $1 strip relayable hosts') 1952 1953ifdef(`_BESTMX_IS_LOCAL_',`dnl 1954ifelse(_BESTMX_IS_LOCAL_, `', `dnl 1955# unlimited bestmx 1956R$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3', 1957`dnl 1958# limit bestmx to $=B 1959R$* < @ $* $=B > $* $: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4') 1960R$* $=O $* < @ $* @@ $=w . > $* $@ $>"Rcpt_ok" $1 $2 $3 1961R$* < @ $* @@ $=w . > $* $: $1 < @ $3 > $4 1962R$* < @ $* @@ $* > $* $: $1 < @ $2 > $4') 1963 1964ifdef(`_BLACKLIST_RCPT_',`dnl 1965ifdef(`_ACCESS_TABLE_', `dnl 1966# blacklist local users or any host from receiving mail 1967R$* $: <?> $1 1968dnl user is now tagged with @ to be consistent with check_mail 1969dnl and to distinguish users from hosts (com would be host, com@ would be user) 1970R<?> $+ < @ $=w > $: <> <$1 < @ $2 >> $| <F:$1@$2> <U:$1@> <D:$2> 1971R<?> $+ < @ $* > $: <> <$1 < @ $2 >> $| <F:$1@$2> <D:$2> 1972R<?> $+ $: <> <$1> $| <U:$1@> 1973dnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>> 1974dnl will only return user<@domain when "reversing" the args 1975R<> <$*> $| <$+> $: <@> <$1> $| $>SearchList <+ To> $| <$2> <> 1976R<@> <$*> $| <$*> $: <$2> <$1> reverse result 1977R<?> <$*> $: @ $1 mark address as no match 1978dnl we may have to filter here because otherwise some RHSs 1979dnl would be interpreted as generic error messages... 1980dnl error messages should be "tagged" by prefixing them with error: ! 1981dnl that would make a lot of things easier. 1982R<$={Accept}> <$*> $: @ $2 mark address as no match 1983ifdef(`_ACCESS_SKIP_', `dnl 1984R<SKIP> <$*> $: @ $1 mark address as no match', `dnl') 1985ifdef(`_DELAY_COMPAT_8_10_',`dnl 1986dnl compatility with 8.11/8.10: 1987dnl we have to filter these because otherwise they would be interpreted 1988dnl as generic error message... 1989dnl error messages should be "tagged" by prefixing them with error: ! 1990dnl that would make a lot of things easier. 1991dnl maybe we should stop checks already here (if SPAM_xyx)? 1992R<$={SpamTag}> <$*> $: @ $2 mark address as no match') 1993R<REJECT> $* $#error $@ 5.2.1 $: confRCPTREJ_MSG 1994R<DISCARD> $* $#discard $: discard 1995ifdef(`_FFR_QUARANTINE', 1996`R<QUARANTINE:$+> $* $#error $@ quarantine $: $1', `dnl') 1997dnl error tag 1998R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4 1999R<ERROR:$+> $* $#error $: $1 2000ifdef(`_ATMPF_', `R<_ATMPF_> $* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2001dnl generic error from access map 2002R<$+> $* $#error $: $1 error from access db 2003R@ $* $1 remove mark', `dnl')', `dnl') 2004 2005ifdef(`_PROMISCUOUS_RELAY_', `divert(-1)', `dnl') 2006# authenticated via TLS? 2007R$* $: $1 $| $>RelayTLS client authenticated? 2008R$* $| $# $+ $# $2 error/ok? 2009R$* $| $* $: $1 no 2010 2011R$* $: $1 $| $>"Local_Relay_Auth" $&{auth_type} 2012dnl workspace: localpart<@domain> $| result of Local_Relay_Auth 2013R$* $| $# $* $# $2 2014dnl if Local_Relay_Auth returns NO then do not check $={TrustAuthMech} 2015R$* $| NO $: $1 2016R$* $| $* $: $1 $| $&{auth_type} 2017dnl workspace: localpart<@domain> [ $| ${auth_type} ] 2018dnl empty ${auth_type}? 2019R$* $| $: $1 2020dnl mechanism ${auth_type} accepted? 2021dnl use $# to override further tests (delay_checks): see check_rcpt below 2022R$* $| $={TrustAuthMech} $# RELAY 2023dnl remove ${auth_type} 2024R$* $| $* $: $1 2025dnl workspace: localpart<@domain> | localpart 2026ifelse(defn(`_NO_UUCP_'), `r', 2027`R$* ! $* < @ $* > $: <REMOTE> $2 < @ BANG_PATH > 2028R$* ! $* $: <REMOTE> $2 < @ BANG_PATH >', `dnl') 2029# anything terminating locally is ok 2030ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 2031R$+ < @ $* $=m > $@ RELAY', `dnl') 2032R$+ < @ $=w > $@ RELAY 2033ifdef(`_RELAY_HOSTS_ONLY_', 2034`R$+ < @ $=R > $@ RELAY 2035ifdef(`_ACCESS_TABLE_', `dnl 2036R$+ < @ $+ > $: <$(access To:$2 $: ? $)> <$1 < @ $2 >> 2037dnl workspace: <Result-of-lookup | ?> <localpart<@domain>> 2038R<?> <$+ < @ $+ >> $: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')', 2039`R$+ < @ $* $=R > $@ RELAY 2040ifdef(`_ACCESS_TABLE_', `dnl 2041R$+ < @ $+ > $: $>D <$2> <?> <+ To> <$1 < @ $2 >>',`dnl')') 2042ifdef(`_ACCESS_TABLE_', `dnl 2043dnl workspace: <Result-of-lookup | ?> <localpart<@domain>> 2044R<RELAY> $* $@ RELAY 2045ifdef(`_ATMPF_', `R<$* _ATMPF_> $* $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2046R<$*> <$*> $: $2',`dnl') 2047 2048 2049ifdef(`_RELAY_MX_SERVED_', `dnl 2050# allow relaying for hosts which we MX serve 2051R$+ < @ $+ > $: < : $(mxserved $2 $) : > $1 < @ $2 > 2052dnl this must not necessarily happen if the client is checked first... 2053R< : $* <TEMP> : > $* $#TEMP $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1 2054R<$* : $=w . : $*> $* $@ RELAY 2055R< : $* : > $* $: $2', 2056`dnl') 2057 2058# check for local user (i.e. unqualified address) 2059R$* $: <?> $1 2060R<?> $* < @ $+ > $: <REMOTE> $1 < @ $2 > 2061# local user is ok 2062dnl is it really? the standard requires user@domain, not just user 2063dnl but we should accept it anyway (maybe making it an option: 2064dnl RequireFQDN ?) 2065dnl postmaster must be accepted without domain (DRUMS) 2066ifdef(`_REQUIRE_QUAL_RCPT_', `dnl 2067R<?> postmaster $@ OK 2068# require qualified recipient? 2069dnl prepend daemon_flags 2070R<?> $+ $: $&{daemon_flags} $| <?> $1 2071dnl workspace: ${daemon_flags} $| <?> localpart 2072dnl do not allow these at all or only from local systems? 2073dnl r flag? add client_name 2074R$* r $* $| <?> $+ $: < ? $&{client_name} > <?> $3 2075dnl no r flag: relay to local user (only local part) 2076# no qualified recipient required 2077R$* $| <?> $+ $@ RELAY 2078dnl client_name is empty 2079R<?> <?> $+ $@ RELAY 2080dnl client_name is local 2081R<? $=w> <?> $+ $@ RELAY 2082dnl client_name is not local 2083R<? $+> $+ $#error $@ 5.5.4 $: "553 Domain name required"', `dnl 2084dnl no qualified recipient required 2085R<?> $+ $@ RELAY') 2086dnl it is a remote user: remove mark and then check client 2087R<$+> $* $: $2 2088dnl currently the recipient address is not used below 2089 2090###################################################################### 2091### Relay_ok: is the relay/sender ok? 2092dnl input: ignored 2093dnl output: see explanation at call 2094###################################################################### 2095SRelay_ok 2096# anything originating locally is ok 2097# check IP address 2098R$* $: $&{client_addr} 2099R$@ $@ RELAY originated locally 2100R0 $@ RELAY originated locally 2101R$=R $* $@ RELAY relayable IP address 2102ifdef(`_ACCESS_TABLE_', `dnl 2103R$* $: $>A <$1> <?> <+ Connect> <$1> 2104R<RELAY> $* $@ RELAY relayable IP address 2105ifdef(`_FFR_REJECT_IP_IN_CHECK_RCPT_',`dnl 2106dnl this will cause rejections in cases like: 2107dnl Connect:My.Host.Domain RELAY 2108dnl Connect:My.Net REJECT 2109dnl since in check_relay client_name is checked before client_addr 2110R<REJECT> $* $@ REJECT rejected IP address') 2111ifdef(`_ATMPF_', `R<_ATMPF_> $* $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2112R<$*> <$*> $: $2', `dnl') 2113R$* $: [ $1 ] put brackets around it... 2114R$=w $@ RELAY ... and see if it is local 2115 2116ifdef(`_RELAY_DB_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl 2117ifdef(`_RELAY_LOCAL_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl 2118ifdef(`_RELAY_MAIL_FROM_', `dnl 2119dnl input: {client_addr} or something "broken" 2120dnl just throw the input away; we do not need it. 2121# check whether FROM is allowed to use system as relay 2122R$* $: <?> $>CanonAddr $&f 2123R<?> $+ < @ $+ . > <?> $1 < @ $2 > remove trailing dot 2124ifdef(`_RELAY_LOCAL_FROM_', `dnl 2125# check whether local FROM is ok 2126R<?> $+ < @ $=w > $@ RELAY FROM local', `dnl') 2127ifdef(`_RELAY_DB_FROM_', `dnl 2128R<?> $+ < @ $+ > $: <@> $>SearchList <! From> $| <F:$1@$2> ifdef(`_RELAY_DB_FROM_DOMAIN_', ifdef(`_RELAY_HOSTS_ONLY_', `<E:$2>', `<D:$2>')) <> 2129R<@> <RELAY> $@ RELAY RELAY FROM sender ok 2130ifdef(`_ATMPF_', `R<@> <_ATMPF_> $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2131', `dnl 2132ifdef(`_RELAY_DB_FROM_DOMAIN_', 2133`errprint(`*** ERROR: _RELAY_DB_FROM_DOMAIN_ requires _RELAY_DB_FROM_ 2134')', 2135`dnl') 2136dnl')', `dnl') 2137dnl notice: the rulesets above do not leave a unique workspace behind. 2138dnl it does not matter in this case because the following rule ignores 2139dnl the input. otherwise these rules must "clean up" the workspace. 2140 2141# check client name: first: did it resolve? 2142dnl input: ignored 2143R$* $: < $&{client_resolve} > 2144R<TEMP> $#TEMP $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} 2145R<FORGED> $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} 2146R<FAIL> $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} 2147dnl ${client_resolve} should be OK, so go ahead 2148R$* $: <@> $&{client_name} 2149dnl should not be necessary since it has been done for client_addr already 2150R<@> $@ RELAY 2151dnl workspace: <@> ${client_name} (not empty) 2152# pass to name server to make hostname canonical 2153R<@> $* $=P $:<?> $1 $2 2154R<@> $+ $:<?> $[ $1 $] 2155dnl workspace: <?> ${client_name} (canonified) 2156R$* . $1 strip trailing dots 2157ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 2158R<?> $* $=m $@ RELAY', `dnl') 2159R<?> $=w $@ RELAY 2160ifdef(`_RELAY_HOSTS_ONLY_', 2161`R<?> $=R $@ RELAY 2162ifdef(`_ACCESS_TABLE_', `dnl 2163R<?> $* $: <$(access Connect:$1 $: ? $)> <$1> 2164R<?> <$*> $: <$(access $1 $: ? $)> <$1>',`dnl')', 2165`R<?> $* $=R $@ RELAY 2166ifdef(`_ACCESS_TABLE_', `dnl 2167R<?> $* $: $>D <$1> <?> <+ Connect> <$1>',`dnl')') 2168ifdef(`_ACCESS_TABLE_', `dnl 2169R<RELAY> $* $@ RELAY 2170ifdef(`_ATMPF_', `R<$* _ATMPF_> $* $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2171R<$*> <$*> $: $2',`dnl') 2172dnl end of _PROMISCUOUS_RELAY_ 2173divert(0) 2174ifdef(`_DELAY_CHECKS_',`dnl 2175# turn a canonical address in the form user<@domain> 2176# qualify unqual. addresses with $j 2177dnl it might have been only user (without <@domain>) 2178SFullAddr 2179R$* <@ $+ . > $1 <@ $2 > 2180R$* <@ $* > $@ $1 <@ $2 > 2181R$+ $@ $1 <@ $j > 2182 2183# call all necessary rulesets 2184Scheck_rcpt 2185dnl this test should be in the Basic_check_rcpt ruleset 2186dnl which is the correct DSN code? 2187# R$@ $#error $@ 5.1.3 $: "553 Recipient address required" 2188R$+ $: $1 $| $>checkrcpt $1 2189dnl now we can simply stop checks by returning "$# xyz" instead of just "ok" 2190R$+ $| $#$* $#$2 2191R$+ $| $* $: <?> $>FullAddr $>CanonAddr $1 2192ifdef(`_SPAM_FH_', 2193`dnl lookup user@ and user@address 2194ifdef(`_ACCESS_TABLE_', `', 2195`errprint(`*** ERROR: FEATURE(`delay_checks', `argument') requires FEATURE(`access_db') 2196')')dnl 2197dnl one of the next two rules is supposed to match 2198dnl this code has been copied from BLACKLIST... etc 2199dnl and simplified by omitting some < >. 2200R<?> $+ < @ $=w > $: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 > <U: $1@> 2201R<?> $+ < @ $* > $: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 > 2202dnl R<?> $@ something_is_very_wrong_here 2203# lookup the addresses only with Spam tag 2204R<> $* $| <$+> $: <@> $1 $| $>SearchList <! Spam> $| <$2> <> 2205R<@> $* $| $* $: $2 $1 reverse result 2206dnl', `dnl') 2207ifdef(`_SPAM_FRIEND_', 2208`# is the recipient a spam friend? 2209ifdef(`_SPAM_HATER_', 2210 `errprint(`*** ERROR: define either SpamHater or SpamFriend 2211')', `dnl') 2212R<FRIEND> $+ $@ SPAMFRIEND 2213R<$*> $+ $: $2', 2214`dnl') 2215ifdef(`_SPAM_HATER_', 2216`# is the recipient no spam hater? 2217R<HATER> $+ $: $1 spam hater: continue checks 2218R<$*> $+ $@ NOSPAMHATER everyone else: stop 2219dnl',`dnl') 2220dnl run further checks: check_mail 2221dnl should we "clean up" $&f? 2222ifdef(`_FFR_MAIL_MACRO', 2223`R$* $: $1 $| $>checkmail $&{mail_from}', 2224`R$* $: $1 $| $>checkmail <$&f>') 2225dnl recipient (canonical format) $| result of checkmail 2226R$* $| $#$* $#$2 2227dnl run further checks: check_relay 2228R$* $| $* $: $1 $| $>checkrelay $&{client_name} $| $&{client_addr} 2229R$* $| $#$* $#$2 2230R$* $| $* $: $1 2231', `dnl') 2232 2233ifdef(`_ACCESS_TABLE_', `dnl', `divert(-1)') 2234###################################################################### 2235### F: LookUpFull -- search for an entry in access database 2236### 2237### lookup of full key (which should be an address) and 2238### variations if +detail exists: +* and without +detail 2239### 2240### Parameters: 2241### <$1> -- key 2242### <$2> -- default (what to return if not found in db) 2243dnl must not be empty 2244### <$3> -- mark (must be <(!|+) single-token>) 2245### ! does lookup only with tag 2246### + does lookup with and without tag 2247### <$4> -- passthru (additional data passed unchanged through) 2248dnl returns: <default> <passthru> 2249dnl <result> <passthru> 2250###################################################################### 2251 2252SF 2253dnl workspace: <key> <def> <o tag> <thru> 2254dnl full lookup 2255dnl 2 3 4 5 2256R<$+> <$*> <$- $-> <$*> $: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5> 2257dnl no match, try without tag 2258dnl 1 2 3 4 2259R<?> <$+> <$*> <+ $-> <$*> $: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4> 2260dnl no match, +detail: try +* 2261dnl 1 2 3 4 5 6 7 2262R<?> <$+ + $* @ $+> <$*> <$- $-> <$*> 2263 $: <$(access $6`'_TAG_DELIM_`'$1+*@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7> 2264dnl no match, +detail: try +* without tag 2265dnl 1 2 3 4 5 6 2266R<?> <$+ + $* @ $+> <$*> <+ $-> <$*> 2267 $: <$(access $1+*@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6> 2268dnl no match, +detail: try without +detail 2269dnl 1 2 3 4 5 6 7 2270R<?> <$+ + $* @ $+> <$*> <$- $-> <$*> 2271 $: <$(access $6`'_TAG_DELIM_`'$1@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7> 2272dnl no match, +detail: try without +detail and without tag 2273dnl 1 2 3 4 5 6 2274R<?> <$+ + $* @ $+> <$*> <+ $-> <$*> 2275 $: <$(access $1@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6> 2276dnl no match, return <default> <passthru> 2277dnl 1 2 3 4 5 2278R<?> <$+> <$*> <$- $-> <$*> $@ <$2> <$5> 2279ifdef(`_ATMPF_', `dnl tempfail? 2280dnl 2 3 4 5 2281R<$+ _ATMPF_> <$*> <$- $-> <$*> $@ <_ATMPF_> <$5>', `dnl') 2282dnl match, return <match> <passthru> 2283dnl 2 3 4 5 2284R<$+> <$*> <$- $-> <$*> $@ <$1> <$5> 2285 2286###################################################################### 2287### E: LookUpExact -- search for an entry in access database 2288### 2289### Parameters: 2290### <$1> -- key 2291### <$2> -- default (what to return if not found in db) 2292dnl must not be empty 2293### <$3> -- mark (must be <(!|+) single-token>) 2294### ! does lookup only with tag 2295### + does lookup with and without tag 2296### <$4> -- passthru (additional data passed unchanged through) 2297dnl returns: <default> <passthru> 2298dnl <result> <passthru> 2299###################################################################### 2300 2301SE 2302dnl 2 3 4 5 2303R<$*> <$*> <$- $-> <$*> $: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5> 2304dnl no match, try without tag 2305dnl 1 2 3 4 2306R<?> <$+> <$*> <+ $-> <$*> $: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4> 2307dnl no match, return default passthru 2308dnl 1 2 3 4 5 2309R<?> <$+> <$*> <$- $-> <$*> $@ <$2> <$5> 2310ifdef(`_ATMPF_', `dnl tempfail? 2311dnl 2 3 4 5 2312R<$+ _ATMPF_> <$*> <$- $-> <$*> $@ <_ATMPF_> <$5>', `dnl') 2313dnl match, return <match> <passthru> 2314dnl 2 3 4 5 2315R<$+> <$*> <$- $-> <$*> $@ <$1> <$5> 2316 2317###################################################################### 2318### U: LookUpUser -- search for an entry in access database 2319### 2320### lookup of key (which should be a local part) and 2321### variations if +detail exists: +* and without +detail 2322### 2323### Parameters: 2324### <$1> -- key (user@) 2325### <$2> -- default (what to return if not found in db) 2326dnl must not be empty 2327### <$3> -- mark (must be <(!|+) single-token>) 2328### ! does lookup only with tag 2329### + does lookup with and without tag 2330### <$4> -- passthru (additional data passed unchanged through) 2331dnl returns: <default> <passthru> 2332dnl <result> <passthru> 2333###################################################################### 2334 2335SU 2336dnl user lookups are always with trailing @ 2337dnl 2 3 4 5 2338R<$+> <$*> <$- $-> <$*> $: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5> 2339dnl no match, try without tag 2340dnl 1 2 3 4 2341R<?> <$+> <$*> <+ $-> <$*> $: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4> 2342dnl do not remove the @ from the lookup: 2343dnl it is part of the +detail@ which is omitted for the lookup 2344dnl no match, +detail: try +* 2345dnl 1 2 3 4 5 6 2346R<?> <$+ + $* @> <$*> <$- $-> <$*> 2347 $: <$(access $5`'_TAG_DELIM_`'$1+*@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6> 2348dnl no match, +detail: try +* without tag 2349dnl 1 2 3 4 5 2350R<?> <$+ + $* @> <$*> <+ $-> <$*> 2351 $: <$(access $1+*@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5> 2352dnl no match, +detail: try without +detail 2353dnl 1 2 3 4 5 6 2354R<?> <$+ + $* @> <$*> <$- $-> <$*> 2355 $: <$(access $5`'_TAG_DELIM_`'$1@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6> 2356dnl no match, +detail: try without +detail and without tag 2357dnl 1 2 3 4 5 2358R<?> <$+ + $* @> <$*> <+ $-> <$*> 2359 $: <$(access $1@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5> 2360dnl no match, return <default> <passthru> 2361dnl 1 2 3 4 5 2362R<?> <$+> <$*> <$- $-> <$*> $@ <$2> <$5> 2363ifdef(`_ATMPF_', `dnl tempfail? 2364dnl 2 3 4 5 2365R<$+ _ATMPF_> <$*> <$- $-> <$*> $@ <_ATMPF_> <$5>', `dnl') 2366dnl match, return <match> <passthru> 2367dnl 2 3 4 5 2368R<$+> <$*> <$- $-> <$*> $@ <$1> <$5> 2369 2370###################################################################### 2371### SearchList: search a list of items in the access map 2372### Parameters: 2373### <exact tag> $| <mark:address> <mark:address> ... <> 2374dnl maybe we should have a @ (again) in front of the mark to 2375dnl avoid errorneous matches (with error messages?) 2376dnl if we can make sure that tag is always a single token 2377dnl then we can omit the delimiter $|, otherwise we need it 2378dnl to avoid errorneous matchs (first rule: D: if there 2379dnl is that mark somewhere in the list, it will be taken). 2380dnl moreover, we can do some tricks to enforce lookup with 2381dnl the tag only, e.g.: 2382### where "exact" is either "+" or "!": 2383### <+ TAG> lookup with and w/o tag 2384### <! TAG> lookup with tag 2385dnl Warning: + and ! should be in OperatorChars (otherwise there must be 2386dnl a blank between them and the tag. 2387### possible values for "mark" are: 2388### D: recursive host lookup (LookUpDomain) 2389dnl A: recursive address lookup (LookUpAddress) [not yet required] 2390### E: exact lookup, no modifications 2391### F: full lookup, try user+ext@domain and user@domain 2392### U: user lookup, try user+ext and user (input must have trailing @) 2393### return: <RHS of lookup> or <?> (not found) 2394###################################################################### 2395 2396# class with valid marks for SearchList 2397dnl if A is activated: add it 2398C{src}E F D U ifdef(`_FFR_SRCHLIST_A', `A') 2399SSearchList 2400# just call the ruleset with the name of the tag... nice trick... 2401dnl 2 3 4 2402R<$+> $| <$={src}:$*> <$*> $: <$1> $| <$4> $| $>$2 <$3> <?> <$1> <> 2403dnl workspace: <o tag> $| <rest> $| <result of lookup> <> 2404dnl no match and nothing left: return 2405R<$+> $| <> $| <?> <> $@ <?> 2406dnl no match but something left: continue 2407R<$+> $| <$+> $| <?> <> $@ $>SearchList <$1> $| <$2> 2408dnl match: return 2409R<$+> $| <$*> $| <$+> <> $@ <$3> 2410dnl return result from recursive invocation 2411R<$+> $| <$+> $@ <$2> 2412dnl endif _ACCESS_TABLE_ 2413divert(0) 2414 2415###################################################################### 2416### trust_auth: is user trusted to authenticate as someone else? 2417### 2418### Parameters: 2419### $1: AUTH= parameter from MAIL command 2420###################################################################### 2421 2422dnl empty ruleset definition so it can be called 2423SLocal_trust_auth 2424Strust_auth 2425R$* $: $&{auth_type} $| $1 2426# required by RFC 2554 section 4. 2427R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" 2428dnl seems to be useful... 2429R$* $| $&{auth_authen} $@ identical 2430R$* $| <$&{auth_authen}> $@ identical 2431dnl call user supplied code 2432R$* $| $* $: $1 $| $>"Local_trust_auth" $1 2433R$* $| $#$* $#$2 2434dnl default: error 2435R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} 2436 2437###################################################################### 2438### Relay_Auth: allow relaying based on authentication? 2439### 2440### Parameters: 2441### $1: ${auth_type} 2442###################################################################### 2443SLocal_Relay_Auth 2444 2445ifdef(`_ACCESS_TABLE_', `dnl 2446###################################################################### 2447### srv_features: which features to offer to a client? 2448### (done in server) 2449###################################################################### 2450Ssrv_features 2451ifdef(`_LOCAL_SRV_FEATURES_', `dnl 2452R$* $: $1 $| $>"Local_srv_features" $1 2453R$* $| $#$* $#$2 2454R$* $| $* $: $1', `dnl') 2455R$* $: $>D <$&{client_name}> <?> <! SRV_FEAT_TAG> <> 2456R<?>$* $: $>A <$&{client_addr}> <?> <! SRV_FEAT_TAG> <> 2457R<?>$* $: <$(access SRV_FEAT_TAG`'_TAG_DELIM_ $: ? $)> 2458R<?>$* $@ OK 2459ifdef(`_ATMPF_', `dnl tempfail? 2460R<$* _ATMPF_>$* $#temp', `dnl') 2461R<$+>$* $# $1 2462 2463###################################################################### 2464### try_tls: try to use STARTTLS? 2465### (done in client) 2466###################################################################### 2467Stry_tls 2468ifdef(`_LOCAL_TRY_TLS_', `dnl 2469R$* $: $1 $| $>"Local_try_tls" $1 2470R$* $| $#$* $#$2 2471R$* $| $* $: $1', `dnl') 2472R$* $: $>D <$&{server_name}> <?> <! TLS_TRY_TAG> <> 2473R<?>$* $: $>A <$&{server_addr}> <?> <! TLS_TRY_TAG> <> 2474R<?>$* $: <$(access TLS_TRY_TAG`'_TAG_DELIM_ $: ? $)> 2475R<?>$* $@ OK 2476ifdef(`_ATMPF_', `dnl tempfail? 2477R<$* _ATMPF_>$* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2478R<NO>$* $#error $@ 5.7.1 $: "550 do not try TLS with " $&{server_name} " ["$&{server_addr}"]" 2479 2480###################################################################### 2481### tls_rcpt: is connection with server "good" enough? 2482### (done in client, per recipient) 2483dnl called from deliver() before RCPT command 2484### 2485### Parameters: 2486### $1: recipient 2487###################################################################### 2488Stls_rcpt 2489ifdef(`_LOCAL_TLS_RCPT_', `dnl 2490R$* $: $1 $| $>"Local_tls_rcpt" $1 2491R$* $| $#$* $#$2 2492R$* $| $* $: $1', `dnl') 2493dnl store name of other side 2494R$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1 2495dnl canonify recipient address 2496R$+ $: <?> $>CanonAddr $1 2497dnl strip trailing dots 2498R<?> $+ < @ $+ . > <?> $1 <@ $2 > 2499dnl full address? 2500R<?> $+ < @ $+ > $: $1 <@ $2 > $| <F:$1@$2> <U:$1@> <D:$2> <E:> 2501dnl only localpart? 2502R<?> $+ $: $1 $| <U:$1@> <E:> 2503dnl look it up 2504dnl also look up a default value via E: 2505R$* $| $+ $: $1 $| $>SearchList <! TLS_RCPT_TAG> $| $2 <> 2506dnl found nothing: stop here 2507R$* $| <?> $@ OK 2508ifdef(`_ATMPF_', `dnl tempfail? 2509R$* $| <$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2510dnl use the generic routine (for now) 2511R$* $| <$+> $@ $>"TLS_connection" $&{verify} $| <$2>') 2512 2513###################################################################### 2514### tls_client: is connection with client "good" enough? 2515### (done in server) 2516### 2517### Parameters: 2518### ${verify} $| (MAIL|STARTTLS) 2519###################################################################### 2520dnl MAIL: called from check_mail 2521dnl STARTTLS: called from smtp() after STARTTLS has been accepted 2522Stls_client 2523ifdef(`_LOCAL_TLS_CLIENT_', `dnl 2524R$* $: $1 $| $>"Local_tls_client" $1 2525R$* $| $#$* $#$2 2526R$* $| $* $: $1', `dnl') 2527ifdef(`_ACCESS_TABLE_', `dnl 2528dnl store name of other side 2529R$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1 2530dnl ignore second arg for now 2531dnl maybe use it to distinguish permanent/temporary error? 2532dnl if MAIL: permanent (STARTTLS has not been offered) 2533dnl if STARTTLS: temporary (offered but maybe failed) 2534R$* $| $* $: $1 $| $>D <$&{client_name}> <?> <! TLS_CLT_TAG> <> 2535R$* $| <?>$* $: $1 $| $>A <$&{client_addr}> <?> <! TLS_CLT_TAG> <> 2536dnl do a default lookup: just TLS_CLT_TAG 2537R$* $| <?>$* $: $1 $| <$(access TLS_CLT_TAG`'_TAG_DELIM_ $: ? $)> 2538ifdef(`_ATMPF_', `dnl tempfail? 2539R$* $| <$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2540R$* $@ $>"TLS_connection" $1', `dnl 2541R$* $| $* $@ $>"TLS_connection" $1') 2542 2543###################################################################### 2544### tls_server: is connection with server "good" enough? 2545### (done in client) 2546### 2547### Parameter: 2548### ${verify} 2549###################################################################### 2550dnl i.e. has the server been authenticated and is encryption active? 2551dnl called from deliver() after STARTTLS command 2552Stls_server 2553ifdef(`_LOCAL_TLS_SERVER_', `dnl 2554R$* $: $1 $| $>"Local_tls_server" $1 2555R$* $| $#$* $#$2 2556R$* $| $* $: $1', `dnl') 2557ifdef(`_ACCESS_TABLE_', `dnl 2558dnl store name of other side 2559R$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1 2560R$* $: $1 $| $>D <$&{server_name}> <?> <! TLS_SRV_TAG> <> 2561R$* $| <?>$* $: $1 $| $>A <$&{server_addr}> <?> <! TLS_SRV_TAG> <> 2562dnl do a default lookup: just TLS_SRV_TAG 2563R$* $| <?>$* $: $1 $| <$(access TLS_SRV_TAG`'_TAG_DELIM_ $: ? $)> 2564ifdef(`_ATMPF_', `dnl tempfail? 2565R$* $| <$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 2566R$* $@ $>"TLS_connection" $1', `dnl 2567R$* $@ $>"TLS_connection" $1') 2568 2569###################################################################### 2570### TLS_connection: is TLS connection "good" enough? 2571### 2572### Parameters: 2573ifdef(`_ACCESS_TABLE_', `dnl 2574### ${verify} $| <Requirement> [<>]', `dnl 2575### ${verify}') 2576### Requirement: RHS from access map, may be ? for none. 2577dnl syntax for Requirement: 2578dnl [(PERM|TEMP)+] (VERIFY[:bits]|ENCR:bits) [+extensions] 2579dnl extensions: could be a list of further requirements 2580dnl for now: CN:string {cn_subject} == string 2581###################################################################### 2582STLS_connection 2583ifdef(`_ACCESS_TABLE_', `dnl', `dnl use default error 2584dnl deal with TLS handshake failures: abort 2585RSOFTWARE $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake." 2586divert(-1)') 2587dnl common ruleset for tls_{client|server} 2588dnl input: ${verify} $| <ResultOfLookup> [<>] 2589dnl remove optional <> 2590R$* $| <$*>$* $: $1 $| <$2> 2591dnl workspace: ${verify} $| <ResultOfLookup> 2592# create the appropriate error codes 2593dnl permanent or temporary error? 2594R$* $| <PERM + $={tls} $*> $: $1 $| <503:5.7.0> <$2 $3> 2595R$* $| <TEMP + $={tls} $*> $: $1 $| <403:4.7.0> <$2 $3> 2596dnl default case depends on TLS_PERM_ERR 2597R$* $| <$={tls} $*> $: $1 $| <ifdef(`TLS_PERM_ERR', `503:5.7.0', `403:4.7.0')> <$2 $3> 2598dnl workspace: ${verify} $| [<SMTP:ESC>] <ResultOfLookup> 2599# deal with TLS handshake failures: abort 2600RSOFTWARE $| <$-:$+> $* $#error $@ $2 $: $1 " TLS handshake failed." 2601dnl no <reply:dns> i.e. not requirements in the access map 2602dnl use default error 2603RSOFTWARE $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake failed." 2604R$* $| <$*> <VERIFY> $: <$2> <VERIFY> <> $1 2605dnl separate optional requirements 2606R$* $| <$*> <VERIFY + $+> $: <$2> <VERIFY> <$3> $1 2607R$* $| <$*> <$={tls}:$->$* $: <$2> <$3:$4> <> $1 2608dnl separate optional requirements 2609R$* $| <$*> <$={tls}:$- + $+>$* $: <$2> <$3:$4> <$5> $1 2610dnl some other value in access map: accept 2611dnl this also allows to override the default case (if used) 2612R$* $| $* $@ OK 2613# authentication required: give appropriate error 2614# other side did authenticate (via STARTTLS) 2615dnl workspace: <SMTP:ESC> <{VERIFY,ENCR}[:BITS]> <[extensions]> ${verify} 2616dnl only verification required and it succeeded 2617R<$*><VERIFY> <> OK $@ OK 2618dnl verification required and it succeeded but extensions are given 2619dnl change it to <SMTP:ESC> <REQ:0> <extensions> 2620R<$*><VERIFY> <$+> OK $: <$1> <REQ:0> <$2> 2621dnl verification required + some level of encryption 2622R<$*><VERIFY:$-> <$*> OK $: <$1> <REQ:$2> <$3> 2623dnl just some level of encryption required 2624R<$*><ENCR:$-> <$*> $* $: <$1> <REQ:$2> <$3> 2625dnl workspace: 2626dnl 1. <SMTP:ESC> <VERIFY [:bits]> <[extensions]> {verify} (!= OK) 2627dnl 2. <SMTP:ESC> <REQ:bits> <[extensions]> 2628dnl verification required but ${verify} is not set (case 1.) 2629R<$-:$+><VERIFY $*> <$*> $#error $@ $2 $: $1 " authentication required" 2630R<$-:$+><VERIFY $*> <$*> FAIL $#error $@ $2 $: $1 " authentication failed" 2631R<$-:$+><VERIFY $*> <$*> NO $#error $@ $2 $: $1 " not authenticated" 2632R<$-:$+><VERIFY $*> <$*> NOT $#error $@ $2 $: $1 " no authentication requested" 2633R<$-:$+><VERIFY $*> <$*> NONE $#error $@ $2 $: $1 " other side does not support STARTTLS" 2634dnl some other value for ${verify} 2635R<$-:$+><VERIFY $*> <$*> $+ $#error $@ $2 $: $1 " authentication failure " $4 2636dnl some level of encryption required: get the maximum level (case 2.) 2637R<$*><REQ:$-> <$*> $: <$1> <REQ:$2> <$3> $>max $&{cipher_bits} : $&{auth_ssf} 2638dnl compare required bits with actual bits 2639R<$*><REQ:$-> <$*> $- $: <$1> <$2:$4> <$3> $(arith l $@ $4 $@ $2 $) 2640R<$-:$+><$-:$-> <$*> TRUE $#error $@ $2 $: $1 " encryption too weak " $4 " less than " $3 2641dnl strength requirements fulfilled 2642dnl TLS Additional Requirements Separator 2643dnl this should be something which does not appear in the extensions itself 2644dnl @ could be part of a CN, DN, etc... 2645dnl use < > ? those are encoded in CN, DN, ... 2646define(`_TLS_ARS_', `++')dnl 2647dnl workspace: 2648dnl <SMTP:ESC> <REQ:bits> <extensions> result-of-compare 2649R<$-:$+><$-:$-> <$*> $* $: <$1:$2 _TLS_ARS_ $5> 2650dnl workspace: <SMTP:ESC _TLS_ARS_ extensions> 2651dnl continue: check extensions 2652R<$-:$+ _TLS_ARS_ > $@ OK 2653dnl split extensions into own list 2654R<$-:$+ _TLS_ARS_ $+ > $: <$1:$2> <$3> 2655R<$-:$+> < $+ _TLS_ARS_ $+ > <$1:$2> <$3> <$4> 2656R<$-:$+> $+ $@ $>"TLS_req" $3 $| <$1:$2> 2657 2658###################################################################### 2659### TLS_req: check additional TLS requirements 2660### 2661### Parameters: [<list> <of> <req>] $| <$-:$+> 2662### $-: SMTP reply code 2663### $+: Enhanced Status Code 2664dnl further requirements for this ruleset: 2665dnl name of "other side" is stored is {TLS_name} (client/server_name) 2666dnl 2667dnl currently only CN[:common_name] is implemented 2668dnl right now this is only a logical AND 2669dnl i.e. all requirements must be true 2670dnl how about an OR? CN must be X or CN must be Y or .. 2671dnl use a macro to compute this as a trivial sequential 2672dnl operations (no precedences etc)? 2673###################################################################### 2674STLS_req 2675dnl no additional requirements: ok 2676R $| $+ $@ OK 2677dnl require CN: but no CN specified: use name of other side 2678R<CN> $* $| <$+> $: <CN:$&{TLS_Name}> $1 $| <$2> 2679dnl match, check rest 2680R<CN:$&{cn_subject}> $* $| <$+> $@ $>"TLS_req" $1 $| <$2> 2681dnl CN does not match 2682dnl 1 2 3 4 2683R<CN:$+> $* $| <$-:$+> $#error $@ $4 $: $3 " CN " $&{cn_subject} " does not match " $1 2684dnl cert subject 2685R<CS:$&{cert_subject}> $* $| <$+> $@ $>"TLS_req" $1 $| <$2> 2686dnl CS does not match 2687dnl 1 2 3 4 2688R<CS:$+> $* $| <$-:$+> $#error $@ $4 $: $3 " CERT Subject " $&{cert_subject} " does not match " $1 2689dnl match, check rest 2690R<CI:$&{cert_issuer}> $* $| <$+> $@ $>"TLS_req" $1 $| <$2> 2691dnl CI does not match 2692dnl 1 2 3 4 2693R<CI:$+> $* $| <$-:$+> $#error $@ $4 $: $3 " CERT Issuer " $&{cert_issuer} " does not match " $1 2694dnl return from recursive call 2695ROK $@ OK 2696 2697###################################################################### 2698### max: return the maximum of two values separated by : 2699### 2700### Parameters: [$-]:[$-] 2701###################################################################### 2702Smax 2703R: $: 0 2704R:$- $: $1 2705R$-: $: $1 2706R$-:$- $: $(arith l $@ $1 $@ $2 $) : $1 : $2 2707RTRUE:$-:$- $: $2 2708R$-:$-:$- $: $2 2709dnl endif _ACCESS_TABLE_ 2710divert(0) 2711 2712###################################################################### 2713### RelayTLS: allow relaying based on TLS authentication 2714### 2715### Parameters: 2716### none 2717###################################################################### 2718SRelayTLS 2719# authenticated? 2720dnl we do not allow relaying for anyone who can present a cert 2721dnl signed by a "trusted" CA. For example, even if we put verisigns 2722dnl CA in CERTPath so we can authenticate users, we do not allow 2723dnl them to abuse our server (they might be easier to get hold of, 2724dnl but anyway). 2725dnl so here is the trick: if the verification succeeded 2726dnl we look up the cert issuer in the access map 2727dnl (maybe after extracting a part with a regular expression) 2728dnl if this returns RELAY we relay without further questions 2729dnl if it returns SUBJECT we perform a similar check on the 2730dnl cert subject. 2731ifdef(`_ACCESS_TABLE_', `dnl 2732R$* $: <?> $&{verify} 2733R<?> OK $: OK authenticated: continue 2734R<?> $* $@ NO not authenticated 2735ifdef(`_CERT_REGEX_ISSUER_', `dnl 2736R$* $: $(CERTIssuer $&{cert_issuer} $)', 2737`R$* $: $&{cert_issuer}') 2738R$+ $: $(access CERTISSUER`'_TAG_DELIM_`'$1 $) 2739dnl use $# to stop further checks (delay_check) 2740RRELAY $# RELAY 2741ifdef(`_CERT_REGEX_SUBJECT_', `dnl 2742RSUBJECT $: <@> $(CERTSubject $&{cert_subject} $)', 2743`RSUBJECT $: <@> $&{cert_subject}') 2744R<@> $+ $: <@> $(access CERTSUBJECT`'_TAG_DELIM_`'$1 $) 2745R<@> RELAY $# RELAY 2746R$* $: NO', `dnl') 2747 2748###################################################################### 2749### authinfo: lookup authinfo in the access map 2750### 2751### Parameters: 2752### $1: {server_name} 2753### $2: {server_addr} 2754dnl both are currently ignored 2755dnl if it should be done via another map, we either need to restrict 2756dnl functionality (it calls D and A) or copy those rulesets (or add another 2757dnl parameter which I want to avoid, it's quite complex already) 2758###################################################################### 2759dnl omit this ruleset if neither is defined? 2760dnl it causes DefaultAuthInfo to be ignored 2761dnl (which may be considered a good thing). 2762Sauthinfo 2763ifdef(`_AUTHINFO_TABLE_', `dnl 2764R$* $: <$(authinfo AuthInfo:$&{server_name} $: ? $)> 2765R<?> $: <$(authinfo AuthInfo:$&{server_addr} $: ? $)> 2766R<?> $: <$(authinfo AuthInfo: $: ? $)> 2767R<?> $@ no no authinfo available 2768R<$*> $# $1 2769dnl', `dnl 2770ifdef(`_ACCESS_TABLE_', `dnl 2771R$* $: $1 $| $>D <$&{server_name}> <?> <! AuthInfo> <> 2772R$* $| <?>$* $: $1 $| $>A <$&{server_addr}> <?> <! AuthInfo> <> 2773R$* $| <?>$* $: $1 $| <$(access AuthInfo`'_TAG_DELIM_ $: ? $)> <> 2774R$* $| <?>$* $@ no no authinfo available 2775R$* $| <$*> <> $# $2 2776dnl', `dnl')') 2777 2778undivert(9)dnl LOCAL_RULESETS 2779# 2780###################################################################### 2781###################################################################### 2782##### 2783`##### MAIL FILTER DEFINITIONS' 2784##### 2785###################################################################### 2786###################################################################### 2787_MAIL_FILTERS_ 2788# 2789###################################################################### 2790###################################################################### 2791##### 2792`##### MAILER DEFINITIONS' 2793##### 2794###################################################################### 2795###################################################################### 2796undivert(7)dnl MAILER_DEFINITIONS 2797 2798