---------------------
PatchSet 860 
Date: 2000/11/21 00:11:15
Author: rbcollins
Branch: auth_rewrite
Tag: (none) 
Log:
nearly complete

Members: 
	configure.in:1.1.1.3.10.17.2.1->1.1.1.3.10.17.2.2 
	src/authenticate.c:1.1.1.3.12.17.2.4->1.1.1.3.12.17.2.5 
	src/client_side.c:1.1.1.3.4.1.2.30.2.1->1.1.1.3.4.1.2.30.2.2 
	src/errorpage.c:1.1.1.3.10.9->1.1.1.3.10.9.2.1 
	src/structs.h:1.1.1.3.4.1.2.26.2.3->1.1.1.3.4.1.2.26.2.4 
	src/typedefs.h:1.1.1.3.12.13.2.3->1.1.1.3.12.13.2.4 
	src/auth/basic/auth_basic.c:1.1.2.2->1.1.2.3 
	src/auth/ntlm/auth_ntlm.c:1.1.2.2->1.1.2.3 

Index: squid/configure.in
===================================================================
RCS file: /cvsroot/squid-sf//squid/configure.in,v
retrieving revision 1.1.1.3.10.17.2.1
retrieving revision 1.1.1.3.10.17.2.2
diff -u -r1.1.1.3.10.17.2.1 -r1.1.1.3.10.17.2.2
--- squid/configure.in	20 Nov 2000 06:55:35 -0000	1.1.1.3.10.17.2.1
+++ squid/configure.in	21 Nov 2000 00:11:15 -0000	1.1.1.3.10.17.2.2
@@ -3,13 +3,13 @@
 dnl
 dnl  Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9)
 dnl
-dnl  $Id: configure.in,v 1.1.1.3.10.17.2.1 2000/11/20 06:55:35 rbcollins Exp $
+dnl  $Id: configure.in,v 1.1.1.3.10.17.2.2 2000/11/21 00:11:15 rbcollins Exp $
 dnl
 dnl
 dnl
 AC_INIT(src/main.c)
 AC_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.1.1.3.10.17.2.1 $)dnl
+AC_REVISION($Revision: 1.1.1.3.10.17.2.2 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AC_CONFIG_AUX_DIR(cfgaux)
 
@@ -689,7 +689,7 @@
   esac
 ],
 [ if test -z "$AUTH_MODULES"; then
-    AUTH_MODULES="basic ntlm"
+    AUTH_MODULES="ntlm basic"
   fi
 ])
 echo "Auth scheme modules built: $AUTH_MODULES"
Index: squid/src/authenticate.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/authenticate.c,v
retrieving revision 1.1.1.3.12.17.2.4
retrieving revision 1.1.1.3.12.17.2.5
diff -u -r1.1.1.3.12.17.2.4 -r1.1.1.3.12.17.2.5
--- squid/src/authenticate.c	20 Nov 2000 22:40:33 -0000	1.1.1.3.12.17.2.4
+++ squid/src/authenticate.c	21 Nov 2000 00:11:16 -0000	1.1.1.3.12.17.2.5
@@ -1,6 +1,6 @@
 
 /*
- * $Id: authenticate.c,v 1.1.1.3.12.17.2.4 2000/11/20 22:40:33 rbcollins Exp $
+ * $Id: authenticate.c,v 1.1.1.3.12.17.2.5 2000/11/21 00:11:16 rbcollins Exp $
  *
  * DEBUG: section 29    Authenticator
  * AUTHOR: Duane Wessels
@@ -114,34 +114,6 @@
         ("authenticateDecodeAuth: Unsupported proxy-auth scheme, '%s'\n",
         proxy_auth); 
     return;
-#if 0
-    if (strncasecmp(proxy_auth, "Basic ", 6) == 0)  {
-        if (Config.Program.authenticate != NULL) {
-        proxy_auth += 6;
-        auth_user->auth_type = AUTH_BASIC;
-//        auth_user->proxy_auth = xstrdup(proxy_auth);
-//        authenticateDecodeBasicAuth(auth_user);
-          authenticateDecodeBasicAuth(auth_user, proxy_auth);
-        } else
-            auth_user->auth_type = AUTH_UNKNOWN;
-    } else
-    if (strncmp("NTLM ", proxy_auth, 5) == 0) {
-        if (Config.Program.ntlmauthenticate != NULL) {
-        proxy_auth += 5;
-        auth_user->auth_type = AUTH_NTLM;
-//        auth_user->proxy_auth = xstrdup(proxy_auth);
-//        authenticateDecodeNTLMAuth(auth_user);
-        authenticateDecodeNTLMAuth(auth_user, proxy_auth);
-        } else
-            auth_user->auth_type = AUTH_UNKNOWN;
-    } else
-    {
-        debug(29, 1)
-            ("authenticateDecodeAuth: Unsupported proxy-auth scheme, '%s'\n",
-            proxy_auth); auth_user->auth_type = AUTH_UNKNOWN;
-        return;
-    }
-#endif
 }
 #if 0
 static void
@@ -149,410 +121,8 @@
 {
     cbdataFree(r);
 }
-
-/* Basic Scheme */
-
-/* log a basic user in
- */
-static acl_proxy_auth_user *
-authenticateBasicAuthenticateUser(acl_proxy_auth_user *data, const char * proxy_auth) {
-    acl_proxy_auth_hash_pointer *usernamehash, *proxy_auth_hash=NULL;
-    acl_proxy_auth_user *auth_user=data;
-    /* if the password is not ok, do an identity */
-    if (auth_user->flags.credentials_ok!=1)
-        return auth_user;
-
-    /* password was checked and did match */
-    debug(29, 4) ("authenticateBasicAuthenticateuser: user '%s' validated OK\n",
-        auth_user->auth_data.basic_auth.username);
-    /* see if this is an existing user with a different proxy_auth string */
-    if ((usernamehash = hash_lookup(proxy_auth_username_cache,
-        auth_user->auth_data.basic_auth.username))) {
-        while ((usernamehash->auth_user->auth_type != auth_user->auth_type) &&
-            (usernamehash->next) &&
-            !strcmp(usernamehash->auth_user->auth_data.basic_auth.username,auth_user->auth_data.basic_auth.username) )
-            usernamehash=usernamehash->next;
-        if (usernamehash->auth_user->auth_type==auth_user->auth_type) {
-            /*
-             * add another link from the new proxy_auth to the
-             * auth_user structure and update the information */
-            assert(proxy_auth_hash == NULL);
-            authenticateProxyAuthCacheAddLink(proxy_auth, usernamehash->auth_user);
-            /* maybe the p/w changed. update in the old structure */
-            xfree(usernamehash->auth_user->auth_data.basic_auth.passwd);
-            usernamehash->auth_user->auth_data.basic_auth.passwd =
-                auth_user->auth_data.basic_auth.passwd;
-            auth_user->auth_data.basic_auth.passwd = NULL;
-            /* and remove the temporary structure */
-            authenticateAuthUserUnlock(auth_user);
-            authenticateFreeProxyAuthUser(auth_user);
-            auth_user = usernamehash->auth_user;
-            /* lock the structure for this request */
-            authenticateAuthUserLock(auth_user);
-        }
-    } else {
-        /* store user in hash's */
-        authenticateUserNameCacheAdd(auth_user);
-        authenticateProxyAuthCacheAddLink(proxy_auth, auth_user);
-    }
-    /* auth_user is now linked, we reset these values
-     * after external auth occurs anyway */
-    auth_user->expiretime =  current_time.tv_sec;
-    auth_user->ip_expiretime = squid_curtime;
-    return auth_user;
-}
-
-int authenticateBasicDirection(acl_proxy_auth_user *auth_user) {
-/* null auth_user is checked for by authenticateDirection */
-    switch (auth_user->flags.credentials_ok) {
-        case 0: /* not checked */
-            return -1;
-        case 1: /* checked & ok */
-            return 0;
-        case 2: /* partway through checking. Invalid for basic */
-            return -2;
-        case 3: /* authentication process failed. */
-            return -2;
-    }
-    return -2;
-}
-
-static void
-authenticateBasicHandleReply(void *data, char *reply)
-{
-    authenticateStateData *r = data;
-    acl_proxy_auth_user *auth_user;
-    int valid;
-    char *t = NULL;
-    debug(29, 5) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : "<NULL>");
-    if (reply) {
-	if ((t = strchr(reply, ' ')))
-	    *t = '\0';
-	if (*reply == '\0')
-	    reply = NULL;
-    }
-    assert(r->auth_user != NULL);
-    assert(r->auth_user->auth_type == AUTH_BASIC);
-    auth_user=r->auth_user;    
-    if (reply && (strncasecmp(reply, "OK", 2) == 0))
-        auth_user->flags.credentials_ok = 1;
-    else
-        auth_user->flags.credentials_ok = 2;
-    valid = cbdataValid(r->data);
-    cbdataUnlock(r->data);
-    if (valid)
-	r->handler(r->data, NULL);
-#if 0
-    if (valid)
-        r->handler(r->data, reply);
-#endif
-    authenticateStateFree(r);
-}
-
-static void
-authenticateBasicStats(StoreEntry * sentry)
-{
-    storeAppendPrintf(sentry, "Basic Authenticator Statistics:\n");
-    helperStats(sentry, basicauthenticators);
-}
-
-/*
- * Decode a Basic [Proxy-]Auth string, placing the results in the passed
- * Auth_user structure.
- */
-
-static void
-authenticateDecodeBasicAuth(acl_proxy_auth_user *auth_user, const char * proxy_auth) {
-    char *sent_auth;
-    char *cleartext;
-    assert(auth_user->auth_type == AUTH_BASIC);
-
-    /* Trim leading whitespace before decoding */
-    while (xisspace(*proxy_auth))
-        proxy_auth++;
-    /* username and password */
-    sent_auth = xstrdup(proxy_auth);
-    /* Trim trailing \n before decoding */
-    strtok(sent_auth, "\n");
-    cleartext = uudecode(sent_auth);
-    xfree(sent_auth);
-    /*
-     * Don't allow NL or CR in the credentials.
-     * Oezguer Kesim <oec@codeblau.de>
-     */
-    strtok(cleartext, "\r\n");
-    debug(29, 6) ("authenticateDecodeBasicAuth: cleartext = '%s'\n", cleartext);
-    /* have we been called twice? */
-    assert(auth_user->auth_data.basic_auth.username == NULL);
-    auth_user->auth_data.basic_auth.username =
-        xstrndup(cleartext, USER_IDENT_SZ);
-    xfree(cleartext);
-    /* again, have we been called twice? */
-    assert(auth_user->auth_data.basic_auth.passwd == NULL);
-    if ((cleartext =
-        strchr(auth_user->auth_data.basic_auth.username, ':')) != NULL)
-            *(cleartext)++ = '\0';
-    if (cleartext == NULL) {
-        debug(29, 2) ("authenticateDecodeBasicAuth: no password in proxy authorization header '%s'\n",
-            proxy_auth); auth_user->auth_type = AUTH_BROKEN;
-    }
-    if (*cleartext == '\0') {
-        debug(29, 2) ("authenticateDecodeBasicAuth: Disallowing empty password,"
-            "user is '%s'\n", auth_user->auth_data.basic_auth.username);
-        auth_user->auth_type = AUTH_BROKEN;
-    }
-    /* special case: we have to free the strings for user and password
-     * if we are not returning AUTH_BASIC else the UserFree function will
-     * be confused.
-     */
-    if (auth_user->auth_type != AUTH_BASIC) {
-        if (auth_user->auth_data.basic_auth.username)
-             xfree(auth_user->auth_data.basic_auth.username);
-        } else {
-             auth_user->auth_data.basic_auth.passwd = xstrndup(cleartext, USER_IDENT_SZ);
-        }
-    /* we are finished with the proxy_auth */
-//    xfree(auth_user->proxy_auth);
-//    auth_user->proxy_auth = NULL;
-    return;
-}
-
-/* send the initial data to a basic authenticator module */
-static void
-authenticateBasicStart(acl_proxy_auth_user * auth_user, RH * handler, void *data)
-{
-    authenticateStateData *r = NULL;
-    char buf[8192];
-    assert(auth_user);
-    assert(handler);
-    assert(auth_user->auth_type==AUTH_BASIC);
-    debug(29, 5) ("authenticateStart: '%s:%s'\n", auth_user->auth_data.basic_auth.username,
-        auth_user->auth_data.basic_auth.passwd);
-    if (Config.Program.authenticate == NULL) {
-        handler(data, NULL);
-        return;
-    }
-    r = xcalloc(1, sizeof(authenticateStateData));
-    cbdataAdd(r, cbdataXfree, 0);
-    r->handler = handler;
-    cbdataLock(data);
-    r->data = data;
-    r->auth_user = auth_user;
-    snprintf(buf, 8192, "%s %s\n", auth_user->auth_data.basic_auth.username, auth_user->auth_data.basic_auth.passwd);
-    helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r);
-}
-
-/* NTLM Scheme */
-
-int authenticateNTLMDirection(acl_proxy_auth_user *auth_user) {
-/* null auth_user is checked for by authenticateDirection */
-     switch (auth_user->auth_data.ntlm_auth.auth_state) {
-        case AUTHENTICATE_STATE_NONE: /* no progress at all.*/
-            debug(28,1) ("authenticateNTLMDirection: called before NTLM Authenticate!. Report a bug to squid-dev.\n");
-            return -2;
-        case AUTHENTICATE_STATE_NEGOTIATE: /* send to helper */
-        case AUTHENTICATE_STATE_RESPONSE: /*send to helper */
-            return -1;
-        case AUTHENTICATE_STATE_CHALLENGE: /* send to client */
-            return 1;
-        case AUTHENTICATE_STATE_DONE: /* do nothing.. */
-            return 0;
-    }
-    return -2;
-}
-
-static stateful_helper_callback_t
-authenticateNTLMHandleReply(void *data, void * lastserver, char *reply)
-{
-#if 0
-    authenticateStatefulStateData *r = data;
-#endif
-    authenticateStateData *r = data;
-    int valid;
-    stateful_helper_callback_t result = S_HELPER_UNKNOWN;
-#if 0
-    void *nextserver=NULL;
-#endif
-    char *t = NULL;
-    acl_proxy_auth_user *auth_user;
-    debug(29, 5) ("authenticateNTLMHandleReply: Helper: '%d' {%s}\n", lastserver, reply ? reply : "<NULL>");
-    valid = cbdataValid(r->data);
-    cbdataUnlock(r->data);
-    if (valid) {
-        if (reply) {
-            /* seperate out the useful data */
-            if (strncasecmp(reply, "CH ", 3) == 0) {
-	        reply += 3;
-                /* we have been given a Challenge */
-                /* we should check we weren't given an empty challenge */
-#if 0
-	        result=S_HELPER_RESERVE;
-#endif
-                assert(r->auth_user != NULL);
-                assert(r->auth_user->auth_type == AUTH_NTLM);
-                auth_user=r->auth_user;
-                result=S_HELPER_DEFER;
-#if 0
-                nextserver=lastserver;
-#endif
-	        debug(29,5)("authenticateNTLMHandleReply: helper '%d'\n",lastserver);
-                assert(auth_user->auth_data.ntlm_auth.auth_state == AUTHENTICATE_STATE_NEGOTIATE);
-//                auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_CHALLENGE;
-                auth_user->auth_data.ntlm_auth.authhelper = lastserver;
-                auth_user->auth_data.ntlm_auth.authchallenge =
-                    xstrndup(reply, NTLM_CHALLENGE_SZ+5);
-            } 
-	    else if (strncasecmp(reply, "OK ", 3) == 0) {
-	        /* we're finished, release the helper*/
-                reply+=3;
-                assert(r->auth_user != NULL);
-                assert(r->auth_user->auth_type == AUTH_NTLM);
-                auth_user=r->auth_user;
-	        result=S_HELPER_RELEASE;
-                /* we only expect OK when finishing the handshake */
-                assert(auth_user->auth_data.ntlm_auth.auth_state == AUTHENTICATE_STATE_RESPONSE);
-                auth_user->auth_data.ntlm_auth.username = xstrndup(reply, MAX_LOGIN_SZ);
-                auth_user->auth_data.ntlm_auth.authhelper = NULL;
-                auth_user->flags.credentials_ok = 1; /* login ok */
-            } 
-	    else if (strncasecmp(reply, "RESET OK", 8) == 0) {
-                /* Helper successfully reset */
-	        /* note a reset request returning here MUST NOT reserve the helper */
-	        /* also auth_user does not need to be valid on a reset call */
-                result=S_HELPER_RELEASE;
-                if (r->auth_user) r->auth_user->auth_data.ntlm_auth.authhelper=NULL;
-            } 
-	    else if (strncasecmp(reply, "ERR", 3) == 0) {
-                /* TODO: only work with auth_user here if it exists */
-                assert(r->auth_user != NULL);
-                assert(r->auth_user->auth_type == AUTH_NTLM);
-                auth_user=r->auth_user;
-                /* todo: action of Negotiate state on error */
-                result=S_HELPER_RELEASE; /*some error has occured. no more requests */
-                auth_user->auth_data.ntlm_auth.authhelper = NULL;
-                auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_NONE;
-                if (auth_user->auth_data.ntlm_auth.auth_state == AUTHENTICATE_STATE_NEGOTIATE) {
-                    /* The helper rejected the negotiate. It automatically 
-                     * resets */
-                    auth_user->flags.credentials_ok = 3; /* cannot process */
-                    debug(29, 1) ("authenticateNTLMHandleReply: Error obtaining challenge from helper: %d.\n", lastserver);
-                } else {
-                    auth_user->flags.credentials_ok = 2; /* Login/Usercode failed */
-                    debug(29, 1) ("authenticateNTLMHandleReply: Error validating user via NTLM.\n");
-                }
-                if ((t = strchr(reply, ' ')))/* strip after a space */
-		    *t = '\0';
-            } else { 
-                /* TODO: only work with auth_user here if it exists */
-                assert(r->auth_user != NULL);
-                assert(r->auth_user->auth_type == AUTH_NTLM);
-                auth_user=r->auth_user;
-	        debug(29, 1) ("authenticateNTLMHandleReply: Unsupported helper response, '%s'\n", reply);
-                /* restart the authentication process */
-                auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_NONE;
-                auth_user->flags.credentials_ok = 3; /* cannot process */
-                auth_user->auth_data.ntlm_auth.authhelper = NULL;
-	    }
-#if 0
-	if (*reply == '\0')
-	    reply = NULL;
-#endif
-        } else {
-            fatal("authenticateNTLMHandleReply: called with no result string\n");
-        }
-//	r->handler(r->data, nextserver, reply);
-        r->handler(r->data, NULL);
-    } else {
-        debug(29,1) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%d'.\n",lastserver);
-        result=S_HELPER_RELEASE;
-    }
-#if 0
-    authenticateStatefulStateFree(r);
-#endif
-    authenticateStateFree(r);
-    debug(29,5)("NTLM HandleReply, telling stateful helper : %d\n",result);
-    return result;
-}
-
-
-static void
-authenticateNTLMStateFree(authenticateNTLMStateData * r)
-{
-    cbdataFree(r);
-}
-
-
-static void
-authenticateNTLMStats(StoreEntry * sentry)
-{
-    storeAppendPrintf(sentry, "NTLM Authenticator Statistics:\n");
-    helperStatefulStats(sentry, ntlmauthenticators);
-}
-
-/* send the initial data to a stateful ntlm authenticator module */
-static void
-authenticateNTLMStart(acl_proxy_auth_user * auth_user, RH * handler, void *data)
-{
-#if 0
-    authenticateStatefulStateData *r = NULL;
-#endif
-    authenticateStateData *r = NULL;
-    char buf[8192];
-    char *sent_string=NULL;
-
-    assert(auth_user);
-    assert(handler);
-    assert(data);
-    assert(auth_user->auth_type=AUTH_NTLM);
-    switch(auth_user->auth_data.ntlm_auth.auth_state) {
-        case AUTHENTICATE_STATE_NEGOTIATE:
-            sent_string = xstrdup(auth_user->auth_data.ntlm_auth.ntlmnegotiate);
-            break;
-        case AUTHENTICATE_STATE_RESPONSE:
-            sent_string = xstrdup(auth_user->auth_data.ntlm_auth.ntlmauthenticate);
-            assert(auth_user->auth_data.ntlm_auth.authhelper);
-            debug(28, 6) ("authenticateNTLMStart: Asking NTLMauthenticator '%d'.\n", auth_user->auth_data.ntlm_auth.authhelper);
-            break;
-        default:
-            fatal("Invalid authenticate state for NTLMStart");
-    }
-
-    while (!xisspace(*sent_string))     /*trim NTLM */
-        sent_string++;
-
-    while (xisspace(*sent_string))      /*trim leading spaces */
-        sent_string++;
-    debug(29, 5) ("authenticateNTLMStart: state '%d'\n", auth_user->auth_data.ntlm_auth.auth_state);
-    debug(29, 5) ("authenticateNTLMStart: '%s'\n", sent_string);
-    if (Config.Program.ntlmauthenticate == NULL) {
-        debug(29, 1) ("authenticateNTLMStart: no NTLM program specified:'%s'\n", sent_string);
-//	handler(data,0, NULL);
-            handler(data, NULL);
-	return;
-    }
-    r = xcalloc(1, sizeof(authenticateStateData));
-#if 0
-    r = xcalloc(1, sizeof(authenticateStatefulStateData));
 #endif
-    cbdataAdd(r, cbdataXfree, 0);
-    r->handler = handler;
-    cbdataLock(data);
-    r->data = data;
-    r->auth_user = auth_user;
-    snprintf(buf, 8192, "%s\n", sent_string);
-    helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, auth_user->auth_data.ntlm_auth.authhelper);
-    debug(29,9)("authenticateNTLMstart: finished\n");
-}
 
-/* clear the NTLM helper of being reserved for future requests */
-void
-authenticateNTLMReleasehelper(acl_proxy_auth_user *auth_user){
-    assert(auth_user->auth_type==AUTH_NTLM);
-    debug(29,5) ("authenticateNTLMReleasehelper: releasing helper '%d'\n",auth_user->auth_data.ntlm_auth.authhelper);
-    helperStatefulReleaseServer(auth_user->auth_data.ntlm_auth.authhelper);
-    auth_user->auth_data.ntlm_auth.authhelper=NULL;
-}
-#endif
 /* clear any connection related authentication details */
 void
 authenticateOnCloseConnection(acl_proxy_auth_user *auth_user){
@@ -561,50 +131,6 @@
     }
 }
 
-#if OBSOLETE
-/* send the initial data to a stateful ntlm authenticator module */
-void
-authenticateNTLMStart(const char *proxy_auth, SRH * handler, void *data, helper_
-stateful_server * lastserver)
-{
-    authenticateStatefulStateData *r = NULL;
-    char buf[8192];
-    assert(proxy_auth);
-    assert(handler);
-    assert(data);
-    debug(29, 5) ("authenticateNTLMStart: '%s'\n", proxy_auth);
-    if (Config.Program.ntlmauthenticate == NULL) {
-        debug(29, 1) ("authenticateNTLMStart: no NTLM program specified:'%s'\n",
- proxy_auth);
-        handler(data,0, NULL);
-        return;
-    }
-    r = xcalloc(1, sizeof(authenticateStatefulStateData));
-    cbdataAdd(r, cbdataXfree, 0);
-    r->handler = handler;
-    cbdataLock(data);
-    r->data = data;
-    snprintf(buf, 8192, "%s\n", proxy_auth);
-    helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r
-, lastserver);
-    debug(29,9)("authenticateNTLMstart: finished\n");
-}
-#endif
-#if 0
-/*
- * Decode an NTLM [Proxy-]Auth string, placing the results in the passed
- * Auth_user structure.
- */
-
-void
-authenticateDecodeNTLMAuth(acl_proxy_auth_user *auth_user, const char * proxy_auth) {
-    assert(auth_user->auth_type == AUTH_NTLM);
-    /* all we have to do is identify that it's NTLM - the helper does the rest */
-    debug(29, 6) ("authenticateDecodeNTLMAuth: NTLM authentication\n");
-    return;
-}
-#endif
-
 /**** PUBLIC FUNCTIONS (ALL GENERIC!)  ****/
 
 /* send the initial data to an authenticator module */
@@ -613,29 +139,12 @@
 {
     assert(auth_user);
     assert(handler);
+    debug(29,5)("authenticateStart: auth_user '%d'\n", auth_user);
     if (auth_user->auth_module>0)
         authscheme_list[auth_user->auth_module-1].authStart(auth_user, handler, data);
     else
         handler(data,NULL);
 }
-#if 0
-    assert((auth_user->auth_type==AUTH_BASIC) ||
-           (auth_user->auth_type==AUTH_NTLM));
-    switch(auth_user->auth_type) {
-        case AUTH_NTLM:
-            authenticateNTLMStart(auth_user, handler, data);
-            break;
-        case AUTH_BASIC:
-            debug(28, 4)
-                ("AuthenticateStart: going to ask authenticator on %s\n",
-                auth_user->auth_data.basic_auth.username);
-            /* we must still check this user's password */
-            authenticateBasicStart(auth_user, handler, data);
-            break;
-        default:
-    }
-}
-#endif
 
 /*
  * Check a auth_user pointer for validity. Does not check passwords, just data
@@ -701,181 +210,6 @@
     debug (29, 7) ("Couldn't find user in cache: assuming not logged in.\n");
     return 0;
 }
-#if 0
-static acl_proxy_auth_user *
-authenticateNTLMAuthenticateUser(void *data, const char * proxy_auth, ConnStateData *conn) {
-    acl_proxy_auth_user *auth_user=data;
-    acl_proxy_auth_hash_pointer *usernamehash, *proxy_auth_hash=NULL;
-    LOCAL_ARRAY(char, ntlmhash, NTLM_CHALLENGE_SZ * 2);
-//    char * proxy_auth=auth_user->proxy_auth;
-    assert(auth_user->auth_type==AUTH_NTLM);
-    switch (auth_user->auth_data.ntlm_auth.auth_state) {
-        case AUTHENTICATE_STATE_NONE:
-            /* we've recieved a negotiate request. pass to a helper */
-            debug(29, 3) ("authenticateNTLMAuthenticateUser: auth state ntlm none. %s\n",
-                proxy_auth);
-            auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_NEGOTIATE;
-//            auth_user->auth_data.ntlm_auth.ntlmnegotiate = auth_user->proxy_auth;
-//            /* use it up.  */
-//            auth_user->proxy_auth=NULL;
-
-            auth_user->auth_data.ntlm_auth.ntlmnegotiate=xstrndup(proxy_auth, NTLM_CHALLENGE_SZ+5);
-            conn->auth_type=AUTH_NTLM;
-            conn->auth_user=auth_user;   
-
-            return auth_user;
-            break;
-        case AUTHENTICATE_STATE_NEGOTIATE:
-            auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_CHALLENGE;
-//            xfree(auth_user->proxy_auth);
-//           auth_user->proxy_auth=NULL;
-            return auth_user;
-            break;
-        case AUTHENTICATE_STATE_CHALLENGE:
-            /* we should have recieved a NTLM challenge. pass it to the same 
-             * helper process */
-            debug(29,3) ("authenticateNTLMAuthenticateUser: auth state challenge with header %s.\n", proxy_auth);
-            /* do a cache lookup here. If it matches it's a successful ntlm 
-             * challenge - release the helper and use the existing auth_user 
-             * details. */
-            if (strncmp("NTLM ", proxy_auth, 5) == 0) {
-#if 0
-                 proxy_auth += 5;
-#endif
-                 auth_user->auth_data.ntlm_auth.ntlmauthenticate = xstrdup(proxy_auth);
-//                 xfree(auth_user->proxy_auth);
-//                 auth_user->proxy_auth = NULL;
-            } else {
-                fatal("Incorrect scheme in auth header\n");
-                /* TODO: more fault tolerance.. reset the auth scheme here */
-            }
-             /* cache entries have authenticateauthheaderchallengestring */
-            snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", 
-                auth_user->auth_data.ntlm_auth.ntlmauthenticate,
-                auth_user->auth_data.ntlm_auth.authchallenge);
-            /* see if we already know this user's authenticate */
-            debug(29,3)("aclMatchProxyAuth: cache lookup with key '%s'\n",ntlmhash);
-            assert(proxy_auth_cache!=NULL);
-            proxy_auth_hash = hash_lookup(proxy_auth_cache, ntlmhash);
-            if (!proxy_auth_hash) { /* not in the hash table */
-                debug(29,3)("authenticateNTLMAuthenticateUser: proxy-auth cache miss.\n");
-                auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_RESPONSE;
-#if 0
-                xstrndup(proxy_auth, NTLM_CHALLENGE_SZ+5);
-#endif
-                /* verify with the ntlm helper */
-            } else {
-                debug(29,3)("authenticateNTLMAuthenticateUser: ntlm proxy-auth cache hit\n");
-                /* throw away the temporary entry */
-                authenticateNTLMReleasehelper(auth_user);
-                authenticateAuthUserUnlock(auth_user);
-                authenticateFreeProxyAuthUser(auth_user);
-
-                auth_user = proxy_auth_hash->auth_user;
-                authenticateAuthUserLock(auth_user);
-                conn->auth_user=auth_user;
-                /* we found one */
-                debug(29, 3) ("found matching cache entry\n");
-                assert(auth_user->auth_type == AUTH_NTLM);
-                debug(29, 3) ("Username to be used is %s\n",
-                    auth_user->auth_data.ntlm_auth.username);
-                auth_user->flags.credentials_ok = 1; /* authenticated ok */
-                /* on ntlm auth we do not unlock the auth_user until the
-                 * connection is dropped. Thank MS for this quirk */
-                auth_user->expiretime = current_time.tv_sec ;
-                auth_user->ip_expiretime = squid_curtime;
-            }
-            return auth_user;
-            break;
-        case AUTHENTICATE_STATE_RESPONSE:
-            /* auth-challenge pair cache miss. We've just got the response */
-            /*add to cache and let them through */
-            auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_DONE;
-            /* this connection is authenticated */
-            debug(29, 3) ("validated\nch    %s\nauth     %s\nauthuser %s\n",
-                auth_user->auth_data.ntlm_auth.authchallenge,
-                auth_user->auth_data.ntlm_auth.ntlmauthenticate,
-                auth_user->auth_data.ntlm_auth.username);
-            /* cache entries have authenticateauthheaderchallengestring */
-            snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", auth_user->auth_data.ntlm_auth.ntlmauthenticate,
-                auth_user->auth_data.ntlm_auth.authchallenge);
-            /* see if this is an existing user with a different proxy_auth 
-             * string */
-            if ((usernamehash = hash_lookup(proxy_auth_username_cache,
-                auth_user->auth_data.ntlm_auth.username))) {
-                while ((usernamehash->auth_user->auth_type != 
-                    auth_user->auth_type) && (usernamehash->next) &&
-                    !strcmp(usernamehash->auth_user->auth_data.ntlm_auth.username, auth_user->auth_data.ntlm_auth.username) ) 
-                    usernamehash=usernamehash->next;
-                if (usernamehash->auth_user->auth_type==auth_user->auth_type) {
-                    /*
-                     * add another link from the new proxy_auth to the
-                     * auth_user structure and update the information */
-                     assert(proxy_auth_hash == NULL);
-                     authenticateProxyAuthCacheAddLink(ntlmhash, usernamehash->auth_user);
-                    /* we can't seamlessly recheck the username due to the 
-                     * challenge nature of the protocol. Just free the 
-                     * temporary auth_user */
-                    authenticateAuthUserUnlock(auth_user);
-                    authenticateFreeProxyAuthUser(auth_user);
-                    auth_user = usernamehash->auth_user;
-                    authenticateAuthUserLock(auth_user);
-                    conn->auth_user=auth_user;
-                }
-            } else {
-                /* store user in hash's */
-                authenticateUserNameCacheAdd(auth_user);
-                authenticateProxyAuthCacheAddLink(ntlmhash, auth_user);
-            }
-            /* set these to now because this is either a new login from an 
-             * existing user or a new user */
-            auth_user->expiretime = current_time.tv_sec ;
-            auth_user->ip_expiretime = squid_curtime;
-            auth_user->flags.credentials_ok=1; /*authenticated ok */
-            return auth_user;
-            break;
-#if 0 
-done in acl.c
-    case AUTHENTICATE_STATE_DONE:
-        debug(28, 5) ("aclMatchProxyAuth: connection in state Done. using connec
-tion credentials for the request.\n");
-        /* is it working right? */
-        assert(checklist->auth_user == NULL);
-        assert(checklist->conn->auth_user != NULL);
-        /* we have a valid username. */
-        auth_user = checklist->conn->auth_user;
-        /* store the username in the request for logging */
-        xstrncpy(checklist->request->authuser,
-            auth_user->auth_data.ntlm_auth.username,
-            USER_IDENT_SZ);
-        if (auth_user->expiretime + Config.authenticateTTL > current_time.tv_sec
-)
-        {
-            auth_user->expiretime = current_time.tv_sec;
-        }
-        else{
-            //user passed externa; authentication in every case to get here. f.
-Let it through
-        }
-
-        /* we don't unlock the auth_user until the connection is dropped. Thank
-         * MS for this quirk. */
-            if (authenticateCheckAuthUserIP(checklist->src_addr, auth_user)){
-                /* Once the match is completed we have finished with the
-                 * auth_user structure */
-                /* check to see if we have matched the user-acl before */
-                return aclCacheMatchAcl(&auth_user->proxy_match_cache, acltype,
-                    data, auth_user->auth_data.ntlm_auth.username);
-            } else {
-                    return 0;
-            }
-        break;
-#endif
-    }
-
-    return auth_user;
-}
-#endif
 
 /*
  * authenticateAuthenticateUser: log this user in returns a new auth_user.
@@ -892,27 +226,8 @@
         return authscheme_list[auth_user->auth_module-1].authAuthenticate(auth_user, request, conn, type);
     return auth_user;
 
-
 #if 0
     proxy_auth = httpHeaderGetStr(&request->header, type);
-    debug(29,6) ("authenticateAuthenticateUser: authentication header type %d, value '%s'\n.", type,proxy_auth);
-    /* switch used so we get warn-on-compile if new AUTH type added but not 
-     * handled */
-    switch (auth_user->auth_type){
-        case AUTH_BASIC:
-            return authenticateBasicAuthenticateUser(auth_user, proxy_auth);
-            break;
-        case AUTH_NTLM:
-            return authenticateNTLMAuthenticateUser(auth_user, proxy_auth, conn);
-            break;
-        case AUTH_UNKNOWN:
-        case AUTH_BROKEN:
-            /* Identity operation */
-            auth_user->flags.credentials_ok=3; 
-            return auth_user;
-    }
-    /*identity function */
-    return auth_user;
 #endif
 }
 
@@ -923,21 +238,6 @@
   if (auth_user->auth_module>0)
       return authscheme_list[auth_user->auth_module-1].authUserUsername(auth_user);
     return NULL;
-#if 0
-    switch (auth_user->auth_type) {
-        case AUTH_UNKNOWN:
-        case AUTH_BROKEN:
-            return NULL;
-            break;
-        case AUTH_BASIC:
-            return auth_user->auth_data.basic_auth.username;
-            break;
-        case AUTH_NTLM:
-            return auth_user->auth_data.ntlm_auth.username;
-            break;
-    }
-    return NULL;
-#endif
 }
 
 /* returns
@@ -952,76 +252,19 @@
     if (authenticateUserAuthenticated(auth_user)) return 0;
     if (auth_user->auth_module>0)
         return authscheme_list[auth_user->auth_module-1].getdirection(auth_user);
-#if 0
-    switch (auth_user->auth_type) {
-        case AUTH_UNKNOWN:
-        case AUTH_BROKEN:
-            return -2;
-        case AUTH_BASIC:
-            return authenticateBasicDirection(auth_user);
-        case AUTH_NTLM:
-            return authenticateNTLMDirection(auth_user);
-    }
-#endif
     return -2;
 }
 
-
-
 void
 authenticateInit(void)
 {
     authSchemeSetup();
-#if 0
-    static int init = 0;
-    static int ntlminit = 0;
-    if (Config.Program.authenticate){
-        if (basicauthenticators == NULL)
-		basicauthenticators = helperCreate("basicauthenticator");
-	    basicauthenticators->cmdline = Config.Program.authenticate;
-	    basicauthenticators->n_to_start = Config.authenticateChildren;
-	    basicauthenticators->ipc_type = IPC_TCP_SOCKET;
-	    helperOpenServers(basicauthenticators);
-	    if (!init) {
-		cachemgrRegister("basicauthenticator",
-		    "User Authenticator Stats",
-		    authenticateBasicStats, 0, 1);
-		init++;
-	    }
-	}
-    if (Config.Program.ntlmauthenticate){
-        if (ntlmauthenticators == NULL)
-		ntlmauthenticators = helperStatefulCreate("ntlmauthenticator");
-	    ntlmauthenticators->cmdline = Config.Program.ntlmauthenticate;
-	    ntlmauthenticators->n_to_start = Config.ntlmauthenticateChildren;
-	    ntlmauthenticators->ipc_type = IPC_TCP_SOCKET;
-	    helperStatefulOpenServers(ntlmauthenticators);
-	    if (!ntlminit) {
-		cachemgrRegister("ntlmauthenticator",
-		    "User NTLM Authenticator Stats",
-		    authenticateNTLMStats, 0, 1);
-		ntlminit++;
-	    }
-	}
-#endif
 }
 
 void
 authenticateShutdown(void)
 {
     int i;
-#if 0
-    if (basicauthenticators)
-        helperShutdown(basicauthenticators);
-    if (ntlmauthenticators)
-        helperStatefulShutdown(ntlmauthenticators);
-    if (!shutting_down)
-	return;
-    helperFree(basicauthenticators);
-    basicauthenticators = NULL;
-    helperStatefulFree(ntlmauthenticators);
-    ntlmauthenticators = NULL;
-#endif
     /* find the currently known authscheme types */
     for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) {
         authscheme_list[i].donefunc();
@@ -1034,9 +277,10 @@
 authenticateFixErrorHeader(HttpReply * rep, ErrorState * err)
 /* send the auth types we are configured to support (and have compiled in!) */
 {
-    auth_type_t auth_type=err->auth_type;
+/*    auth_type_t auth_type=err->auth_type;
     auth_state_t auth_state=err->auth_state;
     char *authchallenge=err->authchallenge;
+*/  acl_proxy_auth_user *auth_user=err->auth_user;
     int type;
     switch (err->http_status) {
     case HTTP_PROXY_AUTHENTICATION_REQUIRED:
@@ -1053,8 +297,18 @@
 	return;
      break;
      }
-    debug(29,9)("authenticateFixErrorHeader: headertype:%d authtype:%d authstate:%d\n",type,auth_type,auth_state);
+    debug(29,9)("authenticateFixErrorHeader: headertype:%d authuser:%d\n",type,auth_user);
+    if ((auth_user !=NULL) && (auth_user->auth_module>0))
+        authscheme_list[auth_user->auth_module-1].authFixErrorHeader(auth_user, rep, type, err->request);
+    else {
+        int i;
+        /* call each currently known authscheme */
+        for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) {
+            authscheme_list[i].authFixErrorHeader(auth_user,rep, type, err->request);
+        }
+    }
 
+#if OBSOLETE
     switch (auth_type){
     case AUTH_UNKNOWN: 
 #if 0
@@ -1118,6 +372,7 @@
         fatal("Unknown authentication type");
     }
     return;
+#endif
 }
 
 
Index: squid/src/client_side.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v
retrieving revision 1.1.1.3.4.1.2.30.2.1
retrieving revision 1.1.1.3.4.1.2.30.2.2
diff -u -r1.1.1.3.4.1.2.30.2.1 -r1.1.1.3.4.1.2.30.2.2
--- squid/src/client_side.c	20 Nov 2000 13:18:04 -0000	1.1.1.3.4.1.2.30.2.1
+++ squid/src/client_side.c	21 Nov 2000 00:11:16 -0000	1.1.1.3.4.1.2.30.2.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.c,v 1.1.1.3.4.1.2.30.2.1 2000/11/20 13:18:04 rbcollins Exp $
+ * $Id: client_side.c,v 1.1.1.3.4.1.2.30.2.2 2000/11/21 00:11:16 rbcollins Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -259,6 +259,9 @@
 	err = errorCon(page_id, status);
 	err->request = requestLink(http->request);
 	err->src_addr = http->conn->peer.sin_addr;
+        if (http->conn->auth_user)
+            err->auth_user=http->conn->auth_user;
+#if OBSOLETE
         err->auth_type = http->conn->auth_type;
         if (http->conn->auth_user) {
             if (http->conn->auth_user->auth_type==AUTH_NTLM)
@@ -267,6 +270,7 @@
 	    err->auth_state = AUTHENTICATE_STATE_NONE;
         if ((http->conn->auth_user) && (http->conn->auth_user->auth_type==AUTH_NTLM))
   	    err->authchallenge = http->conn->auth_user->auth_data.ntlm_auth.authchallenge; 
+#endif
 	errorAppendEntry(http->entry, err);
     }
 }
Index: squid/src/errorpage.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/errorpage.c,v
retrieving revision 1.1.1.3.10.9
retrieving revision 1.1.1.3.10.9.2.1
diff -u -r1.1.1.3.10.9 -r1.1.1.3.10.9.2.1
--- squid/src/errorpage.c	16 Nov 2000 11:47:00 -0000	1.1.1.3.10.9
+++ squid/src/errorpage.c	21 Nov 2000 00:11:16 -0000	1.1.1.3.10.9.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: errorpage.c,v 1.1.1.3.10.9 2000/11/16 11:47:00 rbcollins Exp $
+ * $Id: errorpage.c,v 1.1.1.3.10.9.2.1 2000/11/21 00:11:16 rbcollins Exp $
  *
  * DEBUG: section 4     Error Generation
  * AUTHOR: Duane Wessels
@@ -277,7 +277,7 @@
     storeBuffer(entry);
     rep = errorBuildReply(err);
     /* Add authentication header */
-    debug(28,6)("errorpage:state:type %d:%d.\n",err->auth_state,err->auth_type);
+//    debug(28,6)("errorpage:state:type %d:%d.\n",err->auth_state,err->auth_type);
     authenticateFixErrorHeader(rep, err);
     httpReplySwapOut(rep, entry);
     httpReplyAbsorb(mem->reply, rep);
Index: squid/src/structs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/structs.h,v
retrieving revision 1.1.1.3.4.1.2.26.2.3
retrieving revision 1.1.1.3.4.1.2.26.2.4
diff -u -r1.1.1.3.4.1.2.26.2.3 -r1.1.1.3.4.1.2.26.2.4
--- squid/src/structs.h	20 Nov 2000 22:40:33 -0000	1.1.1.3.4.1.2.26.2.3
+++ squid/src/structs.h	21 Nov 2000 00:11:16 -0000	1.1.1.3.4.1.2.26.2.4
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.3 2000/11/20 22:40:33 rbcollins Exp $
+ * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.4 2000/11/21 00:11:16 rbcollins Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -135,6 +135,7 @@
 //    STFSPARSE *parsefunc;
 //    STFSRECONFIGURE *reconfigurefunc;
     AUTHSAUTHUSER *authAuthenticate;
+    AUTHSFIXERR   *authFixErrorHeader;
     AUTHSUSERNAME *authUserUsername;
     AUTHSONCLOSEC *oncloseconnection;
     AUTHSDECODE   *decodeauth;
@@ -1591,9 +1592,10 @@
     err_type type;
     int page_id;
     http_status http_status;
-    auth_type_t auth_type;
+    acl_proxy_auth_user * auth_user; 
+/*    auth_type_t auth_type;
     auth_state_t auth_state;
-    char *authchallenge;
+    char *authchallenge; */
     request_t *request;
     char *url;
     int xerrno;
Index: squid/src/typedefs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v
retrieving revision 1.1.1.3.12.13.2.3
retrieving revision 1.1.1.3.12.13.2.4
diff -u -r1.1.1.3.12.13.2.3 -r1.1.1.3.12.13.2.4
--- squid/src/typedefs.h	20 Nov 2000 22:40:33 -0000	1.1.1.3.12.13.2.3
+++ squid/src/typedefs.h	21 Nov 2000 00:11:16 -0000	1.1.1.3.12.13.2.4
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.1.1.3.12.13.2.3 2000/11/20 22:40:33 rbcollins Exp $
+ * $Id: typedefs.h,v 1.1.1.3.12.13.2.4 2000/11/21 00:11:16 rbcollins Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -293,6 +293,7 @@
 typedef acl_proxy_auth_user * AUTHSAUTHUSER(acl_proxy_auth_user *, request_t *, ConnStateData *, http_hdr_type);
 typedef void  AUTHSDECODE(acl_proxy_auth_user *, const char *);
 typedef int   AUTHSDIRECTION(acl_proxy_auth_user *);
+typedef void  AUTHSFIXERR(acl_proxy_auth_user *, HttpReply *, http_hdr_type, request_t *);
 typedef char *AUTHSUSERNAME(acl_proxy_auth_user *);
 typedef void  AUTHSONCLOSEC(acl_proxy_auth_user *);
 typedef void  AUTHSSETUP(authscheme_entry_t *);
Index: squid/src/auth/basic/auth_basic.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/auth/basic/auth_basic.c,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -r1.1.2.2 -r1.1.2.3
--- squid/src/auth/basic/auth_basic.c	20 Nov 2000 22:40:33 -0000	1.1.2.2
+++ squid/src/auth/basic/auth_basic.c	21 Nov 2000 00:11:16 -0000	1.1.2.3
@@ -71,7 +71,8 @@
 static HLPCB authenticateBasicHandleReply;
 static AUTHSAUTHUSER  authenticateBasicAuthenticateUser;
 static AUTHSDIRECTION authenticateBasicDirection;
-static AUTHSDECODE authenticateBasicDecodeAuth;
+static AUTHSDECODE    authenticateBasicDecodeAuth;
+static AUTHSFIXERR    authenticateBasicFixErrorHeader;
 static AUTHSSTART  authenticateBasicStart;
 static AUTHSSTATS  authenticateBasicStats;
 static AUTHSUSERNAME authenticateBasicUsername;
@@ -104,6 +105,7 @@
 //    authscheme->parsefunc = storeUfsDirParse;
 //    authscheme->reconfigurefunc = storeUfsDirReconfigure;
     authscheme->authAuthenticate = authenticateBasicAuthenticateUser;
+    authscheme->authFixErrorHeader=authenticateBasicFixErrorHeader;
     authscheme->authStart   =authenticateBasicStart;
     authscheme->authStats   =authenticateBasicStats;
     authscheme->authUserUsername = authenticateBasicUsername;
@@ -201,6 +203,14 @@
     return -2;
 }
 
+void
+authenticateBasicFixErrorHeader(acl_proxy_auth_user *auth_user, HttpReply *rep, http_hdr_type type, request_t * request){
+    if (Config.Program.authenticate){
+        debug(29, 5) ("authenticateFixErrorHeader: Sending type:%d header: 'Basic realm=\"%s\"'\n",type,Config.proxyAuthRealm);
+    httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", Config.proxyAuthRealm);
+    }
+}
+
 static void
 authenticateBasicHandleReply(void *data, char *reply)
 {
Index: squid/src/auth/ntlm/auth_ntlm.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/auth/ntlm/auth_ntlm.c,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -r1.1.2.2 -r1.1.2.3
--- squid/src/auth/ntlm/auth_ntlm.c	20 Nov 2000 22:40:34 -0000	1.1.2.2
+++ squid/src/auth/ntlm/auth_ntlm.c	21 Nov 2000 00:11:16 -0000	1.1.2.3
@@ -69,6 +69,7 @@
 static void  authenticateNTLMStart(acl_proxy_auth_user *, RH * handler, void *);
 static HLPSCB authenticateNTLMHandleReply;
 static AUTHSAUTHUSER  authenticateNTLMAuthenticateUser;
+static AUTHSFIXERR    authenticateNTLMFixErrorHeader;
 static AUTHSDIRECTION authenticateNTLMDirection;
 static AUTHSDECODE authenticateDecodeNTLMAuth;
 static AUTHSONCLOSEC authenticateNTLMOnCloseConnection;
@@ -107,6 +108,7 @@
 //    authscheme->parsefunc = storeUfsDirParse;
 //    authscheme->reconfigurefunc = storeUfsDirReconfigure;
     authscheme->authAuthenticate = authenticateNTLMAuthenticateUser;
+    authscheme->authFixErrorHeader=authenticateNTLMFixErrorHeader;
     authscheme->authStart   =authenticateNTLMStart;
     authscheme->authStats   =authenticateNTLMStats;
     authscheme->authUserUsername = authenticateNTLMUsername;
@@ -151,6 +153,48 @@
     return -2;
 }
 
+/*
+ * Send the authenticate error header(s). Note: IE has a bug and the NTLM header
+ * must be first. To ensure that, the configure use --enable-auth=ntlm, anything
+ * else.
+ */
+void
+authenticateNTLMFixErrorHeader(acl_proxy_auth_user *auth_user, HttpReply *rep, http_hdr_type type, request_t * request){
+    if (Config.Program.ntlmauthenticate){
+        /* New request, no user details */
+        if (auth_user == NULL) {
+            debug(29, 5) ("authenticateFixErrorHeader: Sending type:%d header: 'NTLM'\n",type);
+            httpHeaderPutStrf(&rep->header, type, "NTLM");
+            /* drop the connection */
+            httpHeaderDelByName(&rep->header, "keep-alive"); 
+            /* NTLM has problems if the initial connection is not dropped
+               I haven't checked the RFC compliance of this hack - RBCollins*/
+            request->flags.proxy_keepalive = 0;
+        } else {
+            switch (auth_user->auth_data.ntlm_auth.auth_state){
+            case AUTHENTICATE_STATE_NONE:
+                debug(29, 5) ("authenticateFixErrorHeader: Sending type:%d header: 'NTLM'\n",type);
+                httpHeaderPutStrf(&rep->header, type, "NTLM");
+                /* drop the connection */
+                httpHeaderDelByName(&rep->header, "keep-alive");
+                /* NTLM has problems if the initial connection is not dropped
+                 I haven't checked the RFC compliance of this hack - RBCollins*/
+                request->flags.proxy_keepalive = 0;
+            break;
+            case AUTHENTICATE_STATE_CHALLENGE: 
+                /* we are 'waiting' for a response */
+                /* pass the challenge to the client */
+                debug(29, 5) ("authenticateFixErrorHeader: Sending type:%d header: 'NTLM %s'\n",type,auth_user->auth_data.ntlm_auth.authchallenge);
+                httpHeaderPutStrf(&rep->header, type, "NTLM %s", auth_user->auth_data.ntlm_auth.authchallenge);
+            break;
+            default:
+                debug(29,1)("authenticateFixErrorHeader: state %d.\n",auth_user->auth_data.ntlm_auth.auth_state);
+                fatal("unexpected state in AuthenticateFixErrorHeader.\n");
+            }
+        }
+    }
+}
+
 static stateful_helper_callback_t
 authenticateNTLMHandleReply(void *data, void * lastserver, char *reply)
 {
