00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #pragma once
00030
00031 #ifndef OPENSCAP_OVAL_PROBES_SYSTEMDSHARED_H_
00032 #define OPENSCAP_OVAL_PROBES_SYSTEMDSHARED_H_
00033
00034 #ifdef HAVE_CONFIG_H
00035 #include <config.h>
00036 #endif
00037
00038 #include <dbus/dbus.h>
00039 #include "common/debug_priv.h"
00040
00041
00042
00043
00044
00045 typedef struct
00046 {
00047 dbus_uint32_t first32;
00048 dbus_uint32_t second32;
00049 } _DBus8ByteStruct;
00050
00051 typedef union
00052 {
00053 unsigned char bytes[8];
00054 dbus_int16_t i16;
00055 dbus_uint16_t u16;
00056 dbus_int32_t i32;
00057 dbus_uint32_t u32;
00058 dbus_bool_t bool_val;
00059 #ifdef DBUS_HAVE_INT64
00060 dbus_int64_t i64;
00061 dbus_uint64_t u64;
00062 #endif
00063 _DBus8ByteStruct eight;
00064 double dbl;
00065 unsigned char byt;
00066 char *str;
00067 int fd;
00068 } _DBusBasicValue;
00069
00070 static char *get_path_by_unit(DBusConnection *conn, const char *unit)
00071 {
00072 DBusMessage *msg = NULL;
00073 DBusPendingCall *pending = NULL;
00074 _DBusBasicValue path;
00075 char *ret = NULL;
00076
00077 msg = dbus_message_new_method_call(
00078 "org.freedesktop.systemd1",
00079 "/org/freedesktop/systemd1",
00080 "org.freedesktop.systemd1.Manager",
00081
00082
00083 "LoadUnit"
00084 );
00085 if (msg == NULL) {
00086 dI("Failed to create dbus_message via dbus_message_new_method_call!");
00087 goto cleanup;
00088 }
00089
00090 DBusMessageIter args;
00091
00092 dbus_message_iter_init_append(msg, &args);
00093 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &unit)) {
00094 dI("Failed to append unit '%s' string parameter to dbus message!", unit);
00095 goto cleanup;
00096 }
00097
00098 if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
00099 dI("Failed to send message via dbus!");
00100 goto cleanup;
00101 }
00102 if (pending == NULL) {
00103 dI("Invalid dbus pending call!");
00104 goto cleanup;
00105 }
00106
00107 dbus_connection_flush(conn);
00108 dbus_message_unref(msg); msg = NULL;
00109
00110 dbus_pending_call_block(pending);
00111 msg = dbus_pending_call_steal_reply(pending);
00112 if (msg == NULL) {
00113 dI("Failed to steal dbus pending call reply.");
00114 goto cleanup;
00115 }
00116 dbus_pending_call_unref(pending); pending = NULL;
00117
00118 if (!dbus_message_iter_init(msg, &args)) {
00119 dI("Failed to initialize iterator over received dbus message.");
00120 goto cleanup;
00121 }
00122
00123 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH) {
00124 dI("Expected string argument in reply. Instead received: %s.", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&args)));
00125 goto cleanup;
00126 }
00127
00128 dbus_message_iter_get_basic(&args, &path);
00129 ret = oscap_strdup(path.str);
00130 dbus_message_unref(msg); msg = NULL;
00131
00132 cleanup:
00133 if (pending != NULL)
00134 dbus_pending_call_unref(pending);
00135
00136 if (msg != NULL)
00137 dbus_message_unref(msg);
00138
00139 return ret;
00140 }
00141
00142 static int get_all_systemd_units(DBusConnection* conn, int(*callback)(const char *, void *), void *cbarg)
00143 {
00144 DBusMessage *msg = NULL;
00145 DBusPendingCall *pending = NULL;
00146 char ret = 1;
00147
00148 msg = dbus_message_new_method_call(
00149 "org.freedesktop.systemd1",
00150 "/org/freedesktop/systemd1",
00151 "org.freedesktop.systemd1.Manager",
00152 "ListUnits"
00153 );
00154 if (msg == NULL) {
00155 dI("Failed to create dbus_message via dbus_message_new_method_call!");
00156 goto cleanup;
00157 }
00158
00159 DBusMessageIter args, unit_iter;
00160
00161
00162 dbus_message_iter_init_append(msg, &args);
00163
00164 if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
00165 dI("Failed to send message via dbus!");
00166 goto cleanup;
00167 }
00168 if (pending == NULL) {
00169 dI("Invalid dbus pending call!");
00170 goto cleanup;
00171 }
00172
00173 dbus_connection_flush(conn);
00174 dbus_message_unref(msg); msg = NULL;
00175
00176 dbus_pending_call_block(pending);
00177 msg = dbus_pending_call_steal_reply(pending);
00178 if (msg == NULL) {
00179 dI("Failed to steal dbus pending call reply.");
00180 goto cleanup;
00181 }
00182 dbus_pending_call_unref(pending); pending = NULL;
00183
00184 if (!dbus_message_iter_init(msg, &args)) {
00185 dI("Failed to initialize iterator over received dbus message.");
00186 goto cleanup;
00187 }
00188
00189 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY) {
00190 dI("Expected array of structs in reply. Instead received: %s.", dbus_message_type_to_string(dbus_message_iter_get_arg_type(&args)));
00191 goto cleanup;
00192 }
00193
00194 dbus_message_iter_recurse(&args, &unit_iter);
00195 do {
00196 if (dbus_message_iter_get_arg_type(&unit_iter) != DBUS_TYPE_STRUCT) {
00197 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)));
00198 goto cleanup;
00199 }
00200
00201 DBusMessageIter unit_name;
00202 dbus_message_iter_recurse(&unit_iter, &unit_name);
00203
00204 if (dbus_message_iter_get_arg_type(&unit_name) != DBUS_TYPE_STRING) {
00205 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)));
00206 goto cleanup;
00207 }
00208
00209 _DBusBasicValue value;
00210 dbus_message_iter_get_basic(&unit_name, &value);
00211 char *unit_name_s = oscap_strdup(value.str);
00212 int cbret = callback(unit_name_s, cbarg);
00213 free(unit_name_s);
00214 if (cbret != 0) {
00215 goto cleanup;
00216 }
00217 }
00218 while (dbus_message_iter_next(&unit_iter));
00219
00220 dbus_message_unref(msg); msg = NULL;
00221
00222 ret = 0;
00223
00224 cleanup:
00225 if (pending != NULL)
00226 dbus_pending_call_unref(pending);
00227
00228 if (msg != NULL)
00229 dbus_message_unref(msg);
00230
00231 return ret;
00232 }
00233
00234 static char *dbus_value_to_string(DBusMessageIter *iter)
00235 {
00236 const int arg_type = dbus_message_iter_get_arg_type(iter);
00237 if (dbus_type_is_basic(arg_type)) {
00238 _DBusBasicValue value;
00239 dbus_message_iter_get_basic(iter, &value);
00240
00241 switch (arg_type)
00242 {
00243 case DBUS_TYPE_BYTE:
00244 return oscap_sprintf("%c", value.byt);
00245
00246 case DBUS_TYPE_BOOLEAN:
00247 return oscap_strdup(value.bool_val ? "true" : "false");
00248
00249 case DBUS_TYPE_INT16:
00250 return oscap_sprintf("%i", value.i16);
00251
00252 case DBUS_TYPE_UINT16:
00253 return oscap_sprintf("%u", value.u16);
00254
00255 case DBUS_TYPE_INT32:
00256 return oscap_sprintf("%i", value.i32);
00257
00258 case DBUS_TYPE_UINT32:
00259 return oscap_sprintf("%u", value.u32);
00260
00261 #ifdef DBUS_HAVE_INT64
00262 case DBUS_TYPE_INT64:
00263 return oscap_sprintf("%lli", value.i32);
00264
00265 case DBUS_TYPE_UINT64:
00266 return oscap_sprintf("%llu", value.u32);
00267 #endif
00268
00269 case DBUS_TYPE_DOUBLE:
00270 return oscap_sprintf("%g", value.dbl);
00271
00272 case DBUS_TYPE_STRING:
00273 case DBUS_TYPE_OBJECT_PATH:
00274 case DBUS_TYPE_SIGNATURE:
00275 return oscap_strdup(value.str);
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 default:
00287 dI("Encountered unknown dbus basic type!");
00288 return oscap_strdup("error, unknown basic type!");
00289 }
00290 }
00291 else if (arg_type == DBUS_TYPE_ARRAY) {
00292 DBusMessageIter array;
00293 dbus_message_iter_recurse(iter, &array);
00294
00295 char *ret = NULL;
00296 do {
00297 char *element = dbus_value_to_string(&array);
00298
00299 if (element == NULL)
00300 continue;
00301
00302 char *old_ret = ret;
00303 if (old_ret == NULL)
00304 ret = oscap_sprintf("%s", element);
00305 else
00306 ret = oscap_sprintf("%s, %s", old_ret, element);
00307
00308 free(old_ret);
00309 free(element);
00310 }
00311 while (dbus_message_iter_next(&array));
00312
00313 return ret;
00314 }
00315
00316
00317
00318
00319
00320
00321 return NULL;
00322 }
00323
00324 static DBusConnection *connect_dbus()
00325 {
00326 DBusConnection *conn = NULL;
00327
00328 DBusError err;
00329 dbus_error_init(&err);
00330
00331 conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
00332 if (dbus_error_is_set(&err)) {
00333 dI("Failed to get DBUS_BUS_SYSTEM connection - %s", err.message);
00334 goto cleanup;
00335 }
00336 if (conn == NULL) {
00337 dI("DBusConnection == NULL!");
00338 goto cleanup;
00339 }
00340
00341 dbus_bus_register(conn, &err);
00342 if (dbus_error_is_set(&err)) {
00343 dI("Failed to register on dbus - %s", err.message);
00344 goto cleanup;
00345 }
00346
00347 cleanup:
00348 dbus_error_free(&err);
00349
00350 return conn;
00351 }
00352
00353 static void disconnect_dbus(DBusConnection *conn)
00354 {
00355
00356
00357
00358
00359 }
00360
00361 #endif