User authentication to services

Rob Taylor robtaylor at fastmail.fm
Thu Jun 17 21:44:56 PDT 2004


Umm. actually I have been working on this - tried to go straight for Havoc's suggested interface earlier..
I've merged my stuff with Kay's (i've currently left the question of the BaseName property - its implented here, but i'm not using it - i have so say i don't quite see the point of it)

This code is mostly untested, i just want to get it out there so someone  knows what i'm doing... I'm writing some unit tests right now.

Thanks,
Rob Taylor

On Fri, 18 Jun 2004 00:17:13 -0400
Havoc Pennington <hp at redhat.com> wrote:

> Hi,
> 
> On Thu, 2004-06-17 at 22:29, Kay Sievers wrote:
> > +bus_driver_handle_get_service_property (DBusConnection *connection,
> 
> Can you sync this function name with the string version? 
> (i.e. change to "get_property")
> 
> >    if (! dbus_message_append_args (request, 
> >  				  DBUS_TYPE_STRING, service_name, 
> > +				  DBUS_TYPE_STRING, "BaseName", 
> >  				  DBUS_TYPE_INVALID))
> 
> Should we name this property BaseService since the spec calls it that?
> 
> As you say, should update the spec. Also, as it says in HACKING "make
> check" should still pass, and it would be a plus to add a little test
> for this new code.
> 
> There are two places you could test. In dispatch.c - it would look a lot
> like check_hello_message() but a bit shorter. This would fully test all
> the OOM cases in driver.c.
> The second option is in test-dbus-glib.c, you could call
> dbus_bus_get_unix_user() there and get test coverage on dbus-bus.c.
> Anyway at least one of those would rock.
> 
> Thanks for your patience, just trying to be really thorough on D-BUS
> patches since bugs are likely to be security problems or crash the whole
> system or login session.
> 
> Havoc
> 
> 
> 
> -- 
> dbus mailing list
> dbus at freedesktop.org
> http://freedesktop.org/mailman/listinfo/dbus
-------------- next part --------------
? 02-dbus-uid.patch
? dbus-uid-04.patch
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	18 Jun 2004 04:43:28 -0000
@@ -855,6 +855,188 @@
   return retval;
 }
 
+typedef dbus_bool_t (*PropertyGetter)(BusService *service, DBusString *service_name, DBusError *error, DBusString *property_return);
+
+static dbus_bool_t property_getter_authuser(BusService *service, DBusString *service_name, DBusError *error, DBusString *property_return)
+{
+  unsigned long uid;
+
+  if (_dbus_string_get_byte (service_name, 0) != ':')
+    {
+      dbus_set_error (error, 
+		      DBUS_ERROR_FAILED,
+		      "'%s' is not a base service", _dbus_string_get_const_data(service_name));
+      return FALSE;
+    }
+
+  if (!dbus_connection_get_unix_user (bus_service_get_primary_owner (service), &uid))   
+    {
+      dbus_set_error (error, 
+		      DBUS_ERROR_FAILED,
+		      "Could not get unix user for '%s'", _dbus_string_get_const_data(service_name));
+      return FALSE;
+    }
+
+  _dbus_string_append_int(property_return, uid);
+
+  return TRUE;
+}
+
+static dbus_bool_t property_getter_basename(BusService *service, DBusString *service_name, DBusError *error, DBusString *property_return)
+{
+  const char *base_name;
+  base_name = bus_connection_get_name (bus_service_get_primary_owner (service));
+  if (base_name == NULL)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+	              "Could not determine base name for '%s'", service);
+      return FALSE;
+    }
+  _dbus_assert (*base_name == ':');
+
+  _dbus_string_append(property_return,base_name);
+
+  return TRUE;  
+}
+
+typedef struct _NamedPropertyGetter
+{
+	const char *name;
+	PropertyGetter property_getter;
+} NamedPropertyGetter;
+
+const static NamedPropertyGetter system_property_getters[] = 
+{
+	{ "AuthUser", property_getter_authuser },
+	{ "BaseName", property_getter_basename },
+	{NULL, NULL}
+};
+
+
+static dbus_bool_t
+bus_driver_handle_get_properties (DBusConnection *connection,
+				     BusTransaction *transaction,
+				     DBusMessage    *message,
+				     DBusError      *error)
+{
+  char **property_list = NULL;
+  char **ret_list = NULL;
+  char *text = NULL;
+
+  int property_list_len;
+  DBusString service_name;
+  DBusString property_val;
+  BusRegistry *registry;
+  BusService *service;
+  DBusMessage *reply;
+  const NamedPropertyGetter *np;
+  int i=0,j=0;
+  dbus_bool_t done;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  reply = NULL;
+  property_list = NULL;
+  ret_list = NULL;
+  text = NULL;
+
+  registry = bus_connection_get_registry (connection);
+
+  if (! dbus_message_get_args ( message, error,
+			        DBUS_TYPE_STRING, text,
+			 	DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+				&property_list, &property_list_len,
+			        DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_string_init_const (&service_name, text);
+
+  service = bus_registry_lookup (registry, &service_name);
+  if (service == NULL)
+    {
+      dbus_set_error (error, 
+		      DBUS_ERROR_SERVICE_HAS_NO_OWNER,
+		      "Could not get owner of service '%s': no such service", text);
+      goto failed;
+    }
+
+  ret_list = dbus_new (char *, property_list_len + 1);
+
+  if (ret_list == NULL)
+    goto failed;
+
+  _dbus_string_init(&property_val);
+
+  for (i=0; i<property_list_len; i++)
+    {
+      np=system_property_getters;
+      done=FALSE;
+      for (;np->name!=NULL;np++) {
+        if (strcmp(property_list[i],np->name))
+	{
+	  if (!(np->property_getter)(service, &service_name, error, &property_val))
+            goto failed;
+          _dbus_string_steal_data(&property_val, &(ret_list[i]));
+          done=TRUE;
+	  break;
+	}
+      }
+      /*fill in null if the user requested a bad property*/
+      if (!done)
+        ret_list[i]=NULL; 
+    }
+
+  ret_list[i] = NULL;
+  
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (! dbus_message_append_args (reply, 
+				  DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, ret_list, i,
+				  DBUS_TYPE_INVALID))
+    goto oom;
+  
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  for (j = 0; j < i; j++)
+    dbus_free (ret_list[i]);
+  dbus_free (ret_list);
+
+  dbus_message_unref (reply);
+  dbus_free (text);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+
+  if (ret_list) 
+    {
+      for (j = 0; j < i; j++)
+        dbus_free (ret_list[i]);
+      dbus_free (ret_list);
+    }
+
+
+   if (ret_list) 
+    {
+      for (j = 0; j < i; j++)
+        dbus_free (ret_list[i]);
+      dbus_free (ret_list);
+    }
+
+ if (reply)
+    dbus_message_unref (reply);
+  dbus_free (text);
+  return FALSE;
+}
+
 /* For speed it might be useful to sort this in order of
  * frequency of use (but doesn't matter with only a few items
  * anyhow)
@@ -875,7 +1057,8 @@
   { "AddMatch", bus_driver_handle_add_match },
   { "RemoveMatch", bus_driver_handle_remove_match },
   { "GetServiceOwner", bus_driver_handle_get_service_owner },
-  { "ReloadConfig", bus_driver_handle_reload_config }
+  { "ReloadConfig", bus_driver_handle_reload_config },
+  { "GetProperties", bus_driver_handle_get_properties }
 };
 
 dbus_bool_t
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	18 Jun 2004 04:43:30 -0000
@@ -627,6 +627,92 @@
 }
 
 /**
+ * Asks the bus to return the requested list of properties from a service.
+ *
+ * The returned ret_list is a #NULL-terminated array of strings.
+ * Each string is a separate malloc block, and the array
+ * itself is a malloc block. You can free this type of
+ * string array with dbus_free_string_array().
+ *
+ * @param connection the connection
+ * @param service_name the service name
+ * @param property_list array of property names to look up 
+ * @param property_list_len length of array of property names  
+ * @param return_list return location for property values
+ * @param return_list_len return location for length of property array
+ * @param error location to store the error
+ * @returns #TRUE if the property list was sucessfully retrieved, #FALSE on error
+ */ 
+dbus_bool_t
+dbus_bus_get_service_properties (DBusConnection *connection,
+                          const char     *service,
+			  const char     **property_list,
+			  int            property_list_len,
+			  char           ***return_list,
+			  int            *return_list_len,
+			  DBusError      *error)
+{
+  DBusMessage *message, *reply;
+
+  _dbus_return_val_if_fail (connection != NULL, -1);
+  _dbus_return_val_if_fail (service != NULL, -1);
+  _dbus_return_val_if_error_is_set (error, -1);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "GetProperties");
+ 
+
+  if (message == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+ 
+  if (!dbus_message_append_args (message,
+				 DBUS_TYPE_STRING, service,
+				 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, property_list, property_list_len,
+				 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  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 FALSE;
+    }  
+
+  if (dbus_set_error_from_message (error, reply))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+  
+  if (!dbus_message_get_args (reply, error,
+			      DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, return_list, return_list_len,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+
+  dbus_message_unref (reply);
+  
+  return TRUE;
+}
+
+/**
  * 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	18 Jun 2004 04:43:30 -0000
@@ -58,6 +58,13 @@
 					   dbus_uint32_t   flags,
 					   dbus_uint32_t  *reply,
 					   DBusError      *error);
+dbus_bool_t	dbus_bus_get_service_properties (DBusConnection *connection,
+                                           const char     *service,
+			                   const char     **property_list,
+			                   int            property_list_len,
+			  		   char           ***return_list,
+					   int            *return_list_len,
+					   DBusError      *error);
 
 void            dbus_bus_add_match        (DBusConnection *connection,
                                            const char     *rule,


More information about the dbus mailing list