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