chiark / gitweb /
libsystemd-bus: sd_bus_request_name: use kdbus_translate_request_name_flags()
[elogind.git] / src / libsystemd-bus / bus-dump.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 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 <sys/capability.h>
23
24 #include "util.h"
25 #include "capability.h"
26 #include "strv.h"
27 #include "audit.h"
28
29 #include "bus-message.h"
30 #include "bus-internal.h"
31 #include "bus-type.h"
32 #include "bus-dump.h"
33
34 static char *indent(unsigned level) {
35         char *p;
36
37         p = new(char, 2 + level + 1);
38         if (!p)
39                 return NULL;
40
41         p[0] = p[1] = ' ';
42         memset(p + 2, '\t', level);
43         p[2 + level] = 0;
44
45         return p;
46 }
47
48 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
49         unsigned level = 1;
50         int r;
51
52         assert(m);
53
54         if (!f)
55                 f = stdout;
56
57         if (with_header) {
58                 fprintf(f,
59                         "%s%s%sType=%s%s%s  Endian=%c  Flags=%u  Version=%u  Serial=%u ",
60                         m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
61                         m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
62                         m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
63                         ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
64                         m->header->endian,
65                         m->header->flags,
66                         m->header->version,
67                         BUS_MESSAGE_SERIAL(m));
68
69                 if (m->reply_serial != 0)
70                         fprintf(f, "  ReplySerial=%u", m->reply_serial);
71
72                 fputs("\n", f);
73
74                 if (m->sender)
75                         fprintf(f, "  Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
76                 if (m->destination)
77                         fprintf(f, "  Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
78                 if (m->path)
79                         fprintf(f, "  Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
80                 if (m->interface)
81                         fprintf(f, "  Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
82                 if (m->member)
83                         fprintf(f, "  Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
84
85                 if (m->sender || m->destination || m->path || m->interface || m->member)
86                         fputs("\n", f);
87
88                 if (sd_bus_error_is_set(&m->error))
89                         fprintf(f,
90                                 "  ErrorName=%s%s%s"
91                                 "  ErrorMessage=%s\"%s\"%s\n",
92                                 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
93                                 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
94
95                 if (m->monotonic != 0)
96                         fprintf(f, "  Monotonic=%llu", (unsigned long long) m->monotonic);
97                 if (m->realtime != 0)
98                         fprintf(f, "  Realtime=%llu", (unsigned long long) m->realtime);
99
100                 if (m->monotonic != 0 || m->realtime != 0)
101                         fputs("\n", f);
102
103                 bus_creds_dump(&m->creds, f);
104         }
105
106         r = sd_bus_message_rewind(m, true);
107         if (r < 0) {
108                 log_error("Failed to rewind: %s", strerror(-r));
109                 return r;
110         }
111
112         fprintf(f, "  MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
113
114         for(;;) {
115                 _cleanup_free_ char *prefix = NULL;
116                 const char *contents = NULL;
117                 char type;
118                 union {
119                         uint8_t u8;
120                         uint16_t u16;
121                         int16_t s16;
122                         uint32_t u32;
123                         int32_t s32;
124                         uint64_t u64;
125                         int64_t s64;
126                         double d64;
127                         const char *string;
128                         int i;
129                 } basic;
130
131                 r = sd_bus_message_peek_type(m, &type, &contents);
132                 if (r < 0) {
133                         log_error("Failed to peek type: %s", strerror(-r));
134                         return r;
135                 }
136
137                 if (r == 0) {
138                         if (level <= 1)
139                                 break;
140
141                         r = sd_bus_message_exit_container(m);
142                         if (r < 0) {
143                                 log_error("Failed to exit container: %s", strerror(-r));
144                                 return r;
145                         }
146
147                         level--;
148
149                         prefix = indent(level);
150                         if (!prefix)
151                                 return log_oom();
152
153                         fprintf(f, "%s};\n", prefix);
154                         continue;
155                 }
156
157                 prefix = indent(level);
158                 if (!prefix)
159                         return log_oom();
160
161                 if (bus_type_is_container(type) > 0) {
162                         r = sd_bus_message_enter_container(m, type, contents);
163                         if (r < 0) {
164                                 log_error("Failed to enter container: %s", strerror(-r));
165                                 return r;
166                         }
167
168                         if (type == SD_BUS_TYPE_ARRAY)
169                                 fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
170                         else if (type == SD_BUS_TYPE_VARIANT)
171                                 fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
172                         else if (type == SD_BUS_TYPE_STRUCT)
173                                 fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
174                         else if (type == SD_BUS_TYPE_DICT_ENTRY)
175                                 fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
176
177                         level ++;
178
179                         continue;
180                 }
181
182                 r = sd_bus_message_read_basic(m, type, &basic);
183                 if (r < 0) {
184                         log_error("Failed to get basic: %s", strerror(-r));
185                         return r;
186                 }
187
188                 assert(r > 0);
189
190                 switch (type) {
191
192                 case SD_BUS_TYPE_BYTE:
193                         fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
194                         break;
195
196                 case SD_BUS_TYPE_BOOLEAN:
197                         fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), yes_no(basic.i), ansi_highlight_off());
198                         break;
199
200                 case SD_BUS_TYPE_INT16:
201                         fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
202                         break;
203
204                 case SD_BUS_TYPE_UINT16:
205                         fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
206                         break;
207
208                 case SD_BUS_TYPE_INT32:
209                         fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
210                         break;
211
212                 case SD_BUS_TYPE_UINT32:
213                         fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
214                         break;
215
216                 case SD_BUS_TYPE_INT64:
217                         fprintf(f, "%sINT64 %s%lli%s;\n", prefix, ansi_highlight(), (long long) basic.s64, ansi_highlight_off());
218                         break;
219
220                 case SD_BUS_TYPE_UINT64:
221                         fprintf(f, "%sUINT64 %s%llu%s;\n", prefix, ansi_highlight(), (unsigned long long) basic.u64, ansi_highlight_off());
222                         break;
223
224                 case SD_BUS_TYPE_DOUBLE:
225                         fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
226                         break;
227
228                 case SD_BUS_TYPE_STRING:
229                         fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
230                         break;
231
232                 case SD_BUS_TYPE_OBJECT_PATH:
233                         fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
234                         break;
235
236                 case SD_BUS_TYPE_SIGNATURE:
237                         fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
238                         break;
239
240                 case SD_BUS_TYPE_UNIX_FD:
241                         fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
242                         break;
243
244                 default:
245                         assert_not_reached("Unknown basic type.");
246                 }
247         }
248
249         fprintf(f, "  };\n\n");
250         return 0;
251 }
252
253 static void dump_capabilities(
254                 sd_bus_creds *c,
255                 FILE *f,
256                 const char *name,
257                 int (*has)(sd_bus_creds *c, int capability)) {
258
259         unsigned long i, last_cap;
260         unsigned n = 0;
261         int r;
262
263         assert(c);
264         assert(f);
265         assert(name);
266         assert(has);
267
268         i = 0;
269         r = has(c, i);
270         if (r < 0)
271                 return;
272
273         fprintf(f, "  %s=", name);
274         last_cap = cap_last_cap();
275
276         for (;;) {
277                 if (r > 0) {
278                         if (n > 0)
279                                 fputc(' ', f);
280                         if (n % 4 == 3)
281                                 fputs("\n          ", f);
282
283                         fputs(cap_to_name(i), f);
284                         n++;
285                 }
286
287                 i++;
288
289                 if (i > last_cap)
290                         break;
291
292                 r = has(c, i);
293         }
294
295         fputs("\n", f);
296 }
297
298 int bus_creds_dump(sd_bus_creds *c, FILE *f) {
299         bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
300         const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
301         uid_t owner, audit_loginuid;
302         uint32_t audit_sessionid;
303         char **cmdline = NULL;
304         int r;
305
306         assert(c);
307
308         if (!f)
309                 f = stdout;
310
311         if (c->mask & SD_BUS_CREDS_PID)
312                 fprintf(f, "  PID=%lu", (unsigned long) c->pid);
313         if (c->mask & SD_BUS_CREDS_PID_STARTTIME)
314                 fprintf(f, "  PIDStartTime=%llu", (unsigned long long) c->pid_starttime);
315         if (c->mask & SD_BUS_CREDS_TID)
316                 fprintf(f, "  TID=%lu", (unsigned long) c->tid);
317         if (c->mask & SD_BUS_CREDS_UID)
318                 fprintf(f, "  UID=%lu", (unsigned long) c->uid);
319         r = sd_bus_creds_get_owner_uid(c, &owner);
320         if (r >= 0)
321                 fprintf(f, "  OwnerUID=%lu", (unsigned long) owner);
322         if (c->mask & SD_BUS_CREDS_GID)
323                 fprintf(f, "  GID=%lu", (unsigned long) c->gid);
324
325         if ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID)) || r >= 0)
326                 fputs("\n", f);
327
328         if (c->mask & SD_BUS_CREDS_EXE)
329                 fprintf(f, "  Exe=%s", c->exe);
330         if (c->mask & SD_BUS_CREDS_COMM)
331                 fprintf(f, "  Comm=%s", c->comm);
332         if (c->mask & SD_BUS_CREDS_TID_COMM)
333                 fprintf(f, "  TIDComm=%s", c->tid_comm);
334         if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
335                 fprintf(f, "  Label=%s", c->label);
336
337         if (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_SELINUX_CONTEXT))
338                 fputs("\n", f);
339
340         if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
341                 char **i;
342
343                 fputs("  CommandLine=", f);
344                 STRV_FOREACH(i, cmdline) {
345                         if (i != cmdline)
346                                 fputc(' ', f);
347
348                         fputs(*i, f);
349                 }
350
351                 fputs("\n", f);
352         }
353
354         if (c->mask & SD_BUS_CREDS_CGROUP)
355                 fprintf(f, "  CGroup=%s", c->cgroup);
356         sd_bus_creds_get_unit(c, &u);
357         if (u)
358                 fprintf(f, "  Unit=%s", u);
359         sd_bus_creds_get_user_unit(c, &uu);
360         if (uu)
361                 fprintf(f, "  UserUnit=%s", uu);
362         sd_bus_creds_get_slice(c, &sl);
363         if (sl)
364                 fprintf(f, "  Slice=%s", sl);
365         sd_bus_creds_get_session(c, &s);
366         if (s)
367                 fprintf(f, "  Session=%s", s);
368
369         if ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s)
370                 fputs("\n", f);
371
372         if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
373                 audit_loginuid_is_set = true;
374                 fprintf(f, "  AuditLoginUID=%lu", (unsigned long) audit_loginuid);
375         }
376         if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
377                 audit_sessionid_is_set = true;
378                 fprintf(f, "  AuditSessionID=%lu", (unsigned long) audit_sessionid);
379         }
380
381         if (audit_loginuid_is_set || audit_sessionid_is_set)
382                 fputs("\n", f);
383
384         dump_capabilities(c, f, "EffectiveCapabilities", sd_bus_creds_has_effective_cap);
385         dump_capabilities(c, f, "PermittedCapabilities", sd_bus_creds_has_permitted_cap);
386         dump_capabilities(c, f, "InheritableCapabilities", sd_bus_creds_has_inheritable_cap);
387         dump_capabilities(c, f, "BoundingCapabilities", sd_bus_creds_has_bounding_cap);
388
389         return 0;
390 }