|
rpm-build |
4f3c61 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
rpm-build |
4f3c61 |
/*
|
|
rpm-build |
4f3c61 |
* soup-auth-manager.c: SoupAuth manager for SoupSession
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Copyright (C) 2007 Red Hat, Inc.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
#ifdef HAVE_CONFIG_H
|
|
rpm-build |
4f3c61 |
#include <config.h>
|
|
rpm-build |
4f3c61 |
#endif
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
#include <string.h>
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
#include "soup-auth-manager.h"
|
|
rpm-build |
4f3c61 |
#include "soup.h"
|
|
rpm-build |
4f3c61 |
#include "soup-connection-auth.h"
|
|
rpm-build |
4f3c61 |
#include "soup-message-private.h"
|
|
rpm-build |
4f3c61 |
#include "soup-message-queue.h"
|
|
rpm-build |
4f3c61 |
#include "soup-path-map.h"
|
|
rpm-build |
4f3c61 |
#include "soup-session-private.h"
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/**
|
|
rpm-build |
4f3c61 |
* SECTION:soup-auth-manager
|
|
rpm-build |
4f3c61 |
* @short_description: HTTP client-side authentication handler
|
|
rpm-build |
4f3c61 |
* @see_also: #SoupSession, #SoupAuth
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* #SoupAuthManager is the #SoupSessionFeature that handles HTTP
|
|
rpm-build |
4f3c61 |
* authentication for a #SoupSession.
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* A #SoupAuthManager is added to the session by default, and normally
|
|
rpm-build |
4f3c61 |
* you don't need to worry about it at all. However, if you want to
|
|
rpm-build |
4f3c61 |
* disable HTTP authentication, you can remove the feature from the
|
|
rpm-build |
4f3c61 |
* session with soup_session_remove_feature_by_type(), or disable it on
|
|
rpm-build |
4f3c61 |
* individual requests with soup_message_disable_feature().
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Since: 2.42
|
|
rpm-build |
4f3c61 |
**/
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/**
|
|
rpm-build |
4f3c61 |
* SOUP_TYPE_AUTH_MANAGER:
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* The #GType of #SoupAuthManager; you can use this with
|
|
rpm-build |
4f3c61 |
* soup_session_remove_feature_by_type() or
|
|
rpm-build |
4f3c61 |
* soup_message_disable_feature().
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* (Although this type has only been publicly visible since libsoup
|
|
rpm-build |
4f3c61 |
* 2.42, it has always existed in the background, and you can use
|
|
rpm-build |
4f3c61 |
* <literal>g_type_from_name ("SoupAuthManager") </literal>
|
|
rpm-build |
4f3c61 |
* to get its #GType in earlier releases.)
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Since: 2.42
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
static void soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
|
|
rpm-build |
4f3c61 |
static SoupSessionFeatureInterface *soup_session_feature_default_interface;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
enum {
|
|
rpm-build |
4f3c61 |
AUTHENTICATE,
|
|
rpm-build |
4f3c61 |
LAST_SIGNAL
|
|
rpm-build |
4f3c61 |
};
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static guint signals[LAST_SIGNAL] = { 0 };
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
struct SoupAuthManagerPrivate {
|
|
rpm-build |
4f3c61 |
SoupSession *session;
|
|
rpm-build |
4f3c61 |
GPtrArray *auth_types;
|
|
rpm-build |
4f3c61 |
gboolean auto_ntlm;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
GMutex lock;
|
|
rpm-build |
4f3c61 |
SoupAuth *proxy_auth;
|
|
rpm-build |
4f3c61 |
GHashTable *auth_hosts;
|
|
rpm-build |
4f3c61 |
};
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
typedef struct {
|
|
rpm-build |
4f3c61 |
SoupURI *uri;
|
|
rpm-build |
4f3c61 |
SoupPathMap *auth_realms; /* path -> scheme:realm */
|
|
rpm-build |
4f3c61 |
GHashTable *auths; /* scheme:realm -> SoupAuth */
|
|
rpm-build |
4f3c61 |
} SoupAuthHost;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
G_DEFINE_TYPE_WITH_CODE (SoupAuthManager, soup_auth_manager, G_TYPE_OBJECT,
|
|
rpm-build |
4f3c61 |
G_ADD_PRIVATE (SoupAuthManager)
|
|
rpm-build |
4f3c61 |
G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
|
|
rpm-build |
4f3c61 |
soup_auth_manager_session_feature_init))
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void soup_auth_host_free (SoupAuthHost *host);
|
|
rpm-build |
4f3c61 |
static SoupAuth *record_auth_for_uri (SoupAuthManagerPrivate *priv,
|
|
rpm-build |
4f3c61 |
SoupURI *uri, SoupAuth *auth,
|
|
rpm-build |
4f3c61 |
gboolean prior_auth_failed);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_init (SoupAuthManager *manager)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
priv = manager->priv = soup_auth_manager_get_instance_private (manager);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
priv->auth_types = g_ptr_array_new_with_free_func ((GDestroyNotify)g_type_class_unref);
|
|
rpm-build |
4f3c61 |
priv->auth_hosts = g_hash_table_new_full (soup_uri_host_hash,
|
|
rpm-build |
4f3c61 |
soup_uri_host_equal,
|
|
rpm-build |
4f3c61 |
NULL,
|
|
rpm-build |
4f3c61 |
(GDestroyNotify)soup_auth_host_free);
|
|
rpm-build |
4f3c61 |
g_mutex_init (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_finalize (GObject *object)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (object)->priv;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_ptr_array_free (priv->auth_types, TRUE);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_hash_table_destroy (priv->auth_hosts);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_clear_object (&priv->proxy_auth);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_clear (&priv->lock);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
G_OBJECT_CLASS (soup_auth_manager_parent_class)->finalize (object);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_class_init (SoupAuthManagerClass *auth_manager_class)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
GObjectClass *object_class = G_OBJECT_CLASS (auth_manager_class);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
object_class->finalize = soup_auth_manager_finalize;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/**
|
|
rpm-build |
4f3c61 |
* SoupAuthManager::authenticate:
|
|
rpm-build |
4f3c61 |
* @manager: the #SoupAuthManager
|
|
rpm-build |
4f3c61 |
* @msg: the #SoupMessage being sent
|
|
rpm-build |
4f3c61 |
* @auth: the #SoupAuth to authenticate
|
|
rpm-build |
4f3c61 |
* @retrying: %TRUE if this is the second (or later) attempt
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Emitted when the manager requires the application to
|
|
rpm-build |
4f3c61 |
* provide authentication credentials.
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* #SoupSession connects to this signal and emits its own
|
|
rpm-build |
4f3c61 |
* #SoupSession::authenticate signal when it is emitted, so
|
|
rpm-build |
4f3c61 |
* you shouldn't need to use this signal directly.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
signals[AUTHENTICATE] =
|
|
rpm-build |
4f3c61 |
g_signal_new ("authenticate",
|
|
rpm-build |
4f3c61 |
G_OBJECT_CLASS_TYPE (object_class),
|
|
rpm-build |
4f3c61 |
G_SIGNAL_RUN_FIRST,
|
|
rpm-build |
4f3c61 |
G_STRUCT_OFFSET (SoupAuthManagerClass, authenticate),
|
|
rpm-build |
4f3c61 |
NULL, NULL,
|
|
rpm-build |
4f3c61 |
NULL,
|
|
rpm-build |
4f3c61 |
G_TYPE_NONE, 3,
|
|
rpm-build |
4f3c61 |
SOUP_TYPE_MESSAGE,
|
|
rpm-build |
4f3c61 |
SOUP_TYPE_AUTH,
|
|
rpm-build |
4f3c61 |
G_TYPE_BOOLEAN);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static int
|
|
rpm-build |
4f3c61 |
auth_type_compare_func (gconstpointer a, gconstpointer b)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthClass **auth1 = (SoupAuthClass **)a;
|
|
rpm-build |
4f3c61 |
SoupAuthClass **auth2 = (SoupAuthClass **)b;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return (*auth1)->strength - (*auth2)->strength;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static gboolean
|
|
rpm-build |
4f3c61 |
soup_auth_manager_add_feature (SoupSessionFeature *feature, GType type)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuthClass *auth_class;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!g_type_is_a (type, SOUP_TYPE_AUTH))
|
|
rpm-build |
4f3c61 |
return FALSE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth_class = g_type_class_ref (type);
|
|
rpm-build |
4f3c61 |
g_ptr_array_add (priv->auth_types, auth_class);
|
|
rpm-build |
4f3c61 |
g_ptr_array_sort (priv->auth_types, auth_type_compare_func);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* Plain SoupSession does not get the backward-compat
|
|
rpm-build |
4f3c61 |
* auto-NTLM behavior; SoupSession subclasses do.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
if (type == SOUP_TYPE_AUTH_NTLM &&
|
|
rpm-build |
4f3c61 |
G_TYPE_FROM_INSTANCE (priv->session) != SOUP_TYPE_SESSION)
|
|
rpm-build |
4f3c61 |
priv->auto_ntlm = TRUE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return TRUE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static gboolean
|
|
rpm-build |
4f3c61 |
soup_auth_manager_remove_feature (SoupSessionFeature *feature, GType type)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuthClass *auth_class;
|
|
rpm-build |
4f3c61 |
guint i;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!g_type_is_a (type, SOUP_TYPE_AUTH))
|
|
rpm-build |
4f3c61 |
return FALSE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth_class = g_type_class_peek (type);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
for (i = 0; i < priv->auth_types->len; i++) {
|
|
rpm-build |
4f3c61 |
if (priv->auth_types->pdata[i] == (gpointer)auth_class) {
|
|
rpm-build |
4f3c61 |
if (type == SOUP_TYPE_AUTH_NTLM)
|
|
rpm-build |
4f3c61 |
priv->auto_ntlm = FALSE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_ptr_array_remove_index (priv->auth_types, i);
|
|
rpm-build |
4f3c61 |
return TRUE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return FALSE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static gboolean
|
|
rpm-build |
4f3c61 |
soup_auth_manager_has_feature (SoupSessionFeature *feature, GType type)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuthClass *auth_class;
|
|
rpm-build |
4f3c61 |
guint i;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!g_type_is_a (type, SOUP_TYPE_AUTH))
|
|
rpm-build |
4f3c61 |
return FALSE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth_class = g_type_class_peek (type);
|
|
rpm-build |
4f3c61 |
for (i = 0; i < priv->auth_types->len; i++) {
|
|
rpm-build |
4f3c61 |
if (priv->auth_types->pdata[i] == (gpointer)auth_class)
|
|
rpm-build |
4f3c61 |
return TRUE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
return FALSE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_attach (SoupSessionFeature *feature, SoupSession *session)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* FIXME: should support multiple sessions */
|
|
rpm-build |
4f3c61 |
priv->session = session;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_session_feature_default_interface->attach (feature, session);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static inline const char *
|
|
rpm-build |
4f3c61 |
auth_header_for_message (SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
if (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) {
|
|
rpm-build |
4f3c61 |
return soup_message_headers_get_list (msg->response_headers,
|
|
rpm-build |
4f3c61 |
"Proxy-Authenticate");
|
|
rpm-build |
4f3c61 |
} else {
|
|
rpm-build |
4f3c61 |
return soup_message_headers_get_list (msg->response_headers,
|
|
rpm-build |
4f3c61 |
"WWW-Authenticate");
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static GSList *
|
|
rpm-build |
4f3c61 |
next_challenge_start (GSList *items)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
/* The relevant grammar (from httpbis):
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* WWW-Authenticate = 1#challenge
|
|
rpm-build |
4f3c61 |
* Proxy-Authenticate = 1#challenge
|
|
rpm-build |
4f3c61 |
* challenge = auth-scheme [ 1*SP ( b64token / #auth-param ) ]
|
|
rpm-build |
4f3c61 |
* auth-scheme = token
|
|
rpm-build |
4f3c61 |
* auth-param = token BWS "=" BWS ( token / quoted-string )
|
|
rpm-build |
4f3c61 |
* b64token = 1*( ALPHA / DIGIT /
|
|
rpm-build |
4f3c61 |
* "-" / "." / "_" / "~" / "+" / "/" ) *"="
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* The fact that quoted-strings can contain commas, equals
|
|
rpm-build |
4f3c61 |
* signs, and auth scheme names makes it tricky to "cheat" on
|
|
rpm-build |
4f3c61 |
* the parsing. So soup_auth_manager_extract_challenge() will
|
|
rpm-build |
4f3c61 |
* have used soup_header_parse_list() to split the header into
|
|
rpm-build |
4f3c61 |
* items. Given the grammar above, the possible items are:
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* auth-scheme
|
|
rpm-build |
4f3c61 |
* auth-scheme 1*SP b64token
|
|
rpm-build |
4f3c61 |
* auth-scheme 1*SP auth-param
|
|
rpm-build |
4f3c61 |
* auth-param
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* where the first three represent the start of a new challenge and
|
|
rpm-build |
4f3c61 |
* the last one does not.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
for (; items; items = items->next) {
|
|
rpm-build |
4f3c61 |
const char *item = items->data;
|
|
rpm-build |
4f3c61 |
const char *sp = strpbrk (item, "\t\r\n ");
|
|
rpm-build |
4f3c61 |
const char *eq = strchr (item, '=');
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!eq) {
|
|
rpm-build |
4f3c61 |
/* No "=", so it can't be an auth-param */
|
|
rpm-build |
4f3c61 |
return items;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
if (!sp || sp > eq) {
|
|
rpm-build |
4f3c61 |
/* No space, or first space appears after the "=",
|
|
rpm-build |
4f3c61 |
* so it must be an auth-param.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
continue;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
while (g_ascii_isspace (*++sp))
|
|
rpm-build |
4f3c61 |
;
|
|
rpm-build |
4f3c61 |
if (sp == eq) {
|
|
rpm-build |
4f3c61 |
/* First "=" appears immediately after the first
|
|
rpm-build |
4f3c61 |
* space, so this must be an auth-param with
|
|
rpm-build |
4f3c61 |
* space around the "=".
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
continue;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* "auth-scheme auth-param" or "auth-scheme b64token" */
|
|
rpm-build |
4f3c61 |
return items;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return NULL;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static char *
|
|
rpm-build |
4f3c61 |
soup_auth_manager_extract_challenge (const char *challenges, const char *scheme)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
GSList *items, *i, *next;
|
|
rpm-build |
4f3c61 |
int schemelen = strlen (scheme);
|
|
rpm-build |
4f3c61 |
char *item;
|
|
rpm-build |
4f3c61 |
GString *challenge;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
items = soup_header_parse_list (challenges);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* First item will start with the scheme name, followed by
|
|
rpm-build |
4f3c61 |
* either nothing, or else a space and then the first
|
|
rpm-build |
4f3c61 |
* auth-param.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
for (i = items; i; i = next_challenge_start (i->next)) {
|
|
rpm-build |
4f3c61 |
item = i->data;
|
|
rpm-build |
4f3c61 |
if (!g_ascii_strncasecmp (item, scheme, schemelen) &&
|
|
rpm-build |
4f3c61 |
(!item[schemelen] || g_ascii_isspace (item[schemelen])))
|
|
rpm-build |
4f3c61 |
break;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
if (!i) {
|
|
rpm-build |
4f3c61 |
soup_header_free_list (items);
|
|
rpm-build |
4f3c61 |
return NULL;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
next = next_challenge_start (i->next);
|
|
rpm-build |
4f3c61 |
challenge = g_string_new (item);
|
|
rpm-build |
4f3c61 |
for (i = i->next; i != next; i = i->next) {
|
|
rpm-build |
4f3c61 |
item = i->data;
|
|
rpm-build |
4f3c61 |
g_string_append (challenge, ", ");
|
|
rpm-build |
4f3c61 |
g_string_append (challenge, item);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_header_free_list (items);
|
|
rpm-build |
4f3c61 |
return g_string_free (challenge, FALSE);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static SoupAuth *
|
|
rpm-build |
4f3c61 |
create_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
const char *header;
|
|
rpm-build |
4f3c61 |
SoupAuthClass *auth_class;
|
|
rpm-build |
4f3c61 |
char *challenge = NULL;
|
|
rpm-build |
4f3c61 |
SoupAuth *auth = NULL;
|
|
rpm-build |
4f3c61 |
int i;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
header = auth_header_for_message (msg);
|
|
rpm-build |
4f3c61 |
if (!header)
|
|
rpm-build |
4f3c61 |
return NULL;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
for (i = priv->auth_types->len - 1; i >= 0; i--) {
|
|
rpm-build |
4f3c61 |
auth_class = priv->auth_types->pdata[i];
|
|
rpm-build |
4f3c61 |
challenge = soup_auth_manager_extract_challenge (header, auth_class->scheme_name);
|
|
rpm-build |
4f3c61 |
if (!challenge)
|
|
rpm-build |
4f3c61 |
continue;
|
|
rpm-build |
4f3c61 |
auth = soup_auth_new (G_TYPE_FROM_CLASS (auth_class), msg, challenge);
|
|
rpm-build |
4f3c61 |
g_free (challenge);
|
|
rpm-build |
4f3c61 |
if (auth)
|
|
rpm-build |
4f3c61 |
break;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return auth;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static gboolean
|
|
rpm-build |
4f3c61 |
check_auth (SoupMessage *msg, SoupAuth *auth)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
const char *header, *scheme;
|
|
rpm-build |
4f3c61 |
char *challenge = NULL;
|
|
rpm-build |
4f3c61 |
gboolean ok = TRUE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
scheme = soup_auth_get_scheme_name (auth);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
header = auth_header_for_message (msg);
|
|
rpm-build |
4f3c61 |
if (header)
|
|
rpm-build |
4f3c61 |
challenge = soup_auth_manager_extract_challenge (header, scheme);
|
|
rpm-build |
4f3c61 |
if (!challenge) {
|
|
rpm-build |
4f3c61 |
ok = FALSE;
|
|
rpm-build |
4f3c61 |
challenge = g_strdup (scheme);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!soup_auth_update (auth, msg, challenge))
|
|
rpm-build |
4f3c61 |
ok = FALSE;
|
|
rpm-build |
4f3c61 |
g_free (challenge);
|
|
rpm-build |
4f3c61 |
return ok;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static SoupAuthHost *
|
|
rpm-build |
4f3c61 |
get_auth_host_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthHost *host;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
host = g_hash_table_lookup (priv->auth_hosts, uri);
|
|
rpm-build |
4f3c61 |
if (host)
|
|
rpm-build |
4f3c61 |
return host;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
host = g_slice_new0 (SoupAuthHost);
|
|
rpm-build |
4f3c61 |
host->uri = soup_uri_copy_host (uri);
|
|
rpm-build |
4f3c61 |
g_hash_table_insert (priv->auth_hosts, host->uri, host);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return host;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_host_free (SoupAuthHost *host)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
g_clear_pointer (&host->auth_realms, soup_path_map_free);
|
|
rpm-build |
4f3c61 |
g_clear_pointer (&host->auths, g_hash_table_destroy);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_uri_free (host->uri);
|
|
rpm-build |
4f3c61 |
g_slice_free (SoupAuthHost, host);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static gboolean
|
|
rpm-build |
4f3c61 |
make_auto_ntlm_auth (SoupAuthManagerPrivate *priv, SoupAuthHost *host)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuth *auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!priv->auto_ntlm)
|
|
rpm-build |
4f3c61 |
return FALSE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth = g_object_new (SOUP_TYPE_AUTH_NTLM,
|
|
rpm-build |
4f3c61 |
SOUP_AUTH_HOST, host->uri->host,
|
|
rpm-build |
4f3c61 |
NULL);
|
|
rpm-build |
4f3c61 |
record_auth_for_uri (priv, host->uri, auth, FALSE);
|
|
rpm-build |
4f3c61 |
g_object_unref (auth);
|
|
rpm-build |
4f3c61 |
return TRUE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
update_authorization_header (SoupMessage *msg, SoupAuth *auth, gboolean is_proxy)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
const char *authorization_header = is_proxy ? "Proxy-Authorization" : "Authorization";
|
|
rpm-build |
4f3c61 |
char *token;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (soup_message_get_auth (msg))
|
|
rpm-build |
4f3c61 |
soup_message_headers_remove (msg->request_headers, authorization_header);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!auth)
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
token = soup_auth_get_authorization (auth, msg);
|
|
rpm-build |
4f3c61 |
if (!token)
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_message_headers_replace (msg->request_headers, authorization_header, token);
|
|
rpm-build |
4f3c61 |
g_free (token);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static SoupAuth *
|
|
rpm-build |
4f3c61 |
lookup_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthHost *host;
|
|
rpm-build |
4f3c61 |
const char *path, *realm;
|
|
rpm-build |
4f3c61 |
SoupAuth *auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* If the message already has a ready auth, use that instead */
|
|
rpm-build |
4f3c61 |
auth = soup_message_get_auth (msg);
|
|
rpm-build |
4f3c61 |
if (auth && soup_auth_is_ready (auth, msg))
|
|
rpm-build |
4f3c61 |
return auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)
|
|
rpm-build |
4f3c61 |
return NULL;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
host = get_auth_host_for_uri (priv, soup_message_get_uri (msg));
|
|
rpm-build |
4f3c61 |
if (!host->auth_realms && !make_auto_ntlm_auth (priv, host))
|
|
rpm-build |
4f3c61 |
return NULL;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
path = soup_message_get_uri (msg)->path;
|
|
rpm-build |
4f3c61 |
if (!path)
|
|
rpm-build |
4f3c61 |
path = "/";
|
|
rpm-build |
4f3c61 |
realm = soup_path_map_lookup (host->auth_realms, path);
|
|
rpm-build |
4f3c61 |
if (realm)
|
|
rpm-build |
4f3c61 |
return g_hash_table_lookup (host->auths, realm);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return NULL;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static SoupAuth *
|
|
rpm-build |
4f3c61 |
lookup_proxy_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuth *auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* If the message already has a ready auth, use that instead */
|
|
rpm-build |
4f3c61 |
auth = soup_message_get_proxy_auth (msg);
|
|
rpm-build |
4f3c61 |
if (auth && soup_auth_is_ready (auth, msg))
|
|
rpm-build |
4f3c61 |
return auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)
|
|
rpm-build |
4f3c61 |
return NULL;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
return priv->proxy_auth;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
authenticate_auth (SoupAuthManager *manager, SoupAuth *auth,
|
|
rpm-build |
4f3c61 |
SoupMessage *msg, gboolean prior_auth_failed,
|
|
rpm-build |
4f3c61 |
gboolean proxy, gboolean can_interact)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = manager->priv;
|
|
rpm-build |
4f3c61 |
SoupURI *uri;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!soup_auth_can_authenticate (auth))
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (proxy) {
|
|
rpm-build |
4f3c61 |
SoupMessageQueue *queue;
|
|
rpm-build |
4f3c61 |
SoupMessageQueueItem *item;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
queue = soup_session_get_queue (priv->session);
|
|
rpm-build |
4f3c61 |
item = soup_message_queue_lookup (queue, msg);
|
|
rpm-build |
4f3c61 |
if (!item)
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* When loaded from the disk cache, the connection is NULL. */
|
|
rpm-build |
4f3c61 |
uri = item->conn ? soup_connection_get_proxy_uri (item->conn) : NULL;
|
|
rpm-build |
4f3c61 |
soup_message_queue_item_unref (item);
|
|
rpm-build |
4f3c61 |
if (!uri)
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
} else
|
|
rpm-build |
4f3c61 |
uri = soup_message_get_uri (msg);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* If a password is specified explicitly in the URI, use it
|
|
rpm-build |
4f3c61 |
* even if the auth had previously already been authenticated.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
if (uri->password && uri->user) {
|
|
rpm-build |
4f3c61 |
soup_auth_authenticate (auth, uri->user, uri->password);
|
|
rpm-build |
4f3c61 |
soup_uri_set_password (uri, NULL);
|
|
rpm-build |
4f3c61 |
soup_uri_set_user (uri, NULL);
|
|
rpm-build |
4f3c61 |
} else if (!soup_auth_is_authenticated (auth) && can_interact) {
|
|
rpm-build |
4f3c61 |
g_signal_emit (manager, signals[AUTHENTICATE], 0,
|
|
rpm-build |
4f3c61 |
msg, auth, prior_auth_failed);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static SoupAuth *
|
|
rpm-build |
4f3c61 |
record_auth_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri,
|
|
rpm-build |
4f3c61 |
SoupAuth *auth, gboolean prior_auth_failed)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthHost *host;
|
|
rpm-build |
4f3c61 |
SoupAuth *old_auth;
|
|
rpm-build |
4f3c61 |
const char *path;
|
|
rpm-build |
4f3c61 |
char *auth_info, *old_auth_info;
|
|
rpm-build |
4f3c61 |
GSList *pspace, *p;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
host = get_auth_host_for_uri (priv, uri);
|
|
rpm-build |
4f3c61 |
auth_info = soup_auth_get_info (auth);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!host->auth_realms) {
|
|
rpm-build |
4f3c61 |
host->auth_realms = soup_path_map_new (g_free);
|
|
rpm-build |
4f3c61 |
host->auths = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
rpm-build |
4f3c61 |
g_free, g_object_unref);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* Record where this auth realm is used. */
|
|
rpm-build |
4f3c61 |
pspace = soup_auth_get_protection_space (auth, uri);
|
|
rpm-build |
4f3c61 |
for (p = pspace; p; p = p->next) {
|
|
rpm-build |
4f3c61 |
path = p->data;
|
|
rpm-build |
4f3c61 |
old_auth_info = soup_path_map_lookup (host->auth_realms, path);
|
|
rpm-build |
4f3c61 |
if (old_auth_info) {
|
|
rpm-build |
4f3c61 |
if (!strcmp (old_auth_info, auth_info))
|
|
rpm-build |
4f3c61 |
continue;
|
|
rpm-build |
4f3c61 |
soup_path_map_remove (host->auth_realms, path);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_path_map_add (host->auth_realms, path,
|
|
rpm-build |
4f3c61 |
g_strdup (auth_info));
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
soup_auth_free_protection_space (auth, pspace);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* Now, make sure the auth is recorded. (If there's a
|
|
rpm-build |
4f3c61 |
* pre-existing good auth, we keep that rather than the new one,
|
|
rpm-build |
4f3c61 |
* since the old one might already be authenticated.)
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
old_auth = g_hash_table_lookup (host->auths, auth_info);
|
|
rpm-build |
4f3c61 |
if (old_auth && (old_auth != auth || !prior_auth_failed)) {
|
|
rpm-build |
4f3c61 |
g_free (auth_info);
|
|
rpm-build |
4f3c61 |
return old_auth;
|
|
rpm-build |
4f3c61 |
} else {
|
|
rpm-build |
4f3c61 |
g_hash_table_insert (host->auths, auth_info,
|
|
rpm-build |
4f3c61 |
g_object_ref (auth));
|
|
rpm-build |
4f3c61 |
return auth;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
auth_got_headers (SoupMessage *msg, gpointer manager)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuth *auth, *prior_auth;
|
|
rpm-build |
4f3c61 |
gboolean prior_auth_failed = FALSE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_lock (&priv->lock);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* See if we used auth last time */
|
|
rpm-build |
4f3c61 |
prior_auth = soup_message_get_auth (msg);
|
|
rpm-build |
4f3c61 |
if (prior_auth && check_auth (msg, prior_auth)) {
|
|
rpm-build |
4f3c61 |
auth = g_object_ref (prior_auth);
|
|
rpm-build |
4f3c61 |
if (!soup_auth_is_ready (auth, msg))
|
|
rpm-build |
4f3c61 |
prior_auth_failed = TRUE;
|
|
rpm-build |
4f3c61 |
} else {
|
|
rpm-build |
4f3c61 |
auth = create_auth (priv, msg);
|
|
rpm-build |
4f3c61 |
if (!auth) {
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) {
|
|
rpm-build |
4f3c61 |
SoupAuth *new_auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
new_auth = record_auth_for_uri (priv, soup_message_get_uri (msg),
|
|
rpm-build |
4f3c61 |
auth, prior_auth_failed);
|
|
rpm-build |
4f3c61 |
g_object_unref (auth);
|
|
rpm-build |
4f3c61 |
auth = g_object_ref (new_auth);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* If we need to authenticate, try to do it. */
|
|
rpm-build |
4f3c61 |
authenticate_auth (manager, auth, msg,
|
|
rpm-build |
4f3c61 |
prior_auth_failed, FALSE, TRUE);
|
|
rpm-build |
4f3c61 |
soup_message_set_auth (msg, auth);
|
|
rpm-build |
4f3c61 |
g_object_unref (auth);
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
auth_got_body (SoupMessage *msg, gpointer manager)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuth *auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_lock (&priv->lock);
|
|
rpm-build |
4f3c61 |
auth = lookup_auth (priv, msg);
|
|
rpm-build |
4f3c61 |
if (auth && soup_auth_is_ready (auth, msg)) {
|
|
rpm-build |
4f3c61 |
if (SOUP_IS_CONNECTION_AUTH (auth)) {
|
|
rpm-build |
4f3c61 |
SoupMessageFlags flags;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
flags = soup_message_get_flags (msg);
|
|
rpm-build |
4f3c61 |
soup_message_set_flags (msg, flags & ~SOUP_MESSAGE_NEW_CONNECTION);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* When not using cached credentials, update the Authorization header
|
|
rpm-build |
4f3c61 |
* right before requeuing the message.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)
|
|
rpm-build |
4f3c61 |
update_authorization_header (msg, auth, FALSE);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_session_requeue_message (priv->session, msg);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
proxy_auth_got_headers (SoupMessage *msg, gpointer manager)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuth *auth = NULL, *prior_auth;
|
|
rpm-build |
4f3c61 |
gboolean prior_auth_failed = FALSE;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_lock (&priv->lock);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* See if we used auth last time */
|
|
rpm-build |
4f3c61 |
prior_auth = soup_message_get_proxy_auth (msg);
|
|
rpm-build |
4f3c61 |
if (prior_auth && check_auth (msg, prior_auth)) {
|
|
rpm-build |
4f3c61 |
if (!soup_auth_is_ready (prior_auth, msg))
|
|
rpm-build |
4f3c61 |
prior_auth_failed = TRUE;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE))
|
|
rpm-build |
4f3c61 |
auth = priv->proxy_auth ? g_object_ref (priv->proxy_auth) : NULL;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (!auth) {
|
|
rpm-build |
4f3c61 |
auth = create_auth (priv, msg);
|
|
rpm-build |
4f3c61 |
if (!auth) {
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE))
|
|
rpm-build |
4f3c61 |
priv->proxy_auth = g_object_ref (auth);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/* If we need to authenticate, try to do it. */
|
|
rpm-build |
4f3c61 |
authenticate_auth (manager, auth, msg,
|
|
rpm-build |
4f3c61 |
prior_auth_failed, TRUE, TRUE);
|
|
rpm-build |
4f3c61 |
soup_message_set_proxy_auth (msg, auth);
|
|
rpm-build |
4f3c61 |
g_object_unref (auth);
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
proxy_auth_got_body (SoupMessage *msg, gpointer manager)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuth *auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_lock (&priv->lock);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth = lookup_proxy_auth (priv, msg);
|
|
rpm-build |
4f3c61 |
if (auth && soup_auth_is_ready (auth, msg)) {
|
|
rpm-build |
4f3c61 |
/* When not using cached credentials, update the Authorization header
|
|
rpm-build |
4f3c61 |
* right before requeuing the message.
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)
|
|
rpm-build |
4f3c61 |
update_authorization_header (msg, auth, TRUE);
|
|
rpm-build |
4f3c61 |
soup_session_requeue_message (priv->session, msg);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
auth_msg_starting (SoupMessage *msg, gpointer manager)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv;
|
|
rpm-build |
4f3c61 |
SoupAuth *auth;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (soup_message_get_flags (msg) & SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)
|
|
rpm-build |
4f3c61 |
return;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_lock (&priv->lock);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
if (msg->method != SOUP_METHOD_CONNECT) {
|
|
rpm-build |
4f3c61 |
auth = lookup_auth (priv, msg);
|
|
rpm-build |
4f3c61 |
if (auth) {
|
|
rpm-build |
4f3c61 |
authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE);
|
|
rpm-build |
4f3c61 |
if (!soup_auth_is_ready (auth, msg))
|
|
rpm-build |
4f3c61 |
auth = NULL;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
soup_message_set_auth (msg, auth);
|
|
rpm-build |
4f3c61 |
update_authorization_header (msg, auth, FALSE);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
auth = lookup_proxy_auth (priv, msg);
|
|
rpm-build |
4f3c61 |
if (auth) {
|
|
rpm-build |
4f3c61 |
authenticate_auth (manager, auth, msg, FALSE, TRUE, FALSE);
|
|
rpm-build |
4f3c61 |
if (!soup_auth_is_ready (auth, msg))
|
|
rpm-build |
4f3c61 |
auth = NULL;
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
soup_message_set_proxy_auth (msg, auth);
|
|
rpm-build |
4f3c61 |
update_authorization_header (msg, auth, TRUE);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_request_queued (SoupSessionFeature *manager,
|
|
rpm-build |
4f3c61 |
SoupSession *session,
|
|
rpm-build |
4f3c61 |
SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
g_signal_connect (msg, "starting",
|
|
rpm-build |
4f3c61 |
G_CALLBACK (auth_msg_starting), manager);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_message_add_status_code_handler (
|
|
rpm-build |
4f3c61 |
msg, "got_headers", SOUP_STATUS_UNAUTHORIZED,
|
|
rpm-build |
4f3c61 |
G_CALLBACK (auth_got_headers), manager);
|
|
rpm-build |
4f3c61 |
soup_message_add_status_code_handler (
|
|
rpm-build |
4f3c61 |
msg, "got_body", SOUP_STATUS_UNAUTHORIZED,
|
|
rpm-build |
4f3c61 |
G_CALLBACK (auth_got_body), manager);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
soup_message_add_status_code_handler (
|
|
rpm-build |
4f3c61 |
msg, "got_headers", SOUP_STATUS_PROXY_UNAUTHORIZED,
|
|
rpm-build |
4f3c61 |
G_CALLBACK (proxy_auth_got_headers), manager);
|
|
rpm-build |
4f3c61 |
soup_message_add_status_code_handler (
|
|
rpm-build |
4f3c61 |
msg, "got_body", SOUP_STATUS_PROXY_UNAUTHORIZED,
|
|
rpm-build |
4f3c61 |
G_CALLBACK (proxy_auth_got_body), manager);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_request_unqueued (SoupSessionFeature *manager,
|
|
rpm-build |
4f3c61 |
SoupSession *session,
|
|
rpm-build |
4f3c61 |
SoupMessage *msg)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
g_signal_handlers_disconnect_matched (msg, G_SIGNAL_MATCH_DATA,
|
|
rpm-build |
4f3c61 |
0, 0, NULL, NULL, manager);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/**
|
|
rpm-build |
4f3c61 |
* soup_auth_manager_use_auth:
|
|
rpm-build |
4f3c61 |
* @manager: a #SoupAuthManager
|
|
rpm-build |
4f3c61 |
* @uri: the #SoupURI under which @auth is to be used
|
|
rpm-build |
4f3c61 |
* @auth: the #SoupAuth to use
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Records that @auth is to be used under @uri, as though a
|
|
rpm-build |
4f3c61 |
* WWW-Authenticate header had been received at that URI. This can be
|
|
rpm-build |
4f3c61 |
* used to "preload" @manager's auth cache, to avoid an extra HTTP
|
|
rpm-build |
4f3c61 |
* round trip in the case where you know ahead of time that a 401
|
|
rpm-build |
4f3c61 |
* response will be returned.
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* This is only useful for authentication types where the initial
|
|
rpm-build |
4f3c61 |
* Authorization header does not depend on any additional information
|
|
rpm-build |
4f3c61 |
* from the server. (Eg, Basic or NTLM, but not Digest.)
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Since: 2.42
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_use_auth (SoupAuthManager *manager,
|
|
rpm-build |
4f3c61 |
SoupURI *uri,
|
|
rpm-build |
4f3c61 |
SoupAuth *auth)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv = manager->priv;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_mutex_lock (&priv->lock);
|
|
rpm-build |
4f3c61 |
record_auth_for_uri (priv, uri, auth, FALSE);
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
/**
|
|
rpm-build |
4f3c61 |
* soup_auth_manager_clear_cached_credentials:
|
|
rpm-build |
4f3c61 |
* @manager: a #SoupAuthManager
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Clear all credentials cached by @manager
|
|
rpm-build |
4f3c61 |
*
|
|
rpm-build |
4f3c61 |
* Since: 2.58
|
|
rpm-build |
4f3c61 |
*/
|
|
rpm-build |
4f3c61 |
void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_clear_cached_credentials (SoupAuthManager *manager)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
SoupAuthManagerPrivate *priv;
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
g_return_if_fail (SOUP_IS_AUTH_MANAGER (manager));
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
priv = manager->priv;
|
|
rpm-build |
4f3c61 |
g_mutex_lock (&priv->lock);
|
|
rpm-build |
4f3c61 |
g_hash_table_remove_all (priv->auth_hosts);
|
|
rpm-build |
4f3c61 |
g_mutex_unlock (&priv->lock);
|
|
rpm-build |
4f3c61 |
}
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
static void
|
|
rpm-build |
4f3c61 |
soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface,
|
|
rpm-build |
4f3c61 |
gpointer interface_data)
|
|
rpm-build |
4f3c61 |
{
|
|
rpm-build |
4f3c61 |
soup_session_feature_default_interface =
|
|
rpm-build |
4f3c61 |
g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE);
|
|
rpm-build |
4f3c61 |
|
|
rpm-build |
4f3c61 |
feature_interface->attach = soup_auth_manager_attach;
|
|
rpm-build |
4f3c61 |
feature_interface->request_queued = soup_auth_manager_request_queued;
|
|
rpm-build |
4f3c61 |
feature_interface->request_unqueued = soup_auth_manager_request_unqueued;
|
|
rpm-build |
4f3c61 |
feature_interface->add_feature = soup_auth_manager_add_feature;
|
|
rpm-build |
4f3c61 |
feature_interface->remove_feature = soup_auth_manager_remove_feature;
|
|
rpm-build |
4f3c61 |
feature_interface->has_feature = soup_auth_manager_has_feature;
|
|
rpm-build |
4f3c61 |
}
|