User authentication to services
Kay Sievers
kay.sievers at vrfy.org
Wed Jun 16 17:49:26 PDT 2004
On Thu, Jan 01, 1970 at 12:00:00AM +0000, Havoc Pennington wrote:
> On Tue, 2004-06-01 at 02:14, Rob Taylor wrote:
> > I'm interested in implementing a solution. However its not clear to me if this proposed solution solves my problem - I need applications to be able to authorise to a service, not a service to applications. and these applications must not be forced to register as a service as there may be multiple instances. Am i understanding this correctly?
> >
>
> Remember that all apps own at least one service, their unique base
> service name. (We have to come up with better terminology!)
>
> Each connection to the bus has a unique ID that never gets recycled (is
> never used by another connection to the same bus). This is called the
> "base service name" at the moment and looks like ":2-5" (the numbers
> change).
>
> Then connections can own 0-N additional well-known service names, such
> as "com.foobar.MyService" - these well-known names can refer to
> different connections at different times, since the owner can disconnect
> and another service can connect and take ownership instead.
>
> So in the authentication case you'd want to track the base service name,
> if you authenticated com.foobar.MyService you have a race condition
> since you don't know that the app currently owning the service is the
> same as the app you authenticated. With the base service name, if the
> name still exists it's still the same app.
Seems pretty silent now, the topic. But I need the get_sender_uid
feature too, so I tried something. Attention, I'm walking in total
darkness in the D-BUS code. :)
The following works for me:
sender = dbus_message_get_sender (message);
uid = dbus_bus_get_sender_uid (connection, sender, NULL);
D-BUS encodes the senders "base service name" in the incoming message,
so I made a method, which passes the name to a 'GetSenderUid' method
in dbus/bus/driver.c. The method iterates over all connections until the
right one is found and dbus_connection_get_unix_user() is called for it.
The uid is passed back to the calling dbus_bus_get_sender_uid().
Is there any better way to find the connection by its name?
Thanks,
Kay
-------------- next part --------------
Index: bus/driver.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/driver.c,v
retrieving revision 1.49
diff -u -r1.49 driver.c
--- bus/driver.c 9 Jun 2004 18:15:09 -0000 1.49
+++ bus/driver.c 17 Jun 2004 00:19:32 -0000
@@ -829,6 +829,115 @@
return FALSE;
}
+struct connection_match
+{
+ DBusConnection *connection;
+ const char *sender;
+};
+
+static dbus_bool_t
+match_sender (DBusConnection *connection,
+ void *data)
+{
+ const char *conn_sender;
+ struct connection_match *match;
+
+ _dbus_verbose ("match_sender() conn=%p\n", connection);
+
+ match = (struct connection_match*) data;
+
+ conn_sender = bus_connection_get_name (connection);
+ if (conn_sender == NULL)
+ return TRUE;
+
+ if (strcmp (match->sender, conn_sender) == 0)
+ {
+ match->connection = connection;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_sender_uid (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ char *sender = NULL;
+ DBusMessage *reply = NULL;
+ unsigned long uid;
+ struct connection_match match;
+ BusContext *context;
+ BusConnections *connections;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ if (! dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &sender,
+ DBUS_TYPE_INVALID))
+ goto failed;
+
+ _dbus_verbose ("bus_driver_handle_get_sender_uid() asked for %s\n", sender);
+
+ /* iterate over connections and pick the one with our 'base service name' */
+ match.connection = NULL;
+ match.sender = sender;
+
+ context = bus_connection_get_context (connection);
+ connections = bus_context_get_connections (context);
+
+ bus_connections_foreach (connections, match_sender, (void *) &match);
+ if (match.connection == NULL)
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_FAILED,
+ "Could not determine connection '%s'", sender);
+ goto failed;
+ }
+
+ _dbus_verbose ("bus_driver_handle_get_sender_uid() found connection\n");
+
+ if (!dbus_connection_get_unix_user (match.connection, &uid))
+ if (context == NULL)
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_FAILED,
+ "Could not determine uid for '%s'", sender);
+ goto failed;
+ }
+
+ _dbus_verbose ("bus_driver_handle_get_sender_uid() found uid=%i\n", (dbus_uint32_t) uid);
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ goto oom;
+
+ if (! dbus_message_append_args (reply,
+ DBUS_TYPE_UINT32, (dbus_uint32_t) uid,
+ DBUS_TYPE_INVALID))
+ goto oom;
+
+ if (! bus_transaction_send_from_driver (transaction, connection, reply))
+ goto oom;
+
+ dbus_message_unref (reply);
+ dbus_free (sender);
+
+ return TRUE;
+
+ oom:
+ BUS_SET_OOM (error);
+
+ failed:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ if (reply)
+ dbus_message_unref (reply);
+ dbus_free (sender);
+ return FALSE;
+}
+
static dbus_bool_t
bus_driver_handle_reload_config (DBusConnection *connection,
BusTransaction *transaction,
@@ -875,6 +984,7 @@
{ "AddMatch", bus_driver_handle_add_match },
{ "RemoveMatch", bus_driver_handle_remove_match },
{ "GetServiceOwner", bus_driver_handle_get_service_owner },
+ { "GetSenderUid", bus_driver_handle_get_sender_uid },
{ "ReloadConfig", bus_driver_handle_reload_config }
};
Index: dbus/dbus-bus.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-bus.c,v
retrieving revision 1.29
diff -u -r1.29 dbus-bus.c
--- dbus/dbus-bus.c 9 Jun 2004 18:15:09 -0000 1.29
+++ dbus/dbus-bus.c 17 Jun 2004 00:19:32 -0000
@@ -627,6 +627,78 @@
}
/**
+ * Asks the bus to return the uid of a sender.
+ *
+ * @param connection the connection
+ * @param service_name the service name
+ * @param error location to store the error
+ * @returns a result code, -1 if error is set
+ */
+dbus_uint32_t
+dbus_bus_get_sender_uid (DBusConnection *connection,
+ const char *sender,
+ DBusError *error)
+{
+ DBusMessage *message, *reply;
+ dbus_uint32_t uid;
+
+ _dbus_return_val_if_fail (connection != NULL, 0);
+ _dbus_return_val_if_fail (sender != NULL, 0);
+ _dbus_return_val_if_error_is_set (error, 0);
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+ DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+ "GetSenderUid");
+
+ if (message == NULL)
+ {
+ _DBUS_SET_OOM (error);
+ return -1;
+ }
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, sender,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ _DBUS_SET_OOM (error);
+ return -1;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
+ error);
+
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return -1;
+ }
+
+ if (dbus_set_error_from_message (error, reply))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ dbus_message_unref (reply);
+ return -1;
+ }
+
+ if (!dbus_message_get_args (reply, error,
+ DBUS_TYPE_UINT32, &uid,
+ DBUS_TYPE_INVALID))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ dbus_message_unref (reply);
+ return -1;
+ }
+
+ dbus_message_unref (reply);
+
+ return uid;
+}
+
+/**
* Checks whether a certain service exists.
*
* @param connection the connection
Index: dbus/dbus-bus.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-bus.h,v
retrieving revision 1.9
diff -u -r1.9 dbus-bus.h
--- dbus/dbus-bus.h 2 Dec 2003 10:44:21 -0000 1.9
+++ dbus/dbus-bus.h 17 Jun 2004 00:19:32 -0000
@@ -45,6 +45,9 @@
dbus_bool_t dbus_bus_set_base_service (DBusConnection *connection,
const char *base_service);
const char* dbus_bus_get_base_service (DBusConnection *connection);
+dbus_uint32_t dbus_bus_get_sender_uid (DBusConnection *connection,
+ const char *sender,
+ DBusError *error);
int dbus_bus_acquire_service (DBusConnection *connection,
const char *service_name,
unsigned int flags,
More information about the dbus
mailing list