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

前端之家收集整理的这篇文章主要介绍了c – 在Linux上为Qt应用程序获取root访问权的正确方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

美好的一天

背景:

我正在为Linux系统创建一个OpenVPN包装器应用程序,该应用程序即将完成.我遇到了一些障碍.

OpenVPN需要root访问权来修改路由表(添加删除路由).这是事情变得模糊和混乱的地方.

希望通过扩展this question,可以共享一些行业标准答案和解决方案.

文档:

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

让我们考虑以下方法.

1.使用pkexec& polkits

有关最佳做法的一些信息,请查找官方freedesktop polkit documentation herehere

使用pkexec和polkits在线发现了一些教程
  – here,这帮我创建了我的polkit文件.
  – SO Thread
  – 用于Qt应用程序的lovely small tutorial

关于pkexec和polkits的简要解释(我的理解):

> polkits:

polkits由行动和规则组成(参见深入阅读和解释的文件).它定义了应用程序的操作以及与之关联的规则.规则可以定义为属于特定组的用户,其中操作查询规则,成功传递规则,用户自动进行身份验证(没有弹出密码提示),否则他们需要输入管理员密码

> pkexec:

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

这些需要在/usr/share / polkit-1 / actions /和/usr/share/polkit-1/rules.d/中添加操作(在其他目录中,请参阅所有位置的文档)

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

注意:有qt-polkit库可供使用,请参阅他们的github repository

对于简单的TL; DR版本,请参阅this

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

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

/usr/share/polkit-1/actions

Policy Kit文件名:
    com.myappname.something.policy //需要.policy

注意:

com.myappname.something

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

政策套件内容

关于我的政策文件的注释(重要的位)

>这只是一个示例,请参阅官方示例和说明的文档:
>< vendor>我的应用名称< / vendor>是应用程序名称,它可以有空格
>< action id =“com.myappname.something.myaction-name”>这里有任何动作名称.
>注意!
文件名 – > com.myappname.something.policy和,
动作ID – > com.myappname.something.myaction-name应该具有相同的命名空间
>图标名称应与最新的freedesktop图标规格here一致

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

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

只要它们符合大小并且是.png,您只能传递文件名(省略格式)

>非常重要:

当调用pkexec< myappname>,并且没有这些行时(老实说,我不太确定它们的用途),会遇到类似这样的错误:

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

Aborted (core dumped)

注意:保持密钥相同,但是您可以并且可能应该将exec.path密钥更改为您的应用程序位置.

政策工具包如何运作?

简而言之,如果你回顾前面提到的可爱的example(并跳过所有非常相似的文件名),它就变得清晰了.

当一个人跑:

pkexec 

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

这由动作(上面提到的策略工具包)处理.此外,规则利用动作id来执行附加查询等,这些可以在上面提供的示例中查看.

输入管理员密码后,根据输入默认值的“设置”(参见here),我们有:

auth_admin_keep

Like auth_admin but the authorization is kept for a brief period (e.g. five minutes).

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

2. Sudo(/ etc / sudoers):

这似乎是大多数需要root访问权限的用户方法,但不建议:

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

/bin/sh -c sudo -v

将导致各种Linux发行版中的退出代码为1(从而导致我搜索备选方案)

3. setuid():

一个非常好的example可以在这里找到,不幸的是它似乎不适用于现代Linux发行版,因为它是一个很容易被利用的安全漏洞.

简而言之,该过程需要一个:

chmod +x 

并使用getuid()检查是否在应用程序中设置了s位以获取用户ID,并使用getgid()获取用户的组ID.

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

但是,这似乎不适用于现代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))

Aborted (core dumped)

告别,setuid()

4.其他方法

> PAM

进一步阅读,见

> man page
> tutorial/explanation
>关于跨平台PAM整合的QT Forum问题

> QT用户模式
Qt提供了small implementation for acquiring root access,但它仅适用于使用yum包管理器的Linux发行版.

关于此问题的后续问题,见this QT Forum question

问题:

上面可能只包括一小部分可用的方法获取root访问权限,但考虑到某些应用程序是全局使用的,它们经常被攻击或撬开甚至受到攻击.

在做了这项研究之后,它扩大了我的知识,但没有给我一个推荐的确定方法,但只提示.

题:

上面哪种方法在工业上是首选的,即何时我应该使用另一种方法(PAM vs polkits vs simple sudo),如果有其他方法可用,这些是首选吗?

最佳答案

However,this does not seem to work with modern day Linux systems.
Here is the output of executing a root owned application with the s
bit set,run as a normal (unprivileged) user:

2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid,(null))

上述错误与现代Linux系统无关.它是对使用setuid而不理解它的愚蠢开发人员的Qt保护.

只需致电

QCoreApplication::setSetuidAllowed(true)

当你的应用程序启动时,你可以做setuid()就好了.您甚至可以在下载到“普通”用户之前运行特权命令.

摘要

您的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是根)

然后它启动一个新进程(在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");

最后一行将向子进程发送消息.您在子进程中读取stdin,解析命令,检查它以确保它不是恶意的(或恶意取决于您的意图!)并执行命令.

猜你在找的Linux相关文章