_ RU.LINUX (2:5077/15.22) ___________________________________________ RU.LINUX _
From : Solar Designer 2:5020/400 04 Oct 98 11:38:38
Subj : макросы для strcpy/strcat/[v]sprintf
________________________________________________________________________________
From: Solar Designer <solar@cannabis.dataforce.net>
Valentin Nechayev <netch@lucky.net> wrote:
> SD> 3. Проверка пароля (root или gid=shadow).
Вот тут некрасиво выходит, чтобы портабельно и везде безопасно.
Вариант 1:
1. setuid под юзера.
2. exec своего продолжения, чтобы address space от shadow очистить.
Вариант 2:
1. exec продолжения с какой-то передачей uid'а.
2. setuid уже в продолжении.
Проблема в первом варианте: риск ptrace'а между пунктами 1 и 2 на
некоторых (пусть даже кривых) системах, где нет аналога current->dumpable
или он не сбрасывается при setuid. Да, это race, но от этого не легче.
Тем не менее, djb'шный checkpassword сделан именно так, я даже думаю не
намылить ли djb об этом. ;-) Тем более, что там обнаружился еще и ляп
пострашнее, пока даже в эхе не скажу (сейчас еще пойду проверю). Хотя,
конечно, всякий там login на эту тему не особо аккуратен. Да и фиксить
такие вещи надо все-таки в ядре. Hо если уж делать идеальный код, так,
чтобы он не был дыряв даже на сломанных системах, ... Короче, не знаю.
Второй вариант лишен этого недостатка, но сама передача uid'а будет
лишним кодом, выполняемым под рутом. Причем "лишним" в буквальном смысле
на не-таких-уж-кривых системах вроде Linux'а. ;-)
> Свести до минимума действия под рутом, обложить их тысячью проверками.
Вот тут возникает некоторое противоречие -- часть из этой "тысячи проверок"
сама будет вынуждена выполняться под рутом. ;-) Поэтому тысячу я делать не
буду, а ограничусь разумным количеством, достаточным для того, чтобы часть
работающая под рутом совсем не доверяла остальным.
> Работу собственно с ящиком вывести в дочерний процесс, у которого resuid -
> выбранный пользователь, resgid - хотя бы nogroup. Анализ кода возврата
> ребенка может разве что вынудить к действию оставить временный файл для
> отладки, но лучше и этого не делать - просто передать код дальше.
Hа самом деле есть вариант и без временного файла совсем, во всех случаях.
Hо с риском потери мыла при вырубании питания. А есть-таки и вариант _без_
такого риска, ценой некоторых тормозов, и запуска "восстановителя" из rc.d
скриптов до inetd и MTA.
> SD> протокол для взаимодействия частей pop3 демона, работающих полностью
> SD> под разными uid'ами. Второй вариант сложнее, но IMHO предпочтительнее.
> Да.
Пока начал уже делать по такому варианту, "черновик". ;-) Форкается и
говорит сам с собой через pipe. Вроде не так уж и сложно получается. :-)
В таком варианте, чтобы кому-то получить рута, надо найти как минимум два
бага -- по одному в каждой части.
В состоянии authentication:
client (remote) <-> pop3 protocol (uid=pop3) -> auth/setuid (uid=0)
В состоянии transaction:
client (remote) <-> pop3 protocol & mailbox access (uid=user)
В состоянии update, реализация без временного файла:
client (remote) <-> pop3 protocol & mailbox access (uid=user)
В состоянии update, реализация с временным файлом:
client (remote) <-> pop3 protocol (uid=user) -> unlink (uid=0)
Как видно, из-за временного файла, если его делать, пришлось бы все время
держать лишний процесс для "хранения" рута. ;-(
> SD> Также, желательно будет временами проходить через лишний exec() дабы
> SD> прочистить address space от остатков shadow после вызовов libc. Иначе
> SD> делать setuid под самого юзера будет на некоторых системах (не Linux,
> SD> а, например, Solaris до 2.6 не включительно) небезопасно из-за ptrace.
> Форкнутый ребенок делает exec() с определенными ключами и уже resuid на
> пользователя.
Здесь придется выбрать между двумя вариантами -- см. выше.
> Если система позволяет измерения точнее чем до секунды - воспользоваться.
Да, но тут важна не точность измерений, а формат времени в файловой
системе (который обычно меньшей точности).
> Вполне хорошо.
Тогда буду делать. :-) Кстати, вот cucipop вообще таких проверок не делает
и лок не держит -- просто в расчете, что ничего, кроме прихода нового мыла,
с mailbox'ом делать не будут. А если будут -- запорченный mailbox. ;-) Так
что, тоже можно оставить как опцию для ускорения работы, на сайтах, где
юзерам ничего, кроме pop3, для чтения мыла и не дают.
> SD> Баг, как известно, тупейший -- в Dprintf. А вообще, там такого много, так
> SD> что я просто пересобрал со своими макросами для strcpy/strcat/[v]sprintf,
> SD> которые когда-то кидал в security-audit уже. (Hу и, конечно, убедился,
> SD> что vsprintf бинарник больше не знает.)
> А макросы можешь привести сюда?
> Я к чему - во-первых, лучше иметь готовый комплект, которым можно будет всем
> пользоваться, а, во-вторых, сверить бы. У меня свой комплект (могу привести)
> - хотелось бы сравнить идеи и реализацию.
Да. Только сначала скажу disclaimer -- это _не_ решение проблемы, и вообще
не правильный путь к решению -- а то еще опять кто-нибудь разговоры начнет.
Известная проблема: sizeof() руганется на incomplete type при некоторых
описаниях extern'ов. Hапример, встречается в squid'е. Если твой вариант
чем-то лучше -- покажи, было бы интересно посмотреть.