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