diff options
author | Havoc Pennington <hp@redhat.com> | 2002-12-27 00:44:41 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2002-12-27 00:44:41 +0000 |
commit | ff5283ab92c668453fd2f28c1715a1e0e9b949f5 (patch) | |
tree | 24cf1119e1d203dd08cd4d797ac8640d35451faa /dbus/dbus-auth.c | |
parent | f3729626de0093762c9d00a8d02db9c96fbd5bd2 (diff) |
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
* dbus/dbus-marshal.c: Add macros to do int swapping in-place and
avoid swap_bytes() overhead (ignoring possible assembly stuff for
now). Main point is because I wanted unpack_uint32 to implement
_dbus_verbose_bytes
(_dbus_verbose_bytes): new function
* dbus/dbus-string.c (_dbus_string_validate_ascii): new function
* dbus/dbus-message.c (_dbus_message_loader_get_is_corrupted): add
mechanism to handle a corrupt message stream
(_dbus_message_loader_new): fix preallocation to only prealloc,
not prelengthen
* dbus/dbus-string.c (_dbus_string_skip_blank): fix this function
(_dbus_string_test): enhance tests for copy/move and fix the
functions
* dbus/dbus-transport-unix.c: Hold references in more places to
avoid reentrancy problems
* dbus/dbus-transport.c: ditto
* dbus/dbus-connection.c (dbus_connection_dispatch_message): don't
leak reference count in no-message case
* test/watch.c (do_mainloop): handle adding/removing watches
during iteration over the watches. Also, ref the connection/server
stored on a watch, so we don't try to mangle a destroyed one.
* dbus/dbus-transport-unix.c (do_authentication): perform
authentication
* dbus/dbus-auth.c (get_state): add a state
AUTHENTICATED_WITH_UNUSED_BYTES and return it if required
(_dbus_auth_get_unused_bytes): append the unused bytes
to the passed in string, rather than prepend
* dbus/dbus-transport.c (_dbus_transport_init_base): create
the auth conversation DBusAuth
* dbus/dbus-transport-unix.c (_dbus_transport_new_for_fd)
(_dbus_transport_new_for_domain_socket): when creating a
transport, pass in whether it's a client-side or server-side
transport so we know which DBusAuth to create
Diffstat (limited to 'dbus/dbus-auth.c')
-rw-r--r-- | dbus/dbus-auth.c | 140 |
1 files changed, 112 insertions, 28 deletions
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index b2fca832..566abaed 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -255,7 +255,12 @@ get_state (DBusAuth *auth) if (auth->need_disconnect) return DBUS_AUTH_STATE_NEED_DISCONNECT; else if (auth->authenticated) - return DBUS_AUTH_STATE_AUTHENTICATED; + { + if (_dbus_string_get_length (&auth->incoming) > 0) + return DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES; + else + return DBUS_AUTH_STATE_AUTHENTICATED; + } else if (auth->needed_memory) return DBUS_AUTH_STATE_WAITING_FOR_MEMORY; else if (_dbus_string_get_length (&auth->outgoing) > 0) @@ -272,7 +277,10 @@ shutdown_mech (DBusAuth *auth) auth->authenticated = FALSE; if (auth->mech != NULL) - { + { + _dbus_verbose ("Shutting down mechanism %s\n", + auth->mech->mechanism); + if (DBUS_AUTH_IS_CLIENT (auth)) (* auth->mech->client_shutdown_func) (auth); else @@ -483,6 +491,9 @@ process_auth (DBusAuth *auth, auth->mech = find_mech (&mech); if (auth->mech != NULL) { + _dbus_verbose ("Trying mechanism %s\n", + auth->mech->mechanism); + if (!(* auth->mech->server_data_func) (auth, &decoded_response)) goto failed; @@ -578,6 +589,7 @@ process_error_server (DBusAuth *auth, return TRUE; } +/* return FALSE if no memory, TRUE if all OK */ static dbus_bool_t get_word (const DBusString *str, int *start, @@ -585,9 +597,10 @@ get_word (const DBusString *str, { int i; + _dbus_string_skip_blank (str, *start, start); _dbus_string_find_blank (str, *start, &i); - - if (i != *start) + + if (i > *start) { if (!_dbus_string_copy_len (str, *start, i, word, 0)) return FALSE; @@ -616,7 +629,7 @@ process_mechanisms (DBusAuth *auth, { DBusString m; const DBusAuthMechanismHandler *mech; - + if (!_dbus_string_init (&m, _DBUS_INT_MAX)) goto nomem; @@ -635,11 +648,24 @@ process_mechanisms (DBusAuth *auth, * preference. Of course when the server is us, * it lists things in that order anyhow. */ + + _dbus_verbose ("Adding mechanism %s to list we will try\n", + mech->mechanism); if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try, (void*) mech)) goto nomem; } + else + { + const char *s; + + _dbus_string_get_const_data (&m, &s); + _dbus_verbose ("Server offered mechanism \"%s\" that we don't know how to use\n", + s); + } + + _dbus_string_free (&m); } auth->already_got_mechanisms = TRUE; @@ -706,7 +732,11 @@ process_rejected (DBusAuth *auth, 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); } else { @@ -815,25 +845,53 @@ process_command (DBusAuth *auth) auth->needed_memory = TRUE; return FALSE; } + + if (eol > _DBUS_ONE_MEGABYTE) + { + /* This is a giant line, someone is trying to hose us. */ + if (!_dbus_string_append (&auth->outgoing, "ERROR \"Command too long\"\r\n")) + goto out; + else + goto next_command; + } if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &command, 0)) goto out; + + if (!_dbus_string_validate_ascii (&command, 0, + _dbus_string_get_length (&command))) + { + _dbus_verbose ("Command contained non-ASCII chars or embedded nul\n"); + if (!_dbus_string_append (&auth->outgoing, "ERROR \"Command contained non-ASCII\"\r\n")) + goto out; + else + goto next_command; + } + + { + const char *q; + _dbus_string_get_const_data (&command, &q); + _dbus_verbose ("got command \"%s\"\n", q); + } _dbus_string_find_blank (&command, 0, &i); _dbus_string_skip_blank (&command, i, &j); - if (i != j) - _dbus_string_delete (&command, i, j); + if (j > i) + _dbus_string_delete (&command, i, j - i); if (!_dbus_string_move (&command, i, &args, 0)) goto out; - + i = 0; while (auth->handlers[i].command != NULL) { if (_dbus_string_equal_c_str (&command, auth->handlers[i].command)) { + _dbus_verbose ("Processing auth command %s\n", + auth->handlers[i].command); + if (!(* auth->handlers[i].func) (auth, &command, &args)) goto out; @@ -847,6 +905,8 @@ process_command (DBusAuth *auth) if (!process_unknown (auth, &command, &args)) goto out; } + + next_command: /* We've succeeded in processing the whole command so drop it out * of the incoming buffer and return TRUE to try another command. @@ -1002,6 +1062,15 @@ _dbus_auth_do_work (DBusAuth *auth) _dbus_verbose ("Disconnecting due to excessive data buffered in auth phase\n"); break; } + + if (auth->mech == NULL && + auth->already_got_mechanisms && + DBUS_AUTH_CLIENT (auth)->mechs_to_try == NULL) + { + auth->need_disconnect = TRUE; + _dbus_verbose ("Disconnecting because we are out of mechanisms to try using\n"); + break; + } } while (process_command (auth)); @@ -1009,41 +1078,55 @@ _dbus_auth_do_work (DBusAuth *auth) } /** - * Gets bytes that need to be sent to the - * peer we're conversing with. + * Gets bytes that need to be sent to the peer we're conversing with. + * After writing some bytes, _dbus_auth_bytes_sent() must be called + * to notify the auth object that they were written. * * @param auth the auth conversation - * @param str initialized string object to be filled in with bytes to send - * @returns #FALSE if not enough memory to fill in the bytes + * @param str return location for a ref to the buffer to send + * @returns #FALSE if nothing to send */ dbus_bool_t -_dbus_auth_get_bytes_to_send (DBusAuth *auth, - DBusString *str) +_dbus_auth_get_bytes_to_send (DBusAuth *auth, + const DBusString **str) { _dbus_assert (auth != NULL); _dbus_assert (str != NULL); + + *str = NULL; if (DBUS_AUTH_IN_END_STATE (auth)) return FALSE; - auth->needed_memory = FALSE; - - _dbus_string_set_length (str, 0); + if (_dbus_string_get_length (&auth->outgoing) == 0) + return FALSE; - if (!_dbus_string_move (&auth->outgoing, - 0, str, 0)) - { - auth->needed_memory = TRUE; - return FALSE; - } + *str = &auth->outgoing; - if (auth->authenticated_pending_output) - auth->authenticated = TRUE; - return TRUE; } /** + * Notifies the auth conversation object that + * the given number of bytes of the outgoing buffer + * have been written out. + * + * @param auth the auth conversation + * @param bytes_sent number of bytes written out + */ +void +_dbus_auth_bytes_sent (DBusAuth *auth, + int bytes_sent) +{ + _dbus_string_delete (&auth->outgoing, + 0, bytes_sent); + + if (auth->authenticated_pending_output && + _dbus_string_get_length (&auth->outgoing) == 0) + auth->authenticated = TRUE; +} + +/** * Stores bytes received from the peer we're conversing with. * * @param auth the auth conversation @@ -1082,7 +1165,7 @@ _dbus_auth_bytes_received (DBusAuth *auth, * succeeded. * * @param auth the auth conversation - * @param str string to place the unused bytes in + * @param str string to append the unused bytes to * @returns #FALSE if not enough memory to return the bytes */ dbus_bool_t @@ -1093,7 +1176,8 @@ _dbus_auth_get_unused_bytes (DBusAuth *auth, return FALSE; if (!_dbus_string_move (&auth->incoming, - 0, str, 0)) + 0, str, + _dbus_string_get_length (str))) return FALSE; return TRUE; |