#include #include #include #include #include #include typedef int errno_t; #define EOK 0 #define INFOPIPE_DBUS_NAME "org.freedesktop.sssd.infopipe" #define INFOPIPE_INTERFACE "org.freedesktop.sssd.infopipe" #define INFOPIPE_PATH "/org/freedesktop/sssd/infopipe" #define SSS_METHOD_DOMAIN_LIST "ListDomains" #define DBUS_PROP_IFACE "org.freedesktop.DBus.Properties" static DBusMessage* sss_dbus_infopipe_call(DBusConnection *conn, const char *method) { return dbus_message_new_method_call(INFOPIPE_DBUS_NAME, INFOPIPE_PATH, INFOPIPE_INTERFACE, method); } static DBusMessage* sss_dbus_property_call(DBusConnection *conn, const char *object_path, const char *method) { return dbus_message_new_method_call(INFOPIPE_DBUS_NAME, object_path, DBUS_PROP_IFACE, method); } errno_t sss_dbus_get_string_property(TALLOC_CTX *mem_ctx, DBusConnection *conn, DBusError *error, const char *object_path, const char *property, char **_out) { DBusMessage *msg = NULL; DBusMessage *reply = NULL; DBusMessageIter iter; DBusMessageIter subiter; char *prop = NULL; dbus_bool_t dbret; errno_t ret; msg = sss_dbus_property_call(conn, object_path, "Get"); if (msg == NULL) { ret = ENOMEM; goto done; } dbret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID); if (!dbret) { ret = ENOMEM; goto done; } reply = dbus_connection_send_with_reply_and_block(conn, msg, 5000, error); if (dbus_error_is_set(error)) { ret = EIO; goto done; } dbus_message_iter_init(reply, &iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { ret = EINVAL; goto done; } dbus_message_iter_recurse(&iter, &subiter); if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING) { ret = EINVAL; goto done; } dbus_message_iter_get_basic(&subiter, &prop); *_out = talloc_strdup(mem_ctx, prop); if (*_out == NULL) { ret = ENOMEM; goto done; } ret = EOK; done: if (msg != NULL) { dbus_message_unref(msg); } if (reply != NULL) { dbus_message_unref(reply); } return ret; } errno_t sss_dbus_list_domains(TALLOC_CTX *mem_ctx, DBusConnection *conn, DBusError *error, char ***_domains) { DBusMessage *msg = NULL; DBusMessage *reply = NULL; char **domains = NULL; char **objects = NULL; int num_objects; dbus_bool_t dbret; errno_t ret; int i; if (conn == NULL || error == NULL) { ret = EINVAL; goto done; } msg = sss_dbus_infopipe_call(conn, SSS_METHOD_DOMAIN_LIST); if (msg == NULL) { ret = ENOMEM; goto done; } reply = dbus_connection_send_with_reply_and_block(conn, msg, 5000, error); if (dbus_error_is_set(error)) { ret = EIO; goto done; } dbret = dbus_message_get_args(reply, error, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objects, &num_objects, DBUS_TYPE_INVALID); if (!dbret) { ret = EIO; goto done; } if (objects == NULL || num_objects == 0) { ret = ENOENT; goto done; } domains = talloc_zero_array(mem_ctx, char*, num_objects + 1); if (domains == NULL) { ret = ENOMEM; goto done; } for (i = 0; i < num_objects; i++) { ret = sss_dbus_get_string_property(domains, conn, error, objects[i], "name", &domains[i]); if (ret != EOK) { goto done; } } *_domains = domains; ret = EOK; done: if (ret != EOK) { talloc_free(domains); } if (msg != NULL) { dbus_message_unref(msg); } if (reply != NULL) { dbus_message_unref(reply); } return ret; } int main(int argc, const char **argv) { DBusConnection *conn = NULL; DBusError error; char **domains = NULL; errno_t ret; int i; dbus_error_init(&error); conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error); if (dbus_error_is_set(&error)) { fprintf(stderr, "Failed to open connection to bus: %s\n", error.message); return 1; } ret = sss_dbus_list_domains(NULL, conn, &error, &domains); if (ret != EOK) { fprintf(stderr, "Error [%d]: %s\n", ret, strerror(ret)); return 1; } for (i = 0; domains[i] != NULL; i++) { printf("%s\n", domains[i]); } dbus_connection_unref(conn); return 0; }