📄 pkinit.c
字号:
if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) { AuthPack_Win2k ap; ret = decode_AuthPack_Win2k(eContent.data, eContent.length, &ap, NULL); if (ret) { krb5_set_error_string(context, "can't decode AuthPack: %d", ret); goto out; } ret = pk_check_pkauthenticator_win2k(context, &ap.pkAuthenticator, req); if (ret) { free_AuthPack_Win2k(&ap); goto out; } client_params->type = PKINIT_COMPAT_WIN2K; client_params->nonce = ap.pkAuthenticator.nonce; if (ap.clientPublicValue) { krb5_set_error_string(context, "DH not supported for windows"); ret = KRB5KRB_ERR_GENERIC; goto out; } free_AuthPack_Win2k(&ap); } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) { AuthPack ap; ret = decode_AuthPack(eContent.data, eContent.length, &ap, NULL); if (ret) { krb5_set_error_string(context, "can't decode AuthPack: %d", ret); free_AuthPack(&ap); goto out; } ret = pk_check_pkauthenticator(context, &ap.pkAuthenticator, req); if (ret) { free_AuthPack(&ap); goto out; } client_params->type = PKINIT_COMPAT_27; client_params->nonce = ap.pkAuthenticator.nonce; if (ap.clientPublicValue) { ret = get_dh_param(context, config, ap.clientPublicValue, client_params); if (ret) { free_AuthPack(&ap); goto out; } } if (ap.supportedCMSTypes) { ret = hx509_peer_info_alloc(kdc_identity->hx509ctx, &client_params->peer); if (ret) { free_AuthPack(&ap); goto out; } ret = hx509_peer_info_set_cms_algs(kdc_identity->hx509ctx, client_params->peer, ap.supportedCMSTypes->val, ap.supportedCMSTypes->len); if (ret) { free_AuthPack(&ap); goto out; } } free_AuthPack(&ap); } else krb5_abortx(context, "internal pkinit error"); kdc_log(context, config, 0, "PK-INIT request of type %s", type);out: if (ret) krb5_warn(context, ret, "PKINIT"); if (signed_content.data) free(signed_content.data); krb5_data_free(&eContent); der_free_oid(&eContentType); der_free_oid(&contentInfoOid); if (ret) _kdc_pk_free_client_param(context, client_params); else *ret_params = client_params; return ret;}/* * */static krb5_error_codeBN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer){ integer->length = BN_num_bytes(bn); integer->data = malloc(integer->length); if (integer->data == NULL) { krb5_clear_error_string(context); return ENOMEM; } BN_bn2bin(bn, integer->data); integer->negative = BN_is_negative(bn); return 0;}static krb5_error_codepk_mk_pa_reply_enckey(krb5_context context, krb5_kdc_configuration *config, pk_client_params *client_params, const KDC_REQ *req, const krb5_data *req_buffer, krb5_keyblock *reply_key, ContentInfo *content_info){ const heim_oid *envelopedAlg = NULL, *sdAlg = NULL; krb5_error_code ret; krb5_data buf, signed_data; size_t size; int do_win2k = 0; krb5_data_zero(&buf); krb5_data_zero(&signed_data); /* * If the message client is a win2k-type but it send pa data * 09-binding it expects a IETF (checksum) reply so there can be * no replay attacks. */ switch (client_params->type) { case PKINIT_COMPAT_WIN2K: { int i = 0; if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL && config->pkinit_require_binding == 0) { do_win2k = 1; } break; } case PKINIT_COMPAT_27: break; default: krb5_abortx(context, "internal pkinit error"); } if (do_win2k) { ReplyKeyPack_Win2k kp; memset(&kp, 0, sizeof(kp)); envelopedAlg = oid_id_rsadsi_des_ede3_cbc(); sdAlg = oid_id_pkcs7_data(); ret = copy_EncryptionKey(reply_key, &kp.replyKey); if (ret) { krb5_clear_error_string(context); goto out; } kp.nonce = client_params->nonce; ASN1_MALLOC_ENCODE(ReplyKeyPack_Win2k, buf.data, buf.length, &kp, &size,ret); free_ReplyKeyPack_Win2k(&kp); } else { krb5_crypto ascrypto; ReplyKeyPack kp; memset(&kp, 0, sizeof(kp)); sdAlg = oid_id_pkrkeydata(); ret = copy_EncryptionKey(reply_key, &kp.replyKey); if (ret) { krb5_clear_error_string(context); goto out; } ret = krb5_crypto_init(context, reply_key, 0, &ascrypto); if (ret) { krb5_clear_error_string(context); goto out; } ret = krb5_create_checksum(context, ascrypto, 6, 0, req_buffer->data, req_buffer->length, &kp.asChecksum); if (ret) { krb5_clear_error_string(context); goto out; } ret = krb5_crypto_destroy(context, ascrypto); if (ret) { krb5_clear_error_string(context); goto out; } ASN1_MALLOC_ENCODE(ReplyKeyPack, buf.data, buf.length, &kp, &size,ret); free_ReplyKeyPack(&kp); } if (ret) { krb5_set_error_string(context, "ASN.1 encoding of ReplyKeyPack " "failed (%d)", ret); goto out; } if (buf.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); { hx509_query *q; hx509_cert cert; ret = hx509_query_alloc(kdc_identity->hx509ctx, &q); if (ret) goto out; hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); ret = hx509_certs_find(kdc_identity->hx509ctx, kdc_identity->certs, q, &cert); hx509_query_free(kdc_identity->hx509ctx, q); if (ret) goto out; ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx, 0, sdAlg, buf.data, buf.length, NULL, cert, client_params->peer, client_params->client_anchors, kdc_identity->certpool, &signed_data); hx509_cert_free(cert); } krb5_data_free(&buf); if (ret) goto out; if (client_params->type == PKINIT_COMPAT_WIN2K) { ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &signed_data, &buf); if (ret) goto out; krb5_data_free(&signed_data); signed_data = buf; } ret = hx509_cms_envelope_1(kdc_identity->hx509ctx, 0, client_params->cert, signed_data.data, signed_data.length, envelopedAlg, oid_id_pkcs7_signedData(), &buf); if (ret) goto out; ret = _krb5_pk_mk_ContentInfo(context, &buf, oid_id_pkcs7_envelopedData(), content_info);out: krb5_data_free(&buf); krb5_data_free(&signed_data); return ret;}/* * */static krb5_error_codepk_mk_pa_reply_dh(krb5_context context, DH *kdc_dh, pk_client_params *client_params, krb5_keyblock *reply_key, ContentInfo *content_info, hx509_cert *kdc_cert){ KDCDHKeyInfo dh_info; krb5_data signed_data, buf; ContentInfo contentinfo; krb5_error_code ret; size_t size; heim_integer i; memset(&contentinfo, 0, sizeof(contentinfo)); memset(&dh_info, 0, sizeof(dh_info)); krb5_data_zero(&buf); krb5_data_zero(&signed_data); *kdc_cert = NULL; ret = BN_to_integer(context, kdc_dh->pub_key, &i); if (ret) return ret; ASN1_MALLOC_ENCODE(DHPublicKey, buf.data, buf.length, &i, &size, ret); if (ret) { krb5_set_error_string(context, "ASN.1 encoding of " "DHPublicKey failed (%d)", ret); krb5_clear_error_string(context); return ret; } if (buf.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); dh_info.subjectPublicKey.length = buf.length * 8; dh_info.subjectPublicKey.data = buf.data; dh_info.nonce = client_params->nonce; ASN1_MALLOC_ENCODE(KDCDHKeyInfo, buf.data, buf.length, &dh_info, &size, ret); if (ret) { krb5_set_error_string(context, "ASN.1 encoding of " "KdcDHKeyInfo failed (%d)", ret); goto out; } if (buf.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); /* * Create the SignedData structure and sign the KdcDHKeyInfo * filled in above */ { hx509_query *q; hx509_cert cert; ret = hx509_query_alloc(kdc_identity->hx509ctx, &q); if (ret) goto out; hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); ret = hx509_certs_find(kdc_identity->hx509ctx, kdc_identity->certs, q, &cert); hx509_query_free(kdc_identity->hx509ctx, q); if (ret) goto out; ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx, 0, oid_id_pkdhkeydata(), buf.data, buf.length, NULL, cert, client_params->peer, client_params->client_anchors, kdc_identity->certpool, &signed_data); *kdc_cert = cert; } if (ret) goto out; ret = _krb5_pk_mk_ContentInfo(context, &signed_data, oid_id_pkcs7_signedData(), content_info); if (ret) goto out; out: if (ret && *kdc_cert) { hx509_cert_free(*kdc_cert); *kdc_cert = NULL; } krb5_data_free(&buf); krb5_data_free(&signed_data); free_KDCDHKeyInfo(&dh_info); return ret;}/* * */krb5_error_code_kdc_pk_mk_pa_reply(krb5_context context, krb5_kdc_configuration *config, pk_client_params *client_params, const hdb_entry_ex *client, const KDC_REQ *req, const krb5_data *req_buffer, krb5_keyblock **reply_key, METHOD_DATA *md){ krb5_error_code ret; void *buf; size_t len, size; krb5_enctype enctype; int pa_type; hx509_cert kdc_cert = NULL; int i; if (!config->enable_pkinit) { krb5_clear_error_string(context); return 0; } if (req->req_body.etype.len > 0) { for (i = 0; i < req->req_body.etype.len; i++) if (krb5_enctype_valid(context, req->req_body.etype.val[i]) == 0) break; if (req->req_body.etype.len <= i) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_string(context, "No valid enctype available from client"); goto out; } enctype = req->req_body.etype.val[i]; } else enctype = ETYPE_DES3_CBC_SHA1; if (client_params->type == PKINIT_COMPAT_27) { PA_PK_AS_REP rep; const char *type, *other = ""; memset(&rep, 0, sizeof(rep)); pa_type = KRB5_PADATA_PK_AS_REP; if (client_params->dh == NULL) { ContentInfo info; type = "enckey"; rep.element = choice_PA_PK_AS_REP_encKeyPack; ret = krb5_generate_random_keyblock(context, enctype, &client_params->reply_key); if (ret) { free_PA_PK_AS_REP(&rep); goto out; } ret = pk_mk_pa_reply_enckey(context, config, client_params, req, req_buffer, &client_params->reply_key, &info); if (ret) { free_PA_PK_AS_REP(&rep); goto out; } ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data, rep.u.encKeyPack.length, &info, &size, ret); free_ContentInfo(&info); if (ret) { krb5_set_error_string(context, "encoding of Key ContentInfo " "failed %d", ret); free_PA_PK_AS_REP(&rep); goto out; } if (rep.u.encKeyPack.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); } else { ContentInfo info; type = "dh"; if (client_params->dh_group_name) other = client_params->dh_group_name; rep.element = choice_PA_PK_AS_REP_dhInfo; ret = generate_dh_keyblock(context, client_params, enctype, &client_params->reply_key); if (ret) return ret; ret = pk_mk_pa_reply_dh(context, client_params->dh, client_params, &client_params->reply_key, &info, &kdc_cert); ASN1_MALLOC_ENCODE(ContentInfo, rep.u.dhInfo.dhSignedData.data, rep.u.dhInfo.dhSignedData.length, &info, &size, ret); free_ContentInfo(&info); if (ret) { krb5_set_error_string(context, "encoding of Key ContentInfo " "failed %d", ret); free_PA_PK_AS_REP(&rep); goto out; } if (rep.u.encKeyPack.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); } if (ret) { free_PA_PK_AS_REP(&rep); goto out; } ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret); free_PA_PK_AS_REP(&rep); if (ret) { krb5_set_error_string(context, "encode PA-PK-AS-REP failed %d", ret); goto out; } if (len != size) krb5_abortx(context, "Internal ASN.1 encoder error"); kdc_log(context, config, 0, "PK-INIT using %s %s", type, other); } else if (client_params->type == PKINIT_COMPAT_WIN2K) { PA_PK_AS_REP_Win2k rep; ContentInfo info; if (client_params->dh) { krb5_set_error_string(context, "Windows PK-INIT doesn't support DH"); ret = KRB5KRB_ERR_GENERIC; goto out; } memset(&rep, 0, sizeof(rep)); pa_type = KRB5_PADATA_PK_AS_REP_19; rep.element = choice_PA_PK_AS_REP_encKeyPack; ret = krb5_generate_random_keyblock(context, enctype, &client_params->reply_key); if (ret) { free_PA_PK_AS_REP_Win2k(&rep); goto out;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -