summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-auth.c135
-rw-r--r--dbus/dbus-internals.h9
-rw-r--r--dbus/dbus-marshal.c19
-rw-r--r--dbus/dbus-string.c2
-rw-r--r--dbus/dbus-sysdeps.c11
-rw-r--r--dbus/dbus-transport-unix.c276
6 files changed, 342 insertions, 110 deletions
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index 566abaed..d39a7770 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -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));
}
}
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index 2b7772f3..027b3ef6 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -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;
diff --git a/dbus/dbus-marshal.c b/dbus/dbus-marshal.c
index 9fbfb4e1..d8d0d5f7 100644
--- a/dbus/dbus-marshal.c
+++ b/dbus/dbus-marshal.c
@@ -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
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index c4a51d5b..6dc28577 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -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;
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 76b9c5ce..fed88144 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -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;
}
diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c
index c1487a0f..dd0c6833 100644
--- a/dbus/dbus-transport-unix.c
+++ b/dbus/dbus-transport-unix.c
@@ -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;
}