summaryrefslogtreecommitdiff
path: root/libsoup
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2007-09-25 03:11:18 +0000
committerDan Winship <danw@src.gnome.org>2007-09-25 03:11:18 +0000
commit1ef84727183daf0fcf8043383c012834576ee359 (patch)
treef08d1d4f6bf343f822c87288673f48cd7ea43bbf /libsoup
parentb8b3779563f8f49a81b0bf117ba8f0256671ee14 (diff)
downloadlibsoup-1ef84727183daf0fcf8043383c012834576ee359.tar.gz
add "realm" field to the struct. (SoupAuthClass) remove "get_realm"
* libsoup/soup-auth.h (SoupAuth): add "realm" field to the struct. (SoupAuthClass) remove "get_realm" virtual method. * libsoup/soup-auth.c (soup_auth_new_from_header_list): Parse the WWW-Authenticate/Proxy-Authenticate header here, set realm, and pass the params hash to the construct method. (soup_auth_get_info): Return an identifier for the auth: "SCHEME:REALM" * libsoup/soup-auth-basic.c: * libsoup/soup-auth-digest.c: update * libsoup/soup-session.c (invalidate_auth, update_auth_internal): use soup_auth_get_info(). svn path=/trunk/; revision=934
Diffstat (limited to 'libsoup')
-rw-r--r--libsoup/soup-auth-basic.c27
-rw-r--r--libsoup/soup-auth-digest.c41
-rw-r--r--libsoup/soup-auth.c77
-rw-r--r--libsoup/soup-auth.h6
-rw-r--r--libsoup/soup-session.c70
5 files changed, 109 insertions, 112 deletions
diff --git a/libsoup/soup-auth-basic.c b/libsoup/soup-auth-basic.c
index 235b7f34..003bda6f 100644
--- a/libsoup/soup-auth-basic.c
+++ b/libsoup/soup-auth-basic.c
@@ -17,15 +17,14 @@
#include "soup-misc.h"
#include "soup-uri.h"
-static void construct (SoupAuth *auth, const char *header);
+static void construct (SoupAuth *auth, GHashTable *auth_params);
static GSList *get_protection_space (SoupAuth *auth, const SoupUri *source_uri);
-static const char *get_realm (SoupAuth *auth);
static void authenticate (SoupAuth *auth, const char *username, const char *password);
static gboolean is_authenticated (SoupAuth *auth);
static char *get_authorization (SoupAuth *auth, SoupMessage *msg);
typedef struct {
- char *realm, *token;
+ char *token;
} SoupAuthBasicPrivate;
#define SOUP_AUTH_BASIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_BASIC, SoupAuthBasicPrivate))
@@ -41,7 +40,6 @@ finalize (GObject *object)
{
SoupAuthBasicPrivate *priv = SOUP_AUTH_BASIC_GET_PRIVATE (object);
- g_free (priv->realm);
g_free (priv->token);
G_OBJECT_CLASS (soup_auth_basic_parent_class)->finalize (object);
@@ -59,7 +57,6 @@ soup_auth_basic_class_init (SoupAuthBasicClass *auth_basic_class)
auth_class->construct = construct;
auth_class->get_protection_space = get_protection_space;
- auth_class->get_realm = get_realm;
auth_class->authenticate = authenticate;
auth_class->is_authenticated = is_authenticated;
auth_class->get_authorization = get_authorization;
@@ -69,19 +66,9 @@ soup_auth_basic_class_init (SoupAuthBasicClass *auth_basic_class)
static void
-construct (SoupAuth *auth, const char *header)
+construct (SoupAuth *auth, GHashTable *auth_params)
{
- SoupAuthBasicPrivate *priv = SOUP_AUTH_BASIC_GET_PRIVATE (auth);
- GHashTable *tokens;
-
- header += sizeof ("Basic");
-
- tokens = soup_header_param_parse_list (header);
- if (!tokens)
- return;
-
- priv->realm = soup_header_param_copy_token (tokens, "realm");
- soup_header_param_destroy_hash (tokens);
+ ;
}
static GSList *
@@ -99,12 +86,6 @@ get_protection_space (SoupAuth *auth, const SoupUri *source_uri)
return g_slist_prepend (NULL, space);
}
-static const char *
-get_realm (SoupAuth *auth)
-{
- return SOUP_AUTH_BASIC_GET_PRIVATE (auth)->realm;
-}
-
static void
authenticate (SoupAuth *auth, const char *username, const char *password)
{
diff --git a/libsoup/soup-auth-digest.c b/libsoup/soup-auth-digest.c
index 6b911470..3841e988 100644
--- a/libsoup/soup-auth-digest.c
+++ b/libsoup/soup-auth-digest.c
@@ -21,9 +21,8 @@
#include "soup-misc.h"
#include "soup-uri.h"
-static void construct (SoupAuth *auth, const char *header);
+static void construct (SoupAuth *auth, GHashTable *auth_params);
static GSList *get_protection_space (SoupAuth *auth, const SoupUri *source_uri);
-static const char *get_realm (SoupAuth *auth);
static void authenticate (SoupAuth *auth, const char *username, const char *password);
static gboolean is_authenticated (SoupAuth *auth);
static char *get_authorization (SoupAuth *auth, SoupMessage *msg);
@@ -44,7 +43,6 @@ typedef struct {
char hex_a1[33];
/* These are provided by the server */
- char *realm;
char *nonce;
QOPType qop_options;
AlgorithmType algorithm;
@@ -71,8 +69,6 @@ finalize (GObject *object)
if (priv->user)
g_free (priv->user);
- if (priv->realm)
- g_free (priv->realm);
if (priv->nonce)
g_free (priv->nonce);
if (priv->domain)
@@ -94,7 +90,6 @@ soup_auth_digest_class_init (SoupAuthDigestClass *auth_digest_class)
auth_class->scheme_name = "Digest";
auth_class->get_protection_space = get_protection_space;
- auth_class->get_realm = get_realm;
auth_class->construct = construct;
auth_class->authenticate = authenticate;
auth_class->is_authenticated = is_authenticated;
@@ -149,27 +144,19 @@ decode_algorithm (const char *name)
}
static void
-construct (SoupAuth *auth, const char *header)
+construct (SoupAuth *auth, GHashTable *auth_params)
{
SoupAuthDigestPrivate *priv = SOUP_AUTH_DIGEST_GET_PRIVATE (auth);
- GHashTable *tokens;
char *tmp, *ptr;
- header += sizeof ("Digest");
-
- tokens = soup_header_param_parse_list (header);
- if (!tokens)
- return;
-
priv->nc = 1;
/* We're just going to do qop=auth for now */
priv->qop = QOP_AUTH;
- priv->realm = soup_header_param_copy_token (tokens, "realm");
- priv->domain = soup_header_param_copy_token (tokens, "domain");
- priv->nonce = soup_header_param_copy_token (tokens, "nonce");
+ priv->domain = soup_header_param_copy_token (auth_params, "domain");
+ priv->nonce = soup_header_param_copy_token (auth_params, "nonce");
- tmp = soup_header_param_copy_token (tokens, "qop");
+ tmp = soup_header_param_copy_token (auth_params, "qop");
ptr = tmp;
while (ptr && *ptr) {
@@ -185,11 +172,9 @@ construct (SoupAuth *auth, const char *header)
}
g_free (tmp);
- tmp = soup_header_param_copy_token (tokens, "algorithm");
+ tmp = soup_header_param_copy_token (auth_params, "algorithm");
priv->algorithm = decode_algorithm (tmp);
g_free (tmp);
-
- soup_header_param_destroy_hash (tokens);
}
static GSList *
@@ -238,12 +223,6 @@ get_protection_space (SoupAuth *auth, const SoupUri *source_uri)
return space;
}
-static const char *
-get_realm (SoupAuth *auth)
-{
- return SOUP_AUTH_DIGEST_GET_PRIVATE (auth)->realm;
-}
-
static void
authenticate (SoupAuth *auth, const char *username, const char *password)
{
@@ -269,11 +248,7 @@ authenticate (SoupAuth *auth, const char *username, const char *password)
soup_md5_update (&ctx, username, strlen (username));
soup_md5_update (&ctx, ":", 1);
- if (priv->realm) {
- soup_md5_update (&ctx, priv->realm,
- strlen (priv->realm));
- }
-
+ soup_md5_update (&ctx, auth->realm, strlen (auth->realm));
soup_md5_update (&ctx, ":", 1);
if (password)
soup_md5_update (&ctx, password, strlen (password));
@@ -397,7 +372,7 @@ get_authorization (SoupAuth *auth, SoupMessage *msg)
"Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", %s%s%s "
"%s%s%s %s%s%s uri=\"%s\", response=\"%s\"",
priv->user,
- priv->realm,
+ auth->realm,
priv->nonce,
priv->qop ? "cnonce=\"" : "",
diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c
index 5c7ac8da..51ad491a 100644
--- a/libsoup/soup-auth.c
+++ b/libsoup/soup-auth.c
@@ -14,12 +14,26 @@
#include "soup-auth.h"
#include "soup-auth-basic.h"
#include "soup-auth-digest.h"
+#include "soup-headers.h"
G_DEFINE_TYPE (SoupAuth, soup_auth, G_TYPE_OBJECT)
static void
+finalize (GObject *object)
+{
+ SoupAuth *auth = SOUP_AUTH (object);
+
+ g_free (auth->realm);
+
+ G_OBJECT_CLASS (soup_auth_parent_class)->finalize (object);
+}
+
+static void
soup_auth_class_init (SoupAuthClass *auth_class)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (auth_class);
+
+ object_class->finalize = finalize;
}
static void
@@ -27,15 +41,18 @@ soup_auth_init (SoupAuth *auth)
{
}
+typedef GType (*GTypeFunc) (void);
+
typedef struct {
- const char *scheme;
- GType (*type_func) (void);
- int strength;
+ const char *name;
+ int len;
+ GTypeFunc type_func;
+ int strength;
} AuthScheme;
static AuthScheme known_auth_schemes [] = {
- { "Basic", soup_auth_basic_get_type, 0 },
- { "Digest", soup_auth_digest_get_type, 3 },
+ { "Basic", sizeof ("Basic") - 1, soup_auth_basic_get_type, 0 },
+ { "Digest", sizeof ("Digest") - 1, soup_auth_digest_get_type, 3 },
{ NULL }
};
@@ -53,18 +70,21 @@ static AuthScheme known_auth_schemes [] = {
SoupAuth *
soup_auth_new_from_header_list (const GSList *vals)
{
- char *header = NULL;
+ char *header = NULL, *realm;
AuthScheme *scheme = NULL, *iter;
SoupAuth *auth = NULL;
+ GHashTable *params;
g_return_val_if_fail (vals != NULL, NULL);
while (vals) {
char *tryheader = vals->data;
- for (iter = known_auth_schemes; iter->scheme; iter++) {
- if (!g_ascii_strncasecmp (tryheader, iter->scheme,
- strlen (iter->scheme))) {
+ for (iter = known_auth_schemes; iter->name; iter++) {
+ if (!g_ascii_strncasecmp (tryheader, iter->name,
+ iter->len) &&
+ (!tryheader[iter->len] ||
+ g_ascii_isspace (tryheader[iter->len]))) {
if (!scheme ||
scheme->strength < iter->strength) {
header = tryheader;
@@ -81,16 +101,20 @@ soup_auth_new_from_header_list (const GSList *vals)
if (!scheme)
return NULL;
- auth = g_object_new (scheme->type_func (), NULL);
- if (!auth)
+ params = soup_header_param_parse_list (header + scheme->len);
+ if (!params)
return NULL;
-
- SOUP_AUTH_GET_CLASS (auth)->construct (auth, header);
- if (!soup_auth_get_realm (auth)) {
- g_object_unref (auth);
+ realm = soup_header_param_copy_token (params, "realm");
+ if (!realm) {
+ soup_header_param_destroy_hash (params);
return NULL;
}
+ auth = g_object_new (scheme->type_func (), NULL);
+ auth->realm = realm;
+
+ SOUP_AUTH_GET_CLASS (auth)->construct (auth, params);
+ soup_header_param_destroy_hash (params);
return auth;
}
@@ -143,7 +167,28 @@ soup_auth_get_realm (SoupAuth *auth)
{
g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
- return SOUP_AUTH_GET_CLASS (auth)->get_realm (auth);
+ return auth->realm;
+}
+
+/**
+ * soup_auth_get_info:
+ * @auth: a #SoupAuth
+ *
+ * Gets an identifier for @auth. #SoupAuth objects from the same
+ * server with the same identifier refer to the same authentication
+ * domain (eg, the URLs associated with them take the same usernames
+ * and passwords).
+ *
+ * Return value: the identifier
+ **/
+char *
+soup_auth_get_info (SoupAuth *auth)
+{
+ g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
+
+ return g_strdup_printf ("%s:%s",
+ SOUP_AUTH_GET_CLASS (auth)->scheme_name,
+ auth->realm);
}
/**
diff --git a/libsoup/soup-auth.h b/libsoup/soup-auth.h
index be49573d..0feda0c7 100644
--- a/libsoup/soup-auth.h
+++ b/libsoup/soup-auth.h
@@ -18,6 +18,7 @@
typedef struct {
GObject parent;
+ char *realm;
} SoupAuth;
typedef struct {
@@ -26,13 +27,11 @@ typedef struct {
const char *scheme_name;
void (*construct) (SoupAuth *auth,
- const char *header);
+ GHashTable *auth_params);
GSList * (*get_protection_space) (SoupAuth *auth,
const SoupUri *source_uri);
- const char * (*get_realm) (SoupAuth *auth);
-
void (*authenticate) (SoupAuth *auth,
const char *username,
const char *password);
@@ -49,6 +48,7 @@ SoupAuth *soup_auth_new_from_header_list (const GSList *vals);
const char *soup_auth_get_scheme_name (SoupAuth *auth);
const char *soup_auth_get_realm (SoupAuth *auth);
+char *soup_auth_get_info (SoupAuth *auth);
void soup_auth_authenticate (SoupAuth *auth,
const char *username,
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 5c35d40a..ef4a4126 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -692,20 +692,17 @@ lookup_auth (SoupSession *session, SoupMessage *msg, gboolean proxy)
static void
invalidate_auth (SoupSessionHost *host, SoupAuth *auth)
{
- char *realm;
+ char *info;
gpointer key, value;
- realm = g_strdup_printf ("%s:%s",
- soup_auth_get_scheme_name (auth),
- soup_auth_get_realm (auth));
-
- if (g_hash_table_lookup_extended (host->auths, realm, &key, &value) &&
+ info = soup_auth_get_info (auth);
+ if (g_hash_table_lookup_extended (host->auths, info, &key, &value) &&
auth == (SoupAuth *)value) {
- g_hash_table_remove (host->auths, realm);
+ g_hash_table_remove (host->auths, info);
g_free (key);
g_object_unref (auth);
}
- g_free (realm);
+ g_free (info);
}
static gboolean
@@ -749,10 +746,10 @@ update_auth_internal (SoupSession *session, SoupMessage *msg,
{
SoupSessionHost *host;
SoupAuth *new_auth, *prior_auth, *old_auth;
- gpointer old_path, old_realm;
+ gpointer old_path, old_auth_info;
const SoupUri *msg_uri;
const char *path;
- char *realm;
+ char *auth_info;
GSList *pspace, *p;
gboolean prior_auth_failed = FALSE;
@@ -771,17 +768,21 @@ update_auth_internal (SoupSession *session, SoupMessage *msg,
if (!new_auth)
return FALSE;
+ auth_info = soup_auth_get_info (new_auth);
+
/* See if this auth is the same auth we used last time */
prior_auth = proxy ? soup_message_get_proxy_auth (msg) : soup_message_get_auth (msg);
- if (prior_auth &&
- G_OBJECT_TYPE (prior_auth) == G_OBJECT_TYPE (new_auth) &&
- !strcmp (soup_auth_get_realm (prior_auth),
- soup_auth_get_realm (new_auth))) {
- /* The server didn't like the username/password we
- * provided before. Invalidate it and note this fact.
- */
- invalidate_auth (host, prior_auth);
- prior_auth_failed = TRUE;
+ if (prior_auth) {
+ char *old_auth_info = soup_auth_get_info (prior_auth);
+
+ if (!strcmp (old_auth_info, auth_info)) {
+ /* The server didn't like the username/password we
+ * provided before. Invalidate it and note this fact.
+ */
+ invalidate_auth (host, prior_auth);
+ prior_auth_failed = TRUE;
+ }
+ g_free (old_auth_info);
}
if (!host->auth_realms) {
@@ -789,18 +790,13 @@ update_auth_internal (SoupSession *session, SoupMessage *msg,
host->auths = g_hash_table_new (g_str_hash, g_str_equal);
}
- /* Record where this auth realm is used */
- realm = g_strdup_printf ("%s:%s",
- soup_auth_get_scheme_name (new_auth),
- soup_auth_get_realm (new_auth));
-
- /*
- * RFC 2617 is somewhat unclear about the scope of protection
- * spaces with regard to proxies. The only mention of it is
- * as an aside in section 3.2.1, where it is defining the fields
- * of a Digest challenge and says that the protection space is
- * always the entire proxy. Is this the case for all authentication
- * schemes or just Digest? Who knows, but we're assuming all.
+ /* Record where this auth realm is used. RFC 2617 is somewhat
+ * unclear about the scope of protection spaces with regard to
+ * proxies. The only mention of it is as an aside in section
+ * 3.2.1, where it is defining the fields of a Digest
+ * challenge and says that the protection space is always the
+ * entire proxy. Is this the case for all authentication
+ * schemes or just Digest? Who knows, but we're assuming all.
*/
if (proxy)
pspace = g_slist_prepend (NULL, g_strdup (""));
@@ -810,14 +806,14 @@ update_auth_internal (SoupSession *session, SoupMessage *msg,
for (p = pspace; p; p = p->next) {
path = p->data;
if (g_hash_table_lookup_extended (host->auth_realms, path,
- &old_path, &old_realm)) {
+ &old_path, &old_auth_info)) {
g_hash_table_remove (host->auth_realms, old_path);
g_free (old_path);
- g_free (old_realm);
+ g_free (old_auth_info);
}
g_hash_table_insert (host->auth_realms,
- g_strdup (path), g_strdup (realm));
+ g_strdup (path), g_strdup (auth_info));
}
soup_auth_free_protection_space (new_auth, pspace);
@@ -825,13 +821,13 @@ update_auth_internal (SoupSession *session, SoupMessage *msg,
* pre-existing auth, we keep that rather than the new one,
* since the old one might already be authenticated.)
*/
- old_auth = g_hash_table_lookup (host->auths, realm);
+ old_auth = g_hash_table_lookup (host->auths, auth_info);
if (old_auth) {
- g_free (realm);
+ g_free (auth_info);
g_object_unref (new_auth);
new_auth = old_auth;
} else
- g_hash_table_insert (host->auths, realm, new_auth);
+ g_hash_table_insert (host->auths, auth_info, new_auth);
/* If we need to authenticate, try to do it. */
if (!soup_auth_is_authenticated (new_auth)) {