summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2013-09-07 21:13:48 -0400
committerGreg Hudson <ghudson@mit.edu>2013-09-18 18:22:16 -0400
commitd750ef3130b76dd079e863ed395eb3620a37386b (patch)
treeaf9702fd08a842a14cf1caf0ac8609fda7021057 /src/lib
parent6d53a8bf53c7380598698c3df98c96ab26db63b0 (diff)
downloadkrb5-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')
-rw-r--r--src/lib/gssapi/generic/gssapi_ext.h41
-rw-r--r--src/lib/gssapi/krb5/gssapiP_krb5.h34
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c6
-rw-r--r--src/lib/gssapi/krb5/k5sealiov.c49
-rw-r--r--src/lib/gssapi/krb5/k5sealv3iov.c15
-rw-r--r--src/lib/gssapi/krb5/k5unsealiov.c15
-rw-r--r--src/lib/gssapi/krb5/util_cksum.c19
-rw-r--r--src/lib/gssapi/krb5/util_crypt.c11
-rw-r--r--src/lib/gssapi/libgssapi_krb5.exports3
-rw-r--r--src/lib/gssapi/mechglue/g_unwrap_iov.c25
-rw-r--r--src/lib/gssapi/mechglue/g_wrap_iov.c49
-rw-r--r--src/lib/gssapi/mechglue/mglueP.h29
-rw-r--r--src/lib/gssapi/spnego/gssapiP_spnego.h27
-rw-r--r--src/lib/gssapi/spnego/spnego_mech.c33
-rw-r--r--src/lib/gssapi32.def4
15 files changed, 310 insertions, 50 deletions
diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h
index d8c8b6ab85..9ad44216d0 100644
--- a/src/lib/gssapi/generic/gssapi_ext.h
+++ b/src/lib/gssapi/generic/gssapi_ext.h
@@ -238,6 +238,7 @@ typedef struct gss_iov_buffer_desc_struct {
#define GSS_IOV_BUFFER_TYPE_PADDING 9 /* Padding */
#define GSS_IOV_BUFFER_TYPE_STREAM 10 /* Complete wrap token */
#define GSS_IOV_BUFFER_TYPE_SIGN_ONLY 11 /* Sign only packet data */
+#define GSS_IOV_BUFFER_TYPE_MIC_TOKEN 12 /* MIC token destination */
#define GSS_IOV_BUFFER_FLAG_MASK 0xFFFF0000
#define GSS_IOV_BUFFER_FLAG_ALLOCATE 0x00010000 /* indicates GSS should allocate */
@@ -326,6 +327,46 @@ OM_uint32 KRB5_CALLCONV gss_wrap_iov_length
int); /* iov_count */
/*
+ * Produce a GSSAPI MIC token for a sequence of buffers. All SIGN_ONLY and
+ * DATA buffers will be signed, in the order they appear. One MIC_TOKEN buffer
+ * must be included for the result. Suitable space should be provided for the
+ * MIC_TOKEN buffer by calling gss_get_mic_iov_length, or the ALLOCATE flag
+ * should be set on that buffer. If the ALLOCATE flag is used, use
+ * gss_release_iov_buffer to free the allocated buffer within the iov list when
+ * it is no longer needed.
+ */
+OM_uint32 KRB5_CALLCONV 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 */
+
+/*
+ * Query the MIC_TOKEN buffer length within the iov list.
+ */
+OM_uint32 KRB5_CALLCONV 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 */
+
+/*
+ * Verify the MIC_TOKEN buffer within the iov list against the SIGN_ONLY and
+ * DATA buffers in the order they appear. Return values are the same as for
+ * gss_verify_mic.
+ */
+OM_uint32 KRB5_CALLCONV 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 */
+
+/*
* Release buffers that have the ALLOCATED flag set.
*/
OM_uint32 KRB5_CALLCONV gss_release_iov_buffer
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 310ff58195..01678168f0 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 a1bb92dc05..a408259cfb 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 3dafd1f5f9..0b99a77e95 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 d7c92875ee..8f6c4d4413 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 f80f4d05d6..24853abeca 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 4877c71ebb..cfd585ec72 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 b7b4a0a605..055093cd72 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)
diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
index 242a3c0dc8..4929c71014 100644
--- a/src/lib/gssapi/libgssapi_krb5.exports
+++ b/src/lib/gssapi/libgssapi_krb5.exports
@@ -65,6 +65,8 @@ gss_export_name
gss_export_name_composite
gss_export_sec_context
gss_get_mic
+gss_get_mic_iov
+gss_get_mic_iov_length
gss_get_name_attribute
gss_import_cred
gss_import_name
@@ -139,6 +141,7 @@ gss_unwrap_iov
gss_userok
gss_verify
gss_verify_mic
+gss_verify_mic_iov
gss_wrap
gss_wrap_aead
gss_wrap_iov
diff --git a/src/lib/gssapi/mechglue/g_unwrap_iov.c b/src/lib/gssapi/mechglue/g_unwrap_iov.c
index aad9c76958..9b95c0162c 100644
--- a/src/lib/gssapi/mechglue/g_unwrap_iov.c
+++ b/src/lib/gssapi/mechglue/g_unwrap_iov.c
@@ -111,3 +111,28 @@ int iov_count;
return (GSS_S_BAD_MECH);
}
+
+OM_uint32 KRB5_CALLCONV
+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 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ status = val_unwrap_iov_args(minor_status, context_handle, NULL,
+ qop_state, iov, iov_count);
+ if (status != GSS_S_COMPLETE)
+ return status;
+
+ /* Select the approprate underlying mechanism routine and call it. */
+ ctx = (gss_union_ctx_id_t)context_handle;
+ mech = gssint_get_mechanism(ctx->mech_type);
+ if (mech == NULL)
+ return GSS_S_BAD_MECH;
+ if (mech->gss_verify_mic_iov == NULL)
+ return GSS_S_UNAVAILABLE;
+ return mech->gss_verify_mic_iov(minor_status, ctx->internal_ctx_id,
+ qop_state, iov, iov_count);
+}
diff --git a/src/lib/gssapi/mechglue/g_wrap_iov.c b/src/lib/gssapi/mechglue/g_wrap_iov.c
index 9586c587e7..17a2537e0e 100644
--- a/src/lib/gssapi/mechglue/g_wrap_iov.c
+++ b/src/lib/gssapi/mechglue/g_wrap_iov.c
@@ -176,6 +176,55 @@ int iov_count;
}
OM_uint32 KRB5_CALLCONV
+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 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ status = val_wrap_iov_args(minor_status, context_handle, 0, qop_req, NULL,
+ iov, iov_count);
+ if (status != GSS_S_COMPLETE)
+ return status;
+
+ /* Select the approprate underlying mechanism routine and call it. */
+ ctx = (gss_union_ctx_id_t)context_handle;
+ mech = gssint_get_mechanism(ctx->mech_type);
+ if (mech == NULL)
+ return GSS_S_BAD_MECH;
+ if (mech->gss_get_mic_iov == NULL)
+ return GSS_S_UNAVAILABLE;
+ return mech->gss_get_mic_iov(minor_status, ctx->internal_ctx_id, qop_req,
+ iov, iov_count);
+}
+
+OM_uint32 KRB5_CALLCONV
+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 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ status = val_wrap_iov_args(minor_status, context_handle, 0, qop_req, NULL,
+ iov, iov_count);
+ if (status != GSS_S_COMPLETE)
+ return status;
+
+ /* Select the approprate underlying mechanism routine and call it. */
+ ctx = (gss_union_ctx_id_t)context_handle;
+ mech = gssint_get_mechanism(ctx->mech_type);
+ if (mech == NULL)
+ return GSS_S_BAD_MECH;
+ if (mech->gss_get_mic_iov_length == NULL)
+ return GSS_S_UNAVAILABLE;
+ return mech->gss_get_mic_iov_length(minor_status, ctx->internal_ctx_id,
+ qop_req, iov, iov_count);
+}
+
+OM_uint32 KRB5_CALLCONV
gss_release_iov_buffer (minor_status,
iov,
iov_count)
diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
index 9e02474a82..e56b9c1a58 100644
--- a/src/lib/gssapi/mechglue/mglueP.h
+++ b/src/lib/gssapi/mechglue/mglueP.h
@@ -674,6 +674,35 @@ typedef struct gss_config {
gss_cred_id_t * /* cred_handle */
/* */);
+ /* get_mic_iov extensions, added in 1.12 */
+
+ OM_uint32 (KRB5_CALLCONV *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 *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 *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 */
+ );
+
} *gss_mechanism;
/*
diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h
index 9d8fe52c92..bc23f56717 100644
--- a/src/lib/gssapi/spnego/gssapiP_spnego.h
+++ b/src/lib/gssapi/spnego/gssapiP_spnego.h
@@ -629,6 +629,33 @@ spnego_gss_import_cred(
gss_cred_id_t *cred_handle
);
+OM_uint32 KRB5_CALLCONV
+spnego_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
+spnego_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
+spnego_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
+);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index 33c8c88080..24c344066d 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -280,6 +280,12 @@ static struct gss_config spnego_mechanism =
spnego_gss_acquire_cred_with_password,
spnego_gss_export_cred,
spnego_gss_import_cred,
+ NULL, /* gssspi_import_sec_context_by_mech */
+ NULL, /* gssspi_import_name_by_mech */
+ NULL, /* gssspi_import_cred_by_mech */
+ spnego_gss_get_mic_iov,
+ spnego_gss_verify_mic_iov,
+ spnego_gss_get_mic_iov_length
};
#ifdef _GSS_STATIC_LINK
@@ -2837,6 +2843,33 @@ spnego_gss_import_cred(OM_uint32 *minor_status,
return (ret);
}
+OM_uint32 KRB5_CALLCONV
+spnego_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)
+{
+ return gss_get_mic_iov(minor_status, context_handle, qop_req, iov,
+ iov_count);
+}
+
+OM_uint32 KRB5_CALLCONV
+spnego_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)
+{
+ return gss_verify_mic_iov(minor_status, context_handle, qop_state, iov,
+ iov_count);
+}
+
+OM_uint32 KRB5_CALLCONV
+spnego_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)
+{
+ return gss_get_mic_iov_length(minor_status, context_handle, qop_req, iov,
+ iov_count);
+}
+
/*
* We will release everything but the ctx_handle so that it
* can be passed back to init/accept context. This routine should
diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def
index 00c707474b..9e18a66920 100644
--- a/src/lib/gssapi32.def
+++ b/src/lib/gssapi32.def
@@ -176,3 +176,7 @@ EXPORTS
gss_store_cred_into @141
gss_export_cred @142
gss_import_cred @143
+; Added in 1.12
+ gss_get_mic_iov @144
+ gss_get_mic_iov_length @145
+ gss_verify_mic_iov @146