krb5_error_code KRB5_LIB_FUNCTION krb5_get_in_tkt_with_skey (krb5_context context, krb5_flags options, krb5_addresses *addrs, const krb5_enctype *etypes, const krb5_preauthtype *pre_auth_types, const krb5_keyblock *key, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep *ret_as_reply) { if(key == NULL) return krb5_get_in_tkt_with_keytab (context, options, addrs, etypes, pre_auth_types, NULL, ccache, creds, ret_as_reply); else return krb5_get_in_tkt (context, options, addrs, etypes, pre_auth_types, krb5_skey_key_proc, key, NULL, NULL, creds, ccache, ret_as_reply); }
/* Similar to krb5_get_in_tkt_with_password. Attempts to get an initial ticket for creds->client to use server creds->server, (realm is taken from creds->client), with options options, and using creds->times.starttime, creds->times.endtime, creds->times.renew_till as from, till, and rtime. creds->times.renew_till is ignored unless the RENEWABLE option is requested. If addrs is non-NULL, it is used for the addresses requested. If it is null, the system standard addresses are used. If keyblock is NULL, an appropriate key for creds->client is retrieved from the system key store (e.g. /etc/srvtab). If keyblock is non-NULL, it is used as the decryption key. A succesful call will place the ticket in the credentials cache ccache. returns system errors, encryption errors */ krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options, krb5_address *const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, const krb5_keyblock *key, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply) { krb5_error_code retval; char *server; krb5_principal server_princ, client_princ; int use_master = 0; krb5_get_init_creds_opt *opts = NULL; #ifndef LEAN_CLIENT if (key == NULL) { return krb5_get_in_tkt_with_keytab(context, options, addrs, ktypes, pre_auth_types, NULL, ccache, creds, ret_as_reply); } #endif /* LEAN_CLIENT */ retval = krb5int_populate_gic_opt(context, &opts, options, addrs, ktypes, pre_auth_types, creds); if (retval) return retval; retval = krb5_unparse_name(context, creds->server, &server); if (retval) { krb5_get_init_creds_opt_free(context, opts); return retval; } server_princ = creds->server; client_princ = creds->client; retval = krb5int_get_init_creds(context, creds, creds->client, krb5_prompter_posix, NULL, 0, server, opts, get_as_key_skey, (void *) key, &use_master, ret_as_reply); krb5_free_unparsed_name(context, server); krb5_get_init_creds_opt_free(context, opts); if (retval) return retval; krb5_free_principal( context, creds->server); krb5_free_principal( context, creds->client); creds->client = client_princ; creds->server = server_princ; /* store it in the ccache! */ if (ccache) retval = krb5_cc_store_cred(context, ccache, creds); return retval; }
/* * Get a ticket granting ticket and stuff it in the cache */ static const char * get_tgt( char * keytab_name, char * principal_name) { krb5_context context; krb5_error_code ret; krb5_principal client = NULL, server = NULL; krb5_creds creds; krb5_keytab keytab; krb5_ccache ccache; krb5_timestamp now; #ifdef KRB5_HEIMDAL_INCLUDES krb5_data tgtname = { KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME }; #else krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME }; #endif static char *error = NULL; if (error != NULL) { amfree(error); error = NULL; } if ((ret = krb5_init_context(&context)) != 0) { error = vstrallocf(_("error initializing krb5 context: %s"), error_message(ret)); return (error); } /*krb5_init_ets(context);*/ if(!keytab_name) { error = vstrallocf(_("error -- no krb5 keytab defined")); return(error); } if(!principal_name) { error = vstrallocf(_("error -- no krb5 principal defined")); return(error); } /* * Resolve keytab file into a keytab object */ if ((ret = krb5_kt_resolve(context, keytab_name, &keytab)) != 0) { error = vstrallocf(_("error resolving keytab %s: %s"), keytab_name, error_message(ret)); return (error); } /* * Resolve the amanda service held in the keytab into a principal * object */ ret = krb5_parse_name(context, principal_name, &client); if (ret != 0) { error = vstrallocf(_("error parsing %s: %s"), principal_name, error_message(ret)); return (error); } #ifdef KRB5_HEIMDAL_INCLUDES ret = krb5_build_principal_ext(context, &server, krb5_realm_length(*krb5_princ_realm(context, client)), krb5_realm_data(*krb5_princ_realm(context, client)), tgtname.length, tgtname.data, krb5_realm_length(*krb5_princ_realm(context, client)), krb5_realm_data(*krb5_princ_realm(context, client)), 0); #else ret = krb5_build_principal_ext(context, &server, krb5_princ_realm(context, client)->length, krb5_princ_realm(context, client)->data, tgtname.length, tgtname.data, krb5_princ_realm(context, client)->length, krb5_princ_realm(context, client)->data, 0); #endif if (ret != 0) { error = vstrallocf(_("error while building server name: %s"), error_message(ret)); return (error); } ret = krb5_timeofday(context, &now); if (ret != 0) { error = vstrallocf(_("error getting time of day: %s"), error_message(ret)); return (error); } memset(&creds, 0, SIZEOF(creds)); creds.times.starttime = 0; creds.times.endtime = now + AMANDA_TKT_LIFETIME; creds.client = client; creds.server = server; /* * Get a ticket for the service, using the keytab */ ret = krb5_get_in_tkt_with_keytab(context, 0, NULL, NULL, NULL, keytab, 0, &creds, 0); if (ret != 0) { error = vstrallocf(_("error getting ticket for %s: %s"), principal_name, error_message(ret)); goto cleanup2; } if ((ret = krb5_cc_default(context, &ccache)) != 0) { error = vstrallocf(_("error initializing ccache: %s"), error_message(ret)); goto cleanup; } if ((ret = krb5_cc_initialize(context, ccache, client)) != 0) { error = vstrallocf(_("error initializing ccache: %s"), error_message(ret)); goto cleanup; } if ((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) { error = vstrallocf(_("error storing creds in ccache: %s"), error_message(ret)); /* FALLTHROUGH */ } krb5_cc_close(context, ccache); cleanup: krb5_free_cred_contents(context, &creds); cleanup2: #if 0 krb5_free_principal(context, client); krb5_free_principal(context, server); #endif krb5_free_context(context); return (error); }
/* * create Kerberos memory cache */ int krb5_create_cache(struct main_args *margs,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; int retval=0; int found=0; krb5_error_code code = 0; kparam.context=NULL; if (!domain || !strcmp(domain,"")) return(1); /* * Initialise Kerberos */ code = krb5_init_context(&kparam.context); if (code) { fprintf(stderr, "%s| %s: Error while initialising Kerberos library : %s\n",LogTime(), PROGRAM, error_message(code)); retval=1; goto cleanup; } /* * getting default keytab name */ if (margs->debug) fprintf(stderr, "%s| %s: 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 = strdup(p ? p : buf); if (margs->debug) fprintf(stderr, "%s| %s: Got default keytab file name %s\n",LogTime(), PROGRAM, keytab_name); code = krb5_kt_resolve(kparam.context, keytab_name, &keytab); if (code) { fprintf(stderr, "%s| %s: 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) { fprintf(stderr, "%s| %s: Error while starting keytab scan : %s\n", LogTime(), PROGRAM, error_message(code)); retval=1; goto cleanup; } if (margs->debug) fprintf(stderr, "%s| %s: 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) { principal_list=realloc(principal_list,sizeof(krb5_principal)*(nprinc+1)); krb5_copy_principal(kparam.context,entry.principal,&principal_list[nprinc++]); if (margs->debug) #ifdef HAVE_HEIMDAL_KERBEROS fprintf(stderr, "%s| %s: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, entry.principal->realm); #else fprintf(stderr, "%s| %s: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, krb5_princ_realm(kparam.context, entry.principal)->data); #endif #ifdef HAVE_HEIMDAL_KERBEROS if (!strcasecmp(domain, entry.principal->realm)) #else if (!strcasecmp(domain,krb5_princ_realm(kparam.context, entry.principal)->data)) #endif { code = krb5_unparse_name(kparam.context, entry.principal, &principal_name); if (code) { fprintf(stderr, "%s| %s: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code)); } else { if (margs->debug) fprintf(stderr, "%s| %s: Found principal name: %s\n", LogTime(), PROGRAM, principal_name); found=1; } } #if defined(HAVE_HEIMDAL_KERBEROS) || ( defined(HAVE_KRB5_KT_FREE_ENTRY) && HAVE_DECL_KRB5_KT_FREE_ENTRY==1) code = krb5_kt_free_entry(kparam.context,&entry); #else code = krb5_free_keytab_entry_contents(kparam.context,&entry); #endif if (code) { fprintf(stderr, "%s| %s: Error while freeing keytab entry : %s\n", LogTime(), PROGRAM, error_message(code)); retval=1; break; } if (found) break; } if (code && code != KRB5_KT_END) { fprintf(stderr, "%s| %s: 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) { fprintf(stderr, "%s| %s: Error while ending keytab scan : %s\n", LogTime(), PROGRAM, error_message(code)); retval=1; goto cleanup; } /* * prepare memory credential cache */ #ifndef HAVE_KRB5_MEMORY_CACHE mem_cache=malloc(strlen("FILE:/tmp/squid_ldap_")+16); snprintf(mem_cache,strlen("FILE:/tmp/squid_ldap_")+16,"FILE:/tmp/squid_ldap_%d",(int)getpid()); #else mem_cache=malloc(strlen("MEMORY:squid_ldap_")+16); snprintf(mem_cache,strlen("MEMORY:squid_ldap_")+16,"MEMORY:squid_ldap_%d",(int)getpid()); #endif setenv("KRB5CCNAME",mem_cache,1); if (margs->debug) fprintf(stderr, "%s| %s: Set credential cache to %s\n",LogTime(), PROGRAM,mem_cache); code = krb5_cc_resolve(kparam.context, mem_cache , &kparam.cc); if (code) { fprintf(stderr, "%s| %s: Error while resolving memory ccache : %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) { if (margs->debug) { fprintf(stderr, "%s| %s: Did not find a principal in keytab for domain %s.\n",LogTime(), PROGRAM,domain); fprintf(stderr, "%s| %s: Try to get principal of trusted domain.\n",LogTime(), PROGRAM); } creds = malloc(sizeof(*creds)); memset(creds, 0, sizeof(*creds)); for (i=0;i<nprinc;i++) { /* * get credentials */ code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name); if (code) { if (margs->debug) fprintf(stderr, "%s| %s: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code)); goto loop_end; } if (margs->debug) fprintf(stderr, "%s| %s: 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); #else service=malloc(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); if (service) free(service); code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0); #endif if (code) { if (margs->debug) fprintf(stderr, "%s| %s: 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) { fprintf(stderr, "%s| %s: 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) { if (margs->debug) fprintf(stderr, "%s| %s: Error while storing credentials : %s\n",LogTime(), PROGRAM, error_message(code)); goto loop_end; } if (creds->server) krb5_free_principal(kparam.context,creds->server); #ifdef HAVE_HEIMDAL_KERBEROS service=malloc(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=malloc(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); if (service) free(service); if (code) { fprintf(stderr, "%s| %s: 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) { if (margs->debug) fprintf(stderr, "%s| %s: Error while getting tgt : %s\n",LogTime(), PROGRAM, error_message(code)); goto loop_end; } else { if (margs->debug) fprintf(stderr, "%s| %s: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name); break; } loop_end: if (principal_name) free(principal_name); principal_name=NULL; } if (tgt_creds) krb5_free_creds(kparam.context,tgt_creds); tgt_creds=NULL; if (creds) krb5_free_creds(kparam.context,creds); creds=NULL; } if (principal_name) { if (margs->debug) fprintf(stderr, "%s| %s: Got principal name %s\n",LogTime(), PROGRAM, principal_name); /* * build principal */ code = krb5_parse_name(kparam.context, principal_name, &principal); if (code) { fprintf(stderr, "%s| %s: Error while parsing name %s : %s\n", LogTime(), PROGRAM, principal_name,error_message(code)); retval=1; goto cleanup; } creds = malloc(sizeof(*creds)); memset(creds, 0, sizeof(*creds)); /* * get credentials */ #if HAVE_GET_INIT_CREDS_KEYTAB code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, NULL); #else service=malloc(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); if (service) free(service); code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0); #endif if (code) { fprintf(stderr, "%s| %s: Error while initialising credentials from keytab : %s\n",LogTime(), PROGRAM, error_message(code)); retval=1; goto cleanup; } code = krb5_cc_initialize(kparam.context, kparam.cc, principal); if (code) { fprintf(stderr, "%s| %s: Error while initializing memory caches : %s\n",LogTime(), PROGRAM, error_message(code)); retval=1; goto cleanup; } code = krb5_cc_store_cred(kparam.context, kparam.cc, creds); if (code) { fprintf(stderr, "%s| %s: Error while storing credentials : %s\n",LogTime(), PROGRAM, error_message(code)); retval=1; goto cleanup; } if (margs->debug) fprintf(stderr, "%s| %s: Stored credentials\n",LogTime(), PROGRAM); } else { if (margs->debug) fprintf(stderr, "%s| %s: Got no principal name\n",LogTime(), PROGRAM); retval=1; } cleanup: if (keytab) krb5_kt_close(kparam.context, keytab); if (keytab_name) free(keytab_name); if (principal_name) free(principal_name); if (mem_cache) free(mem_cache); if (principal) krb5_free_principal(kparam.context,principal); for (i=0;i<nprinc;i++) { if (principal_list[i]) krb5_free_principal(kparam.context,principal_list[i]); } if (principal_list) free(principal_list); if (creds) krb5_free_creds(kparam.context,creds); return(retval); }