📄 pkinit.c
字号:
content.data, content.length, ctx->id, &contentType, &content, &host); if (ret) goto out; /* make sure that it is the kdc's certificate */ ret = pk_verify_host(context, realm, hi, ctx, host); if (ret) { goto out; }#if 0 if (type == COMPAT_WIN2K) { if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; } } else { if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; } }#endif switch(type) { case COMPAT_WIN2K: ret = get_reply_key(context, &content, req_buffer, key); if (ret != 0 && ctx->require_binding == 0) ret = get_reply_key_win(context, &content, nonce, key); break; case COMPAT_IETF: ret = get_reply_key(context, &content, req_buffer, key); break; } if (ret) goto out; /* XXX compare given etype with key->etype */ out: if (host) _krb5_pk_cert_free(host); der_free_oid(&contentType); krb5_data_free(&content); return ret;}static krb5_error_codepk_rd_pa_reply_dh(krb5_context context, const heim_octet_string *indata, const heim_oid *dataType, const char *realm, krb5_pk_init_ctx ctx, krb5_enctype etype, const krb5_krbhst_info *hi, const DHNonce *c_n, const DHNonce *k_n, unsigned nonce, PA_DATA *pa, krb5_keyblock **key){ unsigned char *p, *dh_gen_key = NULL; struct krb5_pk_cert *host = NULL; BIGNUM *kdc_dh_pubkey = NULL; KDCDHKeyInfo kdc_dh_info; heim_oid contentType = { 0, NULL }; krb5_data content; krb5_error_code ret; int dh_gen_keylen; size_t size; krb5_data_zero(&content); memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } ret = _krb5_pk_verify_sign(context, indata->data, indata->length, ctx->id, &contentType, &content, &host); if (ret) goto out; /* make sure that it is the kdc's certificate */ ret = pk_verify_host(context, realm, hi, ctx, host); if (ret) goto out; if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { krb5_set_error_string(context, "pkinit - dh reply contains wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; } ret = decode_KDCDHKeyInfo(content.data, content.length, &kdc_dh_info, &size); if (ret) { krb5_set_error_string(context, "pkinit - " "failed to decode KDC DH Key Info"); goto out; } if (kdc_dh_info.nonce != nonce) { krb5_set_error_string(context, "PKINIT: DH nonce is wrong"); ret = KRB5KRB_AP_ERR_MODIFIED; goto out; } if (kdc_dh_info.dhKeyExpiration) { if (k_n == NULL) { krb5_set_error_string(context, "pkinit; got key expiration " "without server nonce"); ret = KRB5KRB_ERR_GENERIC; goto out; } if (c_n == NULL) { krb5_set_error_string(context, "pkinit; got DH reuse but no " "client nonce"); ret = KRB5KRB_ERR_GENERIC; goto out; } } else { if (k_n) { krb5_set_error_string(context, "pkinit: got server nonce " "without key expiration"); ret = KRB5KRB_ERR_GENERIC; goto out; } c_n = NULL; } p = kdc_dh_info.subjectPublicKey.data; size = (kdc_dh_info.subjectPublicKey.length + 7) / 8; { DHPublicKey k; ret = decode_DHPublicKey(p, size, &k, NULL); if (ret) { krb5_set_error_string(context, "pkinit: can't decode " "without key expiration"); goto out; } kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k); free_DHPublicKey(&k); if (kdc_dh_pubkey == NULL) { ret = KRB5KRB_ERR_GENERIC; goto out; } } dh_gen_keylen = DH_size(ctx->dh); size = BN_num_bytes(ctx->dh->p); if (size < dh_gen_keylen) size = dh_gen_keylen; dh_gen_key = malloc(size); if (dh_gen_key == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; goto out; } memset(dh_gen_key, 0, size - dh_gen_keylen); dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen), kdc_dh_pubkey, ctx->dh); if (dh_gen_keylen == -1) { krb5_set_error_string(context, "PKINIT: Can't compute Diffie-Hellman key"); ret = KRB5KRB_ERR_GENERIC; goto out; } *key = malloc (sizeof (**key)); if (*key == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; goto out; } ret = _krb5_pk_octetstring2key(context, etype, dh_gen_key, dh_gen_keylen, c_n, k_n, *key); if (ret) { krb5_set_error_string(context, "PKINIT: can't create key from DH key"); free(*key); *key = NULL; goto out; } out: if (kdc_dh_pubkey) BN_free(kdc_dh_pubkey); if (dh_gen_key) { memset(dh_gen_key, 0, DH_size(ctx->dh)); free(dh_gen_key); } if (host) _krb5_pk_cert_free(host); if (content.data) krb5_data_free(&content); der_free_oid(&contentType); free_KDCDHKeyInfo(&kdc_dh_info); return ret;}krb5_error_code KRB5_LIB_FUNCTION_krb5_pk_rd_pa_reply(krb5_context context, const char *realm, void *c, krb5_enctype etype, const krb5_krbhst_info *hi, unsigned nonce, const krb5_data *req_buffer, PA_DATA *pa, krb5_keyblock **key){ krb5_pk_init_ctx ctx = c; krb5_error_code ret; size_t size; /* Check for IETF PK-INIT first */ if (ctx->type == COMPAT_IETF) { PA_PK_AS_REP rep; heim_octet_string os, data; heim_oid oid; if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { krb5_set_error_string(context, "PKINIT: wrong padata recv"); return EINVAL; } ret = decode_PA_PK_AS_REP(pa->padata_value.data, pa->padata_value.length, &rep, &size); if (ret) { krb5_set_error_string(context, "Failed to decode pkinit AS rep"); return ret; } switch (rep.element) { case choice_PA_PK_AS_REP_dhInfo: os = rep.u.dhInfo.dhSignedData; break; case choice_PA_PK_AS_REP_encKeyPack: os = rep.u.encKeyPack; break; default: free_PA_PK_AS_REP(&rep); krb5_set_error_string(context, "PKINIT: -27 reply " "invalid content type"); return EINVAL; } ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL); if (ret) { free_PA_PK_AS_REP(&rep); krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); return ret; } switch (rep.element) { case choice_PA_PK_AS_REP_dhInfo: ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi, ctx->clientDHNonce, rep.u.dhInfo.serverDHNonce, nonce, pa, key); break; case choice_PA_PK_AS_REP_encKeyPack: ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm, ctx, etype, hi, nonce, req_buffer, pa, key); break; default: krb5_abortx(context, "pk-init as-rep case not possible to happen"); } der_free_octet_string(&data); der_free_oid(&oid); free_PA_PK_AS_REP(&rep); } else if (ctx->type == COMPAT_WIN2K) { PA_PK_AS_REP_Win2k w2krep; /* Check for Windows encoding of the AS-REP pa data */ #if 0 /* should this be ? */ if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { krb5_set_error_string(context, "PKINIT: wrong padata recv"); return EINVAL; }#endif memset(&w2krep, 0, sizeof(w2krep)); ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data, pa->padata_value.length, &w2krep, &size); if (ret) { krb5_set_error_string(context, "PKINIT: Failed decoding windows " "pkinit reply %d", ret); return ret; } krb5_clear_error_string(context); switch (w2krep.element) { case choice_PA_PK_AS_REP_Win2k_encKeyPack: { heim_octet_string data; heim_oid oid; ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack, &oid, &data, NULL); free_PA_PK_AS_REP_Win2k(&w2krep); if (ret) { krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); return ret; } ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm, ctx, etype, hi, nonce, req_buffer, pa, key); der_free_octet_string(&data); der_free_oid(&oid); break; } default: free_PA_PK_AS_REP_Win2k(&w2krep); krb5_set_error_string(context, "PKINIT: win2k reply invalid " "content type"); ret = EINVAL; break; } } else { krb5_set_error_string(context, "PKINIT: unknown reply type"); ret = EINVAL; } return ret;}struct prompter { krb5_context context; krb5_prompter_fct prompter; void *prompter_data;};static int hx_pass_prompter(void *data, const hx509_prompt *prompter){ krb5_error_code ret; krb5_prompt prompt; krb5_data password_data; struct prompter *p = data; password_data.data = prompter->reply.data; password_data.length = prompter->reply.length; prompt.prompt = prompter->prompt; prompt.hidden = hx509_prompt_hidden(prompter->type); prompt.reply = &password_data; switch (prompter->type) { case HX509_PROMPT_TYPE_INFO: prompt.type = KRB5_PROMPT_TYPE_INFO; break; case HX509_PROMPT_TYPE_PASSWORD: case HX509_PROMPT_TYPE_QUESTION: default: prompt.type = KRB5_PROMPT_TYPE_PASSWORD; break; } ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt); if (ret) { memset (prompter->reply.data, 0, prompter->reply.length); return 1; } return 0;}void KRB5_LIB_FUNCTION_krb5_pk_allow_proxy_certificate(struct krb5_pk_identity *id, int boolean){ hx509_verify_set_proxy_certificate(id->verify_ctx, boolean);}krb5_error_code KRB5_LIB_FUNCTION_krb5_pk_load_id(krb5_context context, struct krb5_pk_identity **ret_id, const char *user_id, const char *anchor_id, char * const *chain_list, char * const *revoke_list, krb5_prompter_fct prompter, void *prompter_data, char *password){ struct krb5_pk_identity *id = NULL; hx509_lock lock = NULL; struct prompter p; int ret; *ret_id = NULL; if (anchor_id == NULL) { krb5_set_error_string(context, "PKINIT: No anchor given"); return HEIM_PKINIT_NO_VALID_CA; } if (user_id == NULL) { krb5_set_error_string(context, "PKINIT: No user certificate given"); return HEIM_PKINIT_NO_PRIVATE_KEY; } /* load cert */ id = calloc(1, sizeof(*id)); if (id == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } ret = hx509_context_init(&id->hx509ctx); if (ret) goto out; ret = hx509_lock_init(id->hx509ctx, &lock); if (password && password[0]) hx509_lock_add_password(lock, password); if (prompter) { p.context = context; p.prompter = prompter; p.prompter_data = prompter_data; ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p); if (ret) goto out; } ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs); if (ret) { _krb5_pk_copy_error(context, id->hx509ctx, ret, "Failed to init cert certs"); goto out; } ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors); if (ret) { _krb5_pk_copy_error(context, id->hx509ctx, ret, "Failed to init anchors"); goto out; } ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain", 0, NULL, &id->certpool); if (ret) { _krb5_pk_copy_error(context, id->hx509ctx, ret, "Failed to init chain"); goto out; } while (chain_list && *chain_list) { ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain_list); if (ret) { _krb5_pk_copy_error(context, id->hx509ctx, ret, "Failed to laod chain %s", *chain_list); goto out; } chain_list++; } if (revoke_list) { ret = hx509_revoke_init(id->hx509ctx, &id->revokectx); if (ret) { _krb5_pk_copy_error(context, id->hx509ctx, ret, "Failed init revoke list"); goto out; } while (*revoke_list) { ret = hx509_revoke_add_crl(id->hx509ctx, id->revokectx, *revoke_list); if (ret) { _krb5_pk_copy_error(context, id->hx509ctx, ret, "Failed load revoke list"); goto out; } revoke_list++; } } else hx509_context_set_missing_revoke(id->hx509ctx, 1); ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx); if (ret) { _krb5_pk_copy_error(context, id->hx509ctx, ret, "Failed init verify context");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -