|
Open SCAP Library
|
00001 00007 /* 00008 * Copyright 2014 Red Hat Inc., Durham, North Carolina. 00009 * All Rights Reserved. 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Lesser General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2.1 of the License, or (at your option) any later version. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this library; if not, write to the Free Software 00023 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 * 00025 * Authors: 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 // Old versions of libdbus API don't have DBusBasicValue and DBus8ByteStruct 00042 // as a public typedefs. 00043 // These two typedefs were copied from libdbus 1.8 branch, see 00044 // http://cgit.freedesktop.org/dbus/dbus/tree/dbus/dbus-types.h?h=dbus-1.8#n137 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 // LoadUnit is similar to GetUnit except it will load the unit file 00082 // if it hasn't been loaded yet. 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 // the args should be empty for this call 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 // non-basic types 00278 //case DBUS_TYPE_ARRAY: 00279 //case DBUS_TYPE_STRUCT: 00280 //case DBUS_TYPE_DICT_ENTRY: 00281 //case DBUS_TYPE_VARIANT: 00282 00283 //case DBUS_TYPE_UNIX_FD: 00284 // return oscap_sprintf("%i", value.fd); 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 else if (arg_type == DBUS_TYPE_VARIANT) { 00316 DBusMessageIter inner; 00317 dbus_message_iter_recurse(iter, &inner); 00318 return dbus_value_to_string(&inner); 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 // NOOP 00356 00357 // Connections retrieved via dbus_bus_get shall not be destroyed, 00358 // these connections are shared. 00359 } 00360 00361 #endif
1.7.3