#| File:  $MAILVAR/db/smtp-policy.src
#|
#|  Policy based filter database boilerplate for smtpserver
#|  This file is compiled into actual database by command:
#|         $MAILBIN/policy-builder.sh
#|
#|  File syntax and semantics are explained towards the _end_ of this file.
#|
#|  Further documentation about related files, see file:
#|       doc/guides/smtp-policy
#|  See also comments in this file about various sub-options!

#|-----------
#|
#| Default handling boilerplates:
#|
#|   "We are not relaying between off-site hosts, except when ..."
#|
#| You MUST uncomment one of these default-defining pairs, or the blocking
#| of relay hijack will not work at all !
#|
#| -- 1st alternate: No MX target usage, no DNS existence verify
#|    Will accept for reception only those domains explicitely listed
#|    in  'smtp-policy.mx'  and  'localnames'  files.  Will not do
#|    verifications on validity/invalidity of source domains:  <foo@bar>
#
# _default_dot		relaycustomer - relaytarget -
# _default_ipaddr	relaycustomer - relaytarget -
#
#| -- 2nd alternate: No MX target usage, DNS existence verify
#|    Like the 1st alternate, except will verify the sender (mail from:<..>)
#|    address for existence of the DNS MX and/or A/AAAA data -- e.g. validity.
#|    If RBL parameters are set below, will use them.
#
# _default_dot		relaycustomer - relaytarget - senderokwithdns + = _rbl1
# _default_ipaddr	relaycustomer - relaytarget - senderokwithdns + = _rbl0
#
#| -- 3rd alternate: MX relay trust, DNS existence verify
#|    For the people who are in deep s*...  That is, those who for some
#|    reason have given open permissions for people to use their server
#|    as MX backup for their clients, but don't know all domains valid
#|    to go thru...  Substitutes accurate data to user's whimsical DNS
#|    maintenance activities.  Vulnerable to unauthorized inbound MX
#|    service abuse.
#|    If RBL parameters are set below, will use them.

_default_dot		relaycustomer - acceptifmx - senderokwithdns + = _rbl1
_default_ipaddr		relaycustomer - acceptifmx - senderokwithdns + = _rbl0

#| -- 4th alternate: Sender & recipient DNS existence verify
#|    This is more of an example for the symmetry's sake, verifies that
#|    the source and destination domains are DNS resolvable, but does not
#|    block relaying -- DANGER! DANGER! WILL ROBINSON! DANGER!
#
# _default_dot		senderokwithdns - acceptifdns -
# _default_ipaddr	senderokwithdns - acceptifdns -
#


#| -----------------------------------
#|  Now use above defined macroes at these default labels:
.		= _default_dot
[0.0.0.0]/0	= _default_ipaddr

#| -----------------------------------
#|
#| RBL type test rules:

#| First RBL variant: NONE OF THE RBL TESTS
_rbl0           # Nothing at early phase
_rbl1           # Nothing at late phase

#| Second RBL variant: Early block with RBL+DUL+RSS
#_rbl0          test-dns-rbl      +:dul.maps.vix.com:relays.mail-abuse.org
#_rbl1          # Nothing at late phase

#| Third RBL variant: Late block with RBL+DUL+RSS
#_rbl0          rcpt-dns-rbl      +:dul.maps.vix.com:relays.mail-abuse.org
#_rbl1          test-rcpt-dns-rbl +

#|  (The "+" at the DNS zone defines is treated as shorthand to
#|   "rbl.maps.vix.com")
#|
#|  The Third RBL variant means that all target domains can all by themselves
#|  choose if they use RBL to do source filtering.  The ``= _RBL1'' test
#|  *must* be added to all domain instances where the check is wanted.
#|  (Including the last-resort domain default of ".")
#|  (Or inverting: If some recipient domain is *not* wanting RBL-type tests,
#|   that domain shall have  ``test-rcpt-dns-rbl -'' attribute pair given for
#|   it at the input datasets -- consider  smtp-policy.mx  file!)
#|
#|-----------
#|
#| If your system has ``whoson'' server (see contrib/whoson-*.tgz),
#| you can activate it by adding  'trust-whoson +' attribute pair to
#| the wild-card IP address test:  [0.0.0.0]/0  of your choise.
#|
#|-----------
#|
#| If you want explicitely to run content-filter even for locally
#| accepted source IP addresses, you can activate it by adding
#| 'filtering +' attribute pair to  a)  the wild-card IP address test:
#|     [0.0.0.0]/0
#| of your choice above, and  b)  into  _full_rights  further below.
#|
#| This attribute pair is looked up only in early connect tests, never
#| afterwards.   If the attribute pair is not present, tests causing
#| internal  'always_accept'  flag to be set will disable the lookup
#| (effectively 'filtering -').
#|
#| With 'filtering +' added into  _full_rights,  entering explicite
#| 'filtering -'  for an address literal in  smtp-policy.relay*  file
#| will disable the content filtering for given address, while it
#| is activated for all others.
#|
#|-----------
#|
#| For outbound relaying control for fixed IP address networks, see
#| comments in file:  smtp-policy.relay
#|
#|-----------
#|
#| Generally we refuse SMTP connections from host in private address space
#| and refuse mails to or from <user@[nn.nn.nn.nn]> if nn.nn.nn.nn is a
#| private IP address...
#|
_private_address    message "We reject your network" rejectnet + message "We don't accept email from this source address" rejectsource + relaycustomer - relaytarget -
#[172.16.0.0]/12         = _private_address
#[192.168.0.0]/16        = _private_address
#[10.0.0.0]/8            = _private_address
#|
#| ...but hosts in the address range 192.168.16.0-192.168.17.255 may be
#| our SMTP clients.
#|
#[192.168.16.0]/23	rejectnet - = _private_address

#| Hosts of our organization can do anything...
#|
_our_network	= _full_rights

#|    Boilerplate macroes for various things.
#|    If RBL parameters are set above, will use them.

_full_rights	rejectnet - relaycustnet + relaytarget +               = _rbl1
_localnames	rejectnet - relaycustnet - localdomain + relaytarget + = _rbl1
_relaytarget	relaytarget +                                          = _rbl1

#|
#| Thanks, no bulk mails! Drop them when used as sources, also reject
#| when asked to send for them.
#|
_bulk_mail	message "Your address is not liked source for email" rejectsource + message "Your IP address is not liked source for email" rejectnet + message "This is not accepted relay target" relaytarget -
#|
#| The actual list of domains, and perhaps user addresses should
#| be gotten from some active Anti-SPAM database
#|
#nobody.com		= _bulk_mail
#.nobody.com		= _bulk_mail
#nodomain.com		= _bulk_mail
#.nodomain.com		= _bulk_mail
#|
#| Some source users we reject always: (frequent spammers..)
#| (see comment above about Anti-SPAM databases)
#| (Do note that these are SMTP ENVELOPE items, not RFC-822 items!)
#|
#friend@		= _bulk_mail
#friends@		= _bulk_mail

#----------------------------------
#| Syntax:
#|
#| key	[attribute value]... [= _tag]
#|
#|  The db compiler  does not accept completely empty value-set input,
#|  therefore there are comments in all  _ZZZ  entries if nothing else!
#| 
#| Where:
#|
#| 'key' is 
#|   - a domain name optionally preceded by a dot (.)
#|   - "user@" / "user@domain" names.
#|   - an IP address expression in canonical [nn.nn.nn.nn]/prefix form.
#|	Unspecified bits must be 0. (Network IPv6 addresses containing
#|       IPv4-mapped addresses are translated into plain IPv4.)
#|   - any arbitrary word referred as '_tag' at the right side
#|     '_tag' may be any key of this database
#|
#| 'attribute' and 'value' are tokens. They are used by policytest() to
#|     make decisions.  Attribute names, and understood value tokens are:
#|
#|	'='		'_any_token_with_starting_underscore' (aliasing)
#|				Recursion up to 3 levels is supported
#|	'rejectnet'	{ '+', '-' }
#|	'freezenet'	{ '+', '-' }
#|	'rejectsource'	{ '+', '-' }
#|	'freezesource'	{ '+', '-' }
#|	'relaycustomer'	{ '+', '-' }
#|	'relaycustnet'	{ '+', '-' }
#|	'relaytarget'	{ '+', '-' }
#|	'freeze'	{ '+', '-' }
#|	'senderokwithdns' { '+', '-' }
#|	'acceptifmx'	{ '+', '-' }
#|	'acceptifdns'	{ '+', '-' }
#|	'sendernorelay' { '+', '-' }
#|	'test-dns-rbl'	{ '+', '-', "suffix.one:suffix.two" }
#|	  Sample suffixes: rbl.maps.vix.com  relays.mail-abuse.org
#|			   dul.maps.vix.com
#|			   ok.orbs.org:relays.orbs.org  <-- that is a PAIR!
#|	'rcpt-dns-rbl'	{ '+', '-', "suffix.one:suffix.two" }
#|	'test-rcpt-dns-rbl' { '+', '-', "suffix.one:suffix.two" }
#|	'message'	"quoted constant string message"
#|	'localdomain'	{ '+', '-' }
#|	'maxinsize'	nnn
#|	'maxoutsize'	nnn
#|	'fulltrustnet'	{ '+', '-' }
#|	'trustrecipients' { '+', '-' }
#|	'trust-whoson'	{ '+', '-' }
#|	'filtering'	{ '+', '-' }
#|
#| Semantics:
#|
#| The policytest() functions called by smtpserver to check the client host,
#| the sender's and recipients' addresses.  policytest() looks for name, and
#| address of client host as well as full and partial user address, and domain
#| part of sender and recipient addresses in this database.  The retrieved
#| attributes are used to make decissions on acepting or rejecting
#| the incoming mail.
#|
#| If looking for 'foo.bar.edu' and exact match failed, the database looks
#| keys in sequence:  '.foo.bar.edu', '.bar.edu', '.edu', and '.'.
#|
#| The order of entries in this file is indifferent.
#|
#| When searching an IP address the entry with the most common (leftside) bits
#| is returned. So you can have a [0.0.0.0]/0 entry what specifies the default
#| addributes for all unlisted IP addresses. (Both IPv4 and IPv6)
#|
#| '=' is a special attribute.
#| The notation '= _tag' means "See also at '_tag'". If server() doesn't
#| find the requested attribute of the object, it will replace object name
#| with '_tag' and restarts search.
#| 

#| Here is an example configuration, assumed the following decision
#| chains of smtpserver/policytest.c routines:
#|
#| Connection establishment:  (IP address tested)
#|
#|  if (IP address of SMTP client has 'REJECTNET +' attribute) then
#|   any further conversation refused
#|   [state->always_reject = 1; return REJECT;]
#|  if (IP address of SMTP client has 'FREEZENET +' attribute) then
#|   we present happy face, but always put the messages into a freezer..
#|   [state->always_freeze = 1; return FREEZE;]
#|  if (IP address of SMTP client has 'FILTERING' attribute) then
#|   set  state->content_filter  1/0 depending on '+'/'-' value
#|   If this attribute doesn't exist, set: state->content_filter = -1
#|   This will latter interact with  state->always_accept  variable
#|   in the content-filter interface...
#|  if (IP address of SMTP client has 'RELAYCUSTNET +' attribute) then
#|   sender accepted, recipients not checked
#|   [state->always_accept = 1; return ACCEPT;]
#|  if (IP address of SMTP client has 'TEST-DNS-RBL +' attribute) then
#|   we use RealtimeBlockingList DNS database.  If we get match from
#|   there, we do: [state->always_reject = 1; return REJECT;]
#|  if (IP address of SMTP client has "RCPT-DNS-RBL" attribute then
#|   save RBL lookup result for processing at "RCPTO TO:" phase
#|   [state->rbl_msg = <RBL_LOOKUP_RESULT>;]
#|  else
#|   return ACCEPT
#|
#| Connection extablishment; connection source DOMAIN test
#| (This is done on the reverser information of the IP address
#|  of the session source.)
#|
#|  if (state->always_reject == 1) return REJECT;
#|  if (state->always_freeze == 1) return FREEZE;
#|  if (state->always_accept == 1) return ACCEPT;
#|
#|  if (source domain of address of SMTP client has 'REJECTNET +' attribute) then
#|   any further conversation refused
#|   [state->always_reject = 1; return REJECT;]
#|  if (source domain of of SMTP client has 'FREEZENET +' attribute) then
#|   we present happy face, but always put the messages into a freezer..
#|   [state->always_freeze = 1; return FREEZE;]
#|  if (source domain of SMTP client has 'RCPT-DNS-RBL "_Message' like attributes
#|   then save it for rejection at rcpt to: phase
#|   [state->rbl_msg = values[P_A_RcptDnsRBL] + 1;]
#|  else
#|   return ACCEPT
#|
#| HELO/EHLO parameter string:
#|
#|  if (state->always_reject == 1) return REJECT;
#|  if (state->always_freeze == 1) return FREEZE;
#|  if (state->always_accept == 1) return ACCEPT;
#|
#|  if (HELO-name of SMTP client has 'REJECTNET +' attribute) then
#|   any further conversation refused
#|   [state->always_reject = 1; return REJECT;]
#|  if (HELO-name of SMTP client has 'FREEZENET +' attribute) then
#|   we present happy face, but always put the messages into a freezer..
#|   [state->always_freeze = 1; return FREEZE;]
#|  default: return ACCEPT
#|
#| MAIL FROM address:
#|
#|  set state->rcpt_nocheck  = 0;
#|  set state->sender_reject = 0;
#|  set state->sender_freeze = 0;
#|
#|  if (state->always_reject == 1) return REJECT;
#|  if (state->always_freeze == 1) return FREEZE;
#|  if (state->always_accept == 1) return ACCEPT;
#|
#|  if (sender's address has 'REJECTSOURCE +' attribute) then
#|   sender rejected, any further conversation refused
#|   [state->always_reject = 1; return REJECT;]
#|  if (sender's address has 'FREEZESOURCE +' attribute) then
#|   we accept with the happy face, but place it into a freezer
#|   [state->always_freeze = 1; return FREEZE;]
#|  when (sender's address is not in policy-db, continue with sender's domain)
#|
#|  if (sender's domain is not in policy-db) then
#|    return ACCEPT
#|
#|  if (sender's domain has 'REJECTSOURCE +' attribute) then
#|   sender rejected, any further conversation refused
#|   [state->sender_reject = 1; return REJECT;]
#|  if (sender's domain has 'FREEZESOURCE +' attribute) then
#|   we accept with the happy face, but place it into a freezer
#|   [state->sender_freeze = 1; return FREEZE;]
#|  if (sender's domain has 'RELAYCUSTOMER +' attribute) then
#|   DANGER ! DANGER !
#|   We will accept all destination addresses for this MAIL FROM,
#|   except those that are explicitely blocked, of course..
#|   [state->rcpt_nocheck = 1; return ACCEPT;]
#|  if (sender's domain has 'SENDEROKWITHDNS +' attribute) then
#|    verify that is DNS data for the target domain.  If yes, return ACCEPT;
#|    if not, return SOFTREJECT
#|  if (sender's domain has 'SENDEROKWITHDNS -' attribute) then
#|    verify that is DNS data for the target domain.  If yes, return ACCEPT;
#|    if not, return REJECT
#|  else
#|    return ACCEPT
#|
#| RCPT TO address:
#|
#|  if (state->always_reject == 1) return REJECT;
#|  if (state->sender_reject == 1) return REJECT;
#|  if (state->always_freeze == 1) return FREEZE;
#|  if (state->sender_freeze == 1) return FREEZE;
#|  if (state->always_accept == 1) return ACCEPT;
#|
#|  if (recipient address has 'RELAYTARGET +' attribute) then
#|    return ACCEPT
#|  if (recipient address has 'RELAYTARGET -' attribute) then
#|    return REJECT
#|  if (recipient address has 'FREEZE +' attribute) then
#|    we accept with the happy face, but place it into a freezer
#|    [status->sender_freeze = 1; return FREEZE;]
#|  if (recipient address has 'TEST-RCPT-DNS-RBL +' attribute) then
#|    return REJECT if have state->rblmsg
#|
#|  if (recipient's domain has 'RELAYTARGET +' attribute) then
#|    return ACCEPT
#|  if (recipient's domain has 'RELAYTARGET -' attribute) then
#|    return REJECT
#|  if (recipient's domain has 'FREEZE +' attribute) then
#|    we accept with the happy face, but place it into a freezer
#|    [status->sender_freeze = 1; return FREEZE;]
#|
#|  if (recipient domain has 'TEST-RCPT-DNS-RBL +' attribute) then
#|    return REJECT if have state->rblmsg
#|
#|
#|  If (state->rcpt_nocheck  == 1) return ACCEPT;
#|
#|  If (recipient's domain has 'ACCEPTIFMX +' attribute) then
#|    Verify that we are MX for the target domain.  If yes, return ACCEPT;
#|    If not, return SOFTREJECT
#|  If (recipient's domain has 'ACCEPTIFMX -' attribute) then
#|    Verify that we are MX for the target domain.  If yes, return ACCEPT;
#|    If not, return REJECT
#|  If (recipient's domain has 'ACCEPTIFDNS +' attribute) then
#|    Verify that we are MX for the target domain.  If yes, return ACCEPT;
#|    If not, return SOFTREJECT
#|  If (recipient's domain has 'ACCEPTIFDNS -' attribute) then
#|    Verify that we are MX for the target domain.  If yes, return ACCEPT;
#|    If not, return REJECT
#|  Else
#|    return ACCEPT
#| 
#| ------
#|
