Binary files 3.4/.bzr/repository/packs/2aa5ce40707dccfac2902bbdbb08e1ba.pack and 3.4-mm/.bzr/repository/packs/2aa5ce40707dccfac2902bbdbb08e1ba.pack differ
diff -rubwBEN 3.4/configure.ac 3.4-mm/configure.ac
--- 3.4/configure.ac	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/configure.ac	2013-08-26 22:20:21.900403927 +0100
@@ -1906,6 +1906,10 @@
     AC_DEFINE(HAVE_KRB5_GET_ERROR_MESSAGE,1,
       [Define to 1 if you have krb5_get_error_message]),)
   AC_CHECK_DECLS(krb5_kt_free_entry,,,[#include <krb5.h>])
+  AC_CHECK_TYPE(krb5_pac,
+    AC_DEFINE(HAVE_KRB5_PAC,1,
+      [Define to 1 if you have krb5_pac]),,
+      [#include <krb5.h>])
   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]),)
@@ -1924,6 +1928,33 @@
   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_MSG_CHECKING([for krb5_get_init_creds_free requires krb5_context])
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+	#include <krb5.h>
+    ]],[[krb5_context context;
+	 krb5_get_init_creds_opt *options;
+	 krb5_get_init_creds_opt_free(context, options)]])],[
+	AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_FREE_CONTEXT,1,
+		  [Define to 1 if you krb5_get_init_creds_free requires krb5_context])
+	AC_MSG_RESULT(yes)
+    ],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)])
+
+
+  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/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc	2013-08-26 22:05:50.730382326 +0100
@@ -78,22 +78,10 @@
             pp = p;
             p = p->next;
         }
-        if (p->group) {
-            xfree(p->group);
-            p->group = NULL;
-        }
-        if (p->domain) {
-            xfree(p->domain);
-            p->domain = NULL;
-        }
-        if (pp && pp->next) {
-            xfree(pp->next);
-            pp->next = NULL;
-        }
-        if (p == gdsp) {
-            xfree(gdsp);
-            gdsp = NULL;
-        }
+        safe_free(p->group);
+        safe_free(p->domain);
+        safe_free(pp->next);
+        safe_free(gdsp);
         p = gdsp;
     }
 }
@@ -109,22 +97,10 @@
             pp = p;
             p = p->next;
         }
-        if (p->netbios) {
-            xfree(p->netbios);
-            p->netbios = NULL;
-        }
-        if (p->domain) {
-            xfree(p->domain);
-            p->domain = NULL;
-        }
-        if (pp && pp->next) {
-            xfree(pp->next);
-            pp->next = NULL;
-        }
-        if (p == ndsp) {
-            xfree(ndsp);
-            ndsp = NULL;
-        }
+        safe_free(p->netbios);
+        safe_free(p->domain);
+        safe_free(pp->next);
+        safe_free(ndsp);
         p = ndsp;
     }
 }
@@ -140,22 +116,10 @@
             pp = p;
             p = p->next;
         }
-        if (p->lserver) {
-            xfree(p->lserver);
-            p->lserver = NULL;
-        }
-        if (p->domain) {
-            xfree(p->domain);
-            p->domain = NULL;
-        }
-        if (pp && pp->next) {
-            xfree(pp->next);
-            pp->next = NULL;
-        }
-        if (p == lssp) {
-            xfree(lssp);
-            lssp = NULL;
-        }
+        safe_free(p->lserver);
+        safe_free(p->domain);
+        safe_free(pp->next);
+        safe_free(lssp);
         p = lssp;
     }
 }
@@ -163,50 +127,17 @@
 void
 clean_args(struct main_args *margs)
 {
-    if (margs->glist) {
-        xfree(margs->glist);
-        margs->glist = NULL;
-    }
-    if (margs->ulist) {
-        xfree(margs->ulist);
-        margs->ulist = NULL;
-    }
-    if (margs->tlist) {
-        xfree(margs->tlist);
-        margs->tlist = NULL;
-    }
-    if (margs->nlist) {
-        xfree(margs->nlist);
-        margs->nlist = NULL;
-    }
-    if (margs->llist) {
-        xfree(margs->llist);
-        margs->llist = NULL;
-    }
-    if (margs->luser) {
-        xfree(margs->luser);
-        margs->luser = NULL;
-    }
-    if (margs->lpass) {
-        xfree(margs->lpass);
-        margs->lpass = NULL;
-    }
-    if (margs->lbind) {
-        xfree(margs->lbind);
-        margs->lbind = NULL;
-    }
-    if (margs->lurl) {
-        xfree(margs->lurl);
-        margs->lurl = NULL;
-    }
-    if (margs->ssl) {
-        xfree(margs->ssl);
-        margs->ssl = NULL;
-    }
-    if (margs->ddomain) {
-        xfree(margs->ddomain);
-        margs->ddomain = NULL;
-    }
+    safe_free(margs->glist);
+    safe_free(margs->ulist);
+    safe_free(margs->tlist);
+    safe_free(margs->nlist);
+    safe_free(margs->llist);
+    safe_free(margs->luser);
+    safe_free(margs->lpass);
+    safe_free(margs->lbind);
+    safe_free(margs->lurl);
+    safe_free(margs->ssl);
+    safe_free(margs->ddomain);
     if (margs->groups) {
         clean_gd(margs->groups);
         margs->groups = NULL;
@@ -413,8 +344,8 @@
                 log((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, up, np);
             domain = get_netbios_name(&margs, netbios);
             user = nuser;
-            xfree(up);
-            xfree(np);
+	    safe_free(up);
+            safe_free(np);
         } else if (domain) {
             strup(domain);
             *domain = '\0';
@@ -436,8 +367,8 @@
         else
             log((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, up, domain ? dp : "NULL");
 
-        xfree(up);
-        xfree(dp);
+	safe_free(up);
+        safe_free(dp);
         if (!strcmp(user, "QQ") && domain && !strcmp(domain, "QQ")) {
             clean_args(&margs);
             exit(-1);
diff -rubwBEN 3.4/helpers/external_acl/kerberos_ldap_group/support_group.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_group.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/support_group.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_group.cc	2013-08-26 22:05:50.730382326 +0100
@@ -47,9 +47,9 @@
 {
     while (gdsp) {
         struct gdstruct *gdspn = gdsp->next;
-        xfree(gdsp->group);
-        xfree(gdsp->domain);
-        xfree(gdsp);
+        safe_free(gdsp->group);
+        safe_free(gdsp->domain);
+        safe_free(gdsp);
         gdsp = gdspn;
     }
 }
@@ -148,13 +148,13 @@
             ichar = (ival - 48) * 16;
         else {
             debug((char *) "%s| %s: WARNING: Invalid Hex value %c\n", LogTime(), PROGRAM, ival);
-            xfree(ul);
+            safe_free(ul);
             return NULL;
         }
 
         if (n == a - 1) {
             debug((char *) "%s| %s: WARNING: Invalid Hex UTF-8 string %s\n", LogTime(), PROGRAM, up);
-            xfree(ul);
+            safe_free(ul);
             return NULL;
         }
         ++n;
@@ -167,7 +167,7 @@
             ichar = ichar + ival - 48;
         else {
             debug((char *) "%s| %s: WARNING: Invalid Hex value %c\n", LogTime(), PROGRAM, ival);
-            xfree(ul);
+            safe_free(ul);
             return NULL;
         }
 
@@ -187,7 +187,7 @@
                 ul[nl] = ichar;
                 ul[nl + 1] = '\0';
                 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
-                xfree(ul);
+                safe_free(ul);
                 return NULL;
             }
         } else if (iUTF3) {
@@ -216,7 +216,7 @@
                 ul[nl] = ichar;
                 ul[nl + 1] = '\0';
                 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
-                xfree(ul);
+                safe_free(ul);
                 return NULL;
             }
         } else if (iUTF4) {
@@ -244,7 +244,7 @@
                 ul[nl] = ichar;
                 ul[nl + 1] = '\0';
                 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
-                xfree(ul);
+                safe_free(ul);
                 return NULL;
             }
         } else if (ichar < 0x80) {
@@ -270,7 +270,7 @@
             ul[nl] = ichar;
             ul[nl + 1] = '\0';
             debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
-            xfree(ul);
+            safe_free(ul);
             return NULL;
         }
         ++n;
@@ -280,7 +280,7 @@
     if (iUTF2 || iUTF3 || iUTF4) {
         debug((char *) "%s| %s: INFO: iUTF2: %d iUTF3: %d iUTF4: %d\n", LogTime(), PROGRAM, iUTF2, iUTF3, iUTF4);
         debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
-        xfree(ul);
+        safe_free(ul);
         return NULL;
     }
     if (flag && upd)
@@ -319,15 +319,15 @@
 
     // NP: will point to the start of a temporary assembly buffer used by 'p' and 'gp'
     //     for catenation of the hp1, hp2, and up buffer contents from above.
-    //     necessary for xfree() because both p and gp move over the assembly area
+    //     necessary for safe_free() because both p and gp move over the assembly area
     char *gpbuf = NULL;
 
     // release the allocated UTF decoding buffers
 #define cleanup() { \
-    xfree(gpbuf); \
-    xfree(hp1); \
-    xfree(hp2); \
-    xfree(up); \
+    safe_free(gpbuf); \
+    safe_free(hp1); \
+    safe_free(hp2); \
+    safe_free(up); \
     free_gd(gdsp); \
  }
 
diff -rubwBEN 3.4/helpers/external_acl/kerberos_ldap_group/support_krb5.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_krb5.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/support_krb5.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_krb5.cc	2013-08-26 22:05:50.730382326 +0100
@@ -184,10 +184,10 @@
     if (!principal_name) {
         debug((char *) "%s| %s: DEBUG: Did not find a principal in keytab for domain %s.\n", LogTime(), PROGRAM, domain);
         debug((char *) "%s| %s: DEBUG: Try to get principal of trusted domain.\n", LogTime(), PROGRAM);
-        creds = (krb5_creds *) xmalloc(sizeof(*creds));
-        memset(creds, 0, sizeof(*creds));
 
         for (i = 0; i < nprinc; ++i) {
+            creds = (krb5_creds *) xmalloc(sizeof(*creds));
+            memset(creds, 0, sizeof(*creds));
             /*
              * get credentials
              */
@@ -205,8 +205,7 @@
             snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain);
             creds->client = principal_list[i];
             code = krb5_parse_name(kparam.context, service, &creds->server);
-            if (service)
-                xfree(service);
+            safe_free(service);
             code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
 #endif
             if (code) {
@@ -233,8 +232,7 @@
             snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3, "krbtgt/%s@%s", domain, krb5_princ_realm(kparam.context, principal_list[i])->data);
 #endif
             code = krb5_parse_name(kparam.context, service, &creds->server);
-            if (service)
-                xfree(service);
+            safe_free(service);
             if (code) {
                 error((char *) "%s| %s: ERROR: Error while initialising TGT credentials : %s\n", LogTime(), PROGRAM, error_message(code));
                 goto loop_end;
@@ -250,11 +248,17 @@
             }
 
 loop_end:
-            if (principal_name)
-                xfree(principal_name);
-            principal_name = NULL;
+            safe_free(principal_name);
+	    if (tgt_creds)
+		krb5_free_creds(kparam.context, tgt_creds);
+	    tgt_creds = NULL;
+	    if (creds)
+		krb5_free_creds(kparam.context, creds);
+            creds = NULL;
+
         }
 
+        safe_free(principal_name);
         if (tgt_creds)
             krb5_free_creds(kparam.context, tgt_creds);
         tgt_creds = NULL;
@@ -287,8 +291,7 @@
         snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain);
         creds->client = principal;
         code = krb5_parse_name(kparam.context, service, &creds->server);
-        if (service)
-            xfree(service);
+        safe_free(service);
         code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
 #endif
         if (code) {
@@ -316,20 +319,16 @@
 cleanup:
     if (keytab)
         krb5_kt_close(kparam.context, keytab);
-    if (keytab_name)
-        xfree(keytab_name);
-    if (principal_name)
-        xfree(principal_name);
-    if (mem_cache)
-        xfree(mem_cache);
+    safe_free(keytab_name);
+    safe_free(principal_name);
+    safe_free(mem_cache);
     if (principal)
         krb5_free_principal(kparam.context, principal);
     for (i = 0; i < nprinc; ++i) {
         if (principal_list[i])
             krb5_free_principal(kparam.context, principal_list[i]);
     }
-    if (principal_list)
-        xfree(principal_list);
+    safe_free(principal_list);
     if (creds)
         krb5_free_creds(kparam.context, creds);
 
diff -rubwBEN 3.4/helpers/external_acl/kerberos_ldap_group/support_ldap.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_ldap.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/support_ldap.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_ldap.cc	2013-08-26 22:05:50.731382326 +0100
@@ -319,10 +319,9 @@
      */
     if (attr_value) {
         for (j = 0; j < max_attr; ++j) {
-            xfree(attr_value[j]);
+            safe_free(attr_value[j]);
         }
-        xfree(attr_value);
-        attr_value = NULL;
+        safe_free(attr_value);
     }
     ldap_msgfree(res);
     return rc;
@@ -357,18 +356,18 @@
     search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
     snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-    xfree(ldap_filter_esc);
+    safe_free(ldap_filter_esc);
 
     if (depth > margs->mdepth) {
         debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM, depth, margs->mdepth);
-        xfree(search_exp);
+        safe_free(search_exp);
         return 0;
     }
     debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
     rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                            search_exp, NULL, 0,
                            NULL, NULL, &searchtime, 0, &res);
-    xfree(search_exp);
+    safe_free(search_exp);
 
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
@@ -436,10 +435,9 @@
      */
     if (attr_value) {
         for (j = 0; j < max_attr; ++j) {
-            xfree(attr_value[j]);
+            safe_free(attr_value[j]);
         }
-        xfree(attr_value);
-        attr_value = NULL;
+        safe_free(attr_value);
     }
     ldap_msgfree(res);
 
@@ -508,8 +506,7 @@
         debug((char *) "%s| %s: DEBUG: Set certificate file for ldap server to %s.(Changeable through setting environment variable TLS_CACERTFILE)\n", LogTime(), PROGRAM, ssl_cacertfile);
         rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ssl_cacertfile);
         if (ssl_cacertfile && free_path) {
-            xfree(ssl_cacertfile);
-            ssl_cacertfile = NULL;
+            safe_free(ssl_cacertfile);
         }
         if (rc != LDAP_OPT_SUCCESS) {
             error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
@@ -543,10 +540,7 @@
         rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 0);
         debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
     }
-    if (ssl_certdbpath) {
-        xfree(ssl_certdbpath);
-        ssl_certdbpath = NULL;
-    }
+    safe_free(ssl_certdbpath);
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
         return rc;
@@ -588,15 +582,15 @@
                     if ((values = ldap_get_values_len(ld, msg, attr)) != NULL) {
                         for (il = 0; values[il] != NULL; ++il) {
 
-                            attr_value = (char **) xrealloc(attr_value, (il + 1) * sizeof(char *));
+                            attr_value = (char **) xrealloc(attr_value, (max_attr + 1) * sizeof(char *));
                             if (!attr_value)
                                 break;
 
-                            attr_value[il] = (char *) xmalloc(values[il]->bv_len + 1);
-                            memcpy(attr_value[il], values[il]->bv_val, values[il]->bv_len);
-                            attr_value[il][values[il]->bv_len] = 0;
+                            attr_value[max_attr] = (char *) xmalloc(values[il]->bv_len + 1);
+                            memcpy(attr_value[max_attr], values[il]->bv_val, values[il]->bv_len);
+                            attr_value[max_attr][values[il]->bv_len] = 0;
+                            max_attr++;
                         }
-                        max_attr = il;
                     }
                     ber_bvecfree(values);
                 }
@@ -660,8 +654,8 @@
     rc = ldap_url_parse(ldapuri, &url);
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
-        xfree(ldapuri);
-        xfree(url);
+        safe_free(ldapuri);
+        safe_free(url);
         return NULL;
     }
 #else
@@ -669,7 +663,7 @@
 #endif
     safe_free(url);
     rc = ldap_initialize(&ld, ldapuri);
-    xfree(ldapuri);
+    safe_free(ldapuri);
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
         ldap_unbind(ld);
@@ -725,8 +719,8 @@
             rc = ldap_url_parse(ldapuri, &url);
             if (rc != LDAP_SUCCESS) {
                 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
-                xfree(ldapuri);
-                xfree(url);
+                safe_free(ldapuri);
+                safe_free(url);
                 return NULL;
             }
 #else
@@ -734,7 +728,7 @@
 #endif
             safe_free(url);
             rc = ldap_initialize(&ld, ldapuri);
-            xfree(ldapuri);
+            safe_free(ldapuri);
             if (rc != LDAP_SUCCESS) {
                 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
                 ldap_unbind(ld);
@@ -940,7 +934,7 @@
 
         }
         nhosts = free_hostname_list(&hlist, nhosts);
-        xfree(bindp);
+        safe_free(bindp);
         if (margs->lbind) {
             bindp = xstrdup(margs->lbind);
         } else {
@@ -977,13 +971,13 @@
     search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
     snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-    xfree(ldap_filter_esc);
+    safe_free(ldap_filter_esc);
 
     debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
     rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                            search_exp, NULL, 0,
                            NULL, NULL, &searchtime, 0, &res);
-    xfree(search_exp);
+    safe_free(search_exp);
 
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
@@ -1062,10 +1056,9 @@
          */
         if (attr_value) {
             for (j = 0; j < max_attr; ++j) {
-                xfree(attr_value[j]);
+                safe_free(attr_value[j]);
             }
-            xfree(attr_value);
-            attr_value = NULL;
+            safe_free(attr_value);
         }
         ldap_msgfree(res);
     } else if (ldap_count_entries(ld, res) == 0 && margs->AD) {
@@ -1091,13 +1084,13 @@
         search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
         snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-        xfree(ldap_filter_esc);
+        safe_free(ldap_filter_esc);
 
         debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
         rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                                search_exp, NULL, 0,
                                NULL, NULL, &searchtime, 0, &res);
-        xfree(search_exp);
+        safe_free(search_exp);
 
         debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
 
@@ -1115,13 +1108,13 @@
             search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
             snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-            xfree(ldap_filter_esc);
+            safe_free(ldap_filter_esc);
 
             debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
             rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                                    search_exp, NULL, 0,
                                    NULL, NULL, &searchtime, 0, &res);
-            xfree(search_exp);
+            safe_free(search_exp);
 
             max_attr_2 = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value_2);
             /*
@@ -1144,10 +1137,9 @@
              */
             if (attr_value_2) {
                 for (j = 0; j < max_attr_2; ++j) {
-                    xfree(attr_value_2[j]);
+                    safe_free(attr_value_2[j]);
                 }
-                xfree(attr_value_2);
-                attr_value_2 = NULL;
+                safe_free(attr_value_2);
             }
             ldap_msgfree(res);
 
@@ -1162,10 +1154,9 @@
          */
         if (attr_value) {
             for (j = 0; j < max_attr; ++j) {
-                xfree(attr_value[j]);
+                safe_free(attr_value[j]);
             }
-            xfree(attr_value);
-            attr_value = NULL;
+            safe_free(attr_value);
         }
     }
     rc = ldap_unbind(ld);
@@ -1180,11 +1171,11 @@
         krb5_cleanup();
 #endif
     if (lcreds) {
-        xfree(lcreds->dn);
-        xfree(lcreds->pw);
-        xfree(lcreds);
+        safe_free(lcreds->dn);
+        safe_free(lcreds->pw);
+        safe_free(lcreds);
     }
-    xfree(bindp);
+    safe_free(bindp);
     return (retval);
 }
 #endif
diff -rubwBEN 3.4/helpers/external_acl/kerberos_ldap_group/support_lserver.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_lserver.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/support_lserver.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_lserver.cc	2013-08-26 22:05:50.731382326 +0100
@@ -45,9 +45,9 @@
 {
     while (lssp) {
         struct lsstruct *lsspn = lssp->next;
-        xfree(lssp->lserver);
-        xfree(lssp->domain);
-        xfree(lssp);
+        safe_free(lssp->lserver);
+        safe_free(lssp->domain);
+        safe_free(lssp);
         lssp = lsspn;
     }
 }
diff -rubwBEN 3.4/helpers/external_acl/kerberos_ldap_group/support_netbios.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_netbios.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/support_netbios.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_netbios.cc	2013-08-26 22:05:50.732382326 +0100
@@ -46,9 +46,9 @@
 {
     while (ndsp) {
         struct ndstruct *ndspn = ndsp->next;
-        xfree(ndsp->netbios);
-        xfree(ndsp->domain);
-        xfree(ndsp);
+        safe_free(ndsp->netbios);
+        safe_free(ndsp->domain);
+        safe_free(ndsp);
         ndsp = ndspn;
     }
 }
diff -rubwBEN 3.4/helpers/external_acl/kerberos_ldap_group/support_resolv.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_resolv.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/support_resolv.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_resolv.cc	2013-08-26 22:05:50.732382326 +0100
@@ -153,14 +153,10 @@
 
     hp = *hlist;
     for (i = 0; i < nhosts; ++i) {
-        if (hp[i].host)
-            xfree(hp[i].host);
-        hp[i].host = NULL;
+        safe_free(hp[i].host);
     }
 
-    if (hp)
-        xfree(hp);
-    hp = NULL;
+    safe_free(hp);
     *hlist = hp;
     return 0;
 }
@@ -290,7 +286,7 @@
         error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM, service);
         nsError(h_errno, service);
         if (margs->ssl) {
-            xfree(service);
+            safe_free(service);
             service = (char *) xmalloc(strlen("_ldap._tcp.") + strlen(domain) + 1);
             strcpy(service, "_ldap._tcp.");
             strcat(service, domain);
@@ -419,7 +415,7 @@
                 if (hp[i].port == hp[j].port ||
                         (hp[i].port == -1 && hp[j].port == 389) ||
                         (hp[i].port == 389 && hp[j].port == -1)) {
-                    xfree(hp[j].host);
+                    safe_free(hp[j].host);
                     for (k = j + 1; k < nhosts; ++k) {
                         hp[k - 1].host = hp[k].host;
                         hp[k - 1].port = hp[k].port;
@@ -443,10 +439,8 @@
             debug((char *) "%s| %s: DEBUG: Host: %s Port: %d Priority: %d Weight: %d\n", LogTime(), PROGRAM, hp[i].host, hp[i].port, hp[i].priority, hp[i].weight);
         }
     }
-    if (buffer)
-        xfree(buffer);
-    if (service)
-        xfree(service);
+    safe_free(buffer);
+    safe_free(service);
     *hlist = hp;
     return (nhosts);
 }
diff -rubwBEN 3.4/helpers/external_acl/kerberos_ldap_group/support_sasl.cc 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_sasl.cc
--- 3.4/helpers/external_acl/kerberos_ldap_group/support_sasl.cc	2013-08-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/external_acl/kerberos_ldap_group/support_sasl.cc	2013-08-26 22:05:50.733382326 +0100
@@ -196,20 +196,14 @@
 {
     lutilSASLdefaults *defs = (lutilSASLdefaults *) defaults;
 
-    if (defs->mech)
-        xfree(defs->mech);
-    if (defs->realm)
-        xfree(defs->realm);
-    if (defs->authcid)
-        xfree(defs->authcid);
-    if (defs->passwd)
-        xfree(defs->passwd);
-    if (defs->authzid)
-        xfree(defs->authzid);
-    if (defs->resps)
-        xfree(defs->resps);
+    safe_free(defs->mech);
+    safe_free(defs->realm);
+    safe_free(defs->authcid);
+    safe_free(defs->passwd);
+    safe_free(defs->authzid);
+    safe_free(defs->resps);
 
-    xfree(defs);
+    safe_free(defs);
 }
 
 int
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-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/negotiate_auth/kerberos/Makefile.am	2013-08-26 22:06:23.054383127 +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-26 22:02:02.226038000 +0100
+++ 3.4-mm/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc	2013-08-26 22:06:50.003383795 +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)
@@ -155,7 +83,7 @@
 
 int
 check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
-              const char *function, int log)
+              const char *function, int log, int sout)
 {
     if (GSS_ERROR(major_status)) {
         OM_uint32 maj_stat, min_stat;
@@ -198,6 +126,7 @@
             gss_release_buffer(&min_stat, &status_string);
         } while (msg_ctx);
         debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
+	if (sout)
         fprintf(stdout, "BH %s failed: %s\n", function, buf);
         if (log)
             fprintf(stderr, "%s| %s: INFO: User not authenticated\n", LogTime(),
@@ -213,6 +142,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)) && HAVE_KRB5_PAC
+    char ad_groups[MAX_PAC_GROUP_SIZE];
+    char *ag=NULL;
+    krb5_context context = NULL;
+    krb5_error_code ret;
+    krb5_pac pac;
+#if HAVE_HEIMDAL_KERBEROS
+    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 +226,7 @@
         snprintf((char *) service.value, strlen(service_name) + strlen(host_name) + 2,
                  "%s@%s", service_name, host_name);
         service.length = strlen((char *) service.value);
+        safe_free(host_name);
     }
 
     while (1) {
@@ -338,23 +281,14 @@
             if (kerberosToken) {
                 /* Allocated by parseNegTokenInit, but no matching free function exists.. */
                 if (!spnego_flag)
-                    xfree((char *) kerberosToken);
-                kerberosToken = NULL;
+                    safe_free(kerberosToken);
             }
             if (spnego_flag) {
                 /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
                 if (spnegoToken)
-                    xfree((char *) spnegoToken);
-                spnegoToken = NULL;
-            }
-            if (token) {
-                xfree(token);
-                token = NULL;
-            }
-            if (host_name) {
-                xfree(host_name);
-                host_name = NULL;
+                    safe_free(spnegoToken);
             }
+            safe_free(token);
             fprintf(stdout, "BH quit command\n");
             exit(0);
         }
@@ -405,13 +339,13 @@
                                            gss_nt_service_name, &server_name);
         }
 
-        if (check_gss_err(major_status, minor_status, "gss_import_name()", log))
+        if (check_gss_err(major_status, minor_status, "gss_import_name()", log, 1))
             goto cleanup;
 
         major_status =
             gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
                              GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, NULL, NULL);
-        if (check_gss_err(major_status, minor_status, "gss_acquire_cred()", log))
+        if (check_gss_err(major_status, minor_status, "gss_acquire_cred()", log, 1))
             goto cleanup;
 
         major_status = gss_accept_sec_context(&minor_status,
@@ -433,7 +367,7 @@
             base64_encode_str(token, base64_encode_len(spnegoTokenLength),
                               (const char *) spnegoToken, spnegoTokenLength);
 
-            if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log))
+            if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log, 1))
                 goto cleanup;
             if (major_status & GSS_S_CONTINUE_NEEDED) {
                 debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
@@ -445,7 +379,7 @@
                 gss_display_name(&minor_status, client_name, &output_token,
                                  NULL);
 
-            if (check_gss_err(major_status, minor_status, "gss_display_name()", log))
+            if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1))
                 goto cleanup;
             user = (char *) xmalloc(output_token.length + 1);
             if (user == NULL) {
@@ -458,14 +392,49 @@
             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)) && HAVE_KRB5_PAC
+	    ret = krb5_init_context(&context);
+	    if (!check_k5_err(context, "krb5_init_context", ret)) {
+#define ADWIN2KPAC 128
+#if HAVE_HEIMDAL_KERBEROS
+		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, 0)) {
+		    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);
+#define KRB5PACLOGONINFO        1 
+		major_status = gss_map_name_to_any(&minor_status, client_name, KRB5PACLOGONINFO, &type_id, (gss_any_t *)&pac);
+		if (!check_gss_err(major_status, minor_status, "gss_map_name_to_any()", log, 0)) {
+		    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);
             if (log)
                 fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(),
                         PROGRAM, rfc1738_escape(user));
             goto cleanup;
         } else {
-            if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log))
+            if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log, 1))
                 goto cleanup;
             if (major_status & GSS_S_CONTINUE_NEEDED) {
                 debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
@@ -477,7 +446,7 @@
                 gss_display_name(&minor_status, client_name, &output_token,
                                  NULL);
 
-            if (check_gss_err(major_status, minor_status, "gss_display_name()", log))
+            if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1))
                 goto cleanup;
             /*
              *  Return dummy token AA. May need an extra return tag then AF
@@ -511,23 +480,15 @@
         if (kerberosToken) {
             /* Allocated by parseNegTokenInit, but no matching free function exists.. */
             if (!spnego_flag)
-                xfree((char *) kerberosToken);
-            kerberosToken = NULL;
+                safe_free(kerberosToken);
         }
         if (spnego_flag) {
             /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
             if (spnegoToken)
-                xfree((char *) spnegoToken);
-            spnegoToken = NULL;
-        }
-        if (token) {
-            xfree(token);
-            token = NULL;
-        }
-        if (user) {
-            xfree(user);
-            user = NULL;
+                safe_free(spnegoToken);
         }
+        safe_free(token);
+        safe_free(user);
         continue;
     }
 }
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-26 22:07:10.874384313 +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
+
+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)) && HAVE_KRB5_PAC
+#define MAX_PAC_GROUP_SIZE 200*60
+typedef struct {
+    uint16_t length;
+    uint16_t maxlength;
+    uint32_t pointer;
+} RPC_UNICODE_STRING;
+
+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-26 22:06:50.003383795 +0100
@@ -0,0 +1,455 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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)) && HAVE_KRB5_PAC
+
+#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);
+	    }
+	    safe_free(ag);
+	}
+
+	/* 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))) {
+                    debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",
+                                LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+		}
+		safe_free(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); 
+	    }
+        }
+	safe_free(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, (int)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, (int)ad_data->length);
+    if (Rids) {
+        for ( l=0; l<(int)GroupCount; l++) {
+	    safe_free(Rids[l]);
+        }
+        safe_free(Rids);
+    }
+    krb5_free_data(context, ad_data);
+    return ad_groups; 
+k5clean:
+    if (Rids) {
+        for ( l=0; l<(int)GroupCount; l++) {
+	    safe_free(Rids[l]);
+        }
+        safe_free(Rids);
+    }
+    krb5_free_data(context, ad_data);
+    return NULL;
+}
+#endif
diff -rubwBEN 3.4/helpers/negotiate_auth/kerberos/test_negotiate_auth.sh 3.4-mm/helpers/negotiate_auth/kerberos/test_negotiate_auth.sh
--- 3.4/helpers/negotiate_auth/kerberos/test_negotiate_auth.sh	1970-01-01 01:00:00.000000000 +0100
+++ 3.4-mm/helpers/negotiate_auth/kerberos/test_negotiate_auth.sh	2013-08-26 22:07:33.730384880 +0100
@@ -0,0 +1,7 @@
+#!/bin/bash
+if [[ -z "$1" ]]; then
+	echo "Need squid hostname"
+	exit 0
+fi
+dir=`dirname $0`
+$dir/negotiate_kerberos_auth_test $1 | awk '{sub(/Token:/,"YR"); print $0}END{print "QQ"}' | $dir/negotiate_kerberos_auth -d
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-26 22:02:02.226038000 +0100
+++ 3.4-mm/src/peer_proxy_negotiate_auth.cc	2013-08-26 22:08:04.895385652 +0100
@@ -210,21 +210,29 @@
         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;
+#if HAVE_KRB5_PRINCIPAL_GET_REALM
+        const char *client_realm;
+#else
+        krb5_realm client_realm;
+#endif
 #endif
         char *mem_cache;
 
@@ -236,7 +244,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,10 +264,15 @@
                            << 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);
+                                        (krb5_const_realm)&client_realm, KRB5_TGS_NAME, 
+				 	(krb5_const_realm)&client_realm, NULL);
                 if (code) {
                     debugs(11, 5,
                            HERE << "Error while getting krbtgt principal : " <<
@@ -400,7 +413,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 +425,18 @@
                        " : " << 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);
+#if HAVE_KRB5_GET_INIT_CREDS_FREE_CONTEXT
+	krb5_get_init_creds_opt_free(kparam.context, options);
+#else
+	krb5_get_init_creds_opt_free(options);
+#endif
+#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 +440,7 @@
             code =
                 krb5_get_init_creds_keytab(kparam.context, creds, principal,
                                            keytab, 0, NULL, &options);
+#endif
             if (code) {
                 debugs(11, 5,
                        HERE <<

