User authentication to services

Kay Sievers kay.sievers at vrfy.org
Wed Jun 23 15:25:14 PDT 2004


On Fri, Jun 18, 2004 at 04:25:14PM +0200, Olivier Andrieu wrote:
>  Kay Sievers [Fri, 18 Jun 2004]:
>  > > - the BaseName property replicates the functionality of 
>  > >   the GetServiceOwner, so we need to decide between these two.
>  > 
>  > I've replaced it by GetProperty and changed:
>  >   dbus/glib/dbus-gproxy.c:dbus_gproxy_new_for_service_owner() to call
>  >   it instead. (Hmm, needs to be tested if it still works)
>  > 
>  > Is it ok, this way? If yes, I will change the spec too.
> 
> What's wrong with having two different methods ? With a single
> GetProperty method the reply message carries either an INT32 or a
> STRING. That(s not very nice.
> 
>  > > - the name "GetServiceProperty" isn't a bit funny; it's a 
>  > >   property of the connection, not the service. 
>  > >   Suggest just "GetProperty"
> 
> But the base name is a property of the service.

Ok, here is a version that doesn't touch the existing code. It also
avoids the multiplexing method with the dynamic return type.
It just adds a "GetConnectionUnixUser" method similar to "GetServiceOwner".
The method is explained in the spec and a unit test in dispatch.c is
also added.

Thanks,
Kay
-------------- next part --------------
? dbus/dbus-glib-error-enum.h
Index: bus/dispatch.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.c,v
retrieving revision 1.57
diff -u -r1.57 dispatch.c
--- bus/dispatch.c	16 Mar 2004 18:00:34 -0000	1.57
+++ bus/dispatch.c	23 Jun 2004 22:10:15 -0000
@@ -924,6 +924,142 @@
  * but the correct thing may include OOM errors.
  */
 static dbus_bool_t
+check_get_connection_unix_user (BusContext     *context,
+                                DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+  const char *base_service_name;
+  dbus_uint32_t uid;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_get_connection_unix_user for %p\n", connection);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "GetConnectionUnixUser");
+
+  if (message == NULL)
+    return TRUE;
+
+  base_service_name = dbus_bus_get_base_service (connection);
+
+  if (!dbus_message_append_args (message, 
+                                 DBUS_TYPE_STRING, base_service_name,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  /* send our message */
+  bus_test_run_clients_loop (TRUE);
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+  block_connection_until_message_from_bus (context, connection);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      
+      dbus_connection_unref (connection);
+      
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "GetConnectionUnixUser", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+        {
+          ; /* good, expected */
+        }
+      else
+        {
+          warn_unexpected (connection, message,
+	                   "method_return for GetConnectionUnixUser");
+
+          goto out;
+        }
+
+    retry_get_property:
+
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_UINT32, &uid,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              _dbus_verbose ("no memory to get uid by GetProperty\n");
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto retry_get_property;
+            }
+          else
+            {
+              _dbus_assert (dbus_error_is_set (&error));
+              _dbus_warn ("Did not get the expected DBUS_TYPE_UINT from GetProperty\n");
+              goto out;
+            }
+        }
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  dbus_error_free (&error);
+  
+  if (message)
+    dbus_message_unref (message);
+  
+  return retval;
+}
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
 check_add_match_all (BusContext     *context,
                      DBusConnection *connection)
 {
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	23 Jun 2004 22:10:16 -0000
@@ -830,6 +830,82 @@
 }
 
 static dbus_bool_t
+bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
+                                            BusTransaction *transaction,
+                                            DBusMessage    *message,
+                                            DBusError      *error)
+{
+  char *service;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *serv;
+  DBusConnection *conn;
+  DBusMessage *reply;
+  unsigned long uid;
+  const char *base_name;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_STRING, &service,
+			       DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_verbose ("asked for UID of connection %s\n", service);
+
+  _dbus_string_init_const (&str, service);
+  serv = bus_registry_lookup (registry, &str);
+  if (serv == NULL)
+    {
+      dbus_set_error (error, 
+		      DBUS_ERROR_SERVICE_HAS_NO_OWNER,
+		      "Could not get owner of service '%s': no such service", service);
+      goto failed;
+    }
+
+  conn = bus_service_get_primary_owner (serv);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (!dbus_connection_get_unix_user (conn, &uid))
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+                      "Could not determine UID for '%s'", service);
+      goto failed;
+    }
+
+  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 (service);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+  dbus_free (service);
+  return FALSE;
+}
+
+static dbus_bool_t
 bus_driver_handle_reload_config (DBusConnection *connection,
 				 BusTransaction *transaction,
 				 DBusMessage    *message,
@@ -875,6 +951,7 @@
   { "AddMatch", bus_driver_handle_add_match },
   { "RemoveMatch", bus_driver_handle_remove_match },
   { "GetServiceOwner", bus_driver_handle_get_service_owner },
+  { "GetConnectionUnixUser", bus_driver_handle_get_connection_unix_user },
   { "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	23 Jun 2004 22:10:16 -0000
@@ -546,6 +546,79 @@
 }
 
 /**
+ * Asks the bus to return the uid of a service.
+ *
+ * @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
+ */ 
+unsigned long
+dbus_bus_get_unix_user (DBusConnection *connection,
+                        const char     *service,
+                        DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  dbus_uint32_t uid;
+
+  _dbus_return_val_if_fail (connection != NULL, DBUS_UID_UNSET);
+  _dbus_return_val_if_fail (service != NULL, DBUS_UID_UNSET);
+  _dbus_return_val_if_error_is_set (error, DBUS_UID_UNSET);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "GetConnectionUnixUser");
+
+  if (message == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return DBUS_UID_UNSET;
+    }
+ 
+  if (!dbus_message_append_args (message,
+				 DBUS_TYPE_STRING, service,
+				 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      _DBUS_SET_OOM (error);
+      return DBUS_UID_UNSET;
+    }
+  
+  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 DBUS_UID_UNSET;
+    }  
+
+  if (dbus_set_error_from_message (error, reply))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return DBUS_UID_UNSET;
+    }
+  
+  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 DBUS_UID_UNSET;
+    }
+
+  dbus_message_unref (reply);
+  
+  return (unsigned long) uid;
+}
+
+
+/**
  * Asks the bus to try to acquire a certain service.
  *
  * @todo these docs are not complete, need to document the
Index: dbus/dbus-bus.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-bus.h,v
retrieving revision 1.10
diff -u -r1.10 dbus-bus.h
--- dbus/dbus-bus.h	20 Jun 2004 15:28:15 -0000	1.10
+++ dbus/dbus-bus.h	23 Jun 2004 22:10:16 -0000
@@ -38,6 +38,9 @@
 dbus_bool_t     dbus_bus_set_base_service (DBusConnection *connection,
 					   const char     *base_service);
 const char*     dbus_bus_get_base_service (DBusConnection *connection);
+unsigned long   dbus_bus_get_unix_user    (DBusConnection *connection,
+			                   const char     *service,
+                                           DBusError      *error);
 int             dbus_bus_acquire_service  (DBusConnection *connection,
 					   const char     *service_name,
 					   unsigned int    flags,
Index: doc/dbus-specification.xml
===================================================================
RCS file: /cvs/dbus/dbus/doc/dbus-specification.xml,v
retrieving revision 1.10
diff -u -r1.10 dbus-specification.xml
--- doc/dbus-specification.xml	2 Jun 2004 14:03:58 -0000	1.10
+++ doc/dbus-specification.xml	23 Jun 2004 22:10:19 -0000
@@ -2497,6 +2497,57 @@
        </para>
       </sect3>
 
+      <sect3 id="bus-messages-get-connection-unix-user">
+        <title><literal>org.freedesktop.DBus.GetConnectionUnixUser</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            UINT32 GetConnectionUnixUser (in STRING connection_name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name of the connection/service to query</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        Reply arguments:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Argument</entry>
+                <entry>Type</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>0</entry>
+                <entry>UINT32</entry>
+                <entry>unix user id</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+        Returns the unix uid of the process connected to the server. If unable to
+	determine it, a <literal>org.freedesktop.DBus.Error.Failed</literal>
+	error is returned.
+       </para>
+      </sect3>
+
       <sect3 id="bus-messages-out-of-memory">
         <title><literal>org.freedesktop.DBus.Error.NoMemory</literal></title>
         <para>


More information about the dbus mailing list