Передать привилегии root командам os в Python

Я добавляю функциональность в приложение PyQt5. Эта новая функция включает в себя копирование, связывание и удаление файлов (и ссылок), которые могут находиться в защищенных каталогах, поэтому такие команды, как os.symlink или же shutil.copyfile потерпит неудачу

Конечно, основное приложение не запускается с правами суперпользователя (и просьба об этом пользователей не обсуждается), поэтому мне нужен обходной путь.

Во-первых, конечно, обернуть критический код в блоки try / кроме и исследовать любые исключения. Если выясняется, что проблема заключается в отсутствии прав root, я бы попросил ввести пароль в диалоговом окне (предположительно, сохраняя пароль до тех пор, пока текущий диалог активен).

Но я не уверен, как я могу повторить шаг с паролем root. Я бы настоятельно предпочел сделать это в домене Python (или Qt предоставляет некоторую поддержку для файловых операций? Держу пари, что это возможно, но я не смог найти это). Я думаю, что это возможно сделать, выполнив файловые операции в команде оболочки и каким-то образом передать ей пароль, но, поскольку Python и PyQt были разработаны для того, чтобы оградить программиста от хитросплетений различий в ОС, я бы предпочел избежать этого пути.

Какой-то псевдокод должен дать четкое представление о вопросе:

def my_copy(source, dest):
    try:
        os.path.symlink(source, dest)
    except: # check for permission problem:
        # use dialog to ask for password
        # repeat the symlink procedure with password

2 ответа

Решение

То, что вы пытаетесь сделать здесь, в принципе невозможно в большинстве современных операционных систем, и на то есть веская причина.

Представьте себе типичного пользователя macOS или Windows, который ожидает авторизации, используя сканер отпечатков пальцев вместо ввода своего пароля. Или слепой пользователь. Или кто-то, кто по праву недоволен тем, что ваше приложение хранит свой пароль в виде открытого текста в строке Python в неядерной памяти (не говоря уже о диалоговом окне Windows, чьи события могут быть перехвачены любым процессом). Вот почему современные платформы поставляются с такой структурой, как libPAM /XSSO Услуги авторизации. и т.п.

И способ повышения привилегий настолько отличается в Windows и POSIX, или даже в macOS и Linux, не говоря уже о том, что он развивается так быстро, что, насколько я знаю, нет кроссплатформенного фреймворка для этого.

Фактически, большинство систем в первую очередь препятствуют повышению привилегий через приложения. В Windows вы часто просите ОС запустить вспомогательное приложение с повышенными привилегиями (и ОС затем применит соответствующую политику и решит, что запрашивать). В macOS вы обычно пишете демон LaunchServices, для которого вы получаете разрешение во время установки (используя специальные API установщика), а не во время выполнения. Для традиционных не серверных приложений POSIX вы обычно делаете что-то подобное, но с setuid помощник, который вы можете создать во время установки только потому, что установка запускается от имени пользователя root. Для традиционных серверов POSIX вы часто начинаете с прав пользователя root, а затем удаляете privs после разветвления и запуска аналогичного вспомогательного демона.

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

Оберните код try/ кроме в цикле со счетчиком:

def my_copy(source, dest):
    for attempts in [1, 2]:
        try:
            os.path.symlink(source, dest)
            # we succeeded, so don't try any more
            break
        except: # check for permission problem:
            if attempts == 1:
                # use dialog to ask for password
                # repeat the symlink procedure with password
            else:
                 # we already tried as root, and failed again
                 break
Другие вопросы по тегам