diff -w -B -r -u -N squid-3.0.STABLE16/configure.in squid-3.0.STABLE16-krb5/configure.in
--- squid-3.0.STABLE16/configure.in	2009-06-15 08:31:33.000000000 +0100
+++ squid-3.0.STABLE16-krb5/configure.in	2009-08-01 16:22:49.000000000 +0100
@@ -1575,30 +1575,116 @@
 fi
 AC_SUBST(DIGEST_AUTH_HELPERS)
 
-if `echo "$NEGOTIATE_AUTH_HELPERS" | $EGREP "squid_kerb_auth|all" >/dev/null`; then
+old_CPPFLAGS=$CPPFLAGS
+old_LIBS=$LIBS
+AC_ARG_WITH(krb5-config,
+ [  --with-krb5-config=PATH specify path to krb5-config @<:@default=detect@:>@],
+ [if test x"$withval" = xyes; then
+     unset krb5confpath
+  elif test x"$withval" != xno; then
+     krb5confpath=$withval
+  else
+     krb5confpath=no
+  fi])
+
+if test x"$krb5confpath" != xno; then
+    if test x"$krb5confpath" != x; then
+        if ! test -x "$krb5confpath"; then
+            AC_MSG_WARN([krb5-config '$krb5confpath' not executable, ignoring])
+            AC_CHECK_PROG(ac_krb5_config, krb5-config, yes, no)
+            krb5confpath=krb5-config
+        fi
+        krb5_config_path=`dirname $krb5confpath`
+        AC_CHECK_PROG(ac_krb5_config, krb5-config, yes, no, $krb5_config_path)
+    else
     AC_CHECK_PROG(ac_krb5_config,krb5-config,yes,no)
+        krb5confpath=krb5-config
+    fi
+fi
+
     if test "x$ac_krb5_config" = "xyes" ; then
-       ac_heimdal=`krb5-config --version 2>/dev/null | grep -i heimdal`
-       ac_solaris=`krb5-config --version 2>/dev/null | grep -i solaris`
+    ac_heimdal=`$krb5confpath --version 2>/dev/null | grep -i heimdal`
+    ac_solaris=`$krb5confpath --version 2>/dev/null | grep -i solaris`
        if test "x$ac_heimdal" != "x" ; then
           AC_DEFINE(HAVE_HEIMDAL_KERBEROS,1,[Define to 1 if you have Heimdal Kerberos])
        else
           AC_DEFINE(HAVE_MIT_KERBEROS,1,[Define to 1 if you have MIT Kerberos])
        fi
        if test "x$ac_solaris" != "x" ; then
-          KRB5INCS="-I/usr/include/gssapi"
-          KRB5LIBS="-L/usr/lib -R/usr/lib -lgss -lresolv -lsocket -lnsl"
+        KRB5INCS=`$krb5confpath --cflags krb5 2>/dev/null`
+        KRB5LIBS=`$krb5confpath --libs krb5 2>/dev/null`
+        KRB5INCS="-I/usr/include/gssapi $KRB5INCS" 
+        KRB5LIBS="-L/usr/lib -R/usr/lib -lgss -lresolv -lsocket -lnsl $KRB5LIBS"
        else
-          KRB5INCS=`krb5-config --cflags gssapi 2>/dev/null` 
-          KRB5LIBS=`krb5-config --libs gssapi 2>/dev/null` 
-       fi
-       AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_krb5.h gssapi/gssapi_generic.h)
+        KRB5INCS=`$krb5confpath --cflags krb5 2>/dev/null`
+        KRB5LIBS=`$krb5confpath --libs krb5 2>/dev/null`
+        KRB5INCS="`$krb5confpath --cflags gssapi 2>/dev/null` $KRB5INCS"
+        KRB5LIBS="`$krb5confpath --libs gssapi 2>/dev/null` $KRB5LIBS"
     fi
-    old_CPPFLAGS=$CPPFLAGS
     CPPFLAGS="$CPPFLAGS $KRB5INCS"
-    old_LIBS=$LIBS
     LIBS="$LIBS $KRB5LIBS"
-    AC_CACHE_CHECK([for SPNEGO support],ac_cv_have_spnego,[
+    AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_krb5.h)
+    if test "x$ac_heimdal" == "x" ; then
+        AC_CHECK_HEADERS(gssapi/gssapi_generic.h)
+    fi
+    AC_CHECK_HEADERS(krb5.h com_err.h)
+    if test "x$ac_heimdal" == "x" ; then
+        AC_CHECK_HEADERS(profile.h)
+    fi
+    AC_CHECK_LIB(krb5,krb5_kt_free_entry,
+        AC_DEFINE(HAVE_KRB5_KT_FREE_ENTRY,1,[Define to 1 if you have krb5_kt_free_entry]),)
+    AC_CHECK_LIB(krb5,krb5_get_init_creds_keytab,
+        AC_DEFINE(HAVE_GET_INIT_CREDS_KEYTAB,1,[Define to 1 if you have krb5_get_init_creds_keytab]),)
+    AC_CHECK_LIB(krb5,krb5_get_max_time_skew,
+        AC_DEFINE(HAVE_KRB5_GET_MAX_TIME_SKEW,1,[Define to 1 if you have krb5_get_max_time_skew]),)
+    AC_MSG_CHECKING([for memory cache])
+    AC_TRY_RUN([
+#include<krb5.h>
+main()
+{
+    krb5_context context;
+    krb5_ccache cc;
+
+    krb5_init_context(&context);
+    return krb5_cc_resolve(context, "MEMORY:test_cache", &cc);
+}],
+    [AC_DEFINE(HAVE_KRB5_MEMORY_CACHE,1, [Define to 1 if you have MEMORY: cache support])
+     AC_MSG_RESULT(yes)],
+    AC_MSG_RESULT(no))
+
+    AC_MSG_CHECKING([for working gssapi])
+    AC_TRY_RUN([
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+
+#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+
+#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+int
+main(void)
+{
+        OM_uint32 val;
+        gss_OID_set set;
+
+        gss_create_empty_oid_set(&val, &set);
+
+        return 0;
+}
+],  [AC_DEFINE(HAVE_GSSAPI, 1, [GSSAPI support])
+     AC_MSG_RESULT(yes)],
+    AC_MSG_RESULT(no))
+    AC_MSG_CHECKING([for spnego support])
     AC_TRY_RUN([
 #ifdef HAVE_HEIMDAL_KERBEROS
 #ifdef HAVE_GSSAPI_GSSAPI_H
@@ -1638,13 +1724,31 @@
 
  return 1;
 }],
-  ac_cv_have_spnego=yes,
-  ac_cv_have_spnego=no)])
+    [ac_cv_have_spnego=yes
+     AC_DEFINE(HAVE_SPNEGO,1, [Define to 1 if you have SPNEGO support])   
+     AC_MSG_RESULT(yes)],
+    [ac_cv_have_spnego=no
+     AC_MSG_RESULT(no)])
+    AC_MSG_CHECKING([for working krb5])
+    AC_TRY_RUN([
+#ifdef HAVE_KRB5_H
+#include <krb5.h>
+#endif
+
+int
+main(void)
+{
+        krb5_context context;
+
+        krb5_init_context(&context);
+
+        return 0;
+}
+],  [AC_DEFINE(HAVE_KRB5, 1, [KRB5 support])
+     AC_MSG_RESULT(yes)],
+    AC_MSG_RESULT(no))
   LIBS=$old_LIBS
   CPPFLAGS=$old_CPPFLAGS
-  if test x"$ac_cv_have_spnego" = x"yes"; then
-    AC_DEFINE(HAVE_SPNEGO,1, [Define to 1 if you have SPNEGO support])
-  fi
   AC_SUBST(KRB5INCS)
   AC_SUBST(KRB5LIBS)
 fi
diff -w -B -r -u -N squid-3.0.STABLE16/src/http.cc squid-3.0.STABLE16-krb5/src/http.cc
--- squid-3.0.STABLE16/src/http.cc	2009-06-15 08:31:31.000000000 +0100
+++ squid-3.0.STABLE16-krb5/src/http.cc	2009-07-26 12:26:46.000000000 +0100
@@ -1464,6 +1464,14 @@
             }
         } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
             /* Nothing to do */
+#if HAVE_KRB5 && HAVE_GSSAPI 
+        } else if (strcmp(orig_request->peer_login, "NEGOTIATE") == 0) {
+             char *Token;
+             Token = peer_proxy_negotiate_auth(NULL,request->peer_host);
+             if (Token) {
+               httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Negotiate %s",Token);
+             }
+#endif /* HAVE_KRB5 && HAVE_GSSAPI */
         } else {
             httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
                               base64_encode(orig_request->peer_login));
@@ -1800,6 +1808,7 @@
     }
 
     mb.init();
+    request->peer_host=_peer?_peer->host:NULL;
     buildRequestPrefix(request, orig_request, entry, &mb, flags);
     debugs(11, 6, "httpSendRequest: FD " << fd << ":\n" << mb.buf);
     comm_write_mbuf(fd, &mb, requestSender, this);
diff -w -B -r -u -N squid-3.0.STABLE16/src/HttpRequest.h squid-3.0.STABLE16-krb5/src/HttpRequest.h
--- squid-3.0.STABLE16/src/HttpRequest.h	2009-06-15 08:31:28.000000000 +0100
+++ squid-3.0.STABLE16-krb5/src/HttpRequest.h	2009-07-25 15:11:18.000000000 +0100
@@ -114,6 +114,8 @@
 
     char *peer_login;		/* Configured peer login:password */
 
+    char *peer_host;           /* Selected peer host*/
+
     time_t lastmod;		/* Used on refreshes */
 
     const char *vary_headers;	/* Used when varying entities are detected. Changes how the store key is calculated */
diff -w -B -r -u -N squid-3.0.STABLE16/src/Makefile.am squid-3.0.STABLE16-krb5/src/Makefile.am
--- squid-3.0.STABLE16/src/Makefile.am	2009-06-15 08:31:28.000000000 +0100
+++ squid-3.0.STABLE16-krb5/src/Makefile.am	2009-07-26 00:25:33.000000000 +0100
@@ -195,6 +195,7 @@
 
 INCLUDES        = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/lib/libTrie/include
 INCLUDES	+= @SQUID_CPPUNIT_INC@
+INCLUDES	+= @KRB5INCS@ 
 
 EXTRA_PROGRAMS = \
 	DiskIO/DiskDaemon/diskd \
@@ -559,6 +560,7 @@
 	$(SNMP_SOURCE) \
 	squid.h \
 	SquidNew.cc \
+        peer_proxy_negotiate_auth.cc \
 	$(SSL_SOURCE) \
 	stat.cc \
 	StatHist.cc \
@@ -667,7 +669,8 @@
 	-lmiscutil \
 	@XTRA_LIBS@ \
 	@EPOLL_LIBS@ \
-	@MINGW_LIBS@ 
+	@MINGW_LIBS@ \
+	@KRB5LIBS@ 
 squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \
 	@STORE_OBJS@ \
 	@STORE_LINKOBJS@ \
@@ -854,6 +857,7 @@
 	send-announce.cc \
 	$(SNMP_SOURCE) \
 	squid.h \
+        peer_proxy_negotiate_auth.cc \
 	$(SSL_SOURCE) \
 	tunnel.cc \
 	Server.cc \
@@ -903,7 +907,8 @@
 	-L$(top_builddir)/lib -lmiscutil \
 	@XTRA_LIBS@ \
 	@EPOLL_LIBS@ \
-	@MINGW_LIBS@ 
+	@MINGW_LIBS@ \
+	@KRB5LIBS@ 
 ufsdump_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \
 	@STORE_OBJS@ \
 	@STORE_LINKOBJS@ \
diff -w -B -r -u -N squid-3.0.STABLE16/src/peer_proxy_negotiate_auth.cc squid-3.0.STABLE16-krb5/src/peer_proxy_negotiate_auth.cc
--- squid-3.0.STABLE16/src/peer_proxy_negotiate_auth.cc	1970-01-01 01:00:00.000000000 +0100
+++ squid-3.0.STABLE16-krb5/src/peer_proxy_negotiate_auth.cc	2009-08-01 16:23:18.000000000 +0100
@@ -0,0 +1,473 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * Author: Markus Moeller (markus_moeller at compuserve.com)
+ *
+ * Copyright (C) 2007 Markus Moeller. All rights reserved.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * -----------------------------------------------------------------------------
+ */
+/*
+ * Hosted at http://sourceforge.net/projects/squidkerbauth
+ */
+
+#include <squid.h>
+
+#if HAVE_KRB5 && HAVE_GSSAPI
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if HAVE_PROFILE_H
+#include <profile.h>
+#endif /* HAVE_PROFILE_H */
+#if HAVE_KRB5_H
+#include <krb5.h>
+#endif /* HAVE_KRB5_H */
+#if HAVE_COM_ERR_H
+#include <com_err.h>
+#endif /* HAVE_COM_ERR_H */
+
+#if HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif /* HAVE_GSSAPI_H */
+#if HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif /* HAVE_GSSAPI_GSSAPI_EXT_H */
+#if HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif /* HAVE_GSSAPI_GSSAPI_KRB5_H */
+#if HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif /* HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+#ifndef gss_nt_service_name
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#endif
+
+#if HAVE_HEIMDAL_KERBEROS
+#define error_message(code) krb5_get_err_text(kparam.context,code)
+#endif
+
+#ifndef gss_mech_spnego
+static gss_OID_desc _gss_mech_spnego  = {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
+gss_OID gss_mech_spnego = &_gss_mech_spnego;
+#endif
+
+#if HAVE_NAS_KERBEROS
+#include <ibm_svc/krb5_svc.h>
+const char *KRB5_CALLCONV error_message(long code) {
+ char *msg=NULL;
+ krb5_svc_get_msg(code,&msg);
+ return msg;
+}
+#endif
+
+static struct kstruct {
+  krb5_context context;
+  char* mem_cache_env;
+  krb5_ccache cc;
+} kparam = {NULL, NULL, NULL};
+
+int krb5_create_cache(char* keytab_filename, char* principal_name);
+void krb5_cleanup(void);
+
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function);
+
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function){
+  if (GSS_ERROR(major_status)) {
+    OM_uint32 maj_stat,min_stat;
+    OM_uint32 msg_ctx = 0;
+    gss_buffer_desc status_string;
+    char buf[1024];
+    size_t len;
+
+    len = 0;
+    msg_ctx = 0;
+    while (!msg_ctx) {
+      /* convert major status code (GSS-API error) to text */
+      maj_stat = gss_display_status(&min_stat, major_status,
+                                    GSS_C_GSS_CODE,
+                                    GSS_C_NULL_OID,
+                                    &msg_ctx, &status_string);
+      if (maj_stat == GSS_S_COMPLETE) {
+        if (sizeof(buf) > len + status_string.length + 1) {
+          memcpy(buf+len, status_string.value, status_string.length);
+          len += status_string.length;
+        }
+        gss_release_buffer(&min_stat, &status_string);
+        break;
+      }
+      gss_release_buffer(&min_stat, &status_string);
+    }
+    if (sizeof(buf) > len + 2) {
+      strcpy(buf+len, ". ");
+      len += 2;
+    }
+    msg_ctx = 0;
+    while (!msg_ctx) {
+      /* convert minor status code (underlying routine error) to text */
+      maj_stat = gss_display_status(&min_stat, minor_status,
+                                    GSS_C_MECH_CODE,
+                                    GSS_C_NULL_OID,
+                                    &msg_ctx, &status_string);
+      if (maj_stat == GSS_S_COMPLETE) {
+        if (sizeof(buf) > len + status_string.length ) {
+          memcpy(buf+len, status_string.value, status_string.length);
+          len += status_string.length;
+        }
+        gss_release_buffer(&min_stat, &status_string);
+        break;
+      }
+      gss_release_buffer(&min_stat, &status_string);
+    }
+    debugs(11, 5, HERE << function << "failed: " << buf);
+    return(1);
+  }
+  return(0);
+}
+
+void krb5_cleanup() {
+    debugs(11, 5, HERE << "Cleanup kerberos context");
+    if (kparam.context) {
+        if (kparam.cc)
+            krb5_cc_destroy(kparam.context,kparam.cc);
+        kparam.cc=NULL;
+        krb5_free_context(kparam.context);
+        kparam.context=NULL;
+        if (kparam.mem_cache_env)
+            xfree(kparam.mem_cache_env);
+        kparam.mem_cache_env=NULL;
+    }
+}
+
+int krb5_create_cache(char* kf, char* pn){
+
+#define KT_PATH_MAX 256
+#define MAX_RENEW_TIME "365d"
+
+  static char *keytab_filename=NULL, *principal_name=NULL;
+  static krb5_keytab	keytab = 0;
+  static krb5_keytab_entry entry;
+  static krb5_kt_cursor cursor;
+  static krb5_creds	*creds=NULL;
+#if HAVE_HEIMDAL_KERBEROS
+  static krb5_creds	creds2;
+#endif
+  static krb5_principal principal = NULL;
+  static krb5_deltat	skew;
+
+  krb5_get_init_creds_opt 	options;
+  krb5_error_code 		code = 0;
+  krb5_deltat			rlife;
+#if HAVE_PROFILE_H
+  profile_t                     profile;
+#else
+  krb5_kdc_flags 		flags;
+  krb5_realm 			*client_realm;
+#endif
+  char* mem_cache;
+
+restart:
+  if (creds &&
+     (creds->times.endtime - time(0) > skew) &&
+     (creds->times.renew_till - time(0) > 2*skew))
+    {
+      if (creds->times.endtime - time(0) < 2*skew)
+        {
+#if !HAVE_HEIMDAL_KERBEROS
+           /* renew ticket */
+           code = krb5_get_renewed_creds(kparam.context, creds, principal, kparam.cc, NULL);
+#else
+           /* renew ticket */
+           flags.i = 0;
+           flags.b.renewable = flags.b.renew = 1;
+
+           code = krb5_cc_get_principal(kparam.context, kparam.cc, &creds2.client);
+           if (code)
+             {
+                debugs(11, 5, HERE << "Error while getting principal from credential cache : " << error_message(code));
+                return(1) ;
+             }
+           client_realm = krb5_princ_realm (kparam.context, creds2.client);
+           code = krb5_make_principal(kparam.context, &creds2.server, *client_realm,
+                               KRB5_TGS_NAME, *client_realm, NULL);
+           if (code)
+             {
+                debugs(11, 5, HERE << "Error while getting krbtgt principal : " << error_message(code));
+                return(1) ;
+             }
+           code = krb5_get_kdc_cred(kparam.context, kparam.cc, flags, NULL, NULL, &creds2, &creds);
+#endif
+           if (code)
+             {
+                if ( code == KRB5KRB_AP_ERR_TKT_EXPIRED ) 
+                  {
+                     creds=NULL;
+                     /* this can happen because of clock skew */
+                     goto restart;
+                  }
+                  debugs(11, 5, HERE << "Error while get credentials : " << error_message(code));
+                  return(1) ;
+             }
+        } 
+    } 
+  else
+    {
+      /* reinit */
+      if (!kparam.context)
+        {
+          code = krb5_init_context(&kparam.context);
+          if (code)
+            {
+              debugs(11, 5, HERE << "Error while initialising Kerberos library : " << error_message(code));
+              return(1) ;
+            }
+          kparam.mem_cache_env=NULL;
+        }
+
+#if HAVE_PROFILE_H
+      code = krb5_get_profile (kparam.context, &profile);
+      if (code)
+        {
+           if (profile)
+              profile_release(profile);
+           debugs(11, 5, HERE << "Error while getting profile : " << error_message(code));
+           return(1) ;
+        }
+      code = profile_get_integer(profile, "libdefaults", "clockskew", 0, 5 * 60, &skew);
+      if (profile)
+         profile_release(profile);
+      if (code)
+        {
+           debugs(11, 5, HERE << "Error while getting clockskew : " << error_message(code));
+           return(1) ;
+        }
+#else
+#if HAVE_KRB5_GET_MAX_TIME_SKEW      
+      skew=krb5_get_max_time_skew(kparam.context);
+#else
+      skew=kparam.context->max_skew;
+#endif
+#endif
+
+      if (!kf) 
+        {
+           char      buf[KT_PATH_MAX], *p;
+
+           krb5_kt_default_name(kparam.context, buf, KT_PATH_MAX);
+           p = strchr(buf, ':');            
+           if (p) p++;
+           if (keytab_filename)
+               xfree(keytab_filename);                       
+           keytab_filename = strdup(p ? p : buf);
+        }
+      else {
+          keytab_filename = strdup(kf); 
+        }
+
+      code = krb5_kt_resolve(kparam.context, keytab_filename, &keytab);
+      if (code)
+        {
+           debugs(11, 5, HERE << "Error while resolving keytab filename " << keytab_filename << " : " << error_message(code));
+           return(1);
+        }
+
+      if (!pn)
+        {
+           code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor);
+           if (code)
+             {
+                 debugs(11, 5, HERE << "Error while starting keytab scan : " << error_message(code));
+                 return(1);
+             }
+           code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor);
+           krb5_copy_principal(kparam.context,entry.principal,&principal);
+           if (code && code != KRB5_KT_END)
+             {
+                 debugs(11, 5, HERE << "Error while scanning keytab : " << error_message(code));
+                 return(1);
+             }
+
+           code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor);
+           if (code)
+             {
+                 debugs(11, 5, HERE << "Error while ending keytab scan : " << error_message(code));
+                return(1);
+             }
+#if HAVE_HEIMDAL_KERBEROS || ( HAVE_KRB5_KT_FREE_ENTRY && HAVE_DECL_KRB5_KT_FREE_ENTRY)
+           code = krb5_kt_free_entry(kparam.context,&entry);
+#else
+           code = krb5_free_keytab_entry_contents(kparam.context,&entry);
+#endif
+           if (code)
+           {
+               debugs(11, 5, HERE << "Error while freeing keytab entry : " << error_message(code));
+               return(1);
+           }
+
+        }
+      else {
+           principal_name=strdup(pn);
+        }
+
+      if (!principal) 
+        {
+           code = krb5_parse_name(kparam.context, principal_name, &principal);
+           if (code)
+             {
+                debugs(11, 5, HERE << "Error while parsing principal name " << principal_name << " : " << error_message(code));
+                return (1);
+             }
+        }
+
+      creds = (krb5_creds *)xmalloc(sizeof(*creds));
+      memset(creds, 0, sizeof(*creds));
+      krb5_get_init_creds_opt_init(&options);
+      code = krb5_string_to_deltat((char *)MAX_RENEW_TIME, &rlife);
+      if (code != 0 || rlife == 0)
+        {
+           debugs(11, 5, HERE << "Error bad lifetime value " << MAX_RENEW_TIME << " : " << error_message(code));
+           return (1);
+        }
+      krb5_get_init_creds_opt_set_renew_life(&options, rlife);
+          
+      code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, &options);
+      if (code)
+        {
+           debugs(11, 5, HERE << "Error while initializing credentials from keytab : " << error_message(code));
+           return (1);
+        }
+
+#if !HAVE_KRB5_MEMORY_CACHE
+      mem_cache=(char *)xmalloc(strlen("FILE:/tmp/squid_proxy_auth_")+16);
+      snprintf(mem_cache,strlen("FILE:/tmp/squid_proxy_auth_")+16,"FILE:/tmp/squid_proxy_auth_%d",getpid());
+#else
+      mem_cache=(char *)xmalloc(strlen("MEMORY:squid_proxy_auth_")+16);
+      snprintf(mem_cache,strlen("MEMORY:squid_proxy_auth_")+16,"MEMORY:squid_proxy_auth_%d",getpid());
+#endif
+
+      kparam.mem_cache_env=(char *)xmalloc(strlen("KRB5CCNAME=")+strlen(mem_cache)+1);
+      strcpy(kparam.mem_cache_env,"KRB5CCNAME=");
+      strcat(kparam.mem_cache_env,mem_cache);
+      putenv(kparam.mem_cache_env);
+      code = krb5_cc_resolve(kparam.context, mem_cache , &kparam.cc);
+      if (mem_cache)
+          xfree(mem_cache);
+      if (code) 
+        {
+           debugs(11, 5, HERE << "Error while resolving memory credential cache : " << error_message(code));
+           return(1) ;
+        }
+      code = krb5_cc_initialize(kparam.context, kparam.cc, principal);
+      if (code) 
+        {
+           debugs(11, 5, HERE << "Error while initializing memory credential cache : " << error_message(code));
+           return(1) ;
+        }
+      code = krb5_cc_store_cred(kparam.context, kparam.cc, creds);
+      if (code) 
+        {
+           debugs(11, 5, HERE << "Error while storing credentials : " << error_message(code));
+           return(1) ;
+        }
+
+      if (!creds->times.starttime) 
+        creds->times.starttime = creds->times.authtime;
+    }
+    return(0);
+}
+
+char *peer_proxy_negotiate_auth(char* principal_name, char *proxy) {
+ int rc=0;
+ OM_uint32 major_status, minor_status;
+ gss_ctx_id_t          gss_context = GSS_C_NO_CONTEXT;
+ gss_name_t            server_name = GSS_C_NO_NAME;
+ gss_buffer_desc       service = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc       input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc       output_token = GSS_C_EMPTY_BUFFER;
+ char   *token = NULL;
+
+  setbuf(stdout,NULL);
+  setbuf(stdin,NULL);
+
+  if (!proxy ) {
+     debugs(11, 5, HERE << "Error : No proxy server name");
+     return NULL;
+  }
+
+  debugs(11, 5, HERE << "Creating credential cache");
+  rc = krb5_create_cache(NULL,principal_name);
+  if (rc) {
+     debugs(11, 5, HERE << "Error : Failed to create Kerberos cache");
+     krb5_cleanup();
+     return NULL;
+  }
+
+  service.value = (void *)xmalloc(strlen("HTTP")+strlen(proxy)+2);
+  snprintf((char *)service.value,strlen("HTTP")+strlen(proxy)+2,"%s@%s","HTTP",proxy);
+  service.length = strlen((char *)service.value);
+ 
+  debugs(11, 5, HERE << "Import gss name");
+  major_status = gss_import_name(&minor_status, &service,
+                                 gss_nt_service_name, &server_name);
+ 
+  if (check_gss_err(major_status,minor_status,"gss_import_name()") )
+      goto cleanup;
+
+  debugs(11, 5, HERE << "Initialize gss security context");
+  major_status = gss_init_sec_context(&minor_status,
+                                      GSS_C_NO_CREDENTIAL,
+                                      &gss_context,
+                                      server_name,
+                                      gss_mech_spnego,
+                                      0,
+                                      0,
+                                      GSS_C_NO_CHANNEL_BINDINGS,
+                                      &input_token,
+                                      NULL,
+                                      &output_token,
+                                      NULL,
+                                      NULL);
+
+  if (check_gss_err(major_status,minor_status,"gss_init_sec_context()") )
+      goto cleanup;
+
+  debugs(11, 5, HERE << "Got token with length" << output_token.length);
+  if (output_token.length) {
+
+      token = (char *)base64_encode_bin((const char*)output_token.value,output_token.length);
+  } 
+
+
+cleanup:
+  gss_delete_sec_context(&minor_status, &gss_context, NULL);
+  gss_release_buffer(&minor_status, &service);
+  gss_release_buffer(&minor_status, &input_token);
+  gss_release_buffer(&minor_status, &output_token);
+  gss_release_name(&minor_status, &server_name);
+
+  return token; 
+}
+#ifdef __cplusplus
+}
+#endif
+#endif /* HAVE_KRB5 && HAVE_GSSAPI */
+
diff -w -B -r -u -N squid-3.0.STABLE16/src/protos.h squid-3.0.STABLE16-krb5/src/protos.h
--- squid-3.0.STABLE16/src/protos.h	2009-06-15 08:31:32.000000000 +0100
+++ squid-3.0.STABLE16-krb5/src/protos.h	2009-07-26 00:05:04.000000000 +0100
@@ -822,4 +822,5 @@
 
 #endif
 
+SQUIDCEXTERN char *peer_proxy_negotiate_auth(char *principal_name, char *proxy);
 #endif /* SQUID_PROTOS_H */
diff -w -B -r -u -N squid-3.0.STABLE16/src/tunnel.cc squid-3.0.STABLE16-krb5/src/tunnel.cc
--- squid-3.0.STABLE16/src/tunnel.cc	2009-06-15 08:31:33.000000000 +0100
+++ squid-3.0.STABLE16-krb5/src/tunnel.cc	2009-07-25 16:01:09.000000000 +0100
@@ -740,6 +740,7 @@
 
     tunnelState->servers = fs;
     tunnelState->host = fs->_peer ? fs->_peer->host : request->host;
+    request->peer_host = fs->_peer ? fs->_peer->host : NULL;
 
     if (fs->_peer == NULL) {
         tunnelState->port = request->port;

