1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-auth.c: HTTP Authentication framework
5 * Copyright (C) 2001-2003, Ximian, Inc.
14 #include "soup-auth.h"
16 #include "soup-connection-auth.h"
17 #include "soup-marshal.h"
21 * @short_description: HTTP client-side authentication support
22 * @see_also: #SoupSession
24 * #SoupAuth objects store the authentication data associated with a
25 * given bit of web space. They are created automatically by
32 * The abstract base class for handling authentication. Specific HTTP
33 * Authentication mechanisms are implemented by its subclasses, but
34 * applications never need to be aware of the specific subclasses
42 #define SOUP_AUTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH, SoupAuthPrivate))
44 G_DEFINE_ABSTRACT_TYPE (SoupAuth, soup_auth, G_TYPE_OBJECT)
53 PROP_IS_AUTHENTICATED,
59 soup_auth_init (SoupAuth *auth)
64 soup_auth_finalize (GObject *object)
66 SoupAuth *auth = SOUP_AUTH (object);
67 SoupAuthPrivate *priv = SOUP_AUTH_GET_PRIVATE (auth);
72 G_OBJECT_CLASS (soup_auth_parent_class)->finalize (object);
76 soup_auth_set_property (GObject *object, guint prop_id,
77 const GValue *value, GParamSpec *pspec)
79 SoupAuth *auth = SOUP_AUTH (object);
80 SoupAuthPrivate *priv = SOUP_AUTH_GET_PRIVATE (object);
84 auth->realm = g_value_dup_string (value);
87 priv->host = g_value_dup_string (value);
89 case PROP_IS_FOR_PROXY:
90 priv->proxy = g_value_get_boolean (value);
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
99 soup_auth_get_property (GObject *object, guint prop_id,
100 GValue *value, GParamSpec *pspec)
102 SoupAuth *auth = SOUP_AUTH (object);
103 SoupAuthPrivate *priv = SOUP_AUTH_GET_PRIVATE (object);
106 case PROP_SCHEME_NAME:
107 g_value_set_string (value, soup_auth_get_scheme_name (auth));
111 g_free (auth->realm);
112 g_value_set_string (value, soup_auth_get_realm (auth));
117 g_value_set_string (value, soup_auth_get_host (auth));
119 case PROP_IS_FOR_PROXY:
120 g_value_set_boolean (value, priv->proxy);
122 case PROP_IS_AUTHENTICATED:
123 g_value_set_boolean (value, soup_auth_is_authenticated (auth));
126 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
133 soup_auth_class_init (SoupAuthClass *auth_class)
135 GObjectClass *object_class = G_OBJECT_CLASS (auth_class);
137 g_type_class_add_private (auth_class, sizeof (SoupAuthPrivate));
139 object_class->finalize = soup_auth_finalize;
140 object_class->set_property = soup_auth_set_property;
141 object_class->get_property = soup_auth_get_property;
145 * SOUP_AUTH_SCHEME_NAME:
147 * An alias for the #SoupAuth:scheme-name property. (The
148 * authentication scheme name.)
150 g_object_class_install_property (
151 object_class, PROP_SCHEME_NAME,
152 g_param_spec_string (SOUP_AUTH_SCHEME_NAME,
154 "Authentication scheme name",
160 * An alias for the #SoupAuth:realm property. (The
161 * authentication realm.)
163 g_object_class_install_property (
164 object_class, PROP_REALM,
165 g_param_spec_string (SOUP_AUTH_REALM,
167 "Authentication realm",
173 * An alias for the #SoupAuth:host property. (The
174 * host being authenticated to.)
176 g_object_class_install_property (
177 object_class, PROP_HOST,
178 g_param_spec_string (SOUP_AUTH_HOST,
180 "Authentication host",
184 * SOUP_AUTH_IS_FOR_PROXY:
186 * An alias for the #SoupAuth:is-for-proxy property. (Whether
187 * or not the auth is for a proxy server.)
189 g_object_class_install_property (
190 object_class, PROP_IS_FOR_PROXY,
191 g_param_spec_boolean (SOUP_AUTH_IS_FOR_PROXY,
193 "Whether or not the auth is for a proxy server",
197 * SOUP_AUTH_IS_AUTHENTICATED:
199 * An alias for the #SoupAuth:is-authenticated property.
200 * (Whether or not the auth has been authenticated.)
202 g_object_class_install_property (
203 object_class, PROP_IS_AUTHENTICATED,
204 g_param_spec_boolean (SOUP_AUTH_IS_AUTHENTICATED,
206 "Whether or not the auth is authenticated",
213 * @type: the type of auth to create (a subtype of #SoupAuth)
214 * @msg: the #SoupMessage the auth is being created for
215 * @auth_header: the WWW-Authenticate/Proxy-Authenticate header
217 * Creates a new #SoupAuth of type @type with the information from
218 * @msg and @auth_header.
220 * This is called by #SoupSession; you will normally not create auths
223 * Return value: the new #SoupAuth, or %NULL if it could not be
227 soup_auth_new (GType type, SoupMessage *msg, const char *auth_header)
231 const char *scheme, *realm;
233 g_return_val_if_fail (g_type_is_a (type, SOUP_TYPE_AUTH), NULL);
234 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
235 g_return_val_if_fail (auth_header != NULL, NULL);
237 auth = g_object_new (type,
238 SOUP_AUTH_IS_FOR_PROXY, (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED),
239 SOUP_AUTH_HOST, soup_message_get_uri (msg)->host,
242 scheme = soup_auth_get_scheme_name (auth);
243 if (g_ascii_strncasecmp (auth_header, scheme, strlen (scheme)) != 0) {
244 g_object_unref (auth);
248 params = soup_header_parse_param_list (auth_header + strlen (scheme));
250 params = g_hash_table_new (NULL, NULL);
252 realm = g_hash_table_lookup (params, "realm");
254 auth->realm = g_strdup (realm);
256 if (!SOUP_AUTH_GET_CLASS (auth)->update (auth, msg, params)) {
257 g_object_unref (auth);
260 soup_header_free_param_list (params);
267 * @msg: the #SoupMessage @auth is being updated for
268 * @auth_header: the WWW-Authenticate/Proxy-Authenticate header
270 * Updates @auth with the information from @msg and @auth_header,
271 * possibly un-authenticating it. As with soup_auth_new(), this is
272 * normally only used by #SoupSession.
274 * Return value: %TRUE if @auth is still a valid (but potentially
275 * unauthenticated) #SoupAuth. %FALSE if something about @auth_params
276 * could not be parsed or incorporated into @auth at all.
279 soup_auth_update (SoupAuth *auth, SoupMessage *msg, const char *auth_header)
282 const char *scheme, *realm;
283 gboolean was_authenticated, success;
285 g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE);
286 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE);
287 g_return_val_if_fail (auth_header != NULL, FALSE);
289 scheme = soup_auth_get_scheme_name (auth);
290 if (g_ascii_strncasecmp (auth_header, scheme, strlen (scheme)) != 0)
293 params = soup_header_parse_param_list (auth_header + strlen (scheme));
295 params = g_hash_table_new (NULL, NULL);
297 realm = g_hash_table_lookup (params, "realm");
298 if (realm && auth->realm && strcmp (realm, auth->realm) != 0) {
299 soup_header_free_param_list (params);
303 was_authenticated = soup_auth_is_authenticated (auth);
304 success = SOUP_AUTH_GET_CLASS (auth)->update (auth, msg, params);
305 if (was_authenticated != soup_auth_is_authenticated (auth))
306 g_object_notify (G_OBJECT (auth), SOUP_AUTH_IS_AUTHENTICATED);
307 soup_header_free_param_list (params);
312 * soup_auth_authenticate:
314 * @username: the username provided by the user or client
315 * @password: the password provided by the user or client
317 * Call this on an auth to authenticate it; normally this will cause
318 * the auth's message to be requeued with the new authentication info.
321 soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password)
323 gboolean was_authenticated;
325 g_return_if_fail (SOUP_IS_AUTH (auth));
326 g_return_if_fail (username != NULL);
327 g_return_if_fail (password != NULL);
329 was_authenticated = soup_auth_is_authenticated (auth);
330 SOUP_AUTH_GET_CLASS (auth)->authenticate (auth, username, password);
331 if (was_authenticated != soup_auth_is_authenticated (auth))
332 g_object_notify (G_OBJECT (auth), SOUP_AUTH_IS_AUTHENTICATED);
336 * soup_auth_is_for_proxy:
339 * Tests whether or not @auth is associated with a proxy server rather
340 * than an "origin" server.
342 * Return value: %TRUE or %FALSE
345 soup_auth_is_for_proxy (SoupAuth *auth)
347 g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE);
349 return SOUP_AUTH_GET_PRIVATE (auth)->proxy;
353 * soup_auth_get_scheme_name:
356 * Returns @auth's scheme name. (Eg, "Basic", "Digest", or "NTLM")
358 * Return value: the scheme name
361 soup_auth_get_scheme_name (SoupAuth *auth)
363 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
365 return SOUP_AUTH_GET_CLASS (auth)->scheme_name;
369 * soup_auth_get_host:
372 * Returns the host that @auth is associated with.
374 * Return value: the hostname
377 soup_auth_get_host (SoupAuth *auth)
379 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
381 return SOUP_AUTH_GET_PRIVATE (auth)->host;
386 * soup_auth_get_realm:
389 * Returns @auth's realm. This is an identifier that distinguishes
390 * separate authentication spaces on a given server, and may be some
391 * string that is meaningful to the user. (Although it is probably not
394 * Return value: the realm name
397 soup_auth_get_realm (SoupAuth *auth)
399 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
405 * soup_auth_get_info:
408 * Gets an opaque identifier for @auth, for use as a hash key or the
409 * like. #SoupAuth objects from the same server with the same
410 * identifier refer to the same authentication domain (eg, the URLs
411 * associated with them take the same usernames and passwords).
413 * Return value: the identifier
416 soup_auth_get_info (SoupAuth *auth)
418 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
420 if (SOUP_IS_CONNECTION_AUTH (auth))
421 return g_strdup (SOUP_AUTH_GET_CLASS (auth)->scheme_name);
423 return g_strdup_printf ("%s:%s",
424 SOUP_AUTH_GET_CLASS (auth)->scheme_name,
430 * soup_auth_is_authenticated:
433 * Tests if @auth has been given a username and password
435 * Return value: %TRUE if @auth has been given a username and password
438 soup_auth_is_authenticated (SoupAuth *auth)
440 g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE);
442 return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth);
446 * soup_auth_get_authorization:
448 * @msg: the #SoupMessage to be authorized
450 * Generates an appropriate "Authorization" header for @msg. (The
451 * session will only call this if soup_auth_is_authenticated()
454 * Return value: the "Authorization" header, which must be freed.
457 soup_auth_get_authorization (SoupAuth *auth, SoupMessage *msg)
459 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
460 g_return_val_if_fail (msg != NULL, NULL);
462 return SOUP_AUTH_GET_CLASS (auth)->get_authorization (auth, msg);
466 * soup_auth_is_ready:
468 * @msg: a #SoupMessage
470 * Tests if @auth is ready to make a request for @msg with. For most
471 * auths, this is equivalent to soup_auth_is_authenticated(), but for
472 * some auth types (eg, NTLM), the auth may be sendable (eg, as an
473 * authentication request) even before it is authenticated.
475 * Return value: %TRUE if @auth is ready to make a request with.
480 soup_auth_is_ready (SoupAuth *auth,
483 g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE);
484 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), TRUE);
486 if (SOUP_AUTH_GET_CLASS (auth)->is_ready)
487 return SOUP_AUTH_GET_CLASS (auth)->is_ready (auth, msg);
489 return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth);
493 * soup_auth_get_protection_space:
495 * @source_uri: the URI of the request that @auth was generated in
498 * Returns a list of paths on the server which @auth extends over.
499 * (All subdirectories of these paths are also assumed to be part
500 * of @auth's protection space, unless otherwise discovered not to
503 * Return value: (element-type utf8) (transfer full): the list of
504 * paths, which can be freed with soup_auth_free_protection_space().
507 soup_auth_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
509 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
510 g_return_val_if_fail (source_uri != NULL, NULL);
512 return SOUP_AUTH_GET_CLASS (auth)->get_protection_space (auth, source_uri);
516 * soup_auth_free_protection_space: (skip)
518 * @space: the return value from soup_auth_get_protection_space()
523 soup_auth_free_protection_space (SoupAuth *auth, GSList *space)
525 g_slist_free_full (space, g_free);
529 soup_auth_get_saved_users (SoupAuth *auth)
535 soup_auth_get_saved_password (SoupAuth *auth, const char *user)
541 soup_auth_has_saved_password (SoupAuth *auth, const char *username,
542 const char *password)
547 soup_auth_save_password (SoupAuth *auth, const char *username,
548 const char *password)