+}
+
+static dbus_bool_t
+send_rejected (DBusAuth *auth)
+{
+ DBusString command;
+ DBusAuthServer *server_auth;
+ int i;
+
+ if (!_dbus_string_init (&command))
+ return FALSE;
+
+ if (!_dbus_string_append (&command,
+ "REJECTED"))
+ goto nomem;
+
+ i = 0;
+ while (all_mechanisms[i].mechanism != NULL)
+ {
+ if (!_dbus_string_append (&command,
+ " "))
+ goto nomem;
+
+ if (!_dbus_string_append (&command,
+ all_mechanisms[i].mechanism))
+ goto nomem;
+
+ ++i;
+ }
+
+ if (!_dbus_string_append (&command, "\r\n"))
+ goto nomem;
+
+ if (!_dbus_string_copy (&command, 0, &auth->outgoing,
+ _dbus_string_get_length (&auth->outgoing)))
+ goto nomem;
+
+ shutdown_mech (auth);
+
+ _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
+ server_auth = DBUS_AUTH_SERVER (auth);
+ server_auth->failures += 1;
+
+ if (server_auth->failures >= server_auth->max_failures)
+ goto_state (auth, &common_state_need_disconnect);
+ else
+ goto_state (auth, &server_state_waiting_for_auth);
+
+ _dbus_string_free (&command);
+
+ return TRUE;
+
+ nomem:
+ _dbus_string_free (&command);
+ return FALSE;
+}
+
+static dbus_bool_t
+send_error (DBusAuth *auth, const char *message)
+{
+ return _dbus_string_append_printf (&auth->outgoing,
+ "ERROR \"%s\"\r\n", message);
+}
+
+static dbus_bool_t
+send_ok (DBusAuth *auth)
+{
+ 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
+ {
+ _dbus_string_set_length (&auth->outgoing, orig_len);
+ return FALSE;
+ }
+}
+
+static dbus_bool_t
+send_begin (DBusAuth *auth)
+{
+
+ if (!_dbus_string_append (&auth->outgoing,
+ "BEGIN\r\n"))
+ return FALSE;
+
+ goto_state (auth, &common_state_authenticated);
+ return TRUE;
+}
+
+static dbus_bool_t
+process_ok(DBusAuth *auth,
+ const DBusString *args_from_ok) {
+
+ 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_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
+ return FALSE;
+ }
+
+ _dbus_verbose ("Got GUID '%s' from the server\n",
+ _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
+
+ if (auth->unix_fd_possible)
+ return send_negotiate_unix_fd(auth);
+
+ _dbus_verbose("Not negotiating unix fd passing, since not possible\n");
+ return send_begin (auth);
+}
+
+static dbus_bool_t
+send_cancel (DBusAuth *auth)
+{
+ if (_dbus_string_append (&auth->outgoing, "CANCEL\r\n"))
+ {
+ goto_state (auth, &client_state_waiting_for_reject);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static dbus_bool_t
+process_data (DBusAuth *auth,
+ const DBusString *args,
+ DBusAuthDataFunction data_func)
+{
+ int end;
+ DBusString decoded;
+
+ if (!_dbus_string_init (&decoded))
+ return FALSE;
+
+ if (!_dbus_string_hex_decode (args, 0, &end, &decoded, 0))
+ {
+ _dbus_string_free (&decoded);
+ return FALSE;
+ }
+
+ if (_dbus_string_get_length (args) != end)
+ {
+ _dbus_string_free (&decoded);
+ if (!send_error (auth, "Invalid hex encoding"))
+ return FALSE;
+
+ return TRUE;
+ }
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+ if (_dbus_string_validate_ascii (&decoded, 0,
+ _dbus_string_get_length (&decoded)))
+ _dbus_verbose ("%s: data: '%s'\n",
+ DBUS_AUTH_NAME (auth),
+ _dbus_string_get_const_data (&decoded));
+#endif
+
+ if (!(* data_func) (auth, &decoded))
+ {
+ _dbus_string_free (&decoded);
+ return FALSE;
+ }
+
+ _dbus_string_free (&decoded);
+ return TRUE;
+}
+
+static dbus_bool_t
+send_negotiate_unix_fd (DBusAuth *auth)
+{
+ if (!_dbus_string_append (&auth->outgoing,
+ "NEGOTIATE_UNIX_FD\r\n"))
+ return FALSE;
+
+ goto_state (auth, &client_state_waiting_for_agree_unix_fd);
+ return TRUE;
+}
+
+static dbus_bool_t
+send_agree_unix_fd (DBusAuth *auth)
+{
+ _dbus_assert(auth->unix_fd_possible);
+
+ auth->unix_fd_negotiated = TRUE;
+ _dbus_verbose("Agreed to UNIX FD passing\n");
+
+ if (!_dbus_string_append (&auth->outgoing,
+ "AGREE_UNIX_FD\r\n"))
+ return FALSE;
+
+ goto_state (auth, &server_state_waiting_for_begin);
+ return TRUE;
+}
+
+static dbus_bool_t
+handle_auth (DBusAuth *auth, const DBusString *args)
+{
+ if (_dbus_string_get_length (args) == 0)