Взгляните на самбу, чтобы увидеть, как это можно сделать. Демон samba запускается от имени пользователя root, но при первой возможности разветвляется и принимает учетные данные обычного пользователя.
В системах Unix есть два отдельных набора учетных данных: реальные идентификаторы пользователя / группы и эффективные идентификаторы пользователя / группы. Реальный набор определяет, кем вы являетесь на самом деле, а эффективный набор определяет, к чему вы можете получить доступ. Вы можете изменить эффективный uid / gid по своему усмотрению, если вы используете root, включая обычного пользователя, и обратно, поскольку ваши настоящие идентификаторы пользователя / группы остаются root во время перехода. Таким образом, альтернативный способ сделать это в одном процессе - использовать seteuid/gid
для применения разрешений разных пользователей туда и обратно по мере необходимости. Если демон вашего сервера работает от имени пользователя root или имеет CAP_SETUID
, это будет разрешено.
Однако обратите внимание, что если у вас есть возможность переключать эффективный uid / gid по прихоти и ваше приложение подрывается, тогда эта подрывная деятельность может, например, переключить эффективный uid / gid обратно на 0, и у вас может быть серьезная уязвимость в системе безопасности. Вот почему разумно как можно скорее навсегда отказаться от всех привилегий, включая ваш настоящий пользовательский uid / gid.
По этой причине нормально и безопаснее иметь один прослушивающий сокет, работающий от имени пользователя root, а затем отключиться и изменить как реальный, так и эффективный идентификаторы пользователей, вызвав setuid
. Тогда он не может вернуться назад. У вашего разветвленного процесса будет сокет, который был accept()
ed, поскольку это вилка. Каждый процесс просто закрывает ненужные файловые дескрипторы; сокеты остаются активными, поскольку на них ссылаются файловые дескрипторы в противоположных процессах.
Вы также можете попытаться обеспечить соблюдение разрешений, изучив их по отдельности, но я надеюсь, что очевидно, что это потенциально подвержено ошибкам, имеет множество крайних случаев и с большей вероятностью пойдет не так (например, это не будет работать со списками ACL POSIX. если вы специально не реализуете это тоже).
Итак, у вас есть три варианта:
- Вилка и _5 _ / _ 6_ нужному пользователю. Если требуется связь, используйте
pipe(2)
или socketpair(2)
перед форк-вилкой.
- Не используйте форк и _9 _ / _ 10_ по мере необходимости (менее безопасный: более вероятно, что ваш сервер может быть скомпрометирован случайно).
- Не связывайтесь с системными учетными данными; выполнить принудительное применение разрешений вручную (менее безопасно: вероятность неправильной авторизации выше).
Если вам нужно связаться с демоном, то, хотя это может быть сложнее сделать это через сокет или канал, первый вариант действительно является правильным безопасным способом сделать это. См., Например, как ssh разделяет привилегии. Вы также можете подумать, можете ли вы изменить свою архитектуру, чтобы вместо какого-либо взаимодействия процесс мог просто использовать некоторую память или дисковое пространство.
Вы упомянули, что рассматривали возможность запуска отдельного процесса для каждого пользователя, но вам нужен один прослушивающий TCP-порт. Вы все еще можете это сделать. Просто пусть главный демон прослушивает порт TCP и отправляет запросы каждому пользовательскому демону и обменивается данными по мере необходимости (например, через сокеты домена Unix). Фактически это было бы почти то же самое, что иметь разветвляющийся мастер-демон; Думаю, последнее оказалось бы проще реализовать.
Дальнейшее чтение: credentials(7)
справочная страница. Также обратите внимание, что в Linux есть файловая система uid / gids; это почти то же самое, что и эффективный uid / gids, за исключением других вещей, таких как отправка сигналов. Если у ваших пользователей нет доступа к оболочке и они не могут запускать произвольный код, вам не нужно беспокоиться о разнице.
person
Robie Basak
schedule
13.02.2011