[PATCH 0/6] MR11718: secur32: Further separation between lsa/user mode data.
From: Piotr Caban <piotr@codeweavers.com> --- dlls/msv1_0/main.c | 19 ++++++++++++++++++- dlls/secur32/lsa.c | 7 ++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/dlls/msv1_0/main.c b/dlls/msv1_0/main.c index 73dfcdac92a..97c35b52d05 100644 --- a/dlls/msv1_0/main.c +++ b/dlls/msv1_0/main.c @@ -1299,6 +1299,8 @@ static NTSTATUS NTAPI ntlm_SpInitLsaModeContext( LSA_SEC_HANDLE cred_handle, LSA goto done; } + status = lsa_secpkg_table->MapBuffer( input->pBuffers + idx, input->pBuffers + idx ); + if (status) goto done; challenge = input->pBuffers[idx].pvBuffer; ctx->req_attrs |= ctx_req; *ctx_attr = 0; @@ -1384,7 +1386,7 @@ static NTSTATUS NTAPI ntlm_SpInitLsaModeContext( LSA_SEC_HANDLE cred_handle, LSA if (ctx_req & ISC_REQ_ALLOCATE_MEMORY) { /* freed with secur32.FreeContextBuffer */ - if (!(output->pBuffers[idx].pvBuffer = RtlAllocateHeap( GetProcessHeap(), 0, bin_len ))) + if (!(output->pBuffers[idx].pvBuffer = lsa_secpkg_table->AllocateLsaHeap( bin_len ))) { status = SEC_E_INSUFFICIENT_MEMORY; goto done; @@ -1397,6 +1399,15 @@ static NTSTATUS NTAPI ntlm_SpInitLsaModeContext( LSA_SEC_HANDLE cred_handle, LSA status = SEC_E_BUFFER_TOO_SMALL; goto done; } + else + { + NTSTATUS ret = lsa_secpkg_table->MapBuffer( output->pBuffers + idx, output->pBuffers + idx ); + if (ret) + { + status = ret; + goto done; + } + } if (!output->pBuffers[idx].pvBuffer) { @@ -1482,6 +1493,8 @@ static NTSTATUS NTAPI ntlm_SpAcceptLsaModeContext( LSA_SEC_HANDLE cred_handle, L status = SEC_E_INVALID_TOKEN; goto done; } + status = lsa_secpkg_table->MapBuffer( input->pBuffers, input->pBuffers ); + if (status) goto done; negotiate = input->pBuffers[0].pvBuffer; if (!(ctx = calloc( 1, sizeof(*ctx) ))) goto done; @@ -1566,6 +1579,8 @@ static NTSTATUS NTAPI ntlm_SpAcceptLsaModeContext( LSA_SEC_HANDLE cred_handle, L } output->pBuffers[0].cbBuffer = bin_len; output->pBuffers[0].BufferType = SECBUFFER_TOKEN; + status = lsa_secpkg_table->MapBuffer( output->pBuffers, output->pBuffers ); + if (status) goto done; memcpy( output->pBuffers[0].pvBuffer, bin, bin_len ); *new_ctx_handle = (LSA_SEC_HANDLE)ctx; @@ -1595,6 +1610,8 @@ static NTSTATUS NTAPI ntlm_SpAcceptLsaModeContext( LSA_SEC_HANDLE cred_handle, L goto done; } else bin_len = input->pBuffers[0].cbBuffer; + status = lsa_secpkg_table->MapBuffer( input->pBuffers, input->pBuffers ); + if (status) goto done; memcpy( bin, input->pBuffers[0].pvBuffer, bin_len ); authenticate = input->pBuffers[0].pvBuffer; diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index f81cd3522b3..de04ab9316d 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -910,6 +910,11 @@ static const SecurityFunctionTableA lsa_sspi_tableA = NULL, /* SetContextAttributesA */ }; +static NTSTATUS NTAPI lsa_MapBuffer( SecBuffer *in, SecBuffer *out ) +{ + return SEC_E_OK; +} + static BOOLEAN NTAPI lsa_GetCallInfo( SECPKG_CALL_INFO *info ) { memset( info, 0, sizeof(*info) ); @@ -940,7 +945,7 @@ static const LSA_SECPKG_FUNCTION_TABLE lsa_secpkg_table = NULL, /* GetClientInfo */ NULL, /* RegisterNotification */ NULL, /* CancelNotification */ - NULL, /* MapBuffer */ + lsa_MapBuffer, NULL, /* CreateToken */ NULL, /* AuditLogon */ NULL, /* CallPackage */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11718
From: Piotr Caban <piotr@codeweavers.com> --- dlls/kerberos/krb5_ap.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c index 2d239d8263c..e628267d1db 100644 --- a/dlls/kerberos/krb5_ap.c +++ b/dlls/kerberos/krb5_ap.c @@ -626,6 +626,12 @@ static NTSTATUS NTAPI kerberos_SpInitLsaModeContext( LSA_SEC_HANDLE credential, idx = get_buffer_index( input, SECBUFFER_TOKEN ); if (idx != -1) { + status = lsa_funcs->MapBuffer( input->pBuffers + idx, input->pBuffers + idx ); + if (status) + { + free( target ); + return status; + } params.input_token = input->pBuffers[idx].pvBuffer; params.input_token_length = input->pBuffers[idx].cbBuffer; } @@ -645,6 +651,15 @@ static NTSTATUS NTAPI kerberos_SpInitLsaModeContext( LSA_SEC_HANDLE credential, } output->pBuffers[idx].cbBuffer = KERBEROS_MAX_BUF; } + else + { + status = lsa_funcs->MapBuffer( output->pBuffers + idx, output->pBuffers + idx ); + if (status) + { + free( target ); + return status; + } + } params.output_token = output->pBuffers[idx].pvBuffer; params.output_token_length = &output->pBuffers[idx].cbBuffer; @@ -700,10 +715,14 @@ static NTSTATUS NTAPI kerberos_SpAcceptLsaModeContext( LSA_SEC_HANDLE credential if (input) { if ((idx = get_buffer_index( input, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN; + status = lsa_funcs->MapBuffer( input->pBuffers + idx, input->pBuffers + idx ); + if (status) return status; params.input_token = input->pBuffers[idx].pvBuffer; params.input_token_length = input->pBuffers[idx].cbBuffer; } if ((idx = get_buffer_index( output, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN; + status = lsa_funcs->MapBuffer( output->pBuffers + idx, output->pBuffers + idx ); + if (status) return status; params.output_token = output->pBuffers[idx].pvBuffer; params.output_token_length = &output->pBuffers[idx].cbBuffer; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11718
From: Piotr Caban <piotr@codeweavers.com> --- dlls/kerberos/krb5_ap.c | 4 +-- dlls/secur32/lsa.c | 63 +++++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c index e628267d1db..074a99eddfb 100644 --- a/dlls/kerberos/krb5_ap.c +++ b/dlls/kerberos/krb5_ap.c @@ -672,7 +672,7 @@ static NTSTATUS NTAPI kerberos_SpInitLsaModeContext( LSA_SEC_HANDLE credential, if (status == SEC_E_OK) { - *mapped_context = TRUE; + /* FIXME: *mapped_context = TRUE; */ expiry_to_timestamp( exptime, expiry ); } } @@ -732,7 +732,7 @@ static NTSTATUS NTAPI kerberos_SpAcceptLsaModeContext( LSA_SEC_HANDLE credential *new_context = create_context_handle( context_handle, new_context_handle ); if (!status) { - *mapped_context = TRUE; + /* FIXME: *mapped_context = TRUE; */ expiry_to_timestamp( exptime, expiry ); } /* FIXME: initialize context_data */ diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index de04ab9316d..bdaaed7a8cc 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -500,6 +500,27 @@ static SECURITY_STATUS WINAPI lsa_FreeCredentialsHandle(CredHandle *credential) return status; } +static SECURITY_STATUS WINAPI lsa_DeleteSecurityContext(CtxtHandle *context) +{ + struct lsa_handle *lsa_ctx; + SECURITY_STATUS status; + + TRACE("%p\n", context); + + if (!context) return SEC_E_INVALID_HANDLE; + lsa_ctx = (struct lsa_handle *)context->dwLower; + if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE; + + if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->DeleteContext) + return SEC_E_UNSUPPORTED_FUNCTION; + + if (lsa_ctx->package->user_api && lsa_ctx->package->user_api->DeleteUserModeContext) + lsa_ctx->package->user_api->DeleteUserModeContext(lsa_ctx->handle); + status = lsa_ctx->package->lsa_api->DeleteContext(lsa_ctx->handle); + free(lsa_ctx); + return status; +} + static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW( CredHandle *credential, CtxtHandle *context, SEC_WCHAR *target_name, ULONG context_req, ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2, @@ -509,8 +530,9 @@ static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW( struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx; struct lsa_package *package = NULL; UNICODE_STRING target_name_us; - BOOLEAN mapped_context; + BOOLEAN mapped_context = FALSE; LSA_SEC_HANDLE new_handle; + SecBuffer ctx_data = { 0 }; TRACE("%p %p %s %#lx %ld %ld %p %ld %p %p %p %p\n", credential, context, debugstr_w(target_name), context_req, reserved1, target_data_rep, input, @@ -536,16 +558,32 @@ static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW( if (target_name) RtlInitUnicodeString(&target_name_us, target_name); + if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY; + status = package->lsa_api->InitLsaModeContext(lsa_cred ? lsa_cred->handle : 0, lsa_ctx ? lsa_ctx->handle : 0, target_name ? &target_name_us : NULL, context_req, target_data_rep, - input, &new_handle, output, context_attr, ts_expiry, &mapped_context, NULL /* FIXME */); + input, &new_handle, output, context_attr, ts_expiry, &mapped_context, &ctx_data); if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED) { - if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY; new_lsa_ctx->package = package; new_lsa_ctx->handle = new_handle; new_context->dwLower = (ULONG_PTR)new_lsa_ctx; new_context->dwUpper = 0; + + if (mapped_context) + { + NTSTATUS ret = package->user_api->InitUserModeContext( new_handle, &ctx_data ); + FreeContextBuffer( ctx_data.pvBuffer ); + if (ret) + { + lsa_DeleteSecurityContext( new_context ); + return ret; + } + } + } + else + { + free( new_lsa_ctx ); } return status; } @@ -620,25 +658,6 @@ static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext( return status; } -static SECURITY_STATUS WINAPI lsa_DeleteSecurityContext(CtxtHandle *context) -{ - struct lsa_handle *lsa_ctx; - SECURITY_STATUS status; - - TRACE("%p\n", context); - - if (!context) return SEC_E_INVALID_HANDLE; - lsa_ctx = (struct lsa_handle *)context->dwLower; - if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE; - - if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->DeleteContext) - return SEC_E_UNSUPPORTED_FUNCTION; - - status = lsa_ctx->package->lsa_api->DeleteContext(lsa_ctx->handle); - free(lsa_ctx); - return status; -} - static SECURITY_STATUS WINAPI lsa_QueryContextAttributesW(CtxtHandle *context, ULONG attribute, void *buffer) { struct lsa_handle *lsa_ctx; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11718
From: Piotr Caban <piotr@codeweavers.com> --- dlls/secur32/lsa.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index bdaaed7a8cc..8ecc8ef933a 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -621,8 +621,9 @@ static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext( SECURITY_STATUS status; struct lsa_package *package = NULL; struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx; - BOOLEAN mapped_context; + BOOLEAN mapped_context = FALSE; LSA_SEC_HANDLE new_handle; + SecBuffer ctx_data = { 0 }; TRACE("%p %p %p %#lx %#lx %p %p %p %p\n", credential, context, input, context_req, target_data_rep, new_context, output, context_attr, ts_expiry); @@ -644,16 +645,33 @@ static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext( if (!package->lsa_api || !package->lsa_api->AcceptLsaModeContext) return SEC_E_UNSUPPORTED_FUNCTION; + if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY; + status = package->lsa_api->AcceptLsaModeContext(lsa_cred ? lsa_cred->handle : 0, lsa_ctx ? lsa_ctx->handle : 0, input, context_req, target_data_rep, &new_handle, output, - context_attr, ts_expiry, &mapped_context, NULL /* FIXME */); + context_attr, ts_expiry, &mapped_context, &ctx_data); if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED) { - if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY; new_lsa_ctx->package = package; new_lsa_ctx->handle = new_handle; new_context->dwLower = (ULONG_PTR)new_lsa_ctx; new_context->dwUpper = 0; + + if (mapped_context) + { + NTSTATUS ret = package->user_api->InitUserModeContext( new_handle, &ctx_data ); + FreeContextBuffer( ctx_data.pvBuffer ); + if (ret) + { + lsa_DeleteSecurityContext( new_context ); + free( new_lsa_ctx ); + return ret; + } + } + } + else + { + free( new_lsa_ctx ); } return status; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11718
From: Piotr Caban <piotr@codeweavers.com> --- dlls/secur32/negotiate.c | 250 ++++++++++++++++++++++++++++----------- 1 file changed, 179 insertions(+), 71 deletions(-) diff --git a/dlls/secur32/negotiate.c b/dlls/secur32/negotiate.c index 9a363e933a7..1c9864912b4 100644 --- a/dlls/secur32/negotiate.c +++ b/dlls/secur32/negotiate.c @@ -39,12 +39,40 @@ struct sec_handle { SECPKG_FUNCTION_TABLE *krb; SECPKG_FUNCTION_TABLE *ntlm; - SECPKG_USER_FUNCTION_TABLE *user_krb; - SECPKG_USER_FUNCTION_TABLE *user_ntlm; LSA_SEC_HANDLE handle_krb; LSA_SEC_HANDLE handle_ntlm; }; +struct user_context_data +{ + enum + { + SSP_KERBEROS, + SSP_NTLM + } ssp; + BOOLEAN mapped_ctx; + /* BYTE ssp_context_data[]; */ +}; + +struct user_ctx +{ + struct list entry; + LSA_SEC_HANDLE handle; + SECPKG_USER_FUNCTION_TABLE *funcs; +}; + +static struct list user_ctx_list = LIST_INIT(user_ctx_list); +static CRITICAL_SECTION user_ctx_cs; +static CRITICAL_SECTION_DEBUG user_ctx_debug = +{ + 0, 0, &user_ctx_cs, + { &user_ctx_debug.ProcessLocksList, &user_ctx_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": user_ctx_cs") } +}; +static CRITICAL_SECTION user_ctx_cs = { &user_ctx_debug, -1, 0, 0, 0, 0 }; + +static LSA_SECPKG_FUNCTION_TABLE *lsa_funcs; + #define WINE_NO_CACHED_CREDENTIALS 0x10000000 #define NEGO_MAX_TOKEN 48256 @@ -115,6 +143,8 @@ static NTSTATUS NTAPI nego_SpInitialize( ULONG_PTR package_id, SECPKG_PARAMETERS LSA_SECPKG_FUNCTION_TABLE *lsa_function_table ) { TRACE( "%Iu, %p, %p\n", package_id, params, lsa_function_table ); + + lsa_funcs = lsa_function_table; return STATUS_SUCCESS; } @@ -158,10 +188,7 @@ static NTSTATUS NTAPI nego_SpAcquireCredentialsHandle( ret = package->SpAcquireCredentialsHandle( principal_us, credential_use, logon_id, auth_data, get_key_fn, get_key_arg, &cred->handle_krb, expiry ); if (ret == SEC_E_OK) - { cred->krb = package; - cred->user_krb = user; - } } if ((package = lsa_find_package( "NTLM", &user ))) @@ -171,10 +198,7 @@ static NTSTATUS NTAPI nego_SpAcquireCredentialsHandle( ret = package->SpAcquireCredentialsHandle( principal_us, cred_use, logon_id, auth_data, get_key_fn, get_key_arg, &cred->handle_ntlm, expiry ); if (ret == SEC_E_OK) - { cred->ntlm = package; - cred->user_ntlm = user; - } } if (cred->krb || cred->ntlm) @@ -225,8 +249,6 @@ static NTSTATUS NTAPI nego_SpInitLsaModeContext( LSA_SEC_HANDLE credential, LSA_ if (!(new_ctxt = ctxt = calloc( 1, sizeof(*ctxt) ))) return SEC_E_INSUFFICIENT_MEMORY; ctxt->krb = cred->krb; ctxt->ntlm = cred->ntlm; - ctxt->user_krb = cred->user_krb; - ctxt->user_ntlm = cred->user_ntlm; } if (!handle) return SEC_E_INVALID_HANDLE; @@ -238,14 +260,12 @@ static NTSTATUS NTAPI nego_SpInitLsaModeContext( LSA_SEC_HANDLE credential, LSA_ if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->ntlm = NULL; - ctxt->user_ntlm = NULL; *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } else { ctxt->krb = NULL; - ctxt->user_krb = NULL; } } @@ -257,12 +277,37 @@ static NTSTATUS NTAPI nego_SpInitLsaModeContext( LSA_SEC_HANDLE credential, LSA_ if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->krb = NULL; - ctxt->user_krb = NULL; *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } } + if (ret == SEC_E_OK) + { + struct user_context_data *data; + ULONG size = sizeof( *data ) + context_data->cbBuffer; + SecBuffer negotiate_data; + + data = lsa_funcs->AllocateLsaHeap( size ); + if (!data) + { + lsa_funcs->FreeLsaHeap( context_data->pvBuffer ); + free( new_ctxt ); + return SEC_E_INSUFFICIENT_MEMORY; + } + negotiate_data.cbBuffer = size; + negotiate_data.pvBuffer = data; + negotiate_data.BufferType = context_data->BufferType; + data->ssp = ctxt->krb ? SSP_KERBEROS : SSP_NTLM; + data->mapped_ctx = *mapped_context; + memcpy( data + 1, context_data->pvBuffer, context_data->cbBuffer ); + lsa_funcs->FreeLsaHeap( context_data->pvBuffer ); + + + *mapped_context = TRUE; + *context_data = negotiate_data; + } + free( new_ctxt ); return ret; } @@ -287,8 +332,6 @@ static NTSTATUS NTAPI nego_SpAcceptLsaModeContext( LSA_SEC_HANDLE credential, LS if (!(new_ctxt = ctxt = calloc( 1, sizeof(*ctxt) ))) return SEC_E_INSUFFICIENT_MEMORY; ctxt->krb = cred->krb; ctxt->ntlm = cred->ntlm; - ctxt->user_krb = cred->user_krb; - ctxt->user_ntlm = cred->user_ntlm; } if (!handle) return SEC_E_INVALID_HANDLE; @@ -301,14 +344,12 @@ static NTSTATUS NTAPI nego_SpAcceptLsaModeContext( LSA_SEC_HANDLE credential, LS if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->ntlm = NULL; - ctxt->user_ntlm = NULL; *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } else { ctxt->krb = NULL; - ctxt->user_krb = NULL; } } @@ -321,12 +362,36 @@ static NTSTATUS NTAPI nego_SpAcceptLsaModeContext( LSA_SEC_HANDLE credential, LS if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->krb = NULL; - ctxt->user_krb = NULL; *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } } + if (ret == SEC_E_OK) + { + struct user_context_data *data; + ULONG size = sizeof( *data ) + context_data->cbBuffer; + SecBuffer negotiate_data; + + data = lsa_funcs->AllocateLsaHeap( size ); + if (!data) + { + lsa_funcs->FreeLsaHeap( context_data->pvBuffer ); + free( new_ctxt ); + return SEC_E_INSUFFICIENT_MEMORY; + } + negotiate_data.cbBuffer = size; + negotiate_data.pvBuffer = data; + negotiate_data.BufferType = context_data->BufferType; + data->ssp = ctxt->krb ? SSP_KERBEROS : SSP_NTLM; + data->mapped_ctx = *mapped_context; + memcpy( data + 1, context_data->pvBuffer, context_data->cbBuffer ); + lsa_funcs->FreeLsaHeap( context_data->pvBuffer ); + + *mapped_context = TRUE; + *context_data = negotiate_data; + } + free( new_ctxt ); return ret; } @@ -432,98 +497,141 @@ static NTSTATUS NTAPI nego_SpInstanceInit(ULONG version, SECPKG_DLL_FUNCTIONS *d return STATUS_SUCCESS; } -static NTSTATUS NTAPI nego_SpMakeSignature( LSA_SEC_HANDLE context, ULONG quality_of_protection, - SecBufferDesc *message, ULONG message_seq_no ) +static struct user_ctx* find_user_ctx( LSA_SEC_HANDLE handle ) { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - struct sec_handle *ctxt; + struct user_ctx *ret; - TRACE( "%Ix, %#lx, %p, %lu\n", context, quality_of_protection, message, message_seq_no ); + EnterCriticalSection( &user_ctx_cs ); + LIST_FOR_EACH_ENTRY( ret, &user_ctx_list, struct user_ctx, entry ) + { + if (ret->handle == handle) + { + LeaveCriticalSection( &user_ctx_cs ); + return ret; + } + } + LeaveCriticalSection( &user_ctx_cs ); + return NULL; +} - if (!context) return SEC_E_INVALID_HANDLE; +static NTSTATUS NTAPI nego_SpInitUserModeContext( LSA_SEC_HANDLE handle, SecBuffer *buf ) +{ + struct user_context_data *data = buf->pvBuffer; + SECPKG_FUNCTION_TABLE *package; + struct user_ctx *ctx; + SecBuffer ctx_data; + NTSTATUS status = SEC_E_OK; - ctxt = (struct sec_handle *)context; - if (ctxt->user_krb) + TRACE( "%Ix, %p\n", handle, buf); + + if (buf->cbBuffer < sizeof( *data )) + return SEC_E_INTERNAL_ERROR; + + EnterCriticalSection( &user_ctx_cs ); + ctx = find_user_ctx( handle ); + if (!ctx) { - ret = ctxt->user_krb->MakeSignature( ctxt->handle_krb, quality_of_protection, message, message_seq_no ); + ctx = malloc( sizeof(*ctx) ); + if (!ctx) + { + LeaveCriticalSection( &user_ctx_cs ); + return SEC_E_INSUFFICIENT_MEMORY; + } + list_add_head( &user_ctx_list, &ctx->entry ); } - else if (ctxt->user_ntlm) + LeaveCriticalSection( &user_ctx_cs ); + + ctx_data.cbBuffer = buf->cbBuffer - sizeof(*data); + ctx_data.BufferType = buf->BufferType; + ctx_data.pvBuffer = data + 1; + + ctx->handle = handle; + + if (data->ssp == SSP_KERBEROS) + package = lsa_find_package( "Kerberos", &ctx->funcs ); + else + package = lsa_find_package( "NTLM", &ctx->funcs ); + if (!package) + status = SEC_E_INTERNAL_ERROR; + + if (!status && data->mapped_ctx) + status = ctx->funcs->InitUserModeContext( handle, &ctx_data ); + if (status) { - ret = ctxt->user_ntlm->MakeSignature( ctxt->handle_ntlm, quality_of_protection, message, message_seq_no ); + EnterCriticalSection( &user_ctx_cs ); + list_remove( &ctx->entry ); + free( ctx ); + LeaveCriticalSection( &user_ctx_cs ); + return status; } - return ret; + return STATUS_SUCCESS; +} + +static NTSTATUS NTAPI nego_SpMakeSignature( LSA_SEC_HANDLE context, ULONG quality_of_protection, + SecBufferDesc *message, ULONG message_seq_no ) +{ + struct user_ctx *ctxt; + + TRACE( "%Ix, %#lx, %p, %lu\n", context, quality_of_protection, message, message_seq_no ); + + if (!(ctxt = find_user_ctx( context ))) return SEC_E_INVALID_HANDLE; + return ctxt->funcs->MakeSignature( ctxt->handle, quality_of_protection, message, message_seq_no ); } static NTSTATUS NTAPI nego_SpVerifySignature( LSA_SEC_HANDLE context, SecBufferDesc *message, ULONG message_seq_no, ULONG *quality_of_protection ) { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - struct sec_handle *ctxt; + struct user_ctx *ctxt; TRACE( "%Ix, %p, %lu, %p\n", context, message, message_seq_no, quality_of_protection ); - if (!context) return SEC_E_INVALID_HANDLE; - - ctxt = (struct sec_handle *)context; - if (ctxt->user_krb) - { - ret = ctxt->user_krb->VerifySignature( ctxt->handle_krb, message, message_seq_no, quality_of_protection ); - } - else if (ctxt->user_ntlm) - { - ret = ctxt->user_ntlm->VerifySignature( ctxt->handle_ntlm, message, message_seq_no, quality_of_protection ); - } - return ret; + if (!(ctxt = find_user_ctx( context ))) return SEC_E_INVALID_HANDLE; + return ctxt->funcs->VerifySignature( ctxt->handle, message, message_seq_no, quality_of_protection ); } static NTSTATUS NTAPI nego_SpSealMessage( LSA_SEC_HANDLE context, ULONG quality_of_protection, SecBufferDesc *message, ULONG message_seq_no ) { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - struct sec_handle *ctxt; + struct user_ctx *ctxt; TRACE( "%Ix, %#lx, %p, %lu\n", context, quality_of_protection, message, message_seq_no ); - if (!context) return SEC_E_INVALID_HANDLE; - - ctxt = (struct sec_handle *)context; - if (ctxt->user_krb) - { - ret = ctxt->user_krb->SealMessage( ctxt->handle_krb, quality_of_protection, message, message_seq_no ); - } - else if (ctxt->user_ntlm) - { - ret = ctxt->user_ntlm->SealMessage( ctxt->handle_ntlm, quality_of_protection, message, message_seq_no ); - } - return ret; + if (!(ctxt = find_user_ctx( context ))) return SEC_E_INVALID_HANDLE; + return ctxt->funcs->SealMessage( ctxt->handle, quality_of_protection, message, message_seq_no ); } static NTSTATUS NTAPI nego_SpUnsealMessage( LSA_SEC_HANDLE context, SecBufferDesc *message, ULONG message_seq_no, ULONG *quality_of_protection ) { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - struct sec_handle *ctxt; + struct user_ctx *ctxt; TRACE( "%Ix, %p, %lu, %p\n", context, message, message_seq_no, quality_of_protection ); - if (!context) return SEC_E_INVALID_HANDLE; + if (!(ctxt = find_user_ctx( context ))) return SEC_E_INVALID_HANDLE; + return ctxt->funcs->UnsealMessage( ctxt->handle, message, message_seq_no, quality_of_protection ); +} - ctxt = (struct sec_handle *)context; - if (ctxt->user_krb) - { - ret = ctxt->user_krb->UnsealMessage( ctxt->handle_krb, message, message_seq_no, quality_of_protection ); - } - else if (ctxt->user_ntlm) +static NTSTATUS NTAPI nego_SpDeleteUserModeContext( LSA_SEC_HANDLE handle ) +{ + struct user_ctx *user_ctx; + + TRACE( "%Ix\n", handle ); + + EnterCriticalSection( &user_ctx_cs ); + user_ctx = find_user_ctx( handle ); + if (user_ctx) { - ret = ctxt->user_ntlm->UnsealMessage( ctxt->handle_ntlm, message, message_seq_no, quality_of_protection ); + list_remove( &user_ctx->entry ); + free( user_ctx ); } - return ret; + LeaveCriticalSection( &user_ctx_cs ); + return STATUS_SUCCESS; } static SECPKG_USER_FUNCTION_TABLE nego_user_table = { nego_SpInstanceInit, - NULL, /* SpInitUserModeContext */ + nego_SpInitUserModeContext, nego_SpMakeSignature, nego_SpVerifySignature, nego_SpSealMessage, @@ -531,7 +639,7 @@ static SECPKG_USER_FUNCTION_TABLE nego_user_table = NULL, /* SpGetContextToken */ NULL, /* SpQueryContextAttributes */ NULL, /* SpCompleteAuthToken */ - NULL, /* SpDeleteContext */ + nego_SpDeleteUserModeContext, NULL, /* SpFormatCredentialsFn */ NULL, /* SpMarshallSupplementalCreds */ NULL, /* SpExportSecurityContext */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11718
From: Piotr Caban <piotr@codeweavers.com> --- dlls/msv1_0/main.c | 254 ++++++++++++++++++++++++++++++++---------- dlls/msv1_0/unixlib.h | 19 ---- 2 files changed, 194 insertions(+), 79 deletions(-) diff --git a/dlls/msv1_0/main.c b/dlls/msv1_0/main.c index 97c35b52d05..ebfcd330a48 100644 --- a/dlls/msv1_0/main.c +++ b/dlls/msv1_0/main.c @@ -155,6 +155,48 @@ static CRITICAL_SECTION_DEBUG local_auth_debug = }; static CRITICAL_SECTION local_auth_cs = { &local_auth_debug, -1, 0, 0, 0, 0 }; +struct user_context_data +{ + enum mode mode; + unsigned int flags; + char session_key[16]; +}; + +struct user_ctx +{ + struct list entry; + LSA_SEC_HANDLE handle; + + enum mode mode; + unsigned int flags; + struct + { + unsigned int seq_no; + struct arc4_info arc4info; + } ntlm; + struct + { + char send_sign_key[16]; + char send_seal_key[16]; + char recv_sign_key[16]; + char recv_seal_key[16]; + unsigned int send_seq_no; + unsigned int recv_seq_no; + struct arc4_info send_arc4info; + struct arc4_info recv_arc4info; + } ntlm2; +}; + +static struct list user_ctx_list = LIST_INIT(user_ctx_list); +static CRITICAL_SECTION user_ctx_cs; +static CRITICAL_SECTION_DEBUG user_ctx_debug = +{ + 0, 0, &user_ctx_cs, + { &user_ctx_debug.ProcessLocksList, &user_ctx_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": user_ctx_cs") } +}; +static CRITICAL_SECTION user_ctx_cs = { &user_ctx_debug, -1, 0, 0, 0, 0 }; + static const char *debugstr_challenge( const BYTE challenge[8] ) { return wine_dbg_sprintf( "%02x%02x%02x%02x%02x%02x%02x%02x", @@ -951,21 +993,21 @@ static const char client_to_server_seal_constant[] = "session key to client-to-s static const char server_to_client_sign_constant[] = "session key to server-to-client signing key magic constant"; static const char server_to_client_seal_constant[] = "session key to server-to-client sealing key magic constant"; -static void create_ntlm2_subkeys( struct ntlm_ctx *ctx ) +static void create_ntlm2_subkeys( struct user_ctx *ctx, const char *session_key ) { if (ctx->mode == MODE_CLIENT) { - calc_ntlm2_subkey( ctx->session_key, client_to_server_sign_constant, ctx->crypt.ntlm2.send_sign_key ); - calc_ntlm2_subkey( ctx->session_key, client_to_server_seal_constant, ctx->crypt.ntlm2.send_seal_key ); - calc_ntlm2_subkey( ctx->session_key, server_to_client_sign_constant, ctx->crypt.ntlm2.recv_sign_key ); - calc_ntlm2_subkey( ctx->session_key, server_to_client_seal_constant, ctx->crypt.ntlm2.recv_seal_key ); + calc_ntlm2_subkey( session_key, client_to_server_sign_constant, ctx->ntlm2.send_sign_key ); + calc_ntlm2_subkey( session_key, client_to_server_seal_constant, ctx->ntlm2.send_seal_key ); + calc_ntlm2_subkey( session_key, server_to_client_sign_constant, ctx->ntlm2.recv_sign_key ); + calc_ntlm2_subkey( session_key, server_to_client_seal_constant, ctx->ntlm2.recv_seal_key ); } else { - calc_ntlm2_subkey( ctx->session_key, server_to_client_sign_constant, ctx->crypt.ntlm2.send_sign_key ); - calc_ntlm2_subkey( ctx->session_key, server_to_client_seal_constant, ctx->crypt.ntlm2.send_seal_key ); - calc_ntlm2_subkey( ctx->session_key, client_to_server_sign_constant, ctx->crypt.ntlm2.recv_sign_key ); - calc_ntlm2_subkey( ctx->session_key, client_to_server_seal_constant, ctx->crypt.ntlm2.recv_seal_key ); + calc_ntlm2_subkey( session_key, server_to_client_sign_constant, ctx->ntlm2.send_sign_key ); + calc_ntlm2_subkey( session_key, server_to_client_seal_constant, ctx->ntlm2.send_seal_key ); + calc_ntlm2_subkey( session_key, client_to_server_sign_constant, ctx->ntlm2.recv_sign_key ); + calc_ntlm2_subkey( session_key, client_to_server_seal_constant, ctx->ntlm2.recv_seal_key ); } } @@ -1419,14 +1461,24 @@ static NTSTATUS NTAPI ntlm_SpInitLsaModeContext( LSA_SEC_HANDLE cred_handle, LSA output->pBuffers[idx].cbBuffer = bin_len; memcpy( output->pBuffers[idx].pvBuffer, bin, bin_len ); - arc4_init( &ctx->crypt.ntlm.arc4info, ctx->session_key, 16 ); - ctx->crypt.ntlm.seq_no = 0; - create_ntlm2_subkeys( ctx ); - arc4_init( &ctx->crypt.ntlm2.send_arc4info, ctx->crypt.ntlm2.send_seal_key, 16 ); - arc4_init( &ctx->crypt.ntlm2.recv_arc4info, ctx->crypt.ntlm2.recv_seal_key, 16 ); - ctx->crypt.ntlm2.send_seq_no = 0; - ctx->crypt.ntlm2.recv_seq_no = 0; + if (status == SEC_E_OK) + { + struct user_context_data *data = lsa_secpkg_table->AllocateLsaHeap( sizeof( *data )); + if (!data) + { + if (!ctx_handle && !input) *new_ctx_handle = 0; + status = SEC_E_INSUFFICIENT_MEMORY; + goto done; + } + data->mode = ctx->mode; + data->flags = ctx->flags; + memcpy( data->session_key, ctx->session_key, sizeof(data->session_key) ); + + *mapped_ctx = TRUE; + ctx_data->cbBuffer = sizeof( *data ); + ctx_data->pvBuffer = data; + } done: if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED && !ctx_handle && !input) { @@ -1730,15 +1782,24 @@ static NTSTATUS NTAPI ntlm_SpAcceptLsaModeContext( LSA_SEC_HANDLE cred_handle, L done: if (status == SEC_E_OK) { - arc4_init( &ctx->crypt.ntlm.arc4info, ctx->session_key, 16 ); - ctx->crypt.ntlm.seq_no = 0; - create_ntlm2_subkeys( ctx ); - arc4_init( &ctx->crypt.ntlm2.send_arc4info, ctx->crypt.ntlm2.send_seal_key, 16 ); - arc4_init( &ctx->crypt.ntlm2.recv_arc4info, ctx->crypt.ntlm2.recv_seal_key, 16 ); - ctx->crypt.ntlm2.send_seq_no = 0; - ctx->crypt.ntlm2.recv_seq_no = 0; + struct user_context_data *data = lsa_secpkg_table->AllocateLsaHeap( sizeof( *data )); - *new_ctx_handle = (LSA_SEC_HANDLE)ctx; + if (!data) + { + status = SEC_E_INSUFFICIENT_MEMORY; + } + else + { + data->mode = ctx->mode; + data->flags = ctx->flags; + memcpy( data->session_key, ctx->session_key, sizeof(data->session_key) ); + + *mapped_ctx = TRUE; + ctx_data->cbBuffer = sizeof( *data ); + ctx_data->pvBuffer = data; + + *new_ctx_handle = (LSA_SEC_HANDLE)ctx; + } } if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED && !ctx_handle) @@ -2038,7 +2099,62 @@ static NTSTATUS NTAPI ntlm_SpInstanceInit( ULONG version, SECPKG_DLL_FUNCTIONS * return STATUS_SUCCESS; } -static SECURITY_STATUS create_signature( struct ntlm_ctx *ctx, unsigned int flags, SecBufferDesc *msg, +static struct user_ctx* find_user_ctx( LSA_SEC_HANDLE handle ) +{ + struct user_ctx *ret; + + EnterCriticalSection( &user_ctx_cs ); + LIST_FOR_EACH_ENTRY( ret, &user_ctx_list, struct user_ctx, entry ) + { + if (ret->handle == handle) + { + LeaveCriticalSection( &user_ctx_cs ); + return ret; + } + } + LeaveCriticalSection( &user_ctx_cs ); + return NULL; +} + +static NTSTATUS NTAPI ntlm_SpInitUserModeContext( LSA_SEC_HANDLE handle, SecBuffer *buf ) +{ + struct user_context_data *data = buf->pvBuffer; + struct user_ctx *ctx; + + TRACE( "%Ix, %p\n", handle, buf); + + if (buf->cbBuffer != sizeof( *data )) + return SEC_E_INTERNAL_ERROR; + + EnterCriticalSection( &user_ctx_cs ); + ctx = find_user_ctx( handle ); + if (!ctx) + { + ctx = malloc( sizeof(*ctx) ); + if (!ctx) + { + LeaveCriticalSection( &user_ctx_cs ); + return SEC_E_INSUFFICIENT_MEMORY; + } + list_add_head( &user_ctx_list, &ctx->entry ); + } + + ctx->handle = handle; + ctx->mode = data->mode; + ctx->flags = data->flags; + + arc4_init( &ctx->ntlm.arc4info, data->session_key, 16 ); + ctx->ntlm.seq_no = 0; + create_ntlm2_subkeys( ctx, data->session_key ); + arc4_init( &ctx->ntlm2.send_arc4info, ctx->ntlm2.send_seal_key, 16 ); + arc4_init( &ctx->ntlm2.recv_arc4info, ctx->ntlm2.recv_seal_key, 16 ); + ctx->ntlm2.send_seq_no = 0; + ctx->ntlm2.recv_seq_no = 0; + LeaveCriticalSection( &user_ctx_cs ); + return STATUS_SUCCESS; +} + +static SECURITY_STATUS create_signature( struct user_ctx *ctx, unsigned int flags, SecBufferDesc *msg, SecBuffer *sig_buf, enum sign_direction dir, BOOL encrypt ) { unsigned int i, sign_version = 1; @@ -2051,23 +2167,23 @@ static SECURITY_STATUS create_signature( struct ntlm_ctx *ctx, unsigned int flag if (dir == SIGN_SEND) { - seq_no[0] = (ctx->crypt.ntlm2.send_seq_no >> 0) & 0xff; - seq_no[1] = (ctx->crypt.ntlm2.send_seq_no >> 8) & 0xff; - seq_no[2] = (ctx->crypt.ntlm2.send_seq_no >> 16) & 0xff; - seq_no[3] = (ctx->crypt.ntlm2.send_seq_no >> 24) & 0xff; - ctx->crypt.ntlm2.send_seq_no++; + seq_no[0] = (ctx->ntlm2.send_seq_no >> 0) & 0xff; + seq_no[1] = (ctx->ntlm2.send_seq_no >> 8) & 0xff; + seq_no[2] = (ctx->ntlm2.send_seq_no >> 16) & 0xff; + seq_no[3] = (ctx->ntlm2.send_seq_no >> 24) & 0xff; + ctx->ntlm2.send_seq_no++; - hmac_md5_init( &hmac_md5, ctx->crypt.ntlm2.send_sign_key, 16 ); + hmac_md5_init( &hmac_md5, ctx->ntlm2.send_sign_key, 16 ); } else { - seq_no[0] = (ctx->crypt.ntlm2.recv_seq_no >> 0) & 0xff; - seq_no[1] = (ctx->crypt.ntlm2.recv_seq_no >> 8) & 0xff; - seq_no[2] = (ctx->crypt.ntlm2.recv_seq_no >> 16) & 0xff; - seq_no[3] = (ctx->crypt.ntlm2.recv_seq_no >> 24) & 0xff; - ctx->crypt.ntlm2.recv_seq_no++; + seq_no[0] = (ctx->ntlm2.recv_seq_no >> 0) & 0xff; + seq_no[1] = (ctx->ntlm2.recv_seq_no >> 8) & 0xff; + seq_no[2] = (ctx->ntlm2.recv_seq_no >> 16) & 0xff; + seq_no[3] = (ctx->ntlm2.recv_seq_no >> 24) & 0xff; + ctx->ntlm2.recv_seq_no++; - hmac_md5_init( &hmac_md5, ctx->crypt.ntlm2.recv_sign_key, 16 ); + hmac_md5_init( &hmac_md5, ctx->ntlm2.recv_sign_key, 16 ); } hmac_md5_update( &hmac_md5, seq_no, 4 ); @@ -2081,9 +2197,9 @@ static SECURITY_STATUS create_signature( struct ntlm_ctx *ctx, unsigned int flag if (encrypt && flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { if (dir == SIGN_SEND) - arc4_process( &ctx->crypt.ntlm2.send_arc4info, digest, 8 ); + arc4_process( &ctx->ntlm2.send_arc4info, digest, 8 ); else - arc4_process( &ctx->crypt.ntlm2.recv_arc4info, digest, 8 ); + arc4_process( &ctx->ntlm2.recv_arc4info, digest, 8 ); } sig[0] = (sign_version >> 0) & 0xff; @@ -2116,13 +2232,13 @@ static SECURITY_STATUS create_signature( struct ntlm_ctx *ctx, unsigned int flag sig[9] = (crc >> 8) & 0xff; sig[10] = (crc >> 16) & 0xff; sig[11] = (crc >> 24) & 0xff; - sig[12] = (ctx->crypt.ntlm.seq_no >> 0) & 0xff; - sig[13] = (ctx->crypt.ntlm.seq_no >> 8) & 0xff; - sig[14] = (ctx->crypt.ntlm.seq_no >> 16) & 0xff; - sig[15] = (ctx->crypt.ntlm.seq_no >> 24) & 0xff; - ctx->crypt.ntlm.seq_no++; + sig[12] = (ctx->ntlm.seq_no >> 0) & 0xff; + sig[13] = (ctx->ntlm.seq_no >> 8) & 0xff; + sig[14] = (ctx->ntlm.seq_no >> 16) & 0xff; + sig[15] = (ctx->ntlm.seq_no >> 24) & 0xff; + ctx->ntlm.seq_no++; - if (encrypt) arc4_process( &ctx->crypt.ntlm.arc4info, sig + 4, 12 ); + if (encrypt) arc4_process( &ctx->ntlm.arc4info, sig + 4, 12 ); return SEC_E_OK; } @@ -2140,7 +2256,7 @@ static SECURITY_STATUS create_signature( struct ntlm_ctx *ctx, unsigned int flag static NTSTATUS NTAPI ntlm_SpMakeSignature( LSA_SEC_HANDLE handle, ULONG qop, SecBufferDesc *msg, ULONG msg_seq_no ) { - struct ntlm_ctx *ctx = (struct ntlm_ctx *)handle; + struct user_ctx *ctx; int idx; TRACE( "%#Ix, %#lx, %p, %lu\n", handle, qop, msg, msg_seq_no ); @@ -2151,11 +2267,12 @@ static NTSTATUS NTAPI ntlm_SpMakeSignature( LSA_SEC_HANDLE handle, ULONG qop, Se if (!msg || !msg->pBuffers || msg->cBuffers < 2 || (idx = get_buffer_index( msg, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN; if (msg->pBuffers[idx].cbBuffer < 16) return SEC_E_BUFFER_TOO_SMALL; + if (!(ctx = find_user_ctx( handle ))) return SEC_E_INVALID_HANDLE; return create_signature( ctx, ctx->flags, msg, &msg->pBuffers[idx], SIGN_SEND, TRUE ); } -static NTSTATUS verify_signature( struct ntlm_ctx *ctx, unsigned int flags, SecBufferDesc *msg, SecBuffer *sig_buf ) +static NTSTATUS verify_signature( struct user_ctx *ctx, unsigned int flags, SecBufferDesc *msg, SecBuffer *sig_buf ) { NTSTATUS status; unsigned int i, sig_idx = 0; @@ -2198,7 +2315,7 @@ static NTSTATUS verify_signature( struct ntlm_ctx *ctx, unsigned int flags, SecB static NTSTATUS NTAPI ntlm_SpVerifySignature( LSA_SEC_HANDLE handle, SecBufferDesc *msg, ULONG msg_seq_no, ULONG *qop ) { - struct ntlm_ctx *ctx = (struct ntlm_ctx *)handle; + struct user_ctx *ctx; int idx; TRACE( "%#Ix, %p, %lu, %p\n", handle, msg, msg_seq_no, qop ); @@ -2208,6 +2325,7 @@ static NTSTATUS NTAPI ntlm_SpVerifySignature( LSA_SEC_HANDLE handle, SecBufferDe if (!msg || !msg->pBuffers || msg->cBuffers < 2 || (idx = get_buffer_index( msg, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN; if (msg->pBuffers[idx].cbBuffer < 16) return SEC_E_BUFFER_TOO_SMALL; + if (!(ctx = find_user_ctx( handle ))) return SEC_E_INVALID_HANDLE; return verify_signature( ctx, ctx->flags, msg, &msg->pBuffers[idx] ); } @@ -2215,13 +2333,14 @@ static NTSTATUS NTAPI ntlm_SpVerifySignature( LSA_SEC_HANDLE handle, SecBufferDe static NTSTATUS NTAPI ntlm_SpSealMessage( LSA_SEC_HANDLE handle, ULONG qop, SecBufferDesc *msg, ULONG msg_seq_no ) { int token_idx, data_idx; - struct ntlm_ctx *ctx; + struct user_ctx *ctx; TRACE( "%#Ix, %#lx, %p %lu\n", handle, qop, msg, msg_seq_no ); if (qop) FIXME( "ignoring quality of protection %#lx\n", qop ); if (msg_seq_no) FIXME( "ignoring message sequence number %lu\n", msg_seq_no ); if (!handle) return SEC_E_INVALID_HANDLE; + if (!(ctx = find_user_ctx( handle ))) return SEC_E_INVALID_HANDLE; if (!msg || !msg->pBuffers || msg->cBuffers < 2 || (token_idx = get_buffer_index( msg, SECBUFFER_TOKEN )) == -1 || @@ -2229,15 +2348,14 @@ static NTSTATUS NTAPI ntlm_SpSealMessage( LSA_SEC_HANDLE handle, ULONG qop, SecB if (msg->pBuffers[token_idx].cbBuffer < 16) return SEC_E_BUFFER_TOO_SMALL; - ctx = (struct ntlm_ctx *)handle; if (ctx->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY && ctx->flags & NTLMSSP_NEGOTIATE_SEAL) { create_signature( ctx, ctx->flags, msg, &msg->pBuffers[token_idx], SIGN_SEND, FALSE ); - arc4_process( &ctx->crypt.ntlm2.send_arc4info, msg->pBuffers[data_idx].pvBuffer, + arc4_process( &ctx->ntlm2.send_arc4info, msg->pBuffers[data_idx].pvBuffer, msg->pBuffers[data_idx].cbBuffer ); if (ctx->flags & NTLMSSP_NEGOTIATE_KEY_EXCH) - arc4_process( &ctx->crypt.ntlm2.send_arc4info, (char *)msg->pBuffers[token_idx].pvBuffer + 4, 8 ); + arc4_process( &ctx->ntlm2.send_arc4info, (char *)msg->pBuffers[token_idx].pvBuffer + 4, 8 ); } else { @@ -2245,8 +2363,8 @@ static NTSTATUS NTAPI ntlm_SpSealMessage( LSA_SEC_HANDLE handle, ULONG qop, SecB create_signature( ctx, ctx->flags | NTLMSSP_NEGOTIATE_SIGN, msg, &msg->pBuffers[token_idx], SIGN_SEND, FALSE ); - arc4_process( &ctx->crypt.ntlm.arc4info, msg->pBuffers[data_idx].pvBuffer, msg->pBuffers[data_idx].cbBuffer ); - arc4_process( &ctx->crypt.ntlm.arc4info, sig + 4, 12 ); + arc4_process( &ctx->ntlm.arc4info, msg->pBuffers[data_idx].pvBuffer, msg->pBuffers[data_idx].cbBuffer ); + arc4_process( &ctx->ntlm.arc4info, sig + 4, 12 ); if (ctx->flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || !ctx->flags) memset( sig + 4, 0, 4 ); } @@ -2258,12 +2376,13 @@ static NTSTATUS NTAPI ntlm_SpUnsealMessage( LSA_SEC_HANDLE handle, SecBufferDesc { int i, data_idx, stream_idx, token_idx; SecBuffer token_buf; - struct ntlm_ctx *ctx; + struct user_ctx *ctx; TRACE( "%#Ix, %p, %lu, %p\n", handle, msg, msg_seq_no, qop ); if (msg_seq_no) FIXME( "ignoring message sequence number %lu\n", msg_seq_no ); if (!handle) return SEC_E_INVALID_HANDLE; + if (!(ctx = find_user_ctx( handle ))) return SEC_E_INVALID_HANDLE; if (!msg || !msg->pBuffers || msg->cBuffers < 2) return SEC_E_INVALID_TOKEN; @@ -2291,13 +2410,12 @@ static NTSTATUS NTAPI ntlm_SpUnsealMessage( LSA_SEC_HANDLE handle, SecBufferDesc token_buf = msg->pBuffers[token_idx]; } - ctx = (struct ntlm_ctx *)handle; if (ctx->flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY && ctx->flags & NTLMSSP_NEGOTIATE_SEAL) { for (i = 0; i < msg->cBuffers; i++) { if (msg->pBuffers[i].BufferType != SECBUFFER_DATA) continue; - arc4_process( &ctx->crypt.ntlm2.recv_arc4info, msg->pBuffers[i].pvBuffer, + arc4_process( &ctx->ntlm2.recv_arc4info, msg->pBuffers[i].pvBuffer, msg->pBuffers[i].cbBuffer ); } } @@ -2306,7 +2424,7 @@ static NTSTATUS NTAPI ntlm_SpUnsealMessage( LSA_SEC_HANDLE handle, SecBufferDesc for (i = 0; i < msg->cBuffers; i++) { if (msg->pBuffers[i].BufferType != SECBUFFER_DATA) continue; - arc4_process( &ctx->crypt.ntlm.arc4info, msg->pBuffers[i].pvBuffer, + arc4_process( &ctx->ntlm.arc4info, msg->pBuffers[i].pvBuffer, msg->pBuffers[i].cbBuffer); } } @@ -2316,10 +2434,26 @@ static NTSTATUS NTAPI ntlm_SpUnsealMessage( LSA_SEC_HANDLE handle, SecBufferDesc return verify_signature( ctx, ctx->flags | NTLMSSP_NEGOTIATE_SIGN, msg, &token_buf ); } +static NTSTATUS NTAPI ntlm_SpDeleteUserModeContext( LSA_SEC_HANDLE handle ) +{ + struct user_ctx *user_ctx; + TRACE( "%Ix\n", handle ); + + EnterCriticalSection( &user_ctx_cs ); + user_ctx = find_user_ctx( handle ); + if (user_ctx) + { + list_remove( &user_ctx->entry ); + free( user_ctx ); + } + LeaveCriticalSection( &user_ctx_cs ); + return STATUS_SUCCESS; +} + static SECPKG_USER_FUNCTION_TABLE ntlm_user_table = { ntlm_SpInstanceInit, - NULL, /* SpInitUserModeContext */ + ntlm_SpInitUserModeContext, ntlm_SpMakeSignature, ntlm_SpVerifySignature, ntlm_SpSealMessage, @@ -2327,7 +2461,7 @@ static SECPKG_USER_FUNCTION_TABLE ntlm_user_table = NULL, /* SpGetContextToken */ NULL, /* SpQueryContextAttributes */ NULL, /* SpCompleteAuthToken */ - NULL, /* SpDeleteContext */ + ntlm_SpDeleteUserModeContext, NULL, /* SpFormatCredentialsFn */ NULL, /* SpMarshallSupplementalCreds */ NULL, /* SpExportSecurityContext */ diff --git a/dlls/msv1_0/unixlib.h b/dlls/msv1_0/unixlib.h index 058dd095594..6beda3e2505 100644 --- a/dlls/msv1_0/unixlib.h +++ b/dlls/msv1_0/unixlib.h @@ -86,25 +86,6 @@ struct ntlm_ctx char *negotiate; HANDLE token; /* local authentication token */ struct hmac_md5_ctx mic; /* local authentication MIC */ - struct - { - struct - { - unsigned int seq_no; - struct arc4_info arc4info; - } ntlm; - struct - { - char send_sign_key[16]; - char send_seal_key[16]; - char recv_sign_key[16]; - char recv_seal_key[16]; - unsigned int send_seq_no; - unsigned int recv_seq_no; - struct arc4_info send_arc4info; - struct arc4_info recv_arc4info; - } ntlm2; - } crypt; }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11718
participants (2)
-
Piotr Caban -
Piotr Caban (@piotr)