# vim:set ft=exim noet nowrap ts=8 sw=2:

# 20220402 @cyme notes {at} notes.for.sabi.co.UK

# This file is divided into several parts, all but the last of which are
# terminated by a line containing the word "end". The parts must appear
# in the correct order, and all must be present (even if some of them are
# in fact empty). Blank lines, and lines starting with # are ignored.

# MAIN CONFIGURATION SETTINGS

exim_user			=EXIM_USER
exim_group			=EXIM_GROUP

# If you are running Exim under its own uid (recommended), then you should 
# set up that uid as a trusted user by de-commenting the following and
# changing the name if necessary.

trusted_users			=root:EXIM_USER
trusted_groups			=root:MAIL_GROUP:EXIM_GROUP

.ifdef TLS_PRIVATEKEY
.ifdef TLS_USER
daemon_smtp_ports		=25:465:587
# Beware however that this is only for server mode, these have to be
# repeated for each transport that needs to connect to an SMTP server
# in client TLS mode. http://www.credentia.cc/certs/howto/exim.html
# Also some syntax is different between OpenSSL or GNU/TLS:
#   http://www.exim.org/exim-html-current/doc/html/spec_html/index.html#toc0296
tls_on_connect_ports		=465
.else
daemon_smtp_ports		=25:587
.endif

log_selector			=+tls_peerdn
#log_selector			=+dkim_verbose
tls_advertise_hosts		=*
#tls_try_verify_hosts		=*
#gnutls_compat_mode		=true
#tls_dhparam			=ike23
tls_verify_certificates		=TLS_CACERT
tls_certificate			=TLS_CERTIFICATE
tls_privatekey			=TLS_PRIVATEKEY
.endif

received_header_text		="Received: \
  ${if def:sender_rcvhost\
    {from ${sender_rcvhost}}\
    {${if def:sender_ident {${sender_ident}}}\
     ${if def:sender_helo_name {(HELO ${sender_helo_name})}}}}\n\
  \tby ${primary_hostname} \
    ${if def:received_protocol {with ${received_protocol}}}\
    ${if def:tls_cipher {(Cipher ${tls_cipher})}}\
    ${if def:tls_peerdn {(PeerDN ${tls_peerdn})}}\
    Exim ${version_number}\n\
  \tid ${message_id}\
    ${if def:authenticated_id {by authid <${authenticated_id}>}}\
    ${if def:sender_host_authenticated {with ${sender_host_authenticated}}}\
  ${if def:received_for {\n\tfor <${received_for}>}}"

# The default for 'acl_smtp_etrn', 'acl_smtp_expn', 'acl_smtp_vrfy',
# and 'acl_smtp_rcpt' is 'deny'.

# https://serverfault.com/a/644397
# https://serverfault.com/a/614678

#acl_not_smtp			=
#acl_smtp_connect		=
acl_smtp_starttls		=accept
acl_smtp_auth			=acl_check_auth
#acl_smtp_etrn			=
#acl_smtp_helo			=
acl_smtp_expn			=acl_check_local
acl_smtp_vrfy			=accept
acl_smtp_mail			=acl_check_mail_from
acl_smtp_rcpt			=acl_check_rcpt_to
#acl_smtp_data			=acl_check_data

allow_domain_literals		=true
percent_hack_domains		=

host_lookup			=!*
#helo_verify_hosts		=
#helo_try_verify_hosts		=
#helo_accept_junk_hosts		=
#host_reject_connection		=

rfc1413_hosts			=!*
rfc1413_query_timeout		=30s

# This option unfreezes frozen bounce messages after two days, tries
# once more to deliver them, and ignores any delivery failures.
ignore_bounce_errors_after	=2d

# This option cancels (removes) frozen messages that are older than a week.
timeout_frozen_after		=7d

queue_only			=false
#queue_only_file		=/var/run/ppp-down
.ifdef QUEUEING
queue_domains			=!+local_domains
queue_smtp_domains		=!+local_domains
.endif

#smtp_verify			=true
smtp_accept_max			=10
smtp_accept_max_per_host	=3
smtp_accept_queue		=8
smtp_accept_queue_per_connection=80
smtp_accept_reserve		=3
smtp_reserve_hosts		=+local_domains

# No local deliveries will ever be run under the uids of these users.

#never_users			=root

keep_environment		=
add_environment			=

 log_file_path			=syslog
#log_file_path			=/var/log/exim/%s.log

########################################################################

begin acl

# Some bits inspired by: http://ns2.Wananchi.com/~wash/RT2/configure.txt
# Lots of ACL examples here: http://Marc.Merlins.org/linux/exim/

acl_check_local:

  accept authenticated		=*

  accept hosts			=:

  accept hosts			=+relay_from_hosts

acl_check_auth:

# accept condition		=${if eq {${uc:${smtp_command_argument}}}{CRAM-MD5} {yes}{no}}

  accept
    warn log_message		=AUTH: Verified TLS peer "dn=$tls_peerdn"
    encrypted			=*
    condition			=$tls_certificate_verified

  deny
    message			=AUTH: Authentication requires TLS encryption or CRAM-MD5

acl_check_mail_from:

  # http://www.exim.org/static/doc/security/CVE-2019-15846.txt
  # to be prepended to your mail acl (the ACL referenced
  # by the acl_smtp_mail main config option)
# deny condition		=${if eq{\\}{${substr{-1}{1}{$tls_in_sni}}}}
  deny condition		=${if eq{\\}{${substr{-1}{1}{$tls_in_peerdn}}}}

  deny
    message			=MAIL FROM: Only ASCII can be used in envelope sender\n\
				 (see RFC 2821, section 4.1.2)
    senders			=\N[\x80-\xFF]\N

  deny
    message			=MAIL FROM: "$sender_address" has invalid $sender_verify_failure
    !verify			=sender

.ifdef FILE_DENY_F
  # Check the sender.
  deny
    message			=MAIL FROM: No more space
    senders			=lsearch*@;FILE_DENY_F
.endif

  accept

acl_check_rcpt_to:

  deny
    message			=RCPT_TO: Cannot have "@%!/|" in local part
    local_parts			=[@%!/|]

.ifdef FILE_ACCEPT_AF
  # Accept specific recipient address/sender address combinations.
  accept
    senders			=${lookup{${local_part}@${domain}} \
				  lsearch*@{FILE_ACCEPT_AF}}
.endif

.ifdef FILE_DENY_A
  # Deny specific recipient addresses.
  deny
    message			=RCPT_TO: Connection fault
    recipients			=lsearch*@;FILE_DENY_A
.endif

# warn
#   message			=X-Blacklisted-At: ${dnslist_domain}
#   dnslists			=blackholes.mail-abuse.org\
#				 :dialup.mail-abuse.org

# defer
#   message			=Try again later

  # Check who has connected.

  accept
    hosts			=:
    control			=submission/sender_retain
    control			=dkim_disable_verify

  accept
    hosts			=+relay_from_hosts
    control			=submission/sender_retain
    control			=dkim_disable_verify

  accept
    hosts			=+auth_relay_hosts
    authenticated		=*
    control			=submission/sender_retain
    control			=dkim_disable_verify

  # Check the destination.

  accept domains		=+relay_to_domains

  accept domains		=+local_domains

.ifdef DKIM_RECEIVE
  warn
    control			=dkim_disable_verify
.endif

  require
    message			=RCPT_TO: Invalid recipient "$acl_verify_message"
    verify			=recipient

  defer
    ratelimit			=7/1m/$recipients
    message			=RCPT_TO: Rate limit exceeded for $recipients: $sender_rate/$sender_rate_period (max $sender_rate_limit)

  deny
    message			=RCPT_TO: Relay not permitted

acl_check_data:

  deny
    message			=DATA: Only ASCII allowed in 'Subject:' header.\n\
 				 (see RFC 2822, sections 3.6.5, 2.2.1)
    condition			=${if match {${h_Subject:}}{\N[\x80-\xFF]\N}\
 				  {yes}{no}}

  deny
    message			=DATA: Only ASCII allowed in 'From:' header.\n\
 				 (see RFC 2822, sections 3.4, 3.2.4, 3.2.5)
    condition			=${if match {${h_From:}}{\N[\x80-\xFF]\N}\
 				  {yes}{no}}

  accept

########################################################################

begin routers

# ROUTERS CONFIGURATION
# ORDER MATTERS GREATLY HERE

# Possible routers:
# allow_accept	Always accepts an address. It has no private options.
# dnslookup	Routes by DNS lookup (descended from lookuphost).
# ipliteral	Routes IP literal addresses (unchanged).
# iplookup	Special-purpose lookup router (unchanged).
# manualroute	Routes domains from explicit data (descended from domainlist).
# queryprogram	Routes addresses by running a program (detail changed).
# redirect	Redirects addresses; handles all the functions previously
#		supported by aliasfile, forwardfile, and smartuser without
#		a transport.

# Possible router conditions in the order in which they are tested:

# 1) verify status, expn status, domains, local_parts, check_local_user
# 2) debug_print
# 3) senders, require_files, condition

# First we alias addresses which include domains, as this may change
# the delivery domain, from example from remote to local or viceversa.
# The aliasing routers are in order of most specific to most generic.

# Now we know the real delivery domain, and first we route to remote domains.

.ifdef FILE_ALIAS_A2A
# Alias a single address to another single address.

alias_address_to_address:
  debug_print			="R: ${local_part}@${domain}: address to address"
  driver			=redirect
  require_files			=FILE_ALIAS_A2A
  data				=${lookup {${local_part}@${domain}} \
				    lsearch{FILE_ALIAS_A2A}}
#				    partial1-lsearch*@{FILE_ALIAS_A2A}}
  repeat_use			=false
  local_part_suffix		=_*
  local_part_suffix_optional	=true
  qualify_preserve_domain	=false
  check_local_user		=false
  allow_fail			=true
  allow_defer			=true
  file_transport		=address_file
  pipe_transport		=address_pipe
.endif

.ifdef FILE_ALIAS_D2A
# Alias a whole domain to a single address.

alias_domain_to_address:
  debug_print			="R: ${local_part}@${domain}: domain to address"
  driver			=redirect
  require_files			=FILE_ALIAS_D2A
  data				=${lookup {${domain}} \
				    partial1-lsearch*{FILE_ALIAS_D2A}}
  repeat_use			=false
  qualify_preserve_domain	=false
  check_local_user		=false
  allow_fail			=true
  allow_defer			=true
  file_transport		=address_file
  pipe_transport		=address_pipe
.endif

.ifdef FILE_ALIAS_D2D
# Alias a whole domain to another whole domain, with the same local part.

alias_domain_to_domain:
  debug_print			="R: ${local_part}@${domain}: domain to domain"
  driver			=redirect
  require_files			=FILE_ALIAS_D2D
  data				=${lookup {${domain}} \
				    partial1-lsearch*{FILE_ALIAS_D2D} \
				      {${local_part}@${value}} {}}
  repeat_use			=false
  qualify_preserve_domain	=false
  check_local_user		=false
  allow_fail			=true
  allow_defer			=true
  forbid_file			=true
  forbid_pipe			=true
.endif

# Lastly, we alias it to some smarthost.

.ifdef FILE_ALIAS_D2HOST
# We want to route some domains to a ''smart'' (gw) host.

domain_smarthost:
  debug_print			="R: ${local_part}@${domain}: smarthost"
  driver			=manualroute
  domains			=!+local_domains
  require_files			=FILE_ALIAS_D2HOST
  route_data			=${lookup {${domain}} \
				    partial1-lsearch*{FILE_ALIAS_D2HOST}}
  host_find_failed		=defer
  same_domain_copy_routing	=true
  verify			=false
  transport			=remote_smtp
.ifdef SEND_ERRORS_TO
  errors_to			=SEND_ERRORS_TO
.endif
  # Setting this to 'false' means only smarthost routing is allowed.
  more				=true
.endif

# Now we know the real delivery domain, and first we route to remote domains.

# This router handled IP literal addresses @[a.b.c.d], which is
# required by the relevant RFCs and is still useful.

domain_literal:
  debug_print			="R: ${local_part}@${domain}: domain literal"
  driver			=ipliteral
  domains			=!+local_domains
  transport			=remote_smtp
.ifdef SEND_ERRORS_TO
  errors_to			=SEND_ERRORS_TO
.endif

# This router routes to remote hosts over SMTP using a DNS lookup
# with default options.

dnslookup_relay:
  debug_print			="R: ${local_part}@${domain}: DNS MX relay"
  driver			=dnslookup
  domains			=+relay_to_domains
  same_domain_copy_routing	=yes
  transport			=remote_smtp
.ifdef SEND_ERRORS_TO
  errors_to			=SEND_ERRORS_TO
.endif
  more				=false

dnslookup:
  debug_print			="R: ${local_part}@${domain}: DNS MX non relay"
  driver			=dnslookup
  domains			=!+local_domains
  ignore_target_hosts		=0.0.0.0/32:127.0.0.0/8:192.0.2.0/24:240.0.0.0/4
.ifdef IPV4_ONLY_DOMAINS
  ipv4_only			=IPV4_ONLY_DOMAINS
.endif
  transport			=remote_smtp
.ifdef SEND_ERRORS_TO
  errors_to			=SEND_ERRORS_TO
.endif
  more				=false

# OK, the domain now is guaranteed to be local, because the preceding
# routers handled all possible cases of non local domains.

# From this point onwards we only really care about local parts,
# as we assume that all local domains share the same list of users.

# Classic mailing lists: alias a local part to a list of addresses in a file.

alias_user_to_list:
  debug_print			="R: alias to '/etc/list/${local_part}'"
  driver			=redirect
  file				=/etc/list/${local_part}
  include_directory		=/etc/list
  local_part_prefix		=list-
  check_local_user		=false
  allow_fail			=true
  allow_defer			=true
  forbid_file			=true
  forbid_pipe			=true
  one_time			=true

# Classic aliases: alias a local part to a single address.

alias_user_to_address:
  debug_print			="R: alias ${local_part} in '/etc/aliases'"
  driver			=redirect
  data				=${lookup {${local_part}} lsearch{/etc/aliases}}
  local_part_suffix		=_*
  local_part_suffix_optional	=true
  check_local_user		=false
  user				=EXIM_USER
  group				=MAIL_GROUP
  allow_fail			=true
  allow_defer			=true
  file_transport		=address_file
  pipe_transport		=address_pipe

# Now the local part must be the address of some user...

userforward:
  debug_print			="R: alias in '~${home}/.forward'"
  driver			=redirect
  file				=${home}/.forward
  check_ancestor		=true
  check_local_user		=true
  verify			=false
  expn				=false
# filter			=true
  file_transport		=address_file
  pipe_transport		=address_pipe
  reply_transport		=address_reply

# The domain is local and neither the domain nor the local part are aliased...

# If it is root, we deliver the mail without further ado

toroot:
  debug_print			="R: deliver to 'root'"
  driver			=accept
  local_parts			=root
  transport			=local_delivery

# It's a normal user mailbox...

.ifdef BOGOFILTERING
# So first check whether is has been filtered for spam, if it has not,
# then do so. 
bogofilter:
  debug_print			="R: pass to 'bogofiltering' transport'"
  driver			=accept
  condition			=${if or \
				   {{def:h_X-SpamFiltered:}\
				    {def:h_X-BogoFiltered:}\
				    {def:h_X-UWA-UCE-Check:}\
				    {def:h_X-Spam:}} {no}{yes}}
  check_local_user
  verify			=false
  expn				=false
  transport			=bogofiltering
.endif

# If the user is on vacation, send an automatic reply now,
# and continue as if it had not matched here.

onvacation:
  debug_print			="R: check for '${home}/.vacation'"
  driver			=accept
  condition			=${if eq {${h_X-Spam}}{Yes} {no} {yes}}
  require_files			="${home}/.vacation"
  unseen			=true
  transport			=vacationing

# If the user has a procmailrc file we pass the mail to
# procmail

doprocmail:
  debug_print			="R: check for '${home}/.procmailrc'"
  driver			=accept
  require_files			="${home}/.procmailrc"
  transport			=procmail
  more				=false

# else we append it directly to the user's mailbox

localuser:
  debug_print			="R: local delivery for '${local_part}'"
  driver			=accept
  caseful_local_part		=true
  local_part_suffix		=_*
  local_part_suffix_optional	=true
  check_local_user		=true
  transport			=local_delivery
  more				=false

# It's not an alias, a mailing list, root, or a user; is it
# Superman? No, it's a bad address

#dosink:
#  driver			=smartuser
#  verify			=false
#  transport			=unknown

########################################################################

begin transports

# TRANPORTS CONFIGURATION

# Here are some pretty standard transports

# http://www.exim.org/exim-html-current/doc/html/spec_html/ch33.html

remote_smtp:
# debug_print			="T: connect to remote SMTP"
  debug_print			="T: SMTP dkim_domain=$dkim_domain dkim_private_key=$dkim_private_key"
  driver			=smtp
.ifdef SMTP_SOURCE_ADDRESSES
  interface			=SMTP_SOURCE_ADDRESSES
.endif
  connection_max_messages	=500
  #rcpt_max			=100
.ifdef SEND_RETURN_PATH
  return_path			=SEND_RETURN_PATH
.endif
.ifdef FILE_SENDCRAM
  hosts_try_auth		=*
.endif

  hosts_require_tls		=SMTP.sabi.co.UK
# hosts_require_tls		=*
.ifdef TLS_SEND
  # in TLS mode. http://www.madboa.com/geek/exim4-ssl-client/
  # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-encrypted_smtp_connections_using_tlsssl.html
  #gnutls_compat_mode		=true
  #tls_dhparam			=ike23
  tls_verify_certificates	=TLS_CACERT
  tls_certificate		=TLS_CERTIFICATE
  tls_privatekey		=TLS_PRIVATEKEY
  tls_tempfail_tryclear		=false
.endif

.ifdef DKIM_DOMAIN
    dkim_domain			=DKIM_DOMAIN
.endif
.ifdef DKIM_IDENTITY
    dkim_identity		=DKIM_IDENTITY
.endif
.ifdef DKIM_SELECTOR
  dkim_selector			=DKIM_SELECTOR
.endif
.ifdef DKIM_PRIVATE_KEY
  dkim_private_key		=DKIM_PRIVATE_KEY
.endif
.ifdef DKIM_CANON
  dkim_canon			=DKIM_CANON
.endif
.ifdef DKIM_STRICT
  dkim_strict			=DKIM_STRICT
.endif
.ifdef DKIM_SIGN_HEADERS
  dkim_sign_headers		=DKIM_SIGN_HEADERS
.endif

local_delivery:
  debug_print			="T: append to '/var/mail/${local_part}'"
  driver			=appendfile
  file				=/var/mail/${local_part}
  notify_comsat			=true
  envelope_to_add		=true
  return_path_add		=true
  delivery_date_add		=true
  group				=MAIL_GROUP
  mode				=0660

procmail:
  debug_print			="T: run 'procmail -d ${local_part}'"
  driver			=pipe
  command			="/usr/bin/procmail -d ${local_part}"

flexfax:
  debug_print			="T: run '| mailfax'"
  driver			=pipe
  command			="/usr/bin/mailfax"

unknown:
  debug_print			="T: run '| exiunknown'"
  driver			=pipe
  command			="/usr/sbin/exiunknown"
  ignore_status			=true
  return_output			=true
  user				=EXIM_USER
  group				=MAIL_GROUP

bogofiltering:
  debug_print			="T: pipe via 'bogofilter -e -p -l'"
  driver			=pipe
  command			=/usr/sbin/exim4 -oMr BogoFiltered -bS
  ignore_status			=false
  log_output			=true
  return_output			=false 
  return_fail_output		=true
  return_path_add		=false
  envelope_to_add		=false
  use_shell			=false
  use_bsmtp			=true
  batch_max			=8
  transport_filter		=/usr/bin/bogofilter -e -p -l
  headers_add			=X-BogoFiltered: Yes
  user				=EXIM_USER
  group				=MAIL_GROUP
  home_directory		="/tmp"
  current_directory		="/tmp"

vacationing:
  debug_print			="T: send contents of '${home}/.vacation'"
  driver			=autoreply
  file				="${home}/.vacation"
  to				="${return_path}"
  from				="${local_part}@${domain}"
  subject			="Re: ${header_subject}"
  text				="[User '${local_part}' vacation message]\n\n"
  once				="${home}/.vacation_sent"
  log				="${home}/.vacation_log"

# The transports address_pipe, address_file, address_directory and
# address_reply are used by exim internally, and their names are
# conventional (well-known to exim).

# address_pipe	is used for handling pipe addresses generated by alias
#		or .forward files.
# address_file	is used for handling file addresses generated by alias
#		or .forward files.
# address_directory is used for handling file addresses generated by alias
#		or .forward files if the path ends in "/".
# address_reply is used for handling autoreplies generated by the filtering
#		option of the forwardfile director.

address_pipe:
  debug_print			="T: internal: 'address_pipe'"
  driver			=pipe
  return_output			=true
  ignore_status			=true

address_file:
  debug_print			="T: internal: 'address_file'"
  driver			=appendfile
# notify_comsat			=true
  delivery_date_add		=true
  envelope_to_add		=true
  return_path_add		=true

address_directory:
  debug_print			="T: internal: 'address_directory'"
  driver			=appendfile
  message_prefix		=""

address_reply:
  debug_print			="T: internal: 'address_reply'"
  driver			=autoreply

########################################################################

begin retry

# RETRY CONFIGURATION

# This single retry rule applies to all domains and all errors. It specifies
# retries every 15 minutes for 2 hours, then increasing retry intervals,
# starting at 2 hours and increasing each time by a factor of 1.5, up to 16
# hours, then retries every 8 hours until 4 days have passed since the first
# failed delivery.

# Domain	       Error	   Retries
# ------	       -----	   -------

*		       *	   F,2h,15m; G,16h,2h,1.5; F,4d,8h

########################################################################

begin rewrite

# REWRITE CONFIGURATION

########################################################################

begin authenticators

# http://kb.philross.co.uk/2008/03/15/configuring-exim-to-use-gmail-as-a-smarthost/
# http://wiki.exim.org/AuthenticatedSmtpUsingPamAndPasswords
# https://secure.grepular.com/Exim_Client_Authentication_Recipe

# Authenticators user variables 'server_*' when receiving incoming mail,
# and 'client_*' when forwarding mail to another MTA that requires authentication.

# http://www.exim.org/exim-html-current/doc/html/spec_html/ch35.html

# SENDCRAM:	HOST:USER:PLAIN
# USERCRAM:	USER:MD5:PLAIN

cram:
  driver			=cram_md5
  public_name			=CRAM-MD5
# Authenticate this server as a client to another server.
.ifdef FILE_SENDCRAM
# client_condition		=${if def:tls_out_cipher}
  client_name			=${lookup{$host} lsearch{FILE_SENDCRAM} {${extract{1}{::}{$value}}} fail}
  client_secret			=${lookup{$host} lsearch{FILE_SENDCRAM} {${extract{2}{::}{$value}}} fail}
.endif
# Authenticate a client to this server.
.ifdef FILE_USERCRAM
  server_advertise_condition	=yes
# server_condition		=${if def:tls_in_cipher}
  server_set_id			=$auth1
  server_secret			=${lookup{$auth1} lsearch{FILE_USERCRAM} {${extract{2}{::}{$value}}} fail}
.endif

# http://www.exim.org/exim-html-current/doc/html/spec_html/ch34.html#SECTplainserver

# In the following the use of 'crypteq' means that the stored passwords
# must be of the form "{md5}5f4dcc3b5aa765d61d8327deb882cf99".

# It is really important to ensure that 'lookup' fails if its value is used:
# http://www.exim.org/exim-html-4.66/doc/html/FAQ-html/FAQ_7.html#TOC259
# {${lookup ... {$value}fail}}

# SENDPASS:	HOST:USER:PLAIN
# USERPASS:	USER:MD5:PLAIN

plain:
  driver			=plaintext
  public_name			=PLAIN
# Authenticate this server as a client to another server.
.ifdef FILE_SENDPASS
  client_condition		=${if def:tls_out_cipher}
  client_ignore_invalid_base64	=yes
# client_send			=${lookup {$host} lsearch{FILE_SENDPASS} {$value} fail}
  client_send			=${lookup {$host} lsearch{FILE_SENDPASS} {^${extract{1}{::}{$value}}^${extract{2}{::}{$value}}} fail}
.endif
# Authenticate a client to this server.
  server_set_id			=$auth1
  server_advertise_condition	=${if def:tls_in_cipher}
  server_prompts		=PLAIN DATA
.ifdef FILE_USERPASS
#   server_condition		=${lookup {$auth1} lsearch{FILE_USERPASS} {${if crypteq{$auth2}{${extract{1}{::}{$value}}} {yes}{no}}} {no}}
    server_condition		=${lookup {$auth1} lsearch{FILE_USERPASS} {${if eq{$auth2}{${extract{2}{::}{$value}}} {yes}{no}}} {no}}
.else
.ifdef HAS_PAM
  server_condition		=${if pam{$auth2:${sg{$auth3}{:}{::}}} {yes}{no}}
.else
  server_condition		=no
.endif
.endif

login:
  driver			=plaintext
  public_name			=LOGIN
# Authenticate this server as a client to another server.
.ifdef FILE_SENDPASS
  client_condition		=${if def:tls_out_cipher}
# client_send			=${lookup {$host} lsearch{FILE_SENDPASS} {$value} fail}
  client_send			=${lookup {$host} lsearch{FILE_SENDPASS} {\: ${extract{1}{::}{$value}} \: ${extract{2}{::}{$value}}} fail}
.endif
# Authenticate a client to this server.
  server_advertise_condition	=${if def:tls_in_cipher}
  server_prompts		=Username:: : Password::
  server_set_id			=$auth1
.ifdef FILE_USERPASS
#   server_condition		=${lookup {$auth1} lsearch{FILE_USERPASS} {${if crypteq{$auth2}{${extract{1}{::}{$value}}} {yes}{no}}} {no}}
    server_condition		=${lookup {$auth1} lsearch{FILE_USERPASS} {${if eq{$auth2}{${extract{2}{::}{$value}}} {yes}{no}}} {no}}
.else
.ifdef HAS_PAM
    server_condition		=${if pam{$auth1:${sg{$auth2}{:}{::}}} {yes}{no}}
.else
.ifdef LDAP_AUTHDN
  server_condition		=${if and{ \
				    {!eq{$auth1}{}} \
				    {ldapauth \
				      {user="cn=${quote_ldap_dn:$auth1},LDAP_AUTHDN" \
					pass=${quote:$auth2} ldap://LDAP_AUTHSV/}}} {yes}{no}}
  server_set_id			=uid=$auth1,LDAP_AUTHDN
.else
  server_condition		=no
.endif
.endif
.endif
