From 643fee7739774d08fb91ebf3daf5a6676f5b25a3 Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Thu, 6 May 2010 11:49:22 +0200 Subject: [PATCH 4/5] Implement negotiation of Maybe type support --- dbus/dbus-auth.c | 130 ++++++++++++++++++++++++++++++++++++++- dbus/dbus-auth.h | 3 + dbus/dbus-connection.c | 11 +++ dbus/dbus-message.c | 3 +- dbus/dbus-transport-protected.h | 2 + dbus/dbus-transport-socket.c | 2 + dbus/dbus-transport.c | 12 ++++ dbus/dbus-transport.h | 1 + 8 files changed, 160 insertions(+), 4 deletions(-) diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index 3173f34..efaeafa 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -126,7 +126,9 @@ typedef enum { DBUS_AUTH_COMMAND_ERROR, DBUS_AUTH_COMMAND_UNKNOWN, DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD, - DBUS_AUTH_COMMAND_AGREE_UNIX_FD + DBUS_AUTH_COMMAND_AGREE_UNIX_FD, + DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE, + DBUS_AUTH_COMMAND_AGREE_MAYBE } DBusAuthCommand; /** @@ -191,6 +193,9 @@ struct DBusAuth unsigned int unix_fd_possible : 1; /**< This side could do unix fd passing */ unsigned int unix_fd_negotiated : 1; /**< Unix fd was successfully negotiated */ + + unsigned int maybe_possible : 1; /**< This side supports the Maybe type */ + unsigned int maybe_negotiated : 1; /**< Maybe was successfully negotiated */ }; /** @@ -234,6 +239,8 @@ static dbus_bool_t send_begin (DBusAuth *auth); static dbus_bool_t send_cancel (DBusAuth *auth); static dbus_bool_t send_negotiate_unix_fd (DBusAuth *auth); static dbus_bool_t send_agree_unix_fd (DBusAuth *auth); +static dbus_bool_t send_negotiate_maybe (DBusAuth *auth); +static dbus_bool_t send_agree_maybe (DBusAuth *auth); /** * Client states @@ -275,6 +282,9 @@ static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth *aut static dbus_bool_t handle_client_state_waiting_for_agree_unix_fd (DBusAuth *auth, DBusAuthCommand command, const DBusString *args); +static dbus_bool_t handle_client_state_waiting_for_agree_maybe (DBusAuth *auth, + DBusAuthCommand command, + const DBusString *args); static const DBusAuthStateData client_state_need_send_auth = { "NeedSendAuth", NULL @@ -291,6 +301,9 @@ static const DBusAuthStateData client_state_waiting_for_reject = { static const DBusAuthStateData client_state_waiting_for_agree_unix_fd = { "WaitingForAgreeUnixFD", handle_client_state_waiting_for_agree_unix_fd }; +static const DBusAuthStateData client_state_waiting_for_agree_maybe = { + "WaitingForAgreeMaybe", handle_client_state_waiting_for_agree_maybe +}; /** * Common terminal states. Terminal states have handler == NULL. @@ -1587,6 +1600,10 @@ process_ok(DBusAuth *auth, return send_negotiate_unix_fd(auth); _dbus_verbose("Not negotiating unix fd passing, since not possible\n"); + + if (auth->maybe_possible) + return send_negotiate_maybe (auth); + return send_begin (auth); } @@ -1674,6 +1691,33 @@ send_agree_unix_fd (DBusAuth *auth) } static dbus_bool_t +send_negotiate_maybe (DBusAuth *auth) +{ + if (!_dbus_string_append (&auth->outgoing, + "NEGOTIATE_MAYBE\r\n")) + return FALSE; + + goto_state (auth, &client_state_waiting_for_agree_maybe); + return TRUE; +} + +static dbus_bool_t +send_agree_maybe (DBusAuth *auth) +{ + _dbus_assert(auth->maybe_possible); + + auth->maybe_negotiated = TRUE; + _dbus_verbose("Agreed to MAYBE passing\n"); + + if (!_dbus_string_append (&auth->outgoing, + "AGREE_MAYBE\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) @@ -1765,12 +1809,14 @@ handle_server_state_waiting_for_auth (DBusAuth *auth, return send_rejected (auth); case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: return send_error (auth, "Need to authenticate first"); case DBUS_AUTH_COMMAND_REJECTED: case DBUS_AUTH_COMMAND_OK: case DBUS_AUTH_COMMAND_UNKNOWN: case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + case DBUS_AUTH_COMMAND_AGREE_MAYBE: default: return send_error (auth, "Unknown command"); } @@ -1798,12 +1844,14 @@ handle_server_state_waiting_for_data (DBusAuth *auth, return TRUE; case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: return send_error (auth, "Need to authenticate first"); case DBUS_AUTH_COMMAND_REJECTED: case DBUS_AUTH_COMMAND_OK: case DBUS_AUTH_COMMAND_UNKNOWN: case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + case DBUS_AUTH_COMMAND_AGREE_MAYBE: default: return send_error (auth, "Unknown command"); } @@ -1832,10 +1880,17 @@ handle_server_state_waiting_for_begin (DBusAuth *auth, else return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible"); + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: + if (auth->maybe_possible) + return send_agree_maybe(auth); + else + return send_error(auth, "Maybe passing not supported, not authenticated or otherwise not possible"); + case DBUS_AUTH_COMMAND_REJECTED: case DBUS_AUTH_COMMAND_OK: case DBUS_AUTH_COMMAND_UNKNOWN: case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + case DBUS_AUTH_COMMAND_AGREE_MAYBE: default: return send_error (auth, "Unknown command"); @@ -2011,6 +2066,8 @@ handle_client_state_waiting_for_data (DBusAuth *auth, case DBUS_AUTH_COMMAND_UNKNOWN: case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: + case DBUS_AUTH_COMMAND_AGREE_MAYBE: default: return send_error (auth, "Unknown command"); } @@ -2039,6 +2096,8 @@ handle_client_state_waiting_for_ok (DBusAuth *auth, case DBUS_AUTH_COMMAND_UNKNOWN: case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: + case DBUS_AUTH_COMMAND_AGREE_MAYBE: default: return send_error (auth, "Unknown command"); } @@ -2063,6 +2122,8 @@ handle_client_state_waiting_for_reject (DBusAuth *auth, case DBUS_AUTH_COMMAND_UNKNOWN: case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: + case DBUS_AUTH_COMMAND_AGREE_MAYBE: default: goto_state (auth, &common_state_need_disconnect); return TRUE; @@ -2080,12 +2141,46 @@ handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth, _dbus_assert(auth->unix_fd_possible); auth->unix_fd_negotiated = TRUE; _dbus_verbose("Sucessfully negotiated UNIX FD passing\n"); - return send_begin (auth); + return send_negotiate_maybe (auth); case DBUS_AUTH_COMMAND_ERROR: _dbus_assert(auth->unix_fd_possible); auth->unix_fd_negotiated = FALSE; _dbus_verbose("Failed to negotiate UNIX FD passing\n"); + return send_negotiate_maybe (auth); + + case DBUS_AUTH_COMMAND_OK: + case DBUS_AUTH_COMMAND_DATA: + case DBUS_AUTH_COMMAND_REJECTED: + case DBUS_AUTH_COMMAND_AUTH: + case DBUS_AUTH_COMMAND_CANCEL: + case DBUS_AUTH_COMMAND_BEGIN: + case DBUS_AUTH_COMMAND_UNKNOWN: + case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: + case DBUS_AUTH_COMMAND_AGREE_MAYBE: + default: + return send_error (auth, "Unknown command"); + } +} + +static dbus_bool_t +handle_client_state_waiting_for_agree_maybe (DBusAuth *auth, + DBusAuthCommand command, + const DBusString *args) +{ + switch (command) + { + case DBUS_AUTH_COMMAND_AGREE_MAYBE: + _dbus_assert(auth->maybe_possible); + auth->maybe_negotiated = TRUE; + _dbus_verbose("Sucessfully negotiated MAYBE passing\n"); + return send_begin (auth); + + case DBUS_AUTH_COMMAND_ERROR: + _dbus_assert(auth->maybe_possible); + auth->maybe_negotiated = FALSE; + _dbus_verbose("Failed to negotiate MAYBE passing\n"); return send_begin (auth); case DBUS_AUTH_COMMAND_OK: @@ -2096,6 +2191,8 @@ handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth, case DBUS_AUTH_COMMAND_BEGIN: case DBUS_AUTH_COMMAND_UNKNOWN: case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + case DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE: default: return send_error (auth, "Unknown command"); } @@ -2118,7 +2215,9 @@ static const DBusAuthCommandName auth_command_names[] = { { "OK", DBUS_AUTH_COMMAND_OK }, { "ERROR", DBUS_AUTH_COMMAND_ERROR }, { "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD }, - { "AGREE_UNIX_FD", DBUS_AUTH_COMMAND_AGREE_UNIX_FD } + { "AGREE_UNIX_FD", DBUS_AUTH_COMMAND_AGREE_UNIX_FD }, + { "NEGOTIATE_MAYBE", DBUS_AUTH_COMMAND_NEGOTIATE_MAYBE }, + { "AGREE_MAYBE", DBUS_AUTH_COMMAND_AGREE_MAYBE } }; static DBusAuthCommand @@ -2817,6 +2916,31 @@ _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth) return auth->unix_fd_negotiated; } +/** + * Sets whether maybe passing was enabled by the client and + * hence shall be negotiated. + * + * @param auth the auth conversation + * @param b TRUE if maybe passing shall be negotiated, otherwise FALSE + */ +void +_dbus_auth_set_maybe_possible(DBusAuth *auth, dbus_bool_t b) +{ + auth->maybe_possible = b; +} + +/** + * Queries whether maybe passing was sucessfully negotiated. + * + * @param auth the auth conversion + * @returns #TRUE if maybe passing was negotiated. + */ +dbus_bool_t +_dbus_auth_get_maybe_negotiated(DBusAuth *auth) +{ + return auth->maybe_negotiated; +} + /** @} */ /* tests in dbus-auth-util.c */ diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h index ae3f364..13d6fba 100644 --- a/dbus/dbus-auth.h +++ b/dbus/dbus-auth.h @@ -77,6 +77,9 @@ const char* _dbus_auth_get_guid_from_server(DBusAuth *auth); void _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b); dbus_bool_t _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth); +void _dbus_auth_set_maybe_possible (DBusAuth *auth, dbus_bool_t b); +dbus_bool_t _dbus_auth_get_maybe_negotiated(DBusAuth *auth); + DBUS_END_DECLS diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 5a595d8..c5cf815 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -3098,6 +3098,17 @@ dbus_connection_can_send_type(DBusConnection *connection, if (!_dbus_type_is_valid(type)) return FALSE; + if (type == DBUS_TYPE_MAYBE) + { + dbus_bool_t b; + + CONNECTION_LOCK (connection); + b = _dbus_transport_can_pass_maybe (connection->transport); + CONNECTION_UNLOCK (connection); + + return b; + } + if (type != DBUS_TYPE_UNIX_FD) return TRUE; diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index bf22017..5960d8c 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -2630,7 +2630,8 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter, _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); _dbus_return_val_if_fail (_DBUS_TYPE_IS_ARRAYLIKE (real->u.writer.container_type), FALSE); - _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_MAYBE && n_elements < 2, FALSE); + _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY + || (real->u.writer.container_type == DBUS_TYPE_MAYBE && n_elements < 2), FALSE); _dbus_return_val_if_fail (value != NULL, FALSE); _dbus_return_val_if_fail (n_elements >= 0, FALSE); _dbus_return_val_if_fail (n_elements <= diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 44b9d78..3462ed4 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -140,6 +140,8 @@ DBusTransportOpenResult _dbus_transport_open_platform_specific (DBusAddressEntry #define DBUS_TRANSPORT_CAN_SEND_UNIX_FD(x) \ _dbus_auth_get_unix_fd_negotiated((x)->auth) +#define DBUS_TRANSPORT_CAN_SEND_MAYBE(x) \ + _dbus_auth_get_maybe_negotiated((x)->auth) DBUS_END_DECLS diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index 1d4c2bf..28fd49b 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -1268,6 +1268,8 @@ _dbus_transport_new_for_socket (int fd, _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd)); #endif + _dbus_auth_set_maybe_possible (socket_transport->base.auth, TRUE); + socket_transport->fd = fd; socket_transport->message_bytes_written = 0; diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index a078f7c..bb35529 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -829,6 +829,18 @@ _dbus_transport_can_pass_unix_fd(DBusTransport *transport) } /** + * Returns TRUE if the transport supports sending maybes. + * + * @param transport the transport + * @returns #TRUE if TRUE it is possible to send maybes across the transport. + */ +dbus_bool_t +_dbus_transport_can_pass_maybe (DBusTransport *transport) +{ + return DBUS_TRANSPORT_CAN_SEND_MAYBE (transport); +} + +/** * Gets the address of a transport. It will be * #NULL for a server-side transport. * diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 0db048a..a0d3972 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -41,6 +41,7 @@ dbus_bool_t _dbus_transport_get_is_connected (DBusTransport dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_anonymous (DBusTransport *transport); dbus_bool_t _dbus_transport_can_pass_unix_fd (DBusTransport *transport); +dbus_bool_t _dbus_transport_can_pass_maybe (DBusTransport *transport); const char* _dbus_transport_get_address (DBusTransport *transport); const char* _dbus_transport_get_server_id (DBusTransport *transport); -- 1.7.3.2