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