From f34892135abfe53cbad8dda3ed5dad29e2ebbd2b Mon Sep 17 00:00:00 2001 From: Cosimo Alfarano Date: Mon, 3 Oct 2011 17:00:23 +0100 Subject: [PATCH 1/8] Factor out DBusAuthorization from DBusTransport In order to authorize/reject a connection in a polite way, instead of cutting it off after authentication succeed and Hello() is sent, because authorization failed, we need to factor out some authorization bits from DBusTransport and pass them to DBusAuth. Bug: #39720 --- dbus/Makefile.am | 10 +- dbus/dbus-authorization.c | 364 +++++++++++++++++++++++++++++++++++++++ dbus/dbus-authorization.h | 55 ++++++ dbus/dbus-transport-protected.h | 13 +-- dbus/dbus-transport.c | 308 ++++++++++----------------------- 5 files changed, 516 insertions(+), 234 deletions(-) create mode 100644 dbus/dbus-authorization.c create mode 100644 dbus/dbus-authorization.h diff --git a/dbus/Makefile.am b/dbus/Makefile.am index 3c44ae4..251f086 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -139,6 +139,8 @@ DBUS_LIB_SOURCES= \ dbus-address.c \ dbus-auth.c \ dbus-auth.h \ + dbus-authorization.c \ + dbus-authorization.h \ dbus-auth-script.c \ dbus-auth-script.h \ dbus-bus.c \ @@ -198,8 +200,8 @@ DBUS_LIB_SOURCES= \ DBUS_SHARED_SOURCES= \ dbus-dataslot.c \ dbus-dataslot.h \ - dbus-file.c \ - dbus-file.h \ + dbus-file.c \ + dbus-file.h \ dbus-hash.c \ dbus-hash.h \ dbus-internals.c \ @@ -211,8 +213,8 @@ DBUS_SHARED_SOURCES= \ dbus-memory.c \ dbus-mempool.c \ dbus-mempool.h \ - dbus-pipe.c \ - dbus-pipe.h \ + dbus-pipe.c \ + dbus-pipe.h \ dbus-string.c \ dbus-string.h \ dbus-string-private.h \ diff --git a/dbus/dbus-authorization.c b/dbus/dbus-authorization.c new file mode 100644 index 0000000..3c43989 --- /dev/null +++ b/dbus/dbus-authorization.c @@ -0,0 +1,364 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-transport.c DBusTransport object (internal to D-Bus implementation) + * + * Copyright (C) 2002, 2003 Red Hat Inc. + * Copyright (C) 2011 Nokia corp. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include "dbus-internals.h" +#include "dbus-authorization.h" +#include "dbus-connection.h" +#include "dbus-connection-internal.h" + +struct DBusAuthorization { + int refcount; + + DBusConnection *connection; + + /* User'sauthorization 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. + * This is called after authentication, to check whether the authenticated + * user is authorized. + * + * 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. + * This is called after authentication, to check whether the authenticated + * user is authorized. + * + * 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); + _dbus_assert (self->connection != NULL); + + uid = _dbus_credentials_get_unix_uid (auth_identity); + + _dbus_verbose ("unlock connection before executing user's authorization callback\n"); + _dbus_connection_ref_unlocked (self->connection); + _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); + _dbus_connection_unref_unlocked (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); + _dbus_assert (self->connection != 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_ref_unlocked (self->connection); + _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); + _dbus_connection_unref_unlocked (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 either + * 1) root or + * 2) has the same UID as us (ie the server process) or + * 3) anonymous is allowed (and by default it's not) + */ + + 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 (self->unix_authorization_cb != NULL && + _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) + 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)) + 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..504a9c6 --- /dev/null +++ b/dbus/dbus-authorization.h @@ -0,0 +1,55 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-transport-protected.h Used by subclasses of DBusTransport object (internal to D-Bus implementation) + * + * Copyright (C) 2002, 2004 Red Hat Inc. + * Copyright (C) 2011 Nokia Corporation + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#ifndef _DBUS_AUTHORIZATION_H +#define _DBUS_AUTHORIZATION_H + +#include +#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_AUTHORIZATION_H */ diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 44b9d78..4840c11 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -88,6 +89,7 @@ struct DBusTransport DBusMessageLoader *loader; /**< Message-loading buffer. */ DBusAuth *auth; /**< Authentication conversation */ + DBusAuthorization *authorization; /**< Authorization policy */ DBusCredentials *credentials; /**< Credentials of other end read from the socket */ @@ -100,23 +102,12 @@ struct DBusTransport char *expected_guid; /**< GUID we expect the server to have, #NULL on server side or if we don't have an expectation */ - DBusAllowUnixUserFunction unix_user_function; /**< Function for checking whether a user is authorized. */ - void *unix_user_data; /**< Data for unix_user_function */ - - DBusFreeFunction free_unix_user_data; /**< Function to free unix_user_data */ - - DBusAllowWindowsUserFunction windows_user_function; /**< Function for checking whether a user is authorized. */ - void *windows_user_data; /**< Data for windows_user_function */ - - DBusFreeFunction free_windows_user_data; /**< Function to free windows_user_data */ - unsigned int disconnected : 1; /**< #TRUE if we are disconnected. */ unsigned int authenticated : 1; /**< Cache of auth state; use _dbus_transport_get_is_authenticated() to query value */ unsigned int send_credentials_pending : 1; /**< #TRUE if we need to send credentials */ 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, diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index f743d01..1ef189e 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -28,6 +28,7 @@ #include "dbus-connection-internal.h" #include "dbus-watch.h" #include "dbus-auth.h" +#include "dbus-authorization.h" #include "dbus-address.h" #include "dbus-credentials.h" #include "dbus-mainloop.h" @@ -107,6 +108,7 @@ _dbus_transport_init_base (DBusTransport *transport, { DBusMessageLoader *loader; DBusAuth *auth; + DBusAuthorization *authorization = NULL; /* non-NULL only if is_server=TRUE */ DBusCounter *counter; char *address_copy; DBusCredentials *creds; @@ -114,13 +116,26 @@ _dbus_transport_init_base (DBusTransport *transport, loader = _dbus_message_loader_new (); if (loader == NULL) return FALSE; - - if (server_guid) - auth = _dbus_auth_server_new (server_guid); + + if (server_guid != NULL) + { + authorization = _dbus_authorization_new (); + if (authorization == NULL) + { + _dbus_message_loader_unref (loader); + return FALSE; /* OOM */ + } + + auth = _dbus_auth_server_new (server_guid); + } else - auth = _dbus_auth_client_new (); + { + auth = _dbus_auth_client_new (); + } if (auth == NULL) { + if (authorization != NULL) + _dbus_authorization_unref (authorization); _dbus_message_loader_unref (loader); return FALSE; } @@ -129,6 +144,8 @@ _dbus_transport_init_base (DBusTransport *transport, if (counter == NULL) { _dbus_auth_unref (auth); + if (authorization != NULL) + _dbus_authorization_unref (authorization); _dbus_message_loader_unref (loader); return FALSE; } @@ -138,11 +155,13 @@ _dbus_transport_init_base (DBusTransport *transport, { _dbus_counter_unref (counter); _dbus_auth_unref (auth); + if (authorization != NULL) + _dbus_authorization_unref (authorization); _dbus_message_loader_unref (loader); return FALSE; } - if (server_guid) + if (server_guid != NULL) { _dbus_assert (address == NULL); address_copy = NULL; @@ -156,6 +175,8 @@ _dbus_transport_init_base (DBusTransport *transport, _dbus_credentials_unref (creds); _dbus_counter_unref (counter); _dbus_auth_unref (auth); + if (authorization != NULL) + _dbus_authorization_unref (authorization); _dbus_message_loader_unref (loader); return FALSE; } @@ -164,6 +185,7 @@ _dbus_transport_init_base (DBusTransport *transport, transport->refcount = 1; transport->vtable = vtable; transport->loader = loader; + transport->authorization = authorization; transport->auth = auth; transport->live_messages = counter; transport->authenticated = FALSE; @@ -172,15 +194,7 @@ _dbus_transport_init_base (DBusTransport *transport, transport->send_credentials_pending = !transport->is_server; transport->receive_credentials_pending = transport->is_server; transport->address = address_copy; - - transport->unix_user_function = NULL; - transport->unix_user_data = NULL; - transport->free_unix_user_data = NULL; - transport->windows_user_function = NULL; - transport->windows_user_data = NULL; - transport->free_windows_user_data = NULL; - transport->expected_guid = NULL; /* Try to default to something that won't totally hose the system, @@ -204,6 +218,10 @@ _dbus_transport_init_base (DBusTransport *transport, if (transport->address) _dbus_verbose ("Initialized transport on address %s\n", transport->address); + /* we can have authorization data set only in server mode */ + _dbus_assert ((transport->is_server && transport->authorization != NULL) || + (!transport->is_server && transport->authorization == NULL)); + return TRUE; } @@ -219,14 +237,10 @@ _dbus_transport_finalize_base (DBusTransport *transport) if (!transport->disconnected) _dbus_transport_disconnect (transport); - if (transport->free_unix_user_data != NULL) - (* transport->free_unix_user_data) (transport->unix_user_data); - - if (transport->free_windows_user_data != NULL) - (* transport->free_windows_user_data) (transport->windows_user_data); - _dbus_message_loader_unref (transport->loader); _dbus_auth_unref (transport->auth); + if (transport->authorization) + _dbus_authorization_unref (transport->authorization); _dbus_counter_set_notify (transport->live_messages, 0, 0, NULL, NULL); _dbus_counter_unref (transport->live_messages); @@ -529,164 +543,6 @@ _dbus_transport_get_is_connected (DBusTransport *transport) return !transport->disconnected; } -static dbus_bool_t -auth_via_unix_user_function (DBusTransport *transport) -{ - DBusCredentials *auth_identity; - dbus_bool_t allow; - DBusConnection *connection; - DBusAllowUnixUserFunction unix_user_function; - void *unix_user_data; - dbus_uid_t uid; - - /* Dropping the lock here probably isn't that safe. */ - - auth_identity = _dbus_auth_get_identity (transport->auth); - _dbus_assert (auth_identity != NULL); - - connection = transport->connection; - unix_user_function = transport->unix_user_function; - unix_user_data = transport->unix_user_data; - uid = _dbus_credentials_get_unix_uid (auth_identity); - - _dbus_verbose ("unlock\n"); - _dbus_connection_unlock (connection); - - allow = (* unix_user_function) (connection, - uid, - unix_user_data); - - _dbus_verbose ("lock post unix user function\n"); - _dbus_connection_lock (connection); - - if (allow) - { - _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); - } - else - { - _dbus_verbose ("Client UID "DBUS_UID_FORMAT - " was rejected, disconnecting\n", - _dbus_credentials_get_unix_uid (auth_identity)); - _dbus_transport_disconnect (transport); - } - - return allow; -} - -static dbus_bool_t -auth_via_windows_user_function (DBusTransport *transport) -{ - DBusCredentials *auth_identity; - dbus_bool_t allow; - DBusConnection *connection; - DBusAllowWindowsUserFunction windows_user_function; - void *windows_user_data; - char *windows_sid; - - /* Dropping the lock here probably isn't that safe. */ - - auth_identity = _dbus_auth_get_identity (transport->auth); - _dbus_assert (auth_identity != NULL); - - connection = transport->connection; - windows_user_function = transport->windows_user_function; - windows_user_data = transport->unix_user_data; - windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); - - if (windows_sid == NULL) - { - /* OOM */ - return FALSE; - } - - _dbus_verbose ("unlock\n"); - _dbus_connection_unlock (connection); - - allow = (* windows_user_function) (connection, - windows_sid, - windows_user_data); - - _dbus_verbose ("lock post windows user function\n"); - _dbus_connection_lock (connection); - - if (allow) - { - _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); - } - else - { - _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", - _dbus_credentials_get_windows_sid (auth_identity)); - _dbus_transport_disconnect (transport); - } - - return allow; -} - -static dbus_bool_t -auth_via_default_rules (DBusTransport *transport) -{ - DBusCredentials *auth_identity; - DBusCredentials *our_identity; - dbus_bool_t allow; - - 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 or 3) anonymous is allowed. - */ - - our_identity = _dbus_credentials_new_from_current_process (); - if (our_identity == NULL) - { - /* OOM */ - return FALSE; - } - - if (transport->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 authorized as SID '%s'" - "matching our SID '%s'\n", - _dbus_credentials_get_windows_sid(auth_identity), - _dbus_credentials_get_windows_sid(our_identity)); - else - _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT - " matching our UID "DBUS_UID_FORMAT"\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 authorized as SID '%s'" - " but our SID is '%s', disconnecting\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 authorized as UID "DBUS_UID_FORMAT - " but our UID is "DBUS_UID_FORMAT", disconnecting\n", - _dbus_credentials_get_unix_uid(auth_identity), - _dbus_credentials_get_unix_uid(our_identity)); - _dbus_transport_disconnect (transport); - allow = FALSE; - } - - _dbus_credentials_unref (our_identity); - - return allow; -} - - /** * Returns #TRUE if we have been authenticated. Will return #TRUE * even if the transport is disconnected. @@ -752,33 +608,18 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) */ if (maybe_authenticated && transport->is_server) { - dbus_bool_t allow; DBusCredentials *auth_identity; - + auth_identity = _dbus_auth_get_identity (transport->auth); _dbus_assert (auth_identity != NULL); - /* If we have an auth'd user and a user function, delegate - * deciding whether auth credentials are good enough to the - * app; otherwise, use our default decision process. - */ - if (transport->unix_user_function != NULL && - _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) + /* If we have an authenticated user, delegate deciding whether auth + * credentials are good enough to the app */ + if (!_dbus_authorization_do_authorization (transport->authorization, auth_identity)) { - allow = auth_via_unix_user_function (transport); - } - else if (transport->windows_user_function != NULL && - _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) - { - allow = auth_via_windows_user_function (transport); - } - else - { - allow = auth_via_default_rules (transport); + _dbus_transport_disconnect (transport); + maybe_authenticated = FALSE; } - - if (!allow) - maybe_authenticated = FALSE; } transport->authenticated = maybe_authenticated; @@ -908,6 +749,8 @@ _dbus_transport_set_connection (DBusTransport *transport, _dbus_assert (transport->connection == NULL); transport->connection = connection; + if (transport->is_server) + _dbus_authorization_set_connection (transport->authorization, connection); _dbus_transport_ref (transport); if (!(* transport->vtable->connection_set) (transport)) @@ -1390,20 +1233,33 @@ _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, * @param old_data the old user data to be freed * @param old_free_data_function old free data function to free it with */ -void +inline void _dbus_transport_set_unix_user_function (DBusTransport *transport, DBusAllowUnixUserFunction function, void *data, DBusFreeFunction free_data_function, void **old_data, DBusFreeFunction *old_free_data_function) -{ - *old_data = transport->unix_user_data; - *old_free_data_function = transport->free_unix_user_data; - - transport->unix_user_function = function; - transport->unix_user_data = data; - transport->free_unix_user_data = free_data_function; +{ + if (transport->is_server) + { + _dbus_authorization_set_unix_authorization_callback (transport->authorization, + function, + data, + free_data_function, + old_data, + old_free_data_function); + } + else + { + /* We are not a server, thus we don't use user authorization callbacks. + * It's probably a common client&server call, trying to unset data if + * something is there (it's OK). + * We don't have any data already set, but just to be sure, we return + * the just passed one to be freed, or NULL if nothing's been passed */ + *old_data = data; + *old_free_data_function = free_data_function; + } } /** @@ -1450,19 +1306,32 @@ _dbus_transport_get_windows_user (DBusTransport *transport, */ void -_dbus_transport_set_windows_user_function (DBusTransport *transport, +_dbus_transport_set_windows_user_function (DBusTransport *transport, DBusAllowWindowsUserFunction function, - void *data, - DBusFreeFunction free_data_function, - void **old_data, - DBusFreeFunction *old_free_data_function) + void *data, + DBusFreeFunction free_data_function, + void **old_data, + DBusFreeFunction *old_free_data_function) { - *old_data = transport->windows_user_data; - *old_free_data_function = transport->free_windows_user_data; - - transport->windows_user_function = function; - transport->windows_user_data = data; - transport->free_windows_user_data = free_data_function; + if (transport->is_server) + { + _dbus_authorization_set_windows_authorization_callback (transport->authorization, + function, + data, + free_data_function, + old_data, + old_free_data_function); + } + else + { + /* We are not a server, thus we don't use user authorization callbacks. + * It's probably a common client&server call, trying to unset data if + * something is there (it's OK). + * We don't have any data already set, but just to be sure, we return + * the just passed one to be freed, or NULL if nothing's been passed */ + *old_data = data; + *old_free_data_function = free_data_function; + } } /** @@ -1486,11 +1355,12 @@ _dbus_transport_set_auth_mechanisms (DBusTransport *transport, * @param transport the transport * @param value #TRUE to allow anonymous connection */ -void +inline void _dbus_transport_set_allow_anonymous (DBusTransport *transport, dbus_bool_t value) { - transport->allow_anonymous = value != FALSE; + if (transport->is_server) + _dbus_authorization_set_allow_anonymous (transport->authorization, value); } #ifdef DBUS_ENABLE_STATS -- 1.7.6.3