1

Я создаю утилиту, которая будет работать на машинах Linux. Для целей этого обсуждения, скажем, его аналог сделать.

Вот в чем дело: иногда, когда вы запускаете утилиту, она создает файлы в каталоге, в котором вы работаете, и они должны создаваться тем же пользователем / группой, что и пользователь, запускающий инструмент. Это сценарий "make main.o" - создайте main.o из main.c. Это будет значение по умолчанию, когда вы запускаете утилиту как свой собственный пользователь, и это нормально.

Иногда, когда вы запускаете утилиту, она создает файлы в /usr /local /bin и тому подобное, которые должны быть root:root. Это сценарий "sudo make install" - создайте /usr /local /bin / исполняемый файл под root:root. Это будет значение по умолчанию при запуске утилиты от имени пользователя root, что нормально.

Проблема в том, что во всех случаях утилите необходимо управлять некоторыми дополнительными файлами кэша, например, в /var /cache /utility. Когда вы запускаете утилиту от имени пользователя root, эти файлы представляют собой root:root, что является проблемой при следующем запуске утилиты от имени обычного пользователя. Они не могут быть удалены / изменены.

Что меня интересует, так это хорошая идея создать отдельного пользователя / группу для этой утилиты при ее установке? Я знаю, что Apache, SVN и другие делают это. Это единственный подход, который я могу придумать, но я открыт для других решений.

Если у меня действительно есть выделенный пользователь / группа для утилиты, как мне временно принять личность этого пользователя для управления файлами кэша, а затем возобновить предыдущую идентичность для оставшейся части выполнения (для создания обычных файлов в качестве пользователя :user, а системные файлы как root:root)?

То, что я получил до сих пор, выглядит примерно так:

  • getpwnam(prefined_utility_user_name) // получаем идентификатор пользователя
  • seteuid(utility_uid)
  • setegid(utility_gid)

// делать вещи в / var / cache / utility

  • seteuid(getuid()) // возобновить предыдущий идентификатор
  • setegid(getgid()) // возобновить предыдущую группу

ПРОБЛЕМА: предполагая, что предопределенная_идентичность НЕ работает при запуске утилиты как вы сами! Работает, когда вы запускаете от имени пользователя root (очевидно).

Я прекрасно добавляю себя и других пользователей в группу, связанную с утилитой. Однако это не работает. Итак - как мне заставить это работать? Это плохая идея?

РЕДАКТИРОВАТЬ: ответ на предложение ниже

Я еще немного почитал и думаю, что у меня есть хорошее решение, используя # 2, которое вы предложили, это выглядит так

Исполняемый файл утилиты принадлежит утилите: полезности и имеет права как u+s, так и g+s. Поэтому, когда я начинаю выполнять, у меня есть euid/egid полезности и полезности соответственно. У меня есть ruid/rgid того, кто запустил программу. Итак, что я могу сделать, когда я начинаю выполнять, setegid(getgid()) и seteuid(getuid()). Это позволяет процессу принять личность того, кто выполнил программу. Я буду поддерживать это в течение всей продолжительности программы, ЗА ИСКЛЮЧЕНИЕМ при работе с /var /cache /utility, я использую ту же технику, чтобы предположить наличие утилиты: служебной идентичности.

Мне не нужно разделять программное обеспечение, нет группы, к которой должен принадлежать ваш пользователь, исполняемому файлу просто нужны свой пользователь / группа, а также u+s и g+s. Я полагаю, вы должны верить, что программа не является вредоносной, но в любом случае вы должны предположить, что вы собираетесь ее выполнить. Мысли?

1 ответ1

0

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

Это интересная проблема. Есть разные способы решить это. Я не знаю, есть ли приемлемое решение для наилучшей практики, но вот несколько вариантов.

  1. Установите права доступа для липкой группы в /var/cache/utility .

    Этот подход позволяет вашей утилите работать с разрешениями инициаторов. Убедитесь, что пользователь входит в группу, которой принадлежит /var/cache/utility , и измените разрешения, чтобы назначение группы было привязанным ко всему содержимому. Вы можете сделать это с помощью следующего:

    mkdir /var/cache/utility
    chown -R :user /var/cache/utility
    chmod 2770 /var/cache/utility
    usermod -a -G users joe
    

    Теперь, поскольку joe в users , когда он запускает вашу утилиту, все в порядке. Групповое представление любых измененных файлов в /var/cache/utility останется users . Проблема в том, что нет группы, к которой автоматически принадлежат все пользователи. Таким образом, этот метод не будет работать автоматически для всех пользователей. Существует также проблема безопасности. Ваша утилита может корректно изменять файлы в /var/cache/utility , но эти методы открывают шлюзы на дикий запад пользовательского пространства.

  2. Разделите вашу утилиту на передние и задние части.

    Разделение утилиты на внешние и внутренние части неудобно, но заставляет вас формализовать рабочий интерфейс. Связь между частями может принимать две общие формы:

    • Socket comms, будь то Unix-сокеты или TCP-сокеты. Это требует, чтобы ваш сервер был сервисом.

    • Инструменты командной строки. Это значительно проще, чем при использовании сокетов, и ваш сервер не работает непрерывно.

    Идея состоит в том, чтобы uid-execute-sticky-bit на вашем бэкэнде, чтобы он автоматически запускался под учетной записью владельца, независимо от текущего вошедшего в систему пользователя. Внешний интерфейс будет по-прежнему работать под учетными данными пользователя.

    Посмотрите, можете ли вы разделить свою утилиту так, чтобы все манипуляции с кешем выполнялись бэкэндом, а другие действия выполнялись во внешнем интерфейсе. Вы можете установить uid серверной части следующим образом:

    chmod u+s /usr/bin/utility-back-end
    

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

    find / -xdev \( -perm -4000 \) -type f -print0 | xargs -0 ls -l
    

Надеюсь, это поможет.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .