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