diff options
-rw-r--r-- | bus/dispatch.c | 5 | ||||
-rw-r--r-- | dbus/dbus-auth.c | 184 | ||||
-rw-r--r-- | dbus/dbus-auth.h | 2 | ||||
-rw-r--r-- | dbus/dbus-transport-protected.h | 3 | ||||
-rw-r--r-- | dbus/dbus-transport-socket.c | 6 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 1 |
6 files changed, 170 insertions, 31 deletions
diff --git a/bus/dispatch.c b/bus/dispatch.c index ca9a8433..8ed88dad 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -4791,6 +4791,11 @@ bus_unix_fds_passing_test(const DBusString *test_data_dir) if (!_dbus_close(two[0], &error)) _dbus_assert_not_reached("Failed to close pipe #2 "); + if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD))) + _dbus_assert_not_reached("Connection cannot do fd passing"); + + if (!(dbus_connection_can_send_type(bar, DBUS_TYPE_UNIX_FD))) + _dbus_assert_not_reached("Connection cannot do fd passing"); if (!dbus_connection_send (foo, m, NULL)) _dbus_assert_not_reached("Failed to send fds"); diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index ec7cf312..f1c83ae4 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -122,7 +122,9 @@ typedef enum { DBUS_AUTH_COMMAND_REJECTED, DBUS_AUTH_COMMAND_OK, DBUS_AUTH_COMMAND_ERROR, - DBUS_AUTH_COMMAND_UNKNOWN + DBUS_AUTH_COMMAND_UNKNOWN, + DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD, + DBUS_AUTH_COMMAND_AGREE_UNIX_FD } DBusAuthCommand; /** @@ -184,6 +186,9 @@ struct DBusAuth unsigned int already_got_mechanisms : 1; /**< Client already got mech list */ unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */ unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */ + + unsigned int unix_fd_possible : 1; /**< This side could do unix fd passing */ + unsigned int unix_fd_negotiated : 1; /**< Unix fd was successfully negotiated */ }; /** @@ -223,9 +228,10 @@ static dbus_bool_t send_rejected (DBusAuth *auth); static dbus_bool_t send_error (DBusAuth *auth, const char *message); static dbus_bool_t send_ok (DBusAuth *auth); -static dbus_bool_t send_begin (DBusAuth *auth, - const DBusString *args_from_ok); +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); /** * Client states @@ -264,6 +270,9 @@ static dbus_bool_t handle_client_state_waiting_for_ok (DBusAuth *aut static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth *auth, DBusAuthCommand command, const DBusString *args); +static dbus_bool_t handle_client_state_waiting_for_agree_unix_fd (DBusAuth *auth, + DBusAuthCommand command, + const DBusString *args); static const DBusAuthStateData client_state_need_send_auth = { "NeedSendAuth", NULL @@ -277,7 +286,10 @@ static const DBusAuthStateData client_state_waiting_for_ok = { static const DBusAuthStateData client_state_waiting_for_reject = { "WaitingForReject", handle_client_state_waiting_for_reject }; - +static const DBusAuthStateData client_state_waiting_for_agree_unix_fd = { + "WaitingForAgreeUnixFD", handle_client_state_waiting_for_agree_unix_fd +}; + /** * Common terminal states. Terminal states have handler == NULL. */ @@ -1522,9 +1534,21 @@ send_ok (DBusAuth *auth) } static dbus_bool_t -send_begin (DBusAuth *auth, - const DBusString *args_from_ok) +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 */ @@ -1549,20 +1573,19 @@ send_begin (DBusAuth *auth, return TRUE; } - if (_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0) && - _dbus_string_append (&auth->outgoing, "BEGIN\r\n")) - { - _dbus_verbose ("Got GUID '%s' from the server\n", - _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server)); - - goto_state (auth, &common_state_authenticated); - return TRUE; - } - else - { + 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 @@ -1622,6 +1645,33 @@ process_data (DBusAuth *auth, } 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) @@ -1712,9 +1762,13 @@ handle_server_state_waiting_for_auth (DBusAuth *auth, case DBUS_AUTH_COMMAND_ERROR: return send_rejected (auth); + case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + 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: default: return send_error (auth, "Unknown command"); } @@ -1741,9 +1795,13 @@ handle_server_state_waiting_for_data (DBusAuth *auth, goto_state (auth, &common_state_need_disconnect); return TRUE; + case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + 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: default: return send_error (auth, "Unknown command"); } @@ -1766,9 +1824,16 @@ handle_server_state_waiting_for_begin (DBusAuth *auth, goto_state (auth, &common_state_authenticated); return TRUE; + case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + if (auth->unix_fd_possible) + return send_agree_unix_fd(auth); + else + return send_error(auth, "Unix FD 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: default: return send_error (auth, "Unknown command"); @@ -1933,7 +1998,7 @@ handle_client_state_waiting_for_data (DBusAuth *auth, return process_rejected (auth, args); case DBUS_AUTH_COMMAND_OK: - return send_begin (auth, args); + return process_ok(auth, args); case DBUS_AUTH_COMMAND_ERROR: return send_cancel (auth); @@ -1942,6 +2007,8 @@ handle_client_state_waiting_for_data (DBusAuth *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_AGREE_UNIX_FD: default: return send_error (auth, "Unknown command"); } @@ -1958,7 +2025,7 @@ handle_client_state_waiting_for_ok (DBusAuth *auth, return process_rejected (auth, args); case DBUS_AUTH_COMMAND_OK: - return send_begin (auth, args); + return process_ok(auth, args); case DBUS_AUTH_COMMAND_DATA: case DBUS_AUTH_COMMAND_ERROR: @@ -1968,6 +2035,8 @@ handle_client_state_waiting_for_ok (DBusAuth *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_AGREE_UNIX_FD: default: return send_error (auth, "Unknown command"); } @@ -1990,12 +2059,46 @@ handle_client_state_waiting_for_reject (DBusAuth *auth, case DBUS_AUTH_COMMAND_OK: case DBUS_AUTH_COMMAND_ERROR: case DBUS_AUTH_COMMAND_UNKNOWN: + case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: + case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: default: goto_state (auth, &common_state_need_disconnect); return TRUE; } } +static dbus_bool_t +handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth, + DBusAuthCommand command, + const DBusString *args) +{ + switch (command) + { + case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: + _dbus_assert(auth->unix_fd_possible); + auth->unix_fd_negotiated = TRUE; + _dbus_verbose("Sucessfully negotiated UNIX FD passing\n"); + return send_begin (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_begin (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: + default: + return send_error (auth, "Unknown command"); + } +} + /** * Mapping from command name to enum */ @@ -2005,13 +2108,15 @@ typedef struct { } DBusAuthCommandName; static const DBusAuthCommandName auth_command_names[] = { - { "AUTH", DBUS_AUTH_COMMAND_AUTH }, - { "CANCEL", DBUS_AUTH_COMMAND_CANCEL }, - { "DATA", DBUS_AUTH_COMMAND_DATA }, - { "BEGIN", DBUS_AUTH_COMMAND_BEGIN }, - { "REJECTED", DBUS_AUTH_COMMAND_REJECTED }, - { "OK", DBUS_AUTH_COMMAND_OK }, - { "ERROR", DBUS_AUTH_COMMAND_ERROR } + { "AUTH", DBUS_AUTH_COMMAND_AUTH }, + { "CANCEL", DBUS_AUTH_COMMAND_CANCEL }, + { "DATA", DBUS_AUTH_COMMAND_DATA }, + { "BEGIN", DBUS_AUTH_COMMAND_BEGIN }, + { "REJECTED", DBUS_AUTH_COMMAND_REJECTED }, + { "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 } }; static DBusAuthCommand @@ -2685,6 +2790,31 @@ _dbus_auth_set_context (DBusAuth *auth, &auth->context, 0, _dbus_string_get_length (context)); } +/** + * Sets whether unix fd passing is potentially on the transport and + * hence shall be negotiated. + * + * @param auth the auth conversation + * @param b TRUE when unix fd passing shall be negotiated, otherwise FALSE + */ +void +_dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b) +{ + auth->unix_fd_possible = b; +} + +/** + * Queries whether unix fd passing was sucessfully negotiated. + * + * @param auth the auth conversion + * @returns #TRUE when unix fd passing was negotiated. + */ +dbus_bool_t +_dbus_auth_get_unix_fd_negotiated(DBusAuth *auth) +{ + return auth->unix_fd_negotiated; +} + /** @} */ /* tests in dbus-auth-util.c */ diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h index 14f8320a..5680df11 100644 --- a/dbus/dbus-auth.h +++ b/dbus/dbus-auth.h @@ -75,6 +75,8 @@ dbus_bool_t _dbus_auth_set_context (DBusAuth *auth, const DBusString *context); 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); DBUS_END_DECLS diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 023549d0..8c389a6d 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -144,6 +144,9 @@ DBusTransportOpenResult _dbus_transport_open_platform_specific (DBusAddressEntry DBusTransport **transport_p, DBusError *error); +#define DBUS_TRANSPORT_CAN_SEND_UNIX_FD(x) \ + _dbus_auth_get_unix_fd_negotiated((x)->auth) + DBUS_END_DECLS #endif /* DBUS_TRANSPORT_PROTECTED_H */ diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index cc49c851..76699506 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -594,7 +594,7 @@ do_writing (DBusTransport *transport) #endif #ifdef HAVE_UNIX_FD_PASSING - if (socket_transport->message_bytes_written <= 0 && transport->can_pass_unix_fd) + if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) { /* Send the fds along with the first byte of the message */ const int *unix_fds; @@ -777,7 +777,7 @@ do_reading (DBusTransport *transport) &buffer); #ifdef HAVE_UNIX_FD_PASSING - if (transport->can_pass_unix_fd) + if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) { int *fds, n_fds; @@ -1244,7 +1244,7 @@ _dbus_transport_new_for_socket (int fd, goto failed_4; #ifdef HAVE_UNIX_FD_PASSING - socket_transport->base.can_pass_unix_fd = _dbus_socket_can_pass_unix_fd(fd); + _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd)); #endif socket_transport->fd = fd; diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 97ee0e9b..7ba01357 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -184,7 +184,6 @@ _dbus_transport_init_base (DBusTransport *transport, transport->credentials = creds; #ifdef HAVE_UNIX_FD_PASSING - transport->can_pass_unix_fd = FALSE; transport->unix_fds = NULL; transport->n_unix_fds = 0; #endif |