C++の応用 - PolKit
ナビゲーションに移動
検索に移動
概要
PolKit(以前は、PolicyKitとして知られていた)は、非特権ユーザセッションと特権システムコンテキストの間のネゴシエータとして機能するアプリケーションフレームワークである。
PolKitは、ユーザ、グループ、名前により特定のアクションを制限する機能を持つ。
ユーザセッションのプロセスが、システムコンテキストでアクションを実行するごとに、PolKitはクエリされる。
所謂、ポリシーで指定された設定に基づいて、"yes"、"no"、"needs authentication"である可能性がある。
sudo
のような古典的な権限承認プログラムとは異なり、PolKitはセッション全体に対してroot権限を与えるのではなく、各アクションに対してのみ権限を与える。
Qtを使用してPolkitを利用する場合は、Qtの基礎_-_管理者権限のページを参照すること。
PolKitのインストール
パッケージ管理システムからインストール
# RHEL sudo dnf install polkit-devel # SUSE sudo zypper install polkit-devel
ソースコードからインストール
多くのLinuxディストリビューションには、初期状態でPolKitがインストールされている。
もし、別途インストールする必要がある場合、ソースコードからPolKitをインストールする。
PolKitのビルドに必要なライブラリをインストールする。
# SUSE sudo zypper install meson dbus-1-devel libexpat-devel systemd-devel glib2-devel gtk3-devel gobject-introspection-devel mozjs78-devel pam-devel duktape-devel gtk-dpc
PolKitの公式WebサイトまたはGitLabにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf polkit-<バージョン>.tar.gz cd polkit-<バージョン>
また、git clone
コマンドを実行して、PolKitのソースコードをダウンロードする。
git clone https://gitlab.freedesktop.org/polkit/polkit.git cd polkit
PolKitをビルドおよびインストールする。
設定可能なオプションの一覧は、meson configure
コマンドで取得することができる。
# RHEL meson setup build --prefix=<PolKitのインストールディレクトリ> -Dos_type=redhat -Dexamples=true -Dman=true -Dgtk_doc=true # SUSE meson setup build --prefix=<PolKitのインストールディレクトリ> -Dos_type=suse -Dexamples=true -Dman=true -Dgtk_doc=true meson compile -C build meson install -C build
CMakeファイルの設定
Pkg-Configを使用しない場合
# CMakeLists.txtファイル
# 実行ファイルの場合
add_executable(<プロジェクト名>
# ...略
)
# ライブラリの場合
add_library(<プロジェクト名>
# ...略
)
## インクルードファイル
include_directories(
# ...略
/usr/lib64/glib-2.0/include
/usr/include/glib-2.0
/usr/include/polkit-1
# ...略
)
## ライブラリファイル
target_link_libraries(<プロジェクト名>
# ...略
glib-2.0
polkit-gobject-1
gobject-2.0
gio-2.0
# ...略
)
Pkg-Configを使用する場合
# CMakeLists.txtファイル
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLIB2 REQUIRED glib-2.0)
pkg_check_modules(POLKITGOBJECT2 REQUIRED polkit-gobject-1)
pkg_check_modules(GOBJECT2 REQUIRED gobject-2.0)
pkg_check_modules(GIO2 REQUIRED gio-2.0)
# 実行ファイルの場合
add_executable(<プロジェクト名>
# ...略
)
# ライブラリの場合
add_library(<プロジェクト名>
# ...略
)
include_directories(
${GLIB2_INCLUDE_DIRS}
${POLKITGOBJECT2_INCLUDE_DIRS}
${GOBJECT2_INCLUDE_DIRS}
${GIO2_INCLUDE_DIRS}
)
link_directories(
${GLIB2_LIBRARY_DIRS}
${POLKITGOBJECT2_LIBRARY_DIRS}
${GOBJECT2_LIBRARY_DIRS}
${GIO2_LIBRARY_DIRS}
)
add_definitions(
${GLIB2_CFLAGS_OTHER}
${POLKITGOBJECT2_CFLAGS_OTHER}
${GOBJECT2_CFLAGS_OTHER}
${GIO2_CFLAGS_OTHER}
)
QMakeファイルの設定
Pkg-Configを使用する場合
CONFIG += link_pkgconfig
PKGCONFIG += \
glib-2.0 \
polkit-gobject-1 \
gobject-2.0 \
gio-2.0
LIBS += \
-lglib-2.0 \
-lpolkit-gobject-1 \
-lgobject-2.0 \
-lgio-2.0
Pkg-Configを使用しない場合
LIBS += \
-lglib-2.0 \
-lpolkit-gobject-1 \
-lgobject-2.0 \
-lgio-2.0
INCLUDEPATH += \
/usr/lib64/glib-2.0/include \
/usr/include/glib-2.0 \
/usr/include/polkit-1
サンプルコード
#include <polkit/polkit.h>
void check_authorization(PolkitAuthority *authority, GAsyncResult *res, gpointer user_data);
gboolean do_cancel(GCancellable *cancellable);
int main()
{
// Action ID for PolKit
const gchar *action_id = "org.example.policykit.do";
// メインイベントループを作成
GMainLoop *loop = g_main_loop_new(nullptr, FALSE);
// 権威への参照を同期的に取得 (応答を受け取るまで呼び出し元のスレッドはブロックされる)
// 非同期にする場合は、polkit_authority_get_async関数を使用する
PolkitAuthority *authority = polkit_authority_get_sync(nullptr, nullptr);
// 多くのクライアントはD-Busを介してメカニズムと通信するため、PolkitSystemBusNameを使用する
// しかし、この例では、呼び出しプロセスのプロセスIDを使用する
// 親プロセスが終了した場合、init(1)が認可されているかどうかをチェックしないように注意する (常に認可されている)
// 親プロセスのPIDを取得
auto parent_pid = getppid();
if (parent_pid == 1) {
g_printerr("Parent process was reaped by init(1)\n");
return -1;
}
// 詳細情報の取得
PolkitSubject *subject = polkit_unix_process_new_for_owner(parent_pid, 0, getuid());
// PolKit認証画面でタイムアウトを使用する場合 (以下の例では、10[sec])
GCancellable *cancellable = g_cancellable_new();
g_timeout_add(1000 * 10, (GSourceFunc)do_cancel, cancellable);
// 認証画面の表示 (タイムアウト設定なし)
polkit_authority_check_authorization(authority, subject, action_id, nullptr,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
nullptr, (GAsyncReadyCallback)check_authorization, loop);
// 認証画面の表示 (タイムアウト設定あり)
// polkit_authority_check_authorization(authority, subject, action_id, nullptr,
// POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
// cancellable, (GAsyncReadyCallback)check_authorization, loop);
// メインイベントループの実行
g_main_loop_run(loop);
// 終了処理
g_object_unref(authority);
g_object_unref(subject);
g_object_unref(cancellable);
g_main_loop_unref(loop);
return 0;
}
// 認証処理
void check_authorization(PolkitAuthority *authority, GAsyncResult *res, gpointer user_data)
{
GError *error = nullptr;
PolkitAuthorizationResult *result = polkit_authority_check_authorization_finish(authority, res, &error);
if (error != nullptr) {
// タイムアウトになった場合 (タイムアウト処理を指定する必要がある)
g_print ("Error checking authorization: %s\n", error->message);
g_error_free(error);
}
else {
const gchar *result_str;
if (polkit_authorization_result_get_is_authorized(result)) {
// 認証に成功した場合
result_str = "authorized";
}
else if (polkit_authorization_result_get_is_challenge(result)) {
// より詳細な情報が提供された場合に認可されているかどうかを取得
result_str = "challenge";
}
else {
// 認証をキャンセルした場合
result_str = "not authorized";
}
g_print("Authorization result: %s\n", result_str);
}
// メインイベントループの終了
auto loop = static_cast<GMainLoop*>(user_data);
g_main_loop_quit(loop);
}
// タイムアウト処理
gboolean do_cancel(GCancellable *cancellable)
{
g_print("Timer has expired; cancelling authorization check\n");
g_cancellable_cancel(cancellable);
return FALSE;
}