2007-06-12 Havoc Pennington <hp@redhat.com>

* dbus/dbus-auth.c (sha1_handle_second_client_response)
	(handle_server_data_anonymous_mech): add the process ID from
	socket credentials, if available, even if not using EXTERNAL

	* dbus/dbus-transport.c (auth_via_default_rules): support
	allow_anonymous flag

	* dbus/dbus-connection.c (dbus_connection_get_is_anonymous)
	(dbus_connection_set_allow_anonymous): new API for controlling
	anonymous access
This commit is contained in:
Havoc Pennington 2007-06-12 18:36:19 +00:00
parent a789b7b38c
commit 94125e89b6
10 changed files with 153 additions and 13 deletions

View file

@ -665,7 +665,7 @@ _dbus_auth_script_run (const DBusString *filename)
DBusCredentials *authorized_identity;
authorized_identity = _dbus_auth_get_identity (auth);
if (!_dbus_credentials_are_empty (authorized_identity))
if (!_dbus_credentials_are_anonymous (authorized_identity))
{
_dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
goto out;
@ -677,7 +677,7 @@ _dbus_auth_script_run (const DBusString *filename)
DBusCredentials *authorized_identity;
authorized_identity = _dbus_auth_get_identity (auth);
if (_dbus_credentials_are_empty (authorized_identity))
if (_dbus_credentials_are_anonymous (authorized_identity))
{
_dbus_warn ("Expected to have some credentials, but we don't\n");
goto out;

View file

@ -731,6 +731,13 @@ sha1_handle_second_client_response (DBusAuth *auth,
if (!_dbus_credentials_add_credentials (auth->authorized_identity,
auth->desired_identity))
goto out_3;
/* Copy process ID from the socket credentials if it's there
*/
if (!_dbus_credentials_add_credential (auth->authorized_identity,
DBUS_CREDENTIAL_UNIX_PROCESS_ID,
auth->credentials))
goto out_3;
if (!send_ok (auth))
goto out_3;
@ -994,7 +1001,7 @@ static dbus_bool_t
handle_server_data_external_mech (DBusAuth *auth,
const DBusString *data)
{
if (_dbus_credentials_are_empty (auth->credentials))
if (_dbus_credentials_are_anonymous (auth->credentials))
{
_dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
DBUS_AUTH_NAME (auth));
@ -1059,7 +1066,7 @@ handle_server_data_external_mech (DBusAuth *auth,
}
}
if (_dbus_credentials_are_empty (auth->desired_identity))
if (_dbus_credentials_are_anonymous (auth->desired_identity))
{
_dbus_verbose ("%s: desired user %s is no good\n",
DBUS_AUTH_NAME (auth),
@ -1075,8 +1082,7 @@ handle_server_data_external_mech (DBusAuth *auth,
auth->desired_identity))
return FALSE;
/* also copy process ID from the socket credentials - FIXME this
* should be done even if auth EXTERNAL not used
/* also copy process ID from the socket credentials
*/
if (!_dbus_credentials_add_credential (auth->authorized_identity,
DBUS_CREDENTIAL_UNIX_PROCESS_ID,
@ -1192,6 +1198,13 @@ handle_server_data_anonymous_mech (DBusAuth *auth,
/* We want to be anonymous (clear in case some other protocol got midway through I guess) */
_dbus_credentials_clear (auth->desired_identity);
/* Copy process ID from the socket credentials
*/
if (!_dbus_credentials_add_credential (auth->authorized_identity,
DBUS_CREDENTIAL_UNIX_PROCESS_ID,
auth->credentials))
return FALSE;
/* Anonymous is always allowed */
if (!send_ok (auth))
return FALSE;

View file

@ -2810,6 +2810,40 @@ dbus_connection_get_is_authenticated (DBusConnection *connection)
return res;
}
/**
* Gets whether the connection is not authenticated as a specific
* user. If the connection is not authenticated, this function
* returns #TRUE, and if it is authenticated but as an anonymous user,
* it returns #TRUE. If it is authenticated as a specific user, then
* this returns #FALSE. (Note that if the connection was authenticated
* as anonymous then disconnected, this function still returns #TRUE.)
*
* If the connection is not anonymous, you can use
* dbus_connection_get_unix_user() and
* dbus_connection_get_windows_user() to see who it's authorized as.
*
* If you want to prevent non-anonymous authorization, use
* dbus_server_set_auth_mechanisms() to remove the mechanisms that
* allow proving user identity (i.e. only allow the ANONYMOUS
* mechanism).
*
* @param connection the connection
* @returns #TRUE if not authenticated or authenticated as anonymous
*/
dbus_bool_t
dbus_connection_get_is_anonymous (DBusConnection *connection)
{
dbus_bool_t res;
_dbus_return_val_if_fail (connection != NULL, FALSE);
CONNECTION_LOCK (connection);
res = _dbus_transport_get_is_anonymous (connection->transport);
CONNECTION_UNLOCK (connection);
return res;
}
/**
* Set whether _exit() should be called when the connection receives a
* disconnect signal. The call to _exit() comes after any handlers for
@ -4986,6 +5020,43 @@ dbus_connection_set_windows_user_function (DBusConnection *connecti
(* old_free_function) (old_data);
}
/**
* This function must be called on the server side of a connection when the
* connection is first seen in the #DBusNewConnectionFunction. If set to
* #TRUE (the default is #FALSE), then the connection can proceed even if
* the client does not authenticate as some user identity, i.e. clients
* can connect anonymously.
*
* This setting interacts with the available authorization mechanisms
* (see dbus_server_set_auth_mechanisms()). Namely, an auth mechanism
* such as ANONYMOUS that supports anonymous auth must be included in
* the list of available mechanisms for anonymous login to work.
*
* This setting also changes the default rule for connections
* authorized as a user; normally, if a connection authorizes as
* a user identity, it is permitted if the user identity is
* root or the user identity matches the user identity of the server
* process. If anonymous connections are allowed, however,
* then any user identity is allowed.
*
* You can override the rules for connections authorized as a
* user identity with dbus_connection_set_unix_user_function()
* and dbus_connection_set_windows_user_function().
*
* @param connection the connection
* @param value whether to allow authentication as an anonymous user
*/
void
dbus_connection_set_allow_anonymous (DBusConnection *connection,
dbus_bool_t value)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_allow_anonymous (connection->transport, value);
CONNECTION_UNLOCK (connection);
}
/**
*
* Normally #DBusConnection automatically handles all messages to the
@ -4997,7 +5068,6 @@ dbus_connection_set_windows_user_function (DBusConnection *connecti
* handled by the #DBusConnection and instead will be dispatched
* normally to the application.
*
*
* If a normal application sets this flag, it can break things badly.
* So don't set this unless you are the message bus.
*

View file

@ -178,6 +178,7 @@ void dbus_connection_unref (DBusConnection
void dbus_connection_close (DBusConnection *connection);
dbus_bool_t dbus_connection_get_is_connected (DBusConnection *connection);
dbus_bool_t dbus_connection_get_is_authenticated (DBusConnection *connection);
dbus_bool_t dbus_connection_get_is_anonymous (DBusConnection *connection);
void dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
dbus_bool_t exit_on_disconnect);
void dbus_connection_flush (DBusConnection *connection);
@ -239,6 +240,8 @@ void dbus_connection_set_windows_user_function (DBusConnection
DBusAllowWindowsUserFunction function,
void *data,
DBusFreeFunction free_data_function);
void dbus_connection_set_allow_anonymous (DBusConnection *connection,
dbus_bool_t value);
void dbus_connection_set_route_peer_messages (DBusConnection *connection,
dbus_bool_t value);

View file

@ -104,6 +104,7 @@ _dbus_credentials_test (const char *test_data_dir)
_dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds), SAMPLE_SID) == 0);
_dbus_assert (!_dbus_credentials_are_empty (creds));
_dbus_assert (!_dbus_credentials_are_anonymous (creds));
/* Test copy */
creds2 = _dbus_credentials_copy (creds);
@ -193,6 +194,7 @@ _dbus_credentials_test (const char *test_data_dir)
_dbus_assert (_dbus_credentials_get_windows_sid (creds) == NULL);
_dbus_assert (_dbus_credentials_are_empty (creds));
_dbus_assert (_dbus_credentials_are_anonymous (creds));
_dbus_credentials_unref (creds);

View file

@ -288,6 +288,20 @@ _dbus_credentials_are_empty (DBusCredentials *credentials)
credentials->windows_sid == NULL;
}
/**
* Checks whether a credentials object contains a user identity.
*
* @param credentials the object
* @returns #TRUE if there are no user identities in the object
*/
dbus_bool_t
_dbus_credentials_are_anonymous (DBusCredentials *credentials)
{
return
credentials->unix_uid == DBUS_UID_UNSET &&
credentials->windows_sid == NULL;
}
/**
* Merge all credentials found in the second object into the first object,
* overwriting the first object if there are any overlaps.

View file

@ -54,6 +54,7 @@ const char* _dbus_credentials_get_windows_sid (DBusCredentials
dbus_bool_t _dbus_credentials_are_superset (DBusCredentials *credentials,
DBusCredentials *possible_subset);
dbus_bool_t _dbus_credentials_are_empty (DBusCredentials *credentials);
dbus_bool_t _dbus_credentials_are_anonymous (DBusCredentials *credentials);
dbus_bool_t _dbus_credentials_add_credentials (DBusCredentials *credentials,
DBusCredentials *other_credentials);
/* must silently allow 'which' to not exist */

View file

@ -116,6 +116,7 @@ struct DBusTransport
unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */
unsigned int is_server : 1; /**< #TRUE if on the server side */
unsigned int unused_bytes_recovered : 1; /**< #TRUE if we've recovered unused bytes from auth */
unsigned int allow_anonymous : 1; /**< #TRUE if an anonymous client can connect */
};
dbus_bool_t _dbus_transport_init_base (DBusTransport *transport,

View file

@ -603,10 +603,10 @@ auth_via_default_rules (DBusTransport *transport)
auth_identity = _dbus_auth_get_identity (transport->auth);
_dbus_assert (auth_identity != NULL);
/* By default, connection is allowed if the client is
* 1) root or 2) has the same UID as us
/* By default, connection is allowed if the client is 1) root or 2)
* has the same UID as us or 3) anonymous is allowed.
*/
our_identity = _dbus_credentials_new_from_current_process ();
if (our_identity == NULL)
{
@ -614,7 +614,8 @@ auth_via_default_rules (DBusTransport *transport)
return FALSE;
}
if (_dbus_credentials_get_unix_uid (auth_identity) == 0 ||
if (transport->allow_anonymous ||
_dbus_credentials_get_unix_uid (auth_identity) == 0 ||
_dbus_credentials_same_user (our_identity,
auth_identity))
{
@ -755,6 +756,28 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
}
}
/**
* See dbus_connection_get_is_anonymous().
*
* @param transport the transport
* @returns #TRUE if not authenticated or authenticated as anonymous
*/
dbus_bool_t
_dbus_transport_get_is_anonymous (DBusTransport *transport)
{
DBusCredentials *auth_identity;
if (!transport->authenticated)
return TRUE;
auth_identity = _dbus_auth_get_identity (transport->auth);
if (_dbus_credentials_are_anonymous (auth_identity))
return TRUE;
else
return FALSE;
}
/**
* Gets the address of a transport. It will be
* #NULL for a server-side transport.
@ -1298,5 +1321,17 @@ _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
}
/**
* See dbus_connection_set_allow_anonymous()
*
* @param transport the transport
* @param value #TRUE to allow anonymous connection
*/
void
_dbus_transport_set_allow_anonymous (DBusTransport *transport,
dbus_bool_t value)
{
transport->allow_anonymous = value != FALSE;
}
/** @} */

View file

@ -39,6 +39,7 @@ void _dbus_transport_unref (DBusTransport
void _dbus_transport_disconnect (DBusTransport *transport);
dbus_bool_t _dbus_transport_get_is_connected (DBusTransport *transport);
dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport);
dbus_bool_t _dbus_transport_get_is_anonymous (DBusTransport *transport);
const char* _dbus_transport_get_address (DBusTransport *transport);
dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport,
DBusWatch *watch,
@ -78,8 +79,8 @@ void _dbus_transport_set_windows_user_function (DBusTransport
DBusFreeFunction *old_free_data_function);
dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
const char **mechanisms);
void _dbus_transport_set_allow_anonymous (DBusTransport *transport,
dbus_bool_t value);
DBUS_END_DECLS