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