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., 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 <libgen.h>
39 #include <limits.h>
40 #include <stdio.h>
41 #include "common/debug_priv.h"
42 #include "oscap_helpers.h"
43 #include "oval_dbus.h"
44 
45 
46 static char *get_path_by_unit(DBusConnection *conn, const char *unit)
47 {
48  DBusMessage *msg = NULL;
49  DBusPendingCall *pending = NULL;
50  _DBusBasicValue path;
51  char *ret = NULL;
52 
53  msg = dbus_message_new_method_call(
54  "org.freedesktop.systemd1",
55  "/org/freedesktop/systemd1",
56  "org.freedesktop.systemd1.Manager",
57  // LoadUnit is similar to GetUnit except it will load the unit file
58  // if it hasn't been loaded yet.
59  "LoadUnit"
60  );
61  dD("LoadUnit: %s", unit);
62 
63  if (msg == NULL) {
64  dD("Failed to create dbus_message via dbus_message_new_method_call!");
65  goto cleanup;
66  }
67 
68  DBusMessageIter args;
69 
70  dbus_message_iter_init_append(msg, &args);
71  if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &unit)) {
72  dD("Failed to append unit '%s' string parameter to dbus message!", unit);
73  goto cleanup;
74  }
75 
76  if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
77  dD("Failed to send message via dbus!");
78  goto cleanup;
79  }
80  if (pending == NULL) {
81  dD("Invalid dbus pending call!");
82  goto cleanup;
83  }
84 
85  dbus_connection_flush(conn);
86  dbus_message_unref(msg); msg = NULL;
87 
88  dbus_pending_call_block(pending);
89  msg = dbus_pending_call_steal_reply(pending);
90  if (msg == NULL) {
91  dD("Failed to steal dbus pending call reply.");
92  goto cleanup;
93  }
94  dbus_pending_call_unref(pending); pending = NULL;
95 
96  if (!dbus_message_iter_init(msg, &args)) {
97  dD("Failed to initialize iterator over received dbus message.");
98  goto cleanup;
99  }
100 
101  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) {
102  dD("Expected object path argument in reply. Instead received: %s.", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&args)));
103  goto cleanup;
104  }
105 
106  dbus_message_iter_get_basic(&args, &path);
107  ret = oscap_strdup(path.str);
108  dbus_message_unref(msg); msg = NULL;
109 
110 cleanup:
111  if (pending != NULL)
112  dbus_pending_call_unref(pending);
113 
114  if (msg != NULL)
115  dbus_message_unref(msg);
116 
117  return ret;
118 }
119 
120 static int get_all_systemd_units(DBusConnection* conn, int(*callback)(const char *, void *), void *cbarg)
121 {
122  DBusMessage *msg = NULL;
123  DBusPendingCall *pending = NULL;
124  char ret = 1;
125 
126  msg = dbus_message_new_method_call(
127  "org.freedesktop.systemd1",
128  "/org/freedesktop/systemd1",
129  "org.freedesktop.systemd1.Manager",
130  "ListUnitFiles"
131  );
132  if (msg == NULL) {
133  dD("Failed to create dbus_message via dbus_message_new_method_call!");
134  goto cleanup;
135  }
136 
137  DBusMessageIter args, unit_iter;
138 
139  // the args should be empty for this call
140  dbus_message_iter_init_append(msg, &args);
141 
142  if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
143  dD("Failed to send message via dbus!");
144  goto cleanup;
145  }
146  if (pending == NULL) {
147  dD("Invalid dbus pending call!");
148  goto cleanup;
149  }
150 
151  dbus_connection_flush(conn);
152  dbus_message_unref(msg); msg = NULL;
153 
154  dbus_pending_call_block(pending);
155  msg = dbus_pending_call_steal_reply(pending);
156  if (msg == NULL) {
157  dD("Failed to steal dbus pending call reply.");
158  goto cleanup;
159  }
160  dbus_pending_call_unref(pending); pending = NULL;
161 
162  if (!dbus_message_iter_init(msg, &args)) {
163  dD("Failed to initialize iterator over received dbus message.");
164  goto cleanup;
165  }
166 
167  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY) {
168  dD("Expected array of structs in reply. Instead received: %s.", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&args)));
169  goto cleanup;
170  }
171 
172  dbus_message_iter_recurse(&args, &unit_iter);
173  do {
174  if (dbus_message_iter_get_arg_type(&unit_iter) != DBUS_TYPE_STRUCT) {
175  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)));
176  goto cleanup;
177  }
178 
179  DBusMessageIter unit_full_path_and_name;
180  dbus_message_iter_recurse(&unit_iter, &unit_full_path_and_name);
181 
182  if (dbus_message_iter_get_arg_type(&unit_full_path_and_name) != DBUS_TYPE_STRING) {
183  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)));
184  goto cleanup;
185  }
186 
187  _DBusBasicValue value;
188  dbus_message_iter_get_basic(&unit_full_path_and_name, &value);
189  char *unit_name_s = oscap_strdup(basename(value.str));
190  oscap_strrm(unit_name_s, "@");
191  int cbret = callback(unit_name_s, cbarg);
192  free(unit_name_s);
193  if (cbret != 0) {
194  goto cleanup;
195  }
196  }
197  while (dbus_message_iter_next(&unit_iter));
198 
199  dbus_message_unref(msg); msg = NULL;
200 
201  ret = 0;
202 
203 cleanup:
204  if (pending != NULL)
205  dbus_pending_call_unref(pending);
206 
207  if (msg != NULL)
208  dbus_message_unref(msg);
209 
210  return ret;
211 }
212 
213 #endif
oscap debug helpers private header
Definition: oval_dbus.h:40
char * str
as char* (string, object path or signature)
Definition: oval_dbus.h:54