From: Markus Moeller Date: Wed, 29 Oct 2014 04:47:53 +0000 (-0700) Subject: ext_kerberos_ldap_group_acl: -n option to disable automated SASL/GSSAPI X-Git-Tag: merge-candidate-3-v1~526 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7451e5ad6ac9da02c6325c81faaaa7a0d2e4d6a7;p=thirdparty%2Fsquid.git ext_kerberos_ldap_group_acl: -n option to disable automated SASL/GSSAPI The -n option disables the automated Kerberos authentication (SASL/GSSAPI) to AD and requires username/password (SASL/SIMPLE) instead. Also, improvements in caching Kerberos credentials for setup with low Squid cache TTL. --- 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 f186cb06fc..37b7841b76 100644 --- a/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc +++ b/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc @@ -45,6 +45,10 @@ #include "support.h" #include +#if HAVE_KRB5 +struct kstruct kparam; +#endif + void init_args(struct main_args *margs) { @@ -61,6 +65,7 @@ init_args(struct main_args *margs) margs->rc_allow = 0; margs->AD = 0; margs->mdepth = 5; + margs->nokerberos = 0; margs->ddomain = NULL; margs->groups = NULL; margs->ndoms = NULL; @@ -173,13 +178,18 @@ main(int argc, char *const argv[]) char *nuser, *nuser8 = NULL, *netbios; int opt; struct main_args margs; +#if HAVE_KRB5 + krb5_error_code code = 0; + + kparam.context = NULL; +#endif setbuf(stdout, NULL); setbuf(stdin, NULL); init_args(&margs); - while (-1 != (opt = getopt(argc, argv, "diasg:D:N:S:u:U:t:T:p:l:b:m:h"))) { + while (-1 != (opt = getopt(argc, argv, "diasng:D:N:S:u:U:t:T:p:l:b:m:h"))) { switch (opt) { case 'd': debug_enabled = 1; @@ -193,6 +203,9 @@ main(int argc, char *const argv[]) case 's': margs.ssl = (char *) "yes"; break; + case 'n': + margs.nokerberos = 1; + break; case 'g': margs.glist = xstrdup(optarg); break; @@ -236,6 +249,7 @@ main(int argc, char *const argv[]) fprintf(stderr, "squid_kerb_ldap [-d] [-i] -g group list [-D domain] [-N netbios domain map] [-s] [-u ldap user] [-p ldap user password] [-l ldap url] [-b ldap bind path] [-a] [-m max depth] [-h]\n"); fprintf(stderr, "-d full debug\n"); fprintf(stderr, "-i informational messages\n"); + fprintf(stderr, "-n do not use Kerberos to authenticate to AD. Requires -u , -p and -l option\n"); fprintf(stderr, "-g group list\n"); fprintf(stderr, "-t group list (only group name hex UTF-8 format)\n"); fprintf(stderr, "-T group list (all in hex UTF-8 format - except seperator @)\n"); @@ -280,7 +294,7 @@ main(int argc, char *const argv[]) if (create_gd(&margs)) { if ( margs.glist != NULL ) { debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM, margs.glist ? margs.glist : "NULL"); - SEND_ERR(""); + SEND_BH(""); clean_args(&margs); exit(1); } else { @@ -290,16 +304,36 @@ main(int argc, char *const argv[]) } if (create_nd(&margs)) { debug((char *) "%s| %s: FATAL: Error in netbios list: %s\n", LogTime(), PROGRAM, margs.nlist ? margs.nlist : "NULL"); - SEND_ERR(""); + SEND_BH(""); clean_args(&margs); exit(1); } if (create_ls(&margs)) { debug((char *) "%s| %s: Error in ldap server list: %s\n", LogTime(), PROGRAM, margs.llist ? margs.llist : "NULL"); - SEND_ERR(""); + SEND_BH(""); clean_args(&margs); exit(1); } + +#if HAVE_KRB5 + /* + * Initialise Kerberos + */ + + code = krb5_init_context(&kparam.context); + for (int i=0; i @@ -60,16 +60,16 @@ extern "C" { #endif /* HAVE_COM_ERR_H */ #define LDAP_DEPRECATED 1 -#ifdef HAVE_LDAP_REBIND_FUNCTION +#if HAVE_LDAP_REBIND_FUNCTION #define LDAP_REFERRALS #endif -#ifdef HAVE_LBER_H +#if HAVE_LBER_H #include #endif -#ifdef HAVE_LDAP_H +#if HAVE_LDAP_H #include #endif -#ifdef HAVE_MOZLDAP_LDAP_H +#if HAVE_MOZLDAP_LDAP_H #include #endif @@ -103,6 +103,7 @@ struct main_args { int rc_allow; int AD; int mdepth; + int nokerberos; char *ddomain; struct gdstruct *groups; struct ndstruct *ndoms; @@ -161,11 +162,6 @@ int create_gd(struct main_args *margs); int create_nd(struct main_args *margs); int create_ls(struct main_args *margs); -#ifdef HAVE_KRB5 -int krb5_create_cache(char *domain); -void krb5_cleanup(void); -#endif - 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); @@ -174,4 +170,17 @@ size_t free_hostname_list(struct hstruct **hlist, size_t nhosts); int tool_sasl_bind(LDAP * ld, char *binddn, char *ssl); #endif +#if HAVE_KRB5 +#define MAX_DOMAINS 16 +#define MAX_SKEW 300 +struct kstruct { + krb5_context context; + krb5_ccache cc[MAX_DOMAINS]; + char* mem_ccache[MAX_DOMAINS]; + int ncache; +}; +int krb5_create_cache(char *domain); +void krb5_cleanup(void); +#endif + #define PROGRAM "kerberos_ldap_group" diff --git a/helpers/external_acl/kerberos_ldap_group/support_krb5.cc b/helpers/external_acl/kerberos_ldap_group/support_krb5.cc index be9ab3df1e..eb0bac05b5 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_krb5.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_krb5.cc @@ -37,23 +37,22 @@ #include "support.h" -struct kstruct { - krb5_context context; - krb5_ccache cc; -}; - -static struct kstruct kparam; +#if HAVE_KRB5 +extern struct kstruct kparam; +#endif #define KT_PATH_MAX 256 void krb5_cleanup() { - if (kparam.context) { - if (kparam.cc) - krb5_cc_destroy(kparam.context, kparam.cc); - krb5_free_context(kparam.context); - } + if (kparam.context) + for (int i=0; iserver, &principal_name); + if (code2) { + error((char *) "%s| %s: ERROR: Error while unparsing principal : %s\n", LogTime(), PROGRAM, error_message(code2)); + code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); + if (code) { + error((char *) "%s| %s: ERROR: while destroying ccache : %s\n", LogTime(), PROGRAM, error_message(code)); + } + if (creds) + krb5_free_creds(kparam.context, creds); + safe_free(creds); + safe_free(principal_name); + debug((char *) "%s| %s: DEBUG: Reset credential cache to %s\n", LogTime(), PROGRAM, mem_cache); + code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); + if (code) { + error((char *) "%s| %s: ERROR: Error while resolving memory ccache : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + goto cleanup; + } + code =1; + break; + } + if (!strncmp(KRB5_TGS_NAME,principal_name,KRB5_TGS_NAME_SIZE)) { + time_t now; + static krb5_deltat skew=MAX_SKEW; + + debug((char *) "%s| %s: DEBUG: Found %s in cache : %s\n", LogTime(), PROGRAM,KRB5_TGS_NAME,principal_name); + /* + * Check time + */ + time(&now); + debug((char *) "%s| %s: DEBUG: credential time diff %d\n", LogTime(), PROGRAM, (int)(creds->times.endtime - now)); + if (creds->times.endtime - now < 2*skew) { + debug((char *) "%s| %s: DEBUG: credential will soon expire %d\n", LogTime(), PROGRAM, (int)(creds->times.endtime - now)); + if (principal) + krb5_free_principal(kparam.context, principal); + principal = NULL; + code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); + if (code) { + error((char *) "%s| %s: ERROR: while destroying ccache : %s\n", LogTime(), PROGRAM, error_message(code)); + } + if (creds) + krb5_free_creds(kparam.context, creds); + creds = NULL; + safe_free(principal_name); + debug((char *) "%s| %s: DEBUG: Reset credential cache to %s\n", LogTime(), PROGRAM, mem_cache); + code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); + if (code) { + error((char *) "%s| %s: ERROR: Error while resolving memory ccache : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + goto cleanup; + } + code = 1; + } else { + safe_free(principal_name); + } + break; + } + if (creds) + krb5_free_creds(kparam.context, creds); + creds = (krb5_creds *) xcalloc(1,sizeof(*creds)); + safe_free(principal_name); + } + if (creds) + krb5_free_creds(kparam.context, creds); + creds = NULL; + code2 = krb5_cc_end_seq_get(kparam.context, kparam.cc[ccindex], &ccursor); + if (code2) { + error((char *) "%s| %s: ERROR: Error while ending ccache scan : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + goto cleanup; + } + } } - code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor); if (code) { - error((char *) "%s| %s: ERROR: Error while starting keytab scan : %s\n", LogTime(), PROGRAM, error_message(code)); - retval = 1; - goto cleanup; - } - debug((char *) "%s| %s: DEBUG: Get principal name from keytab %s\n", LogTime(), PROGRAM, keytab_name); + /* + * getting default keytab name + */ - nprinc = 0; - while ((code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor)) == 0) { - int found = 0; + debug((char *) "%s| %s: DEBUG: Get default keytab file name\n", LogTime(), PROGRAM); + krb5_kt_default_name(kparam.context, buf, KT_PATH_MAX); + p = strchr(buf, ':'); /* Find the end if "FILE:" */ + if (p) + ++p; /* step past : */ + keytab_name = xstrdup(p ? p : buf); + debug((char *) "%s| %s: DEBUG: Got default keytab file name %s\n", LogTime(), PROGRAM, keytab_name); - principal_list = (krb5_principal *) xrealloc(principal_list, sizeof(krb5_principal) * (nprinc + 1)); - krb5_copy_principal(kparam.context, entry.principal, &principal_list[nprinc++]); + code = krb5_kt_resolve(kparam.context, keytab_name, &keytab); + if (code) { + error((char *) "%s| %s: ERROR: Error while resolving keytab %s : %s\n", LogTime(), PROGRAM, keytab_name, error_message(code)); + retval = 1; + goto cleanup; + } + code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor); + if (code) { + error((char *) "%s| %s: ERROR: Error while starting keytab scan : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + goto cleanup; + } + debug((char *) "%s| %s: DEBUG: Get principal name from keytab %s\n", LogTime(), PROGRAM, keytab_name); + + 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++]); #if USE_HEIMDAL_KRB5 - debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, entry.principal->realm); + debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, entry.principal->realm); #else - debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, krb5_princ_realm(kparam.context, entry.principal)->data); + debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, krb5_princ_realm(kparam.context, entry.principal)->data); #endif #if USE_HEIMDAL_KRB5 - if (!strcasecmp(domain, entry.principal->realm)) + if (!strcasecmp(domain, entry.principal->realm)) #else - if (!strcasecmp(domain, krb5_princ_realm(kparam.context, entry.principal)->data)) + if (!strcasecmp(domain, krb5_princ_realm(kparam.context, entry.principal)->data)) #endif - { - code = krb5_unparse_name(kparam.context, entry.principal, &principal_name); - if (code) { - error((char *) "%s| %s: ERROR: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code)); - } else { - debug((char *) "%s| %s: DEBUG: Found principal name: %s\n", LogTime(), PROGRAM, principal_name); - found = 1; + { + code = krb5_unparse_name(kparam.context, entry.principal, &principal_name); + if (code) { + error((char *) "%s| %s: ERROR: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code)); + } else { + debug((char *) "%s| %s: DEBUG: Found principal name: %s\n", LogTime(), PROGRAM, principal_name); + found = 1; + } } - } #if USE_HEIMDAL_KRB5 || ( HAVE_KRB5_KT_FREE_ENTRY && HAVE_DECL_KRB5_KT_FREE_ENTRY ) - code = krb5_kt_free_entry(kparam.context, &entry); + code = krb5_kt_free_entry(kparam.context, &entry); #else - code = krb5_free_keytab_entry_contents(kparam.context, &entry); + code = krb5_free_keytab_entry_contents(kparam.context, &entry); #endif - if (code) { - error((char *) "%s| %s: ERROR: Error while freeing keytab entry : %s\n", LogTime(), PROGRAM, error_message(code)); - retval = 1; - break; - } - if (found) { - debug((char *) "%s| %s: DEBUG: Got principal name %s\n", LogTime(), PROGRAM, principal_name); - /* - * build principal - */ - code = krb5_parse_name(kparam.context, principal_name, &principal); if (code) { - error((char *) "%s| %s: ERROR: Error while parsing name %s : %s\n", LogTime(), PROGRAM, principal_name, error_message(code)); - safe_free(principal_name); - if (principal) - krb5_free_principal(kparam.context, principal); - found = 0; - continue; + error((char *) "%s| %s: ERROR: Error while freeing keytab entry : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + break; } - creds = (krb5_creds *) xcalloc(1,sizeof(*creds)); + if (found) { + debug((char *) "%s| %s: DEBUG: Got principal name %s\n", LogTime(), PROGRAM, principal_name); + /* + * build principal + */ + code = krb5_parse_name(kparam.context, principal_name, &principal); + if (code) { + error((char *) "%s| %s: ERROR: Error while parsing name %s : %s\n", LogTime(), PROGRAM, principal_name, error_message(code)); + safe_free(principal_name); + if (principal) + krb5_free_principal(kparam.context, principal); + found = 0; + continue; + } + creds = (krb5_creds *) xcalloc(1,sizeof(*creds)); - /* - * get credentials - */ + /* + * get credentials + */ #if HAVE_GET_INIT_CREDS_KEYTAB - code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, NULL); + code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, NULL); #else - service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3); - 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); - xfree(service); - code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0); + service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3); + 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); + xfree(service); + code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0); #endif - if (code) { - error((char *) "%s| %s: ERROR: Error while initialising credentials from keytab : %s\n", LogTime(), PROGRAM, error_message(code)); - safe_free(principal_name); - if (principal) - krb5_free_principal(kparam.context, principal); - if (creds) - krb5_free_creds(kparam.context, creds); - creds = NULL; - found = 0; - continue; - } - code = krb5_cc_initialize(kparam.context, kparam.cc, principal); - if (code) { - error((char *) "%s| %s: ERROR: Error while initializing memory caches : %s\n", LogTime(), PROGRAM, error_message(code)); - safe_free(principal_name); - if (principal) - krb5_free_principal(kparam.context, principal); - if (creds) - krb5_free_creds(kparam.context, creds); - creds = NULL; - found = 0; - continue; - } - code = krb5_cc_store_cred(kparam.context, kparam.cc, creds); - if (code) { - error((char *) "%s| %s: ERROR: Error while storing credentials : %s\n", LogTime(), PROGRAM, error_message(code)); - if (principal) - krb5_free_principal(kparam.context, principal); - safe_free(principal_name); - if (creds) - krb5_free_creds(kparam.context, creds); - creds = NULL; - found = 0; - continue; + if (code) { + error((char *) "%s| %s: ERROR: Error while initialising credentials from keytab : %s\n", LogTime(), PROGRAM, error_message(code)); + safe_free(principal_name); + if (principal) + krb5_free_principal(kparam.context, principal); + if (creds) + krb5_free_creds(kparam.context, creds); + creds = NULL; + found = 0; + continue; + } + code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal); + if (code) { + error((char *) "%s| %s: ERROR: Error while initializing memory caches : %s\n", LogTime(), PROGRAM, error_message(code)); + safe_free(principal_name); + if (principal) + krb5_free_principal(kparam.context, principal); + if (creds) + krb5_free_creds(kparam.context, creds); + creds = NULL; + found = 0; + continue; + } + code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds); + if (code) { + error((char *) "%s| %s: ERROR: Error while storing credentials : %s\n", LogTime(), PROGRAM, error_message(code)); + if (principal) + krb5_free_principal(kparam.context, principal); + safe_free(principal_name); + if (creds) + krb5_free_creds(kparam.context, creds); + creds = NULL; + found = 0; + continue; + } + debug((char *) "%s| %s: DEBUG: Stored credentials\n", LogTime(), PROGRAM); + break; } - debug((char *) "%s| %s: DEBUG: Stored credentials\n", LogTime(), PROGRAM); - break; } - } - if (code && code != KRB5_KT_END) { - error((char *) "%s| %s: ERROR: Error while scanning keytab : %s\n", LogTime(), PROGRAM, error_message(code)); - retval = 1; - goto cleanup; - } - code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor); - if (code) { - error((char *) "%s| %s: ERROR: Error while ending keytab scan : %s\n", LogTime(), PROGRAM, error_message(code)); - retval = 1; - goto cleanup; - } + if (code && code != KRB5_KT_END) { + error((char *) "%s| %s: ERROR: Error while scanning keytab : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + goto cleanup; + } + code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor); + if (code) { + error((char *) "%s| %s: ERROR: Error while ending keytab scan : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + goto cleanup; + } - /* - * 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); + /* + * 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); - for (i = 0; i < nprinc; ++i) { - krb5_creds *tgt_creds = NULL; - creds = (krb5_creds *) xmalloc(sizeof(*creds)); - memset(creds, 0, sizeof(*creds)); - /* - * get credentials - */ - code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name); - if (code) { - debug((char *) "%s| %s: DEBUG: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code)); - goto loop_end; - } - debug((char *) "%s| %s: DEBUG: Keytab entry has principal: %s\n", LogTime(), PROGRAM, principal_name); + for (i = 0; i < nprinc; ++i) { + krb5_creds *tgt_creds = NULL; + creds = (krb5_creds *) xmalloc(sizeof(*creds)); + memset(creds, 0, sizeof(*creds)); + /* + * get credentials + */ + code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name); + if (code) { + debug((char *) "%s| %s: DEBUG: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code)); + goto loop_end; + } + debug((char *) "%s| %s: DEBUG: Keytab entry has principal: %s\n", LogTime(), PROGRAM, principal_name); #if HAVE_GET_INIT_CREDS_KEYTAB - code = krb5_get_init_creds_keytab(kparam.context, creds, principal_list[i], keytab, 0, NULL, NULL); + code = krb5_get_init_creds_keytab(kparam.context, creds, principal_list[i], keytab, 0, NULL, NULL); #else - service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3); - 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); - xfree(service); - code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0); + service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3); + 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); + xfree(service); + code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0); #endif - if (code) { - debug((char *) "%s| %s: DEBUG: Error while initialising credentials from keytab : %s\n", LogTime(), PROGRAM, error_message(code)); - goto loop_end; - } - code = krb5_cc_initialize(kparam.context, kparam.cc, principal_list[i]); - if (code) { - error((char *) "%s| %s: ERROR: Error while initializing memory caches : %s\n", LogTime(), PROGRAM, error_message(code)); - goto loop_end; - } - code = krb5_cc_store_cred(kparam.context, kparam.cc, creds); - if (code) { - debug((char *) "%s| %s: DEBUG: Error while storing credentials : %s\n", LogTime(), PROGRAM, error_message(code)); - goto loop_end; - } - if (creds->server) - krb5_free_principal(kparam.context, creds->server); + if (code) { + debug((char *) "%s| %s: DEBUG: Error while initialising credentials from keytab : %s\n", LogTime(), PROGRAM, error_message(code)); + goto loop_end; + } + code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal_list[i]); + if (code) { + error((char *) "%s| %s: ERROR: Error while initializing memory caches : %s\n", LogTime(), PROGRAM, error_message(code)); + goto loop_end; + } + code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds); + if (code) { + debug((char *) "%s| %s: DEBUG: Error while storing credentials : %s\n", LogTime(), PROGRAM, error_message(code)); + goto loop_end; + } + if (creds->server) + krb5_free_principal(kparam.context, creds->server); #if USE_HEIMDAL_KRB5 - service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3); - snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3, "krbtgt/%s@%s", domain, principal_list[i]->realm); + service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3); + snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3, "krbtgt/%s@%s", domain, principal_list[i]->realm); #else - service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3); - 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); + service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3); + 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); - xfree(service); - if (code) { - error((char *) "%s| %s: ERROR: Error while initialising TGT credentials : %s\n", LogTime(), PROGRAM, error_message(code)); - goto loop_end; - } - code = krb5_get_credentials(kparam.context, 0, kparam.cc, creds, &tgt_creds); - if (code) { - debug((char *) "%s| %s: DEBUG: Error while getting tgt : %s\n", LogTime(), PROGRAM, error_message(code)); - goto loop_end; - } else { - debug((char *) "%s| %s: DEBUG: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name); + code = krb5_parse_name(kparam.context, service, &creds->server); + xfree(service); + if (code) { + error((char *) "%s| %s: ERROR: Error while initialising TGT credentials : %s\n", LogTime(), PROGRAM, error_message(code)); + goto loop_end; + } + code = krb5_get_credentials(kparam.context, 0, kparam.cc[ccindex], creds, &tgt_creds); + if (code) { + debug((char *) "%s| %s: DEBUG: Error while getting tgt : %s\n", LogTime(), PROGRAM, error_message(code)); + goto loop_end; + } else { + debug((char *) "%s| %s: DEBUG: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name); + if (tgt_creds) + krb5_free_creds(kparam.context, tgt_creds); + tgt_creds = NULL; + break; + } + +loop_end: + safe_free(principal_name); if (tgt_creds) krb5_free_creds(kparam.context, tgt_creds); tgt_creds = NULL; - break; + if (creds) + krb5_free_creds(kparam.context, creds); + creds = NULL; + } -loop_end: - 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 (creds) - krb5_free_creds(kparam.context, creds); - creds = NULL; + } else { + debug((char *) "%s| %s: DEBUG: Got principal from ccache\n", LogTime(), PROGRAM); + /* + * get credentials + */ + code = krb5_unparse_name(kparam.context, principal, &principal_name); + if (code) { + debug((char *) "%s| %s: DEBUG: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code)); + retval = 1; + goto cleanup; + } + debug((char *) "%s| %s: DEBUG: ccache has principal: %s\n", LogTime(), PROGRAM, principal_name); } + if (!principal_name) { debug((char *) "%s| %s: DEBUG: Got no principal name\n", LogTime(), PROGRAM); retval = 1; @@ -359,7 +484,6 @@ cleanup: xfree(principal_list); if (creds) krb5_free_creds(kparam.context, creds); - return (retval); } #endif diff --git a/helpers/external_acl/kerberos_ldap_group/support_ldap.cc b/helpers/external_acl/kerberos_ldap_group/support_ldap.cc index 1f3d50f8eb..7c37ba89b0 100644 --- a/helpers/external_acl/kerberos_ldap_group/support_ldap.cc +++ b/helpers/external_acl/kerberos_ldap_group/support_ldap.cc @@ -47,7 +47,7 @@ #include "squid.h" #include "util.h" -#ifdef HAVE_LDAP +#if HAVE_LDAP #include "support.h" #include @@ -888,9 +888,14 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group) debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM); #if HAVE_KRB5 - kc = krb5_create_cache(domain); - if (kc) { - error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM); + if (margs->nokerberos) { + kc = 1; + debug((char *) "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n", LogTime(), PROGRAM); + } else { + kc = krb5_create_cache(domain); + if (kc) { + error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM); + } } #else kc = 1; @@ -1375,10 +1380,6 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group) } debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM); cleanup: -#if HAVE_KRB5 - if (domain) - krb5_cleanup(); -#endif if (lcreds) { xfree(lcreds->dn); xfree(lcreds->pw);