http://linux.ufaras.ru/SendmailACL.html
-----------------------------------------
LOCAL_CONFIG
Ksyslog syslog
Kallow hash /etc/mail/allow
Kdeny hash /etc/mail/deny
C{OnlyLocal}OK NOR
F{Group1}/etc/mail/group1
F{Group2}/etc/mail/group2
F{Group3}/etc/mail/group3
LOCAL_RULESETS
SLocal_check_rcpt
# ПОЛИТИКА: Все, что не разрешено, то запрещено!
# Это локальный набор правил, обрабатывающий адрес получателя.
# На вход в Local_check_rcpt подается заключенный в угловые скобки адрес получателя.
# Сначала разберемся с бездоменными локальными получателями.
# Помечаем любого получателя меткой
R$+ $: $1
# Освобождаем от метки доменных получателей
R<$+@$+> $: <$1@$2>
# С меткой остались только бездоменные получатели, и мы присоединяем
# полностью разрешенное имя хоста, которое определяется
# следующим образом: сначала вызывается команда gethostname,
# которая дает имя хоста, это имя хоста затем передается команде gethostbyname,
# которое должно вернуть каноническое имя хоста (см. op.me).
# Позаботьтесь самостоятельно о том,
# чтобы это имя попало в класс $=w - перечень всех доменных имен, под которыми известен хост.
# Потому что в дальнейшем для определения локальности почты я буду пользоваться именно этим классом
#
R<$+> $: <$1@$j>
# Теперь "все сестры с серьгами", а получатели с доменами, можно от метки освободиться
R<$+> $: <$1>
#Добавляем адрес отправителя - $&f
R$* $: $(syslog syslog:last: $1 $) $1
R$* $: $&f $| $1
R$* $: $(syslog syslog:last1: $1 $) $1
# Все неправильности (несуществующий или неразрезолвленный домен, запреты в access, etc) с эл.адресом отправителя уже обработаны в check_mail, поэтому мы их не обрабатываем.
# Для пользователей delay_check эти проверки не провожу, иначе никогда этот набор не закончу.
# Канонизируем адреса отправителя и получателя
R$* $| $* $: $2 $| $>Parse0 $>3 $1
R$* $| $* $: $2 $| $>Parse0 $>3 $1
# Отлупы мэйлер-даемона пропускаем
R<@> $| $* $@ OK
R$+<@$+> $| $+<@$+> $: $1<@$2> $| $3<@$4>
R$+<@$+.> $| $+<@$+.> $: $1<@$2.> $| $3<@$4.>
R$+ $#error $: "553 5.1.8 Domain of sender/recipient address does not exist."
# Блокировки для виртуальных доменов.
# Пока не знаю, как это втолкнуть в CheckACL - ведь я туда не передаю домен локального отправителя
# И не хотелось бы с ним там таскаться
#$+<@apache.anrb.ru.> $| $+<@mail.ru.> $#error $: 553 You are not allowed to send to this recipient -Nooo
R$* $: $(syslog syslog:last2: $1 $) $1
# Добавляем макрос $&{auth_authen} - свидетельство имевшей место smtp-авторизации
# Если отправитель использовал smtp-авторизацию, то значение макроса совпадет с именем клиента.
#
R$+ $: <$&{auth_authen}> $1
R$* $: $(syslog syslog:last3: $1 $) $1
# Если отправитель использовал smtp-авторизацию, то в угловых скобках что-то будет (<$+>)
# Ели при этом почта предназначена локальному клиенту (домен принадлежит классу w),
# то пропускаем письмо дальше
R<$+> $+<@$+> $| $+<@$=w.> $@ OK
R$* $: $(syslog syslog:last4 $1 $) $1
# Если отправитель авторизовался, но отправляет письмо внешнему клиенту
# (случай с локальными получателями обработан предыд. правилом), то отправляем
# использованное локальным отправителем для авторизации имя и адрес внешних получателя
# в CheckACL для проверки наличия прав для отправки письма
# В этом случае использованный отправителем эл.адрес нас не интересует, самое главное, он авторизовался.
#
R<$+> $+<@$+> $| $+<@$+> $: $>CheckACL From:$1:$4<@$5>
ROK $@ OK
#### delay_check: #Если отправитель авторизовался, но не указал домен в эл. адресе, то мы его спросим, зачем он нам морочит голову
#### delay_check: R<$+> $+ $| $+ $# error $: "553 Where is your mail domain?"
# Кто остался не охваченым нашими правилами в случае smtp-авторизации
R<$-> $* $: $(syslog syslog:problem0: <$1>$2 $) <$1>$2
#R<$*> $* $: $(syslog syslog:problem000: <$1>$2 $) <$1>$2
# А это отправители без smtp-авторизации
R<>$* $: $(syslog syslog:no-auth: $1 $) $1
# Избавляемся от признака smtp-авторизации
R<$*>$* $: $2
# Проверяем локальность IP-адреса.
# Добавляем IP-адрес отправителя - $&{client_addr}
R$+ $: $&{client_addr} $| $1
R$* $: $(syslog syslog:last6: $1 $) $1
# Пометим словом почту с непосредственно с нашего сервера
R 127.0.0.1 $| $+ $: $| $1
R$* $: $(syslog syslog:last60: $1 $) $1
# Пометим словом почту с ip-адресов, указанных в /etc/mail/relay-domains
R $=R $* $| $+ $: $| $3
R$* $: $(syslog syslog:last600: $1 $) $1
# Анализируем файл /etc/mail/access:
R $-.$-.$-.$- $| $+ $: <$(access $1.$2.$3.$4 $:$1.$2.$3 $)> $| $5
R$* $: $(syslog syslog:last61: $1 $) $1
R<$-.$-.$-> $| $+ $: <$(access $1.$2.$3 $:$1.$2 $)> $| $4
R$* $: $(syslog syslog:last62: $1 $) $1
R<$-.$-> $| $+ $: <$(access $1.$2 $:NOR $)> $3
# Проверяем результаты просмотра файла /etc/mail/access.
# Взято из Scheck_mail sendmail.cf:
# check results
R $* $#discard $: discard
R<> $* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
## delay_check: R $* $#error $@ quarantine $: $1
## delay_check: R $* $#error $@ 5.7.1 $: "550 Access denied"
## delay_check: R $* $#error $@ $1.$2.$3 $: $4
## delay_check: R $* $#error $: $1
#Если отправителю разрешено релеить (из access правило вернулось с меткой ),
#и домены отправителя и получателя - локальные (принадлежат классу w, $=w) - пропускаем письмо
R $| $+<@$=w.> $| $+<@$=w.> $@ OK
R$* $: $(syslog syslog:last7: $1 $) $1
# Если отправителю разрешено релеить,
# домен отправителя - локальные (принадлежат классу w, $=w),
# а домен получателя любой другой кроме локального (локальщики с доменом уже пропущены предыдущим правилом)
# - отправляем имя локального отправителя ($1) без домена и адрес внешнего получателя полностью $3<@$4>
# в набор правил CheckACL
R $| $+<@$=w.> $| $+<@$+> $: $>CheckACL From:$1:$3<@$4>
R$* $: $(syslog syslog:last8: $1 $) $1
ROK $@ OK
# Если отправителю разрешено релеить (из access правило вернулось с меткой ),
# а домен отправителя нелокальный (локальные домены уже обработаны тремя предыдущими правилами, домен получателя нас не интересует и мб любым)
# - запрещаем такую почту.
# Мы разрешаем локальному юзеру указывать посторонний домен
# только в случае использования им smtp-авторизации,
# ведь в этом случае он предоставляет нам свое автризационное имя для проверки в ACL.
R $| $+<@$+> $| $+<@$+> $#error $: "553 Non valid local domain name."
R$* $: $(syslog syslog:last12: $1 $) $1
#### delay_check: # Не разрешаем бездоменных отправителей из локальной сети.
#### delay_check: # Все доменные отправители уже обработаны предыд. правилами
#### delay_check: R $| $+ $| $+<@$+> $# error $: "553 Where is your mail domain?"
# Там кто-то остался из релейщиков?
R $* $: $(syslog syslog:problem1: $1 $) $1
# Избавляемся от IP-адреса, он нам больше не понадобится
# Вообще-то это правило лишнее, потому что после прохода через файл /etc/mail/access,
# ip-адрес преобразуется в один из ключей: RELAY, OK, DISCARD, etc, и в явном виде больше использоваться не будет.
# Но мы подстрахуемся, предварительно записав сообщение о казусе в лог
R$-.$-.$-.$- $| $* $: $(syslog syslog:problem2: $1.$2.$3.$4 $5 $) $1.$2.$3.$4 $5
R$-.$-.$-.$- $| $* $: $5
R$* $: $(syslog syslog:last13: $1 $) $1
# Вроде бы всех, кто имеет право релеить почту, мы обработали.
# Всех, кто был заблокирован в /etc/mail/access, мы тоже обработали.
# Остались те, у кого в качестве ключа в access стоит ОК,
# и те, кто вообще не упомянут в access ().
# Эти две последние группы имеют право отправлять почту только нашим локальным клиентам.
# Но на всякий случай мы сделаем проверку, а вдруг кто остался непомеченным
# И заодно запретим внешнюю() почту, подписанную нашим доменом ($=w).
R $+<@$=w.> $| $+<@$+> $#error $: "553 Please use your own domain name."
R$+ $: $1
R$* $: $(syslog syslog:last131: $1 $) $1
R <$={OnlyLocal}> $+ $: $2
R $+ $: $(syslog syslog:problem3: $1 $) $1
# После всех манипуляций у нас должна остаться пара внешний отправитель:локальный получатель
# $+<@$+> $| $+<@$=w.>
# Если получатель локальный ($=w), то отправляем тройку To:лок.получатель:внеш.отправитель в
# набор правил CheckACL.
R$+<@$+> $| $+<@$=w.> $: $>CheckACL To:$3:$1<@$2>
R$* $: $(syslog syslog:last14: $1 $) $1
ROK $@ OK
R$* $: $(syslog syslog:last140: $1 $) $1
#### А этот куда намылился? Внешниий IP, в smtp-авторизации не замечен, внешний получатель -
#### а мы не OPEN RELAY!
#### Вообще-то этого перца прекрасно заблокирует и сам sendmail, но позже.
#### А если это можно сделать раньше, то почему бы это не сделать сразу.
R$+<@$+> $| $+<@$+> $#error $: "553 Go away. We are not open relay!"
R$* $: $(syslog syslog:last15: $1 $) $1
#### delay_check: # Бездоменный отправитель. Его также потом заблокирует основной набор правил check_mail,
#### delay_check: # но мы сделаем это раньше.
#### delay_check: R$+ $| $+ $#error $: "553 Where is your domain name?"
#Кто остался не охваченым нашими правилами
R$* $: $(syslog syslog:problem5: $1 $) $1
SCheckACL
# Итак, вот набор правил, непосредственно проверяющий права пар пользователей,
# прописанные в файлах /etc/mail/allow(deny).
# На вход этому набору правил подается метка To: или From:, указывающая
# на направление движения почты относительно локального пользователя, и пара
# локальный пользователь:внешний пользователь.
# Эта пара (лок.отправитель:внеш.получатель или лок.получатель:внеш.отправитель)
# может быть задана пятью способами.
# Первый: локальный юзер или группа:внешний e-mail
# Второй: локальный юзер или группа:внешний почтовый домен
# Третий: локальный юзер или группа:весь внешний мир
# Четвертый: все локальные юзеры:внешний e-mail
# Пятый: все локальные юзеры:внешний почтовый домен
# Так как по условию задачи файл /etc/mail/allow имеет приоритет перед /etc/mail/deny,
# то сначала проверяем, разрешено ли паре общение, и только потом, не запрещено ли оно.
# По умолчанию, все не разрешено - запрещено.
# Поэтому последним правилом в наборе CheckACL стоит правило, запрещающее все,
# что не попало в вышестоящие разрешения
#R $#error $: "553 You cannot send any mail to this recipient."
# 1. Сначала разберемся с парами лок.отправитель:внеш.e-mail внеш.получателя или лок.получатель:e-mail внеш.отправителя
# По условию задачи права этой пары имеют преимущество перед остальныит ограничениями
# 1.1.1 Указана ли пара в файле allow?
R$* $: $(syslog syslog:ACL0: $1 $) $1
R$+ $: $(allow $1 $)
R$* $: $(syslog syslog:ACL1-1-1: $1 $) $1
# Да - пропускаем письмо дальше
RALLOW $@ OK
# Нет - продолжаем
# 1.1.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:внеш.получатель(отправитель) в файле allow?
R$+ : $={Group1} : $+ $: <$(allow $1:group1:$3 $:NOAL $)> $1:$2:$3
R$* $: $(syslog syslog:ACL1-1-2: $1 $) $1
# Да - пропускаем письмо дальше
R $+ $@ OK
# Нет - избавляемся от метки
R $+ $: $1
R$* $: $(syslog syslog:ACL1-1-2: $1 $) $1
# 1.1.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:внеш.получатель(отправитель) в файле allow?
R$+ : $={Group2} : $+ $: <$(allow $1:group2:$3 $:NOAL $)> $1:$2:$3
R$* $: $(syslog syslog:ACL1-1-3: $1 $) $1
R $+ $@ OK
R $+ $: $1
# 1.2.1. Указана ли пара в файле deny?
R$+ $: $(deny $1 $)
R$* $: $(syslog syslog:ACL1-2-1: $1 $) $1
# Да - блокируем
RDENY $#error $: "553 You cannot send any mail to this recipient."
# Нет - продолжаем
# 1.2.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:внеш.получатель(отправитель) в файле deny?
R$+ : $={Group1} : $+ $: <$(deny $1:group1:$3 $:NODEN $)> $1:$2:$3
R$* $: $(syslog syslog:ACL1-2-2: $1 $) $1
# Да - блокируем
R $+ $#error $: "553 You cannot send any mail to this recipient."
# Нет - избавляемся от метки
R $+ $: $1
R$* $: $(syslog syslog:ACL1-2-2: $1 $) $1
# 1.2.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:внеш.получатель(отправитель) в файле deny?
R$+ : $={Group2} : $+ $: <$(deny $1:group2:$3 $:NODEN $)> $1:$2:$3
R$* $: $(syslog syslog:ACL1-2-3: $1 $) $1
R $+ $#error $: "553 You cannot send any mail to this recipient."
R $+ $: $1
R$* $: $(syslog syslog:ACL1-2-3: $1 $) $1
# 2. Теперь разберемся с парами лок.юзер:домен внешнего получателя(отправителя)
#
# 2.1.1 Прописана ли эта пара в файле allow?
R$+:$+:$+<$+> $: <$(allow $1:$2:<$4> $:NOAL $)> $1:$2:$3<$4>
R$* $: $(syslog syslog:ACL2-1-1: $1 $) $1
R $+ $@ OK
R $+ $: $1
R$* $: $(syslog syslog:ACL2-1-1: $1 $) $1
# 2.1.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:домен внеш.получателя(отправителя) в файле allow?
R$+ : $={Group1} : $+<$+> $: <$(allow $1:group1:<$4> $:NOAL $)> $1:$2:$3<$4>
R$* $: $(syslog syslog:ACL2-1-2: $1 $) $1
R $+ $@ OK
R $+ $: $1
# 2.1.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:домен внеш.получателя(отправителя) в файле allow?
R$+ : $={Group2} : $+<$+> $: <$(allow $1:group2:<$4> $:NOAL $)> $1:$2:$3<$4>
R$* $: $(syslog syslog:ACL2-1-3: $1 $) $1
R $+ $@ OK
R $+ $: $1
# 2.2.1. Проверяем, а не запрещена ли часом пара лок.юзер:внешний_почтовый_домен в файле deny?
R$+:$+:$+<$+> $: <$(deny $1:$2:<$4> $:NODEN $)> $1:$2:$3<$4>
R$* $: $(syslog syslog:ACL2-2-1: $1 $) $1
# Да - блокируем
R $+ $#error $: "553 You cannot send any mail to this domain."
R $+ $: $1
# 2.2.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:домен внеш.получателя(отправителя) в файле deny?
R$+ : $={Group1} : $+<$+> $: <$(deny $1:group1:<$4> $:NODEN $)> $1:$2:$3<$4>
R$* $: $(syslog syslog:ACL2-2-2: $1 $) $1
R $+ $#error $: "553 You cannot send any mail to this domain."
R $+ $: $1
# 2.2.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:домен внешнего получателя(отправителя) в файле deny?
R$+ : $={Group2} : $+<$+> $: <$(deny $1:group2:<$4> $:NODEN $)> $1:$2:$3<$4>
R$* $: $(syslog syslog:ACL2-2-3: $1 $) $1
R $+ $#error $: "553 You cannot send any mail to this domain."
R $+ $: $1
# 3. Следующая пара - локальный юзер:получатель(отправитель)_all.
# 3.1.1. Проверяем, указана ли эта пара в файле allow:
# (проверка в deny будет избыточной, тк политика по умолчанию -
# все, что не разрешено, то запрещено).
R$+:$+:$+ $:<$(allow $1:$2:all $:NOAL $)> $1:$2:$3
R$* $: $(syslog syslog:ACL3-1-1: $1 $) $1
R $+ $@ OK
R $+ $: $1
# 3.1.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:all в файле allow?
R$+ : $={Group1} : $+ $: <$(allow $1:group1:all $:NOAL $)> $1:$2:$3
R$* $: $(syslog syslog:ACL3-1-2: $1 $) $1
R $+ $@ OK
R $+ $: $1
# 3.1.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:all в файле allow?
R$+ : $={Group2} : $+ $: <$(allow $1:group2:all $:NOAL $)> $1:$2:$3
R$* $: $(syslog syslog:ACL3-1-3: $1 $) $1
R $+ $@ OK
R $+ $: $1
# 4. Еще одна пара - любой локальный юзер:e-mail внешнего получателя(отправителя).
# 4.1. Проверяем, указана ли эта пара в файле allow
R$+:$+:$+ $:<$(allow $1:all:$3 $:NOAL $)> $1:$2:$3
R$* $: $(syslog syslog:ACL4-1: $1 $) $1
R $+ $@ OK
R $+ $: $1
R$* $: $(syslog syslog:ACL4-1: $1 $) $1
# 4.2. Проверяем, указана ли эта пара в файле deny
R$+:$+:$+ $:<$(deny $1:all:$3 $:NODEN $)> $1:$2:$3
R$* $: $(syslog syslog:ACL4-2: $1 $) $1
R $+ $#error $: "553 You cannot send any mail to this user."
R $+ $: $1
R$* $: $(syslog syslog:ACL4-2: $1 $) $1
# 5. Последняя пара - любой локальный юзер:домен внешнего получателя(отправителя).
# 5.1. Проверяем, указана ли эта пара в файле allow
R$+:$+:$+<$+> $:<$(allow $1:all:<$4> $:NOAL $)> $1:$2:$3<$4>
R$* $: $(syslog syslog:ACL5-1: $1 $) $1
R $+ $@ OK
# 5.2. Проверяем, указана ли эта пара в файле deny - излишнее, так как политика
# и так запретит все, что не разрешено.
#R$+:$+:$+<$+> $:<$(deny $1:all:<$4> $:NODEN $)>
#R$* $: $(syslog syslog:ACL5-2: $1 $) $1
#R $#error $: "553 You cannot send any mail to this domain."
## Заключение. Нет - блокируем письмо
R $#error $: "553 You cannot send any mail to this recipient."
# Кто-нибудь остался не охваченым нашими правилами?
R$* $: $(syslog syslog:problem4: $1 $)