From: Dmitry Timoshkov dmitry@baikal.ru
This fix is needed for sasl_decode() because it receives continuous buffer and has to build separate data and token buffers from it, otherwise it passes wrong buffer sizes to DecryptMessage() when token size is different from KERBEROS_SECURITY_TRAILER. sasl_encode() doesn't have this problem because EncryptMessage() sets token size to the value returned by kerberos/gss_wrap(). Samba server that I'm connecting to returns trailer for encrypted data 60 bytes long, while KERBEROS_SECURITY_TRAILER is equal to 64.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/kerberos/unixlib.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/dlls/kerberos/unixlib.c b/dlls/kerberos/unixlib.c index 93acecc1567..28b3dc1e4c2 100644 --- a/dlls/kerberos/unixlib.c +++ b/dlls/kerberos/unixlib.c @@ -414,6 +414,7 @@ MAKE_FUNCPTR( gss_unwrap_iov ); MAKE_FUNCPTR( gss_verify_mic ); MAKE_FUNCPTR( gss_wrap ); MAKE_FUNCPTR( gss_wrap_iov ); +MAKE_FUNCPTR( gss_wrap_iov_length ); #undef MAKE_FUNCPTR
static BOOL load_gssapi_krb5(void) @@ -450,6 +451,7 @@ static BOOL load_gssapi_krb5(void) LOAD_FUNCPTR( gss_verify_mic ) LOAD_FUNCPTR( gss_wrap ) LOAD_FUNCPTR( gss_wrap_iov ) + LOAD_FUNCPTR( gss_wrap_iov_length ) #undef LOAD_FUNCPTR return TRUE;
@@ -840,6 +842,36 @@ static NTSTATUS get_session_key( gss_ctx_id_t ctx, SecPkgContext_SessionKey *key return STATUS_SUCCESS; }
+static ULONG gss_trailer_length( gss_ctx_id_t ctx ) +{ + OM_uint32 ret, minor_status, flags; + gss_iov_buffer_desc iov[4]; + + ret = pgss_inquire_context( &minor_status, ctx, NULL, NULL, NULL, NULL, &flags, NULL, NULL ); + if (ret != GSS_S_COMPLETE) return 0; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[0].buffer.length = 0; + iov[0].buffer.value = NULL; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.length = 0; + iov[1].buffer.value = NULL; + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[2].buffer.length = 0; + iov[2].buffer.value = NULL; + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER; + iov[3].buffer.length = 0; + iov[3].buffer.value = NULL; + + ret = pgss_wrap_iov_length( &minor_status, ctx, (flags & GSS_C_CONF_FLAG) ? 1 : 0, GSS_C_QOP_DEFAULT, NULL, iov, ARRAY_SIZE(iov) ); + TRACE( "gss_wrap_iov_length returned %#x minor status %#x\n", ret, minor_status ); + if (GSS_ERROR( ret )) trace_gss_status( ret, minor_status ); + if (ret == GSS_S_COMPLETE) + return iov[0].buffer.length + iov[3].buffer.length; + + return 0; +} + static NTSTATUS query_context_attributes( void *args ) { struct query_context_attributes_params *params = args; @@ -858,15 +890,19 @@ static NTSTATUS query_context_attributes( void *args ) ULONG size_max_signature, size_security_trailer; gss_ctx_id_t ctx = ctxhandle_sspi_to_gss( params->context );
+ size_security_trailer = gss_trailer_length( ctx ); + if (is_dce_style_context( ctx )) { size_max_signature = KERBEROS_MAX_SIGNATURE_DCE; - size_security_trailer = KERBEROS_SECURITY_TRAILER_DCE; + if (!size_security_trailer) + size_security_trailer = KERBEROS_SECURITY_TRAILER_DCE; } else { size_max_signature = KERBEROS_MAX_SIGNATURE; - size_security_trailer = KERBEROS_SECURITY_TRAILER; + if (!size_security_trailer) + size_security_trailer = KERBEROS_SECURITY_TRAILER; } sizes->cbMaxToken = KERBEROS_MAX_BUF; sizes->cbMaxSignature = size_max_signature;
https://gitlab.winehq.org/wine/wine/-/merge_requests/8116 is an alternative approach to this MR.
This merge request was closed by Dmitry Timoshkov.