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