diff options
author | Dan Winship <danw@gnome.org> | 2012-12-28 16:45:31 -0500 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2014-03-28 13:28:43 -0400 |
commit | 94ab8c1140f58e762e747344ec522521f8a518af (patch) | |
tree | d1fd7df7698faae426dda0773cd5a2ee652484a3 | |
parent | 6c14af04775a9de4dfa3fa0cc15a7ad0462ef3d9 (diff) | |
download | libsoup-wip/auth.tar.gz |
soup-message: expose auth/proxy-authwip/auth
Add SoupMessage:auth and :proxy-auth properties, make the
corresponding getters and setters public, so that callers can force
their own authentication in some cases.
https://bugzilla.gnome.org/show_bug.cgi?id=690839
-rw-r--r-- | libsoup/libsoup-2.4.sym | 4 | ||||
-rw-r--r-- | libsoup/soup-auth-manager.c | 1 | ||||
-rw-r--r-- | libsoup/soup-message-private.h | 8 | ||||
-rw-r--r-- | libsoup/soup-message.c | 173 | ||||
-rw-r--r-- | libsoup/soup-message.h | 16 | ||||
-rw-r--r-- | tests/auth-test.c | 57 |
6 files changed, 230 insertions, 29 deletions
diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index be4cd7f4..dfea6791 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -227,11 +227,13 @@ soup_message_disable_feature soup_message_finished soup_message_flags_get_type soup_message_get_address +soup_message_get_auth soup_message_get_first_party soup_message_get_flags soup_message_get_https_status soup_message_get_http_version soup_message_get_priority +soup_message_get_proxy_auth soup_message_get_soup_request soup_message_get_type soup_message_get_uri @@ -276,11 +278,13 @@ soup_message_new soup_message_new_from_uri soup_message_priority_get_type soup_message_restarted +soup_message_set_auth soup_message_set_chunk_allocator soup_message_set_first_party soup_message_set_flags soup_message_set_http_version soup_message_set_priority +soup_message_set_proxy_auth soup_message_set_redirect soup_message_set_request soup_message_set_response diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index f40a9282..c2b39eb1 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -14,7 +14,6 @@ #include "soup-auth-manager.h" #include "soup.h" #include "soup-connection-auth.h" -#include "soup-message-private.h" #include "soup-message-queue.h" #include "soup-path-map.h" #include "soup-session-private.h" diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 35cc9887..c26d4761 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -89,14 +89,6 @@ void soup_message_io_server (SoupMessage *msg, gpointer user_data); void soup_message_io_cleanup (SoupMessage *msg); -/* Auth handling */ -void soup_message_set_auth (SoupMessage *msg, - SoupAuth *auth); -SoupAuth *soup_message_get_auth (SoupMessage *msg); -void soup_message_set_proxy_auth (SoupMessage *msg, - SoupAuth *auth); -SoupAuth *soup_message_get_proxy_auth (SoupMessage *msg); - /* I/O */ void soup_message_io_stop (SoupMessage *msg); void soup_message_io_finished (SoupMessage *msg); diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 23fd8b08..54f45686 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -139,6 +139,8 @@ enum { PROP_TLS_CERTIFICATE, PROP_TLS_ERRORS, PROP_PRIORITY, + PROP_AUTH, + PROP_PROXY_AUTH, LAST_PROP }; @@ -244,6 +246,12 @@ soup_message_set_property (GObject *object, guint prop_id, case PROP_PRIORITY: priv->priority = g_value_get_enum (value); break; + case PROP_AUTH: + soup_message_set_auth (msg, g_value_get_object (value)); + break; + case PROP_PROXY_AUTH: + soup_message_set_proxy_auth (msg, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -314,6 +322,12 @@ soup_message_get_property (GObject *object, guint prop_id, case PROP_PRIORITY: g_value_set_enum (value, priv->priority); break; + case PROP_AUTH: + g_value_set_object (value, priv->auth); + break; + case PROP_PROXY_AUTH: + g_value_set_object (value, priv->proxy_auth); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -939,6 +953,57 @@ soup_message_class_init (SoupMessageClass *message_class) SOUP_TYPE_MESSAGE_PRIORITY, SOUP_MESSAGE_PRIORITY_NORMAL, G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_AUTH: + * + * Alias for the #SoupMessage:auth property, qv. + * + * Since: 2.46 + **/ + /** + * SoupMessage:auth: + * + * The #SoupAuth used with this request. + * + * Note that the #SoupSession will overwrite this before + * sending the message if it believes that a different + * #SoupAuth is the correct one to be using. + * + * Since: 2.46 + */ + g_object_class_install_property ( + object_class, PROP_AUTH, + g_param_spec_object (SOUP_MESSAGE_AUTH, + "Auth", + "The SoupAuth used with this request", + SOUP_TYPE_AUTH, + G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_PROXY_AUTH: + * + * Alias for the #SoupMessage:proxy-auth property, qv. + * + * Since: 2.46 + **/ + /** + * SoupMessage:proxy-auth: + * + * The #SoupAuth used with this request for proxy + * authentication. + * + * Note that the #SoupSession will overwrite this before + * sending the message if it believes that a different + * #SoupAuth is the correct one to be using. + * + * Since: 2.46 + */ + g_object_class_install_property ( + object_class, PROP_PROXY_AUTH, + g_param_spec_object (SOUP_MESSAGE_PROXY_AUTH, + "Proxy auth", + "The SoupAuth used with this request for proxy authentication", + SOUP_TYPE_AUTH, + G_PARAM_READWRITE)); } @@ -1272,6 +1337,23 @@ soup_message_add_status_code_handler (SoupMessage *msg, } +/** + * soup_message_set_auth: + * @msg: a #SoupMessage + * @auth: a #SoupAuth, or %NULL + * + * Sets @msg to authenticate to its destination using @auth, which + * must have already been fully authenticated. If @auth is %NULL, @msg + * will not authenticate to its destination. + * + * Note that the #SoupSession will overwrite this before sending the + * message if it believes that a different #SoupAuth is the correct + * one to be using. This method is primarily useful if you want to + * force the use of Basic auth on a request before having seen a + * 401 Unauthorized response. + * + * Since: 2.46 + **/ void soup_message_set_auth (SoupMessage *msg, SoupAuth *auth) { @@ -1283,24 +1365,43 @@ soup_message_set_auth (SoupMessage *msg, SoupAuth *auth) priv = SOUP_MESSAGE_GET_PRIVATE (msg); - if (priv->auth) { - g_object_unref (priv->auth); - soup_message_headers_remove (msg->request_headers, - "Authorization"); + if (auth != priv->auth) { + if (priv->auth) + g_object_unref (priv->auth); + priv->auth = auth; + if (priv->auth) + g_object_ref (priv->auth); } - priv->auth = auth; - if (!priv->auth) - return; - g_object_ref (priv->auth); - token = soup_auth_get_authorization (auth, msg); - if (token) { + if (priv->auth) { + token = soup_auth_get_authorization (auth, msg); soup_message_headers_replace (msg->request_headers, "Authorization", token); g_free (token); + } else { + soup_message_headers_remove (msg->request_headers, + "Authorization"); } } +/** + * soup_message_get_auth: + * @msg: a #SoupMessage + * + * Gets the #SoupAuth used by @msg for authentication. + * + * Note that libsoup updates #SoupMessage:auth only immediately before + * sending a message; if you call soup_message_get_auth() from a + * #SoupSession:authenticate handler, it will return the #SoupAuth + * that previously failed (or %NULL if the previous attempt was + * unauthenticated), not the #SoupAuth that is currently being + * authenticated. + * + * Return value: (transfer none): the #SoupAuth used by @msg for + * authentication, or %NULL if @msg is unauthenticated. + * + * Since: 2.46 + **/ SoupAuth * soup_message_get_auth (SoupMessage *msg) { @@ -1309,6 +1410,24 @@ soup_message_get_auth (SoupMessage *msg) return SOUP_MESSAGE_GET_PRIVATE (msg)->auth; } +/** + * soup_message_set_proxy_auth: + * @msg: a #SoupMessage + * @auth: a #SoupAuth, or %NULL + * + * Sets @msg to authenticate to its proxy using @auth, which must have + * already been fully authenticated. If @auth is %NULL, @msg will not + * authenticate to its proxy. + * + * As with soup_message_set_auth(), note that the #SoupSession will + * overwrite this before sending the message if it believes that a + * different #SoupAuth is the correct one to be using. This method is + * primarily useful if you want to force the use of Basic auth on a + * request before having seen a 407 Proxy Authentication Required + * response. + * + * Since: 2.46 + **/ void soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth) { @@ -1320,22 +1439,36 @@ soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth) priv = SOUP_MESSAGE_GET_PRIVATE (msg); + if (auth != priv->proxy_auth) { + if (priv->proxy_auth) + g_object_unref (priv->proxy_auth); + priv->proxy_auth = auth; + if (priv->proxy_auth) + g_object_ref (priv->proxy_auth); + } + if (priv->proxy_auth) { - g_object_unref (priv->proxy_auth); + token = soup_auth_get_authorization (auth, msg); + soup_message_headers_replace (msg->request_headers, + "Proxy-Authorization", token); + g_free (token); + } else { soup_message_headers_remove (msg->request_headers, "Proxy-Authorization"); } - priv->proxy_auth = auth; - if (!priv->proxy_auth) - return; - - g_object_ref (priv->proxy_auth); - token = soup_auth_get_authorization (auth, msg); - soup_message_headers_replace (msg->request_headers, - "Proxy-Authorization", token); - g_free (token); } +/** + * soup_message_get_proxy_auth: + * @msg: a #SoupMessage + * + * Gets the #SoupAuth used by @msg for authentication to its proxy.. + * + * Return value: the #SoupAuth used by @msg for authentication to its + * proxy, or %NULL if @msg isn't authenticated to its proxy. + * + * Since: 2.46 + **/ SoupAuth * soup_message_get_proxy_auth (SoupMessage *msg) { diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index b02d293b..0df0e0dd 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -77,6 +77,8 @@ GType soup_message_get_type (void); #define SOUP_MESSAGE_TLS_CERTIFICATE "tls-certificate" #define SOUP_MESSAGE_TLS_ERRORS "tls-errors" #define SOUP_MESSAGE_PRIORITY "priority" +#define SOUP_MESSAGE_AUTH "auth" +#define SOUP_MESSAGE_PROXY_AUTH "proxy-auth" SoupMessage *soup_message_new (const char *method, const char *uri_string); @@ -206,6 +208,20 @@ void soup_message_set_priority (SoupMessage *msg, SOUP_AVAILABLE_IN_2_44 SoupMessagePriority soup_message_get_priority (SoupMessage *msg); + +/* Auth handling */ +SOUP_AVAILABLE_IN_2_46 +void soup_message_set_auth (SoupMessage *msg, + SoupAuth *auth); +SOUP_AVAILABLE_IN_2_46 +SoupAuth *soup_message_get_auth (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_46 +void soup_message_set_proxy_auth (SoupMessage *msg, + SoupAuth *auth); +SOUP_AVAILABLE_IN_2_46 +SoupAuth *soup_message_get_proxy_auth (SoupMessage *msg); + + void soup_message_wrote_informational (SoupMessage *msg); void soup_message_wrote_headers (SoupMessage *msg); void soup_message_wrote_chunk (SoupMessage *msg); diff --git a/tests/auth-test.c b/tests/auth-test.c index 8ed5cead..3e49d2a4 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -1162,6 +1162,62 @@ do_disappearing_auth_test (void) soup_test_server_quit_unref (server); } +static void +preauth_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + gboolean *authenticated = data; + + g_assert_false (*authenticated); + + *authenticated = TRUE; + soup_auth_authenticate (auth, "user1", "realm1"); +} + +static void +do_preauth_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupAuth *auth; + char *uri; + gboolean authenticated; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (preauth_authenticate), + &authenticated); + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + + /* Test with right password */ + msg = soup_message_new (SOUP_METHOD_GET, uri); + auth = soup_auth_new (SOUP_TYPE_AUTH_BASIC, msg, "Basic realm=\"realm1\""); + soup_auth_authenticate (auth, "user1", "realm1"); + soup_message_set_auth (msg, auth); + g_object_unref (auth); + + authenticated = FALSE; + soup_session_send_message (session, msg); + g_assert_false (authenticated); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + /* Test with wrong password */ + msg = soup_message_new (SOUP_METHOD_GET, uri); + auth = soup_auth_new (SOUP_TYPE_AUTH_BASIC, msg, "Basic realm=\"realm1\""); + soup_auth_authenticate (auth, "user1", "wrong"); + soup_message_set_auth (msg, auth); + g_object_unref (auth); + + authenticated = FALSE; + soup_session_send_message (session, msg); + g_assert_true (authenticated); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + + g_free (uri); +} + static SoupAuthTest relogin_tests[] = { { "Auth provided via URL, should succeed", "Basic/realm12/", "1", TRUE, "01", SOUP_STATUS_OK }, @@ -1278,6 +1334,7 @@ main (int argc, char **argv) g_test_add_func ("/auth/auth-close", do_auth_close_test); g_test_add_func ("/auth/infinite-auth", do_infinite_auth_test); g_test_add_func ("/auth/disappearing-auth", do_disappearing_auth_test); + g_test_add_func ("/auth/preauth", do_preauth_test); ret = g_test_run (); |