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.
This commit is contained in:
Havoc Pennington 2002-12-27 02:07:21 +00:00
parent ff5283ab92
commit b3ef8b0e9b
7 changed files with 353 additions and 110 deletions

View file

@ -1,3 +1,14 @@
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

View 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;
@ -678,6 +683,58 @@ process_mechanisms (DBusAuth *auth,
return FALSE;
}
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,
@ -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));
}
}

View 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;

View 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

View 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;

View 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;
}

View 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);
@ -291,6 +296,100 @@ write_data_from_auth (DBusTransport *transport)
return FALSE;
}
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,
@ -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;
}