1 /*
2 * Copyright (C) 2013, 2014, 2016 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19 #include <config.h>
20
21 #include "testutils.h"
22
23 #if defined(__ELF__)
24
25 # include "virpolkit.h"
26 # include "virgdbus.h"
27 # include "virlog.h"
28 # include "virmock.h"
29 # define VIR_FROM_THIS VIR_FROM_NONE
30
31 VIR_LOG_INIT("tests.systemdtest");
32
33 /* Some interesting numbers */
34 # define THE_PID 1458
35 # define THE_TIME 11011000001
36 # define THE_UID 1729
37
VIR_MOCK_WRAP_RET_ARGS(g_dbus_connection_call_sync,GVariant *,GDBusConnection *,connection,const gchar *,bus_name,const gchar *,object_path,const gchar *,interface_name,const gchar *,method_name,GVariant *,parameters,const GVariantType *,reply_type,GDBusCallFlags,flags,gint,timeout_msec,GCancellable *,cancellable,GError **,error)38 VIR_MOCK_WRAP_RET_ARGS(g_dbus_connection_call_sync,
39 GVariant *,
40 GDBusConnection *, connection,
41 const gchar *, bus_name,
42 const gchar *, object_path,
43 const gchar *, interface_name,
44 const gchar *, method_name,
45 GVariant *, parameters,
46 const GVariantType *, reply_type,
47 GDBusCallFlags, flags,
48 gint, timeout_msec,
49 GCancellable *, cancellable,
50 GError **, error)
51 {
52 GVariant *reply = NULL;
53 g_autoptr(GVariant) params = parameters;
54
55 if (params)
56 g_variant_ref_sink(params);
57
58 VIR_MOCK_REAL_INIT(g_dbus_connection_call_sync);
59
60 if (STREQ(bus_name, "org.freedesktop.PolicyKit1") &&
61 STREQ(method_name, "CheckAuthorization")) {
62 g_autoptr(GVariantIter) iter = NULL;
63 GVariantBuilder builder;
64 char *type;
65 char *actionid;
66 int is_authorized = 1;
67 int is_challenge = 0;
68
69 g_variant_get(params, "((&s@a{sv})&sa{ss}@u@s)",
70 &type,
71 NULL,
72 &actionid,
73 &iter,
74 NULL,
75 NULL);
76
77 g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}"));
78
79 if (STREQ(actionid, "org.libvirt.test.success")) {
80 is_authorized = 1;
81 is_challenge = 0;
82 } else if (STREQ(actionid, "org.libvirt.test.challenge")) {
83 is_authorized = 0;
84 is_challenge = 1;
85 } else if (STREQ(actionid, "org.libvirt.test.cancelled")) {
86 is_authorized = 0;
87 is_challenge = 0;
88 g_variant_builder_add(&builder, "{ss}", "polkit.dismissed", "true");
89 } else if (STREQ(actionid, "org.libvirt.test.details")) {
90 char *key;
91 char *val;
92 is_authorized = 0;
93 is_challenge = 0;
94
95 while (g_variant_iter_loop(iter, "{ss}", &key, &val)) {
96 if (STREQ(key, "org.libvirt.test.person") && STREQ(val, "Fred")) {
97 is_authorized = 1;
98 is_challenge = 0;
99 }
100 }
101 } else {
102 is_authorized = 0;
103 is_challenge = 0;
104 }
105
106 reply = g_variant_new("((bb@a{ss}))", is_authorized, is_challenge,
107 g_variant_builder_end(&builder));
108 } else {
109 reply = g_variant_new("()");
110 }
111
112 return reply;
113 }
114
115
116
testPolkitAuthSuccess(const void * opaque G_GNUC_UNUSED)117 static int testPolkitAuthSuccess(const void *opaque G_GNUC_UNUSED)
118 {
119 if (virPolkitCheckAuth("org.libvirt.test.success",
120 THE_PID,
121 THE_TIME,
122 THE_UID,
123 NULL,
124 true) < 0)
125 return -1;
126
127 return 0;
128 }
129
130
testPolkitAuthDenied(const void * opaque G_GNUC_UNUSED)131 static int testPolkitAuthDenied(const void *opaque G_GNUC_UNUSED)
132 {
133 int rv;
134 virErrorPtr err;
135
136 rv = virPolkitCheckAuth("org.libvirt.test.deny",
137 THE_PID,
138 THE_TIME,
139 THE_UID,
140 NULL,
141 true);
142
143 if (rv == 0) {
144 fprintf(stderr, "Unexpected auth success\n");
145 return -1;
146 } else if (rv != -2) {
147 return -1;
148 }
149
150 err = virGetLastError();
151 if (!err || !strstr(err->message,
152 _("access denied by policy"))) {
153 fprintf(stderr, "Incorrect error response\n");
154 return -1;
155 }
156
157 return 0;
158 }
159
160
testPolkitAuthChallenge(const void * opaque G_GNUC_UNUSED)161 static int testPolkitAuthChallenge(const void *opaque G_GNUC_UNUSED)
162 {
163 int rv;
164 virErrorPtr err;
165
166 rv = virPolkitCheckAuth("org.libvirt.test.challenge",
167 THE_PID,
168 THE_TIME,
169 THE_UID,
170 NULL,
171 true);
172
173 if (rv == 0) {
174 fprintf(stderr, "Unexpected auth success\n");
175 return -1;
176 } else if (rv != -2) {
177 return -1;
178 }
179
180 err = virGetLastError();
181 if (!err || err->domain != VIR_FROM_POLKIT ||
182 err->code != VIR_ERR_AUTH_UNAVAILABLE ||
183 !strstr(err->message, _("no polkit agent available to authenticate"))) {
184 fprintf(stderr, "Incorrect error response\n");
185 return -1;
186 }
187
188 return 0;
189 }
190
191
testPolkitAuthCancelled(const void * opaque G_GNUC_UNUSED)192 static int testPolkitAuthCancelled(const void *opaque G_GNUC_UNUSED)
193 {
194 int rv;
195 virErrorPtr err;
196
197 rv = virPolkitCheckAuth("org.libvirt.test.cancelled",
198 THE_PID,
199 THE_TIME,
200 THE_UID,
201 NULL,
202 true);
203
204 if (rv == 0) {
205 fprintf(stderr, "Unexpected auth success\n");
206 return -1;
207 } else if (rv != -2) {
208 return -1;
209 }
210
211 err = virGetLastError();
212 if (!err || !strstr(err->message,
213 _("user cancelled authentication process"))) {
214 fprintf(stderr, "Incorrect error response\n");
215 return -1;
216 }
217
218 return 0;
219 }
220
221
testPolkitAuthDetailsSuccess(const void * opaque G_GNUC_UNUSED)222 static int testPolkitAuthDetailsSuccess(const void *opaque G_GNUC_UNUSED)
223 {
224 const char *details[] = {
225 "org.libvirt.test.person", "Fred",
226 NULL,
227 };
228
229 if (virPolkitCheckAuth("org.libvirt.test.details",
230 THE_PID,
231 THE_TIME,
232 THE_UID,
233 details,
234 true) < 0)
235 return -1;
236
237 return 0;
238 }
239
240
testPolkitAuthDetailsDenied(const void * opaque G_GNUC_UNUSED)241 static int testPolkitAuthDetailsDenied(const void *opaque G_GNUC_UNUSED)
242 {
243 int rv;
244 virErrorPtr err;
245 const char *details[] = {
246 "org.libvirt.test.person", "Joe",
247 NULL,
248 };
249
250 rv = virPolkitCheckAuth("org.libvirt.test.details",
251 THE_PID,
252 THE_TIME,
253 THE_UID,
254 details,
255 true);
256
257 if (rv == 0) {
258 fprintf(stderr, "Unexpected auth success\n");
259 return -1;
260 } else if (rv != -2) {
261 return -1;
262 }
263
264 err = virGetLastError();
265 if (!err || !strstr(err->message,
266 _("access denied by policy"))) {
267 fprintf(stderr, "Incorrect error response\n");
268 return -1;
269 }
270
271 return 0;
272 }
273
274
275 static int
mymain(void)276 mymain(void)
277 {
278 int ret = 0;
279
280 if (virTestRun("Polkit auth success ", testPolkitAuthSuccess, NULL) < 0)
281 ret = -1;
282 if (virTestRun("Polkit auth deny ", testPolkitAuthDenied, NULL) < 0)
283 ret = -1;
284 if (virTestRun("Polkit auth challenge ", testPolkitAuthChallenge, NULL) < 0)
285 ret = -1;
286 if (virTestRun("Polkit auth cancel ", testPolkitAuthCancelled, NULL) < 0)
287 ret = -1;
288 if (virTestRun("Polkit auth details success ", testPolkitAuthDetailsSuccess, NULL) < 0)
289 ret = -1;
290 if (virTestRun("Polkit auth details deny ", testPolkitAuthDetailsDenied, NULL) < 0)
291 ret = -1;
292
293 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
294 }
295
296 VIR_TEST_MAIN_PRELOAD(mymain, VIR_TEST_MOCK("virgdbus"))
297
298 #else /* ! __ELF__ */
299 int
300 main(void)
301 {
302 return EXIT_AM_SKIP;
303 }
304 #endif /* ! __ELF__ */
305