divert(-1) # # Copyright (c) 2004 Victor Ustugov # This hack is under BSD License # Redistributions of source code must retain the above copyright notice # # hacks disscussion's maillist - http://www.mta.org.ua/mailman/listinfo/sendmail-conf # # # Check HELO FQDN # # проверка разрешения имен аргумента команды EHLO/HELO # dnl # механизм проверки следующий: dnl # 1. поизводится получение A записи аргумента команды HELO dnl # 2. полученная A запись сравнивается с A записью рилея dnl # 3. если A записи равны, проверка оканчивается успешно dnl # 4. если A записи не равны, сравниваются доменные части HELO и PTR записи рилея dnl # 5. если они не равны, возвращается сообщение об ошибке dnl # 6. если доменные части HELO и PTR записи рилея равны, то сравниваются номера dnl # сетей класса C полученной ранее A записи HELO и A записи рилея dnl # 7. если номера сетей равны (A запись HELO и A запись рилея находятся в одной dnl # сети класса C), то проверка оканчивается успешно dnl # 8. в противном случае возвращается сообщение об ошибке dnl # dnl # исключения необходимо перечислить в переменной confCHECK_HELO_FQDN_SKIP dnl # возможные значения: dnl # LOCALHOST - исключения сделаны для ${client_addr}, находящихся в $w в виде IP адреса в dnl # квадратных скобках, т. е. если клиент находится на том же хосте, что и сервер dnl # AUTH - исключения из проверки для авторизованных отправтелей dnl # OUTGOING - исключения из проверки исходящих сообщений (A или PTR запись рилея указана dnl # в access_db с квалификатором Connect или без него и со значением RELAY) dnl # подробнее о понятии "исходящим сообщений см. HACK(`is_outgoing') dnl # ACCESS_DB - исключение из проверки для хостов, IP адрес, сеть, имя хоста или доменная dnl # зона которых указана в access_db с квалификатором Connect и значением dnl # OK или RELAY. при использовании ACCESS_DB можно не использовать OUTGOING dnl # SPAMFRIEND - исключение из проверки для получателей, указанных в access_db с dnl # квалификатором Spam и значением FRIEND dnl # dnl # несколько значений можно указывать через пробел dnl # пример: dnl # define(`confCHECK_HELO_FQDN_SKIP', `LOCALHOST OUTGOING AUTH') dnl # divert(0) VERSIONID(`$Id: check_helo_fqdn.m4,v 8.12-0.06 2004/07/23 15:10:19 corvax Exp $')dnl divert(-1) dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `ACCESS_DB', ` ifdef(`_ACCESS_TABLE_', `', ` errprint(`*** ERROR: HACK(check_helo_fqdn) requires FEATURE(access_db) ')') ') dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `SPAMFRIEND', ` ifdef(`_DELAY_CHECKS_', `', ` errprint(`*** ERROR: HACK(check_helo_fqdn) with SPAMFRIEND in confCHECK_HELO_FQDN_SKIP requires FEATURE(delay_checks, FRIEND) ')')') HACK(`precheck_envelope')dnl dnl dnl LOCAL_CONFIG dnl dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `OUTGOING', `dnl HACK(`is_outgoing')dnl ') dnl dnl LOCAL_RULESETS dnl dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `SPAMFRIEND', ` SLocal_check_rcpt # R $* $: $>Parse0 $>3 $1 R $+ < @ $+ > $* $: $1 < @ $2 > $3 $| $1@$2 $| R $* $| $+@$+ . $| $: $1 $| $2@$3 $| R $* $| $+@$+ $| $: $1 $| $2@$3 $| $>SearchList $| <> R $* $| $+@$+ $| $: $1 $| $2@$3 dnl R $* $| $* $| $* $: $1 $| $2 $| $>CheckHeloFQDN $&s $| $&{client_name} $| $&{client_addr} R $* $| $* $| $#$* $#$3 R $* $| $* $| $* $| $* $| $* $: $1 R $* $| $* $: $1 ', ` SLocal_check_mail R $* $: $1 $| $>CheckHeloFQDN $&s $| $&{client_name} $| $&{client_addr} R $* $| $#$* $#$2 R $* $| $* $| $* $| $* $: $1 R $* $| $* $: $1 ') SCheckHeloFQDN dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `AUTH', `dnl # skip checks for authentificated senders R $* $| $* $| $* $: $&{auth_type} $| $1 $| $2 $| $3 R $+ $| $* $| $* $| $* $@ SKIP_AUTH R $* $| $* $| $* $| $* $: $2 $| $3 $| $4 ') dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `LOCALHOST', ` # skip checks for localhost R $* $| $=w $| $* $@ SKIP_LOCAL # подставляем IP адрес рилея в квадратных скобках R $* $| $* $| $* $: $1 $| $2 $| [ $3 ] # если он присутствует в $w (т. е. является адресом интерфеса этого же хоста), не производим проверку helo R $* $| $* $| [127.0.0.1] $@ SKIP_LOCAL R $* $| $* $| $=w $@ SKIP_LOCAL R $* $| $* $| [ $+ ] $: $1 $| $2 $| $3 ') dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `ACCESS_DB', ` # skip checks for host addresses/networks which have OK or RELAY value in access_db R $* $| $* $| $+ $: $1 $| $2 $| $3 $| $>A <$3> <> R $* $| $* $| $+ $| <$={Accept}> <> $@ SKIP_ACCESSDB R $* $| $* $| $+ $| $* $: $1 $| $2 $| $3 # skip checks for hostname/domains which have OK or ACCEPT value in access_db R $* $| $+ $| $+ $: $1 $| $2 $| $3 $| $>D <$2> <> R $* $| $+ $| $+ $| <$={Accept}> <> $@ SKIP_ACCESSDB R $* $| $+ $| $+ $| $* $: $1 $| $2 $| $3 ') dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `OUTGOING', `dnl # skip checks for outgoing messages R $* $| $* $| $* $: $&{IsOutgoing} $| $1 $| $2 $| $3 R $| $* $| $* $| $* $: $| $1 $| $2 $| $3 $>SetIsOutgoing R $| $* $| $* $| $* $: $&{IsOutgoing} $| $1 $| $2 $| $3 R YES $| $* $| $* $| $* $@ SKIP_OUTGOING R $* $| $* $| $* $| $* $: $2 $| $3 $| $4 ') dnl # try to resolve A record of HELO R $+ $| $* $| $* $: $1 $| $2 $| $3 $| $(dns_a $1 $) # if temporarily resolve problem occured R $+ $| $* $| $* $| $* $#TEMP $@ 4.7.1 $: "450 Access temporarily denied. Can not resolve A record of $1" # save A record of HELO R $+ $| $* $| $* $| $* $: $1 $| $2 $| $3 $(macro {HELO_A} $@ $4 $) # if resolving failed R $&{HELO_A} $| $* $| $* $#error $@ 5.7.1 $: "550 Name IP lookup failed for " $&{HELO_A} # add the dot to relay IP address R $* $| $* $| $* $: $1 $| $2 $| $3 . # compare relay IP address with A record of HELO R $* $| $* $| $&{HELO_A} $@ OK # mark line R $* $| $* $| $* $: $1 $| $2 $| $3 # save HELO domain part R $-.$+ $| $* $| $* $: $1.$2 $| $3 $| $4 $(macro {HELO_DOMAIN} $@ $2 $) # compare domain part of relay PTR record with HELO domain part R $* $| $- . $&{HELO_DOMAIN} $| $* $: $1 $| $2.$&{HELO_DOMAIN} $| $3 # return error message if they are not equal R $* $| $* $#error $@ 5.7.1 $: "550 Forged HELO used " $1 # calculate network number of A record of HELO (network C class) R $* $| $* $| $* $: $1 $| $2 $| $3 $| $&{HELO_A} R $* $| $* $| $* $| $-.$-.$-.$-. $: $1 $| $2 $| $3 $(macro {HELO_A} $@ $4.$5.$6 $) # compare relay network with nwteork of the A record of HELO R $* $| $* $| $&{HELO_A}.$-. $@ OK # return error message if they are not equal R $* $| $* $#error $@ 5.7.1 $: "550 Forged HELO used " $1 dnl