bool_t xdr_krb5_principal(XDR *xdrs, krb5_principal *objp) { int ret; char *p = NULL; krb5_principal pr = NULL; static krb5_context context = NULL; /* using a static context here is ugly, but should work ok, and the other solutions are even uglier */ if (!context && kadm5_init_krb5_context(&context)) return(FALSE); switch(xdrs->x_op) { case XDR_ENCODE: if (*objp) { if((ret = krb5_unparse_name(context, *objp, &p)) != 0) return FALSE; } if(!xdr_nullstring(xdrs, &p)) return FALSE; if (p) free(p); break; case XDR_DECODE: if(!xdr_nullstring(xdrs, &p)) return FALSE; if (p) { ret = krb5_parse_name(context, p, &pr); if(ret != 0) return FALSE; *objp = pr; free(p); } else *objp = NULL; break; case XDR_FREE: if(*objp != NULL) krb5_free_principal(context, *objp); break; } return TRUE; }
static int cli_credentials_set_from_ccache(struct cli_credentials *cred, struct ccache_container *ccache, enum credentials_obtained obtained, const char **error_string) { krb5_principal princ; krb5_error_code ret; char *name; if (cred->ccache_obtained > obtained) { return 0; } ret = krb5_cc_get_principal(ccache->smb_krb5_context->krb5_context, ccache->ccache, &princ); if (ret) { (*error_string) = talloc_asprintf(cred, "failed to get principal from ccache: %s\n", smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context, ret, cred)); return ret; } ret = krb5_unparse_name(ccache->smb_krb5_context->krb5_context, princ, &name); if (ret) { (*error_string) = talloc_asprintf(cred, "failed to unparse principal from ccache: %s\n", smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context, ret, cred)); return ret; } cli_credentials_set_principal(cred, name, obtained); free(name); krb5_free_principal(ccache->smb_krb5_context->krb5_context, princ); /* set the ccache_obtained here, as it just got set to UNINITIALISED by the calls above */ cred->ccache_obtained = obtained; return 0; }
static int set_random_password (krb5_principal principal, int keepold) { krb5_error_code ret; char pw[128]; random_password (pw, sizeof(pw)); ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw); if (ret == 0) { char *princ_name; krb5_unparse_name(context, principal, &princ_name); printf ("%s's password set to \"%s\"\n", princ_name, pw); free (princ_name); } memset (pw, 0, sizeof(pw)); return ret; }
/* * initialize * * initialize the cache, check to see if one already exists for this * principal if not set our principal to this principal. This * searching enables ticket sharing */ krb5_error_code KRB5_CALLCONV krb5_stdcc_initialize (krb5_context context, krb5_ccache id, krb5_principal princ) { stdccCacheDataPtr ccapi_data = NULL; int err; char *cName = NULL; krb5_error_code retval; if ((retval = stdcc_setup(context, NULL))) return retval; /* test id for null */ if (id == NULL) return KRB5_CC_NOMEM; if ((retval = krb5_unparse_name(context, princ, &cName))) return retval; ccapi_data = id->data; if (ccapi_data->NamedCache) cc_close(gCntrlBlock, &ccapi_data->NamedCache); err = cc_create(gCntrlBlock, ccapi_data->cache_name, cName, CC_CRED_V5, 0L, &ccapi_data->NamedCache); if (err != CC_NOERROR) { krb5_free_unparsed_name(context, cName); return cc_err_xlate(err); } #if 0 /* * Some implementations don't set the principal name * correctly, so we force set it to the correct value. */ err = cc_set_principal(gCntrlBlock, ccapi_data->NamedCache, CC_CRED_V5, cName); #endif krb5_free_unparsed_name(context, cName); cache_changed(); return cc_err_xlate(err); }
krb5_error_code krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in, const krb5_data *crealm, const krb5_data *srealm) { krb5_data trans; struct check_data cdata; krb5_error_code r; trans.length = trans_in->length; trans.data = (char *) trans_in->data; if (trans.length && (trans.data[trans.length-1] == '\0')) trans.length--; Tprintf (("krb5_check_transited_list(trans=\"%.*s\", crealm=\"%.*s\", srealm=\"%.*s\")\n", (int) trans.length, trans.data, (int) crealm->length, crealm->data, (int) srealm->length, srealm->data)); if (trans.length == 0) return 0; r = krb5_walk_realm_tree (ctx, crealm, srealm, &cdata.tgs, KRB5_REALM_BRANCH_CHAR); if (r) { Tprintf (("error %ld\n", (long) r)); return r; } #ifdef DEBUG /* avoid compiler warning about 'd' unused */ { int i; Tprintf (("tgs list = {\n")); for (i = 0; cdata.tgs[i]; i++) { char *name; r = krb5_unparse_name (ctx, cdata.tgs[i], &name); Tprintf (("\t'%s'\n", name)); free (name); } Tprintf (("}\n")); } #endif cdata.ctx = ctx; r = foreach_realm (check_realm_in_list, &cdata, crealm, srealm, &trans); krb5_free_realm_tree (ctx, cdata.tgs); return r; }
krb5_error_code KRB5_CALLCONV krb5_cc_cache_match(krb5_context context, krb5_principal client, krb5_ccache *cache_out) { krb5_error_code ret; krb5_cccol_cursor cursor; krb5_ccache cache = NULL; krb5_principal princ; char *name; krb5_boolean eq; *cache_out = NULL; ret = krb5_cccol_cursor_new(context, &cursor); if (ret) return ret; while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 && cache != NULL) { ret = krb5_cc_get_principal(context, cache, &princ); if (ret == 0) { eq = krb5_principal_compare(context, princ, client); krb5_free_principal(context, princ); if (eq) break; } krb5_cc_close(context, cache); } krb5_cccol_cursor_free(context, &cursor); if (ret) return ret; if (cache == NULL) { ret = krb5_unparse_name(context, client, &name); if (ret == 0) { k5_setmsg(context, KRB5_CC_NOTFOUND, _("Can't find client principal %s in cache collection"), name); krb5_free_unparsed_name(context, name); } ret = KRB5_CC_NOTFOUND; } else *cache_out = cache; return ret; }
krb5_error_code smb_krb5_unparse_name(krb5_context context, krb5_const_principal principal, char **unix_name) { krb5_error_code ret; char *utf8_name; ret = krb5_unparse_name(context, principal, &utf8_name); if (ret) { return ret; } if (pull_utf8_allocate(unix_name, utf8_name)==-1) { krb5_free_unparsed_name(context, utf8_name); return ENOMEM; } krb5_free_unparsed_name(context, utf8_name); return 0; }
jobject BuildClientPrincipal(JNIEnv *env, krb5_context kcontext, krb5_principal principalName) { // Get the full principal string. char *principalString = NULL; jobject principal = NULL; int err = krb5_unparse_name (kcontext, principalName, &principalString); if (!err) { // Make a PrincipalName from the full string and the type. Let the PrincipalName class parse it out. jstring principalStringObj = (*env)->NewStringUTF(env, principalString); if (principalStringObj == NULL) { if (principalString != NULL) { krb5_free_unparsed_name (kcontext, principalString); } return (jobject) NULL; } principal = (*env)->NewObject(env, principalNameClass, principalNameConstructor, principalStringObj, principalName->type); if (principalString != NULL) { krb5_free_unparsed_name (kcontext, principalString); } (*env)->DeleteLocalRef(env, principalStringObj); } return principal; }
/* * call-seq: * get_default_principal -> string * * Call krb5_cc_get_principal() to get the principal from the default * cachefile. Returns the default principal on success, raises a * Krb5Auth::Krb5::Exception on failure. */ static VALUE Krb5_get_default_principal(VALUE self) { struct ruby_krb5 *kerb; char *princ_name; VALUE result; krb5_error_code krbret; krb5_ccache cc; Data_Get_Struct(self, struct ruby_krb5, kerb); if (!kerb) { NOSTRUCT_EXCEPT(); return Qfalse; } krbret = krb5_cc_default(kerb->ctx, &cc); if (krbret) { Krb5_register_error(krbret); return Qfalse; } krbret = krb5_cc_get_principal(kerb->ctx, cc, &kerb->princ); if (krbret) { krb5_cc_close(kerb->ctx, cc); Krb5_register_error(krbret); return Qnil; } krb5_cc_close(kerb->ctx, cc); krbret = krb5_unparse_name(kerb->ctx, kerb->princ, &princ_name); if (krbret) { Krb5_register_error(krbret); return Qnil; } result = rb_str_new2(princ_name); free(princ_name); return result; }
krb5_error_code krb5_dbe_update_mod_princ_data(krb5_context context, krb5_db_entry *entry, krb5_timestamp mod_date, krb5_const_principal mod_princ) { krb5_tl_data tl_data; krb5_error_code retval = 0; krb5_octet * nextloc = 0; char * unparse_mod_princ = 0; unsigned int unparse_mod_princ_size; if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ))) return(retval); unparse_mod_princ_size = strlen(unparse_mod_princ) + 1; if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4)) == NULL) { free(unparse_mod_princ); return(ENOMEM); } tl_data.tl_data_type = KRB5_TL_MOD_PRINC; tl_data.tl_data_length = unparse_mod_princ_size + 4; tl_data.tl_data_contents = nextloc; /* Mod Date */ krb5_kdb_encode_int32(mod_date, nextloc); /* Mod Princ */ memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size); retval = krb5_dbe_update_tl_data(context, entry, &tl_data); free(unparse_mod_princ); free(nextloc); return(retval); }
static krb5_error_code foreach(krb5_context context, HDB *db, hdb_entry_ex *ent, void *data) { struct foreach_data *d = data; char *princ; krb5_error_code ret; ret = krb5_unparse_name(context, ent->entry.principal, &princ); if(ret) return ret; if(d->exp){ if(fnmatch(d->exp, princ, 0) == 0 || fnmatch(d->exp2, princ, 0) == 0) ret = add_princ(d, princ); else free(princ); }else{ ret = add_princ(d, princ); } if(ret) free(princ); return ret; }
static int do_check_entry(krb5_principal principal, void *data) { krb5_error_code ret; kadm5_principal_ent_rec princ; char *name; int i; ret = krb5_unparse_name(context, principal, &name); if (ret) return 1; memset (&princ, 0, sizeof(princ)); ret = kadm5_get_principal(kadm_handle, principal, &princ, KADM5_PRINCIPAL | KADM5_KEY_DATA); if(ret) { krb5_warn(context, ret, "Failed to get principal: %s", name); free(name); return 0; } for (i = 0; i < princ.n_key_data; i++) { size_t keysize; ret = krb5_enctype_keysize(context, princ.key_data[i].key_data_type[0], &keysize); if (ret == 0 && keysize != princ.key_data[i].key_data_length[0]) { krb5_warnx(context, "Principal %s enctype %d, wrong length: %lu\n", name, princ.key_data[i].key_data_type[0], (unsigned long)princ.key_data[i].key_data_length); } } free(name); kadm5_free_principal_ent(kadm_handle, &princ); return 0; }
void test_425_conv_principal(krb5_context ctx, char *name, char *inst, char *realm) { krb5_error_code retval; krb5_principal princ; char *out_name; retval = krb5_425_conv_principal(ctx, name, inst, realm, &princ); if (retval) { com_err("krb5_425_conv_principal", retval, 0); return; } retval = krb5_unparse_name(ctx, princ, &out_name); if (retval) { com_err("krb5_unparse_name", retval, 0); return; } printf("425_converted principal(%s, %s, %s): '%s'\n", name, inst, realm, out_name); free(out_name); krb5_free_principal(ctx, princ); }
/* * krb5_principal_size() - Determine the size required to externalize * the krb5_principal. */ static krb5_error_code krb5_principal_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_principal principal; char *fname; /* * krb5_principal requires: * krb5_int32 for KV5M_PRINCIPAL * krb5_int32 for flattened name size * strlen(name) for name. * krb5_int32 for KV5M_PRINCIPAL */ kret = EINVAL; if ((principal = (krb5_principal) arg) && !(kret = krb5_unparse_name(kcontext, principal, &fname))) { *sizep += (3*sizeof(krb5_int32)) + strlen(fname); krb5_xfree(fname); } return(kret); }
static void test_alname(krb5_context context, krb5_const_realm realm, const char *user, const char *inst, const char *localuser, int ok) { krb5_principal p; char localname[1024]; krb5_error_code ret; char *princ; ret = krb5_make_principal(context, &p, realm, user, inst, NULL); if (ret) krb5_err(context, 1, ret, "krb5_build_principal"); ret = krb5_unparse_name(context, p, &princ); if (ret) krb5_err(context, 1, ret, "krb5_unparse_name"); ret = krb5_aname_to_localname(context, p, sizeof(localname), localname); krb5_free_principal(context, p); free(princ); if (ret) { if (!ok) return; krb5_err(context, 1, ret, "krb5_aname_to_localname: %s -> %s", princ, localuser); } if (strcmp(localname, localuser) != 0) { if (ok) errx(1, "compared failed %s != %s (should have succeded)", localname, localuser); } else { if (!ok) errx(1, "compared failed %s == %s (should have failed)", localname, localuser); } }
static krb5_error_code fetch_server (krb5_context context, krb5_kdc_configuration *config, const Ticket *t, char **spn, hdb_entry_ex **server, const char *from) { krb5_error_code ret; krb5_principal sprinc; ret = _krb5_principalname2krb5_principal(context, &sprinc, t->sname, t->realm); if (ret) { kdc_log(context, config, 0, "_krb5_principalname2krb5_principal: %s", krb5_get_err_text(context, ret)); return ret; } ret = krb5_unparse_name(context, sprinc, spn); if (ret) { krb5_free_principal(context, sprinc); kdc_log(context, config, 0, "krb5_unparse_name: %s", krb5_get_err_text(context, ret)); return ret; } ret = _kdc_db_fetch(context, config, sprinc, HDB_F_GET_SERVER, NULL, server); krb5_free_principal(context, sprinc); if (ret) { kdc_log(context, config, 0, "Request to convert ticket from %s for unknown principal %s: %s", from, *spn, krb5_get_err_text(context, ret)); if (ret == HDB_ERR_NOENTRY) ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; return ret; } return 0; }
static void test_cache_iter(krb5_context context, const char *type, int destroy) { krb5_cc_cache_cursor cursor; krb5_error_code ret; krb5_ccache id; ret = krb5_cc_cache_get_first (context, type, &cursor); if (ret == KRB5_CC_NOSUPP) return; else if (ret) krb5_err(context, 1, ret, "krb5_cc_cache_get_first(%s)", type); while ((ret = krb5_cc_cache_next (context, cursor, &id)) == 0) { krb5_principal principal; char *name; if (debug_flag) printf("name: %s\n", krb5_cc_get_name(context, id)); ret = krb5_cc_get_principal(context, id, &principal); if (ret == 0) { ret = krb5_unparse_name(context, principal, &name); if (ret == 0) { if (debug_flag) printf("\tprincipal: %s\n", name); free(name); } krb5_free_principal(context, principal); } if (destroy) krb5_cc_destroy(context, id); else krb5_cc_close(context, id); } krb5_cc_cache_end_seq_get(context, cursor); }
krb5_error_code KRB5_CALLCONV krb5_init_creds_set_keytab(krb5_context context, krb5_init_creds_context ctx, krb5_keytab keytab) { krb5_enctype *etype_list; krb5_error_code ret; char *name; ctx->gak_fct = get_as_key_keytab; ctx->gak_data = keytab; ret = lookup_etypes_for_keytab(context, keytab, ctx->request->client, &etype_list); if (ret) { TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(context, ret); return 0; } TRACE_INIT_CREDS_KEYTAB_LOOKUP(context, etype_list); /* Error out if we have no keys for the client principal. */ if (etype_list == NULL) { ret = krb5_unparse_name(context, ctx->request->client, &name); if (ret == 0) { krb5_set_error_message(context, KRB5_KT_NOTFOUND, _("Keytab contains no suitable keys for " "%s"), name); } krb5_free_unparsed_name(context, name); return KRB5_KT_NOTFOUND; } /* Sort the request enctypes so the ones in the keytab appear first. */ ret = sort_enctypes(ctx->request->ktype, ctx->request->nktypes, etype_list); free(etype_list); return ret; }
static krb5_error_code LDAP_principal2message(krb5_context context, HDB * db, krb5_principal princ, LDAPMessage ** msg) { char *name, *name_short = NULL; krb5_error_code ret; krb5_realm *r, *r0; *msg = NULL; ret = krb5_unparse_name(context, princ, &name); if (ret) return ret; ret = krb5_get_default_realms(context, &r0); if(ret) { free(name); return ret; } for (r = r0; *r != NULL; r++) { if(strcmp(krb5_principal_get_realm(context, princ), *r) == 0) { ret = krb5_unparse_name_short(context, princ, &name_short); if (ret) { krb5_free_host_realm(context, r0); free(name); return ret; } break; } } krb5_free_host_realm(context, r0); ret = LDAP__lookup_princ(context, db, name, name_short, msg); free(name); free(name_short); return ret; }
/* * * Function: Reads the name and realm out of the ccache. * * Parameters: * ccache - credentials cache to get info from * * name - buffer to hold user name * * realm - buffer to hold the realm * * * Returns: TRUE if read names, FALSE if not * */ int k5_name_from_ccache(krb5_ccache k5_ccache) { krb5_error_code code; krb5_principal princ; char name[ANAME_SZ]; char realm[REALM_SZ]; char *defname; if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ)) return FALSE; code = krb5_unparse_name(k5_context, princ, &defname); if (code) { return FALSE; } k5_kname_parse(name, realm, defname); /* Extract the components */ strcpy(cns_res.name, name); strcpy(cns_res.realm, realm); return TRUE; }
kim_error kim_identity_get_string (kim_identity in_identity, kim_string *out_string) { kim_error err = KIM_NO_ERROR; char *unparsed_name = NULL; if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err) { err = krb5_error (in_identity->context, krb5_unparse_name (in_identity->context, in_identity->principal, &unparsed_name)); } if (!err) { err = kim_string_copy (out_string, unparsed_name); } if (unparsed_name) { krb5_free_unparsed_name (in_identity->context, unparsed_name); } return check_error (err); }
static krb5_error_code bind_principal(krb5_context context, sqlite3 *db, sqlite3_stmt *stmt, int col, krb5_const_principal principal) { krb5_error_code ret; char *str; ret = krb5_unparse_name(context, principal, &str); if (ret) return ret; ret = sqlite3_bind_text(stmt, col, str, -1, free_krb5); if (ret != SQLITE_OK) { krb5_xfree(str); krb5_set_error_message(context, ENOMEM, N_("scache bind principal: %s", ""), sqlite3_errmsg(db)); return ENOMEM; } return 0; }
OM_uint32 gss_display_name (OM_uint32 * minor_status, const gss_name_t input_name, gss_buffer_t output_name_buffer, gss_OID * output_name_type ) { krb5_error_code kret; char *buf; size_t len; GSSAPI_KRB5_INIT (); kret = krb5_unparse_name (gssapi_krb5_context, input_name, &buf); if (kret) { *minor_status = kret; gssapi_krb5_set_error_string (); return GSS_S_FAILURE; } len = strlen (buf); output_name_buffer->length = len; output_name_buffer->value = malloc(len + 1); if (output_name_buffer->value == NULL) { free (buf); *minor_status = ENOMEM; return GSS_S_FAILURE; } memcpy (output_name_buffer->value, buf, len); ((char *)output_name_buffer->value)[len] = '\0'; free (buf); if (output_name_type) *output_name_type = GSS_KRB5_NT_PRINCIPAL_NAME; *minor_status = 0; return GSS_S_COMPLETE; }
static const char* KRB5_CALLCONV acc_get_name(krb5_context context, krb5_ccache id) { krb5_acc *a = ACACHE(id); int32_t error; if (a->cache_name == NULL) { krb5_error_code ret; krb5_principal principal; char *name; ret = _krb5_get_default_principal_local(context, &principal); if (ret) return NULL; ret = krb5_unparse_name(context, principal, &name); krb5_free_principal(context, principal); if (ret) return NULL; error = (*a->context->func->create_new_ccache)(a->context, cc_credentials_v5, name, &a->ccache); krb5_xfree(name); if (error) return NULL; error = get_cc_name(a); if (error) return NULL; } return a->cache_name; }
static krb5_error_code get_new_tickets(krb5_context context, krb5_principal principal, krb5_ccache ccache, krb5_deltat ticket_life, int interactive) { krb5_error_code ret; krb5_creds cred; char passwd[256]; krb5_deltat start_time = 0; krb5_deltat renew = 0; const char *renewstr = NULL; krb5_enctype *enctype = NULL; krb5_ccache tempccache = NULL; krb5_init_creds_context ctx = NULL; krb5_get_init_creds_opt *opt = NULL; krb5_prompter_fct prompter = krb5_prompter_posix; #ifndef NO_NTLM struct ntlm_buf ntlmkey; memset(&ntlmkey, 0, sizeof(ntlmkey)); #endif passwd[0] = '\0'; if (!interactive) prompter = NULL; if (password_file) { FILE *f; if (strcasecmp("STDIN", password_file) == 0) f = stdin; else f = fopen(password_file, "r"); if (f == NULL) { krb5_warnx(context, "Failed to open the password file %s", password_file); return errno; } if (fgets(passwd, sizeof(passwd), f) == NULL) { krb5_warnx(context, N_("Failed to read password from file %s", ""), password_file); fclose(f); return EINVAL; /* XXX Need a better error */ } if (f != stdin) fclose(f); passwd[strcspn(passwd, "\n")] = '\0'; } #ifdef __APPLE__ if (passwd[0] == '\0') { const char *realm; OSStatus osret; UInt32 length; void *buffer; char *name; realm = krb5_principal_get_realm(context, principal); ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); if (ret) goto nopassword; osret = SecKeychainFindGenericPassword(NULL, strlen(realm), realm, strlen(name), name, &length, &buffer, NULL); free(name); if (osret == noErr && length < sizeof(passwd) - 1) { memcpy(passwd, buffer, length); passwd[length] = '\0'; } nopassword: do { } while(0); } #endif memset(&cred, 0, sizeof(cred)); ret = krb5_get_init_creds_opt_alloc(context, &opt); if (ret) { krb5_warn(context, ret, "krb5_get_init_creds_opt_alloc"); goto out; } krb5_get_init_creds_opt_set_default_flags(context, "kinit", krb5_principal_get_realm(context, principal), opt); if (forwardable_flag != -1) krb5_get_init_creds_opt_set_forwardable(opt, forwardable_flag); if (proxiable_flag != -1) krb5_get_init_creds_opt_set_proxiable(opt, proxiable_flag); if (anonymous_flag) krb5_get_init_creds_opt_set_anonymous(opt, anonymous_flag); if (pac_flag != -1) krb5_get_init_creds_opt_set_pac_request(context, opt, pac_flag ? TRUE : FALSE); if (canonicalize_flag) krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE); if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag) krb5_get_init_creds_opt_set_win2k(context, opt, TRUE); if (pk_user_id || ent_user_id || anonymous_flag) { ret = krb5_get_init_creds_opt_set_pkinit(context, opt, principal, pk_user_id, pk_x509_anchors, NULL, NULL, pk_use_enckey ? 2 : 0 | anonymous_flag ? 4 : 0, prompter, NULL, passwd); if (ret) { krb5_warn(context, ret, "krb5_get_init_creds_opt_set_pkinit"); goto out; } if (ent_user_id) krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id); } if (addrs_flag != -1) krb5_get_init_creds_opt_set_addressless(context, opt, addrs_flag ? FALSE : TRUE); if (renew_life == NULL && renewable_flag) renewstr = "1 month"; if (renew_life) renewstr = renew_life; if (renewstr) { renew = parse_time(renewstr, "s"); if (renew < 0) errx(1, "unparsable time: %s", renewstr); krb5_get_init_creds_opt_set_renew_life(opt, renew); } if (ticket_life != 0) krb5_get_init_creds_opt_set_tkt_life(opt, ticket_life); if (start_str) { int tmp = parse_time(start_str, "s"); if (tmp < 0) errx(1, N_("unparsable time: %s", ""), start_str); start_time = tmp; } if (etype_str.num_strings) { int i; enctype = malloc(etype_str.num_strings * sizeof(*enctype)); if (enctype == NULL) errx(1, "out of memory"); for(i = 0; i < etype_str.num_strings; i++) { ret = krb5_string_to_enctype(context, etype_str.strings[i], &enctype[i]); if (ret) errx(1, "unrecognized enctype: %s", etype_str.strings[i]); } krb5_get_init_creds_opt_set_etype_list(opt, enctype, etype_str.num_strings); } ret = krb5_init_creds_init(context, principal, prompter, NULL, start_time, opt, &ctx); if (ret) { krb5_warn(context, ret, "krb5_init_creds_init"); goto out; } if (server_str) { ret = krb5_init_creds_set_service(context, ctx, server_str); if (ret) { krb5_warn(context, ret, "krb5_init_creds_set_service"); goto out; } } if (fast_armor_cache_string) { krb5_ccache fastid; ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid); if (ret) { krb5_warn(context, ret, "krb5_cc_resolve(FAST cache)"); goto out; } ret = krb5_init_creds_set_fast_ccache(context, ctx, fastid); if (ret) { krb5_warn(context, ret, "krb5_init_creds_set_fast_ccache"); goto out; } } if (use_keytab || keytab_str) { ret = krb5_init_creds_set_keytab(context, ctx, kt); if (ret) { krb5_warn(context, ret, "krb5_init_creds_set_keytab"); goto out; } } else if (pk_user_id || ent_user_id || anonymous_flag) { } else if (!interactive && passwd[0] == '\0') { static int already_warned = 0; if (!already_warned) krb5_warnx(context, "Not interactive, failed to get " "initial ticket"); krb5_get_init_creds_opt_free(context, opt); already_warned = 1; return 0; } else { if (passwd[0] == '\0') { char *p, *prompt; int aret = 0; ret = krb5_unparse_name(context, principal, &p); if (ret) errx(1, "failed to generate passwd prompt: not enough memory"); aret = asprintf(&prompt, N_("%s's Password: "******""), p); free(p); if (aret == -1) errx(1, "failed to generate passwd prompt: not enough memory"); if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ memset(passwd, 0, sizeof(passwd)); errx(1, "failed to read password"); } free(prompt); } if (passwd[0]) { ret = krb5_init_creds_set_password(context, ctx, passwd); if (ret) { krb5_warn(context, ret, "krb5_init_creds_set_password"); goto out; } } } ret = krb5_init_creds_get(context, ctx); #ifndef NO_NTLM if (ntlm_domain && passwd[0]) heim_ntlm_nt_key(passwd, &ntlmkey); #endif memset(passwd, 0, sizeof(passwd)); switch(ret){ case 0: break; case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */ exit(1); case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_MODIFIED: case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5_GET_IN_TKT_LOOP: krb5_warnx(context, N_("Password incorrect", "")); goto out; case KRB5KRB_AP_ERR_V4_REPLY: krb5_warnx(context, N_("Looks like a Kerberos 4 reply", "")); goto out; case KRB5KDC_ERR_KEY_EXPIRED: krb5_warnx(context, N_("Password expired", "")); goto out; default: krb5_warn(context, ret, "krb5_get_init_creds"); goto out; } krb5_process_last_request(context, opt, ctx); ret = krb5_init_creds_get_creds(context, ctx, &cred); if (ret) { krb5_warn(context, ret, "krb5_init_creds_get_creds"); goto out; } if (ticket_life != 0) { if (abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) { char life[64]; unparse_time_approx(cred.times.endtime - cred.times.starttime, life, sizeof(life)); krb5_warnx(context, N_("NOTICE: ticket lifetime is %s", ""), life); } } if (renew_life) { if (abs(cred.times.renew_till - cred.times.starttime - renew) > 30) { char life[64]; unparse_time_approx(cred.times.renew_till - cred.times.starttime, life, sizeof(life)); krb5_warnx(context, N_("NOTICE: ticket renewable lifetime is %s", ""), life); } } krb5_free_cred_contents(context, &cred); ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache), NULL, &tempccache); if (ret) { krb5_warn(context, ret, "krb5_cc_new_unique"); goto out; } ret = krb5_init_creds_store(context, ctx, tempccache); if (ret) { krb5_warn(context, ret, "krb5_init_creds_store"); goto out; } krb5_init_creds_free(context, ctx); ctx = NULL; ret = krb5_cc_move(context, tempccache, ccache); if (ret) { krb5_warn(context, ret, "krb5_cc_move"); goto out; } tempccache = NULL; if (switch_cache_flags) krb5_cc_switch(context, ccache); #ifndef NO_NTLM if (ntlm_domain && ntlmkey.data) store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey); #endif if (ok_as_delegate_flag || windows_flag || use_referrals_flag) { unsigned char d = 0; krb5_data data; if (ok_as_delegate_flag || windows_flag) d |= 1; if (use_referrals_flag || windows_flag) d |= 2; data.length = 1; data.data = &d; krb5_cc_set_config(context, ccache, NULL, "realm-config", &data); } out: krb5_get_init_creds_opt_free(context, opt); if (ctx) krb5_init_creds_free(context, ctx); if (tempccache) krb5_cc_close(context, tempccache); if (enctype) free(enctype); return ret; }
static int kinit_check_tgt(kinit_data *kid, int *remaining) { int ret=3; krb5_principal princ; krb5_error_code rc; krb5_cc_cursor cursor; krb5_creds creds; char *name; time_t now=time(NULL); rc = krb5_cc_get_principal(kid->ctx, kid->ccache, &princ); if (rc) { log_krb5_errmsg(kid->ctx, "krb5_cc_get_principal", rc); return 2; } else { if (!krb5_principal_compare(kid->ctx, kid->princ, princ)) { Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "Principal in ccache does not match requested principal\n"); krb5_free_principal(kid->ctx, princ); return 2; } } rc = krb5_cc_start_seq_get(kid->ctx, kid->ccache, &cursor); if (rc) { log_krb5_errmsg(kid->ctx, "krb5_cc_start_seq_get", rc); krb5_free_principal(kid->ctx, princ); return -1; } while (!(rc = krb5_cc_next_cred(kid->ctx, kid->ccache, &cursor, &creds))) { if (krb5_is_config_principal(kid->ctx, creds.server)) { krb5_free_cred_contents(kid->ctx, &creds); continue; } if (creds.server->length==2 && (!strcmp(creds.server->data[0].data, "krbtgt")) && (!strcmp(creds.server->data[1].data, princ->realm.data))) { krb5_unparse_name(kid->ctx, creds.server, &name); *remaining = (time_t)creds.times.endtime-now; if ( *remaining <= 0) { Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "kinit_qtask: TGT (%s) expired\n", name); } else { Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "kinit_qtask: TGT (%s) expires in %dh:%02dm:%02ds\n", name, *remaining/3600, (*remaining%3600)/60, *remaining%60); } free(name); if (*remaining <= 30) { if (creds.times.renew_till-60 > now) { int renewal=creds.times.renew_till-now; Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "kinit_qtask: Time remaining for renewal: %dh:%02dm:%02ds\n", renewal/3600, (renewal%3600)/60, renewal%60); ret = 1; } else { Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "kinit_qtask: Only short time left for renewal. " "Trying to re-init.\n"); ret = 2; } } else { ret=0; } krb5_free_cred_contents(kid->ctx, &creds); break; } krb5_free_cred_contents(kid->ctx, &creds); } krb5_cc_end_seq_get(kid->ctx, kid->ccache, &cursor); krb5_free_principal(kid->ctx, princ); return ret; }
int print_keytab (const char *in_name) { krb5_error_code err = 0; krb5_keytab kt; krb5_keytab_entry entry; krb5_kt_cursor cursor; char keytab_name[BUFSIZ]; /* hopefully large enough for any type */ if (!err) { if (!in_name) { err = krb5_kt_default (kcontext, &kt); printiferr (err, "while resolving default keytab"); } else { err = krb5_kt_resolve (kcontext, in_name, &kt); printiferr (err, "while resolving keytab %s", in_name); } } if (!err) { err = krb5_kt_get_name (kcontext, kt, keytab_name, sizeof (keytab_name)); printiferr (err, "while getting keytab name"); } if (!err) { printmsg ("Keytab name: %s\n", keytab_name); } if (!err) { err = krb5_kt_start_seq_get (kcontext, kt, &cursor); printiferr (err, "while starting scan of keytab %s", keytab_name); } if (!err) { if (show_entry_timestamps) { printmsg ("KVNO Timestamp"); printfiller (' ', get_timestamp_width () - sizeof ("Timestamp") + 2); printmsg ("Principal\n"); printmsg ("---- "); printfiller ('-', get_timestamp_width ()); printmsg (" "); printfiller ('-', 78 - get_timestamp_width () - sizeof ("KVNO")); printmsg ("\n"); } else { printmsg("KVNO Principal\n"); printmsg("---- --------------------------------------------------------------------------\n"); } } while (!err) { char *principal_name = NULL; err = krb5_kt_next_entry (kcontext, kt, &entry, &cursor); if (err == KRB5_KT_END) { err = 0; break; } if (!err) { err = krb5_unparse_name (kcontext, entry.principal, &principal_name); printiferr (err, "while unparsing principal name"); } if (!err) { printmsg ("%4d ", entry.vno); if (show_entry_timestamps) { printtime (entry.timestamp); printmsg (" "); } printmsg ("%s", principal_name); if (show_enctypes) { printmsg (" (%s) ", enctype_to_string (entry.key.enctype)); } if (show_entry_DES_keys) { unsigned int i; printmsg (" (0x"); for (i = 0; i < entry.key.length; i++) { printmsg ("%02x", entry.key.contents[i]); } printmsg (")"); } printmsg ("\n"); } printiferr (err, "while scanning keytab %s", keytab_name); if (principal_name) { krb5_free_unparsed_name (kcontext, principal_name); } } if (!err) { err = krb5_kt_end_seq_get (kcontext, kt, &cursor); printiferr (err, "while ending scan of keytab %s", keytab_name); } return err ? 1 : 0; }
static krb5_error_code krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context, const krb5_ap_req *req, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket, int check_valid_flag) { krb5_error_code retval = 0; krb5_timestamp currenttime; krb5_principal_data princ_data; req->ticket->enc_part2 == NULL; if (server && krb5_is_referral_realm(&server->realm)) { char *realm; princ_data = *server; server = &princ_data; retval = krb5_get_default_realm(context, &realm); if (retval) return retval; princ_data.realm.data = realm; princ_data.realm.length = strlen(realm); } if (server && !krb5_principal_compare(context, server, req->ticket->server)) { char *found_name = 0, *wanted_name = 0; if (krb5_unparse_name(context, server, &wanted_name) == 0 && krb5_unparse_name(context, req->ticket->server, &found_name) == 0) krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC, "Wrong principal in request (found %s, wanted %s)", found_name, wanted_name); krb5_free_unparsed_name(context, wanted_name); krb5_free_unparsed_name(context, found_name); retval = KRB5KRB_AP_WRONG_PRINC; goto cleanup; } /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY) do we need special processing here ? */ /* decrypt the ticket */ if ((*auth_context)->keyblock) { /* User to User authentication */ if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock, req->ticket))) goto cleanup; krb5_free_keyblock(context, (*auth_context)->keyblock); (*auth_context)->keyblock = NULL; } else { if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab))) goto cleanup; } /* XXX this is an evil hack. check_valid_flag is set iff the call is not from inside the kdc. we can use this to determine which key usage to use */ if ((retval = decrypt_authenticator(context, req, &((*auth_context)->authentp), check_valid_flag))) goto cleanup; if (!krb5_principal_compare(context, (*auth_context)->authentp->client, req->ticket->enc_part2->client)) { retval = KRB5KRB_AP_ERR_BADMATCH; goto cleanup; } if ((*auth_context)->remote_addr && !krb5_address_search(context, (*auth_context)->remote_addr, req->ticket->enc_part2->caddrs)) { retval = KRB5KRB_AP_ERR_BADADDR; goto cleanup; } /* okay, now check cross-realm policy */ #if defined(_SINGLE_HOP_ONLY) /* Single hop cross-realm tickets only */ { krb5_transited *trans = &(req->ticket->enc_part2->transited); /* If the transited list is empty, then we have at most one hop */ if (trans->tr_contents.data && trans->tr_contents.data[0]) retval = KRB5KRB_AP_ERR_ILL_CR_TKT; } #elif defined(_NO_CROSS_REALM) /* No cross-realm tickets */ { char * lrealm; krb5_data * realm; krb5_transited * trans; realm = krb5_princ_realm(context, req->ticket->enc_part2->client); trans = &(req->ticket->enc_part2->transited); /* * If the transited list is empty, then we have at most one hop * So we also have to check that the client's realm is the local one */ krb5_get_default_realm(context, &lrealm); if ((trans->tr_contents.data && trans->tr_contents.data[0]) || strlen(lrealm) != realm->length || memcmp(lrealm, realm->data, strlen(lrealm))) { retval = KRB5KRB_AP_ERR_ILL_CR_TKT; } free(lrealm); } #else /* Hierarchical Cross-Realm */ { krb5_data * realm; krb5_transited * trans; realm = krb5_princ_realm(context, req->ticket->enc_part2->client); trans = &(req->ticket->enc_part2->transited); /* * If the transited list is not empty, then check that all realms * transited are within the hierarchy between the client's realm * and the local realm. */ if (trans->tr_contents.data && trans->tr_contents.data[0]) { retval = krb5_check_transited_list(context, &(trans->tr_contents), realm, krb5_princ_realm (context, server)); } } #endif if (retval) goto cleanup; /* only check rcache if sender has provided one---some services may not be able to use replay caches (such as datagram servers) */ if ((*auth_context)->rcache) { krb5_donot_replay rep; krb5_tkt_authent tktauthent; tktauthent.ticket = req->ticket; tktauthent.authenticator = (*auth_context)->authentp; if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) { retval = krb5_rc_store(context, (*auth_context)->rcache, &rep); krb5_xfree(rep.server); krb5_xfree(rep.client); } if (retval) goto cleanup; } retval = krb5_validate_times(context, &req->ticket->enc_part2->times); if (retval != 0) goto cleanup; if ((retval = krb5_timeofday(context, ¤ttime))) goto cleanup; if (!in_clock_skew((*auth_context)->authentp->ctime)) { retval = KRB5KRB_AP_ERR_SKEW; goto cleanup; } if (check_valid_flag) { if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) { retval = KRB5KRB_AP_ERR_TKT_INVALID; goto cleanup; } } /* check if the various etypes are permitted */ if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) { /* no etype check needed */; } else if ((*auth_context)->permitted_etypes == NULL) { int etype; /* check against the default set */ if ((!krb5_is_permitted_enctype(context, etype = req->ticket->enc_part.enctype)) || (!krb5_is_permitted_enctype(context, etype = req->ticket->enc_part2->session->enctype)) || (((*auth_context)->authentp->subkey) && !krb5_is_permitted_enctype(context, etype = (*auth_context)->authentp->subkey->enctype))) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } } else { /* check against the set in the auth_context */ int i; for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == req->ticket->enc_part.enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(req->ticket->enc_part.enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == req->ticket->enc_part2->session->enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } if ((*auth_context)->authentp->subkey) { for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == (*auth_context)->authentp->subkey->enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } } } (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number; if ((*auth_context)->authentp->subkey) { if ((retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey, &((*auth_context)->recv_subkey)))) goto cleanup; retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey, &((*auth_context)->send_subkey)); if (retval) { krb5_free_keyblock(context, (*auth_context)->recv_subkey); (*auth_context)->recv_subkey = NULL; goto cleanup; } } else { (*auth_context)->recv_subkey = 0; (*auth_context)->send_subkey = 0; } if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session, &((*auth_context)->keyblock)))) goto cleanup; /* * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used * then the default sequence number is the one's complement of the * sequence number sent ot us. */ if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && (*auth_context)->remote_seq_number) { (*auth_context)->local_seq_number ^= (*auth_context)->remote_seq_number; } if (ticket) if ((retval = krb5_copy_ticket(context, req->ticket, ticket))) goto cleanup; if (ap_req_options) *ap_req_options = req->ap_options; retval = 0; cleanup: if (server == &princ_data) krb5_free_default_realm(context, princ_data.realm.data); if (retval) { /* only free if we're erroring out...otherwise some applications will need the output. */ if (req->ticket->enc_part2) krb5_free_enc_tkt_part(context, req->ticket->enc_part2); req->ticket->enc_part2 = NULL; } return retval; }
/* Get a TGT for use at the remote host */ krb5_error_code KRB5_CALLCONV krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf) /* Should forwarded TGT also be forwardable? */ { krb5_replay_data replaydata; krb5_data * scratch = 0; krb5_address **addrs = NULL; krb5_error_code retval; krb5_creds creds, tgt; krb5_creds *pcreds; krb5_flags kdcoptions; int close_cc = 0; int free_rhost = 0; krb5_enctype enctype = 0; krb5_keyblock *session_key; krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes; memset((char *)&creds, 0, sizeof(creds)); memset((char *)&tgt, 0, sizeof(creds)); if (cc == 0) { if ((retval = krb5int_cc_default(context, &cc))) goto errout; close_cc = 1; } retval = krb5_auth_con_getkey (context, auth_context, &session_key); if (retval) goto errout; if (session_key) { enctype = session_key->enctype; krb5_free_keyblock (context, session_key); session_key = NULL; } else if (server) { /* must server be non-NULL when rhost is given? */ /* Try getting credentials to see what the remote side supports. Not bulletproof, just a heuristic. */ krb5_creds in, *out = 0; memset (&in, 0, sizeof(in)); retval = krb5_copy_principal (context, server, &in.server); if (retval) goto punt; retval = krb5_copy_principal (context, client, &in.client); if (retval) goto punt; retval = krb5_get_credentials (context, 0, cc, &in, &out); if (retval) goto punt; /* Got the credentials. Okay, now record the enctype and throw them away. */ enctype = out->keyblock.enctype; krb5_free_creds (context, out); punt: krb5_free_cred_contents (context, &in); } if ((retval = krb5_copy_principal(context, client, &creds.client))) goto errout; if ((retval = krb5_build_principal_ext(context, &creds.server, client->realm.length, client->realm.data, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, client->realm.length, client->realm.data, 0))) goto errout; /* fetch tgt directly from cache */ context->use_conf_ktypes = 1; retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES, &creds, &tgt); context->use_conf_ktypes = old_use_conf_ktypes; if (retval) goto errout; /* tgt->client must be equal to creds.client */ if (!krb5_principal_compare(context, tgt.client, creds.client)) { /* Solaris Kerberos */ char *r_name = NULL; char *t_name = NULL; krb5_error_code r_err, t_err; t_err = krb5_unparse_name(context, tgt.client, &t_name); r_err = krb5_unparse_name(context, creds.client, &r_name); krb5_set_error_message(context, KRB5_PRINC_NOMATCH, dgettext(TEXT_DOMAIN, "Requested principal and ticket don't match: Requested principal is '%s' and TGT principal is '%s'"), r_err ? "unknown" : r_name, t_err ? "unknown" : t_name); if (r_name) krb5_free_unparsed_name(context, r_name); if (t_name) krb5_free_unparsed_name(context, t_name); retval = KRB5_PRINC_NOMATCH; goto errout; } if (!tgt.ticket.length) { retval = KRB5_NO_TKT_SUPPLIED; goto errout; } if (tgt.addresses && *tgt.addresses) { if (rhost == NULL) { if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) { retval = KRB5_FWD_BAD_PRINCIPAL; goto errout; } if (krb5_princ_size(context, server) < 2){ retval = KRB5_CC_BADNAME; goto errout; } rhost = malloc(server->data[1].length+1); if (!rhost) { retval = ENOMEM; goto errout; } free_rhost = 1; /* Solaris Kerberos */ (void) memcpy(rhost, server->data[1].data, server->data[1].length); rhost[server->data[1].length] = '\0'; } retval = krb5_os_hostaddr(context, rhost, &addrs); if (retval) goto errout; } creds.keyblock.enctype = enctype; creds.times = tgt.times; creds.times.starttime = 0; kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED; if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */ kdcoptions &= ~(KDC_OPT_FORWARDABLE); if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, addrs, &creds, &pcreds))) { if (enctype) { creds.keyblock.enctype = 0; if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, addrs, &creds, &pcreds))) goto errout; } else goto errout; } retval = krb5_mk_1cred(context, auth_context, pcreds, &scratch, &replaydata); krb5_free_creds(context, pcreds); /* * Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be * more robust. */ if (scratch) { if (retval) krb5_free_data(context, scratch); else { *outbuf = *scratch; krb5_xfree(scratch); } } errout: if (addrs) krb5_free_addresses(context, addrs); /* Solaris Kerberos */ if (close_cc) (void) krb5_cc_close(context, cc); if (free_rhost) free(rhost); krb5_free_cred_contents(context, &creds); krb5_free_cred_contents(context, &tgt); return retval; }
static krb5_error_code verify_client_san(krb5_context context, pkinit_kdc_context plgctx, pkinit_kdc_req_context reqctx, krb5_principal client, int *valid_san) { krb5_error_code retval; krb5_principal *princs = NULL; krb5_principal *upns = NULL; int i; #ifdef DEBUG_SAN_INFO char *client_string = NULL, *san_string; #endif retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx, reqctx->cryptoctx, plgctx->idctx, &princs, plgctx->opts->allow_upn ? &upns : NULL, NULL); if (retval) { pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__); retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; goto out; } /* XXX Verify this is consistent with client side XXX */ #if 0 retval = call_san_checking_plugins(context, plgctx, reqctx, princs, upns, NULL, &plugin_decision, &ignore); pkiDebug("%s: call_san_checking_plugins() returned retval %d\n", __FUNCTION__); if (retval) { retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; goto cleanup; } pkiDebug("%s: call_san_checking_plugins() returned decision %d\n", __FUNCTION__, plugin_decision); if (plugin_decision != NO_DECISION) { retval = plugin_decision; goto out; } #endif #ifdef DEBUG_SAN_INFO krb5_unparse_name(context, client, &client_string); #endif pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__); for (i = 0; princs != NULL && princs[i] != NULL; i++) { #ifdef DEBUG_SAN_INFO krb5_unparse_name(context, princs[i], &san_string); pkiDebug("%s: Comparing client '%s' to pkinit san value '%s'\n", __FUNCTION__, client_string, san_string); krb5_free_unparsed_name(context, san_string); #endif if (krb5_principal_compare(context, princs[i], client)) { pkiDebug("%s: pkinit san match found\n", __FUNCTION__); *valid_san = 1; retval = 0; goto out; } } pkiDebug("%s: no pkinit san match found\n", __FUNCTION__); /* * XXX if cert has names but none match, should we * be returning KRB5KDC_ERR_CLIENT_NAME_MISMATCH here? */ if (upns == NULL) { pkiDebug("%s: no upn sans (or we wouldn't accept them anyway)\n", __FUNCTION__); retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; goto out; } pkiDebug("%s: Checking upn sans\n", __FUNCTION__); for (i = 0; upns[i] != NULL; i++) { #ifdef DEBUG_SAN_INFO krb5_unparse_name(context, upns[i], &san_string); pkiDebug("%s: Comparing client '%s' to upn san value '%s'\n", __FUNCTION__, client_string, san_string); krb5_free_unparsed_name(context, san_string); #endif if (krb5_principal_compare(context, upns[i], client)) { pkiDebug("%s: upn san match found\n", __FUNCTION__); *valid_san = 1; retval = 0; goto out; } } pkiDebug("%s: no upn san match found\n", __FUNCTION__); /* We found no match */ if (princs != NULL || upns != NULL) { *valid_san = 0; /* XXX ??? If there was one or more name in the cert, but * none matched the client name, then return mismatch? */ retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; } retval = 0; out: if (princs != NULL) { for (i = 0; princs[i] != NULL; i++) krb5_free_principal(context, princs[i]); free(princs); } if (upns != NULL) { for (i = 0; upns[i] != NULL; i++) krb5_free_principal(context, upns[i]); free(upns); } #ifdef DEBUG_SAN_INFO if (client_string != NULL) krb5_free_unparsed_name(context, client_string); #endif pkiDebug("%s: returning retval %d, valid_san %d\n", __FUNCTION__, retval, *valid_san); return retval; }