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 A record of HELO/EHLO # Проверка A записи аргумента команды EHLO/HELO # dnl # отказ от приема писем, A запись HELO/EHLO которых указана в access_db с dnl # квалификатором Helo_A и сообщением об ошибке. dnl # имеет смысл данную проверку использовать для отказа от приема сообщений, dnl # HELO/EHLO которых резолвится в адрес из частных, зарезервированных, dnl # служебных и других немаршрутизируемых сетей, перечисленных в RFC 3330 dnl # dnl # исключения необходимо перечислить в переменной confCHECK_HELO_A_SKIP dnl # возможные значения: dnl # LOCALHOST - исключения сделаны для ${client_addr}, перечисленных dnl # в $w в виде IP адреса в квадратных скобках, а также для dnl # ${client_name}, перечисленных в $w, т. е. если клиент dnl # находится на том же хосте, что и сервер dnl # AUTH - исключения из проверки для авторизованных отправтелей dnl # OUTGOING - исключения из проверки исходящих сообщений (A или PTR dnl # запись рилея указана в access_db с квалификатором dnl # Connect или без него и со значением RELAY) dnl # подробнее о понятии "исходящим сообщений см. HACK(`is_outgoing') dnl # ACCESS_DB - исключение из проверки для: dnl # 1. хостов, IP адрес, сеть, имя хоста или доменная зона dnl # которых указана в access_db с квалификатором dnl # HELO_A_SKIP_RELAY и значением OK или SKIP; dnl # 2. адресов и доменов получателей, указанных в access_db dnl # с квалификатором HELO_A_SKIP_RCPT со значением OK или SKIP dnl # SPAMFRIEND - исключение из проверки для получателей, указанных в dnl # access_db с квалификатором Spam и значением SPAMFRIEND dnl # dnl # несколько значений можно указывать через пробел dnl # пример: dnl # define(`confCHECK_HELO_A_SKIP', `LOCALHOST OUTGOING AUTH') dnl # divert(0) VERSIONID(`$Id: check_helo_a.m4,v 8.12-0.01 2004/08/22 11:07:52 corvax Exp $')dnl divert(-1) dnl ifdef(`confCHECK_HELO_A_SKIP', `', `define(`confCHECK_HELO_A_SKIP', `LOCALHOST AUTH OUTGOING SPAMFRIEND ACCESS_DB')') ifelse(len(X`'confCHECK_HELO_A_SKIP), `1', `define(`confCHECK_HELO_A_SKIP', `LOCALHOST AUTH OUTGOING SPAMFRIEND ACCESS_DB')') dnl ifelse_strstr(confCHECK_HELO_A_SKIP, `ACCESS_DB', ` ifdef(`_ACCESS_TABLE_', `', ` errprint(`*** ERROR: HACK(check_helo_a) requires FEATURE(access_db) ')') ') dnl ifelse_strstr(confCHECK_HELO_A_SKIP, `SPAMFRIEND', ` ifdef(`_DELAY_CHECKS_', `', ` errprint(`*** ERROR: HACK(check_helo_a) with SPAMFRIEND in confCHECK_HELO_A_SKIP requires FEATURE(delay_checks, FRIEND) ')')') HACK(`precheck_envelope')dnl dnl ifelse_strstr(confCHECK_HELO_A_SKIP, `OUTGOING', `dnl HACK(`is_outgoing')dnl ') dnl dnl LOCAL_RULESETS dnl dnl SLocal_check_rcpt # R $* $: $>Parse0 $>3 $1 R $+ < @ $+ > $* $: $1 < @ $2 > $3 $| $1@$2 R $* $| $+@$+ . $: $1 $| $2@$3 ifelse_strstr(confCHECK_HELO_A_SKIP, `SPAMFRIEND', ` R $* $| $+@$+ $: $1 $| $2@$3 $| $>SearchList $| <> R $* $| $+@$+ $| $* $: $1 R $* $| $+@$+ $| $* $: $1 $| $2@$3 ') ifelse_strstr(confCHECK_HELO_A_SKIP, `ACCESS_DB', ` R $* $| $+@$+ $: $1 $| $2@$3 $| $>SearchList $| <> R $* $| $+@$+ $| <$={Accept}> $* $: $1 R $* $| $+@$+ $| $* $: $1 R $* $| $+@$+ $| $* $: $1 $| $2@$3 ') R $* $| $* $: $1 $| $2 $| $>CheckHeloA $&s $| $&{client_name} $| $&{client_addr} R $* $| $* $| $#$* $#$3 R $* $| $* $: $1 SCheckHeloA dnl ifelse_strstr(confCHECK_HELO_A_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_A_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_A_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 $* $| $* $| $+ $| <> $@ 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 $* $| $+ $| $+ $| <> $@ SKIP_ACCESSDB R $* $| $+ $| $+ $| $* $: $1 $| $2 $| $3 ') dnl ifelse_strstr(confCHECK_HELO_A_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 ') # try to resolve A record of HELO/EHLO R $+ $| $* $| $* $: $1 $| $2 $| $3 $| $(dns_a $1 $) # if temporarily resolve problem occured R $+ $| $* $| $* $| $* $@ SKIP_TEMPFAIL # lookup IP address in access_db R $+ $| $* $| $* $| $-.$-.$-.$-. $: $1 $| $2 $| $3 $| $>A <$4.$5.$6.$7> <> R $* $| $* $| $* $| <$={Accept}> <> $@ SKIP_ACCESSDB_HELO_A R $* $| $* $| $* $| <> $@ SKIP_ACCESSDB_HELO_A # вывод сообщений об ошибках R $* $| $* $| $* $| <$*> $#error $@ 5.7.1 $: "554 Access denied. A record of HELO " $1 " cannot refer to private or special address space" R $* $| $* $| $* $| <$*> $#error $@ 5.7.1 $: $4 R $* $| $* $| $* $| <$*> $#error $@ 5.7.1 $: $4 R $* $| $* $| $* $| <$*> $#discard $: discard R $* $| $* $| $* $| <$*> $#discard $: $4 R $* $| $* $| $* $| <$*> $#discard $: $4 R $* $| $* $| $* $| <$*> $#error $@ TEMPFAIL $: "Try again later" R $* $| $* $| $* $| <$*> $#error $@ TEMPFAIL $: $4. "Try again later" R $* $| $* $| $* $| <$*> $#error $@ TEMPFAIL $: $4. "Try again later" R $* $| $* $| $* $| <$*> $#error $@ $4.$5.$6 $: $7 R $* $| $* $| $* $| <$*> $#error $@ UNAVAILABLE $: $4 R $* $| $* $| $* $| <$*> $#error $@ UNAVAILABLE $: $4 R $* $| $* $| $* $| <$*> <$*> $#error $: $4 # результат поиска неопределенный R $* $| $* $| $* $| $* $: $1 $| $2 $| $3