|
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 |
}
|