diff options
author | Dan Winship <danw@src.gnome.org> | 2007-09-25 03:11:18 +0000 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2007-09-25 03:11:18 +0000 |
commit | 1ef84727183daf0fcf8043383c012834576ee359 (patch) | |
tree | f08d1d4f6bf343f822c87288673f48cd7ea43bbf /libsoup | |
parent | b8b3779563f8f49a81b0bf117ba8f0256671ee14 (diff) | |
download | libsoup-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.c | 27 | ||||
-rw-r--r-- | libsoup/soup-auth-digest.c | 41 | ||||
-rw-r--r-- | libsoup/soup-auth.c | 77 | ||||
-rw-r--r-- | libsoup/soup-auth.h | 6 | ||||
-rw-r--r-- | libsoup/soup-session.c | 70 |
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)) { |