From 1e6b28eb960ac181b2c2cf5693b0877fac06d9e7 Mon Sep 17 00:00:00 2001
From: Cosimo Alfarano <cosimo.alfarano@collabora.com>
Date: Mon, 3 Oct 2011 17:16:17 +0100
Subject: [PATCH 2/8] Actually use DBusAuthorization in DBusAuth EXTERNAL mech

Also update the authentication script so that DBusAuthorization default
rules are used during testing
---
 dbus/dbus-auth-script.c |   13 +++++++++-
 dbus/dbus-auth.c        |   59 ++++++++++++++++++++++++++++++++++++++--------
 dbus/dbus-auth.h        |    4 ++-
 dbus/dbus-connection.c  |    2 +-
 dbus/dbus-transport.c   |    9 ++++---
 5 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c
index 6285e3b..06df299 100644
--- a/dbus/dbus-auth-script.c
+++ b/dbus/dbus-auth-script.c
@@ -30,6 +30,7 @@
 #include "dbus-hash.h"
 #include "dbus-credentials.h"
 #include "dbus-internals.h"
+#include "dbus-authorization.h"
 
 /**
  * @defgroup DBusAuthScript code for running unit test scripts for DBusAuth
@@ -401,6 +402,7 @@ _dbus_auth_script_run (const DBusString *filename)
                                                "SERVER"))
         {
           DBusCredentials *creds;
+          DBusAuthorization *authorization;
           
           if (auth != NULL)
             {
@@ -408,7 +410,16 @@ _dbus_auth_script_run (const DBusString *filename)
               goto out;
             }
 
-          auth = _dbus_auth_server_new (&guid);
+          /* empty authorization, it will use default rules */
+          authorization = _dbus_authorization_new ();
+          if (authorization == NULL)
+            {
+              _dbus_warn ("no memory to create DBusAuthorization\n");
+              goto out;
+            }
+          auth = _dbus_auth_server_new (&guid, authorization);
+          /* DBusAuth owns it, or finalized on OOM */
+          _dbus_authorization_unref (authorization);
           if (auth == NULL)
             {
               _dbus_warn ("no memory to create DBusAuth\n");
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index d2c37a7..74ec91a 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -30,6 +30,7 @@
 #include "dbus-sha.h"
 #include "dbus-protocol.h"
 #include "dbus-credentials.h"
+#include "dbus-authorization.h"
 
 /**
  * @defgroup DBusAuth Authentication
@@ -213,6 +214,8 @@ typedef struct
 {
   DBusAuth base;    /**< Parent class */
 
+  DBusAuthorization *authorization;             /* DBus Authorization callbacks */
+
   int failures;     /**< Number of times client has been rejected */
   int max_failures; /**< Number of times we reject before disconnect */
 
@@ -752,6 +755,16 @@ sha1_handle_second_client_response (DBusAuth         *auth,
                                          DBUS_CREDENTIAL_UNIX_PROCESS_ID,
                                          auth->credentials))
     goto out_3;
+
+  /* Do a authorization of the transport, in order to REJECT immediately the
+   * connection if needed (FDO#39720) */
+  if (!_dbus_authorization_do_authorization (DBUS_AUTH_SERVER (auth)->authorization,
+                                             auth->authenticated_identity))
+    {
+      if (send_rejected (auth))
+        retval = TRUE;
+      goto out_3;
+    }
   
   if (!send_ok (auth))
     goto out_3;
@@ -1115,12 +1128,24 @@ handle_server_data_external_mech (DBusAuth         *auth,
                                              DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
                                              auth->credentials))
         return FALSE;
-      
-      if (!send_ok (auth))
-        return FALSE;
 
-      _dbus_verbose ("%s: authenticated client based on socket credentials\n",
-                     DBUS_AUTH_NAME (auth));
+      /* Do a authorization of the transport, in order to REJECT immediately
+       * the connection if needed (FDO#39720) */
+      if (_dbus_authorization_do_authorization (DBUS_AUTH_SERVER (auth)->authorization,
+            auth->authorized_identity))
+        {
+          if (!send_ok (auth))
+            return FALSE;
+        }
+      else
+        {
+          _dbus_verbose ("%s: desired identity does not match server identity: "
+                         "not authorized\n", DBUS_AUTH_NAME (auth));
+          return send_rejected (auth);
+        }
+
+      _dbus_verbose ("%s: authenticated and authorized client based on "
+                     "socket credentials\n", DBUS_AUTH_NAME (auth));
 
       return TRUE;
     }
@@ -1219,10 +1244,19 @@ handle_server_data_anonymous_mech (DBusAuth         *auth,
                                          DBUS_CREDENTIAL_UNIX_PROCESS_ID,
                                          auth->credentials))
     return FALSE;
-  
-  /* Anonymous is always allowed */
-  if (!send_ok (auth))
-    return FALSE;
+ 
+  /* Do a authorization of the transport, in order to REJECT immediately the
+   * connection if needed (FDO#39720) */
+  if (!_dbus_authorization_do_authorization (DBUS_AUTH_SERVER (auth)->authorization,
+                                             auth->authenticated_identity))
+    {
+      if (!send_rejected (auth))
+        return FALSE; /* OOM */
+    }
+  else if (!send_ok (auth))
+    {
+      return FALSE; /* OOM */
+    }
 
   _dbus_verbose ("%s: authenticated client as anonymous\n",
                  DBUS_AUTH_NAME (auth));
@@ -2244,7 +2278,8 @@ process_command (DBusAuth *auth)
  * @returns the new object or #NULL if no memory
  */
 DBusAuth*
-_dbus_auth_server_new (const DBusString *guid)
+_dbus_auth_server_new (const DBusString *guid,
+    DBusAuthorization *authorization)
 {
   DBusAuth *auth;
   DBusAuthServer *server_auth;
@@ -2272,7 +2307,8 @@ _dbus_auth_server_new (const DBusString *guid)
   server_auth = DBUS_AUTH_SERVER (auth);
 
   server_auth->guid = guid_copy;
-  
+  server_auth->authorization = _dbus_authorization_ref (authorization);
+
   /* perhaps this should be per-mechanism with a lower
    * max
    */
@@ -2363,6 +2399,7 @@ _dbus_auth_unref (DBusAuth *auth)
           _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
 
           _dbus_string_free (& DBUS_AUTH_SERVER (auth)->guid);
+          _dbus_authorization_unref (DBUS_AUTH_SERVER (auth)->authorization);
         }
 
       if (auth->keyring)
diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h
index ae3f364..a6577f9 100644
--- a/dbus/dbus-auth.h
+++ b/dbus/dbus-auth.h
@@ -27,6 +27,7 @@
 #include <dbus/dbus-errors.h>
 #include <dbus/dbus-string.h>
 #include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-authorization.h>
 
 DBUS_BEGIN_DECLS
 
@@ -41,7 +42,8 @@ typedef enum
   DBUS_AUTH_STATE_AUTHENTICATED
 } DBusAuthState;
 
-DBusAuth*     _dbus_auth_server_new          (const DBusString       *guid);
+DBusAuth*     _dbus_auth_server_new          (const DBusString       *guid,
+    DBusAuthorization *authorization);
 DBusAuth*     _dbus_auth_client_new          (void);
 DBusAuth*     _dbus_auth_ref                 (DBusAuth               *auth);
 void          _dbus_auth_unref               (DBusAuth               *auth);
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 9128ffc..3e74ca1 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -5309,7 +5309,7 @@ dbus_connection_get_windows_user (DBusConnection             *connection,
  * is allowed to connect. When an incoming connection has
  * authenticated with a particular user ID, this function is called;
  * if it returns #TRUE, the connection is allowed to proceed,
- * otherwise the connection is disconnected.
+ * otherwise the connection is REJECTED.
  *
  * If the function is set to #NULL (as it is by default), then
  * only the same user owning the server process will be allowed to
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index 1ef189e..328479f 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -126,7 +126,7 @@ _dbus_transport_init_base (DBusTransport             *transport,
           return FALSE; /* OOM */
         }
 
-      auth = _dbus_auth_server_new (server_guid);
+      auth = _dbus_auth_server_new (server_guid, authorization);
     }
   else
     {
@@ -615,7 +615,8 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
           
           /* 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))
+          if (!_dbus_authorization_do_authorization (transport->authorization,
+                                                     auth_identity))
             {
               _dbus_transport_disconnect (transport);
               maybe_authenticated = FALSE;
@@ -1233,7 +1234,7 @@ _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
  */
-inline void
+void
 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
                                         DBusAllowUnixUserFunction  function,
                                         void                      *data,
@@ -1355,7 +1356,7 @@ _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
  * @param transport the transport
  * @param value #TRUE to allow anonymous connection
  */
-inline void
+void
 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
                                      dbus_bool_t                 value)
 {
-- 
1.7.6.3