diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | configure.in | 14 | ||||
-rw-r--r-- | dbus/dbus-auth.c | 96 | ||||
-rw-r--r-- | dbus/dbus-auth.h | 1 | ||||
-rw-r--r-- | dbus/dbus-transport-protected.h | 4 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 57 | ||||
-rw-r--r-- | doc/TODO | 7 | ||||
-rw-r--r-- | doc/dbus-specification.xml | 18 | ||||
-rw-r--r-- | test/data/auth/fallback.auth-script | 2 |
9 files changed, 187 insertions, 29 deletions
@@ -1,3 +1,20 @@ +2005-05-05 Havoc Pennington <hp@redhat.com> + + * configure.in (LT_*): add notes on how the libtool versioning + works to save thinking. Increment soname to indicate protocol + breakage (though really the library interface hasn't changed I + guess) + + * dbus/dbus-transport.c (_dbus_transport_get_is_authenticated): + verify the GUID received from server matches what we were + expecting, if we had an expectation + + * dbus/dbus-auth.c (send_ok): send GUID along with the OK command + (_dbus_auth_get_guid_from_server): new function + (send_begin): parse the OK args + + * doc/dbus-specification.xml: add GUID to the auth protocol + 2005-05-05 John (J5) Palmieri <johnp@redhat.com> * Fix my name in previous changelog ;) diff --git a/configure.in b/configure.in index cc918e74..111ef6c8 100644 --- a/configure.in +++ b/configure.in @@ -17,13 +17,23 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The name of the gettext d ## must come before we use the $USE_MAINTAINER_MODE variable later AM_MAINTAINER_MODE -# libtool versioning - this applies to libhal and libhal-storage +# libtool versioning - this applies to libdbus # # See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details # -LT_CURRENT=1 + +## increment if the interface has additions, changes, removals. +LT_CURRENT=2 + +## increment any time the source changes; set to +## 0 if you increment CURRENT LT_REVISION=0 + +## increment if any interfaces have been added; set to 0 +## if any interfaces have been changed or removed. removal has +## precedence over adding, so set to 0 if both happened. LT_AGE=0 + AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index 2a1bbd4c..ced93303 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -199,6 +199,8 @@ typedef struct DBusAuth base; /**< Parent class */ DBusList *mechs_to_try; /**< Mechanisms we got from the server that we're going to try using */ + + DBusString guid_from_server; /**< GUID received from server */ } DBusAuthClient; @@ -226,7 +228,8 @@ 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); +static dbus_bool_t send_begin (DBusAuth *auth, + const DBusString *args_from_ok); static dbus_bool_t send_cancel (DBusAuth *auth); /** @@ -1329,25 +1332,69 @@ send_error (DBusAuth *auth, const char *message) static dbus_bool_t send_ok (DBusAuth *auth) { - if (_dbus_string_append (&auth->outgoing, "OK\r\n")) + 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 - return FALSE; + { + _dbus_string_set_length (&auth->outgoing, orig_len); + return FALSE; + } } static dbus_bool_t -send_begin (DBusAuth *auth) +send_begin (DBusAuth *auth, + const DBusString *args_from_ok) { - if (_dbus_string_append (&auth->outgoing, "BEGIN\r\n")) + 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_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 - return FALSE; + { + _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0); + return FALSE; + } } static dbus_bool_t @@ -1364,8 +1411,8 @@ send_cancel (DBusAuth *auth) static dbus_bool_t process_data (DBusAuth *auth, - const DBusString *args, - DBusAuthDataFunction data_func) + const DBusString *args, + DBusAuthDataFunction data_func) { int end; DBusString decoded; @@ -1710,7 +1757,7 @@ handle_client_state_waiting_for_data (DBusAuth *auth, return process_rejected (auth, args); case DBUS_AUTH_COMMAND_OK: - return send_begin (auth); + return send_begin (auth, args); case DBUS_AUTH_COMMAND_ERROR: return send_cancel (auth); @@ -1735,7 +1782,7 @@ handle_client_state_waiting_for_ok (DBusAuth *auth, return process_rejected (auth, args); case DBUS_AUTH_COMMAND_OK: - return send_begin (auth); + return send_begin (auth, args); case DBUS_AUTH_COMMAND_DATA: case DBUS_AUTH_COMMAND_ERROR: @@ -1974,10 +2021,19 @@ DBusAuth* _dbus_auth_client_new (void) { DBusAuth *auth; + DBusString guid_str; + + if (!_dbus_string_init (&guid_str)) + return NULL; auth = _dbus_auth_new (sizeof (DBusAuthClient)); if (auth == NULL) - return NULL; + { + _dbus_string_free (&guid_str); + return NULL; + } + + DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str; auth->side = auth_side_client; auth->state = &client_state_need_send_auth; @@ -2027,6 +2083,7 @@ _dbus_auth_unref (DBusAuth *auth) if (DBUS_AUTH_IS_CLIENT (auth)) { + _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server); _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try); } else @@ -2402,6 +2459,23 @@ _dbus_auth_get_identity (DBusAuth *auth, } /** + * Gets the GUID from the server if we've authenticated; gets + * #NULL otherwise. + * @param auth the auth object + * @returns the GUID in ASCII hex format + */ +const char* +_dbus_auth_get_guid_from_server (DBusAuth *auth) +{ + _dbus_assert (DBUS_AUTH_IS_CLIENT (auth)); + + if (auth->state == &common_state_authenticated) + return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server); + else + return NULL; +} + +/** * Sets the "authentication context" which scopes cookies * with the DBUS_COOKIE_SHA1 auth mechanism for example. * diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h index 6ed5040e..9cff8b56 100644 --- a/dbus/dbus-auth.h +++ b/dbus/dbus-auth.h @@ -74,6 +74,7 @@ void _dbus_auth_get_identity (DBusAuth *auth, DBusCredentials *credentials); dbus_bool_t _dbus_auth_set_context (DBusAuth *auth, const DBusString *context); +const char* _dbus_auth_get_guid_from_server(DBusAuth *auth); DBUS_END_DECLS diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 879c3db8..f3ad3370 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -96,7 +96,9 @@ struct DBusTransport DBusCounter *live_messages_size; /**< Counter for size of all live messages. */ - char *address; /**< Address of this server */ + char *address; /**< Address of the server we are connecting to (#NULL for the server side of a transport) */ + + char *expected_guid; /**< GUID we expect the server to have, #NULL on server side or if we don't have an expectation */ DBusAllowUnixUserFunction unix_user_function; /**< Function for checking whether a user is authorized. */ void *unix_user_data; /**< Data for unix_user_function */ diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index b271d944..cfc86e4a 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -153,6 +153,8 @@ _dbus_transport_init_base (DBusTransport *transport, transport->unix_user_function = NULL; transport->unix_user_data = NULL; transport->free_unix_user_data = NULL; + + transport->expected_guid = NULL; /* Try to default to something that won't totally hose the system, * but doesn't impose too much of a limitation. @@ -195,6 +197,7 @@ _dbus_transport_finalize_base (DBusTransport *transport) 0, NULL, NULL); _dbus_counter_unref (transport->live_messages_size); dbus_free (transport->address); + dbus_free (transport->expected_guid); } /** @@ -213,7 +216,9 @@ _dbus_transport_open (DBusAddressEntry *entry, const char *address_problem_type; const char *address_problem_field; const char *address_problem_other; - const char *method; + const char *method; + const char *expected_guid_orig; + char *expected_guid; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -221,6 +226,14 @@ _dbus_transport_open (DBusAddressEntry *entry, address_problem_type = NULL; address_problem_field = NULL; address_problem_other = NULL; + expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); + expected_guid = _dbus_strdup (expected_guid_orig); + + if (expected_guid_orig != NULL && expected_guid == NULL) + { + _DBUS_SET_OOM (error); + return NULL; + } method = dbus_address_entry_get_method (entry); _dbus_assert (method != NULL); @@ -306,11 +319,20 @@ _dbus_transport_open (DBusAddressEntry *entry, } if (transport == NULL) - _DBUS_ASSERT_ERROR_IS_SET (error); + { + _DBUS_ASSERT_ERROR_IS_SET (error); + dbus_free (expected_guid); + } + else + { + transport->expected_guid = expected_guid; + } return transport; bad_address: + dbus_free (expected_guid); + if (address_problem_type != NULL) dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "Address of type %s was missing argument %s", @@ -442,6 +464,35 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) maybe_authenticated = FALSE; } } + + if (maybe_authenticated && !transport->is_server) + { + const char *server_guid; + + server_guid = _dbus_auth_get_guid_from_server (transport->auth); + _dbus_assert (server_guid != NULL); + + if (transport->expected_guid && + strcmp (transport->expected_guid, server_guid) != 0) + { + _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", + transport->expected_guid, server_guid); + _dbus_transport_disconnect (transport); + _dbus_connection_unref_unlocked (transport->connection); + return FALSE; + } + + if (transport->expected_guid == NULL) + { + transport->expected_guid = _dbus_strdup (server_guid); + + if (transport->expected_guid == NULL) + { + _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME); + return FALSE; + } + } + } /* If we've authenticated as some identity, check that the auth * identity is the same as our own identity. In the future, we @@ -518,7 +569,7 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) } } } - + transport->authenticated = maybe_authenticated; _dbus_connection_unref_unlocked (transport->connection); @@ -31,10 +31,6 @@ Important for 1.0 - dbus-pending-call.c has some API and thread safety issues to review - - transmit GUID from server to client in the auth protocol, so - connections can be shared even if the address used to connect - to them didn't have a GUID in it. - - Add test harness for selinux allow/deny cf. this message http://lists.freedesktop.org/archives/dbus/2005-April/002506.html @@ -63,6 +59,9 @@ Might as Well for 1.0 Can Be Post 1.0 === + - if the GUID is obtained only during authentication, not in the address, + we could still share the connection + - Allow a dbus_g_proxy_to_string()/g_object_to_string() that would convert the proxy to an "IOR" and dbus_g_proxy_from_string() that would decode; using these, dbus-glib users could avoid diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index ff625447..0ea43a87 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -1337,7 +1337,7 @@ <itemizedlist> <listitem><para>REJECTED <space-separated list of mechanism names></para></listitem> - <listitem><para>OK</para></listitem> + <listitem><para>OK <GUID in hex></para></listitem> <listitem><para>DATA <data in hex encoding></para></listitem> <listitem><para>ERROR</para></listitem> </itemizedlist> @@ -1478,6 +1478,10 @@ The server must not accept additional commands using this protocol after the OK command has been sent. </para> + <para> + The OK command has one argument, which is the GUID of the server. + See <xref linkend="addresses"/> for more on server GUIDs. + </para> </sect2> <sect2 id="auth-command-error"> <title>ERROR Command</title> @@ -1516,7 +1520,7 @@ (MAGIC_COOKIE is a made up mechanism) C: AUTH MAGIC_COOKIE 3138363935333137393635383634 - S: OK + S: OK 1234deadbeef C: BEGIN </programlisting> </figure> @@ -1528,7 +1532,7 @@ C: AUTH SKEY 7ab83f32ee S: DATA 8799cabb2ea93e C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f - S: OK + S: OK 1234deadbeef C: BEGIN </programlisting> </figure> @@ -1538,7 +1542,7 @@ C: FOOBAR S: ERROR C: AUTH MAGIC_COOKIE 3736343435313230333039 - S: OK + S: OK 1234deadbeef C: BEGIN </programlisting> </figure> @@ -1550,7 +1554,7 @@ C: AUTH SKEY 7ab83f32ee S: DATA 8799cabb2ea93e C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f - S: OK + S: OK 1234deadbeef C: BEGIN </programlisting> </figure> @@ -1566,7 +1570,7 @@ C: AUTH SKEY 7ab83f32ee S: DATA 8799cabb2ea93e C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f - S: OK + S: OK 1234deadbeef C: BEGIN </programlisting> </figure> @@ -1582,7 +1586,7 @@ C: AUTH SKEY 7ab83f32ee S: DATA 8799cabb2ea93e C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f - S: OK + S: OK 1234deadbeef C: BEGIN </programlisting> </figure> diff --git a/test/data/auth/fallback.auth-script b/test/data/auth/fallback.auth-script index ebe7ae28..f598b77e 100644 --- a/test/data/auth/fallback.auth-script +++ b/test/data/auth/fallback.auth-script @@ -16,7 +16,7 @@ SEND 'REJECTED EXTERNAL DBUS_COOKIE_SHA1 DBUS_TEST_NONEXISTENT_MECH' EXPECT_COMMAND AUTH ## of course real DBUS_COOKIE_SHA1 would not send this here... -SEND 'OK' +SEND 'OK 1234deadbeef' EXPECT_COMMAND BEGIN EXPECT_STATE AUTHENTICATED |