From c9c0adce43caa00345ad2aeb55822eabde523c2c Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 19 Jul 2004 20:55:58 +0000 Subject: 2004-07-19 David Zeuthen * 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 | 32 ++++++++++ bus/dispatch.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++- bus/driver.c | 78 +++++++++++++++++++++++ dbus/dbus-auth.c | 4 +- dbus/dbus-connection.c | 31 ++++++++++ dbus/dbus-connection.h | 2 + dbus/dbus-protocol.h | 1 + dbus/dbus-transport.c | 32 ++++++++++ dbus/dbus-transport.h | 2 + 9 files changed, 341 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 789a5364..664bc89f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2004-07-19 David Zeuthen + + * 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 * dbus/dbus-message.c: Message counter fix, patch by Christian diff --git a/bus/dispatch.c b/bus/dispatch.c index f38a9904..9bc89a7c 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -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)) { diff --git a/bus/driver.c b/bus/driver.c index 84e1d6b6..a0d433f0 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -906,6 +906,83 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection, return FALSE; } +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, @@ -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 } }; diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index 83dfc8a7..ee3b878d 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -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 diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index d68c3958..58ab7900 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2984,6 +2984,37 @@ dbus_connection_get_unix_user (DBusConnection *connection, return result; } +/** + * 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 diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index fb6dfbcd..12de0c05 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -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, diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index c30339c9..00c3ba7d 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -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 } diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 371ecbfb..ada960d4 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -937,6 +937,38 @@ _dbus_transport_get_unix_user (DBusTransport *transport, return FALSE; } +/** + * 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(). * diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 2c17c2a1..b6c7a4ec 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -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, -- cgit v1.2.1