2005-05-05 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Thu, 5 May 2005 22:02:11 +0000 (22:02 +0000)
committerHavoc Pennington <hp@redhat.com>
Thu, 5 May 2005 22:02:11 +0000 (22:02 +0000)
* configure.in (LT_*): add notes on how the libtool versioning
works to save thinking. Increment soname to indicate protocol
breakage (though really the library interface hasn't changed I
guess)

* dbus/dbus-transport.c (_dbus_transport_get_is_authenticated):
verify the GUID received from server matches what we were
expecting, if we had an expectation

* dbus/dbus-auth.c (send_ok): send GUID along with the OK command
(_dbus_auth_get_guid_from_server): new function
(send_begin): parse the OK args

* doc/dbus-specification.xml: add GUID to the auth protocol

ChangeLog
configure.in
dbus/dbus-auth.c
dbus/dbus-auth.h
dbus/dbus-transport-protected.h
dbus/dbus-transport.c
doc/TODO
doc/dbus-specification.xml
test/data/auth/fallback.auth-script

index 408a4e3..1fbbf85 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2005-05-05  Havoc Pennington  <hp@redhat.com>
+
+       * configure.in (LT_*): add notes on how the libtool versioning
+       works to save thinking. Increment soname to indicate protocol
+       breakage (though really the library interface hasn't changed I
+       guess)
+
+       * dbus/dbus-transport.c (_dbus_transport_get_is_authenticated):
+       verify the GUID received from server matches what we were
+       expecting, if we had an expectation
+
+       * dbus/dbus-auth.c (send_ok): send GUID along with the OK command
+       (_dbus_auth_get_guid_from_server): new function
+       (send_begin): parse the OK args
+
+       * doc/dbus-specification.xml: add GUID to the auth protocol
+
 2005-05-05  John (J5) Palmieri  <johnp@redhat.com>
 
        * Fix my name in previous changelog ;)
index cc918e7..111ef6c 100644 (file)
@@ -17,13 +17,23 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The name of the gettext d
  ## must come before we use the $USE_MAINTAINER_MODE variable later
 AM_MAINTAINER_MODE
 
-# libtool versioning - this applies to libhal and libhal-storage
+# libtool versioning - this applies to libdbus
 #
 # See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
 #
-LT_CURRENT=1
+
+## increment if the interface has additions, changes, removals.
+LT_CURRENT=2
+
+## increment any time the source changes; set to
+##  0 if you increment CURRENT
 LT_REVISION=0
+
+## increment if any interfaces have been added; set to 0
+## if any interfaces have been changed or removed. removal has
+## precedence over adding, so set to 0 if both happened.
 LT_AGE=0
+
 AC_SUBST(LT_CURRENT)
 AC_SUBST(LT_REVISION)
 AC_SUBST(LT_AGE)
index 2a1bbd4..ced9330 100644 (file)
@@ -199,6 +199,8 @@ typedef struct
   DBusAuth base;    /**< Parent class */
 
   DBusList *mechs_to_try; /**< Mechanisms we got from the server that we're going to try using */
+
+  DBusString guid_from_server; /**< GUID received from server */
   
 } DBusAuthClient;
 
@@ -226,7 +228,8 @@ static dbus_bool_t send_rejected             (DBusAuth *auth);
 static dbus_bool_t send_error                (DBusAuth *auth,
                                               const char *message);
 static dbus_bool_t send_ok                   (DBusAuth *auth);
-static dbus_bool_t send_begin                (DBusAuth *auth);
+static dbus_bool_t send_begin                (DBusAuth *auth,
+                                              const DBusString *args_from_ok);
 static dbus_bool_t send_cancel               (DBusAuth *auth);
 
 /**
@@ -1329,25 +1332,69 @@ send_error (DBusAuth *auth, const char *message)
 static dbus_bool_t
 send_ok (DBusAuth *auth)
 {
-  if (_dbus_string_append (&auth->outgoing, "OK\r\n"))
+  int orig_len;
+
+  orig_len = _dbus_string_get_length (&auth->outgoing);
+  
+  if (_dbus_string_append (&auth->outgoing, "OK ") &&
+      _dbus_string_copy (& DBUS_AUTH_SERVER (auth)->guid,
+                         0,
+                         &auth->outgoing,
+                         _dbus_string_get_length (&auth->outgoing)) &&
+      _dbus_string_append (&auth->outgoing, "\r\n"))
     {
       goto_state (auth, &server_state_waiting_for_begin);
       return TRUE;
     }
   else
-    return FALSE;
+    {
+      _dbus_string_set_length (&auth->outgoing, orig_len);
+      return FALSE;
+    }
 }
 
 static dbus_bool_t
-send_begin (DBusAuth *auth)
+send_begin (DBusAuth         *auth,
+            const DBusString *args_from_ok)
 {
-  if (_dbus_string_append (&auth->outgoing, "BEGIN\r\n"))
+  int end_of_hex;
+  
+  /* "args_from_ok" should be the GUID, whitespace already pulled off the front */
+  _dbus_assert (_dbus_string_get_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server) == 0);
+
+  /* We decode the hex string to binary, using guid_from_server as scratch... */
+  
+  end_of_hex = 0;
+  if (!_dbus_string_hex_decode (args_from_ok, 0, &end_of_hex,
+                                & DBUS_AUTH_CLIENT (auth)->guid_from_server, 0))
+    return FALSE;
+
+  /* now clear out the scratch */
+  _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
+  
+  if (end_of_hex != _dbus_string_get_length (args_from_ok) ||
+      end_of_hex == 0)
+    {
+      _dbus_verbose ("Bad GUID from server, parsed %d bytes and had %d bytes from server\n",
+                     end_of_hex, _dbus_string_get_length (args_from_ok));
+      goto_state (auth, &common_state_need_disconnect);
+      return TRUE;
+    }
+
+  if (_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0) &&
+      _dbus_string_append (&auth->outgoing, "BEGIN\r\n"))
     {
+      _dbus_verbose ("Got GUID '%s' from the server\n",
+                     _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
+      
       goto_state (auth, &common_state_authenticated);
       return TRUE;
     }
   else
-    return FALSE;
+    {
+      _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
+      return FALSE;
+    }
 }
 
 static dbus_bool_t
@@ -1364,8 +1411,8 @@ send_cancel (DBusAuth *auth)
 
 static dbus_bool_t
 process_data (DBusAuth             *auth,
-             const DBusString     *args,
-             DBusAuthDataFunction  data_func)
+              const DBusString     *args,
+              DBusAuthDataFunction  data_func)
 {
   int end;
   DBusString decoded;
@@ -1710,7 +1757,7 @@ handle_client_state_waiting_for_data (DBusAuth         *auth,
       return process_rejected (auth, args);
 
     case DBUS_AUTH_COMMAND_OK:
-      return send_begin (auth);
+      return send_begin (auth, args);
 
     case DBUS_AUTH_COMMAND_ERROR:
       return send_cancel (auth);
@@ -1735,7 +1782,7 @@ handle_client_state_waiting_for_ok (DBusAuth         *auth,
       return process_rejected (auth, args);
 
     case DBUS_AUTH_COMMAND_OK:
-      return send_begin (auth);
+      return send_begin (auth, args);
 
     case DBUS_AUTH_COMMAND_DATA:
     case DBUS_AUTH_COMMAND_ERROR:
@@ -1974,10 +2021,19 @@ DBusAuth*
 _dbus_auth_client_new (void)
 {
   DBusAuth *auth;
+  DBusString guid_str;
+
+  if (!_dbus_string_init (&guid_str))
+    return NULL;
 
   auth = _dbus_auth_new (sizeof (DBusAuthClient));
   if (auth == NULL)
-    return NULL;
+    {
+      _dbus_string_free (&guid_str);
+      return NULL;
+    }
+
+  DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str;
 
   auth->side = auth_side_client;
   auth->state = &client_state_need_send_auth;
@@ -2027,6 +2083,7 @@ _dbus_auth_unref (DBusAuth *auth)
 
       if (DBUS_AUTH_IS_CLIENT (auth))
         {
+          _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
           _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
         }
       else
@@ -2402,6 +2459,23 @@ _dbus_auth_get_identity (DBusAuth               *auth,
 }
 
 /**
+ * Gets the GUID from the server if we've authenticated; gets
+ * #NULL otherwise.
+ * @param auth the auth object
+ * @returns the GUID in ASCII hex format
+ */
+const char*
+_dbus_auth_get_guid_from_server (DBusAuth *auth)
+{
+  _dbus_assert (DBUS_AUTH_IS_CLIENT (auth));
+  
+  if (auth->state == &common_state_authenticated)
+    return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
+  else
+    return NULL;
+}
+
+/**
  * Sets the "authentication context" which scopes cookies
  * with the DBUS_COOKIE_SHA1 auth mechanism for example.
  *
index 6ed5040..9cff8b5 100644 (file)
@@ -74,6 +74,7 @@ void          _dbus_auth_get_identity        (DBusAuth               *auth,
                                               DBusCredentials        *credentials);
 dbus_bool_t   _dbus_auth_set_context         (DBusAuth               *auth,
                                               const DBusString       *context);
+const char*   _dbus_auth_get_guid_from_server(DBusAuth               *auth);
 
 
 DBUS_END_DECLS
index 879c3db..f3ad337 100644 (file)
@@ -96,7 +96,9 @@ struct DBusTransport
   DBusCounter *live_messages_size;            /**< Counter for size of all live messages. */
 
 
-  char *address;                              /**< Address of this server */
+  char *address;                              /**< Address of the server we are connecting to (#NULL for the server side of a transport) */
+
+  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 */
index b271d94..cfc86e4 100644 (file)
@@ -153,6 +153,8 @@ _dbus_transport_init_base (DBusTransport             *transport,
   transport->unix_user_function = NULL;
   transport->unix_user_data = NULL;
   transport->free_unix_user_data = NULL;
+
+  transport->expected_guid = NULL;
   
   /* Try to default to something that won't totally hose the system,
    * but doesn't impose too much of a limitation.
@@ -195,6 +197,7 @@ _dbus_transport_finalize_base (DBusTransport *transport)
                             0, NULL, NULL);
   _dbus_counter_unref (transport->live_messages_size);
   dbus_free (transport->address);
+  dbus_free (transport->expected_guid);
 }
 
 /**
@@ -213,7 +216,9 @@ _dbus_transport_open (DBusAddressEntry *entry,
   const char *address_problem_type;
   const char *address_problem_field;
   const char *address_problem_other;
-  const char *method;     
+  const char *method;
+  const char *expected_guid_orig;
+  char *expected_guid;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
@@ -221,6 +226,14 @@ _dbus_transport_open (DBusAddressEntry *entry,
   address_problem_type = NULL;
   address_problem_field = NULL;
   address_problem_other = NULL;
+  expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
+  expected_guid = _dbus_strdup (expected_guid_orig);
+
+  if (expected_guid_orig != NULL && expected_guid == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
   
   method = dbus_address_entry_get_method (entry);
   _dbus_assert (method != NULL);
@@ -306,11 +319,20 @@ _dbus_transport_open (DBusAddressEntry *entry,
     }
 
   if (transport == NULL)
-    _DBUS_ASSERT_ERROR_IS_SET (error);
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_free (expected_guid);
+    }
+  else
+    {
+      transport->expected_guid = expected_guid;
+    }
   
   return transport;
   
  bad_address:
+  dbus_free (expected_guid);
+  
   if (address_problem_type != NULL)
     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
                     "Address of type %s was missing argument %s",
@@ -442,6 +464,35 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
               maybe_authenticated = FALSE;
             }
         }
+
+      if (maybe_authenticated && !transport->is_server)
+        {
+          const char *server_guid;
+
+          server_guid = _dbus_auth_get_guid_from_server (transport->auth);
+          _dbus_assert (server_guid != NULL);
+
+          if (transport->expected_guid &&
+              strcmp (transport->expected_guid, server_guid) != 0)
+            {
+              _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
+                             transport->expected_guid, server_guid);
+              _dbus_transport_disconnect (transport);
+              _dbus_connection_unref_unlocked (transport->connection);
+              return FALSE;
+            }
+
+          if (transport->expected_guid == NULL)
+            {
+              transport->expected_guid = _dbus_strdup (server_guid);
+
+              if (transport->expected_guid == NULL)
+                {
+                  _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME);
+                  return FALSE;
+                }
+            }
+        }
       
       /* If we've authenticated as some identity, check that the auth
        * identity is the same as our own identity.  In the future, we
@@ -518,7 +569,7 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
                 }
             }
         }
-
+      
       transport->authenticated = maybe_authenticated;
 
       _dbus_connection_unref_unlocked (transport->connection);
index f25eac0..0c126c1 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -31,10 +31,6 @@ Important for 1.0
 
  - dbus-pending-call.c has some API and thread safety issues to review
 
- - transmit GUID from server to client in the auth protocol, so 
-   connections can be shared even if the address used to connect
-   to them didn't have a GUID in it.
-
  - Add test harness for selinux allow/deny cf. this message
    http://lists.freedesktop.org/archives/dbus/2005-April/002506.html
 
@@ -63,6 +59,9 @@ Might as Well for 1.0
 Can Be Post 1.0
 ===
 
+ - if the GUID is obtained only during authentication, not in the address, 
+   we could still share the connection
+
  - Allow a dbus_g_proxy_to_string()/g_object_to_string() that
    would convert the proxy to an "IOR" and dbus_g_proxy_from_string()
    that would decode; using these, dbus-glib users could avoid
index ff62544..0ea43a8 100644 (file)
 
         <itemizedlist>
          <listitem><para>REJECTED &lt;space-separated list of mechanism names&gt;</para></listitem>
-         <listitem><para>OK</para></listitem>
+         <listitem><para>OK &lt;GUID in hex&gt;</para></listitem>
          <listitem><para>DATA &lt;data in hex encoding&gt;</para></listitem>
          <listitem><para>ERROR</para></listitem>
        </itemizedlist>
         The server must not accept additional commands using this protocol 
         after the OK command has been sent.
       </para>
+      <para>
+        The OK command has one argument, which is the GUID of the server.
+        See <xref linkend="addresses"/> for more on server GUIDs.
+      </para>
     </sect2>
     <sect2 id="auth-command-error">
       <title>ERROR Command</title>
             (MAGIC_COOKIE is a made up mechanism)
 
             C: AUTH MAGIC_COOKIE 3138363935333137393635383634
-            S: OK
+            S: OK 1234deadbeef
             C: BEGIN
           </programlisting>
        </figure>
             C: AUTH SKEY 7ab83f32ee
             S: DATA 8799cabb2ea93e
             C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
-            S: OK
+            S: OK 1234deadbeef
             C: BEGIN
           </programlisting>
        </figure>
             C: FOOBAR
             S: ERROR
             C: AUTH MAGIC_COOKIE 3736343435313230333039
-            S: OK
+            S: OK 1234deadbeef
             C: BEGIN
           </programlisting>
        </figure>
             C: AUTH SKEY 7ab83f32ee
             S: DATA 8799cabb2ea93e
             C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
-            S: OK
+            S: OK 1234deadbeef
             C: BEGIN
           </programlisting>
        </figure>
             C: AUTH SKEY 7ab83f32ee
             S: DATA 8799cabb2ea93e
             C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
-            S: OK
+            S: OK 1234deadbeef
             C: BEGIN
           </programlisting>
        </figure>
             C: AUTH SKEY 7ab83f32ee
             S: DATA 8799cabb2ea93e
             C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
-            S: OK
+            S: OK 1234deadbeef
             C: BEGIN
           </programlisting>
        </figure>
index ebe7ae2..f598b77 100644 (file)
@@ -16,7 +16,7 @@ SEND 'REJECTED EXTERNAL DBUS_COOKIE_SHA1 DBUS_TEST_NONEXISTENT_MECH'
 
 EXPECT_COMMAND AUTH
 ## of course real DBUS_COOKIE_SHA1 would not send this here...
-SEND 'OK'
+SEND 'OK 1234deadbeef'
 
 EXPECT_COMMAND BEGIN
 EXPECT_STATE AUTHENTICATED