Open SCAP Library
systemdshared.h
1 
7 /*
8  * Copyright 2014 Red Hat Inc., Durham, North Carolina.
9  * All Rights Reserved.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  * Authors:
26  *
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 
33 #include <dbus/dbus.h>
34 #include "common/debug_priv.h"
35 
36 // Old versions of libdbus API don't have DBusBasicValue and DBus8ByteStruct
37 // as a public typedefs.
38 // These two typedefs were copied from libdbus 1.8 branch, see
39 // http://cgit.freedesktop.org/dbus/dbus/tree/dbus/dbus-types.h?h=dbus-1.8#n137
40 typedef struct
41 {
42  dbus_uint32_t first32;
43  dbus_uint32_t second32;
45 
46 typedef union
47 {
48  unsigned char bytes[8];
49  dbus_int16_t i16;
50  dbus_uint16_t u16;
51  dbus_int32_t i32;
52  dbus_uint32_t u32;
53  dbus_bool_t bool_val;
54 #ifdef DBUS_HAVE_INT64
55  dbus_int64_t i64;
56  dbus_uint64_t u64;
57 #endif
59  double dbl;
60  unsigned char byt;
61  char *str;
62  int fd;
64 
65 static char *get_path_by_unit(DBusConnection *conn, const char *unit)
66 {
67  DBusMessage *msg = NULL;
68  DBusPendingCall *pending = NULL;
69  _DBusBasicValue path;
70  char *ret = NULL;
71 
72  msg = dbus_message_new_method_call(
73  "org.freedesktop.systemd1",
74  "/org/freedesktop/systemd1",
75  "org.freedesktop.systemd1.Manager",
76  // LoadUnit is similar to GetUnit except it will load the unit file
77  // if it hasn't been loaded yet.
78  "LoadUnit"
79  );
80  if (msg == NULL) {
81  dI("Failed to create dbus_message via dbus_message_new_method_call!\n");
82  goto cleanup;
83  }
84 
85  DBusMessageIter args;
86 
87  dbus_message_iter_init_append(msg, &args);
88  if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &unit)) {
89  dI("Failed to append unit '%s' string parameter to dbus message!\n", unit);
90  goto cleanup;
91  }
92 
93  if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
94  dI("Failed to send message via dbus!\n");
95  goto cleanup;
96  }
97  if (pending == NULL) {
98  dI("Invalid dbus pending call!\n");
99  goto cleanup;
100  }
101 
102  dbus_connection_flush(conn);
103  dbus_message_unref(msg); msg = NULL;
104 
105  dbus_pending_call_block(pending);
106  msg = dbus_pending_call_steal_reply(pending);
107  if (msg == NULL) {
108  dI("Failed to steal dbus pending call reply.\n");
109  goto cleanup;
110  }
111  dbus_pending_call_unref(pending); pending = NULL;
112 
113  if (!dbus_message_iter_init(msg, &args)) {
114  dI("Failed to initialize iterator over received dbus message.\n");
115  goto cleanup;
116  }
117 
118  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) {
119  dI("Expected string argument in reply. Instead received: %s.\n", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&args)));
120  goto cleanup;
121  }
122 
123  dbus_message_iter_get_basic(&args, &path);
124  ret = oscap_strdup(path.str);
125  dbus_message_unref(msg); msg = NULL;
126 
127 cleanup:
128  if (pending != NULL)
129  dbus_pending_call_unref(pending);
130 
131  if (msg != NULL)
132  dbus_message_unref(msg);
133 
134  return ret;
135 }
136 
137 static int get_all_systemd_units(DBusConnection* conn, int(*callback)(const char *, void *), void *cbarg)
138 {
139  DBusMessage *msg = NULL;
140  DBusPendingCall *pending = NULL;
141  char ret = 1;
142 
143  msg = dbus_message_new_method_call(
144  "org.freedesktop.systemd1",
145  "/org/freedesktop/systemd1",
146  "org.freedesktop.systemd1.Manager",
147  "ListUnits"
148  );
149  if (msg == NULL) {
150  dI("Failed to create dbus_message via dbus_message_new_method_call!\n");
151  goto cleanup;
152  }
153 
154  DBusMessageIter args, unit_iter;
155 
156  // the args should be empty for this call
157  dbus_message_iter_init_append(msg, &args);
158 
159  if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
160  dI("Failed to send message via dbus!\n");
161  goto cleanup;
162  }
163  if (pending == NULL) {
164  dI("Invalid dbus pending call!\n");
165  goto cleanup;
166  }
167 
168  dbus_connection_flush(conn);
169  dbus_message_unref(msg); msg = NULL;
170 
171  dbus_pending_call_block(pending);
172  msg = dbus_pending_call_steal_reply(pending);
173  if (msg == NULL) {
174  dI("Failed to steal dbus pending call reply.\n");
175  goto cleanup;
176  }
177  dbus_pending_call_unref(pending); pending = NULL;
178 
179  if (!dbus_message_iter_init(msg, &args)) {
180  dI("Failed to initialize iterator over received dbus message.\n");
181  goto cleanup;
182  }
183 
184  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY) {
185  dI("Expected array of structs in reply. Instead received: %s.\n", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&args)));
186  goto cleanup;
187  }
188 
189  dbus_message_iter_recurse(&args, &unit_iter);
190  do {
191  if (dbus_message_iter_get_arg_type(&unit_iter) != DBUS_TYPE_STRUCT) {
192  dI("Expected unit struct as elements in returned array. Instead received: %s.\n", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&unit_iter)));
193  goto cleanup;
194  }
195 
196  DBusMessageIter unit_name;
197  dbus_message_iter_recurse(&unit_iter, &unit_name);
198 
199  if (dbus_message_iter_get_arg_type(&unit_name) != DBUS_TYPE_STRING) {
200  dI("Expected string as the first element in the unit struct. Instead received: %s.\n", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&unit_name)));
201  goto cleanup;
202  }
203 
204  _DBusBasicValue value;
205  dbus_message_iter_get_basic(&unit_name, &value);
206  char *unit_name_s = oscap_strdup(value.str);
207  int cbret = callback(unit_name_s, cbarg);
208  oscap_free(unit_name_s);
209  if (cbret != 0) {
210  goto cleanup;
211  }
212  }
213  while (dbus_message_iter_next(&unit_iter));
214 
215  dbus_message_unref(msg); msg = NULL;
216 
217  ret = 0;
218 
219 cleanup:
220  if (pending != NULL)
221  dbus_pending_call_unref(pending);
222 
223  if (msg != NULL)
224  dbus_message_unref(msg);
225 
226  return ret;
227 }
228 
229 static char *dbus_value_to_string(DBusMessageIter *iter)
230 {
231  const int arg_type = dbus_message_iter_get_arg_type(iter);
232  if (dbus_type_is_basic(arg_type)) {
233  _DBusBasicValue value;
234  dbus_message_iter_get_basic(iter, &value);
235 
236  switch (arg_type)
237  {
238  case DBUS_TYPE_BYTE:
239  return oscap_sprintf("%c", value.byt);
240 
241  case DBUS_TYPE_BOOLEAN:
242  return oscap_strdup(value.bool_val ? "true" : "false");
243 
244  case DBUS_TYPE_INT16:
245  return oscap_sprintf("%i", value.i16);
246 
247  case DBUS_TYPE_UINT16:
248  return oscap_sprintf("%u", value.u16);
249 
250  case DBUS_TYPE_INT32:
251  return oscap_sprintf("%i", value.i32);
252 
253  case DBUS_TYPE_UINT32:
254  return oscap_sprintf("%u", value.u32);
255 
256 #ifdef DBUS_HAVE_INT64
257  case DBUS_TYPE_INT64:
258  return oscap_sprintf("%lli", value.i32);
259 
260  case DBUS_TYPE_UINT64:
261  return oscap_sprintf("%llu", value.u32);
262 #endif
263 
264  case DBUS_TYPE_DOUBLE:
265  return oscap_sprintf("%g", value.dbl);
266 
267  case DBUS_TYPE_STRING:
268  case DBUS_TYPE_OBJECT_PATH:
269  case DBUS_TYPE_SIGNATURE:
270  return oscap_strdup(value.str);
271 
272  // non-basic types
273  //case DBUS_TYPE_ARRAY:
274  //case DBUS_TYPE_STRUCT:
275  //case DBUS_TYPE_DICT_ENTRY:
276  //case DBUS_TYPE_VARIANT:
277 
278  //case DBUS_TYPE_UNIX_FD:
279  // return oscap_sprintf("%i", value.fd);
280 
281  default:
282  dI("Encountered unknown dbus basic type!\n");
283  return oscap_strdup("error, unknown basic type!");
284  }
285  }
286  else if (arg_type == DBUS_TYPE_ARRAY) {
287  DBusMessageIter array;
288  dbus_message_iter_recurse(iter, &array);
289 
290  char *ret = NULL;
291  do {
292  char *element = dbus_value_to_string(&array);
293 
294  if (element == NULL)
295  continue;
296 
297  char *old_ret = ret;
298  if (old_ret == NULL)
299  ret = oscap_sprintf("%s", element);
300  else
301  ret = oscap_sprintf("%s, %s", old_ret, element);
302 
303  oscap_free(old_ret);
304  oscap_free(element);
305  }
306  while (dbus_message_iter_next(&array));
307 
308  return ret;
309  }/*
310  else if (arg_type == DBUS_TYPE_VARIANT) {
311  DBusMessageIter inner;
312  dbus_message_iter_recurse(iter, &inner);
313  return dbus_value_to_string(&inner);
314  }*/
315 
316  return NULL;
317 }
318 
319 static DBusConnection *connect_dbus()
320 {
321  DBusConnection *conn = NULL;
322 
323  DBusError err;
324  dbus_error_init(&err);
325 
326  conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
327  if (dbus_error_is_set(&err)) {
328  dI("Failed to get DBUS_BUS_SYSTEM connection - %s\n", err.message);
329  goto cleanup;
330  }
331  if (conn == NULL) {
332  dI("DBusConnection == NULL!\n");
333  goto cleanup;
334  }
335 
336  dbus_bus_register(conn, &err);
337  if (dbus_error_is_set(&err)) {
338  dI("Failed to register on dbus - %s\n", err.message);
339  goto cleanup;
340  }
341 
342 cleanup:
343  dbus_error_free(&err);
344 
345  return conn;
346 }
347 
348 static void disconnect_dbus(DBusConnection *conn)
349 {
350  // NOOP
351 
352  // Connections retrieved via dbus_bus_get shall not be destroyed,
353  // these connections are shared.
354 }
Definition: systemdshared.h:40
dbus_int32_t i32
as int32
Definition: systemdshared.h:51
unsigned char byt
as byte
Definition: systemdshared.h:60
dbus_uint32_t u32
as int32
Definition: systemdshared.h:52
int fd
as Unix file descriptor
Definition: systemdshared.h:62
_DBus8ByteStruct eight
as 8-byte struct
Definition: systemdshared.h:58
char * str
as char* (string, object path or signature)
Definition: systemdshared.h:61
Definition: systemdshared.h:46
dbus_int16_t i16
as int16
Definition: systemdshared.h:49
oscap debug helpers private header
dbus_bool_t bool_val
as boolean
Definition: systemdshared.h:53
#define oscap_free(p)
free wrapper
Definition: alloc.h:152
dbus_uint16_t u16
as int16
Definition: systemdshared.h:50
double dbl
as double
Definition: systemdshared.h:59