10Sstevel@tonic-gatedivert(-1) 20Sstevel@tonic-gate# 32197Sjbeck# Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers. 40Sstevel@tonic-gate# All rights reserved. 50Sstevel@tonic-gate# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. 60Sstevel@tonic-gate# Copyright (c) 1988, 1993 70Sstevel@tonic-gate# The Regents of the University of California. All rights reserved. 80Sstevel@tonic-gate# 90Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 100Sstevel@tonic-gate# Use is subject to license terms. 110Sstevel@tonic-gate# 120Sstevel@tonic-gate# ident "%Z%%M% %I% %E% SMI" 130Sstevel@tonic-gate# 140Sstevel@tonic-gate# By using this file, you agree to the terms and conditions set 150Sstevel@tonic-gate# forth in the LICENSE file which can be found at the top level of 160Sstevel@tonic-gate# the sendmail distribution. 170Sstevel@tonic-gate# 180Sstevel@tonic-gate# 190Sstevel@tonic-gatedivert(0) 200Sstevel@tonic-gate 21*3544SjbeckVERSIONID(`$Id: proto.m4,v 8.726 2007/01/04 18:27:46 ca Exp $') 220Sstevel@tonic-gate 230Sstevel@tonic-gate# level CF_LEVEL config file format 240Sstevel@tonic-gateV`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Sun') 250Sstevel@tonic-gatedivert(-1) 260Sstevel@tonic-gate 270Sstevel@tonic-gatednl if MAILER(`local') not defined: do it ourself; be nice 280Sstevel@tonic-gatednl maybe we should issue a warning? 290Sstevel@tonic-gateifdef(`_MAILER_local_',`', `MAILER(local)') 300Sstevel@tonic-gate 310Sstevel@tonic-gate# do some sanity checking 320Sstevel@tonic-gateifdef(`__OSTYPE__',, 330Sstevel@tonic-gate `errprint(`*** ERROR: No system type defined (use OSTYPE macro) 340Sstevel@tonic-gate')') 350Sstevel@tonic-gate 360Sstevel@tonic-gate# pick our default mailers 370Sstevel@tonic-gateifdef(`confSMTP_MAILER',, `define(`confSMTP_MAILER', `esmtp')') 380Sstevel@tonic-gateifdef(`confLOCAL_MAILER',, `define(`confLOCAL_MAILER', `local')') 390Sstevel@tonic-gateifdef(`confRELAY_MAILER',, 400Sstevel@tonic-gate `define(`confRELAY_MAILER', 410Sstevel@tonic-gate `ifdef(`_MAILER_smtp_', `relay', 420Sstevel@tonic-gate `ifdef(`_MAILER_uucp', `uucp-new', `unknown')')')') 430Sstevel@tonic-gateifdef(`confUUCP_MAILER',, `define(`confUUCP_MAILER', `uucp-old')') 440Sstevel@tonic-gatedefine(`_SMTP_', `confSMTP_MAILER')dnl for readability only 450Sstevel@tonic-gatedefine(`_LOCAL_', `confLOCAL_MAILER')dnl for readability only 460Sstevel@tonic-gatedefine(`_RELAY_', `confRELAY_MAILER')dnl for readability only 470Sstevel@tonic-gatedefine(`_UUCP_', `confUUCP_MAILER')dnl for readability only 480Sstevel@tonic-gate 490Sstevel@tonic-gate# back compatibility with old config files 500Sstevel@tonic-gateifdef(`confDEF_GROUP_ID', 510Sstevel@tonic-gate`errprint(`*** confDEF_GROUP_ID is obsolete. 520Sstevel@tonic-gate Use confDEF_USER_ID with a colon in the value instead. 530Sstevel@tonic-gate')') 540Sstevel@tonic-gateifdef(`confREAD_TIMEOUT', 550Sstevel@tonic-gate`errprint(`*** confREAD_TIMEOUT is obsolete. 560Sstevel@tonic-gate Use individual confTO_<timeout> parameters instead. 570Sstevel@tonic-gate')') 580Sstevel@tonic-gateifdef(`confMESSAGE_TIMEOUT', 590Sstevel@tonic-gate `define(`_ARG_', index(confMESSAGE_TIMEOUT, /)) 600Sstevel@tonic-gate ifelse(_ARG_, -1, 610Sstevel@tonic-gate `define(`confTO_QUEUERETURN', confMESSAGE_TIMEOUT)', 620Sstevel@tonic-gate `define(`confTO_QUEUERETURN', 630Sstevel@tonic-gate substr(confMESSAGE_TIMEOUT, 0, _ARG_)) 640Sstevel@tonic-gate define(`confTO_QUEUEWARN', 650Sstevel@tonic-gate substr(confMESSAGE_TIMEOUT, eval(_ARG_+1)))')') 660Sstevel@tonic-gateifdef(`confMIN_FREE_BLOCKS', `ifelse(index(confMIN_FREE_BLOCKS, /), -1,, 670Sstevel@tonic-gate`errprint(`*** compound confMIN_FREE_BLOCKS is obsolete. 680Sstevel@tonic-gate Use confMAX_MESSAGE_SIZE for the second part of the value. 690Sstevel@tonic-gate')')') 700Sstevel@tonic-gate 710Sstevel@tonic-gate 720Sstevel@tonic-gate# Sanity check on ldap_routing feature 730Sstevel@tonic-gate# If the user doesn't specify a new map, they better have given as a 740Sstevel@tonic-gate# default LDAP specification which has the LDAP base (and most likely the host) 750Sstevel@tonic-gateifdef(`confLDAP_DEFAULT_SPEC',, `ifdef(`_LDAP_ROUTING_WARN_', `errprint(` 760Sstevel@tonic-gateWARNING: Using default FEATURE(ldap_routing) map definition(s) 770Sstevel@tonic-gatewithout setting confLDAP_DEFAULT_SPEC option. 780Sstevel@tonic-gate')')')dnl 790Sstevel@tonic-gate 800Sstevel@tonic-gate# clean option definitions below.... 810Sstevel@tonic-gatedefine(`_OPTION', `ifdef(`$2', `O $1`'ifelse(defn(`$2'), `',, `=$2')', `#O $1`'ifelse(`$3', `',,`=$3')')')dnl 820Sstevel@tonic-gate 830Sstevel@tonic-gatednl required to "rename" the check_* rulesets... 840Sstevel@tonic-gatedefine(`_U_',ifdef(`_DELAY_CHECKS_',`',`_')) 850Sstevel@tonic-gatednl default relaying denied message 860Sstevel@tonic-gateifdef(`confRELAY_MSG', `', `define(`confRELAY_MSG', 870Sstevel@tonic-gateifdef(`_USE_AUTH_', `"550 Relaying denied. Proper authentication required."', `"550 Relaying denied"'))') 880Sstevel@tonic-gateifdef(`confRCPTREJ_MSG', `', `define(`confRCPTREJ_MSG', `"550 Mailbox disabled for this recipient"')') 890Sstevel@tonic-gatedefine(`_CODE553', `553') 900Sstevel@tonic-gatedivert(0)dnl 910Sstevel@tonic-gate 920Sstevel@tonic-gate# override file safeties - setting this option compromises system security, 930Sstevel@tonic-gate# addressing the actual file configuration problem is preferred 940Sstevel@tonic-gate# need to set this before any file actions are encountered in the cf file 950Sstevel@tonic-gate_OPTION(DontBlameSendmail, `confDONT_BLAME_SENDMAIL', `safe') 960Sstevel@tonic-gate 970Sstevel@tonic-gate# default LDAP map specification 980Sstevel@tonic-gate# need to set this now before any LDAP maps are defined 990Sstevel@tonic-gate_OPTION(LDAPDefaultSpec, `confLDAP_DEFAULT_SPEC', `-h localhost') 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate################## 1020Sstevel@tonic-gate# local info # 1030Sstevel@tonic-gate################## 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate# my LDAP cluster 1060Sstevel@tonic-gate# need to set this before any LDAP lookups are done (including classes) 1070Sstevel@tonic-gateifdef(`confLDAP_CLUSTER', `D{sendmailMTACluster}`'confLDAP_CLUSTER', `#D{sendmailMTACluster}$m') 1080Sstevel@tonic-gate 1090Sstevel@tonic-gateCwlocalhost 1100Sstevel@tonic-gateifdef(`USE_CW_FILE', 1110Sstevel@tonic-gate`# file containing names of hosts for which we receive email 1120Sstevel@tonic-gateFw`'confCW_FILE', 1130Sstevel@tonic-gate `dnl') 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate# my official domain name 1160Sstevel@tonic-gate# ... `define' this only if sendmail cannot automatically determine your domain 1170Sstevel@tonic-gateifdef(`confDOMAIN_NAME', `Dj`'confDOMAIN_NAME', `#Dj$w.Foo.COM') 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate# host/domain names ending with a token in class P are canonical 1200Sstevel@tonic-gateCP. 1210Sstevel@tonic-gate 1220Sstevel@tonic-gateifdef(`UUCP_RELAY', 1230Sstevel@tonic-gate`# UUCP relay host 1240Sstevel@tonic-gateDY`'UUCP_RELAY 1250Sstevel@tonic-gateCPUUCP 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate')dnl 1280Sstevel@tonic-gateifdef(`BITNET_RELAY', 1290Sstevel@tonic-gate`# BITNET relay host 1300Sstevel@tonic-gateDB`'BITNET_RELAY 1310Sstevel@tonic-gateCPBITNET 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate')dnl 1340Sstevel@tonic-gateifdef(`DECNET_RELAY', 1350Sstevel@tonic-gate`define(`_USE_DECNET_SYNTAX_', 1)dnl 1360Sstevel@tonic-gate# DECnet relay host 1370Sstevel@tonic-gateDC`'DECNET_RELAY 1380Sstevel@tonic-gateCPDECNET 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate')dnl 1410Sstevel@tonic-gateifdef(`FAX_RELAY', 1420Sstevel@tonic-gate`# FAX relay host 1430Sstevel@tonic-gateDF`'FAX_RELAY 1440Sstevel@tonic-gateCPFAX 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate')dnl 1470Sstevel@tonic-gate# "Smart" relay host (may be null) 1480Sstevel@tonic-gateDS`'ifdef(`SMART_HOST', `SMART_HOST') 1490Sstevel@tonic-gate 1500Sstevel@tonic-gateifdef(`LUSER_RELAY', `dnl 1510Sstevel@tonic-gate# place to which unknown users should be forwarded 1520Sstevel@tonic-gateKuser user -m -a<> 1530Sstevel@tonic-gateDL`'LUSER_RELAY', 1540Sstevel@tonic-gate`dnl') 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate# operators that cannot be in local usernames (i.e., network indicators) 1570Sstevel@tonic-gateCO @ % ifdef(`_NO_UUCP_', `', `!') 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate# a class with just dot (for identifying canonical names) 1600Sstevel@tonic-gateC.. 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate# a class with just a left bracket (for identifying domain literals) 1630Sstevel@tonic-gateC[[ 1640Sstevel@tonic-gate 1650Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 1660Sstevel@tonic-gate# access_db acceptance class 1670Sstevel@tonic-gateC{Accept}OK RELAY 1680Sstevel@tonic-gateifdef(`_DELAY_COMPAT_8_10_',`dnl 1690Sstevel@tonic-gateifdef(`_BLACKLIST_RCPT_',`dnl 1700Sstevel@tonic-gate# possible access_db RHS for spam friends/haters 1710Sstevel@tonic-gateC{SpamTag}SPAMFRIEND SPAMHATER')')', 1720Sstevel@tonic-gate`dnl') 1730Sstevel@tonic-gate 1740Sstevel@tonic-gatednl mark for "domain is ok" (resolved or accepted anyway) 1750Sstevel@tonic-gatedefine(`_RES_OK_', `OKR')dnl 1760Sstevel@tonic-gateifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',`dnl',`dnl 1770Sstevel@tonic-gate# Resolve map (to check if a host exists in check_mail) 1780Sstevel@tonic-gateKresolve host -a<_RES_OK_> -T<TEMP>') 1790Sstevel@tonic-gateC{ResOk}_RES_OK_ 1800Sstevel@tonic-gate 1810Sstevel@tonic-gateifdef(`_NEED_MACRO_MAP_', `dnl 1820Sstevel@tonic-gateifdef(`_MACRO_MAP_', `', `# macro storage map 1830Sstevel@tonic-gatedefine(`_MACRO_MAP_', `1')dnl 1840Sstevel@tonic-gateKmacro macro')', `dnl') 1850Sstevel@tonic-gate 1860Sstevel@tonic-gateifdef(`confCR_FILE', `dnl 1870Sstevel@tonic-gate# Hosts for which relaying is permitted ($=R) 1880Sstevel@tonic-gateFR`'confCR_FILE', 1890Sstevel@tonic-gate`dnl') 1900Sstevel@tonic-gate 1910Sstevel@tonic-gatedefine(`TLS_SRV_TAG', `"TLS_Srv"')dnl 1920Sstevel@tonic-gatedefine(`TLS_CLT_TAG', `"TLS_Clt"')dnl 1930Sstevel@tonic-gatedefine(`TLS_RCPT_TAG', `"TLS_Rcpt"')dnl 1940Sstevel@tonic-gatedefine(`TLS_TRY_TAG', `"Try_TLS"')dnl 1950Sstevel@tonic-gatedefine(`SRV_FEAT_TAG', `"Srv_Features"')dnl 1960Sstevel@tonic-gatednl this may be useful in other contexts too 1970Sstevel@tonic-gateifdef(`_ARITH_MAP_', `', `# arithmetic map 1980Sstevel@tonic-gatedefine(`_ARITH_MAP_', `1')dnl 1990Sstevel@tonic-gateKarith arith') 2000Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 2010Sstevel@tonic-gateifdef(`_MACRO_MAP_', `', `# macro storage map 2020Sstevel@tonic-gatedefine(`_MACRO_MAP_', `1')dnl 2030Sstevel@tonic-gateKmacro macro') 2040Sstevel@tonic-gate# possible values for TLS_connection in access map 2050Sstevel@tonic-gateC{Tls}VERIFY ENCR', `dnl') 2060Sstevel@tonic-gateifdef(`_CERT_REGEX_ISSUER_', `dnl 2070Sstevel@tonic-gate# extract relevant part from cert issuer 2080Sstevel@tonic-gateKCERTIssuer regex _CERT_REGEX_ISSUER_', `dnl') 2090Sstevel@tonic-gateifdef(`_CERT_REGEX_SUBJECT_', `dnl 2100Sstevel@tonic-gate# extract relevant part from cert subject 2110Sstevel@tonic-gateKCERTSubject regex _CERT_REGEX_SUBJECT_', `dnl') 2120Sstevel@tonic-gate 2130Sstevel@tonic-gateifdef(`LOCAL_RELAY', `dnl 2140Sstevel@tonic-gate# who I send unqualified names to if `FEATURE(stickyhost)' is used 2150Sstevel@tonic-gate# (null means deliver locally) 2160Sstevel@tonic-gateDR`'LOCAL_RELAY') 2170Sstevel@tonic-gate 2180Sstevel@tonic-gateifdef(`MAIL_HUB', `dnl 2190Sstevel@tonic-gate# who gets all local email traffic 2200Sstevel@tonic-gate# ($R has precedence for unqualified names if `FEATURE(stickyhost)' is used) 2210Sstevel@tonic-gateDH`'MAIL_HUB') 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate# dequoting map 2240Sstevel@tonic-gateKdequote dequote`'ifdef(`confDEQUOTE_OPTS', ` confDEQUOTE_OPTS', `') 2250Sstevel@tonic-gate 2260Sstevel@tonic-gatedivert(0)dnl # end of nullclient diversion 2270Sstevel@tonic-gate# class E: names that should be exposed as from this host, even if we masquerade 2280Sstevel@tonic-gate# class L: names that should be delivered locally, even if we have a relay 2290Sstevel@tonic-gate# class M: domains that should be converted to $M 2300Sstevel@tonic-gate# class N: domains that should not be converted to $M 2310Sstevel@tonic-gate#CL root 2320Sstevel@tonic-gateundivert(5)dnl 2330Sstevel@tonic-gateifdef(`_VIRTHOSTS_', `CR$={VirtHost}', `dnl') 2340Sstevel@tonic-gate 2350Sstevel@tonic-gateifdef(`MASQUERADE_NAME', `dnl 2360Sstevel@tonic-gate# who I masquerade as (null for no masquerading) (see also $=M) 2370Sstevel@tonic-gateDM`'MASQUERADE_NAME') 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate# my name for error messages 2400Sstevel@tonic-gateifdef(`confMAILER_NAME', `Dn`'confMAILER_NAME', `#DnMAILER-DAEMON') 2410Sstevel@tonic-gate 2420Sstevel@tonic-gateundivert(6)dnl LOCAL_CONFIG 2430Sstevel@tonic-gateinclude(_CF_DIR_`m4/version.m4') 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate############### 2460Sstevel@tonic-gate# Options # 2470Sstevel@tonic-gate############### 2480Sstevel@tonic-gateifdef(`confAUTO_REBUILD', 2490Sstevel@tonic-gate`errprint(WARNING: `confAUTO_REBUILD' is no longer valid. 2500Sstevel@tonic-gate There was a potential for a denial of service attack if this is set. 2510Sstevel@tonic-gate)')dnl 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate# strip message body to 7 bits on input? 2540Sstevel@tonic-gate_OPTION(SevenBitInput, `confSEVEN_BIT_INPUT', `False') 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate# 8-bit data handling 2570Sstevel@tonic-gate_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `pass8') 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate# wait for alias file rebuild (default units: minutes) 2600Sstevel@tonic-gate_OPTION(AliasWait, `confALIAS_WAIT', `5m') 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate# location of alias file 2630Sstevel@tonic-gate_OPTION(AliasFile, `ALIAS_FILE', `MAIL_SETTINGS_DIR`'aliases') 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate# minimum number of free blocks on filesystem 2660Sstevel@tonic-gate_OPTION(MinFreeBlocks, `confMIN_FREE_BLOCKS', `100') 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate# maximum message size 2690Sstevel@tonic-gate_OPTION(MaxMessageSize, `confMAX_MESSAGE_SIZE', `0') 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate# substitution for space (blank) characters 2720Sstevel@tonic-gate_OPTION(BlankSub, `confBLANK_SUB', `_') 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate# avoid connecting to "expensive" mailers on initial submission? 2750Sstevel@tonic-gate_OPTION(HoldExpensive, `confCON_EXPENSIVE', `False') 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate# checkpoint queue runs after every N successful deliveries 2780Sstevel@tonic-gate_OPTION(CheckpointInterval, `confCHECKPOINT_INTERVAL', `10') 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate# default delivery mode 2810Sstevel@tonic-gate_OPTION(DeliveryMode, `confDELIVERY_MODE', `background') 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate# error message header/file 2840Sstevel@tonic-gate_OPTION(ErrorHeader, `confERROR_MESSAGE', `MAIL_SETTINGS_DIR`'error-header') 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate# error mode 2870Sstevel@tonic-gate_OPTION(ErrorMode, `confERROR_MODE', `print') 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate# save Unix-style "From_" lines at top of header? 2900Sstevel@tonic-gate_OPTION(SaveFromLine, `confSAVE_FROM_LINES', `False') 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate# queue file mode (qf files) 2930Sstevel@tonic-gate_OPTION(QueueFileMode, `confQUEUE_FILE_MODE', `0600') 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate# temporary file mode 2960Sstevel@tonic-gate_OPTION(TempFileMode, `confTEMP_FILE_MODE', `0600') 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate# match recipients against GECOS field? 2990Sstevel@tonic-gate_OPTION(MatchGECOS, `confMATCH_GECOS', `False') 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate# maximum hop count 3020Sstevel@tonic-gate_OPTION(MaxHopCount, `confMAX_HOP', `25') 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate# location of help file 3050Sstevel@tonic-gateO HelpFile=ifdef(`HELP_FILE', HELP_FILE, `MAIL_SETTINGS_DIR`'helpfile') 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate# ignore dots as terminators in incoming messages? 3080Sstevel@tonic-gate_OPTION(IgnoreDots, `confIGNORE_DOTS', `False') 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate# name resolver options 3110Sstevel@tonic-gate_OPTION(ResolverOptions, `confBIND_OPTS', `+AAONLY') 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate# deliver MIME-encapsulated error messages? 3140Sstevel@tonic-gate_OPTION(SendMimeErrors, `confMIME_FORMAT_ERRORS', `True') 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate# Forward file search path 3170Sstevel@tonic-gate_OPTION(ForwardPath, `confFORWARD_PATH', `/var/forward/$u:$z/.forward.$w:$z/.forward') 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate# open connection cache size 3200Sstevel@tonic-gate_OPTION(ConnectionCacheSize, `confMCI_CACHE_SIZE', `2') 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate# open connection cache timeout 3230Sstevel@tonic-gate_OPTION(ConnectionCacheTimeout, `confMCI_CACHE_TIMEOUT', `5m') 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate# persistent host status directory 3260Sstevel@tonic-gate_OPTION(HostStatusDirectory, `confHOST_STATUS_DIRECTORY', `.hoststat') 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate# single thread deliveries (requires HostStatusDirectory)? 3290Sstevel@tonic-gate_OPTION(SingleThreadDelivery, `confSINGLE_THREAD_DELIVERY', `False') 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate# use Errors-To: header? 3320Sstevel@tonic-gate_OPTION(UseErrorsTo, `confUSE_ERRORS_TO', `False') 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate# log level 3350Sstevel@tonic-gate_OPTION(LogLevel, `confLOG_LEVEL', `10') 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate# send to me too, even in an alias expansion? 3380Sstevel@tonic-gate_OPTION(MeToo, `confME_TOO', `True') 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate# verify RHS in newaliases? 3410Sstevel@tonic-gate_OPTION(CheckAliases, `confCHECK_ALIASES', `False') 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate# default messages to old style headers if no special punctuation? 3440Sstevel@tonic-gate_OPTION(OldStyleHeaders, `confOLD_STYLE_HEADERS', `False') 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate# SMTP daemon options 3470Sstevel@tonic-gateifelse(defn(`confDAEMON_OPTIONS'), `', `dnl', 3480Sstevel@tonic-gate`errprint(WARNING: `confDAEMON_OPTIONS' is no longer valid. 3490Sstevel@tonic-gate Use `DAEMON_OPTIONS()'; see cf/README. 3500Sstevel@tonic-gate)'dnl 3510Sstevel@tonic-gate`DAEMON_OPTIONS(`confDAEMON_OPTIONS')') 3520Sstevel@tonic-gateifelse(defn(`_DPO_'), `', 3530Sstevel@tonic-gate`ifdef(`_NETINET6_', `O DaemonPortOptions=Name=MTA-v4, Family=inet 3540Sstevel@tonic-gateO DaemonPortOptions=Name=MTA-v6, Family=inet6',`O DaemonPortOptions=Name=MTA')', `_DPO_') 3550Sstevel@tonic-gateifdef(`_NO_MSA_', `dnl', `O DaemonPortOptions=Port=587, Name=MSA, M=E') 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate# SMTP client options 3580Sstevel@tonic-gateifelse(defn(`confCLIENT_OPTIONS'), `', `dnl', 3590Sstevel@tonic-gate`errprint(WARNING: `confCLIENT_OPTIONS' is no longer valid. See cf/README for more information. 3600Sstevel@tonic-gate)'dnl 3610Sstevel@tonic-gate`CLIENT_OPTIONS(`confCLIENT_OPTIONS')') 3620Sstevel@tonic-gateifelse(defn(`_CPO_'), `', 3630Sstevel@tonic-gate`#O ClientPortOptions=Family=inet, Address=0.0.0.0', `_CPO_') 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate# Modifiers to `define' {daemon_flags} for direct submissions 3660Sstevel@tonic-gate_OPTION(DirectSubmissionModifiers, `confDIRECT_SUBMISSION_MODIFIERS', `') 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate# Use as mail submission program? See sendmail/SECURITY 3690Sstevel@tonic-gate_OPTION(UseMSP, `confUSE_MSP', `') 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate# privacy flags 3720Sstevel@tonic-gate_OPTION(PrivacyOptions, `confPRIVACY_FLAGS', `authwarnings') 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate# who (if anyone) should get extra copies of error messages 3750Sstevel@tonic-gate_OPTION(PostmasterCopy, `confCOPY_ERRORS_TO', `Postmaster') 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate# slope of queue-only function 3780Sstevel@tonic-gate_OPTION(QueueFactor, `confQUEUE_FACTOR', `600000') 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate# limit on number of concurrent queue runners 3810Sstevel@tonic-gate_OPTION(MaxQueueChildren, `confMAX_QUEUE_CHILDREN', `') 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate# maximum number of queue-runners per queue-grouping with multiple queues 3840Sstevel@tonic-gate_OPTION(MaxRunnersPerQueue, `confMAX_RUNNERS_PER_QUEUE', `1') 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate# priority of queue runners (nice(3)) 3870Sstevel@tonic-gate_OPTION(NiceQueueRun, `confNICE_QUEUE_RUN', `') 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate# shall we sort the queue by hostname first? 3900Sstevel@tonic-gate_OPTION(QueueSortOrder, `confQUEUE_SORT_ORDER', `priority') 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate# minimum time in queue before retry 3930Sstevel@tonic-gate_OPTION(MinQueueAge, `confMIN_QUEUE_AGE', `30m') 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate# how many jobs can you process in the queue? 396616Sjbeck_OPTION(MaxQueueRunSize, `confMAX_QUEUE_RUN_SIZE', `0') 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate# perform initial split of envelope without checking MX records 3990Sstevel@tonic-gate_OPTION(FastSplit, `confFAST_SPLIT', `1') 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate# queue directory 4020Sstevel@tonic-gateO QueueDirectory=ifdef(`QUEUE_DIR', QUEUE_DIR, `/var/spool/mqueue') 4030Sstevel@tonic-gate 404*3544Sjbeck# key for shared memory; 0 to turn off, -1 to auto-select 4050Sstevel@tonic-gate_OPTION(SharedMemoryKey, `confSHARED_MEMORY_KEY', `0') 4060Sstevel@tonic-gate 407*3544Sjbeck# file to store auto-selected key for shared memory (SharedMemoryKey = -1) 408*3544Sjbeck_OPTION(SharedMemoryKeyFile, `confSHARED_MEMORY_KEY_FILE', `') 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate# timeouts (many of these) 4110Sstevel@tonic-gate_OPTION(Timeout.initial, `confTO_INITIAL', `5m') 4120Sstevel@tonic-gate_OPTION(Timeout.connect, `confTO_CONNECT', `5m') 4130Sstevel@tonic-gate_OPTION(Timeout.aconnect, `confTO_ACONNECT', `0s') 4140Sstevel@tonic-gate_OPTION(Timeout.iconnect, `confTO_ICONNECT', `5m') 4150Sstevel@tonic-gate_OPTION(Timeout.helo, `confTO_HELO', `5m') 4160Sstevel@tonic-gate_OPTION(Timeout.mail, `confTO_MAIL', `10m') 4170Sstevel@tonic-gate_OPTION(Timeout.rcpt, `confTO_RCPT', `1h') 4180Sstevel@tonic-gate_OPTION(Timeout.datainit, `confTO_DATAINIT', `5m') 4190Sstevel@tonic-gate_OPTION(Timeout.datablock, `confTO_DATABLOCK', `1h') 4200Sstevel@tonic-gate_OPTION(Timeout.datafinal, `confTO_DATAFINAL', `1h') 4210Sstevel@tonic-gate_OPTION(Timeout.rset, `confTO_RSET', `5m') 4220Sstevel@tonic-gate_OPTION(Timeout.quit, `confTO_QUIT', `2m') 4230Sstevel@tonic-gate_OPTION(Timeout.misc, `confTO_MISC', `2m') 4240Sstevel@tonic-gate_OPTION(Timeout.command, `confTO_COMMAND', `1h') 4250Sstevel@tonic-gate_OPTION(Timeout.ident, `confTO_IDENT', `5s') 4260Sstevel@tonic-gate_OPTION(Timeout.fileopen, `confTO_FILEOPEN', `60s') 4270Sstevel@tonic-gate_OPTION(Timeout.control, `confTO_CONTROL', `2m') 4280Sstevel@tonic-gate_OPTION(Timeout.queuereturn, `confTO_QUEUERETURN', `5d') 4290Sstevel@tonic-gate_OPTION(Timeout.queuereturn.normal, `confTO_QUEUERETURN_NORMAL', `5d') 4300Sstevel@tonic-gate_OPTION(Timeout.queuereturn.urgent, `confTO_QUEUERETURN_URGENT', `2d') 4310Sstevel@tonic-gate_OPTION(Timeout.queuereturn.non-urgent, `confTO_QUEUERETURN_NONURGENT', `7d') 4320Sstevel@tonic-gate_OPTION(Timeout.queuereturn.dsn, `confTO_QUEUERETURN_DSN', `5d') 4330Sstevel@tonic-gate_OPTION(Timeout.queuewarn, `confTO_QUEUEWARN', `4h') 4340Sstevel@tonic-gate_OPTION(Timeout.queuewarn.normal, `confTO_QUEUEWARN_NORMAL', `4h') 4350Sstevel@tonic-gate_OPTION(Timeout.queuewarn.urgent, `confTO_QUEUEWARN_URGENT', `1h') 4360Sstevel@tonic-gate_OPTION(Timeout.queuewarn.non-urgent, `confTO_QUEUEWARN_NONURGENT', `12h') 4370Sstevel@tonic-gate_OPTION(Timeout.queuewarn.dsn, `confTO_QUEUEWARN_DSN', `4h') 4380Sstevel@tonic-gate_OPTION(Timeout.hoststatus, `confTO_HOSTSTATUS', `30m') 4390Sstevel@tonic-gate_OPTION(Timeout.resolver.retrans, `confTO_RESOLVER_RETRANS', `5s') 4400Sstevel@tonic-gate_OPTION(Timeout.resolver.retrans.first, `confTO_RESOLVER_RETRANS_FIRST', `5s') 4410Sstevel@tonic-gate_OPTION(Timeout.resolver.retrans.normal, `confTO_RESOLVER_RETRANS_NORMAL', `5s') 4420Sstevel@tonic-gate_OPTION(Timeout.resolver.retry, `confTO_RESOLVER_RETRY', `4') 4430Sstevel@tonic-gate_OPTION(Timeout.resolver.retry.first, `confTO_RESOLVER_RETRY_FIRST', `4') 4440Sstevel@tonic-gate_OPTION(Timeout.resolver.retry.normal, `confTO_RESOLVER_RETRY_NORMAL', `4') 4450Sstevel@tonic-gate_OPTION(Timeout.lhlo, `confTO_LHLO', `2m') 4460Sstevel@tonic-gate_OPTION(Timeout.auth, `confTO_AUTH', `10m') 4470Sstevel@tonic-gate_OPTION(Timeout.starttls, `confTO_STARTTLS', `1h') 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate# time for DeliverBy; extension disabled if less than 0 4500Sstevel@tonic-gate_OPTION(DeliverByMin, `confDELIVER_BY_MIN', `0') 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate# should we not prune routes in route-addr syntax addresses? 4530Sstevel@tonic-gate_OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES', `False') 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate# queue up everything before forking? 4560Sstevel@tonic-gate_OPTION(SuperSafe, `confSAFE_QUEUE', `True') 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate# status file 459*3544Sjbeck_OPTION(StatusFile, `STATUS_FILE') 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate# time zone handling: 4620Sstevel@tonic-gate# if undefined, use system default 4630Sstevel@tonic-gate# if defined but null, use TZ envariable passed in 4640Sstevel@tonic-gate# if defined and non-null, use that info 4650Sstevel@tonic-gateifelse(confTIME_ZONE, `USE_SYSTEM', `#O TimeZoneSpec=', 4660Sstevel@tonic-gate confTIME_ZONE, `USE_TZ', `O TimeZoneSpec=', 4670Sstevel@tonic-gate `O TimeZoneSpec=confTIME_ZONE') 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate# default UID (can be username or userid:groupid) 4700Sstevel@tonic-gate_OPTION(DefaultUser, `confDEF_USER_ID', `mailnull') 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate# list of locations of user database file (null means no lookup) 4730Sstevel@tonic-gate_OPTION(UserDatabaseSpec, `confUSERDB_SPEC', `MAIL_SETTINGS_DIR`'userdb') 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate# fallback MX host 4760Sstevel@tonic-gate_OPTION(FallbackMXhost, `confFALLBACK_MX', `fall.back.host.net') 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate# fallback smart host 4790Sstevel@tonic-gate_OPTION(FallbackSmartHost, `confFALLBACK_SMARTHOST', `fall.back.host.net') 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate# if we are the best MX host for a site, try it directly instead of config err 4820Sstevel@tonic-gate_OPTION(TryNullMXList, `confTRY_NULL_MX_LIST', `False') 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate# load average at which we just queue messages 4850Sstevel@tonic-gate_OPTION(QueueLA, `confQUEUE_LA', `8') 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate# load average at which we refuse connections 4880Sstevel@tonic-gate_OPTION(RefuseLA, `confREFUSE_LA', `12') 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate# log interval when refusing connections for this long 4910Sstevel@tonic-gate_OPTION(RejectLogInterval, `confREJECT_LOG_INTERVAL', `3h') 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate# load average at which we delay connections; 0 means no limit 4940Sstevel@tonic-gate_OPTION(DelayLA, `confDELAY_LA', `0') 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate# maximum number of children we allow at one time 4970Sstevel@tonic-gate_OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `0') 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate# maximum number of new connections per second 5000Sstevel@tonic-gate_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `0') 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate# Width of the window 5030Sstevel@tonic-gate_OPTION(ConnectionRateWindowSize, `confCONNECTION_RATE_WINDOW_SIZE', `60s') 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate# work recipient factor 5060Sstevel@tonic-gate_OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', `30000') 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate# deliver each queued job in a separate process? 5090Sstevel@tonic-gate_OPTION(ForkEachJob, `confSEPARATE_PROC', `False') 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate# work class factor 5120Sstevel@tonic-gate_OPTION(ClassFactor, `confWORK_CLASS_FACTOR', `1800') 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate# work time factor 5150Sstevel@tonic-gate_OPTION(RetryFactor, `confWORK_TIME_FACTOR', `90000') 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate# default character set 5180Sstevel@tonic-gate_OPTION(DefaultCharSet, `confDEF_CHAR_SET', `unknown-8bit') 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others) 5210Sstevel@tonic-gate_OPTION(ServiceSwitchFile, `confSERVICE_SWITCH_FILE', `MAIL_SETTINGS_DIR`'service.switch') 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate# hosts file (normally /etc/hosts) 5240Sstevel@tonic-gate_OPTION(HostsFile, `confHOSTS_FILE', `/etc/hosts') 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate# dialup line delay on connection failure 527616Sjbeck_OPTION(DialDelay, `confDIAL_DELAY', `0s') 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate# action to take if there are no recipients in the message 530616Sjbeck_OPTION(NoRecipientAction, `confNO_RCPT_ACTION', `none') 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate# chrooted environment for writing to files 533616Sjbeck_OPTION(SafeFileEnvironment, `confSAFE_FILE_ENV', `') 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate# are colons OK in addresses? 5360Sstevel@tonic-gate_OPTION(ColonOkInAddr, `confCOLON_OK_IN_ADDR', `True') 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate# shall I avoid expanding CNAMEs (violates protocols)? 5390Sstevel@tonic-gate_OPTION(DontExpandCnames, `confDONT_EXPAND_CNAMES', `False') 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate# SMTP initial login message (old $e macro) 5420Sstevel@tonic-gate_OPTION(SmtpGreetingMessage, `confSMTP_LOGIN_MSG', `$j Sendmail $v ready at $b') 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate# UNIX initial From header format (old $l macro) 5450Sstevel@tonic-gate_OPTION(UnixFromLine, `confFROM_LINE', `From $g $d') 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate# From: lines that have embedded newlines are unwrapped onto one line 5480Sstevel@tonic-gate_OPTION(SingleLineFromHeader, `confSINGLE_LINE_FROM_HEADER', `False') 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate# Allow HELO SMTP command that does not `include' a host name 5510Sstevel@tonic-gate_OPTION(AllowBogusHELO, `confALLOW_BOGUS_HELO', `False') 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) 5540Sstevel@tonic-gate_OPTION(MustQuoteChars, `confMUST_QUOTE_CHARS', `.') 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate# delimiter (operator) characters (old $o macro) 5570Sstevel@tonic-gate_OPTION(OperatorChars, `confOPERATORS', `.:@[]') 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate# shall I avoid calling initgroups(3) because of high NIS costs? 5600Sstevel@tonic-gate_OPTION(DontInitGroups, `confDONT_INIT_GROUPS', `False') 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate# are group-writable `:include:' and .forward files (un)trustworthy? 5630Sstevel@tonic-gate# True (the default) means they are not trustworthy. 5640Sstevel@tonic-gate_OPTION(UnsafeGroupWrites, `confUNSAFE_GROUP_WRITES', `True') 5650Sstevel@tonic-gateifdef(`confUNSAFE_GROUP_WRITES', 5660Sstevel@tonic-gate`errprint(`WARNING: confUNSAFE_GROUP_WRITES is deprecated; use confDONT_BLAME_SENDMAIL. 5670Sstevel@tonic-gate')') 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate# where do errors that occur when sending errors get sent? 5700Sstevel@tonic-gate_OPTION(DoubleBounceAddress, `confDOUBLE_BOUNCE_ADDRESS', `postmaster') 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate# where to save bounces if all else fails 5730Sstevel@tonic-gate_OPTION(DeadLetterDrop, `confDEAD_LETTER_DROP', `/var/tmp/dead.letter') 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate# what user id do we assume for the majority of the processing? 5760Sstevel@tonic-gate_OPTION(RunAsUser, `confRUN_AS_USER', `sendmail') 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate# maximum number of recipients per SMTP envelope 5790Sstevel@tonic-gate_OPTION(MaxRecipientsPerMessage, `confMAX_RCPTS_PER_MESSAGE', `0') 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate# limit the rate recipients per SMTP envelope are accepted 5820Sstevel@tonic-gate# once the threshold number of recipients have been rejected 5830Sstevel@tonic-gate_OPTION(BadRcptThrottle, `confBAD_RCPT_THROTTLE', `0') 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate# shall we get local names from our installed interfaces? 5860Sstevel@tonic-gate_OPTION(DontProbeInterfaces, `confDONT_PROBE_INTERFACES', `False') 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate# Return-Receipt-To: header implies DSN request 5890Sstevel@tonic-gate_OPTION(RrtImpliesDsn, `confRRT_IMPLIES_DSN', `False') 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate# override connection address (for testing) 5920Sstevel@tonic-gate_OPTION(ConnectOnlyTo, `confCONNECT_ONLY_TO', `0.0.0.0') 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate# Trusted user for file ownership and starting the daemon 5950Sstevel@tonic-gate_OPTION(TrustedUser, `confTRUSTED_USER', `root') 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate# Control socket for daemon management 5980Sstevel@tonic-gate_OPTION(ControlSocketName, `confCONTROL_SOCKET_NAME', `/var/spool/mqueue/.control') 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate# Maximum MIME header length to protect MUAs 6010Sstevel@tonic-gate_OPTION(MaxMimeHeaderLength, `confMAX_MIME_HEADER_LENGTH', `2048/1024') 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate# Maximum length of the sum of all headers 6040Sstevel@tonic-gate_OPTION(MaxHeadersLength, `confMAX_HEADERS_LENGTH', `32768') 6050Sstevel@tonic-gate 6060Sstevel@tonic-gate# Maximum depth of alias recursion 6070Sstevel@tonic-gate_OPTION(MaxAliasRecursion, `confMAX_ALIAS_RECURSION', `10') 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate# location of pid file 6100Sstevel@tonic-gate_OPTION(PidFile, `confPID_FILE', `/var/run/sendmail.pid') 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate# Prefix string for the process title shown on 'ps' listings 6130Sstevel@tonic-gate_OPTION(ProcessTitlePrefix, `confPROCESS_TITLE_PREFIX', `prefix') 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate# Data file (df) memory-buffer file maximum size 6160Sstevel@tonic-gate_OPTION(DataFileBufferSize, `confDF_BUFFER_SIZE', `4096') 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate# Transcript file (xf) memory-buffer file maximum size 6190Sstevel@tonic-gate_OPTION(XscriptFileBufferSize, `confXF_BUFFER_SIZE', `4096') 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate# lookup type to find information about local mailboxes 6220Sstevel@tonic-gate_OPTION(MailboxDatabase, `confMAILBOX_DATABASE', `pw') 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate# override compile time flag REQUIRES_DIR_FSYNC 6250Sstevel@tonic-gate_OPTION(RequiresDirfsync, `confREQUIRES_DIR_FSYNC', `true') 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate# list of authentication mechanisms 6280Sstevel@tonic-gate_OPTION(AuthMechanisms, `confAUTH_MECHANISMS', `EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5') 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate# Authentication realm 6310Sstevel@tonic-gate_OPTION(AuthRealm, `confAUTH_REALM', `') 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate# default authentication information for outgoing connections 6340Sstevel@tonic-gate_OPTION(DefaultAuthInfo, `confDEF_AUTH_INFO', `MAIL_SETTINGS_DIR`'default-auth-info') 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate# SMTP AUTH flags 6370Sstevel@tonic-gate_OPTION(AuthOptions, `confAUTH_OPTIONS', `') 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate# SMTP AUTH maximum encryption strength 6400Sstevel@tonic-gate_OPTION(AuthMaxBits, `confAUTH_MAX_BITS', `') 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate# SMTP STARTTLS server options 6430Sstevel@tonic-gate_OPTION(TLSSrvOptions, `confTLS_SRV_OPTIONS', `') 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate# Input mail filters 6460Sstevel@tonic-gate_OPTION(InputMailFilters, `confINPUT_MAIL_FILTERS', `') 6470Sstevel@tonic-gate 6480Sstevel@tonic-gateifelse(len(X`'_MAIL_FILTERS_DEF), `1', `dnl', `dnl 6490Sstevel@tonic-gate# Milter options 6500Sstevel@tonic-gate_OPTION(Milter.LogLevel, `confMILTER_LOG_LEVEL', `') 6510Sstevel@tonic-gate_OPTION(Milter.macros.connect, `confMILTER_MACROS_CONNECT', `') 6520Sstevel@tonic-gate_OPTION(Milter.macros.helo, `confMILTER_MACROS_HELO', `') 6530Sstevel@tonic-gate_OPTION(Milter.macros.envfrom, `confMILTER_MACROS_ENVFROM', `') 6540Sstevel@tonic-gate_OPTION(Milter.macros.envrcpt, `confMILTER_MACROS_ENVRCPT', `') 6550Sstevel@tonic-gate_OPTION(Milter.macros.eom, `confMILTER_MACROS_EOM', `')') 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate# CA directory 6580Sstevel@tonic-gate_OPTION(CACertPath, `confCACERT_PATH', `') 6590Sstevel@tonic-gate# CA file 6600Sstevel@tonic-gate_OPTION(CACertFile, `confCACERT', `') 6610Sstevel@tonic-gate# Server Cert 6620Sstevel@tonic-gate_OPTION(ServerCertFile, `confSERVER_CERT', `') 6630Sstevel@tonic-gate# Server private key 6640Sstevel@tonic-gate_OPTION(ServerKeyFile, `confSERVER_KEY', `') 6650Sstevel@tonic-gate# Client Cert 6660Sstevel@tonic-gate_OPTION(ClientCertFile, `confCLIENT_CERT', `') 6670Sstevel@tonic-gate# Client private key 6680Sstevel@tonic-gate_OPTION(ClientKeyFile, `confCLIENT_KEY', `') 6690Sstevel@tonic-gate# File containing certificate revocation lists 6700Sstevel@tonic-gate_OPTION(CRLFile, `confCRL', `') 6710Sstevel@tonic-gate# DHParameters (only required if DSA/DH is used) 6720Sstevel@tonic-gate_OPTION(DHParameters, `confDH_PARAMETERS', `') 6730Sstevel@tonic-gate# Random data source (required for systems without /dev/urandom under OpenSSL) 6740Sstevel@tonic-gate_OPTION(RandFile, `confRAND_FILE', `') 6750Sstevel@tonic-gate 676*3544Sjbeck# Maximum number of "useless" commands before slowing down 677*3544Sjbeck_OPTION(MaxNOOPCommands, `confMAX_NOOP_COMMANDS', `20') 678*3544Sjbeck 679*3544Sjbeck# Name to use for EHLO (defaults to $j) 680*3544Sjbeck_OPTION(HeloName, `confHELO_NAME') 681*3544Sjbeck 6820Sstevel@tonic-gate############################ 6830Sstevel@tonic-gate`# QUEUE GROUP DEFINITIONS #' 6840Sstevel@tonic-gate############################ 6850Sstevel@tonic-gate_QUEUE_GROUP_ 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate########################### 6880Sstevel@tonic-gate# Message precedences # 6890Sstevel@tonic-gate########################### 6900Sstevel@tonic-gate 6910Sstevel@tonic-gatePfirst-class=0 6920Sstevel@tonic-gatePspecial-delivery=100 6930Sstevel@tonic-gatePlist=-30 6940Sstevel@tonic-gatePbulk=-60 6950Sstevel@tonic-gatePjunk=-100 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate##################### 6980Sstevel@tonic-gate# Trusted users # 6990Sstevel@tonic-gate##################### 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate# this is equivalent to setting class "t" 7020Sstevel@tonic-gateifdef(`_USE_CT_FILE_', `', `#')Ft`'ifdef(`confCT_FILE', confCT_FILE, `MAIL_SETTINGS_DIR`'trusted-users') 7030Sstevel@tonic-gateTroot 7040Sstevel@tonic-gateTdaemon 7050Sstevel@tonic-gateifdef(`_NO_UUCP_', `dnl', `Tuucp') 7060Sstevel@tonic-gateifdef(`confTRUSTED_USERS', `T`'confTRUSTED_USERS', `dnl') 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate######################### 7090Sstevel@tonic-gate# Format of headers # 7100Sstevel@tonic-gate######################### 7110Sstevel@tonic-gate 7120Sstevel@tonic-gateifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `$?x$x <$g>$|$g$.')')dnl 7130Sstevel@tonic-gateifdef(`confMESSAGEID_HEADER',, `define(`confMESSAGEID_HEADER', `<$t.$i@$j>')')dnl 7140Sstevel@tonic-gateH?P?Return-Path: <$g> 7150Sstevel@tonic-gateHReceived: confRECEIVED_HEADER 7160Sstevel@tonic-gateH?D?Resent-Date: $a 7170Sstevel@tonic-gateH?D?Date: $a 7180Sstevel@tonic-gateH?F?Resent-From: confFROM_HEADER 7190Sstevel@tonic-gateH?F?From: confFROM_HEADER 7200Sstevel@tonic-gateH?x?Full-Name: $x 7210Sstevel@tonic-gate# HPosted-Date: $a 7220Sstevel@tonic-gate# H?l?Received-Date: $b 7230Sstevel@tonic-gateH?M?Resent-Message-Id: confMESSAGEID_HEADER 7240Sstevel@tonic-gateH?M?Message-Id: confMESSAGEID_HEADER 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate# 7270Sstevel@tonic-gate###################################################################### 7280Sstevel@tonic-gate###################################################################### 7290Sstevel@tonic-gate##### 7300Sstevel@tonic-gate##### REWRITING RULES 7310Sstevel@tonic-gate##### 7320Sstevel@tonic-gate###################################################################### 7330Sstevel@tonic-gate###################################################################### 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate############################################ 7360Sstevel@tonic-gate### Ruleset 3 -- Name Canonicalization ### 7370Sstevel@tonic-gate############################################ 7380Sstevel@tonic-gateScanonify=3 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate# handle null input (translate to <@> special case) 7410Sstevel@tonic-gateR$@ $@ <@> 7420Sstevel@tonic-gate 7430Sstevel@tonic-gate# strip group: syntax (not inside angle brackets!) and trailing semicolon 7440Sstevel@tonic-gateR$* $: $1 <@> mark addresses 7450Sstevel@tonic-gateR$* < $* > $* <@> $: $1 < $2 > $3 unmark <addr> 7460Sstevel@tonic-gateR@ $* <@> $: @ $1 unmark @host:... 7470Sstevel@tonic-gateR$* [ IPv6 : $+ ] <@> $: $1 [ IPv6 : $2 ] unmark IPv6 addr 7480Sstevel@tonic-gateR$* :: $* <@> $: $1 :: $2 unmark node::addr 7490Sstevel@tonic-gateR:`include': $* <@> $: :`include': $1 unmark :`include':... 7500Sstevel@tonic-gateR$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon 7510Sstevel@tonic-gateR$* : $* <@> $: $2 strip colon if marked 7520Sstevel@tonic-gateR$* <@> $: $1 unmark 7530Sstevel@tonic-gateR$* ; $1 strip trailing semi 7540Sstevel@tonic-gateR$* < $+ :; > $* $@ $2 :; <@> catch <list:;> 7550Sstevel@tonic-gateR$* < $* ; > $1 < $2 > bogus bracketed semi 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate# null input now results from list:; syntax 7580Sstevel@tonic-gateR$@ $@ :; <@> 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate# strip angle brackets -- note RFC733 heuristic to get innermost item 7610Sstevel@tonic-gateR$* $: < $1 > housekeeping <> 7620Sstevel@tonic-gateR$+ < $* > < $2 > strip excess on left 7630Sstevel@tonic-gateR< $* > $+ < $1 > strip excess on right 7640Sstevel@tonic-gateR<> $@ < @ > MAIL FROM:<> case 7650Sstevel@tonic-gateR< $+ > $: $1 remove housekeeping <> 7660Sstevel@tonic-gate 7670Sstevel@tonic-gateifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl 7680Sstevel@tonic-gate# make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later 7690Sstevel@tonic-gateR@ $+ , $+ @ $1 : $2 change all "," to ":" 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate# localize and dispose of route-based addresses 7720Sstevel@tonic-gatednl XXX: IPv6 colon conflict 7730Sstevel@tonic-gateifdef(`NO_NETINET6', `dnl', 7740Sstevel@tonic-gate`R@ [$+] : $+ $@ $>Canonify2 < @ [$1] > : $2 handle <route-addr>') 7750Sstevel@tonic-gateR@ $+ : $+ $@ $>Canonify2 < @$1 > : $2 handle <route-addr> 7760Sstevel@tonic-gatednl',`dnl 7770Sstevel@tonic-gate# strip route address <@a,@b,@c:user@d> -> <user@d> 7780Sstevel@tonic-gateR@ $+ , $+ $2 7790Sstevel@tonic-gateifdef(`NO_NETINET6', `dnl', 7800Sstevel@tonic-gate`R@ [ $* ] : $+ $2') 7810Sstevel@tonic-gateR@ $+ : $+ $2 7820Sstevel@tonic-gatednl') 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate# find focus for list syntax 7850Sstevel@tonic-gateR $+ : $* ; @ $+ $@ $>Canonify2 $1 : $2 ; < @ $3 > list syntax 7860Sstevel@tonic-gateR $+ : $* ; $@ $1 : $2; list syntax 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate# find focus for @ syntax addresses 7890Sstevel@tonic-gateR$+ @ $+ $: $1 < @ $2 > focus on domain 7900Sstevel@tonic-gateR$+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right 7910Sstevel@tonic-gateR$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical 7920Sstevel@tonic-gate 7930Sstevel@tonic-gatednl This is flagged as an error in S0; no need to silently fix it here. 7940Sstevel@tonic-gatednl # do some sanity checking 7950Sstevel@tonic-gatednl R$* < @ $~[ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs 7960Sstevel@tonic-gate 7970Sstevel@tonic-gateifdef(`_NO_UUCP_', `dnl', 7980Sstevel@tonic-gate`# convert old-style addresses to a domain-based address 7990Sstevel@tonic-gateR$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names 8000Sstevel@tonic-gateR$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps 8010Sstevel@tonic-gateR$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains 8020Sstevel@tonic-gate') 8030Sstevel@tonic-gateifdef(`_USE_DECNET_SYNTAX_', 8040Sstevel@tonic-gate`# convert node::user addresses into a domain-based address 8050Sstevel@tonic-gateR$- :: $+ $@ $>Canonify2 $2 < @ $1 .DECNET > resolve DECnet names 8060Sstevel@tonic-gateR$- . $- :: $+ $@ $>Canonify2 $3 < @ $1.$2 .DECNET > numeric DECnet addr 8070Sstevel@tonic-gate', 8080Sstevel@tonic-gate `dnl') 8090Sstevel@tonic-gate# if we have % signs, take the rightmost one 8100Sstevel@tonic-gateR$* % $* $1 @ $2 First make them all @s. 8110Sstevel@tonic-gateR$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. 8120Sstevel@tonic-gateR$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate# else we must be a local name 8150Sstevel@tonic-gateR$* $@ $>Canonify2 $1 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate################################################ 8190Sstevel@tonic-gate### Ruleset 96 -- bottom half of ruleset 3 ### 8200Sstevel@tonic-gate################################################ 8210Sstevel@tonic-gate 8220Sstevel@tonic-gateSCanonify2=96 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate# handle special cases for local names 8250Sstevel@tonic-gateR$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all 8260Sstevel@tonic-gateR$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain 8270Sstevel@tonic-gateifdef(`_NO_UUCP_', `dnl', 8280Sstevel@tonic-gate`R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain') 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate# check for IPv4/IPv6 domain literal 8310Sstevel@tonic-gateR$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [addr] 8320Sstevel@tonic-gateR$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal 8330Sstevel@tonic-gateR$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr 8340Sstevel@tonic-gate 8350Sstevel@tonic-gateifdef(`_DOMAIN_TABLE_', `dnl 8360Sstevel@tonic-gate# look up domains in the domain table 8370Sstevel@tonic-gateR$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3', `dnl') 8380Sstevel@tonic-gate 8390Sstevel@tonic-gateundivert(2)dnl LOCAL_RULE_3 8400Sstevel@tonic-gate 8410Sstevel@tonic-gateifdef(`_BITDOMAIN_TABLE_', `dnl 8420Sstevel@tonic-gate# handle BITNET mapping 8430Sstevel@tonic-gateR$* < @ $+ .BITNET > $* $: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3', `dnl') 8440Sstevel@tonic-gate 8450Sstevel@tonic-gateifdef(`_UUDOMAIN_TABLE_', `dnl 8460Sstevel@tonic-gate# handle UUCP mapping 8470Sstevel@tonic-gateR$* < @ $+ .UUCP > $* $: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3', `dnl') 8480Sstevel@tonic-gate 8490Sstevel@tonic-gateifdef(`_NO_UUCP_', `dnl', 8500Sstevel@tonic-gate`ifdef(`UUCP_RELAY', 8510Sstevel@tonic-gate`# pass UUCP addresses straight through 8520Sstevel@tonic-gateR$* < @ $+ . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', 8530Sstevel@tonic-gate`# if really UUCP, handle it immediately 8540Sstevel@tonic-gateifdef(`_CLASS_U_', 8550Sstevel@tonic-gate`R$* < @ $=U . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 8560Sstevel@tonic-gateifdef(`_CLASS_V_', 8570Sstevel@tonic-gate`R$* < @ $=V . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 8580Sstevel@tonic-gateifdef(`_CLASS_W_', 8590Sstevel@tonic-gate`R$* < @ $=W . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 8600Sstevel@tonic-gateifdef(`_CLASS_X_', 8610Sstevel@tonic-gate`R$* < @ $=X . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 8620Sstevel@tonic-gateifdef(`_CLASS_Y_', 8630Sstevel@tonic-gate`R$* < @ $=Y . UUCP > $* $@ $1 < @ $2 . UUCP . > $3', `dnl') 8640Sstevel@tonic-gate 8650Sstevel@tonic-gateifdef(`_NO_CANONIFY_', `dnl', `dnl 8660Sstevel@tonic-gate# try UUCP traffic as a local address 8670Sstevel@tonic-gateR$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 8680Sstevel@tonic-gateR$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3') 8690Sstevel@tonic-gate')') 8700Sstevel@tonic-gate# hostnames ending in class P are always canonical 8710Sstevel@tonic-gateR$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 8720Sstevel@tonic-gatednl apply the next rule only for hostnames not in class P 8730Sstevel@tonic-gatednl this even works for phrases in class P since . is in class P 8740Sstevel@tonic-gatednl which daemon flags are set? 8750Sstevel@tonic-gateR$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 8760Sstevel@tonic-gatednl the other rules in this section only apply if the hostname 8770Sstevel@tonic-gatednl does not end in class P hence no further checks are done here 8780Sstevel@tonic-gatednl if this ever changes make sure the lookups are "protected" again! 8790Sstevel@tonic-gateifdef(`_NO_CANONIFY_', `dnl 8800Sstevel@tonic-gatednl do not canonify unless: 8810Sstevel@tonic-gatednl domain ends in class {Canonify} (this does not work if the intersection 8820Sstevel@tonic-gatednl with class P is non-empty) 8830Sstevel@tonic-gatednl or {daemon_flags} has c set 8840Sstevel@tonic-gate# pass to name server to make hostname canonical if in class {Canonify} 8850Sstevel@tonic-gateR$* $| $* < @ $* $={Canonify} > $* $: $2 < @ $[ $3 $4 $] > $5 8860Sstevel@tonic-gate# pass to name server to make hostname canonical if requested 8870Sstevel@tonic-gateR$* c $* $| $* < @ $* > $* $: $3 < @ $[ $4 $] > $5 8880Sstevel@tonic-gatednl trailing dot? -> do not apply _CANONIFY_HOSTS_ 8890Sstevel@tonic-gateR$* $| $* < @ $+ . > $* $: $2 < @ $3 . > $4 8900Sstevel@tonic-gate# add a trailing dot to qualified hostnames so other rules will work 8910Sstevel@tonic-gateR$* $| $* < @ $+.$+ > $* $: $2 < @ $3.$4 . > $5 8920Sstevel@tonic-gateifdef(`_CANONIFY_HOSTS_', `dnl 8930Sstevel@tonic-gatednl this should only apply to unqualified hostnames 8940Sstevel@tonic-gatednl but if a valid character inside an unqualified hostname is an OperatorChar 8950Sstevel@tonic-gatednl then $- does not work. 8960Sstevel@tonic-gate# lookup unqualified hostnames 8970Sstevel@tonic-gateR$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4', `dnl')', `dnl 8980Sstevel@tonic-gatednl _NO_CANONIFY_ is not set: canonify unless: 8990Sstevel@tonic-gatednl {daemon_flags} contains CC (do not canonify) 9000Sstevel@tonic-gatednl but add a trailing dot to qualified hostnames so other rules will work 9010Sstevel@tonic-gatednl should we do this for every hostname: even unqualified? 9020Sstevel@tonic-gateR$* CC $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 9030Sstevel@tonic-gateR$* CC $* $| $* $: $3 9040Sstevel@tonic-gateifdef(`_FFR_NOCANONIFY_HEADERS', `dnl 9050Sstevel@tonic-gate# do not canonify header addresses 9060Sstevel@tonic-gateR$* $| $* < @ $* $~P > $* $: $&{addr_type} $| $2 < @ $3 $4 > $5 9070Sstevel@tonic-gateR$* h $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 9080Sstevel@tonic-gateR$* h $* $| $* $: $3', `dnl') 9090Sstevel@tonic-gate# pass to name server to make hostname canonical 9100Sstevel@tonic-gateR$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4') 9110Sstevel@tonic-gatednl remove {daemon_flags} for other cases 9120Sstevel@tonic-gateR$* $| $* $: $2 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate# local host aliases and pseudo-domains are always canonical 9150Sstevel@tonic-gateR$* < @ $=w > $* $: $1 < @ $2 . > $3 9160Sstevel@tonic-gateifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 9170Sstevel@tonic-gate`R$* < @ $* $=M > $* $: $1 < @ $2 $3 . > $4', 9180Sstevel@tonic-gate`R$* < @ $=M > $* $: $1 < @ $2 . > $3') 9190Sstevel@tonic-gateifdef(`_VIRTUSER_TABLE_', `dnl 9200Sstevel@tonic-gatednl virtual hosts are also canonical 9210Sstevel@tonic-gateifdef(`_VIRTUSER_ENTIRE_DOMAIN_', 9220Sstevel@tonic-gate`R$* < @ $* $={VirtHost} > $* $: $1 < @ $2 $3 . > $4', 9230Sstevel@tonic-gate`R$* < @ $={VirtHost} > $* $: $1 < @ $2 . > $3')', 9240Sstevel@tonic-gate`dnl') 9250Sstevel@tonic-gateifdef(`_GENERICS_TABLE_', `dnl 9260Sstevel@tonic-gatednl hosts for genericstable are also canonical 9270Sstevel@tonic-gateifdef(`_GENERICS_ENTIRE_DOMAIN_', 9280Sstevel@tonic-gate`R$* < @ $* $=G > $* $: $1 < @ $2 $3 . > $4', 9290Sstevel@tonic-gate`R$* < @ $=G > $* $: $1 < @ $2 . > $3')', 9300Sstevel@tonic-gate`dnl') 9310Sstevel@tonic-gatednl remove superfluous dots (maybe repeatedly) which may have been added 9320Sstevel@tonic-gatednl by one of the rules before 9330Sstevel@tonic-gateR$* < @ $* . . > $* $1 < @ $2 . > $3 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate################################################## 9370Sstevel@tonic-gate### Ruleset 4 -- Final Output Post-rewriting ### 9380Sstevel@tonic-gate################################################## 9390Sstevel@tonic-gateSfinal=4 9400Sstevel@tonic-gate 9410Sstevel@tonic-gateR$+ :; <@> $@ $1 : handle <list:;> 9420Sstevel@tonic-gateR$* <@> $@ handle <> and list:; 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate# strip trailing dot off possibly canonical name 9450Sstevel@tonic-gateR$* < @ $+ . > $* $1 < @ $2 > $3 9460Sstevel@tonic-gate 9470Sstevel@tonic-gate# eliminate internal code 9480Sstevel@tonic-gateR$* < @ *LOCAL* > $* $1 < @ $j > $2 9490Sstevel@tonic-gate 9500Sstevel@tonic-gate# externalize local domain info 9510Sstevel@tonic-gateR$* < $+ > $* $1 $2 $3 defocus 9520Sstevel@tonic-gateR@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 <route-addr> canonical 9530Sstevel@tonic-gateR@ $* $@ @ $1 ... and exit 9540Sstevel@tonic-gate 9550Sstevel@tonic-gateifdef(`_NO_UUCP_', `dnl', 9560Sstevel@tonic-gate`# UUCP must always be presented in old form 9570Sstevel@tonic-gateR$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u') 9580Sstevel@tonic-gate 9590Sstevel@tonic-gateifdef(`_USE_DECNET_SYNTAX_', 9600Sstevel@tonic-gate`# put DECnet back in :: form 9610Sstevel@tonic-gateR$+ @ $+ . DECNET $2 :: $1 u@h.DECNET => h::u', 9620Sstevel@tonic-gate `dnl') 9630Sstevel@tonic-gate# delete duplicate local names 9640Sstevel@tonic-gateR$+ % $=w @ $=w $1 @ $2 u%host@host => u@host 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate############################################################## 9690Sstevel@tonic-gate### Ruleset 97 -- recanonicalize and call ruleset zero ### 9700Sstevel@tonic-gate### (used for recursive calls) ### 9710Sstevel@tonic-gate############################################################## 9720Sstevel@tonic-gate 9730Sstevel@tonic-gateSRecurse=97 9740Sstevel@tonic-gateR$* $: $>canonify $1 9750Sstevel@tonic-gateR$* $@ $>parse $1 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate###################################### 9790Sstevel@tonic-gate### Ruleset 0 -- Parse Address ### 9800Sstevel@tonic-gate###################################### 9810Sstevel@tonic-gate 9820Sstevel@tonic-gateSparse=0 9830Sstevel@tonic-gate 9840Sstevel@tonic-gateR$* $: $>Parse0 $1 initial parsing 9850Sstevel@tonic-gateR<@> $#_LOCAL_ $: <@> special case error msgs 9860Sstevel@tonic-gateR$* $: $>ParseLocal $1 handle local hacks 9870Sstevel@tonic-gateR$* $: $>Parse1 $1 final parsing 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate# 9900Sstevel@tonic-gate# Parse0 -- do initial syntax checking and eliminate local addresses. 9910Sstevel@tonic-gate# This should either return with the (possibly modified) input 9920Sstevel@tonic-gate# or return with a #error mailer. It should not return with a 9930Sstevel@tonic-gate# #mailer other than the #error mailer. 9940Sstevel@tonic-gate# 9950Sstevel@tonic-gate 9960Sstevel@tonic-gateSParse0 9970Sstevel@tonic-gateR<@> $@ <@> special case error msgs 9980Sstevel@tonic-gateR$* : $* ; <@> $#error $@ 5.1.3 $: "_CODE553 List:; syntax illegal for recipient addresses" 9990Sstevel@tonic-gateR@ <@ $* > < @ $1 > catch "@@host" bogosity 10000Sstevel@tonic-gateR<@ $+> $#error $@ 5.1.3 $: "_CODE553 User address required" 10010Sstevel@tonic-gateR$+ <@> $#error $@ 5.1.3 $: "_CODE553 Hostname required" 10020Sstevel@tonic-gateR$* $: <> $1 10030Sstevel@tonic-gatednl allow tricks like [host1]:[host2] 10040Sstevel@tonic-gateR<> $* < @ [ $* ] : $+ > $* $1 < @ [ $2 ] : $3 > $4 10050Sstevel@tonic-gateR<> $* < @ [ $* ] , $+ > $* $1 < @ [ $2 ] , $3 > $4 10060Sstevel@tonic-gatednl but no a@[b]c 10070Sstevel@tonic-gateR<> $* < @ [ $* ] $+ > $* $#error $@ 5.1.2 $: "_CODE553 Invalid address" 10080Sstevel@tonic-gateR<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 10090Sstevel@tonic-gateR<> $* <$* : $* > $* $#error $@ 5.1.3 $: "_CODE553 Colon illegal in host name part" 10100Sstevel@tonic-gateR<> $* $1 10110Sstevel@tonic-gateR$* < @ . $* > $* $#error $@ 5.1.2 $: "_CODE553 Invalid host name" 10120Sstevel@tonic-gateR$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "_CODE553 Invalid host name" 10130Sstevel@tonic-gatednl no a@b@ 10140Sstevel@tonic-gateR$* < @ $* @ > $* $#error $@ 5.1.2 $: "_CODE553 Invalid route address" 10150Sstevel@tonic-gatednl no a@b@c 10160Sstevel@tonic-gateR$* @ $* < @ $* > $* $#error $@ 5.1.3 $: "_CODE553 Invalid route address" 10170Sstevel@tonic-gatednl comma only allowed before @; this check is not complete 10180Sstevel@tonic-gateR$* , $~O $* $#error $@ 5.1.3 $: "_CODE553 Invalid route address" 10190Sstevel@tonic-gate 10200Sstevel@tonic-gateifdef(`_STRICT_RFC821_', `# more RFC 821 checks 10210Sstevel@tonic-gateR$* . < @ $* > $* $#error $@ 5.1.2 $: "_CODE553 Local part must not end with a dot" 10220Sstevel@tonic-gateR. $* < @ $* > $* $#error $@ 5.1.2 $: "_CODE553 Local part must not begin with a dot" 10230Sstevel@tonic-gatednl', `dnl') 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate# now delete the local info -- note $=O to find characters that cause forwarding 10260Sstevel@tonic-gateR$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user 10270Sstevel@tonic-gateR< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... 10280Sstevel@tonic-gateR$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here 10290Sstevel@tonic-gateR< @ $+ > $#error $@ 5.1.3 $: "_CODE553 User address required" 10300Sstevel@tonic-gateR$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... 10310Sstevel@tonic-gateR$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" 10320Sstevel@tonic-gateR< @ *LOCAL* > $#error $@ 5.1.3 $: "_CODE553 User address required" 10330Sstevel@tonic-gateR$* $=O $* < @ *LOCAL* > 10340Sstevel@tonic-gate $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... 10350Sstevel@tonic-gateR$* < @ *LOCAL* > $: $1 10360Sstevel@tonic-gate 10370Sstevel@tonic-gate# 10380Sstevel@tonic-gate# Parse1 -- the bottom half of ruleset 0. 10390Sstevel@tonic-gate# 10400Sstevel@tonic-gate 10410Sstevel@tonic-gateSParse1 10420Sstevel@tonic-gateifdef(`_LDAP_ROUTING_', `dnl 10430Sstevel@tonic-gate# handle LDAP routing for hosts in $={LDAPRoute} 10440Sstevel@tonic-gateR$+ < @ $={LDAPRoute} . > $: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $2> <> 10450Sstevel@tonic-gateR$+ < @ $={LDAPRouteEquiv} . > $: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $M> <>', 10460Sstevel@tonic-gate`dnl') 10470Sstevel@tonic-gate 10480Sstevel@tonic-gateifdef(`_MAILER_smtp_', 10490Sstevel@tonic-gate`# handle numeric address spec 10500Sstevel@tonic-gatednl there is no check whether this is really an IP number 10510Sstevel@tonic-gateR$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec 10520Sstevel@tonic-gateR$* < @ [ $+ ] > $* $: $1 < @ [ $2 ] : $S > $3 Add smart host to path 10530Sstevel@tonic-gateR$* < @ [ $+ ] : > $* $#_SMTP_ $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send 10540Sstevel@tonic-gateR$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer 10550Sstevel@tonic-gateR$* < @ [ $+ ] : $+ > $* $#_SMTP_ $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer', 10560Sstevel@tonic-gate `dnl') 10570Sstevel@tonic-gate 10580Sstevel@tonic-gateifdef(`_VIRTUSER_TABLE_', `dnl 10590Sstevel@tonic-gate# handle virtual users 10600Sstevel@tonic-gateifdef(`_VIRTUSER_STOP_ONE_LEVEL_RECURSION_',`dnl 10610Sstevel@tonic-gatednl this is not a documented option 10620Sstevel@tonic-gatednl it stops looping in virtusertable mapping if input and output 10630Sstevel@tonic-gatednl are identical, i.e., if address A is mapped to A. 10640Sstevel@tonic-gatednl it does not deal with multi-level recursion 10650Sstevel@tonic-gate# handle full domains in RHS of virtusertable 10660Sstevel@tonic-gateR$+ < @ $+ > $: $(macro {RecipientAddress} $) $1 < @ $2 > 10670Sstevel@tonic-gateR$+ < @ $+ > $: <?> $1 < @ $2 > $| $>final $1 < @ $2 > 10680Sstevel@tonic-gateR<?> $+ $| $+ $: $1 $(macro {RecipientAddress} $@ $2 $) 10690Sstevel@tonic-gateR<?> $+ $| $* $: $1', 10700Sstevel@tonic-gate`dnl') 10710Sstevel@tonic-gateR$+ $: <!> $1 Mark for lookup 10720Sstevel@tonic-gatednl input: <!> local<@domain> 10730Sstevel@tonic-gateifdef(`_VIRTUSER_ENTIRE_DOMAIN_', 10740Sstevel@tonic-gate`R<!> $+ < @ $* $={VirtHost} . > $: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >', 10750Sstevel@tonic-gate`R<!> $+ < @ $={VirtHost} . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >') 10760Sstevel@tonic-gatednl input: <result-of-lookup | @> local<@domain> | <!> local<@domain> 10770Sstevel@tonic-gateR<!> $+ < @ $=w . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . > 10780Sstevel@tonic-gatednl if <@> local<@domain>: no match but try lookup 10790Sstevel@tonic-gatednl user+detail: try user++@domain if detail not empty 10800Sstevel@tonic-gateR<@> $+ + $+ < @ $* . > 10810Sstevel@tonic-gate $: < $(virtuser $1 + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 10820Sstevel@tonic-gatednl user+detail: try user+*@domain 10830Sstevel@tonic-gateR<@> $+ + $* < @ $* . > 10840Sstevel@tonic-gate $: < $(virtuser $1 + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 10850Sstevel@tonic-gatednl user+detail: try user@domain 10860Sstevel@tonic-gateR<@> $+ + $* < @ $* . > 10870Sstevel@tonic-gate $: < $(virtuser $1 @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 10880Sstevel@tonic-gatednl try default entry: @domain 10890Sstevel@tonic-gatednl ++@domain 10900Sstevel@tonic-gateR<@> $+ + $+ < @ $+ . > $: < $(virtuser + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 10910Sstevel@tonic-gatednl +*@domain 10920Sstevel@tonic-gateR<@> $+ + $* < @ $+ . > $: < $(virtuser + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . > 10930Sstevel@tonic-gatednl @domain if +detail exists 10940Sstevel@tonic-gatednl if no match, change marker to prevent a second @domain lookup 10950Sstevel@tonic-gateR<@> $+ + $* < @ $+ . > $: < $(virtuser @ $3 $@ $1 $@ $2 $@ +$2 $: ! $) > $1 + $2 < @ $3 . > 10960Sstevel@tonic-gatednl without +detail 10970Sstevel@tonic-gateR<@> $+ < @ $+ . > $: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . > 10980Sstevel@tonic-gatednl no match 10990Sstevel@tonic-gateR<@> $+ $: $1 11000Sstevel@tonic-gatednl remove mark 11010Sstevel@tonic-gateR<!> $+ $: $1 11020Sstevel@tonic-gateR< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 11030Sstevel@tonic-gateR< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 11040Sstevel@tonic-gateifdef(`_VIRTUSER_STOP_ONE_LEVEL_RECURSION_',`dnl 11050Sstevel@tonic-gate# check virtuser input address against output address, if same, skip recursion 11060Sstevel@tonic-gateR< $+ > $+ < @ $+ > $: < $1 > $2 < @ $3 > $| $1 11070Sstevel@tonic-gate# it is the same: stop now 11080Sstevel@tonic-gateR< $+ > $+ < @ $+ > $| $&{RecipientAddress} $: $>ParseLocal $>Parse0 $>canonify $1 11090Sstevel@tonic-gateR< $+ > $+ < @ $+ > $| $* $: < $1 > $2 < @ $3 > 11100Sstevel@tonic-gatednl', `dnl') 11110Sstevel@tonic-gatednl this is not a documented option 11120Sstevel@tonic-gatednl it performs no looping at all for virtusertable 11130Sstevel@tonic-gateifdef(`_NO_VIRTUSER_RECURSION_', 11140Sstevel@tonic-gate`R< $+ > $+ < @ $+ > $: $>ParseLocal $>Parse0 $>canonify $1', 11150Sstevel@tonic-gate`R< $+ > $+ < @ $+ > $: $>Recurse $1') 11160Sstevel@tonic-gatednl', `dnl') 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate# short circuit local delivery so forwarded email works 11190Sstevel@tonic-gateifdef(`_MAILER_usenet_', `dnl 11200Sstevel@tonic-gateR$+ . USENET < @ $=w . > $#usenet $@ usenet $: $1 handle usenet specially', `dnl') 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate 11230Sstevel@tonic-gateifdef(`_STICKY_LOCAL_DOMAIN_', 11240Sstevel@tonic-gate`R$+ < @ $=w . > $: < $H > $1 < @ $2 . > first try hub 11250Sstevel@tonic-gateR< $+ > $+ < $+ > $>MailerToTriple < $1 > $2 < $3 > yep .... 11260Sstevel@tonic-gatednl $H empty (but @$=w.) 11270Sstevel@tonic-gateR< > $+ + $* < $+ > $#_LOCAL_ $: $1 + $2 plussed name? 11280Sstevel@tonic-gateR< > $+ < $+ > $#_LOCAL_ $: @ $1 nope, local address', 11290Sstevel@tonic-gate`R$=L < @ $=w . > $#_LOCAL_ $: @ $1 special local names 11300Sstevel@tonic-gateR$+ < @ $=w . > $#_LOCAL_ $: $1 regular local name') 11310Sstevel@tonic-gate 11320Sstevel@tonic-gateifdef(`_MAILER_TABLE_', `dnl 11330Sstevel@tonic-gate# not local -- try mailer table lookup 11340Sstevel@tonic-gateR$* <@ $+ > $* $: < $2 > $1 < @ $2 > $3 extract host name 11350Sstevel@tonic-gateR< $+ . > $* $: < $1 > $2 strip trailing dot 11360Sstevel@tonic-gateR< $+ > $* $: < $(mailertable $1 $) > $2 lookup 11370Sstevel@tonic-gatednl it is $~[ instead of $- to avoid matches on IPv6 addresses 11380Sstevel@tonic-gateR< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check -- resolved? 11390Sstevel@tonic-gateR< $+ > $* $: $>Mailertable <$1> $2 try domain', 11400Sstevel@tonic-gate`dnl') 11410Sstevel@tonic-gateundivert(4)dnl UUCP rules from `MAILER(uucp)' 11420Sstevel@tonic-gate 11430Sstevel@tonic-gateifdef(`_NO_UUCP_', `dnl', 11440Sstevel@tonic-gate`# resolve remotely connected UUCP links (if any) 11450Sstevel@tonic-gateifdef(`_CLASS_V_', 11460Sstevel@tonic-gate`R$* < @ $=V . UUCP . > $* $: $>MailerToTriple < $V > $1 <@$2.UUCP.> $3', 11470Sstevel@tonic-gate `dnl') 11480Sstevel@tonic-gateifdef(`_CLASS_W_', 11490Sstevel@tonic-gate`R$* < @ $=W . UUCP . > $* $: $>MailerToTriple < $W > $1 <@$2.UUCP.> $3', 11500Sstevel@tonic-gate `dnl') 11510Sstevel@tonic-gateifdef(`_CLASS_X_', 11520Sstevel@tonic-gate`R$* < @ $=X . UUCP . > $* $: $>MailerToTriple < $X > $1 <@$2.UUCP.> $3', 11530Sstevel@tonic-gate `dnl')') 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate# resolve fake top level domains by forwarding to other hosts 11560Sstevel@tonic-gateifdef(`BITNET_RELAY', 11570Sstevel@tonic-gate`R$*<@$+.BITNET.>$* $: $>MailerToTriple < $B > $1 <@$2.BITNET.> $3 user@host.BITNET', 11580Sstevel@tonic-gate `dnl') 11590Sstevel@tonic-gateifdef(`DECNET_RELAY', 11600Sstevel@tonic-gate`R$*<@$+.DECNET.>$* $: $>MailerToTriple < $C > $1 <@$2.DECNET.> $3 user@host.DECNET', 11610Sstevel@tonic-gate `dnl') 11620Sstevel@tonic-gateifdef(`_MAILER_pop_', 11630Sstevel@tonic-gate`R$+ < @ POP. > $#pop $: $1 user@POP', 11640Sstevel@tonic-gate `dnl') 11650Sstevel@tonic-gateifdef(`_MAILER_fax_', 11660Sstevel@tonic-gate`R$+ < @ $+ .FAX. > $#fax $@ $2 $: $1 user@host.FAX', 11670Sstevel@tonic-gate`ifdef(`FAX_RELAY', 11680Sstevel@tonic-gate`R$*<@$+.FAX.>$* $: $>MailerToTriple < $F > $1 <@$2.FAX.> $3 user@host.FAX', 11690Sstevel@tonic-gate `dnl')') 11700Sstevel@tonic-gate 11710Sstevel@tonic-gateifdef(`UUCP_RELAY', 11720Sstevel@tonic-gate`# forward non-local UUCP traffic to our UUCP relay 11730Sstevel@tonic-gateR$*<@$*.UUCP.>$* $: $>MailerToTriple < $Y > $1 <@$2.UUCP.> $3 uucp mail', 11740Sstevel@tonic-gate`ifdef(`_MAILER_uucp_', 11750Sstevel@tonic-gate`# forward other UUCP traffic straight to UUCP 11760Sstevel@tonic-gateR$* < @ $+ .UUCP. > $* $#_UUCP_ $@ $2 $: $1 < @ $2 .UUCP. > $3 user@host.UUCP', 11770Sstevel@tonic-gate `dnl')') 11780Sstevel@tonic-gateifdef(`_MAILER_usenet_', ` 11790Sstevel@tonic-gate# addresses sent to net.group.USENET will get forwarded to a newsgroup 11800Sstevel@tonic-gateR$+ . USENET $#usenet $@ usenet $: $1', 11810Sstevel@tonic-gate `dnl') 11820Sstevel@tonic-gate 11830Sstevel@tonic-gateifdef(`_LOCAL_RULES_', 11840Sstevel@tonic-gate`# figure out what should stay in our local mail system 11850Sstevel@tonic-gateundivert(1)', `dnl') 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate# pass names that still have a host to a smarthost (if defined) 11880Sstevel@tonic-gateR$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name 11890Sstevel@tonic-gate 11900Sstevel@tonic-gate# deal with other remote names 11910Sstevel@tonic-gateifdef(`_MAILER_smtp_', 11920Sstevel@tonic-gate`R$* < @$* > $* $#_SMTP_ $@ $2 $: $1 < @ $2 > $3 user@host.domain', 11930Sstevel@tonic-gate`R$* < @$* > $* $#error $@ 5.1.2 $: "_CODE553 Unrecognized host name " $2') 11940Sstevel@tonic-gate 11950Sstevel@tonic-gate# handle locally delivered names 11960Sstevel@tonic-gateR$=L $#_LOCAL_ $: @ $1 special local names 11970Sstevel@tonic-gateR$+ $#_LOCAL_ $: $1 regular local names 11980Sstevel@tonic-gate 11990Sstevel@tonic-gate########################################################################### 12000Sstevel@tonic-gate### Ruleset 5 -- special rewriting after aliases have been expanded ### 12010Sstevel@tonic-gate########################################################################### 12020Sstevel@tonic-gate 12030Sstevel@tonic-gateSLocal_localaddr 12040Sstevel@tonic-gateSlocaladdr=5 12050Sstevel@tonic-gateR$+ $: $1 $| $>"Local_localaddr" $1 12060Sstevel@tonic-gateR$+ $| $#ok $@ $1 no change 12070Sstevel@tonic-gateR$+ $| $#$* $#$2 12080Sstevel@tonic-gateR$+ $| $* $: $1 12090Sstevel@tonic-gate 12100Sstevel@tonic-gateifdef(`_PRESERVE_LUSER_HOST_', `dnl 12110Sstevel@tonic-gate# Preserve rcpt_host in {Host} 12120Sstevel@tonic-gateR$+ $: $1 $| $&h $| $&{Host} check h and {Host} 12130Sstevel@tonic-gateR$+ $| $| $: $(macro {Host} $@ $) $1 no h or {Host} 12140Sstevel@tonic-gateR$+ $| $| $+ $: $1 h not set, {Host} set 12150Sstevel@tonic-gateR$+ $| +$* $| $* $: $1 h is +detail, {Host} set 12160Sstevel@tonic-gateR$+ $| $* @ $+ $| $* $: $(macro {Host} $@ @$3 $) $1 set {Host} to host in h 12170Sstevel@tonic-gateR$+ $| $+ $| $* $: $(macro {Host} $@ @$2 $) $1 set {Host} to h 12180Sstevel@tonic-gate')dnl 12190Sstevel@tonic-gate 12200Sstevel@tonic-gateifdef(`_FFR_5_', `dnl 12210Sstevel@tonic-gate# Preserve host in a macro 12220Sstevel@tonic-gateR$+ $: $(macro {LocalAddrHost} $) $1 12230Sstevel@tonic-gateR$+ @ $+ $: $(macro {LocalAddrHost} $@ @ $2 $) $1') 12240Sstevel@tonic-gate 12250Sstevel@tonic-gateifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `', `dnl 12260Sstevel@tonic-gate# deal with plussed users so aliases work nicely 12270Sstevel@tonic-gateR$+ + * $#_LOCAL_ $@ $&h $: $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') 12280Sstevel@tonic-gateR$+ + $* $#_LOCAL_ $@ + $2 $: $1 + *`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') 12290Sstevel@tonic-gate') 12300Sstevel@tonic-gate# prepend an empty "forward host" on the front 12310Sstevel@tonic-gateR$+ $: <> $1 12320Sstevel@tonic-gate 12330Sstevel@tonic-gateifdef(`LUSER_RELAY', `dnl 12340Sstevel@tonic-gate# send unrecognized local users to a relay host 12350Sstevel@tonic-gateifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `dnl 12360Sstevel@tonic-gateR< > $+ + $* $: < ? $L > <+ $2> $(user $1 $) look up user+ 12370Sstevel@tonic-gateR< > $+ $: < ? $L > < > $(user $1 $) look up user 12380Sstevel@tonic-gateR< ? $* > < $* > $+ <> $: < > $3 $2 found; strip $L 12390Sstevel@tonic-gateR< ? $* > < $* > $+ $: < $1 > $3 $2 not found', ` 12400Sstevel@tonic-gateR< > $+ $: < $L > $(user $1 $) look up user 12410Sstevel@tonic-gateR< $* > $+ <> $: < > $2 found; strip $L') 12420Sstevel@tonic-gateifdef(`_PRESERVE_LUSER_HOST_', `dnl 12430Sstevel@tonic-gateR< $+ > $+ $: < $1 > $2 $&{Host}') 12440Sstevel@tonic-gatednl') 12450Sstevel@tonic-gate 12460Sstevel@tonic-gateifdef(`MAIL_HUB', `dnl 12470Sstevel@tonic-gateR< > $+ $: < $H > $1 try hub', `dnl') 12480Sstevel@tonic-gateifdef(`LOCAL_RELAY', `dnl 12490Sstevel@tonic-gateR< > $+ $: < $R > $1 try relay', `dnl') 12500Sstevel@tonic-gateifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `dnl 12510Sstevel@tonic-gateR< > $+ $@ $1', `dnl 12520Sstevel@tonic-gateR< > $+ $: < > < $1 <> $&h > nope, restore +detail 12530Sstevel@tonic-gateifdef(`_PRESERVE_LUSER_HOST_', `dnl 12540Sstevel@tonic-gateR< > < $+ @ $+ <> + $* > $: < > < $1 + $3 @ $2 > check whether +detail') 12550Sstevel@tonic-gateR< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail 12560Sstevel@tonic-gateR< > < $+ <> $* > $: < > < $1 > else discard 12570Sstevel@tonic-gateR< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part 12580Sstevel@tonic-gateR< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') strip the extra + 12590Sstevel@tonic-gateR< > < $+ > $@ $1 no +detail 12600Sstevel@tonic-gateR$+ $: $1 <> $&h add +detail back in 12610Sstevel@tonic-gateifdef(`_PRESERVE_LUSER_HOST_', `dnl 12620Sstevel@tonic-gateR$+ @ $+ <> + $* $: $1 + $3 @ $2 check whether +detail') 12630Sstevel@tonic-gateR$+ <> + $* $: $1 + $2 check whether +detail 12640Sstevel@tonic-gateR$+ <> $* $: $1 else discard') 12650Sstevel@tonic-gateR< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension 12660Sstevel@tonic-gateR< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension 12670Sstevel@tonic-gateifdef(`_PRESERVE_LUSER_HOST_', `dnl 12680Sstevel@tonic-gatednl it is $~[ instead of $- to avoid matches on IPv6 addresses 12690Sstevel@tonic-gateR< $~[ : $+ > $+ @ $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $4 >') 12700Sstevel@tonic-gateR< $~[ : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > 12710Sstevel@tonic-gateifdef(`_PRESERVE_LUSER_HOST_', `dnl 12720Sstevel@tonic-gateR< $+ > $+ @ $+ $@ $>MailerToTriple < $1 > $2 < @ $3 >') 12730Sstevel@tonic-gateR< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > 12740Sstevel@tonic-gate 12750Sstevel@tonic-gateifdef(`_MAILER_TABLE_', `dnl 12760Sstevel@tonic-gateifdef(`_LDAP_ROUTING_', `dnl 12770Sstevel@tonic-gate################################################################### 12780Sstevel@tonic-gate### Ruleset LDAPMailertable -- mailertable lookup for LDAP ### 12790Sstevel@tonic-gatednl input: <Domain> FullAddress 12800Sstevel@tonic-gate################################################################### 12810Sstevel@tonic-gate 12820Sstevel@tonic-gateSLDAPMailertable 12830Sstevel@tonic-gateR< $+ > $* $: < $(mailertable $1 $) > $2 lookup 12840Sstevel@tonic-gateR< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check resolved? 12850Sstevel@tonic-gateR< $+ > $* $: < $1 > $>Mailertable <$1> $2 try domain 12860Sstevel@tonic-gateR< $+ > $#$* $#$2 found 12870Sstevel@tonic-gateR< $+ > $* $#_RELAY_ $@ $1 $: $2 not found, direct relay', 12880Sstevel@tonic-gate`dnl') 12890Sstevel@tonic-gate 12900Sstevel@tonic-gate################################################################### 12910Sstevel@tonic-gate### Ruleset 90 -- try domain part of mailertable entry ### 12920Sstevel@tonic-gatednl input: LeftPartOfDomain <RightPartOfDomain> FullAddress 12930Sstevel@tonic-gate################################################################### 12940Sstevel@tonic-gate 12950Sstevel@tonic-gateSMailertable=90 12960Sstevel@tonic-gatednl shift and check 12970Sstevel@tonic-gatednl %2 is not documented in cf/README 12980Sstevel@tonic-gateR$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4 12990Sstevel@tonic-gatednl it is $~[ instead of $- to avoid matches on IPv6 addresses 13000Sstevel@tonic-gateR$* <$~[ : $* > $* $>MailerToTriple < $2 : $3 > $4 check -- resolved? 13010Sstevel@tonic-gateR$* < . $+ > $* $@ $>Mailertable $1 . <$2> $3 no -- strip & try again 13020Sstevel@tonic-gatednl is $2 always empty? 13030Sstevel@tonic-gateR$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "." 13040Sstevel@tonic-gateR< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 "." found? 13050Sstevel@tonic-gatednl return full address 13060Sstevel@tonic-gateR< $* > $* $@ $2 no mailertable match', 13070Sstevel@tonic-gate`dnl') 13080Sstevel@tonic-gate 13090Sstevel@tonic-gate################################################################### 13100Sstevel@tonic-gate### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### 13110Sstevel@tonic-gatednl input: in general: <[mailer:]host> lp<@domain>rest 13120Sstevel@tonic-gatednl <> address -> address 13130Sstevel@tonic-gatednl <error:d.s.n:text> -> error 13140Sstevel@tonic-gatednl <error:keyword:text> -> error 13150Sstevel@tonic-gatednl <error:text> -> error 13160Sstevel@tonic-gatednl <mailer:user@host> lp<@domain>rest -> mailer host user 13170Sstevel@tonic-gatednl <mailer:host> address -> mailer host address 13180Sstevel@tonic-gatednl <localdomain> address -> address 13190Sstevel@tonic-gatednl <host> address -> relay host address 13200Sstevel@tonic-gate################################################################### 13210Sstevel@tonic-gate 13220Sstevel@tonic-gateSMailerToTriple=95 13230Sstevel@tonic-gateR< > $* $@ $1 strip off null relay 13240Sstevel@tonic-gateR< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 13250Sstevel@tonic-gateR< error : $- : $+ > $* $#error $@ $(dequote $1 $) $: $2 13260Sstevel@tonic-gateR< error : $+ > $* $#error $: $1 13270Sstevel@tonic-gateR< local : $* > $* $>CanonLocal < $1 > $2 13280Sstevel@tonic-gatednl it is $~[ instead of $- to avoid matches on IPv6 addresses 13290Sstevel@tonic-gateR< $~[ : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user 13300Sstevel@tonic-gateR< $~[ : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer 13310Sstevel@tonic-gateR< $=w > $* $@ $2 delete local host 13320Sstevel@tonic-gateR< $+ > $* $#_RELAY_ $@ $1 $: $2 use unqualified mailer 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate################################################################### 13350Sstevel@tonic-gate### Ruleset CanonLocal -- canonify local: syntax ### 13360Sstevel@tonic-gatednl input: <user> address 13370Sstevel@tonic-gatednl <x> <@host> : rest -> Recurse rest 13380Sstevel@tonic-gatednl <x> p1 $=O p2 <@host> -> Recurse p1 $=O p2 13390Sstevel@tonic-gatednl <> user <@host> rest -> local user@host user 13400Sstevel@tonic-gatednl <> user -> local user user 13410Sstevel@tonic-gatednl <user@host> lp <@domain> rest -> <user> lp <@host> [cont] 13420Sstevel@tonic-gatednl <user> lp <@host> rest -> local lp@host user 13430Sstevel@tonic-gatednl <user> lp -> local lp user 13440Sstevel@tonic-gate################################################################### 13450Sstevel@tonic-gate 13460Sstevel@tonic-gateSCanonLocal 13470Sstevel@tonic-gate# strip local host from routed addresses 13480Sstevel@tonic-gateR< $* > < @ $+ > : $+ $@ $>Recurse $3 13490Sstevel@tonic-gateR< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate# strip trailing dot from any host name that may appear 13520Sstevel@tonic-gateR< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate# handle local: syntax -- use old user, either with or without host 13550Sstevel@tonic-gateR< > $* < @ $* > $* $#_LOCAL_ $@ $1@$2 $: $1 13560Sstevel@tonic-gateR< > $+ $#_LOCAL_ $@ $1 $: $1 13570Sstevel@tonic-gate 13580Sstevel@tonic-gate# handle local:user@host syntax -- ignore host part 13590Sstevel@tonic-gateR< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > 13600Sstevel@tonic-gate 13610Sstevel@tonic-gate# handle local:user syntax 13620Sstevel@tonic-gateR< $+ > $* <@ $* > $* $#_LOCAL_ $@ $2@$3 $: $1 13630Sstevel@tonic-gateR< $+ > $* $#_LOCAL_ $@ $2 $: $1 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate################################################################### 13660Sstevel@tonic-gate### Ruleset 93 -- convert header names to masqueraded form ### 13670Sstevel@tonic-gate################################################################### 13680Sstevel@tonic-gate 13690Sstevel@tonic-gateSMasqHdr=93 13700Sstevel@tonic-gate 13710Sstevel@tonic-gateifdef(`_GENERICS_TABLE_', `dnl 13720Sstevel@tonic-gate# handle generics database 13730Sstevel@tonic-gateifdef(`_GENERICS_ENTIRE_DOMAIN_', 13740Sstevel@tonic-gatednl if generics should be applied add a @ as mark 13750Sstevel@tonic-gate`R$+ < @ $* $=G . > $: < $1@$2$3 > $1 < @ $2$3 . > @ mark', 13760Sstevel@tonic-gate`R$+ < @ $=G . > $: < $1@$2 > $1 < @ $2 . > @ mark') 13770Sstevel@tonic-gateR$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark 13780Sstevel@tonic-gatednl workspace: either user<@domain> or <user@domain> user <@domain> @ 13790Sstevel@tonic-gatednl ignore the first case for now 13800Sstevel@tonic-gatednl if it has the mark lookup full address 13810Sstevel@tonic-gatednl broken: %1 is full address not just detail 13820Sstevel@tonic-gateR< $+ > $+ < $* > @ $: < $(generics $1 $: @ $1 $) > $2 < $3 > 13830Sstevel@tonic-gatednl workspace: ... or <match|@user@domain> user <@domain> 13840Sstevel@tonic-gatednl no match, try user+detail@domain 13850Sstevel@tonic-gateR<@$+ + $* @ $+> $+ < @ $+ > 13860Sstevel@tonic-gate $: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) > $4 < @ $5 > 13870Sstevel@tonic-gateR<@$+ + $* @ $+> $+ < @ $+ > 13880Sstevel@tonic-gate $: < $(generics $1@$3 $: $) > $4 < @ $5 > 13890Sstevel@tonic-gatednl no match, remove mark 13900Sstevel@tonic-gateR<@$+ > $+ < @ $+ > $: < > $2 < @ $3 > 13910Sstevel@tonic-gatednl no match, try @domain for exceptions 13920Sstevel@tonic-gateR< > $+ < @ $+ . > $: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . > 13930Sstevel@tonic-gatednl workspace: ... or <match> user <@domain> 13940Sstevel@tonic-gatednl no match, try local part 13950Sstevel@tonic-gateR< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 > 13960Sstevel@tonic-gateR< > $+ + $* < @ $+ > $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 > 13970Sstevel@tonic-gateR< > $+ + $* < @ $+ > $: < $(generics $1 $: $) > $1 + $2 < @ $3 > 13980Sstevel@tonic-gateR< $* @ $* > $* < $* > $@ $>canonify $1 @ $2 found qualified 13990Sstevel@tonic-gateR< $+ > $* < $* > $: $>canonify $1 @ *LOCAL* found unqualified 14000Sstevel@tonic-gateR< > $* $: $1 not found', 14010Sstevel@tonic-gate`dnl') 14020Sstevel@tonic-gate 14030Sstevel@tonic-gate# do not masquerade anything in class N 14040Sstevel@tonic-gateR$* < @ $* $=N . > $@ $1 < @ $2 $3 . > 14050Sstevel@tonic-gate 14060Sstevel@tonic-gateifdef(`MASQUERADE_NAME', `dnl 14070Sstevel@tonic-gate# special case the users that should be exposed 14080Sstevel@tonic-gateR$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed 14090Sstevel@tonic-gateifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 14100Sstevel@tonic-gate`R$=E < @ $* $=M . > $@ $1 < @ $2 $3 . >', 14110Sstevel@tonic-gate`R$=E < @ $=M . > $@ $1 < @ $2 . >') 14120Sstevel@tonic-gateifdef(`_LIMITED_MASQUERADE_', `dnl', 14130Sstevel@tonic-gate`R$=E < @ $=w . > $@ $1 < @ $2 . >') 14140Sstevel@tonic-gate 14150Sstevel@tonic-gate# handle domain-specific masquerading 14160Sstevel@tonic-gateifdef(`_MASQUERADE_ENTIRE_DOMAIN_', 14170Sstevel@tonic-gate`R$* < @ $* $=M . > $* $: $1 < @ $2 $3 . @ $M > $4 convert masqueraded doms', 14180Sstevel@tonic-gate`R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms') 14190Sstevel@tonic-gateifdef(`_LIMITED_MASQUERADE_', `dnl', 14200Sstevel@tonic-gate`R$* < @ $=w . > $* $: $1 < @ $2 . @ $M > $3') 14210Sstevel@tonic-gateR$* < @ *LOCAL* > $* $: $1 < @ $j . @ $M > $2 14220Sstevel@tonic-gateR$* < @ $+ @ > $* $: $1 < @ $2 > $3 $M is null 14230Sstevel@tonic-gateR$* < @ $+ @ $+ > $* $: $1 < @ $3 . > $4 $M is not null 14240Sstevel@tonic-gatednl', `dnl no masquerading 14250Sstevel@tonic-gatednl just fix *LOCAL* leftovers 14260Sstevel@tonic-gateR$* < @ *LOCAL* > $@ $1 < @ $j . >') 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate################################################################### 14290Sstevel@tonic-gate### Ruleset 94 -- convert envelope names to masqueraded form ### 14300Sstevel@tonic-gate################################################################### 14310Sstevel@tonic-gate 14320Sstevel@tonic-gateSMasqEnv=94 14330Sstevel@tonic-gateifdef(`_MASQUERADE_ENVELOPE_', 14340Sstevel@tonic-gate`R$+ $@ $>MasqHdr $1', 14350Sstevel@tonic-gate`R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2') 14360Sstevel@tonic-gate 14370Sstevel@tonic-gate################################################################### 14380Sstevel@tonic-gate### Ruleset 98 -- local part of ruleset zero (can be null) ### 14390Sstevel@tonic-gate################################################################### 14400Sstevel@tonic-gate 14410Sstevel@tonic-gateSParseLocal=98 14420Sstevel@tonic-gateundivert(3)dnl LOCAL_RULE_0 14430Sstevel@tonic-gate 14440Sstevel@tonic-gateifdef(`_LDAP_ROUTING_', `dnl 14450Sstevel@tonic-gate###################################################################### 14460Sstevel@tonic-gate### LDAPExpand: Expand address using LDAP routing 14470Sstevel@tonic-gate### 14480Sstevel@tonic-gate### Parameters: 14490Sstevel@tonic-gate### <$1> -- parsed address (user < @ domain . >) (pass through) 14500Sstevel@tonic-gate### <$2> -- RFC822 address (user @ domain) (used for lookup) 14510Sstevel@tonic-gate### <$3> -- +detail information 14520Sstevel@tonic-gate### 14530Sstevel@tonic-gate### Returns: 14540Sstevel@tonic-gate### Mailer triplet ($#mailer $@ host $: address) 14550Sstevel@tonic-gate### Parsed address (user < @ domain . >) 14560Sstevel@tonic-gate###################################################################### 14570Sstevel@tonic-gate 14580Sstevel@tonic-gate# SMTP operation modes 14590Sstevel@tonic-gateC{SMTPOpModes} s d D 14600Sstevel@tonic-gate 14610Sstevel@tonic-gateSLDAPExpand 14620Sstevel@tonic-gate# do the LDAP lookups 14630Sstevel@tonic-gateR<$+><$+><$*> $: <$(ldapmra $2 $: $)> <$(ldapmh $2 $: $)> <$1> <$2> <$3> 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate# look for temporary failures and... 14660Sstevel@tonic-gateR<$* <TMPF>> <$*> <$+> <$+> <$*> $: $&{opMode} $| TMPF <$&{addr_type}> $| $3 14670Sstevel@tonic-gateR<$*> <$* <TMPF>> <$+> <$+> <$*> $: $&{opMode} $| TMPF <$&{addr_type}> $| $3 14680Sstevel@tonic-gateifelse(_LDAP_ROUTE_MAPTEMP_, `_TEMPFAIL_', `dnl 14690Sstevel@tonic-gate# ... temp fail RCPT SMTP commands 14700Sstevel@tonic-gateR$={SMTPOpModes} $| TMPF <e r> $| $+ $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."') 14710Sstevel@tonic-gate# ... return original address for MTA to queue up 14720Sstevel@tonic-gateR$* $| TMPF <$*> $| $+ $@ $3 14730Sstevel@tonic-gate 14740Sstevel@tonic-gate# if mailRoutingAddress and local or non-existant mailHost, 14750Sstevel@tonic-gate# return the new mailRoutingAddress 14760Sstevel@tonic-gateifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl 14770Sstevel@tonic-gateR<$+@$+> <$=w> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 $6 @ $2 14780Sstevel@tonic-gateR<$+@$+> <> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 $5 @ $2') 14790Sstevel@tonic-gateR<$+> <$=w> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 14800Sstevel@tonic-gateR<$+> <> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 14810Sstevel@tonic-gate 14820Sstevel@tonic-gate 14830Sstevel@tonic-gate# if mailRoutingAddress and non-local mailHost, 14840Sstevel@tonic-gate# relay to mailHost with new mailRoutingAddress 14850Sstevel@tonic-gateifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl 14860Sstevel@tonic-gateifdef(`_MAILER_TABLE_', `dnl 14870Sstevel@tonic-gate# check mailertable for host, relay from there 14880Sstevel@tonic-gateR<$+@$+> <$+> <$+> <$+> <$*> $>LDAPMailertable <$3> $>canonify $1 $6 @ $2', 14890Sstevel@tonic-gate`R<$+@$+> <$+> <$+> <$+> <$*> $#_RELAY_ $@ $3 $: $>canonify $1 $6 @ $2')') 14900Sstevel@tonic-gateifdef(`_MAILER_TABLE_', `dnl 14910Sstevel@tonic-gate# check mailertable for host, relay from there 14920Sstevel@tonic-gateR<$+> <$+> <$+> <$+> <$*> $>LDAPMailertable <$2> $>canonify $1', 14930Sstevel@tonic-gate`R<$+> <$+> <$+> <$+> <$*> $#_RELAY_ $@ $2 $: $>canonify $1') 14940Sstevel@tonic-gate 14950Sstevel@tonic-gate# if no mailRoutingAddress and local mailHost, 14960Sstevel@tonic-gate# return original address 14970Sstevel@tonic-gateR<> <$=w> <$+> <$+> <$*> $@ $2 14980Sstevel@tonic-gate 14990Sstevel@tonic-gate 15000Sstevel@tonic-gate# if no mailRoutingAddress and non-local mailHost, 15010Sstevel@tonic-gate# relay to mailHost with original address 15020Sstevel@tonic-gateifdef(`_MAILER_TABLE_', `dnl 15030Sstevel@tonic-gate# check mailertable for host, relay from there 15040Sstevel@tonic-gateR<> <$+> <$+> <$+> <$*> $>LDAPMailertable <$1> $2', 15050Sstevel@tonic-gate`R<> <$+> <$+> <$+> <$*> $#_RELAY_ $@ $1 $: $2') 15060Sstevel@tonic-gate 15070Sstevel@tonic-gateifdef(`_LDAP_ROUTE_DETAIL_', 15080Sstevel@tonic-gate`# if no mailRoutingAddress and no mailHost, 15090Sstevel@tonic-gate# try without +detail 15100Sstevel@tonic-gateR<> <> <$+> <$+ + $* @ $+> <> $@ $>LDAPExpand <$1> <$2 @ $4> <+$3>')dnl 15110Sstevel@tonic-gate 15120Sstevel@tonic-gateifdef(`_LDAP_ROUTE_NODOMAIN_', `dnl', ` 15130Sstevel@tonic-gate# if still no mailRoutingAddress and no mailHost, 15140Sstevel@tonic-gate# try @domain 15150Sstevel@tonic-gateifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl 15160Sstevel@tonic-gateR<> <> <$+> <$+ + $* @ $+> <> $@ $>LDAPExpand <$1> <@ $4> <+$3>') 15170Sstevel@tonic-gateR<> <> <$+> <$+ @ $+> <$*> $@ $>LDAPExpand <$1> <@ $3> <$4>') 15180Sstevel@tonic-gate 15190Sstevel@tonic-gate# if no mailRoutingAddress and no mailHost and this was a domain attempt, 15200Sstevel@tonic-gateifelse(_LDAP_ROUTING_, `_MUST_EXIST_', `dnl 15210Sstevel@tonic-gate# user does not exist 15220Sstevel@tonic-gateR<> <> <$+> <@ $+> <$*> $: <?> < $&{addr_type} > < $1 > 15230Sstevel@tonic-gate# only give error for envelope recipient 15240Sstevel@tonic-gateR<?> <e r> <$+> $#error $@ nouser $: "550 User unknown" 15250Sstevel@tonic-gateifdef(`_LDAP_SENDER_MUST_EXIST_', `dnl 15260Sstevel@tonic-gate# and the sender too 15270Sstevel@tonic-gateR<?> <e s> <$+> $#error $@ nouser $: "550 User unknown"') 15280Sstevel@tonic-gateR<?> <$*> <$+> $@ $2', 15290Sstevel@tonic-gate`dnl 15300Sstevel@tonic-gate# return the original address 15310Sstevel@tonic-gateR<> <> <$+> <@ $+> <$*> $@ $1')', 15320Sstevel@tonic-gate`dnl') 15330Sstevel@tonic-gate 15340Sstevel@tonic-gateifelse(substr(confDELIVERY_MODE,0,1), `d', `errprint(`WARNING: Antispam rules not available in deferred delivery mode. 15350Sstevel@tonic-gate')') 15360Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl', `divert(-1)') 15370Sstevel@tonic-gate###################################################################### 15380Sstevel@tonic-gate### D: LookUpDomain -- search for domain in access database 15390Sstevel@tonic-gate### 15400Sstevel@tonic-gate### Parameters: 15410Sstevel@tonic-gate### <$1> -- key (domain name) 15420Sstevel@tonic-gate### <$2> -- default (what to return if not found in db) 15430Sstevel@tonic-gatednl must not be empty 15440Sstevel@tonic-gate### <$3> -- mark (must be <(!|+) single-token>) 15450Sstevel@tonic-gate### ! does lookup only with tag 15460Sstevel@tonic-gate### + does lookup with and without tag 15470Sstevel@tonic-gate### <$4> -- passthru (additional data passed unchanged through) 15480Sstevel@tonic-gatednl returns: <default> <passthru> 15490Sstevel@tonic-gatednl <result> <passthru> 15500Sstevel@tonic-gate###################################################################### 15510Sstevel@tonic-gate 15520Sstevel@tonic-gateSD 15530Sstevel@tonic-gatednl workspace <key> <default> <passthru> <mark> 15540Sstevel@tonic-gatednl lookup with tag (in front, no delimiter here) 15550Sstevel@tonic-gatednl 2 3 4 5 15560Sstevel@tonic-gateR<$*> <$+> <$- $-> <$*> $: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5> 15570Sstevel@tonic-gatednl workspace <result-of-lookup|?> <key> <default> <passthru> <mark> 15580Sstevel@tonic-gatednl lookup without tag? 15590Sstevel@tonic-gatednl 1 2 3 4 15600Sstevel@tonic-gateR<?> <$+> <$+> <+ $-> <$*> $: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4> 15610Sstevel@tonic-gateifdef(`_LOOKUPDOTDOMAIN_', `dnl omit first component: lookup .rest 15620Sstevel@tonic-gatednl XXX apply this also to IP addresses? 15630Sstevel@tonic-gatednl currently it works the wrong way round for [1.2.3.4] 15640Sstevel@tonic-gatednl 1 2 3 4 5 6 15650Sstevel@tonic-gateR<?> <$+.$+> <$+> <$- $-> <$*> $: < $(access $5`'_TAG_DELIM_`'.$2 $: ? $) > <$1.$2> <$3> <$4 $5> <$6> 15660Sstevel@tonic-gatednl 1 2 3 4 5 15670Sstevel@tonic-gateR<?> <$+.$+> <$+> <+ $-> <$*> $: < $(access .$2 $: ? $) > <$1.$2> <$3> <+ $4> <$5>', `dnl') 15680Sstevel@tonic-gateifdef(`_ACCESS_SKIP_', `dnl 15690Sstevel@tonic-gatednl found SKIP: return <default> and <passthru> 15700Sstevel@tonic-gatednl 1 2 3 4 5 15710Sstevel@tonic-gateR<SKIP> <$+> <$+> <$- $-> <$*> $@ <$2> <$5>', `dnl') 15720Sstevel@tonic-gatednl not found: IPv4 net (no check is done whether it is an IP number!) 15730Sstevel@tonic-gatednl 1 2 3 4 5 6 15740Sstevel@tonic-gateR<?> <[$+.$-]> <$+> <$- $-> <$*> $@ $>D <[$1]> <$3> <$4 $5> <$6> 15750Sstevel@tonic-gateifdef(`NO_NETINET6', `dnl', 15760Sstevel@tonic-gate`dnl not found: IPv6 net 15770Sstevel@tonic-gatednl (could be merged with previous rule if we have a class containing .:) 15780Sstevel@tonic-gatednl 1 2 3 4 5 6 15790Sstevel@tonic-gateR<?> <[$+::$-]> <$+> <$- $-> <$*> $: $>D <[$1]> <$3> <$4 $5> <$6> 15800Sstevel@tonic-gateR<?> <[$+:$-]> <$+> <$- $-> <$*> $: $>D <[$1]> <$3> <$4 $5> <$6>') 15810Sstevel@tonic-gatednl not found, but subdomain: try again 15820Sstevel@tonic-gatednl 1 2 3 4 5 6 15830Sstevel@tonic-gateR<?> <$+.$+> <$+> <$- $-> <$*> $@ $>D <$2> <$3> <$4 $5> <$6> 15840Sstevel@tonic-gateifdef(`_FFR_LOOKUPTAG_', `dnl lookup Tag: 15850Sstevel@tonic-gatednl 1 2 3 4 15860Sstevel@tonic-gateR<?> <$+> <$+> <! $-> <$*> $: < $(access $3`'_TAG_DELIM_ $: ? $) > <$1> <$2> <! $3> <$4>', `dnl') 15870Sstevel@tonic-gatednl not found, no subdomain: return <default> and <passthru> 15880Sstevel@tonic-gatednl 1 2 3 4 5 15890Sstevel@tonic-gateR<?> <$+> <$+> <$- $-> <$*> $@ <$2> <$5> 15900Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 15910Sstevel@tonic-gatednl 2 3 4 5 6 15920Sstevel@tonic-gateR<$* _ATMPF_> <$+> <$+> <$- $-> <$*> $@ <_ATMPF_> <$6>', `dnl') 15930Sstevel@tonic-gatednl return <result of lookup> and <passthru> 15940Sstevel@tonic-gatednl 2 3 4 5 6 15950Sstevel@tonic-gateR<$*> <$+> <$+> <$- $-> <$*> $@ <$1> <$6> 15960Sstevel@tonic-gate 15970Sstevel@tonic-gate###################################################################### 15980Sstevel@tonic-gate### A: LookUpAddress -- search for host address in access database 15990Sstevel@tonic-gate### 16000Sstevel@tonic-gate### Parameters: 16010Sstevel@tonic-gate### <$1> -- key (dot quadded host address) 16020Sstevel@tonic-gate### <$2> -- default (what to return if not found in db) 16030Sstevel@tonic-gatednl must not be empty 16040Sstevel@tonic-gate### <$3> -- mark (must be <(!|+) single-token>) 16050Sstevel@tonic-gate### ! does lookup only with tag 16060Sstevel@tonic-gate### + does lookup with and without tag 16070Sstevel@tonic-gate### <$4> -- passthru (additional data passed through) 16080Sstevel@tonic-gatednl returns: <default> <passthru> 16090Sstevel@tonic-gatednl <result> <passthru> 16100Sstevel@tonic-gate###################################################################### 16110Sstevel@tonic-gate 16120Sstevel@tonic-gateSA 16130Sstevel@tonic-gatednl lookup with tag 16140Sstevel@tonic-gatednl 2 3 4 5 16150Sstevel@tonic-gateR<$+> <$+> <$- $-> <$*> $: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5> 16160Sstevel@tonic-gatednl lookup without tag 16170Sstevel@tonic-gatednl 1 2 3 4 16180Sstevel@tonic-gateR<?> <$+> <$+> <+ $-> <$*> $: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4> 16190Sstevel@tonic-gatednl workspace <result-of-lookup|?> <key> <default> <mark> <passthru> 16200Sstevel@tonic-gateifdef(`_ACCESS_SKIP_', `dnl 16210Sstevel@tonic-gatednl found SKIP: return <default> and <passthru> 16220Sstevel@tonic-gatednl 1 2 3 4 5 16230Sstevel@tonic-gateR<SKIP> <$+> <$+> <$- $-> <$*> $@ <$2> <$5>', `dnl') 16240Sstevel@tonic-gateifdef(`NO_NETINET6', `dnl', 16250Sstevel@tonic-gate`dnl no match; IPv6: remove last part 16260Sstevel@tonic-gatednl 1 2 3 4 5 6 16270Sstevel@tonic-gateR<?> <$+::$-> <$+> <$- $-> <$*> $@ $>A <$1> <$3> <$4 $5> <$6> 16280Sstevel@tonic-gateR<?> <$+:$-> <$+> <$- $-> <$*> $@ $>A <$1> <$3> <$4 $5> <$6>') 16290Sstevel@tonic-gatednl no match; IPv4: remove last part 16300Sstevel@tonic-gatednl 1 2 3 4 5 6 16310Sstevel@tonic-gateR<?> <$+.$-> <$+> <$- $-> <$*> $@ $>A <$1> <$3> <$4 $5> <$6> 16320Sstevel@tonic-gatednl no match: return default 16330Sstevel@tonic-gatednl 1 2 3 4 5 16340Sstevel@tonic-gateR<?> <$+> <$+> <$- $-> <$*> $@ <$2> <$5> 16350Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 16360Sstevel@tonic-gatednl 2 3 4 5 6 16370Sstevel@tonic-gateR<$* _ATMPF_> <$+> <$+> <$- $-> <$*> $@ <_ATMPF_> <$6>', `dnl') 16380Sstevel@tonic-gatednl match: return result 16390Sstevel@tonic-gatednl 2 3 4 5 6 16400Sstevel@tonic-gateR<$*> <$+> <$+> <$- $-> <$*> $@ <$1> <$6> 16410Sstevel@tonic-gatednl endif _ACCESS_TABLE_ 16420Sstevel@tonic-gatedivert(0) 16430Sstevel@tonic-gate###################################################################### 16440Sstevel@tonic-gate### CanonAddr -- Convert an address into a standard form for 16450Sstevel@tonic-gate### relay checking. Route address syntax is 16460Sstevel@tonic-gate### crudely converted into a %-hack address. 16470Sstevel@tonic-gate### 16480Sstevel@tonic-gate### Parameters: 16490Sstevel@tonic-gate### $1 -- full recipient address 16500Sstevel@tonic-gate### 16510Sstevel@tonic-gate### Returns: 16520Sstevel@tonic-gate### parsed address, not in source route form 16530Sstevel@tonic-gatednl user%host%host<@domain> 16540Sstevel@tonic-gatednl host!user<@domain> 16550Sstevel@tonic-gate###################################################################### 16560Sstevel@tonic-gate 16570Sstevel@tonic-gateSCanonAddr 16580Sstevel@tonic-gateR$* $: $>Parse0 $>canonify $1 make domain canonical 16590Sstevel@tonic-gateifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl 16600Sstevel@tonic-gateR< @ $+ > : $* @ $* < @ $1 > : $2 % $3 change @ to % in src route 16610Sstevel@tonic-gateR$* < @ $+ > : $* : $* $3 $1 < @ $2 > : $4 change to % hack. 16620Sstevel@tonic-gateR$* < @ $+ > : $* $3 $1 < @ $2 > 16630Sstevel@tonic-gatednl') 16640Sstevel@tonic-gate 16650Sstevel@tonic-gate###################################################################### 16660Sstevel@tonic-gate### ParseRecipient -- Strip off hosts in $=R as well as possibly 16670Sstevel@tonic-gate### $* $=m or the access database. 16680Sstevel@tonic-gate### Check user portion for host separators. 16690Sstevel@tonic-gate### 16700Sstevel@tonic-gate### Parameters: 16710Sstevel@tonic-gate### $1 -- full recipient address 16720Sstevel@tonic-gate### 16730Sstevel@tonic-gate### Returns: 16740Sstevel@tonic-gate### parsed, non-local-relaying address 16750Sstevel@tonic-gate###################################################################### 16760Sstevel@tonic-gate 16770Sstevel@tonic-gateSParseRecipient 16780Sstevel@tonic-gatednl mark and canonify address 16790Sstevel@tonic-gateR$* $: <?> $>CanonAddr $1 16800Sstevel@tonic-gatednl workspace: <?> localpart<@domain[.]> 16810Sstevel@tonic-gateR<?> $* < @ $* . > <?> $1 < @ $2 > strip trailing dots 16820Sstevel@tonic-gatednl workspace: <?> localpart<@domain> 16830Sstevel@tonic-gateR<?> $- < @ $* > $: <?> $(dequote $1 $) < @ $2 > dequote local part 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate# if no $=O character, no host in the user portion, we are done 16860Sstevel@tonic-gateR<?> $* $=O $* < @ $* > $: <NO> $1 $2 $3 < @ $4> 16870Sstevel@tonic-gatednl no $=O in localpart: return 16880Sstevel@tonic-gateR<?> $* $@ $1 16890Sstevel@tonic-gate 16900Sstevel@tonic-gatednl workspace: <NO> localpart<@domain>, where localpart contains $=O 16910Sstevel@tonic-gatednl mark everything which has an "authorized" domain with <RELAY> 16920Sstevel@tonic-gateifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 16930Sstevel@tonic-gate# if we relay, check username portion for user%host so host can be checked also 16940Sstevel@tonic-gateR<NO> $* < @ $* $=m > $: <RELAY> $1 < @ $2 $3 >', `dnl') 16950Sstevel@tonic-gatednl workspace: <(NO|RELAY)> localpart<@domain>, where localpart contains $=O 16960Sstevel@tonic-gatednl if mark is <NO> then change it to <RELAY> if domain is "authorized" 16970Sstevel@tonic-gate 16980Sstevel@tonic-gatednl what if access map returns something else than RELAY? 16990Sstevel@tonic-gatednl we are only interested in RELAY entries... 17000Sstevel@tonic-gatednl other To: entries: blacklist recipient; generic entries? 17010Sstevel@tonic-gatednl if it is an error we probably do not want to relay anyway 17020Sstevel@tonic-gateifdef(`_RELAY_HOSTS_ONLY_', 17030Sstevel@tonic-gate`R<NO> $* < @ $=R > $: <RELAY> $1 < @ $2 > 17040Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 17050Sstevel@tonic-gateR<NO> $* < @ $+ > $: <$(access To:$2 $: NO $)> $1 < @ $2 > 17060Sstevel@tonic-gateR<NO> $* < @ $+ > $: <$(access $2 $: NO $)> $1 < @ $2 >',`dnl')', 17070Sstevel@tonic-gate`R<NO> $* < @ $* $=R > $: <RELAY> $1 < @ $2 $3 > 17080Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 17090Sstevel@tonic-gateR<NO> $* < @ $+ > $: $>D <$2> <NO> <+ To> <$1 < @ $2 >> 17100Sstevel@tonic-gateR<$+> <$+> $: <$1> $2',`dnl')') 17110Sstevel@tonic-gate 17120Sstevel@tonic-gate 17130Sstevel@tonic-gateifdef(`_RELAY_MX_SERVED_', `dnl 17140Sstevel@tonic-gatednl do "we" ($=w) act as backup MX server for the destination domain? 17150Sstevel@tonic-gateR<NO> $* < @ $+ > $: <MX> < : $(mxserved $2 $) : > < $1 < @$2 > > 17160Sstevel@tonic-gateR<MX> < : $* <TEMP> : > $* $#TEMP $@ 4.4.0 $: "450 Can not check MX records for recipient host " $1 17170Sstevel@tonic-gatednl yes: mark it as <RELAY> 17180Sstevel@tonic-gateR<MX> < $* : $=w. : $* > < $+ > $: <RELAY> $4 17190Sstevel@tonic-gatednl no: put old <NO> mark back 17200Sstevel@tonic-gateR<MX> < : $* : > < $+ > $: <NO> $2', `dnl') 17210Sstevel@tonic-gate 17220Sstevel@tonic-gatednl do we relay to this recipient domain? 17230Sstevel@tonic-gateR<RELAY> $* < @ $* > $@ $>ParseRecipient $1 17240Sstevel@tonic-gatednl something else 17250Sstevel@tonic-gateR<$+> $* $@ $2 17260Sstevel@tonic-gate 17270Sstevel@tonic-gate 17280Sstevel@tonic-gate###################################################################### 17290Sstevel@tonic-gate### check_relay -- check hostname/address on SMTP startup 17300Sstevel@tonic-gate###################################################################### 17310Sstevel@tonic-gate 17320Sstevel@tonic-gateifdef(`_CONTROL_IMMEDIATE_',`dnl 17330Sstevel@tonic-gateScheck_relay 17340Sstevel@tonic-gateifdef(`_RATE_CONTROL_IMMEDIATE_',`dnl 17350Sstevel@tonic-gatednl workspace: ignored... 17360Sstevel@tonic-gateR$* $: $>"RateControl" dummy', `dnl') 17370Sstevel@tonic-gateifdef(`_CONN_CONTROL_IMMEDIATE_',`dnl 17380Sstevel@tonic-gatednl workspace: ignored... 17390Sstevel@tonic-gateR$* $: $>"ConnControl" dummy', `dnl') 17400Sstevel@tonic-gatednl') 17410Sstevel@tonic-gate 17420Sstevel@tonic-gateSLocal_check_relay 17430Sstevel@tonic-gateScheck`'_U_`'relay 17440Sstevel@tonic-gateifdef(`_USE_CLIENT_PTR_',`dnl 17450Sstevel@tonic-gateR$* $| $* $: $&{client_ptr} $| $2', `dnl') 17460Sstevel@tonic-gateR$* $: $1 $| $>"Local_check_relay" $1 17470Sstevel@tonic-gateR$* $| $* $| $#$* $#$3 17480Sstevel@tonic-gateR$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 17490Sstevel@tonic-gate 17500Sstevel@tonic-gateSBasic_check_relay 17510Sstevel@tonic-gate# check for deferred delivery mode 17520Sstevel@tonic-gateR$* $: < $&{deliveryMode} > $1 17530Sstevel@tonic-gateR< d > $* $@ deferred 17540Sstevel@tonic-gateR< $* > $* $: $2 17550Sstevel@tonic-gate 17560Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 17570Sstevel@tonic-gatednl workspace: {client_name} $| {client_addr} 17580Sstevel@tonic-gateR$+ $| $+ $: $>D < $1 > <?> <+ Connect> < $2 > 17590Sstevel@tonic-gatednl workspace: <result-of-lookup> <{client_addr}> 17600Sstevel@tonic-gatednl OR $| $+ if client_name is empty 17610Sstevel@tonic-gateR $| $+ $: $>A < $1 > <?> <+ Connect> <> empty client_name 17620Sstevel@tonic-gatednl workspace: <result-of-lookup> <{client_addr}> 17630Sstevel@tonic-gateR<?> <$+> $: $>A < $1 > <?> <+ Connect> <> no: another lookup 17640Sstevel@tonic-gatednl workspace: <result-of-lookup> (<>|<{client_addr}>) 17650Sstevel@tonic-gateR<?> <$*> $: OK found nothing 17660Sstevel@tonic-gatednl workspace: <result-of-lookup> (<>|<{client_addr}>) | OK 17670Sstevel@tonic-gateR<$={Accept}> <$*> $@ $1 return value of lookup 17680Sstevel@tonic-gateR<REJECT> <$*> $#error ifdef(`confREJECT_MSG', `$: confREJECT_MSG', `$@ 5.7.1 $: "550 Access denied"') 17690Sstevel@tonic-gateR<DISCARD> <$*> $#discard $: discard 17700Sstevel@tonic-gateR<QUARANTINE:$+> <$*> $#error $@ quarantine $: $1 17710Sstevel@tonic-gatednl error tag 17720Sstevel@tonic-gateR<ERROR:$-.$-.$-:$+> <$*> $#error $@ $1.$2.$3 $: $4 17730Sstevel@tonic-gateR<ERROR:$+> <$*> $#error $: $1 17740Sstevel@tonic-gateifdef(`_ATMPF_', `R<$* _ATMPF_> <$*> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 17750Sstevel@tonic-gatednl generic error from access map 17760Sstevel@tonic-gateR<$+> <$*> $#error $: $1', `dnl') 17770Sstevel@tonic-gate 17780Sstevel@tonic-gateifdef(`_RBL_',`dnl 17790Sstevel@tonic-gate# DNS based IP address spam list 17800Sstevel@tonic-gatednl workspace: ignored... 17810Sstevel@tonic-gateR$* $: $&{client_addr} 17820Sstevel@tonic-gateR$-.$-.$-.$- $: <?> $(host $4.$3.$2.$1._RBL_. $: OK $) 17830Sstevel@tonic-gateR<?>OK $: OKSOFAR 17840Sstevel@tonic-gateR<?>$+ $#error $@ 5.7.1 $: "550 Rejected: " $&{client_addr} " listed at _RBL_"', 17850Sstevel@tonic-gate`dnl') 17860Sstevel@tonic-gateifdef(`_RATE_CONTROL_',`dnl 17870Sstevel@tonic-gateifdef(`_RATE_CONTROL_IMMEDIATE_',`', `dnl 17880Sstevel@tonic-gatednl workspace: ignored... 17890Sstevel@tonic-gateR$* $: $>"RateControl" dummy')', `dnl') 17900Sstevel@tonic-gateifdef(`_CONN_CONTROL_',`dnl 17910Sstevel@tonic-gateifdef(`_CONN_CONTROL_IMMEDIATE_',`',`dnl 17920Sstevel@tonic-gatednl workspace: ignored... 17930Sstevel@tonic-gateR$* $: $>"ConnControl" dummy')', `dnl') 17940Sstevel@tonic-gateundivert(8) 1795*3544Sjbeckifdef(`_REQUIRE_RDNS_', `dnl 1796*3544SjbeckR$* $: $&{client_addr} $| $&{client_resolve} 1797*3544SjbeckR$=R $* $@ RELAY We relay for these 1798*3544SjbeckR$* $| OK $@ OK Resolves. 1799*3544SjbeckR$* $| FAIL $#error $@ 5.7.1 $: 550 Fix reverse DNS for $1 1800*3544SjbeckR$* $| TEMP $#error $@ 4.1.8 $: 451 Client IP address $1 does not resolve 1801*3544SjbeckR$* $| FORGED $#error $@ 4.1.8 $: 451 Possibly forged hostname for $1 1802*3544Sjbeck', `dnl') 18030Sstevel@tonic-gate 18040Sstevel@tonic-gate###################################################################### 18050Sstevel@tonic-gate### check_mail -- check SMTP ``MAIL FROM:'' command argument 18060Sstevel@tonic-gate###################################################################### 18070Sstevel@tonic-gate 18080Sstevel@tonic-gateSLocal_check_mail 18090Sstevel@tonic-gateScheck`'_U_`'mail 18100Sstevel@tonic-gateR$* $: $1 $| $>"Local_check_mail" $1 18110Sstevel@tonic-gateR$* $| $#$* $#$2 18120Sstevel@tonic-gateR$* $| $* $@ $>"Basic_check_mail" $1 18130Sstevel@tonic-gate 18140Sstevel@tonic-gateSBasic_check_mail 18150Sstevel@tonic-gate# check for deferred delivery mode 18160Sstevel@tonic-gateR$* $: < $&{deliveryMode} > $1 18170Sstevel@tonic-gateR< d > $* $@ deferred 18180Sstevel@tonic-gateR< $* > $* $: $2 18190Sstevel@tonic-gate 18200Sstevel@tonic-gate# authenticated? 18210Sstevel@tonic-gatednl done first: we can require authentication for every mail transaction 18220Sstevel@tonic-gatednl workspace: address as given by MAIL FROM: (sender) 18230Sstevel@tonic-gateR$* $: $1 $| $>"tls_client" $&{verify} $| MAIL 18240Sstevel@tonic-gateR$* $| $#$+ $#$2 18250Sstevel@tonic-gatednl undo damage: remove result of tls_client call 18260Sstevel@tonic-gateR$* $| $* $: $1 18270Sstevel@tonic-gate 18280Sstevel@tonic-gatednl workspace: address as given by MAIL FROM: 18290Sstevel@tonic-gateR<> $@ <OK> we MUST accept <> (RFC 1123) 18300Sstevel@tonic-gateifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl 18310Sstevel@tonic-gatednl do some additional checks 18320Sstevel@tonic-gatednl no user@host 18330Sstevel@tonic-gatednl no user@localhost (if nonlocal sender) 18340Sstevel@tonic-gatednl this is a pretty simple canonification, it will not catch every case 18350Sstevel@tonic-gatednl just make sure the address has <> around it (which is required by 18360Sstevel@tonic-gatednl the RFC anyway, maybe we should complain if they are missing...) 18370Sstevel@tonic-gatednl dirty trick: if it is user@host, just add a dot: user@host. this will 18380Sstevel@tonic-gatednl not be modified by host lookups. 18390Sstevel@tonic-gateR$+ $: <?> $1 18400Sstevel@tonic-gateR<?><$+> $: <@> <$1> 18410Sstevel@tonic-gateR<?>$+ $: <@> <$1> 18420Sstevel@tonic-gatednl workspace: <@> <address> 18430Sstevel@tonic-gatednl prepend daemon_flags 18440Sstevel@tonic-gateR$* $: $&{daemon_flags} $| $1 18450Sstevel@tonic-gatednl workspace: ${daemon_flags} $| <@> <address> 18460Sstevel@tonic-gatednl do not allow these at all or only from local systems? 18470Sstevel@tonic-gateR$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > 18480Sstevel@tonic-gatednl accept unqualified sender: change mark to avoid test 18490Sstevel@tonic-gateR$* u $* $| <@> < $* > $: <?> < $3 > 18500Sstevel@tonic-gatednl workspace: ${daemon_flags} $| <@> <address> 18510Sstevel@tonic-gatednl or: <? ${client_name} > <address> 18520Sstevel@tonic-gatednl or: <?> <address> 18530Sstevel@tonic-gatednl remove daemon_flags 18540Sstevel@tonic-gateR$* $| $* $: $2 18550Sstevel@tonic-gate# handle case of @localhost on address 18560Sstevel@tonic-gateR<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > 18570Sstevel@tonic-gateR<@> < $* @ [127.0.0.1] > 18580Sstevel@tonic-gate $: < ? $&{client_name} > < $1 @ [127.0.0.1] > 18590Sstevel@tonic-gateR<@> < $* @ localhost.$m > 18600Sstevel@tonic-gate $: < ? $&{client_name} > < $1 @ localhost.$m > 18610Sstevel@tonic-gateifdef(`_NO_UUCP_', `dnl', 18620Sstevel@tonic-gate`R<@> < $* @ localhost.UUCP > 18630Sstevel@tonic-gate $: < ? $&{client_name} > < $1 @ localhost.UUCP >') 18640Sstevel@tonic-gatednl workspace: < ? $&{client_name} > <user@localhost|host> 18650Sstevel@tonic-gatednl or: <@> <address> 18660Sstevel@tonic-gatednl or: <?> <address> (thanks to u in ${daemon_flags}) 18670Sstevel@tonic-gateR<@> $* $: $1 no localhost as domain 18680Sstevel@tonic-gatednl workspace: < ? $&{client_name} > <user@localhost|host> 18690Sstevel@tonic-gatednl or: <address> 18700Sstevel@tonic-gatednl or: <?> <address> (thanks to u in ${daemon_flags}) 18710Sstevel@tonic-gateR<? $=w> $* $: $2 local client: ok 18720Sstevel@tonic-gateR<? $+> <$+> $#error $@ 5.5.4 $: "_CODE553 Real domain name required for sender address" 18730Sstevel@tonic-gatednl remove <?> (happens only if ${client_name} == "" or u in ${daemon_flags}) 18740Sstevel@tonic-gateR<?> $* $: $1') 18750Sstevel@tonic-gatednl workspace: address (or <address>) 18760Sstevel@tonic-gateR$* $: <?> $>CanonAddr $1 canonify sender address and mark it 18770Sstevel@tonic-gatednl workspace: <?> CanonicalAddress (i.e. address in canonical form localpart<@host>) 18780Sstevel@tonic-gatednl there is nothing behind the <@host> so no trailing $* needed 18790Sstevel@tonic-gateR<?> $* < @ $+ . > <?> $1 < @ $2 > strip trailing dots 18800Sstevel@tonic-gate# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) 18810Sstevel@tonic-gateR<?> $* < @ $* $=P > $: <_RES_OK_> $1 < @ $2 $3 > 18820Sstevel@tonic-gatednl workspace <mark> CanonicalAddress where mark is ? or OK 18830Sstevel@tonic-gatednl A sender address with my local host name ($j) is safe 18840Sstevel@tonic-gateR<?> $* < @ $j > $: <_RES_OK_> $1 < @ $j > 18850Sstevel@tonic-gateifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_', 18860Sstevel@tonic-gate`R<?> $* < @ $+ > $: <_RES_OK_> $1 < @ $2 > ... unresolvable OK', 18870Sstevel@tonic-gate`R<?> $* < @ $+ > $: <? $(resolve $2 $: $2 <PERM> $) > $1 < @ $2 > 18880Sstevel@tonic-gateR<? $* <$->> $* < @ $+ > 18890Sstevel@tonic-gate $: <$2> $3 < @ $4 >') 18900Sstevel@tonic-gatednl workspace <mark> CanonicalAddress where mark is ?, _RES_OK_, PERM, TEMP 18910Sstevel@tonic-gatednl mark is ? iff the address is user (wo @domain) 18920Sstevel@tonic-gate 18930Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 18940Sstevel@tonic-gate# check sender address: user@address, user@, address 18950Sstevel@tonic-gatednl should we remove +ext from user? 18960Sstevel@tonic-gatednl workspace: <mark> CanonicalAddress where mark is: ?, _RES_OK_, PERM, TEMP 18970Sstevel@tonic-gateR<$+> $+ < @ $* > $: @<$1> <$2 < @ $3 >> $| <F:$2@$3> <U:$2@> <D:$3> 18980Sstevel@tonic-gateR<$+> $+ $: @<$1> <$2> $| <U:$2@> 18990Sstevel@tonic-gatednl workspace: @<mark> <CanonicalAddress> $| <@type:address> .... 19000Sstevel@tonic-gatednl $| is used as delimiter, otherwise false matches may occur: <user<@domain>> 19010Sstevel@tonic-gatednl will only return user<@domain when "reversing" the args 19020Sstevel@tonic-gateR@ <$+> <$*> $| <$+> $: <@> <$1> <$2> $| $>SearchList <+ From> $| <$3> <> 19030Sstevel@tonic-gatednl workspace: <@><mark> <CanonicalAddress> $| <result> 19040Sstevel@tonic-gateR<@> <$+> <$*> $| <$*> $: <$3> <$1> <$2> reverse result 19050Sstevel@tonic-gatednl workspace: <result> <mark> <CanonicalAddress> 19060Sstevel@tonic-gate# retransform for further use 19070Sstevel@tonic-gatednl required form: 19080Sstevel@tonic-gatednl <ResultOfLookup|mark> CanonicalAddress 19090Sstevel@tonic-gateR<?> <$+> <$*> $: <$1> $2 no match 19100Sstevel@tonic-gateR<$+> <$+> <$*> $: <$1> $3 relevant result, keep it', `dnl') 19110Sstevel@tonic-gatednl workspace <ResultOfLookup|mark> CanonicalAddress 19120Sstevel@tonic-gatednl mark is ? iff the address is user (wo @domain) 19130Sstevel@tonic-gate 19140Sstevel@tonic-gateifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl 19150Sstevel@tonic-gate# handle case of no @domain on address 19160Sstevel@tonic-gatednl prepend daemon_flags 19170Sstevel@tonic-gateR<?> $* $: $&{daemon_flags} $| <?> $1 19180Sstevel@tonic-gatednl accept unqualified sender: change mark to avoid test 19190Sstevel@tonic-gateR$* u $* $| <?> $* $: <_RES_OK_> $3 19200Sstevel@tonic-gatednl remove daemon_flags 19210Sstevel@tonic-gateR$* $| $* $: $2 19220Sstevel@tonic-gateR<?> $* $: < ? $&{client_addr} > $1 19230Sstevel@tonic-gateR<?> $* $@ <_RES_OK_> ...local unqualed ok 19240Sstevel@tonic-gateR<? $+> $* $#error $@ 5.5.4 $: "_CODE553 Domain name required for sender address " $&f 19250Sstevel@tonic-gate ...remote is not') 19260Sstevel@tonic-gate# check results 19270Sstevel@tonic-gateR<?> $* $: @ $1 mark address: nothing known about it 1928*3544SjbeckR<$={ResOk}> $* $: @ $2 domain ok 19290Sstevel@tonic-gateR<TEMP> $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve" 19300Sstevel@tonic-gateR<PERM> $* $#error $@ 5.1.8 $: "_CODE553 Domain of sender address " $&f " does not exist" 19310Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 19320Sstevel@tonic-gateR<$={Accept}> $* $# $1 accept from access map 19330Sstevel@tonic-gateR<DISCARD> $* $#discard $: discard 19340Sstevel@tonic-gateR<QUARANTINE:$+> $* $#error $@ quarantine $: $1 19350Sstevel@tonic-gateR<REJECT> $* $#error ifdef(`confREJECT_MSG', `$: confREJECT_MSG', `$@ 5.7.1 $: "550 Access denied"') 19360Sstevel@tonic-gatednl error tag 19370Sstevel@tonic-gateR<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4 19380Sstevel@tonic-gateR<ERROR:$+> $* $#error $: $1 19390Sstevel@tonic-gateifdef(`_ATMPF_', `R<_ATMPF_> $* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 19400Sstevel@tonic-gatednl generic error from access map 19410Sstevel@tonic-gateR<$+> $* $#error $: $1 error from access db', 19420Sstevel@tonic-gate`dnl') 1943*3544Sjbeckdnl workspace: @ CanonicalAddress (i.e. address in canonical form localpart<@host>) 1944*3544Sjbeck 1945*3544Sjbeckifdef(`_BADMX_CHK_', `dnl 1946*3544SjbeckR@ $*<@$+>$* $: $1<@$2>$3 $| $>BadMX $2 1947*3544SjbeckR$* $| $#$* $#$2 1948*3544Sjbeck 1949*3544SjbeckSBadMX 1950*3544Sjbeck# Look up MX records and ferret away a copy of the original address. 1951*3544Sjbeck# input: domain part of address to check 1952*3544SjbeckR$+ $:<MX><$1><:$(mxlist $1$):><:> 1953*3544Sjbeck# workspace: <MX><domain><: mxlist-result $><:> 1954*3544SjbeckR<MX><$+><:$*<TEMP>:><$*> $#error $@ 4.1.2 $: "450 MX lookup failure for "$1 1955*3544Sjbeck# workspace: <MX> <original destination> <unchecked mxlist> <checked mxlist> 1956*3544Sjbeck# Recursively run badmx check on each mx. 1957*3544SjbeckR<MX><$*><:$+:$*><:$*> <MX><$1><:$3><: $4 $(badmx $2 $):> 1958*3544Sjbeck# See if any of them fail. 1959*3544SjbeckR<MX><$*><$*><$*<BADMX>:$*> $#error $@ 5.1.2 $:"550 Illegal MX record for recipient host "$1 1960*3544Sjbeck# Reverse the mxlists so we can use the same argument order again. 1961*3544SjbeckR<MX><$*><$*><$*> $:<MX><$1><$3><$2> 1962*3544SjbeckR<MX><$*><:$+:$*><:$*> <MX><$1><:$3><:$4 $(dnsA $2 $) :> 1963*3544Sjbeck 1964*3544Sjbeck# Reverse the lists so we can use the same argument order again. 1965*3544SjbeckR<MX><$*><$*><$*> $:<MX><$1><$3><$2> 1966*3544SjbeckR<MX><$*><:$+:$*><:$*> <MX><$1><:$3><:$4 $(BadMXIP $2 $) :> 1967*3544Sjbeck 1968*3544SjbeckR<MX><$*><$*><$*<BADMXIP>:$*> $#error $@ 5.1.2 $:"550 Invalid MX record for recipient host "$1', 1969*3544Sjbeck`dnl') 1970*3544Sjbeck 19710Sstevel@tonic-gate 19720Sstevel@tonic-gate###################################################################### 19730Sstevel@tonic-gate### check_rcpt -- check SMTP ``RCPT TO:'' command argument 19740Sstevel@tonic-gate###################################################################### 19750Sstevel@tonic-gate 19760Sstevel@tonic-gateSLocal_check_rcpt 19770Sstevel@tonic-gateScheck`'_U_`'rcpt 19780Sstevel@tonic-gateR$* $: $1 $| $>"Local_check_rcpt" $1 19790Sstevel@tonic-gateR$* $| $#$* $#$2 19800Sstevel@tonic-gateR$* $| $* $@ $>"Basic_check_rcpt" $1 19810Sstevel@tonic-gate 19820Sstevel@tonic-gateSBasic_check_rcpt 19830Sstevel@tonic-gate# empty address? 19840Sstevel@tonic-gateR<> $#error $@ nouser $: "553 User address required" 19850Sstevel@tonic-gateR$@ $#error $@ nouser $: "553 User address required" 19860Sstevel@tonic-gate# check for deferred delivery mode 19870Sstevel@tonic-gateR$* $: < $&{deliveryMode} > $1 19880Sstevel@tonic-gateR< d > $* $@ deferred 19890Sstevel@tonic-gateR< $* > $* $: $2 19900Sstevel@tonic-gate 19910Sstevel@tonic-gateifdef(`_REQUIRE_QUAL_RCPT_', `dnl 19920Sstevel@tonic-gatednl this code checks for user@host where host is not a FQHN. 19930Sstevel@tonic-gatednl it is not activated. 19940Sstevel@tonic-gatednl notice: code to check for a recipient without a domain name is 19950Sstevel@tonic-gatednl available down below; look for the same macro. 19960Sstevel@tonic-gatednl this check is done here because the name might be qualified by the 19970Sstevel@tonic-gatednl canonicalization. 19980Sstevel@tonic-gate# require fully qualified domain part? 19990Sstevel@tonic-gatednl very simple canonification: make sure the address is in < > 20000Sstevel@tonic-gateR$+ $: <?> $1 20010Sstevel@tonic-gateR<?> <$+> $: <@> <$1> 20020Sstevel@tonic-gateR<?> $+ $: <@> <$1> 20030Sstevel@tonic-gateR<@> < postmaster > $: postmaster 20040Sstevel@tonic-gateR<@> < $* @ $+ . $+ > $: < $1 @ $2 . $3 > 20050Sstevel@tonic-gatednl prepend daemon_flags 20060Sstevel@tonic-gateR<@> $* $: $&{daemon_flags} $| <@> $1 20070Sstevel@tonic-gatednl workspace: ${daemon_flags} $| <@> <address> 20082197Sjbeckdnl _r_equire qual.rcpt: ok 20090Sstevel@tonic-gateR$* r $* $| <@> < $+ @ $+ > $: < $3 @ $4 > 20100Sstevel@tonic-gatednl do not allow these at all or only from local systems? 20110Sstevel@tonic-gateR$* r $* $| <@> < $* > $: < ? $&{client_name} > < $3 > 20120Sstevel@tonic-gateR<?> < $* > $: <$1> 20130Sstevel@tonic-gateR<? $=w> < $* > $: <$1> 20140Sstevel@tonic-gateR<? $+> <$+> $#error $@ 5.5.4 $: "553 Fully qualified domain name required" 20150Sstevel@tonic-gatednl remove daemon_flags for other cases 20160Sstevel@tonic-gateR$* $| <@> $* $: $2', `dnl') 20170Sstevel@tonic-gate 20180Sstevel@tonic-gatednl ################################################################## 20190Sstevel@tonic-gatednl call subroutines for recipient and relay 20200Sstevel@tonic-gatednl possible returns from subroutines: 20210Sstevel@tonic-gatednl $#TEMP temporary failure 20220Sstevel@tonic-gatednl $#error permanent failure (or temporary if from access map) 20230Sstevel@tonic-gatednl $#other stop processing 20240Sstevel@tonic-gatednl RELAY RELAYing allowed 20250Sstevel@tonic-gatednl other otherwise 20260Sstevel@tonic-gate###################################################################### 20270Sstevel@tonic-gateR$* $: $1 $| @ $>"Rcpt_ok" $1 20280Sstevel@tonic-gatednl temporary failure? remove mark @ and remember 20290Sstevel@tonic-gateR$* $| @ $#TEMP $+ $: $1 $| T $2 20300Sstevel@tonic-gatednl error or ok (stop) 20310Sstevel@tonic-gateR$* $| @ $#$* $#$2 20320Sstevel@tonic-gateifdef(`_PROMISCUOUS_RELAY_', `divert(-1)', `dnl') 20330Sstevel@tonic-gateR$* $| @ RELAY $@ RELAY 20340Sstevel@tonic-gatednl something else: call check sender (relay) 20350Sstevel@tonic-gateR$* $| @ $* $: O $| $>"Relay_ok" $1 20360Sstevel@tonic-gatednl temporary failure: call check sender (relay) 20370Sstevel@tonic-gateR$* $| T $+ $: T $2 $| $>"Relay_ok" $1 20380Sstevel@tonic-gatednl temporary failure? return that 20390Sstevel@tonic-gateR$* $| $#TEMP $+ $#error $2 20400Sstevel@tonic-gatednl error or ok (stop) 20410Sstevel@tonic-gateR$* $| $#$* $#$2 20420Sstevel@tonic-gateR$* $| RELAY $@ RELAY 20430Sstevel@tonic-gatednl something else: return previous temp failure 20440Sstevel@tonic-gateR T $+ $| $* $#error $1 20450Sstevel@tonic-gate# anything else is bogus 20460Sstevel@tonic-gateR$* $#error $@ 5.7.1 $: confRELAY_MSG 20470Sstevel@tonic-gatedivert(0) 20480Sstevel@tonic-gate 20490Sstevel@tonic-gate###################################################################### 20500Sstevel@tonic-gate### Rcpt_ok: is the recipient ok? 20510Sstevel@tonic-gatednl input: recipient address (RCPT TO) 20520Sstevel@tonic-gatednl output: see explanation at call 20530Sstevel@tonic-gate###################################################################### 20540Sstevel@tonic-gateSRcpt_ok 20550Sstevel@tonic-gateifdef(`_LOOSE_RELAY_CHECK_',`dnl 20560Sstevel@tonic-gateR$* $: $>CanonAddr $1 20570Sstevel@tonic-gateR$* < @ $* . > $1 < @ $2 > strip trailing dots', 20580Sstevel@tonic-gate`R$* $: $>ParseRecipient $1 strip relayable hosts') 20590Sstevel@tonic-gate 20600Sstevel@tonic-gateifdef(`_BESTMX_IS_LOCAL_',`dnl 20610Sstevel@tonic-gateifelse(_BESTMX_IS_LOCAL_, `', `dnl 20620Sstevel@tonic-gate# unlimited bestmx 20630Sstevel@tonic-gateR$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3', 20640Sstevel@tonic-gate`dnl 20650Sstevel@tonic-gate# limit bestmx to $=B 20660Sstevel@tonic-gateR$* < @ $* $=B > $* $: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4') 20670Sstevel@tonic-gateR$* $=O $* < @ $* @@ $=w . > $* $@ $>"Rcpt_ok" $1 $2 $3 20680Sstevel@tonic-gateR$* < @ $* @@ $=w . > $* $: $1 < @ $3 > $4 20690Sstevel@tonic-gateR$* < @ $* @@ $* > $* $: $1 < @ $2 > $4') 20700Sstevel@tonic-gate 20710Sstevel@tonic-gateifdef(`_BLACKLIST_RCPT_',`dnl 20720Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 20730Sstevel@tonic-gate# blacklist local users or any host from receiving mail 20740Sstevel@tonic-gateR$* $: <?> $1 20750Sstevel@tonic-gatednl user is now tagged with @ to be consistent with check_mail 20760Sstevel@tonic-gatednl and to distinguish users from hosts (com would be host, com@ would be user) 20770Sstevel@tonic-gateR<?> $+ < @ $=w > $: <> <$1 < @ $2 >> $| <F:$1@$2> <U:$1@> <D:$2> 20780Sstevel@tonic-gateR<?> $+ < @ $* > $: <> <$1 < @ $2 >> $| <F:$1@$2> <D:$2> 20790Sstevel@tonic-gateR<?> $+ $: <> <$1> $| <U:$1@> 20800Sstevel@tonic-gatednl $| is used as delimiter, otherwise false matches may occur: <user<@domain>> 20810Sstevel@tonic-gatednl will only return user<@domain when "reversing" the args 20820Sstevel@tonic-gateR<> <$*> $| <$+> $: <@> <$1> $| $>SearchList <+ To> $| <$2> <> 20830Sstevel@tonic-gateR<@> <$*> $| <$*> $: <$2> <$1> reverse result 20840Sstevel@tonic-gateR<?> <$*> $: @ $1 mark address as no match 20850Sstevel@tonic-gatednl we may have to filter here because otherwise some RHSs 20860Sstevel@tonic-gatednl would be interpreted as generic error messages... 20870Sstevel@tonic-gatednl error messages should be "tagged" by prefixing them with error: ! 20880Sstevel@tonic-gatednl that would make a lot of things easier. 20890Sstevel@tonic-gateR<$={Accept}> <$*> $: @ $2 mark address as no match 20900Sstevel@tonic-gateifdef(`_ACCESS_SKIP_', `dnl 20910Sstevel@tonic-gateR<SKIP> <$*> $: @ $1 mark address as no match', `dnl') 20920Sstevel@tonic-gateifdef(`_DELAY_COMPAT_8_10_',`dnl 20930Sstevel@tonic-gatednl compatility with 8.11/8.10: 20940Sstevel@tonic-gatednl we have to filter these because otherwise they would be interpreted 20950Sstevel@tonic-gatednl as generic error message... 20960Sstevel@tonic-gatednl error messages should be "tagged" by prefixing them with error: ! 20970Sstevel@tonic-gatednl that would make a lot of things easier. 20980Sstevel@tonic-gatednl maybe we should stop checks already here (if SPAM_xyx)? 20990Sstevel@tonic-gateR<$={SpamTag}> <$*> $: @ $2 mark address as no match') 21000Sstevel@tonic-gateR<REJECT> $* $#error $@ 5.2.1 $: confRCPTREJ_MSG 21010Sstevel@tonic-gateR<DISCARD> $* $#discard $: discard 21020Sstevel@tonic-gateR<QUARANTINE:$+> $* $#error $@ quarantine $: $1 21030Sstevel@tonic-gatednl error tag 21040Sstevel@tonic-gateR<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4 21050Sstevel@tonic-gateR<ERROR:$+> $* $#error $: $1 21060Sstevel@tonic-gateifdef(`_ATMPF_', `R<_ATMPF_> $* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 21070Sstevel@tonic-gatednl generic error from access map 21080Sstevel@tonic-gateR<$+> $* $#error $: $1 error from access db 21090Sstevel@tonic-gateR@ $* $1 remove mark', `dnl')', `dnl') 21100Sstevel@tonic-gate 21110Sstevel@tonic-gateifdef(`_PROMISCUOUS_RELAY_', `divert(-1)', `dnl') 21120Sstevel@tonic-gate# authenticated via TLS? 21130Sstevel@tonic-gateR$* $: $1 $| $>RelayTLS client authenticated? 21140Sstevel@tonic-gateR$* $| $# $+ $# $2 error/ok? 21150Sstevel@tonic-gateR$* $| $* $: $1 no 21160Sstevel@tonic-gate 21170Sstevel@tonic-gateR$* $: $1 $| $>"Local_Relay_Auth" $&{auth_type} 21180Sstevel@tonic-gatednl workspace: localpart<@domain> $| result of Local_Relay_Auth 21190Sstevel@tonic-gateR$* $| $# $* $# $2 21200Sstevel@tonic-gatednl if Local_Relay_Auth returns NO then do not check $={TrustAuthMech} 21210Sstevel@tonic-gateR$* $| NO $: $1 21220Sstevel@tonic-gateR$* $| $* $: $1 $| $&{auth_type} 21230Sstevel@tonic-gatednl workspace: localpart<@domain> [ $| ${auth_type} ] 21240Sstevel@tonic-gatednl empty ${auth_type}? 21250Sstevel@tonic-gateR$* $| $: $1 21260Sstevel@tonic-gatednl mechanism ${auth_type} accepted? 21270Sstevel@tonic-gatednl use $# to override further tests (delay_checks): see check_rcpt below 21280Sstevel@tonic-gateR$* $| $={TrustAuthMech} $# RELAY 21290Sstevel@tonic-gatednl remove ${auth_type} 21300Sstevel@tonic-gateR$* $| $* $: $1 21310Sstevel@tonic-gatednl workspace: localpart<@domain> | localpart 21320Sstevel@tonic-gateifelse(defn(`_NO_UUCP_'), `r', 21330Sstevel@tonic-gate`R$* ! $* < @ $* > $: <REMOTE> $2 < @ BANG_PATH > 21340Sstevel@tonic-gateR$* ! $* $: <REMOTE> $2 < @ BANG_PATH >', `dnl') 21350Sstevel@tonic-gate# anything terminating locally is ok 21360Sstevel@tonic-gateifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 21370Sstevel@tonic-gateR$+ < @ $* $=m > $@ RELAY', `dnl') 21380Sstevel@tonic-gateR$+ < @ $=w > $@ RELAY 21390Sstevel@tonic-gateifdef(`_RELAY_HOSTS_ONLY_', 21400Sstevel@tonic-gate`R$+ < @ $=R > $@ RELAY 21410Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 21420Sstevel@tonic-gateR$+ < @ $+ > $: <$(access To:$2 $: ? $)> <$1 < @ $2 >> 21430Sstevel@tonic-gatednl workspace: <Result-of-lookup | ?> <localpart<@domain>> 21440Sstevel@tonic-gateR<?> <$+ < @ $+ >> $: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')', 21450Sstevel@tonic-gate`R$+ < @ $* $=R > $@ RELAY 21460Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 21470Sstevel@tonic-gateifdef(`_RELAY_FULL_ADDR_', `dnl 21480Sstevel@tonic-gateR$+ < @ $+ > $: $1 < @ $2 > $| $>SearchList <+ To> $| <F:$1@$2> <D:$2> <F:$1@> <> 21490Sstevel@tonic-gateR$+ < @ $+ > $| <$*> $: <$3> <$1 <@ $2>> 21500Sstevel@tonic-gateR$+ < @ $+ > $| $* $: <$3> <$1 <@ $2>>', 21510Sstevel@tonic-gate`R$+ < @ $+ > $: $>D <$2> <?> <+ To> <$1 < @ $2 >>')')') 21520Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 21530Sstevel@tonic-gatednl workspace: <Result-of-lookup | ?> <localpart<@domain>> 21540Sstevel@tonic-gateR<RELAY> $* $@ RELAY 21550Sstevel@tonic-gateifdef(`_ATMPF_', `R<$* _ATMPF_> $* $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 21560Sstevel@tonic-gateR<$*> <$*> $: $2',`dnl') 21570Sstevel@tonic-gate 21580Sstevel@tonic-gate 21590Sstevel@tonic-gateifdef(`_RELAY_MX_SERVED_', `dnl 21600Sstevel@tonic-gate# allow relaying for hosts which we MX serve 21610Sstevel@tonic-gateR$+ < @ $+ > $: < : $(mxserved $2 $) : > $1 < @ $2 > 21620Sstevel@tonic-gatednl this must not necessarily happen if the client is checked first... 21630Sstevel@tonic-gateR< : $* <TEMP> : > $* $#TEMP $@ 4.4.0 $: "450 Can not check MX records for recipient host " $1 21640Sstevel@tonic-gateR<$* : $=w . : $*> $* $@ RELAY 21650Sstevel@tonic-gateR< : $* : > $* $: $2', 21660Sstevel@tonic-gate`dnl') 21670Sstevel@tonic-gate 21680Sstevel@tonic-gate# check for local user (i.e. unqualified address) 21690Sstevel@tonic-gateR$* $: <?> $1 21700Sstevel@tonic-gateR<?> $* < @ $+ > $: <REMOTE> $1 < @ $2 > 21710Sstevel@tonic-gate# local user is ok 21720Sstevel@tonic-gatednl is it really? the standard requires user@domain, not just user 21730Sstevel@tonic-gatednl but we should accept it anyway (maybe making it an option: 21740Sstevel@tonic-gatednl RequireFQDN ?) 21750Sstevel@tonic-gatednl postmaster must be accepted without domain (DRUMS) 21760Sstevel@tonic-gateifdef(`_REQUIRE_QUAL_RCPT_', `dnl 21770Sstevel@tonic-gateR<?> postmaster $@ OK 21780Sstevel@tonic-gate# require qualified recipient? 21790Sstevel@tonic-gatednl prepend daemon_flags 21800Sstevel@tonic-gateR<?> $+ $: $&{daemon_flags} $| <?> $1 21810Sstevel@tonic-gatednl workspace: ${daemon_flags} $| <?> localpart 21820Sstevel@tonic-gatednl do not allow these at all or only from local systems? 21830Sstevel@tonic-gatednl r flag? add client_name 21840Sstevel@tonic-gateR$* r $* $| <?> $+ $: < ? $&{client_name} > <?> $3 21850Sstevel@tonic-gatednl no r flag: relay to local user (only local part) 21860Sstevel@tonic-gate# no qualified recipient required 21870Sstevel@tonic-gateR$* $| <?> $+ $@ RELAY 21880Sstevel@tonic-gatednl client_name is empty 21890Sstevel@tonic-gateR<?> <?> $+ $@ RELAY 21900Sstevel@tonic-gatednl client_name is local 21910Sstevel@tonic-gateR<? $=w> <?> $+ $@ RELAY 21920Sstevel@tonic-gatednl client_name is not local 21930Sstevel@tonic-gateR<? $+> $+ $#error $@ 5.5.4 $: "553 Domain name required"', `dnl 21940Sstevel@tonic-gatednl no qualified recipient required 21950Sstevel@tonic-gateR<?> $+ $@ RELAY') 21960Sstevel@tonic-gatednl it is a remote user: remove mark and then check client 21970Sstevel@tonic-gateR<$+> $* $: $2 21980Sstevel@tonic-gatednl currently the recipient address is not used below 21990Sstevel@tonic-gate 22000Sstevel@tonic-gate###################################################################### 22010Sstevel@tonic-gate### Relay_ok: is the relay/sender ok? 22020Sstevel@tonic-gatednl input: ignored 22030Sstevel@tonic-gatednl output: see explanation at call 22040Sstevel@tonic-gate###################################################################### 22050Sstevel@tonic-gateSRelay_ok 22060Sstevel@tonic-gate# anything originating locally is ok 22070Sstevel@tonic-gate# check IP address 22080Sstevel@tonic-gateR$* $: $&{client_addr} 22090Sstevel@tonic-gateR$@ $@ RELAY originated locally 22100Sstevel@tonic-gateR0 $@ RELAY originated locally 22110Sstevel@tonic-gateR127.0.0.1 $@ RELAY originated locally 22120Sstevel@tonic-gateRIPv6:::1 $@ RELAY originated locally 22130Sstevel@tonic-gateR$=R $* $@ RELAY relayable IP address 22140Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 22150Sstevel@tonic-gateR$* $: $>A <$1> <?> <+ Connect> <$1> 22160Sstevel@tonic-gateR<RELAY> $* $@ RELAY relayable IP address 22170Sstevel@tonic-gateifdef(`_FFR_REJECT_IP_IN_CHECK_RCPT_',`dnl 22180Sstevel@tonic-gatednl this will cause rejections in cases like: 22190Sstevel@tonic-gatednl Connect:My.Host.Domain RELAY 22200Sstevel@tonic-gatednl Connect:My.Net REJECT 22210Sstevel@tonic-gatednl since in check_relay client_name is checked before client_addr 22220Sstevel@tonic-gateR<REJECT> $* $@ REJECT rejected IP address') 22230Sstevel@tonic-gateifdef(`_ATMPF_', `R<_ATMPF_> $* $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 22240Sstevel@tonic-gateR<$*> <$*> $: $2', `dnl') 22250Sstevel@tonic-gateR$* $: [ $1 ] put brackets around it... 22260Sstevel@tonic-gateR$=w $@ RELAY ... and see if it is local 22270Sstevel@tonic-gate 22280Sstevel@tonic-gateifdef(`_RELAY_DB_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl 22290Sstevel@tonic-gateifdef(`_RELAY_LOCAL_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl 22300Sstevel@tonic-gateifdef(`_RELAY_MAIL_FROM_', `dnl 22310Sstevel@tonic-gatednl input: {client_addr} or something "broken" 22320Sstevel@tonic-gatednl just throw the input away; we do not need it. 22330Sstevel@tonic-gate# check whether FROM is allowed to use system as relay 22340Sstevel@tonic-gateR$* $: <?> $>CanonAddr $&f 22350Sstevel@tonic-gateR<?> $+ < @ $+ . > <?> $1 < @ $2 > remove trailing dot 22360Sstevel@tonic-gateifdef(`_RELAY_LOCAL_FROM_', `dnl 22370Sstevel@tonic-gate# check whether local FROM is ok 22380Sstevel@tonic-gateR<?> $+ < @ $=w > $@ RELAY FROM local', `dnl') 22390Sstevel@tonic-gateifdef(`_RELAY_DB_FROM_', `dnl 22400Sstevel@tonic-gateR<?> $+ < @ $+ > $: <@> $>SearchList <! From> $| <F:$1@$2> ifdef(`_RELAY_DB_FROM_DOMAIN_', ifdef(`_RELAY_HOSTS_ONLY_', `<E:$2>', `<D:$2>')) <> 22410Sstevel@tonic-gateR<@> <RELAY> $@ RELAY RELAY FROM sender ok 22420Sstevel@tonic-gateifdef(`_ATMPF_', `R<@> <_ATMPF_> $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 22430Sstevel@tonic-gate', `dnl 22440Sstevel@tonic-gateifdef(`_RELAY_DB_FROM_DOMAIN_', 22450Sstevel@tonic-gate`errprint(`*** ERROR: _RELAY_DB_FROM_DOMAIN_ requires _RELAY_DB_FROM_ 22460Sstevel@tonic-gate')', 22470Sstevel@tonic-gate`dnl') 22480Sstevel@tonic-gatednl')', `dnl') 22490Sstevel@tonic-gatednl notice: the rulesets above do not leave a unique workspace behind. 22500Sstevel@tonic-gatednl it does not matter in this case because the following rule ignores 22510Sstevel@tonic-gatednl the input. otherwise these rules must "clean up" the workspace. 22520Sstevel@tonic-gate 22530Sstevel@tonic-gate# check client name: first: did it resolve? 22540Sstevel@tonic-gatednl input: ignored 22550Sstevel@tonic-gateR$* $: < $&{client_resolve} > 22560Sstevel@tonic-gateR<TEMP> $#TEMP $@ 4.4.0 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} 22570Sstevel@tonic-gateR<FORGED> $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} 22580Sstevel@tonic-gateR<FAIL> $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} 22590Sstevel@tonic-gatednl ${client_resolve} should be OK, so go ahead 22600Sstevel@tonic-gateR$* $: <@> $&{client_name} 22610Sstevel@tonic-gatednl should not be necessary since it has been done for client_addr already 22620Sstevel@tonic-gatednl this rule actually may cause a problem if {client_name} resolves to "" 22630Sstevel@tonic-gatednl however, this should not happen since the forward lookup should fail 22640Sstevel@tonic-gatednl and {client_resolve} should be TEMP or FAIL. 22650Sstevel@tonic-gatednl nevertheless, removing the rule doesn't hurt. 22660Sstevel@tonic-gatednl R<@> $@ RELAY 22670Sstevel@tonic-gatednl workspace: <@> ${client_name} (not empty) 22680Sstevel@tonic-gate# pass to name server to make hostname canonical 22690Sstevel@tonic-gateR<@> $* $=P $:<?> $1 $2 22700Sstevel@tonic-gateR<@> $+ $:<?> $[ $1 $] 22710Sstevel@tonic-gatednl workspace: <?> ${client_name} (canonified) 22720Sstevel@tonic-gateR$* . $1 strip trailing dots 22730Sstevel@tonic-gateifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl 22740Sstevel@tonic-gateR<?> $* $=m $@ RELAY', `dnl') 22750Sstevel@tonic-gateR<?> $=w $@ RELAY 22760Sstevel@tonic-gateifdef(`_RELAY_HOSTS_ONLY_', 22770Sstevel@tonic-gate`R<?> $=R $@ RELAY 22780Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 22790Sstevel@tonic-gateR<?> $* $: <$(access Connect:$1 $: ? $)> <$1> 22800Sstevel@tonic-gateR<?> <$*> $: <$(access $1 $: ? $)> <$1>',`dnl')', 22810Sstevel@tonic-gate`R<?> $* $=R $@ RELAY 22820Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 22830Sstevel@tonic-gateR<?> $* $: $>D <$1> <?> <+ Connect> <$1>',`dnl')') 22840Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 22850Sstevel@tonic-gateR<RELAY> $* $@ RELAY 22860Sstevel@tonic-gateifdef(`_ATMPF_', `R<$* _ATMPF_> $* $#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 22870Sstevel@tonic-gateR<$*> <$*> $: $2',`dnl') 22880Sstevel@tonic-gatednl end of _PROMISCUOUS_RELAY_ 22890Sstevel@tonic-gatedivert(0) 22900Sstevel@tonic-gateifdef(`_DELAY_CHECKS_',`dnl 22910Sstevel@tonic-gate# turn a canonical address in the form user<@domain> 22920Sstevel@tonic-gate# qualify unqual. addresses with $j 22930Sstevel@tonic-gatednl it might have been only user (without <@domain>) 22940Sstevel@tonic-gateSFullAddr 22950Sstevel@tonic-gateR$* <@ $+ . > $1 <@ $2 > 22960Sstevel@tonic-gateR$* <@ $* > $@ $1 <@ $2 > 22970Sstevel@tonic-gateR$+ $@ $1 <@ $j > 22980Sstevel@tonic-gate 22990Sstevel@tonic-gateSDelay_TLS_Clt 23000Sstevel@tonic-gate# authenticated? 23010Sstevel@tonic-gatednl code repeated here from Basic_check_mail 23020Sstevel@tonic-gatednl only called from check_rcpt in delay mode if checkrcpt returns $# 23030Sstevel@tonic-gateR$* $: $1 $| $>"tls_client" $&{verify} $| MAIL 23040Sstevel@tonic-gateR$* $| $#$+ $#$2 23050Sstevel@tonic-gatednl return result from checkrcpt 23060Sstevel@tonic-gateR$* $| $* $# $1 23070Sstevel@tonic-gateR$* $# $1 23080Sstevel@tonic-gate 23090Sstevel@tonic-gateSDelay_TLS_Clt2 23100Sstevel@tonic-gate# authenticated? 23110Sstevel@tonic-gatednl code repeated here from Basic_check_mail 23120Sstevel@tonic-gatednl only called from check_rcpt in delay mode if stopping due to Friend/Hater 23130Sstevel@tonic-gateR$* $: $1 $| $>"tls_client" $&{verify} $| MAIL 23140Sstevel@tonic-gateR$* $| $#$+ $#$2 23150Sstevel@tonic-gatednl return result from friend/hater check 23160Sstevel@tonic-gateR$* $| $* $@ $1 23170Sstevel@tonic-gateR$* $@ $1 23180Sstevel@tonic-gate 23190Sstevel@tonic-gate# call all necessary rulesets 23200Sstevel@tonic-gateScheck_rcpt 23210Sstevel@tonic-gatednl this test should be in the Basic_check_rcpt ruleset 23220Sstevel@tonic-gatednl which is the correct DSN code? 23230Sstevel@tonic-gate# R$@ $#error $@ 5.1.3 $: "553 Recipient address required" 23240Sstevel@tonic-gate 23250Sstevel@tonic-gateR$+ $: $1 $| $>checkrcpt $1 23260Sstevel@tonic-gatednl now we can simply stop checks by returning "$# xyz" instead of just "ok" 23270Sstevel@tonic-gatednl on error (or discard) stop now 23280Sstevel@tonic-gateR$+ $| $#error $* $#error $2 23290Sstevel@tonic-gateR$+ $| $#discard $* $#discard $2 23300Sstevel@tonic-gatednl otherwise call tls_client; see above 23310Sstevel@tonic-gateR$+ $| $#$* $@ $>"Delay_TLS_Clt" $2 23320Sstevel@tonic-gateR$+ $| $* $: <?> $>FullAddr $>CanonAddr $1 23330Sstevel@tonic-gateifdef(`_SPAM_FH_', 23340Sstevel@tonic-gate`dnl lookup user@ and user@address 23350Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `', 23360Sstevel@tonic-gate`errprint(`*** ERROR: FEATURE(`delay_checks', `argument') requires FEATURE(`access_db') 23370Sstevel@tonic-gate')')dnl 23380Sstevel@tonic-gatednl one of the next two rules is supposed to match 23390Sstevel@tonic-gatednl this code has been copied from BLACKLIST... etc 23400Sstevel@tonic-gatednl and simplified by omitting some < >. 23410Sstevel@tonic-gateR<?> $+ < @ $=w > $: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 > <U: $1@> 23420Sstevel@tonic-gateR<?> $+ < @ $* > $: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 > 23430Sstevel@tonic-gatednl R<?> $@ something_is_very_wrong_here 23440Sstevel@tonic-gate# lookup the addresses only with Spam tag 23450Sstevel@tonic-gateR<> $* $| <$+> $: <@> $1 $| $>SearchList <! Spam> $| <$2> <> 23460Sstevel@tonic-gateR<@> $* $| $* $: $2 $1 reverse result 23470Sstevel@tonic-gatednl', `dnl') 23480Sstevel@tonic-gateifdef(`_SPAM_FRIEND_', 23490Sstevel@tonic-gate`# is the recipient a spam friend? 23500Sstevel@tonic-gateifdef(`_SPAM_HATER_', 23510Sstevel@tonic-gate `errprint(`*** ERROR: define either Hater or Friend -- not both. 23520Sstevel@tonic-gate')', `dnl') 23530Sstevel@tonic-gateR<FRIEND> $+ $@ $>"Delay_TLS_Clt2" SPAMFRIEND 23540Sstevel@tonic-gateR<$*> $+ $: $2', 23550Sstevel@tonic-gate`dnl') 23560Sstevel@tonic-gateifdef(`_SPAM_HATER_', 23570Sstevel@tonic-gate`# is the recipient no spam hater? 23580Sstevel@tonic-gateR<HATER> $+ $: $1 spam hater: continue checks 23590Sstevel@tonic-gateR<$*> $+ $@ $>"Delay_TLS_Clt2" NOSPAMHATER everyone else: stop 23600Sstevel@tonic-gatednl',`dnl') 2361*3544Sjbeck 23620Sstevel@tonic-gatednl run further checks: check_mail 23630Sstevel@tonic-gatednl should we "clean up" $&f? 23640Sstevel@tonic-gateifdef(`_FFR_MAIL_MACRO', 23650Sstevel@tonic-gate`R$* $: $1 $| $>checkmail $&{mail_from}', 23660Sstevel@tonic-gate`R$* $: $1 $| $>checkmail <$&f>') 23670Sstevel@tonic-gatednl recipient (canonical format) $| result of checkmail 23680Sstevel@tonic-gateR$* $| $#$* $#$2 23690Sstevel@tonic-gatednl run further checks: check_relay 23700Sstevel@tonic-gateR$* $| $* $: $1 $| $>checkrelay $&{client_name} $| $&{client_addr} 23710Sstevel@tonic-gateR$* $| $#$* $#$2 23720Sstevel@tonic-gateR$* $| $* $: $1 23730Sstevel@tonic-gate', `dnl') 23740Sstevel@tonic-gate 2375*3544Sjbeckifdef(`_BLOCK_BAD_HELO_', `dnl 2376*3544SjbeckR$* $: $1 $| <$&{auth_authen}> Get auth info 2377*3544Sjbeckdnl Bypass the test for users who have authenticated. 2378*3544SjbeckR$* $| <$+> $: $1 skip if auth 2379*3544SjbeckR$* $| <$*> $: $1 $| <$&{client_addr}> [$&s] Get connection info 2380*3544Sjbeckdnl Bypass for local clients -- IP address starts with $=R 2381*3544SjbeckR$* $| <$=R $*> [$*] $: $1 skip if local client 2382*3544Sjbeckdnl Bypass a "sendmail -bs" session, which use 0 for client ip address 2383*3544SjbeckR$* $| <0> [$*] $: $1 skip if sendmail -bs 2384*3544Sjbeckdnl Reject our IP - assumes "[ip]" is in class $=w 2385*3544SjbeckR$* $| <$*> $=w $#error $@ 5.7.1 $:"550 bogus HELO name used: " $&s 2386*3544Sjbeckdnl Reject our hostname 2387*3544SjbeckR$* $| <$*> [$=w] $#error $@ 5.7.1 $:"550 bogus HELO name used: " $&s 2388*3544Sjbeckdnl Pass anything else with a "." in the domain parameter 2389*3544SjbeckR$* $| <$*> [$+.$+] $: $1 qualified domain ok 2390*3544Sjbeckdnl Reject if there was no "." or only an initial or final "." 2391*3544SjbeckR$* $| <$*> [$*] $#error $@ 5.7.1 $:"550 bogus HELO name used: " $&s 2392*3544Sjbeckdnl Clean up the workspace 2393*3544SjbeckR$* $| $* $: $1 2394*3544Sjbeck', `dnl') 2395*3544Sjbeck 23960Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl', `divert(-1)') 23970Sstevel@tonic-gate###################################################################### 23980Sstevel@tonic-gate### F: LookUpFull -- search for an entry in access database 23990Sstevel@tonic-gate### 24000Sstevel@tonic-gate### lookup of full key (which should be an address) and 24010Sstevel@tonic-gate### variations if +detail exists: +* and without +detail 24020Sstevel@tonic-gate### 24030Sstevel@tonic-gate### Parameters: 24040Sstevel@tonic-gate### <$1> -- key 24050Sstevel@tonic-gate### <$2> -- default (what to return if not found in db) 24060Sstevel@tonic-gatednl must not be empty 24070Sstevel@tonic-gate### <$3> -- mark (must be <(!|+) single-token>) 24080Sstevel@tonic-gate### ! does lookup only with tag 24090Sstevel@tonic-gate### + does lookup with and without tag 24100Sstevel@tonic-gate### <$4> -- passthru (additional data passed unchanged through) 24110Sstevel@tonic-gatednl returns: <default> <passthru> 24120Sstevel@tonic-gatednl <result> <passthru> 24130Sstevel@tonic-gate###################################################################### 24140Sstevel@tonic-gate 24150Sstevel@tonic-gateSF 24160Sstevel@tonic-gatednl workspace: <key> <def> <o tag> <thru> 24170Sstevel@tonic-gatednl full lookup 24180Sstevel@tonic-gatednl 2 3 4 5 24190Sstevel@tonic-gateR<$+> <$*> <$- $-> <$*> $: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5> 24200Sstevel@tonic-gatednl no match, try without tag 24210Sstevel@tonic-gatednl 1 2 3 4 24220Sstevel@tonic-gateR<?> <$+> <$*> <+ $-> <$*> $: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4> 24230Sstevel@tonic-gatednl no match, +detail: try +* 24240Sstevel@tonic-gatednl 1 2 3 4 5 6 7 24250Sstevel@tonic-gateR<?> <$+ + $* @ $+> <$*> <$- $-> <$*> 24260Sstevel@tonic-gate $: <$(access $6`'_TAG_DELIM_`'$1+*@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7> 24270Sstevel@tonic-gatednl no match, +detail: try +* without tag 24280Sstevel@tonic-gatednl 1 2 3 4 5 6 24290Sstevel@tonic-gateR<?> <$+ + $* @ $+> <$*> <+ $-> <$*> 24300Sstevel@tonic-gate $: <$(access $1+*@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6> 24310Sstevel@tonic-gatednl no match, +detail: try without +detail 24320Sstevel@tonic-gatednl 1 2 3 4 5 6 7 24330Sstevel@tonic-gateR<?> <$+ + $* @ $+> <$*> <$- $-> <$*> 24340Sstevel@tonic-gate $: <$(access $6`'_TAG_DELIM_`'$1@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7> 24350Sstevel@tonic-gatednl no match, +detail: try without +detail and without tag 24360Sstevel@tonic-gatednl 1 2 3 4 5 6 24370Sstevel@tonic-gateR<?> <$+ + $* @ $+> <$*> <+ $-> <$*> 24380Sstevel@tonic-gate $: <$(access $1@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6> 24390Sstevel@tonic-gatednl no match, return <default> <passthru> 24400Sstevel@tonic-gatednl 1 2 3 4 5 24410Sstevel@tonic-gateR<?> <$+> <$*> <$- $-> <$*> $@ <$2> <$5> 24420Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 24430Sstevel@tonic-gatednl 2 3 4 5 24440Sstevel@tonic-gateR<$+ _ATMPF_> <$*> <$- $-> <$*> $@ <_ATMPF_> <$5>', `dnl') 24450Sstevel@tonic-gatednl match, return <match> <passthru> 24460Sstevel@tonic-gatednl 2 3 4 5 24470Sstevel@tonic-gateR<$+> <$*> <$- $-> <$*> $@ <$1> <$5> 24480Sstevel@tonic-gate 24490Sstevel@tonic-gate###################################################################### 24500Sstevel@tonic-gate### E: LookUpExact -- search for an entry in access database 24510Sstevel@tonic-gate### 24520Sstevel@tonic-gate### Parameters: 24530Sstevel@tonic-gate### <$1> -- key 24540Sstevel@tonic-gate### <$2> -- default (what to return if not found in db) 24550Sstevel@tonic-gatednl must not be empty 24560Sstevel@tonic-gate### <$3> -- mark (must be <(!|+) single-token>) 24570Sstevel@tonic-gate### ! does lookup only with tag 24580Sstevel@tonic-gate### + does lookup with and without tag 24590Sstevel@tonic-gate### <$4> -- passthru (additional data passed unchanged through) 24600Sstevel@tonic-gatednl returns: <default> <passthru> 24610Sstevel@tonic-gatednl <result> <passthru> 24620Sstevel@tonic-gate###################################################################### 24630Sstevel@tonic-gate 24640Sstevel@tonic-gateSE 24650Sstevel@tonic-gatednl 2 3 4 5 24660Sstevel@tonic-gateR<$*> <$*> <$- $-> <$*> $: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5> 24670Sstevel@tonic-gatednl no match, try without tag 24680Sstevel@tonic-gatednl 1 2 3 4 24690Sstevel@tonic-gateR<?> <$+> <$*> <+ $-> <$*> $: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4> 24700Sstevel@tonic-gatednl no match, return default passthru 24710Sstevel@tonic-gatednl 1 2 3 4 5 24720Sstevel@tonic-gateR<?> <$+> <$*> <$- $-> <$*> $@ <$2> <$5> 24730Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 24740Sstevel@tonic-gatednl 2 3 4 5 24750Sstevel@tonic-gateR<$+ _ATMPF_> <$*> <$- $-> <$*> $@ <_ATMPF_> <$5>', `dnl') 24760Sstevel@tonic-gatednl match, return <match> <passthru> 24770Sstevel@tonic-gatednl 2 3 4 5 24780Sstevel@tonic-gateR<$+> <$*> <$- $-> <$*> $@ <$1> <$5> 24790Sstevel@tonic-gate 24800Sstevel@tonic-gate###################################################################### 24810Sstevel@tonic-gate### U: LookUpUser -- search for an entry in access database 24820Sstevel@tonic-gate### 24830Sstevel@tonic-gate### lookup of key (which should be a local part) and 24840Sstevel@tonic-gate### variations if +detail exists: +* and without +detail 24850Sstevel@tonic-gate### 24860Sstevel@tonic-gate### Parameters: 24870Sstevel@tonic-gate### <$1> -- key (user@) 24880Sstevel@tonic-gate### <$2> -- default (what to return if not found in db) 24890Sstevel@tonic-gatednl must not be empty 24900Sstevel@tonic-gate### <$3> -- mark (must be <(!|+) single-token>) 24910Sstevel@tonic-gate### ! does lookup only with tag 24920Sstevel@tonic-gate### + does lookup with and without tag 24930Sstevel@tonic-gate### <$4> -- passthru (additional data passed unchanged through) 24940Sstevel@tonic-gatednl returns: <default> <passthru> 24950Sstevel@tonic-gatednl <result> <passthru> 24960Sstevel@tonic-gate###################################################################### 24970Sstevel@tonic-gate 24980Sstevel@tonic-gateSU 24990Sstevel@tonic-gatednl user lookups are always with trailing @ 25000Sstevel@tonic-gatednl 2 3 4 5 25010Sstevel@tonic-gateR<$+> <$*> <$- $-> <$*> $: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5> 25020Sstevel@tonic-gatednl no match, try without tag 25030Sstevel@tonic-gatednl 1 2 3 4 25040Sstevel@tonic-gateR<?> <$+> <$*> <+ $-> <$*> $: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4> 25050Sstevel@tonic-gatednl do not remove the @ from the lookup: 25060Sstevel@tonic-gatednl it is part of the +detail@ which is omitted for the lookup 25070Sstevel@tonic-gatednl no match, +detail: try +* 25080Sstevel@tonic-gatednl 1 2 3 4 5 6 25090Sstevel@tonic-gateR<?> <$+ + $* @> <$*> <$- $-> <$*> 25100Sstevel@tonic-gate $: <$(access $5`'_TAG_DELIM_`'$1+*@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6> 25110Sstevel@tonic-gatednl no match, +detail: try +* without tag 25120Sstevel@tonic-gatednl 1 2 3 4 5 25130Sstevel@tonic-gateR<?> <$+ + $* @> <$*> <+ $-> <$*> 25140Sstevel@tonic-gate $: <$(access $1+*@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5> 25150Sstevel@tonic-gatednl no match, +detail: try without +detail 25160Sstevel@tonic-gatednl 1 2 3 4 5 6 25170Sstevel@tonic-gateR<?> <$+ + $* @> <$*> <$- $-> <$*> 25180Sstevel@tonic-gate $: <$(access $5`'_TAG_DELIM_`'$1@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6> 25190Sstevel@tonic-gatednl no match, +detail: try without +detail and without tag 25200Sstevel@tonic-gatednl 1 2 3 4 5 25210Sstevel@tonic-gateR<?> <$+ + $* @> <$*> <+ $-> <$*> 25220Sstevel@tonic-gate $: <$(access $1@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5> 25230Sstevel@tonic-gatednl no match, return <default> <passthru> 25240Sstevel@tonic-gatednl 1 2 3 4 5 25250Sstevel@tonic-gateR<?> <$+> <$*> <$- $-> <$*> $@ <$2> <$5> 25260Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 25270Sstevel@tonic-gatednl 2 3 4 5 25280Sstevel@tonic-gateR<$+ _ATMPF_> <$*> <$- $-> <$*> $@ <_ATMPF_> <$5>', `dnl') 25290Sstevel@tonic-gatednl match, return <match> <passthru> 25300Sstevel@tonic-gatednl 2 3 4 5 25310Sstevel@tonic-gateR<$+> <$*> <$- $-> <$*> $@ <$1> <$5> 25320Sstevel@tonic-gate 25330Sstevel@tonic-gate###################################################################### 25340Sstevel@tonic-gate### SearchList: search a list of items in the access map 25350Sstevel@tonic-gate### Parameters: 25360Sstevel@tonic-gate### <exact tag> $| <mark:address> <mark:address> ... <> 25370Sstevel@tonic-gatednl maybe we should have a @ (again) in front of the mark to 25380Sstevel@tonic-gatednl avoid errorneous matches (with error messages?) 25390Sstevel@tonic-gatednl if we can make sure that tag is always a single token 25400Sstevel@tonic-gatednl then we can omit the delimiter $|, otherwise we need it 25410Sstevel@tonic-gatednl to avoid errorneous matchs (first rule: D: if there 25420Sstevel@tonic-gatednl is that mark somewhere in the list, it will be taken). 25430Sstevel@tonic-gatednl moreover, we can do some tricks to enforce lookup with 25440Sstevel@tonic-gatednl the tag only, e.g.: 25450Sstevel@tonic-gate### where "exact" is either "+" or "!": 25460Sstevel@tonic-gate### <+ TAG> lookup with and w/o tag 25470Sstevel@tonic-gate### <! TAG> lookup with tag 25480Sstevel@tonic-gatednl Warning: + and ! should be in OperatorChars (otherwise there must be 25490Sstevel@tonic-gatednl a blank between them and the tag. 25500Sstevel@tonic-gate### possible values for "mark" are: 25510Sstevel@tonic-gate### D: recursive host lookup (LookUpDomain) 25520Sstevel@tonic-gatednl A: recursive address lookup (LookUpAddress) [not yet required] 25530Sstevel@tonic-gate### E: exact lookup, no modifications 25540Sstevel@tonic-gate### F: full lookup, try user+ext@domain and user@domain 25550Sstevel@tonic-gate### U: user lookup, try user+ext and user (input must have trailing @) 25560Sstevel@tonic-gate### return: <RHS of lookup> or <?> (not found) 25570Sstevel@tonic-gate###################################################################### 25580Sstevel@tonic-gate 25590Sstevel@tonic-gate# class with valid marks for SearchList 25600Sstevel@tonic-gatednl if A is activated: add it 25610Sstevel@tonic-gateC{Src}E F D U ifdef(`_FFR_SRCHLIST_A', `A') 25620Sstevel@tonic-gateSSearchList 25630Sstevel@tonic-gate# just call the ruleset with the name of the tag... nice trick... 25640Sstevel@tonic-gatednl 2 3 4 25650Sstevel@tonic-gateR<$+> $| <$={Src}:$*> <$*> $: <$1> $| <$4> $| $>$2 <$3> <?> <$1> <> 25660Sstevel@tonic-gatednl workspace: <o tag> $| <rest> $| <result of lookup> <> 25670Sstevel@tonic-gatednl no match and nothing left: return 25680Sstevel@tonic-gateR<$+> $| <> $| <?> <> $@ <?> 25690Sstevel@tonic-gatednl no match but something left: continue 25700Sstevel@tonic-gateR<$+> $| <$+> $| <?> <> $@ $>SearchList <$1> $| <$2> 25710Sstevel@tonic-gatednl match: return 25720Sstevel@tonic-gateR<$+> $| <$*> $| <$+> <> $@ <$3> 25730Sstevel@tonic-gatednl return result from recursive invocation 25740Sstevel@tonic-gateR<$+> $| <$+> $@ <$2> 25750Sstevel@tonic-gatednl endif _ACCESS_TABLE_ 25760Sstevel@tonic-gatedivert(0) 25770Sstevel@tonic-gate 25780Sstevel@tonic-gate###################################################################### 25790Sstevel@tonic-gate### trust_auth: is user trusted to authenticate as someone else? 25800Sstevel@tonic-gate### 25810Sstevel@tonic-gate### Parameters: 25820Sstevel@tonic-gate### $1: AUTH= parameter from MAIL command 25830Sstevel@tonic-gate###################################################################### 25840Sstevel@tonic-gate 25850Sstevel@tonic-gatednl empty ruleset definition so it can be called 25860Sstevel@tonic-gateSLocal_trust_auth 25870Sstevel@tonic-gateStrust_auth 25880Sstevel@tonic-gateR$* $: $&{auth_type} $| $1 25890Sstevel@tonic-gate# required by RFC 2554 section 4. 25900Sstevel@tonic-gateR$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" 25910Sstevel@tonic-gatednl seems to be useful... 25920Sstevel@tonic-gateR$* $| $&{auth_authen} $@ identical 25930Sstevel@tonic-gateR$* $| <$&{auth_authen}> $@ identical 25940Sstevel@tonic-gatednl call user supplied code 25950Sstevel@tonic-gateR$* $| $* $: $1 $| $>"Local_trust_auth" $2 25960Sstevel@tonic-gateR$* $| $#$* $#$2 25970Sstevel@tonic-gatednl default: error 25980Sstevel@tonic-gateR$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} 25990Sstevel@tonic-gate 26000Sstevel@tonic-gate###################################################################### 26010Sstevel@tonic-gate### Relay_Auth: allow relaying based on authentication? 26020Sstevel@tonic-gate### 26030Sstevel@tonic-gate### Parameters: 26040Sstevel@tonic-gate### $1: ${auth_type} 26050Sstevel@tonic-gate###################################################################### 26060Sstevel@tonic-gateSLocal_Relay_Auth 26070Sstevel@tonic-gate 26080Sstevel@tonic-gate###################################################################### 26090Sstevel@tonic-gate### srv_features: which features to offer to a client? 26100Sstevel@tonic-gate### (done in server) 26110Sstevel@tonic-gate###################################################################### 26120Sstevel@tonic-gateSsrv_features 26130Sstevel@tonic-gateifdef(`_LOCAL_SRV_FEATURES_', `dnl 26140Sstevel@tonic-gateR$* $: $1 $| $>"Local_srv_features" $1 26150Sstevel@tonic-gateR$* $| $#$* $#$2 26160Sstevel@tonic-gateR$* $| $* $: $1', `dnl') 26170Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 26180Sstevel@tonic-gateR$* $: $>D <$&{client_name}> <?> <! SRV_FEAT_TAG> <> 26190Sstevel@tonic-gateR<?>$* $: $>A <$&{client_addr}> <?> <! SRV_FEAT_TAG> <> 26200Sstevel@tonic-gateR<?>$* $: <$(access SRV_FEAT_TAG`'_TAG_DELIM_ $: ? $)> 26210Sstevel@tonic-gateR<?>$* $@ OK 26220Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 26230Sstevel@tonic-gateR<$* _ATMPF_>$* $#temp', `dnl') 26240Sstevel@tonic-gateR<$+>$* $# $1') 26250Sstevel@tonic-gate 26260Sstevel@tonic-gate###################################################################### 26270Sstevel@tonic-gate### try_tls: try to use STARTTLS? 26280Sstevel@tonic-gate### (done in client) 26290Sstevel@tonic-gate###################################################################### 26300Sstevel@tonic-gateStry_tls 26310Sstevel@tonic-gateifdef(`_LOCAL_TRY_TLS_', `dnl 26320Sstevel@tonic-gateR$* $: $1 $| $>"Local_try_tls" $1 26330Sstevel@tonic-gateR$* $| $#$* $#$2 26340Sstevel@tonic-gateR$* $| $* $: $1', `dnl') 26350Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 26360Sstevel@tonic-gateR$* $: $>D <$&{server_name}> <?> <! TLS_TRY_TAG> <> 26370Sstevel@tonic-gateR<?>$* $: $>A <$&{server_addr}> <?> <! TLS_TRY_TAG> <> 26380Sstevel@tonic-gateR<?>$* $: <$(access TLS_TRY_TAG`'_TAG_DELIM_ $: ? $)> 26390Sstevel@tonic-gateR<?>$* $@ OK 26400Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 26410Sstevel@tonic-gateR<$* _ATMPF_>$* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 26420Sstevel@tonic-gateR<NO>$* $#error $@ 5.7.1 $: "550 do not try TLS with " $&{server_name} " ["$&{server_addr}"]"') 26430Sstevel@tonic-gate 26440Sstevel@tonic-gate###################################################################### 26450Sstevel@tonic-gate### tls_rcpt: is connection with server "good" enough? 26460Sstevel@tonic-gate### (done in client, per recipient) 26470Sstevel@tonic-gatednl called from deliver() before RCPT command 26480Sstevel@tonic-gate### 26490Sstevel@tonic-gate### Parameters: 26500Sstevel@tonic-gate### $1: recipient 26510Sstevel@tonic-gate###################################################################### 26520Sstevel@tonic-gateStls_rcpt 26530Sstevel@tonic-gateifdef(`_LOCAL_TLS_RCPT_', `dnl 26540Sstevel@tonic-gateR$* $: $1 $| $>"Local_tls_rcpt" $1 26550Sstevel@tonic-gateR$* $| $#$* $#$2 26560Sstevel@tonic-gateR$* $| $* $: $1', `dnl') 26570Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 26580Sstevel@tonic-gatednl store name of other side 26590Sstevel@tonic-gateR$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1 26600Sstevel@tonic-gatednl canonify recipient address 26610Sstevel@tonic-gateR$+ $: <?> $>CanonAddr $1 26620Sstevel@tonic-gatednl strip trailing dots 26630Sstevel@tonic-gateR<?> $+ < @ $+ . > <?> $1 <@ $2 > 26640Sstevel@tonic-gatednl full address? 26650Sstevel@tonic-gateR<?> $+ < @ $+ > $: $1 <@ $2 > $| <F:$1@$2> <U:$1@> <D:$2> <E:> 26660Sstevel@tonic-gatednl only localpart? 26670Sstevel@tonic-gateR<?> $+ $: $1 $| <U:$1@> <E:> 26680Sstevel@tonic-gatednl look it up 26690Sstevel@tonic-gatednl also look up a default value via E: 26700Sstevel@tonic-gateR$* $| $+ $: $1 $| $>SearchList <! TLS_RCPT_TAG> $| $2 <> 26710Sstevel@tonic-gatednl found nothing: stop here 26720Sstevel@tonic-gateR$* $| <?> $@ OK 26730Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 26740Sstevel@tonic-gateR$* $| <$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 26750Sstevel@tonic-gatednl use the generic routine (for now) 26760Sstevel@tonic-gateR$* $| <$+> $@ $>"TLS_connection" $&{verify} $| <$2>') 26770Sstevel@tonic-gate 26780Sstevel@tonic-gate###################################################################### 26790Sstevel@tonic-gate### tls_client: is connection with client "good" enough? 26800Sstevel@tonic-gate### (done in server) 26810Sstevel@tonic-gate### 26820Sstevel@tonic-gate### Parameters: 26830Sstevel@tonic-gate### ${verify} $| (MAIL|STARTTLS) 26840Sstevel@tonic-gate###################################################################### 26850Sstevel@tonic-gatednl MAIL: called from check_mail 26860Sstevel@tonic-gatednl STARTTLS: called from smtp() after STARTTLS has been accepted 26870Sstevel@tonic-gateStls_client 26880Sstevel@tonic-gateifdef(`_LOCAL_TLS_CLIENT_', `dnl 26890Sstevel@tonic-gateR$* $: $1 $| $>"Local_tls_client" $1 26900Sstevel@tonic-gateR$* $| $#$* $#$2 26910Sstevel@tonic-gateR$* $| $* $: $1', `dnl') 26920Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 26930Sstevel@tonic-gatednl store name of other side 26940Sstevel@tonic-gateR$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1 26950Sstevel@tonic-gatednl ignore second arg for now 26960Sstevel@tonic-gatednl maybe use it to distinguish permanent/temporary error? 26970Sstevel@tonic-gatednl if MAIL: permanent (STARTTLS has not been offered) 26980Sstevel@tonic-gatednl if STARTTLS: temporary (offered but maybe failed) 26990Sstevel@tonic-gateR$* $| $* $: $1 $| $>D <$&{client_name}> <?> <! TLS_CLT_TAG> <> 27000Sstevel@tonic-gateR$* $| <?>$* $: $1 $| $>A <$&{client_addr}> <?> <! TLS_CLT_TAG> <> 27010Sstevel@tonic-gatednl do a default lookup: just TLS_CLT_TAG 27020Sstevel@tonic-gateR$* $| <?>$* $: $1 $| <$(access TLS_CLT_TAG`'_TAG_DELIM_ $: ? $)> 27030Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 27040Sstevel@tonic-gateR$* $| <$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 27050Sstevel@tonic-gateR$* $@ $>"TLS_connection" $1', `dnl 27060Sstevel@tonic-gateR$* $| $* $@ $>"TLS_connection" $1') 27070Sstevel@tonic-gate 27080Sstevel@tonic-gate###################################################################### 27090Sstevel@tonic-gate### tls_server: is connection with server "good" enough? 27100Sstevel@tonic-gate### (done in client) 27110Sstevel@tonic-gate### 27120Sstevel@tonic-gate### Parameter: 27130Sstevel@tonic-gate### ${verify} 27140Sstevel@tonic-gate###################################################################### 27150Sstevel@tonic-gatednl i.e. has the server been authenticated and is encryption active? 27160Sstevel@tonic-gatednl called from deliver() after STARTTLS command 27170Sstevel@tonic-gateStls_server 27180Sstevel@tonic-gateifdef(`_LOCAL_TLS_SERVER_', `dnl 27190Sstevel@tonic-gateR$* $: $1 $| $>"Local_tls_server" $1 27200Sstevel@tonic-gateR$* $| $#$* $#$2 27210Sstevel@tonic-gateR$* $| $* $: $1', `dnl') 27220Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 27230Sstevel@tonic-gatednl store name of other side 27240Sstevel@tonic-gateR$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1 27250Sstevel@tonic-gateR$* $: $1 $| $>D <$&{server_name}> <?> <! TLS_SRV_TAG> <> 27260Sstevel@tonic-gateR$* $| <?>$* $: $1 $| $>A <$&{server_addr}> <?> <! TLS_SRV_TAG> <> 27270Sstevel@tonic-gatednl do a default lookup: just TLS_SRV_TAG 27280Sstevel@tonic-gateR$* $| <?>$* $: $1 $| <$(access TLS_SRV_TAG`'_TAG_DELIM_ $: ? $)> 27290Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 27300Sstevel@tonic-gateR$* $| <$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 27310Sstevel@tonic-gateR$* $@ $>"TLS_connection" $1', `dnl 27320Sstevel@tonic-gateR$* $@ $>"TLS_connection" $1') 27330Sstevel@tonic-gate 27340Sstevel@tonic-gate###################################################################### 27350Sstevel@tonic-gate### TLS_connection: is TLS connection "good" enough? 27360Sstevel@tonic-gate### 27370Sstevel@tonic-gate### Parameters: 27380Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 27390Sstevel@tonic-gate### ${verify} $| <Requirement> [<>]', `dnl 27400Sstevel@tonic-gate### ${verify}') 27410Sstevel@tonic-gate### Requirement: RHS from access map, may be ? for none. 27420Sstevel@tonic-gatednl syntax for Requirement: 27430Sstevel@tonic-gatednl [(PERM|TEMP)+] (VERIFY[:bits]|ENCR:bits) [+extensions] 27440Sstevel@tonic-gatednl extensions: could be a list of further requirements 27450Sstevel@tonic-gatednl for now: CN:string {cn_subject} == string 27460Sstevel@tonic-gate###################################################################### 27470Sstevel@tonic-gateSTLS_connection 27480Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl', `dnl use default error 27490Sstevel@tonic-gatednl deal with TLS handshake failures: abort 27500Sstevel@tonic-gateRSOFTWARE $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake." 27510Sstevel@tonic-gatedivert(-1)') 27520Sstevel@tonic-gatednl common ruleset for tls_{client|server} 27530Sstevel@tonic-gatednl input: ${verify} $| <ResultOfLookup> [<>] 27540Sstevel@tonic-gatednl remove optional <> 27550Sstevel@tonic-gateR$* $| <$*>$* $: $1 $| <$2> 27560Sstevel@tonic-gatednl workspace: ${verify} $| <ResultOfLookup> 27570Sstevel@tonic-gate# create the appropriate error codes 27580Sstevel@tonic-gatednl permanent or temporary error? 27590Sstevel@tonic-gateR$* $| <PERM + $={Tls} $*> $: $1 $| <503:5.7.0> <$2 $3> 27600Sstevel@tonic-gateR$* $| <TEMP + $={Tls} $*> $: $1 $| <403:4.7.0> <$2 $3> 27610Sstevel@tonic-gatednl default case depends on TLS_PERM_ERR 27620Sstevel@tonic-gateR$* $| <$={Tls} $*> $: $1 $| <ifdef(`TLS_PERM_ERR', `503:5.7.0', `403:4.7.0')> <$2 $3> 27630Sstevel@tonic-gatednl workspace: ${verify} $| [<SMTP:ESC>] <ResultOfLookup> 27640Sstevel@tonic-gate# deal with TLS handshake failures: abort 27650Sstevel@tonic-gateRSOFTWARE $| <$-:$+> $* $#error $@ $2 $: $1 " TLS handshake failed." 27660Sstevel@tonic-gatednl no <reply:dns> i.e. not requirements in the access map 27670Sstevel@tonic-gatednl use default error 27680Sstevel@tonic-gateRSOFTWARE $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake failed." 2769616Sjbeck# deal with TLS protocol errors: abort 2770616SjbeckRPROTOCOL $| <$-:$+> $* $#error $@ $2 $: $1 " STARTTLS failed." 2771616Sjbeckdnl no <reply:dns> i.e. not requirements in the access map 2772616Sjbeckdnl use default error 2773616SjbeckRPROTOCOL $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') STARTTLS failed." 27740Sstevel@tonic-gateR$* $| <$*> <VERIFY> $: <$2> <VERIFY> <> $1 27750Sstevel@tonic-gatednl separate optional requirements 27760Sstevel@tonic-gateR$* $| <$*> <VERIFY + $+> $: <$2> <VERIFY> <$3> $1 27770Sstevel@tonic-gateR$* $| <$*> <$={Tls}:$->$* $: <$2> <$3:$4> <> $1 27780Sstevel@tonic-gatednl separate optional requirements 27790Sstevel@tonic-gateR$* $| <$*> <$={Tls}:$- + $+>$* $: <$2> <$3:$4> <$5> $1 27800Sstevel@tonic-gatednl some other value in access map: accept 27810Sstevel@tonic-gatednl this also allows to override the default case (if used) 27820Sstevel@tonic-gateR$* $| $* $@ OK 27830Sstevel@tonic-gate# authentication required: give appropriate error 27840Sstevel@tonic-gate# other side did authenticate (via STARTTLS) 27850Sstevel@tonic-gatednl workspace: <SMTP:ESC> <{VERIFY,ENCR}[:BITS]> <[extensions]> ${verify} 27860Sstevel@tonic-gatednl only verification required and it succeeded 27870Sstevel@tonic-gateR<$*><VERIFY> <> OK $@ OK 27880Sstevel@tonic-gatednl verification required and it succeeded but extensions are given 27890Sstevel@tonic-gatednl change it to <SMTP:ESC> <REQ:0> <extensions> 27900Sstevel@tonic-gateR<$*><VERIFY> <$+> OK $: <$1> <REQ:0> <$2> 27910Sstevel@tonic-gatednl verification required + some level of encryption 27920Sstevel@tonic-gateR<$*><VERIFY:$-> <$*> OK $: <$1> <REQ:$2> <$3> 27930Sstevel@tonic-gatednl just some level of encryption required 27940Sstevel@tonic-gateR<$*><ENCR:$-> <$*> $* $: <$1> <REQ:$2> <$3> 27950Sstevel@tonic-gatednl workspace: 27960Sstevel@tonic-gatednl 1. <SMTP:ESC> <VERIFY [:bits]> <[extensions]> {verify} (!= OK) 27970Sstevel@tonic-gatednl 2. <SMTP:ESC> <REQ:bits> <[extensions]> 27980Sstevel@tonic-gatednl verification required but ${verify} is not set (case 1.) 27990Sstevel@tonic-gateR<$-:$+><VERIFY $*> <$*> $#error $@ $2 $: $1 " authentication required" 28000Sstevel@tonic-gateR<$-:$+><VERIFY $*> <$*> FAIL $#error $@ $2 $: $1 " authentication failed" 28010Sstevel@tonic-gateR<$-:$+><VERIFY $*> <$*> NO $#error $@ $2 $: $1 " not authenticated" 28020Sstevel@tonic-gateR<$-:$+><VERIFY $*> <$*> NOT $#error $@ $2 $: $1 " no authentication requested" 28030Sstevel@tonic-gateR<$-:$+><VERIFY $*> <$*> NONE $#error $@ $2 $: $1 " other side does not support STARTTLS" 28040Sstevel@tonic-gatednl some other value for ${verify} 28050Sstevel@tonic-gateR<$-:$+><VERIFY $*> <$*> $+ $#error $@ $2 $: $1 " authentication failure " $4 28060Sstevel@tonic-gatednl some level of encryption required: get the maximum level (case 2.) 28070Sstevel@tonic-gateR<$*><REQ:$-> <$*> $: <$1> <REQ:$2> <$3> $>max $&{cipher_bits} : $&{auth_ssf} 28080Sstevel@tonic-gatednl compare required bits with actual bits 28090Sstevel@tonic-gateR<$*><REQ:$-> <$*> $- $: <$1> <$2:$4> <$3> $(arith l $@ $4 $@ $2 $) 28100Sstevel@tonic-gateR<$-:$+><$-:$-> <$*> TRUE $#error $@ $2 $: $1 " encryption too weak " $4 " less than " $3 28110Sstevel@tonic-gatednl strength requirements fulfilled 28120Sstevel@tonic-gatednl TLS Additional Requirements Separator 28130Sstevel@tonic-gatednl this should be something which does not appear in the extensions itself 28140Sstevel@tonic-gatednl @ could be part of a CN, DN, etc... 28150Sstevel@tonic-gatednl use < > ? those are encoded in CN, DN, ... 28160Sstevel@tonic-gatedefine(`_TLS_ARS_', `++')dnl 28170Sstevel@tonic-gatednl workspace: 28180Sstevel@tonic-gatednl <SMTP:ESC> <REQ:bits> <extensions> result-of-compare 28190Sstevel@tonic-gateR<$-:$+><$-:$-> <$*> $* $: <$1:$2 _TLS_ARS_ $5> 28200Sstevel@tonic-gatednl workspace: <SMTP:ESC _TLS_ARS_ extensions> 28210Sstevel@tonic-gatednl continue: check extensions 28220Sstevel@tonic-gateR<$-:$+ _TLS_ARS_ > $@ OK 28230Sstevel@tonic-gatednl split extensions into own list 28240Sstevel@tonic-gateR<$-:$+ _TLS_ARS_ $+ > $: <$1:$2> <$3> 28250Sstevel@tonic-gateR<$-:$+> < $+ _TLS_ARS_ $+ > <$1:$2> <$3> <$4> 28260Sstevel@tonic-gateR<$-:$+> $+ $@ $>"TLS_req" $3 $| <$1:$2> 28270Sstevel@tonic-gate 28280Sstevel@tonic-gate###################################################################### 28290Sstevel@tonic-gate### TLS_req: check additional TLS requirements 28300Sstevel@tonic-gate### 28310Sstevel@tonic-gate### Parameters: [<list> <of> <req>] $| <$-:$+> 28320Sstevel@tonic-gate### $-: SMTP reply code 28330Sstevel@tonic-gate### $+: Enhanced Status Code 28340Sstevel@tonic-gatednl further requirements for this ruleset: 28350Sstevel@tonic-gatednl name of "other side" is stored is {TLS_name} (client/server_name) 28360Sstevel@tonic-gatednl 28370Sstevel@tonic-gatednl currently only CN[:common_name] is implemented 28380Sstevel@tonic-gatednl right now this is only a logical AND 28390Sstevel@tonic-gatednl i.e. all requirements must be true 28400Sstevel@tonic-gatednl how about an OR? CN must be X or CN must be Y or .. 28410Sstevel@tonic-gatednl use a macro to compute this as a trivial sequential 28420Sstevel@tonic-gatednl operations (no precedences etc)? 28430Sstevel@tonic-gate###################################################################### 28440Sstevel@tonic-gateSTLS_req 28450Sstevel@tonic-gatednl no additional requirements: ok 28460Sstevel@tonic-gateR $| $+ $@ OK 28470Sstevel@tonic-gatednl require CN: but no CN specified: use name of other side 28480Sstevel@tonic-gateR<CN> $* $| <$+> $: <CN:$&{TLS_Name}> $1 $| <$2> 28490Sstevel@tonic-gatednl match, check rest 28500Sstevel@tonic-gateR<CN:$&{cn_subject}> $* $| <$+> $@ $>"TLS_req" $1 $| <$2> 28510Sstevel@tonic-gatednl CN does not match 28520Sstevel@tonic-gatednl 1 2 3 4 28530Sstevel@tonic-gateR<CN:$+> $* $| <$-:$+> $#error $@ $4 $: $3 " CN " $&{cn_subject} " does not match " $1 28540Sstevel@tonic-gatednl cert subject 28550Sstevel@tonic-gateR<CS:$&{cert_subject}> $* $| <$+> $@ $>"TLS_req" $1 $| <$2> 28560Sstevel@tonic-gatednl CS does not match 28570Sstevel@tonic-gatednl 1 2 3 4 28580Sstevel@tonic-gateR<CS:$+> $* $| <$-:$+> $#error $@ $4 $: $3 " Cert Subject " $&{cert_subject} " does not match " $1 28590Sstevel@tonic-gatednl match, check rest 28600Sstevel@tonic-gateR<CI:$&{cert_issuer}> $* $| <$+> $@ $>"TLS_req" $1 $| <$2> 28610Sstevel@tonic-gatednl CI does not match 28620Sstevel@tonic-gatednl 1 2 3 4 28630Sstevel@tonic-gateR<CI:$+> $* $| <$-:$+> $#error $@ $4 $: $3 " Cert Issuer " $&{cert_issuer} " does not match " $1 28640Sstevel@tonic-gatednl return from recursive call 28650Sstevel@tonic-gateROK $@ OK 28660Sstevel@tonic-gate 28670Sstevel@tonic-gate###################################################################### 28680Sstevel@tonic-gate### max: return the maximum of two values separated by : 28690Sstevel@tonic-gate### 28700Sstevel@tonic-gate### Parameters: [$-]:[$-] 28710Sstevel@tonic-gate###################################################################### 28720Sstevel@tonic-gateSmax 28730Sstevel@tonic-gateR: $: 0 28740Sstevel@tonic-gateR:$- $: $1 28750Sstevel@tonic-gateR$-: $: $1 28760Sstevel@tonic-gateR$-:$- $: $(arith l $@ $1 $@ $2 $) : $1 : $2 28770Sstevel@tonic-gateRTRUE:$-:$- $: $2 28780Sstevel@tonic-gateR$-:$-:$- $: $2 28790Sstevel@tonic-gatednl endif _ACCESS_TABLE_ 28800Sstevel@tonic-gatedivert(0) 28810Sstevel@tonic-gate 28820Sstevel@tonic-gate###################################################################### 28830Sstevel@tonic-gate### RelayTLS: allow relaying based on TLS authentication 28840Sstevel@tonic-gate### 28850Sstevel@tonic-gate### Parameters: 28860Sstevel@tonic-gate### none 28870Sstevel@tonic-gate###################################################################### 28880Sstevel@tonic-gateSRelayTLS 28890Sstevel@tonic-gate# authenticated? 28900Sstevel@tonic-gatednl we do not allow relaying for anyone who can present a cert 28910Sstevel@tonic-gatednl signed by a "trusted" CA. For example, even if we put verisigns 28920Sstevel@tonic-gatednl CA in CertPath so we can authenticate users, we do not allow 28930Sstevel@tonic-gatednl them to abuse our server (they might be easier to get hold of, 28940Sstevel@tonic-gatednl but anyway). 28950Sstevel@tonic-gatednl so here is the trick: if the verification succeeded 28960Sstevel@tonic-gatednl we look up the cert issuer in the access map 28970Sstevel@tonic-gatednl (maybe after extracting a part with a regular expression) 28980Sstevel@tonic-gatednl if this returns RELAY we relay without further questions 28990Sstevel@tonic-gatednl if it returns SUBJECT we perform a similar check on the 29000Sstevel@tonic-gatednl cert subject. 29010Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 29020Sstevel@tonic-gateR$* $: <?> $&{verify} 29030Sstevel@tonic-gateR<?> OK $: OK authenticated: continue 29040Sstevel@tonic-gateR<?> $* $@ NO not authenticated 29050Sstevel@tonic-gateifdef(`_CERT_REGEX_ISSUER_', `dnl 29060Sstevel@tonic-gateR$* $: $(CERTIssuer $&{cert_issuer} $)', 29070Sstevel@tonic-gate`R$* $: $&{cert_issuer}') 29080Sstevel@tonic-gateR$+ $: $(access CERTISSUER`'_TAG_DELIM_`'$1 $) 29090Sstevel@tonic-gatednl use $# to stop further checks (delay_check) 29100Sstevel@tonic-gateRRELAY $# RELAY 29110Sstevel@tonic-gateifdef(`_CERT_REGEX_SUBJECT_', `dnl 29120Sstevel@tonic-gateRSUBJECT $: <@> $(CERTSubject $&{cert_subject} $)', 29130Sstevel@tonic-gate`RSUBJECT $: <@> $&{cert_subject}') 29140Sstevel@tonic-gateR<@> $+ $: <@> $(access CERTSUBJECT`'_TAG_DELIM_`'$1 $) 29150Sstevel@tonic-gateR<@> RELAY $# RELAY 29160Sstevel@tonic-gateR$* $: NO', `dnl') 29170Sstevel@tonic-gate 29180Sstevel@tonic-gate###################################################################### 29190Sstevel@tonic-gate### authinfo: lookup authinfo in the access map 29200Sstevel@tonic-gate### 29210Sstevel@tonic-gate### Parameters: 29220Sstevel@tonic-gate### $1: {server_name} 29230Sstevel@tonic-gate### $2: {server_addr} 29240Sstevel@tonic-gatednl both are currently ignored 29250Sstevel@tonic-gatednl if it should be done via another map, we either need to restrict 29260Sstevel@tonic-gatednl functionality (it calls D and A) or copy those rulesets (or add another 29270Sstevel@tonic-gatednl parameter which I want to avoid, it's quite complex already) 29280Sstevel@tonic-gate###################################################################### 29290Sstevel@tonic-gatednl omit this ruleset if neither is defined? 29300Sstevel@tonic-gatednl it causes DefaultAuthInfo to be ignored 29310Sstevel@tonic-gatednl (which may be considered a good thing). 29320Sstevel@tonic-gateSauthinfo 29330Sstevel@tonic-gateifdef(`_AUTHINFO_TABLE_', `dnl 29340Sstevel@tonic-gateR$* $: <$(authinfo AuthInfo:$&{server_name} $: ? $)> 29350Sstevel@tonic-gateR<?> $: <$(authinfo AuthInfo:$&{server_addr} $: ? $)> 29360Sstevel@tonic-gateR<?> $: <$(authinfo AuthInfo: $: ? $)> 29370Sstevel@tonic-gateR<?> $@ no no authinfo available 29380Sstevel@tonic-gateR<$*> $# $1 29390Sstevel@tonic-gatednl', `dnl 29400Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 29410Sstevel@tonic-gateR$* $: $1 $| $>D <$&{server_name}> <?> <! AuthInfo> <> 29420Sstevel@tonic-gateR$* $| <?>$* $: $1 $| $>A <$&{server_addr}> <?> <! AuthInfo> <> 29430Sstevel@tonic-gateR$* $| <?>$* $: $1 $| <$(access AuthInfo`'_TAG_DELIM_ $: ? $)> <> 29440Sstevel@tonic-gateR$* $| <?>$* $@ no no authinfo available 29450Sstevel@tonic-gateR$* $| <$*> <> $# $2 29460Sstevel@tonic-gatednl', `dnl')') 29470Sstevel@tonic-gate 29480Sstevel@tonic-gateifdef(`_RATE_CONTROL_',`dnl 29490Sstevel@tonic-gate###################################################################### 29500Sstevel@tonic-gate### RateControl: 29510Sstevel@tonic-gate### Parameters: ignored 29520Sstevel@tonic-gate### return: $#error or OK 29530Sstevel@tonic-gate###################################################################### 29540Sstevel@tonic-gateSRateControl 29550Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 29560Sstevel@tonic-gateR$* $: <A:$&{client_addr}> <E:> 29570Sstevel@tonic-gatednl also look up a default value via E: 29580Sstevel@tonic-gateR$+ $: $>SearchList <! ClientRate> $| $1 <> 29590Sstevel@tonic-gatednl found nothing: stop here 29600Sstevel@tonic-gateR<?> $@ OK 29610Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 29620Sstevel@tonic-gateR<$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 29630Sstevel@tonic-gatednl use the generic routine (for now) 29640Sstevel@tonic-gateR<0> $@ OK no limit 29650Sstevel@tonic-gateR<$+> $: <$1> $| $(arith l $@ $&{client_rate} $@ $1 $) 29660Sstevel@tonic-gatednl log this? Connection rate $&{client_rate} exceeds limit $1. 29670Sstevel@tonic-gateR<$+> $| FALSE $#error $@ 4.3.2 $: _RATE_CONTROL_REPLY Connection rate limit exceeded. 29680Sstevel@tonic-gate')') 29690Sstevel@tonic-gate 29700Sstevel@tonic-gateifdef(`_CONN_CONTROL_',`dnl 29710Sstevel@tonic-gate###################################################################### 29720Sstevel@tonic-gate### ConnControl: 29730Sstevel@tonic-gate### Parameters: ignored 29740Sstevel@tonic-gate### return: $#error or OK 29750Sstevel@tonic-gate###################################################################### 29760Sstevel@tonic-gateSConnControl 29770Sstevel@tonic-gateifdef(`_ACCESS_TABLE_', `dnl 29780Sstevel@tonic-gateR$* $: <A:$&{client_addr}> <E:> 29790Sstevel@tonic-gatednl also look up a default value via E: 29800Sstevel@tonic-gateR$+ $: $>SearchList <! ClientConn> $| $1 <> 29810Sstevel@tonic-gatednl found nothing: stop here 29820Sstevel@tonic-gateR<?> $@ OK 29830Sstevel@tonic-gateifdef(`_ATMPF_', `dnl tempfail? 29840Sstevel@tonic-gateR<$* _ATMPF_> $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl') 29850Sstevel@tonic-gatednl use the generic routine (for now) 29860Sstevel@tonic-gateR<0> $@ OK no limit 29870Sstevel@tonic-gateR<$+> $: <$1> $| $(arith l $@ $&{client_connections} $@ $1 $) 29880Sstevel@tonic-gatednl log this: Open connections $&{client_connections} exceeds limit $1. 29890Sstevel@tonic-gateR<$+> $| FALSE $#error $@ 4.3.2 $: _CONN_CONTROL_REPLY Too many open connections. 29900Sstevel@tonic-gate')') 29910Sstevel@tonic-gate 29920Sstevel@tonic-gateundivert(9)dnl LOCAL_RULESETS 29930Sstevel@tonic-gate# 29940Sstevel@tonic-gate###################################################################### 29950Sstevel@tonic-gate###################################################################### 29960Sstevel@tonic-gate##### 29970Sstevel@tonic-gate`##### MAIL FILTER DEFINITIONS' 29980Sstevel@tonic-gate##### 29990Sstevel@tonic-gate###################################################################### 30000Sstevel@tonic-gate###################################################################### 30010Sstevel@tonic-gate_MAIL_FILTERS_ 30020Sstevel@tonic-gate# 30030Sstevel@tonic-gate###################################################################### 30040Sstevel@tonic-gate###################################################################### 30050Sstevel@tonic-gate##### 30060Sstevel@tonic-gate`##### MAILER DEFINITIONS' 30070Sstevel@tonic-gate##### 30080Sstevel@tonic-gate###################################################################### 30090Sstevel@tonic-gate###################################################################### 30100Sstevel@tonic-gateundivert(7)dnl MAILER_DEFINITIONS 30110Sstevel@tonic-gate 3012