2004-07-19 David Zeuthen <david@fubar.dk>
authorDavid Zeuthen <davidz@redhat.com>
Mon, 19 Jul 2004 20:55:58 +0000 (20:55 +0000)
committerDavid Zeuthen <davidz@redhat.com>
Mon, 19 Jul 2004 20:55:58 +0000 (20:55 +0000)
* dbus/dbus-protocol.h: Add DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN

* bus/dispatch.c:
(check_get_connection_unix_user): Debug says GetProperty; but the
method is called GetConnectionUnixUser
(check_get_connection_unix_process_id): New function
(bus_dispatch_test): Actually call check_get_connection_unix_user();
also call check_get_connection_unix_process_id()

* bus/driver.c:
(bus_driver_handle_get_connection_unix_process_id): New function,
handles GetConnectionUnixProcessID on the org.freedesktop.DBus
interface

* dbus/dbus-auth.c:
(handle_server_data_external_mech): Set pid from the credentials
obtained from the socket

* dbus/dbus-connection.c:
(dbus_connection_get_unix_process_id): New function

* dbus/dbus-connection.h:
Add prototype for dbus_connection_get_unix_process_id

* dbus/dbus-transport.c:
(_dbus_transport_get_unix_process_id): New function

* dbus/dbus-transport.h:
Add prototype for _dbus_transport_get_unix_process_id

ChangeLog
bus/dispatch.c
bus/driver.c
dbus/dbus-auth.c
dbus/dbus-connection.c
dbus/dbus-connection.h
dbus/dbus-protocol.h
dbus/dbus-transport.c
dbus/dbus-transport.h

index 789a536..664bc89 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2004-07-19  David Zeuthen  <david@fubar.dk>
+
+       * dbus/dbus-protocol.h: Add DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN
+
+       * bus/dispatch.c:
+       (check_get_connection_unix_user): Debug says GetProperty; but the
+       method is called GetConnectionUnixUser
+       (check_get_connection_unix_process_id): New function
+       (bus_dispatch_test): Actually call check_get_connection_unix_user();
+       also call check_get_connection_unix_process_id()
+       
+       * bus/driver.c:
+       (bus_driver_handle_get_connection_unix_process_id): New function,
+       handles GetConnectionUnixProcessID on the org.freedesktop.DBus
+       interface
+       
+       * dbus/dbus-auth.c:
+       (handle_server_data_external_mech): Set pid from the credentials
+       obtained from the socket
+       
+       * dbus/dbus-connection.c:
+       (dbus_connection_get_unix_process_id): New function
+       
+       * dbus/dbus-connection.h: 
+       Add prototype for dbus_connection_get_unix_process_id
+       
+       * dbus/dbus-transport.c:
+       (_dbus_transport_get_unix_process_id): New function
+       
+       * dbus/dbus-transport.h:
+       Add prototype for _dbus_transport_get_unix_process_id
+       
 2004-07-19  Olivier Andrieu  <oliv__a@users.sourceforge.net>
 
        * dbus/dbus-message.c: Message counter fix, patch by Christian
index f38a990..9bc89a7 100644 (file)
@@ -1029,7 +1029,7 @@ check_get_connection_unix_user (BusContext     *context,
         {
           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
             {
-              _dbus_verbose ("no memory to get uid by GetProperty\n");
+              _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n");
               dbus_error_free (&error);
               _dbus_wait_for_memory ();
               goto retry_get_property;
@@ -1037,7 +1037,7 @@ check_get_connection_unix_user (BusContext     *context,
           else
             {
               _dbus_assert (dbus_error_is_set (&error));
-              _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetProperty\n");
+              _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n");
               goto out;
             }
         }
@@ -1056,6 +1056,159 @@ check_get_connection_unix_user (BusContext     *context,
   
   return retval;
 }
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_get_connection_unix_process_id (BusContext     *context,
+                                     DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+  const char *base_service_name;
+  dbus_uint32_t pid;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_get_connection_unix_process_id 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,
+                                          "GetConnectionUnixProcessID");
+
+  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",
+                  "GetConnectionUnixProcessID", 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 GetConnectionUnixProcessID");
+
+          goto out;
+        }
+
+    retry_get_property:
+
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_UINT32, &pid,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\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_UINT32 from GetConnectionUnixProcessID\n");
+              goto out;
+            }
+        } else {
+
+         /* test if returned pid is the same as our own pid
+          *
+          * @todo It would probably be good to restructure the tests
+          *       in a way so our parent is the bus that we're testing
+          *       cause then we can test that the pid returned matches
+          *       getppid()
+          */
+         if (pid != (dbus_uint32_t) _dbus_getpid ())
+           {
+              _dbus_assert (dbus_error_is_set (&error));
+              _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\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.
  */
@@ -2787,6 +2940,12 @@ bus_dispatch_test (const DBusString *test_data_dir)
 
   if (!check_add_match_all (context, baz))
     _dbus_assert_not_reached ("AddMatch message failed");
+
+  if (!check_get_connection_unix_user (context, baz))
+    _dbus_assert_not_reached ("GetConnectionUnixUser message failed");
+
+  if (!check_get_connection_unix_process_id (context, baz))
+    _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
   
   if (!check_no_leftovers (context))
     {
index 84e1d6b..a0d433f 100644 (file)
@@ -907,6 +907,83 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
 }
 
 static dbus_bool_t
+bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
+                                                 BusTransaction *transaction,
+                                                 DBusMessage    *message,
+                                                 DBusError      *error)
+{
+  char *service;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *serv;
+  DBusConnection *conn;
+  DBusMessage *reply;
+  unsigned long pid;
+  const char *base_name;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  service = NULL;
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &service,
+                              DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_verbose ("asked for PID 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_process_id (conn, &pid))
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
+                      "Could not determine PID for '%s'", service);
+      goto failed;
+    }
+
+  if (! dbus_message_append_args (reply,
+                                  DBUS_TYPE_UINT32, (dbus_uint32_t) pid,
+                                  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,
@@ -953,6 +1030,7 @@ struct
   { "RemoveMatch", bus_driver_handle_remove_match },
   { "GetServiceOwner", bus_driver_handle_get_service_owner },
   { "GetConnectionUnixUser", bus_driver_handle_get_connection_unix_user },
+  { "GetConnectionUnixProcessID", bus_driver_handle_get_connection_unix_process_id },
   { "ReloadConfig", bus_driver_handle_reload_config }
 };
 
index 83dfc8a..ee3b878 100644 (file)
@@ -1048,9 +1048,9 @@ handle_server_data_external_mech (DBusAuth         *auth,
                      DBUS_AUTH_NAME (auth),
                      auth->desired_identity.uid,
                      auth->credentials.uid);
-      
+
+      auth->authorized_identity.pid = auth->credentials.pid;
       auth->authorized_identity.uid = auth->desired_identity.uid;
-      
       return TRUE;
     }
   else
index d68c395..58ab790 100644 (file)
@@ -2985,6 +2985,37 @@ dbus_connection_get_unix_user (DBusConnection *connection,
 }
 
 /**
+ * Gets the process ID of the connection if any.
+ * Returns #TRUE if the uid is filled in.
+ * Always returns #FALSE prior to authenticating the
+ * connection.
+ *
+ * @param connection the connection
+ * @param pid return location for the process ID
+ * @returns #TRUE if uid is filled in with a valid process ID
+ */
+dbus_bool_t
+dbus_connection_get_unix_process_id (DBusConnection *connection,
+                                    unsigned long  *pid)
+{
+  dbus_bool_t result;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (pid != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_transport_get_is_authenticated (connection->transport))
+    result = FALSE;
+  else
+    result = _dbus_transport_get_unix_process_id (connection->transport,
+                                                 pid);
+  CONNECTION_UNLOCK (connection);
+
+  return result;
+}
+
+/**
  * Sets a predicate function used to determine whether a given user ID
  * is allowed to connect. When an incoming connection has
  * authenticated with a particular user ID, this function is called;
index fb6dfbc..12de0c0 100644 (file)
@@ -138,6 +138,8 @@ void               dbus_connection_set_dispatch_status_function (DBusConnection
                                                                  DBusFreeFunction            free_data_function);
 dbus_bool_t        dbus_connection_get_unix_user                (DBusConnection             *connection,
                                                                  unsigned long              *uid);
+dbus_bool_t        dbus_connection_get_unix_process_id          (DBusConnection             *connection,
+                                                                 unsigned long              *pid);
 void               dbus_connection_set_unix_user_function       (DBusConnection             *connection,
                                                                  DBusAllowUnixUserFunction   function,
                                                                  void                       *data,
index c30339c..00c3ba7 100644 (file)
@@ -154,6 +154,7 @@ extern "C" {
 #define DBUS_ERROR_SPAWN_CHILD_EXITED         "org.freedesktop.DBus.Error.Spawn.ChildExited"
 #define DBUS_ERROR_SPAWN_CHILD_SIGNALED       "org.freedesktop.DBus.Error.Spawn.ChildSignaled"
 #define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
+#define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN    "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
 
 #ifdef __cplusplus
 }
index 371ecbf..ada960d 100644 (file)
@@ -938,6 +938,38 @@ _dbus_transport_get_unix_user (DBusTransport *transport,
 }
 
 /**
+ * See dbus_connection_get_unix_process_id().
+ *
+ * @param transport the transport
+ * @param pid return location for the process ID
+ * @returns #TRUE if uid is filled in with a valid process ID
+ */
+dbus_bool_t
+_dbus_transport_get_unix_process_id (DBusTransport *transport,
+                                    unsigned long *pid)
+{
+  DBusCredentials auth_identity;
+
+  *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
+                         * but we set it to a safe number, INT_MAX,
+                         * just to root out possible bugs in bad callers.
+                         */
+  
+  if (!transport->authenticated)
+    return FALSE;
+  
+  _dbus_auth_get_identity (transport->auth, &auth_identity);
+
+  if (auth_identity.pid != DBUS_PID_UNSET)
+    {
+      *pid = auth_identity.pid;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
  * See dbus_connection_set_unix_user_function().
  *
  * @param transport the transport
index 2c17c2a..b6c7a4e 100644 (file)
@@ -59,6 +59,8 @@ void               _dbus_transport_set_max_received_size  (DBusTransport
 long               _dbus_transport_get_max_received_size  (DBusTransport              *transport);
 dbus_bool_t        _dbus_transport_get_unix_user          (DBusTransport              *transport,
                                                            unsigned long              *uid);
+dbus_bool_t        _dbus_transport_get_unix_process_id     (DBusTransport              *transport,
+                                                           unsigned long              *pid);
 void               _dbus_transport_set_unix_user_function (DBusTransport              *transport,
                                                            DBusAllowUnixUserFunction   function,
                                                            void                       *data,