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 ]) + AC_CHECK_TYPE(krb5_pac, + AC_DEFINE(HAVE_KRB5_PAC,1, + [Define to 1 if you have krb5_pac]),, + [#include ]) 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_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-27 23:56:05.668688680 +0100 @@ -78,22 +78,11 @@ 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); + safe_free(gdsp); p = gdsp; } } @@ -109,22 +98,11 @@ 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); + safe_free(ndsp); p = ndsp; } } @@ -140,22 +118,11 @@ 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); + safe_free(lssp); p = lssp; } } @@ -163,50 +130,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 +347,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 +370,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 -#endif -#if HAVE_STDOI_H -#include -#endif -#if HAVE_NETDB_H -#include -#endif -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_TIME_H -#include -#endif - -#include "util.h" -#include "base64.h" - -#if HAVE_GSSAPI_GSSAPI_H -#include -#elif HAVE_GSSAPI_H -#include -#endif - -#if !HAVE_HEIMDAL_KERBEROS -#if HAVE_GSSAPI_GSSAPI_KRB5_H -#include -#endif -#if HAVE_GSSAPI_GSSAPI_GENERIC_H -#include -#endif -#if HAVE_GSSAPI_GSSAPI_EXT_H -#include -#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 +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_TIME_H +#include +#endif + +#include "util.h" +#include "base64.h" + +#if HAVE_KRB5_H +#if HAVE_BROKEN_SOLARIS_KRB5_H +#warn "Warning! You have a broken Solaris 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 +} +#else +#include +#endif +#endif /* HAVE_KRB5_H */ + +#if HAVE_GSSAPI_GSSAPI_H +#include +#elif HAVE_GSSAPI_H +#include +#endif + +#if !HAVE_HEIMDAL_KERBEROS +#if HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#endif +#if HAVE_GSSAPI_GSSAPI_GENERIC_H +#include +#endif +#if HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif +#else +#if HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#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 <<