|
|
- /*
- * Copyright (c) 2003-2007 Andrea Luzzardi <scox@sig11.org>
- *
- * This file is part of the pam_usb project. pam_usb is free software;
- * you can redistribute it and/or modify it under the terms of the GNU General
- * Public License version 2, as published by the Free Software Foundation.
- *
- * pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
- * Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdarg.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include "mem.h"
- #include "log.h"
- #include "hal.h"
-
- DBusConnection *pusb_hal_dbus_connect(void)
- {
- DBusConnection *dbus = NULL;
- DBusError error;
-
- dbus_error_init(&error);
- if (!(dbus = dbus_bus_get(DBUS_BUS_SYSTEM, &error)))
- {
- /* Workaround for https://bugs.freedesktop.org/show_bug.cgi?id=11876 */
- uid_t ruid;
- uid_t euid;
-
- if (!(euid = geteuid()) && (ruid = getuid()))
- {
- dbus_error_free(&error);
- setreuid(euid, euid);
- dbus = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
- setreuid(ruid, euid);
- }
- if (!dbus)
- {
- log_error("Cannot connect to system bus: %s\n",
- error.message);
- dbus_error_free(&error);
- return (NULL);
- }
- }
- return (dbus);
- }
-
- void pusb_hal_dbus_disconnect(DBusConnection *dbus)
- {
- dbus_connection_unref(dbus);
- }
-
- void pusb_hal_free_string_array(char **str_array, int length)
- {
- int i;
-
- if (str_array == NULL)
- return ;
-
- for (i = 0; i < length; ++i)
- xfree(str_array[i]);
- xfree(str_array);
- }
-
- char **pusb_hal_get_string_array_from_iter(DBusMessageIter *iter, int *num_elements)
- {
- int count;
- char **buffer;
-
- count = 0;
- buffer = (char **)xmalloc(sizeof(char *) * 8);
-
- buffer[0] = NULL;
- while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING ||
- dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_OBJECT_PATH)
- {
- const char *value;
-
- if ((count % 8) == 0 && count != 0) {
- buffer = xrealloc(buffer, sizeof (char *) * (count + 8));
- }
-
- dbus_message_iter_get_basic(iter, &value);
- buffer[count] = xstrdup(value);
-
- dbus_message_iter_next(iter);
- count++;
- }
-
- if (num_elements != NULL)
- *num_elements = count;
- return buffer;
- }
-
-
-
- DBusMessage *pusb_hal_get_raw_property(DBusConnection *dbus,
- const char *udi,
- const char *name)
- {
- DBusMessage *message;
- DBusMessage *reply;
- DBusMessageIter iter;
- DBusError error;
- char *iface = "org.freedesktop.UDisks.Device";
-
- message = dbus_message_new_method_call("org.freedesktop.UDisks", udi,
- "org.freedesktop.DBus.Properties",
- "Get");
- if (message == NULL) {
- log_error("Could not allocate D-BUS message\n");
- return (NULL);
- }
- dbus_message_iter_init_append(message, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &iface);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
-
- dbus_error_init(&error);
- reply = dbus_connection_send_with_reply_and_block(dbus,
- message, -1,
- &error);
- dbus_message_unref(message);
- if (dbus_error_is_set(&error)) {
- log_error("Error communicating with D-BUS\n");
- return (NULL);
- }
- dbus_error_free(&error);
- return (reply);
- }
-
- char *pusb_hal_get_string_property(DBusConnection *dbus,
- const char *udi,
- const char *name)
- {
- DBusMessage *reply;
- DBusMessageIter reply_iter;
- char *data;
- char *dbus_str;
-
- reply = pusb_hal_get_raw_property(dbus, udi, name);
- if (reply == NULL) {
- return (NULL);
- }
-
- dbus_message_iter_init(reply, &reply_iter);
-
- if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_VARIANT)
- {
- dbus_message_unref(reply);
- return (NULL);
- }
-
- DBusMessageIter subiter;
- dbus_message_iter_recurse(&reply_iter, &subiter);
- dbus_message_iter_get_basic(&subiter, &dbus_str);
- if (dbus_str != NULL)
- data = xstrdup(dbus_str);
- dbus_message_unref(reply);
- return (data);
- }
-
- char **pusb_hal_get_string_array_property(DBusConnection *dbus,
- const char *udi,
- const char *name,
- int *n_items)
- {
- DBusMessage *reply;
- DBusMessageIter reply_iter;
- char **items;
-
- reply = pusb_hal_get_raw_property(dbus, udi, name);
- if (reply == NULL) {
- return (NULL);
- }
-
- dbus_message_iter_init(reply, &reply_iter);
-
- if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_VARIANT)
- {
- dbus_message_unref(reply);
- return (NULL);
- }
-
- DBusMessageIter subiter, subsubiter;
- dbus_message_iter_recurse(&reply_iter, &subiter);
- dbus_message_iter_recurse(&subiter, &subsubiter);
- items = pusb_hal_get_string_array_from_iter(&subsubiter, n_items);
- dbus_message_unref(reply);
- if (!*n_items)
- {
- pusb_hal_free_string_array(items, *n_items);
- return (NULL);
- }
- return (items);
- }
-
-
-
- int pusb_hal_get_bool_property(DBusConnection *dbus,
- const char *udi,
- const char *name,
- dbus_bool_t *value)
- {
- DBusMessage *reply;
- DBusMessageIter reply_iter;
-
- reply = pusb_hal_get_raw_property(dbus, udi, name);
- if (reply == NULL) {
- return (0);
- }
-
- dbus_message_iter_init(reply, &reply_iter);
-
- if (dbus_message_iter_get_arg_type(&reply_iter) !=
- DBUS_TYPE_VARIANT)
- {
- dbus_message_unref(reply);
- return (0);
- }
-
- DBusMessageIter subiter;
- dbus_message_iter_recurse(&reply_iter, &subiter);
- dbus_message_iter_get_basic(&subiter, value);
- dbus_message_unref(reply);
- return (1);
- }
-
- int pusb_hal_check_property(DBusConnection *dbus,
- const char *udi,
- const char *name,
- const char *value)
- {
- char *data;
- int retval;
-
- data = pusb_hal_get_string_property(dbus, udi, name);
- if (!data)
- return (0);
- retval = (strcmp(data, value) == 0);
- xfree(data);
- return (retval);
- }
-
- char **pusb_hal_find_all_items(DBusConnection *dbus, int *count)
- {
- DBusError error;
- DBusMessage *message;
- DBusMessage *reply;
- DBusMessageIter iter_array, reply_iter;
- char **devices;
- int n_devices;
-
- *count = 0;
- message = dbus_message_new_method_call("org.freedesktop.UDisks",
- "/org/freedesktop/UDisks",
- "org.freedesktop.UDisks",
- "EnumerateDevices");
- if (message == NULL)
- {
- log_error("Couldn't allocate D-BUS message\n");
- return (NULL);
- }
- dbus_error_init(&error);
- reply = dbus_connection_send_with_reply_and_block(dbus,
- message, -1,
- &error);
- dbus_message_unref(message);
- if (dbus_error_is_set(&error)) {
- log_error("Error communicating with D-BUS\n");
- return (NULL);
- }
- if (reply == NULL) {
- return (NULL);
- }
- dbus_message_iter_init(reply, &reply_iter);
- if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
- log_error("Malformed D-BUS reply");
- return (NULL);
- }
- dbus_message_iter_recurse(&reply_iter, &iter_array);
- devices = pusb_hal_get_string_array_from_iter(&iter_array, &n_devices);
- dbus_message_unref(reply);
- if (!n_devices)
- {
- pusb_hal_free_string_array(devices, n_devices);
- return (NULL);
- }
- *count = n_devices;
- return (devices);
- }
-
- char *pusb_hal_find_item(DBusConnection *dbus,
- ...)
- {
- char **devices;
- int n_devices;
- char *udi = NULL;
- va_list ap;
- int i;
-
- devices = pusb_hal_find_all_items(dbus, &n_devices);
- if (!devices)
- return (NULL);
- if (!n_devices)
- return (NULL);
-
- for (i = 0; i < n_devices; ++i)
- {
- char *key = NULL;
- int match = 1;
-
- va_start(ap, dbus);
- while ((key = va_arg(ap, char *)))
- {
- char *value = NULL;
-
- value = va_arg(ap, char *);
- if (!value || *value == 0x0)
- continue ;
- if (!pusb_hal_check_property(dbus, devices[i],
- key, value))
- {
- match = 0;
- break;
- }
- }
- if (match)
- {
- udi = xstrdup(devices[i]);
- break;
- }
- va_end(ap);
- }
- pusb_hal_free_string_array(devices, n_devices);
- return (udi);
- }
|