proto.m4 revision 110647
138032Speterdivert(-1)
238032Speter#
394334Sgshapiro# Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
464562Sgshapiro#	All rights reserved.
538032Speter# Copyright (c) 1983, 1995 Eric P. Allman.  All rights reserved.
638032Speter# Copyright (c) 1988, 1993
738032Speter#	The Regents of the University of California.  All rights reserved.
838032Speter#
938032Speter# By using this file, you agree to the terms and conditions set
1038032Speter# forth in the LICENSE file which can be found at the top level of
1138032Speter# the sendmail distribution.
1238032Speter#
1338032Speter#
1438032Speterdivert(0)
1538032Speter
16110647SgshapiroVERSIONID(`$Id: proto.m4,v 8.649.2.14 2002/12/30 15:46:02 ca Exp $')
1738032Speter
1864562Sgshapiro# level CF_LEVEL config file format
1964562SgshapiroV`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Berkeley')
2038032Speterdivert(-1)
2138032Speter
2290792Sgshapirodnl if MAILER(`local') not defined: do it ourself; be nice
2390792Sgshapirodnl maybe we should issue a warning?
2490792Sgshapiroifdef(`_MAILER_local_',`', `MAILER(local)')
2590792Sgshapiro
2638032Speter# do some sanity checking
2738032Speterifdef(`__OSTYPE__',,
2864562Sgshapiro	`errprint(`*** ERROR: No system type defined (use OSTYPE macro)
2964562Sgshapiro')')
3038032Speter
3138032Speter# pick our default mailers
3238032Speterifdef(`confSMTP_MAILER',, `define(`confSMTP_MAILER', `esmtp')')
3338032Speterifdef(`confLOCAL_MAILER',, `define(`confLOCAL_MAILER', `local')')
3438032Speterifdef(`confRELAY_MAILER',,
3538032Speter	`define(`confRELAY_MAILER',
3638032Speter		`ifdef(`_MAILER_smtp_', `relay',
3738032Speter			`ifdef(`_MAILER_uucp', `uucp-new', `unknown')')')')
3838032Speterifdef(`confUUCP_MAILER',, `define(`confUUCP_MAILER', `uucp-old')')
3938032Speterdefine(`_SMTP_', `confSMTP_MAILER')dnl		for readability only
4038032Speterdefine(`_LOCAL_', `confLOCAL_MAILER')dnl	for readability only
4138032Speterdefine(`_RELAY_', `confRELAY_MAILER')dnl	for readability only
4238032Speterdefine(`_UUCP_', `confUUCP_MAILER')dnl		for readability only
4338032Speter
4438032Speter# back compatibility with old config files
4538032Speterifdef(`confDEF_GROUP_ID',
4664562Sgshapiro`errprint(`*** confDEF_GROUP_ID is obsolete.
4764562Sgshapiro    Use confDEF_USER_ID with a colon in the value instead.
4864562Sgshapiro')')
4938032Speterifdef(`confREAD_TIMEOUT',
5064562Sgshapiro`errprint(`*** confREAD_TIMEOUT is obsolete.
5164562Sgshapiro    Use individual confTO_<timeout> parameters instead.
5264562Sgshapiro')')
5338032Speterifdef(`confMESSAGE_TIMEOUT',
5438032Speter	`define(`_ARG_', index(confMESSAGE_TIMEOUT, /))
5538032Speter	 ifelse(_ARG_, -1,
5638032Speter		`define(`confTO_QUEUERETURN', confMESSAGE_TIMEOUT)',
5738032Speter		`define(`confTO_QUEUERETURN',
5838032Speter			substr(confMESSAGE_TIMEOUT, 0, _ARG_))
5938032Speter		 define(`confTO_QUEUEWARN',
6038032Speter			substr(confMESSAGE_TIMEOUT, eval(_ARG_+1)))')')
6138032Speterifdef(`confMIN_FREE_BLOCKS', `ifelse(index(confMIN_FREE_BLOCKS, /), -1,,
6264562Sgshapiro`errprint(`*** compound confMIN_FREE_BLOCKS is obsolete.
6364562Sgshapiro    Use confMAX_MESSAGE_SIZE for the second part of the value.
6464562Sgshapiro')')')
6538032Speter
6664562Sgshapiro
6764562Sgshapiro# Sanity check on ldap_routing feature
6864562Sgshapiro# If the user doesn't specify a new map, they better have given as a
6964562Sgshapiro# default LDAP specification which has the LDAP base (and most likely the host)
7064562Sgshapiroifdef(`confLDAP_DEFAULT_SPEC',, `ifdef(`_LDAP_ROUTING_WARN_', `errprint(`
7164562SgshapiroWARNING: Using default FEATURE(ldap_routing) map definition(s)
7264562Sgshapirowithout setting confLDAP_DEFAULT_SPEC option.
7364562Sgshapiro')')')dnl
7464562Sgshapiro
7538032Speter# clean option definitions below....
7664562Sgshapirodefine(`_OPTION', `ifdef(`$2', `O $1`'ifelse(defn(`$2'), `',, `=$2')', `#O $1`'ifelse(`$3', `',,`=$3')')')dnl
7738032Speter
7864562Sgshapirodnl required to "rename" the check_* rulesets...
7964562Sgshapirodefine(`_U_',ifdef(`_DELAY_CHECKS_',`',`_'))
8064562Sgshapirodnl default relaying denied message
8190792Sgshapiroifdef(`confRELAY_MSG', `', `define(`confRELAY_MSG',
8290792Sgshapiroifdef(`_USE_AUTH_', `"550 Relaying denied. Proper authentication required."', `"550 Relaying denied"'))')
8390792Sgshapiroifdef(`confRCPTREJ_MSG', `', `define(`confRCPTREJ_MSG', `"550 Mailbox disabled for this recipient"')')
8490792Sgshapirodefine(`_CODE553', `553')
8538032Speterdivert(0)dnl
8638032Speter
8764562Sgshapiro# override file safeties - setting this option compromises system security,
8864562Sgshapiro# addressing the actual file configuration problem is preferred
8964562Sgshapiro# need to set this before any file actions are encountered in the cf file
9064562Sgshapiro_OPTION(DontBlameSendmail, `confDONT_BLAME_SENDMAIL', `safe')
9138032Speter
9264562Sgshapiro# default LDAP map specification
9364562Sgshapiro# need to set this now before any LDAP maps are defined
9464562Sgshapiro_OPTION(LDAPDefaultSpec, `confLDAP_DEFAULT_SPEC', `-h localhost')
9564562Sgshapiro
9638032Speter##################
9738032Speter#   local info   #
9838032Speter##################
9938032Speter
10090792Sgshapiro# my LDAP cluster
10190792Sgshapiro# need to set this before any LDAP lookups are done (including classes)
10290792Sgshapiroifdef(`confLDAP_CLUSTER', `D{sendmailMTACluster}`'confLDAP_CLUSTER', `#D{sendmailMTACluster}$m')
10390792Sgshapiro
10438032SpeterCwlocalhost
10538032Speterifdef(`USE_CW_FILE',
10638032Speter`# file containing names of hosts for which we receive email
10738032SpeterFw`'confCW_FILE',
10838032Speter	`dnl')
10938032Speter
11038032Speter# my official domain name
11138032Speter# ... `define' this only if sendmail cannot automatically determine your domain
11238032Speterifdef(`confDOMAIN_NAME', `Dj`'confDOMAIN_NAME', `#Dj$w.Foo.COM')
11338032Speter
11438032SpeterCP.
11538032Speter
11638032Speterifdef(`UUCP_RELAY',
11738032Speter`# UUCP relay host
11838032SpeterDY`'UUCP_RELAY
11938032SpeterCPUUCP
12038032Speter
12138032Speter')dnl
12238032Speterifdef(`BITNET_RELAY',
12338032Speter`#  BITNET relay host
12438032SpeterDB`'BITNET_RELAY
12538032SpeterCPBITNET
12638032Speter
12738032Speter')dnl
12838032Speterifdef(`DECNET_RELAY',
12938032Speter`define(`_USE_DECNET_SYNTAX_', 1)dnl
13038032Speter# DECnet relay host
13138032SpeterDC`'DECNET_RELAY
13238032SpeterCPDECNET
13338032Speter
13438032Speter')dnl
13538032Speterifdef(`FAX_RELAY',
13638032Speter`# FAX relay host
13738032SpeterDF`'FAX_RELAY
13838032SpeterCPFAX
13938032Speter
14038032Speter')dnl
14138032Speter# "Smart" relay host (may be null)
14290792SgshapiroDS`'ifdef(`SMART_HOST', `SMART_HOST')
14338032Speter
14438032Speterifdef(`LUSER_RELAY', `dnl
14538032Speter# place to which unknown users should be forwarded
14638032SpeterKuser user -m -a<>
14738032SpeterDL`'LUSER_RELAY',
14838032Speter`dnl')
14938032Speter
15038032Speter# operators that cannot be in local usernames (i.e., network indicators)
15138032SpeterCO @ % ifdef(`_NO_UUCP_', `', `!')
15238032Speter
15338032Speter# a class with just dot (for identifying canonical names)
15438032SpeterC..
15538032Speter
15638032Speter# a class with just a left bracket (for identifying domain literals)
15738032SpeterC[[
15838032Speter
15964562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
16064562Sgshapiro# access_db acceptance class
16164562SgshapiroC{Accept}OK RELAY
16290792Sgshapiroifdef(`_DELAY_COMPAT_8_10_',`dnl
16364562Sgshapiroifdef(`_BLACKLIST_RCPT_',`dnl
16464562Sgshapiro# possible access_db RHS for spam friends/haters
16564562SgshapiroC{SpamTag}SPAMFRIEND SPAMHATER')')',
16638032Speter`dnl')
16738032Speter
16890792Sgshapirodnl mark for "domain is ok" (resolved or accepted anyway)
16990792Sgshapirodefine(`_RES_OK_', `OKR')dnl
17038032Speterifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',`dnl',`dnl
17138032Speter# Resolve map (to check if a host exists in check_mail)
17290792SgshapiroKresolve host -a<_RES_OK_> -T<TEMP>')
17390792SgshapiroC{ResOk}_RES_OK_
17438032Speter
17580785Sgshapiroifdef(`_NEED_MACRO_MAP_', `dnl
17680785Sgshapiroifdef(`_MACRO_MAP_', `', `# macro storage map
17780785Sgshapirodefine(`_MACRO_MAP_', `1')dnl
17880785SgshapiroKmacro macro')', `dnl')
17966494Sgshapiro
18038032Speterifdef(`confCR_FILE', `dnl
18166494Sgshapiro# Hosts for which relaying is permitted ($=R)
18238032SpeterFR`'confCR_FILE',
18338032Speter`dnl')
18438032Speter
18590792Sgshapirodefine(`TLS_SRV_TAG', `"TLS_Srv"')dnl
18690792Sgshapirodefine(`TLS_CLT_TAG', `"TLS_Clt"')dnl
18790792Sgshapirodefine(`TLS_RCPT_TAG', `"TLS_Rcpt"')dnl
18890792Sgshapirodefine(`TLS_TRY_TAG', `"Try_TLS"')dnl
18990792Sgshapirodefine(`SRV_FEAT_TAG', `"Srv_Features"')dnl
19064562Sgshapirodnl this may be useful in other contexts too
19164562Sgshapiroifdef(`_ARITH_MAP_', `', `# arithmetic map
19264562Sgshapirodefine(`_ARITH_MAP_', `1')dnl
19364562SgshapiroKarith arith')
19464562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
19590792Sgshapiroifdef(`_MACRO_MAP_', `', `# macro storage map
19690792Sgshapirodefine(`_MACRO_MAP_', `1')dnl
19790792SgshapiroKmacro macro')
19890792Sgshapiro# possible values for TLS_connection in access map
19964562SgshapiroC{tls}VERIFY ENCR', `dnl')
20064562Sgshapiroifdef(`_CERT_REGEX_ISSUER_', `dnl
20164562Sgshapiro# extract relevant part from cert issuer
20264562SgshapiroKCERTIssuer regex _CERT_REGEX_ISSUER_', `dnl')
20364562Sgshapiroifdef(`_CERT_REGEX_SUBJECT_', `dnl
20464562Sgshapiro# extract relevant part from cert subject
20564562SgshapiroKCERTSubject regex _CERT_REGEX_SUBJECT_', `dnl')
20664562Sgshapiro
20790792Sgshapiroifdef(`LOCAL_RELAY', `dnl
208110647Sgshapiro# who I send unqualified names to if `FEATURE(stickyhost)' is used
209110560Sgshapiro# (null means deliver locally)
21090792SgshapiroDR`'LOCAL_RELAY')
21138032Speter
21290792Sgshapiroifdef(`MAIL_HUB', `dnl
213110560Sgshapiro# who gets all local email traffic
214110647Sgshapiro# ($R has precedence for unqualified names if `FEATURE(stickyhost)' is used)
21590792SgshapiroDH`'MAIL_HUB')
21638032Speter
21738032Speter# dequoting map
21890792SgshapiroKdequote dequote`'ifdef(`confDEQUOTE_OPTS', ` confDEQUOTE_OPTS', `')
21938032Speter
22038032Speterdivert(0)dnl	# end of nullclient diversion
22138032Speter# class E: names that should be exposed as from this host, even if we masquerade
22264562Sgshapiro# class L: names that should be delivered locally, even if we have a relay
22338032Speter# class M: domains that should be converted to $M
22464562Sgshapiro# class N: domains that should not be converted to $M
22538032Speter#CL root
22638032Speterundivert(5)dnl
22764562Sgshapiroifdef(`_VIRTHOSTS_', `CR$={VirtHost}', `dnl')
22838032Speter
22990792Sgshapiroifdef(`MASQUERADE_NAME', `dnl
23038032Speter# who I masquerade as (null for no masquerading) (see also $=M)
23190792SgshapiroDM`'MASQUERADE_NAME')
23238032Speter
23338032Speter# my name for error messages
23438032Speterifdef(`confMAILER_NAME', `Dn`'confMAILER_NAME', `#DnMAILER-DAEMON')
23538032Speter
23664562Sgshapiroundivert(6)dnl LOCAL_CONFIG
23738032Speterinclude(_CF_DIR_`m4/version.m4')
23838032Speter
23938032Speter###############
24038032Speter#   Options   #
24138032Speter###############
24290792Sgshapiroifdef(`confAUTO_REBUILD',
24390792Sgshapiro`errprint(WARNING: `confAUTO_REBUILD' is no longer valid.
24490792Sgshapiro	There was a potential for a denial of service attack if this is set.
24590792Sgshapiro)')dnl
24638032Speter
24738032Speter# strip message body to 7 bits on input?
24864562Sgshapiro_OPTION(SevenBitInput, `confSEVEN_BIT_INPUT', `False')
24938032Speter
25038032Speter# 8-bit data handling
25177349Sgshapiro_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `pass8')
25238032Speter
25338032Speter# wait for alias file rebuild (default units: minutes)
25464562Sgshapiro_OPTION(AliasWait, `confALIAS_WAIT', `5m')
25538032Speter
25638032Speter# location of alias file
25764562Sgshapiro_OPTION(AliasFile, `ALIAS_FILE', `MAIL_SETTINGS_DIR`'aliases')
25864562Sgshapiro
25938032Speter# minimum number of free blocks on filesystem
26064562Sgshapiro_OPTION(MinFreeBlocks, `confMIN_FREE_BLOCKS', `100')
26138032Speter
26238032Speter# maximum message size
26364562Sgshapiro_OPTION(MaxMessageSize, `confMAX_MESSAGE_SIZE', `1000000')
26438032Speter
26538032Speter# substitution for space (blank) characters
26664562Sgshapiro_OPTION(BlankSub, `confBLANK_SUB', `_')
26738032Speter
26838032Speter# avoid connecting to "expensive" mailers on initial submission?
26964562Sgshapiro_OPTION(HoldExpensive, `confCON_EXPENSIVE', `False')
27038032Speter
27138032Speter# checkpoint queue runs after every N successful deliveries
27264562Sgshapiro_OPTION(CheckpointInterval, `confCHECKPOINT_INTERVAL', `10')
27338032Speter
27438032Speter# default delivery mode
27564562Sgshapiro_OPTION(DeliveryMode, `confDELIVERY_MODE', `background')
27638032Speter
27738032Speter# error message header/file
27864562Sgshapiro_OPTION(ErrorHeader, `confERROR_MESSAGE', `MAIL_SETTINGS_DIR`'error-header')
27938032Speter
28038032Speter# error mode
28164562Sgshapiro_OPTION(ErrorMode, `confERROR_MODE', `print')
28238032Speter
28338032Speter# save Unix-style "From_" lines at top of header?
28464562Sgshapiro_OPTION(SaveFromLine, `confSAVE_FROM_LINES', `False')
28538032Speter
28690792Sgshapiro# queue file mode (qf files)
28790792Sgshapiro_OPTION(QueueFileMode, `confQUEUE_FILE_MODE', `0600')
28890792Sgshapiro
28938032Speter# temporary file mode
29064562Sgshapiro_OPTION(TempFileMode, `confTEMP_FILE_MODE', `0600')
29138032Speter
29238032Speter# match recipients against GECOS field?
29364562Sgshapiro_OPTION(MatchGECOS, `confMATCH_GECOS', `False')
29438032Speter
29538032Speter# maximum hop count
29690792Sgshapiro_OPTION(MaxHopCount, `confMAX_HOP', `25')
29738032Speter
29838032Speter# location of help file
29964562SgshapiroO HelpFile=ifdef(`HELP_FILE', HELP_FILE, `MAIL_SETTINGS_DIR`'helpfile')
30038032Speter
30138032Speter# ignore dots as terminators in incoming messages?
30264562Sgshapiro_OPTION(IgnoreDots, `confIGNORE_DOTS', `False')
30338032Speter
30438032Speter# name resolver options
30564562Sgshapiro_OPTION(ResolverOptions, `confBIND_OPTS', `+AAONLY')
30638032Speter
30738032Speter# deliver MIME-encapsulated error messages?
30864562Sgshapiro_OPTION(SendMimeErrors, `confMIME_FORMAT_ERRORS', `True')
30938032Speter
31038032Speter# Forward file search path
31164562Sgshapiro_OPTION(ForwardPath, `confFORWARD_PATH', `/var/forward/$u:$z/.forward.$w:$z/.forward')
31238032Speter
31338032Speter# open connection cache size
31464562Sgshapiro_OPTION(ConnectionCacheSize, `confMCI_CACHE_SIZE', `2')
31538032Speter
31638032Speter# open connection cache timeout
31764562Sgshapiro_OPTION(ConnectionCacheTimeout, `confMCI_CACHE_TIMEOUT', `5m')
31838032Speter
31938032Speter# persistent host status directory
32064562Sgshapiro_OPTION(HostStatusDirectory, `confHOST_STATUS_DIRECTORY', `.hoststat')
32138032Speter
32238032Speter# single thread deliveries (requires HostStatusDirectory)?
32364562Sgshapiro_OPTION(SingleThreadDelivery, `confSINGLE_THREAD_DELIVERY', `False')
32438032Speter
32538032Speter# use Errors-To: header?
32664562Sgshapiro_OPTION(UseErrorsTo, `confUSE_ERRORS_TO', `False')
32738032Speter
32838032Speter# log level
32964562Sgshapiro_OPTION(LogLevel, `confLOG_LEVEL', `10')
33038032Speter
33138032Speter# send to me too, even in an alias expansion?
33264562Sgshapiro_OPTION(MeToo, `confME_TOO', `True')
33338032Speter
33438032Speter# verify RHS in newaliases?
33564562Sgshapiro_OPTION(CheckAliases, `confCHECK_ALIASES', `False')
33638032Speter
33738032Speter# default messages to old style headers if no special punctuation?
33864562Sgshapiro_OPTION(OldStyleHeaders, `confOLD_STYLE_HEADERS', `False')
33938032Speter
34038032Speter# SMTP daemon options
34164562Sgshapiroifelse(defn(`confDAEMON_OPTIONS'), `', `dnl',
34294334Sgshapiro`errprint(WARNING: `confDAEMON_OPTIONS' is no longer valid.
34394334Sgshapiro	Use `DAEMON_OPTIONS()'; see cf/README.
34464562Sgshapiro)'dnl
34564562Sgshapiro`DAEMON_OPTIONS(`confDAEMON_OPTIONS')')
34666494Sgshapiroifelse(defn(`_DPO_'), `',
34790792Sgshapiro`ifdef(`_NETINET6_', `O DaemonPortOptions=Name=MTA-v4, Family=inet
34890792SgshapiroO DaemonPortOptions=Name=MTA-v6, Family=inet6',`O DaemonPortOptions=Name=MTA')', `_DPO_')
34964562Sgshapiroifdef(`_NO_MSA_', `dnl', `O DaemonPortOptions=Port=587, Name=MSA, M=E')
35038032Speter
35164562Sgshapiro# SMTP client options
35290792Sgshapiroifelse(defn(`confCLIENT_OPTIONS'), `', `dnl',
35390792Sgshapiro`errprint(WARNING: `confCLIENT_OPTIONS' is no longer valid.  See cf/README for more information.
35490792Sgshapiro)'dnl
35590792Sgshapiro`CLIENT_OPTIONS(`confCLIENT_OPTIONS')')
35690792Sgshapiroifelse(defn(`_CPO_'), `',
35790792Sgshapiro`#O ClientPortOptions=Family=inet, Address=0.0.0.0', `_CPO_')
35864562Sgshapiro
35990792Sgshapiro# Modifiers to `define' {daemon_flags} for direct submissions
36090792Sgshapiro_OPTION(DirectSubmissionModifiers, `confDIRECT_SUBMISSION_MODIFIERS', `')
36190792Sgshapiro
36290792Sgshapiro# Use as mail submission program? See sendmail/SECURITY
36390792Sgshapiro_OPTION(UseMSP, `confUSE_MSP', `')
36490792Sgshapiro
36538032Speter# privacy flags
36664562Sgshapiro_OPTION(PrivacyOptions, `confPRIVACY_FLAGS', `authwarnings')
36738032Speter
36838032Speter# who (if anyone) should get extra copies of error messages
36964562Sgshapiro_OPTION(PostmasterCopy, `confCOPY_ERRORS_TO', `Postmaster')
37038032Speter
37138032Speter# slope of queue-only function
37264562Sgshapiro_OPTION(QueueFactor, `confQUEUE_FACTOR', `600000')
37338032Speter
37490792Sgshapiro# limit on number of concurrent queue runners
37590792Sgshapiro_OPTION(MaxQueueChildren, `confMAX_QUEUE_CHILDREN', `')
37690792Sgshapiro
37790792Sgshapiro# maximum number of queue-runners per queue-grouping with multiple queues
37890792Sgshapiro_OPTION(MaxRunnersPerQueue, `confMAX_RUNNERS_PER_QUEUE', `1')
37990792Sgshapiro
38090792Sgshapiro# priority of queue runners (nice(3))
38190792Sgshapiro_OPTION(NiceQueueRun, `confNICE_QUEUE_RUN', `')
38290792Sgshapiro
38390792Sgshapiro# shall we sort the queue by hostname first?
38490792Sgshapiro_OPTION(QueueSortOrder, `confQUEUE_SORT_ORDER', `priority')
38590792Sgshapiro
38690792Sgshapiro# minimum time in queue before retry
38790792Sgshapiro_OPTION(MinQueueAge, `confMIN_QUEUE_AGE', `30m')
38890792Sgshapiro
38990792Sgshapiro# how many jobs can you process in the queue?
39090792Sgshapiro_OPTION(MaxQueueRunSize, `confMAX_QUEUE_RUN_SIZE', `10000')
39190792Sgshapiro
39290792Sgshapiro# perform initial split of envelope without checking MX records
39390792Sgshapiro_OPTION(FastSplit, `confFAST_SPLIT', `1')
39490792Sgshapiro
39538032Speter# queue directory
39664562SgshapiroO QueueDirectory=ifdef(`QUEUE_DIR', QUEUE_DIR, `/var/spool/mqueue')
39738032Speter
39890792Sgshapiro# key for shared memory; 0 to turn off
39990792Sgshapiro_OPTION(SharedMemoryKey, `confSHARED_MEMORY_KEY', `0')
40090792Sgshapiro
40194334Sgshapiroifdef(`confSHARED_MEMORY_KEY_FILE', `dnl
40294334Sgshapiro# file to store key for shared memory (if SharedMemoryKey = -1)
40394334SgshapiroO SharedMemoryKeyFile=confSHARED_MEMORY_KEY_FILE')
40494334Sgshapiro
40538032Speter# timeouts (many of these)
40664562Sgshapiro_OPTION(Timeout.initial, `confTO_INITIAL', `5m')
40764562Sgshapiro_OPTION(Timeout.connect, `confTO_CONNECT', `5m')
40890792Sgshapiro_OPTION(Timeout.aconnect, `confTO_ACONNECT', `0s')
40964562Sgshapiro_OPTION(Timeout.iconnect, `confTO_ICONNECT', `5m')
41064562Sgshapiro_OPTION(Timeout.helo, `confTO_HELO', `5m')
41164562Sgshapiro_OPTION(Timeout.mail, `confTO_MAIL', `10m')
41264562Sgshapiro_OPTION(Timeout.rcpt, `confTO_RCPT', `1h')
41364562Sgshapiro_OPTION(Timeout.datainit, `confTO_DATAINIT', `5m')
41464562Sgshapiro_OPTION(Timeout.datablock, `confTO_DATABLOCK', `1h')
41564562Sgshapiro_OPTION(Timeout.datafinal, `confTO_DATAFINAL', `1h')
41664562Sgshapiro_OPTION(Timeout.rset, `confTO_RSET', `5m')
41764562Sgshapiro_OPTION(Timeout.quit, `confTO_QUIT', `2m')
41864562Sgshapiro_OPTION(Timeout.misc, `confTO_MISC', `2m')
41964562Sgshapiro_OPTION(Timeout.command, `confTO_COMMAND', `1h')
42064562Sgshapiro_OPTION(Timeout.ident, `confTO_IDENT', `5s')
42164562Sgshapiro_OPTION(Timeout.fileopen, `confTO_FILEOPEN', `60s')
42264562Sgshapiro_OPTION(Timeout.control, `confTO_CONTROL', `2m')
42364562Sgshapiro_OPTION(Timeout.queuereturn, `confTO_QUEUERETURN', `5d')
42464562Sgshapiro_OPTION(Timeout.queuereturn.normal, `confTO_QUEUERETURN_NORMAL', `5d')
42564562Sgshapiro_OPTION(Timeout.queuereturn.urgent, `confTO_QUEUERETURN_URGENT', `2d')
42664562Sgshapiro_OPTION(Timeout.queuereturn.non-urgent, `confTO_QUEUERETURN_NONURGENT', `7d')
42764562Sgshapiro_OPTION(Timeout.queuewarn, `confTO_QUEUEWARN', `4h')
42864562Sgshapiro_OPTION(Timeout.queuewarn.normal, `confTO_QUEUEWARN_NORMAL', `4h')
42964562Sgshapiro_OPTION(Timeout.queuewarn.urgent, `confTO_QUEUEWARN_URGENT', `1h')
43064562Sgshapiro_OPTION(Timeout.queuewarn.non-urgent, `confTO_QUEUEWARN_NONURGENT', `12h')
43164562Sgshapiro_OPTION(Timeout.hoststatus, `confTO_HOSTSTATUS', `30m')
43264562Sgshapiro_OPTION(Timeout.resolver.retrans, `confTO_RESOLVER_RETRANS', `5s')
43364562Sgshapiro_OPTION(Timeout.resolver.retrans.first, `confTO_RESOLVER_RETRANS_FIRST', `5s')
43464562Sgshapiro_OPTION(Timeout.resolver.retrans.normal, `confTO_RESOLVER_RETRANS_NORMAL', `5s')
43564562Sgshapiro_OPTION(Timeout.resolver.retry, `confTO_RESOLVER_RETRY', `4')
43664562Sgshapiro_OPTION(Timeout.resolver.retry.first, `confTO_RESOLVER_RETRY_FIRST', `4')
43764562Sgshapiro_OPTION(Timeout.resolver.retry.normal, `confTO_RESOLVER_RETRY_NORMAL', `4')
43890792Sgshapiro_OPTION(Timeout.lhlo, `confTO_LHLO', `2m')
43990792Sgshapiro_OPTION(Timeout.auth, `confTO_AUTH', `10m')
44090792Sgshapiro_OPTION(Timeout.starttls, `confTO_STARTTLS', `1h')
44138032Speter
44290792Sgshapiro# time for DeliverBy; extension disabled if less than 0
44390792Sgshapiro_OPTION(DeliverByMin, `confDELIVER_BY_MIN', `0')
44490792Sgshapiro
44538032Speter# should we not prune routes in route-addr syntax addresses?
44664562Sgshapiro_OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES', `False')
44738032Speter
44838032Speter# queue up everything before forking?
44964562Sgshapiro_OPTION(SuperSafe, `confSAFE_QUEUE', `True')
45038032Speter
45138032Speter# status file
45264562SgshapiroO StatusFile=ifdef(`STATUS_FILE', `STATUS_FILE', `MAIL_SETTINGS_DIR`'statistics')
45338032Speter
45438032Speter# time zone handling:
45538032Speter#  if undefined, use system default
45638032Speter#  if defined but null, use TZ envariable passed in
45738032Speter#  if defined and non-null, use that info
45838032Speterifelse(confTIME_ZONE, `USE_SYSTEM', `#O TimeZoneSpec=',
45938032Speter	confTIME_ZONE, `USE_TZ', `O TimeZoneSpec=',
46038032Speter	`O TimeZoneSpec=confTIME_ZONE')
46138032Speter
46238032Speter# default UID (can be username or userid:groupid)
46364562Sgshapiro_OPTION(DefaultUser, `confDEF_USER_ID', `mailnull')
46438032Speter
46538032Speter# list of locations of user database file (null means no lookup)
46664562Sgshapiro_OPTION(UserDatabaseSpec, `confUSERDB_SPEC', `MAIL_SETTINGS_DIR`'userdb')
46738032Speter
46838032Speter# fallback MX host
46964562Sgshapiro_OPTION(FallbackMXhost, `confFALLBACK_MX', `fall.back.host.net')
47038032Speter
47138032Speter# if we are the best MX host for a site, try it directly instead of config err
47264562Sgshapiro_OPTION(TryNullMXList, `confTRY_NULL_MX_LIST', `False')
47338032Speter
47438032Speter# load average at which we just queue messages
47564562Sgshapiro_OPTION(QueueLA, `confQUEUE_LA', `8')
47638032Speter
47738032Speter# load average at which we refuse connections
47864562Sgshapiro_OPTION(RefuseLA, `confREFUSE_LA', `12')
47938032Speter
48090792Sgshapiro# load average at which we delay connections; 0 means no limit
48190792Sgshapiro_OPTION(DelayLA, `confDELAY_LA', `0')
48290792Sgshapiro
48338032Speter# maximum number of children we allow at one time
48498841Sgshapiro_OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `0')
48538032Speter
48638032Speter# maximum number of new connections per second
48771345Sgshapiro_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `0')
48838032Speter
48938032Speter# work recipient factor
49064562Sgshapiro_OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', `30000')
49138032Speter
49238032Speter# deliver each queued job in a separate process?
49364562Sgshapiro_OPTION(ForkEachJob, `confSEPARATE_PROC', `False')
49438032Speter
49538032Speter# work class factor
49664562Sgshapiro_OPTION(ClassFactor, `confWORK_CLASS_FACTOR', `1800')
49738032Speter
49838032Speter# work time factor
49964562Sgshapiro_OPTION(RetryFactor, `confWORK_TIME_FACTOR', `90000')
50038032Speter
50138032Speter# default character set
50264562Sgshapiro_OPTION(DefaultCharSet, `confDEF_CHAR_SET', `iso-8859-1')
50338032Speter
50490792Sgshapiro# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others)
50564562Sgshapiro_OPTION(ServiceSwitchFile, `confSERVICE_SWITCH_FILE', `MAIL_SETTINGS_DIR`'service.switch')
50638032Speter
50738032Speter# hosts file (normally /etc/hosts)
50864562Sgshapiro_OPTION(HostsFile, `confHOSTS_FILE', `/etc/hosts')
50938032Speter
51038032Speter# dialup line delay on connection failure
51164562Sgshapiro_OPTION(DialDelay, `confDIAL_DELAY', `10s')
51238032Speter
51338032Speter# action to take if there are no recipients in the message
51464562Sgshapiro_OPTION(NoRecipientAction, `confNO_RCPT_ACTION', `add-to-undisclosed')
51538032Speter
51638032Speter# chrooted environment for writing to files
51764562Sgshapiro_OPTION(SafeFileEnvironment, `confSAFE_FILE_ENV', `/arch')
51838032Speter
51938032Speter# are colons OK in addresses?
52064562Sgshapiro_OPTION(ColonOkInAddr, `confCOLON_OK_IN_ADDR', `True')
52138032Speter
52238032Speter# shall I avoid expanding CNAMEs (violates protocols)?
52364562Sgshapiro_OPTION(DontExpandCnames, `confDONT_EXPAND_CNAMES', `False')
52438032Speter
52538032Speter# SMTP initial login message (old $e macro)
52664562Sgshapiro_OPTION(SmtpGreetingMessage, `confSMTP_LOGIN_MSG', `$j Sendmail $v ready at $b')
52738032Speter
52838032Speter# UNIX initial From header format (old $l macro)
52964562Sgshapiro_OPTION(UnixFromLine, `confFROM_LINE', `From $g $d')
53038032Speter
53138032Speter# From: lines that have embedded newlines are unwrapped onto one line
53264562Sgshapiro_OPTION(SingleLineFromHeader, `confSINGLE_LINE_FROM_HEADER', `False')
53338032Speter
53438032Speter# Allow HELO SMTP command that does not `include' a host name
53564562Sgshapiro_OPTION(AllowBogusHELO, `confALLOW_BOGUS_HELO', `False')
53638032Speter
53738032Speter# Characters to be quoted in a full name phrase (@,;:\()[] are automatic)
53864562Sgshapiro_OPTION(MustQuoteChars, `confMUST_QUOTE_CHARS', `.')
53938032Speter
54038032Speter# delimiter (operator) characters (old $o macro)
54164562Sgshapiro_OPTION(OperatorChars, `confOPERATORS', `.:@[]')
54238032Speter
54338032Speter# shall I avoid calling initgroups(3) because of high NIS costs?
54464562Sgshapiro_OPTION(DontInitGroups, `confDONT_INIT_GROUPS', `False')
54538032Speter
54638032Speter# are group-writable `:include:' and .forward files (un)trustworthy?
54790792Sgshapiro# True (the default) means they are not trustworthy.
54864562Sgshapiro_OPTION(UnsafeGroupWrites, `confUNSAFE_GROUP_WRITES', `True')
54990792Sgshapiroifdef(`confUNSAFE_GROUP_WRITES',
55090792Sgshapiro`errprint(`WARNING: confUNSAFE_GROUP_WRITES is deprecated; use confDONT_BLAME_SENDMAIL.
55190792Sgshapiro')')
55238032Speter
55338032Speter# where do errors that occur when sending errors get sent?
55464562Sgshapiro_OPTION(DoubleBounceAddress, `confDOUBLE_BOUNCE_ADDRESS', `postmaster')
55538032Speter
55664562Sgshapiro# where to save bounces if all else fails
55764562Sgshapiro_OPTION(DeadLetterDrop, `confDEAD_LETTER_DROP', `/var/tmp/dead.letter')
55864562Sgshapiro
55938032Speter# what user id do we assume for the majority of the processing?
56064562Sgshapiro_OPTION(RunAsUser, `confRUN_AS_USER', `sendmail')
56138032Speter
56238032Speter# maximum number of recipients per SMTP envelope
56364562Sgshapiro_OPTION(MaxRecipientsPerMessage, `confMAX_RCPTS_PER_MESSAGE', `100')
56438032Speter
56590792Sgshapiro# limit the rate recipients per SMTP envelope are accepted
56690792Sgshapiro# once the threshold number of recipients have been rejected
56790792Sgshapiro_OPTION(BadRcptThrottle, `confBAD_RCPT_THROTTLE', `20')
56890792Sgshapiro
56938032Speter# shall we get local names from our installed interfaces?
57064562Sgshapiro_OPTION(DontProbeInterfaces, `confDONT_PROBE_INTERFACES', `False')
57138032Speter
57264562Sgshapiro# Return-Receipt-To: header implies DSN request
57364562Sgshapiro_OPTION(RrtImpliesDsn, `confRRT_IMPLIES_DSN', `False')
57464562Sgshapiro
57564562Sgshapiro# override connection address (for testing)
57664562Sgshapiro_OPTION(ConnectOnlyTo, `confCONNECT_ONLY_TO', `0.0.0.0')
57764562Sgshapiro
57864562Sgshapiro# Trusted user for file ownership and starting the daemon
57964562Sgshapiro_OPTION(TrustedUser, `confTRUSTED_USER', `root')
58064562Sgshapiro
58164562Sgshapiro# Control socket for daemon management
58264562Sgshapiro_OPTION(ControlSocketName, `confCONTROL_SOCKET_NAME', `/var/spool/mqueue/.control')
58364562Sgshapiro
58464562Sgshapiro# Maximum MIME header length to protect MUAs
58564562Sgshapiro_OPTION(MaxMimeHeaderLength, `confMAX_MIME_HEADER_LENGTH', `0/0')
58664562Sgshapiro
58764562Sgshapiro# Maximum length of the sum of all headers
58864562Sgshapiro_OPTION(MaxHeadersLength, `confMAX_HEADERS_LENGTH', `32768')
58964562Sgshapiro
59064562Sgshapiro# Maximum depth of alias recursion
59164562Sgshapiro_OPTION(MaxAliasRecursion, `confMAX_ALIAS_RECURSION', `10')
59264562Sgshapiro
59364562Sgshapiro# location of pid file
59464562Sgshapiro_OPTION(PidFile, `confPID_FILE', `/var/run/sendmail.pid')
59564562Sgshapiro
59664562Sgshapiro# Prefix string for the process title shown on 'ps' listings
59764562Sgshapiro_OPTION(ProcessTitlePrefix, `confPROCESS_TITLE_PREFIX', `prefix')
59864562Sgshapiro
59964562Sgshapiro# Data file (df) memory-buffer file maximum size
60064562Sgshapiro_OPTION(DataFileBufferSize, `confDF_BUFFER_SIZE', `4096')
60164562Sgshapiro
60264562Sgshapiro# Transcript file (xf) memory-buffer file maximum size
60364562Sgshapiro_OPTION(XscriptFileBufferSize, `confXF_BUFFER_SIZE', `4096')
60464562Sgshapiro
60590792Sgshapiro# lookup type to find information about local mailboxes
60690792Sgshapiro_OPTION(MailboxDatabase, `confMAILBOX_DATABASE', `pw')
60790792Sgshapiro
60864562Sgshapiro# list of authentication mechanisms
60990792Sgshapiro_OPTION(AuthMechanisms, `confAUTH_MECHANISMS', `EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5')
61064562Sgshapiro
61164562Sgshapiro# default authentication information for outgoing connections
61264562Sgshapiro_OPTION(DefaultAuthInfo, `confDEF_AUTH_INFO', `MAIL_SETTINGS_DIR`'default-auth-info')
61364562Sgshapiro
61464562Sgshapiro# SMTP AUTH flags
61564562Sgshapiro_OPTION(AuthOptions, `confAUTH_OPTIONS', `')
61664562Sgshapiro
61790792Sgshapiro# SMTP AUTH maximum encryption strength
61890792Sgshapiro_OPTION(AuthMaxBits, `confAUTH_MAX_BITS', `')
61990792Sgshapiro
62090792Sgshapiro# SMTP STARTTLS server options
62190792Sgshapiro_OPTION(TLSSrvOptions, `confTLS_SRV_OPTIONS', `')
62290792Sgshapiro
62364562Sgshapiro# Input mail filters
62464562Sgshapiro_OPTION(InputMailFilters, `confINPUT_MAIL_FILTERS', `')
62564562Sgshapiro
62698841Sgshapiroifelse(len(X`'_MAIL_FILTERS_DEF), `1', `dnl', `dnl
62764562Sgshapiro# Milter options
62890792Sgshapiro_OPTION(Milter.LogLevel, `confMILTER_LOG_LEVEL', `')
62964562Sgshapiro_OPTION(Milter.macros.connect, `confMILTER_MACROS_CONNECT', `')
63064562Sgshapiro_OPTION(Milter.macros.helo, `confMILTER_MACROS_HELO', `')
63164562Sgshapiro_OPTION(Milter.macros.envfrom, `confMILTER_MACROS_ENVFROM', `')
63264562Sgshapiro_OPTION(Milter.macros.envrcpt, `confMILTER_MACROS_ENVRCPT', `')')
63364562Sgshapiro
63464562Sgshapiro# CA directory
635110560Sgshapiro_OPTION(CACertPath, `confCACERT_PATH', `')
63664562Sgshapiro# CA file
637110560Sgshapiro_OPTION(CACertFile, `confCACERT', `')
63864562Sgshapiro# Server Cert
63964562Sgshapiro_OPTION(ServerCertFile, `confSERVER_CERT', `')
64064562Sgshapiro# Server private key
64164562Sgshapiro_OPTION(ServerKeyFile, `confSERVER_KEY', `')
64264562Sgshapiro# Client Cert
64364562Sgshapiro_OPTION(ClientCertFile, `confCLIENT_CERT', `')
64464562Sgshapiro# Client private key
64564562Sgshapiro_OPTION(ClientKeyFile, `confCLIENT_KEY', `')
64664562Sgshapiro# DHParameters (only required if DSA/DH is used)
64764562Sgshapiro_OPTION(DHParameters, `confDH_PARAMETERS', `')
64864562Sgshapiro# Random data source (required for systems without /dev/urandom under OpenSSL)
64964562Sgshapiro_OPTION(RandFile, `confRAND_FILE', `')
65064562Sgshapiro
65190792Sgshapiro############################
65290792Sgshapiro`# QUEUE GROUP DEFINITIONS  #'
65390792Sgshapiro############################
65490792Sgshapiro_QUEUE_GROUP_
65542575Speter
65638032Speter###########################
65738032Speter#   Message precedences   #
65838032Speter###########################
65938032Speter
66038032SpeterPfirst-class=0
66138032SpeterPspecial-delivery=100
66238032SpeterPlist=-30
66338032SpeterPbulk=-60
66438032SpeterPjunk=-100
66538032Speter
66638032Speter#####################
66738032Speter#   Trusted users   #
66838032Speter#####################
66938032Speter
67038032Speter# this is equivalent to setting class "t"
67164562Sgshapiroifdef(`_USE_CT_FILE_', `', `#')Ft`'ifdef(`confCT_FILE', confCT_FILE, `MAIL_SETTINGS_DIR`'trusted-users')
67238032SpeterTroot
67338032SpeterTdaemon
67438032Speterifdef(`_NO_UUCP_', `dnl', `Tuucp')
67538032Speterifdef(`confTRUSTED_USERS', `T`'confTRUSTED_USERS', `dnl')
67638032Speter
67738032Speter#########################
67838032Speter#   Format of headers   #
67938032Speter#########################
68038032Speter
68138032Speterifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `$?x$x <$g>$|$g$.')')dnl
68238032SpeterH?P?Return-Path: <$g>
68338032SpeterHReceived: confRECEIVED_HEADER
68438032SpeterH?D?Resent-Date: $a
68538032SpeterH?D?Date: $a
68638032SpeterH?F?Resent-From: confFROM_HEADER
68738032SpeterH?F?From: confFROM_HEADER
68838032SpeterH?x?Full-Name: $x
68938032Speter# HPosted-Date: $a
69038032Speter# H?l?Received-Date: $b
69138032SpeterH?M?Resent-Message-Id: <$t.$i@$j>
69238032SpeterH?M?Message-Id: <$t.$i@$j>
69364562Sgshapiro
69438032Speter#
69538032Speter######################################################################
69638032Speter######################################################################
69738032Speter#####
69838032Speter#####			REWRITING RULES
69938032Speter#####
70038032Speter######################################################################
70138032Speter######################################################################
70238032Speter
70338032Speter############################################
70438032Speter###  Ruleset 3 -- Name Canonicalization  ###
70538032Speter############################################
70664562SgshapiroScanonify=3
70738032Speter
70838032Speter# handle null input (translate to <@> special case)
70938032SpeterR$@			$@ <@>
71038032Speter
71138032Speter# strip group: syntax (not inside angle brackets!) and trailing semicolon
71238032SpeterR$*			$: $1 <@>			mark addresses
71338032SpeterR$* < $* > $* <@>	$: $1 < $2 > $3			unmark <addr>
71438032SpeterR@ $* <@>		$: @ $1				unmark @host:...
71590792SgshapiroR$* [ IPv6 : $+ ] <@>	$: $1 [ IPv6 : $2 ]		unmark IPv6 addr
71638032SpeterR$* :: $* <@>		$: $1 :: $2			unmark node::addr
71738032SpeterR:`include': $* <@>	$: :`include': $1			unmark :`include':...
71838032SpeterR$* : $* [ $* ]		$: $1 : $2 [ $3 ] <@>		remark if leading colon
71938032SpeterR$* : $* <@>		$: $2				strip colon if marked
72038032SpeterR$* <@>			$: $1				unmark
72138032SpeterR$* ;			   $1				strip trailing semi
72271345SgshapiroR$* < $+ :; > $*	$@ $2 :; <@>			catch <list:;>
72338032SpeterR$* < $* ; >		   $1 < $2 >			bogus bracketed semi
72438032Speter
72538032Speter# null input now results from list:; syntax
72638032SpeterR$@			$@ :; <@>
72738032Speter
72838032Speter# strip angle brackets -- note RFC733 heuristic to get innermost item
72938032SpeterR$*			$: < $1 >			housekeeping <>
73038032SpeterR$+ < $* >		   < $2 >			strip excess on left
73138032SpeterR< $* > $+		   < $1 >			strip excess on right
73238032SpeterR<>			$@ < @ >			MAIL FROM:<> case
73338032SpeterR< $+ >			$: $1				remove housekeeping <>
73438032Speter
73564562Sgshapiroifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl
73638032Speter# make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later
73738032SpeterR@ $+ , $+		@ $1 : $2			change all "," to ":"
73838032Speter
73938032Speter# localize and dispose of route-based addresses
74090792Sgshapirodnl XXX: IPv6 colon conflict
74190792Sgshapiroifdef(`NO_NETINET6', `dnl',
74290792Sgshapiro`R@ [$+] : $+		$@ $>Canonify2 < @ [$1] > : $2	handle <route-addr>')
74364562SgshapiroR@ $+ : $+		$@ $>Canonify2 < @$1 > : $2	handle <route-addr>
74464562Sgshapirodnl',`dnl
74564562Sgshapiro# strip route address <@a,@b,@c:user@d> -> <user@d>
74664562SgshapiroR@ $+ , $+		$2
74790792Sgshapiroifdef(`NO_NETINET6', `dnl',
74890792Sgshapiro`R@ [ $* ] : $+		$2')
74964562SgshapiroR@ $+ : $+		$2
75064562Sgshapirodnl')
75138032Speter
75238032Speter# find focus for list syntax
75364562SgshapiroR $+ : $* ; @ $+	$@ $>Canonify2 $1 : $2 ; < @ $3 >	list syntax
75438032SpeterR $+ : $* ;		$@ $1 : $2;			list syntax
75538032Speter
75638032Speter# find focus for @ syntax addresses
75738032SpeterR$+ @ $+		$: $1 < @ $2 >			focus on domain
75838032SpeterR$+ < $+ @ $+ >		$1 $2 < @ $3 >			move gaze right
75964562SgshapiroR$+ < @ $+ >		$@ $>Canonify2 $1 < @ $2 >	already canonical
76038032Speter
76190792Sgshapirodnl This is flagged as an error in S0; no need to silently fix it here.
76290792Sgshapirodnl # do some sanity checking
76390792Sgshapirodnl R$* < @ $~[ $* : $* > $*	$1 < @ $2 $3 > $4	nix colons in addrs
76438032Speter
76538032Speterifdef(`_NO_UUCP_', `dnl',
76638032Speter`# convert old-style addresses to a domain-based address
76764562SgshapiroR$- ! $+		$@ $>Canonify2 $2 < @ $1 .UUCP >	resolve uucp names
76864562SgshapiroR$+ . $- ! $+		$@ $>Canonify2 $3 < @ $1 . $2 >		domain uucps
76964562SgshapiroR$+ ! $+		$@ $>Canonify2 $2 < @ $1 .UUCP >	uucp subdomains
77038032Speter')
77138032Speterifdef(`_USE_DECNET_SYNTAX_',
77238032Speter`# convert node::user addresses into a domain-based address
77364562SgshapiroR$- :: $+		$@ $>Canonify2 $2 < @ $1 .DECNET >	resolve DECnet names
77464562SgshapiroR$- . $- :: $+		$@ $>Canonify2 $3 < @ $1.$2 .DECNET >	numeric DECnet addr
77538032Speter',
77638032Speter	`dnl')
77738032Speter# if we have % signs, take the rightmost one
77838032SpeterR$* % $*		$1 @ $2				First make them all @s.
77938032SpeterR$* @ $* @ $*		$1 % $2 @ $3			Undo all but the last.
78064562SgshapiroR$* @ $*		$@ $>Canonify2 $1 < @ $2 >	Insert < > and finish
78138032Speter
78238032Speter# else we must be a local name
78364562SgshapiroR$*			$@ $>Canonify2 $1
78438032Speter
78538032Speter
78638032Speter################################################
78738032Speter###  Ruleset 96 -- bottom half of ruleset 3  ###
78838032Speter################################################
78938032Speter
79064562SgshapiroSCanonify2=96
79138032Speter
79238032Speter# handle special cases for local names
79338032SpeterR$* < @ localhost > $*		$: $1 < @ $j . > $2		no domain at all
79438032SpeterR$* < @ localhost . $m > $*	$: $1 < @ $j . > $2		local domain
79538032Speterifdef(`_NO_UUCP_', `dnl',
79638032Speter`R$* < @ localhost . UUCP > $*	$: $1 < @ $j . > $2		.UUCP domain')
79764562Sgshapiro
79890792Sgshapiro# check for IPv4/IPv6 domain literal
79990792SgshapiroR$* < @ [ $+ ] > $*		$: $1 < @@ [ $2 ] > $3		mark [addr]
80038032SpeterR$* < @@ $=w > $*		$: $1 < @ $j . > $3		self-literal
80138032SpeterR$* < @@ $+ > $*		$@ $1 < @ $2 > $3		canon IP addr
80238032Speter
80364562Sgshapiroifdef(`_DOMAIN_TABLE_', `dnl
80438032Speter# look up domains in the domain table
80538032SpeterR$* < @ $+ > $* 		$: $1 < @ $(domaintable $2 $) > $3', `dnl')
80638032Speter
80764562Sgshapiroundivert(2)dnl LOCAL_RULE_3
80838032Speter
80964562Sgshapiroifdef(`_BITDOMAIN_TABLE_', `dnl
81038032Speter# handle BITNET mapping
81138032SpeterR$* < @ $+ .BITNET > $*		$: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3', `dnl')
81238032Speter
81364562Sgshapiroifdef(`_UUDOMAIN_TABLE_', `dnl
81438032Speter# handle UUCP mapping
81538032SpeterR$* < @ $+ .UUCP > $*		$: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3', `dnl')
81638032Speter
81738032Speterifdef(`_NO_UUCP_', `dnl',
81838032Speter`ifdef(`UUCP_RELAY',
81938032Speter`# pass UUCP addresses straight through
82038032SpeterR$* < @ $+ . UUCP > $*		$@ $1 < @ $2 . UUCP . > $3',
82138032Speter`# if really UUCP, handle it immediately
82238032Speterifdef(`_CLASS_U_',
82338032Speter`R$* < @ $=U . UUCP > $*	$@ $1 < @ $2 . UUCP . > $3', `dnl')
82438032Speterifdef(`_CLASS_V_',
82538032Speter`R$* < @ $=V . UUCP > $*	$@ $1 < @ $2 . UUCP . > $3', `dnl')
82638032Speterifdef(`_CLASS_W_',
82738032Speter`R$* < @ $=W . UUCP > $*	$@ $1 < @ $2 . UUCP . > $3', `dnl')
82838032Speterifdef(`_CLASS_X_',
82938032Speter`R$* < @ $=X . UUCP > $*	$@ $1 < @ $2 . UUCP . > $3', `dnl')
83038032Speterifdef(`_CLASS_Y_',
83138032Speter`R$* < @ $=Y . UUCP > $*	$@ $1 < @ $2 . UUCP . > $3', `dnl')
83238032Speter
83338032Speterifdef(`_NO_CANONIFY_', `dnl', `dnl
83438032Speter# try UUCP traffic as a local address
83538032SpeterR$* < @ $+ . UUCP > $*		$: $1 < @ $[ $2 $] . UUCP . > $3
83638032SpeterR$* < @ $+ . . UUCP . > $*	$@ $1 < @ $2 . > $3')
83738032Speter')')
83864562Sgshapiro# hostnames ending in class P are always canonical
83964562SgshapiroR$* < @ $* $=P > $*		$: $1 < @ $2 $3 . > $4
84064562Sgshapirodnl apply the next rule only for hostnames not in class P
84164562Sgshapirodnl this even works for phrases in class P since . is in class P
84264562Sgshapirodnl which daemon flags are set?
84364562SgshapiroR$* < @ $* $~P > $*		$: $&{daemon_flags} $| $1 < @ $2 $3 > $4
84464562Sgshapirodnl the other rules in this section only apply if the hostname
84564562Sgshapirodnl does not end in class P hence no further checks are done here
84664562Sgshapirodnl if this ever changes make sure the lookups are "protected" again!
84764562Sgshapiroifdef(`_NO_CANONIFY_', `dnl
84864562Sgshapirodnl do not canonify unless:
84964562Sgshapirodnl domain ends in class {Canonify} (this does not work if the intersection
85064562Sgshapirodnl	with class P is non-empty)
85164562Sgshapirodnl or {daemon_flags} has c set
85264562Sgshapiro# pass to name server to make hostname canonical if in class {Canonify}
85364562SgshapiroR$* $| $* < @ $* $={Canonify} > $*	$: $2 < @ $[ $3 $4 $] > $5
85464562Sgshapiro# pass to name server to make hostname canonical if requested
85564562SgshapiroR$* c $* $| $* < @ $* > $*	$: $3 < @ $[ $4 $] > $5
85664562Sgshapirodnl trailing dot? -> do not apply _CANONIFY_HOSTS_
85764562SgshapiroR$* $| $* < @ $+ . > $*		$: $2 < @ $3 . > $4
85864562Sgshapiro# add a trailing dot to qualified hostnames so other rules will work
85964562SgshapiroR$* $| $* < @ $+.$+ > $*	$: $2 < @ $3.$4 . > $5
86064562Sgshapiroifdef(`_CANONIFY_HOSTS_', `dnl
86164562Sgshapirodnl this should only apply to unqualified hostnames
86264562Sgshapirodnl but if a valid character inside an unqualified hostname is an OperatorChar
86364562Sgshapirodnl then $- does not work.
86464562Sgshapiro# lookup unqualified hostnames
86590792SgshapiroR$* $| $* < @ $* > $*		$: $2 < @ $[ $3 $] > $4', `dnl')', `dnl
86664562Sgshapirodnl _NO_CANONIFY_ is not set: canonify unless:
86764562Sgshapirodnl {daemon_flags} contains CC (do not canonify)
86871345Sgshapirodnl but add a trailing dot to qualified hostnames so other rules will work
86971345Sgshapirodnl should we do this for every hostname: even unqualified?
87071345SgshapiroR$* CC $* $| $* < @ $+.$+ > $*	$: $3 < @ $4.$5 . > $6
87164562SgshapiroR$* CC $* $| $*			$: $3
87290792Sgshapiroifdef(`_FFR_NOCANONIFY_HEADERS', `dnl
87390792Sgshapiro# do not canonify header addresses
87490792SgshapiroR$* $| $* < @ $* $~P > $*	$: $&{addr_type} $| $2 < @ $3 $4 > $5
87590792SgshapiroR$* h $* $| $* < @ $+.$+ > $*	$: $3 < @ $4.$5 . > $6
87690792SgshapiroR$* h $* $| $*			$: $3', `dnl')
87738032Speter# pass to name server to make hostname canonical
87864562SgshapiroR$* $| $* < @ $* > $*		$: $2 < @ $[ $3 $] > $4')
87964562Sgshapirodnl remove {daemon_flags} for other cases
88064562SgshapiroR$* $| $*			$: $2
88138032Speter
88238032Speter# local host aliases and pseudo-domains are always canonical
88338032SpeterR$* < @ $=w > $*		$: $1 < @ $2 . > $3
88438032Speterifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
88538032Speter`R$* < @ $* $=M > $*		$: $1 < @ $2 $3 . > $4',
88638032Speter`R$* < @ $=M > $*		$: $1 < @ $2 . > $3')
88764562Sgshapiroifdef(`_VIRTUSER_TABLE_', `dnl
88864562Sgshapirodnl virtual hosts are also canonical
88964562Sgshapiroifdef(`_VIRTUSER_ENTIRE_DOMAIN_',
89064562Sgshapiro`R$* < @ $* $={VirtHost} > $* 	$: $1 < @ $2 $3 . > $4',
89164562Sgshapiro`R$* < @ $={VirtHost} > $* 	$: $1 < @ $2 . > $3')',
89264562Sgshapiro`dnl')
89390792Sgshapiroifdef(`_GENERICS_TABLE_', `dnl
89490792Sgshapirodnl hosts for genericstable are also canonical
89590792Sgshapiroifdef(`_GENERICS_ENTIRE_DOMAIN_',
89690792Sgshapiro`R$* < @ $* $=G > $* 	$: $1 < @ $2 $3 . > $4',
89790792Sgshapiro`R$* < @ $=G > $* 	$: $1 < @ $2 . > $3')',
89890792Sgshapiro`dnl')
89964562Sgshapirodnl remove superfluous dots (maybe repeatedly) which may have been added
90064562Sgshapirodnl by one of the rules before
90138032SpeterR$* < @ $* . . > $*		$1 < @ $2 . > $3
90238032Speter
90338032Speter
90438032Speter##################################################
90538032Speter###  Ruleset 4 -- Final Output Post-rewriting  ###
90638032Speter##################################################
90764562SgshapiroSfinal=4
90838032Speter
90971345SgshapiroR$+ :; <@>		$@ $1 :				handle <list:;>
91038032SpeterR$* <@>			$@				handle <> and list:;
91138032Speter
91238032Speter# strip trailing dot off possibly canonical name
91338032SpeterR$* < @ $+ . > $*	$1 < @ $2 > $3
91438032Speter
91564562Sgshapiro# eliminate internal code
91638032SpeterR$* < @ *LOCAL* > $*	$1 < @ $j > $2
91738032Speter
91838032Speter# externalize local domain info
91938032SpeterR$* < $+ > $*		$1 $2 $3			defocus
92038032SpeterR@ $+ : @ $+ : $+	@ $1 , @ $2 : $3		<route-addr> canonical
92138032SpeterR@ $*			$@ @ $1				... and exit
92238032Speter
92338032Speterifdef(`_NO_UUCP_', `dnl',
92438032Speter`# UUCP must always be presented in old form
92538032SpeterR$+ @ $- . UUCP		$2!$1				u@h.UUCP => h!u')
92638032Speter
92738032Speterifdef(`_USE_DECNET_SYNTAX_',
92838032Speter`# put DECnet back in :: form
92938032SpeterR$+ @ $+ . DECNET	$2 :: $1			u@h.DECNET => h::u',
93038032Speter	`dnl')
93138032Speter# delete duplicate local names
93238032SpeterR$+ % $=w @ $=w		$1 @ $2				u%host@host => u@host
93338032Speter
93438032Speter
93538032Speter
93638032Speter##############################################################
93738032Speter###   Ruleset 97 -- recanonicalize and call ruleset zero   ###
93838032Speter###		   (used for recursive calls)		   ###
93938032Speter##############################################################
94038032Speter
94164562SgshapiroSRecurse=97
94264562SgshapiroR$*			$: $>canonify $1
94364562SgshapiroR$*			$@ $>parse $1
94438032Speter
94538032Speter
94638032Speter######################################
94738032Speter###   Ruleset 0 -- Parse Address   ###
94838032Speter######################################
94938032Speter
95064562SgshapiroSparse=0
95138032Speter
95238032SpeterR$*			$: $>Parse0 $1		initial parsing
95338032SpeterR<@>			$#_LOCAL_ $: <@>		special case error msgs
95464562SgshapiroR$*			$: $>ParseLocal $1	handle local hacks
95538032SpeterR$*			$: $>Parse1 $1		final parsing
95638032Speter
95738032Speter#
95838032Speter#  Parse0 -- do initial syntax checking and eliminate local addresses.
95938032Speter#	This should either return with the (possibly modified) input
96038032Speter#	or return with a #error mailer.  It should not return with a
96138032Speter#	#mailer other than the #error mailer.
96238032Speter#
96338032Speter
96438032SpeterSParse0
96538032SpeterR<@>			$@ <@>			special case error msgs
96690792SgshapiroR$* : $* ; <@>		$#error $@ 5.1.3 $: "_CODE553 List:; syntax illegal for recipient addresses"
96764562SgshapiroR@ <@ $* >		< @ $1 >		catch "@@host" bogosity
96890792SgshapiroR<@ $+>			$#error $@ 5.1.3 $: "_CODE553 User address required"
96990792SgshapiroR$+ <@>			$#error $@ 5.1.3 $: "_CODE553 Hostname required"
97038032SpeterR$*			$: <> $1
97190792Sgshapirodnl allow tricks like [host1]:[host2]
97290792SgshapiroR<> $* < @ [ $* ] : $+ > $*	$1 < @ [ $2 ] : $3 > $4
97390792SgshapiroR<> $* < @ [ $* ] , $+ > $*	$1 < @ [ $2 ] , $3 > $4
97490792Sgshapirodnl but no a@[b]c
97590792SgshapiroR<> $* < @ [ $* ] $+ > $*	$#error $@ 5.1.2 $: "_CODE553 Invalid address"
97690792SgshapiroR<> $* < @ [ $+ ] > $*		$1 < @ [ $2 ] > $3
97790792SgshapiroR<> $* <$* : $* > $*	$#error $@ 5.1.3 $: "_CODE553 Colon illegal in host name part"
97838032SpeterR<> $*			$1
97990792SgshapiroR$* < @ . $* > $*	$#error $@ 5.1.2 $: "_CODE553 Invalid host name"
98090792SgshapiroR$* < @ $* .. $* > $*	$#error $@ 5.1.2 $: "_CODE553 Invalid host name"
98190792Sgshapirodnl no a@b@
98290792SgshapiroR$* < @ $* @ > $*	$#error $@ 5.1.2 $: "_CODE553 Invalid route address"
98390792Sgshapirodnl no a@b@c
98490792SgshapiroR$* @ $* < @ $* > $*	$#error $@ 5.1.3 $: "_CODE553 Invalid route address"
98564562Sgshapirodnl comma only allowed before @; this check is not complete
98690792SgshapiroR$* , $~O $*		$#error $@ 5.1.3 $: "_CODE553 Invalid route address"
98738032Speter
98890792Sgshapiroifdef(`_STRICT_RFC821_', `# more RFC 821 checks
98990792SgshapiroR$* . < @ $* > $*	$#error $@ 5.1.2 $: "_CODE553 Local part must not end with a dot"
99090792SgshapiroR. $* < @ $* > $*	$#error $@ 5.1.2 $: "_CODE553 Local part must not begin with a dot"
99190792Sgshapirodnl', `dnl')
99290792Sgshapiro
99338032Speter# now delete the local info -- note $=O to find characters that cause forwarding
99464562SgshapiroR$* < @ > $*		$@ $>Parse0 $>canonify $1	user@ => user
99564562SgshapiroR< @ $=w . > : $*	$@ $>Parse0 $>canonify $2	@here:... -> ...
99638032SpeterR$- < @ $=w . >		$: $(dequote $1 $) < @ $2 . >	dequote "foo"@here
99790792SgshapiroR< @ $+ >		$#error $@ 5.1.3 $: "_CODE553 User address required"
99864562SgshapiroR$* $=O $* < @ $=w . >	$@ $>Parse0 $>canonify $1 $2 $3	...@here -> ...
99938032SpeterR$- 			$: $(dequote $1 $) < @ *LOCAL* >	dequote "foo"
100090792SgshapiroR< @ *LOCAL* >		$#error $@ 5.1.3 $: "_CODE553 User address required"
100138032SpeterR$* $=O $* < @ *LOCAL* >
100264562Sgshapiro			$@ $>Parse0 $>canonify $1 $2 $3	...@*LOCAL* -> ...
100338032SpeterR$* < @ *LOCAL* >	$: $1
100438032Speter
100538032Speter#
100638032Speter#  Parse1 -- the bottom half of ruleset 0.
100738032Speter#
100838032Speter
100938032SpeterSParse1
101064562Sgshapiroifdef(`_LDAP_ROUTING_', `dnl
101164562Sgshapiro# handle LDAP routing for hosts in $={LDAPRoute}
101290792SgshapiroR$+ < @ $={LDAPRoute} . >	$: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $2> <>
101390792SgshapiroR$+ < @ $={LDAPRouteEquiv} . >	$: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $M> <>',
101464562Sgshapiro`dnl')
101564562Sgshapiro
101638032Speterifdef(`_MAILER_smtp_',
101738032Speter`# handle numeric address spec
101864562Sgshapirodnl there is no check whether this is really an IP number
101964562SgshapiroR$* < @ [ $+ ] > $*	$: $>ParseLocal $1 < @ [ $2 ] > $3	numeric internet spec
102064562SgshapiroR$* < @ [ $+ ] > $*	$1 < @ [ $2 ] : $S > $3		Add smart host to path
102190792SgshapiroR$* < @ [ $+ ] : > $*		$#_SMTP_ $@ [$2] $: $1 < @ [$2] > $3	no smarthost: send
102264562SgshapiroR$* < @ [ $+ ] : $- : $*> $*	$#$3 $@ $4 $: $1 < @ [$2] > $5	smarthost with mailer
102364562SgshapiroR$* < @ [ $+ ] : $+ > $*	$#_SMTP_ $@ $3 $: $1 < @ [$2] > $4	smarthost without mailer',
102438032Speter	`dnl')
102538032Speter
102664562Sgshapiroifdef(`_VIRTUSER_TABLE_', `dnl
102738032Speter# handle virtual users
102890792Sgshapiroifdef(`_VIRTUSER_STOP_ONE_LEVEL_RECURSION_',`dnl
102990792Sgshapirodnl this is not a documented option
103090792Sgshapirodnl it stops looping in virtusertable mapping if input and output
103190792Sgshapirodnl are identical, i.e., if address A is mapped to A.
103290792Sgshapirodnl it does not deal with multi-level recursion
103390792Sgshapiro# handle full domains in RHS of virtusertable
103490792SgshapiroR$+ < @ $+ >			$: $(macro {RecipientAddress} $) $1 < @ $2 >
103590792SgshapiroR$+ < @ $+ > 			$: <?> $1 < @ $2 > $| $>final $1 < @ $2 >
103690792SgshapiroR<?> $+ $| $+			$: $1 $(macro {RecipientAddress} $@ $2 $)
103790792SgshapiroR<?> $+ $| $*			$: $1',
103890792Sgshapiro`dnl')
103964562SgshapiroR$+			$: <!> $1		Mark for lookup
104090792Sgshapirodnl input: <!> local<@domain>
104164562Sgshapiroifdef(`_VIRTUSER_ENTIRE_DOMAIN_',
104264562Sgshapiro`R<!> $+ < @ $* $={VirtHost} . > 	$: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >',
104364562Sgshapiro`R<!> $+ < @ $={VirtHost} . > 	$: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >')
104490792Sgshapirodnl input: <result-of-lookup | @> local<@domain> | <!> local<@domain>
104564562SgshapiroR<!> $+ < @ $=w . > 	$: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
104690792Sgshapirodnl if <@> local<@domain>: no match but try lookup
104790792Sgshapirodnl user+detail: try user++@domain if detail not empty
104890792SgshapiroR<@> $+ + $+ < @ $* . >
104990792Sgshapiro			$: < $(virtuser $1 + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
105090792Sgshapirodnl user+detail: try user+*@domain
105138032SpeterR<@> $+ + $* < @ $* . >
105290792Sgshapiro			$: < $(virtuser $1 + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
105390792Sgshapirodnl user+detail: try user@domain
105438032SpeterR<@> $+ + $* < @ $* . >
105590792Sgshapiro			$: < $(virtuser $1 @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
105664562Sgshapirodnl try default entry: @domain
105790792Sgshapirodnl ++@domain
105890792SgshapiroR<@> $+ + $+ < @ $+ . >	$: < $(virtuser + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
105964562Sgshapirodnl +*@domain
106090792SgshapiroR<@> $+ + $* < @ $+ . >	$: < $(virtuser + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
106164562Sgshapirodnl @domain if +detail exists
106298121Sgshapirodnl if no match, change marker to prevent a second @domain lookup
106398121SgshapiroR<@> $+ + $* < @ $+ . >	$: < $(virtuser @ $3 $@ $1 $@ $2 $@ +$2 $: ! $) > $1 + $2 < @ $3 . >
106498121Sgshapirodnl without +detail
106538032SpeterR<@> $+ < @ $+ . >	$: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
106690792Sgshapirodnl no match
106738032SpeterR<@> $+			$: $1
106890792Sgshapirodnl remove mark
106964562SgshapiroR<!> $+			$: $1
107064562SgshapiroR< error : $-.$-.$- : $+ > $* 	$#error $@ $1.$2.$3 $: $4
107138032SpeterR< error : $- $+ > $* 	$#error $@ $(dequote $1 $) $: $2
107290792Sgshapiroifdef(`_VIRTUSER_STOP_ONE_LEVEL_RECURSION_',`dnl
107390792Sgshapiro# check virtuser input address against output address, if same, skip recursion
107490792SgshapiroR< $+ > $+ < @ $+ >				$: < $1 > $2 < @ $3 > $| $1
107590792Sgshapiro# it is the same: stop now
107690792SgshapiroR< $+ > $+ < @ $+ > $| $&{RecipientAddress}	$: $>ParseLocal $>Parse0 $>canonify $1
107790792SgshapiroR< $+ > $+ < @ $+ > $| $* 			$: < $1 > $2 < @ $3 >
107890792Sgshapirodnl', `dnl')
107980785Sgshapirodnl this is not a documented option
108080785Sgshapirodnl it performs no looping at all for virtusertable
108177349Sgshapiroifdef(`_NO_VIRTUSER_RECURSION_',
108277349Sgshapiro`R< $+ > $+ < @ $+ >	$: $>ParseLocal $>Parse0 $>canonify $1',
108377349Sgshapiro`R< $+ > $+ < @ $+ >	$: $>Recurse $1')
108477349Sgshapirodnl', `dnl')
108538032Speter
108638032Speter# short circuit local delivery so forwarded email works
108738032Speterifdef(`_MAILER_usenet_', `dnl
108864562SgshapiroR$+ . USENET < @ $=w . >	$#usenet $@ usenet $: $1	handle usenet specially', `dnl')
108966494Sgshapiro
109066494Sgshapiro
109138032Speterifdef(`_STICKY_LOCAL_DOMAIN_',
109238032Speter`R$+ < @ $=w . >		$: < $H > $1 < @ $2 . >		first try hub
109364562SgshapiroR< $+ > $+ < $+ >	$>MailerToTriple < $1 > $2 < $3 >	yep ....
109464562Sgshapirodnl $H empty (but @$=w.)
109538032SpeterR< > $+ + $* < $+ >	$#_LOCAL_ $: $1 + $2		plussed name?
109638032SpeterR< > $+ < $+ >		$#_LOCAL_ $: @ $1			nope, local address',
109764562Sgshapiro`R$=L < @ $=w . >	$#_LOCAL_ $: @ $1			special local names
109838032SpeterR$+ < @ $=w . >		$#_LOCAL_ $: $1			regular local name')
109938032Speter
110064562Sgshapiroifdef(`_MAILER_TABLE_', `dnl
110138032Speter# not local -- try mailer table lookup
110238032SpeterR$* <@ $+ > $*		$: < $2 > $1 < @ $2 > $3	extract host name
110338032SpeterR< $+ . > $*		$: < $1 > $2			strip trailing dot
110438032SpeterR< $+ > $*		$: < $(mailertable $1 $) > $2	lookup
110564562Sgshapirodnl it is $~[ instead of $- to avoid matches on IPv6 addresses
110664562SgshapiroR< $~[ : $* > $* 	$>MailerToTriple < $1 : $2 > $3		check -- resolved?
110764562SgshapiroR< $+ > $*		$: $>Mailertable <$1> $2		try domain',
110838032Speter`dnl')
110964562Sgshapiroundivert(4)dnl UUCP rules from `MAILER(uucp)'
111038032Speter
111138032Speterifdef(`_NO_UUCP_', `dnl',
111238032Speter`# resolve remotely connected UUCP links (if any)
111338032Speterifdef(`_CLASS_V_',
111464562Sgshapiro`R$* < @ $=V . UUCP . > $*		$: $>MailerToTriple < $V > $1 <@$2.UUCP.> $3',
111538032Speter	`dnl')
111638032Speterifdef(`_CLASS_W_',
111764562Sgshapiro`R$* < @ $=W . UUCP . > $*		$: $>MailerToTriple < $W > $1 <@$2.UUCP.> $3',
111838032Speter	`dnl')
111938032Speterifdef(`_CLASS_X_',
112064562Sgshapiro`R$* < @ $=X . UUCP . > $*		$: $>MailerToTriple < $X > $1 <@$2.UUCP.> $3',
112138032Speter	`dnl')')
112238032Speter
112338032Speter# resolve fake top level domains by forwarding to other hosts
112438032Speterifdef(`BITNET_RELAY',
112564562Sgshapiro`R$*<@$+.BITNET.>$*	$: $>MailerToTriple < $B > $1 <@$2.BITNET.> $3	user@host.BITNET',
112638032Speter	`dnl')
112738032Speterifdef(`DECNET_RELAY',
112864562Sgshapiro`R$*<@$+.DECNET.>$*	$: $>MailerToTriple < $C > $1 <@$2.DECNET.> $3	user@host.DECNET',
112938032Speter	`dnl')
113038032Speterifdef(`_MAILER_pop_',
113138032Speter`R$+ < @ POP. >		$#pop $: $1			user@POP',
113238032Speter	`dnl')
113338032Speterifdef(`_MAILER_fax_',
113438032Speter`R$+ < @ $+ .FAX. >	$#fax $@ $2 $: $1		user@host.FAX',
113538032Speter`ifdef(`FAX_RELAY',
113664562Sgshapiro`R$*<@$+.FAX.>$*		$: $>MailerToTriple < $F > $1 <@$2.FAX.> $3	user@host.FAX',
113738032Speter	`dnl')')
113838032Speter
113938032Speterifdef(`UUCP_RELAY',
114038032Speter`# forward non-local UUCP traffic to our UUCP relay
114164562SgshapiroR$*<@$*.UUCP.>$*		$: $>MailerToTriple < $Y > $1 <@$2.UUCP.> $3	uucp mail',
114238032Speter`ifdef(`_MAILER_uucp_',
114338032Speter`# forward other UUCP traffic straight to UUCP
114438032SpeterR$* < @ $+ .UUCP. > $*		$#_UUCP_ $@ $2 $: $1 < @ $2 .UUCP. > $3	user@host.UUCP',
114538032Speter	`dnl')')
114638032Speterifdef(`_MAILER_usenet_', `
114738032Speter# addresses sent to net.group.USENET will get forwarded to a newsgroup
114864562SgshapiroR$+ . USENET		$#usenet $@ usenet $: $1',
114938032Speter	`dnl')
115038032Speter
115138032Speterifdef(`_LOCAL_RULES_',
115238032Speter`# figure out what should stay in our local mail system
115338032Speterundivert(1)', `dnl')
115438032Speter
115538032Speter# pass names that still have a host to a smarthost (if defined)
115664562SgshapiroR$* < @ $* > $*		$: $>MailerToTriple < $S > $1 < @ $2 > $3	glue on smarthost name
115738032Speter
115838032Speter# deal with other remote names
115938032Speterifdef(`_MAILER_smtp_',
116064562Sgshapiro`R$* < @$* > $*		$#_SMTP_ $@ $2 $: $1 < @ $2 > $3	user@host.domain',
116190792Sgshapiro`R$* < @$* > $*		$#error $@ 5.1.2 $: "_CODE553 Unrecognized host name " $2')
116238032Speter
116338032Speter# handle locally delivered names
116464562SgshapiroR$=L			$#_LOCAL_ $: @ $1		special local names
116538032SpeterR$+			$#_LOCAL_ $: $1			regular local names
116638032Speter
116738032Speter###########################################################################
116838032Speter###   Ruleset 5 -- special rewriting after aliases have been expanded   ###
116938032Speter###########################################################################
117038032Speter
117164562SgshapiroSLocal_localaddr
117264562SgshapiroSlocaladdr=5
117364562SgshapiroR$+			$: $1 $| $>"Local_localaddr" $1
117490792SgshapiroR$+ $| $#ok		$@ $1			no change
117564562SgshapiroR$+ $| $#$*		$#$2
117664562SgshapiroR$+ $| $*		$: $1
117738032Speter
117890792Sgshapiroifdef(`_PRESERVE_LUSER_HOST_', `dnl
117990792Sgshapiro# Preserve rcpt_host in {Host}
118090792SgshapiroR$+			$: $1 $| $&h $| $&{Host}	check h and {Host}
118190792SgshapiroR$+ $| $|		$: $(macro {Host} $@ $) $1	no h or {Host}
118290792SgshapiroR$+ $| $| $+		$: $1			h not set, {Host} set
118390792SgshapiroR$+ $| +$* $| $*	$: $1			h is +detail, {Host} set
118495154SgshapiroR$+ $| $* @ $+ $| $*	$: $(macro {Host} $@ @$3 $) $1	set {Host} to host in h
118590792SgshapiroR$+ $| $+ $| $*		$: $(macro {Host} $@ @$2 $) $1	set {Host} to h
118690792Sgshapiro')dnl
118790792Sgshapiro
118890792Sgshapiroifdef(`_FFR_5_', `dnl
118966494Sgshapiro# Preserve host in a macro
119066494SgshapiroR$+			$: $(macro {LocalAddrHost} $) $1
119166494SgshapiroR$+ @ $+		$: $(macro {LocalAddrHost} $@ @ $2 $) $1')
119266494Sgshapiro
119390792Sgshapiroifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `', `dnl
119438032Speter# deal with plussed users so aliases work nicely
119566494SgshapiroR$+ + *			$#_LOCAL_ $@ $&h $: $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}')
119666494SgshapiroR$+ + $*		$#_LOCAL_ $@ + $2 $: $1 + *`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}')
119766494Sgshapiro')
119838032Speter# prepend an empty "forward host" on the front
119938032SpeterR$+			$: <> $1
120038032Speter
120138032Speterifdef(`LUSER_RELAY', `dnl
120238032Speter# send unrecognized local users to a relay host
120390792Sgshapiroifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `dnl
120466494SgshapiroR< > $+ + $*		$: < ? $L > <+ $2> $(user $1 $)	look up user+
120566494SgshapiroR< > $+			$: < ? $L > < > $(user $1 $)	look up user
120666494SgshapiroR< ? $* > < $* > $+ <>	$: < > $3 $2			found; strip $L
120766494SgshapiroR< ? $* > < $* > $+	$: < $1 > $3 $2			not found', `
120864562SgshapiroR< > $+ 		$: < $L > $(user $1 $)		look up user
120990792SgshapiroR< $* > $+ <>		$: < > $2			found; strip $L')
121090792Sgshapiroifdef(`_PRESERVE_LUSER_HOST_', `dnl
121190792SgshapiroR< $+ > $+		$: < $1 > $2 $&{Host}')
121290792Sgshapirodnl')
121338032Speter
121490792Sgshapiroifdef(`MAIL_HUB', `dnl
121590792SgshapiroR< > $+			$: < $H > $1			try hub', `dnl')
121690792Sgshapiroifdef(`LOCAL_RELAY', `dnl
121790792SgshapiroR< > $+			$: < $R > $1			try relay', `dnl')
121890792Sgshapiroifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `dnl
121990792SgshapiroR< > $+			$@ $1', `dnl
122064562SgshapiroR< > $+			$: < > < $1 <> $&h >		nope, restore +detail
122190792Sgshapiroifdef(`_PRESERVE_LUSER_HOST_', `dnl
122290792SgshapiroR< > < $+ @ $+ <> + $* >	$: < > < $1 + $3 @ $2 >	check whether +detail')
122364562SgshapiroR< > < $+ <> + $* >	$: < > < $1 + $2 >		check whether +detail
122464562SgshapiroR< > < $+ <> $* >	$: < > < $1 >			else discard
122538032SpeterR< > < $+ + $* > $*	   < > < $1 > + $2 $3		find the user part
122666494SgshapiroR< > < $+ > + $*	$#_LOCAL_ $@ $2 $: @ $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}')		strip the extra +
122738032SpeterR< > < $+ >		$@ $1				no +detail
122843730SpeterR$+			$: $1 <> $&h			add +detail back in
122990792Sgshapiroifdef(`_PRESERVE_LUSER_HOST_', `dnl
123090792SgshapiroR$+ @ $+ <> + $*	$: $1 + $3 @ $2			check whether +detail')
123143730SpeterR$+ <> + $*		$: $1 + $2			check whether +detail
123266494SgshapiroR$+ <> $*		$: $1				else discard')
123364562SgshapiroR< local : $* > $*	$: $>MailerToTriple < local : $1 > $2	no host extension
123464562SgshapiroR< error : $* > $*	$: $>MailerToTriple < error : $1 > $2	no host extension
123590792Sgshapiroifdef(`_PRESERVE_LUSER_HOST_', `dnl
123690792Sgshapirodnl it is $~[ instead of $- to avoid matches on IPv6 addresses
123790792SgshapiroR< $~[ : $+ > $+ @ $+	$: $>MailerToTriple < $1 : $2 > $3 < @ $4 >')
123890792SgshapiroR< $~[ : $+ > $+	$: $>MailerToTriple < $1 : $2 > $3 < @ $2 >
123990792Sgshapiroifdef(`_PRESERVE_LUSER_HOST_', `dnl
124090792SgshapiroR< $+ > $+ @ $+		$@ $>MailerToTriple < $1 > $2 < @ $3 >')
124164562SgshapiroR< $+ > $+		$@ $>MailerToTriple < $1 > $2 < @ $1 >
124238032Speter
124364562Sgshapiroifdef(`_MAILER_TABLE_', `dnl
124490792Sgshapiroifdef(`_LDAP_ROUTING_', `dnl
124538032Speter###################################################################
124690792Sgshapiro###  Ruleset LDAPMailertable -- mailertable lookup for LDAP     ###
124790792Sgshapirodnl input: <Domain> FullAddress
124890792Sgshapiro###################################################################
124990792Sgshapiro
125090792SgshapiroSLDAPMailertable
125190792SgshapiroR< $+ > $*		$: < $(mailertable $1 $) > $2		lookup
125290792SgshapiroR< $~[ : $* > $*	$>MailerToTriple < $1 : $2 > $3		check resolved?
125390792SgshapiroR< $+ > $*		$: < $1 > $>Mailertable <$1> $2		try domain
125490792SgshapiroR< $+ > $#$*		$#$2					found
125590792SgshapiroR< $+ > $*		$#_RELAY_ $@ $1 $: $2			not found, direct relay',
125690792Sgshapiro`dnl')
125790792Sgshapiro
125890792Sgshapiro###################################################################
125938032Speter###  Ruleset 90 -- try domain part of mailertable entry 	###
126064562Sgshapirodnl input: LeftPartOfDomain <RightPartOfDomain> FullAddress
126138032Speter###################################################################
126238032Speter
126364562SgshapiroSMailertable=90
126464562Sgshapirodnl shift and check
126564562Sgshapirodnl %2 is not documented in cf/README
126638032SpeterR$* <$- . $+ > $*	$: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4
126764562Sgshapirodnl it is $~[ instead of $- to avoid matches on IPv6 addresses
126864562SgshapiroR$* <$~[ : $* > $*	$>MailerToTriple < $2 : $3 > $4		check -- resolved?
126964562SgshapiroR$* < . $+ > $* 	$@ $>Mailertable $1 . <$2> $3		no -- strip & try again
127064562Sgshapirodnl is $2 always empty?
127138032SpeterR$* < $* > $*		$: < $(mailertable . $@ $1$2 $) > $3	try "."
127264562SgshapiroR< $~[ : $* > $*	$>MailerToTriple < $1 : $2 > $3		"." found?
127364562Sgshapirodnl return full address
127438032SpeterR< $* > $*		$@ $2				no mailertable match',
127538032Speter`dnl')
127638032Speter
127738032Speter###################################################################
127838032Speter###  Ruleset 95 -- canonify mailer:[user@]host syntax to triple	###
127964562Sgshapirodnl input: in general: <[mailer:]host> lp<@domain>rest
128064562Sgshapirodnl	<> address				-> address
128164562Sgshapirodnl	<error:d.s.n:text>			-> error
128264562Sgshapirodnl	<error:text>				-> error
128364562Sgshapirodnl	<mailer:user@host> lp<@domain>rest	-> mailer host user
128464562Sgshapirodnl	<mailer:host> address			-> mailer host address
128564562Sgshapirodnl	<localdomain> address			-> address
128664562Sgshapirodnl	<host> address				-> relay host address
128738032Speter###################################################################
128838032Speter
128964562SgshapiroSMailerToTriple=95
129038032SpeterR< > $*				$@ $1			strip off null relay
129164562SgshapiroR< error : $-.$-.$- : $+ > $* 	$#error $@ $1.$2.$3 $: $4
129238032SpeterR< error : $- $+ > $*		$#error $@ $(dequote $1 $) $: $2
129338032SpeterR< local : $* > $*		$>CanonLocal < $1 > $2
129490792Sgshapirodnl it is $~[ instead of $- to avoid matches on IPv6 addresses
129590792SgshapiroR< $~[ : $+ @ $+ > $*<$*>$*	$# $1 $@ $3 $: $2<@$3>	use literal user
129690792SgshapiroR< $~[ : $+ > $*		$# $1 $@ $2 $: $3	try qualified mailer
129738032SpeterR< $=w > $*			$@ $2			delete local host
129838032SpeterR< $+ > $*			$#_RELAY_ $@ $1 $: $2	use unqualified mailer
129938032Speter
130038032Speter###################################################################
130138032Speter###  Ruleset CanonLocal -- canonify local: syntax		###
130264562Sgshapirodnl input: <user> address
130364562Sgshapirodnl <x> <@host> : rest			-> Recurse rest
130464562Sgshapirodnl <x> p1 $=O p2 <@host>		-> Recurse p1 $=O p2
130564562Sgshapirodnl <> user <@host> rest		-> local user@host user
130664562Sgshapirodnl <> user				-> local user user
130764562Sgshapirodnl <user@host> lp <@domain> rest	-> <user> lp <@host> [cont]
130864562Sgshapirodnl <user> lp <@host> rest		-> local lp@host user
130964562Sgshapirodnl <user> lp				-> local lp user
131038032Speter###################################################################
131138032Speter
131238032SpeterSCanonLocal
131343730Speter# strip local host from routed addresses
131464562SgshapiroR< $* > < @ $+ > : $+		$@ $>Recurse $3
131564562SgshapiroR< $* > $+ $=O $+ < @ $+ >	$@ $>Recurse $2 $3 $4
131643730Speter
131738032Speter# strip trailing dot from any host name that may appear
131838032SpeterR< $* > $* < @ $* . >		$: < $1 > $2 < @ $3 >
131938032Speter
132038032Speter# handle local: syntax -- use old user, either with or without host
132138032SpeterR< > $* < @ $* > $*		$#_LOCAL_ $@ $1@$2 $: $1
132238032SpeterR< > $+				$#_LOCAL_ $@ $1    $: $1
132338032Speter
132438032Speter# handle local:user@host syntax -- ignore host part
132538032SpeterR< $+ @ $+ > $* < @ $* >	$: < $1 > $3 < @ $4 >
132638032Speter
132738032Speter# handle local:user syntax
132838032SpeterR< $+ > $* <@ $* > $*		$#_LOCAL_ $@ $2@$3 $: $1
132938032SpeterR< $+ > $* 			$#_LOCAL_ $@ $2    $: $1
133038032Speter
133138032Speter###################################################################
133238032Speter###  Ruleset 93 -- convert header names to masqueraded form	###
133338032Speter###################################################################
133438032Speter
133564562SgshapiroSMasqHdr=93
133638032Speter
133764562Sgshapiroifdef(`_GENERICS_TABLE_', `dnl
133838032Speter# handle generics database
133938032Speterifdef(`_GENERICS_ENTIRE_DOMAIN_',
134064562Sgshapirodnl if generics should be applied add a @ as mark
134138032Speter`R$+ < @ $* $=G . >	$: < $1@$2$3 > $1 < @ $2$3 . > @	mark',
134238032Speter`R$+ < @ $=G . >	$: < $1@$2 > $1 < @ $2 . > @	mark')
134338032SpeterR$+ < @ *LOCAL* >	$: < $1@$j > $1 < @ *LOCAL* > @	mark
134464562Sgshapirodnl workspace: either user<@domain> or <user@domain> user <@domain> @
134564562Sgshapirodnl ignore the first case for now
134664562Sgshapirodnl if it has the mark lookup full address
134790792Sgshapirodnl broken: %1 is full address not just detail
134864562SgshapiroR< $+ > $+ < $* > @	$: < $(generics $1 $: @ $1 $) > $2 < $3 >
134964562Sgshapirodnl workspace: ... or <match|@user@domain> user <@domain>
135064562Sgshapirodnl no match, try user+detail@domain
135164562SgshapiroR<@$+ + $* @ $+> $+ < @ $+ >
135264562Sgshapiro		$: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) >  $4 < @ $5 >
135364562SgshapiroR<@$+ + $* @ $+> $+ < @ $+ >
135464562Sgshapiro		$: < $(generics $1@$3 $: $) > $4 < @ $5 >
135564562Sgshapirodnl no match, remove mark
135664562SgshapiroR<@$+ > $+ < @ $+ >	$: < > $2 < @ $3 >
135764562Sgshapirodnl no match, try @domain for exceptions
135864562SgshapiroR< > $+ < @ $+ . >	$: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . >
135964562Sgshapirodnl workspace: ... or <match> user <@domain>
136064562Sgshapirodnl no match, try local part
136138032SpeterR< > $+ < @ $+ > 	$: < $(generics $1 $: $) > $1 < @ $2 >
136264562SgshapiroR< > $+ + $* < @ $+ > 	$: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 >
136364562SgshapiroR< > $+ + $* < @ $+ > 	$: < $(generics $1 $: $) > $1 + $2 < @ $3 >
136464562SgshapiroR< $* @ $* > $* < $* >	$@ $>canonify $1 @ $2		found qualified
136564562SgshapiroR< $+ > $* < $* >	$: $>canonify $1 @ *LOCAL*	found unqualified
136638032SpeterR< > $*			$: $1				not found',
136738032Speter`dnl')
136838032Speter
136964562Sgshapiro# do not masquerade anything in class N
137064562SgshapiroR$* < @ $* $=N . >	$@ $1 < @ $2 $3 . >
137164562Sgshapiro
137290792Sgshapiroifdef(`MASQUERADE_NAME', `dnl
137338032Speter# special case the users that should be exposed
137438032SpeterR$=E < @ *LOCAL* >	$@ $1 < @ $j . >		leave exposed
137538032Speterifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
137638032Speter`R$=E < @ $* $=M . >	$@ $1 < @ $2 $3 . >',
137738032Speter`R$=E < @ $=M . >	$@ $1 < @ $2 . >')
137838032Speterifdef(`_LIMITED_MASQUERADE_', `dnl',
137938032Speter`R$=E < @ $=w . >	$@ $1 < @ $2 . >')
138038032Speter
138138032Speter# handle domain-specific masquerading
138238032Speterifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
138338032Speter`R$* < @ $* $=M . > $*	$: $1 < @ $2 $3 . @ $M > $4	convert masqueraded doms',
138438032Speter`R$* < @ $=M . > $*	$: $1 < @ $2 . @ $M > $3	convert masqueraded doms')
138538032Speterifdef(`_LIMITED_MASQUERADE_', `dnl',
138638032Speter`R$* < @ $=w . > $*	$: $1 < @ $2 . @ $M > $3')
138738032SpeterR$* < @ *LOCAL* > $*	$: $1 < @ $j . @ $M > $2
138838032SpeterR$* < @ $+ @ > $*	$: $1 < @ $2 > $3		$M is null
138938032SpeterR$* < @ $+ @ $+ > $*	$: $1 < @ $3 . > $4		$M is not null
139090792Sgshapirodnl', `dnl no masquerading
139190792Sgshapirodnl just fix *LOCAL* leftovers
139290792SgshapiroR$* < @ *LOCAL* >	$@ $1 < @ $j . >')
139338032Speter
139438032Speter###################################################################
139538032Speter###  Ruleset 94 -- convert envelope names to masqueraded form	###
139638032Speter###################################################################
139738032Speter
139864562SgshapiroSMasqEnv=94
139938032Speterifdef(`_MASQUERADE_ENVELOPE_',
140064562Sgshapiro`R$+			$@ $>MasqHdr $1',
140138032Speter`R$* < @ *LOCAL* > $*	$: $1 < @ $j . > $2')
140238032Speter
140338032Speter###################################################################
140438032Speter###  Ruleset 98 -- local part of ruleset zero (can be null)	###
140538032Speter###################################################################
140638032Speter
140764562SgshapiroSParseLocal=98
140864562Sgshapiroundivert(3)dnl LOCAL_RULE_0
140938032Speter
141064562Sgshapiroifdef(`_LDAP_ROUTING_', `dnl
141190792Sgshapiro######################################################################
141290792Sgshapiro###  LDAPExpand: Expand address using LDAP routing
141390792Sgshapiro###
141490792Sgshapiro###	Parameters:
141590792Sgshapiro###		<$1> -- parsed address (user < @ domain . >) (pass through)
141690792Sgshapiro###		<$2> -- RFC822 address (user @ domain) (used for lookup)
141790792Sgshapiro###		<$3> -- +detail information
141890792Sgshapiro###
141990792Sgshapiro###	Returns:
142090792Sgshapiro###		Mailer triplet ($#mailer $@ host $: address)
142190792Sgshapiro###		Parsed address (user < @ domain . >)
142290792Sgshapiro######################################################################
142390792Sgshapiro
142464562SgshapiroSLDAPExpand
142564562Sgshapiro# do the LDAP lookups
142690792SgshapiroR<$+><$+><$*>	$: <$(ldapmra $2 $: $)> <$(ldapmh $2 $: $)> <$1> <$2> <$3>
142764562Sgshapiro
142894334Sgshapiro# look for temporary failures (return original address, MTA will queue up)
1429102528SgshapiroR<$* <TMPF>> <$*> <$+> <$+> <$*>	$@ $3
1430102528SgshapiroR<$*> <$* <TMPF>> <$+> <$+> <$*>	$@ $3
143194334Sgshapiro
143264562Sgshapiro# if mailRoutingAddress and local or non-existant mailHost,
143364562Sgshapiro# return the new mailRoutingAddress
143490792Sgshapiroifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl
143590792SgshapiroR<$+@$+> <$=w> <$+> <$+> <$*>	$@ $>Parse0 $>canonify $1 $6 @ $2
143690792SgshapiroR<$+@$+> <> <$+> <$+> <$*>	$@ $>Parse0 $>canonify $1 $5 @ $2')
143790792SgshapiroR<$+> <$=w> <$+> <$+> <$*>	$@ $>Parse0 $>canonify $1
143890792SgshapiroR<$+> <> <$+> <$+> <$*>		$@ $>Parse0 $>canonify $1
143964562Sgshapiro
144098121Sgshapiro
144164562Sgshapiro# if mailRoutingAddress and non-local mailHost,
144264562Sgshapiro# relay to mailHost with new mailRoutingAddress
144390792Sgshapiroifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl
144490792Sgshapiroifdef(`_MAILER_TABLE_', `dnl
144590792Sgshapiro# check mailertable for host, relay from there
144690792SgshapiroR<$+@$+> <$+> <$+> <$+> <$*>	$>LDAPMailertable <$3> $>canonify $1 $6 @ $2',
144790792Sgshapiro`R<$+@$+> <$+> <$+> <$+> <$*>	$#_RELAY_ $@ $3 $: $>canonify $1 $6 @ $2')')
144890792Sgshapiroifdef(`_MAILER_TABLE_', `dnl
144990792Sgshapiro# check mailertable for host, relay from there
145090792SgshapiroR<$+> <$+> <$+> <$+> <$*>	$>LDAPMailertable <$2> $>canonify $1',
145190792Sgshapiro`R<$+> <$+> <$+> <$+> <$*>	$#_RELAY_ $@ $2 $: $>canonify $1')
145264562Sgshapiro
145364562Sgshapiro# if no mailRoutingAddress and local mailHost,
145464562Sgshapiro# return original address
145590792SgshapiroR<> <$=w> <$+> <$+> <$*>	$@ $2
145664562Sgshapiro
145798121Sgshapiro
145864562Sgshapiro# if no mailRoutingAddress and non-local mailHost,
145964562Sgshapiro# relay to mailHost with original address
146090792Sgshapiroifdef(`_MAILER_TABLE_', `dnl
146190792Sgshapiro# check mailertable for host, relay from there
146290792SgshapiroR<> <$+> <$+> <$+> <$*>		$>LDAPMailertable <$1> $2',
146390792Sgshapiro`R<> <$+> <$+> <$+> <$*>	$#_RELAY_ $@ $1 $: $2')
146464562Sgshapiro
146590792Sgshapiroifdef(`_LDAP_ROUTE_DETAIL_',
146690792Sgshapiro`# if no mailRoutingAddress and no mailHost,
146790792Sgshapiro# try without +detail
146890792SgshapiroR<> <> <$+> <$+ + $* @ $+> <>	$@ $>LDAPExpand <$1> <$2 @ $4> <+$3>')dnl
146990792Sgshapiro
147090792Sgshapiro# if still no mailRoutingAddress and no mailHost,
147164562Sgshapiro# try @domain
147290792Sgshapiroifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl
147390792SgshapiroR<> <> <$+> <$+ + $* @ $+> <>	$@ $>LDAPExpand <$1> <@ $4> <+$3>')
147490792SgshapiroR<> <> <$+> <$+ @ $+> <$*>	$@ $>LDAPExpand <$1> <@ $3> <$4>
147564562Sgshapiro
147664562Sgshapiro# if no mailRoutingAddress and no mailHost and this was a domain attempt,
147764562Sgshapiroifelse(_LDAP_ROUTING_, `_MUST_EXIST_', `dnl
147864562Sgshapiro# user does not exist
147990792SgshapiroR<> <> <$+> <@ $+> <$*>		$: <?> < $&{addr_type} > < $1 >
148090792Sgshapiro# only give error for envelope recipient
148190792SgshapiroR<?> <e r> <$+>			$#error $@ nouser $: "550 User unknown"
148290792SgshapiroR<?> <$*> <$+>			$@ $2',
148364562Sgshapiro`dnl
148464562Sgshapiro# return the original address
148590792SgshapiroR<> <> <$+> <@ $+> <$*>		$@ $1')',
148664562Sgshapiro`dnl')
148764562Sgshapiro
148864562Sgshapiroifelse(substr(confDELIVERY_MODE,0,1), `d', `errprint(`WARNING: Antispam rules not available in deferred delivery mode.
148964562Sgshapiro')')
149090792Sgshapiroifdef(`_ACCESS_TABLE_', `dnl', `divert(-1)')
149138032Speter######################################################################
149290792Sgshapiro###  D: LookUpDomain -- search for domain in access database
149338032Speter###
149438032Speter###	Parameters:
149538032Speter###		<$1> -- key (domain name)
149638032Speter###		<$2> -- default (what to return if not found in db)
149764562Sgshapirodnl			must not be empty
149890792Sgshapiro###		<$3> -- mark (must be <(!|+) single-token>)
149964562Sgshapiro###			! does lookup only with tag
150064562Sgshapiro###			+ does lookup with and without tag
150190792Sgshapiro###		<$4> -- passthru (additional data passed unchanged through)
150264562Sgshapirodnl returns:		<default> <passthru>
150364562Sgshapirodnl 			<result> <passthru>
150438032Speter######################################################################
150538032Speter
150690792SgshapiroSD
150764562Sgshapirodnl workspace <key> <default> <passthru> <mark>
150864562Sgshapirodnl lookup with tag (in front, no delimiter here)
150990792Sgshapirodnl    2    3  4    5
151090792SgshapiroR<$*> <$+> <$- $-> <$*>		$: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5>
151164562Sgshapirodnl workspace <result-of-lookup|?> <key> <default> <passthru> <mark>
151264562Sgshapirodnl lookup without tag?
151390792Sgshapirodnl   1    2      3    4
151490792SgshapiroR<?> <$+> <$+> <+ $-> <$*>	$: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4>
151590792Sgshapiroifdef(`_LOOKUPDOTDOMAIN_', `dnl omit first component: lookup .rest
151690792Sgshapirodnl XXX apply this also to IP addresses?
151790792Sgshapirodnl currently it works the wrong way round for [1.2.3.4]
151890792Sgshapirodnl   1  2    3    4  5    6
151990792SgshapiroR<?> <$+.$+> <$+> <$- $-> <$*>	$: < $(access $5`'_TAG_DELIM_`'.$2 $: ? $) > <$1.$2> <$3> <$4 $5> <$6>
152090792Sgshapirodnl   1  2    3      4    5
152190792SgshapiroR<?> <$+.$+> <$+> <+ $-> <$*>	$: < $(access .$2 $: ? $) > <$1.$2> <$3> <+ $4> <$5>', `dnl')
152290792Sgshapiroifdef(`_ACCESS_SKIP_', `dnl
152390792Sgshapirodnl found SKIP: return <default> and <passthru>
152490792Sgshapirodnl      1    2    3  4    5
152590792SgshapiroR<SKIP> <$+> <$+> <$- $-> <$*>	$@ <$2> <$5>', `dnl')
152690792Sgshapirodnl not found: IPv4 net (no check is done whether it is an IP number!)
152790792Sgshapirodnl    1  2     3    4  5    6
152890792SgshapiroR<?> <[$+.$-]> <$+> <$- $-> <$*>	$@ $>D <[$1]> <$3> <$4 $5> <$6>
152990792Sgshapiroifdef(`NO_NETINET6', `dnl',
153090792Sgshapiro`dnl not found: IPv6 net
153190792Sgshapirodnl (could be merged with previous rule if we have a class containing .:)
153290792Sgshapirodnl    1   2     3    4  5    6
153390792SgshapiroR<?> <[$+::$-]> <$+> <$- $-> <$*>	$: $>D <[$1]> <$3> <$4 $5> <$6>
153490792SgshapiroR<?> <[$+:$-]> <$+> <$- $-> <$*>	$: $>D <[$1]> <$3> <$4 $5> <$6>')
153564562Sgshapirodnl not found, but subdomain: try again
153690792Sgshapirodnl   1  2    3    4  5    6
153790792SgshapiroR<?> <$+.$+> <$+> <$- $-> <$*>	$@ $>D <$2> <$3> <$4 $5> <$6>
153890792Sgshapiroifdef(`_FFR_LOOKUPTAG_', `dnl lookup Tag:
153990792Sgshapirodnl   1    2      3    4
154090792SgshapiroR<?> <$+> <$+> <! $-> <$*>	$: < $(access $3`'_TAG_DELIM_ $: ? $) > <$1> <$2> <! $3> <$4>', `dnl')
154190792Sgshapirodnl not found, no subdomain: return <default> and <passthru>
154290792Sgshapirodnl   1    2    3  4    5
154390792SgshapiroR<?> <$+> <$+> <$- $-> <$*>	$@ <$2> <$5>
154490792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
154590792Sgshapirodnl            2    3    4  5    6
154690792SgshapiroR<$* _ATMPF_> <$+> <$+> <$- $-> <$*>	$@ <_ATMPF_> <$6>', `dnl')
154790792Sgshapirodnl return <result of lookup> and <passthru>
154890792Sgshapirodnl    2    3    4  5    6
154990792SgshapiroR<$*> <$+> <$+> <$- $-> <$*>	$@ <$1> <$6>
155038032Speter
155138032Speter######################################################################
155290792Sgshapiro###  A: LookUpAddress -- search for host address in access database
155338032Speter###
155438032Speter###	Parameters:
155538032Speter###		<$1> -- key (dot quadded host address)
155638032Speter###		<$2> -- default (what to return if not found in db)
155764562Sgshapirodnl			must not be empty
155890792Sgshapiro###		<$3> -- mark (must be <(!|+) single-token>)
155964562Sgshapiro###			! does lookup only with tag
156064562Sgshapiro###			+ does lookup with and without tag
156190792Sgshapiro###		<$4> -- passthru (additional data passed through)
156264562Sgshapirodnl	returns:	<default> <passthru>
156364562Sgshapirodnl			<result> <passthru>
156438032Speter######################################################################
156538032Speter
156690792SgshapiroSA
156764562Sgshapirodnl lookup with tag
156890792Sgshapirodnl    2    3  4    5
156990792SgshapiroR<$+> <$+> <$- $-> <$*>		$: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5>
157064562Sgshapirodnl lookup without tag
157190792Sgshapirodnl   1    2      3    4
157290792SgshapiroR<?> <$+> <$+> <+ $-> <$*>	$: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4>
157390792Sgshapirodnl workspace <result-of-lookup|?> <key> <default> <mark> <passthru>
157490792Sgshapiroifdef(`_ACCESS_SKIP_', `dnl
157590792Sgshapirodnl found SKIP: return <default> and <passthru>
157690792Sgshapirodnl      1    2    3  4    5
157790792SgshapiroR<SKIP> <$+> <$+> <$- $-> <$*>	$@ <$2> <$5>', `dnl')
157890792Sgshapiroifdef(`NO_NETINET6', `dnl',
157990792Sgshapiro`dnl no match; IPv6: remove last part
158090792Sgshapirodnl   1   2    3    4  5    6
158190792SgshapiroR<?> <$+::$-> <$+> <$- $-> <$*>		$@ $>A <$1> <$3> <$4 $5> <$6>
158290792SgshapiroR<?> <$+:$-> <$+> <$- $-> <$*>		$@ $>A <$1> <$3> <$4 $5> <$6>')
158364562Sgshapirodnl no match; IPv4: remove last part
158490792Sgshapirodnl   1  2    3    4  5    6
158590792SgshapiroR<?> <$+.$-> <$+> <$- $-> <$*>		$@ $>A <$1> <$3> <$4 $5> <$6>
158664562Sgshapirodnl no match: return default
158790792Sgshapirodnl   1    2    3  4    5
158890792SgshapiroR<?> <$+> <$+> <$- $-> <$*>	$@ <$2> <$5>
158990792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
159090792Sgshapirodnl            2    3    4  5    6
159190792SgshapiroR<$* _ATMPF_> <$+> <$+> <$- $-> <$*>	$@ <_ATMPF_> <$6>', `dnl')
159264562Sgshapirodnl match: return result
159390792Sgshapirodnl    2    3    4  5    6
159490792SgshapiroR<$*> <$+> <$+> <$- $-> <$*>	$@ <$1> <$6>
159590792Sgshapirodnl endif _ACCESS_TABLE_
159690792Sgshapirodivert(0)
159738032Speter######################################################################
159842575Speter###  CanonAddr --	Convert an address into a standard form for
159942575Speter###			relay checking.  Route address syntax is
160042575Speter###			crudely converted into a %-hack address.
160142575Speter###
160242575Speter###	Parameters:
160342575Speter###		$1 -- full recipient address
160442575Speter###
160542575Speter###	Returns:
160642575Speter###		parsed address, not in source route form
160764562Sgshapirodnl		user%host%host<@domain>
160864562Sgshapirodnl		host!user<@domain>
160942575Speter######################################################################
161042575Speter
161142575SpeterSCanonAddr
161264562SgshapiroR$*			$: $>Parse0 $>canonify $1	make domain canonical
161364562Sgshapiroifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl
161442575SpeterR< @ $+ > : $* @ $*	< @ $1 > : $2 % $3	change @ to % in src route
161542575SpeterR$* < @ $+ > : $* : $*	$3 $1 < @ $2 > : $4	change to % hack.
161642575SpeterR$* < @ $+ > : $*	$3 $1 < @ $2 >
161764562Sgshapirodnl')
161842575Speter
161942575Speter######################################################################
162038032Speter###  ParseRecipient --	Strip off hosts in $=R as well as possibly
162138032Speter###			$* $=m or the access database.
162238032Speter###			Check user portion for host separators.
162338032Speter###
162438032Speter###	Parameters:
162538032Speter###		$1 -- full recipient address
162638032Speter###
162738032Speter###	Returns:
162838032Speter###		parsed, non-local-relaying address
162938032Speter######################################################################
163038032Speter
163138032SpeterSParseRecipient
163264562Sgshapirodnl mark and canonify address
163342575SpeterR$*				$: <?> $>CanonAddr $1
163464562Sgshapirodnl workspace: <?> localpart<@domain[.]>
163542575SpeterR<?> $* < @ $* . >		<?> $1 < @ $2 >			strip trailing dots
163664562Sgshapirodnl workspace: <?> localpart<@domain>
163742575SpeterR<?> $- < @ $* >		$: <?> $(dequote $1 $) < @ $2 >	dequote local part
163838032Speter
163938032Speter# if no $=O character, no host in the user portion, we are done
164042575SpeterR<?> $* $=O $* < @ $* >		$: <NO> $1 $2 $3 < @ $4>
164164562Sgshapirodnl no $=O in localpart: return
164242575SpeterR<?> $*				$@ $1
164338032Speter
164490792Sgshapirodnl workspace: <NO> localpart<@domain>, where localpart contains $=O
164564562Sgshapirodnl mark everything which has an "authorized" domain with <RELAY>
164638032Speterifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
164738032Speter# if we relay, check username portion for user%host so host can be checked also
164842575SpeterR<NO> $* < @ $* $=m >		$: <RELAY> $1 < @ $2 $3 >', `dnl')
164964562Sgshapirodnl workspace: <(NO|RELAY)> localpart<@domain>, where localpart contains $=O
165064562Sgshapirodnl if mark is <NO> then change it to <RELAY> if domain is "authorized"
165190792Sgshapiro
165290792Sgshapirodnl what if access map returns something else than RELAY?
165390792Sgshapirodnl we are only interested in RELAY entries...
165490792Sgshapirodnl other To: entries: blacklist recipient; generic entries?
165590792Sgshapirodnl if it is an error we probably do not want to relay anyway
165638032Speterifdef(`_RELAY_HOSTS_ONLY_',
165742575Speter`R<NO> $* < @ $=R >		$: <RELAY> $1 < @ $2 >
165864562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
165964562SgshapiroR<NO> $* < @ $+ >		$: <$(access To:$2 $: NO $)> $1 < @ $2 >
166042575SpeterR<NO> $* < @ $+ >		$: <$(access $2 $: NO $)> $1 < @ $2 >',`dnl')',
166142575Speter`R<NO> $* < @ $* $=R >		$: <RELAY> $1 < @ $2 $3 >
166264562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
166390792SgshapiroR<NO> $* < @ $+ >		$: $>D <$2> <NO> <+ To> <$1 < @ $2 >>
166442575SpeterR<$+> <$+>			$: <$1> $2',`dnl')')
166538032Speter
166664562Sgshapiro
166790792Sgshapiroifdef(`_RELAY_MX_SERVED_', `dnl
166890792Sgshapirodnl do "we" ($=w) act as backup MX server for the destination domain?
166990792SgshapiroR<NO> $* < @ $+ >		$: <MX> < : $(mxserved $2 $) : > < $1 < @$2 > >
167090792SgshapiroR<MX> < : $* <TEMP> : > $*	$#TEMP $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1
167190792Sgshapirodnl yes: mark it as <RELAY>
167290792SgshapiroR<MX> < $* : $=w. : $* > < $+ >	$: <RELAY> $4
167390792Sgshapirodnl no: put old <NO> mark back
167490792SgshapiroR<MX> < : $* : > < $+ >		$: <NO> $2', `dnl')
167590792Sgshapiro
167690792Sgshapirodnl do we relay to this recipient domain?
167742575SpeterR<RELAY> $* < @ $* >		$@ $>ParseRecipient $1
167890792Sgshapirodnl something else
167990792SgshapiroR<$+> $*			$@ $2
168042575Speter
168164562Sgshapiro
168238032Speter######################################################################
168338032Speter###  check_relay -- check hostname/address on SMTP startup
168438032Speter######################################################################
168538032Speter
168638032SpeterSLocal_check_relay
168764562SgshapiroScheck`'_U_`'relay
168838032SpeterR$*			$: $1 $| $>"Local_check_relay" $1
168938032SpeterR$* $| $* $| $#$*	$#$3
169038032SpeterR$* $| $* $| $*		$@ $>"Basic_check_relay" $1 $| $2
169138032Speter
169238032SpeterSBasic_check_relay
169338032Speter# check for deferred delivery mode
169498121SgshapiroR$*			$: < $&{deliveryMode} > $1
169538032SpeterR< d > $*		$@ deferred
169638032SpeterR< $* > $*		$: $2
169738032Speter
169864562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
169966494Sgshapirodnl workspace: {client_name} $| {client_addr}
170090792SgshapiroR$+ $| $+		$: $>D < $1 > <?> <+ Connect> < $2 >
170166494Sgshapirodnl workspace: <result-of-lookup> <{client_addr}>
1702110560Sgshapirodnl OR $| $+ if client_name is empty
1703110560SgshapiroR   $| $+		$: $>A < $1 > <?> <+ Connect> <>	empty client_name
1704110560Sgshapirodnl workspace: <result-of-lookup> <{client_addr}>
170590792SgshapiroR<?> <$+>		$: $>A < $1 > <?> <+ Connect> <>	no: another lookup
170690792Sgshapirodnl workspace: <result-of-lookup> (<>|<{client_addr}>)
170790792SgshapiroR<?> <$*>		$: OK				found nothing
170890792Sgshapirodnl workspace: <result-of-lookup> (<>|<{client_addr}>) | OK
170990792SgshapiroR<$={Accept}> <$*>	$@ $1				return value of lookup
171090792SgshapiroR<REJECT> <$*>		$#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"')
171190792SgshapiroR<DISCARD> <$*>		$#discard $: discard
171290792Sgshapiroifdef(`_FFR_QUARANTINE',
171390792Sgshapiro`R<QUARANTINE:$+> <$*>	$#error $@ quarantine $: $1', `dnl')
171464562Sgshapirodnl error tag
171566494SgshapiroR<ERROR:$-.$-.$-:$+> <$*>	$#error $@ $1.$2.$3 $: $4
171666494SgshapiroR<ERROR:$+> <$*>		$#error $: $1
171790792Sgshapiroifdef(`_ATMPF_', `R<$* _ATMPF_> <$*>		$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
171864562Sgshapirodnl generic error from access map
171966494SgshapiroR<$+> <$*>		$#error $: $1', `dnl')
172038032Speter
172164562Sgshapiroifdef(`_RBL_',`dnl
172264562Sgshapiro# DNS based IP address spam list
172390792Sgshapirodnl workspace: ignored...
172438032SpeterR$*			$: $&{client_addr}
172564562SgshapiroR$-.$-.$-.$-		$: <?> $(host $4.$3.$2.$1._RBL_. $: OK $)
172664562SgshapiroR<?>OK			$: OKSOFAR
172798121SgshapiroR<?>$+			$#error $@ 5.7.1 $: "550 Rejected: " $&{client_addr} " listed at _RBL_"',
172838032Speter`dnl')
172964562Sgshapiroundivert(8)
173038032Speter
173138032Speter######################################################################
173238032Speter###  check_mail -- check SMTP ``MAIL FROM:'' command argument
173338032Speter######################################################################
173438032Speter
173538032SpeterSLocal_check_mail
173664562SgshapiroScheck`'_U_`'mail
173738032SpeterR$*			$: $1 $| $>"Local_check_mail" $1
173838032SpeterR$* $| $#$*		$#$2
173938032SpeterR$* $| $*		$@ $>"Basic_check_mail" $1
174038032Speter
174138032SpeterSBasic_check_mail
174238032Speter# check for deferred delivery mode
174398121SgshapiroR$*			$: < $&{deliveryMode} > $1
174438032SpeterR< d > $*		$@ deferred
174538032SpeterR< $* > $*		$: $2
174638032Speter
174764562Sgshapiro# authenticated?
174864562Sgshapirodnl done first: we can require authentication for every mail transaction
174964562Sgshapirodnl workspace: address as given by MAIL FROM: (sender)
175064562SgshapiroR$*			$: $1 $| $>"tls_client" $&{verify} $| MAIL
175164562SgshapiroR$* $| $#$+		$#$2
175264562Sgshapirodnl undo damage: remove result of tls_client call
175364562SgshapiroR$* $| $*		$: $1
175438032Speter
175564562Sgshapirodnl workspace: address as given by MAIL FROM:
175664562SgshapiroR<>			$@ <OK>			we MUST accept <> (RFC 1123)
175738032Speterifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl
175864562Sgshapirodnl do some additional checks
175964562Sgshapirodnl no user@host
176064562Sgshapirodnl no user@localhost (if nonlocal sender)
176164562Sgshapirodnl this is a pretty simple canonification, it will not catch every case
176264562Sgshapirodnl just make sure the address has <> around it (which is required by
176364562Sgshapirodnl the RFC anyway, maybe we should complain if they are missing...)
176464562Sgshapirodnl dirty trick: if it is user@host, just add a dot: user@host. this will
176564562Sgshapirodnl not be modified by host lookups.
176664562SgshapiroR$+			$: <?> $1
176764562SgshapiroR<?><$+>		$: <@> <$1>
176864562SgshapiroR<?>$+			$: <@> <$1>
176964562Sgshapirodnl workspace: <@> <address>
177064562Sgshapirodnl prepend daemon_flags
177164562SgshapiroR$*			$: $&{daemon_flags} $| $1
177264562Sgshapirodnl workspace: ${daemon_flags} $| <@> <address>
177364562Sgshapirodnl do not allow these at all or only from local systems?
177464562SgshapiroR$* f $* $| <@> < $* @ $- >	$: < ? $&{client_name} > < $3 @ $4 >
177564562Sgshapirodnl accept unqualified sender: change mark to avoid test
177664562SgshapiroR$* u $* $| <@> < $* >	$: <?> < $3 >
177764562Sgshapirodnl workspace: ${daemon_flags} $| <@> <address>
177864562Sgshapirodnl        or:                    <? ${client_name} > <address>
177964562Sgshapirodnl        or:                    <?> <address>
178064562Sgshapirodnl remove daemon_flags
178164562SgshapiroR$* $| $*		$: $2
178238032Speter# handle case of @localhost on address
178364562SgshapiroR<@> < $* @ localhost >	$: < ? $&{client_name} > < $1 @ localhost >
178464562SgshapiroR<@> < $* @ [127.0.0.1] >
178564562Sgshapiro			$: < ? $&{client_name} > < $1 @ [127.0.0.1] >
178664562SgshapiroR<@> < $* @ localhost.$m >
178764562Sgshapiro			$: < ? $&{client_name} > < $1 @ localhost.$m >
178838032Speterifdef(`_NO_UUCP_', `dnl',
178964562Sgshapiro`R<@> < $* @ localhost.UUCP >
179064562Sgshapiro			$: < ? $&{client_name} > < $1 @ localhost.UUCP >')
179164562Sgshapirodnl workspace: < ? $&{client_name} > <user@localhost|host>
179264562Sgshapirodnl	or:    <@> <address>
179364562Sgshapirodnl	or:    <?> <address>	(thanks to u in ${daemon_flags})
179464562SgshapiroR<@> $*			$: $1			no localhost as domain
179564562Sgshapirodnl workspace: < ? $&{client_name} > <user@localhost|host>
179664562Sgshapirodnl	or:    <address>
179764562Sgshapirodnl	or:    <?> <address>	(thanks to u in ${daemon_flags})
179864562SgshapiroR<? $=w> $*		$: $2			local client: ok
179990792SgshapiroR<? $+> <$+>		$#error $@ 5.5.4 $: "_CODE553 Real domain name required for sender address"
180064562Sgshapirodnl remove <?> (happens only if ${client_name} == "" or u in ${daemon_flags})
180164562SgshapiroR<?> $*			$: $1')
180264562Sgshapirodnl workspace: address (or <address>)
180364562SgshapiroR$*			$: <?> $>CanonAddr $1		canonify sender address and mark it
180464562Sgshapirodnl workspace: <?> CanonicalAddress (i.e. address in canonical form localpart<@host>)
180564562Sgshapirodnl there is nothing behind the <@host> so no trailing $* needed
180664562SgshapiroR<?> $* < @ $+ . >	<?> $1 < @ $2 >			strip trailing dots
180764562Sgshapiro# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc)
1808102528SgshapiroR<?> $* < @ $* $=P >	$: <_RES_OK_> $1 < @ $2 $3 >
180964562Sgshapirodnl workspace <mark> CanonicalAddress	where mark is ? or OK
181098121Sgshapirodnl A sender address with my local host name ($j) is safe
1811102528SgshapiroR<?> $* < @ $j >	$: <_RES_OK_> $1 < @ $j >
181264562Sgshapiroifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',
181390792Sgshapiro`R<?> $* < @ $+ >	$: <_RES_OK_> $1 < @ $2 >		... unresolvable OK',
181464562Sgshapiro`R<?> $* < @ $+ >	$: <? $(resolve $2 $: $2 <PERM> $) > $1 < @ $2 >
181564562SgshapiroR<? $* <$->> $* < @ $+ >
181664562Sgshapiro			$: <$2> $3 < @ $4 >')
181790792Sgshapirodnl workspace <mark> CanonicalAddress	where mark is ?, _RES_OK_, PERM, TEMP
181864562Sgshapirodnl mark is ? iff the address is user (wo @domain)
181938032Speter
182064562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
182164562Sgshapiro# check sender address: user@address, user@, address
182264562Sgshapirodnl should we remove +ext from user?
182390792Sgshapirodnl workspace: <mark> CanonicalAddress where mark is: ?, _RES_OK_, PERM, TEMP
182490792SgshapiroR<$+> $+ < @ $* >	$: @<$1> <$2 < @ $3 >> $| <F:$2@$3> <U:$2@> <D:$3>
182564562SgshapiroR<$+> $+		$: @<$1> <$2> $| <U:$2@>
182664562Sgshapirodnl workspace: @<mark> <CanonicalAddress> $| <@type:address> ....
182764562Sgshapirodnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>>
182864562Sgshapirodnl will only return user<@domain when "reversing" the args
182990792SgshapiroR@ <$+> <$*> $| <$+>	$: <@> <$1> <$2> $| $>SearchList <+ From> $| <$3> <>
183064562Sgshapirodnl workspace: <@><mark> <CanonicalAddress> $| <result>
183164562SgshapiroR<@> <$+> <$*> $| <$*>	$: <$3> <$1> <$2>		reverse result
183264562Sgshapirodnl workspace: <result> <mark> <CanonicalAddress>
183338032Speter# retransform for further use
183464562Sgshapirodnl required form:
183564562Sgshapirodnl <ResultOfLookup|mark> CanonicalAddress
183664562SgshapiroR<?> <$+> <$*>		$: <$1> $2	no match
183764562SgshapiroR<$+> <$+> <$*>		$: <$1> $3	relevant result, keep it', `dnl')
183864562Sgshapirodnl workspace <ResultOfLookup|mark> CanonicalAddress
183964562Sgshapirodnl mark is ? iff the address is user (wo @domain)
184038032Speter
184138032Speterifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl
184238032Speter# handle case of no @domain on address
184364562Sgshapirodnl prepend daemon_flags
184464562SgshapiroR<?> $*			$: $&{daemon_flags} $| <?> $1
184564562Sgshapirodnl accept unqualified sender: change mark to avoid test
184690792SgshapiroR$* u $* $| <?> $*	$: <_RES_OK_> $3
184764562Sgshapirodnl remove daemon_flags
184864562SgshapiroR$* $| $*		$: $2
1849110560SgshapiroR<?> $*			$: < ? $&{client_addr} > $1
1850102528SgshapiroR<?> $*			$@ <_RES_OK_>			...local unqualed ok
185190792SgshapiroR<? $+> $*		$#error $@ 5.5.4 $: "_CODE553 Domain name required for sender address " $&f
185238032Speter							...remote is not')
185338032Speter# check results
185464562SgshapiroR<?> $*			$: @ $1		mark address: nothing known about it
185590792SgshapiroR<$={ResOk}> $*		$@ <_RES_OK_>	domain ok: stop
185664562SgshapiroR<TEMP> $*		$#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve"
185790792SgshapiroR<PERM> $*		$#error $@ 5.1.8 $: "_CODE553 Domain of sender address " $&f " does not exist"
185864562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
185990792SgshapiroR<$={Accept}> $*	$# $1		accept from access map
186038032SpeterR<DISCARD> $*		$#discard $: discard
186190792Sgshapiroifdef(`_FFR_QUARANTINE',
186290792Sgshapiro`R<QUARANTINE:$+> $*	$#error $@ quarantine $: $1', `dnl')
186364562SgshapiroR<REJECT> $*		$#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"')
186464562Sgshapirodnl error tag
186564562SgshapiroR<ERROR:$-.$-.$-:$+> $*		$#error $@ $1.$2.$3 $: $4
186664562SgshapiroR<ERROR:$+> $*		$#error $: $1
186790792Sgshapiroifdef(`_ATMPF_', `R<_ATMPF_> $*		$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
186864562Sgshapirodnl generic error from access map
186964562SgshapiroR<$+> $*		$#error $: $1		error from access db',
187038032Speter`dnl')
187138032Speter
187238032Speter######################################################################
187338032Speter###  check_rcpt -- check SMTP ``RCPT TO:'' command argument
187438032Speter######################################################################
187538032Speter
187638032SpeterSLocal_check_rcpt
187764562SgshapiroScheck`'_U_`'rcpt
187838032SpeterR$*			$: $1 $| $>"Local_check_rcpt" $1
187938032SpeterR$* $| $#$*		$#$2
188038032SpeterR$* $| $*		$@ $>"Basic_check_rcpt" $1
188138032Speter
188238032SpeterSBasic_check_rcpt
188390792Sgshapiro# empty address?
188490792SgshapiroR<>			$#error $@ nouser $: "553 User address required"
188590792SgshapiroR$@			$#error $@ nouser $: "553 User address required"
188638032Speter# check for deferred delivery mode
188798121SgshapiroR$*			$: < $&{deliveryMode} > $1
188838032SpeterR< d > $*		$@ deferred
188938032SpeterR< $* > $*		$: $2
189038032Speter
189164562Sgshapiroifdef(`_REQUIRE_QUAL_RCPT_', `dnl
189290792Sgshapirodnl this code checks for user@host where host is not a FQHN.
189390792Sgshapirodnl it is not activated.
189490792Sgshapirodnl notice: code to check for a recipient without a domain name is
189590792Sgshapirodnl available down below; look for the same macro.
189690792Sgshapirodnl this check is done here because the name might be qualified by the
189790792Sgshapirodnl canonicalization.
189890792Sgshapiro# require fully qualified domain part?
189990792Sgshapirodnl very simple canonification: make sure the address is in < >
190064562SgshapiroR$+			$: <?> $1
190190792SgshapiroR<?> <$+>		$: <@> <$1>
190290792SgshapiroR<?> $+			$: <@> <$1>
190390792SgshapiroR<@> < postmaster >	$: postmaster
1904110560SgshapiroR<@> < $* @ $+ . $+ >	$: < $1 @ $2 . $3 >
190564562Sgshapirodnl prepend daemon_flags
190690792SgshapiroR<@> $*			$: $&{daemon_flags} $| <@> $1
190764562Sgshapirodnl workspace: ${daemon_flags} $| <@> <address>
190864562Sgshapirodnl do not allow these at all or only from local systems?
190990792SgshapiroR$* r $* $| <@> < $* @ $* >	$: < ? $&{client_name} > < $3 @ $4 >
191064562SgshapiroR<?> < $* >		$: <$1>
191164562SgshapiroR<? $=w> < $* >		$: <$1>
191290792SgshapiroR<? $+> <$+>		$#error $@ 5.5.4 $: "553 Fully qualified domain name required"
191364562Sgshapirodnl remove daemon_flags for other cases
191464562SgshapiroR$* $| <@> $*		$: $2', `dnl')
191564562Sgshapiro
191690792Sgshapirodnl ##################################################################
191790792Sgshapirodnl call subroutines for recipient and relay
191890792Sgshapirodnl possible returns from subroutines:
191990792Sgshapirodnl $#TEMP	temporary failure
192090792Sgshapirodnl $#error	permanent failure (or temporary if from access map)
192190792Sgshapirodnl $#other	stop processing
192290792Sgshapirodnl RELAY	RELAYing allowed
192390792Sgshapirodnl other	otherwise
192490792Sgshapiro######################################################################
192590792SgshapiroR$*			$: $1 $| @ $>"Rcpt_ok" $1
192690792Sgshapirodnl temporary failure? remove mark @ and remember
192790792SgshapiroR$* $| @ $#TEMP $+	$: $1 $| T $2
192890792Sgshapirodnl error or ok (stop)
192990792SgshapiroR$* $| @ $#$*		$#$2
193090792Sgshapiroifdef(`_PROMISCUOUS_RELAY_', `divert(-1)', `dnl')
193190792SgshapiroR$* $| @ RELAY		$@ RELAY
193290792Sgshapirodnl something else: call check sender (relay)
193390792SgshapiroR$* $| @ $*		$: O $| $>"Relay_ok" $1
193490792Sgshapirodnl temporary failure: call check sender (relay)
193590792SgshapiroR$* $| T $+		$: T $2 $| $>"Relay_ok" $1
193690792Sgshapirodnl temporary failure? return that
193790792SgshapiroR$* $| $#TEMP $+	$#error $2
193890792Sgshapirodnl error or ok (stop)
193990792SgshapiroR$* $| $#$*		$#$2
194090792SgshapiroR$* $| RELAY		$@ RELAY
194190792Sgshapirodnl something else: return previous temp failure
194290792SgshapiroR T $+ $| $*		$#error $1
194390792Sgshapiro# anything else is bogus
194490792SgshapiroR$*			$#error $@ 5.7.1 $: confRELAY_MSG
194590792Sgshapirodivert(0)
194690792Sgshapiro
194790792Sgshapiro######################################################################
194890792Sgshapiro### Rcpt_ok: is the recipient ok?
194990792Sgshapirodnl input: recipient address (RCPT TO)
195090792Sgshapirodnl output: see explanation at call
195190792Sgshapiro######################################################################
195290792SgshapiroSRcpt_ok
195338032Speterifdef(`_LOOSE_RELAY_CHECK_',`dnl
195442575SpeterR$*			$: $>CanonAddr $1
195538032SpeterR$* < @ $* . >		$1 < @ $2 >			strip trailing dots',
195638032Speter`R$*			$: $>ParseRecipient $1		strip relayable hosts')
195738032Speter
195842575Speterifdef(`_BESTMX_IS_LOCAL_',`dnl
195942575Speterifelse(_BESTMX_IS_LOCAL_, `', `dnl
196042575Speter# unlimited bestmx
196142575SpeterR$* < @ $* > $*			$: $1 < @ $2 @@ $(bestmx $2 $) > $3',
196242575Speter`dnl
196342575Speter# limit bestmx to $=B
196443730SpeterR$* < @ $* $=B > $*		$: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4')
196590792SgshapiroR$* $=O $* < @ $* @@ $=w . > $*	$@ $>"Rcpt_ok" $1 $2 $3
196642575SpeterR$* < @ $* @@ $=w . > $*	$: $1 < @ $3 > $4
196742575SpeterR$* < @ $* @@ $* > $*		$: $1 < @ $2 > $4')
196842575Speter
196938032Speterifdef(`_BLACKLIST_RCPT_',`dnl
197064562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
197138032Speter# blacklist local users or any host from receiving mail
197238032SpeterR$*			$: <?> $1
197364562Sgshapirodnl user is now tagged with @ to be consistent with check_mail
197464562Sgshapirodnl and to distinguish users from hosts (com would be host, com@ would be user)
197590792SgshapiroR<?> $+ < @ $=w >	$: <> <$1 < @ $2 >> $| <F:$1@$2> <U:$1@> <D:$2>
197690792SgshapiroR<?> $+ < @ $* >	$: <> <$1 < @ $2 >> $| <F:$1@$2> <D:$2>
197764562SgshapiroR<?> $+			$: <> <$1> $| <U:$1@>
197864562Sgshapirodnl $| is used as delimiter, otherwise false matches may occur: <user<@domain>>
197964562Sgshapirodnl will only return user<@domain when "reversing" the args
198090792SgshapiroR<> <$*> $| <$+>	$: <@> <$1> $| $>SearchList <+ To> $| <$2> <>
198164562SgshapiroR<@> <$*> $| <$*>	$: <$2> <$1>		reverse result
198264562SgshapiroR<?> <$*>		$: @ $1		mark address as no match
198390792Sgshapirodnl we may have to filter here because otherwise some RHSs
198490792Sgshapirodnl would be interpreted as generic error messages...
198590792Sgshapirodnl error messages should be "tagged" by prefixing them with error: !
198690792Sgshapirodnl that would make a lot of things easier.
198764562SgshapiroR<$={Accept}> <$*>	$: @ $2		mark address as no match
198890792Sgshapiroifdef(`_ACCESS_SKIP_', `dnl
198990792SgshapiroR<SKIP> <$*>		$: @ $1		mark address as no match', `dnl')
199090792Sgshapiroifdef(`_DELAY_COMPAT_8_10_',`dnl
199190792Sgshapirodnl compatility with 8.11/8.10:
199264562Sgshapirodnl we have to filter these because otherwise they would be interpreted
199364562Sgshapirodnl as generic error message...
199464562Sgshapirodnl error messages should be "tagged" by prefixing them with error: !
199564562Sgshapirodnl that would make a lot of things easier.
199664562Sgshapirodnl maybe we should stop checks already here (if SPAM_xyx)?
199764562SgshapiroR<$={SpamTag}> <$*>	$: @ $2		mark address as no match')
199890792SgshapiroR<REJECT> $*		$#error $@ 5.2.1 $: confRCPTREJ_MSG
199964562SgshapiroR<DISCARD> $*		$#discard $: discard
200090792Sgshapiroifdef(`_FFR_QUARANTINE',
200190792Sgshapiro`R<QUARANTINE:$+> $*	$#error $@ quarantine $: $1', `dnl')
200264562Sgshapirodnl error tag
200364562SgshapiroR<ERROR:$-.$-.$-:$+> $*		$#error $@ $1.$2.$3 $: $4
200464562SgshapiroR<ERROR:$+> $*		$#error $: $1
200590792Sgshapiroifdef(`_ATMPF_', `R<_ATMPF_> $*		$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
200664562Sgshapirodnl generic error from access map
200764562SgshapiroR<$+> $*		$#error $: $1		error from access db
200864562SgshapiroR@ $*			$1		remove mark', `dnl')', `dnl')
200938032Speter
201090792Sgshapiroifdef(`_PROMISCUOUS_RELAY_', `divert(-1)', `dnl')
201190792Sgshapiro# authenticated via TLS?
201290792SgshapiroR$*			$: $1 $| $>RelayTLS	client authenticated?
201390792SgshapiroR$* $| $# $+		$# $2			error/ok?
201490792SgshapiroR$* $| $*		$: $1			no
201564562Sgshapiro
201690792SgshapiroR$*			$: $1 $| $>"Local_Relay_Auth" $&{auth_type}
201790792Sgshapirodnl workspace: localpart<@domain> $| result of Local_Relay_Auth
201890792SgshapiroR$* $| $# $*		$# $2
201990792Sgshapirodnl if Local_Relay_Auth returns NO then do not check $={TrustAuthMech}
202090792SgshapiroR$* $| NO		$: $1
202190792SgshapiroR$* $| $*		$: $1 $| $&{auth_type}
202290792Sgshapirodnl workspace: localpart<@domain> [ $| ${auth_type} ]
202364562Sgshapirodnl empty ${auth_type}?
202464562SgshapiroR$* $|			$: $1
202564562Sgshapirodnl mechanism ${auth_type} accepted?
202664562Sgshapirodnl use $# to override further tests (delay_checks): see check_rcpt below
202790792SgshapiroR$* $| $={TrustAuthMech}	$# RELAY
202890792Sgshapirodnl remove ${auth_type}
202964562SgshapiroR$* $| $*		$: $1
203071345Sgshapirodnl workspace: localpart<@domain> | localpart
203164562Sgshapiroifelse(defn(`_NO_UUCP_'), `r',
203271345Sgshapiro`R$* ! $* < @ $* >	$: <REMOTE> $2 < @ BANG_PATH >
203371345SgshapiroR$* ! $* 		$: <REMOTE> $2 < @ BANG_PATH >', `dnl')
203438032Speter# anything terminating locally is ok
203538032Speterifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
203690792SgshapiroR$+ < @ $* $=m >	$@ RELAY', `dnl')
203790792SgshapiroR$+ < @ $=w >		$@ RELAY
203838032Speterifdef(`_RELAY_HOSTS_ONLY_',
203990792Sgshapiro`R$+ < @ $=R >		$@ RELAY
204064562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
204164562SgshapiroR$+ < @ $+ >		$: <$(access To:$2 $: ? $)> <$1 < @ $2 >>
204264562Sgshapirodnl workspace: <Result-of-lookup | ?> <localpart<@domain>>
204364562SgshapiroR<?> <$+ < @ $+ >>	$: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')',
204490792Sgshapiro`R$+ < @ $* $=R >	$@ RELAY
204564562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
204690792SgshapiroR$+ < @ $+ >		$: $>D <$2> <?> <+ To> <$1 < @ $2 >>',`dnl')')
204764562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
204864562Sgshapirodnl workspace: <Result-of-lookup | ?> <localpart<@domain>>
204990792SgshapiroR<RELAY> $*		$@ RELAY
205090792Sgshapiroifdef(`_ATMPF_', `R<$* _ATMPF_> $*		$#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
205138032SpeterR<$*> <$*>		$: $2',`dnl')
205238032Speter
205364562Sgshapiro
205438032Speterifdef(`_RELAY_MX_SERVED_', `dnl
205538032Speter# allow relaying for hosts which we MX serve
205664562SgshapiroR$+ < @ $+ >		$: < : $(mxserved $2 $) : > $1 < @ $2 >
205764562Sgshapirodnl this must not necessarily happen if the client is checked first...
205890792SgshapiroR< : $* <TEMP> : > $*	$#TEMP $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1
205990792SgshapiroR<$* : $=w . : $*> $*	$@ RELAY
206042575SpeterR< : $* : > $*		$: $2',
206138032Speter`dnl')
206238032Speter
206338032Speter# check for local user (i.e. unqualified address)
206438032SpeterR$*			$: <?> $1
206542575SpeterR<?> $* < @ $+ >	$: <REMOTE> $1 < @ $2 >
206638032Speter# local user is ok
206764562Sgshapirodnl is it really? the standard requires user@domain, not just user
206864562Sgshapirodnl but we should accept it anyway (maybe making it an option:
206964562Sgshapirodnl RequireFQDN ?)
207064562Sgshapirodnl postmaster must be accepted without domain (DRUMS)
207164562Sgshapiroifdef(`_REQUIRE_QUAL_RCPT_', `dnl
207290792SgshapiroR<?> postmaster		$@ OK
207364562Sgshapiro# require qualified recipient?
207464562Sgshapirodnl prepend daemon_flags
207564562SgshapiroR<?> $+			$: $&{daemon_flags} $| <?> $1
207664562Sgshapirodnl workspace: ${daemon_flags} $| <?> localpart
207764562Sgshapirodnl do not allow these at all or only from local systems?
207864562Sgshapirodnl r flag? add client_name
207964562SgshapiroR$* r $* $| <?> $+	$: < ? $&{client_name} > <?> $3
208064562Sgshapirodnl no r flag: relay to local user (only local part)
208164562Sgshapiro# no qualified recipient required
208290792SgshapiroR$* $| <?> $+		$@ RELAY
208364562Sgshapirodnl client_name is empty
208490792SgshapiroR<?> <?> $+		$@ RELAY
208564562Sgshapirodnl client_name is local
208690792SgshapiroR<? $=w> <?> $+		$@ RELAY
208764562Sgshapirodnl client_name is not local
208864562SgshapiroR<? $+> $+		$#error $@ 5.5.4 $: "553 Domain name required"', `dnl
208964562Sgshapirodnl no qualified recipient required
209090792SgshapiroR<?> $+			$@ RELAY')
209164562Sgshapirodnl it is a remote user: remove mark and then check client
209238032SpeterR<$+> $*		$: $2
209364562Sgshapirodnl currently the recipient address is not used below
209438032Speter
209590792Sgshapiro######################################################################
209690792Sgshapiro### Relay_ok: is the relay/sender ok?
209790792Sgshapirodnl input: ignored
209890792Sgshapirodnl output: see explanation at call
209990792Sgshapiro######################################################################
210090792SgshapiroSRelay_ok
210138032Speter# anything originating locally is ok
210264562Sgshapiro# check IP address
210364562SgshapiroR$*			$: $&{client_addr}
210490792SgshapiroR$@			$@ RELAY		originated locally
210590792SgshapiroR0			$@ RELAY		originated locally
2106110560SgshapiroR127.0.0.1		$@ RELAY		originated locally
2107110560SgshapiroRIPv6:::1		$@ RELAY		originated locally
210890792SgshapiroR$=R $*			$@ RELAY		relayable IP address
210964562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
211090792SgshapiroR$*			$: $>A <$1> <?> <+ Connect> <$1>
211190792SgshapiroR<RELAY> $* 		$@ RELAY		relayable IP address
2112102528Sgshapiroifdef(`_FFR_REJECT_IP_IN_CHECK_RCPT_',`dnl
2113102528Sgshapirodnl this will cause rejections in cases like:
2114102528Sgshapirodnl Connect:My.Host.Domain	RELAY
2115102528Sgshapirodnl Connect:My.Net		REJECT
2116102528Sgshapirodnl since in check_relay client_name is checked before client_addr
2117102528SgshapiroR<REJECT> $* 		$@ REJECT		rejected IP address')
211890792Sgshapiroifdef(`_ATMPF_', `R<_ATMPF_> $*		$#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
211964562SgshapiroR<$*> <$*>		$: $2', `dnl')
212064562SgshapiroR$*			$: [ $1 ]		put brackets around it...
212190792SgshapiroR$=w			$@ RELAY		... and see if it is local
212264562Sgshapiro
212364562Sgshapiroifdef(`_RELAY_DB_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl
212464562Sgshapiroifdef(`_RELAY_LOCAL_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl
212564562Sgshapiroifdef(`_RELAY_MAIL_FROM_', `dnl
212664562Sgshapirodnl input: {client_addr} or something "broken"
212764562Sgshapirodnl just throw the input away; we do not need it.
212864562Sgshapiro# check whether FROM is allowed to use system as relay
212964562SgshapiroR$*			$: <?> $>CanonAddr $&f
213090792SgshapiroR<?> $+ < @ $+ . >	<?> $1 < @ $2 >		remove trailing dot
213164562Sgshapiroifdef(`_RELAY_LOCAL_FROM_', `dnl
213264562Sgshapiro# check whether local FROM is ok
213390792SgshapiroR<?> $+ < @ $=w >	$@ RELAY		FROM local', `dnl')
213464562Sgshapiroifdef(`_RELAY_DB_FROM_', `dnl
213594334SgshapiroR<?> $+ < @ $+ >	$: <@> $>SearchList <! From> $| <F:$1@$2> ifdef(`_RELAY_DB_FROM_DOMAIN_', ifdef(`_RELAY_HOSTS_ONLY_', `<E:$2>', `<D:$2>')) <>
213690792SgshapiroR<@> <RELAY>		$@ RELAY		RELAY FROM sender ok
213790792Sgshapiroifdef(`_ATMPF_', `R<@> <_ATMPF_>		$#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
213890792Sgshapiro', `dnl
213990792Sgshapiroifdef(`_RELAY_DB_FROM_DOMAIN_',
214090792Sgshapiro`errprint(`*** ERROR: _RELAY_DB_FROM_DOMAIN_ requires _RELAY_DB_FROM_
214164562Sgshapiro')',
214264562Sgshapiro`dnl')
214364562Sgshapirodnl')', `dnl')
214490792Sgshapirodnl notice: the rulesets above do not leave a unique workspace behind.
214590792Sgshapirodnl it does not matter in this case because the following rule ignores
214690792Sgshapirodnl the input. otherwise these rules must "clean up" the workspace.
214764562Sgshapiro
214864562Sgshapiro# check client name: first: did it resolve?
214964562Sgshapirodnl input: ignored
215064562SgshapiroR$*			$: < $&{client_resolve} >
215190792SgshapiroR<TEMP>			$#TEMP $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr}
215264562SgshapiroR<FORGED>		$#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name}
215364562SgshapiroR<FAIL>			$#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name}
215464562Sgshapirodnl ${client_resolve} should be OK, so go ahead
215590792SgshapiroR$*			$: <@> $&{client_name}
215690792Sgshapirodnl should not be necessary since it has been done for client_addr already
2157110560Sgshapirodnl this rule actually may cause a problem if {client_name} resolves to ""
2158110560Sgshapirodnl however, this should not happen since the forward lookup should fail
2159110560Sgshapirodnl and {client_resolve} should be TEMP or FAIL.
2160110560Sgshapirodnl nevertheless, removing the rule doesn't hurt.
2161110560Sgshapirodnl R<@>			$@ RELAY
216290792Sgshapirodnl workspace: <@> ${client_name} (not empty)
216338032Speter# pass to name server to make hostname canonical
216490792SgshapiroR<@> $* $=P 		$:<?>  $1 $2
216590792SgshapiroR<@> $+			$:<?>  $[ $1 $]
216690792Sgshapirodnl workspace: <?> ${client_name} (canonified)
216764562SgshapiroR$* .			$1			strip trailing dots
216838032Speterifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
216990792SgshapiroR<?> $* $=m		$@ RELAY', `dnl')
217090792SgshapiroR<?> $=w		$@ RELAY
217138032Speterifdef(`_RELAY_HOSTS_ONLY_',
217290792Sgshapiro`R<?> $=R		$@ RELAY
217364562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
217464562SgshapiroR<?> $*			$: <$(access Connect:$1 $: ? $)> <$1>
217564562SgshapiroR<?> <$*>		$: <$(access $1 $: ? $)> <$1>',`dnl')',
217690792Sgshapiro`R<?> $* $=R			$@ RELAY
217764562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
217890792SgshapiroR<?> $*			$: $>D <$1> <?> <+ Connect> <$1>',`dnl')')
217964562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
218090792SgshapiroR<RELAY> $*		$@ RELAY
218190792Sgshapiroifdef(`_ATMPF_', `R<$* _ATMPF_> $*		$#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
218238032SpeterR<$*> <$*>		$: $2',`dnl')
218390792Sgshapirodnl end of _PROMISCUOUS_RELAY_
218464562Sgshapirodivert(0)
218564562Sgshapiroifdef(`_DELAY_CHECKS_',`dnl
218664562Sgshapiro# turn a canonical address in the form user<@domain>
218764562Sgshapiro# qualify unqual. addresses with $j
218864562Sgshapirodnl it might have been only user (without <@domain>)
218964562SgshapiroSFullAddr
219064562SgshapiroR$* <@ $+ . >		$1 <@ $2 >
219164562SgshapiroR$* <@ $* >		$@ $1 <@ $2 >
219264562SgshapiroR$+			$@ $1 <@ $j >
219338032Speter
2194110560SgshapiroSDelay_TLS_Client
2195110560Sgshapiro# authenticated?
2196110560Sgshapirodnl code repeated here from Basic_check_mail
2197110560Sgshapirodnl only called from check_rcpt in delay mode if checkrcpt returns $#
2198110560SgshapiroR$*			$: $1 $| $>"tls_client" $&{verify} $| MAIL
2199110560SgshapiroR$* $| $#$+		$#$2
2200110560Sgshapirodnl return result from checkrcpt
2201110560SgshapiroR$*			$# $1
2202110560Sgshapiro
2203110560SgshapiroSDelay_TLS_Client2
2204110560Sgshapiro# authenticated?
2205110560Sgshapirodnl code repeated here from Basic_check_mail
2206110560Sgshapirodnl only called from check_rcpt in delay mode if stopping due to Friend/Hater
2207110560SgshapiroR$*			$: $1 $| $>"tls_client" $&{verify} $| MAIL
2208110560SgshapiroR$* $| $#$+		$#$2
2209110560Sgshapirodnl return result from friend/hater check
2210110560SgshapiroR$*			$@ $1
2211110560Sgshapiro
221264562Sgshapiro# call all necessary rulesets
221364562SgshapiroScheck_rcpt
221464562Sgshapirodnl this test should be in the Basic_check_rcpt ruleset
221564562Sgshapirodnl which is the correct DSN code?
221664562Sgshapiro# R$@			$#error $@ 5.1.3 $: "553 Recipient address required"
2217110560Sgshapiro
221864562SgshapiroR$+			$: $1 $| $>checkrcpt $1
221964562Sgshapirodnl now we can simply stop checks by returning "$# xyz" instead of just "ok"
2220110560Sgshapirodnl on error (or discard) stop now
2221110560SgshapiroR$+ $| $#error $*	$#error $2
2222110560SgshapiroR$+ $| $#discard $*	$#discard $2
2223110560Sgshapirodnl otherwise call tls_client; see above
2224110560SgshapiroR$+ $| $#$*		$@ $>"Delay_TLS_Client" $2
222564562SgshapiroR$+ $| $*		$: <?> $>FullAddr $>CanonAddr $1
222664562Sgshapiroifdef(`_SPAM_FH_',
222764562Sgshapiro`dnl lookup user@ and user@address
222864562Sgshapiroifdef(`_ACCESS_TABLE_', `',
222964562Sgshapiro`errprint(`*** ERROR: FEATURE(`delay_checks', `argument') requires FEATURE(`access_db')
223064562Sgshapiro')')dnl
223164562Sgshapirodnl one of the next two rules is supposed to match
223264562Sgshapirodnl this code has been copied from BLACKLIST... etc
223364562Sgshapirodnl and simplified by omitting some < >.
223490792SgshapiroR<?> $+ < @ $=w >	$: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 > <U: $1@>
223590792SgshapiroR<?> $+ < @ $* >	$: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 >
223664562Sgshapirodnl R<?>		$@ something_is_very_wrong_here
223790792Sgshapiro# lookup the addresses only with Spam tag
223890792SgshapiroR<> $* $| <$+>		$: <@> $1 $| $>SearchList <! Spam> $| <$2> <>
223964562SgshapiroR<@> $* $| $*		$: $2 $1		reverse result
224064562Sgshapirodnl', `dnl')
224164562Sgshapiroifdef(`_SPAM_FRIEND_',
224264562Sgshapiro`# is the recipient a spam friend?
224364562Sgshapiroifdef(`_SPAM_HATER_',
2244110560Sgshapiro	`errprint(`*** ERROR: define either Hater or Friend -- not both.
224564562Sgshapiro')', `dnl')
2246110560SgshapiroR<FRIEND> $+		$@ $>"Delay_TLS_Client2" SPAMFRIEND
224764562SgshapiroR<$*> $+		$: $2',
224864562Sgshapiro`dnl')
224964562Sgshapiroifdef(`_SPAM_HATER_',
225064562Sgshapiro`# is the recipient no spam hater?
225190792SgshapiroR<HATER> $+		$: $1			spam hater: continue checks
2252110560SgshapiroR<$*> $+		$@ $>"Delay_TLS_Client2" NOSPAMHATER	everyone else: stop
225364562Sgshapirodnl',`dnl')
225464562Sgshapirodnl run further checks: check_mail
225564562Sgshapirodnl should we "clean up" $&f?
225690792Sgshapiroifdef(`_FFR_MAIL_MACRO',
225790792Sgshapiro`R$*			$: $1 $| $>checkmail $&{mail_from}',
225890792Sgshapiro`R$*			$: $1 $| $>checkmail <$&f>')
225994334Sgshapirodnl recipient (canonical format) $| result of checkmail
226064562SgshapiroR$* $| $#$*		$#$2
226164562Sgshapirodnl run further checks: check_relay
226294334SgshapiroR$* $| $*		$: $1 $| $>checkrelay $&{client_name} $| $&{client_addr}
226364562SgshapiroR$* $| $#$*		$#$2
226438032SpeterR$* $| $*		$: $1
226538032Speter', `dnl')
226690792Sgshapiro
226790792Sgshapiroifdef(`_ACCESS_TABLE_', `dnl', `divert(-1)')
226864562Sgshapiro######################################################################
226990792Sgshapiro###  F: LookUpFull -- search for an entry in access database
227090792Sgshapiro###
227190792Sgshapiro###	lookup of full key (which should be an address) and
227290792Sgshapiro###	variations if +detail exists: +* and without +detail
227390792Sgshapiro###
227490792Sgshapiro###	Parameters:
227590792Sgshapiro###		<$1> -- key
227690792Sgshapiro###		<$2> -- default (what to return if not found in db)
227790792Sgshapirodnl			must not be empty
227890792Sgshapiro###		<$3> -- mark (must be <(!|+) single-token>)
227990792Sgshapiro###			! does lookup only with tag
228090792Sgshapiro###			+ does lookup with and without tag
228190792Sgshapiro###		<$4> -- passthru (additional data passed unchanged through)
228290792Sgshapirodnl returns:		<default> <passthru>
228390792Sgshapirodnl 			<result> <passthru>
228490792Sgshapiro######################################################################
228590792Sgshapiro
228690792SgshapiroSF
228790792Sgshapirodnl workspace: <key> <def> <o tag> <thru>
228890792Sgshapirodnl full lookup
228990792Sgshapirodnl    2    3  4    5
229090792SgshapiroR<$+> <$*> <$- $-> <$*>		$: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5>
229190792Sgshapirodnl no match, try without tag
229290792Sgshapirodnl   1    2      3    4
229390792SgshapiroR<?> <$+> <$*> <+ $-> <$*>	$: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4>
229490792Sgshapirodnl no match, +detail: try +*
229590792Sgshapirodnl   1    2    3    4    5  6    7
229690792SgshapiroR<?> <$+ + $* @ $+> <$*> <$- $-> <$*>
229790792Sgshapiro			$: <$(access $6`'_TAG_DELIM_`'$1+*@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7>
229890792Sgshapirodnl no match, +detail: try +* without tag
229990792Sgshapirodnl   1    2    3    4      5    6
230090792SgshapiroR<?> <$+ + $* @ $+> <$*> <+ $-> <$*>
230190792Sgshapiro			$: <$(access $1+*@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6>
230290792Sgshapirodnl no match, +detail: try without +detail
230390792Sgshapirodnl   1    2    3    4    5  6    7
230490792SgshapiroR<?> <$+ + $* @ $+> <$*> <$- $-> <$*>
230590792Sgshapiro			$: <$(access $6`'_TAG_DELIM_`'$1@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7>
230690792Sgshapirodnl no match, +detail: try without +detail and without tag
230790792Sgshapirodnl   1    2    3    4      5    6
230890792SgshapiroR<?> <$+ + $* @ $+> <$*> <+ $-> <$*>
230990792Sgshapiro			$: <$(access $1@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6>
231090792Sgshapirodnl no match, return <default> <passthru>
231190792Sgshapirodnl   1    2    3  4    5
231290792SgshapiroR<?> <$+> <$*> <$- $-> <$*>	$@ <$2> <$5>
231390792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
231490792Sgshapirodnl            2    3  4    5
231590792SgshapiroR<$+ _ATMPF_> <$*> <$- $-> <$*>	$@ <_ATMPF_> <$5>', `dnl')
231690792Sgshapirodnl match, return <match> <passthru>
231790792Sgshapirodnl    2    3  4    5
231890792SgshapiroR<$+> <$*> <$- $-> <$*>		$@ <$1> <$5>
231990792Sgshapiro
232090792Sgshapiro######################################################################
232190792Sgshapiro###  E: LookUpExact -- search for an entry in access database
232290792Sgshapiro###
232390792Sgshapiro###	Parameters:
232490792Sgshapiro###		<$1> -- key
232590792Sgshapiro###		<$2> -- default (what to return if not found in db)
232690792Sgshapirodnl			must not be empty
232790792Sgshapiro###		<$3> -- mark (must be <(!|+) single-token>)
232890792Sgshapiro###			! does lookup only with tag
232990792Sgshapiro###			+ does lookup with and without tag
233090792Sgshapiro###		<$4> -- passthru (additional data passed unchanged through)
233190792Sgshapirodnl returns:		<default> <passthru>
233290792Sgshapirodnl 			<result> <passthru>
233390792Sgshapiro######################################################################
233490792Sgshapiro
233590792SgshapiroSE
233690792Sgshapirodnl    2    3  4    5
233790792SgshapiroR<$*> <$*> <$- $-> <$*>		$: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5>
233890792Sgshapirodnl no match, try without tag
233990792Sgshapirodnl   1    2      3    4
234090792SgshapiroR<?> <$+> <$*> <+ $-> <$*>	$: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4>
234190792Sgshapirodnl no match, return default passthru
234290792Sgshapirodnl   1    2    3  4    5
234390792SgshapiroR<?> <$+> <$*> <$- $-> <$*>	$@ <$2> <$5>
234490792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
234590792Sgshapirodnl            2    3  4    5
234690792SgshapiroR<$+ _ATMPF_> <$*> <$- $-> <$*>	$@ <_ATMPF_> <$5>', `dnl')
234790792Sgshapirodnl match, return <match> <passthru>
234890792Sgshapirodnl    2    3  4    5
234990792SgshapiroR<$+> <$*> <$- $-> <$*>		$@ <$1> <$5>
235090792Sgshapiro
235190792Sgshapiro######################################################################
235290792Sgshapiro###  U: LookUpUser -- search for an entry in access database
235390792Sgshapiro###
235490792Sgshapiro###	lookup of key (which should be a local part) and
235590792Sgshapiro###	variations if +detail exists: +* and without +detail
235690792Sgshapiro###
235790792Sgshapiro###	Parameters:
235890792Sgshapiro###		<$1> -- key (user@)
235990792Sgshapiro###		<$2> -- default (what to return if not found in db)
236090792Sgshapirodnl			must not be empty
236190792Sgshapiro###		<$3> -- mark (must be <(!|+) single-token>)
236290792Sgshapiro###			! does lookup only with tag
236390792Sgshapiro###			+ does lookup with and without tag
236490792Sgshapiro###		<$4> -- passthru (additional data passed unchanged through)
236590792Sgshapirodnl returns:		<default> <passthru>
236690792Sgshapirodnl 			<result> <passthru>
236790792Sgshapiro######################################################################
236890792Sgshapiro
236990792SgshapiroSU
237090792Sgshapirodnl user lookups are always with trailing @
237190792Sgshapirodnl    2    3  4    5
237290792SgshapiroR<$+> <$*> <$- $-> <$*>		$: <$(access $4`'_TAG_DELIM_`'$1 $: ? $)> <$1> <$2> <$3 $4> <$5>
237390792Sgshapirodnl no match, try without tag
237490792Sgshapirodnl   1    2      3    4
237590792SgshapiroR<?> <$+> <$*> <+ $-> <$*>	$: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4>
237690792Sgshapirodnl do not remove the @ from the lookup:
237790792Sgshapirodnl it is part of the +detail@ which is omitted for the lookup
237890792Sgshapirodnl no match, +detail: try +*
237990792Sgshapirodnl   1    2      3    4  5    6
238090792SgshapiroR<?> <$+ + $* @> <$*> <$- $-> <$*>
238190792Sgshapiro			$: <$(access $5`'_TAG_DELIM_`'$1+*@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6>
238290792Sgshapirodnl no match, +detail: try +* without tag
238390792Sgshapirodnl   1    2      3      4    5
238490792SgshapiroR<?> <$+ + $* @> <$*> <+ $-> <$*>
238590792Sgshapiro			$: <$(access $1+*@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5>
238690792Sgshapirodnl no match, +detail: try without +detail
238790792Sgshapirodnl   1    2      3    4  5    6
238890792SgshapiroR<?> <$+ + $* @> <$*> <$- $-> <$*>
238990792Sgshapiro			$: <$(access $5`'_TAG_DELIM_`'$1@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6>
239090792Sgshapirodnl no match, +detail: try without +detail and without tag
239190792Sgshapirodnl   1    2      3      4    5
239290792SgshapiroR<?> <$+ + $* @> <$*> <+ $-> <$*>
239390792Sgshapiro			$: <$(access $1@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5>
239490792Sgshapirodnl no match, return <default> <passthru>
239590792Sgshapirodnl   1    2    3  4    5
239690792SgshapiroR<?> <$+> <$*> <$- $-> <$*>	$@ <$2> <$5>
239790792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
239890792Sgshapirodnl            2    3  4    5
239990792SgshapiroR<$+ _ATMPF_> <$*> <$- $-> <$*>	$@ <_ATMPF_> <$5>', `dnl')
240090792Sgshapirodnl match, return <match> <passthru>
240190792Sgshapirodnl    2    3  4    5
240290792SgshapiroR<$+> <$*> <$- $-> <$*>		$@ <$1> <$5>
240390792Sgshapiro
240490792Sgshapiro######################################################################
240564562Sgshapiro###  SearchList: search a list of items in the access map
240664562Sgshapiro###	Parameters:
240764562Sgshapiro###		<exact tag> $| <mark:address> <mark:address> ... <>
240864562Sgshapirodnl	maybe we should have a @ (again) in front of the mark to
240964562Sgshapirodnl	avoid errorneous matches (with error messages?)
241064562Sgshapirodnl	if we can make sure that tag is always a single token
241164562Sgshapirodnl	then we can omit the delimiter $|, otherwise we need it
241290792Sgshapirodnl	to avoid errorneous matchs (first rule: D: if there
241364562Sgshapirodnl	is that mark somewhere in the list, it will be taken).
241464562Sgshapirodnl	moreover, we can do some tricks to enforce lookup with
241564562Sgshapirodnl	the tag only, e.g.:
241664562Sgshapiro###	where "exact" is either "+" or "!":
241764562Sgshapiro###	<+ TAG>	lookup with and w/o tag
241864562Sgshapiro###	<! TAG>	lookup with tag
241964562Sgshapirodnl	Warning: + and ! should be in OperatorChars (otherwise there must be
242064562Sgshapirodnl		a blank between them and the tag.
242164562Sgshapiro###	possible values for "mark" are:
242290792Sgshapiro###		D: recursive host lookup (LookUpDomain)
242364562Sgshapirodnl		A: recursive address lookup (LookUpAddress) [not yet required]
242464562Sgshapiro###		E: exact lookup, no modifications
242564562Sgshapiro###		F: full lookup, try user+ext@domain and user@domain
242664562Sgshapiro###		U: user lookup, try user+ext and user (input must have trailing @)
242764562Sgshapiro###	return: <RHS of lookup> or <?> (not found)
242864562Sgshapiro######################################################################
242938032Speter
243064562Sgshapiro# class with valid marks for SearchList
243164562Sgshapirodnl if A is activated: add it
243290792SgshapiroC{src}E F D U ifdef(`_FFR_SRCHLIST_A', `A')
243364562SgshapiroSSearchList
243490792Sgshapiro# just call the ruleset with the name of the tag... nice trick...
243590792Sgshapirodnl       2       3    4
243690792SgshapiroR<$+> $| <$={src}:$*> <$*>	$: <$1> $| <$4> $| $>$2 <$3> <?> <$1> <>
243790792Sgshapirodnl workspace: <o tag> $| <rest> $| <result of lookup> <>
243890792Sgshapirodnl no match and nothing left: return
243990792SgshapiroR<$+> $| <> $| <?> <>		$@ <?>
244090792Sgshapirodnl no match but something left: continue
244190792SgshapiroR<$+> $| <$+> $| <?> <>		$@ $>SearchList <$1> $| <$2>
244290792Sgshapirodnl match: return
244390792SgshapiroR<$+> $| <$*> $| <$+> <>	$@ <$3>
244464562Sgshapirodnl return result from recursive invocation
244590792SgshapiroR<$+> $| <$+>			$@ <$2>
244690792Sgshapirodnl endif _ACCESS_TABLE_
244790792Sgshapirodivert(0)
244838032Speter
244990792Sgshapiro######################################################################
245090792Sgshapiro###  trust_auth: is user trusted to authenticate as someone else?
245190792Sgshapiro###
245290792Sgshapiro###	Parameters:
245390792Sgshapiro###		$1: AUTH= parameter from MAIL command
245490792Sgshapiro######################################################################
245590792Sgshapiro
245690792Sgshapirodnl empty ruleset definition so it can be called
245790792SgshapiroSLocal_trust_auth
245864562SgshapiroStrust_auth
245964562SgshapiroR$*			$: $&{auth_type} $| $1
246064562Sgshapiro# required by RFC 2554 section 4.
246164562SgshapiroR$@ $| $*		$#error $@ 5.7.1 $: "550 not authenticated"
246264562Sgshapirodnl seems to be useful...
246364562SgshapiroR$* $| $&{auth_authen}		$@ identical
246464562SgshapiroR$* $| <$&{auth_authen}>	$@ identical
246564562Sgshapirodnl call user supplied code
246664562SgshapiroR$* $| $*		$: $1 $| $>"Local_trust_auth" $1
246764562SgshapiroR$* $| $#$*		$#$2
246864562Sgshapirodnl default: error
246964562SgshapiroR$*			$#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author}
247064562Sgshapiro
247190792Sgshapiro######################################################################
247290792Sgshapiro###  Relay_Auth: allow relaying based on authentication?
247390792Sgshapiro###
247490792Sgshapiro###	Parameters:
247590792Sgshapiro###		$1: ${auth_type}
247690792Sgshapiro######################################################################
247790792SgshapiroSLocal_Relay_Auth
247864562Sgshapiro
247990792Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
248090792Sgshapiro######################################################################
248190792Sgshapiro###  srv_features: which features to offer to a client?
248290792Sgshapiro###	(done in server)
248390792Sgshapiro######################################################################
248490792SgshapiroSsrv_features
248590792Sgshapiroifdef(`_LOCAL_SRV_FEATURES_', `dnl
248690792SgshapiroR$*			$: $1 $| $>"Local_srv_features" $1
248790792SgshapiroR$* $| $#$*		$#$2
248890792SgshapiroR$* $| $*		$: $1', `dnl')
248990792SgshapiroR$*		$: $>D <$&{client_name}> <?> <! SRV_FEAT_TAG> <>
249090792SgshapiroR<?>$*		$: $>A <$&{client_addr}> <?> <! SRV_FEAT_TAG> <>
249190792SgshapiroR<?>$*		$: <$(access SRV_FEAT_TAG`'_TAG_DELIM_ $: ? $)>
249264562SgshapiroR<?>$*		$@ OK
249390792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
249490792SgshapiroR<$* _ATMPF_>$*	$#temp', `dnl')
249590792SgshapiroR<$+>$*		$# $1
249664562Sgshapiro
249790792Sgshapiro######################################################################
249890792Sgshapiro###  try_tls: try to use STARTTLS?
249990792Sgshapiro###	(done in client)
250090792Sgshapiro######################################################################
250164562SgshapiroStry_tls
250290792Sgshapiroifdef(`_LOCAL_TRY_TLS_', `dnl
250390792SgshapiroR$*			$: $1 $| $>"Local_try_tls" $1
250490792SgshapiroR$* $| $#$*		$#$2
250590792SgshapiroR$* $| $*		$: $1', `dnl')
250690792SgshapiroR$*		$: $>D <$&{server_name}> <?> <! TLS_TRY_TAG> <>
250790792SgshapiroR<?>$*		$: $>A <$&{server_addr}> <?> <! TLS_TRY_TAG> <>
250890792SgshapiroR<?>$*		$: <$(access TLS_TRY_TAG`'_TAG_DELIM_ $: ? $)>
250964562SgshapiroR<?>$*		$@ OK
251090792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
251190792SgshapiroR<$* _ATMPF_>$*	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
251271345SgshapiroR<NO>$*		$#error $@ 5.7.1 $: "550 do not try TLS with " $&{server_name} " ["$&{server_addr}"]"
2513102528Sgshapiro 
251490792Sgshapiro######################################################################
251590792Sgshapiro###  tls_rcpt: is connection with server "good" enough?
251690792Sgshapiro###	(done in client, per recipient)
251790792Sgshapirodnl called from deliver() before RCPT command
251890792Sgshapiro###
251990792Sgshapiro###	Parameters:
252090792Sgshapiro###		$1: recipient
252190792Sgshapiro######################################################################
252290792SgshapiroStls_rcpt
252390792Sgshapiroifdef(`_LOCAL_TLS_RCPT_', `dnl
252490792SgshapiroR$*			$: $1 $| $>"Local_tls_rcpt" $1
252590792SgshapiroR$* $| $#$*		$#$2
252690792SgshapiroR$* $| $*		$: $1', `dnl')
252790792Sgshapirodnl store name of other side
252890792SgshapiroR$*			$: $(macro {TLS_Name} $@ $&{server_name} $) $1
252990792Sgshapirodnl canonify recipient address
253090792SgshapiroR$+			$: <?> $>CanonAddr $1
253190792Sgshapirodnl strip trailing dots
253290792SgshapiroR<?> $+ < @ $+ . >	<?> $1 <@ $2 >
253390792Sgshapirodnl full address?
253490792SgshapiroR<?> $+ < @ $+ >	$: $1 <@ $2 > $| <F:$1@$2> <U:$1@> <D:$2> <E:>
253590792Sgshapirodnl only localpart?
253690792SgshapiroR<?> $+			$: $1 $| <U:$1@> <E:>
253790792Sgshapirodnl look it up
253890792Sgshapirodnl also look up a default value via E:
253990792SgshapiroR$* $| $+	$: $1 $| $>SearchList <! TLS_RCPT_TAG> $| $2 <>
254090792Sgshapirodnl found nothing: stop here
254190792SgshapiroR$* $| <?>	$@ OK
254290792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
254390792SgshapiroR$* $| <$* _ATMPF_>	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
254490792Sgshapirodnl use the generic routine (for now)
254590792SgshapiroR$* $| <$+>	$@ $>"TLS_connection" $&{verify} $| <$2>')
254664562Sgshapiro
254790792Sgshapiro######################################################################
254890792Sgshapiro###  tls_client: is connection with client "good" enough?
254990792Sgshapiro###	(done in server)
255090792Sgshapiro###
255190792Sgshapiro###	Parameters:
255290792Sgshapiro###		${verify} $| (MAIL|STARTTLS)
255390792Sgshapiro######################################################################
255464562Sgshapirodnl MAIL: called from check_mail
255564562Sgshapirodnl STARTTLS: called from smtp() after STARTTLS has been accepted
255664562SgshapiroStls_client
255790792Sgshapiroifdef(`_LOCAL_TLS_CLIENT_', `dnl
255890792SgshapiroR$*			$: $1 $| $>"Local_tls_client" $1
255990792SgshapiroR$* $| $#$*		$#$2
256090792SgshapiroR$* $| $*		$: $1', `dnl')
256164562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
256290792Sgshapirodnl store name of other side
256390792SgshapiroR$*		$: $(macro {TLS_Name} $@ $&{server_name} $) $1
256464562Sgshapirodnl ignore second arg for now
256564562Sgshapirodnl maybe use it to distinguish permanent/temporary error?
256664562Sgshapirodnl if MAIL: permanent (STARTTLS has not been offered)
256764562Sgshapirodnl if STARTTLS: temporary (offered but maybe failed)
256890792SgshapiroR$* $| $*	$: $1 $| $>D <$&{client_name}> <?> <! TLS_CLT_TAG> <>
256990792SgshapiroR$* $| <?>$*	$: $1 $| $>A <$&{client_addr}> <?> <! TLS_CLT_TAG> <>
257064562Sgshapirodnl do a default lookup: just TLS_CLT_TAG
257164562SgshapiroR$* $| <?>$*	$: $1 $| <$(access TLS_CLT_TAG`'_TAG_DELIM_ $: ? $)>
257290792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
257390792SgshapiroR$* $| <$* _ATMPF_>	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
257490792SgshapiroR$*		$@ $>"TLS_connection" $1', `dnl
257590792SgshapiroR$* $| $*	$@ $>"TLS_connection" $1')
257664562Sgshapiro
257790792Sgshapiro######################################################################
257890792Sgshapiro###  tls_server: is connection with server "good" enough?
257990792Sgshapiro###	(done in client)
258090792Sgshapiro###
258190792Sgshapiro###	Parameter:
258290792Sgshapiro###		${verify}
258390792Sgshapiro######################################################################
258464562Sgshapirodnl i.e. has the server been authenticated and is encryption active?
258564562Sgshapirodnl called from deliver() after STARTTLS command
258664562SgshapiroStls_server
258790792Sgshapiroifdef(`_LOCAL_TLS_SERVER_', `dnl
258890792SgshapiroR$*			$: $1 $| $>"Local_tls_server" $1
258990792SgshapiroR$* $| $#$*		$#$2
259090792SgshapiroR$* $| $*		$: $1', `dnl')
259164562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
259290792Sgshapirodnl store name of other side
259390792SgshapiroR$*		$: $(macro {TLS_Name} $@ $&{server_name} $) $1
259490792SgshapiroR$*		$: $1 $| $>D <$&{server_name}> <?> <! TLS_SRV_TAG> <>
259590792SgshapiroR$* $| <?>$*	$: $1 $| $>A <$&{server_addr}> <?> <! TLS_SRV_TAG> <>
259664562Sgshapirodnl do a default lookup: just TLS_SRV_TAG
259764562SgshapiroR$* $| <?>$*	$: $1 $| <$(access TLS_SRV_TAG`'_TAG_DELIM_ $: ? $)>
259890792Sgshapiroifdef(`_ATMPF_', `dnl tempfail?
259990792SgshapiroR$* $| <$* _ATMPF_>	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."', `dnl')
260090792SgshapiroR$*		$@ $>"TLS_connection" $1', `dnl
260190792SgshapiroR$*		$@ $>"TLS_connection" $1')
260264562Sgshapiro
260390792Sgshapiro######################################################################
260490792Sgshapiro###  TLS_connection: is TLS connection "good" enough?
260590792Sgshapiro###
260690792Sgshapiro###	Parameters:
260764562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
260890792Sgshapiro###		${verify} $| <Requirement> [<>]', `dnl
260990792Sgshapiro###		${verify}')
261090792Sgshapiro###		Requirement: RHS from access map, may be ? for none.
261190792Sgshapirodnl	syntax for Requirement:
261290792Sgshapirodnl	[(PERM|TEMP)+] (VERIFY[:bits]|ENCR:bits) [+extensions]
261390792Sgshapirodnl	extensions: could be a list of further requirements
261490792Sgshapirodnl		for now: CN:string	{cn_subject} == string
261590792Sgshapiro######################################################################
261690792SgshapiroSTLS_connection
261790792Sgshapiroifdef(`_ACCESS_TABLE_', `dnl', `dnl use default error
261890792Sgshapirodnl deal with TLS handshake failures: abort
261990792SgshapiroRSOFTWARE	$#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake."
262090792Sgshapirodivert(-1)')
262164562Sgshapirodnl common ruleset for tls_{client|server}
262290792Sgshapirodnl input: ${verify} $| <ResultOfLookup> [<>]
262364562Sgshapirodnl remove optional <>
262464562SgshapiroR$* $| <$*>$*			$: $1 $| <$2>
262590792Sgshapirodnl workspace: ${verify} $| <ResultOfLookup>
262690792Sgshapiro# create the appropriate error codes
262764562Sgshapirodnl permanent or temporary error?
262864562SgshapiroR$* $| <PERM + $={tls} $*>	$: $1 $| <503:5.7.0> <$2 $3>
262964562SgshapiroR$* $| <TEMP + $={tls} $*>	$: $1 $| <403:4.7.0> <$2 $3>
263064562Sgshapirodnl default case depends on TLS_PERM_ERR
263164562SgshapiroR$* $| <$={tls} $*>		$: $1 $| <ifdef(`TLS_PERM_ERR', `503:5.7.0', `403:4.7.0')> <$2 $3>
263290792Sgshapirodnl workspace: ${verify} $| [<SMTP:ESC>] <ResultOfLookup>
263390792Sgshapiro# deal with TLS handshake failures: abort
263464562SgshapiroRSOFTWARE $| <$-:$+> $* 	$#error $@ $2 $: $1 " TLS handshake failed."
263564562Sgshapirodnl no <reply:dns> i.e. not requirements in the access map
263664562Sgshapirodnl use default error
263764562SgshapiroRSOFTWARE $| $* 		$#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake failed."
263890792SgshapiroR$* $| <$*> <VERIFY>		$: <$2> <VERIFY> <> $1
263990792Sgshapirodnl separate optional requirements
264090792SgshapiroR$* $| <$*> <VERIFY + $+>	$: <$2> <VERIFY> <$3> $1
264190792SgshapiroR$* $| <$*> <$={tls}:$->$*	$: <$2> <$3:$4> <> $1
264290792Sgshapirodnl separate optional requirements
264390792SgshapiroR$* $| <$*> <$={tls}:$- + $+>$*	$: <$2> <$3:$4> <$5> $1
264464562Sgshapirodnl some other value in access map: accept
264564562Sgshapirodnl this also allows to override the default case (if used)
264664562SgshapiroR$* $| $*			$@ OK
264764562Sgshapiro# authentication required: give appropriate error
264864562Sgshapiro# other side did authenticate (via STARTTLS)
264990792Sgshapirodnl workspace: <SMTP:ESC> <{VERIFY,ENCR}[:BITS]> <[extensions]> ${verify}
265064562Sgshapirodnl only verification required and it succeeded
265190792SgshapiroR<$*><VERIFY> <> OK		$@ OK
265290792Sgshapirodnl verification required and it succeeded but extensions are given
265390792Sgshapirodnl change it to <SMTP:ESC> <REQ:0>  <extensions>
265490792SgshapiroR<$*><VERIFY> <$+> OK		$: <$1> <REQ:0> <$2>
265564562Sgshapirodnl verification required + some level of encryption
265690792SgshapiroR<$*><VERIFY:$-> <$*> OK	$: <$1> <REQ:$2> <$3>
265764562Sgshapirodnl just some level of encryption required
265890792SgshapiroR<$*><ENCR:$-> <$*> $*		$: <$1> <REQ:$2> <$3>
265990792Sgshapirodnl workspace:
266090792Sgshapirodnl 1. <SMTP:ESC> <VERIFY [:bits]>  <[extensions]> {verify} (!= OK)
266190792Sgshapirodnl 2. <SMTP:ESC> <REQ:bits>  <[extensions]>
266290792Sgshapirodnl verification required but ${verify} is not set (case 1.)
266390792SgshapiroR<$-:$+><VERIFY $*> <$*>	$#error $@ $2 $: $1 " authentication required"
266490792SgshapiroR<$-:$+><VERIFY $*> <$*> FAIL	$#error $@ $2 $: $1 " authentication failed"
266590792SgshapiroR<$-:$+><VERIFY $*> <$*> NO	$#error $@ $2 $: $1 " not authenticated"
266690792SgshapiroR<$-:$+><VERIFY $*> <$*> NOT	$#error $@ $2 $: $1 " no authentication requested"
266790792SgshapiroR<$-:$+><VERIFY $*> <$*> NONE	$#error $@ $2 $: $1 " other side does not support STARTTLS"
266864562Sgshapirodnl some other value for ${verify}
266990792SgshapiroR<$-:$+><VERIFY $*> <$*> $+	$#error $@ $2 $: $1 " authentication failure " $4
267090792Sgshapirodnl some level of encryption required: get the maximum level (case 2.)
267190792SgshapiroR<$*><REQ:$-> <$*>		$: <$1> <REQ:$2> <$3> $>max $&{cipher_bits} : $&{auth_ssf}
267264562Sgshapirodnl compare required bits with actual bits
267390792SgshapiroR<$*><REQ:$-> <$*> $-		$: <$1> <$2:$4> <$3> $(arith l $@ $4 $@ $2 $)
267490792SgshapiroR<$-:$+><$-:$-> <$*> TRUE	$#error $@ $2 $: $1 " encryption too weak " $4 " less than " $3
267590792Sgshapirodnl strength requirements fulfilled
267690792Sgshapirodnl TLS Additional Requirements Separator
267790792Sgshapirodnl this should be something which does not appear in the extensions itself
267890792Sgshapirodnl @ could be part of a CN, DN, etc...
267990792Sgshapirodnl use < > ? those are encoded in CN, DN, ...
268090792Sgshapirodefine(`_TLS_ARS_', `++')dnl
268190792Sgshapirodnl workspace:
268290792Sgshapirodnl <SMTP:ESC> <REQ:bits> <extensions> result-of-compare
268390792SgshapiroR<$-:$+><$-:$-> <$*> $*		$: <$1:$2 _TLS_ARS_ $5>
268490792Sgshapirodnl workspace: <SMTP:ESC _TLS_ARS_ extensions>
268590792Sgshapirodnl continue: check  extensions
268690792SgshapiroR<$-:$+ _TLS_ARS_ >			$@ OK
268790792Sgshapirodnl split extensions into own list
268890792SgshapiroR<$-:$+ _TLS_ARS_ $+ >			$: <$1:$2> <$3>
268990792SgshapiroR<$-:$+> < $+ _TLS_ARS_ $+ >		<$1:$2> <$3> <$4>
269090792SgshapiroR<$-:$+> $+			$@ $>"TLS_req" $3 $| <$1:$2>
269164562Sgshapiro
269290792Sgshapiro######################################################################
269390792Sgshapiro###  TLS_req: check additional TLS requirements
269490792Sgshapiro###
269590792Sgshapiro###	Parameters: [<list> <of> <req>] $| <$-:$+>
269690792Sgshapiro###		$-: SMTP reply code
269790792Sgshapiro###		$+: Enhanced Status Code
269890792Sgshapirodnl  further requirements for this ruleset:
269990792Sgshapirodnl	name of "other side" is stored is {TLS_name} (client/server_name)
270090792Sgshapirodnl
270190792Sgshapirodnl	currently only CN[:common_name] is implemented
270290792Sgshapirodnl	right now this is only a logical AND
270390792Sgshapirodnl	i.e. all requirements must be true
270490792Sgshapirodnl	how about an OR? CN must be X or CN must be Y or ..
270590792Sgshapirodnl	use a macro to compute this as a trivial sequential
270690792Sgshapirodnl	operations (no precedences etc)?
270790792Sgshapiro######################################################################
270890792SgshapiroSTLS_req
270990792Sgshapirodnl no additional requirements: ok
271090792SgshapiroR $| $+		$@ OK
271190792Sgshapirodnl require CN: but no CN specified: use name of other side
271290792SgshapiroR<CN> $* $| <$+>		$: <CN:$&{TLS_Name}> $1 $| <$2>
271390792Sgshapirodnl match, check rest
271490792SgshapiroR<CN:$&{cn_subject}> $* $| <$+>		$@ $>"TLS_req" $1 $| <$2>
271590792Sgshapirodnl CN does not match
271690792Sgshapirodnl  1   2      3  4
271790792SgshapiroR<CN:$+> $* $| <$-:$+>	$#error $@ $4 $: $3 " CN " $&{cn_subject} " does not match " $1
271890792Sgshapirodnl cert subject
271990792SgshapiroR<CS:$&{cert_subject}> $* $| <$+>	$@ $>"TLS_req" $1 $| <$2>
272090792Sgshapirodnl CS does not match
272190792Sgshapirodnl  1   2      3  4
2722110560SgshapiroR<CS:$+> $* $| <$-:$+>	$#error $@ $4 $: $3 " Cert Subject " $&{cert_subject} " does not match " $1
272390792Sgshapirodnl match, check rest
272490792SgshapiroR<CI:$&{cert_issuer}> $* $| <$+>	$@ $>"TLS_req" $1 $| <$2>
272590792Sgshapirodnl CI does not match
272690792Sgshapirodnl  1   2      3  4
2727110560SgshapiroR<CI:$+> $* $| <$-:$+>	$#error $@ $4 $: $3 " Cert Issuer " $&{cert_issuer} " does not match " $1
272890792Sgshapirodnl return from recursive call
272990792SgshapiroROK			$@ OK
273090792Sgshapiro
273190792Sgshapiro######################################################################
273290792Sgshapiro###  max: return the maximum of two values separated by :
273390792Sgshapiro###
273490792Sgshapiro###	Parameters: [$-]:[$-]
273590792Sgshapiro######################################################################
273664562SgshapiroSmax
273764562SgshapiroR:		$: 0
273864562SgshapiroR:$-		$: $1
273964562SgshapiroR$-:		$: $1
274064562SgshapiroR$-:$-		$: $(arith l $@ $1 $@ $2 $) : $1 : $2
274164562SgshapiroRTRUE:$-:$-	$: $2
274290792SgshapiroR$-:$-:$-	$: $2
274390792Sgshapirodnl endif _ACCESS_TABLE_
274490792Sgshapirodivert(0)
274564562Sgshapiro
274690792Sgshapiro######################################################################
274790792Sgshapiro###  RelayTLS: allow relaying based on TLS authentication
274890792Sgshapiro###
274990792Sgshapiro###	Parameters:
275090792Sgshapiro###		none
275190792Sgshapiro######################################################################
275290792SgshapiroSRelayTLS
275364562Sgshapiro# authenticated?
275464562Sgshapirodnl we do not allow relaying for anyone who can present a cert
275564562Sgshapirodnl signed by a "trusted" CA. For example, even if we put verisigns
2756110560Sgshapirodnl CA in CertPath so we can authenticate users, we do not allow
275764562Sgshapirodnl them to abuse our server (they might be easier to get hold of,
275864562Sgshapirodnl but anyway).
275964562Sgshapirodnl so here is the trick: if the verification succeeded
276064562Sgshapirodnl we look up the cert issuer in the access map
276164562Sgshapirodnl (maybe after extracting a part with a regular expression)
276264562Sgshapirodnl if this returns RELAY we relay without further questions
276364562Sgshapirodnl if it returns SUBJECT we perform a similar check on the
276464562Sgshapirodnl cert subject.
276564562Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
276690792SgshapiroR$*			$: <?> $&{verify}
276790792SgshapiroR<?> OK			$: OK		authenticated: continue
276890792SgshapiroR<?> $*			$@ NO		not authenticated
276964562Sgshapiroifdef(`_CERT_REGEX_ISSUER_', `dnl
277090792SgshapiroR$*			$: $(CERTIssuer $&{cert_issuer} $)',
277190792Sgshapiro`R$*			$: $&{cert_issuer}')
277290792SgshapiroR$+			$: $(access CERTISSUER`'_TAG_DELIM_`'$1 $)
277364562Sgshapirodnl use $# to stop further checks (delay_check)
277490792SgshapiroRRELAY			$# RELAY
277564562Sgshapiroifdef(`_CERT_REGEX_SUBJECT_', `dnl
277690792SgshapiroRSUBJECT		$: <@> $(CERTSubject $&{cert_subject} $)',
277790792Sgshapiro`RSUBJECT		$: <@> $&{cert_subject}')
277890792SgshapiroR<@> $+			$: <@> $(access CERTSUBJECT`'_TAG_DELIM_`'$1 $)
277990792SgshapiroR<@> RELAY		$# RELAY
278090792SgshapiroR$*			$: NO', `dnl')
278164562Sgshapiro
278290792Sgshapiro######################################################################
278390792Sgshapiro###  authinfo: lookup authinfo in the access map
278490792Sgshapiro###
278590792Sgshapiro###	Parameters:
278690792Sgshapiro###		$1: {server_name}
278790792Sgshapiro###		$2: {server_addr}
278890792Sgshapirodnl	both are currently ignored
278990792Sgshapirodnl if it should be done via another map, we either need to restrict
279090792Sgshapirodnl functionality (it calls D and A) or copy those rulesets (or add another
279190792Sgshapirodnl parameter which I want to avoid, it's quite complex already)
279290792Sgshapiro######################################################################
279390792Sgshapirodnl omit this ruleset if neither is defined?
279490792Sgshapirodnl it causes DefaultAuthInfo to be ignored
279590792Sgshapirodnl (which may be considered a good thing).
279690792SgshapiroSauthinfo
279790792Sgshapiroifdef(`_AUTHINFO_TABLE_', `dnl
279890792SgshapiroR$*		$: <$(authinfo AuthInfo:$&{server_name} $: ? $)>
279990792SgshapiroR<?>		$: <$(authinfo AuthInfo:$&{server_addr} $: ? $)>
280090792SgshapiroR<?>		$: <$(authinfo AuthInfo: $: ? $)>
280190792SgshapiroR<?>		$@ no				no authinfo available
280290792SgshapiroR<$*>		$# $1
280390792Sgshapirodnl', `dnl
280490792Sgshapiroifdef(`_ACCESS_TABLE_', `dnl
280590792SgshapiroR$*		$: $1 $| $>D <$&{server_name}> <?> <! AuthInfo> <>
280690792SgshapiroR$* $| <?>$*	$: $1 $| $>A <$&{server_addr}> <?> <! AuthInfo> <>
280790792SgshapiroR$* $| <?>$*	$: $1 $| <$(access AuthInfo`'_TAG_DELIM_ $: ? $)> <>
280890792SgshapiroR$* $| <?>$*	$@ no				no authinfo available
280990792SgshapiroR$* $| <$*> <>	$# $2
281090792Sgshapirodnl', `dnl')')
281190792Sgshapiro
281264562Sgshapiroundivert(9)dnl LOCAL_RULESETS
281338032Speter#
281438032Speter######################################################################
281538032Speter######################################################################
281638032Speter#####
281764562Sgshapiro`#####			MAIL FILTER DEFINITIONS'
281864562Sgshapiro#####
281964562Sgshapiro######################################################################
282064562Sgshapiro######################################################################
282190792Sgshapiro_MAIL_FILTERS_
282264562Sgshapiro#
282364562Sgshapiro######################################################################
282464562Sgshapiro######################################################################
282564562Sgshapiro#####
282638032Speter`#####			MAILER DEFINITIONS'
282738032Speter#####
282838032Speter######################################################################
282938032Speter######################################################################
283064562Sgshapiroundivert(7)dnl MAILER_DEFINITIONS
283166494Sgshapiro
2832