summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2012-12-28 16:45:31 -0500
committerDan Winship <danw@gnome.org>2014-03-28 13:28:43 -0400
commit94ab8c1140f58e762e747344ec522521f8a518af (patch)
treed1fd7df7698faae426dda0773cd5a2ee652484a3
parent6c14af04775a9de4dfa3fa0cc15a7ad0462ef3d9 (diff)
downloadlibsoup-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.sym4
-rw-r--r--libsoup/soup-auth-manager.c1
-rw-r--r--libsoup/soup-message-private.h8
-rw-r--r--libsoup/soup-message.c173
-rw-r--r--libsoup/soup-message.h16
-rw-r--r--tests/auth-test.c57
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 ();