在 Linux 上为 Qt 应用程序获取 root 访问权限的正确方法

2023-12-28

Good day

背景:

我正在为 Linux 系统创建一个 OpenVPN 包装应用程序,该应用程序已接近完成。我遇到了一个小障碍。

OpenVPN 需要 root 访问权限才能修改路由表(添加和删除路由)。这就是事情变得有点模糊和混乱的地方。

希望通过扩展这个问题 https://stackoverflow.com/questions/5929220/get-root-privileges-to-my-qt-app,一些行业标准答案和解决方案可以分享。

文档:

因此,经过几个小时的搜索,我编制了一份获取 root 访问权限的可能方法列表,但似乎没有一个是官方的,也没有提供任何真正可靠的指导来获取此 SU 权限。

让我们考虑以下方法。


1. 使用 pkexec 和 polkits

请找官方freedesktop polkit 文档在这里 https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html and here https://www.freedesktop.org/software/polkit/docs/latest/polkit-apps.html有关最佳实践的一些信息

网上找到了一些使用 pkexec 和 polkits 的教程 -here https://greyok.github.io/simple-polkit-tutorial.html,这帮助我创建了我的 polkit 文件。 -所以线程 https://stackoverflow.com/questions/5625870/how-to-launch-a-qprocess-with-root-rights- 还有一个可爱的小教程 https://q-a-assistant.info/life-arts/is-there-a-way-to-gain-superuser-access-from-a-qt-app/3365703对于 Qt 应用程序

简要解释一下(我的理解)pkexec and polkits:

  • polkits:

polkit 由操作和规则组成(有关深入阅读和解释,请参阅文档)。它定义了应用程序的操作以及与其关联的规则。规则可以定义为属于特定组的用户,通过该操作查询规则,如果成功通过规则,则自动对用户进行身份验证(不会弹出密码提示),否则需要输入管理员权限密码

  • pkexec:

用于与 polkit 操作交互并对应用程序进行身份验证以获取 root 访问权限的应用程序。

这些需要添加一个动作/usr/share/polkit-1/actions/ and /usr/share/polkit-1/rules.d/(除其他目录外,请参阅所有位置的文档)

这种方法似乎很好用(但需要更多的解释才能轻松理解,我认为)

注:有qt-polkit可供使用的库,请参阅它们github 存储库 https://github.com/KDE/polkit-qt-1

对于简单的 TL;DR 版本,请参阅this https://askubuntu.com/a/525515/376524

我创建的 polkit 文件(请注意,这可能不正确,但它对我有用):

可以找到/添加它的位置(还有其他位置)

/usr/share/polkit-1/actions

策略工具包文件名: com.myappname.something.policy //.policy是必须的

Note:

com.myappname.something

被称为策略的命名空间(阅读文档,这个不会清楚)

政策工具包内容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/software/polkit/policyconfig-1.dtd">
<policyconfig>
  <vendor>My App Name</vendor>
  <vendor_url>http://myappurl.com/</vendor_url>

  <action id="com.myappname.something.myaction-name">
    <description>Run the polkit for My App which requires it for X usage</description>
    <message>My App requires access to X, which requires root authentication, please let me have su access</message>
    <icon_name>myappname</icon_name>
    <defaults>
      <allow_any>auth_admin_keep</allow_any>
      <allow_inactive>auth_admin_keep</allow_inactive>
      <allow_active>auth_admin_keep</allow_active>
    </defaults>
    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/myappname</annotate>
    <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
  </action>

</policyconfig>

关于我的策略文件的注释(重要部分)

  • 这只是一个示例,请参阅官方文档获取示例和说明:
  • <vendor>My App Name</vendor>是应用程序名称,可以有空格
  • <action id="com.myappname.something.myaction-name">此处任何操作名称。

  • 笔记! 文件名->com.myappname.something.policy和, 这action id -> com.myappname.something.myaction-name应该有相同的命名空间

  • 图标名称应符合最新的 freedesktop 图标规范here https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#example

TL;DR(或者不想): 图标位置是:

 1. /home/yourusername/.icons (sometimes not there)
 2. /home/yourusername/.local/share/icons
 2. /usr/share/icons

只要它们符合尺寸并且是.png,可以只传递文件名(省略格式)

  • Very Important:

    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/myappname</annotate>
    <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
    

打电话时pkexec <myappname>,并且没有这些行(老实说,我不太确定他们的目的),会遇到类似这样的错误:

2017-12-19 12::58:24 Fatal: QXcbConnection: Could not connect to display  ((null):0, (null))

Aborted (core dumped)

注意:保留key相同,但是您可以并且可能应该更改exec.path您的应用程序位置的关键。

政策工具包如何发挥作用?

简而言之,如果你回顾一下可爱的example https://greyok.github.io/simple-polkit-tutorial.html前面提到过(并跳过所有非常相似的文件名称),它就变得清晰了。

当一个人运行时:

pkexec <myappname> 

这会调用本地身份验证代理以 root 身份运行应用程序(在我们的示例中)。

这是由actions(上述政策套件)。此外,规则利用action id执行附加查询等,可以在上面提供的示例中查看。

输入管理员密码后,根据输入默认值的“设置”(请参阅here https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html), 我们有:

auth_admin_keep

与 auth_admin 类似,但授权会保留很短的一段时间(例如五分钟)。

因此,用户可以(在我的 OpenVPN 应用程序中)在接下来的 5 分钟内连接到 OpenVPN 连接,直到再次请求密码。


2. Sudo(/etc/sudoers):

对于大多数需要 root 访问权限的用户来说,这似乎是首选方法,但不建议这样做:

例如在运行主应用程序之前通过调用 singleShot 检查 root 访问权限QProcess带参数:

/bin/sh -c sudo -v

将导致退出代码为1在各种 Linux 发行版中(因此导致我寻找替代方案)


3. setuid():

一个十分好的example https://forum.qt.io/post/153042可以在这里找到,不幸的是它似乎不适用于现代 Linux 发行版,因为它是一个很容易被利用的安全漏洞。

简而言之,这一过程需要:

chmod +x <executable>

并检查s位在应用程序中使用设置getuid()获取用户 ID 和getgid()获取用户的组ID。

这些函数可以在 Linux 头文件中找到,定义如下:

<sys/types.h> // defines structs
<unistd.h>    // defines methods

然而,这似乎不适用于现代 Linux 系统。这是使用 root 拥有的应用程序执行的输出s位设置,以普通(非特权)用户身份运行:

2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid, this is a security hole. ((null):0, (null))

Aborted (core dumped)

告别,setuid()


4、其他方法:

  • PAM

如需进一步阅读,请参阅

  • man page https://linux.die.net/man/3/pam
  • 教程/解释 https://www.packtpub.com/books/content/development-pluggable-authentication-modules-pam
  • A QT Forum https://forum.qt.io/topic/15005/qt-linux-unix-pam-and-cross-platform-authentication-systems关于跨平台 PAM 集成的问题

    • QT usermodeQt 提供了一个获取 root 访问权限的小实现 https://wiki.qt.io/How_to_get_applications_running_with_root_privileges,但它仅适用于使用以下命令的 Linux 发行版yum包管理器。

对此有一个后续问题,请参阅这个QT论坛问题 https://forum.qt.io/topic/11729/admin-user-mode-adapt-gui-to-current-privileges


Problem:

以上可能仅包括获取root访问权限的可用方法的一小部分,但是考虑到某些应用程序在全球范围内使用,它们经常受到攻击或撬开甚至被破坏。

经过这项研究,它拓宽了我的知识面,但并没有给我一个推荐的万无一失的方法,而只是提示。

问题:

上述哪种方法在行业中是首选,即我什么时候应该使用其中一种而不是另一种(PAM、polkits 或简单 sudo),如果有其他方法可用,这些是首选方法吗?


然而,这似乎不适用于现代 Linux 系统。 这是使用 s 执行 root 拥有的应用程序的输出 位设置,以普通(非特权)用户身份运行:

2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid, this is a security hole. ((null):0, (null))

上述错误与现代 Linux 系统无关。它是 Qt 的保护措施,防止愚蠢的开发人员在不了解 setuid 的情况下使用它。

只需致电

QCoreApplication::setSetuidAllowed(true)

当您的应用程序启动时,您就可以执行 setuid() 了。您甚至可以在降级为“普通”用户之前运行特权命令。

Summary:

您的 Qt 应用程序必须具有 root 所有者,并设置了 setuid 位。示例 debmaker 是我的 Qt 应用程序,我想从中执行特权操作。因此,在构建 debmaker 后,我会:

sudo chown root:root debmaker
sudo chmod 4755 debmaker

(后者设置setuid位)

现在运行 Qt 应用程序

./debmaker

应用程序做的第一件事是检查 geteuid()==0 和 getuid()==1000 (1000 是我的用户 ID,0 是 root)

然后它启动一个新进程(使用 Qt 中的 QProcess)。这将在特权模式下运行。 (例如我的子进程称为 chroot)

现在通过调用将主应用程序(我的 debmaker)降至普通用户级别

setuid(getuid());

chroot(子进程)将继续以 root 用户身份运行。

主应用程序现在不再以提升模式运行,但可以向仍以提升模式运行的子进程发送请求。

QProcess *chroot = new QProcess;
blah blah setup the chroot and start it
chroot->write("chown root:root /home/oosman/foo");

最后一行将向子进程发送一条消息。您在子进程中读取标准输入,解析命令,检查它以确保其不是恶意的(或恶意的,具体取决于您的意图!)并执行命令。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Linux 上为 Qt 应用程序获取 root 访问权限的正确方法 的相关文章

随机推荐