]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
negotiate_kerberos_auth: upgrade to present group= keys
authorMarkus Moeller <huaraz@moeller.plus.com>
Fri, 27 Sep 2013 15:21:54 +0000 (09:21 -0600)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 27 Sep 2013 15:21:54 +0000 (09:21 -0600)
Use the new kv-pair protocol extensions for emitting group details
directly at the time of authentication. group=X key-value pair is
used to emit the Kerberos SIDS values presented by MS Active
Directory environments.

Also, update the Hiemdal library support for recent library versions.

Also, polish the Kerberos and LDAP Group related code to avoid memory
leaks and improve C++ coding style.

18 files changed:
configure.ac
helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc
helpers/external_acl/kerberos_ldap_group/support.h
helpers/external_acl/kerberos_ldap_group/support_group.cc
helpers/external_acl/kerberos_ldap_group/support_krb5.cc
helpers/external_acl/kerberos_ldap_group/support_ldap.cc
helpers/external_acl/kerberos_ldap_group/support_log.cc
helpers/external_acl/kerberos_ldap_group/support_lserver.cc
helpers/external_acl/kerberos_ldap_group/support_netbios.cc
helpers/external_acl/kerberos_ldap_group/support_resolv.cc
helpers/external_acl/kerberos_ldap_group/support_sasl.cc
helpers/negotiate_auth/kerberos/Makefile.am
helpers/negotiate_auth/kerberos/negotiate_kerberos.h [new file with mode: 0644]
helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc
helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc
helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc [new file with mode: 0644]
helpers/negotiate_auth/kerberos/test_negotiate_auth.sh [new file with mode: 0755]
src/peer_proxy_negotiate_auth.cc

index 2f206d0cf743c0d5ad29ce7dcae9c24999a33706..60ff2c0b9b5393abad784f1364b53e3c73258a93 100644 (file)
@@ -1907,6 +1907,10 @@ if test "x$ac_krb5_config" = "xyes" ; then
     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]),)
@@ -1925,6 +1929,33 @@ if test "x$ac_krb5_config" = "xyes" ; then
   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,
index 6f0c1cd01b700ab9af5de1561a231b414209333d..8867366de44b49248f14212a2dbc7170559bc4e5 100644 (file)
@@ -65,7 +65,7 @@ init_args(struct main_args *margs)
 
 void clean_gd(struct gdstruct *gdsp);
 void clean_nd(struct ndstruct *ndsp);
-void clean_ls(struct ndstruct *lssp);
+void clean_ls(struct lsstruct *lssp);
 
 void
 clean_gd(struct gdstruct *gdsp)
@@ -78,22 +78,12 @@ clean_gd(struct gdstruct *gdsp)
             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);
+        if (pp)
+            safe_free(pp->next);
+        if (p == gdsp)
+            safe_free(gdsp);
         p = gdsp;
     }
 }
@@ -109,22 +99,12 @@ clean_nd(struct ndstruct *ndsp)
             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);
+        if (pp)
+            safe_free(pp->next);
+        if (p == ndsp)
+            safe_free(ndsp);
         p = ndsp;
     }
 }
@@ -140,22 +120,12 @@ clean_ls(struct lsstruct *lssp)
             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);
+        if (pp)
+            safe_free(pp->next);
+        if (p == lssp)
+            safe_free(lssp);
         p = lssp;
     }
 }
@@ -163,50 +133,17 @@ clean_ls(struct lsstruct *lssp)
 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 +350,8 @@ main(int argc, char *const argv[])
                 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 +373,8 @@ main(int argc, char *const argv[])
         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);
@@ -477,7 +414,7 @@ void
 strup(char *s)
 {
     while (*s) {
-        *s = toupper((unsigned char) *s);
+        *s = (char)toupper((unsigned char) *s);
         ++s;
     }
 }
index 5edd83e3dad2b00c214f792b18acf6819d239ba4..2f6bc6549c1d1767d8f61b5d80a6bbfaced1d4a1 100644 (file)
@@ -156,13 +156,13 @@ int create_nd(struct main_args *margs);
 int create_ls(struct main_args *margs);
 
 #ifdef HAVE_KRB5
-int krb5_create_cache(struct main_args *margs, char *domain);
+int krb5_create_cache(char *domain);
 void krb5_cleanup(void);
 #endif
 
-int get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *domain);
-int get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *name);
-int free_hostname_list(struct hstruct **hlist, int nhosts);
+size_t get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, size_t nhosts, char *domain);
+size_t get_hostname_list(struct hstruct **hlist, size_t nhosts, char *name);
+size_t free_hostname_list(struct hstruct **hlist, size_t nhosts);
 
 #if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
 int tool_sasl_bind(LDAP * ld, char *binddn, char *ssl);
index 3ff3cca29a10b1847c0a9f643a24dd2b425158d7..1b9209ce85d3bc88b260e0abd0acb0b828a23387 100644 (file)
@@ -31,6 +31,7 @@
 #include "support.h"
 
 struct gdstruct *init_gd(void);
+void free_gd(struct gdstruct *gdsp);
 
 struct gdstruct *
 init_gd(void) {
@@ -59,7 +60,8 @@ char *utf8dup(struct main_args *margs);
 char *
 utf8dup(struct main_args *margs)
 {
-    int c = 0, s;
+    size_t c = 0;
+    unsigned char s;
     size_t n;
     char *src;
     unsigned char *p, *dupp;
@@ -79,7 +81,7 @@ utf8dup(struct main_args *margs)
                 *p = 194;
                 ++p;
                 *p = s;
-            } else if (s > 191 && s < 256) {
+            } else if (s > 191) {
                 *p = 195;
                 ++p;
                 *p = s - 64;
@@ -121,7 +123,7 @@ hex_utf_char(struct main_args *margs, int flag)
         return NULL;
 
     char *upd = strrchr(up, '@');
-    size_t a = (upd ? (upd - up) : strlen(up) );
+    size_t a = (upd ? (size_t)(upd - up) : strlen(up) );
 
     char *ul = (char *) xmalloc(strlen(up)+1);
     size_t n = 0;
@@ -174,17 +176,17 @@ hex_utf_char(struct main_args *margs, int flag)
         if (iUTF2) {
             if (iUTF2 == 0xC2 && ichar > 0x7F && ichar < 0xC0) {
                 iUTF2 = 0;
-                ul[nl - 1] = ichar;
+                ul[nl - 1] = (char)ichar;
             } else if (iUTF2 == 0xC3 && ichar > 0x7F && ichar < 0xC0) {
                 iUTF2 = 0;
-                ul[nl - 1] = ichar + 64;
+                ul[nl - 1] = (char)(ichar + 64);
             } else if (iUTF2 > 0xC3 && iUTF2 < 0xE0 && ichar > 0x7F && ichar < 0xC0) {
                 iUTF2 = 0;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else {
                 iUTF2 = 0;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ul[nl + 1] = '\0';
                 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
                 xfree(ul);
@@ -193,27 +195,27 @@ hex_utf_char(struct main_args *margs, int flag)
         } else if (iUTF3) {
             if (iUTF3 == 0xE0 && ichar > 0x9F && ichar < 0xC0) {
                 iUTF3 = 1;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else if (iUTF3 > 0xE0 && iUTF3 < 0xED && ichar > 0x7F && ichar < 0xC0) {
                 iUTF3 = 2;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else if (iUTF3 == 0xED && ichar > 0x7F && ichar < 0xA0) {
                 iUTF3 = 3;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else if (iUTF3 > 0xED && iUTF3 < 0xF0 && ichar > 0x7F && ichar < 0xC0) {
                 iUTF3 = 4;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else if (iUTF3 > 0 && iUTF3 < 5 && ichar > 0x7F && ichar < 0xC0) {
                 iUTF3 = 0;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else {
                 iUTF3 = 0;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ul[nl + 1] = '\0';
                 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
                 xfree(ul);
@@ -222,26 +224,26 @@ hex_utf_char(struct main_args *margs, int flag)
         } else if (iUTF4) {
             if (iUTF4 == 0xF0 && ichar > 0x8F && ichar < 0xC0) {
                 iUTF4 = 1;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else if (iUTF4 > 0xF0 && iUTF3 < 0xF4 && ichar > 0x7F && ichar < 0xC0) {
                 iUTF4 = 2;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else if (iUTF4 == 0xF4 && ichar > 0x7F && ichar < 0x90) {
                 iUTF4 = 3;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else if (iUTF4 > 0 && iUTF4 < 5 && ichar > 0x7F && ichar < 0xC0) {
                 if (iUTF4 == 4)
                     iUTF4 = 0;
                 else
                     iUTF4 = 4;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ++nl;
             } else {
                 iUTF4 = 0;
-                ul[nl] = ichar;
+                ul[nl] = (char)ichar;
                 ul[nl + 1] = '\0';
                 debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
                 xfree(ul);
@@ -249,25 +251,25 @@ hex_utf_char(struct main_args *margs, int flag)
             }
         } else if (ichar < 0x80) {
             /* UTF1 */
-            ul[nl] = ichar;
+            ul[nl] = (char)ichar;
             ++nl;
         } else if (ichar > 0xC1 && ichar < 0xE0) {
             /* UTF2 (Latin) */
             iUTF2 = ichar;
-            ul[nl] = ichar;
+            ul[nl] = (char)ichar;
             ++nl;
         } else if (ichar > 0xDF && ichar < 0xF0) {
             /* UTF3 */
             iUTF3 = ichar;
-            ul[nl] = ichar;
+            ul[nl] = (char)ichar;
             ++nl;
         } else if (ichar > 0xEF && ichar < 0xF5) {
             /* UTF4 */
             iUTF4 = ichar;
-            ul[nl] = ichar;
+            ul[nl] = (char)ichar;
             ++nl;
         } else {
-            ul[nl] = ichar;
+            ul[nl] = (char)ichar;
             ul[nl + 1] = '\0';
             debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
             xfree(ul);
index b4dfc98ff785b22fbe4d1b05d99f6c349533bf42..eb0a4f9cb258113bc2a2925ec990558607a4aef8 100644 (file)
@@ -33,7 +33,9 @@ struct kstruct {
     krb5_context context;
     char *mem_cache_env;
     krb5_ccache cc;
-} kparam;
+};
+
+static struct kstruct kparam;
 
 #define KT_PATH_MAX 256
 
@@ -50,23 +52,20 @@ krb5_cleanup()
  * create Kerberos memory cache
  */
 int
-krb5_create_cache(struct main_args *margs, char *domain)
+krb5_create_cache(char *domain)
 {
 
     krb5_keytab keytab = 0;
     krb5_keytab_entry entry;
     krb5_kt_cursor cursor;
     krb5_creds *creds = NULL;
-    krb5_creds *tgt_creds = NULL;
     krb5_principal *principal_list = NULL;
     krb5_principal principal = NULL;
     char *service;
     char *keytab_name = NULL, *principal_name = NULL, *mem_cache = NULL;
     char buf[KT_PATH_MAX], *p;
-    int nprinc = 0;
-    int i;
+    size_t j,nprinc = 0;
     int retval = 0;
-    int found = 0;
     krb5_error_code code = 0;
 
     kparam.context = NULL;
@@ -112,6 +111,7 @@ krb5_create_cache(struct main_args *margs, char *domain)
 
     nprinc = 0;
     while ((code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor)) == 0) {
+        int found = 0;
 
         principal_list = (krb5_principal *) xrealloc(principal_list, sizeof(krb5_principal) * (nprinc + 1));
         krb5_copy_principal(kparam.context, entry.principal, &principal_list[nprinc++]);
@@ -182,12 +182,14 @@ krb5_create_cache(struct main_args *margs, char *domain)
      * if no principal name found in keytab for domain use the prinipal name which can get a TGT
      */
     if (!principal_name) {
+        size_t i;
         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) {
+            krb5_creds *tgt_creds = NULL;
+            creds = (krb5_creds *) xmalloc(sizeof(*creds));
+            memset(creds, 0, sizeof(*creds));
             /*
              * get credentials
              */
@@ -205,8 +207,7 @@ krb5_create_cache(struct main_args *margs, char *domain)
             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);
+            xfree(service);
             code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
 #endif
             if (code) {
@@ -233,8 +234,7 @@ krb5_create_cache(struct main_args *margs, char *domain)
             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);
+            xfree(service);
             if (code) {
                 error((char *) "%s| %s: ERROR: Error while initialising TGT credentials : %s\n", LogTime(), PROGRAM, error_message(code));
                 goto loop_end;
@@ -245,19 +245,22 @@ krb5_create_cache(struct main_args *margs, char *domain)
                 goto loop_end;
             } else {
                 debug((char *) "%s| %s: DEBUG: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name);
-                found = 1;
                 break;
             }
 
 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;
+
         }
 
-        if (tgt_creds)
-            krb5_free_creds(kparam.context, tgt_creds);
-        tgt_creds = NULL;
+        safe_free(principal_name);
         if (creds)
             krb5_free_creds(kparam.context, creds);
         creds = NULL;
@@ -287,8 +290,7 @@ loop_end:
         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);
+        xfree(service);
         code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
 #endif
         if (code) {
@@ -316,20 +318,16 @@ loop_end:
 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);
+    xfree(keytab_name);
+    xfree(principal_name);
+    xfree(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]);
+    for (j = 0; j < nprinc; ++j) {
+        if (principal_list[j])
+            krb5_free_principal(kparam.context, principal_list[j]);
     }
-    if (principal_list)
-        xfree(principal_list);
+    xfree(principal_list);
     if (creds)
         krb5_free_creds(kparam.context, creds);
 
index 3069fe2911716ded988e286ebd3a6dafd3c9cdec..cf34404a2a7a5a349b0319b711f065f331b50075 100644 (file)
@@ -35,7 +35,7 @@
 char *convert_domain_to_bind_path(char *domain);
 char *escape_filter(char *filter);
 int check_AD(struct main_args *margs, LDAP * ld);
-int ldap_set_defaults(struct main_args *margs, LDAP * ld);
+int ldap_set_defaults(LDAP * ld);
 int ldap_set_ssl_defaults(struct main_args *margs);
 LDAP *tool_ldap_open(struct main_args *margs, char *host, int port, char *ssl);
 
@@ -51,7 +51,7 @@ LDAP *tool_ldap_open(struct main_args *margs, char *host, int port, char *ssl);
 #define FILTER_AD "(samaccountname=%s)"
 #define ATTRIBUTE_AD "memberof"
 
-int get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
+size_t get_attributes(LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
 int search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth);
 
 #if defined(HAVE_SUN_LDAP_SDK) || defined(HAVE_MOZILLA_LDAP_SDK)
@@ -210,7 +210,7 @@ char *
 convert_domain_to_bind_path(char *domain)
 {
     char *dp, *bindp = NULL, *bp = NULL;
-    int i = 0;
+    size_t i = 0;
 
     if (!domain)
         return NULL;
@@ -243,8 +243,8 @@ convert_domain_to_bind_path(char *domain)
 char *
 escape_filter(char *filter)
 {
-    int i;
     char *ldap_filter_esc, *ldf;
+    size_t i;
 
     i = 0;
     for (ldap_filter_esc = filter; *ldap_filter_esc; ++ldap_filter_esc) {
@@ -278,7 +278,7 @@ escape_filter(char *filter)
     *ldf = '\0';
 
     return ldap_filter_esc;
-};
+}
 
 int
 check_AD(struct main_args *margs, LDAP * ld)
@@ -286,8 +286,8 @@ check_AD(struct main_args *margs, LDAP * ld)
     LDAPMessage *res;
     char **attr_value = NULL;
     struct timeval searchtime;
-    int max_attr = 0;
-    int j, rc = 0;
+    size_t max_attr = 0;
+    int rc = 0;
 
 #define FILTER_SCHEMA "(objectclass=*)"
 #define ATTRIBUTE_SCHEMA "schemaNamingContext"
@@ -301,7 +301,7 @@ check_AD(struct main_args *margs, LDAP * ld)
                            NULL, NULL, &searchtime, 0, &res);
 
     if (rc == LDAP_SUCCESS)
-        max_attr = get_attributes(margs, ld, res, ATTRIBUTE_SCHEMA, &attr_value);
+        max_attr = get_attributes(ld, res, ATTRIBUTE_SCHEMA, &attr_value);
 
     if (max_attr == 1) {
         ldap_msgfree(res);
@@ -318,11 +318,11 @@ check_AD(struct main_args *margs, LDAP * ld)
      * Cleanup
      */
     if (attr_value) {
+        size_t j;
         for (j = 0; j < max_attr; ++j) {
             xfree(attr_value[j]);
         }
-        xfree(attr_value);
-        attr_value = NULL;
+        safe_free(attr_value);
     }
     ldap_msgfree(res);
     return rc;
@@ -332,11 +332,11 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
 {
     LDAPMessage *res = NULL;
     char **attr_value = NULL;
-    int max_attr = 0;
+    size_t max_attr = 0;
     char *filter = NULL;
     char *search_exp = NULL;
-    int j, rc = 0, retval = 0;
-    char *av = NULL, *avp = NULL;
+    size_t j;
+    int rc = 0, retval = 0;
     int ldepth;
     char *ldap_filter_esc = NULL;
     struct timeval searchtime;
@@ -378,9 +378,9 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
     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");
 
     if (margs->AD)
-        max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
+        max_attr = get_attributes(ld, res, ATTRIBUTE_AD, &attr_value);
     else
-        max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
+        max_attr = get_attributes(ld, res, ATTRIBUTE, &attr_value);
 
     /*
      * Compare group names
@@ -388,10 +388,12 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
     retval = 0;
     ldepth = depth + 1;
     for (j = 0; j < max_attr; ++j) {
+        char *av = NULL;
 
         /* Compare first CN= value assuming it is the same as the group name itself */
         av = attr_value[j];
         if (!strncasecmp("CN=", av, 3)) {
+            char *avp = NULL;
             av += 3;
             if ((avp = strchr(av, ','))) {
                 *avp = '\0';
@@ -399,17 +401,17 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
         }
         if (debug_enabled) {
             int n;
-            debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
+            debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
             for (n = 0; av[n] != '\0'; ++n)
                 fprintf(stderr, "%02x", (unsigned char) av[n]);
             fprintf(stderr, "\n");
         }
         if (!strcasecmp(group, av)) {
             retval = 1;
-            debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+            debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
             break;
         } else
-            debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+            debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
         /*
          * Do recursive group search
          */
@@ -418,13 +420,14 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
         if (search_group_tree(margs, ld, bindp, av, group, ldepth)) {
             retval = 1;
             if (!strncasecmp("CN=", av, 3)) {
+                char *avp = NULL;
                 av += 3;
                 if ((avp = strchr(av, ','))) {
                     *avp = '\0';
                 }
             }
             if (debug_enabled)
-                debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+                debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
             else
                 break;
 
@@ -438,8 +441,7 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
         for (j = 0; j < max_attr; ++j) {
             xfree(attr_value[j]);
         }
-        xfree(attr_value);
-        attr_value = NULL;
+        safe_free(attr_value);
     }
     ldap_msgfree(res);
 
@@ -447,7 +449,7 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
 }
 
 int
-ldap_set_defaults(struct main_args *margs, LDAP * ld)
+ldap_set_defaults(LDAP * ld)
 {
     int val, rc = 0;
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
@@ -484,14 +486,14 @@ ldap_set_ssl_defaults(struct main_args *margs)
 #endif
 #ifdef HAVE_OPENLDAP
     int val;
-    char *ssl_cacertfile = NULL;
-    int free_path;
 #elif defined(HAVE_LDAPSSL_CLIENT_INIT)
     char *ssl_certdbpath = NULL;
 #endif
 
 #ifdef HAVE_OPENLDAP
     if (!margs->rc_allow) {
+        char *ssl_cacertfile = NULL;
+        int free_path;
         debug((char *) "%s| %s: DEBUG: Enable server certificate check for ldap server.\n", LogTime(), PROGRAM);
         val = LDAP_OPT_X_TLS_DEMAND;
         rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
@@ -509,7 +511,6 @@ ldap_set_ssl_defaults(struct main_args *margs)
         rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ssl_cacertfile);
         if (ssl_cacertfile && free_path) {
             xfree(ssl_cacertfile);
-            ssl_cacertfile = NULL;
         }
         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 +544,7 @@ ldap_set_ssl_defaults(struct main_args *margs)
         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;
-    }
+    xfree(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;
@@ -557,13 +555,13 @@ ldap_set_ssl_defaults(struct main_args *margs)
     return LDAP_SUCCESS;
 }
 
-int
-get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
+size_t
+get_attributes(LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
 {
 
     LDAPMessage *msg;
     char **attr_value = NULL;
-    int max_attr = 0;
+    size_t max_attr = 0;
 
     attr_value = *ret_value;
     /*
@@ -588,15 +586,15 @@ get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char
                     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);
                 }
@@ -615,7 +613,7 @@ get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char
         }
     }
 
-    debug((char *) "%s| %s: DEBUG: %d ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
+    debug((char *) "%s| %s: DEBUG: %ld ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
 
     *ret_value = attr_value;
     return max_attr;
@@ -661,13 +659,13 @@ tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
         xfree(ldapuri);
-        xfree(url);
+        ldap_free_urldesc(url);
         return NULL;
     }
 #else
 #error "No URL parsing function"
 #endif
-    safe_free(url);
+    ldap_free_urldesc(url);
     rc = ldap_initialize(&ld, ldapuri);
     xfree(ldapuri);
     if (rc != LDAP_SUCCESS) {
@@ -679,7 +677,7 @@ tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
 #else
     ld = ldap_init(host, port);
 #endif
-    rc = ldap_set_defaults(margs, ld);
+    rc = ldap_set_defaults(ld);
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
         ldap_unbind(ld);
@@ -726,13 +724,13 @@ tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
             if (rc != LDAP_SUCCESS) {
                 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
                 xfree(ldapuri);
-                xfree(url);
+                ldap_free_urldesc(url);
                 return NULL;
             }
 #else
 #error "No URL parsing function"
 #endif
-            safe_free(url);
+            ldap_free_urldesc(url);
             rc = ldap_initialize(&ld, ldapuri);
             xfree(ldapuri);
             if (rc != LDAP_SUCCESS) {
@@ -741,7 +739,7 @@ tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
                 ld = NULL;
                 return NULL;
             }
-            rc = ldap_set_defaults(margs, ld);
+            rc = ldap_set_defaults(ld);
             if (rc != LDAP_SUCCESS) {
                 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
                 ldap_unbind(ld);
@@ -757,7 +755,7 @@ tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
             ld = NULL;
             return NULL;
         }
-        rc = ldap_set_defaults(margs, ld);
+        rc = ldap_set_defaults(ld);
         if (rc != LDAP_SUCCESS) {
             error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
             ldap_unbind(ld);
@@ -787,18 +785,12 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
     char *filter = NULL;
     char *search_exp;
     struct timeval searchtime;
-    int i, j, rc = 0, kc = 1;
+    int rc = 0, kc = 1;
     int retval;
     char **attr_value = NULL;
-    char *av = NULL, *avp = NULL;
-    int max_attr = 0;
+    size_t max_attr = 0;
     struct hstruct *hlist = NULL;
-    int nhosts = 0;
-    char *hostname;
-    char *host;
-    int port;
-    char *ssl = NULL;
-    char *p;
+    size_t nhosts = 0;
     char *ldap_filter_esc = NULL;
 
     searchtime.tv_sec = SEARCH_TIMEOUT;
@@ -810,7 +802,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
         debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM);
 
 #ifdef HAVE_KRB5
-        kc = krb5_create_cache(margs, domain);
+        kc = krb5_create_cache(domain);
         if (kc) {
             error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM);
         }
@@ -839,6 +831,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
     debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM);
 
     if (domain && !kc) {
+        size_t i;
         if (margs->ssl) {
             debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
         }
@@ -848,7 +841,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
          */
         nhosts = get_ldap_hostname_list(margs, &hlist, 0, domain);
         for (i = 0; i < nhosts; ++i) {
-            port = 389;
+            int port = 389;
             if (hlist[i].port != -1)
                 port = hlist[i].port;
             debug((char *) "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n", LogTime(), PROGRAM, hlist[i].host, port);
@@ -893,6 +886,12 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
         bindp = convert_domain_to_bind_path(domain);
     }
     if ((!domain || !ld) && margs->lurl && strstr(margs->lurl, "://")) {
+        char *hostname;
+        char *host;
+        int port;
+        char *ssl = NULL;
+        char *p;
+        size_t i;
         /*
          * If username does not contain a domain and a url was given then try it
          */
@@ -912,8 +911,8 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
             ++p;
             port = atoi(p);
         }
-        nhosts = get_hostname_list(margs, &hlist, 0, host);
-        safe_free(host);
+        nhosts = get_hostname_list(&hlist, 0, host);
+        xfree(host);
         for (i = 0; i < nhosts; ++i) {
 
             ld = tool_ldap_open(margs, hlist[i].host, port, ssl);
@@ -995,22 +994,25 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
     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");
 
     if (ldap_count_entries(ld, res) != 0) {
+        size_t k;
 
         if (margs->AD)
-            max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
+            max_attr = get_attributes(ld, res, ATTRIBUTE_AD, &attr_value);
         else {
-            max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
+            max_attr = get_attributes(ld, res, ATTRIBUTE, &attr_value);
         }
 
         /*
          * Compare group names
          */
         retval = 0;
-        for (j = 0; j < max_attr; ++j) {
+        for (k = 0; k < max_attr; ++k) {
+            char *av = NULL;
 
             /* Compare first CN= value assuming it is the same as the group name itself */
-            av = attr_value[j];
+            av = attr_value[k];
             if (!strncasecmp("CN=", av, 3)) {
+                char *avp = NULL;
                 av += 3;
                 if ((avp = strchr(av, ','))) {
                     *avp = '\0';
@@ -1018,7 +1020,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
             }
             if (debug_enabled) {
                 int n;
-                debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
+                debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, k + 1, av);
                 for (n = 0; av[n] != '\0'; ++n)
                     fprintf(stderr, "%02x", (unsigned char) av[n]);
                 fprintf(stderr, "\n");
@@ -1026,32 +1028,35 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
             if (!strcasecmp(group, av)) {
                 retval = 1;
                 if (debug_enabled)
-                    debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+                    debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, k + 1, av, group);
                 else
                     break;
             } else
-                debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+                debug((char *) "%s| %s: DEBUG: Entry %ld \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, k + 1, av, group);
         }
         /*
          * Do recursive group search for AD only since posixgroups can not contain other groups
          */
         if (!retval && margs->AD) {
+            size_t j;
             if (debug_enabled && max_attr > 0) {
                 debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM);
             }
             for (j = 0; j < max_attr; ++j) {
+                char *av = NULL;
 
                 av = attr_value[j];
                 if (search_group_tree(margs, ld, bindp, av, group, 1)) {
                     retval = 1;
                     if (!strncasecmp("CN=", av, 3)) {
+                        char *avp = NULL;
                         av += 3;
                         if ((avp = strchr(av, ','))) {
                             *avp = '\0';
                         }
                     }
                     if (debug_enabled)
-                        debug((char *) "%s| %s: DEBUG: Entry %d group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
+                        debug((char *) "%s| %s: DEBUG: Entry %ld group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
                     else
                         break;
                 }
@@ -1061,11 +1066,11 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
          * Cleanup
          */
         if (attr_value) {
+            size_t j;
             for (j = 0; j < max_attr; ++j) {
                 xfree(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) {
@@ -1101,11 +1106,11 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
 
         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");
 
-        max_attr = get_attributes(margs, ld, res, ATTRIBUTE_GID, &attr_value);
+        max_attr = get_attributes(ld, res, ATTRIBUTE_GID, &attr_value);
 
         if (max_attr == 1) {
             char **attr_value_2 = NULL;
-            int max_attr_2 = 0;
+            size_t max_attr_2 = 0;
 
             ldap_msgfree(res);
             filter = (char *) FILTER_GID;
@@ -1123,15 +1128,14 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
                                    NULL, NULL, &searchtime, 0, &res);
             xfree(search_exp);
 
-            max_attr_2 = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value_2);
+            max_attr_2 = get_attributes(ld, res, ATTRIBUTE, &attr_value_2);
             /*
              * Compare group names
              */
             retval = 0;
             if (max_attr_2 == 1) {
-
                 /* Compare first CN= value assuming it is the same as the group name itself */
-                av = attr_value_2[0];
+                char *av = attr_value_2[0];
                 if (!strcasecmp(group, av)) {
                     retval = 1;
                     debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, av, group);
@@ -1143,11 +1147,11 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
              * Cleanup
              */
             if (attr_value_2) {
+                size_t j;
                 for (j = 0; j < max_attr_2; ++j) {
                     xfree(attr_value_2[j]);
                 }
-                xfree(attr_value_2);
-                attr_value_2 = NULL;
+                safe_free(attr_value_2);
             }
             ldap_msgfree(res);
 
@@ -1161,11 +1165,11 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
          * Cleanup
          */
         if (attr_value) {
+            size_t j;
             for (j = 0; j < max_attr; ++j) {
                 xfree(attr_value[j]);
             }
-            xfree(attr_value);
-            attr_value = NULL;
+            safe_free(attr_value);
         }
     }
     rc = ldap_unbind(ld);
index fceec56315ea191a16b50856de8e3165d45fcfcc..56bcdab05e059ec24544426b2eb395c23598f6e9 100644 (file)
 const char *
 LogTime()
 {
-    struct tm *tm;
-    struct timeval now;
     static time_t last_t = 0;
+    struct timeval now;
     static char buf[128];
 
     gettimeofday(&now, NULL);
     if (now.tv_sec != last_t) {
+        struct tm *tm;
         time_t tmp = now.tv_sec;
         tm = localtime(&tmp);
         strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
index d7e4bd018323c7e3e14007d0320e6e0573a20e47..29e2932595857315fd27ab82ed08807a61b805aa 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "support.h"
 struct lsstruct *init_ls(void);
+void free_ls(struct lsstruct *lssp);
 
 struct lsstruct *
 init_ls(void) {
index 6d2269a65c987ff38f7ec4d5474ce9eeb949dd87..86b5eb3d0e03e6c71d7e9cf14199fae519c5ca99 100644 (file)
@@ -30,6 +30,7 @@
 #include "support.h"
 
 struct ndstruct *init_nd(void);
+void free_nd(struct ndstruct *ndsp);
 
 struct ndstruct *
 init_nd(void) {
index e984f4ee5162a356e48c8bcb27d93e474d20b751..8df8fd2fff501b24c5d0bfc081d8fac3cd8857dd 100644 (file)
@@ -95,10 +95,10 @@ static void
 sort(struct hstruct *array, int nitems, int (*cmp) (struct hstruct *, struct hstruct *), int begin, int end)
 {
     if (end > begin) {
-        int pivot = begin;
         int l = begin + 1;
         int r = end;
         while (l < r) {
+            int pivot = begin;
             if (cmp(&array[l], &array[pivot]) <= 0) {
                 l += 1;
             } else {
@@ -116,7 +116,7 @@ sort(struct hstruct *array, int nitems, int (*cmp) (struct hstruct *, struct hst
 static void
 msort(struct hstruct *array, size_t nitems, int (*cmp) (struct hstruct *, struct hstruct *))
 {
-    sort(array, nitems, cmp, 0, nitems - 1);
+    sort(array, (int)nitems, cmp, 0, (int)(nitems - 1));
 }
 
 static int
@@ -145,33 +145,25 @@ compare_hosts(struct hstruct *host1, struct hstruct *host2)
     return 0;
 }
 
-int
-free_hostname_list(struct hstruct **hlist, int nhosts)
+size_t
+free_hostname_list(struct hstruct **hlist, size_t nhosts)
 {
     struct hstruct *hp = NULL;
-    int i;
+    size_t i;
 
     hp = *hlist;
     for (i = 0; i < nhosts; ++i) {
-        if (hp[i].host)
-            xfree(hp[i].host);
-        hp[i].host = NULL;
+        xfree(hp[i].host);
     }
 
-    if (hp)
-        xfree(hp);
-    hp = NULL;
+    safe_free(hp);
     *hlist = hp;
     return 0;
 }
 
-int
-get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, char *name)
+size_t
+get_hostname_list(struct hstruct **hlist, size_t nhosts, char *name)
 {
-    /*
-     * char host[sysconf(_SC_HOST_NAME_MAX)];
-     */
-    char host[1024];
     struct addrinfo *hres = NULL, *hres_list;
     int rc, count;
     struct hstruct *hp = NULL;
@@ -194,6 +186,10 @@ get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, c
     hres_list = hres;
     count = 0;
     while (hres_list) {
+        /*
+         * char host[sysconf(_SC_HOST_NAME_MAX)];
+         */
+        char host[1024];
         rc = getnameinfo(hres_list->ai_addr, hres_list->ai_addrlen, host, sizeof(host), NULL, 0, 0);
         if (rc != 0) {
             error((char *) "%s| %s: ERROR: Error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc));
@@ -219,24 +215,21 @@ get_hostname_list(struct main_args *margs, struct hstruct **hlist, int nhosts, c
     return (nhosts);
 }
 
-int
-get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh, char *domain)
+size_t
+get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, size_t nh, char *domain)
 {
 
     /*
      * char name[sysconf(_SC_HOST_NAME_MAX)];
      */
     char name[1024];
-    char host[NS_MAXDNAME];
     char *service = NULL;
     struct hstruct *hp = NULL;
     struct lsstruct *ls = NULL;
-    int nhosts = 0;
+    size_t nhosts = 0;
     int size;
-    int type, rdlength;
-    int priority, weight, port;
     int len, olen;
-    int i, j, k;
+    size_t i, j, k;
     u_char *buffer = NULL;
     u_char *p;
 
@@ -305,7 +298,7 @@ get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh,
     }
     if (len > PACKETSZ_MULT * NS_PACKETSZ) {
         olen = len;
-        buffer = (u_char *) xrealloc(buffer, len);
+        buffer = (u_char *) xrealloc(buffer, (size_t)len);
         if ((len = res_search(service, ns_c_in, ns_t_srv, (u_char *) buffer, len)) < 0) {
             error((char *) "%s| %s: ERROR: Error while resolving service record %s with res_search\n", LogTime(), PROGRAM, service);
             nsError(h_errno, service);
@@ -322,7 +315,7 @@ get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh,
         error((char *) "%s| %s: ERROR: Message to small: %d < header size\n", LogTime(), PROGRAM, len);
         goto finalise;
     }
-    if ((size = dn_expand(buffer, buffer + len, p, name, sysconf(_SC_HOST_NAME_MAX))) < 0) {
+    if ((size = dn_expand(buffer, buffer + len, p, name, sizeof(name))) < 0) {
         error((char *) "%s| %s: ERROR: Error while expanding query name with dn_expand:  %s\n", LogTime(), PROGRAM, strerror(errno));
         goto finalise;
     }
@@ -333,7 +326,8 @@ get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh,
         goto finalise;
     }
     while (p < buffer + len) {
-        if ((size = dn_expand(buffer, buffer + len, p, name, sysconf(_SC_HOST_NAME_MAX))) < 0) {
+        int type, rdlength;
+        if ((size = dn_expand(buffer, buffer + len, p, name, sizeof(name))) < 0) {
             error((char *) "%s| %s: ERROR: Error while expanding answer name with dn_expand:  %s\n", LogTime(), PROGRAM, strerror(errno));
             goto finalise;
         }
@@ -351,6 +345,8 @@ get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh,
         NS_GET16(rdlength, p); /* RR data length (16bit) */
 
         if (type == ns_t_srv) {        /* SRV record */
+            int priority, weight, port;
+            char host[NS_MAXDNAME];
             if (p > buffer + len) {
                 error((char *) "%s| %s: ERROR: Message to small: %d < header + query name,type,class + answer name + RR type,class,ttl + RR data length\n", LogTime(), PROGRAM, len);
                 goto finalise;
@@ -400,7 +396,7 @@ get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, int nh,
     }
 
 finalise:
-    nhosts = get_hostname_list(margs, &hp, nh, domain);
+    nhosts = get_hostname_list(&hp, nh, domain);
 
     debug("%s| %s: DEBUG: Adding %s to list\n", LogTime(), PROGRAM, domain);
 
@@ -435,7 +431,7 @@ cleanup:
     }
 
     /* Sort by Priority / Weight */
-    msort(hp, nhosts, compare_hosts);
+    msort(hp, (size_t)nhosts, compare_hosts);
 
     if (debug_enabled) {
         debug((char *) "%s| %s: DEBUG: Sorted ldap server names for domain %s:\n", LogTime(), PROGRAM, domain);
@@ -443,10 +439,8 @@ cleanup:
             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);
+    xfree(buffer);
+    xfree(service);
     *hlist = hp;
     return (nhosts);
 }
index dd0c9f2beb62a1cc1d68c4e9aa9376eb75d0d3ad..a3ca2fffcc4ef563363074e2506f3b3a645131a0 100644 (file)
@@ -196,18 +196,12 @@ lutil_sasl_freedefs(
 {
     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);
+    xfree(defs->mech);
+    xfree(defs->realm);
+    xfree(defs->authcid);
+    xfree(defs->passwd);
+    xfree(defs->authzid);
+    xfree(defs->resps);
 
     xfree(defs);
 }
index 4d6f4e8e9ad140a019dd4622e7024b4add5f2796..83772615a6b1f0185dfc3ffcd0249b0b83fb4a2d 100644 (file)
@@ -7,7 +7,7 @@ libexec_PROGRAMS = negotiate_kerberos_auth negotiate_kerberos_auth_test
 
 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 --git a/helpers/negotiate_auth/kerberos/negotiate_kerberos.h b/helpers/negotiate_auth/kerberos/negotiate_kerberos.h
new file mode 100644 (file)
index 0000000..82277e1
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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 sout);
+
+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 HAVE_PAC_SUPPORT 1
+#define MAX_PAC_GROUP_SIZE 200*60
+typedef struct {
+    uint16_t length;
+    uint16_t maxlength;
+    uint32_t pointer;
+} RPC_UNICODE_STRING;
+
+int check_k5_err(krb5_context context, const char *msg, krb5_error_code code);
+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);
+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);
+#else
+#define HAVE_PAC_SUPPORT 0
+#endif
index d7b35a8b5e4f063207da6f2a24615388f759d27a..7668ac0abaac1b313db8bb8a70f005dd3293e175 100644 (file)
 
 #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 @@ gethost_name(void)
 
 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,7 +126,8 @@ check_gss_err(OM_uint32 major_status, OM_uint32 minor_status,
             gss_release_buffer(&min_stat, &status_string);
         } while (msg_ctx);
         debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
-        fprintf(stdout, "BH %s failed: %s\n", 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(),
                     PROGRAM);
@@ -213,7 +142,20 @@ main(int argc, char *const argv[])
     char buf[MAX_AUTHTOKEN_LEN];
     char *c, *p;
     char *user = NULL;
-    int length = 0;
+    char *rfc_user = NULL;
+#if HAVE_PAC_SUPPORT
+    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
+    long length = 0;
     static int err = 0;
     int opt, log = 0, norealm = 0;
     OM_uint32 ret_flags = 0, spnego_flag = 0;
@@ -284,6 +226,7 @@ main(int argc, char *const argv[])
         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);
     }
 
     while (1) {
@@ -312,7 +255,7 @@ main(int argc, char *const argv[])
             err = 0;
             continue;
         }
-        debug((char *) "%s| %s: DEBUG: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf, length);
+        debug((char *) "%s| %s: DEBUG: Got '%s' from squid (length: %ld).\n", LogTime(), PROGRAM, buf, length);
 
         if (buf[0] == '\0') {
             debug((char *) "%s| %s: ERROR: Invalid request\n", LogTime(), PROGRAM);
@@ -338,23 +281,13 @@ main(int argc, char *const argv[])
             if (kerberosToken) {
                 /* Allocated by parseNegTokenInit, but no matching free function exists.. */
                 if (!spnego_flag)
-                    xfree((char *) kerberosToken);
-                kerberosToken = NULL;
+                    xfree(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;
+                xfree(spnegoToken);
             }
+            xfree(token);
             fprintf(stdout, "BH quit command\n");
             exit(0);
         }
@@ -373,12 +306,12 @@ main(int argc, char *const argv[])
             fprintf(stdout, "BH Invalid negotiate request\n");
             continue;
         }
-        input_token.length = base64_decode_len(buf+3);
+        input_token.length = (size_t)base64_decode_len(buf+3);
         debug((char *) "%s| %s: DEBUG: Decode '%s' (decoded length: %d).\n",
               LogTime(), PROGRAM, buf + 3, (int) input_token.length);
         input_token.value = xmalloc(input_token.length);
 
-        input_token.length = base64_decode((char *) input_token.value, input_token.length, buf+3);
+        input_token.length = (size_t)base64_decode((char *) input_token.value, (unsigned int)input_token.length, buf+3);
 
         if ((input_token.length >= sizeof ntlmProtocol + 1) &&
                 (!memcmp(input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
@@ -399,19 +332,20 @@ main(int argc, char *const argv[])
             } else {
                 server_name = GSS_C_NO_NAME;
                 major_status = GSS_S_COMPLETE;
+                minor_status = 0;
             }
         } else {
             major_status = gss_import_name(&minor_status, &service,
                                            gss_nt_service_name, &server_name);
         }
 
-        if (check_gss_err(major_status, minor_status, "gss_import_name()", 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,
@@ -424,16 +358,16 @@ main(int argc, char *const argv[])
         if (output_token.length) {
             spnegoToken = (const unsigned char *) output_token.value;
             spnegoTokenLength = output_token.length;
-            token = (char *) xmalloc(base64_encode_len(spnegoTokenLength));
+            token = (char *) xmalloc((size_t)base64_encode_len((int)spnegoTokenLength));
             if (token == NULL) {
                 debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                 fprintf(stdout, "BH Not enough memory\n");
                 goto cleanup;
             }
-            base64_encode_str(token, base64_encode_len(spnegoTokenLength),
-                              (const char *) spnegoToken, spnegoTokenLength);
+            base64_encode_str(token, base64_encode_len((int)spnegoTokenLength),
+                              (const char *) spnegoToken, (int)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 @@ main(int argc, char *const argv[])
                 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 @@ main(int argc, char *const argv[])
             if (norealm && (p = strchr(user, '@')) != NULL) {
                 *p = '\0';
             }
+
+#if HAVE_PAC_SUPPORT
+            ret = krb5_init_context(&context);
+            if (!check_k5_err(context, "krb5_init_context", ret)) {
+#if HAVE_HEIMDAL_KERBEROS
+#define ADWIN2KPAC 128
+                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 @@ main(int argc, char *const argv[])
                 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,14 @@ cleanup:
         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;
     }
 }
index 0299f5345630d75d67719fea2581bae125d9748b..141ab82adf0444f70c2ad1d8c4b768e5acf1d43f 100644 (file)
@@ -196,9 +196,9 @@ squid_kerb_proxy_auth(char *proxy)
         goto cleanup;
 
     if (output_token.length) {
-        token = (char *) xmalloc(base64_encode_len(output_token.length));
-        base64_encode_str(token, base64_encode_len(output_token.length),
-                          (const char *) output_token.value, output_token.length);
+        token = (char *) xmalloc((size_t)base64_encode_len((int)output_token.length));
+        base64_encode_str(token, base64_encode_len((int)output_token.length),
+                          (const char *) output_token.value, (int)output_token.length);
     }
 cleanup:
     gss_delete_sec_context(&minor_status, &gss_context, NULL);
diff --git a/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc b/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc
new file mode 100644 (file)
index 0000000..27901ef
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * -----------------------------------------------------------------------------
+ *
+ * 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"
+
+#include "negotiate_kerberos.h"
+
+#if HAVE_PAC_SUPPORT
+
+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 = (uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
+    string->maxlength = (uint16_t)((p[bpos+2]<<0) | (p[bpos+2+1]<<8));
+    string->pointer = (uint32_t)((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 = ((uint64_t)p[bpos+5]<<0) | ((uint64_t)p[bpos+4]<<8) | ((uint64_t)p[bpos+3]<<16) | ((uint64_t)p[bpos+2]<<24) | ((uint64_t)p[bpos+1]<<32) | ((uint64_t)p[bpos]<<40);
+    bpos = bpos+6;
+
+    return var;
+}
+
+uint32_t
+get4byt(void)
+{
+    uint32_t var;
+
+    var=(uint32_t)((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=(uint16_t)((p[bpos]<<0) | (p[bpos+1]<<8));
+    bpos = bpos+2;
+
+    return var;
+}
+
+uint8_t
+get1byt(void)
+{
+    uint8_t var;
+
+    var=(uint8_t)((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 = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
+        bpos = bpos+4;
+        off = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
+        bpos = bpos+4;
+        len = (uint32_t)((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;
+        size_t 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, (int)(length+4)))) {
+                debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",
+                      LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
+            }
+            xfree(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)
+{
+    if (ExtraSids!= 0) {
+        uint32_t ngroup;
+        uint32_t *pa;
+        char *ag;
+        size_t 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, (int)length))) {
+                    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, (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))==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++) {
+            xfree(Rids[l]);
+        }
+        xfree(Rids);
+    }
+    krb5_free_data(context, ad_data);
+    return ad_groups;
+k5clean:
+    if (Rids) {
+        for ( l=0; l<(int)GroupCount; l++) {
+            xfree(Rids[l]);
+        }
+        xfree(Rids);
+    }
+    krb5_free_data(context, ad_data);
+    return NULL;
+}
+#endif
diff --git a/helpers/negotiate_auth/kerberos/test_negotiate_auth.sh b/helpers/negotiate_auth/kerberos/test_negotiate_auth.sh
new file mode 100755 (executable)
index 0000000..0d4b385
--- /dev/null
@@ -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
index 845e85320b3967caee34a1ac90bac03f9c041cb7..0098581a7cc53776fd1e6567bf5dfe3c7ff1b0d0 100644 (file)
@@ -210,21 +210,29 @@ extern "C" {
         static krb5_keytab_entry entry;
         static krb5_kt_cursor cursor;
         static krb5_creds *creds = NULL;
-#if HAVE_HEIMDAL_KERBEROS
+#if HAVE_HEIMDAL_KERBEROS && !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 HAVE_HEIMDAL_KERBEROS && !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 @@ restart:
                 (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 @@ restart:
                            << 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 @@ restart:
 
             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,11 +425,22 @@ restart:
                        " : " << 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);
+#endif
             if (code) {
                 debugs(11, 5,
                        HERE <<