📄 init_creds_pw.c
字号:
if (ctx->pk_init_ctx) { ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md); if (ret) return ret; } else if (in_md->len != 0) { struct pa_info_data paid, *ppaid; memset(&paid, 0, sizeof(paid)); paid.etype = ENCTYPE_NULL; ppaid = process_pa_info(context, creds->client, a, &paid, in_md); pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md); if (ppaid) free_paid(context, ppaid); } pa_data_add_pac_request(context, ctx, *out_md); if ((*out_md)->len == 0) { free(*out_md); *out_md = NULL; } return 0;}static krb5_error_codeprocess_pa_data_to_key(krb5_context context, krb5_get_init_creds_ctx *ctx, krb5_creds *creds, AS_REQ *a, krb5_kdc_rep *rep, const krb5_krbhst_info *hi, krb5_keyblock **key){ struct pa_info_data paid, *ppaid = NULL; krb5_error_code ret; krb5_enctype etype; PA_DATA *pa; memset(&paid, 0, sizeof(paid)); etype = rep->kdc_rep.enc_part.etype; if (rep->kdc_rep.padata) { paid.etype = etype; ppaid = process_pa_info(context, creds->client, a, &paid, rep->kdc_rep.padata); } if (ppaid == NULL) { ret = krb5_get_pw_salt (context, creds->client, &paid.salt); if (ret) return ret; paid.etype = etype; paid.s2kparams = NULL; } pa = NULL; if (rep->kdc_rep.padata) { int idx = 0; pa = krb5_find_padata(rep->kdc_rep.padata->val, rep->kdc_rep.padata->len, KRB5_PADATA_PK_AS_REP, &idx); if (pa == NULL) { idx = 0; pa = krb5_find_padata(rep->kdc_rep.padata->val, rep->kdc_rep.padata->len, KRB5_PADATA_PK_AS_REP_19, &idx); } } if (pa && ctx->pk_init_ctx) {#ifdef PKINIT ret = _krb5_pk_rd_pa_reply(context, a->req_body.realm, ctx->pk_init_ctx, etype, hi, ctx->pk_nonce, &ctx->req_buffer, pa, key);#else krb5_set_error_string(context, "no support for PKINIT compiled in"); ret = EINVAL;#endif } else if (ctx->password) ret = pa_data_to_key_plain(context, creds->client, ctx, paid.salt, paid.s2kparams, etype, key); else { krb5_set_error_string(context, "No usable pa data type"); ret = EINVAL; } free_paid(context, &paid); return ret;}static krb5_error_codeinit_cred_loop(krb5_context context, krb5_get_init_creds_opt *init_cred_opts, const krb5_prompter_fct prompter, void *prompter_data, krb5_get_init_creds_ctx *ctx, krb5_creds *creds, krb5_kdc_rep *ret_as_reply){ krb5_error_code ret; krb5_kdc_rep rep; METHOD_DATA md; krb5_data resp; size_t len; size_t size; krb5_krbhst_info *hi = NULL; krb5_sendto_ctx stctx = NULL; memset(&md, 0, sizeof(md)); memset(&rep, 0, sizeof(rep)); _krb5_get_init_creds_opt_free_krb5_error(init_cred_opts); if (ret_as_reply) memset(ret_as_reply, 0, sizeof(*ret_as_reply)); ret = init_creds_init_as_req(context, ctx->flags, creds, ctx->addrs, ctx->etypes, &ctx->as_req); if (ret) return ret; ret = krb5_sendto_ctx_alloc(context, &stctx); if (ret) goto out; krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); /* Set a new nonce. */ krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce)); ctx->nonce &= 0xffffffff; /* XXX these just needs to be the same when using Windows PK-INIT */ ctx->pk_nonce = ctx->nonce; /* * Increase counter when we want other pre-auth types then * KRB5_PA_ENC_TIMESTAMP. */#define MAX_PA_COUNTER 3 ctx->pa_counter = 0; while (ctx->pa_counter < MAX_PA_COUNTER) { ctx->pa_counter++; if (ctx->as_req.padata) { free_METHOD_DATA(ctx->as_req.padata); free(ctx->as_req.padata); ctx->as_req.padata = NULL; } /* Set a new nonce. */ ctx->as_req.req_body.nonce = ctx->nonce; /* fill_in_md_data */ ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx, &md, &ctx->as_req.padata, prompter, prompter_data); if (ret) goto out; krb5_data_free(&ctx->req_buffer); ASN1_MALLOC_ENCODE(AS_REQ, ctx->req_buffer.data, ctx->req_buffer.length, &ctx->as_req, &len, ret); if (ret) goto out; if(len != ctx->req_buffer.length) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_sendto_context (context, stctx, &ctx->req_buffer, creds->client->realm, &resp); if (ret) goto out; memset (&rep, 0, sizeof(rep)); ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size); if (ret == 0) { krb5_data_free(&resp); krb5_clear_error_string(context); break; } else { /* let's try to parse it as a KRB-ERROR */ KRB_ERROR error; ret = krb5_rd_error(context, &resp, &error); if(ret && resp.data && ((char*)resp.data)[0] == 4) ret = KRB5KRB_AP_ERR_V4_REPLY; krb5_data_free(&resp); if (ret) goto out; ret = krb5_error_from_rd_error(context, &error, creds); /* * If no preauth was set and KDC requires it, give it one * more try. */ if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) { free_METHOD_DATA(&md); memset(&md, 0, sizeof(md)); if (error.e_data) { ret = decode_METHOD_DATA(error.e_data->data, error.e_data->length, &md, NULL); if (ret) krb5_set_error_string(context, "failed to decode METHOD DATA"); } else { /* XXX guess what the server want here add add md */ } krb5_free_error_contents(context, &error); if (ret) goto out; } else { _krb5_get_init_creds_opt_set_krb5_error(context, init_cred_opts, &error); if (ret_as_reply) rep.error = error; else krb5_free_error_contents(context, &error); goto out; } } } { krb5_keyblock *key = NULL; unsigned flags = 0; if (ctx->flags.request_anonymous) flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; if (ctx->flags.canonicalize) { flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; flags |= EXTRACT_TICKET_MATCH_REALM; } ret = process_pa_data_to_key(context, ctx, creds, &ctx->as_req, &rep, hi, &key); if (ret) goto out; ret = _krb5_extract_ticket(context, &rep, creds, key, NULL, KRB5_KU_AS_REP_ENC_PART, NULL, ctx->nonce, flags, NULL, NULL); krb5_free_keyblock(context, key); } /* * Verify referral data */ if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) && (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK) == 0) { PA_ClientCanonicalized canon; krb5_crypto crypto; krb5_data data; PA_DATA *pa; size_t len; pa = find_pa_data(rep.kdc_rep.padata, KRB5_PADATA_CLIENT_CANONICALIZED); if (pa == NULL) { ret = EINVAL; krb5_set_error_string(context, "Client canonicalizion not signed"); goto out; } ret = decode_PA_ClientCanonicalized(pa->padata_value.data, pa->padata_value.length, &canon, &len); if (ret) { krb5_set_error_string(context, "Failed to decode " "PA_ClientCanonicalized"); goto out; } ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, &canon.names, &len, ret); if (ret) goto out; if (data.length != len) krb5_abortx(context, "internal asn.1 error"); ret = krb5_crypto_init(context, &creds->session, 0, &crypto); if (ret) { free(data.data); free_PA_ClientCanonicalized(&canon); goto out; } ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES, data.data, data.length, &canon.canon_checksum); krb5_crypto_destroy(context, crypto); free(data.data); free_PA_ClientCanonicalized(&canon); if (ret) { krb5_set_error_string(context, "Failed to verify " "client canonicalized data"); goto out; } }out: if (stctx) krb5_sendto_ctx_free(context, stctx); krb5_data_free(&ctx->req_buffer); free_METHOD_DATA(&md); memset(&md, 0, sizeof(md)); if (ret == 0 && ret_as_reply) *ret_as_reply = rep; else krb5_free_kdc_rep (context, &rep); return ret;}krb5_error_code KRB5_LIB_FUNCTIONkrb5_get_init_creds(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_prompter_fct prompter, void *data, krb5_deltat start_time, const char *in_tkt_service, krb5_get_init_creds_opt *options){ krb5_get_init_creds_ctx ctx; krb5_kdc_rep kdc_reply; krb5_error_code ret; char buf[BUFSIZ]; int done; memset(&kdc_reply, 0, sizeof(kdc_reply)); ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; done = 0; while(!done) { memset(&kdc_reply, 0, sizeof(kdc_reply)); ret = init_cred_loop(context, options, prompter, data, &ctx, &ctx.cred, &kdc_reply); switch (ret) { case 0 : done = 1; break; case KRB5KDC_ERR_KEY_EXPIRED : /* try to avoid recursion */ /* don't try to change password where then where none */ if (prompter == NULL || ctx.password == NULL) goto out; krb5_clear_error_string (context); if (ctx.in_tkt_service != NULL && strcmp (ctx.in_tkt_service, "kadmin/changepw") == 0) goto out; ret = change_password (context, client, ctx.password, buf, sizeof(buf), prompter, data, options); if (ret) goto out; ctx.password = buf; break; default: goto out; } } if (prompter) print_expire (context, krb5_principal_get_realm (context, ctx.cred.client), &kdc_reply, prompter, data); out: memset (buf, 0, sizeof(buf)); free_init_creds_ctx(context, &ctx); krb5_free_kdc_rep (context, &kdc_reply); if (ret == 0) *creds = ctx.cred; else krb5_free_cred_contents (context, &ctx.cred); return ret;}krb5_error_code KRB5_LIB_FUNCTIONkrb5_get_init_creds_password(krb5_context context, krb5_creds *creds, krb5_principal client, const char *password, krb5_prompter_fct prompter, void *data, krb5_deltat start_time, const char *in_tkt_service, krb5_get_init_creds_opt *in_options){ krb5_get_init_creds_opt *options; char buf[BUFSIZ]; krb5_error_code ret; if (in_options == NULL) { const char *realm = krb5_principal_get_realm(context, client); ret = krb5_get_init_creds_opt_alloc(context, &options); if (ret == 0) krb5_get_init_creds_opt_set_default_flags(context, NULL, realm, options); } else ret = _krb5_get_init_creds_opt_copy(context, in_options, &options); if (ret) return ret; if (password == NULL && options->opt_private->password == NULL && options->opt_private->pk_init_ctx == NULL) { krb5_prompt prompt; krb5_data password_data; char *p, *q; krb5_unparse_name (context, client, &p); asprintf (&q, "%s's Password: ", p); free (p); prompt.prompt = q; password_data.data = buf; password_data.length = sizeof(buf); prompt.hidden = 1; prompt.reply = &password_data; prompt.type = KRB5_PROMPT_TYPE_PASSWORD; ret = (*prompter) (context, data, NULL, NULL, 1, &prompt); free (q); if (ret) { memset (buf, 0, sizeof(buf)); krb5_get_init_creds_opt_free(context, options); ret = KRB5_LIBOS_PWDINTR; krb5_clear_error_string (context); return ret; } password = password_data.data; } if (options->opt_private->password == NULL) { ret = krb5_get_init_creds_opt_set_pa_password(context, options, password, NULL); if (ret) { krb5_get_init_creds_opt_free(context, options); memset(buf, 0, sizeof(buf)); return ret; } } ret = krb5_get_init_creds(context, creds, client, prompter, data, start_time, in_tkt_service, options); krb5_get_init_creds_opt_free(context, options); memset(buf, 0, sizeof(buf)); return ret;}static krb5_error_codeinit_creds_keyblock_key_proc (krb5_context context, krb5_enctype type, krb5_salt salt, krb5_const_pointer keyseed, krb5_keyblock **key){ return krb5_copy_keyblock (context, keyseed, key);}krb5_error_code KRB5_LIB_FUNCTIONkrb5_get_init_creds_keyblock(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_keyblock *keyblock, krb5_deltat start_time, const char *in_tkt_service, krb5_get_init_creds_opt *options){ struct krb5_get_init_creds_ctx ctx; krb5_error_code ret; ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; ret = krb5_get_in_cred (context, KDCOptions2int(ctx.flags), ctx.addrs, ctx.etypes, ctx.pre_auth_types, NULL, init_creds_keyblock_key_proc, keyblock, NULL, NULL, &ctx.cred, NULL); if (ret == 0 && creds) *creds = ctx.cred; else krb5_free_cred_contents (context, &ctx.cred); out: free_init_creds_ctx(context, &ctx); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -