]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/machine/image-dbus.c
bus-util: support details in CheckAuthorization calls
[thirdparty/systemd.git] / src / machine / image-dbus.c
CommitLineData
ebeccf9e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
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
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
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include "bus-label.h"
ebeccf9e 23#include "strv.h"
1ddb263d 24#include "bus-util.h"
003dffde
LP
25#include "machine-image.h"
26#include "image-dbus.h"
ebeccf9e 27
1ddb263d 28static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType);
ebeccf9e 29
1ddb263d 30int bus_image_method_remove(
08682124
LP
31 sd_bus_message *message,
32 void *userdata,
33 sd_bus_error *error) {
34
1ddb263d 35 Image *image = userdata;
70244d1d 36 Manager *m = image->userdata;
08682124
LP
37 int r;
38
08682124 39 assert(message);
1ddb263d 40 assert(image);
08682124 41
70244d1d
LP
42 r = bus_verify_polkit_async(
43 message,
44 CAP_SYS_ADMIN,
45 "org.freedesktop.machine1.manage-images",
403ed0e5 46 NULL,
70244d1d 47 false,
c529695e 48 UID_INVALID,
70244d1d
LP
49 &m->polkit_registry,
50 error);
51 if (r < 0)
52 return r;
53 if (r == 0)
54 return 1; /* Will call us back */
55
08682124
LP
56 r = image_remove(image);
57 if (r < 0)
58 return r;
59
60 return sd_bus_reply_method_return(message, NULL);
61}
62
1ddb263d 63int bus_image_method_rename(
ebd93cb6
LP
64 sd_bus_message *message,
65 void *userdata,
66 sd_bus_error *error) {
67
1ddb263d 68 Image *image = userdata;
70244d1d 69 Manager *m = image->userdata;
ebd93cb6
LP
70 const char *new_name;
71 int r;
72
ebd93cb6 73 assert(message);
1ddb263d 74 assert(image);
ebd93cb6
LP
75
76 r = sd_bus_message_read(message, "s", &new_name);
77 if (r < 0)
78 return r;
79
80 if (!image_name_is_valid(new_name))
81 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
82
70244d1d
LP
83 r = bus_verify_polkit_async(
84 message,
85 CAP_SYS_ADMIN,
86 "org.freedesktop.machine1.manage-images",
403ed0e5 87 NULL,
70244d1d 88 false,
c529695e 89 UID_INVALID,
70244d1d
LP
90 &m->polkit_registry,
91 error);
92 if (r < 0)
93 return r;
94 if (r == 0)
95 return 1; /* Will call us back */
96
ebd93cb6
LP
97 r = image_rename(image, new_name);
98 if (r < 0)
99 return r;
100
101 return sd_bus_reply_method_return(message, NULL);
102}
103
1ddb263d 104int bus_image_method_clone(
ebd93cb6
LP
105 sd_bus_message *message,
106 void *userdata,
107 sd_bus_error *error) {
108
1ddb263d 109 Image *image = userdata;
70244d1d 110 Manager *m = image->userdata;
ebd93cb6
LP
111 const char *new_name;
112 int r, read_only;
113
ebd93cb6 114 assert(message);
1ddb263d 115 assert(image);
ebd93cb6
LP
116
117 r = sd_bus_message_read(message, "sb", &new_name, &read_only);
118 if (r < 0)
119 return r;
120
121 if (!image_name_is_valid(new_name))
122 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
123
70244d1d
LP
124 r = bus_verify_polkit_async(
125 message,
126 CAP_SYS_ADMIN,
127 "org.freedesktop.machine1.manage-images",
403ed0e5 128 NULL,
70244d1d 129 false,
c529695e 130 UID_INVALID,
70244d1d
LP
131 &m->polkit_registry,
132 error);
133 if (r < 0)
134 return r;
135 if (r == 0)
136 return 1; /* Will call us back */
137
ebd93cb6
LP
138 r = image_clone(image, new_name, read_only);
139 if (r < 0)
140 return r;
141
142 return sd_bus_reply_method_return(message, NULL);
143}
144
1ddb263d 145int bus_image_method_mark_read_only(
ebd93cb6
LP
146 sd_bus_message *message,
147 void *userdata,
148 sd_bus_error *error) {
149
1ddb263d 150 Image *image = userdata;
70244d1d 151 Manager *m = image->userdata;
ebd93cb6
LP
152 int r, read_only;
153
ebd93cb6
LP
154 assert(message);
155
ebd93cb6
LP
156 r = sd_bus_message_read(message, "b", &read_only);
157 if (r < 0)
158 return r;
159
70244d1d
LP
160 r = bus_verify_polkit_async(
161 message,
162 CAP_SYS_ADMIN,
163 "org.freedesktop.machine1.manage-images",
403ed0e5 164 NULL,
70244d1d 165 false,
c529695e 166 UID_INVALID,
70244d1d
LP
167 &m->polkit_registry,
168 error);
169 if (r < 0)
170 return r;
171 if (r == 0)
172 return 1; /* Will call us back */
173
ebd93cb6
LP
174 r = image_read_only(image, read_only);
175 if (r < 0)
176 return r;
177
178 return sd_bus_reply_method_return(message, NULL);
179}
180
d6ce17c7 181int bus_image_method_set_limit(
d6ce17c7
LP
182 sd_bus_message *message,
183 void *userdata,
184 sd_bus_error *error) {
185
186 Image *image = userdata;
187 Manager *m = image->userdata;
188 uint64_t limit;
189 int r;
190
d6ce17c7
LP
191 assert(message);
192
193 r = sd_bus_message_read(message, "t", &limit);
194 if (r < 0)
195 return r;
196
197 r = bus_verify_polkit_async(
198 message,
199 CAP_SYS_ADMIN,
200 "org.freedesktop.machine1.manage-images",
403ed0e5 201 NULL,
d6ce17c7
LP
202 false,
203 UID_INVALID,
204 &m->polkit_registry,
205 error);
206 if (r < 0)
207 return r;
208 if (r == 0)
209 return 1; /* Will call us back */
210
211 r = image_set_limit(image, limit);
212 if (r < 0)
213 return r;
214
215 return sd_bus_reply_method_return(message, NULL);
216}
217
ebeccf9e
LP
218const sd_bus_vtable image_vtable[] = {
219 SD_BUS_VTABLE_START(0),
1ddb263d
LP
220 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0),
221 SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0),
222 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0),
223 SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0),
224 SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0),
225 SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0),
c19de711 226 SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
1ddb263d 227 SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
c19de711 228 SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
1ddb263d 229 SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
70244d1d
LP
230 SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
231 SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED),
232 SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED),
233 SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
d6ce17c7 234 SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED),
ebeccf9e
LP
235 SD_BUS_VTABLE_END
236};
237
1ddb263d
LP
238static int image_flush_cache(sd_event_source *s, void *userdata) {
239 Manager *m = userdata;
240 Image *i;
241
242 assert(s);
243 assert(m);
244
245 while ((i = hashmap_steal_first(m->image_cache)))
246 image_unref(i);
247
248 return 0;
249}
250
ebeccf9e 251int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
1ddb263d
LP
252 _cleanup_free_ char *e = NULL;
253 Manager *m = userdata;
254 Image *image = NULL;
255 const char *p;
ebeccf9e
LP
256 int r;
257
258 assert(bus);
259 assert(path);
260 assert(interface);
261 assert(found);
262
1ddb263d
LP
263 p = startswith(path, "/org/freedesktop/machine1/image/");
264 if (!p)
265 return 0;
266
267 e = bus_label_unescape(p);
268 if (!e)
269 return -ENOMEM;
270
271 image = hashmap_get(m->image_cache, e);
272 if (image) {
273 *found = image;
274 return 1;
275 }
276
277 r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops);
278 if (r < 0)
279 return r;
280
281 if (!m->image_cache_defer_event) {
282 r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m);
283 if (r < 0)
284 return r;
285
286 r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
287 if (r < 0)
288 return r;
289 }
290
291 r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
292 if (r < 0)
293 return r;
294
295 r = image_find(e, &image);
ebeccf9e
LP
296 if (r <= 0)
297 return r;
298
70244d1d
LP
299 image->userdata = m;
300
1ddb263d
LP
301 r = hashmap_put(m->image_cache, image->name, image);
302 if (r < 0) {
303 image_unref(image);
304 return r;
305 }
306
307 *found = image;
ebeccf9e
LP
308 return 1;
309}
310
311char *image_bus_path(const char *name) {
312 _cleanup_free_ char *e = NULL;
313
314 assert(name);
315
316 e = bus_label_escape(name);
317 if (!e)
318 return NULL;
319
320 return strappend("/org/freedesktop/machine1/image/", e);
321}
322
323int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
324 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
325 _cleanup_strv_free_ char **l = NULL;
326 Image *image;
327 Iterator i;
328 int r;
329
330 assert(bus);
331 assert(path);
332 assert(nodes);
333
334 images = hashmap_new(&string_hash_ops);
335 if (!images)
336 return -ENOMEM;
337
338 r = image_discover(images);
339 if (r < 0)
340 return r;
341
342 HASHMAP_FOREACH(image, images, i) {
343 char *p;
344
345 p = image_bus_path(image->name);
346 if (!p)
347 return -ENOMEM;
348
349 r = strv_consume(&l, p);
350 if (r < 0)
351 return r;
352 }
353
354 *nodes = l;
355 l = NULL;
356
357 return 1;
358}