# These functions are used by the smtpserver to do synchronous address checking. quadprint (quad) { #| This is a prettyprinter for address quads. What it prints is what someone #| doing a VRFY or EXPN query to the SMTP server will see. local text case $(channel $quad) in local) sift "$(user $quad)" in [|/].* text="local delivery for" ;; .* text=$(login2uid $(user $quad)) # ignore return value if text="$(fullname $(user $quad))"; then text="$text" else if text="$(fullname $(recase -l $(user $quad)))"; then text="$text" else text="550 no such user:" fi fi ;; tfis ;; usenet) text="newsgroup:" ;; *) text="$(channel $quad) delivery" case "$(host $quad)" in -|'') text="$text for" ;; *) text="$text to $(host $quad) for" ;; esac ;; esac echo "$text <$(user $quad)>" } server (key) { #| The smtpserver program starts the router in interactive mode and runs this #| function to interface with the rest of the configuration code. The key #| specifies the semantics of the additional arguments provided by the #| smtpserver. The key values are: init, to, from, verify, and expand. local a A B A=$(newattribute default_attributes type sender) B=$(newattribute default_attributes type expandsender) #| In doing a VRFY operation, it is not desired to do any alias expansion. #| This can be avoided by modifying the attributes of default_attributes to #| shortcircuit alias expansion. It is assumed that default_attributes is #| otherwise proper for the purpose. The value specified for the privilege #| level should be appropriate. case $key in to|from|verify|expand) a="$1" sift "$a" in <(.+)> a="\1" ;; tfis if rfc822syntax "$a"; then ; else echo "501 illegal address syntax: <$a>" return fi ;; esac case $key in init) # If you want to log incoming connections, it can be done here #echo server "$@" >> /tmp/server # turn off fliename globbing set -f # redefine the log function log () { } ;; hello) rejected= accepted= set none $@ ; shift # $1=rhostname $2=ihostaddr if [ $(getattrib rejectnet "$2") = "+" -o \ $(getattrib rejectnet "$1") = "+" ]; then rejected=true echo "501 5.7.1 You are not authorized to send mail." return fi if [ $(getattrib relaycustnet "$2") = "+" -o \ $(getattrib relaycustnet "$1") = "+" ]; then accepted=true echo "250 We accept your mails." return fi echo "250 Seems to be" ;; to|from) a="$(router "$1" default_attributes)" for i in $(elements $a) do for j in $(elements $i) do case $(channel $j) in error) echo "550 unresolvable address: <$1>" return ;; esac #| If any of the addresses in the expansion gave errors, we reject the #| original address. The lack of distinction between different kinds of errors #| may be inadequate in some situations. done done domain= tsift "$1" in .*@([^@]*) domain="\1" break ;; .* echo "250 Ok" return ;; tfist case $key in from) if [ X"$rejected" = Xtrue -o \ $(getattrib rejectsource $domain) = "+" ]; then rejected=true echo "501 5.7.1 You are not authorized to send mail." return fi if [ X"$accepted" = Xtrue -o \ $(getattrib relaycustomer $domain) = "+" ]; then accepted=true echo "250 2.7.1 Sender accepted." return fi ;; to) if [ X"$rejected" = Xtrue ]; then echo "501 5.7.1 You are not authorized to send mail." return fi if [ $(getattrib relaytarget $domain) = "+" -o \ X"$accepted" = Xtrue ]; then echo "250 2.7.1 Recipent accepted." return else echo "501 5.7.1 This host is not relaying for '$domain'. Recipient rejected." return fi ;; esac echo "250 Ok (verified)" ;; verify) a="$(router "$1" $A)" #| Invoke the router function with alias expansion turned off. for i in $(elements $a) do for j in $(elements $i) do quadprint $j done done ;; expand) a="$(router "$1" $B)" #| Invoke the router function with alias expansion enabled. for i in $(elements $a) do for j in $(elements $i) do quadprint $j done done ;; esac } # initializing policy database if [ -f $MAILSHARE/db/policy.dir ]; then relation -lt ndbm -d longestmatch -f $MAILSHARE/db/policy policy else policy () { return 1 } fi getattrib (attrib,object) { if [ X"$object" = X ]; then echo 'empty_object' return 1 fi for loopcnt in 0 1 2 3 4 5 6 7 8 9 # to prevent endless =tag loops do attributelist=$(list $(policy "$object") ) value=$(get attributelist "$attrib") if [ X$value != X ]; then echo $value # attribute specified return 0 fi object=$(get attributelist =) # "See at $object" if [ X$object = X ]; then echo . # unspecified return 0 fi done echo 'too_many_indirection' return 1 }