Как выполнять манипуляции с файлами / каталогами с учетом пользовательских привилегий? - PullRequest
8 голосов
/ 31 января 2011

У меня есть серверное приложение, которое будет работать под системной учетной записью, поскольку в любой момент оно будет обрабатывать запросы от имени любого пользователя в системе.Эти запросы состоят из инструкций по манипулированию файловой системой.

В этом и заключается подвох: программе необходимо учитывать привилегии конкретного пользователя при выполнении действий.Например, joe не должен иметь возможность изменять /home/larry, если его разрешения 755.

. В настоящее время моя стратегия такова:

  • Получить владельца / группуfile
  • Сравните его с идентификатором пользователя / идентификатором группы пользователя, который пытается выполнить действие
  • Если совпадает (или не совпадает), используйте соответствующую часть поля разрешения в полефайл, чтобы разрешить или запретить действие

Это разумно?Есть ли более простой способ сделать это?

Сначала я думал о том, чтобы несколько экземпляров приложения работали под учетными записями пользователя - но это не вариант, потому что тогда только один из экземпляров может прослушиватьданный порт TCP.

Ответы [ 3 ]

3 голосов
/ 31 января 2011

Я хотел бы иметь свой сервер fork () и немедленно setuid(uid), чтобы отказаться от привилегий root.Тогда любая манипуляция с файлом будет от имени пользователя, которым вы стали.Поскольку вы - дочерний элемент сервера, вы по-прежнему содержите дочерний сокет accept () ed, в котором будет выполняться запрос (и я предполагаю ответ).Это (очевидно) требует привилегии root для демона.

Передача файловых дескрипторов между процессами в этом случае представляется излишне сложной, так как у дочернего элемента уже есть дескриптор "request".

3 голосов
/ 14 февраля 2011

Взгляните на samba , чтобы получить пример этого.Демон samba запускается от имени пользователя root, но разветвляется и принимает учетные данные обычного пользователя как можно скорее.

У систем Unix есть два отдельных набора учетных данных: идентификаторы реального пользователя / группы и эффективные идентификаторы пользователя / группы.Реальный набор определяет, кто вы на самом деле, а эффективный набор определяет, к чему вы можете получить доступ.Вы можете изменить действующий uid / gid по своему усмотрению, если вы являетесь пользователем root, в том числе обычным пользователем и обратно, поскольку ваши реальные идентификаторы пользователей / групп остаются корневыми во время перехода.Таким образом, альтернативный способ сделать это в одном процессе - использовать seteuid/gid для применения разрешений разных пользователей туда и обратно по мере необходимости.Если ваш серверный сервер работает от имени пользователя root или имеет CAP_SETUID, то это будет разрешено.

Однако обратите внимание, что если у вас есть возможность переключать эффективный uid / gid на прихоть, а ваше приложение подрывается, то этоSubversion может, например, переключить эффективный uid / gid обратно на 0, и вы можете столкнуться с серьезной уязвимостью безопасности.Вот почему целесообразно как можно скорее удалить все привилегии навсегда, включая вашего реального пользователя uid / gid.

По этой причине нормально и безопаснее иметь один прослушивающий сокет, работающий от имени пользователя root, а затем forkвыключите и измените действительные и эффективные идентификаторы пользователей, вызвав setuid.Тогда это не может измениться назад.У вашего разветвленного процесса будет сокет, который был accept() ed, так как он является форком.Каждый процесс просто закрывает файловые дескрипторы, которые им не нужны;сокеты остаются в живых, так как на них ссылаются файловые дескрипторы в противоположных процессах.

Вы также можете попытаться применить права доступа, проверив их индивидуально самостоятельно, но я надеюсь, что очевидно, что это потенциально подвержено ошибкам, имеет множество крайних вариантов и с большей вероятностью пойдет не так (например, он не будет работать с POSIX ACL, если вы не реализуете это специально).

Итак, у вас есть три варианта:

  1. Вилка и setgid() / setuid() пользователю, которого вы хотите.Если требуется связь, используйте pipe(2) или socketpair(2) перед тем, как разветвляться.
  2. Не разветвляйтесь и seteuid() / setegid() вокруг, если это необходимо (менее безопасно: с большей вероятностью скомпрометировать сервер случайно).
  3. Не связывайтесь с системными учетными данными;выполнить принудительное разрешение вручную (менее безопасно: более вероятно, что авторизация будет неправильной).

Если вам нужно связаться с демоном, тогда, возможно, будет сложнее сделать это через сокет или канал,Первый вариант - это правильный безопасный способ сделать это.Посмотрите , например, как ssh делает разделение привилегий .Вы также можете подумать, можете ли вы изменить свою архитектуру, чтобы вместо какого-либо взаимодействия процесс мог просто разделить часть памяти или дискового пространства.

Вы упоминаете, что рассматривали возможность запуска отдельного процесса для каждого пользователя, но вам нужен одинпрослушивает порт TCP.Вы все еще можете сделать это.Просто попросите главного демона прослушивать порт TCP и отправлять запросы каждому демону пользователя и связываться по мере необходимости (например, через доменные сокеты Unix).На самом деле это почти то же самое, что иметь разветвляющегося главного демона;Я думаю, что последнее оказалось бы проще реализовать.

Дополнительная информация: справочная страница credentials(7).Также обратите внимание, что в Linux есть файловая система uid / gids;это почти то же самое, что и эффективный uid / gids, за исключением других вещей, таких как отправка сигналов.Если ваши пользователи не имеют доступа к оболочке и не могут запустить произвольный код, вам не нужно беспокоиться о разнице.

2 голосов
/ 31 января 2011

Разрешить запуск одного сервера на порте преобладающего сервера и порождать дочерние процессы для пользователей, которые входят в систему. Дочерние процессы должны отбросить привилегии и от имени пользователя, который вошел в систему. Теперь дочерние процессы больше не могут причинять вред.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...