37 #if HAVE_LDAP && HAVE_KRB5 
   42 extern struct kstruct kparam;
 
   45 #define KT_PATH_MAX 256 
   51         for (
int i=0; i<MAX_DOMAINS; i++) {
 
   53                 krb5_cc_destroy(kparam.context, kparam.cc[i]);
 
   56     krb5_free_context(kparam.context);
 
   60 k5_error2(
const char* msg, 
char* msg2, krb5_error_code code)
 
   63     errmsg = krb5_get_error_message(kparam.context, code);
 
   65 #if HAVE_KRB5_FREE_ERROR_MESSAGE 
   66     krb5_free_error_message(kparam.context, errmsg);
 
   67 #elif HAVE_KRB5_FREE_ERROR_STRING 
   68     krb5_free_error_string(kparam.context, (
char *)errmsg);
 
   75 k5_debug(
const char* msg, krb5_error_code code)
 
   78     errmsg = krb5_get_error_message(kparam.context, code);
 
   80 #if HAVE_KRB5_FREE_ERROR_MESSAGE 
   81     krb5_free_error_message(kparam.context, errmsg);
 
   82 #elif HAVE_KRB5_FREE_ERROR_STRING 
   83     krb5_free_error_string(kparam.context, (
char *)errmsg);
 
   90 k5_error(
const char* msg, krb5_error_code code)
 
   92     k5_error2(msg, (
char *)
"", code);
 
   99 krb5_create_cache(
char *domain, 
char *service_principal_name)
 
  102     krb5_keytab keytab = 
nullptr;
 
  103     krb5_keytab_entry entry;
 
  104     krb5_kt_cursor cursor;
 
  105     krb5_cc_cursor ccursor;
 
  106     krb5_creds *creds = 
nullptr;
 
  107     krb5_principal *principal_list = 
nullptr;
 
  108     krb5_principal principal = 
nullptr;
 
  110     char *keytab_name = 
nullptr, *principal_name = 
nullptr, *mem_cache = 
nullptr;
 
  111     char buf[KT_PATH_MAX], *p;
 
  114     krb5_error_code code = 0;
 
  117     if (!domain || !strcmp(domain, 
""))
 
  123 #if  !HAVE_KRB5_MEMORY_CACHE || HAVE_SUN_LDAP_SDK 
  124     mem_cache = (
char *) 
xmalloc(strlen(
"FILE:/tmp/squid_ldap_") + strlen(domain) + 1 + 16);
 
  125     snprintf(mem_cache, strlen(
"FILE:/tmp/squid_ldap_") + strlen(domain) + 1 + 16, 
"FILE:/tmp/squid_ldap_%s_%d", domain, (
int) getpid());
 
  127     mem_cache = (
char *) 
xmalloc(strlen(
"MEMORY:squid_ldap_") + strlen(domain) + 1 + 16);
 
  128     snprintf(mem_cache, strlen(
"MEMORY:squid_ldap_") + strlen(domain) + 1 + 16, 
"MEMORY:squid_ldap_%s_%d", domain, (
int) getpid());
 
  131     setenv(
"KRB5CCNAME", mem_cache, 1);
 
  132     debug((
char *) 
"%s| %s: DEBUG: Set credential cache to %s\n", 
LogTime(), 
PROGRAM, mem_cache);
 
  133     for (
int i=0; i<MAX_DOMAINS; i++) {
 
  134         if (kparam.mem_ccache[i] && !strcmp(mem_cache,kparam.mem_ccache[i])) {
 
  139     if ( ccindex == -1 ) {
 
  140         kparam.mem_ccache[kparam.ncache]=
xstrdup(mem_cache);
 
  141         ccindex=kparam.ncache;
 
  143         if ( kparam.ncache == MAX_DOMAINS ) {
 
  144             error((
char *) 
"%s| %s: ERROR: Too many domains to support: # domains %d\n", 
LogTime(), 
PROGRAM, kparam.ncache);
 
  148         code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]);
 
  150             k5_error(
"Error while resolving memory ccache", code);
 
  159     code = krb5_cc_get_principal(kparam.context, kparam.cc[ccindex], &principal);
 
  162             krb5_free_principal(kparam.context, principal);
 
  164         k5_debug(
"No default principal found in ccache", code);
 
  169         code = krb5_cc_start_seq_get(kparam.context, kparam.cc[ccindex], &ccursor);
 
  171             k5_error(
"Error while starting ccache scan", code);
 
  172             code = krb5_cc_close (kparam.context, kparam.cc[ccindex]);
 
  174                 k5_error(
"Error while closing ccache", code);
 
  176             if (kparam.cc[ccindex]) {
 
  177                 code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]);
 
  179                     k5_error(
"Error while destroying ccache", code);
 
  183             krb5_error_code code2 = 0;
 
  184             creds = 
static_cast<krb5_creds *
>(
xcalloc(1,
sizeof(*creds)));
 
  185             while ((krb5_cc_next_cred(kparam.context, kparam.cc[ccindex], &ccursor, creds)) == 0) {
 
  186                 code2 = krb5_unparse_name(kparam.context, creds->server, &principal_name);
 
  188                     k5_error(
"Error while unparsing principal", code2);
 
  189                     code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]);
 
  191                         k5_error(
"Error while destroying ccache", code);
 
  194                     krb5_free_creds(kparam.context, creds);
 
  197                     debug((
char *) 
"%s| %s: DEBUG: Reset credential cache to %s\n", 
LogTime(), 
PROGRAM, mem_cache);
 
  198                     code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]);
 
  200                         k5_error(
"Error while resolving memory ccache", code);
 
  207                 if (!strncmp(KRB5_TGS_NAME,principal_name,KRB5_TGS_NAME_SIZE)) {
 
  209                     static krb5_deltat skew=MAX_SKEW;
 
  211                     debug((
char *) 
"%s| %s: DEBUG: Found %s in cache : %s\n", 
LogTime(), 
PROGRAM,KRB5_TGS_NAME,principal_name);
 
  216                     debug((
char *) 
"%s| %s: DEBUG: credential time diff %d\n", 
LogTime(), 
PROGRAM, (
int)(creds->times.endtime - now));
 
  217                     if (creds->times.endtime - now < 2*skew) {
 
  218                         debug((
char *) 
"%s| %s: DEBUG: credential will soon expire %d\n", 
LogTime(), 
PROGRAM, (
int)(creds->times.endtime - now));
 
  220                             krb5_free_principal(kparam.context, principal);
 
  222                         code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]);
 
  224                             k5_error(
"Error  while destroying ccache", code);
 
  227                         krb5_free_creds(kparam.context, creds);
 
  230                         debug((
char *) 
"%s| %s: DEBUG: Reset credential cache to %s\n", 
LogTime(), 
PROGRAM, mem_cache);
 
  231                         code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]);
 
  233                             k5_error(
"Error  while resolving ccache", code);
 
  244                 krb5_free_creds(kparam.context, creds);
 
  245                 creds = 
static_cast<krb5_creds *
>(
xcalloc(1, 
sizeof(*creds)));
 
  249                 krb5_free_creds(kparam.context, creds);
 
  251             code2 = krb5_cc_end_seq_get(kparam.context, kparam.cc[ccindex], &ccursor);
 
  253                 k5_error(
"Error while ending ccache scan", code2);
 
  265         krb5_kt_default_name(kparam.context, buf, KT_PATH_MAX);
 
  266         p = strchr(buf, 
':');   
 
  269         keytab_name = 
xstrdup(p ? p : buf);
 
  270         debug((
char *) 
"%s| %s: DEBUG: Got default keytab file name %s\n", 
LogTime(), 
PROGRAM, keytab_name);
 
  272         code = krb5_kt_resolve(kparam.context, keytab_name, &keytab);
 
  274             k5_error2(
"Error while resolving keytab ", keytab_name,code);
 
  278         code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor);
 
  280             k5_error(
"Error while starting keytab scan", code);
 
  284         debug((
char *) 
"%s| %s: DEBUG: Get principal name from keytab %s\n", 
LogTime(), 
PROGRAM, keytab_name);
 
  287         while ((code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor)) == 0) {
 
  290             principal_list = (krb5_principal *) 
xrealloc(principal_list, 
sizeof(krb5_principal) * (nprinc + 1));
 
  291             krb5_copy_principal(kparam.context, entry.principal, &principal_list[nprinc++]);
 
  292 #if HAVE_LIBHEIMDAL_KRB5 
  293             debug((
char *) 
"%s| %s: DEBUG: Keytab entry has realm name: %s\n", 
LogTime(), 
PROGRAM, entry.principal->realm);
 
  295             debug((
char *) 
"%s| %s: DEBUG: Keytab entry has realm name: %s\n", 
LogTime(), 
PROGRAM, krb5_princ_realm(kparam.context, entry.principal)->data);
 
  297 #if HAVE_LIBHEIMDAL_KRB5 
  298             if (!strcasecmp(domain, entry.principal->realm))
 
  300             if (!strcasecmp(domain, krb5_princ_realm(kparam.context, entry.principal)->data))
 
  303                 code = krb5_unparse_name(kparam.context, entry.principal, &principal_name);
 
  305                     k5_error(
"Error while unparsing principal name", code);
 
  307                     debug((
char *) 
"%s| %s: DEBUG: Found principal name: %s\n", 
LogTime(), 
PROGRAM, principal_name);
 
  309                     if (service_principal_name && strcasecmp(principal_name,service_principal_name) != 0 ) {
 
  310                         debug((
char *) 
"%s| %s: DEBUG: principal name does not match parameter: %s\n", 
LogTime(), 
PROGRAM, service_principal_name);
 
  316 #if HAVE_LIBHEIMDAL_KRB5 || ( HAVE_KRB5_KT_FREE_ENTRY && HAVE_DECL_KRB5_KT_FREE_ENTRY ) 
  317             code = krb5_kt_free_entry(kparam.context, &entry);
 
  319             code = krb5_free_keytab_entry_contents(kparam.context, &entry);
 
  322                 k5_error(
"Error while freeing keytab entry", code);
 
  327                 debug((
char *) 
"%s| %s: DEBUG: Got principal name %s\n", 
LogTime(), 
PROGRAM, principal_name);
 
  331                 code = krb5_parse_name(kparam.context, principal_name, &principal);
 
  333                     k5_error2(
"Error while parsing name ", principal_name,code);
 
  336                         krb5_free_principal(kparam.context, principal);
 
  340                 creds = (krb5_creds *) 
xcalloc(1,
sizeof(*creds));
 
  345 #if HAVE_GET_INIT_CREDS_KEYTAB 
  346                 code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, 
nullptr, 
nullptr);
 
  348                 service = (
char *) 
xmalloc(strlen(
"krbtgt") + 2 * strlen(domain) + 3);
 
  349                 snprintf(service, strlen(
"krbtgt") + 2 * strlen(domain) + 3, 
"krbtgt/%s@%s", domain, domain);
 
  350                 creds->client = principal;
 
  351                 code = krb5_parse_name(kparam.context, service, &creds->server);
 
  353                 code = krb5_get_in_tkt_with_keytab(kparam.context, 0, 
nullptr, 
nullptr, 
nullptr, keytab, 
nullptr, creds, 0);
 
  357                     k5_error(
"Error while initialising credentials from keytab", code);
 
  360                         krb5_free_principal(kparam.context, principal);
 
  362                         krb5_free_creds(kparam.context, creds);
 
  367                 code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal);
 
  369                     k5_error(
"Error while initialising cache", code);
 
  372                         krb5_free_principal(kparam.context, principal);
 
  374                         krb5_free_creds(kparam.context, creds);
 
  379                 code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds);
 
  381                     k5_error(
"Error while storing credentials", code);
 
  383                         krb5_free_principal(kparam.context, principal);
 
  386                         krb5_free_creds(kparam.context, creds);
 
  396         if (code && code != KRB5_KT_END) {
 
  397             k5_error(
"Error while scanning keytab", code);
 
  401         code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor);
 
  403             k5_error(
"Error while ending keytab scan", code);
 
  411         if (!principal_name && !service_principal_name) {
 
  413             debug((
char *) 
"%s| %s: DEBUG: Did not find a principal in keytab for domain %s.\n", 
LogTime(), 
PROGRAM, domain);
 
  414             debug((
char *) 
"%s| %s: DEBUG: Try to get principal of trusted domain.\n", 
LogTime(), 
PROGRAM);
 
  416             for (i = 0; i < nprinc; ++i) {
 
  417                 krb5_creds *tgt_creds = 
nullptr;
 
  418                 creds = (krb5_creds *) 
xmalloc(
sizeof(*creds));
 
  419                 memset(creds, 0, 
sizeof(*creds));
 
  423                 code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name);
 
  425                     k5_error(
"Error while unparsing principal name", code);
 
  428                 debug((
char *) 
"%s| %s: DEBUG: Keytab entry has principal: %s\n", 
LogTime(), 
PROGRAM, principal_name);
 
  430 #if HAVE_GET_INIT_CREDS_KEYTAB 
  431                 code = krb5_get_init_creds_keytab(kparam.context, creds, principal_list[i], keytab, 0, 
nullptr, 
nullptr);
 
  433                 service = (
char *) 
xmalloc(strlen(
"krbtgt") + 2 * strlen(domain) + 3);
 
  434                 snprintf(service, strlen(
"krbtgt") + 2 * strlen(domain) + 3, 
"krbtgt/%s@%s", domain, domain);
 
  435                 creds->client = principal_list[i];
 
  436                 code = krb5_parse_name(kparam.context, service, &creds->server);
 
  438                 code = krb5_get_in_tkt_with_keytab(kparam.context, 0, 
nullptr, 
nullptr, 
nullptr, keytab, 
nullptr, creds, 0);
 
  441                     k5_error(
"Error while initialising credentials from keytab", code);
 
  444                 code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal_list[i]);
 
  446                     k5_error(
"Error while initialising memory caches", code);
 
  449                 code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds);
 
  451                     k5_error(
"Error while storing credentials", code);
 
  455                     krb5_free_principal(kparam.context, creds->server);
 
  456 #if HAVE_LIBHEIMDAL_KRB5 
  457                 service = (
char *) 
xmalloc(strlen(
"krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3);
 
  458                 snprintf(service, strlen(
"krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3, 
"krbtgt/%s@%s", domain, principal_list[i]->realm);
 
  460                 service = (
char *) 
xmalloc(strlen(
"krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3);
 
  461                 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);
 
  463                 code = krb5_parse_name(kparam.context, service, &creds->server);
 
  466                     k5_error(
"Error while initialising TGT credentials", code);
 
  471 #if HAVE_LIBHEIMDAL_KRB5 
  472                 creds->session.keytype = 0;
 
  473                 if (creds->session.keyvalue.length > 0)
 
  474                     krb5_free_keyblock_contents(kparam.context, &creds->session);
 
  476                 creds->keyblock.enctype = 0;
 
  477                 if (creds->keyblock.contents)
 
  478                     krb5_free_keyblock_contents(kparam.context, &creds->keyblock);
 
  480                 code = krb5_get_credentials(kparam.context, 0, kparam.cc[ccindex], creds, &tgt_creds);
 
  482                     k5_error(
"Error while getting tgt", code);
 
  485                     debug((
char *) 
"%s| %s: DEBUG: Found trusted principal name: %s\n", 
LogTime(), 
PROGRAM, principal_name);
 
  487                         krb5_free_creds(kparam.context, tgt_creds);
 
  495                     krb5_free_creds(kparam.context, tgt_creds);
 
  498                     krb5_free_creds(kparam.context, creds);
 
  504                 krb5_free_creds(kparam.context, creds);
 
  512         code = krb5_unparse_name(kparam.context, principal, &principal_name);
 
  514             k5_error(
"Error while unparsing principal name", code);
 
  518         debug((
char *) 
"%s| %s: DEBUG: ccache has principal: %s\n", 
LogTime(), 
PROGRAM, principal_name);
 
  521     if (!principal_name) {
 
  527         krb5_kt_close(kparam.context, keytab);
 
  529     xfree(principal_name);
 
  532         krb5_free_principal(kparam.context, principal);
 
  533     for (j = 0; j < nprinc; ++j) {
 
  534         if (principal_list[j])
 
  535             krb5_free_principal(kparam.context, principal_list[j]);
 
  537     xfree(principal_list);
 
  539         krb5_free_creds(kparam.context, creds);