From 78c447173dfba167ac8082652c02e453e4b519ce Mon Sep 17 00:00:00 2001 From: Ralf Habacker Date: Fri, 23 Aug 2013 01:36:31 +0200 Subject: [PATCH] Add new files really. --- dbus/dbus-authorization.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-authorization.h | 25 ++++ 2 files changed, 369 insertions(+) create mode 100644 dbus/dbus-authorization.c create mode 100644 dbus/dbus-authorization.h diff --git a/dbus/dbus-authorization.c b/dbus/dbus-authorization.c new file mode 100644 index 0000000..05a3aa8 --- /dev/null +++ b/dbus/dbus-authorization.c @@ -0,0 +1,344 @@ +#include +#include "dbus-internals.h" +#include "dbus-authorization.h" +#include "dbus-connection.h" +#include "dbus-connection-internal.h" + +struct DBusAuthorization { + int refcount; + + DBusConnection *connection; + + /* Authorization functions, used as callback by SASL (implemented by + * DBUsAuth) */ + DBusAllowUnixUserFunction unix_authorization_cb; + void *unix_data; + DBusFreeFunction unix_data_free; + + DBusAllowWindowsUserFunction windows_authorization_cb; + void *windows_data; + DBusFreeFunction windows_data_free; + + dbus_bool_t allow_anonymous; +}; + + +DBusAuthorization * +_dbus_authorization_new (void) +{ + DBusAuthorization *ret; + + ret = dbus_malloc0 (sizeof (DBusAuthorization)); + if (ret == NULL) + { + _dbus_verbose ("OOM\n"); + return NULL; /* OOM */ + } + + ret->refcount = 1; + + return ret; +} + +DBusAuthorization * +_dbus_authorization_ref (DBusAuthorization *self) +{ + _dbus_assert (self != NULL); + + self->refcount += 1; + + return self; +} + +void +_dbus_authorization_unref (DBusAuthorization *self) +{ + _dbus_assert (self != NULL); + _dbus_assert (self->refcount > 0); + + self->refcount -= 1; + + if (self->refcount == 0) + { + _dbus_verbose ("last reference, finalizing\n"); + + if (self->unix_data && self->unix_data_free) + { + _dbus_verbose ("freeing unix authorization callback data\n"); + (*self->unix_data_free) (self->unix_data); + self->unix_data = NULL; + } + + if (self->windows_data && self->windows_data_free) + { + _dbus_verbose ("freeing windows authorization callback data\n"); + (*self->windows_data_free) (self->windows_data); + self->windows_data = NULL; + } + + dbus_free (self); + } +} + +/* Called by transport's set_connection with the connection locked */ +void +_dbus_authorization_set_connection (DBusAuthorization *self, + DBusConnection *connection) +{ + _dbus_assert (connection != NULL); + _dbus_assert (self->connection == NULL); + + self->connection = connection; +} + + +/** + * Set the user set authorization callback for Unix identities authorizations. + * The callback will be called at the end of the EXTERNAL authentication + * mechanism and on every message. + + * See dbus_connection_set_unix_authorization_callback() and + * _dbus_transport_set_unix_authorization_callback(). + * + * @param self the authorization struct + * @param function the predicate + * @param data data to pass to the predicate + * @param free_data_function function to free the data + * @param old_data the old user data to be freed + * @param old_free_data_function old free data function to free it with + */ +void +_dbus_authorization_set_unix_authorization_callback (DBusAuthorization *self, + DBusAllowUnixUserFunction function, + void *data, + DBusFreeFunction free_data_function, + void **old_data, + DBusFreeFunction *old_free_data_function) +{ + *old_data = self->unix_data; + *old_free_data_function = self->unix_data_free; + + self->unix_authorization_cb = function; + self->unix_data = data; + self->unix_data_free = free_data_function; +} + +/** + * Set the user set authorization callback for Windows identities + * authorizations. + * The callback will be called at the end of the EXTERNAL authentication + * mechanism and on every message. + * + * See dbus_connection_set_windows_authorization_callback() and + * _dbus_transport_set_windows_authorization_callback(). + * + * @param self the authorization struct + * @param function the predicate + * @param data data to pass to the predicate + * @param free_data_function function to free the data + * @param old_data the old user data to be freed + * @param old_free_data_function old free data function to free it with + */ + +void +_dbus_authorization_set_windows_authorization_callback (DBusAuthorization *self, + DBusAllowWindowsUserFunction function, + void *data, + DBusFreeFunction free_data_function, + void **old_data, + DBusFreeFunction *old_free_data_function) +{ + *old_data = self->windows_data; + *old_free_data_function = self->windows_data_free; + + self->windows_authorization_cb = function; + self->windows_data = data; + self->windows_data_free = free_data_function; +} + +static dbus_bool_t +auth_via_unix_authorization_callback (DBusAuthorization *self, + DBusCredentials *auth_identity) +{ + + dbus_bool_t allow; + dbus_uid_t uid; + + /* Dropping the lock here probably isn't that safe. */ + + _dbus_assert (auth_identity != NULL); + + uid = _dbus_credentials_get_unix_uid (auth_identity); + + _dbus_verbose ("unlock connection before executing user's authorization callback\n"); + _dbus_connection_unlock (self->connection); + + allow = (*self->unix_authorization_cb) (self->connection, + uid, + self->unix_data); + + _dbus_verbose ("lock connection post unix-authorization callback\n"); + _dbus_connection_lock (self->connection); + + if (allow) + { + _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); + } + else + { + _dbus_verbose ("Client UID "DBUS_UID_FORMAT " wasn't authorized.\n", + _dbus_credentials_get_unix_uid (auth_identity)); + } + + return allow; +} + + +static dbus_bool_t +auth_via_windows_authorization_callback (DBusAuthorization *self, + DBusCredentials *auth_identity) +{ + dbus_bool_t allow; + char *windows_sid; + + /* Dropping the lock here probably isn't that safe. */ + + _dbus_assert (auth_identity != NULL); + + windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); + + if (windows_sid == NULL) + return FALSE; /* OOM */ + + _dbus_verbose ("unlock connection before executing user's authorization callback\n"); + _dbus_connection_unlock (self->connection); + + allow = (*self->windows_authorization_cb) (self->connection, + windows_sid, + self->windows_data); + + _dbus_verbose ("lock connection post windows user's authorization callback\n"); + _dbus_connection_lock (self->connection); + + if (allow) + { + _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); + } + else + { + _dbus_verbose ("Client SID '%s' wasn't authorized\n", + _dbus_credentials_get_windows_sid (auth_identity)); + } + + dbus_free (windows_sid); + + return allow; +} + +static dbus_bool_t +auth_via_default_rules (DBusAuthorization *self, + DBusCredentials *auth_identity) + +{ + DBusCredentials *our_identity; + dbus_bool_t allow; + + _dbus_assert (auth_identity != NULL); + + /* 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) + return FALSE; /* OOM */ + + if (self->allow_anonymous || + _dbus_credentials_get_unix_uid (auth_identity) == 0 || + _dbus_credentials_same_user (our_identity, auth_identity)) + { + if (_dbus_credentials_include (our_identity, DBUS_CREDENTIAL_WINDOWS_SID)) + _dbus_verbose ("Client authenticated as SID '%s'" + "matching our SID '%s': authorized\n", + _dbus_credentials_get_windows_sid (auth_identity), + _dbus_credentials_get_windows_sid (our_identity)); + else + _dbus_verbose ("Client authenticated as UID "DBUS_UID_FORMAT + " matching our UID "DBUS_UID_FORMAT": authorized\n", + _dbus_credentials_get_unix_uid (auth_identity), + _dbus_credentials_get_unix_uid (our_identity)); + /* We have authenticated! */ + allow = TRUE; + } + else + { + if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) + _dbus_verbose ("Client authenticated as SID '%s'" + " but our SID is '%s', not authorizing\n", + (_dbus_credentials_get_windows_sid(auth_identity) ? + _dbus_credentials_get_windows_sid(auth_identity) : ""), + (_dbus_credentials_get_windows_sid(our_identity) ? + _dbus_credentials_get_windows_sid(our_identity) : "")); + else + _dbus_verbose ("Client authenticated as UID "DBUS_UID_FORMAT + " but our UID is "DBUS_UID_FORMAT", not authorizing\n", + _dbus_credentials_get_unix_uid(auth_identity), + _dbus_credentials_get_unix_uid(our_identity)); + allow = FALSE; + } + + _dbus_credentials_unref (our_identity); + + return allow; +} + +/* Called with DBusConnection lock held */ +dbus_bool_t +_dbus_authorization_do_authorization (DBusAuthorization *self, + DBusCredentials *auth_identity) +{ + dbus_bool_t allow; + + /* maybe-FIXME: at this point we *should* have a connection set unless we + * are in some test case, but we assert its presence only in some if's + * branches since default_rules does not need one and is used in a test case + * without a connection set */ + + if (_dbus_credentials_are_anonymous (auth_identity)) + { + allow = self->allow_anonymous; + } + if (self->unix_authorization_cb != NULL && + _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) + { + _dbus_assert (self->connection != NULL); + allow = auth_via_unix_authorization_callback (self, auth_identity); + } + else if (self->windows_authorization_cb != NULL && + _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) + { + _dbus_assert (self->connection != NULL); + allow = auth_via_windows_authorization_callback (self, auth_identity); + } + else + { + allow = auth_via_default_rules (self, auth_identity); + } + + return allow; +} + + + +/** + * See dbus_connection_set_allow_anonymous() + * + * @param self an authorization struct + * @param value #TRUE to allow anonymous connection + */ +void +_dbus_authorization_set_allow_anonymous (DBusAuthorization *self, + dbus_bool_t value) +{ + self->allow_anonymous = value != FALSE; +} diff --git a/dbus/dbus-authorization.h b/dbus/dbus-authorization.h new file mode 100644 index 0000000..8f7f1d4 --- /dev/null +++ b/dbus/dbus-authorization.h @@ -0,0 +1,25 @@ +#ifndef _DBUS_AUTHORIZE_H +#define _DBUS_AUTHORIZE_H + +#include +#include + +typedef struct DBusAuthorization DBusAuthorization; + +DBusAuthorization *_dbus_authorization_new (void); +void _dbus_authorization_set_connection (DBusAuthorization *self, + DBusConnection *connection); +DBusAuthorization * _dbus_authorization_ref (DBusAuthorization *self); +void _dbus_authorization_unref (DBusAuthorization *self); +void _dbus_authorization_set_unix_authorization_callback (DBusAuthorization *self, + DBusAllowUnixUserFunction function, void *data, + DBusFreeFunction free_data_function, void **old_data, + DBusFreeFunction *old_free_data_function); +void _dbus_authorization_set_windows_authorization_callback (DBusAuthorization *self, + DBusAllowWindowsUserFunction function, void *data, + DBusFreeFunction free_data_function, void **old_data, + DBusFreeFunction *old_free_data_function); +dbus_bool_t _dbus_authorization_do_authorization (DBusAuthorization *self, DBusCredentials *creds); +void _dbus_authorization_set_allow_anonymous (DBusAuthorization *self, dbus_bool_t value); + +#endif /* _DBUS_AUTHORIZE_H */ -- 2.7.4