Blame libsoup/soup-auth-digest.c

rpm-build 4f3c61
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
rpm-build 4f3c61
/*
rpm-build 4f3c61
 * soup-auth-digest.c: HTTP Digest Authentication
rpm-build 4f3c61
 *
rpm-build 4f3c61
 * Copyright (C) 2001-2003, Ximian, 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-digest.h"
rpm-build 4f3c61
#include "soup.h"
rpm-build 4f3c61
#include "soup-message-private.h"
rpm-build 4f3c61
rpm-build 4f3c61
#ifdef G_OS_WIN32
rpm-build 4f3c61
#include <process.h>
rpm-build 4f3c61
#endif
rpm-build 4f3c61
rpm-build 4f3c61
typedef struct {
rpm-build 4f3c61
	char                    *user;
rpm-build 4f3c61
	char                     hex_urp[33];
rpm-build 4f3c61
	char                     hex_a1[33];
rpm-build 4f3c61
rpm-build 4f3c61
	/* These are provided by the server */
rpm-build 4f3c61
	char                    *nonce;
rpm-build 4f3c61
	char                    *opaque;
rpm-build 4f3c61
	SoupAuthDigestQop        qop_options;
rpm-build 4f3c61
	SoupAuthDigestAlgorithm  algorithm;
rpm-build 4f3c61
	char                    *domain;
rpm-build 4f3c61
rpm-build 4f3c61
	/* These are generated by the client */
rpm-build 4f3c61
	char                    *cnonce;
rpm-build 4f3c61
	int                      nc;
rpm-build 4f3c61
	SoupAuthDigestQop        qop;
rpm-build 4f3c61
} SoupAuthDigestPrivate;
rpm-build 4f3c61
rpm-build 4f3c61
static void recompute_hex_a1 (SoupAuthDigestPrivate *priv);
rpm-build 4f3c61
rpm-build 4f3c61
/**
rpm-build 4f3c61
 * SOUP_TYPE_AUTH_DIGEST:
rpm-build 4f3c61
 *
rpm-build 4f3c61
 * A #GType corresponding to HTTP "Digest" authentication.
rpm-build 4f3c61
 * #SoupSessions support this by default; if you want to disable
rpm-build 4f3c61
 * support for it, call soup_session_remove_feature_by_type(),
rpm-build 4f3c61
 * passing %SOUP_TYPE_AUTH_DIGEST.
rpm-build 4f3c61
 *
rpm-build 4f3c61
 * Since: 2.34
rpm-build 4f3c61
 */
rpm-build 4f3c61
rpm-build 4f3c61
G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthDigest, soup_auth_digest, SOUP_TYPE_AUTH)
rpm-build 4f3c61
rpm-build 4f3c61
static void
rpm-build 4f3c61
soup_auth_digest_init (SoupAuthDigest *digest)
rpm-build 4f3c61
{
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static void
rpm-build 4f3c61
soup_auth_digest_finalize (GObject *object)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (SOUP_AUTH_DIGEST (object));
rpm-build 4f3c61
rpm-build 4f3c61
	g_free (priv->user);
rpm-build 4f3c61
	g_free (priv->nonce);
rpm-build 4f3c61
	g_free (priv->domain);
rpm-build 4f3c61
	g_free (priv->cnonce);
rpm-build 4f3c61
rpm-build 4f3c61
	memset (priv->hex_urp, 0, sizeof (priv->hex_urp));
rpm-build 4f3c61
	memset (priv->hex_a1, 0, sizeof (priv->hex_a1));
rpm-build 4f3c61
rpm-build 4f3c61
	G_OBJECT_CLASS (soup_auth_digest_parent_class)->finalize (object);
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
SoupAuthDigestAlgorithm
rpm-build 4f3c61
soup_auth_digest_parse_algorithm (const char *algorithm)
rpm-build 4f3c61
{
rpm-build 4f3c61
	if (!algorithm || !g_ascii_strcasecmp (algorithm, "MD5"))
rpm-build 4f3c61
		return SOUP_AUTH_DIGEST_ALGORITHM_MD5;
rpm-build 4f3c61
	else if (!g_ascii_strcasecmp (algorithm, "MD5-sess"))
rpm-build 4f3c61
		return SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS;
rpm-build 4f3c61
	else
rpm-build 4f3c61
		return -1;
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
char *
rpm-build 4f3c61
soup_auth_digest_get_algorithm (SoupAuthDigestAlgorithm algorithm)
rpm-build 4f3c61
{
rpm-build 4f3c61
	if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5)
rpm-build 4f3c61
		return g_strdup ("MD5");
rpm-build 4f3c61
	else if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS)
rpm-build 4f3c61
		return g_strdup ("MD5-sess");
rpm-build 4f3c61
	else
rpm-build 4f3c61
		return NULL;
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
SoupAuthDigestQop
rpm-build 4f3c61
soup_auth_digest_parse_qop (const char *qop)
rpm-build 4f3c61
{
rpm-build 4f3c61
	GSList *qop_values, *iter;
rpm-build 4f3c61
	SoupAuthDigestQop out = 0;
rpm-build 4f3c61
rpm-build 4f3c61
	g_return_val_if_fail (qop != NULL, 0);
rpm-build 4f3c61
rpm-build 4f3c61
	qop_values = soup_header_parse_list (qop);
rpm-build 4f3c61
	for (iter = qop_values; iter; iter = iter->next) {
rpm-build 4f3c61
		if (!g_ascii_strcasecmp (iter->data, "auth"))
rpm-build 4f3c61
			out |= SOUP_AUTH_DIGEST_QOP_AUTH;
rpm-build 4f3c61
		else if (!g_ascii_strcasecmp (iter->data, "auth-int"))
rpm-build 4f3c61
			out |= SOUP_AUTH_DIGEST_QOP_AUTH_INT;
rpm-build 4f3c61
	}
rpm-build 4f3c61
	soup_header_free_list (qop_values);
rpm-build 4f3c61
rpm-build 4f3c61
	return out;
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
char *
rpm-build 4f3c61
soup_auth_digest_get_qop (SoupAuthDigestQop qop)
rpm-build 4f3c61
{
rpm-build 4f3c61
	GString *out;
rpm-build 4f3c61
rpm-build 4f3c61
	out = g_string_new (NULL);
rpm-build 4f3c61
	if (qop & SOUP_AUTH_DIGEST_QOP_AUTH)
rpm-build 4f3c61
		g_string_append (out, "auth");
rpm-build 4f3c61
	if (qop & SOUP_AUTH_DIGEST_QOP_AUTH_INT) {
rpm-build 4f3c61
		if (qop & SOUP_AUTH_DIGEST_QOP_AUTH)
rpm-build 4f3c61
			g_string_append (out, ",");
rpm-build 4f3c61
		g_string_append (out, "auth-int");
rpm-build 4f3c61
	}
rpm-build 4f3c61
rpm-build 4f3c61
	return g_string_free (out, FALSE);
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static gboolean
rpm-build 4f3c61
soup_auth_digest_update (SoupAuth *auth, SoupMessage *msg,
rpm-build 4f3c61
			 GHashTable *auth_params)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth);
rpm-build 4f3c61
	SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest);
rpm-build 4f3c61
	const char *stale, *qop;
rpm-build 4f3c61
	guint qop_options;
rpm-build 4f3c61
	gboolean ok = TRUE;
rpm-build 4f3c61
rpm-build 4f3c61
	g_free (priv->domain);
rpm-build 4f3c61
	g_free (priv->nonce);
rpm-build 4f3c61
	g_free (priv->opaque);
rpm-build 4f3c61
rpm-build 4f3c61
	priv->nc = 1;
rpm-build 4f3c61
rpm-build 4f3c61
	priv->domain = g_strdup (g_hash_table_lookup (auth_params, "domain"));
rpm-build 4f3c61
	priv->nonce = g_strdup (g_hash_table_lookup (auth_params, "nonce"));
rpm-build 4f3c61
	priv->opaque = g_strdup (g_hash_table_lookup (auth_params, "opaque"));
rpm-build 4f3c61
rpm-build 4f3c61
	qop = g_hash_table_lookup (auth_params, "qop");
rpm-build 4f3c61
	if (qop) {
rpm-build 4f3c61
		qop_options = soup_auth_digest_parse_qop (qop);
rpm-build 4f3c61
		/* We only support auth */
rpm-build 4f3c61
		if (!(qop_options & SOUP_AUTH_DIGEST_QOP_AUTH))
rpm-build 4f3c61
			ok = FALSE;
rpm-build 4f3c61
		priv->qop = SOUP_AUTH_DIGEST_QOP_AUTH;
rpm-build 4f3c61
	} else
rpm-build 4f3c61
		priv->qop = 0;
rpm-build 4f3c61
rpm-build 4f3c61
	priv->algorithm = soup_auth_digest_parse_algorithm (g_hash_table_lookup (auth_params, "algorithm"));
rpm-build 4f3c61
	if (priv->algorithm == -1)
rpm-build 4f3c61
		ok = FALSE;
rpm-build 4f3c61
rpm-build 4f3c61
	stale = g_hash_table_lookup (auth_params, "stale");
rpm-build 4f3c61
	if (stale && !g_ascii_strcasecmp (stale, "TRUE") && *priv->hex_urp)
rpm-build 4f3c61
		recompute_hex_a1 (priv);
rpm-build 4f3c61
	else {
rpm-build 4f3c61
		g_free (priv->user);
rpm-build 4f3c61
		priv->user = NULL;
rpm-build 4f3c61
		g_free (priv->cnonce);
rpm-build 4f3c61
		priv->cnonce = NULL;
rpm-build 4f3c61
		memset (priv->hex_urp, 0, sizeof (priv->hex_urp));
rpm-build 4f3c61
		memset (priv->hex_a1, 0, sizeof (priv->hex_a1));
rpm-build 4f3c61
        }
rpm-build 4f3c61
rpm-build 4f3c61
	return ok;
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static GSList *
rpm-build 4f3c61
soup_auth_digest_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth);
rpm-build 4f3c61
	SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest);
rpm-build 4f3c61
	GSList *space = NULL;
rpm-build 4f3c61
	SoupURI *uri;
rpm-build 4f3c61
	char **dvec, *d, *dir, *slash;
rpm-build 4f3c61
	int dix;
rpm-build 4f3c61
rpm-build 4f3c61
	if (!priv->domain || !*priv->domain) {
rpm-build 4f3c61
		/* If no domain directive, the protection space is the
rpm-build 4f3c61
		 * whole server.
rpm-build 4f3c61
		 */
rpm-build 4f3c61
		return g_slist_prepend (NULL, g_strdup (""));
rpm-build 4f3c61
	}
rpm-build 4f3c61
rpm-build 4f3c61
	dvec = g_strsplit (priv->domain, " ", 0);
rpm-build 4f3c61
	for (dix = 0; dvec[dix] != NULL; dix++) {
rpm-build 4f3c61
		d = dvec[dix];
rpm-build 4f3c61
		if (*d == '/')
rpm-build 4f3c61
			dir = g_strdup (d);
rpm-build 4f3c61
		else {
rpm-build 4f3c61
			uri = soup_uri_new (d);
rpm-build 4f3c61
			if (uri && uri->scheme == source_uri->scheme &&
rpm-build 4f3c61
			    uri->port == source_uri->port &&
rpm-build 4f3c61
			    !strcmp (uri->host, source_uri->host))
rpm-build 4f3c61
				dir = g_strdup (uri->path);
rpm-build 4f3c61
			else
rpm-build 4f3c61
				dir = NULL;
rpm-build 4f3c61
			if (uri)
rpm-build 4f3c61
				soup_uri_free (uri);
rpm-build 4f3c61
		}
rpm-build 4f3c61
rpm-build 4f3c61
		if (dir) {
rpm-build 4f3c61
			slash = strrchr (dir, '/');
rpm-build 4f3c61
			if (slash && !slash[1])
rpm-build 4f3c61
				*slash = '\0';
rpm-build 4f3c61
rpm-build 4f3c61
			space = g_slist_prepend (space, dir);
rpm-build 4f3c61
		}
rpm-build 4f3c61
	}
rpm-build 4f3c61
	g_strfreev (dvec);
rpm-build 4f3c61
rpm-build 4f3c61
	return space;
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
void
rpm-build 4f3c61
soup_auth_digest_compute_hex_urp (const char *username,
rpm-build 4f3c61
				  const char *realm,
rpm-build 4f3c61
				  const char *password,
rpm-build 4f3c61
				  char        hex_urp[33])
rpm-build 4f3c61
{
rpm-build 4f3c61
	GChecksum *checksum;
rpm-build 4f3c61
rpm-build 4f3c61
	checksum = g_checksum_new (G_CHECKSUM_MD5);
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)username, strlen (username));
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)realm, strlen (realm));
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)password, strlen (password));
rpm-build 4f3c61
	strncpy (hex_urp, g_checksum_get_string (checksum), 33);
rpm-build 4f3c61
	g_checksum_free (checksum);
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
void
rpm-build 4f3c61
soup_auth_digest_compute_hex_a1 (const char              *hex_urp,
rpm-build 4f3c61
				 SoupAuthDigestAlgorithm  algorithm,
rpm-build 4f3c61
				 const char              *nonce,
rpm-build 4f3c61
				 const char              *cnonce,
rpm-build 4f3c61
				 char                     hex_a1[33])
rpm-build 4f3c61
{
rpm-build 4f3c61
	if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5) {
rpm-build 4f3c61
		/* In MD5, A1 is just user:realm:password, so hex_A1
rpm-build 4f3c61
		 * is just hex_urp.
rpm-build 4f3c61
		 */
rpm-build 4f3c61
		/* You'd think you could say "sizeof (hex_a1)" here,
rpm-build 4f3c61
		 * but you'd be wrong.
rpm-build 4f3c61
		 */
rpm-build 4f3c61
		memcpy (hex_a1, hex_urp, 33);
rpm-build 4f3c61
	} else {
rpm-build 4f3c61
		GChecksum *checksum;
rpm-build 4f3c61
rpm-build 4f3c61
		/* In MD5-sess, A1 is hex_urp:nonce:cnonce */
rpm-build 4f3c61
rpm-build 4f3c61
		checksum = g_checksum_new (G_CHECKSUM_MD5);
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)hex_urp, strlen (hex_urp));
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)nonce, strlen (nonce));
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce));
rpm-build 4f3c61
		strncpy (hex_a1, g_checksum_get_string (checksum), 33);
rpm-build 4f3c61
		g_checksum_free (checksum);
rpm-build 4f3c61
	}
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static void
rpm-build 4f3c61
recompute_hex_a1 (SoupAuthDigestPrivate *priv)
rpm-build 4f3c61
{
rpm-build 4f3c61
	soup_auth_digest_compute_hex_a1 (priv->hex_urp,
rpm-build 4f3c61
					 priv->algorithm,
rpm-build 4f3c61
					 priv->nonce,
rpm-build 4f3c61
					 priv->cnonce,
rpm-build 4f3c61
					 priv->hex_a1);
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static void
rpm-build 4f3c61
soup_auth_digest_authenticate (SoupAuth *auth, const char *username,
rpm-build 4f3c61
			       const char *password)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth);
rpm-build 4f3c61
	SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest);
rpm-build 4f3c61
	char *bgen;
rpm-build 4f3c61
rpm-build 4f3c61
	g_clear_pointer (&priv->cnonce, g_free);
rpm-build 4f3c61
	g_clear_pointer (&priv->user, g_free);
rpm-build 4f3c61
rpm-build 4f3c61
	/* Create client nonce */
rpm-build 4f3c61
	bgen = g_strdup_printf ("%p:%lu:%lu",
rpm-build 4f3c61
				auth,
rpm-build 4f3c61
				(unsigned long) getpid (),
rpm-build 4f3c61
				(unsigned long) time (0));
rpm-build 4f3c61
	priv->cnonce = g_base64_encode ((guchar *)bgen, strlen (bgen));
rpm-build 4f3c61
	g_free (bgen);
rpm-build 4f3c61
rpm-build 4f3c61
	priv->user = g_strdup (username);
rpm-build 4f3c61
rpm-build 4f3c61
	/* compute "URP" (user:realm:password) */
rpm-build 4f3c61
	soup_auth_digest_compute_hex_urp (username, auth->realm,
rpm-build 4f3c61
					  password ? password : "",
rpm-build 4f3c61
					  priv->hex_urp);
rpm-build 4f3c61
rpm-build 4f3c61
	/* And compute A1 from that */
rpm-build 4f3c61
	recompute_hex_a1 (priv);
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static gboolean
rpm-build 4f3c61
soup_auth_digest_is_authenticated (SoupAuth *auth)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (SOUP_AUTH_DIGEST (auth));
rpm-build 4f3c61
rpm-build 4f3c61
	return priv->cnonce != NULL;
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
void
rpm-build 4f3c61
soup_auth_digest_compute_response (const char        *method,
rpm-build 4f3c61
				   const char        *uri,
rpm-build 4f3c61
				   const char        *hex_a1,
rpm-build 4f3c61
				   SoupAuthDigestQop  qop,
rpm-build 4f3c61
				   const char        *nonce,
rpm-build 4f3c61
				   const char        *cnonce,
rpm-build 4f3c61
				   int                nc,
rpm-build 4f3c61
				   char               response[33])
rpm-build 4f3c61
{
rpm-build 4f3c61
	char hex_a2[33];
rpm-build 4f3c61
	GChecksum *checksum;
rpm-build 4f3c61
rpm-build 4f3c61
	/* compute A2 */
rpm-build 4f3c61
	checksum = g_checksum_new (G_CHECKSUM_MD5);
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)method, strlen (method));
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)uri, strlen (uri));
rpm-build 4f3c61
	strncpy (hex_a2, g_checksum_get_string (checksum), 33);
rpm-build 4f3c61
	g_checksum_free (checksum);
rpm-build 4f3c61
rpm-build 4f3c61
	/* compute KD */
rpm-build 4f3c61
	checksum = g_checksum_new (G_CHECKSUM_MD5);
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)hex_a1, strlen (hex_a1));
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)nonce, strlen (nonce));
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
rpm-build 4f3c61
	if (qop) {
rpm-build 4f3c61
		char tmp[9];
rpm-build 4f3c61
rpm-build 4f3c61
		g_snprintf (tmp, 9, "%.8x", nc);
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)tmp, strlen (tmp));
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce));
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
rpm-build 4f3c61
		if (!(qop & SOUP_AUTH_DIGEST_QOP_AUTH))
rpm-build 4f3c61
			g_warn_if_reached ();
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)"auth", strlen ("auth"));
rpm-build 4f3c61
		g_checksum_update (checksum, (guchar *)":", 1);
rpm-build 4f3c61
	}
rpm-build 4f3c61
rpm-build 4f3c61
	g_checksum_update (checksum, (guchar *)hex_a2, 32);
rpm-build 4f3c61
	strncpy (response, g_checksum_get_string (checksum), 33);
rpm-build 4f3c61
	g_checksum_free (checksum);
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static void
rpm-build 4f3c61
authentication_info_cb (SoupMessage *msg, gpointer data)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuth *auth = data;
rpm-build 4f3c61
	SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth);
rpm-build 4f3c61
	SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest);
rpm-build 4f3c61
	const char *header;
rpm-build 4f3c61
	GHashTable *auth_params;
rpm-build 4f3c61
	char *nextnonce;
rpm-build 4f3c61
rpm-build 4f3c61
	if (auth != soup_message_get_auth (msg))
rpm-build 4f3c61
		return;
rpm-build 4f3c61
rpm-build 4f3c61
	header = soup_message_headers_get_one (msg->response_headers,
rpm-build 4f3c61
					       soup_auth_is_for_proxy (auth) ?
rpm-build 4f3c61
					       "Proxy-Authentication-Info" :
rpm-build 4f3c61
					       "Authentication-Info");
rpm-build 4f3c61
	g_return_if_fail (header != NULL);
rpm-build 4f3c61
rpm-build 4f3c61
	auth_params = soup_header_parse_param_list (header);
rpm-build 4f3c61
	if (!auth_params)
rpm-build 4f3c61
		return;
rpm-build 4f3c61
rpm-build 4f3c61
	nextnonce = g_strdup (g_hash_table_lookup (auth_params, "nextnonce"));
rpm-build 4f3c61
	if (nextnonce) {
rpm-build 4f3c61
		g_free (priv->nonce);
rpm-build 4f3c61
		priv->nonce = nextnonce;
rpm-build 4f3c61
	}
rpm-build 4f3c61
rpm-build 4f3c61
	soup_header_free_param_list (auth_params);
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static char *
rpm-build 4f3c61
soup_auth_digest_get_authorization (SoupAuth *auth, SoupMessage *msg)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth);
rpm-build 4f3c61
	SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest);
rpm-build 4f3c61
	char response[33], *token;
rpm-build 4f3c61
	char *url, *algorithm;
rpm-build 4f3c61
	GString *out;
rpm-build 4f3c61
	SoupURI *uri;
rpm-build 4f3c61
rpm-build 4f3c61
	uri = soup_message_get_uri (msg);
rpm-build 4f3c61
	g_return_val_if_fail (uri != NULL, NULL);
rpm-build 4f3c61
	url = soup_uri_to_string (uri, TRUE);
rpm-build 4f3c61
rpm-build 4f3c61
	soup_auth_digest_compute_response (msg->method, url, priv->hex_a1,
rpm-build 4f3c61
					   priv->qop, priv->nonce,
rpm-build 4f3c61
					   priv->cnonce, priv->nc,
rpm-build 4f3c61
					   response);
rpm-build 4f3c61
rpm-build 4f3c61
	out = g_string_new ("Digest ");
rpm-build 4f3c61
rpm-build 4f3c61
	soup_header_g_string_append_param_quoted (out, "username", priv->user);
rpm-build 4f3c61
	g_string_append (out, ", ");
rpm-build 4f3c61
	soup_header_g_string_append_param_quoted (out, "realm", auth->realm);
rpm-build 4f3c61
	g_string_append (out, ", ");
rpm-build 4f3c61
	soup_header_g_string_append_param_quoted (out, "nonce", priv->nonce);
rpm-build 4f3c61
	g_string_append (out, ", ");
rpm-build 4f3c61
	soup_header_g_string_append_param_quoted (out, "uri", url);
rpm-build 4f3c61
	g_string_append (out, ", ");
rpm-build 4f3c61
	algorithm = soup_auth_digest_get_algorithm (priv->algorithm);
rpm-build 4f3c61
	g_string_append_printf (out, "algorithm=%s", algorithm);
rpm-build 4f3c61
	g_free (algorithm);
rpm-build 4f3c61
	g_string_append (out, ", ");
rpm-build 4f3c61
	soup_header_g_string_append_param_quoted (out, "response", response);
rpm-build 4f3c61
rpm-build 4f3c61
	if (priv->opaque) {
rpm-build 4f3c61
		g_string_append (out, ", ");
rpm-build 4f3c61
		soup_header_g_string_append_param_quoted (out, "opaque", priv->opaque);
rpm-build 4f3c61
	}
rpm-build 4f3c61
rpm-build 4f3c61
	if (priv->qop) {
rpm-build 4f3c61
		char *qop = soup_auth_digest_get_qop (priv->qop);
rpm-build 4f3c61
rpm-build 4f3c61
		g_string_append (out, ", ");
rpm-build 4f3c61
		soup_header_g_string_append_param_quoted (out, "cnonce", priv->cnonce);
rpm-build 4f3c61
		g_string_append_printf (out, ", nc=%.8x, qop=%s",
rpm-build 4f3c61
					priv->nc, qop);
rpm-build 4f3c61
		g_free (qop);
rpm-build 4f3c61
	}
rpm-build 4f3c61
rpm-build 4f3c61
	g_free (url);
rpm-build 4f3c61
rpm-build 4f3c61
	priv->nc++;
rpm-build 4f3c61
rpm-build 4f3c61
	token = g_string_free (out, FALSE);
rpm-build 4f3c61
rpm-build 4f3c61
	soup_message_add_header_handler (msg,
rpm-build 4f3c61
					 "got_headers",
rpm-build 4f3c61
					 soup_auth_is_for_proxy (auth) ?
rpm-build 4f3c61
					 "Proxy-Authentication-Info" :
rpm-build 4f3c61
					 "Authentication-Info",
rpm-build 4f3c61
					 G_CALLBACK (authentication_info_cb),
rpm-build 4f3c61
					 auth);
rpm-build 4f3c61
	return token;
rpm-build 4f3c61
}
rpm-build 4f3c61
rpm-build 4f3c61
static void
rpm-build 4f3c61
soup_auth_digest_class_init (SoupAuthDigestClass *auth_digest_class)
rpm-build 4f3c61
{
rpm-build 4f3c61
	SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_digest_class);
rpm-build 4f3c61
	GObjectClass *object_class = G_OBJECT_CLASS (auth_digest_class);
rpm-build 4f3c61
rpm-build 4f3c61
	auth_class->scheme_name = "Digest";
rpm-build 4f3c61
	auth_class->strength = 5;
rpm-build 4f3c61
rpm-build 4f3c61
	auth_class->get_protection_space = soup_auth_digest_get_protection_space;
rpm-build 4f3c61
	auth_class->update = soup_auth_digest_update;
rpm-build 4f3c61
	auth_class->authenticate = soup_auth_digest_authenticate;
rpm-build 4f3c61
	auth_class->is_authenticated = soup_auth_digest_is_authenticated;
rpm-build 4f3c61
	auth_class->get_authorization = soup_auth_digest_get_authorization;
rpm-build 4f3c61
rpm-build 4f3c61
	object_class->finalize = soup_auth_digest_finalize;
rpm-build 4f3c61
}