2002-12-26 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Fri, 27 Dec 2002 02:07:21 +0000 (02:07 +0000)
committerHavoc Pennington <hp@redhat.com>
Fri, 27 Dec 2002 02:07:21 +0000 (02:07 +0000)
* dbus/dbus-auth.c: fixes fixes fixes

* dbus/dbus-transport-unix.c: wire up support for
encoding/decoding data on the wire

* dbus/dbus-auth.c (_dbus_auth_encode_data)
(_dbus_auth_decode_data): append to target string
instead of nuking it.

ChangeLog
dbus/dbus-auth.c
dbus/dbus-internals.h
dbus/dbus-marshal.c
dbus/dbus-string.c
dbus/dbus-sysdeps.c
dbus/dbus-transport-unix.c

index a43ef42..bd1c414 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2002-12-26  Havoc Pennington  <hp@pobox.com>
 
+       * dbus/dbus-auth.c: fixes fixes fixes
+
+       * dbus/dbus-transport-unix.c: wire up support for
+       encoding/decoding data on the wire
+
+       * dbus/dbus-auth.c (_dbus_auth_encode_data) 
+       (_dbus_auth_decode_data): append to target string 
+       instead of nuking it.
+
+2002-12-26  Havoc Pennington  <hp@pobox.com>
+
        * dbus/dbus-marshal.h (DBUS_COMPILER_BYTE_ORDER): #ifdef
        WORDS_BIGENDIAN then compiler byte order is DBUS_BIG_ENDIAN,
        doh
index 566abae..d39a777 100644 (file)
@@ -173,6 +173,9 @@ static dbus_bool_t process_error_client (DBusAuth         *auth,
                                          const DBusString *args);
 
 
+static dbus_bool_t client_try_next_mechanism (DBusAuth *auth);
+
+
 static DBusAuthCommandHandler
 server_handlers[] = {
   { "AUTH", process_auth },
@@ -331,7 +334,8 @@ handle_encode_stupid_test_mech (DBusAuth         *auth,
                                 const DBusString *plaintext,
                                 DBusString       *encoded)
 {
-  if (!_dbus_string_base64_encode (plaintext, 0, encoded, 0))
+  if (!_dbus_string_base64_encode (plaintext, 0, encoded,
+                                   _dbus_string_get_length (encoded)))
     return FALSE;
   
   return TRUE;
@@ -342,7 +346,8 @@ handle_decode_stupid_test_mech (DBusAuth         *auth,
                                 const DBusString *encoded,
                                 DBusString       *plaintext)
 {
-  if (!_dbus_string_base64_decode (encoded, 0, plaintext, 0))
+  if (!_dbus_string_base64_decode (encoded, 0, plaintext,
+                                   _dbus_string_get_length (plaintext)))
     return FALSE;
   
   return TRUE;
@@ -679,6 +684,58 @@ process_mechanisms (DBusAuth         *auth,
 }
 
 static dbus_bool_t
+client_try_next_mechanism (DBusAuth *auth)
+{
+  const DBusAuthMechanismHandler *mech;
+  DBusString auth_command;
+
+  if (DBUS_AUTH_CLIENT (auth)->mechs_to_try == NULL)
+    return FALSE;
+
+  mech = DBUS_AUTH_CLIENT (auth)->mechs_to_try->data;
+
+  if (!_dbus_string_init (&auth_command, _DBUS_INT_MAX))
+    return FALSE;
+      
+  if (!_dbus_string_append (&auth_command,
+                            "AUTH "))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (&auth_command,
+                            mech->mechanism))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }
+        
+  if (!_dbus_string_append (&auth_command,
+                            "\r\n"))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }
+
+  if (!_dbus_string_copy (&auth_command, 0,
+                          &auth->outgoing,
+                          _dbus_string_get_length (&auth->outgoing)))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }
+
+  auth->mech = mech;      
+  _dbus_list_pop_first (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
+
+  _dbus_verbose ("Trying mechanism %s\n",
+                 auth->mech->mechanism);
+
+  return TRUE;
+}
+
+static dbus_bool_t
 process_rejected (DBusAuth         *auth,
                   const DBusString *command,
                   const DBusString *args)
@@ -694,49 +751,7 @@ process_rejected (DBusAuth         *auth,
     }
   else if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL)
     {
-      /* Try next mechanism */
-      const DBusAuthMechanismHandler *mech;
-      DBusString auth_command;
-
-      mech = DBUS_AUTH_CLIENT (auth)->mechs_to_try->data;
-
-      if (!_dbus_string_init (&auth_command, _DBUS_INT_MAX))
-        return FALSE;
-      
-      if (!_dbus_string_append (&auth_command,
-                                "AUTH "))
-        {
-          _dbus_string_free (&auth_command);
-          return FALSE;
-        }
-
-      if (!_dbus_string_append (&auth->outgoing,
-                                mech->mechanism))
-        {
-          _dbus_string_free (&auth_command);
-          return FALSE;
-        }
-        
-      if (!_dbus_string_append (&auth->outgoing,
-                                "\r\n"))
-        {
-          _dbus_string_free (&auth_command);
-          return FALSE;
-        }
-
-      if (!_dbus_string_copy (&auth_command, 0,
-                              &auth->outgoing,
-                              _dbus_string_get_length (&auth->outgoing)))
-        {
-          _dbus_string_free (&auth_command);
-          return FALSE;
-        }
-
-      auth->mech = mech;      
-      _dbus_list_pop_first (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
-
-      _dbus_verbose ("Trying mechanism %s\n",
-                     auth->mech->mechanism);
+      client_try_next_mechanism (auth);
     }
   else
     {
@@ -978,9 +993,16 @@ _dbus_auth_client_new (void)
 
   auth->handlers = client_handlers;
 
-  /* Request an auth */
-  if (!_dbus_string_append (&auth->outgoing,
-                            "AUTH DBUS_STUPID_TEST_MECH\r\n"))
+  /* Add a default mechanism to try */
+  if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
+                          (void*) &all_mechanisms[0]))
+    {
+      _dbus_auth_unref (auth);
+      return NULL;
+    }
+
+  /* Now try the mechanism we just added */
+  if (!client_try_next_mechanism (auth))
     {
       _dbus_auth_unref (auth);
       return NULL;
@@ -1215,7 +1237,7 @@ _dbus_auth_needs_encoding (DBusAuth *auth)
  *
  * @param auth the auth conversation
  * @param plaintext the plain text data
- * @param encoded initialized string to fill in with encoded data
+ * @param encoded initialized string to where encoded data is appended
  * @returns #TRUE if we had enough memory and successfully encoded
  */
 dbus_bool_t
@@ -1223,6 +1245,8 @@ _dbus_auth_encode_data (DBusAuth         *auth,
                         const DBusString *plaintext,
                         DBusString       *encoded)
 {
+  _dbus_assert (plaintext != encoded);
+  
   if (!auth->authenticated)
     return FALSE;
   
@@ -1235,7 +1259,8 @@ _dbus_auth_encode_data (DBusAuth         *auth,
     }
   else
     {
-      return _dbus_string_copy (plaintext, 0, encoded, 0);
+      return _dbus_string_copy (plaintext, 0, encoded,
+                                _dbus_string_get_length (encoded));
     }
 }
 
@@ -1270,9 +1295,12 @@ _dbus_auth_needs_decoding (DBusAuth *auth)
  * the peer. If no encoding was negotiated, just copies the bytes (you
  * can avoid this by checking _dbus_auth_needs_decoding()).
  *
+ * @todo We need to be able to distinguish "out of memory" error
+ * from "the data is hosed" error.
+ *
  * @param auth the auth conversation
  * @param encoded the encoded data
- * @param plaintext initialized string to fill in with decoded data
+ * @param plaintext initialized string where decoded data is appended
  * @returns #TRUE if we had enough memory and successfully decoded
  */
 dbus_bool_t
@@ -1280,6 +1308,8 @@ _dbus_auth_decode_data (DBusAuth         *auth,
                         const DBusString *encoded,
                         DBusString       *plaintext)
 {
+  _dbus_assert (plaintext != encoded);
+  
   if (!auth->authenticated)
     return FALSE;
   
@@ -1292,7 +1322,8 @@ _dbus_auth_decode_data (DBusAuth         *auth,
     }
   else
     {
-      return _dbus_string_copy (encoded, 0, plaintext, 0);
+      return _dbus_string_copy (encoded, 0, plaintext,
+                                _dbus_string_get_length (plaintext));
     }
 }
 
index 2b7772f..027b3ef 100644 (file)
@@ -83,8 +83,13 @@ typedef void (* DBusForeachFunction) (void *element,
 dbus_bool_t _dbus_set_fd_nonblocking (int             fd,
                                       DBusResultCode *result);
 
-void _dbus_verbose_bytes (const unsigned char *data,
-                          int                  len);
+void _dbus_verbose_bytes           (const unsigned char *data,
+                                    int                  len);
+void _dbus_verbose_bytes_of_string (const DBusString    *str,
+                                    int                  start,
+                                    int                  len);
+
+
 
 DBUS_END_DECLS;
 
index 9fbfb4e..d8d0d5f 100644 (file)
@@ -342,6 +342,25 @@ _dbus_verbose_bytes (const unsigned char *data,
   _dbus_verbose ("\n");
 }
 
+/**
+ * Dump the given part of the string to verbose log.
+ *
+ * @param str the string
+ * @param start the start of range to dump
+ * @param len length of range
+ */
+void
+_dbus_verbose_bytes_of_string (const DBusString    *str,
+                               int                  start,
+                               int                  len)
+{
+  const char *d;
+
+  _dbus_string_get_const_data_len (str, &d, start, len);
+
+  _dbus_verbose_bytes (d, len);
+}
+
 /** @} */
 
 #ifdef DBUS_BUILD_TESTS
index c4a51d5..6dc2857 100644 (file)
@@ -1407,6 +1407,7 @@ _dbus_string_base64_encode (const DBusString *source,
   const unsigned char *triplet_end;
   const unsigned char *final_end;
   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);  
+  _dbus_assert (source != dest);
   
   /* For each 24 bits (3 bytes) of input, we have 4 chars of
    * output.
@@ -1508,6 +1509,7 @@ _dbus_string_base64_decode (const DBusString *source,
   int sextet_count;
   int pad_count;
   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
+  _dbus_assert (source != dest);
   
   source_len = real_source->len - start;
   s = real_source->str + start;
index 76b9c5c..fed8814 100644 (file)
@@ -116,6 +116,12 @@ _dbus_read (int               fd,
     {
       /* put length back (doesn't actually realloc) */
       _dbus_string_set_length (buffer, start + bytes_read);
+
+#if 0
+      if (bytes_read > 0)
+        _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
+#endif
+      
       return bytes_read;
     }
 }
@@ -148,6 +154,11 @@ _dbus_write (int               fd,
   if (errno == EINTR)
     goto again;
 
+#if 0
+  if (bytes_written > 0)
+    _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
+#endif
+  
   return bytes_written;
 }
 
index c1487a0..dd0c683 100644 (file)
@@ -61,6 +61,9 @@ struct DBusTransportUnix
                                          *   outgoing message that have
                                          *   been written.
                                          */
+  DBusString encoded_message;           /**< Encoded version of current
+                                         *   outgoing message.
+                                         */
 };
 
 static void
@@ -95,6 +98,8 @@ unix_finalize (DBusTransport *transport)
   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
   
   free_watches (transport);
+
+  _dbus_string_free (&unix_transport->encoded_message);
   
   _dbus_transport_finalize_base (transport);
 
@@ -292,6 +297,100 @@ write_data_from_auth (DBusTransport *transport)
 }
 
 static void
+recover_unused_bytes (DBusTransport *transport)
+{
+  
+  if (_dbus_auth_needs_decoding (transport->auth))
+    {
+      DBusString plaintext;
+      DBusString encoded;
+      DBusString *buffer;
+      int orig_len;
+      
+      if (!_dbus_string_init (&plaintext, _DBUS_INT_MAX))
+        goto nomem;
+
+      if (!_dbus_string_init (&encoded, _DBUS_INT_MAX))
+        {
+          _dbus_string_free (&plaintext);
+          goto nomem;
+        }
+      
+      if (!_dbus_auth_get_unused_bytes (transport->auth,
+                                        &encoded))
+        {
+          _dbus_string_free (&plaintext);
+          _dbus_string_free (&encoded);
+          goto nomem;
+        }
+      
+      if (!_dbus_auth_decode_data (transport->auth,
+                                   &encoded, &plaintext))
+        {
+          _dbus_string_free (&plaintext);
+          _dbus_string_free (&encoded);
+          goto nomem;
+        }
+      
+      _dbus_message_loader_get_buffer (transport->loader,
+                                       &buffer);
+      
+      orig_len = _dbus_string_get_length (buffer);
+
+      if (!_dbus_string_move (&plaintext, 0, buffer,
+                              orig_len))
+        {
+          _dbus_string_free (&plaintext);
+          _dbus_string_free (&encoded);
+          goto nomem;
+        }
+      
+      _dbus_verbose (" %d unused bytes sent to message loader\n", 
+                     _dbus_string_get_length (buffer) -
+                     orig_len);
+      
+      _dbus_message_loader_return_buffer (transport->loader,
+                                          buffer,
+                                          _dbus_string_get_length (buffer) -
+                                          orig_len);
+
+      _dbus_string_free (&plaintext);
+      _dbus_string_free (&encoded);
+    }
+  else
+    {
+      DBusString *buffer;
+      int orig_len;
+
+      _dbus_message_loader_get_buffer (transport->loader,
+                                       &buffer);
+                
+      orig_len = _dbus_string_get_length (buffer);
+                
+      if (!_dbus_auth_get_unused_bytes (transport->auth,
+                                        buffer))
+        goto nomem;
+                
+      _dbus_verbose (" %d unused bytes sent to message loader\n", 
+                     _dbus_string_get_length (buffer) -
+                     orig_len);
+      
+      _dbus_message_loader_return_buffer (transport->loader,
+                                          buffer,
+                                          _dbus_string_get_length (buffer) -
+                                          orig_len);
+    }
+  
+  queue_messages (transport);
+
+  return;
+
+ nomem:
+  _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
+  do_io_error (transport);
+}
+
+static void
 do_authentication (DBusTransport *transport,
                    dbus_bool_t    do_reading,
                    dbus_bool_t    do_writing)
@@ -327,35 +426,8 @@ do_authentication (DBusTransport *transport,
           break;
       
         case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
-          {
-            DBusString *buffer;
-            int orig_len;
-
-            _dbus_verbose (" auth state: auth with unused bytes\n");
-            
-            _dbus_message_loader_get_buffer (transport->loader,
-                                             &buffer);
-
-            orig_len = _dbus_string_get_length (buffer);
-            
-            if (!_dbus_auth_get_unused_bytes (transport->auth,
-                                              buffer))
-              {
-                _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
-                do_io_error (transport);
-              }
-
-            _dbus_verbose (" %d unused bytes sent to message loader\n", 
-                           _dbus_string_get_length (buffer) -
-                           orig_len);
-            
-            _dbus_message_loader_return_buffer (transport->loader,
-                                                buffer,
-                                                _dbus_string_get_length (buffer) -
-                                                orig_len);
-
-            queue_messages (transport);
-          }
+          _dbus_verbose (" auth state: auth with unused bytes\n");
+          recover_unused_bytes (transport);
           break;
           
         case DBUS_AUTH_STATE_AUTHENTICATED:
@@ -392,6 +464,7 @@ do_writing (DBusTransport *transport)
       const DBusString *header;
       const DBusString *body;
       int header_len, body_len;
+      int total_bytes_to_write;
       
       if (total > unix_transport->max_bytes_written_per_iteration)
         {
@@ -404,30 +477,67 @@ do_writing (DBusTransport *transport)
       _dbus_assert (message != NULL);
       _dbus_message_lock (message);
 
+      _dbus_verbose ("writing message %p\n", message);
+      
       _dbus_message_get_network_data (message,
                                       &header, &body);
 
       header_len = _dbus_string_get_length (header);
       body_len = _dbus_string_get_length (body);
-      
-      if (unix_transport->message_bytes_written < header_len)
+
+      if (_dbus_auth_needs_encoding (transport->auth))
         {
+          if (_dbus_string_get_length (&unix_transport->encoded_message) == 0)
+            {
+              if (!_dbus_auth_encode_data (transport->auth,
+                                           header, &unix_transport->encoded_message))
+                goto out;
+              
+              if (!_dbus_auth_encode_data (transport->auth,
+                                           body, &unix_transport->encoded_message))
+                {
+                  _dbus_string_set_length (&unix_transport->encoded_message, 0);
+                  goto out;
+                }
+            }
+          
+          total_bytes_to_write = _dbus_string_get_length (&unix_transport->encoded_message);
+
+          _dbus_verbose ("encoded message is %d bytes\n",
+                         total_bytes_to_write);
+          
           bytes_written =
-            _dbus_write_two (unix_transport->fd,
-                             header,
-                             unix_transport->message_bytes_written,
-                             header_len - unix_transport->message_bytes_written,
-                             body,
-                             0, body_len);
+            _dbus_write (unix_transport->fd,
+                         &unix_transport->encoded_message,
+                         unix_transport->message_bytes_written,
+                         total_bytes_to_write - unix_transport->message_bytes_written);
         }
       else
         {
-          bytes_written =
-            _dbus_write (unix_transport->fd,
-                         body,
-                         (unix_transport->message_bytes_written - header_len),
-                         body_len -
-                         (unix_transport->message_bytes_written - header_len));
+          total_bytes_to_write = header_len + body_len;
+
+          _dbus_verbose ("message is %d bytes\n",
+                         total_bytes_to_write);          
+          
+          if (unix_transport->message_bytes_written < header_len)
+            {
+              bytes_written =
+                _dbus_write_two (unix_transport->fd,
+                                 header,
+                                 unix_transport->message_bytes_written,
+                                 header_len - unix_transport->message_bytes_written,
+                                 body,
+                                 0, body_len);
+            }
+          else
+            {
+              bytes_written =
+                _dbus_write (unix_transport->fd,
+                             body,
+                             (unix_transport->message_bytes_written - header_len),
+                             body_len -
+                             (unix_transport->message_bytes_written - header_len));
+            }
         }
 
       if (bytes_written < 0)
@@ -447,19 +557,22 @@ do_writing (DBusTransport *transport)
         }
       else
         {          
-          _dbus_verbose (" wrote %d bytes\n", bytes_written);
+          _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
+                         total_bytes_to_write);
           
           total += bytes_written;
           unix_transport->message_bytes_written += bytes_written;
 
           _dbus_assert (unix_transport->message_bytes_written <=
-                        (header_len + body_len));
+                        total_bytes_to_write);
           
-          if (unix_transport->message_bytes_written == (header_len + body_len))
+          if (unix_transport->message_bytes_written == total_bytes_to_write)
             {
+              unix_transport->message_bytes_written = 0;
+              _dbus_string_set_length (&unix_transport->encoded_message, 0);
+
               _dbus_connection_message_sent (transport->connection,
                                              message);
-              unix_transport->message_bytes_written = 0;
             }
         }
     }
@@ -493,16 +606,59 @@ do_reading (DBusTransport *transport)
 
   if (transport->disconnected)
     goto out;
-  
-  _dbus_message_loader_get_buffer (transport->loader,
-                                   &buffer);
-  
-  bytes_read = _dbus_read (unix_transport->fd,
-                           buffer, unix_transport->max_bytes_read_per_iteration);
 
-  _dbus_message_loader_return_buffer (transport->loader,
-                                      buffer,
-                                      bytes_read < 0 ? 0 : bytes_read);
+  if (_dbus_auth_needs_decoding (transport->auth))
+    {
+      DBusString encoded;
+
+      if (!_dbus_string_init (&encoded, _DBUS_INT_MAX))
+        goto out; /* not enough memory for the moment */
+
+      bytes_read = _dbus_read (unix_transport->fd,
+                               &encoded,
+                               unix_transport->max_bytes_read_per_iteration);
+
+      if (bytes_read > 0)
+        {
+          int orig_len;
+          
+          _dbus_message_loader_get_buffer (transport->loader,
+                                           &buffer);
+
+          orig_len = _dbus_string_get_length (buffer);
+          
+          if (!_dbus_auth_decode_data (transport->auth,
+                                       &encoded, buffer))
+            {
+              /* FIXME argh, we are really fucked here - nowhere to
+               * put "encoded" while we wait for more memory.  Just
+               * screw it for now and disconnect.  The failure may be
+               * due to badly-encoded data instead of lack of memory
+               * anyhow.
+               */
+              _dbus_verbose ("Disconnected from remote app due to failure decoding data\n");
+              do_io_error (transport);
+            }
+
+          _dbus_message_loader_return_buffer (transport->loader,
+                                              buffer,
+                                              _dbus_string_get_length (buffer) - orig_len);
+        }
+
+      _dbus_string_free (&encoded);
+    }
+  else
+    {
+      _dbus_message_loader_get_buffer (transport->loader,
+                                       &buffer);
+      
+      bytes_read = _dbus_read (unix_transport->fd,
+                               buffer, unix_transport->max_bytes_read_per_iteration);
+      
+      _dbus_message_loader_return_buffer (transport->loader,
+                                          buffer,
+                                          bytes_read < 0 ? 0 : bytes_read);
+    }
   
   if (bytes_read < 0)
     {
@@ -748,10 +904,18 @@ _dbus_transport_new_for_fd (int         fd,
   if (unix_transport == NULL)
     return NULL;
 
+  if (!_dbus_string_init (&unix_transport->encoded_message,
+                          _DBUS_INT_MAX))
+    {
+      dbus_free (unix_transport);
+      return NULL;
+    }
+  
   if (!_dbus_transport_init_base (&unix_transport->base,
                                   &unix_vtable,
                                   server))
     {
+      _dbus_string_free (&unix_transport->encoded_message);
       dbus_free (unix_transport);
       return NULL;
     }