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
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;
49 } _DBus8ByteStruct;
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
63 _DBus8ByteStruct eight;
64 double dbl;
65 unsigned char byt;
66 char *str;
67 int fd;
68 } _DBusBasicValue;
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
_DBus8ByteStruct
Definition: systemdshared.h:45
_DBusBasicValue::i32
dbus_int32_t i32
as int32
Definition: systemdshared.h:56
_DBusBasicValue::byt
unsigned char byt
as byte
Definition: systemdshared.h:65
_DBusBasicValue::u32
dbus_uint32_t u32
as int32
Definition: systemdshared.h:57
_DBusBasicValue::fd
int fd
as Unix file descriptor
Definition: systemdshared.h:67
_DBusBasicValue::eight
_DBus8ByteStruct eight
as 8-byte struct
Definition: systemdshared.h:63
_DBusBasicValue::str
char * str
as char* (string, object path or signature)
Definition: systemdshared.h:66
_DBusBasicValue
Definition: systemdshared.h:51
_DBusBasicValue::i16
dbus_int16_t i16
as int16
Definition: systemdshared.h:54
debug_priv.h
oscap debug helpers private header
_DBusBasicValue::bool_val
dbus_bool_t bool_val
as boolean
Definition: systemdshared.h:58
_DBusBasicValue::u16
dbus_uint16_t u16
as int16
Definition: systemdshared.h:55
_DBusBasicValue::dbl
double dbl
as double
Definition: systemdshared.h:64