Make this an abstract GObject. Tweak some of the interfaces around a
authorDan Winship <danw@src.gnome.org>
Tue, 12 Aug 2003 18:00:14 +0000 (18:00 +0000)
committerDan Winship <danw@src.gnome.org>
Tue, 12 Aug 2003 18:00:14 +0000 (18:00 +0000)
* libsoup/soup-auth.c: Make this an abstract GObject. Tweak some
of the interfaces around a little bit.

* libsoup/soup-auth-basic.c: subclass for Basic auth

* libsoup/soup-auth-digest.c: subclass for Digest auth

* libsoup/soup-auth-ntlm.c: subclass for NTLM auth. Move all of
the code from soup-ntlm.c here, and make it private.

* libsoup/soup-ntlm.c: gone

* libsoup/soup-misc.h: Remove the definition of SoupAuthType from
here, and change the signature of SoupAuthorizeFn.

* libsoup/soup-context.c: Use g_object_unref to free auths, use
methods instead of directly access private fields.

* libsoup/soup-queue.c: Likewise

* libsoup/soup-server-auth.c (soup_server_auth_free): Remove all
NTLM references. We have no plans to implement server-side NTLM
auth.

* tests/auth-test.c (identify_auth): Update for auth api changes

17 files changed:
ChangeLog
libsoup/Makefile.am
libsoup/soup-auth-basic.c [new file with mode: 0644]
libsoup/soup-auth-basic.h [new file with mode: 0644]
libsoup/soup-auth-digest.c [new file with mode: 0644]
libsoup/soup-auth-digest.h [new file with mode: 0644]
libsoup/soup-auth-ntlm.c [moved from libsoup/soup-ntlm.c with 83% similarity]
libsoup/soup-auth-ntlm.h [new file with mode: 0644]
libsoup/soup-auth.c
libsoup/soup-auth.h
libsoup/soup-context.c
libsoup/soup-misc.h
libsoup/soup-ntlm.h [deleted file]
libsoup/soup-queue.c
libsoup/soup-server-auth.c
libsoup/soup-server-auth.h
tests/auth-test.c

index 8cd6c78..f8b0942 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,33 @@
 2003-08-12  Dan Winship  <danw@ximian.com>
 
+       * libsoup/soup-auth.c: Make this an abstract GObject. Tweak some
+       of the interfaces around a little bit.
+
+       * libsoup/soup-auth-basic.c: subclass for Basic auth
+
+       * libsoup/soup-auth-digest.c: subclass for Digest auth
+
+       * libsoup/soup-auth-ntlm.c: subclass for NTLM auth. Move all of
+       the code from soup-ntlm.c here, and make it private.
+
+       * libsoup/soup-ntlm.c: gone
+
+       * libsoup/soup-misc.h: Remove the definition of SoupAuthType from
+       here, and change the signature of SoupAuthorizeFn.
+
+       * libsoup/soup-context.c: Use g_object_unref to free auths, use
+       methods instead of directly access private fields.
+
+       * libsoup/soup-queue.c: Likewise
+
+       * libsoup/soup-server-auth.c (soup_server_auth_free): Remove all
+       NTLM references. We have no plans to implement server-side NTLM
+       auth.
+
+       * tests/auth-test.c (identify_auth): Update for auth api changes
+
+2003-08-12  Dan Winship  <danw@ximian.com>
+
        * configure.in (GLIB): add gobject-2.0 to the PKG_CHECK_MODULES
        call
 
index c7bbb65..cf17e6f 100644 (file)
@@ -20,7 +20,6 @@ libsoupinclude_HEADERS =      \
        soup-message.h          \
        soup-method.h           \
        soup-misc.h             \
-       soup-ntlm.h             \
        soup-server-auth.h      \
        soup-server.h           \
        soup-socket.h           \
@@ -41,6 +40,12 @@ libsoup_2_2_la_SOURCES =     \
        soup-address.c          \
        soup-auth.h             \
        soup-auth.c             \
+       soup-auth-basic.h       \
+       soup-auth-basic.c       \
+       soup-auth-digest.h      \
+       soup-auth-digest.c      \
+       soup-auth-ntlm.h        \
+       soup-auth-ntlm.c        \
        soup-context.c          \
        soup-dns.h              \
        soup-dns.c              \
@@ -51,7 +56,6 @@ libsoup_2_2_la_SOURCES =      \
        soup-message.c          \
        soup-method.c           \
        soup-misc.c             \
-       soup-ntlm.c             \
        soup-private.h          \
        soup-queue.h            \
        soup-queue.c            \
diff --git a/libsoup/soup-auth-basic.c b/libsoup/soup-auth-basic.c
new file mode 100644 (file)
index 0000000..78bcfb2
--- /dev/null
@@ -0,0 +1,162 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-auth-basic.c: HTTP Basic Authentication
+ *
+ * Copyright (C) 2001-2003, Ximian, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "soup-auth-basic.h"
+#include "soup-headers.h"
+#include "soup-message.h"
+#include "soup-misc.h"
+#include "soup-private.h"
+#include "soup-uri.h"
+
+static void construct (SoupAuth *auth, const char *header);
+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 invalidate (SoupAuth *auth);
+static gboolean is_authenticated (SoupAuth *auth);
+static char *get_authorization (SoupAuth *auth, SoupMessage *msg);
+
+struct SoupAuthBasicPrivate {
+       char *realm, *token;
+};
+
+#define PARENT_TYPE SOUP_TYPE_AUTH
+static SoupAuthClass *parent_class;
+
+static void
+init (GObject *object)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (object);
+
+       basic->priv = g_new0 (SoupAuthBasicPrivate, 1);
+}
+
+static void
+finalize (GObject *object)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (object);
+
+       g_free (basic->priv->realm);
+       g_free (basic->priv->token);
+       g_free (basic->priv);
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+class_init (GObjectClass *object_class)
+{
+       SoupAuthClass *auth_class = SOUP_AUTH_CLASS (object_class);
+
+       parent_class = g_type_class_ref (PARENT_TYPE);
+
+       auth_class->scheme_name = "Basic";
+
+       auth_class->construct = construct;
+       auth_class->get_protection_space = get_protection_space;
+       auth_class->get_realm = get_realm;
+       auth_class->authenticate = authenticate;
+       auth_class->invalidate = invalidate;
+       auth_class->is_authenticated = is_authenticated;
+       auth_class->get_authorization = get_authorization;
+
+       object_class->finalize = finalize;
+}
+
+SOUP_MAKE_TYPE (soup_auth_basic, SoupAuthBasic, class_init, init, PARENT_TYPE)
+
+
+static void
+construct (SoupAuth *auth, const char *header)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (auth);
+       GHashTable *tokens;
+
+       header += sizeof ("Basic");
+
+       tokens = soup_header_param_parse_list (header);
+       if (!tokens)
+               return;
+
+       basic->priv->realm = soup_header_param_copy_token (tokens, "realm");
+       soup_header_param_destroy_hash (tokens);
+}
+
+static GSList *
+get_protection_space (SoupAuth *auth, const SoupUri *source_uri)
+{
+       char *space, *p;
+
+       space = g_strdup (source_uri->path);
+
+       /* Strip query and filename component */
+       p = strrchr (space, '/');
+       if (p && p != space && p[1])
+               *p = '\0';
+
+       return g_slist_prepend (NULL, space);
+}
+
+static const char *
+get_realm (SoupAuth *auth)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (auth);
+
+       return basic->priv->realm;
+}
+
+static void
+authenticate (SoupAuth *auth, const char *username, const char *password)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (auth);
+       char *user_pass;
+       int len;
+
+       g_return_if_fail (username != NULL);
+       g_return_if_fail (password != NULL);
+
+       user_pass = g_strdup_printf ("%s:%s", username, password);
+       len = strlen (user_pass);
+
+       basic->priv->token = soup_base64_encode (user_pass, len);
+
+       memset (user_pass, 0, len);
+       g_free (user_pass);
+}
+
+static gboolean
+invalidate (SoupAuth *auth)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (auth);
+
+       g_free (basic->priv->token);
+       basic->priv->token = NULL;
+
+       return TRUE;
+}
+
+static gboolean
+is_authenticated (SoupAuth *auth)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (auth);
+
+       return basic->priv->token != NULL;
+}
+
+static char *
+get_authorization (SoupAuth *auth, SoupMessage *msg)
+{
+       SoupAuthBasic *basic = SOUP_AUTH_BASIC (auth);
+
+       return g_strdup_printf ("Basic %s", basic->priv->token);
+}
diff --git a/libsoup/soup-auth-basic.h b/libsoup/soup-auth-basic.h
new file mode 100644 (file)
index 0000000..a0c0956
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#ifndef SOUP_AUTH_BASIC_H
+#define SOUP_AUTH_BASIC_H 1
+
+#include "soup-auth.h"
+
+#define SOUP_TYPE_AUTH_BASIC            (soup_auth_basic_get_type ())
+#define SOUP_AUTH_BASIC(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_BASIC, SoupAuthBasic))
+#define SOUP_AUTH_BASIC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_BASIC, SoupAuthBasicClass))
+#define SOUP_IS_AUTH_BASIC(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_BASIC))
+#define SOUP_IS_AUTH_BASIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_BASIC))
+#define SOUP_AUTH_BASIC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_BASIC, SoupAuthBasicClass))
+
+typedef struct SoupAuthBasicPrivate SoupAuthBasicPrivate;
+
+typedef struct {
+       SoupAuth parent;
+
+       SoupAuthBasicPrivate *priv;
+} SoupAuthBasic;
+
+typedef struct {
+       SoupAuthClass  parent_class;
+
+} SoupAuthBasicClass;
+
+GType soup_auth_basic_get_type (void);
+
+#endif /*SOUP_AUTH_BASIC_H*/
diff --git a/libsoup/soup-auth-digest.c b/libsoup/soup-auth-digest.c
new file mode 100644 (file)
index 0000000..b51673e
--- /dev/null
@@ -0,0 +1,453 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-digest-offset: 8 -*- */
+/*
+ * soup-auth-digest.c: HTTP Digest Authentication
+ *
+ * Copyright (C) 2001-2003, Ximian, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "soup-auth-digest.h"
+#include "soup-headers.h"
+#include "soup-message.h"
+#include "soup-misc.h"
+#include "soup-private.h"
+#include "soup-uri.h"
+#include "md5-utils.h"
+
+static void construct (SoupAuth *auth, const char *header);
+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 invalidate (SoupAuth *auth);
+static gboolean is_authenticated (SoupAuth *auth);
+static char *get_authorization (SoupAuth *auth, SoupMessage *msg);
+
+typedef enum {
+       QOP_NONE     = 0,
+       QOP_AUTH     = 1 << 0,
+       QOP_AUTH_INT = 1 << 1
+} QOPType;
+
+typedef enum {
+       ALGORITHM_MD5      = 1 << 0,
+       ALGORITHM_MD5_SESS = 1 << 1
+} AlgorithmType;
+
+struct SoupAuthDigestPrivate {
+       char          *user;
+       guchar         hex_a1[33];
+
+       /* These are provided by the server */
+       char          *realm;
+       char          *nonce;
+       QOPType        qop_options;
+       AlgorithmType  algorithm;
+       char          *domain;
+
+       /* These are generated by the client */
+       char          *cnonce;
+       int            nc;
+       QOPType        qop;
+};
+
+#define PARENT_TYPE SOUP_TYPE_AUTH
+static SoupAuthClass *parent_class;
+
+static void
+init (GObject *object)
+{
+       SoupAuthDigest *digest = SOUP_AUTH_DIGEST (object);
+
+       digest->priv = g_new0 (SoupAuthDigestPrivate, 1);
+}
+
+static void
+finalize (GObject *object)
+{
+       SoupAuthDigest *digest = SOUP_AUTH_DIGEST (object);
+
+       if (digest->priv->user)
+               g_free (digest->priv->user);
+       if (digest->priv->realm)
+               g_free (digest->priv->realm);
+       if (digest->priv->nonce)
+               g_free (digest->priv->nonce);
+       if (digest->priv->domain)
+               g_free (digest->priv->domain);
+       if (digest->priv->cnonce)
+               g_free (digest->priv->cnonce);
+
+       g_free (digest->priv);
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+class_init (GObjectClass *object_class)
+{
+       SoupAuthClass *auth_class = SOUP_AUTH_CLASS (object_class);
+
+       parent_class = g_type_class_ref (PARENT_TYPE);
+
+       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->invalidate = invalidate;
+       auth_class->is_authenticated = is_authenticated;
+       auth_class->get_authorization = get_authorization;
+
+       object_class->finalize = finalize;
+}
+
+SOUP_MAKE_TYPE (soup_auth_digest, SoupAuthDigest, class_init, init, PARENT_TYPE)
+
+typedef struct {
+       char *name;
+       guint type;
+} DataType;
+
+static DataType qop_types[] = {
+       { "auth",     QOP_AUTH     },
+       { "auth-int", QOP_AUTH_INT }
+};
+
+static DataType algorithm_types[] = {
+       { "MD5",      ALGORITHM_MD5      },
+       { "MD5-sess", ALGORITHM_MD5_SESS }
+};
+
+static guint
+decode_data_type (DataType *dtype, const char *name)
+{
+        int i;
+
+       if (!name)
+               return 0;
+
+        for (i = 0; dtype[i].name; i++) {
+                if (!g_strcasecmp (dtype[i].name, name))
+                       return dtype[i].type;
+        }
+
+       return 0;
+}
+
+static inline guint
+decode_qop (const char *name)
+{
+       return decode_data_type (qop_types, name);
+}
+
+static inline guint
+decode_algorithm (const char *name)
+{
+       return decode_data_type (algorithm_types, name);
+}
+
+static void
+construct (SoupAuth *auth, const char *header)
+{
+       SoupAuthDigest *digest = SOUP_AUTH_DIGEST (auth);
+       GHashTable *tokens;
+       char *tmp, *ptr;
+
+       header += sizeof ("Digest");
+
+       tokens = soup_header_param_parse_list (header);
+       if (!tokens)
+               return;
+
+       digest->priv->nc = 1;
+       /* We're just going to do qop=auth for now */
+       digest->priv->qop = QOP_AUTH;
+
+       digest->priv->realm = soup_header_param_copy_token (tokens, "realm");
+       digest->priv->domain = soup_header_param_copy_token (tokens, "domain");
+       digest->priv->nonce = soup_header_param_copy_token (tokens, "nonce");
+
+       tmp = soup_header_param_copy_token (tokens, "qop");
+       ptr = tmp;
+
+       while (ptr && *ptr) {
+               char *token;
+
+               token = soup_header_param_decode_token ((char **)&ptr);
+               if (token)
+                       digest->priv->qop_options |= decode_qop (token);
+               g_free (token);
+
+               if (*ptr == ',')
+                       ptr++;
+       }
+       g_free (tmp);
+
+       tmp = soup_header_param_copy_token (tokens, "algorithm");
+       digest->priv->algorithm = decode_algorithm (tmp);
+       g_free (tmp);
+
+       soup_header_param_destroy_hash (tokens);
+}
+
+static GSList *
+get_protection_space (SoupAuth *auth, const SoupUri *source_uri)
+{
+       SoupAuthDigest *digest = SOUP_AUTH_DIGEST (auth);
+       GSList *space = NULL;
+       SoupUri *uri;
+       char *domain, *d, *lasts, *dir, *slash;
+
+       if (!digest->priv->domain || !*digest->priv->domain) {
+               /* If no domain directive, the protection space is the
+                * whole server.
+                */
+               return g_slist_prepend (NULL, g_strdup (""));
+       }
+
+       domain = g_strdup (digest->priv->domain);
+       for (d = strtok_r (domain, " ", &lasts); d; d = strtok_r (NULL, " ", &lasts)) {
+               if (*d == '/')
+                       dir = g_strdup (d);
+               else {
+                       uri = soup_uri_new (d);
+                       if (uri && uri->protocol == source_uri->protocol &&
+                           uri->port == source_uri->port &&
+                           !strcmp (uri->host, source_uri->host))
+                               dir = g_strdup (uri->path);
+                       else
+                               dir = NULL;
+                       if (uri)
+                               soup_uri_free (uri);
+               }
+
+               if (dir) {
+                       slash = strrchr (dir, '/');
+                       if (slash && !slash[1])
+                               *slash = '\0';
+
+                       space = g_slist_prepend (space, dir);
+               }
+       }
+       g_free (domain);
+
+       return space;
+}
+
+static const char *
+get_realm (SoupAuth *auth)
+{
+       SoupAuthDigest *digest = SOUP_AUTH_DIGEST (auth);
+
+       return digest->priv->realm;
+}
+
+static void
+digest_hex (guchar *digest, guchar hex[33])
+{
+       guchar *s, *p;
+
+       /* lowercase hexify that bad-boy... */
+       for (s = digest, p = hex; p < hex + 32; s++, p += 2)
+               sprintf (p, "%.2x", *s);
+}
+
+static void
+authenticate (SoupAuth *auth, const char *username, const char *password)
+{
+       SoupAuthDigest *digest = SOUP_AUTH_DIGEST (auth);
+       MD5Context ctx;
+       guchar d[16];
+       char *bgen;
+
+       g_return_if_fail (username != NULL);
+
+       bgen = g_strdup_printf ("%p:%lu:%lu",
+                              auth,
+                              (unsigned long) getpid (),
+                              (unsigned long) time (0));
+       digest->priv->cnonce = soup_base64_encode (bgen, strlen (bgen));
+       g_free (bgen);
+
+       digest->priv->user = g_strdup (username);
+
+       /* compute A1 */
+       md5_init (&ctx);
+
+       md5_update (&ctx, username, strlen (username));
+
+       md5_update (&ctx, ":", 1);
+       if (digest->priv->realm)
+               md5_update (&ctx, digest->priv->realm, strlen (digest->priv->realm));
+
+       md5_update (&ctx, ":", 1);
+       if (password)
+               md5_update (&ctx, password, strlen (password));
+
+       if (digest->priv->algorithm == ALGORITHM_MD5_SESS) {
+               md5_final (&ctx, d);
+
+               md5_init (&ctx);
+               md5_update (&ctx, d, 16);
+               md5_update (&ctx, ":", 1);
+               md5_update (&ctx, digest->priv->nonce, strlen (digest->priv->nonce));
+               md5_update (&ctx, ":", 1);
+               md5_update (&ctx, digest->priv->cnonce, strlen (digest->priv->cnonce));
+       }
+
+       /* hexify A1 */
+       md5_final (&ctx, d);
+       digest_hex (d, digest->priv->hex_a1);
+}
+
+static gboolean
+invalidate (SoupAuth *auth)
+{
+       /* An invalidated Digest auth is useless. You need to get
+        * a new nonce from the server before you can start using it
+        * again.
+        */
+       return FALSE;
+}
+
+static gboolean
+is_authenticated (SoupAuth *auth)
+{
+       SoupAuthDigest *digest = SOUP_AUTH_DIGEST (auth);
+
+       return digest->priv->cnonce != NULL;
+}
+
+static char *
+compute_response (SoupAuthDigest *digest, SoupMessage *msg)
+{
+       guchar hex_a2[33], o[33];
+       guchar d[16];
+       MD5Context md5;
+       char *url;
+       SoupContext *ctx;
+
+       ctx = soup_message_get_context (msg);
+       g_return_val_if_fail (ctx != NULL, NULL);
+       url = soup_uri_to_string (soup_context_get_uri (ctx), TRUE);
+
+       /* compute A2 */
+       md5_init (&md5);
+       md5_update (&md5, msg->method, strlen (msg->method));
+       md5_update (&md5, ":", 1);
+       md5_update (&md5, url, strlen (url));
+
+       g_free (url);
+
+       if (digest->priv->qop == QOP_AUTH_INT) {
+               /* FIXME: Actually implement. Ugh. */
+               md5_update (&md5, ":", 1);
+               md5_update (&md5, "00000000000000000000000000000000", 32);
+       }
+
+       /* now hexify A2 */
+       md5_final (&md5, d);
+       digest_hex (d, hex_a2);
+
+       /* compute KD */
+       md5_init (&md5);
+       md5_update (&md5, digest->priv->hex_a1, 32);
+       md5_update (&md5, ":", 1);
+       md5_update (&md5, digest->priv->nonce, strlen (digest->priv->nonce));
+       md5_update (&md5, ":", 1);
+
+       if (digest->priv->qop) {
+               char *tmp;
+
+               tmp = g_strdup_printf ("%.8x", digest->priv->nc);
+
+               md5_update (&md5, tmp, strlen (tmp));
+               g_free (tmp);
+               md5_update (&md5, ":", 1);
+               md5_update (&md5, digest->priv->cnonce, strlen (digest->priv->cnonce));
+               md5_update (&md5, ":", 1);
+
+               if (digest->priv->qop == QOP_AUTH)
+                       tmp = "auth";
+               else if (digest->priv->qop == QOP_AUTH_INT)
+                       tmp = "auth-int";
+               else
+                       g_assert_not_reached ();
+
+               md5_update (&md5, tmp, strlen (tmp));
+               md5_update (&md5, ":", 1);
+       }
+
+       md5_update (&md5, hex_a2, 32);
+       md5_final (&md5, d);
+
+       digest_hex (d, o);
+
+       return g_strdup (o);
+}
+
+static char *
+get_authorization (SoupAuth *auth, SoupMessage *msg)
+{
+       SoupAuthDigest *digest = (SoupAuthDigest *) auth;
+       char *response;
+       char *qop = NULL;
+       char *nc;
+       char *url;
+       char *out;
+       SoupContext *ctx;
+
+       ctx = soup_message_get_context (msg);
+       g_return_val_if_fail (ctx != NULL, NULL);
+       url = soup_uri_to_string (soup_context_get_uri (ctx), TRUE);
+
+       response = compute_response (digest, msg);
+
+       if (digest->priv->qop == QOP_AUTH)
+               qop = "auth";
+       else if (digest->priv->qop == QOP_AUTH_INT)
+               qop = "auth-int";
+       else
+               g_assert_not_reached ();
+
+       nc = g_strdup_printf ("%.8x", digest->priv->nc);
+
+       out = g_strdup_printf (
+               "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", %s%s%s "
+               "%s%s%s %s%s%s uri=\"%s\", response=\"%s\"",
+               digest->priv->user,
+               digest->priv->realm,
+               digest->priv->nonce,
+
+               digest->priv->qop ? "cnonce=\"" : "",
+               digest->priv->qop ? digest->priv->cnonce : "",
+               digest->priv->qop ? "\"," : "",
+
+               digest->priv->qop ? "nc=" : "",
+               digest->priv->qop ? nc : "",
+               digest->priv->qop ? "," : "",
+
+               digest->priv->qop ? "qop=" : "",
+               digest->priv->qop ? qop : "",
+               digest->priv->qop ? "," : "",
+
+               url,
+               response);
+
+       g_free (response);
+       g_free (url);
+       g_free (nc);
+
+       digest->priv->nc++;
+
+       return out;
+}
diff --git a/libsoup/soup-auth-digest.h b/libsoup/soup-auth-digest.h
new file mode 100644 (file)
index 0000000..3b8e072
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#ifndef SOUP_AUTH_DIGEST_H
+#define SOUP_AUTH_DIGEST_H 1
+
+#include "soup-auth.h"
+
+#define SOUP_TYPE_AUTH_DIGEST            (soup_auth_digest_get_type ())
+#define SOUP_AUTH_DIGEST(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_DIGEST, SoupAuthDigest))
+#define SOUP_AUTH_DIGEST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_DIGEST, SoupAuthDigestClass))
+#define SOUP_IS_AUTH_DIGEST(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_DIGEST))
+#define SOUP_IS_AUTH_DIGEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_DIGEST))
+#define SOUP_AUTH_DIGEST_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_DIGEST, SoupAuthDigestClass))
+
+typedef struct SoupAuthDigestPrivate SoupAuthDigestPrivate;
+
+typedef struct {
+       SoupAuth parent;
+
+       SoupAuthDigestPrivate *priv;
+} SoupAuthDigest;
+
+typedef struct {
+       SoupAuthClass parent_class;
+
+} SoupAuthDigestClass;
+
+GType soup_auth_digest_get_type (void);
+
+#endif /*SOUP_AUTH_DIGEST_H*/
similarity index 83%
rename from libsoup/soup-ntlm.c
rename to libsoup/soup-auth-ntlm.c
index ecef043..0237654 100644 (file)
@@ -1,13 +1,8 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-ntlm-offset: 8 -*- */
 /*
- * soup-ntlm.c: Microsoft Windows NTLM authentication support
+ * soup-auth-ntlm.c: HTTP NTLM Authentication
  *
- * Authors:
- *      Dan Winship (danw@ximian.com)
- *
- * Public domain DES implementation from Phil Karn.
- *
- * All else Copyright (C) 2001-2002, Ximian, Inc.
+ * Copyright (C) 2001-2003, Ximian, Inc.
  */
 
 #ifdef HAVE_CONFIG_H
 #endif
 
 #include <ctype.h>
-#include <stdlib.h>
 #include <string.h>
 
-#include "soup-ntlm.h"
-#include "soup-misc.h"
+#include "soup-auth-ntlm.h"
+#include "soup-private.h"
+#include "soup-uri.h"
+
+static void construct (SoupAuth *auth, const char *header);
+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 invalidate (SoupAuth *auth);
+static gboolean is_authenticated (SoupAuth *auth);
+static char *get_authorization (SoupAuth *auth, SoupMessage *msg);
+
+char     *soup_ntlm_request         (void);
+gboolean  soup_ntlm_parse_challenge (const char  *challenge,
+                                    char       **nonce,
+                                    char       **default_domain);
+char     *soup_ntlm_response        (const char  *nonce, 
+                                    const char  *user,
+                                    const char  *password, 
+                                    const char  *host, 
+                                    const char  *domain);
+
+struct SoupAuthNTLMPrivate {
+       gboolean authenticated;
+       char *header;
+       char *response;
+};
+
+#define PARENT_TYPE SOUP_TYPE_AUTH
+static SoupAuthClass *parent_class;
+
+static void
+init (GObject *object)
+{
+       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (object);
+
+       ntlm->priv = g_new0 (SoupAuthNTLMPrivate, 1);
+}
+
+static void
+finalize (GObject *object)
+{
+       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (object);
+
+       g_free (ntlm->priv->header);
+       g_free (ntlm->priv->response);
+       g_free (ntlm->priv);
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+class_init (GObjectClass *object_class)
+{
+       SoupAuthClass *auth_class = SOUP_AUTH_CLASS (object_class);
+
+       parent_class = g_type_class_ref (PARENT_TYPE);
+
+       auth_class->scheme_name = "NTLM";
+
+       auth_class->construct = construct;
+       auth_class->get_protection_space = get_protection_space;
+       auth_class->get_realm = get_realm;
+       auth_class->authenticate = authenticate;
+       auth_class->invalidate = invalidate;
+       auth_class->is_authenticated = is_authenticated;
+       auth_class->get_authorization = get_authorization;
+
+       object_class->finalize = finalize;
+}
+
+SOUP_MAKE_TYPE (soup_auth_ntlm, SoupAuthNTLM, class_init, init, PARENT_TYPE)
+
+
+SoupAuth *
+soup_auth_ntlm_new (void)
+{
+       SoupAuth *auth;
+
+       auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL);
+       construct (auth, "");
+       return auth;
+}
+
+static void
+construct (SoupAuth *auth, const char *header)
+{
+       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
+
+       ntlm->priv->header = g_strdup (header);
+}
+
+static GSList *
+get_protection_space (SoupAuth *auth, const SoupUri *source_uri)
+{
+       /* The protection space is the whole server. */
+       return g_slist_prepend (NULL, g_strdup (""));
+}
+
+static const char *
+get_realm (SoupAuth *auth)
+{
+       return "";
+}
+
+static void
+authenticate (SoupAuth *auth, const char *username, const char *password)
+{
+       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
+       char *domain, *nonce;
+
+       if (!ntlm->priv->header || strlen (ntlm->priv->header) < sizeof ("NTLM"))
+               return;
+
+       if (ntlm->priv->response)
+               g_free (ntlm->priv->response);
+
+       if (soup_ntlm_parse_challenge (ntlm->priv->header, &nonce, &domain)) {
+               ntlm->priv->response =
+                       soup_ntlm_response (nonce, username, password,
+                                           NULL, domain);
+               g_free (nonce);
+               g_free (domain);
+       } else
+               ntlm->priv->response = NULL;
+
+       g_free (ntlm->priv->header);
+       ntlm->priv->header = NULL;
+
+       ntlm->priv->authenticated = TRUE;
+}
+
+static gboolean
+invalidate (SoupAuth *auth)
+{
+       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
+
+       g_free (ntlm->priv->response);
+       ntlm->priv->response = NULL;
+       g_free (ntlm->priv->header);
+       ntlm->priv->header = NULL;
+
+       ntlm->priv->authenticated = FALSE;
+
+       return TRUE;
+}
+
+static gboolean
+is_authenticated (SoupAuth *auth)
+{
+       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
+
+       return ntlm->priv->authenticated;
+}
+
+static char *
+get_authorization (SoupAuth *auth, SoupMessage *msg)
+{
+       SoupAuthNTLM *ntlm = SOUP_AUTH_NTLM (auth);
+       char *ret;
+
+       if (!ntlm->priv->authenticated)
+               return soup_ntlm_request ();
+
+       /* Otherwise, return the response; but only once */
+       ret = ntlm->priv->response;
+       ntlm->priv->response = NULL;
+       return ret;
+}
+
+
 
 /* MD4 */
 static void md4sum                (const unsigned char *in, 
@@ -43,8 +206,8 @@ static void calc_response         (const guchar        *key,
                           "\x4B\x47\x53\x21\x40\x23\x24\x25" \
                          "\x00\x00\x00\x00\x00"
 
-void
-soup_ntlm_lanmanager_hash (const char *password, guchar hash[21])
+static void
+lanmanager_hash (const char *password, guchar hash[21])
 {
        guchar lm_password [15];
        DES_KS ks;
@@ -65,8 +228,8 @@ soup_ntlm_lanmanager_hash (const char *password, guchar hash[21])
        des (ks, hash + 8);
 }
 
-void
-soup_ntlm_nt_hash (const char *password, guchar hash[21])
+static void
+nt_hash (const char *password, guchar hash[21])
 {
        unsigned char *buf, *p;
 
@@ -188,9 +351,9 @@ soup_ntlm_response (const char *nonce,
        unsigned char *out, *p;
        int state, save;
 
-       soup_ntlm_lanmanager_hash (password, hash);
+       lanmanager_hash (password, hash);
        calc_response (hash, nonce, lm_resp);
-       soup_ntlm_nt_hash (password, hash);
+       nt_hash (password, hash);
        calc_response (hash, nonce, nt_resp);
 
        memset (&resp, 0, sizeof (resp));
diff --git a/libsoup/soup-auth-ntlm.h b/libsoup/soup-auth-ntlm.h
new file mode 100644 (file)
index 0000000..6950bbf
--- /dev/null
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-ntlm-offset: 8 -*- */
+/*
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#ifndef SOUP_AUTH_NTLM_H
+#define SOUP_AUTH_NTLM_H 1
+
+#include "soup-auth.h"
+
+#define SOUP_TYPE_AUTH_NTLM            (soup_auth_ntlm_get_type ())
+#define SOUP_AUTH_NTLM(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLM))
+#define SOUP_AUTH_NTLM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass))
+#define SOUP_IS_AUTH_NTLM(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_NTLM))
+#define SOUP_IS_AUTH_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_NTLM))
+#define SOUP_AUTH_NTLM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass))
+
+typedef struct SoupAuthNTLMPrivate SoupAuthNTLMPrivate;
+
+typedef struct {
+       SoupAuth parent;
+
+       SoupAuthNTLMPrivate *priv;
+} SoupAuthNTLM;
+
+typedef struct {
+       SoupAuthClass  parent_class;
+
+} SoupAuthNTLMClass;
+
+GType     soup_auth_ntlm_get_type (void);
+
+SoupAuth *soup_auth_ntlm_new      (void);
+
+#endif /*SOUP_AUTH_NTLM_H*/
index 9f52d97..6919cdb 100644 (file)
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * soup-auth.c: HTTP Authentication schemes (basic and digest)
+ * soup-auth.c: HTTP Authentication framework
  *
- * Authors:
- *      Joe Shaw (joe@ximian.com)
- *      Jeffrey Steadfast (fejj@ximian.com)
- *      Alex Graveley (alex@ximian.com)
- *
- * Copyright (C) 2001-2002, Ximian, Inc.
+ * Copyright (C) 2001-2003, Ximian, Inc.
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include <unistd.h>
 #include <string.h>
-#include <stdlib.h>
-#include <glib.h>
-
-#include <stdio.h>
-#include <time.h>
 
-#include "md5-utils.h"
 #include "soup-auth.h"
-#include "soup-context.h"
-#include "soup-headers.h"
-#include "soup-message.h"
+#include "soup-auth-basic.h"
+#include "soup-auth-digest.h"
+#include "soup-auth-ntlm.h"
 #include "soup-private.h"
-#include "soup-ntlm.h"
-
-/* 
- * Basic Authentication Support 
- */
-
-typedef struct {
-       SoupAuth auth;
-       gchar *token;
-} SoupAuthBasic;
-
-static char *
-basic_auth_func (SoupAuth *auth, SoupMessage *message)
-{
-       SoupAuthBasic *basic = (SoupAuthBasic *) auth;
-
-       return g_strconcat ("Basic ", basic->token, NULL);
-}
-
-static void
-basic_parse_func (SoupAuth *auth, const char *header)
-{
-       GHashTable *tokens;
-
-       header += sizeof ("Basic");
-
-       tokens = soup_header_param_parse_list (header);
-       if (!tokens) return;
-
-       auth->realm = soup_header_param_copy_token (tokens, "realm");
-
-       soup_header_param_destroy_hash (tokens);
-}
-
-static GSList *
-basic_pspace_func (SoupAuth *auth, const SoupUri *source_uri)
-{
-       char *space, *p;
-
-       space = g_strdup (source_uri->path);
-
-       /* Strip query and filename component */
-       p = strrchr (space, '/');
-       if (p && p != space && p[1])
-               *p = '\0';
-
-       return g_slist_prepend (NULL, space);
-}
-
-static void
-basic_init_func (SoupAuth *auth, const SoupUri *uri)
-{
-       SoupAuthBasic *basic = (SoupAuthBasic *) auth;
-       char *user_pass;
-
-       user_pass = g_strdup_printf ("%s:%s", uri->user, uri->passwd);
-       basic->token = soup_base64_encode (user_pass, strlen (user_pass));
-       g_free (user_pass);
-
-       auth->authenticated = TRUE;
-}
-
-static gboolean
-basic_invalidate_func (SoupAuth *auth)
-{
-       SoupAuthBasic *basic = (SoupAuthBasic *) auth;
-
-       g_free (basic->token);
-       basic->token = NULL;
-       auth->authenticated = FALSE;
-
-       return TRUE;
-}
-
-static void
-basic_free (SoupAuth *auth)
-{
-       SoupAuthBasic *basic = (SoupAuthBasic *) auth;
-
-       g_free (basic->token);
-       g_free (basic);
-}
-
-static SoupAuth *
-soup_auth_new_basic (void)
-{
-       SoupAuthBasic *basic;
-       SoupAuth *auth;
-
-       basic = g_new0 (SoupAuthBasic, 1);
-       auth = (SoupAuth *) basic;
-       auth->type = SOUP_AUTH_TYPE_BASIC;
-       auth->authenticated = FALSE;
-
-       auth->parse_func = basic_parse_func;
-       auth->init_func = basic_init_func;
-       auth->invalidate_func = basic_invalidate_func;
-       auth->pspace_func = basic_pspace_func;
-       auth->auth_func = basic_auth_func;
-       auth->free_func = basic_free;
-
-       return auth;
-}
-
-
-/* 
- * Digest Authentication Support 
- */
-
-typedef enum {
-       QOP_NONE     = 0,
-       QOP_AUTH     = 1 << 0,
-       QOP_AUTH_INT = 1 << 1
-} QOPType;
-
-typedef enum {
-       ALGORITHM_MD5      = 1 << 0,
-       ALGORITHM_MD5_SESS = 1 << 1
-} AlgorithmType;
-
-typedef struct {
-       SoupAuth auth;
-
-       gchar  *user;
-       guchar  hex_a1 [33];
-
-       /* These are provided by the server */
-       char *nonce;
-       QOPType qop_options;
-       AlgorithmType algorithm;
-       char *domain;
-
-       /* These are generated by the client */
-       char *cnonce;
-       int nc;
-       QOPType qop;
-} SoupAuthDigest;
-
-static void
-digest_hex (guchar *digest, guchar hex[33])
-{
-       guchar *s, *p;
-
-       /* lowercase hexify that bad-boy... */
-       for (s = digest, p = hex; p < hex + 32; s++, p += 2)
-               sprintf (p, "%.2x", *s);
-}
-
-static char *
-compute_response (SoupAuthDigest *digest, SoupMessage *msg)
-{
-       const SoupUri *uri;
-       guchar hex_a2[33], o[33];
-       guchar d[16];
-       MD5Context ctx;
-       char *url;
-
-       uri = soup_context_get_uri (msg->context);
-       url = soup_uri_to_string (uri, TRUE);
-
-       /* compute A2 */
-       md5_init (&ctx);
-       md5_update (&ctx, msg->method, strlen (msg->method));
-       md5_update (&ctx, ":", 1);
-       md5_update (&ctx, url, strlen (url));
-       g_free (url);
-
-       if (digest->qop == QOP_AUTH_INT) {
-               /* FIXME: Actually implement. Ugh. */
-               md5_update (&ctx, ":", 1);
-               md5_update (&ctx, "00000000000000000000000000000000", 32);
-       }
-
-       /* now hexify A2 */
-       md5_final (&ctx, d);
-       digest_hex (d, hex_a2);
-
-       /* compute KD */
-       md5_init (&ctx);
-       md5_update (&ctx, digest->hex_a1, 32);
-       md5_update (&ctx, ":", 1);
-       md5_update (&ctx, digest->nonce, strlen (digest->nonce));
-       md5_update (&ctx, ":", 1);
-
-       if (digest->qop) {
-               char *tmp;
-
-               tmp = g_strdup_printf ("%.8x", digest->nc);
-
-               md5_update (&ctx, tmp, strlen (tmp));
-               g_free (tmp);
-               md5_update (&ctx, ":", 1);
-               md5_update (&ctx, digest->cnonce, strlen (digest->cnonce));
-               md5_update (&ctx, ":", 1);
-
-               if (digest->qop == QOP_AUTH)
-                       tmp = "auth";
-               else if (digest->qop == QOP_AUTH_INT)
-                       tmp = "auth-int";
-               else
-                       g_assert_not_reached ();
-
-               md5_update (&ctx, tmp, strlen (tmp));
-               md5_update (&ctx, ":", 1);
-       }
-
-       md5_update (&ctx, hex_a2, 32);
-       md5_final (&ctx, d);
-
-       digest_hex (d, o);
-
-       return g_strdup (o);
-}
-
-static char *
-digest_auth_func (SoupAuth *auth, SoupMessage *message)
-{
-       SoupAuthDigest *digest = (SoupAuthDigest *) auth;
-       const SoupUri *uri;
-       char *response;
-       char *qop = NULL;
-       char *nc;
-       char *url;
-       char *out;
-
-       g_return_val_if_fail (message, NULL);
-
-       response = compute_response (digest, message);
-
-       if (digest->qop == QOP_AUTH)
-               qop = "auth";
-       else if (digest->qop == QOP_AUTH_INT)
-               qop = "auth-int";
-       else
-               g_assert_not_reached ();
-
-       uri = soup_context_get_uri (message->context);
-       url = soup_uri_to_string (uri, TRUE);
-
-       nc = g_strdup_printf ("%.8x", digest->nc);
-
-       out = g_strdup_printf (
-               "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", %s%s%s "
-               "%s%s%s %s%s%s uri=\"%s\", response=\"%s\"",
-               digest->user,
-               auth->realm,
-               digest->nonce,
-
-               digest->qop ? "cnonce=\"" : "",
-               digest->qop ? digest->cnonce : "",
-               digest->qop ? "\"," : "",
-
-               digest->qop ? "nc=" : "",
-               digest->qop ? nc : "",
-               digest->qop ? "," : "",
-
-               digest->qop ? "qop=" : "",
-               digest->qop ? qop : "",
-               digest->qop ? "," : "",
-
-               url,
-               response);
-
-       g_free (response);
-       g_free (url);
-       g_free (nc);
-
-       digest->nc++;
-
-       return out;
-}
-
-typedef struct {
-       char *name;
-       guint type;
-} DataType;
-
-static DataType qop_types[] = {
-       { "auth",     QOP_AUTH     },
-       { "auth-int", QOP_AUTH_INT }
-};
-
-static DataType algorithm_types[] = {
-       { "MD5",      ALGORITHM_MD5      },
-       { "MD5-sess", ALGORITHM_MD5_SESS }
-};
-
-static guint
-decode_data_type (DataType *dtype, const char *name)
-{
-        int i;
-
-       if (!name)
-               return 0;
-
-        for (i = 0; dtype[i].name; i++) {
-                if (!g_strcasecmp (dtype[i].name, name))
-                       return dtype[i].type;
-        }
-
-       return 0;
-}
-
-static inline guint
-decode_qop (const char *name)
-{
-       return decode_data_type (qop_types, name);
-}
-
-static inline guint
-decode_algorithm (const char *name)
-{
-       return decode_data_type (algorithm_types, name);
-}
-
-static void
-digest_parse_func (SoupAuth *auth, const char *header)
-{
-       SoupAuthDigest *digest = (SoupAuthDigest *) auth;
-       GHashTable *tokens;
-       char *tmp, *ptr;
-
-       header += sizeof ("Digest");
-
-       tokens = soup_header_param_parse_list (header);
-       if (!tokens) return;
-
-       auth->realm = soup_header_param_copy_token (tokens, "realm");
-
-       digest->nonce = soup_header_param_copy_token (tokens, "nonce");
-       digest->domain = soup_header_param_copy_token (tokens, "domain");
 
-       tmp = soup_header_param_copy_token (tokens, "qop");
-       ptr = tmp;
-
-       while (ptr && *ptr) {
-               char *token;
-
-               token = soup_header_param_decode_token (&ptr);
-               if (token)
-                       digest->qop_options |= decode_qop (token);
-               g_free (token);
-
-               if (*ptr == ',')
-                       ptr++;
-       }
-
-       g_free (tmp);
-
-       tmp = soup_header_param_copy_token (tokens, "algorithm");
-       digest->algorithm = decode_algorithm (tmp);
-       g_free (tmp);
-
-       soup_header_param_destroy_hash (tokens);
-}
-
-static GSList *
-digest_pspace_func (SoupAuth *auth, const SoupUri *source_uri)
-{
-       SoupAuthDigest *digest = (SoupAuthDigest *) auth;
-       GSList *space = NULL;
-       SoupUri *uri;
-       char *domain, *d, *lasts, *dir, *slash;
-
-       if (!digest->domain || !*digest->domain) {
-               /* If no domain directive, the protection space is the
-                * whole server.
-                */
-               return g_slist_prepend (NULL, g_strdup (""));
-       }
-
-       domain = g_strdup (digest->domain);
-       for (d = strtok_r (domain, " ", &lasts); d; d = strtok_r (NULL, " ", &lasts)) {
-               if (*d == '/')
-                       dir = g_strdup (d);
-               else {
-                       uri = soup_uri_new (d);
-                       if (uri && uri->protocol == source_uri->protocol &&
-                           uri->port == source_uri->port &&
-                           !strcmp (uri->host, source_uri->host))
-                               dir = g_strdup (uri->path);
-                       else
-                               dir = NULL;
-                       if (uri)
-                               soup_uri_free (uri);
-               }
-
-               if (dir) {
-                       slash = strrchr (dir, '/');
-                       if (slash && !slash[1])
-                               *slash = '\0';
-
-                       space = g_slist_prepend (space, dir);
-               }
-       }
-       g_free (domain);
-
-       return space;
-}
-
-static void
-digest_init_func (SoupAuth *auth, const SoupUri *uri)
-{
-       SoupAuthDigest *digest = (SoupAuthDigest *) auth;
-       MD5Context ctx;
-       guchar d[16];
-
-       digest->user = g_strdup (uri->user);
-
-       /* compute A1 */
-       md5_init (&ctx);
-
-       md5_update (&ctx, uri->user, strlen (uri->user));
-
-       md5_update (&ctx, ":", 1);
-       if (auth->realm)
-               md5_update (&ctx, auth->realm, strlen (auth->realm));
-
-       md5_update (&ctx, ":", 1);
-       if (uri->passwd)
-               md5_update (&ctx, uri->passwd, strlen (uri->passwd));
-
-       if (digest->algorithm == ALGORITHM_MD5_SESS) {
-               md5_final (&ctx, d);
-
-               md5_init (&ctx);
-               md5_update (&ctx, d, 16);
-               md5_update (&ctx, ":", 1);
-               md5_update (&ctx, digest->nonce, strlen (digest->nonce));
-               md5_update (&ctx, ":", 1);
-               md5_update (&ctx, digest->cnonce, strlen (digest->cnonce));
-       }
-
-       /* hexify A1 */
-       md5_final (&ctx, d);
-       digest_hex (d, digest->hex_a1);
-
-       auth->authenticated = TRUE;
-}
-
-static gboolean
-digest_invalidate_func (SoupAuth *auth)
-{
-       /* If we failed, we need to get a new nonce from the server
-        * next time, so this can't be reused.
-        */
-       return FALSE;
-}
-
-static void
-digest_free (SoupAuth *auth)
-{
-       SoupAuthDigest *digest = (SoupAuthDigest *) auth;
-
-       g_free (digest->user);
-       g_free (digest->domain);
-
-       g_free (digest->nonce);
-       g_free (digest->cnonce);
-       g_free (digest);
-}
-
-static SoupAuth *
-soup_auth_new_digest (void)
-{
-       SoupAuthDigest *digest;
-       SoupAuth *auth;
-       char *bgen;
-
-       digest = g_new0 (SoupAuthDigest, 1);
-
-       auth = (SoupAuth *) digest;
-       auth->type = SOUP_AUTH_TYPE_DIGEST;
-       auth->authenticated = FALSE;
-
-       auth->parse_func = digest_parse_func;
-       auth->init_func = digest_init_func;
-       auth->invalidate_func = digest_invalidate_func;
-       auth->pspace_func = digest_pspace_func;
-       auth->auth_func = digest_auth_func;
-       auth->free_func = digest_free;
-
-       bgen = g_strdup_printf ("%p:%lu:%lu",
-                              auth,
-                              (unsigned long) getpid (),
-                              (unsigned long) time (0));
-       digest->cnonce = soup_base64_encode (bgen, strlen (bgen));
-       digest->nc = 1;
-       /* We're just going to do qop=auth for now */
-       digest->qop = QOP_AUTH;
-
-       g_free (bgen);
-
-       return auth;
-}
-
-
-/*
- * NTLM Authentication Support
- */
-
-typedef struct {
-       SoupAuth  auth;
-       gchar    *response;
-       gchar    *header;
-} SoupAuthNTLM;
-
-static gchar *
-ntlm_auth (SoupAuth *sa, SoupMessage *msg)
-{
-       SoupAuthNTLM *auth = (SoupAuthNTLM *) sa;
-       char *ret;
-
-       if (!sa->authenticated)
-               return soup_ntlm_request ();
-
-       /* Otherwise, return the response; but only once */
-       ret = auth->response;
-       auth->response = NULL;
-       return ret;
-}
-
-static inline gchar *
-ntlm_get_authmech_token (const SoupUri *uri, gchar *key)
-{
-       gchar *idx;
-       gint len;
-
-       if (!uri->authmech) return NULL;
-
-       idx = strstr (uri->authmech, key);
-       if (idx) {
-               idx += strlen (key);
-
-               len = strcspn (idx, ",; ");
-               if (len)
-                       return g_strndup (idx, len);
-               else
-                       return g_strdup (idx);
-       }
-
-       return NULL;
-}
-
-static void
-ntlm_parse (SoupAuth *sa, const char *header)
-{
-       SoupAuthNTLM *auth = (SoupAuthNTLM *) sa;
-
-       auth->header = g_strdup (header);
-       g_strstrip (auth->header);
-}
-
-static GSList *
-ntlm_pspace (SoupAuth *auth, const SoupUri *source_uri)
-{
-       /* The protection space is the whole server. */
-       return g_slist_prepend (NULL, g_strdup (""));
-}
-
-static void
-ntlm_init (SoupAuth *sa, const SoupUri *uri)
-{
-       SoupAuthNTLM *auth = (SoupAuthNTLM *) sa;
-       gchar *host, *domain, *nonce;
-
-       if (!auth->header || strlen (auth->header) < sizeof ("NTLM"))
-               return;
-
-       if (auth->response)
-               g_free (auth->response);
-
-       host   = ntlm_get_authmech_token (uri, "host=");
-       domain = ntlm_get_authmech_token (uri, "domain=");
-
-       if (!soup_ntlm_parse_challenge (auth->header, &nonce,
-                                       domain ? NULL : &domain))
-               auth->response = NULL;
-       else {
-               auth->response = soup_ntlm_response (nonce,
-                                                    uri->user,
-                                                    uri->passwd,
-                                                    host,
-                                                    domain);
-               g_free (nonce);
-       }
-
-       g_free (host);
-       g_free (domain);
-
-       g_free (auth->header);
-       auth->header = NULL;
-
-       sa->authenticated = TRUE;
-}
-
-static gboolean
-ntlm_invalidate (SoupAuth *sa)
-{
-       SoupAuthNTLM *auth = (SoupAuthNTLM *) sa;
-
-       g_free (auth->response);
-       auth->response = NULL;
-       g_free (auth->header);
-       auth->header = NULL;
-
-       sa->authenticated = FALSE;
-       return TRUE;
-}
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class;
 
 static void
-ntlm_free (SoupAuth *sa)
-{
-       SoupAuthNTLM *auth = (SoupAuthNTLM *) sa;
-
-       g_free (auth->response);
-       g_free (auth->header);
-       g_free (auth);
-}
-
-SoupAuth *
-soup_auth_new_ntlm (void)
+class_init (GObjectClass *object_class)
 {
-       SoupAuthNTLM *auth;
-
-       auth = g_new0 (SoupAuthNTLM, 1);
-       auth->auth.type = SOUP_AUTH_TYPE_NTLM;
-       auth->auth.authenticated = FALSE;
-       auth->auth.realm = g_strdup ("");
-
-       auth->auth.parse_func = ntlm_parse;
-       auth->auth.init_func = ntlm_init;
-       auth->auth.invalidate_func = ntlm_invalidate;
-       auth->auth.pspace_func = ntlm_pspace;
-       auth->auth.auth_func = ntlm_auth;
-       auth->auth.free_func = ntlm_free;
-
-       return (SoupAuth *) auth;
+       parent_class = g_type_class_ref (PARENT_TYPE);
 }
 
+SOUP_MAKE_TYPE (soup_auth, SoupAuth, class_init, NULL, PARENT_TYPE)
 
-/*
- * Generic Authentication Interface
- */
-
-typedef SoupAuth *(*SoupAuthNewFn) (void);
 
 typedef struct {
-       const gchar   *scheme;
-       SoupAuthNewFn  ctor;
-       gint           strength;
+       const char  *scheme;
+       GType      (*type_func) (void);
+       int          strength;
 } AuthScheme; 
 
 static AuthScheme known_auth_schemes [] = {
-       { "Basic",  soup_auth_new_basic,  0 },
-       { "NTLM",   soup_auth_new_ntlm,   2 },
-       { "Digest", soup_auth_new_digest, 3 },
+       { "Basic",  soup_auth_basic_get_type,  0 },
+       { "NTLM",   soup_auth_ntlm_get_type,   2 },
+       { "Digest", soup_auth_digest_get_type, 3 },
        { NULL }
 };
 
 SoupAuth *
-soup_auth_new_from_header_list (const SoupUri *uri,
-                               const GSList  *vals)
+soup_auth_new_from_header_list (const GSList *vals, const char *pref)
 {
-       gchar *header = NULL;
+       char *header = NULL;
        AuthScheme *scheme = NULL, *iter;
        SoupAuth *auth = NULL;
 
        g_return_val_if_fail (vals != NULL, NULL);
 
        while (vals) {
-               gchar *tryheader = vals->data;
+               char *tryheader = vals->data;
 
                for (iter = known_auth_schemes; iter->scheme; iter++) {
-                       if (uri->authmech &&
-                           g_strncasecmp (uri->authmech,
-                                          iter->scheme,
+                       if (pref &&
+                           g_strncasecmp (pref, iter->scheme,
                                           strlen (iter->scheme)) != 0)
                                continue;
-                       if (!g_strncasecmp (tryheader, 
-                                           iter->scheme, 
+                       if (!g_strncasecmp (tryheader, iter->scheme, 
                                            strlen (iter->scheme))) {
                                if (!scheme || 
                                    scheme->strength < iter->strength) {
@@ -723,64 +74,75 @@ soup_auth_new_from_header_list (const SoupUri *uri,
                vals = vals->next;
        }
 
-       if (!scheme) return NULL;
+       if (!scheme)
+               return NULL;
 
-       auth = scheme->ctor ();
-       if (!auth) return NULL;
-
-       if (!auth->parse_func || 
-           !auth->init_func || 
-           !auth->auth_func || 
-           !auth->free_func)
-               g_error ("Faulty Auth Created!!");
-
-       auth->parse_func (auth, header);
+       auth = g_object_new (scheme->type_func (), NULL);
+       if (!auth)
+               return NULL;
 
+       SOUP_AUTH_GET_CLASS (auth)->construct (auth, header);
        return auth;
 }
 
 void
-soup_auth_initialize (SoupAuth *auth, const SoupUri *uri)
+soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password)
+{
+       g_return_if_fail (SOUP_IS_AUTH (auth));
+       g_return_if_fail (username != NULL);
+       g_return_if_fail (password != NULL);
+
+       SOUP_AUTH_GET_CLASS (auth)->authenticate (auth, username, password);
+}
+
+const char *
+soup_auth_get_scheme_name (SoupAuth *auth)
+{
+       g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
+
+       return SOUP_AUTH_GET_CLASS (auth)->scheme_name;
+}
+
+const char *
+soup_auth_get_realm (SoupAuth *auth)
 {
-       g_return_if_fail (auth != NULL);
-       g_return_if_fail (uri != NULL);
+       g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
 
-       auth->init_func (auth, uri);
+       return SOUP_AUTH_GET_CLASS (auth)->get_realm (auth);
 }
 
 gboolean
 soup_auth_invalidate (SoupAuth *auth)
 {
-       g_return_val_if_fail (auth != NULL, FALSE);
+       g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE);
 
-       return auth->invalidate_func (auth);
+       return SOUP_AUTH_GET_CLASS (auth)->invalidate (auth);
 }
 
-gchar *
-soup_auth_authorize (SoupAuth *auth, SoupMessage *msg)
+gboolean
+soup_auth_is_authenticated (SoupAuth *auth)
 {
-       g_return_val_if_fail (auth != NULL, NULL);
-       g_return_val_if_fail (msg != NULL, NULL);
+       g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE);
 
-       return auth->auth_func (auth, msg);
+       return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth);
 }
 
-void
-soup_auth_free (SoupAuth *auth)
+char *
+soup_auth_get_authorization (SoupAuth *auth, SoupMessage *msg)
 {
-       g_return_if_fail (auth != NULL);
+       g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
+       g_return_val_if_fail (msg != NULL, NULL);
 
-       g_free (auth->realm);
-       auth->free_func (auth);
+       return SOUP_AUTH_GET_CLASS (auth)->get_authorization (auth, msg);
 }
 
 GSList *
 soup_auth_get_protection_space (SoupAuth *auth, const SoupUri *source_uri)
 {
-       g_return_val_if_fail (auth != NULL, NULL);
+       g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
        g_return_val_if_fail (source_uri != NULL, NULL);
 
-       return auth->pspace_func (auth, source_uri);
+       return SOUP_AUTH_GET_CLASS (auth)->get_protection_space (auth, source_uri);
 }
 
 void
index 756029e..017331d 100644 (file)
@@ -1,58 +1,66 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * soup-auth.h: Authentication schemes
- *
- * Authors:
- *      Joe Shaw (joe@ximian.com)
- *
- * Copyright (C) 2001-2002, Ximian, Inc.
+ * Copyright (C) 2001-2003, Ximian, Inc.
  */
 
 #ifndef SOUP_AUTH_H
 #define SOUP_AUTH_H 1
 
-#include <libsoup/soup-context.h>
+#include <glib-object.h>
 #include <libsoup/soup-message.h>
-#include <libsoup/soup-misc.h>
+#include <libsoup/soup-uri.h>
 
-typedef   enum _SoupAuthStatus SoupAuthStatus;
-typedef struct _SoupAuth       SoupAuth;
+#define SOUP_TYPE_AUTH            (soup_auth_get_type ())
+#define SOUP_AUTH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_AUTH, SoupAuth))
+#define SOUP_AUTH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH, SoupAuthClass))
+#define SOUP_IS_AUTH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_AUTH))
+#define SOUP_IS_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_AUTH))
+#define SOUP_AUTH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH, SoupAuthClass))
 
-struct _SoupAuth {
-       SoupAuthType    type;
-       char           *realm;
-       gboolean        authenticated;
+typedef struct {
+       GObject parent;
 
-       void     (*parse_func)      (SoupAuth      *auth,
-                                    const gchar   *header);
+} SoupAuth;
 
-       void     (*init_func)       (SoupAuth      *auth, 
-                                    const SoupUri *uri);
+typedef struct {
+       GObjectClass parent_class;
 
-       gboolean (*invalidate_func) (SoupAuth      *auth);
+       const char *scheme_name;
 
-       char    *(*auth_func)       (SoupAuth      *auth, 
-                                    SoupMessage   *message);
+       void         (*construct)            (SoupAuth      *auth,
+                                             const char    *header);
 
-       GSList  *(*pspace_func)     (SoupAuth      *auth,
-                                    const SoupUri *source_uri);
+       GSList *     (*get_protection_space) (SoupAuth      *auth,
+                                             const SoupUri *source_uri);
 
-       void     (*free_func)       (SoupAuth      *auth);
-};
+       const char * (*get_realm)            (SoupAuth      *auth);
 
-SoupAuth   *soup_auth_new_from_header_list  (const SoupUri *uri,
-                                            const GSList  *header);
+       void         (*authenticate)         (SoupAuth      *auth,
+                                             const char    *username,
+                                             const char    *password);
+       gboolean     (*invalidate)           (SoupAuth      *auth);
+       gboolean     (*is_authenticated)     (SoupAuth      *auth);
 
-SoupAuth   *soup_auth_new_ntlm              (void);
+       char *       (*get_authorization)    (SoupAuth      *auth,
+                                             SoupMessage   *msg);
+} SoupAuthClass;
 
-void        soup_auth_initialize            (SoupAuth      *auth,
-                                            const SoupUri *uri);
+GType       soup_auth_get_type              (void);
 
-gboolean    soup_auth_invalidate            (SoupAuth      *auth);
 
-void        soup_auth_free                  (SoupAuth      *auth);
+SoupAuth   *soup_auth_new_from_header_list  (const GSList  *header,
+                                            const char    *pref);
+
+const char *soup_auth_get_scheme_name       (SoupAuth      *auth);
+const char *soup_auth_get_realm             (SoupAuth      *auth);
 
-gchar      *soup_auth_authorize             (SoupAuth      *auth, 
+void        soup_auth_authenticate          (SoupAuth      *auth,
+                                            const char    *username,
+                                            const char    *password);
+gboolean    soup_auth_invalidate            (SoupAuth      *auth);
+gboolean    soup_auth_is_authenticated      (SoupAuth      *auth);
+
+char       *soup_auth_get_authorization     (SoupAuth      *auth, 
                                             SoupMessage   *msg);
 
 GSList     *soup_auth_get_protection_space  (SoupAuth      *auth,
@@ -60,5 +68,4 @@ GSList     *soup_auth_get_protection_space  (SoupAuth      *auth,
 void        soup_auth_free_protection_space (SoupAuth      *auth,
                                             GSList        *space);
 
-
 #endif /* SOUP_AUTH_H */
index 6f79a04..da99619 100644 (file)
@@ -25,6 +25,7 @@
 #include <netinet/in.h>
 
 #include "soup-auth.h"
+#include "soup-auth-ntlm.h"
 #include "soup-context.h"
 #include "soup-private.h"
 #include "soup-misc.h"
@@ -204,7 +205,7 @@ static void
 free_auth (gpointer realm, gpointer auth, gpointer unused)
 {
        g_free (realm);
-       soup_auth_free (auth);
+       g_object_unref (auth);
 }
 
 /**
@@ -266,7 +267,7 @@ connection_free (SoupConnection *conn)
                g_slist_remove (conn->server->connections, conn);
 
        if (conn->auth)
-               soup_auth_free (conn->auth);
+               g_object_unref (conn->auth);
 
        g_io_channel_unref (conn->channel);
        soup_context_unref (conn->context);
@@ -790,7 +791,7 @@ soup_context_lookup_auth (SoupContext *ctx, SoupMessage *msg)
 
        if (ctx->server->use_ntlm && msg && msg->connection) {
                if (!msg->connection->auth)
-                       msg->connection->auth = soup_auth_new_ntlm ();
+                       msg->connection->auth = soup_auth_ntlm_new ();
                return msg->connection->auth;
        }
 
@@ -828,7 +829,7 @@ update_auth_internal (SoupContext *ctx, SoupConnection *conn,
        GSList *pspace, *p;
 
        if (server->use_ntlm && conn && conn->auth) {
-               if (conn->auth->authenticated) {
+               if (soup_auth_is_authenticated (conn->auth)) {
                        /* This is a "permission denied", not a
                         * "password incorrect". There's nothing more
                         * we can do.
@@ -837,22 +838,24 @@ update_auth_internal (SoupContext *ctx, SoupConnection *conn,
                }
 
                /* Free the intermediate auth */
-               soup_auth_free (conn->auth);
+               g_object_unref (conn->auth);
                conn->auth = NULL;
        }
 
        /* Try to construct a new auth from the headers; if we can't,
         * there's no way we'll be able to authenticate.
         */
-       new_auth = soup_auth_new_from_header_list (ctx->uri, headers);
+       new_auth = soup_auth_new_from_header_list (headers, ctx->uri->authmech);
        if (!new_auth)
                return FALSE;
 
        /* See if this auth is the same auth we used last time */
        prior_auth = soup_context_lookup_auth (ctx, NULL);
-       if (prior_auth && prior_auth->type == new_auth->type &&
-           !strcmp (prior_auth->realm, new_auth->realm)) {
-               soup_auth_free (new_auth);
+       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))) {
+               g_object_unref (new_auth);
                if (prior_auth_failed) {
                        /* The server didn't like the username/password
                         * we provided before.
@@ -868,13 +871,13 @@ update_auth_internal (SoupContext *ctx, SoupConnection *conn,
                }
        }
 
-       if (new_auth->type == SOUP_AUTH_TYPE_NTLM) {
+       if (SOUP_IS_AUTH_NTLM (new_auth)) {
                server->use_ntlm = TRUE;
                if (conn) {
                        conn->auth = new_auth;
                        return soup_context_authenticate_auth (ctx, new_auth);
                } else {
-                       soup_auth_free (new_auth);
+                       g_object_unref (new_auth);
                        return FALSE;
                }
        }
@@ -885,7 +888,9 @@ update_auth_internal (SoupContext *ctx, SoupConnection *conn,
        }
 
        /* Record where this auth realm is used */
-       realm = g_strdup_printf ("%d:%s", new_auth->type, new_auth->realm);
+       realm = g_strdup_printf ("%s:%s",
+                                soup_auth_get_scheme_name (new_auth),
+                                soup_auth_get_realm (new_auth));
        pspace = soup_auth_get_protection_space (new_auth, ctx->uri);
        for (p = pspace; p; p = p->next) {
                path = p->data;
@@ -908,13 +913,13 @@ update_auth_internal (SoupContext *ctx, SoupConnection *conn,
        old_auth = g_hash_table_lookup (server->auths, realm);
        if (old_auth) {
                g_free (realm);
-               soup_auth_free (new_auth);
+               g_object_unref (new_auth);
                new_auth = old_auth;
        } else 
                g_hash_table_insert (server->auths, realm, new_auth);
 
        /* Try to authenticate if needed. */
-       if (!new_auth->authenticated)
+       if (!soup_auth_is_authenticated (new_auth))
                return soup_context_authenticate_auth (ctx, new_auth);
 
        return TRUE;
@@ -958,16 +963,16 @@ soup_context_authenticate_auth (SoupContext *ctx, SoupAuth *auth)
        const SoupUri *uri = ctx->uri;
 
        if (!uri->user && soup_auth_fn) {
-               (*soup_auth_fn) (auth->type,
+               (*soup_auth_fn) (soup_auth_get_scheme_name (auth),
                                 (SoupUri *) uri,
-                                auth->realm
+                                soup_auth_get_realm (auth)
                                 soup_auth_fn_user_data);
        }
 
        if (!uri->user)
                return FALSE;
 
-       soup_auth_initialize (auth, uri);
+       soup_auth_authenticate (auth, uri->user, uri->passwd);
        return TRUE;
 }
 
@@ -985,14 +990,16 @@ soup_context_invalidate_auth (SoupContext *ctx, SoupAuth *auth)
                return;
 
        /* Nope, need to remove it completely */
-       realm = g_strdup_printf ("%d:%s", auth->type, auth->realm);
+       realm = g_strdup_printf ("%s:%s",
+                                soup_auth_get_scheme_name (auth),
+                                soup_auth_get_realm (auth));
 
        if (g_hash_table_lookup_extended (ctx->server->auths, realm,
                                          &key, &value) &&
            auth == (SoupAuth *)value) {
                g_hash_table_remove (ctx->server->auths, realm);
                g_free (key);
-               soup_auth_free (auth);
+               g_object_unref (auth);
        }
        g_free (realm);
 }
index 30e97b3..cb97b8b 100644 (file)
@@ -56,15 +56,9 @@ void               soup_get_ssl_cert_files   (const gchar **cert_file,
 
 /* Authentication callback */
 
-typedef enum {
-       SOUP_AUTH_TYPE_BASIC = 1,
-       SOUP_AUTH_TYPE_DIGEST,
-       SOUP_AUTH_TYPE_NTLM,    
-} SoupAuthType;
-
-typedef void (*SoupAuthorizeFn) (SoupAuthType   type,
+typedef void (*SoupAuthorizeFn) (const char    *scheme_name,
                                 SoupUri       *uri,
-                                const gchar   *realm,
+                                const char    *realm,
                                 gpointer       user_data);
 
 void               soup_set_authorize_callback (SoupAuthorizeFn authfn,
diff --git a/libsoup/soup-ntlm.h b/libsoup/soup-ntlm.h
deleted file mode 100644 (file)
index b512857..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-ntlm.h: Microsoft Windows NTLM authentication support
- *
- * Authors:
- *      Dan Winship (danw@ximian.com)
- *
- * Copyright (C) 2001-2002, Ximian, Inc.
- */
-
-#ifndef NTLM_H
-#define NTLM_H 1
-
-#include <glib.h>
-
-void     soup_ntlm_lanmanager_hash (const char *password,
-                                   guchar hash[21]);
-
-void     soup_ntlm_nt_hash         (const char *password,
-                                   guchar hash[21]);
-
-char    *soup_ntlm_request         (void);
-
-gboolean soup_ntlm_parse_challenge (const char *challenge,
-                                   char      **nonce,
-                                   char      **default_domain);
-
-char    *soup_ntlm_response        (const char *nonce, 
-                                   const char *user,
-                                   const char *password,
-                                   const char *host, 
-                                   const char *domain);
-
-#endif /* NTLM_H */
index 9c5c869..ad740d8 100644 (file)
@@ -298,11 +298,11 @@ soup_encode_http_auth (SoupMessage *msg, GString *header, gboolean proxy_auth)
        auth = soup_context_lookup_auth (ctx, msg);
        if (!auth)
                return;
-       if (!auth->authenticated &&
+       if (!soup_auth_is_authenticated (auth) &&
            !soup_context_authenticate_auth (ctx, auth))
                return;
 
-       token = soup_auth_authorize (auth, msg);
+       token = soup_auth_get_authorization (auth, msg);
        if (token) {
                g_string_sprintfa (header, "%s: %s\r\n",
                                   proxy_auth ? 
index c381b10..6c64e40 100644 (file)
@@ -18,7 +18,6 @@
 
 #include "md5-utils.h"
 #include "soup-headers.h"
-#include "soup-ntlm.h"
 
 typedef struct {
        const gchar   *scheme;
@@ -28,7 +27,6 @@ typedef struct {
 
 static AuthScheme known_auth_schemes [] = {
        { "Basic",  SOUP_AUTH_TYPE_BASIC,  0 },
-       { "NTLM",   SOUP_AUTH_TYPE_NTLM,   2 },
        { "Digest", SOUP_AUTH_TYPE_DIGEST, 3 },
        { NULL }
 };
@@ -180,26 +178,6 @@ soup_server_auth_check_passwd (SoupServerAuth *auth,
                        return passwd == auth->basic.passwd;
        case SOUP_AUTH_TYPE_DIGEST:
                return check_digest_passwd (&auth->digest, passwd);
-       case SOUP_AUTH_TYPE_NTLM:
-               if (passwd) {
-                       gchar lm_hash [21], nt_hash [21];
-
-                       soup_ntlm_lanmanager_hash (passwd, lm_hash);
-                       soup_ntlm_nt_hash (passwd, nt_hash);
-
-                       if (memcmp (lm_hash, 
-                                   auth->ntlm.lm_hash, 
-                                   sizeof (lm_hash)) != 0)
-                               return FALSE;
-
-                       if (memcmp (nt_hash, 
-                                   auth->ntlm.nt_hash, 
-                                   sizeof (nt_hash)) != 0)
-                               return FALSE;
-
-                       return TRUE;
-               }
-               return FALSE;
        }
 
        return FALSE;
@@ -215,8 +193,6 @@ soup_server_auth_get_user (SoupServerAuth *auth)
                return auth->basic.user;
        case SOUP_AUTH_TYPE_DIGEST:
                return auth->digest.user;
-       case SOUP_AUTH_TYPE_NTLM:
-               return auth->ntlm.user;
        }
 
        return NULL;
@@ -417,9 +393,6 @@ soup_server_auth_new (SoupServerAuthContext *auth_ctx,
                if (parse_digest (auth_ctx, header, msg, ret))
                        return ret;
                break;
-       case SOUP_AUTH_TYPE_NTLM:
-               g_warning ("NTLM server authentication not yet implemented\n");
-               break;
        }
 
        g_free (ret);
@@ -446,13 +419,6 @@ soup_server_auth_free (SoupServerAuth *auth)
                g_free ((gchar *) auth->digest.digest_uri);
                g_free ((gchar *) auth->digest.digest_response);
                break;
-       case SOUP_AUTH_TYPE_NTLM:
-               g_free ((gchar *) auth->ntlm.host);
-               g_free ((gchar *) auth->ntlm.domain);
-               g_free ((gchar *) auth->ntlm.user);
-               g_free ((gchar *) auth->ntlm.lm_hash);
-               g_free ((gchar *) auth->ntlm.nt_hash);
-               break;
        }
 
        g_free (auth);
index 9866cd8..e387c9c 100644 (file)
@@ -44,6 +44,11 @@ void soup_server_auth_context_challenge (SoupServerAuthContext *auth_ctx,
                                         gchar                 *header_name);
 
 
+typedef enum {
+       SOUP_AUTH_TYPE_BASIC = 1,
+       SOUP_AUTH_TYPE_DIGEST,
+} SoupAuthType;
+
 typedef struct {
        SoupAuthType  type;
        const gchar  *user;
@@ -69,20 +74,10 @@ typedef struct {
        const gchar          *request_method;
 } SoupServerAuthDigest;
 
-typedef struct {
-       SoupAuthType  type;
-       const gchar  *host;
-       const gchar  *domain;
-       const gchar  *user;
-       const gchar  *lm_hash;
-       const gchar  *nt_hash;
-} SoupServerAuthNTLM;
-
 union _SoupServerAuth {
        SoupAuthType          type;
        SoupServerAuthBasic   basic;
        SoupServerAuthDigest  digest;
-       SoupServerAuthNTLM    ntlm;
 };
 
 SoupServerAuth *soup_server_auth_new          (SoupServerAuthContext *auth_ctx, 
index 10af618..f4172c8 100644 (file)
@@ -163,10 +163,10 @@ identify_auth (SoupMessage *msg)
        int num;
 
        auth = soup_context_lookup_auth (msg->context, msg);
-       if (!auth || !auth->authenticated)
+       if (!auth || !soup_auth_is_authenticated (auth))
                return 0;
 
-       header = soup_auth_authorize (auth, msg);
+       header = soup_auth_get_authorization (auth, msg);
        if (!g_ascii_strncasecmp (header, "Basic ", 6)) {
                char *token;
                int len;