]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/polkit.c
build-sys: make PolicyKit support compile-time optional (was runtime-optional already)
[thirdparty/systemd.git] / src / shared / polkit.c
CommitLineData
f401e48c
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
f401e48c
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
f401e48c 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
f401e48c
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <sys/types.h>
23
24#include <errno.h>
25
26#include "util.h"
27#include "dbus-common.h"
28#include "polkit.h"
29
f401e48c
LP
30int verify_polkit(
31 DBusConnection *c,
32 DBusMessage *request,
33 const char *action,
34 bool interactive,
89f13440 35 bool *_challenge,
f401e48c
LP
36 DBusError *error) {
37
46ba8aae
LP
38
39#ifdef ENABLE_POLKIT
f401e48c
LP
40 DBusMessage *m = NULL, *reply = NULL;
41 const char *unix_process = "unix-process", *pid = "pid", *starttime = "start-time", *cancel_id = "";
f401e48c
LP
42 uint32_t flags = interactive ? 1 : 0;
43 pid_t pid_raw;
44 uint32_t pid_u32;
45 unsigned long long starttime_raw;
46 uint64_t starttime_u64;
47 DBusMessageIter iter_msg, iter_struct, iter_array, iter_dict, iter_variant;
48 int r;
89f13440 49 dbus_bool_t authorized = FALSE, challenge = FALSE;
46ba8aae
LP
50#endif
51 const char *sender;
bece1f52 52 unsigned long ul;
f401e48c
LP
53
54 assert(c);
55 assert(request);
56
57 sender = dbus_message_get_sender(request);
58 if (!sender)
59 return -EINVAL;
60
bece1f52 61 ul = dbus_bus_get_unix_user(c, sender, error);
02902965 62 if (ul == (unsigned long) -1)
bece1f52
LP
63 return -EINVAL;
64
65 /* Shortcut things for root, to avoid the PK roundtrip and dependency */
66 if (ul == 0)
67 return 1;
68
46ba8aae
LP
69#ifdef ENABLE_POLKIT
70
f8e2fb7b 71 pid_raw = bus_get_unix_process_id(c, sender, error);
f401e48c
LP
72 if (pid_raw == 0)
73 return -EINVAL;
74
75 r = get_starttime_of_pid(pid_raw, &starttime_raw);
76 if (r < 0)
77 return r;
78
79 m = dbus_message_new_method_call(
80 "org.freedesktop.PolicyKit1",
81 "/org/freedesktop/PolicyKit1/Authority",
82 "org.freedesktop.PolicyKit1.Authority",
83 "CheckAuthorization");
84 if (!m)
85 return -ENOMEM;
86
87 dbus_message_iter_init_append(m, &iter_msg);
88
89 pid_u32 = (uint32_t) pid_raw;
90 starttime_u64 = (uint64_t) starttime_raw;
91
92 if (!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_STRUCT, NULL, &iter_struct) ||
93 !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &unix_process) ||
94 !dbus_message_iter_open_container(&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_array) ||
95 !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
96 !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &pid) ||
97 !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "u", &iter_variant) ||
98 !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &pid_u32) ||
99 !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
100 !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
101 !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
102 !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &starttime) ||
103 !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "t", &iter_variant) ||
104 !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT64, &starttime_u64) ||
105 !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
106 !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
107 !dbus_message_iter_close_container(&iter_struct, &iter_array) ||
108 !dbus_message_iter_close_container(&iter_msg, &iter_struct) ||
109 !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &action) ||
110 !dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_ARRAY, "{ss}", &iter_array) ||
111 !dbus_message_iter_close_container(&iter_msg, &iter_array) ||
112 !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_UINT32, &flags) ||
113 !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &cancel_id)) {
114 r = -ENOMEM;
115 goto finish;
116 }
117
118 reply = dbus_connection_send_with_reply_and_block(c, m, -1, error);
119 if (!reply) {
f401e48c 120
8885064f
LP
121 /* Treat no PK available as access denied */
122 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN)) {
123 r = -EACCES;
124 dbus_error_free(error);
125 goto finish;
126 }
127
f401e48c
LP
128 r = -EIO;
129 goto finish;
130 }
131
132 if (!dbus_message_iter_init(reply, &iter_msg) ||
133 dbus_message_iter_get_arg_type(&iter_msg) != DBUS_TYPE_STRUCT) {
134 r = -EIO;
135 goto finish;
136 }
137
138 dbus_message_iter_recurse(&iter_msg, &iter_struct);
139
140 if (dbus_message_iter_get_arg_type(&iter_struct) != DBUS_TYPE_BOOLEAN) {
141 r = -EIO;
142 goto finish;
143 }
144
145 dbus_message_iter_get_basic(&iter_struct, &authorized);
146
89f13440
LP
147 if (!dbus_message_iter_next(&iter_struct) ||
148 dbus_message_iter_get_arg_type(&iter_struct) != DBUS_TYPE_BOOLEAN) {
149 r = -EIO;
150 goto finish;
151 }
152
153 dbus_message_iter_get_basic(&iter_struct, &challenge);
154
155 if (authorized)
156 r = 1;
157 else if (_challenge) {
158 *_challenge = !!challenge;
159 r = 0;
160 } else
161 r = -EPERM;
f401e48c
LP
162
163finish:
f401e48c
LP
164 if (m)
165 dbus_message_unref(m);
166
167 if (reply)
168 dbus_message_unref(reply);
169
170 return r;
46ba8aae
LP
171#else
172 return -EPERM;
173#endif
f401e48c 174}