diff options
Diffstat (limited to 'source4/heimdal/lib/krb5/pkinit.c')
-rwxr-xr-x | source4/heimdal/lib/krb5/pkinit.c | 115 |
1 files changed, 94 insertions, 21 deletions
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 35a751c291..69f72d7b88 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.58 2005/07/23 10:42:01 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.59 2005/08/12 08:53:00 lha Exp $"); #ifdef PKINIT @@ -58,7 +58,7 @@ RCSID("$Id: pkinit.c,v 1.58 2005/07/23 10:42:01 lha Exp $"); enum { COMPAT_WIN2K = 1, COMPAT_19 = 2, - COMPAT_25 = 3 + COMPAT_27 = 3 }; @@ -716,7 +716,7 @@ pk_mk_padata(krb5_context context, krb5_abortx(context, "internal ASN1 encoder error"); oid = oid_id_pkauthdata(); - } else if (compat == COMPAT_25) { + } else if (compat == COMPAT_27) { AuthPack ap; memset(&ap, 0, sizeof(ap)); @@ -802,7 +802,7 @@ pk_mk_padata(krb5_context context, free_PA_PK_AS_REQ_19(&req_19); - } else if (compat == COMPAT_25) { + } else if (compat == COMPAT_27) { pa_type = KRB5_PADATA_PK_AS_REQ; @@ -871,7 +871,7 @@ _krb5_pk_mk_padata(krb5_context context, if (ret) goto out; - ret = pk_mk_padata(context, COMPAT_25, ctx, req_body, nonce, md); + ret = pk_mk_padata(context, COMPAT_27, ctx, req_body, nonce, md); if (ret) goto out; } @@ -1280,10 +1280,10 @@ _krb5_pk_verify_sign(krb5_context context, } static krb5_error_code -get_reply_key(krb5_context context, - const krb5_data *content, - unsigned nonce, - krb5_keyblock **key) +get_reply_key_19(krb5_context context, + const krb5_data *content, + unsigned nonce, + krb5_keyblock **key) { ReplyKeyPack_19 key_pack; krb5_error_code ret; @@ -1324,6 +1324,69 @@ get_reply_key(krb5_context context, } static krb5_error_code +get_reply_key(krb5_context context, + const krb5_data *content, + const krb5_data *req_buffer, + krb5_keyblock **key) +{ + ReplyKeyPack key_pack; + krb5_error_code ret; + size_t size; + + ret = decode_ReplyKeyPack(content->data, + content->length, + &key_pack, + &size); + if (ret) { + krb5_set_error_string(context, "PKINIT decoding reply key failed"); + free_ReplyKeyPack(&key_pack); + return ret; + } + + { + krb5_crypto crypto; + + /* + * XXX Verify kp.replyKey is a allowed enctype in the + * configuration file + */ + + ret = krb5_crypto_init(context, &key_pack.replyKey, 0, &crypto); + if (ret) { + free_ReplyKeyPack(&key_pack); + return ret; + } + + ret = krb5_verify_checksum(context, crypto, 6, + req_buffer->data, req_buffer->length, + &key_pack.asChecksum); + krb5_crypto_destroy(context, crypto); + if (ret) { + free_ReplyKeyPack(&key_pack); + return ret; + } + } + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "PKINIT failed allocating reply key"); + free_ReplyKeyPack(&key_pack); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = copy_EncryptionKey(&key_pack.replyKey, *key); + free_ReplyKeyPack(&key_pack); + if (ret) { + krb5_set_error_string(context, "PKINIT failed copying reply key"); + free(*key); + } + + return ret; +} + + +static krb5_error_code pk_verify_host(krb5_context context, struct krb5_pk_cert *host) { /* XXX */ @@ -1332,11 +1395,12 @@ pk_verify_host(krb5_context context, struct krb5_pk_cert *host) static krb5_error_code pk_rd_pa_reply_enckey(krb5_context context, - int win2k_compat, + int type, ContentInfo *rep, krb5_pk_init_ctx ctx, krb5_enctype etype, unsigned nonce, + const krb5_data *req_buffer, PA_DATA *pa, krb5_keyblock **key) { @@ -1418,7 +1482,7 @@ pk_rd_pa_reply_enckey(krb5_context context, /* verify content type */ - if (win2k_compat) { + if (type == COMPAT_WIN2K) { if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_data())) { ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; @@ -1481,7 +1545,7 @@ pk_rd_pa_reply_enckey(krb5_context context, length = plain.length; /* win2k uses ContentInfo */ - if (win2k_compat) { + if (type == COMPAT_WIN2K) { ContentInfo ci; ret = decode_ContentInfo(p, length, &ci, &size); @@ -1518,7 +1582,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; } - if (win2k_compat) { + if (type == COMPAT_WIN2K) { if (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; @@ -1532,7 +1596,15 @@ pk_rd_pa_reply_enckey(krb5_context context, } } - ret = get_reply_key(context, &content, nonce, key); + switch(type) { + case COMPAT_WIN2K: + case COMPAT_19: + ret = get_reply_key_19(context, &content, nonce, key); + break; + case COMPAT_27: + ret = get_reply_key(context, &content, req_buffer, key); + break; + } if (ret) goto out; @@ -1728,6 +1800,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, void *c, krb5_enctype etype, unsigned nonce, + const krb5_data *req_buffer, PA_DATA *pa, krb5_keyblock **key) { @@ -1736,7 +1809,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, ContentInfo ci; size_t size; - /* Check for PK-INIT -25 */ + /* Check for PK-INIT -27 */ if (pa->padata_type == KRB5_PADATA_PK_AS_REP) { PA_PK_AS_REP rep; @@ -1781,8 +1854,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, "ContentInfo: %d", ret); break; } - ret = pk_rd_pa_reply_enckey(context, 0, &ci, ctx, - etype, nonce, pa, key); + ret = pk_rd_pa_reply_enckey(context, COMPAT_27, &ci, ctx, + etype, nonce, req_buffer, pa, key); free_ContentInfo(&ci); return ret; default: @@ -1811,9 +1884,9 @@ _krb5_pk_rd_pa_reply(krb5_context context, nonce, pa, key); break; case choice_PA_PK_AS_REP_19_encKeyPack: - ret = pk_rd_pa_reply_enckey(context, 0, + ret = pk_rd_pa_reply_enckey(context, COMPAT_19, &rep19.u.encKeyPack, ctx, - etype, nonce, pa, key); + etype, nonce, NULL, pa, key); break; default: krb5_set_error_string(context, "PKINIT: -19 reply invalid " @@ -1857,8 +1930,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, ret); return ret; } - ret = pk_rd_pa_reply_enckey(context, 1, &ci, ctx, - etype, nonce, pa, key); + ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, ctx, + etype, nonce, NULL, pa, key); free_ContentInfo(&ci); break; default: |