diff options
| author | Greg Hudson <ghudson@mit.edu> | 2013-09-07 21:13:48 -0400 |
|---|---|---|
| committer | Greg Hudson <ghudson@mit.edu> | 2013-09-18 18:22:16 -0400 |
| commit | d750ef3130b76dd079e863ed395eb3620a37386b (patch) | |
| tree | af9702fd08a842a14cf1caf0ac8609fda7021057 /src/lib/gssapi/krb5 | |
| parent | 6d53a8bf53c7380598698c3df98c96ab26db63b0 (diff) | |
| download | krb5-d750ef3130b76dd079e863ed395eb3620a37386b.tar.gz krb5-d750ef3130b76dd079e863ed395eb3620a37386b.tar.xz krb5-d750ef3130b76dd079e863ed395eb3620a37386b.zip | |
Add GSSAPI IOV MIC functions
Add gss_get_mic_iov, gss_get_mic_iov_length, and gss_verify_mic_iov
functions, which work similarly to the corresponding IOV wrap
functions. Add a new buffer type GSS_IOV_BUFFER_TYPE_MIC_TOKEN for
the destination buffer.
Most of the internal code for this was already present, and just
needed to be fixed up and adjusted to use the new buffer type for the
MIC token.
ticket: 7705 (new)
Diffstat (limited to 'src/lib/gssapi/krb5')
| -rw-r--r-- | src/lib/gssapi/krb5/gssapiP_krb5.h | 34 | ||||
| -rw-r--r-- | src/lib/gssapi/krb5/gssapi_krb5.c | 6 | ||||
| -rw-r--r-- | src/lib/gssapi/krb5/k5sealiov.c | 49 | ||||
| -rw-r--r-- | src/lib/gssapi/krb5/k5sealv3iov.c | 15 | ||||
| -rw-r--r-- | src/lib/gssapi/krb5/k5unsealiov.c | 15 | ||||
| -rw-r--r-- | src/lib/gssapi/krb5/util_cksum.c | 19 | ||||
| -rw-r--r-- | src/lib/gssapi/krb5/util_crypt.c | 11 |
7 files changed, 99 insertions, 50 deletions
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index 310ff5819..01678168f 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -403,6 +403,9 @@ gss_iov_buffer_t kg_locate_iov (gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type); +gss_iov_buffer_t kg_locate_header_iov(gss_iov_buffer_desc *iov, int iov_count, + int toktype); + void kg_iov_msglen(gss_iov_buffer_desc *iov, int iov_count, size_t *data_length, @@ -428,7 +431,8 @@ krb5_error_code kg_make_checksum_iov_v3(krb5_context context, krb5_key key, krb5_keyusage sign_usage, gss_iov_buffer_desc *iov, - int iov_count); + int iov_count, + int toktype); krb5_error_code kg_verify_checksum_iov_v3(krb5_context context, krb5_cksumtype type, @@ -437,6 +441,7 @@ krb5_error_code kg_verify_checksum_iov_v3(krb5_context context, krb5_keyusage sign_usage, gss_iov_buffer_desc *iov, int iov_count, + int toktype, krb5_boolean *valid); OM_uint32 kg_seal_iov (OM_uint32 *minor_status, @@ -462,7 +467,8 @@ OM_uint32 kg_seal_iov_length(OM_uint32 *minor_status, gss_qop_t qop_req, int *conf_state, gss_iov_buffer_desc *iov, - int iov_count); + int iov_count, + int toktype); krb5_cryptotype kg_translate_flag_iov(OM_uint32 type); @@ -700,6 +706,22 @@ OM_uint32 KRB5_CALLCONV krb5_gss_get_mic gss_buffer_t /* message_token */ ); +OM_uint32 KRB5_CALLCONV krb5_gss_get_mic_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_get_mic_iov_length +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + OM_uint32 KRB5_CALLCONV krb5_gss_verify_mic (OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ @@ -708,6 +730,14 @@ OM_uint32 KRB5_CALLCONV krb5_gss_verify_mic gss_qop_t * /* qop_state */ ); +OM_uint32 KRB5_CALLCONV krb5_gss_verify_mic_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + OM_uint32 KRB5_CALLCONV krb5_gss_wrap (OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index a1bb92dc0..a408259cf 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -896,6 +896,12 @@ static struct gss_config krb5_mechanism = { krb5_gss_acquire_cred_with_password, krb5_gss_export_cred, krb5_gss_import_cred, + NULL, /* import_sec_context_by_mech */ + NULL, /* import_name_by_mech */ + NULL, /* import_cred_by_mech */ + krb5_gss_get_mic_iov, + krb5_gss_verify_mic_iov, + krb5_gss_get_mic_iov_length, }; #ifdef _GSS_STATIC_LINK diff --git a/src/lib/gssapi/krb5/k5sealiov.c b/src/lib/gssapi/krb5/k5sealiov.c index 3dafd1f5f..0b99a77e9 100644 --- a/src/lib/gssapi/krb5/k5sealiov.c +++ b/src/lib/gssapi/krb5/k5sealiov.c @@ -51,17 +51,16 @@ make_seal_token_v1_iov(krb5_context context, unsigned char *ptr; krb5_keyusage sign_usage = KG_USAGE_SIGN; - assert(toktype == KG_TOK_WRAP_MSG); - md5cksum.length = cksum.length = 0; md5cksum.contents = cksum.contents = NULL; - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); if (header == NULL) return EINVAL; padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); - if (padding == NULL && (ctx->gss_flags & GSS_C_DCE_STYLE) == 0) + if (padding == NULL && toktype == KG_TOK_WRAP_MSG && + (ctx->gss_flags & GSS_C_DCE_STYLE) == 0) return EINVAL; trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); @@ -171,7 +170,7 @@ make_seal_token_v1_iov(krb5_context context, goto cleanup; md5cksum.length = k5_trailerlen; - if (k5_headerlen != 0) { + if (k5_headerlen != 0 && toktype == KG_TOK_WRAP_MSG) { code = kg_make_confounder(context, ctx->enc->keyblock.enctype, ptr + 14 + ctx->cksum_size); if (code != 0) @@ -332,7 +331,8 @@ kg_seal_iov_length(OM_uint32 *minor_status, gss_qop_t qop_req, int *conf_state, gss_iov_buffer_desc *iov, - int iov_count) + int iov_count, + int toktype) { krb5_gss_ctx_id_rec *ctx; gss_iov_buffer_t header, trailer, padding; @@ -341,7 +341,7 @@ kg_seal_iov_length(OM_uint32 *minor_status, unsigned int k5_headerlen = 0, k5_trailerlen = 0, k5_padlen = 0; krb5_error_code code; krb5_context context; - int dce_style; + int dce_or_mic; if (qop_req != GSS_C_QOP_DEFAULT) { *minor_status = (OM_uint32)G_UNKNOWN_QOP; @@ -354,7 +354,7 @@ kg_seal_iov_length(OM_uint32 *minor_status, return GSS_S_NO_CONTEXT; } - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); if (header == NULL) { *minor_status = EINVAL; return GSS_S_FAILURE; @@ -366,12 +366,15 @@ kg_seal_iov_length(OM_uint32 *minor_status, INIT_IOV_DATA(trailer); } - dce_style = ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0); + /* MIC tokens and DCE-style wrap tokens have similar length considerations: + * no padding, and the framing surrounds the header only, not the data. */ + dce_or_mic = ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0 || + toktype == KG_TOK_MIC_MSG); /* For CFX, EC is used instead of padding, and is placed in header or trailer */ padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); if (padding == NULL) { - if (conf_req_flag && ctx->proto == 0 && !dce_style) { + if (conf_req_flag && ctx->proto == 0 && !dce_or_mic) { *minor_status = EINVAL; return GSS_S_FAILURE; } @@ -425,7 +428,7 @@ kg_seal_iov_length(OM_uint32 *minor_status, return GSS_S_FAILURE; } - if (k5_padlen == 0 && dce_style) { + if (k5_padlen == 0 && dce_or_mic) { /* Windows rejects AEAD tokens with non-zero EC */ code = krb5_c_block_size(context, enctype, &ec); if (code != 0) { @@ -439,7 +442,7 @@ kg_seal_iov_length(OM_uint32 *minor_status, } else { gss_trailerlen = k5_trailerlen; /* Kerb-Checksum */ } - } else if (!dce_style) { + } else if (!dce_or_mic) { k5_padlen = (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) ? 1 : 8; if (k5_padlen == 1) @@ -458,14 +461,14 @@ kg_seal_iov_length(OM_uint32 *minor_status, data_size = 14 /* Header */ + ctx->cksum_size + k5_headerlen; - if (!dce_style) + if (!dce_or_mic) data_size += data_length; gss_headerlen = g_token_size(ctx->mech_used, data_size); /* g_token_size() will include data_size as well as the overhead, so * subtract data_length just to get the overhead (ie. token size) */ - if (!dce_style) + if (!dce_or_mic) gss_headerlen -= data_length; } @@ -519,13 +522,13 @@ krb5_gss_wrap_iov_length(OM_uint32 *minor_status, { OM_uint32 major_status; - major_status = kg_seal_iov_length(minor_status, context_handle, conf_req_flag, - qop_req, conf_state, iov, iov_count); + major_status = kg_seal_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, conf_state, iov, + iov_count, KG_TOK_WRAP_MSG); return major_status; } -#if 0 -OM_uint32 +OM_uint32 KRB5_CALLCONV krb5_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, gss_qop_t qop_req, @@ -541,19 +544,17 @@ krb5_gss_get_mic_iov(OM_uint32 *minor_status, return major_status; } -OM_uint32 +OM_uint32 KRB5_CALLCONV krb5_gss_get_mic_iov_length(OM_uint32 *minor_status, gss_ctx_id_t context_handle, - int conf_req_flag, gss_qop_t qop_req, - int *conf_state, gss_iov_buffer_desc *iov, int iov_count) { OM_uint32 major_status; - major_status = kg_seal_iov_length(minor_status, context_handle, conf_req_flag, - qop_req, conf_state, iov, iov_count); + major_status = kg_seal_iov_length(minor_status, context_handle, FALSE, + qop_req, NULL, iov, iov_count, + KG_TOK_MIC_MSG); return major_status; } -#endif diff --git a/src/lib/gssapi/krb5/k5sealv3iov.c b/src/lib/gssapi/krb5/k5sealv3iov.c index d7c92875e..8f6c4d441 100644 --- a/src/lib/gssapi/krb5/k5sealv3iov.c +++ b/src/lib/gssapi/krb5/k5sealv3iov.c @@ -76,7 +76,7 @@ gss_krb5int_make_seal_token_v3_iov(krb5_context context, kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); if (header == NULL) return EINVAL; @@ -240,7 +240,7 @@ gss_krb5int_make_seal_token_v3_iov(krb5_context context, code = kg_make_checksum_iov_v3(context, cksumtype, rrc, key, key_usage, - iov, iov_count); + iov, iov_count, toktype); if (code != 0) goto cleanup; @@ -302,7 +302,7 @@ gss_krb5int_unseal_v3_iov(krb5_context context, if (qop_state != NULL) *qop_state = GSS_C_QOP_DEFAULT; - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); assert(header != NULL); padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); @@ -421,7 +421,7 @@ gss_krb5int_unseal_v3_iov(krb5_context context, code = kg_verify_checksum_iov_v3(context, cksumtype, rrc, key, key_usage, - iov, iov_count, &valid); + iov, iov_count, toktype, &valid); if (code != 0 || valid == FALSE) { *minor_status = code; return GSS_S_BAD_SIG; @@ -438,9 +438,12 @@ gss_krb5int_unseal_v3_iov(krb5_context context, goto defective; seqnum = load_64_be(ptr + 8); - code = kg_verify_checksum_iov_v3(context, cksumtype, 0, + /* For MIC tokens, the GSS header and checksum are in the same buffer. + * Fake up an RRC so that the checksum is expected in the header. */ + rrc = (trailer != NULL) ? 0 : header->buffer.length - 16; + code = kg_verify_checksum_iov_v3(context, cksumtype, rrc, key, key_usage, - iov, iov_count, &valid); + iov, iov_count, toktype, &valid); if (code != 0 || valid == FALSE) { *minor_status = code; return GSS_S_BAD_SIG; diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c index f80f4d05d..24853abec 100644 --- a/src/lib/gssapi/krb5/k5unsealiov.c +++ b/src/lib/gssapi/krb5/k5unsealiov.c @@ -57,12 +57,10 @@ kg_unseal_v1_iov(krb5_context context, size_t sumlen; krb5_keyusage sign_usage = KG_USAGE_SIGN; - assert(toktype == KG_TOK_WRAP_MSG); - md5cksum.length = cksum.length = 0; md5cksum.contents = cksum.contents = NULL; - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); assert(header != NULL); trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); @@ -316,7 +314,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status, unsigned int bodysize; int toktype2; - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); if (header == NULL) { *minor_status = EINVAL; return GSS_S_FAILURE; @@ -328,7 +326,8 @@ kg_unseal_iov_token(OM_uint32 *minor_status, ptr = (unsigned char *)header->buffer.value; input_length = header->buffer.length; - if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0) { + if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0 && + toktype == KG_TOK_WRAP_MSG) { size_t data_length, assoc_data_length; kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); @@ -655,8 +654,7 @@ krb5_gss_unwrap_iov(OM_uint32 *minor_status, return major_status; } -#if 0 -OM_uint32 +OM_uint32 KRB5_CALLCONV krb5_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, gss_qop_t *qop_state, @@ -667,8 +665,7 @@ krb5_gss_verify_mic_iov(OM_uint32 *minor_status, major_status = kg_unseal_iov(minor_status, context_handle, NULL, qop_state, - iov, iov_count, KG_TOK_WRAP_MSG); + iov, iov_count, KG_TOK_MIC_MSG); return major_status; } -#endif diff --git a/src/lib/gssapi/krb5/util_cksum.c b/src/lib/gssapi/krb5/util_cksum.c index 4877c71eb..cfd585ec7 100644 --- a/src/lib/gssapi/krb5/util_cksum.c +++ b/src/lib/gssapi/krb5/util_cksum.c @@ -122,15 +122,13 @@ kg_make_checksum_iov_v1(krb5_context context, krb5_error_code code; gss_iov_buffer_desc *header; krb5_crypto_iov *kiov; - size_t kiov_count; int i = 0, j; size_t conf_len = 0, token_header_len; - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); assert(header != NULL); - kiov_count = 3 + iov_count; - kiov = (krb5_crypto_iov *)xmalloc(kiov_count * sizeof(krb5_crypto_iov)); + kiov = calloc(iov_count + 3, sizeof(krb5_crypto_iov)); if (kiov == NULL) return ENOMEM; @@ -172,7 +170,7 @@ kg_make_checksum_iov_v1(krb5_context context, i++; } - code = krb5_k_make_checksum_iov(context, type, seq, sign_usage, kiov, kiov_count); + code = krb5_k_make_checksum_iov(context, type, seq, sign_usage, kiov, i); if (code == 0) { checksum->length = kiov[0].data.length; checksum->contents = (unsigned char *)kiov[0].data.data; @@ -192,6 +190,7 @@ checksum_iov_v3(krb5_context context, krb5_keyusage sign_usage, gss_iov_buffer_desc *iov, int iov_count, + int toktype, krb5_boolean verify, krb5_boolean *valid) { @@ -210,7 +209,7 @@ checksum_iov_v3(krb5_context context, if (code != 0) return code; - header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + header = kg_locate_header_iov(iov, iov_count, toktype); assert(header != NULL); trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); @@ -273,10 +272,11 @@ kg_make_checksum_iov_v3(krb5_context context, krb5_key key, krb5_keyusage sign_usage, gss_iov_buffer_desc *iov, - int iov_count) + int iov_count, + int toktype) { return checksum_iov_v3(context, type, rrc, key, - sign_usage, iov, iov_count, 0, NULL); + sign_usage, iov, iov_count, toktype, 0, NULL); } krb5_error_code @@ -287,8 +287,9 @@ kg_verify_checksum_iov_v3(krb5_context context, krb5_keyusage sign_usage, gss_iov_buffer_desc *iov, int iov_count, + int toktype, krb5_boolean *valid) { return checksum_iov_v3(context, type, rrc, key, - sign_usage, iov, iov_count, 1, valid); + sign_usage, iov, iov_count, toktype, 1, valid); } diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c index b7b4a0a60..055093cd7 100644 --- a/src/lib/gssapi/krb5/util_crypt.c +++ b/src/lib/gssapi/krb5/util_crypt.c @@ -626,6 +626,17 @@ kg_locate_iov(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type) return p; } +/* Return the IOV where the GSSAPI token header should be placed (and possibly + * the checksum as well, depending on the token type). */ +gss_iov_buffer_t +kg_locate_header_iov(gss_iov_buffer_desc *iov, int iov_count, int toktype) +{ + if (toktype == KG_TOK_MIC_MSG) + return kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_MIC_TOKEN); + else + return kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); +} + void kg_iov_msglen(gss_iov_buffer_desc *iov, int iov_count, size_t *data_length_p, size_t *assoc_data_length_p) |
