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