This patch, inspired by the lukeh's heimdal-mechglue branch appears to fix up gesnec_gssapi for sign/seal, samba->samba when using AES. It also works Samba->Windows and Windows->Samba. However, I'm not sure if I've broken the original intent of this function, and it might make more sense to have a direct gss_sig_length(conext, data_len, &length) function. I'm going to have a look at that approach now. Andrew Bartlett -- Andrew Bartlett http://samba.org/~abartlet/ Samba Developer, SuSE Labs, Novell Inc. http://suse.de Authentication Developer, Samba Team http://samba.org Student Network Administrator, Hawker College http://hawkerc.net
Index: auth/gensec/gensec_gssapi.c =================================================================== --- auth/gensec/gensec_gssapi.c (revision 10115) +++ auth/gensec/gensec_gssapi.c (working copy) @@ -482,8 +482,26 @@ static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security) { - /* not const but work for DCERPC packets and arcfour */ - return 45; + struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data; + OM_uint32 maj_stat, min_stat; + OM_uint32 req_output_size = (1 << 6); + OM_uint32 max_input_size; + maj_stat = gss_wrap_size_limit(&min_stat, + gensec_gssapi_state->gssapi_context, + gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL), + GSS_C_QOP_DEFAULT, + req_output_size, + &max_input_size); + if (GSS_ERROR(maj_stat)) { + TALLOC_CTX *mem_ctx = talloc_new(NULL); + DEBUG(1, ("gensec_gssapi_seal_packet: determinaing signature size with gss_wrap_size_limit failed: %s\n", + gssapi_error_string(mem_ctx, maj_stat, min_stat))); + talloc_free(mem_ctx); + return 0; + } + + /* The difference between the max output and the max input must be the signature */ + return req_output_size - max_input_size; } static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security, @@ -496,7 +514,7 @@ OM_uint32 maj_stat, min_stat; gss_buffer_desc input_token, output_token; int conf_state; - ssize_t sig_length = 0; + ssize_t sig_length; input_token.length = length; input_token.value = data; @@ -514,12 +532,15 @@ return NT_STATUS_ACCESS_DENIED; } - if (output_token.length < length) { + sig_length = gensec_gssapi_sig_size(gensec_security); + + /* Caller must pad to right boundary */ + if (output_token.length != (length + sig_length)) { + DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%d] does not match caller length [%d] plus sig size [%d] = [%d]\n", + output_token.length, length, sig_length, length + sig_length)); return NT_STATUS_INTERNAL_ERROR; } - sig_length = 45; - memcpy(data, ((uint8_t *)output_token.value) + sig_length, length); *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length); Index: heimdal/lib/gssapi/wrap.c =================================================================== --- heimdal/lib/gssapi/wrap.c (revision 10115) +++ heimdal/lib/gssapi/wrap.c (working copy) @@ -167,13 +167,17 @@ switch (keytype) { case KEYTYPE_DES : - case KEYTYPE_ARCFOUR: - case KEYTYPE_ARCFOUR_56: ret = sub_wrap_size(req_output_size, max_input_size, 8, 22); break; case KEYTYPE_DES3 : ret = sub_wrap_size(req_output_size, max_input_size, 8, 34); break; + case KEYTYPE_ARCFOUR: + case KEYTYPE_ARCFOUR_56: + ret = _gssapi_wrap_size_arcfour(minor_status, context_handle, + conf_req_flag, qop_req, + req_output_size, max_input_size, key); + break; default : ret = _gssapi_wrap_size_cfx(minor_status, context_handle, conf_req_flag, qop_req, Index: heimdal/lib/gssapi/cfx.c =================================================================== --- heimdal/lib/gssapi/cfx.c (revision 10115) +++ heimdal/lib/gssapi/cfx.c (working copy) @@ -127,6 +127,7 @@ return GSS_S_FAILURE; } + output_length -= req_output_size; /* token length */ if (output_length < req_output_size) { *max_input_size = (req_output_size - output_length); *max_input_size -= padlength; Index: heimdal/lib/gssapi/arcfour.c =================================================================== --- heimdal/lib/gssapi/arcfour.c (revision 10115) +++ heimdal/lib/gssapi/arcfour.c (working copy) @@ -326,6 +326,35 @@ } OM_uint32 +_gssapi_wrap_size_arcfour(OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size, + krb5_keyblock *key) +{ + size_t len, total_len; + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + req_output_size; + /* if GSS_C_DCE_STYLE is in use: + * - we only need to encapsulate the WRAP token + * - we should not add padding + */ + if (!(context_handle->flags & GSS_C_DCE_STYLE)) { + len += 1 /* padding */; + } + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + total_len -= req_output_size; /* token length */ + if (total_len < req_output_size) { + *max_input_size = (req_output_size - total_len); + } else { + *max_input_size = 0; + } + return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_wrap_arcfour(OM_uint32 * minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, Index: heimdal/lib/gssapi/arcfour.h =================================================================== --- heimdal/lib/gssapi/arcfour.h (revision 10115) +++ heimdal/lib/gssapi/arcfour.h (working copy) @@ -70,5 +70,12 @@ gss_qop_t *qop_state, krb5_keyblock *key, char *type); +OM_uint32 _gssapi_wrap_size_arcfour(OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size, + krb5_keyblock *key); #endif /* GSSAPI_ARCFOUR_H_ */
This is a digitally signed message part