当前位置: 首页 > 工具软件 > KDE-Services > 使用案例 >

KDE提权操作

华萧迟
2023-12-01

背景

之前项目中遇到了一个问题,非管理员权限的用户登录桌面系统之后,也需要进行一些需要root权限的操作,而出于安全方面的考虑,无法直接将用户加入root组,那么桌面系统的源码中就需要使用到KDE提供的提权功能。KDE提供的提权功能可以给指定的自定义操作函数提供等同于root的权限。kde提权操作,需要用到KAuth模块。对这个实现流程做一个记录,方便后续查看。

提权程序的编写

首先是usermanage.actions文件,actions文件是指明需要进行提权操作的函数接口,其中需要着重关注的,是[org.kde.auth.usermanage.read]中的read,此名称必须与后续编写的提权函数名称完全相同,[org.kde.auth.usermanage.write]和[org.kde.auth.usermanage.longaction]中的write、longaction同理。Name和Description自定义。

[Domain]
Name=Auth_Example
Icon=utilities-terminal

[org.kde.auth.usermanage.read]
Name=Example read action
Description=The system is attempting to perform the read action
Policy=yes

[org.kde.auth.usermanage.write]
Name=Example write action
Description=The system is attempting to perform the write action
Policy=yes

[org.kde.auth.usermanage.longaction]
Name=Example longaction
Description=The longaction 
Policy=yes

CMakeLists.txt文件如下,着重关注末尾几行:

project(UserManageHelper)

cmake_minimum_required(VERSION 2.8.12)

################# Disallow in-source build #################

#if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
#   message(FATAL_ERROR "plasma-settings requires an out of source build. Please create a separate build directory and run 'cmake path_to_plasma-settings [options]' there.")
#endif()

#include(CPack)
#include(FeatureSummary)
#find_package(PkgConfig)

################# set KDE specific information #################

find_package(ECM 0.0.8 REQUIRED NO_MODULE)

# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})

include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings)
#include(ECMQMLModules)

find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Core)

################# now find all used packages #################

set (QT_MIN_VERSION "5.4.0")

find_package(KF5Auth NO_MODULE)
find_package(Qt5 5.10.1 CONFIG REQUIRED COMPONENTS
    Core
)

add_executable(usermanagehelper UserManageHelper.cpp)

target_link_libraries(usermanagehelper Qt5::Core KF5::Auth)

install(TARGETS usermanagehelper DESTINATION ${KAUTH_HELPER_INSTALL_DIR})

kauth_install_actions(org.kde.auth.usermanage usermanage.actions)

kauth_install_helper_files(usermanagehelper org.kde.auth.usermanage root)

set_target_properties(usermanagehelper PROPERTIES COMPILE_FLAGS "-Wall -ggdb")

代码的编写就很简单了,继承QObject,实现几个槽函数,这个槽函数的名称和actions文件中是对应的:

#undef QT_NO_CAST_FROM_ASCII
#include "grp.h"
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <QFile>
#include <QTextStream>
#include <QThread>

//! [helper_declaration]
#include <kauth.h>    // 提权操作所必须包含的头文件
#include <QObject>
#include <iostream>

using namespace KAuth;

class UserManageHelper : public QObject
{
    Q_OBJECT
public:
    UserManageHelper();

public Q_SLOTS:
        ActionReply read(const QVariantMap& args);    // 提权操作通用函数原型
        ActionReply write(const QVariantMap& args);
        ActionReply longaction(const QVariantMap& args);
};

UserManageHelper::UserManageHelper()
{

}

ActionReply UserManageHelper::read(const QVariantMap& args)
{
    ActionReply reply;
    QString newfilename = args["newfilename"].toString();    // 取出参数
    QString oldfilename = args["oldfilename"].toString();
    …… // 实现自定义操作
    return reply;
}
//! [helper_read_action]

ActionReply UserManageHelper::write(const QVariantMap &args)
{
//    Q_UNUSED(args)
//    return ActionReply::SuccessReply();

    ActionReply reply;
    ……
    return reply;
}

//! [helper_longaction]
ActionReply UserManageHelper::longaction(const QVariantMap &args)
{
    ……
    return ActionReply::SuccessReply();
}

// 这里需要注意,这里需要替换成实际的名称
KAUTH_HELPER_MAIN("org.kde.auth.usermanage", UserManageHelper)


#include "UserManageHelper.moc"

安装和配置

编译完成后,build目录下除了常规的cmake生成文件以外,需要关注的生成文件还有org.kde.auth.usermanage.conf、org.kde.auth.usermanage.policy和org.kde.auth.usermanage.service。将这三个文件和生成可执行文件拷贝到指定路径,然后添加权限,即可完全提权操作的安装配置。

\cp UserManageHelper/build/usermanagehelper /usr/libexec/kf5/kauth/usermanagehelper
\cp UserManageHelper/build/org.kde.auth.usermanage.policy /usr/share/polkit-1/actions/org.kde.auth.usermanage.policy
\cp UserManageHelper/build/org.kde.auth.usermanage.conf /etc/dbus-1/system.d/org.kde.auth.usermanage.conf
\cp UserManageHelper/build/org.kde.auth.usermanage.service /usr/share/dbus-1/system-services/org.kde.auth.usermanage.service

sudo chmod 755 /usr/libexec/kf5/kauth/usermanagehelper

调用

示例的调用代码如下:

……
#include <KJob>
#include <KIO/CopyJob>
#include <KIconLoader>
#include <KUser>
……

QVariantMap args;
args["newfilename"] = group_filename;    // 设定参数,也就是提权函数中取出的参数
args["oldfilename"] = new_group_filename;
Action readAction(QLatin1String("org.kde.auth.usermanage.read"));
readAction.setHelperId(QLatin1String("org.kde.auth.usermanage"));
readAction.setArguments(args);

ExecuteJob *job = readAction.execute();    
if (!job->exec()) {
    int error = job->error();
    qDebug() << "KAuth returned an error code:" << job->error();
} else {
    QVariantMap map = job->data();
    QString contents = job->data()["contents"].toString();
}

参考链接

https://www.twblogs.net/a/5bf2f67dbd9eee04040a7e60/?lang=zh-cn

 类似资料: