1divert(-1) 2# 3# Copyright (c) 1998-2000 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.446.2.5.2.41 2001/05/23 21:32:16 ca Exp $') 17 18MAILER(local)dnl 19 20# level CF_LEVEL config file format 21V`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Berkeley') 22divert(-1) 23 24# do some sanity checking 25ifdef(`__OSTYPE__',, 26 `errprint(`*** ERROR: No system type defined (use OSTYPE macro) 27')') 28 29# pick our default mailers 30ifdef(`confSMTP_MAILER',, `define(`confSMTP_MAILER', `esmtp')') 31ifdef(`confLOCAL_MAILER',, `define(`confLOCAL_MAILER', `local')') 32ifdef(`confRELAY_MAILER',, 33 `define(`confRELAY_MAILER', 34 `ifdef(`_MAILER_smtp_', `relay', 35 `ifdef(`_MAILER_uucp', `uucp-new', `unknown')')')') 36ifdef(`confUUCP_MAILER',, `define(`confUUCP_MAILER', `uucp-old')') 37define(`_SMTP_', `confSMTP_MAILER')dnl for readability only 38define(`_LOCAL_', `confLOCAL_MAILER')dnl for readability only 39define(`_RELAY_', `confRELAY_MAILER')dnl for readability only 40define(`_UUCP_', `confUUCP_MAILER')dnl for readability only 41 42# back compatibility with old config files 43ifdef(`confDEF_GROUP_ID', 44`errprint(`*** confDEF_GROUP_ID is obsolete. 45 Use confDEF_USER_ID with a colon in the value instead. 46')') 47ifdef(`confREAD_TIMEOUT', 48`errprint(`*** confREAD_TIMEOUT is obsolete. 49 Use individual confTO_<timeout> parameters instead. 50')') 51ifdef(`confMESSAGE_TIMEOUT', 52 `define(`_ARG_', index(confMESSAGE_TIMEOUT, /)) 53 ifelse(_ARG_, -1, 54 `define(`confTO_QUEUERETURN', confMESSAGE_TIMEOUT)', 55 `define(`confTO_QUEUERETURN', 56 substr(confMESSAGE_TIMEOUT, 0, _ARG_)) 57 define(`confTO_QUEUEWARN', 58 substr(confMESSAGE_TIMEOUT, eval(_ARG_+1)))')') 59ifdef(`confMIN_FREE_BLOCKS', `ifelse(index(confMIN_FREE_BLOCKS, /), -1,, 60`errprint(`*** compound confMIN_FREE_BLOCKS is obsolete. 61 Use confMAX_MESSAGE_SIZE for the second part of the value. 62')')') 63 64 65# Sanity check on ldap_routing feature 66# If the user doesn't specify a new map, they better have given as a 67# default LDAP specification which has the LDAP base (and most likely the host) 68ifdef(`confLDAP_DEFAULT_SPEC',, `ifdef(`_LDAP_ROUTING_WARN_', `errprint(` 69WARNING: Using default FEATURE(ldap_routing) map definition(s) 70without setting confLDAP_DEFAULT_SPEC option. 71')')')dnl 72 73# clean option definitions below.... 74define(`_OPTION', `ifdef(`$2', `O $1`'ifelse(defn(`$2'), `',, `=$2')', `#O $1`'ifelse(`$3', `',,`=$3')')')dnl 75 76dnl required to "rename" the check_* rulesets... 77define(`_U_',ifdef(`_DELAY_CHECKS_',`',`_')) 78dnl default relaying denied message 79ifdef(`confRELAY_MSG', `', `define(`confRELAY_MSG', `"550 Relaying denied"')') 80define(`CODE553', `553') 81divert(0)dnl 82 83# override file safeties - setting this option compromises system security, 84# addressing the actual file configuration problem is preferred 85# need to set this before any file actions are encountered in the cf file 86_OPTION(DontBlameSendmail, `confDONT_BLAME_SENDMAIL', `safe') 87 88# default LDAP map specification 89# need to set this now before any LDAP maps are defined 90_OPTION(LDAPDefaultSpec, `confLDAP_DEFAULT_SPEC', `-h localhost') 91 92################## 93# local info # 94################## 95 96Cwlocalhost 97ifdef(`USE_CW_FILE', 98`# file containing names of hosts for which we receive email 99Fw`'confCW_FILE', 100 `dnl') 101 102# my official domain name 103# ... `define' this only if sendmail cannot automatically determine your domain 104ifdef(`confDOMAIN_NAME', `Dj`'confDOMAIN_NAME', `#Dj$w.Foo.COM') 105 106CP. 107 108ifdef(`UUCP_RELAY', 109`# UUCP relay host 110DY`'UUCP_RELAY 111CPUUCP 112 113')dnl 114ifdef(`BITNET_RELAY', 115`# BITNET relay host 116DB`'BITNET_RELAY 117CPBITNET 118 119')dnl 120ifdef(`DECNET_RELAY', 121`define(`_USE_DECNET_SYNTAX_', 1)dnl 122# DECnet relay host 123DC`'DECNET_RELAY 124CPDECNET 125 126')dnl 127ifdef(`FAX_RELAY', 128`# FAX relay host 129DF`'FAX_RELAY 130CPFAX 131 132')dnl 133# "Smart" relay host (may be null) 134DS`'ifdef(`SMART_HOST', SMART_HOST) 135 136ifdef(`LUSER_RELAY', `dnl 137# place to which unknown users should be forwarded 138Kuser user -m -a<> 139DL`'LUSER_RELAY', 140`dnl') 141 142# operators that cannot be in local usernames (i.e., network indicators) 143CO @ % ifdef(`_NO_UUCP_', `', `!') 144 145# a class with just dot (for identifying canonical names) 146C.. 147 148# a class with just a left bracket (for identifying domain literals) 149C[[ 150 151ifdef(`_ACCESS_TABLE_', `dnl 152# access_db acceptance class 153C{Accept}OK RELAY 154ifdef(`_DELAY_CHECKS_',`dnl 155ifdef(`_BLACKLIST_RCPT_',`dnl 156# possible access_db RHS for spam friends/haters 157C{SpamTag}SPAMFRIEND SPAMHATER')')', 158`dnl') 159 160ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',`dnl',`dnl 161# Resolve map (to check if a host exists in check_mail) 162Kresolve host -a<OK> -T<TEMP>') 163 164ifdef(`_FFR_5_', `# macro storage map 165Kmacro macro') 166 167ifdef(`confCR_FILE', `dnl 168# Hosts for which relaying is permitted ($=R) 169FR`'confCR_FILE', 170`dnl') 171 172define(`TLS_SRV_TAG', `TLS_Srv')dnl 173define(`TLS_CLT_TAG', `TLS_Clt')dnl 174define(`TLS_TRY_TAG', `Try_TLS')dnl 175define(`TLS_OFF_TAG', `Offer_TLS')dnl 176dnl this may be useful in other contexts too 177ifdef(`_ARITH_MAP_', `', `# arithmetic map 178define(`_ARITH_MAP_', `1')dnl 179Karith arith') 180ifdef(`_ACCESS_TABLE_', `dnl 181# possible values for tls_connect in access map 182C{tls}VERIFY ENCR', `dnl') 183ifdef(`_CERT_REGEX_ISSUER_', `dnl 184# extract relevant part from cert issuer 185KCERTIssuer regex _CERT_REGEX_ISSUER_', `dnl') 186ifdef(`_CERT_REGEX_SUBJECT_', `dnl 187# extract relevant part from cert subject 188KCERTSubject regex _CERT_REGEX_SUBJECT_', `dnl') 189 190# who I send unqualified names to (null means deliver locally) 191DR`'ifdef(`LOCAL_RELAY', LOCAL_RELAY) 192 193# who gets all local email traffic ($R has precedence for unqualified names) 194DH`'ifdef(`MAIL_HUB', MAIL_HUB) 195 196# dequoting map 197Kdequote dequote 198 199divert(0)dnl # end of nullclient diversion 200# class E: names that should be exposed as from this host, even if we masquerade 201# class L: names that should be delivered locally, even if we have a relay 202# class M: domains that should be converted to $M 203# class N: domains that should not be converted to $M 204#CL root 205undivert(5)dnl 206ifdef(`_VIRTHOSTS_', `CR$={VirtHost}', `dnl') 207 208# who I masquerade as (null for no masquerading) (see also $=M) 209DM`'ifdef(`MASQUERADE_NAME', MASQUERADE_NAME) 210 211# my name for error messages 212ifdef(`confMAILER_NAME', `Dn`'confMAILER_NAME', `#DnMAILER-DAEMON') 213 214undivert(6)dnl LOCAL_CONFIG 215include(_CF_DIR_`m4/version.m4') 216 217############### 218# Options # 219############### 220 221# strip message body to 7 bits on input? 222_OPTION(SevenBitInput, `confSEVEN_BIT_INPUT', `False') 223 224# 8-bit data handling 225_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `pass8') 226 227# wait for alias file rebuild (default units: minutes) 228_OPTION(AliasWait, `confALIAS_WAIT', `5m') 229 230# location of alias file 231_OPTION(AliasFile, `ALIAS_FILE', `MAIL_SETTINGS_DIR`'aliases') 232 233# minimum number of free blocks on filesystem 234_OPTION(MinFreeBlocks, `confMIN_FREE_BLOCKS', `100') 235 236# maximum message size 237_OPTION(MaxMessageSize, `confMAX_MESSAGE_SIZE', `1000000') 238 239# substitution for space (blank) characters 240_OPTION(BlankSub, `confBLANK_SUB', `_') 241 242# avoid connecting to "expensive" mailers on initial submission? 243_OPTION(HoldExpensive, `confCON_EXPENSIVE', `False') 244 245# checkpoint queue runs after every N successful deliveries 246_OPTION(CheckpointInterval, `confCHECKPOINT_INTERVAL', `10') 247 248# default delivery mode 249_OPTION(DeliveryMode, `confDELIVERY_MODE', `background') 250 251# automatically rebuild the alias database? 252# NOTE: There is a potential for a denial of service attack if this is set. 253# This option is deprecated and will be removed from a future version. 254_OPTION(AutoRebuildAliases, `confAUTO_REBUILD', `False') 255 256# error message header/file 257_OPTION(ErrorHeader, `confERROR_MESSAGE', `MAIL_SETTINGS_DIR`'error-header') 258 259# error mode 260_OPTION(ErrorMode, `confERROR_MODE', `print') 261 262# save Unix-style "From_" lines at top of header? 263_OPTION(SaveFromLine, `confSAVE_FROM_LINES', `False') 264 265# temporary file mode 266_OPTION(TempFileMode, `confTEMP_FILE_MODE', `0600') 267 268# match recipients against GECOS field? 269_OPTION(MatchGECOS, `confMATCH_GECOS', `False') 270 271# maximum hop count 272_OPTION(MaxHopCount, `confMAX_HOP', `17') 273 274# location of help file 275O HelpFile=ifdef(`HELP_FILE', HELP_FILE, `MAIL_SETTINGS_DIR`'helpfile') 276 277# ignore dots as terminators in incoming messages? 278_OPTION(IgnoreDots, `confIGNORE_DOTS', `False') 279 280# name resolver options 281_OPTION(ResolverOptions, `confBIND_OPTS', `+AAONLY') 282 283# deliver MIME-encapsulated error messages? 284_OPTION(SendMimeErrors, `confMIME_FORMAT_ERRORS', `True') 285 286# Forward file search path 287_OPTION(ForwardPath, `confFORWARD_PATH', `/var/forward/$u:$z/.forward.$w:$z/.forward') 288 289# open connection cache size 290_OPTION(ConnectionCacheSize, `confMCI_CACHE_SIZE', `2') 291 292# open connection cache timeout 293_OPTION(ConnectionCacheTimeout, `confMCI_CACHE_TIMEOUT', `5m') 294 295# persistent host status directory 296_OPTION(HostStatusDirectory, `confHOST_STATUS_DIRECTORY', `.hoststat') 297 298# single thread deliveries (requires HostStatusDirectory)? 299_OPTION(SingleThreadDelivery, `confSINGLE_THREAD_DELIVERY', `False') 300 301# use Errors-To: header? 302_OPTION(UseErrorsTo, `confUSE_ERRORS_TO', `False') 303 304# log level 305_OPTION(LogLevel, `confLOG_LEVEL', `10') 306 307# send to me too, even in an alias expansion? 308_OPTION(MeToo, `confME_TOO', `True') 309 310# verify RHS in newaliases? 311_OPTION(CheckAliases, `confCHECK_ALIASES', `False') 312 313# default messages to old style headers if no special punctuation? 314_OPTION(OldStyleHeaders, `confOLD_STYLE_HEADERS', `False') 315 316# SMTP daemon options 317ifelse(defn(`confDAEMON_OPTIONS'), `', `dnl', 318`errprint(WARNING: `confDAEMON_OPTIONS' is no longer valid. See cf/README for more information. 319)'dnl 320`DAEMON_OPTIONS(`confDAEMON_OPTIONS')') 321ifelse(defn(`_DPO_'), `', 322`ifdef(`_NETINET6_', `O DaemonPortOptions=Name=MTA-IPv4, Family=inet 323O DaemonPortOptions=Name=MTA-IPv6, Family=inet6',`O DaemonPortOptions=Name=MTA')', `_DPO_') 324ifdef(`_NO_MSA_', `dnl', `O DaemonPortOptions=Port=587, Name=MSA, M=E') 325 326# SMTP client options 327_OPTION(ClientPortOptions, `confCLIENT_OPTIONS', `Address=0.0.0.0') 328 329# privacy flags 330_OPTION(PrivacyOptions, `confPRIVACY_FLAGS', `authwarnings') 331 332# who (if anyone) should get extra copies of error messages 333_OPTION(PostmasterCopy, `confCOPY_ERRORS_TO', `Postmaster') 334 335# slope of queue-only function 336_OPTION(QueueFactor, `confQUEUE_FACTOR', `600000') 337 338# queue directory 339O QueueDirectory=ifdef(`QUEUE_DIR', QUEUE_DIR, `/var/spool/mqueue') 340 341# timeouts (many of these) 342_OPTION(Timeout.initial, `confTO_INITIAL', `5m') 343_OPTION(Timeout.connect, `confTO_CONNECT', `5m') 344_OPTION(Timeout.iconnect, `confTO_ICONNECT', `5m') 345_OPTION(Timeout.helo, `confTO_HELO', `5m') 346_OPTION(Timeout.mail, `confTO_MAIL', `10m') 347_OPTION(Timeout.rcpt, `confTO_RCPT', `1h') 348_OPTION(Timeout.datainit, `confTO_DATAINIT', `5m') 349_OPTION(Timeout.datablock, `confTO_DATABLOCK', `1h') 350_OPTION(Timeout.datafinal, `confTO_DATAFINAL', `1h') 351_OPTION(Timeout.rset, `confTO_RSET', `5m') 352_OPTION(Timeout.quit, `confTO_QUIT', `2m') 353_OPTION(Timeout.misc, `confTO_MISC', `2m') 354_OPTION(Timeout.command, `confTO_COMMAND', `1h') 355_OPTION(Timeout.ident, `confTO_IDENT', `5s') 356_OPTION(Timeout.fileopen, `confTO_FILEOPEN', `60s') 357_OPTION(Timeout.control, `confTO_CONTROL', `2m') 358_OPTION(Timeout.queuereturn, `confTO_QUEUERETURN', `5d') 359_OPTION(Timeout.queuereturn.normal, `confTO_QUEUERETURN_NORMAL', `5d') 360_OPTION(Timeout.queuereturn.urgent, `confTO_QUEUERETURN_URGENT', `2d') 361_OPTION(Timeout.queuereturn.non-urgent, `confTO_QUEUERETURN_NONURGENT', `7d') 362_OPTION(Timeout.queuewarn, `confTO_QUEUEWARN', `4h') 363_OPTION(Timeout.queuewarn.normal, `confTO_QUEUEWARN_NORMAL', `4h') 364_OPTION(Timeout.queuewarn.urgent, `confTO_QUEUEWARN_URGENT', `1h') 365_OPTION(Timeout.queuewarn.non-urgent, `confTO_QUEUEWARN_NONURGENT', `12h') 366_OPTION(Timeout.hoststatus, `confTO_HOSTSTATUS', `30m') 367_OPTION(Timeout.resolver.retrans, `confTO_RESOLVER_RETRANS', `5s') 368_OPTION(Timeout.resolver.retrans.first, `confTO_RESOLVER_RETRANS_FIRST', `5s') 369_OPTION(Timeout.resolver.retrans.normal, `confTO_RESOLVER_RETRANS_NORMAL', `5s') 370_OPTION(Timeout.resolver.retry, `confTO_RESOLVER_RETRY', `4') 371_OPTION(Timeout.resolver.retry.first, `confTO_RESOLVER_RETRY_FIRST', `4') 372_OPTION(Timeout.resolver.retry.normal, `confTO_RESOLVER_RETRY_NORMAL', `4') 373 374# should we not prune routes in route-addr syntax addresses? 375_OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES', `False') 376 377# queue up everything before forking? 378_OPTION(SuperSafe, `confSAFE_QUEUE', `True') 379 380# status file 381O StatusFile=ifdef(`STATUS_FILE', `STATUS_FILE', `MAIL_SETTINGS_DIR`'statistics') 382 383# time zone handling: 384# if undefined, use system default 385# if defined but null, use TZ envariable passed in 386# if defined and non-null, use that info 387ifelse(confTIME_ZONE, `USE_SYSTEM', `#O TimeZoneSpec=', 388 confTIME_ZONE, `USE_TZ', `O TimeZoneSpec=', 389 `O TimeZoneSpec=confTIME_ZONE') 390 391# default UID (can be username or userid:groupid) 392_OPTION(DefaultUser, `confDEF_USER_ID', `mailnull') 393 394# list of locations of user database file (null means no lookup) 395_OPTION(UserDatabaseSpec, `confUSERDB_SPEC', `MAIL_SETTINGS_DIR`'userdb') 396 397# fallback MX host 398_OPTION(FallbackMXhost, `confFALLBACK_MX', `fall.back.host.net') 399 400# if we are the best MX host for a site, try it directly instead of config err 401_OPTION(TryNullMXList, `confTRY_NULL_MX_LIST', `False') 402 403# load average at which we just queue messages 404_OPTION(QueueLA, `confQUEUE_LA', `8') 405 406# load average at which we refuse connections 407_OPTION(RefuseLA, `confREFUSE_LA', `12') 408 409# maximum number of children we allow at one time 410_OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `12') 411 412# maximum number of new connections per second 413_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `0') 414 415# work recipient factor 416_OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', `30000') 417 418# deliver each queued job in a separate process? 419_OPTION(ForkEachJob, `confSEPARATE_PROC', `False') 420 421# work class factor 422_OPTION(ClassFactor, `confWORK_CLASS_FACTOR', `1800') 423 424# work time factor 425_OPTION(RetryFactor, `confWORK_TIME_FACTOR', `90000') 426 427# shall we sort the queue by hostname first? 428_OPTION(QueueSortOrder, `confQUEUE_SORT_ORDER', `priority') 429 430# minimum time in queue before retry 431_OPTION(MinQueueAge, `confMIN_QUEUE_AGE', `30m') 432 433# default character set 434_OPTION(DefaultCharSet, `confDEF_CHAR_SET', `iso-8859-1') 435 436# service switch file (ignored on Solaris, Ultrix, OSF/1, others) 437_OPTION(ServiceSwitchFile, `confSERVICE_SWITCH_FILE', `MAIL_SETTINGS_DIR`'service.switch') 438 439# hosts file (normally /etc/hosts) 440_OPTION(HostsFile, `confHOSTS_FILE', `/etc/hosts') 441 442# dialup line delay on connection failure 443_OPTION(DialDelay, `confDIAL_DELAY', `10s') 444 445# action to take if there are no recipients in the message 446_OPTION(NoRecipientAction, `confNO_RCPT_ACTION', `add-to-undisclosed') 447 448# chrooted environment for writing to files 449_OPTION(SafeFileEnvironment, `confSAFE_FILE_ENV', `/arch') 450 451# are colons OK in addresses? 452_OPTION(ColonOkInAddr, `confCOLON_OK_IN_ADDR', `True') 453 454# how many jobs can you process in the queue? 455_OPTION(MaxQueueRunSize, `confMAX_QUEUE_RUN_SIZE', `10000') 456 457# shall I avoid expanding CNAMEs (violates protocols)? 458_OPTION(DontExpandCnames, `confDONT_EXPAND_CNAMES', `False') 459 460# SMTP initial login message (old $e macro) 461_OPTION(SmtpGreetingMessage, `confSMTP_LOGIN_MSG', `$j Sendmail $v ready at $b') 462 463# UNIX initial From header format (old $l macro) 464_OPTION(UnixFromLine, `confFROM_LINE', `From $g $d') 465 466# From: lines that have embedded newlines are unwrapped onto one line 467_OPTION(SingleLineFromHeader, `confSINGLE_LINE_FROM_HEADER', `False') 468 469# Allow HELO SMTP command that does not `include' a host name 470_OPTION(AllowBogusHELO, `confALLOW_BOGUS_HELO', `False') 471 472# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) 473_OPTION(MustQuoteChars, `confMUST_QUOTE_CHARS', `.') 474 475# delimiter (operator) characters (old $o macro) 476_OPTION(OperatorChars, `confOPERATORS', `.:@[]') 477 478# shall I avoid calling initgroups(3) because of high NIS costs? 479_OPTION(DontInitGroups, `confDONT_INIT_GROUPS', `False') 480 481# are group-writable `:include:' and .forward files (un)trustworthy? 482_OPTION(UnsafeGroupWrites, `confUNSAFE_GROUP_WRITES', `True') 483 484# where do errors that occur when sending errors get sent? 485_OPTION(DoubleBounceAddress, `confDOUBLE_BOUNCE_ADDRESS', `postmaster') 486 487# where to save bounces if all else fails 488_OPTION(DeadLetterDrop, `confDEAD_LETTER_DROP', `/var/tmp/dead.letter') 489 490# what user id do we assume for the majority of the processing? 491_OPTION(RunAsUser, `confRUN_AS_USER', `sendmail') 492 493# maximum number of recipients per SMTP envelope 494_OPTION(MaxRecipientsPerMessage, `confMAX_RCPTS_PER_MESSAGE', `100') 495 496# shall we get local names from our installed interfaces? 497_OPTION(DontProbeInterfaces, `confDONT_PROBE_INTERFACES', `False') 498 499# Return-Receipt-To: header implies DSN request 500_OPTION(RrtImpliesDsn, `confRRT_IMPLIES_DSN', `False') 501 502# override connection address (for testing) 503_OPTION(ConnectOnlyTo, `confCONNECT_ONLY_TO', `0.0.0.0') 504 505# Trusted user for file ownership and starting the daemon 506_OPTION(TrustedUser, `confTRUSTED_USER', `root') 507 508# Control socket for daemon management 509_OPTION(ControlSocketName, `confCONTROL_SOCKET_NAME', `/var/spool/mqueue/.control') 510 511# Maximum MIME header length to protect MUAs 512_OPTION(MaxMimeHeaderLength, `confMAX_MIME_HEADER_LENGTH', `0/0') 513 514# Maximum length of the sum of all headers 515_OPTION(MaxHeadersLength, `confMAX_HEADERS_LENGTH', `32768') 516 517# Maximum depth of alias recursion 518_OPTION(MaxAliasRecursion, `confMAX_ALIAS_RECURSION', `10') 519 520# location of pid file 521_OPTION(PidFile, `confPID_FILE', `/var/run/sendmail.pid') 522 523# Prefix string for the process title shown on 'ps' listings 524_OPTION(ProcessTitlePrefix, `confPROCESS_TITLE_PREFIX', `prefix') 525 526# Data file (df) memory-buffer file maximum size 527_OPTION(DataFileBufferSize, `confDF_BUFFER_SIZE', `4096') 528 529# Transcript file (xf) memory-buffer file maximum size 530_OPTION(XscriptFileBufferSize, `confXF_BUFFER_SIZE', `4096') 531 532# list of authentication mechanisms 533_OPTION(AuthMechanisms, `confAUTH_MECHANISMS', `GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5') 534 535# default authentication information for outgoing connections 536_OPTION(DefaultAuthInfo, `confDEF_AUTH_INFO', `MAIL_SETTINGS_DIR`'default-auth-info') 537 538# SMTP AUTH flags 539_OPTION(AuthOptions, `confAUTH_OPTIONS', `') 540 541ifdef(`_FFR_MILTER', ` 542# Input mail filters 543_OPTION(InputMailFilters, `confINPUT_MAIL_FILTERS', `') 544 545# Milter options 546_OPTION(Milter.macros.connect, `confMILTER_MACROS_CONNECT', `') 547_OPTION(Milter.macros.helo, `confMILTER_MACROS_HELO', `') 548_OPTION(Milter.macros.envfrom, `confMILTER_MACROS_ENVFROM', `') 549_OPTION(Milter.macros.envrcpt, `confMILTER_MACROS_ENVRCPT', `')') 550 551# CA directory 552_OPTION(CACERTPath, `confCACERT_PATH', `') 553# CA file 554_OPTION(CACERTFile, `confCACERT', `') 555# Server Cert 556_OPTION(ServerCertFile, `confSERVER_CERT', `') 557# Server private key 558_OPTION(ServerKeyFile, `confSERVER_KEY', `') 559# Client Cert 560_OPTION(ClientCertFile, `confCLIENT_CERT', `') 561# Client private key 562_OPTION(ClientKeyFile, `confCLIENT_KEY', `') 563# DHParameters (only required if DSA/DH is used) 564_OPTION(DHParameters, `confDH_PARAMETERS', `') 565# Random data source (required for systems without /dev/urandom under OpenSSL) 566_OPTION(RandFile, `confRAND_FILE', `') 567 568ifdef(`confQUEUE_FILE_MODE', 569`# queue file mode (qf files) 570O QueueFileMode=confQUEUE_FILE_MODE 571') 572 573########################### 574# Message precedences # 575########################### 576 577Pfirst-class=0 578Pspecial-delivery=100 579Plist=-30 580Pbulk=-60 581Pjunk=-100 582 583##################### 584# Trusted users # 585##################### 586 587# this is equivalent to setting class "t" 588ifdef(`_USE_CT_FILE_', `', `#')Ft`'ifdef(`confCT_FILE', confCT_FILE, `MAIL_SETTINGS_DIR`'trusted-users') 589Troot 590Tdaemon 591ifdef(`_NO_UUCP_', `dnl', `Tuucp') 592ifdef(`confTRUSTED_USERS', `T`'confTRUSTED_USERS', `dnl') 593 594######################### 595# Format of headers # 596######################### 597 598ifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `$?x$x <$g>$|$g$.')')dnl 599H?P?Return-Path: <$g> 600HReceived: confRECEIVED_HEADER 601H?D?Resent-Date: $a 602H?D?Date: $a 603H?F?Resent-From: confFROM_HEADER 604H?F?From: confFROM_HEADER 605H?x?Full-Name: $x 606# HPosted-Date: $a 607# H?l?Received-Date: $b 608H?M?Resent-Message-Id: <$t.$i@$j> 609H?M?Message-Id: <$t.$i@$j> 610 611# 612###################################################################### 613###################################################################### 614##### 615##### REWRITING RULES 616##### 617###################################################################### 618###################################################################### 619 620############################################ 621### Ruleset 3 -- Name Canonicalization ### 622############################################ 623Scanonify=3 624 625# handle null input (translate to <@> special case) 626R$@ $@ <@> 627 628# strip group: syntax (not inside angle brackets!) and trailing semicolon 629R$* $: $1 <@> mark addresses 630R$* < $* > $* <@> $: $1 < $2 > $3 unmark <addr> 631R@ $* <@> $: @ $1 unmark @host:... 632R$* :: $* <@> $: $1 :: $2 unmark node::addr 633R:`include': $* <@> $: :`include': $1 unmark :`include':... 634R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr 635R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon 636R$* : $* <@> $: $2 strip colon if marked 637R$* <@> $: $1 unmark 638R$* ; $1 strip trailing semi 639R$* < $+ :; > $* $@ $2 :; <@> catch <list:;> 640R$* < $* ; > $1 < $2 > bogus bracketed semi 641 642# null input now results from list:; syntax 643R$@ $@ :; <@> 644 645# strip angle brackets -- note RFC733 heuristic to get innermost item 646R$* $: < $1 > housekeeping <> 647R$+ < $* > < $2 > strip excess on left 648R< $* > $+ < $1 > strip excess on right 649R<> $@ < @ > MAIL FROM:<> case 650R< $+ > $: $1 remove housekeeping <> 651 652ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl 653# make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later 654R@ $+ , $+ @ $1 : $2 change all "," to ":" 655 656# localize and dispose of route-based addresses 657R@ $+ : $+ $@ $>Canonify2 < @$1 > : $2 handle <route-addr> 658dnl',`dnl 659# strip route address <@a,@b,@c:user@d> -> <user@d> 660R@ $+ , $+ $2 661R@ $+ : $+ $2 662dnl') 663 664# find focus for list syntax 665R $+ : $* ; @ $+ $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax 666R $+ : $* ; $@ $1 : $2; list syntax 667 668# find focus for @ syntax addresses 669R$+ @ $+ $: $1 < @ $2 > focus on domain 670R$+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right 671R$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical 672 673# do some sanity checking 674R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs 675 676ifdef(`_NO_UUCP_', `dnl', 677`# convert old-style addresses to a domain-based address 678R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names 679R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps 680R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains 681') 682ifdef(`_USE_DECNET_SYNTAX_', 683`# convert node::user addresses into a domain-based address 684R$- :: $+ $@ $>Canonify2 $2 < @ $1 .DECNET > resolve DECnet names 685R$- . $- :: $+ $@ $>Canonify2 $3 < @ $1.$2 .DECNET > numeric DECnet addr 686', 687 `dnl') 688# if we have % signs, take the rightmost one 689R$* % $* $1 @ $2 First make them all @s. 690R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. 691R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish 692 693# else we must be a local name 694R$* $@ $>Canonify2 $1 695 696 697################################################ 698### Ruleset 96 -- bottom half of ruleset 3 ### 699################################################ 700 701SCanonify2=96 702 703# handle special cases for local names 704R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all 705R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain 706ifdef(`_NO_UUCP_', `dnl', 707`R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain') 708 709# check for IPv6 domain literal (save quoted form) 710R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr 711R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal 712R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr 713 714# check for IPv4 domain literal 715R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] 716R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal 717R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr 718 719ifdef(`_DOMAIN_TABLE_', `dnl 720# look up domains in the domain table 721R$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3', `dnl') 722 723undivert(2)dnl LOCAL_RULE_3 724 725ifdef(`_BITDOMAIN_TABLE_', `dnl 726# handle BITNET mapping 727R$* < @ $+ .BITNET > $* $: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3', `dnl') 728 729ifdef(`_UUDOMAIN_TABLE_', `dnl 730# handle UUCP mapping 731R$* < @ $+ .UUCP > $* $: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3', `dnl') 732 733ifdef(`_NO_UUCP_', `dnl', 734`ifdef(`UUCP_RELAY', 735`# pass UUCP addresses straight through 736R$* < @ $+ . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', 737`# if really UUCP, handle it immediately 738ifdef(`_CLASS_U_', 739`R$* < @ $=U . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 740ifdef(`_CLASS_V_', 741`R$* < @ $=V . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 742ifdef(`_CLASS_W_', 743`R$* < @ $=W . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 744ifdef(`_CLASS_X_', 745`R$* < @ $=X . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 746ifdef(`_CLASS_Y_', 747`R$* < @ $=Y . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 748 749ifdef(`_NO_CANONIFY_', `dnl', `dnl 750# try UUCP traffic as a local address 751R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 752R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3') 753')') 754# hostnames ending in class P are always canonical 755R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 756dnl apply the next rule only for hostnames not in class P 757dnl this even works for phrases in class P since . is in class P 758dnl which daemon flags are set? 759R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 760dnl the other rules in this section only apply if the hostname 761dnl does not end in class P hence no further checks are done here 762dnl if this ever changes make sure the lookups are "protected" again! 763ifdef(`_NO_CANONIFY_', `dnl 764dnl do not canonify unless: 765dnl domain ends in class {Canonify} (this does not work if the intersection 766dnl with class P is non-empty) 767dnl or {daemon_flags} has c set 768# pass to name server to make hostname canonical if in class {Canonify} 769R$* $| $* < @ $* $={Canonify} > $* $: $2 < @ $[ $3 $4 $] > $5 770# pass to name server to make hostname canonical if requested 771R$* c $* $| $* < @ $* > $* $: $3 < @ $[ $4 $] > $5 772dnl trailing dot? -> do not apply _CANONIFY_HOSTS_ 773R$* $| $* < @ $+ . > $* $: $2 < @ $3 . > $4 774# add a trailing dot to qualified hostnames so other rules will work 775R$* $| $* < @ $+.$+ > $* $: $2 < @ $3.$4 . > $5 776ifdef(`_CANONIFY_HOSTS_', `dnl 777dnl this should only apply to unqualified hostnames 778dnl but if a valid character inside an unqualified hostname is an OperatorChar 779dnl then $- does not work. 780# lookup unqualified hostnames 781R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4', `dnl')', `dnl 782dnl _NO_CANONIFY_ is not set: canonify unless: 783dnl {daemon_flags} contains CC (do not canonify) 784dnl but add a trailing dot to qualified hostnames so other rules will work 785dnl should we do this for every hostname: even unqualified? 786R$* CC $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 787R$* CC $* $| $* $: $3 788# pass to name server to make hostname canonical 789R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4') 790dnl remove {daemon_flags} for other cases 791R$* $| $* $: $2 792 793# local host aliases and pseudo-domains are always canonical 794R$* < @ $=w > $* $: $1 < @ $2 . > $3 795ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 796`R$* < @ $* $=M > $* $: $1 < @ $2 $3 . > $4', 797`R$* < @ $=M > $* $: $1 < @ $2 . > $3') 798ifdef(`_VIRTUSER_TABLE_', `dnl 799dnl virtual hosts are also canonical 800ifdef(`_VIRTUSER_ENTIRE_DOMAIN_', 801`R$* < @ $* $={VirtHost} > $* $: $1 < @ $2 $3 . > $4', 802`R$* < @ $={VirtHost} > $* $: $1 < @ $2 . > $3')', 803`dnl') 804dnl remove superfluous dots (maybe repeatedly) which may have been added 805dnl by one of the rules before 806R$* < @ $* . . > $* $1 < @ $2 . > $3 807 808 809################################################## 810### Ruleset 4 -- Final Output Post-rewriting ### 811################################################## 812Sfinal=4 813 814R$+ :; <@> $@ $1 : handle <list:;> 815R$* <@> $@ handle <> and list:; 816 817# strip trailing dot off possibly canonical name 818R$* < @ $+ . > $* $1 < @ $2 > $3 819 820# eliminate internal code 821R$* < @ *LOCAL* > $* $1 < @ $j > $2 822 823# externalize local domain info 824R$* < $+ > $* $1 $2 $3 defocus 825R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 <route-addr> canonical 826R@ $* $@ @ $1 ... and exit 827 828ifdef(`_NO_UUCP_', `dnl', 829`# UUCP must always be presented in old form 830R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u') 831 832ifdef(`_USE_DECNET_SYNTAX_', 833`# put DECnet back in :: form 834R$+ @ $+ . DECNET $2 :: $1 u@h.DECNET => h::u', 835 `dnl') 836# delete duplicate local names 837R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host 838 839 840 841############################################################## 842### Ruleset 97 -- recanonicalize and call ruleset zero ### 843### (used for recursive calls) ### 844############################################################## 845 846SRecurse=97 847R$* $: $>canonify $1 848R$* $@ $>parse $1 849 850 851###################################### 852### Ruleset 0 -- Parse Address ### 853###################################### 854 855Sparse=0 856 857R$* $: $>Parse0 $1 initial parsing 858R<@> $#_LOCAL_ $: <@> special case error msgs 859R$* $: $>ParseLocal $1 handle local hacks 860R$* $: $>Parse1 $1 final parsing 861 862# 863# Parse0 -- do initial syntax checking and eliminate local addresses. 864# This should either return with the (possibly modified) input 865# or return with a #error mailer. It should not return with a 866# #mailer other than the #error mailer. 867# 868 869SParse0 870R<@> $@ <@> special case error msgs 871R$* : $* ; <@> $#error $@ 5.1.3 $: "CODE553 List:; syntax illegal for recipient addresses" 872R@ <@ $* > < @ $1 > catch "@@host" bogosity 873R<@ $+> $#error $@ 5.1.3 $: "CODE553 User address required" 874R$* $: <> $1 875R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 876R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "CODE553 Colon illegal in host name part" 877R<> $* $1 878R$* < @ . $* > $* $#error $@ 5.1.2 $: "CODE553 Invalid host name" 879R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "CODE553 Invalid host name" 880dnl comma only allowed before @; this check is not complete 881R$* , $~O $* $#error $@ 5.1.2 $: "CODE553 Invalid route address" 882 883# now delete the local info -- note $=O to find characters that cause forwarding 884R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user 885R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... 886R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here 887R< @ $+ > $#error $@ 5.1.3 $: "CODE553 User address required" 888R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... 889R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" 890R< @ *LOCAL* > $#error $@ 5.1.3 $: "CODE553 User address required" 891R$* $=O $* < @ *LOCAL* > 892 $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... 893R$* < @ *LOCAL* > $: $1 894 895# 896# Parse1 -- the bottom half of ruleset 0. 897# 898 899SParse1 900ifdef(`_LDAP_ROUTING_', `dnl 901# handle LDAP routing for hosts in $={LDAPRoute} 902R$+ < @ $={LDAPRoute} . > $: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $2>', 903`dnl') 904 905ifdef(`_MAILER_smtp_', 906`# handle numeric address spec 907dnl there is no check whether this is really an IP number 908R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec 909R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path 910R$* < @ [ IPv6 $- ] : > $* 911 $#_SMTP_ $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send 912R$* < @ [ $+ ] : > $* $#_SMTP_ $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send 913R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer 914R$* < @ [ $+ ] : $+ > $* $#_SMTP_ $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer', 915 `dnl') 916 917ifdef(`_VIRTUSER_TABLE_', `dnl 918# handle virtual users 919R$+ $: <!> $1 Mark for lookup 920ifdef(`_VIRTUSER_ENTIRE_DOMAIN_', 921`R<!> $+ < @ $* $={VirtHost} . > $: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >', 922`R<!> $+ < @ $={VirtHost} . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >') 923R<!> $+ < @ $=w . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . > 924R<@> $+ + $* < @ $* . > 925 $: < $(virtuser $1 + * @ $3 $@ $1 $@ $2 $: @ $) > $1 + $2 < @ $3 . > 926R<@> $+ + $* < @ $* . > 927 $: < $(virtuser $1 @ $3 $@ $1 $: @ $) > $1 + $2 < @ $3 . > 928dnl try default entry: @domain 929dnl +*@domain 930R<@> $+ + $+ < @ $+ . > $: < $(virtuser + * @ $3 $@ $1 $@ $2 $: @ $) > $1 + $2 < @ $3 . > 931dnl @domain if +detail exists 932R<@> $+ + $* < @ $+ . > $: < $(virtuser @ $3 $@ $1 $@ $2 $: @ $) > $1 + $2 < @ $3 . > 933dnl without +detail (or no match) 934R<@> $+ < @ $+ . > $: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . > 935R<@> $+ $: $1 936R<!> $+ $: $1 937R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 938R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 939ifdef(`_NO_VIRTUSER_RECURSION_', 940`R< $+ > $+ < @ $+ > $: $>ParseLocal $>Parse0 $>canonify $1', 941`R< $+ > $+ < @ $+ > $: $>Recurse $1') 942dnl', `dnl') 943 944# short circuit local delivery so forwarded email works 945ifdef(`_MAILER_usenet_', `dnl 946R$+ . USENET < @ $=w . > $#usenet $@ usenet $: $1 handle usenet specially', `dnl') 947 948 949ifdef(`_STICKY_LOCAL_DOMAIN_', 950`R$+ < @ $=w . > $: < $H > $1 < @ $2 . > first try hub 951R< $+ > $+ < $+ > $>MailerToTriple < $1 > $2 < $3 > yep .... 952dnl $H empty (but @$=w.) 953R< > $+ + $* < $+ > $#_LOCAL_ $: $1 + $2 plussed name? 954R< > $+ < $+ > $#_LOCAL_ $: @ $1 nope, local address', 955`R$=L < @ $=w . > $#_LOCAL_ $: @ $1 special local names 956R$+ < @ $=w . > $#_LOCAL_ $: $1 regular local name') 957 958ifdef(`_MAILER_TABLE_', `dnl 959# not local -- try mailer table lookup 960R$* <@ $+ > $* $: < $2 > $1 < @ $2 > $3 extract host name 961R< $+ . > $* $: < $1 > $2 strip trailing dot 962R< $+ > $* $: < $(mailertable $1 $) > $2 lookup 963dnl it is $~[ instead of $- to avoid matches on IPv6 addresses 964R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check -- resolved? 965R< $+ > $* $: $>Mailertable <$1> $2 try domain', 966`dnl') 967undivert(4)dnl UUCP rules from `MAILER(uucp)' 968 969ifdef(`_NO_UUCP_', `dnl', 970`# resolve remotely connected UUCP links (if any) 971ifdef(`_CLASS_V_', 972`R$* < @ $=V . UUCP . > $* $: $>MailerToTriple < $V > $1 <@$2.UUCP.> $3', 973 `dnl') 974ifdef(`_CLASS_W_', 975`R$* < @ $=W . UUCP . > $* $: $>MailerToTriple < $W > $1 <@$2.UUCP.> $3', 976 `dnl') 977ifdef(`_CLASS_X_', 978`R$* < @ $=X . UUCP . > $* $: $>MailerToTriple < $X > $1 <@$2.UUCP.> $3', 979 `dnl')') 980 981# resolve fake top level domains by forwarding to other hosts 982ifdef(`BITNET_RELAY', 983`R$*<@$+.BITNET.>$* $: $>MailerToTriple < $B > $1 <@$2.BITNET.> $3 user@host.BITNET', 984 `dnl') 985ifdef(`DECNET_RELAY', 986`R$*<@$+.DECNET.>$* $: $>MailerToTriple < $C > $1 <@$2.DECNET.> $3 user@host.DECNET', 987 `dnl') 988ifdef(`_MAILER_pop_', 989`R$+ < @ POP. > $#pop $: $1 user@POP', 990 `dnl') 991ifdef(`_MAILER_fax_', 992`R$+ < @ $+ .FAX. > $#fax $@ $2 $: $1 user@host.FAX', 993`ifdef(`FAX_RELAY', 994`R$*<@$+.FAX.>$* $: $>MailerToTriple < $F > $1 <@$2.FAX.> $3 user@host.FAX', 995 `dnl')') 996 997ifdef(`UUCP_RELAY', 998`# forward non-local UUCP traffic to our UUCP relay 999R$*<@$*.UUCP.>$* $: $>MailerToTriple < $Y > $1 <@$2.UUCP.> $3 uucp mail', 1000`ifdef(`_MAILER_uucp_', 1001`# forward other UUCP traffic straight to UUCP 1002R$* < @ $+ .UUCP. > $* $#_UUCP_ $@ $2 $: $1 < @ $2 .UUCP. > $3 user@host.UUCP', 1003 `dnl')') 1004ifdef(`_MAILER_usenet_', ` 1005# addresses sent to net.group.USENET will get forwarded to a newsgroup 1006R$+ . USENET $#usenet $@ usenet $: $1', 1007 `dnl') 1008 1009ifdef(`_LOCAL_RULES_', 1010`# figure out what should stay in our local mail system 1011undivert(1)', `dnl') 1012 1013# pass names that still have a host to a smarthost (if defined) 1014R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name 1015 1016# deal with other remote names 1017ifdef(`_MAILER_smtp_', 1018`R$* < @$* > $* $#_SMTP_ $@ $2 $: $1 < @ $2 > $3 user@host.domain', 1019`R$* < @$* > $* $#error $@ 5.1.2 $: "CODE553 Unrecognized host name " $2') 1020 1021# handle locally delivered names 1022R$=L $#_LOCAL_ $: @ $1 special local names 1023R$+ $#_LOCAL_ $: $1 regular local names 1024 1025########################################################################### 1026### Ruleset 5 -- special rewriting after aliases have been expanded ### 1027########################################################################### 1028 1029SLocal_localaddr 1030Slocaladdr=5 1031R$+ $: $1 $| $>"Local_localaddr" $1 1032R$+ $| $#$* $#$2 1033R$+ $| $* $: $1 1034 1035ifdef(`_FFR_5_', ` 1036# Preserve host in a macro 1037R$+ $: $(macro {LocalAddrHost} $) $1 1038R$+ @ $+ $: $(macro {LocalAddrHost} $@ @ $2 $) $1') 1039 1040ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `', ` 1041# deal with plussed users so aliases work nicely 1042R$+ + * $#_LOCAL_ $@ $&h $: $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') 1043R$+ + $* $#_LOCAL_ $@ + $2 $: $1 + *`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') 1044') 1045# prepend an empty "forward host" on the front 1046R$+ $: <> $1 1047 1048ifdef(`LUSER_RELAY', `dnl 1049# send unrecognized local users to a relay host 1050ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', ` 1051R< > $+ + $* $: < ? $L > <+ $2> $(user $1 $) look up user+ 1052R< > $+ $: < ? $L > < > $(user $1 $) look up user 1053R< ? $* > < $* > $+ <> $: < > $3 $2 found; strip $L 1054R< ? $* > < $* > $+ $: < $1 > $3 $2 not found', ` 1055R< > $+ $: < $L > $(user $1 $) look up user 1056R< $* > $+ <> $: < > $2 found; strip $L')', 1057`dnl') 1058 1059# see if we have a relay or a hub 1060R< > $+ $: < $H > $1 try hub 1061R< > $+ $: < $R > $1 try relay 1062ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', ` 1063R< > $+ $@ $1', ` 1064R< > $+ $: < > < $1 <> $&h > nope, restore +detail 1065R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail 1066R< > < $+ <> $* > $: < > < $1 > else discard 1067R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part 1068R< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') strip the extra + 1069R< > < $+ > $@ $1 no +detail 1070R$+ $: $1 <> $&h add +detail back in 1071R$+ <> + $* $: $1 + $2 check whether +detail 1072R$+ <> $* $: $1 else discard') 1073R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension 1074R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension 1075R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > 1076R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > 1077 1078ifdef(`_MAILER_TABLE_', `dnl 1079################################################################### 1080### Ruleset 90 -- try domain part of mailertable entry ### 1081dnl input: LeftPartOfDomain <RightPartOfDomain> FullAddress 1082################################################################### 1083 1084SMailertable=90 1085dnl shift and check 1086dnl %2 is not documented in cf/README 1087R$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4 1088dnl it is $~[ instead of $- to avoid matches on IPv6 addresses 1089R$* <$~[ : $* > $* $>MailerToTriple < $2 : $3 > $4 check -- resolved? 1090R$* < . $+ > $* $@ $>Mailertable $1 . <$2> $3 no -- strip & try again 1091dnl is $2 always empty? 1092R$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "." 1093R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 "." found? 1094dnl return full address 1095R< $* > $* $@ $2 no mailertable match', 1096`dnl') 1097 1098################################################################### 1099### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### 1100dnl input: in general: <[mailer:]host> lp<@domain>rest 1101dnl <> address -> address 1102dnl <error:d.s.n:text> -> error 1103dnl <error:text> -> error 1104dnl <mailer:user@host> lp<@domain>rest -> mailer host user 1105dnl <mailer:host> address -> mailer host address 1106dnl <localdomain> address -> address 1107dnl <[IPv6 number]> address -> relay number address 1108dnl <host> address -> relay host address 1109################################################################### 1110 1111SMailerToTriple=95 1112R< > $* $@ $1 strip off null relay 1113R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 1114R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 1115R< local : $* > $* $>CanonLocal < $1 > $2 1116R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user 1117R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer 1118R< $=w > $* $@ $2 delete local host 1119R< [ IPv6 $+ ] > $* $#_RELAY_ $@ $(dequote $1 $) $: $2 use unqualified mailer 1120R< $+ > $* $#_RELAY_ $@ $1 $: $2 use unqualified mailer 1121 1122################################################################### 1123### Ruleset CanonLocal -- canonify local: syntax ### 1124dnl input: <user> address 1125dnl <x> <@host> : rest -> Recurse rest 1126dnl <x> p1 $=O p2 <@host> -> Recurse p1 $=O p2 1127dnl <> user <@host> rest -> local user@host user 1128dnl <> user -> local user user 1129dnl <user@host> lp <@domain> rest -> <user> lp <@host> [cont] 1130dnl <user> lp <@host> rest -> local lp@host user 1131dnl <user> lp -> local lp user 1132################################################################### 1133 1134SCanonLocal 1135# strip local host from routed addresses 1136R< $* > < @ $+ > : $+ $@ $>Recurse $3 1137R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 1138 1139# strip trailing dot from any host name that may appear 1140R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > 1141 1142# handle local: syntax -- use old user, either with or without host 1143R< > $* < @ $* > $* $#_LOCAL_ $@ $1@$2 $: $1 1144R< > $+ $#_LOCAL_ $@ $1 $: $1 1145 1146# handle local:user@host syntax -- ignore host part 1147R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > 1148 1149# handle local:user syntax 1150R< $+ > $* <@ $* > $* $#_LOCAL_ $@ $2@$3 $: $1 1151R< $+ > $* $#_LOCAL_ $@ $2 $: $1 1152 1153################################################################### 1154### Ruleset 93 -- convert header names to masqueraded form ### 1155################################################################### 1156 1157SMasqHdr=93 1158 1159ifdef(`_GENERICS_TABLE_', `dnl 1160# handle generics database 1161ifdef(`_GENERICS_ENTIRE_DOMAIN_', 1162dnl if generics should be applied add a @ as mark 1163`R$+ < @ $* $=G . > $: < $1@$2$3 > $1 < @ $2$3 . > @ mark', 1164`R$+ < @ $=G . > $: < $1@$2 > $1 < @ $2 . > @ mark') 1165R$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark 1166dnl workspace: either user<@domain> or <user@domain> user <@domain> @ 1167dnl ignore the first case for now 1168dnl if it has the mark lookup full address 1169R< $+ > $+ < $* > @ $: < $(generics $1 $: @ $1 $) > $2 < $3 > 1170dnl workspace: ... or <match|@user@domain> user <@domain> 1171dnl no match, try user+detail@domain 1172R<@$+ + $* @ $+> $+ < @ $+ > 1173 $: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) > $4 < @ $5 > 1174R<@$+ + $* @ $+> $+ < @ $+ > 1175 $: < $(generics $1@$3 $: $) > $4 < @ $5 > 1176dnl no match, remove mark 1177R<@$+ > $+ < @ $+ > $: < > $2 < @ $3 > 1178dnl no match, try @domain for exceptions 1179R< > $+ < @ $+ . > $: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . > 1180dnl workspace: ... or <match> user <@domain> 1181dnl no match, try local part 1182R< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 > 1183R< > $+ + $* < @ $+ > $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 > 1184R< > $+ + $* < @ $+ > $: < $(generics $1 $: $) > $1 + $2 < @ $3 > 1185R< $* @ $* > $* < $* > $@ $>canonify $1 @ $2 found qualified 1186R< $+ > $* < $* > $: $>canonify $1 @ *LOCAL* found unqualified 1187R< > $* $: $1 not found', 1188`dnl') 1189 1190# do not masquerade anything in class N 1191R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > 1192 1193# special case the users that should be exposed 1194R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed 1195ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 1196`R$=E < @ $* $=M . > $@ $1 < @ $2 $3 . >', 1197`R$=E < @ $=M . > $@ $1 < @ $2 . >') 1198ifdef(`_LIMITED_MASQUERADE_', `dnl', 1199`R$=E < @ $=w . > $@ $1 < @ $2 . >') 1200 1201# handle domain-specific masquerading 1202ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 1203`R$* < @ $* $=M . > $* $: $1 < @ $2 $3 . @ $M > $4 convert masqueraded doms', 1204`R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms') 1205ifdef(`_LIMITED_MASQUERADE_', `dnl', 1206`R$* < @ $=w . > $* $: $1 < @ $2 . @ $M > $3') 1207R$* < @ *LOCAL* > $* $: $1 < @ $j . @ $M > $2 1208R$* < @ $+ @ > $* $: $1 < @ $2 > $3 $M is null 1209R$* < @ $+ @ $+ > $* $: $1 < @ $3 . > $4 $M is not null 1210 1211################################################################### 1212### Ruleset 94 -- convert envelope names to masqueraded form ### 1213################################################################### 1214 1215SMasqEnv=94 1216ifdef(`_MASQUERADE_ENVELOPE_', 1217`R$+ $@ $>MasqHdr $1', 1218`R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2') 1219 1220################################################################### 1221### Ruleset 98 -- local part of ruleset zero (can be null) ### 1222################################################################### 1223 1224SParseLocal=98 1225undivert(3)dnl LOCAL_RULE_0 1226 1227ifdef(`_LDAP_ROUTING_', `dnl 1228SLDAPExpand 1229# do the LDAP lookups 1230R<$+><$+> $: <$(ldapmra $2 $: $)> <$(ldapmh $2 $: $)> <$1> <$2> 1231 1232# if mailRoutingAddress and local or non-existant mailHost, 1233# return the new mailRoutingAddress 1234R< $+ > < $=w > < $+ > < $+ > $@ $>Parse0 $>canonify $1 1235R< $+ > < > < $+ > < $+ > $@ $>Parse0 $>canonify $1 1236 1237# if mailRoutingAddress and non-local mailHost, 1238# relay to mailHost with new mailRoutingAddress 1239R< $+ > < $+ > < $+ > < $+ > $#_RELAY_ $@ $2 $: $>canonify $1 1240 1241# if no mailRoutingAddress and local mailHost, 1242# return original address 1243R< > < $=w > <$+> <$+> $@ $2 1244 1245# if no mailRoutingAddress and non-local mailHost, 1246# relay to mailHost with original address 1247R< > < $+ > <$+> <$+> $#_RELAY_ $@ $1 $: $2 1248 1249# if no mailRoutingAddress and no mailHost, 1250# try @domain 1251R< > < > <$+> <$+ @ $+> $@ $>LDAPExpand <$1> <@ $3> 1252 1253# if no mailRoutingAddress and no mailHost and this was a domain attempt, 1254ifelse(_LDAP_ROUTING_, `_MUST_EXIST_', `dnl 1255# user does not exist 1256R< > < > <$+> <@ $+> $#error $@ nouser $: "550 User unknown"', 1257`dnl 1258# return the original address 1259R< > < > <$+> <@ $+> $@ $1')', 1260`dnl') 1261 1262ifelse(substr(confDELIVERY_MODE,0,1), `d', `errprint(`WARNING: Antispam rules not available in deferred delivery mode. 1263')') 1264ifdef(`_ACCESS_TABLE_', `dnl 1265###################################################################### 1266### LookUpDomain -- search for domain in access database 1267### 1268### Parameters: 1269### <$1> -- key (domain name) 1270### <$2> -- default (what to return if not found in db) 1271dnl must not be empty 1272### <$3> -- passthru (additional data passed unchanged through) 1273### <$4> -- mark (must be <(!|+) single-token>) 1274### ! does lookup only with tag 1275### + does lookup with and without tag 1276dnl returns: <default> <passthru> 1277dnl <result> <passthru> 1278###################################################################### 1279 1280SLookUpDomain 1281dnl remove IPv6 mark and dequote address 1282dnl it is a bit ugly because it is checked on each "iteration" 1283R<[IPv6 $-]> <$+> <$*> <$*> $: <[$(dequote $1 $)]> <$2> <$3> <$4> 1284dnl workspace <key> <default> <passthru> <mark> 1285dnl lookup with tag (in front, no delimiter here) 1286R<$*> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3> <$4 $5> 1287dnl workspace <result-of-lookup|?> <key> <default> <passthru> <mark> 1288ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest 1289R<?> <$+.$+> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'.$2 $: ? $) > <$1.$2> <$3> <$4> <$5 $6>', `dnl') 1290dnl lookup without tag? 1291R<?> <$+> <$+> <$*> <+ $*> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4> 1292ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest 1293R<?> <$+.$+> <$+> <$*> <+ $*> $: < $(access .$2 $: ? $) > <$1.$2> <$3> <$4> <+ $5>', `dnl') 1294dnl lookup IP address (no check is done whether it is an IP number!) 1295R<?> <[$+.$-]> <$+> <$*> <$*> $@ $>LookUpDomain <[$1]> <$3> <$4> <$5> 1296dnl lookup IPv6 address 1297R<?> <[$+::$-]> <$+> <$*> <$*> $: $>LookUpDomain <[$1]> <$3> <$4> <$5> 1298R<?> <[$+:$-]> <$+> <$*> <$*> $: $>LookUpDomain <[$1]> <$3> <$4> <$5> 1299dnl not found, but subdomain: try again 1300R<?> <$+.$+> <$+> <$*> <$*> $@ $>LookUpDomain <$2> <$3> <$4> <$5> 1301dnl not found, no subdomain: return default 1302R<?> <$+> <$+> <$*> <$*> $@ <$2> <$3> 1303dnl return result of lookup 1304R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4> 1305 1306###################################################################### 1307### LookUpAddress -- search for host address in access database 1308### 1309### Parameters: 1310### <$1> -- key (dot quadded host address) 1311### <$2> -- default (what to return if not found in db) 1312dnl must not be empty 1313### <$3> -- passthru (additional data passed through) 1314### <$4> -- mark (must be <(!|+) single-token>) 1315### ! does lookup only with tag 1316### + does lookup with and without tag 1317dnl returns: <default> <passthru> 1318dnl <result> <passthru> 1319###################################################################### 1320 1321SLookUpAddress 1322dnl lookup with tag 1323R<$+> <$+> <$*> <$- $+> $: < $(access $5`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3> <$4 $5> 1324dnl lookup without tag 1325R<?> <$+> <$+> <$*> <+ $+> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4> 1326dnl no match; IPv6: remove last part 1327R<?> <$+::$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5> 1328R<?> <$+:$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5> 1329dnl no match; IPv4: remove last part 1330R<?> <$+.$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5> 1331dnl no match: return default 1332R<?> <$+> <$+> <$*> <$*> $@ <$2> <$3> 1333dnl match: return result 1334R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4>', 1335`dnl') 1336 1337###################################################################### 1338### CanonAddr -- Convert an address into a standard form for 1339### relay checking. Route address syntax is 1340### crudely converted into a %-hack address. 1341### 1342### Parameters: 1343### $1 -- full recipient address 1344### 1345### Returns: 1346### parsed address, not in source route form 1347dnl user%host%host<@domain> 1348dnl host!user<@domain> 1349###################################################################### 1350 1351SCanonAddr 1352R$* $: $>Parse0 $>canonify $1 make domain canonical 1353ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl 1354R< @ $+ > : $* @ $* < @ $1 > : $2 % $3 change @ to % in src route 1355R$* < @ $+ > : $* : $* $3 $1 < @ $2 > : $4 change to % hack. 1356R$* < @ $+ > : $* $3 $1 < @ $2 > 1357dnl') 1358 1359###################################################################### 1360### ParseRecipient -- Strip off hosts in $=R as well as possibly 1361### $* $=m or the access database. 1362### Check user portion for host separators. 1363### 1364### Parameters: 1365### $1 -- full recipient address 1366### 1367### Returns: 1368### parsed, non-local-relaying address 1369###################################################################### 1370 1371SParseRecipient 1372dnl mark and canonify address 1373R$* $: <?> $>CanonAddr $1 1374dnl workspace: <?> localpart<@domain[.]> 1375R<?> $* < @ $* . > <?> $1 < @ $2 > strip trailing dots 1376dnl workspace: <?> localpart<@domain> 1377R<?> $- < @ $* > $: <?> $(dequote $1 $) < @ $2 > dequote local part 1378 1379# if no $=O character, no host in the user portion, we are done 1380R<?> $* $=O $* < @ $* > $: <NO> $1 $2 $3 < @ $4> 1381dnl no $=O in localpart: return 1382R<?> $* $@ $1 1383 1384dnl workspace: <?> localpart<@domain>, where localpart contains $=O 1385dnl mark everything which has an "authorized" domain with <RELAY> 1386ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 1387# if we relay, check username portion for user%host so host can be checked also 1388R<NO> $* < @ $* $=m > $: <RELAY> $1 < @ $2 $3 >', `dnl') 1389 1390ifdef(`_RELAY_MX_SERVED_', `dnl 1391dnl do "we" ($=w) act as backup MX server for the destination domain? 1392R<NO> $* < @ $+ > $: <MX> < : $(mxserved $2 $) : > < $1 < @$2 > > 1393R<MX> < : $* <TEMP> : > $* $#error $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1 1394dnl yes: mark it as <RELAY> 1395R<MX> < $* : $=w. : $* > < $+ > $: <RELAY> $4 1396dnl no: put old <NO> mark back 1397R<MX> < : $* : > < $+ > $: <NO> $2', `dnl') 1398 1399dnl workspace: <(NO|RELAY)> localpart<@domain>, where localpart contains $=O 1400dnl if mark is <NO> then change it to <RELAY> if domain is "authorized" 1401ifdef(`_RELAY_HOSTS_ONLY_', 1402`R<NO> $* < @ $=R > $: <RELAY> $1 < @ $2 > 1403ifdef(`_ACCESS_TABLE_', `dnl 1404R<NO> $* < @ $+ > $: <$(access To:$2 $: NO $)> $1 < @ $2 > 1405R<NO> $* < @ $+ > $: <$(access $2 $: NO $)> $1 < @ $2 >',`dnl')', 1406`R<NO> $* < @ $* $=R > $: <RELAY> $1 < @ $2 $3 > 1407ifdef(`_ACCESS_TABLE_', `dnl 1408R<NO> $* < @ $+ > $: $>LookUpDomain <$2> <NO> <$1 < @ $2 >> <+To> 1409R<$+> <$+> $: <$1> $2',`dnl')') 1410 1411 1412R<RELAY> $* < @ $* > $@ $>ParseRecipient $1 1413R<$-> $* $@ $2 1414 1415 1416###################################################################### 1417### check_relay -- check hostname/address on SMTP startup 1418###################################################################### 1419 1420SLocal_check_relay 1421Scheck`'_U_`'relay 1422R$* $: $1 $| $>"Local_check_relay" $1 1423R$* $| $* $| $#$* $#$3 1424R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 1425 1426SBasic_check_relay 1427# check for deferred delivery mode 1428R$* $: < ${deliveryMode} > $1 1429R< d > $* $@ deferred 1430R< $* > $* $: $2 1431 1432ifdef(`_ACCESS_TABLE_', `dnl 1433dnl workspace: {client_name} $| {client_addr} 1434R$+ $| $+ $: $>LookUpDomain < $1 > <?> < $2 > <+Connect> 1435dnl workspace: <result-of-lookup> <{client_addr}> 1436R<?> <$+> $: $>LookUpAddress < $1 > <?> < $1 > <+Connect> no: another lookup 1437dnl workspace: <result-of-lookup> <{client_addr}> 1438R<?> < $+ > $: $1 found nothing 1439dnl workspace: <result-of-lookup> <{client_addr}> 1440dnl or {client_addr} 1441R<$={Accept}> < $* > $@ $1 return value of lookup 1442R<REJECT> $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"') 1443R<DISCARD> $* $#discard $: discard 1444dnl error tag 1445R<ERROR:$-.$-.$-:$+> <$*> $#error $@ $1.$2.$3 $: $4 1446R<ERROR:$+> <$*> $#error $: $1 1447dnl generic error from access map 1448R<$+> <$*> $#error $: $1', `dnl') 1449 1450ifdef(`_RBL_',`dnl 1451# DNS based IP address spam list 1452R$* $: $&{client_addr} 1453R::ffff:$-.$-.$-.$- $: <?> $(host $4.$3.$2.$1._RBL_. $: OK $) 1454R$-.$-.$-.$- $: <?> $(host $4.$3.$2.$1._RBL_. $: OK $) 1455R<?>OK $: OKSOFAR 1456R<?>$+ $#error $@ 5.7.1 $: "550 Mail from " $&{client_addr} " refused by blackhole site _RBL_"', 1457`dnl') 1458undivert(8) 1459 1460###################################################################### 1461### check_mail -- check SMTP ``MAIL FROM:'' command argument 1462###################################################################### 1463 1464SLocal_check_mail 1465Scheck`'_U_`'mail 1466R$* $: $1 $| $>"Local_check_mail" $1 1467R$* $| $#$* $#$2 1468R$* $| $* $@ $>"Basic_check_mail" $1 1469 1470SBasic_check_mail 1471# check for deferred delivery mode 1472R$* $: < ${deliveryMode} > $1 1473R< d > $* $@ deferred 1474R< $* > $* $: $2 1475 1476# authenticated? 1477dnl done first: we can require authentication for every mail transaction 1478dnl workspace: address as given by MAIL FROM: (sender) 1479R$* $: $1 $| $>"tls_client" $&{verify} $| MAIL 1480R$* $| $#$+ $#$2 1481dnl undo damage: remove result of tls_client call 1482R$* $| $* $: $1 1483 1484dnl workspace: address as given by MAIL FROM: 1485R<> $@ <OK> we MUST accept <> (RFC 1123) 1486ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl 1487dnl do some additional checks 1488dnl no user@host 1489dnl no user@localhost (if nonlocal sender) 1490dnl this is a pretty simple canonification, it will not catch every case 1491dnl just make sure the address has <> around it (which is required by 1492dnl the RFC anyway, maybe we should complain if they are missing...) 1493dnl dirty trick: if it is user@host, just add a dot: user@host. this will 1494dnl not be modified by host lookups. 1495R$+ $: <?> $1 1496R<?><$+> $: <@> <$1> 1497R<?>$+ $: <@> <$1> 1498dnl workspace: <@> <address> 1499dnl prepend daemon_flags 1500R$* $: $&{daemon_flags} $| $1 1501dnl workspace: ${daemon_flags} $| <@> <address> 1502dnl do not allow these at all or only from local systems? 1503R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > 1504dnl accept unqualified sender: change mark to avoid test 1505R$* u $* $| <@> < $* > $: <?> < $3 > 1506dnl workspace: ${daemon_flags} $| <@> <address> 1507dnl or: <? ${client_name} > <address> 1508dnl or: <?> <address> 1509dnl remove daemon_flags 1510R$* $| $* $: $2 1511# handle case of @localhost on address 1512R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > 1513R<@> < $* @ [127.0.0.1] > 1514 $: < ? $&{client_name} > < $1 @ [127.0.0.1] > 1515R<@> < $* @ localhost.$m > 1516 $: < ? $&{client_name} > < $1 @ localhost.$m > 1517ifdef(`_NO_UUCP_', `dnl', 1518`R<@> < $* @ localhost.UUCP > 1519 $: < ? $&{client_name} > < $1 @ localhost.UUCP >') 1520dnl workspace: < ? $&{client_name} > <user@localhost|host> 1521dnl or: <@> <address> 1522dnl or: <?> <address> (thanks to u in ${daemon_flags}) 1523R<@> $* $: $1 no localhost as domain 1524dnl workspace: < ? $&{client_name} > <user@localhost|host> 1525dnl or: <address> 1526dnl or: <?> <address> (thanks to u in ${daemon_flags}) 1527R<? $=w> $* $: $2 local client: ok 1528R<? $+> <$+> $#error $@ 5.5.4 $: "CODE553 Real domain name required for sender address" 1529dnl remove <?> (happens only if ${client_name} == "" or u in ${daemon_flags}) 1530R<?> $* $: $1') 1531dnl workspace: address (or <address>) 1532R$* $: <?> $>CanonAddr $1 canonify sender address and mark it 1533dnl workspace: <?> CanonicalAddress (i.e. address in canonical form localpart<@host>) 1534dnl there is nothing behind the <@host> so no trailing $* needed 1535R<?> $* < @ $+ . > <?> $1 < @ $2 > strip trailing dots 1536# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) 1537R<?> $* < @ $* $=P > $: <OK> $1 < @ $2 $3 > 1538dnl workspace <mark> CanonicalAddress where mark is ? or OK 1539ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_', 1540`R<?> $* < @ $+ > $: <OK> $1 < @ $2 > ... unresolvable OK', 1541`R<?> $* < @ $+ > $: <? $(resolve $2 $: $2 <PERM> $) > $1 < @ $2 > 1542R<? $* <$->> $* < @ $+ > 1543 $: <$2> $3 < @ $4 >') 1544dnl workspace <mark> CanonicalAddress where mark is ?, OK, PERM, TEMP 1545dnl mark is ? iff the address is user (wo @domain) 1546 1547ifdef(`_ACCESS_TABLE_', `dnl 1548# check sender address: user@address, user@, address 1549dnl should we remove +ext from user? 1550dnl workspace: <mark> CanonicalAddress where mark is: ?, OK, PERM, TEMP 1551R<$+> $+ < @ $* > $: @<$1> <$2 < @ $3 >> $| <F:$2@$3> <U:$2@> <H:$3> 1552R<$+> $+ $: @<$1> <$2> $| <U:$2@> 1553dnl workspace: @<mark> <CanonicalAddress> $| <@type:address> .... 1554dnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>> 1555dnl will only return user<@domain when "reversing" the args 1556R@ <$+> <$*> $| <$+> $: <@> <$1> <$2> $| $>SearchList <+From> $| <$3> <> 1557dnl workspace: <@><mark> <CanonicalAddress> $| <result> 1558R<@> <$+> <$*> $| <$*> $: <$3> <$1> <$2> reverse result 1559dnl workspace: <result> <mark> <CanonicalAddress> 1560# retransform for further use 1561dnl required form: 1562dnl <ResultOfLookup|mark> CanonicalAddress 1563R<?> <$+> <$*> $: <$1> $2 no match 1564R<$+> <$+> <$*> $: <$1> $3 relevant result, keep it', `dnl') 1565dnl workspace <ResultOfLookup|mark> CanonicalAddress 1566dnl mark is ? iff the address is user (wo @domain) 1567 1568ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl 1569# handle case of no @domain on address 1570dnl prepend daemon_flags 1571R<?> $* $: $&{daemon_flags} $| <?> $1 1572dnl accept unqualified sender: change mark to avoid test 1573R$* u $* $| <?> $* $: <OK> $3 1574dnl remove daemon_flags 1575R$* $| $* $: $2 1576R<?> $* $: < ? $&{client_name} > $1 1577R<?> $* $@ <OK> ...local unqualed ok 1578R<? $+> $* $#error $@ 5.5.4 $: "CODE553 Domain name required for sender address " $&f 1579 ...remote is not') 1580# check results 1581R<?> $* $: @ $1 mark address: nothing known about it 1582R<OK> $* $@ <OK> 1583R<TEMP> $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve" 1584R<PERM> $* $#error $@ 5.1.8 $: "CODE553 Domain of sender address " $&f " does not exist" 1585ifdef(`_ACCESS_TABLE_', `dnl 1586R<$={Accept}> $* $# $1 1587R<DISCARD> $* $#discard $: discard 1588R<REJECT> $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"') 1589dnl error tag 1590R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4 1591R<ERROR:$+> $* $#error $: $1 1592dnl generic error from access map 1593R<$+> $* $#error $: $1 error from access db', 1594`dnl') 1595 1596###################################################################### 1597### check_rcpt -- check SMTP ``RCPT TO:'' command argument 1598###################################################################### 1599 1600SLocal_check_rcpt 1601Scheck`'_U_`'rcpt 1602R$* $: $1 $| $>"Local_check_rcpt" $1 1603R$* $| $#$* $#$2 1604R$* $| $* $@ $>"Basic_check_rcpt" $1 1605 1606SBasic_check_rcpt 1607# check for deferred delivery mode 1608R$* $: < ${deliveryMode} > $1 1609R< d > $* $@ deferred 1610R< $* > $* $: $2 1611 1612ifdef(`_REQUIRE_QUAL_RCPT_', `dnl 1613# require qualified recipient? 1614R$+ $: <?> $1 1615R<?><$+> $: <@> <$1> 1616R<?>$+ $: <@> <$1> 1617dnl prepend daemon_flags 1618R$* $: $&{daemon_flags} $| $1 1619dnl workspace: ${daemon_flags} $| <@> <address> 1620dnl do not allow these at all or only from local systems? 1621R$* r $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > 1622R<?> < $* > $: <$1> 1623R<? $=w> < $* > $: <$1> 1624R<? $+> <$+> $#error $@ 5.5.4 $: "553 Domain name required" 1625dnl remove daemon_flags for other cases 1626R$* $| <@> $* $: $2', `dnl') 1627 1628ifdef(`_LOOSE_RELAY_CHECK_',`dnl 1629R$* $: $>CanonAddr $1 1630R$* < @ $* . > $1 < @ $2 > strip trailing dots', 1631`R$* $: $>ParseRecipient $1 strip relayable hosts') 1632 1633ifdef(`_BESTMX_IS_LOCAL_',`dnl 1634ifelse(_BESTMX_IS_LOCAL_, `', `dnl 1635# unlimited bestmx 1636R$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3', 1637`dnl 1638# limit bestmx to $=B 1639R$* < @ $* $=B > $* $: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4') 1640R$* $=O $* < @ $* @@ $=w . > $* $@ $>"Basic_check_rcpt" $1 $2 $3 1641R$* < @ $* @@ $=w . > $* $: $1 < @ $3 > $4 1642R$* < @ $* @@ $* > $* $: $1 < @ $2 > $4') 1643 1644ifdef(`_BLACKLIST_RCPT_',`dnl 1645ifdef(`_ACCESS_TABLE_', `dnl 1646# blacklist local users or any host from receiving mail 1647R$* $: <?> $1 1648dnl user is now tagged with @ to be consistent with check_mail 1649dnl and to distinguish users from hosts (com would be host, com@ would be user) 1650R<?> $+ < @ $=w > $: <> <$1 < @ $2 >> $| <F:$1@$2> <U:$1@> <H:$2> 1651R<?> $+ < @ $* > $: <> <$1 < @ $2 >> $| <F:$1@$2> <H:$2> 1652R<?> $+ $: <> <$1> $| <U:$1@> 1653dnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>> 1654dnl will only return user<@domain when "reversing" the args 1655R<> <$*> $| <$+> $: <@> <$1> $| $>SearchList <+To> $| <$2> <> 1656R<@> <$*> $| <$*> $: <$2> <$1> reverse result 1657R<?> <$*> $: @ $1 mark address as no match 1658R<$={Accept}> <$*> $: @ $2 mark address as no match 1659ifdef(`_DELAY_CHECKS_',`dnl 1660dnl we have to filter these because otherwise they would be interpreted 1661dnl as generic error message... 1662dnl error messages should be "tagged" by prefixing them with error: ! 1663dnl that would make a lot of things easier. 1664dnl maybe we should stop checks already here (if SPAM_xyx)? 1665R<$={SpamTag}> <$*> $: @ $2 mark address as no match') 1666R<REJECT> $* $#error $@ 5.2.1 $: "550 Mailbox disabled for this recipient" 1667R<DISCARD> $* $#discard $: discard 1668dnl error tag 1669R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4 1670R<ERROR:$+> $* $#error $: $1 1671dnl generic error from access map 1672R<$+> $* $#error $: $1 error from access db 1673R@ $* $1 remove mark', `dnl')', `dnl') 1674 1675ifdef(`_PROMISCUOUS_RELAY_', `divert(-1)') 1676# authenticated? 1677dnl do this unconditionally? this requires to manage CAs carefully 1678dnl just because someone has a CERT signed by a "trusted" CA 1679dnl does not mean we want to allow relaying for her, 1680dnl either use a subroutine or provide something more sophisticated 1681dnl this could for example check the DN (maybe an access map lookup) 1682R$* $: $1 $| $>RelayAuth $1 $| $&{verify} client authenticated? 1683R$* $| $# $+ $# $2 error/ok? 1684R$* $| $* $: $1 no 1685 1686# authenticated by a trusted mechanism? 1687R$* $: $1 $| $&{auth_type} 1688dnl empty ${auth_type}? 1689R$* $| $: $1 1690dnl mechanism ${auth_type} accepted? 1691dnl use $# to override further tests (delay_checks): see check_rcpt below 1692R$* $| $={TrustAuthMech} $# RELAYAUTH 1693dnl undo addition of ${auth_type} 1694R$* $| $* $: $1 1695dnl workspace: localpart<@domain> | localpart 1696ifelse(defn(`_NO_UUCP_'), `r', 1697`R$* ! $* < @ $* > $: <REMOTE> $2 < @ BANG_PATH > 1698R$* ! $* $: <REMOTE> $2 < @ BANG_PATH >', `dnl') 1699# anything terminating locally is ok 1700ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 1701R$+ < @ $* $=m > $@ RELAYTO', `dnl') 1702R$+ < @ $=w > $@ RELAYTO 1703ifdef(`_RELAY_HOSTS_ONLY_', 1704`R$+ < @ $=R > $@ RELAYTO 1705ifdef(`_ACCESS_TABLE_', `dnl 1706R$+ < @ $+ > $: <$(access To:$2 $: ? $)> <$1 < @ $2 >> 1707dnl workspace: <Result-of-lookup | ?> <localpart<@domain>> 1708R<?> <$+ < @ $+ >> $: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')', 1709`R$+ < @ $* $=R > $@ RELAYTO 1710ifdef(`_ACCESS_TABLE_', `dnl 1711R$+ < @ $+ > $: $>LookUpDomain <$2> <?> <$1 < @ $2 >> <+To>',`dnl')') 1712ifdef(`_ACCESS_TABLE_', `dnl 1713dnl workspace: <Result-of-lookup | ?> <localpart<@domain>> 1714R<RELAY> $* $@ RELAYTO 1715R<$*> <$*> $: $2',`dnl') 1716 1717 1718ifdef(`_RELAY_MX_SERVED_', `dnl 1719# allow relaying for hosts which we MX serve 1720R$+ < @ $+ > $: < : $(mxserved $2 $) : > $1 < @ $2 > 1721dnl this must not necessarily happen if the client is checked first... 1722R< : $* <TEMP> : > $* $#error $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1 1723R<$* : $=w . : $*> $* $@ RELAYTO 1724R< : $* : > $* $: $2', 1725`dnl') 1726 1727# check for local user (i.e. unqualified address) 1728R$* $: <?> $1 1729R<?> $* < @ $+ > $: <REMOTE> $1 < @ $2 > 1730# local user is ok 1731dnl is it really? the standard requires user@domain, not just user 1732dnl but we should accept it anyway (maybe making it an option: 1733dnl RequireFQDN ?) 1734dnl postmaster must be accepted without domain (DRUMS) 1735ifdef(`_REQUIRE_QUAL_RCPT_', `dnl 1736R<?> postmaster $@ TOPOSTMASTER 1737# require qualified recipient? 1738dnl prepend daemon_flags 1739R<?> $+ $: $&{daemon_flags} $| <?> $1 1740dnl workspace: ${daemon_flags} $| <?> localpart 1741dnl do not allow these at all or only from local systems? 1742dnl r flag? add client_name 1743R$* r $* $| <?> $+ $: < ? $&{client_name} > <?> $3 1744dnl no r flag: relay to local user (only local part) 1745# no qualified recipient required 1746R$* $| <?> $+ $@ RELAYTOLOCAL 1747dnl client_name is empty 1748R<?> <?> $+ $@ RELAYTOLOCAL 1749dnl client_name is local 1750R<? $=w> <?> $+ $@ RELAYTOLOCAL 1751dnl client_name is not local 1752R<? $+> $+ $#error $@ 5.5.4 $: "553 Domain name required"', `dnl 1753dnl no qualified recipient required 1754R<?> $+ $@ RELAYTOLOCAL') 1755dnl it is a remote user: remove mark and then check client 1756R<$+> $* $: $2 1757dnl currently the recipient address is not used below 1758 1759# anything originating locally is ok 1760# check IP address 1761R$* $: $&{client_addr} 1762R$@ $@ RELAYFROM originated locally 1763R0 $@ RELAYFROM originated locally 1764R$=R $* $@ RELAYFROM relayable IP address 1765ifdef(`_ACCESS_TABLE_', `dnl 1766R$* $: $>LookUpAddress <$1> <?> <$1> <+Connect> 1767R<RELAY> $* $@ RELAYFROM relayable IP address 1768R<$*> <$*> $: $2', `dnl') 1769R$* $: [ $1 ] put brackets around it... 1770R$=w $@ RELAYFROM ... and see if it is local 1771 1772ifdef(`_RELAY_DB_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl 1773ifdef(`_RELAY_LOCAL_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl 1774ifdef(`_RELAY_MAIL_FROM_', `dnl 1775dnl input: {client_addr} or something "broken" 1776dnl just throw the input away; we do not need it. 1777# check whether FROM is allowed to use system as relay 1778R$* $: <?> $>CanonAddr $&f 1779ifdef(`_RELAY_LOCAL_FROM_', `dnl 1780# check whether local FROM is ok 1781R<?> $+ < @ $=w . > $@ RELAYFROMMAIL FROM local', `dnl') 1782ifdef(`_RELAY_DB_FROM_', `dnl 1783R<?> $+ < @ $+ . > <?> $1 < @ $2 > remove trailing dot 1784R<?> $+ < @ $+ > $: $1 < @ $2 > $| $>SearchList <! From> $| <F:$1@$2> ifdef(`_RELAY_DB_FROM_DOMAIN_', `<H:$2>') <> 1785R$* <RELAY> $@ RELAYFROMMAIL RELAY FROM sender ok', `dnl 1786ifdef(`_RELAY_DB_FROM_DOMAIN_', `errprint(`*** ERROR: _RELAY_DB_FROM_DOMAIN_ requires _RELAY_DB_FROM_ 1787')', 1788`dnl') 1789dnl')', `dnl') 1790 1791# check client name: first: did it resolve? 1792dnl input: ignored 1793R$* $: < $&{client_resolve} > 1794R<TEMP> $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} 1795R<FORGED> $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} 1796R<FAIL> $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} 1797dnl ${client_resolve} should be OK, so go ahead 1798R$* $: <?> $&{client_name} 1799# pass to name server to make hostname canonical 1800R<?> $* $~P $:<?> $[ $1 $2 $] 1801R$* . $1 strip trailing dots 1802dnl should not be necessary since it has been done for client_addr already 1803R<?> $@ RELAYFROM 1804ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 1805R<?> $* $=m $@ RELAYFROM', `dnl') 1806R<?> $=w $@ RELAYFROM 1807ifdef(`_RELAY_HOSTS_ONLY_', 1808`R<?> $=R $@ RELAYFROM 1809ifdef(`_ACCESS_TABLE_', `dnl 1810R<?> $* $: <$(access Connect:$1 $: ? $)> <$1> 1811R<?> <$*> $: <$(access $1 $: ? $)> <$1>',`dnl')', 1812`R<?> $* $=R $@ RELAYFROM 1813ifdef(`_ACCESS_TABLE_', `dnl 1814R<?> $* $: $>LookUpDomain <$1> <?> <$1> <+Connect>',`dnl')') 1815ifdef(`_ACCESS_TABLE_', `dnl 1816R<RELAY> $* $@ RELAYFROM 1817R<$*> <$*> $: $2',`dnl') 1818 1819# anything else is bogus 1820R$* $#error $@ 5.7.1 $: confRELAY_MSG 1821divert(0) 1822ifdef(`_DELAY_CHECKS_',`dnl 1823# turn a canonical address in the form user<@domain> 1824# qualify unqual. addresses with $j 1825dnl it might have been only user (without <@domain>) 1826SFullAddr 1827R$* <@ $+ . > $1 <@ $2 > 1828R$* <@ $* > $@ $1 <@ $2 > 1829R$+ $@ $1 <@ $j > 1830 1831# call all necessary rulesets 1832Scheck_rcpt 1833dnl this test should be in the Basic_check_rcpt ruleset 1834dnl which is the correct DSN code? 1835# R$@ $#error $@ 5.1.3 $: "553 Recipient address required" 1836R$+ $: $1 $| $>checkrcpt $1 1837dnl now we can simply stop checks by returning "$# xyz" instead of just "ok" 1838R$+ $| $#$* $#$2 1839R$+ $| $* $: <?> $>FullAddr $>CanonAddr $1 1840ifdef(`_SPAM_FH_', 1841`dnl lookup user@ and user@address 1842ifdef(`_ACCESS_TABLE_', `', 1843`errprint(`*** ERROR: FEATURE(`delay_checks', `argument') requires FEATURE(`access_db') 1844')')dnl 1845dnl one of the next two rules is supposed to match 1846dnl this code has been copied from BLACKLIST... etc 1847dnl and simplified by omitting some < >. 1848R<?> $+ < @ $=w > $: <> $1 < @ $2 > $| <F: $1@$2 > <U: $1@> 1849R<?> $+ < @ $* > $: <> $1 < @ $2 > $| <F: $1@$2 > 1850dnl R<?> $@ something_is_very_wrong_here 1851# lookup the addresses only with To tag 1852R<> $* $| <$+> $: <@> $1 $| $>SearchList <!To> $| <$2> <> 1853R<@> $* $| $* $: $2 $1 reverse result 1854dnl', `dnl') 1855ifdef(`_SPAM_FRIEND_', 1856`# is the recipient a spam friend? 1857ifdef(`_SPAM_HATER_', 1858 `errprint(`*** ERROR: define either SpamHater or SpamFriend 1859')', `dnl') 1860R<SPAMFRIEND> $+ $@ SPAMFRIEND 1861R<$*> $+ $: $2', 1862`dnl') 1863ifdef(`_SPAM_HATER_', 1864`# is the recipient no spam hater? 1865R<SPAMHATER> $+ $: $1 spam hater: continue checks 1866R<$*> $+ $@ NOSPAMHATER everyone else: stop 1867dnl',`dnl') 1868dnl run further checks: check_mail 1869dnl should we "clean up" $&f? 1870R$* $: $1 $| $>checkmail <$&f> 1871R$* $| $#$* $#$2 1872dnl run further checks: check_relay 1873R$* $: $1 $| $>checkrelay $&{client_name} $| $&{client_addr} 1874R$* $| $#$* $#$2 1875R$* $| $* $: $1 1876', `dnl') 1877ifdef(`_ACCESS_TABLE_', `dnl 1878###################################################################### 1879### SearchList: search a list of items in the access map 1880### Parameters: 1881### <exact tag> $| <mark:address> <mark:address> ... <> 1882dnl maybe we should have a @ (again) in front of the mark to 1883dnl avoid errorneous matches (with error messages?) 1884dnl if we can make sure that tag is always a single token 1885dnl then we can omit the delimiter $|, otherwise we need it 1886dnl to avoid errorneous matchs (first rule: H: if there 1887dnl is that mark somewhere in the list, it will be taken). 1888dnl moreover, we can do some tricks to enforce lookup with 1889dnl the tag only, e.g.: 1890### where "exact" is either "+" or "!": 1891### <+ TAG> lookup with and w/o tag 1892### <! TAG> lookup with tag 1893dnl Warning: + and ! should be in OperatorChars (otherwise there must be 1894dnl a blank between them and the tag. 1895### possible values for "mark" are: 1896### H: recursive host lookup (LookUpDomain) 1897dnl A: recursive address lookup (LookUpAddress) [not yet required] 1898### E: exact lookup, no modifications 1899### F: full lookup, try user+ext@domain and user@domain 1900### U: user lookup, try user+ext and user (input must have trailing @) 1901### return: <RHS of lookup> or <?> (not found) 1902###################################################################### 1903 1904# class with valid marks for SearchList 1905dnl if A is activated: add it 1906C{src}E F H U 1907SSearchList 1908# mark H: lookup domain 1909R<$+> $| <H:$+> <$*> $: <$1> $| <@> $>LookUpDomain <$2> <?> <$3> <$1> 1910R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3> 1911dnl A: NOT YET REQUIRED 1912dnl R<$+> $| <A:$+> <$*> $: <$1> $| <@> $>LookUpAddress <$2> <?> <$3> <$1> 1913dnl R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3> 1914dnl lookup of the item with tag 1915dnl this applies to F: U: E: 1916R<$- $-> $| <$={src}:$+> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$4 $: $3:$4 $)> <$5> 1917dnl no match, try without tag 1918R<+ $-> $| <$={src}:$+> <$*> $: <+ $1> $| <$(access $3 $: $2:$3 $)> <$4> 1919dnl do we really have to distinguish these cases? 1920dnl probably yes, there might be a + in the domain part (is that allowed?) 1921dnl user+detail lookups: should it be: 1922dnl user+detail, user+*, user; just like aliases? 1923R<$- $-> $| <F:$* + $*@$+> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$3@$5 $: F:$3 + $4@$5$)> <$6> 1924R<+ $-> $| <F:$* + $*@$+> <$*> $: <+ $1> $| <$(access $2@$4 $: F:$2 + $3@$4$)> <$5> 1925dnl user lookups are always with trailing @ 1926dnl do not remove the @ from the lookup: 1927dnl it is part of the +detail@ which is omitted for the lookup 1928R<$- $-> $| <U:$* + $*> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$3@ $: U:$3 + $4$)> <$5> 1929dnl no match, try without tag 1930R<+ $-> $| <U:$* + $*> <$*> $: <+ $1> $| <$(access $2@ $: U:$2 + $3$)> <$4> 1931dnl no match, try rest of list 1932R<$+> $| <$={src}:$+> <$+> $@ $>SearchList <$1> $| <$4> 1933dnl no match, list empty: return failure 1934R<$+> $| <$={src}:$+> <> $@ <?> 1935dnl got result, return it 1936R<$+> $| <$+> <$*> $@ <$2> 1937dnl return result from recursive invocation 1938R<$+> $| <$+> $@ <$2>', `dnl') 1939 1940# is user trusted to authenticate as someone else? 1941dnl AUTH= parameter from MAIL command 1942Strust_auth 1943R$* $: $&{auth_type} $| $1 1944# required by RFC 2554 section 4. 1945R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" 1946dnl seems to be useful... 1947R$* $| $&{auth_authen} $@ identical 1948R$* $| <$&{auth_authen}> $@ identical 1949dnl call user supplied code 1950R$* $| $* $: $1 $| $>"Local_trust_auth" $1 1951R$* $| $#$* $#$2 1952dnl default: error 1953R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} 1954 1955dnl empty ruleset definition so it can be called 1956SLocal_trust_auth 1957 1958ifdef(`_FFR_TLS_O_T', `dnl 1959Soffer_tls 1960R$* $: $>LookUpDomain <$&{client_name}> <?> <> <! TLS_OFF_TAG> 1961R<?>$* $: $>LookUpAddress <$&{client_addr}> <?> <> <! TLS_OFF_TAG> 1962R<?>$* $: <$(access TLS_OFF_TAG: $: ? $)> 1963R<?>$* $@ OK 1964R<NO> <> $#error $@ 5.7.1 $: "550 do not offer TLS for " $&{client_name} " ["$&{client_addr}"]" 1965 1966Stry_tls 1967R$* $: $>LookUpDomain <$&{server_name}> <?> <> <! TLS_TRY_TAG> 1968R<?>$* $: $>LookUpAddress <$&{server_addr}> <?> <> <! TLS_TRY_TAG> 1969R<?>$* $: <$(access TLS_TRY_TAG: $: ? $)> 1970R<?>$* $@ OK 1971R<NO>$* $#error $@ 5.7.1 $: "550 do not try TLS with " $&{server_name} " ["$&{server_addr}"]" 1972')dnl 1973 1974# is connection with client "good" enough? (done in server) 1975# input: ${verify} $| (MAIL|STARTTLS) 1976dnl MAIL: called from check_mail 1977dnl STARTTLS: called from smtp() after STARTTLS has been accepted 1978Stls_client 1979ifdef(`_ACCESS_TABLE_', `dnl 1980dnl ignore second arg for now 1981dnl maybe use it to distinguish permanent/temporary error? 1982dnl if MAIL: permanent (STARTTLS has not been offered) 1983dnl if STARTTLS: temporary (offered but maybe failed) 1984R$* $| $* $: $1 $| $>LookUpDomain <$&{client_name}> <?> <> <! TLS_CLT_TAG> 1985R$* $| <?>$* $: $1 $| $>LookUpAddress <$&{client_addr}> <?> <> <! TLS_CLT_TAG> 1986dnl do a default lookup: just TLS_CLT_TAG 1987R$* $| <?>$* $: $1 $| <$(access TLS_CLT_TAG`'_TAG_DELIM_ $: ? $)> 1988R$* $@ $>"tls_connection" $1', `dnl 1989R$* $| $* $@ $>"tls_connection" $1') 1990 1991# is connection with server "good" enough? (done in client) 1992dnl i.e. has the server been authenticated and is encryption active? 1993dnl called from deliver() after STARTTLS command 1994# input: ${verify} 1995Stls_server 1996ifdef(`_ACCESS_TABLE_', `dnl 1997R$* $: $1 $| $>LookUpDomain <$&{server_name}> <?> <> <! TLS_SRV_TAG> 1998R$* $| <?>$* $: $1 $| $>LookUpAddress <$&{server_addr}> <?> <> <! TLS_SRV_TAG> 1999dnl do a default lookup: just TLS_SRV_TAG 2000R$* $| <?>$* $: $1 $| <$(access TLS_SRV_TAG`'_TAG_DELIM_ $: ? $)> 2001R$* $@ $>"tls_connection" $1', `dnl 2002R$* $@ $>"tls_connection" $1') 2003 2004Stls_connection 2005ifdef(`_ACCESS_TABLE_', `dnl 2006dnl common ruleset for tls_{client|server} 2007dnl input: $&{verify} $| <ResultOfLookup> [<>] 2008dnl remove optional <> 2009R$* $| <$*>$* $: $1 $| <$2> 2010dnl permanent or temporary error? 2011R$* $| <PERM + $={tls} $*> $: $1 $| <503:5.7.0> <$2 $3> 2012R$* $| <TEMP + $={tls} $*> $: $1 $| <403:4.7.0> <$2 $3> 2013dnl default case depends on TLS_PERM_ERR 2014R$* $| <$={tls} $*> $: $1 $| <ifdef(`TLS_PERM_ERR', `503:5.7.0', `403:4.7.0')> <$2 $3> 2015dnl deal with TLS handshake failures: abort 2016RSOFTWARE $| <$-:$+> $* $#error $@ $2 $: $1 " TLS handshake failed." 2017dnl no <reply:dns> i.e. not requirements in the access map 2018dnl use default error 2019RSOFTWARE $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake failed." 2020R$* $| <$*> <VERIFY> $: <$2> <VERIFY> $1 2021R$* $| <$*> <$={tls}:$->$* $: <$2> <$3:$4> $1 2022dnl some other value in access map: accept 2023dnl this also allows to override the default case (if used) 2024R$* $| $* $@ OK 2025# authentication required: give appropriate error 2026# other side did authenticate (via STARTTLS) 2027dnl workspace: <SMTP:ESC> <{VERIFY,ENCR}[:BITS]> ${verify} 2028dnl only verification required and it succeeded 2029R<$*><VERIFY> OK $@ OK 2030dnl verification required + some level of encryption 2031R<$*><VERIFY:$-> OK $: <$1> <REQ:$2> 2032dnl just some level of encryption required 2033R<$*><ENCR:$-> $* $: <$1> <REQ:$2> 2034dnl verification required but ${verify} is not set 2035R<$-:$+><VERIFY $*> $#error $@ $2 $: $1 " authentication required" 2036R<$-:$+><VERIFY $*> FAIL $#error $@ $2 $: $1 " authentication failed" 2037R<$-:$+><VERIFY $*> NO $#error $@ $2 $: $1 " not authenticated" 2038R<$-:$+><VERIFY $*> NONE $#error $@ $2 $: $1 " other side does not support STARTTLS" 2039dnl some other value for ${verify} 2040R<$-:$+><VERIFY $*> $+ $#error $@ $2 $: $1 " authentication failure " $4 2041dnl some level of encryption required: get the maximum level 2042R<$*><REQ:$-> $: <$1> <REQ:$2> $>max $&{cipher_bits} : $&{auth_ssf} 2043dnl compare required bits with actual bits 2044R<$*><REQ:$-> $- $: <$1> <$2:$3> $(arith l $@ $3 $@ $2 $) 2045R<$-:$+><$-:$-> TRUE $#error $@ $2 $: $1 " encryption too weak " $4 " less than " $3 2046 2047Smax 2048dnl compute the max of two values separated by : 2049R: $: 0 2050R:$- $: $1 2051R$-: $: $1 2052R$-:$- $: $(arith l $@ $1 $@ $2 $) : $1 : $2 2053RTRUE:$-:$- $: $2 2054R$-:$-:$- $: $2', 2055`dnl use default error 2056dnl deal with TLS handshake failures: abort 2057RSOFTWARE $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake."') 2058 2059SRelayAuth 2060# authenticated? 2061dnl we do not allow relaying for anyone who can present a cert 2062dnl signed by a "trusted" CA. For example, even if we put verisigns 2063dnl CA in CERTPath so we can authenticate users, we do not allow 2064dnl them to abuse our server (they might be easier to get hold of, 2065dnl but anyway). 2066dnl so here is the trick: if the verification succeeded 2067dnl we look up the cert issuer in the access map 2068dnl (maybe after extracting a part with a regular expression) 2069dnl if this returns RELAY we relay without further questions 2070dnl if it returns SUBJECT we perform a similar check on the 2071dnl cert subject. 2072R$* $| OK $: $1 2073R$* $| $* $@ NO not authenticated 2074ifdef(`_ACCESS_TABLE_', `dnl 2075ifdef(`_CERT_REGEX_ISSUER_', `dnl 2076R$* $: $1 $| $(CERTIssuer $&{cert_issuer} $)', 2077`R$* $: $1 $| $&{cert_issuer}') 2078R$* $| $+ $: $1 $| $(access CERTISSUER:$2 $) 2079dnl use $# to stop further checks (delay_check) 2080R$* $| RELAY $# RELAYCERTISSUER 2081ifdef(`_CERT_REGEX_SUBJECT_', `dnl 2082R$* $| SUBJECT $: $1 $| <@> $(CERTSubject $&{cert_subject} $)', 2083`R$* $| SUBJECT $: $1 $| <@> $&{cert_subject}') 2084R$* $| <@> $+ $: $1 $| <@> $(access CERTSUBJECT:$2 $) 2085R$* $| <@> RELAY $# RELAYCERTSUBJECT 2086R$* $| $* $: $1', `dnl') 2087 2088undivert(9)dnl LOCAL_RULESETS 2089ifdef(`_FFR_MILTER', ` 2090# 2091###################################################################### 2092###################################################################### 2093##### 2094`##### MAIL FILTER DEFINITIONS' 2095##### 2096###################################################################### 2097###################################################################### 2098_MAIL_FILTERS_') 2099# 2100###################################################################### 2101###################################################################### 2102##### 2103`##### MAILER DEFINITIONS' 2104##### 2105###################################################################### 2106###################################################################### 2107undivert(7)dnl MAILER_DEFINITIONS 2108 2109