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"
20 * @short_description: HTTP client-side authentication support
21 * @see_also: #SoupSession
23 * #SoupAuth objects store the authentication data associated with a
24 * given bit of web space. They are created automatically by
31 * The abstract base class for handling authentication. Specific HTTP
32 * Authentication mechanisms are implemented by its subclasses, but
33 * applications never need to be aware of the specific subclasses
41 #define SOUP_AUTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH, SoupAuthPrivate))
43 G_DEFINE_ABSTRACT_TYPE (SoupAuth, soup_auth, G_TYPE_OBJECT)
52 PROP_IS_AUTHENTICATED,
58 soup_auth_init (SoupAuth *auth)
63 soup_auth_finalize (GObject *object)
65 SoupAuth *auth = SOUP_AUTH (object);
66 SoupAuthPrivate *priv = SOUP_AUTH_GET_PRIVATE (auth);
71 G_OBJECT_CLASS (soup_auth_parent_class)->finalize (object);
75 soup_auth_set_property (GObject *object, guint prop_id,
76 const GValue *value, GParamSpec *pspec)
78 SoupAuth *auth = SOUP_AUTH (object);
79 SoupAuthPrivate *priv = SOUP_AUTH_GET_PRIVATE (object);
83 auth->realm = g_value_dup_string (value);
86 priv->host = g_value_dup_string (value);
88 case PROP_IS_FOR_PROXY:
89 priv->proxy = g_value_get_boolean (value);
92 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
98 soup_auth_get_property (GObject *object, guint prop_id,
99 GValue *value, GParamSpec *pspec)
101 SoupAuth *auth = SOUP_AUTH (object);
102 SoupAuthPrivate *priv = SOUP_AUTH_GET_PRIVATE (object);
105 case PROP_SCHEME_NAME:
106 g_value_set_string (value, soup_auth_get_scheme_name (auth));
110 g_free (auth->realm);
111 g_value_set_string (value, soup_auth_get_realm (auth));
116 g_value_set_string (value, soup_auth_get_host (auth));
118 case PROP_IS_FOR_PROXY:
119 g_value_set_boolean (value, priv->proxy);
121 case PROP_IS_AUTHENTICATED:
122 g_value_set_boolean (value, soup_auth_is_authenticated (auth));
125 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
132 soup_auth_class_init (SoupAuthClass *auth_class)
134 GObjectClass *object_class = G_OBJECT_CLASS (auth_class);
136 g_type_class_add_private (auth_class, sizeof (SoupAuthPrivate));
138 object_class->finalize = soup_auth_finalize;
139 object_class->set_property = soup_auth_set_property;
140 object_class->get_property = soup_auth_get_property;
144 * SOUP_AUTH_SCHEME_NAME:
146 * An alias for the #SoupAuth:scheme-name property. (The
147 * authentication scheme name.)
149 g_object_class_install_property (
150 object_class, PROP_SCHEME_NAME,
151 g_param_spec_string (SOUP_AUTH_SCHEME_NAME,
153 "Authentication scheme name",
159 * An alias for the #SoupAuth:realm property. (The
160 * authentication realm.)
162 g_object_class_install_property (
163 object_class, PROP_REALM,
164 g_param_spec_string (SOUP_AUTH_REALM,
166 "Authentication realm",
172 * An alias for the #SoupAuth:host property. (The
173 * host being authenticated to.)
175 g_object_class_install_property (
176 object_class, PROP_HOST,
177 g_param_spec_string (SOUP_AUTH_HOST,
179 "Authentication host",
183 * SOUP_AUTH_IS_FOR_PROXY:
185 * An alias for the #SoupAuth:is-for-proxy property. (Whether
186 * or not the auth is for a proxy server.)
188 g_object_class_install_property (
189 object_class, PROP_IS_FOR_PROXY,
190 g_param_spec_boolean (SOUP_AUTH_IS_FOR_PROXY,
192 "Whether or not the auth is for a proxy server",
196 * SOUP_AUTH_IS_AUTHENTICATED:
198 * An alias for the #SoupAuth:is-authenticated property.
199 * (Whether or not the auth has been authenticated.)
201 g_object_class_install_property (
202 object_class, PROP_IS_AUTHENTICATED,
203 g_param_spec_boolean (SOUP_AUTH_IS_AUTHENTICATED,
205 "Whether or not the auth is authenticated",
212 * @type: the type of auth to create (a subtype of #SoupAuth)
213 * @msg: the #SoupMessage the auth is being created for
214 * @auth_header: the WWW-Authenticate/Proxy-Authenticate header
216 * Creates a new #SoupAuth of type @type with the information from
217 * @msg and @auth_header.
219 * This is called by #SoupSession; you will normally not create auths
222 * Return value: the new #SoupAuth, or %NULL if it could not be
226 soup_auth_new (GType type, SoupMessage *msg, const char *auth_header)
230 const char *scheme, *realm;
232 g_return_val_if_fail (g_type_is_a (type, SOUP_TYPE_AUTH), NULL);
233 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
234 g_return_val_if_fail (auth_header != NULL, NULL);
236 auth = g_object_new (type,
237 SOUP_AUTH_IS_FOR_PROXY, (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED),
238 SOUP_AUTH_HOST, soup_message_get_uri (msg)->host,
241 scheme = soup_auth_get_scheme_name (auth);
242 if (g_ascii_strncasecmp (auth_header, scheme, strlen (scheme)) != 0) {
243 g_object_unref (auth);
247 params = soup_header_parse_param_list (auth_header + strlen (scheme));
249 params = g_hash_table_new (NULL, NULL);
251 realm = g_hash_table_lookup (params, "realm");
253 auth->realm = g_strdup (realm);
255 if (!SOUP_AUTH_GET_CLASS (auth)->update (auth, msg, params)) {
256 g_object_unref (auth);
259 soup_header_free_param_list (params);
266 * @msg: the #SoupMessage @auth is being updated for
267 * @auth_header: the WWW-Authenticate/Proxy-Authenticate header
269 * Updates @auth with the information from @msg and @auth_header,
270 * possibly un-authenticating it. As with soup_auth_new(), this is
271 * normally only used by #SoupSession.
273 * Return value: %TRUE if @auth is still a valid (but potentially
274 * unauthenticated) #SoupAuth. %FALSE if something about @auth_params
275 * could not be parsed or incorporated into @auth at all.
278 soup_auth_update (SoupAuth *auth, SoupMessage *msg, const char *auth_header)
281 const char *scheme, *realm;
282 gboolean was_authenticated, success;
284 g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE);
285 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE);
286 g_return_val_if_fail (auth_header != NULL, FALSE);
288 scheme = soup_auth_get_scheme_name (auth);
289 if (g_ascii_strncasecmp (auth_header, scheme, strlen (scheme)) != 0)
292 params = soup_header_parse_param_list (auth_header + strlen (scheme));
294 params = g_hash_table_new (NULL, NULL);
296 realm = g_hash_table_lookup (params, "realm");
297 if (realm && auth->realm && strcmp (realm, auth->realm) != 0) {
298 soup_header_free_param_list (params);
302 was_authenticated = soup_auth_is_authenticated (auth);
303 success = SOUP_AUTH_GET_CLASS (auth)->update (auth, msg, params);
304 if (was_authenticated != soup_auth_is_authenticated (auth))
305 g_object_notify (G_OBJECT (auth), SOUP_AUTH_IS_AUTHENTICATED);
306 soup_header_free_param_list (params);
311 * soup_auth_authenticate:
313 * @username: the username provided by the user or client
314 * @password: the password provided by the user or client
316 * Call this on an auth to authenticate it; normally this will cause
317 * the auth's message to be requeued with the new authentication info.
320 soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password)
322 gboolean was_authenticated;
324 g_return_if_fail (SOUP_IS_AUTH (auth));
325 g_return_if_fail (username != NULL);
326 g_return_if_fail (password != NULL);
328 was_authenticated = soup_auth_is_authenticated (auth);
329 SOUP_AUTH_GET_CLASS (auth)->authenticate (auth, username, password);
330 if (was_authenticated != soup_auth_is_authenticated (auth))
331 g_object_notify (G_OBJECT (auth), SOUP_AUTH_IS_AUTHENTICATED);
335 * soup_auth_is_for_proxy:
338 * Tests whether or not @auth is associated with a proxy server rather
339 * than an "origin" server.
341 * Return value: %TRUE or %FALSE
344 soup_auth_is_for_proxy (SoupAuth *auth)
346 g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE);
348 return SOUP_AUTH_GET_PRIVATE (auth)->proxy;
352 * soup_auth_get_scheme_name:
355 * Returns @auth's scheme name. (Eg, "Basic", "Digest", or "NTLM")
357 * Return value: the scheme name
360 soup_auth_get_scheme_name (SoupAuth *auth)
362 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
364 return SOUP_AUTH_GET_CLASS (auth)->scheme_name;
368 * soup_auth_get_host:
371 * Returns the host that @auth is associated with.
373 * Return value: the hostname
376 soup_auth_get_host (SoupAuth *auth)
378 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
380 return SOUP_AUTH_GET_PRIVATE (auth)->host;
385 * soup_auth_get_realm:
388 * Returns @auth's realm. This is an identifier that distinguishes
389 * separate authentication spaces on a given server, and may be some
390 * string that is meaningful to the user. (Although it is probably not
393 * Return value: the realm name
396 soup_auth_get_realm (SoupAuth *auth)
398 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
404 * soup_auth_get_info:
407 * Gets an opaque identifier for @auth, for use as a hash key or the
408 * like. #SoupAuth objects from the same server with the same
409 * identifier refer to the same authentication domain (eg, the URLs
410 * associated with them take the same usernames and passwords).
412 * Return value: the identifier
415 soup_auth_get_info (SoupAuth *auth)
417 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
419 if (SOUP_IS_CONNECTION_AUTH (auth))
420 return g_strdup (SOUP_AUTH_GET_CLASS (auth)->scheme_name);
422 return g_strdup_printf ("%s:%s",
423 SOUP_AUTH_GET_CLASS (auth)->scheme_name,
429 * soup_auth_is_authenticated:
432 * Tests if @auth has been given a username and password
434 * Return value: %TRUE if @auth has been given a username and password
437 soup_auth_is_authenticated (SoupAuth *auth)
439 g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE);
441 return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth);
445 * soup_auth_get_authorization:
447 * @msg: the #SoupMessage to be authorized
449 * Generates an appropriate "Authorization" header for @msg. (The
450 * session will only call this if soup_auth_is_authenticated()
453 * Return value: the "Authorization" header, which must be freed.
456 soup_auth_get_authorization (SoupAuth *auth, SoupMessage *msg)
458 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
459 g_return_val_if_fail (msg != NULL, NULL);
461 return SOUP_AUTH_GET_CLASS (auth)->get_authorization (auth, msg);
465 * soup_auth_is_ready:
467 * @msg: a #SoupMessage
469 * Tests if @auth is ready to make a request for @msg with. For most
470 * auths, this is equivalent to soup_auth_is_authenticated(), but for
471 * some auth types (eg, NTLM), the auth may be sendable (eg, as an
472 * authentication request) even before it is authenticated.
474 * Return value: %TRUE if @auth is ready to make a request with.
479 soup_auth_is_ready (SoupAuth *auth,
482 g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE);
483 g_return_val_if_fail (SOUP_IS_MESSAGE (msg), TRUE);
485 if (SOUP_AUTH_GET_CLASS (auth)->is_ready)
486 return SOUP_AUTH_GET_CLASS (auth)->is_ready (auth, msg);
488 return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth);
492 * soup_auth_get_protection_space:
494 * @source_uri: the URI of the request that @auth was generated in
497 * Returns a list of paths on the server which @auth extends over.
498 * (All subdirectories of these paths are also assumed to be part
499 * of @auth's protection space, unless otherwise discovered not to
502 * Return value: (element-type utf8) (transfer full): the list of
503 * paths, which can be freed with soup_auth_free_protection_space().
506 soup_auth_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
508 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
509 g_return_val_if_fail (source_uri != NULL, NULL);
511 return SOUP_AUTH_GET_CLASS (auth)->get_protection_space (auth, source_uri);
515 * soup_auth_free_protection_space: (skip)
517 * @space: the return value from soup_auth_get_protection_space()
522 soup_auth_free_protection_space (SoupAuth *auth, GSList *space)
524 g_slist_free_full (space, g_free);
528 * soup_auth_get_saved_users:
530 * Return value: (transfer full) (element-type utf8):
533 soup_auth_get_saved_users (SoupAuth *auth)
539 soup_auth_get_saved_password (SoupAuth *auth, const char *user)
545 soup_auth_has_saved_password (SoupAuth *auth, const char *username,
546 const char *password)
551 soup_auth_save_password (SoupAuth *auth, const char *username,
552 const char *password)