Проблема в том, что после Exim 4.94 $local_part, $domain и результат lookup в $value считаются потенциально tainted. Их нельзя напрямую подставлять в путь к pmrc.* или использовать как часть команды pipe. Нужны данные, полученные из контролируемых lookup: $local_part_data и $domain_data.
Что неверно в исходнике
В старом варианте опасны оба фрагмента:
Код: Выделить всё
/usr/local/etc/exim/pmrc.$value
r=$local_part@$value.domain.ru
$value — результат ${lookup ...} и не следует использовать его как «очищенный» фрагмент пути.
$local_part — входные данные SMTP, также tainted.
Проверка exists не «очищает» строку: построенный путь уже содержит tainted-значение.
Статья, на которую ссылается автор, также подчёркивает: простое присваивание или копирование строки taint не снимает; нужно строить маршрутизацию через lookup и использовать *_data.
Рабочая схема
Если aliases.ng содержит соответствие вида:
а файл /usr/local/etc/exim/pmrc.exchange — доверенный, то не используйте результат lookup как имя файла. Вынесите допустимые значения в статически описанные router’ы или примените lookup, который возвращает уже известный, заранее заданный путь.
Например, если допустим только exchange:
Код: Выделить всё
subdomain_exchange:
driver = redirect
domains = +our_domains : +local_domains
local_parts = lsearch;/usr/local/etc/exim/aliases.ng
data = ${if eq{$local_part_data}{user}\
{|/usr/local/bin/procmail -m \
s=${if eq{$sender_address}{}{<>}{$sender_address}} \
r=user@exchange.domain.ru \
/usr/local/etc/exim/pmrc.exchange}\
fail}
pipe_transport = pipe_pm
Но это подходит, только если user и exchange фактически фиксированы. В вашем втором примере зафиксированные:
Код: Выделить всё
r=user@exchange.domain.ru
/usr/local/etc/exim/pmrc.exchange
как раз устраняют tainted-путь, однако local_part_data станет доступен лишь после успешного local_parts = lsearch;.... Сам файл aliases.ng должен содержать валидный lookup для конкретного локального адресата.
Вариант для нескольких поддоменов
Для нескольких значений наиболее надёжный и понятный путь — отдельные router’ы с фиксированными pmrc и адресом назначения:
Код: Выделить всё
subdomain_exchange:
driver = redirect
domains = +our_domains : +local_domains
local_parts = lsearch;/usr/local/etc/exim/aliases.ng
condition = ${if eq{$local_part_data}{exchange}{yes}{no}}
data = |/usr/local/bin/procmail -m \
s=${if eq{$sender_address}{}{<>}{$sender_address}} \
r=exchange@exchange.domain.ru \
/usr/local/etc/exim/pmrc.exchange
pipe_transport = pipe_pm
Если aliases.ng — это таблица входящий_localpart : alias, то local_part_data — именно значение из таблицы, а не исходный local part. Поэтому логика должна опираться на фактический формат файла.
Важный нюанс
Нельзя безопасно «починить» старую конструкцию заменой:
на:
если $local_part_data затем формирует имя файла. Для Exim 4.94+ каталог, имя файла и параметры доставки должны происходить из trusted lookup, либо быть фиксированными в конфиге. Именно это изменение в модели taint проверяет Exim при обновлении.
Для диагностики конкретного адреса удобно запускать:
Код: Выделить всё
exim -bt user@domain.ru
exim -d+expand -bt user@domain.ru
и смотреть, какой router выбран и чему фактически равны $local_part_data, $domain_data и итоговое data. В опубликованной теме пока нет ответов, поэтому проверить предполагаемый формат aliases.ng по материалам форума невозможно.