diff -rubwBEN 3.4/configure.ac 3.4-mm/configure.ac
--- 3.4/configure.ac	2013-08-12 00:01:44.458703000 +0100
+++ 3.4-mm/configure.ac	2013-08-23 13:15:58.440167017 +0100
@@ -1,4 +1,4 @@
-AC_INIT([Squid Web Proxy],[3.4.0.1-BZR],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[3.4.0.1],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
@@ -1924,6 +1924,21 @@
   AC_CHECK_LIB(krb5,profile_release,
     AC_DEFINE(HAVE_PROFILE_RELEASE,1,
       [Define to 1 if you have profile_release]),)
+  AC_CHECK_LIB(krb5,krb5_get_renewed_creds,
+    AC_DEFINE(HAVE_KRB5_GET_RENEWED_CREDS,1,
+      [Define to 1 if you have krb5_get_renewed_creds]),)
+  AC_CHECK_LIB(krb5,krb5_principal_get_realm,
+    AC_DEFINE(HAVE_KRB5_PRINCIPAL_GET_REALM,1,
+      [Define to 1 if you have krb5_principal_get_realm]),)
+  AC_CHECK_LIB(krb5, krb5_get_init_creds_opt_alloc,
+    AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC,1,
+      [Define to 1 if you have krb5_get_init_creds_opt_alloc]),)
+  AC_CHECK_FUNCS(gss_map_name_to_any,
+    AC_DEFINE(HAVE_GSS_MAP_ANY_TO_ANY,1,
+      [Define to 1 if you have gss_map_name_to_any]),)
+  AC_CHECK_FUNCS(gsskrb5_extract_authz_data_from_sec_context,
+    AC_DEFINE(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT,1,
+      [Define to 1 if you have gsskrb5_extract_authz_data_from_sec_context]),)
 
   SQUID_CHECK_KRB5_CONTEXT_MEMORY_CACHE
   SQUID_DEFINE_BOOL(HAVE_KRB5_MEMORY_CACHE,$squid_cv_memory_cache,
diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/Makefile.am 3.4-mm/helpers/negotiate_auth/kerberos/Makefile.am
--- 3.4/helpers/negotiate_auth/kerberos/Makefile.am	2013-08-12 00:01:44.458703000 +0100
+++ 3.4-mm/helpers/negotiate_auth/kerberos/Makefile.am	2013-08-23 13:16:29.677167792 +0100
@@ -7,7 +7,7 @@
 
 AM_CPPFLAGS = $(INCLUDES) -I$(srcdir)
 
-negotiate_kerberos_auth_SOURCES = negotiate_kerberos_auth.cc
+negotiate_kerberos_auth_SOURCES = negotiate_kerberos_auth.cc negotiate_kerberos_pac.cc
 negotiate_kerberos_auth_LDFLAGS = 
 negotiate_kerberos_auth_LDADD = \
 	$(top_builddir)/lib/libmiscencoding.la \
diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc
--- 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc	2013-08-12 00:01:44.458703000 +0100
+++ 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc	2013-08-23 13:16:44.061168148 +0100
@@ -36,79 +36,7 @@
 
 #if HAVE_GSSAPI
 
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_STDOI_H
-#include <stdio.h>
-#endif
-#if HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_TIME_H
-#include <time.h>
-#endif
-
-#include "util.h"
-#include "base64.h"
-
-#if HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#elif HAVE_GSSAPI_H
-#include <gssapi.h>
-#endif
-
-#if !HAVE_HEIMDAL_KERBEROS
-#if HAVE_GSSAPI_GSSAPI_KRB5_H
-#include <gssapi/gssapi_krb5.h>
-#endif
-#if HAVE_GSSAPI_GSSAPI_GENERIC_H
-#include <gssapi/gssapi_generic.h>
-#endif
-#if HAVE_GSSAPI_GSSAPI_EXT_H
-#include <gssapi/gssapi_ext.h>
-#endif
-#endif
-
-#ifndef gss_nt_service_name
-#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
-#endif
-
-#define PROGRAM "negotiate_kerberos_auth"
-
-#ifndef MAX_AUTHTOKEN_LEN
-#define MAX_AUTHTOKEN_LEN   65535
-#endif
-#ifndef SQUID_KERB_AUTH_VERSION
-#define SQUID_KERB_AUTH_VERSION "3.0.4sq"
-#endif
-
-int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
-                  const char *function, int log);
-char *gethost_name(void);
-static const char *LogTime(void);
-
-static const unsigned char ntlmProtocol[] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};
-
-static const char *
-LogTime()
-{
-    struct tm *tm;
-    struct timeval now;
-    static time_t last_t = 0;
-    static char buf[128];
-
-    gettimeofday(&now, NULL);
-    if (now.tv_sec != last_t) {
-        tm = localtime((time_t *) & now.tv_sec);
-        strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
-        last_t = now.tv_sec;
-    }
-    return buf;
-}
+#include "negotiate_kerberos.h"
 
 char *
 gethost_name(void)
@@ -213,6 +141,19 @@
     char buf[MAX_AUTHTOKEN_LEN];
     char *c, *p;
     char *user = NULL;
+    char *rfc_user = NULL;
+#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY)
+    char ad_groups[MAX_PAC_GROUP_SIZE];
+    char *ag=NULL;
+    krb5_context context = NULL;
+    krb5_error_code ret;
+    krb5_pac pac;
+#if HEIMDAL
+    gss_buffer_desc data_set = GSS_C_EMPTY_BUFFER;
+#else
+    gss_buffer_desc type_id = GSS_C_EMPTY_BUFFER;
+#endif
+#endif
     int length = 0;
     static int err = 0;
     int opt, log = 0, norealm = 0;
@@ -284,6 +225,8 @@
         snprintf((char *) service.value, strlen(service_name) + strlen(host_name) + 2,
                  "%s@%s", service_name, host_name);
         service.length = strlen((char *) service.value);
+        xfree(host_name);
+        host_name = NULL;
     }
 
     while (1) {
@@ -351,10 +294,6 @@
                 xfree(token);
                 token = NULL;
             }
-            if (host_name) {
-                xfree(host_name);
-                host_name = NULL;
-            }
             fprintf(stdout, "BH quit command\n");
             exit(0);
         }
@@ -458,8 +397,44 @@
             if (norealm && (p = strchr(user, '@')) != NULL) {
                 *p = '\0';
             }
+
+#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY)
+	    ret = krb5_init_context(&context);
+	    if (!check_k5_err(context, "krb5_init_context", ret)) {
+#define ADWIN2KPAC 128
+#if HEIMDAL
+		major_status = gsskrb5_extract_authz_data_from_sec_context(&minor_status, 
+				gss_context, ADWIN2KPAC, &data_set);
+		if (!check_gss_err(major_status, minor_status, 
+				"gsskrb5_extract_authz_data_from_sec_context()", log)) {
+		    ret = krb5_pac_parse(context, data_set.value, data_set.length, &pac);
+		    gss_release_buffer(&minor_status, &data_set);
+		    if (!check_k5_err(context, "krb5_pac_parse", ret)) {
+			ag = get_ad_groups((char *)&ad_groups, context, pac);
+			krb5_pac_free(context, pac);
+		    }
+		    krb5_free_context(context);
+		}
+#else
+		type_id.value = (void *)"mspac";
+		type_id.length = strlen((char *)type_id.value);
+
+		major_status = gss_map_name_to_any(&minor_status, client_name, 1, &type_id, (gss_any_t *)&pac);
+		if (!check_gss_err(major_status, minor_status, "gss_map_name_to_any()", log)) {
+		    ag = get_ad_groups((char *)&ad_groups,context, pac);
+		}
+		(void)gss_release_any_name_mapping(&minor_status, client_name, &type_id, (gss_any_t *)&pac);
+		krb5_free_context(context);
+#endif
+	    }
+	    if (ag) {
+		debug((char *) "%s| %s: DEBUG: Groups %s\n", LogTime(), PROGRAM, ag);
+	    }
+#endif
             fprintf(stdout, "AF %s %s\n", token, user);
-            debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc1738_escape(user));
+	    rfc_user = rfc1738_escape(user);
+            debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc_user);
+	    xfree(rfc_user);
             if (log)
                 fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
                         PROGRAM, rfc1738_escape(user));
diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos.h 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos.h
--- 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos.h	1970-01-01 01:00:00.000000000 +0100
+++ 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos.h	2013-08-23 13:16:44.088168149 +0100
@@ -0,0 +1,154 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * Author: Markus Moeller (markus_moeller at compuserve.com)
+ *
+ * Copyright (C) 2013 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.
+ *
+ *   As a special exemption, M Moeller gives permission to link this program
+ *   with MIT, Heimdal or other GSS/Kerberos libraries, and distribute
+ *   the resulting executable, without including the source code for
+ *   the Libraries in the source distribution.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include "util.h"
+#include "base64.h"
+
+#if HAVE_KRB5_H
+#if HAVE_BROKEN_SOLARIS_KRB5_H
+#warn "Warning! You have a broken Solaris <krb5.h> system header"
+#warn "http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6837512"
+#if defined(__cplusplus)
+#define KRB5INT_BEGIN_DECLS     extern "C" {
+#define KRB5INT_END_DECLS
+KRB5INT_BEGIN_DECLS
+#endif
+#endif /* HAVE_BROKEN_SOLARIS_KRB5_H */
+#if HAVE_BROKEN_HEIMDAL_KRB5_H
+extern "C" {
+#include <krb5.h>
+}
+#else
+#include <krb5.h>
+#endif
+#endif /* HAVE_KRB5_H */
+
+#if HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+
+#if !HAVE_HEIMDAL_KERBEROS
+#if HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+#if HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+#if HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#else
+#if HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi_krb5.h>
+#endif
+#endif
+
+#ifndef gss_nt_service_name
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#endif
+
+#define PROGRAM "negotiate_kerberos_auth"
+
+#ifndef MAX_AUTHTOKEN_LEN
+#define MAX_AUTHTOKEN_LEN   65535
+#endif
+#ifndef SQUID_KERB_AUTH_VERSION
+#define SQUID_KERB_AUTH_VERSION "3.0.4sq"
+#endif
+
+typedef struct {
+    uint16_t length;
+    uint16_t maxlength;
+    uint32_t pointer;
+} RPC_UNICODE_STRING;
+
+char *gethost_name(void);
+
+static const char *LogTime(void);
+
+static const unsigned char ntlmProtocol[] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};
+
+static const char *
+LogTime()
+{
+    struct tm *tm;
+    struct timeval now;
+    static time_t last_t = 0;
+    static char buf[128];
+
+    gettimeofday(&now, NULL);
+    if (now.tv_sec != last_t) {
+        tm = localtime((time_t *) & now.tv_sec);
+        strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
+        last_t = now.tv_sec;
+    }
+    return buf;
+}
+
+int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
+                  const char *function, int log);
+
+int check_k5_err(krb5_context context, const char *msg, krb5_error_code code);
+
+char *gethost_name(void);
+
+#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY)
+#define MAX_PAC_GROUP_SIZE 200*60
+void align(int n);
+void getustr(RPC_UNICODE_STRING *string);
+char **getgids(char **Rids, uint32_t GroupIds, uint32_t GroupCount);
+char *getdomaingids(char *ad_groups, uint32_t DomainLogonId, char **Rids, uint32_t  GroupCount);
+char *getextrasids(char *ad_groups, uint32_t ExtraSids, uint32_t SidCount, uint32_t GroupCount);
+uint64_t get6byt_be(void);
+uint32_t get4byt(void);
+uint16_t get2byt(void);
+uint8_t get1byt(void);
+char *xstrcpy( char *src, const char*dst);
+char *xstrcat( char *src, const char*dst);
+int checkustr(RPC_UNICODE_STRING *string);
+char *get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac);
+#endif
diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc
--- 3.4/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc	1970-01-01 01:00:00.000000000 +0100
+++ 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc	2013-08-23 13:16:44.088168149 +0100
@@ -0,0 +1,450 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *   As a special exemption, M Moeller gives permission to link this program
+ *   with MIT, Heimdal or other GSS/Kerberos libraries, and distribute
+ *   the resulting executable, without including the source code for
+ *   the Libraries in the source distribution.
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+#include "squid.h"
+#include "rfc1738.h"
+#include "compat/getaddrinfo.h"
+#include "compat/getnameinfo.h"
+
+#if defined(HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT) || defined(HAVE_GSS_MAP_NAME_TO_ANY)
+
+#include "negotiate_kerberos.h"
+
+static int bpos;
+static krb5_data *ad_data;
+static unsigned char *p;
+
+int
+check_k5_err(krb5_context context, const char *function, krb5_error_code code)
+{
+    const char *errmsg;
+
+    if (code) {
+	errmsg = krb5_get_error_message(context, code);
+        debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, errmsg);
+	fprintf(stderr, "%s| %s: ERROR: %s: %s\n", LogTime(), PROGRAM, function, errmsg);
+	krb5_free_error_message(context, errmsg);
+    }
+    return code;
+}
+
+void
+align(int n){
+    if ( bpos % n != 0 ) {
+	int al;
+	al = (bpos/n);
+	bpos = bpos+(bpos-n*al);
+    }
+}
+
+void
+getustr(RPC_UNICODE_STRING *string) {
+
+    string->length = (p[bpos]<<0) | (p[bpos+1]<<8);
+    string->maxlength = (p[bpos+2]<<0) | (p[bpos+2+1]<<8);
+    string->pointer = (p[bpos+4]<<0) | (p[bpos+4+1]<<8) | (p[bpos+4+2]<<16) | (p[bpos+4+3]<<24);
+    bpos = bpos+8;
+
+}
+
+uint64_t
+get6byt_be(void) {
+    uint64_t var;
+
+    var = ((int64_t)p[bpos+5]<<0) | ((int64_t)p[bpos+4]<<8) | ((int64_t)p[bpos+3]<<16) | ((int64_t)p[bpos+2]<<24) | ((int64_t)p[bpos+1]<<32) | ((int64_t)p[bpos]<<40);
+    bpos = bpos+6;
+
+    return var;
+}
+
+uint32_t
+get4byt(void) {
+    uint32_t var;
+
+    var=(p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24);
+    bpos = bpos+4;
+
+    return var;
+}
+
+uint16_t 
+get2byt(void) {
+    uint16_t var;
+
+    var=(p[bpos]<<0) | (p[bpos+1]<<8); 
+    bpos = bpos+2;
+
+    return var;
+}
+
+uint8_t
+get1byt(void) {
+    uint8_t var;
+
+    var=(p[bpos]<<0);
+    bpos = bpos+1;
+
+    return var;
+}
+
+char *
+xstrcpy( char *src, const char*dst) {
+    if (dst) {
+	if (strlen(dst)>MAX_PAC_GROUP_SIZE)
+	    return NULL;
+	else
+	    return strcpy(src,dst);
+    } else
+	return src;
+}
+
+char *
+xstrcat( char *src, const char*dst) {
+    if (dst) {
+        if (strlen(src)+strlen(dst)+1>MAX_PAC_GROUP_SIZE)
+            return NULL;
+        else
+            return strcat(src,dst);
+    } else
+	return src;
+}
+
+
+int
+checkustr(RPC_UNICODE_STRING *string) {
+    uint32_t size,off,len;
+
+    if (string->pointer != 0){
+	align(4);
+	size = (p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24);
+	bpos = bpos+4;
+	off = (p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24);
+	bpos = bpos+4;
+	len = (p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24);
+	bpos = bpos+4;
+	if (len > size || off != 0 || 
+	    string->length > string->maxlength || len != string->length/2) {
+	    debug((char *) "%s| %s: ERROR: RPC_UNICODE_STRING encoding error => size: %d len: %d/%d maxlength: %d offset: %d\n", 
+		    LogTime(), PROGRAM, size, len, string->length, string->maxlength, off);
+	    return -1;
+	}
+	/* UNICODE string */
+	bpos = bpos+string->length;
+    }
+    return 0;
+}
+
+char **
+getgids(char **Rids, uint32_t GroupIds, uint32_t  GroupCount) {
+    if (GroupIds!= 0){
+        uint32_t ngroup;
+        uint32_t sauth;
+        int l;
+
+        align(4);
+        ngroup = get4byt();
+        if ( ngroup != GroupCount) {
+            debug((char *) "%s| %s: ERROR: Group encoding error => GroupCount: %d Array size: %d\n",
+                                LogTime(), PROGRAM, GroupCount, ngroup);
+            return NULL;
+        }
+        debug((char *) "%s| %s: INFO: Found %d rids\n", LogTime(), PROGRAM, GroupCount);
+
+	Rids=(char **)xcalloc(GroupCount*sizeof(char*),1);
+        for ( l=0; l<(int)GroupCount; l++) {
+	    Rids[l]=(char *)xcalloc(4*sizeof(char),1);
+            memcpy((void *)Rids[l],(void *)&p[bpos],4); 
+            sauth = get4byt();
+	    debug((char *) "%s| %s: Info: Got rid: %u\n", LogTime(), PROGRAM, sauth);
+	    /* attribute */
+            bpos = bpos+4; 
+        }
+    }
+    return Rids;
+}
+
+char *
+getdomaingids(char *ad_groups, uint32_t DomainLogonId, char **Rids, uint32_t  GroupCount) {
+    if (DomainLogonId!= 0) {
+        uint32_t nauth;
+        uint8_t rev;
+        uint64_t idauth;
+        uint32_t sauth;
+	char dli[256];
+	char *ag;
+        int length;
+        int l;
+
+        align(4);
+
+        nauth = get4byt();
+	
+	/* prepend rids with DomainID */
+        length=1+1+6+nauth*4;
+	for (l=0; l<(int)GroupCount;l++){
+	    ag=(char *)xcalloc((length+4)*sizeof(char),1);
+	    memcpy((void *)ag,(const void*)&p[bpos],1);
+	    memcpy((void *)&ag[1],(const void*)&p[bpos+1],1);
+	    ag[1] = ag[1]+1;
+	    memcpy((void *)&ag[2],(const void*)&p[bpos+2],6+nauth*4);
+	    memcpy((void *)&ag[length],(const void*)Rids[l],4);
+	    if (l==0) {
+		if (!xstrcpy(ad_groups,"group=")) {
+		    debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", 
+				LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+		}
+	    } else {
+		if (!xstrcat(ad_groups," group=")) {
+                    debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", 
+                                LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+		}
+	    }
+	    if (!xstrcat(ad_groups,base64_encode_bin(ag, length+4))) {
+                    debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", 
+                                LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+	    }
+	    xfree(ag);
+	    xfree(Rids[l]);
+	}
+	xfree(Rids);
+
+	/* mainly for debug only */
+        rev = get1byt();
+        bpos = bpos + 1; /*nsub*/
+        idauth = get6byt_be();
+
+	snprintf(dli,sizeof(dli),"S-%d-%lu",rev,(long unsigned int)idauth);	
+        for ( l=0;l<(int)nauth;l++ ) {
+            sauth = get4byt();
+	    snprintf((char *)&dli[strlen(dli)],sizeof(dli)-strlen(dli),"-%u",sauth);	
+        }
+        debug((char *) "%s| %s: INFO: Got DomainLogonId %s\n", LogTime(), PROGRAM, dli); 
+    }
+    return ad_groups;
+}
+
+char *
+getextrasids(char *ad_groups, uint32_t ExtraSids, uint32_t SidCount, uint32_t GroupCount) {
+    if (ExtraSids!= 0){
+        uint32_t ngroup;
+	uint32_t *pa;
+	char *ag;
+        int length;
+        int l;
+
+        align(4);
+        ngroup = get4byt();
+        if ( ngroup != SidCount) {
+            debug((char *) "%s| %s: ERROR: Group encoding error => SidCount: %d Array size: %d\n",
+                                LogTime(), PROGRAM, SidCount, ngroup);
+	    return NULL;
+        }
+        debug((char *) "%s| %s: INFO: Found %d ExtraSIDs\n", LogTime(), PROGRAM, SidCount);
+
+	pa=(uint32_t *)xmalloc(SidCount*sizeof(uint32_t));
+        for ( l=0; l < (int)SidCount; l++ ){
+            pa[l] = get4byt();
+            bpos = bpos+4; /* attr */
+        }
+        
+        for ( l=0; l<(int)SidCount; l++ ){
+	    char es[256];
+            uint32_t nauth;
+            uint8_t rev;
+            uint64_t idauth;
+            uint32_t sauth;
+            int k;
+            
+	    if (pa[l] != 0){
+		nauth = get4byt();
+
+		length = 1+1+6+nauth*4;
+		ag = (char *)xcalloc((length)*sizeof(char),1);
+		memcpy((void *)ag,(const void*)&p[bpos],length);
+		if (!ad_groups) {
+		    if (!xstrcpy(ad_groups,"group=")) {
+			debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n", 
+                                	LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+		    }
+		} else {
+		    if (!xstrcat(ad_groups," group=")) {
+			debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",
+					LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+		    }
+		}
+		if (!xstrcat(ad_groups,base64_encode_bin(ag, length+4))) {
+                    debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",
+                                LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+		}
+		xfree(ag);
+
+		rev = get1byt();
+		bpos = bpos + 1; /* nsub */
+		idauth = get6byt_be();
+
+		snprintf(es,sizeof(es),"S-%d-%lu",rev,(long unsigned int)idauth);	
+		for ( k=0;k<(int)nauth;k++ ) {
+		    sauth = get4byt();
+		    snprintf((char *)&es[strlen(es)],sizeof(es)-strlen(es),"-%u",sauth);	
+		}
+		debug((char *) "%s| %s: INFO: Got ExtraSid %s\n", LogTime(), PROGRAM, es); 
+	    }
+        }
+	xfree(pa);
+    }
+    return ad_groups;
+}
+
+char *
+get_ad_groups(char *ad_groups, krb5_context context, krb5_pac pac){
+    krb5_error_code ret;
+    RPC_UNICODE_STRING EffectiveName;
+    RPC_UNICODE_STRING FullName;
+    RPC_UNICODE_STRING LogonScript;
+    RPC_UNICODE_STRING ProfilePath;
+    RPC_UNICODE_STRING HomeDirectory;
+    RPC_UNICODE_STRING HomeDirectoryDrive;
+    RPC_UNICODE_STRING LogonServer;
+    RPC_UNICODE_STRING LogonDomainName;
+    uint32_t GroupCount=0;
+    uint32_t GroupIds=0;
+    uint32_t LogonDomainId=0;
+    uint32_t SidCount=0;
+    uint32_t ExtraSids=0;
+    /*
+    uint32_t ResourceGroupDomainSid=0;
+    uint32_t ResourceGroupCount=0;
+    uint32_t ResourceGroupIds=0;
+    */
+    char **Rids=NULL;
+    int l=0;
+
+    ad_data = (krb5_data *)xmalloc(sizeof(krb5_data));
+
+#define KERB_LOGON_INFO 1
+    ret = krb5_pac_get_buffer(context, pac, KERB_LOGON_INFO, ad_data);
+    if (check_k5_err(context, "krb5_pac_get_buffer", ret)) 
+	goto k5clean;
+    
+    p = (unsigned char *)ad_data->data;
+
+    debug((char *) "%s| %s: INFO: Got PAC data of lengh %d\n", 
+		    LogTime(), PROGRAM, ad_data->length);
+
+    /* Skip 16 bytes icommon RPC header
+     * Skip 4 bytes RPC unique pointer referent
+     * http://msdn.microsoft.com/en-gb/library/cc237933.aspx
+     */
+    /* Some data are pointers to data which follows the main KRB5 LOGON structure => 
+     *         So need to read the data 
+     * some logical consistency checks are done when analysineg the pointer data
+     */
+    bpos = 20;
+    /* 8 bytes LogonTime
+     * 8 bytes LogoffTime
+     * 8 bytes KickOffTime
+     * 8 bytes PasswordLastSet
+     * 8 bytes PasswordCanChange
+     * 8 bytes PasswordMustChange
+     */
+    bpos = bpos+48;
+    getustr(&EffectiveName);
+    getustr(&FullName);
+    getustr(&LogonScript);
+    getustr(&ProfilePath);
+    getustr(&HomeDirectory);
+    getustr(&HomeDirectoryDrive);
+    /* 2 bytes LogonCount
+     * 2 bytes BadPasswordCount
+     * 4 bytes UserID
+     * 4 bytes PrimaryGroupId
+     */
+    bpos = bpos+12;
+    GroupCount = get4byt();
+    GroupIds = get4byt();
+    /* 4 bytes UserFlags
+     * 16 bytes UserSessionKey
+     */
+    bpos = bpos+20;
+    getustr(&LogonServer);
+    getustr(&LogonDomainName);
+    LogonDomainId = get4byt();
+    /* 8 bytes Reserved1
+     * 4 bytes UserAccountControl
+     * 4 bytes SubAuthStatus
+     * 8 bytes LastSuccessfullLogon
+     * 8 bytes LastFailedLogon
+     * 4 bytes FailedLogonCount
+     * 4 bytes Reserved2
+     */
+    bpos = bpos+40;
+    SidCount = get4byt();
+    ExtraSids = get4byt();
+    /* 4 bytes ResourceGroupDomainSid
+     * 4 bytes ResourceGroupCount
+     * 4 bytes ResourceGroupIds
+     */
+    bpos = bpos+12;
+    /* 
+     * Read all data from structure => Now check pointers
+     */
+    if (checkustr(&EffectiveName)<0)
+	goto k5clean;
+    if (checkustr(&FullName)<0)
+	goto k5clean;
+    if (checkustr(&LogonScript)<0)
+	goto k5clean;
+    if (checkustr(&ProfilePath)<0)
+	goto k5clean;
+    if (checkustr(&HomeDirectory)<0)
+	goto k5clean;
+    if (checkustr(&HomeDirectoryDrive)<0)
+	goto k5clean;
+    Rids = getgids(Rids,GroupIds,GroupCount);
+    if (checkustr(&LogonServer)<0)
+	goto k5clean;
+    if (checkustr(&LogonDomainName)<0)
+	goto k5clean;
+    ad_groups = getdomaingids(ad_groups,LogonDomainId,Rids,GroupCount);
+    if ((ad_groups = getextrasids(ad_groups,ExtraSids,SidCount,GroupCount))==NULL)
+        goto k5clean;
+    
+    debug((char *) "%s| %s: INFO: Read %d of %d bytes \n", LogTime(), PROGRAM, bpos,ad_data->length);
+    krb5_free_data(context, ad_data);
+    return ad_groups; 
+k5clean:
+    for ( l=0; l<(int)GroupCount; l++) {
+	if (Rids[l])
+	    xfree(Rids[l]);
+    }
+    xfree(Rids);
+    krb5_free_data(context, ad_data);
+    return NULL;
+}
+#endif
diff -rubwBEN 3.4/src/peer_proxy_negotiate_auth.cc 3.4-mm/src/peer_proxy_negotiate_auth.cc
--- 3.4/src/peer_proxy_negotiate_auth.cc	2013-08-12 00:01:44.458703000 +0100
+++ 3.4-mm/src/peer_proxy_negotiate_auth.cc	2013-08-23 13:16:09.959167303 +0100
@@ -210,19 +210,23 @@
         static krb5_keytab_entry entry;
         static krb5_kt_cursor cursor;
         static krb5_creds *creds = NULL;
-#if HAVE_HEIMDAL_KERBEROS
+#if defined(HAVE_HEIMDAL_KERBEROS) && !defined(HAVE_KRB5_GET_RENEWED_CREDS)
         static krb5_creds creds2;
 #endif
         static krb5_principal principal = NULL;
         static krb5_deltat skew;
 
+#if HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+        krb5_get_init_creds_opt *options;
+#else
         krb5_get_init_creds_opt options;
+#endif
         krb5_error_code code = 0;
         krb5_deltat rlife;
 #if HAVE_PROFILE_H && HAVE_KRB5_GET_PROFILE && HAVE_PROFILE_GET_INTEGER && HAVE_PROFILE_RELEASE
         profile_t profile;
 #endif
-#if HAVE_HEIMDAL_KERBEROS
+#if defined(HAVE_HEIMDAL_KERBEROS) && !defined(HAVE_KRB5_GET_RENEWED_CREDS)
         krb5_kdc_flags flags;
         krb5_realm *client_realm;
 #endif
@@ -236,7 +240,7 @@
                 (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
+#if HAVE_KRB5_GET_RENEWED_CREDS
                 /* renew ticket */
                 code =
                     krb5_get_renewed_creds(kparam.context, creds, principal,
@@ -256,7 +260,11 @@
                            << error_message(code));
                     return (1);
                 }
+#if HAVE_KRB5_PRINCIPAL_GET_REALM
+                client_realm = krb5_principal_get_realm(kparam.context, principal);
+#else
                 client_realm = krb5_princ_realm(kparam.context, creds2.client);
+#endif
                 code =
                     krb5_make_principal(kparam.context, &creds2.server,
                                         *client_realm, KRB5_TGS_NAME, *client_realm, NULL);
@@ -400,7 +408,11 @@
 
             creds = (krb5_creds *) xmalloc(sizeof(*creds));
             memset(creds, 0, sizeof(*creds));
+#if HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+	    krb5_get_init_creds_opt_alloc(kparam.context, &options);
+#else
             krb5_get_init_creds_opt_init(&options);
+#endif
             code = krb5_string_to_deltat((char *) MAX_RENEW_TIME, &rlife);
             if (code != 0 || rlife == 0) {
                 debugs(11, 5,
@@ -408,8 +420,14 @@
                        " : " << error_message(code));
                 return (1);
             }
+#if HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+            krb5_get_init_creds_opt_set_renew_life(options, rlife);
+            code =
+                krb5_get_init_creds_keytab(kparam.context, creds, principal,
+                                           keytab, 0, NULL, options);
+	    krb5_get_init_creds_opt_free(kparam.context, options);
+#else
             krb5_get_init_creds_opt_set_renew_life(&options, rlife);
-
             code =
                 krb5_get_init_creds_keytab(kparam.context, creds, principal,
                                            keytab, 0, NULL, &options);
@@ -413,6 +431,7 @@
             code =
                 krb5_get_init_creds_keytab(kparam.context, creds, principal,
                                            keytab, 0, NULL, &options);
+#endif
             if (code) {
                 debugs(11, 5,
                        HERE <<

