xref: /onnv-gate/usr/src/cmd/sendmail/cf/m4/proto.m4 (revision 11440:802724e2906a)
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