LINUX.ORG.RU
ФорумAdmin

Ошибка Exim: Tainted filename for search: '/etc/exim4/domains/site.com/aliases'

 


0

1

Был exim 4.90 обновился до 4.95 перестали работать роуты

в логах ошибки

aliases:
  driver = redirect
  headers_add = X-redirected: yes
  data = ${extract{1}{:}{${lookup{$local_part@$domain}lsearch{/etc/exim4/domains/$domain/aliases}}}}
  require_files = /etc/exim4/domains/$domain/aliases
  redirect_router = dnslookup
  pipe_transport = address_pipe
  unseen
2023-07-27 20:28:43 Tainted filename for search: '/etc/exim4/domains/site.com/aliases'
2023-07-27 20:28:43 H=forward100b.mail.yandex.net [178.154.239.147] X=TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256 CV=no F=<email@yandex.ru> temporarily rejected RCPT <6ad16ede3f3bec87a8e25443d5d156f5@site.com>: failed to expand "${extract{1}{:}{${lookup{$local_part@$domain}lsearch{/etc/exim4/domains/$domain/aliases}}}}": NULL

Гуглеж привел к https://mox.sh/sysadmin/tainted-filename-errors-in-exim-4.94/

Пробовал отключить tainted опцией allow_insecure_tainted_data = yes, но она deprecated в exim 4.95

Пробовал заменить $local_part на $local_part_data

aliases:
  driver = redirect
  headers_add = X-redirected: yes
  data = ${extract{1}{:}{${lookup{$local_part_data@$domain}lsearch{/etc/exim4/domains/$domain/aliases}}}}
  require_files = /etc/exim4/domains/$domain/aliases
  redirect_router = dnslookup
  pipe_transport = address_pipe
  unseen
2023-07-27 20:25:37 Tainted filename for search: '/etc/exim4/domains/site.com/aliases'
2023-07-27 20:25:37 H=(site.com) [96.46.181.242] sender verify defer for <noreply@site.com>: failed to expand "${extract{1}{:}{${lookup{$local_part_data@$domain}lsearch{/etc/exim4/domains/$domain/aliases}}}}": NULL
2023-07-27 20:25:37 H=(site.com) [96.46.181.242] F=<noreply@site.com> A=dovecot_plain:noreply@site.com temporarily rejected RCPT <email1812@yandex.ru>: Could not complete sender verify
2023-07-27 20:25:43 no host name found for IP address 96.46.181.242

Куда копать и что делать?

Перемещено hobbit из general



Последнее исправление: wiemei (всего исправлений: 2)

Читать официальную документацию, переписывать.

Вот прямо отсюда: https://www.exim.org/exim-html-4.95/doc/html/spec_html/ch-string_expansions.html

Там помечено какие переменные содержат tainted data, а какие нет.

Пробовал заменить $local_part на $local_part_data

И $domain на $domain_data имеет смысл. И всё через поиски.

ivanov17
()

Это такая штука для «безопасности». Все строки, полученные по сети от посторонних хостов, считаются потенциально вредоносными (tainted). Если ты используешь tainted строку в каком-то выражении - результат тоже tainted. tainted строки нельзя использовать в качестве каких-либо путей в файловой системе. Сообщить exim-у «я знаю что эта переменная взята из сети, но я сделал все нужные проверки и уверен что она безопасная» невозможно.

Ругается он у тебя не на $local_part а на $domain (до $local_part видимо не успел дойти).

Способов обхода два:

1) тупо склонировать строку, но так чтобы exim это не понял, способа в целом примерно два:

$domain -> ${perl{untaint}{$domain}}

$domain -> ${run{/bin/echo ${quote:$domain}}{$value}}

(я их не проверял, ни первый ни второй, они костыльные и некрасивые, кроме того для первого нужен какой-то перл-модуль к exim-у которого дефолтно нет, а второй создаёт лишние процессы чтобы копировать строки)

2) честно «вычислять» безопасные строки с помощью поиска (lsearch) по файлам-таблицам сначала доменов а потом юзеров доменов (или можно сделать одну плоскую таблицу всех юзеров на всех доменах)

$domain_data и $local_part_data - это не просто «безопасные клоны» $domain и $local_part, а какая-то весьма муть. Чтобы их заполнить (иначе они пустые), нужно использовать директивы domains (для первого) и local_parts/check_local_user (для второго). При этом check_local_user проверяешь $local_part в системных таблицах типа /etc/passwd, так что он обычно не годится.

https://exim.org/exim-html-current/doc/html/spec_html/ch-generic_options_for_...

domains Use: routers‡ Type: domain list† Default: unset

If this option is set, the router is skipped unless the current domain matches the list. If the match is achieved by means of a file lookup, the data that the lookup returned for the domain is placed in $domain_data for use in string expansions of the driver’s private options and in the transport. See section 3.12 for a list of the order in which preconditions are evaluated.

local_parts Use: routers‡ Type: local part list† Default: unset

The router is run only if the local part of the address matches the list. See section 3.12 for a list of the order in which preconditions are evaluated, and section 10.22 for a discussion of local part lists. Because the string is expanded, it is possible to make it depend on the domain, for example:

local_parts = dbm;/usr/local/specials/$domain_data

If the match is achieved by a lookup, the data that the lookup returned for the local part is placed in the variable $local_part_data for use in expansions of the router’s private options or in the transport. You might use this option, for example, if you have a large number of local virtual domains, and you want to send all postmaster mail to the same place without having to set up an alias in each virtual domain:

postmaster:
driver = redirect
local_parts = postmaster
data = postmaster@real.domain.example

Описания этих опций, как и весь остальной мануал по exim-у, чрезвычайно мутные, но при желании можно разобраться.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax
  1. честно «вычислять» безопасные строки с помощью поиска (lsearch) по файлам-таблицам сначала доменов а потом юзеров доменов (или можно сделать одну плоскую таблицу всех юзеров на всех доменах)

Структура хранения такая (в файлах) Есть папка с доменами /etc/exim4/domains/site1.com/ /etc/exim4/domains/site2.com/

Внутри текстовые файлы /etc/exim4/domains/site1.com/aliases /etc/exim4/domains/site1.com/passwd /etc/exim4/domains/site2.com/aliases /etc/exim4/domains/site2.com/passwd

Как вычислять строки по папкам доменов или нужно создавать отдельный файл с списком доменов?

wiemei
() автор топика
Ответ на: комментарий от wiemei
aliases:
  driver = redirect
  headers_add = X-redirected: yes
  domains = /etc/exim4/domains_virtual.txt
  #или так
  domains = dsearch;/etc/exim4/domains
  local_parts = dsearch;/etc/exim4/domains/$domain_data/aliases
  data = ${extract{1}{:}{${lookup{$local_part@$domain}lsearch{/etc/exim4/domains/$domain/aliases}}}}
  redirect_router = dnslookup
  pipe_transport = address_pipe
  unseen

Как то так?

wiemei
() автор топика
Ответ на: комментарий от wiemei

Да, файл со списком доменов, в котором будет делаться поиск домена. Переменную $domain тоже нельзя использовать в именах никаких файлов, в том числе в имени файла для поиска $local_part в нём.

В строке data = опять файл с $domain

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от wiemei

Не знаю, проверь. Из описания непонятно заполняет ли dsearch $domain_data или нет, и чем.

Хотя в описании dsearch есть

The default result is just the requested entry.

то есть он вернёт имя файла в data, наверно работает.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от wiemei

Проблема с роутером теперь решена, возникает другая проблема с транспортом

старый конф работающий до 4.95 версии

local_delivery:
  driver = appendfile
  user = ${extract{2}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}
  directory = "${extract{5}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/passwd}}}}/$domain_data/$local_part"

Если заменяем domain->domain_data, local_part_local_part_data

local_delivery:
  driver = appendfile
  user = ${extract{2}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain_data/passwd}}}}
  directory = "${extract{5}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain_data/passwd}}}}/$domain_data/$local_part_data"

Создаются такие папки в /var/mail/site.com/ ‘{MD5}$1$oeFvhuS$’ хотя должно быть /var/mail/site.com/ support

wiemei
() автор топика