From: Markus Moeller Date: Fri, 27 Sep 2013 15:21:54 +0000 (-0600) Subject: negotiate_kerberos_auth: upgrade to present group= keys X-Git-Tag: SQUID_3_5_0_1~633 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4ebcf1ceefe28d5320166e5bad97a72ef7944c5c;p=thirdparty%2Fsquid.git negotiate_kerberos_auth: upgrade to present group= keys 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. --- diff --git a/configure.ac b/configure.ac index 2f206d0cf7..60ff2c0b9b 100644 --- a/configure.ac +++ b/configure.ac @@ -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 ]) + 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]),) @@ -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_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 --git a/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc b/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc index 6f0c1cd01b..8867366de4 100644 --- a/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc +++ b/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc @@ -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; } } diff --git a/helpers/external_acl/kerberos_ldap_group/support.h b/helpers/external_acl/kerberos_ldap_group/support.h index 5edd83e3da..2f6bc6549c 100644 --- a/helpers/external_acl/kerberos_ldap_group/support.h +++ b/helpers/external_acl/kerberos_ldap_group/support.h @@ -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); diff --git a/helpers/external_acl/kerberos_ldap_group/support_group.cc b/helpers/external_acl/kerberos_ldap_group/support_group.cc index 3ff3cca29a..1b9209ce85 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_group.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_group.cc @@ -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); diff --git a/helpers/external_acl/kerberos_ldap_group/support_krb5.cc b/helpers/external_acl/kerberos_ldap_group/support_krb5.cc index b4dfc98ff7..eb0a4f9cb2 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_krb5.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_krb5.cc @@ -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); diff --git a/helpers/external_acl/kerberos_ldap_group/support_ldap.cc b/helpers/external_acl/kerberos_ldap_group/support_ldap.cc index 3069fe2911..cf34404a2a 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_ldap.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_ldap.cc @@ -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); diff --git a/helpers/external_acl/kerberos_ldap_group/support_log.cc b/helpers/external_acl/kerberos_ldap_group/support_log.cc index fceec56315..56bcdab05e 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_log.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_log.cc @@ -34,13 +34,13 @@ 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); diff --git a/helpers/external_acl/kerberos_ldap_group/support_lserver.cc b/helpers/external_acl/kerberos_ldap_group/support_lserver.cc index d7e4bd0183..29e2932595 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_lserver.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_lserver.cc @@ -29,6 +29,7 @@ #include "support.h" struct lsstruct *init_ls(void); +void free_ls(struct lsstruct *lssp); struct lsstruct * init_ls(void) { diff --git a/helpers/external_acl/kerberos_ldap_group/support_netbios.cc b/helpers/external_acl/kerberos_ldap_group/support_netbios.cc index 6d2269a65c..86b5eb3d0e 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_netbios.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_netbios.cc @@ -30,6 +30,7 @@ #include "support.h" struct ndstruct *init_nd(void); +void free_nd(struct ndstruct *ndsp); struct ndstruct * init_nd(void) { diff --git a/helpers/external_acl/kerberos_ldap_group/support_resolv.cc b/helpers/external_acl/kerberos_ldap_group/support_resolv.cc index e984f4ee51..8df8fd2fff 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_resolv.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_resolv.cc @@ -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); } diff --git a/helpers/external_acl/kerberos_ldap_group/support_sasl.cc b/helpers/external_acl/kerberos_ldap_group/support_sasl.cc index dd0c9f2beb..a3ca2fffcc 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_sasl.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_sasl.cc @@ -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); } diff --git a/helpers/negotiate_auth/kerberos/Makefile.am b/helpers/negotiate_auth/kerberos/Makefile.am index 4d6f4e8e9a..83772615a6 100644 --- a/helpers/negotiate_auth/kerberos/Makefile.am +++ b/helpers/negotiate_auth/kerberos/Makefile.am @@ -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 index 0000000000..82277e1607 --- /dev/null +++ b/helpers/negotiate_auth/kerberos/negotiate_kerberos.h @@ -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 +#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 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 diff --git a/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc b/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc index d7b35a8b5e..7668ac0aba 100644 --- a/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc +++ b/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc @@ -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 @@ 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; } } diff --git a/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc b/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc index 0299f53456..141ab82adf 100644 --- a/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc +++ b/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc @@ -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 index 0000000000..27901ef5fc --- /dev/null +++ b/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc @@ -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 index 0000000000..0d4b385907 --- /dev/null +++ b/helpers/negotiate_auth/kerberos/test_negotiate_auth.sh @@ -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 --git a/src/peer_proxy_negotiate_auth.cc b/src/peer_proxy_negotiate_auth.cc index 845e85320b..0098581a7c 100644 --- a/src/peer_proxy_negotiate_auth.cc +++ b/src/peer_proxy_negotiate_auth.cc @@ -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 <<