[PATCH v2 0/9] MR11653: secur32: Preparation for running lsa functions in separate process.
-- v2: kerberos: Fix client buffer handling in kerberos_SpQueryContextAttributes. kerberos: Use LSA_SECPKG_FUNCTION_TABLE to call Lsa functions. kerberos: Handle SEC_WINNT_AUTH_IDENTITY_EX in SpAcquireCredentialsHandle. msv1_0: Fix client buffer handling in ntlm_SpQueryContextAttributes. msv1_0: Fix client buffer handling in ntlm_SpQueryCredentialsAttributes. msv1_0: Use GetCallInfo to obtain thread and process id. secur32: Handle memory allocated with lsa_AllocateClientBuffer in FreeContextBuffer. https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- include/ntsecpkg.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/ntsecpkg.h b/include/ntsecpkg.h index 836c9c650ef..6b2dde43c55 100644 --- a/include/ntsecpkg.h +++ b/include/ntsecpkg.h @@ -40,6 +40,25 @@ extern "C" { #define SECPKG_INTERFACE_VERSION_7 0x400000 #define SECPKG_INTERFACE_VERSION_8 0x800000 +#define SECPKG_CALL_KERNEL_MODE 0x00001 +#define SECPKG_CALL_ANSI 0x00002 +#define SECPKG_CALL_URGENT 0x00004 +#define SECPKG_CALL_RECURSIVE 0x00008 +#define SECPKG_CALL_IN_PROC 0x00010 +#define SECPKG_CALL_CLEANUP 0x00020 +#define SECPKG_CALL_WOWCLIENT 0x00040 +#define SECPKG_CALL_THREAD_TERM 0x00080 +#define SECPKG_CALL_PROCESS_TERM 0x00100 +#define SECPKG_CALL_IS_TCB 0x00200 +#define SECPKG_CALL_NETWORK_ONLY 0x00400 +#define SECPKG_CALL_WINLOGON 0x00800 +#define SECPKG_CALL_ASYNC_UPDATE 0x01000 +#define SECPKG_CALL_SYSTEM_PROC 0x02000 +#define SECPKG_CALL_NEGO 0x04000 +#define SECPKG_CALL_NEGO_EXTENDER 0x08000 +#define SECPKG_CALL_BUFFER_MARSHAL 0x10000 +#define SECPKG_CALL_UNLOCK 0x20000 + /* enum definitions for Secure Service Provider/Authentication Packages */ typedef enum _LSA_TOKEN_INFORMATION_TYPE { LsaTokenInformationNull, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/secur32/lsa.c | 28 ---------------------------- dlls/secur32/tests/ntlm.c | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index 2741a07adf8..1d1e249c9f2 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -453,8 +453,6 @@ static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA( { SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY; SEC_WCHAR *principalW = NULL, *packageW = NULL; - SEC_WINNT_AUTH_IDENTITY_A *id = auth_data; - SEC_WINNT_AUTH_IDENTITY_W idW = {}; TRACE("%s %s %#lx %p %p %p %p %p\n", debugstr_a(principal), debugstr_a(package), credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry); @@ -471,38 +469,12 @@ static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA( if (!(packageW = malloc( len * sizeof(SEC_WCHAR) ))) goto done; MultiByteToWideChar( CP_ACP, 0, package, -1, packageW, len ); } - if (id && (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)) - { - if (id->UserLength) - { - idW.UserLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 ); - if (!(idW.User = malloc( idW.UserLength * sizeof(SEC_WCHAR) ))) goto done; - MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, idW.User, idW.UserLength ); - } - if (id->DomainLength) - { - idW.DomainLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 ); - if (!(idW.Domain = malloc( idW.DomainLength * sizeof(SEC_WCHAR) ))) goto done; - MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, idW.Domain, idW.DomainLength ); - } - if (id->PasswordLength) - { - idW.PasswordLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 ); - if (!(idW.Password = malloc( idW.PasswordLength * sizeof(SEC_WCHAR) ))) goto done; - MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, idW.Password, idW.PasswordLength ); - } - idW.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - auth_data = &idW; - } status = lsa_AcquireCredentialsHandleW( principalW, packageW, credentials_use, logon_id, auth_data, get_key_fn, get_key_arg, credential, ts_expiry ); done: free( packageW ); free( principalW ); - free( idW.User ); - free( idW.Domain ); - free( idW.Password ); return status; } diff --git a/dlls/secur32/tests/ntlm.c b/dlls/secur32/tests/ntlm.c index db04948587c..dd134b385f3 100644 --- a/dlls/secur32/tests/ntlm.c +++ b/dlls/secur32/tests/ntlm.c @@ -1222,6 +1222,7 @@ static void testAcquireCredentialsHandle(void) TimeStamp ttl; SECURITY_STATUS ret; SEC_WINNT_AUTH_IDENTITY_A id; + SEC_WINNT_AUTH_IDENTITY_EXA idex; PSecPkgInfoA pkg_info = NULL; if(QuerySecurityPackageInfoA(sec_pkg_name, &pkg_info) != SEC_E_OK) @@ -1245,6 +1246,24 @@ static void testAcquireCredentialsHandle(void) getSecError(ret)); FreeCredentialsHandle(&cred); + idex.Version = SEC_WINNT_AUTH_IDENTITY_VERSION; + idex.Length = sizeof(idex); + idex.User = id.User; + idex.UserLength = id.UserLength; + idex.Domain = id.Domain; + idex.DomainLength = id.DomainLength; + idex.Password = id.Password; + idex.PasswordLength = id.PasswordLength; + idex.Flags = id.Flags; + idex.PackageList = NULL; + idex.PackageListLength = 0; + + ret = AcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, + NULL, &idex, NULL, NULL, &cred, &ttl); + ok(ret == SEC_E_OK, "AcquireCredentialsHandle() returned %s\n", + getSecError(ret)); + FreeCredentialsHandle(&cred); + id.DomainLength = 0; ret = AcquireCredentialsHandleA(NULL, sec_pkg_name, SECPKG_CRED_OUTBOUND, NULL, &id, NULL, NULL, &cred, &ttl); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/secur32/secur32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c index 3b8fbc6f36a..5f4171abdd3 100644 --- a/dlls/secur32/secur32.c +++ b/dlls/secur32/secur32.c @@ -647,6 +647,8 @@ static void SECUR32_freeProviders(void) */ SECURITY_STATUS WINAPI FreeContextBuffer( void *pv ) { + if (!RtlValidateHeap( GetProcessHeap(), 0, pv )) + return LsaFreeReturnBuffer( pv ); RtlFreeHeap( GetProcessHeap(), 0, pv ); return SEC_E_OK; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/msv1_0/main.c | 8 ++++---- dlls/secur32/lsa.c | 15 +++++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/dlls/msv1_0/main.c b/dlls/msv1_0/main.c index addbc08ff9c..736fe184e9d 100644 --- a/dlls/msv1_0/main.c +++ b/dlls/msv1_0/main.c @@ -519,15 +519,15 @@ static NTSTATUS NTAPI ntlm_SpAcquireCredentialsHandle( UNICODE_STRING *principal } else { - SECPKG_CLIENT_INFO info; + SECPKG_CALL_INFO info; HANDLE h; - lsa_secpkg_table->GetClientInfo( &info ); - h = OpenThread( THREAD_QUERY_INFORMATION, FALSE, info.ThreadID ); + lsa_secpkg_table->GetCallInfo( &info ); + h = OpenThread( THREAD_QUERY_INFORMATION, FALSE, info.ThreadId ); if (!h || !OpenThreadToken( h, TOKEN_QUERY | TOKEN_DUPLICATE, TRUE, &cred->token )) { CloseHandle( h ); - h = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, info.ProcessID ); + h = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, info.ProcessId ); if (!h || !OpenProcessToken( h, TOKEN_QUERY | TOKEN_DUPLICATE, &cred->token )) WARN("failed to get user token (%ld)\n", GetLastError()); } diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index 1d1e249c9f2..589e4d6bf6e 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -910,14 +910,13 @@ static const SecurityFunctionTableA lsa_sspi_tableA = NULL, /* SetContextAttributesA */ }; -static NTSTATUS NTAPI lsa_GetClientInfo( SECPKG_CLIENT_INFO *info ) +static BOOLEAN NTAPI lsa_GetCallInfo( SECPKG_CALL_INFO *info ) { - FIXME( "%p\n", info ); - memset( info, 0, sizeof(*info) ); - info->ProcessID = GetCurrentProcessId(); - info->ThreadID = GetCurrentThreadId(); - return SEC_E_OK; + info->ProcessId = GetCurrentProcessId(); + info->ThreadId = GetCurrentThreadId(); + info->Attributes = SECPKG_CALL_IN_PROC; + return TRUE; } static const LSA_SECPKG_FUNCTION_TABLE lsa_secpkg_table = @@ -938,7 +937,7 @@ static const LSA_SECPKG_FUNCTION_TABLE lsa_secpkg_table = NULL, /* DuplicateHandle */ NULL, /* SaveSupplementalCredentials */ NULL, /* CreateThread */ - lsa_GetClientInfo, + NULL, /* GetClientInfo */ NULL, /* RegisterNotification */ NULL, /* CancelNotification */ NULL, /* MapBuffer */ @@ -946,7 +945,7 @@ static const LSA_SECPKG_FUNCTION_TABLE lsa_secpkg_table = NULL, /* AuditLogon */ NULL, /* CallPackage */ NULL, /* FreeReturnBuffer */ - NULL, /* GetCallInfo */ + lsa_GetCallInfo, NULL, /* CallPackageEx */ NULL, /* CreateSharedMemory */ NULL, /* AllocateSharedMemory */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/msv1_0/main.c | 63 +++++++++++++++++++++++++++++++++------------- dlls/secur32/lsa.c | 22 ++++++++-------- 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/dlls/msv1_0/main.c b/dlls/msv1_0/main.c index 736fe184e9d..029ad511bcf 100644 --- a/dlls/msv1_0/main.c +++ b/dlls/msv1_0/main.c @@ -556,9 +556,12 @@ done: static NTSTATUS NTAPI ntlm_SpQueryCredentialsAttributes( LSA_SEC_HANDLE handle, ULONG attr, void *buf) { - WCHAR domain_buf[DNLEN + 1], username_buf[UNLEN + 1], *domain, *username; + WCHAR domain[DNLEN + 2], username_buf[UNLEN + 1], *username; struct ntlm_cred *cred = (struct ntlm_cred *)handle; - SecPkgCredentials_NamesW *names = buf; + SecPkgCredentials_NamesW names; + SECPKG_CALL_INFO info; + DWORD domain_len; + NTSTATUS status; size_t len; TRACE( "%#Ix, %lu, %p\n", handle, attr, buf ); @@ -575,12 +578,10 @@ static NTSTATUS NTAPI ntlm_SpQueryCredentialsAttributes( LSA_SEC_HANDLE handle, return STATUS_NOT_IMPLEMENTED; } - username = cred->usernameW; - domain = cred->domainW; if (cred->token) { - DWORD username_len = sizeof(username_buf), domain_len = sizeof(domain_buf); + DWORD username_len = sizeof(username_buf); char tmp[256]; TOKEN_USER *token_user = (TOKEN_USER *)tmp; DWORD size = sizeof(tmp); @@ -601,28 +602,56 @@ static NTSTATUS NTAPI ntlm_SpQueryCredentialsAttributes( LSA_SEC_HANDLE handle, return SEC_E_INTERNAL_ERROR; } } + domain_len = sizeof(domain) - sizeof(WCHAR); r = LookupAccountSidW( NULL, token_user->User.Sid, username_buf, &username_len, - domain_buf, &domain_len, &use); + domain, &domain_len, &use); if (token_user != (TOKEN_USER *)tmp) free( token_user ); if (!r) return SEC_E_INTERNAL_ERROR; username = username_buf; - domain = domain_buf; + } + else + { + username = cred->usernameW; + domain_len = cred->domainW ? wcslen(cred->domainW) : 0; + memcpy( domain, cred->domainW, domain_len * sizeof(WCHAR) ); } - len = 1; - if (domain && domain[0]) len += wcslen( domain ) + 1; + if (domain_len) + { + domain[domain_len++] = '\\'; + domain[domain_len] = 0; + } + + len = domain_len + 1; if (username) len += wcslen( username ); - names->sUserName = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - if (!names->sUserName) return SEC_E_INSUFFICIENT_MEMORY; - names->sUserName[0] = 0; - if (domain && domain[0]) + status = lsa_secpkg_table->AllocateClientBuffer( NULL, len * sizeof(WCHAR), (void **)&names.sUserName ); + if (status) return status; + if (domain_len) { - wcscpy( names->sUserName, domain ); - wcscat( names->sUserName, L"\\" ); + lsa_secpkg_table->CopyToClientBuffer( NULL, (domain_len + 1) * sizeof(WCHAR), + names.sUserName, domain ); } - if (username) wcscat( names->sUserName, username ); - return SEC_E_OK; + if (username) + { + lsa_secpkg_table->CopyToClientBuffer( NULL, (wcslen(username) + 1) * sizeof(WCHAR), + names.sUserName + domain_len, username ); + } + + lsa_secpkg_table->GetCallInfo( &info ); + if (info.Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG sUserName; + } names32 = + { + (ULONG_PTR)names.sUserName + }; + + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(names32), buf, &names32 ); + } + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(names), buf, &names ); } static NTSTATUS NTAPI ntlm_SpFreeCredentialsHandle( LSA_SEC_HANDLE handle ) diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index 589e4d6bf6e..f81cd3522b3 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -921,17 +921,17 @@ static BOOLEAN NTAPI lsa_GetCallInfo( SECPKG_CALL_INFO *info ) static const LSA_SECPKG_FUNCTION_TABLE lsa_secpkg_table = { - NULL, /* CreateLogonSession */ - NULL, /* DeleteLogonSession */ - NULL, /* AddCredential */ - NULL, /* GetCredentials */ - NULL, /* DeleteCredential */ - NULL, /* AllocateLsaHeap */ - NULL, /* FreeLsaHeap */ - NULL, /* AllocateClientBuffer */ - NULL, /* FreeClientBuffer */ - NULL, /* CopyToClientBuffer */ - NULL, /* CopyFromClientBuffer */ + lsa_CreateLogonSession, + lsa_DeleteLogonSession, + lsa_AddCredential, + lsa_GetCredentials, + lsa_DeleteCredential, + lsa_AllocateLsaHeap, + lsa_FreeLsaHeap, + lsa_AllocateClientBuffer, + lsa_FreeClientBuffer, + lsa_CopyToClientBuffer, + lsa_CopyFromClientBuffer, NULL, /* ImpersonateClient */ NULL, /* UnloadPackage */ NULL, /* DuplicateHandle */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/msv1_0/main.c | 187 +++++++++++++++++++++++++++++++++------------ 1 file changed, 139 insertions(+), 48 deletions(-) diff --git a/dlls/msv1_0/main.c b/dlls/msv1_0/main.c index 029ad511bcf..406e7de38bd 100644 --- a/dlls/msv1_0/main.c +++ b/dlls/msv1_0/main.c @@ -1663,22 +1663,47 @@ static NTSTATUS NTAPI ntlm_SpDeleteContext( LSA_SEC_HANDLE handle ) return SEC_E_OK; } -static SecPkgInfoW *build_package_info( const SecPkgInfoW *info ) +static NTSTATUS build_package_info( const SecPkgInfoW *info, SecPkgInfoW **ret, + const SECPKG_CALL_INFO *call_info ) { - SecPkgInfoW *ret; DWORD size_name = (wcslen(info->Name) + 1) * sizeof(WCHAR); DWORD size_comment = (wcslen(info->Comment) + 1) * sizeof(WCHAR); + SecPkgInfoW pkg_info; + NTSTATUS status; - if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + size_name + size_comment ))) return NULL; - ret->fCapabilities = info->fCapabilities; - ret->wVersion = info->wVersion; - ret->wRPCID = info->wRPCID; - ret->cbMaxToken = info->cbMaxToken; - ret->Name = (SEC_WCHAR *)(ret + 1); - memcpy( ret->Name, info->Name, size_name ); - ret->Comment = (SEC_WCHAR *)((char *)ret->Name + size_name); - memcpy( ret->Comment, info->Comment, size_comment ); - return ret; + pkg_info = *info; + status = lsa_secpkg_table->AllocateClientBuffer( NULL, + sizeof(pkg_info) + size_name + size_comment, (void **)ret ); + if (status) return status; + + pkg_info.Name = (SEC_WCHAR *)((*ret) + 1); + pkg_info.Comment = (SEC_WCHAR *)((char *)pkg_info.Name + size_name); + lsa_secpkg_table->CopyToClientBuffer( NULL, size_name, pkg_info.Name, info->Name ); + lsa_secpkg_table->CopyToClientBuffer( NULL, size_comment, pkg_info.Comment, info->Comment ); + + if (call_info->Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG fCapabilities; + USHORT wVersion; + USHORT wRPCID; + ULONG cbMaxToken; + ULONG Name; + ULONG Comment; + } pkg_info32 = + { + pkg_info.fCapabilities, + pkg_info.wVersion, + pkg_info.wRPCID, + pkg_info.cbMaxToken, + (ULONG_PTR)pkg_info.Name, + (ULONG_PTR)pkg_info.Comment + }; + + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(pkg_info32), *ret, &pkg_info32 ); + } + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(pkg_info), *ret, &pkg_info ); } static NTSTATUS NTAPI ntlm_SpQueryContextAttributes( LSA_SEC_HANDLE handle, ULONG attr, void *buf ) @@ -1702,49 +1727,88 @@ static NTSTATUS NTAPI ntlm_SpQueryContextAttributes( LSA_SEC_HANDLE handle, ULON X(SECPKG_ATTR_TARGET_INFORMATION); case SECPKG_ATTR_FLAGS: { - SecPkgContext_Flags *flags = (SecPkgContext_Flags *)buf; + SecPkgContext_Flags flags; struct ntlm_ctx *ctx = (struct ntlm_ctx *)handle; - flags->Flags = 0; - if (ctx->flags & NTLMSSP_NEGOTIATE_SIGN) flags->Flags |= ISC_RET_INTEGRITY; - if (ctx->flags & NTLMSSP_NEGOTIATE_SEAL) flags->Flags |= ISC_RET_CONFIDENTIALITY; - return SEC_E_OK; + flags.Flags = 0; + if (ctx->flags & NTLMSSP_NEGOTIATE_SIGN) flags.Flags |= ISC_RET_INTEGRITY; + if (ctx->flags & NTLMSSP_NEGOTIATE_SEAL) flags.Flags |= ISC_RET_CONFIDENTIALITY; + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(flags), buf, &flags ); } case SECPKG_ATTR_SIZES: { - SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)buf; - sizes->cbMaxToken = NTLM_MAX_BUF; - sizes->cbMaxSignature = 16; - sizes->cbBlockSize = 0; - sizes->cbSecurityTrailer = 16; - return SEC_E_OK; + SecPkgContext_Sizes sizes; + + sizes.cbMaxToken = NTLM_MAX_BUF; + sizes.cbMaxSignature = 16; + sizes.cbBlockSize = 0; + sizes.cbSecurityTrailer = 16; + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(sizes), buf, &sizes ); } case SECPKG_ATTR_NEGOTIATION_INFO: { - SecPkgContext_NegotiationInfoW *info = (SecPkgContext_NegotiationInfoW *)buf; - if (!(info->PackageInfo = build_package_info( &ntlm_package_info ))) return SEC_E_INSUFFICIENT_MEMORY; - info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE; - return SEC_E_OK; + SecPkgContext_NegotiationInfoW info; + SECPKG_CALL_INFO call_info; + NTSTATUS status; + + lsa_secpkg_table->GetCallInfo( &call_info ); + status = build_package_info( &ntlm_package_info, &info.PackageInfo, &call_info ); + if (status) return status; + info.NegotiationState = SECPKG_NEGOTIATION_COMPLETE; + + if (call_info.Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG PackageInfo; + ULONG NegotiationState; + } info32 = + { + (ULONG_PTR)info.PackageInfo, + info.NegotiationState + }; + + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(info32), buf, &info32 ); + } + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(info), buf, &info ); } case SECPKG_ATTR_SESSION_KEY: { struct ntlm_ctx *ctx = (struct ntlm_ctx *)handle; - SecPkgContext_SessionKey *key = (SecPkgContext_SessionKey *)buf; - unsigned char *session_key; - - if (!(session_key = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(ctx->session_key) ))) - return SEC_E_INSUFFICIENT_MEMORY; - memcpy( session_key, ctx->session_key, sizeof(ctx->session_key) ); - key->SessionKey = session_key; - key->SessionKeyLength = sizeof(ctx->session_key); - return SEC_E_OK; + SecPkgContext_SessionKey key; + SECPKG_CALL_INFO info; + NTSTATUS status; + + key.SessionKeyLength = sizeof(ctx->session_key); + status = lsa_secpkg_table->AllocateClientBuffer( NULL, key.SessionKeyLength, (void **)&key.SessionKey ); + if (status) return status; + lsa_secpkg_table->CopyToClientBuffer( NULL, key.SessionKeyLength, key.SessionKey, ctx->session_key ); + + lsa_secpkg_table->GetCallInfo( &info ); + if (info.Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG SessionKeyLength; + ULONG SessionKey; + } key32 = + { + key.SessionKeyLength, + (ULONG_PTR)key.SessionKey + }; + + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(key32), buf, &key32 ); + } + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(key), buf, &key ); } case SECPKG_ATTR_KEY_INFO: { struct ntlm_ctx *ctx = (struct ntlm_ctx *)handle; - SecPkgContext_KeyInfoW *info = (SecPkgContext_KeyInfoW *)buf; + SecPkgContext_KeyInfoW info; SEC_WCHAR *signature_alg; ULONG signature_size, signature_algid; + SECPKG_CALL_INFO call_info; + NTSTATUS status; if (ctx->flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { @@ -1759,21 +1823,48 @@ static NTSTATUS NTAPI ntlm_SpQueryContextAttributes( LSA_SEC_HANDLE handle, ULON signature_algid = 0xffffff7c; } - if (!(info->sSignatureAlgorithmName = RtlAllocateHeap( GetProcessHeap(), 0, signature_size ))) - return SEC_E_INSUFFICIENT_MEMORY; - wcscpy( info->sSignatureAlgorithmName, signature_alg ); + status = lsa_secpkg_table->AllocateClientBuffer( NULL, signature_size, + (void **)&info.sSignatureAlgorithmName ); + if (status) return status; + lsa_secpkg_table->CopyToClientBuffer( NULL, signature_size, + info.sSignatureAlgorithmName, signature_alg ); - if (!(info->sEncryptAlgorithmName = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L"RSADSI RC4") ))) + status = lsa_secpkg_table->AllocateClientBuffer( NULL, sizeof(L"RSADSI RC4"), + (void **)&info.sEncryptAlgorithmName ); + if (status) { - RtlFreeHeap( GetProcessHeap(), 0, info->sSignatureAlgorithmName ); - return SEC_E_INSUFFICIENT_MEMORY; + lsa_secpkg_table->FreeClientBuffer( NULL, info.sSignatureAlgorithmName ); + return status; } - wcscpy( info->sEncryptAlgorithmName, L"RSADSI RC4" ); + lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(L"RSADSI RC4"), + info.sEncryptAlgorithmName, (void *)L"RSADSI RC4" ); - info->KeySize = sizeof(ctx->session_key) * 8; - info->SignatureAlgorithm = signature_algid; - info->EncryptAlgorithm = CALG_RC4; - return SEC_E_OK; + info.KeySize = sizeof(ctx->session_key) * 8; + info.SignatureAlgorithm = signature_algid; + info.EncryptAlgorithm = CALG_RC4; + + lsa_secpkg_table->GetCallInfo( &call_info ); + if (call_info.Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG sSignatureAlgorithmName; + ULONG sEncryptAlgorithmName; + ULONG KeySize; + ULONG SignatureAlgorithm; + ULONG EncryptAlgorithm; + } info32 = + { + (ULONG_PTR)info.sSignatureAlgorithmName, + (ULONG_PTR)info.sEncryptAlgorithmName, + info.KeySize, + info.SignatureAlgorithm, + info.EncryptAlgorithm + }; + + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(info32), buf, &info32 ); + } + return lsa_secpkg_table->CopyToClientBuffer( NULL, sizeof(info), buf, &info ); } #undef X default: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/kerberos/krb5_ap.c | 49 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c index 07a751640ad..dc92f47151a 100644 --- a/dlls/kerberos/krb5_ap.c +++ b/dlls/kerberos/krb5_ap.c @@ -402,12 +402,49 @@ static char *get_password_unixcp( const WCHAR *passwd, ULONG passwd_len ) return ret; } +static void map_auth_data( const void *auth_data, SEC_WINNT_AUTH_IDENTITY_W *id ) +{ + const SEC_WINNT_AUTH_IDENTITY_EXA *exA = auth_data; + const SEC_WINNT_AUTH_IDENTITY_EXW *exW = auth_data; + + if (exW->Version != SEC_WINNT_AUTH_IDENTITY_VERSION) + { + *id = *(SEC_WINNT_AUTH_IDENTITY_W *)auth_data; + } + else if (exW->Flags == SEC_WINNT_AUTH_IDENTITY_UNICODE) + { + id->User = exW->User; + id->UserLength = exW->UserLength; + id->Domain = exW->Domain; + id->DomainLength = exW->DomainLength; + id->Password = exW->Password; + id->PasswordLength = exW->PasswordLength; + id->Flags = exW->Flags; + if (exW->PackageList) + FIXME( "ignoring package list %s\n", debugstr_wn(exW->PackageList, exW->PackageListLength) ); + } + else + { + SEC_WINNT_AUTH_IDENTITY_A *idA = (SEC_WINNT_AUTH_IDENTITY_A *)id; + + idA->User = exA->User; + idA->UserLength = exA->UserLength; + idA->Domain = exA->Domain; + idA->DomainLength = exA->DomainLength; + idA->Password = exA->Password; + idA->PasswordLength = exA->PasswordLength; + idA->Flags = exA->Flags; + if (exA->PackageList) + FIXME( "ignoring package list %s\n", debugstr_an((const char *)exA->PackageList, exA->PackageListLength) ); + } +} + static NTSTATUS NTAPI kerberos_SpAcquireCredentialsHandle( UNICODE_STRING *principal_us, ULONG credential_use, LUID *logon_id, void *auth_data, void *get_key_fn, void *get_key_arg, LSA_SEC_HANDLE *credential, TimeStamp *expiry ) { char *principal = NULL, *username = NULL, *password = NULL; - SEC_WINNT_AUTH_IDENTITY_W *id = auth_data; + SEC_WINNT_AUTH_IDENTITY_W id; NTSTATUS status = SEC_E_INSUFFICIENT_MEMORY; struct cred_handle *cred_handle; ULONG exptime; @@ -416,16 +453,18 @@ static NTSTATUS NTAPI kerberos_SpAcquireCredentialsHandle( logon_id, auth_data, get_key_fn, get_key_arg, credential, expiry ); if (principal_us && !(principal = get_str_unixcp( principal_us ))) return SEC_E_INSUFFICIENT_MEMORY; - if (id) + if (auth_data) { - if (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI) + map_auth_data( auth_data, &id ); + + if (id.Flags & SEC_WINNT_AUTH_IDENTITY_ANSI) { FIXME( "ANSI identity not supported\n" ); status = SEC_E_UNSUPPORTED_FUNCTION; goto done; } - if (!(username = get_username_unixcp( id->User, id->UserLength, id->Domain, id->DomainLength ))) goto done; - if (!(password = get_password_unixcp( id->Password, id->PasswordLength ))) goto done; + if (!(username = get_username_unixcp( id.User, id.UserLength, id.Domain, id.DomainLength ))) goto done; + if (!(password = get_password_unixcp( id.Password, id.PasswordLength ))) goto done; } if (!(cred_handle = calloc( 1, sizeof(*cred_handle) ))) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/kerberos/krb5_ap.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c index dc92f47151a..6d9b78d3732 100644 --- a/dlls/kerberos/krb5_ap.c +++ b/dlls/kerberos/krb5_ap.c @@ -69,7 +69,7 @@ static const SecPkgInfoW infoW = kerberos_comment_W }; -static LSA_DISPATCH_TABLE lsa_dispatch; +static LSA_SECPKG_FUNCTION_TABLE *lsa_funcs; struct cred_handle { @@ -134,17 +134,15 @@ static NTSTATUS NTAPI kerberos_LsaApInitializePackage(ULONG package_id, PLSA_DIS ERR( "no Kerberos support, expect problems\n" ); } - lsa_dispatch = *dispatch; - - kerberos_name = lsa_dispatch.AllocateLsaHeap(sizeof(MICROSOFT_KERBEROS_NAME_A)); + kerberos_name = dispatch->AllocateLsaHeap(sizeof(MICROSOFT_KERBEROS_NAME_A)); if (!kerberos_name) return STATUS_NO_MEMORY; memcpy(kerberos_name, MICROSOFT_KERBEROS_NAME_A, sizeof(MICROSOFT_KERBEROS_NAME_A)); - *package_name = lsa_dispatch.AllocateLsaHeap(sizeof(**package_name)); + *package_name = dispatch->AllocateLsaHeap(sizeof(**package_name)); if (!*package_name) { - lsa_dispatch.FreeLsaHeap(kerberos_name); + dispatch->FreeLsaHeap(kerberos_name); return STATUS_NO_MEMORY; } @@ -161,11 +159,11 @@ static NTSTATUS copy_to_client( PLSA_CLIENT_REQUEST lsa_req, KERB_QUERY_TKT_CACH char *client_str; KERB_QUERY_TKT_CACHE_RESPONSE *client_resp; - status = lsa_dispatch.AllocateClientBuffer( lsa_req, size, out ); + status = lsa_funcs->AllocateClientBuffer( lsa_req, size, out ); if (status != STATUS_SUCCESS) return status; client_resp = *out; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, offsetof(KERB_QUERY_TKT_CACHE_RESPONSE, Tickets), + status = lsa_funcs->CopyToClientBuffer(lsa_req, offsetof(KERB_QUERY_TKT_CACHE_RESPONSE, Tickets), client_resp, resp); if (status != STATUS_SUCCESS) goto fail; @@ -187,25 +185,25 @@ static NTSTATUS copy_to_client( PLSA_CLIENT_REQUEST lsa_req, KERB_QUERY_TKT_CACH RtlSecondsSince1970ToTime( resp->Tickets[i].EndTime.QuadPart, &ticket.EndTime ); RtlSecondsSince1970ToTime( resp->Tickets[i].RenewTime.QuadPart, &ticket.RenewTime ); - status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.RealmName.MaximumLength, + status = lsa_funcs->CopyToClientBuffer(lsa_req, ticket.RealmName.MaximumLength, client_str, ticket.RealmName.Buffer); if (status != STATUS_SUCCESS) goto fail; ticket.RealmName.Buffer = (WCHAR *)client_str; client_str += ticket.RealmName.MaximumLength; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.ServerName.MaximumLength, + status = lsa_funcs->CopyToClientBuffer(lsa_req, ticket.ServerName.MaximumLength, client_str, ticket.ServerName.Buffer); if (status != STATUS_SUCCESS) goto fail; ticket.ServerName.Buffer = (WCHAR *)client_str; client_str += ticket.ServerName.MaximumLength; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, sizeof(ticket), &client_resp->Tickets[i], &ticket); + status = lsa_funcs->CopyToClientBuffer(lsa_req, sizeof(ticket), &client_resp->Tickets[i], &ticket); if (status != STATUS_SUCCESS) goto fail; } return STATUS_SUCCESS; fail: - lsa_dispatch.FreeClientBuffer(lsa_req, client_resp); + lsa_funcs->FreeClientBuffer(lsa_req, client_resp); return status; } @@ -217,11 +215,11 @@ static NTSTATUS copy_to_client_ex( PLSA_CLIENT_REQUEST lsa_req, KERB_QUERY_TKT_C char *client_str; KERB_QUERY_TKT_CACHE_EX_RESPONSE *client_resp; - status = lsa_dispatch.AllocateClientBuffer( lsa_req, size, out ); + status = lsa_funcs->AllocateClientBuffer( lsa_req, size, out ); if (status != STATUS_SUCCESS) return status; client_resp = *out; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, offsetof(KERB_QUERY_TKT_CACHE_EX_RESPONSE, Tickets), + status = lsa_funcs->CopyToClientBuffer(lsa_req, offsetof(KERB_QUERY_TKT_CACHE_EX_RESPONSE, Tickets), client_resp, resp); if (status != STATUS_SUCCESS) goto fail; @@ -235,37 +233,37 @@ static NTSTATUS copy_to_client_ex( PLSA_CLIENT_REQUEST lsa_req, KERB_QUERY_TKT_C RtlSecondsSince1970ToTime( resp->Tickets[i].EndTime.QuadPart, &ticket.EndTime ); RtlSecondsSince1970ToTime( resp->Tickets[i].RenewTime.QuadPart, &ticket.RenewTime ); - status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.ClientRealm.MaximumLength, + status = lsa_funcs->CopyToClientBuffer(lsa_req, ticket.ClientRealm.MaximumLength, client_str, ticket.ClientRealm.Buffer); if (status != STATUS_SUCCESS) goto fail; ticket.ClientRealm.Buffer = (WCHAR *)client_str; client_str += ticket.ClientRealm.MaximumLength; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.ClientName.MaximumLength, + status = lsa_funcs->CopyToClientBuffer(lsa_req, ticket.ClientName.MaximumLength, client_str, ticket.ClientName.Buffer); if (status != STATUS_SUCCESS) goto fail; ticket.ClientName.Buffer = (WCHAR *)client_str; client_str += ticket.ClientName.MaximumLength; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.ServerRealm.MaximumLength, + status = lsa_funcs->CopyToClientBuffer(lsa_req, ticket.ServerRealm.MaximumLength, client_str, ticket.ServerRealm.Buffer); if (status != STATUS_SUCCESS) goto fail; ticket.ServerRealm.Buffer = (WCHAR *)client_str; client_str += ticket.ServerRealm.MaximumLength; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.ServerName.MaximumLength, + status = lsa_funcs->CopyToClientBuffer(lsa_req, ticket.ServerName.MaximumLength, client_str, ticket.ServerName.Buffer); if (status != STATUS_SUCCESS) goto fail; ticket.ServerName.Buffer = (WCHAR *)client_str; client_str += ticket.ServerName.MaximumLength; - status = lsa_dispatch.CopyToClientBuffer(lsa_req, sizeof(ticket), &client_resp->Tickets[i], &ticket); + status = lsa_funcs->CopyToClientBuffer(lsa_req, sizeof(ticket), &client_resp->Tickets[i], &ticket); if (status != STATUS_SUCCESS) goto fail; } return STATUS_SUCCESS; fail: - lsa_dispatch.FreeClientBuffer(lsa_req, client_resp); + lsa_funcs->FreeClientBuffer(lsa_req, client_resp); return status; } @@ -739,6 +737,8 @@ static NTSTATUS NTAPI kerberos_SpInitialize(ULONG_PTR package_id, SECPKG_PARAMET { TRACE("%Iu, %p, %p\n", package_id, params, lsa_function_table); + lsa_funcs = lsa_function_table; + if (!__wine_unixlib_handle) { if (__wine_init_unix_call() || KRB5_CALL( process_attach, NULL )) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
From: Piotr Caban <piotr@codeweavers.com> --- dlls/kerberos/krb5_ap.c | 117 +++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 26 deletions(-) diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c index 6d9b78d3732..80af6efa60d 100644 --- a/dlls/kerberos/krb5_ap.c +++ b/dlls/kerberos/krb5_ap.c @@ -654,22 +654,47 @@ static NTSTATUS NTAPI kerberos_SpDeleteContext( LSA_SEC_HANDLE context ) return status; } -static SecPkgInfoW *build_package_info( const SecPkgInfoW *info ) +static NTSTATUS build_package_info( const SecPkgInfoW *info, SecPkgInfoW **ret, + const SECPKG_CALL_INFO *call_info ) { - SecPkgInfoW *ret; DWORD size_name = (wcslen(info->Name) + 1) * sizeof(WCHAR); DWORD size_comment = (wcslen(info->Comment) + 1) * sizeof(WCHAR); + SecPkgInfoW pkg_info; + NTSTATUS status; - if (!(ret = malloc( sizeof(*ret) + size_name + size_comment ))) return NULL; - ret->fCapabilities = info->fCapabilities; - ret->wVersion = info->wVersion; - ret->wRPCID = info->wRPCID; - ret->cbMaxToken = info->cbMaxToken; - ret->Name = (SEC_WCHAR *)(ret + 1); - memcpy( ret->Name, info->Name, size_name ); - ret->Comment = (SEC_WCHAR *)((char *)ret->Name + size_name); - memcpy( ret->Comment, info->Comment, size_comment ); - return ret; + pkg_info = *info; + status = lsa_funcs->AllocateClientBuffer( NULL, + sizeof(pkg_info) + size_name + size_comment, (void **)ret ); + if (status) return status; + + pkg_info.Name = (SEC_WCHAR *)((*ret) + 1); + pkg_info.Comment = (SEC_WCHAR *)((char *)pkg_info.Name + size_name); + lsa_funcs->CopyToClientBuffer( NULL, size_name, pkg_info.Name, info->Name ); + lsa_funcs->CopyToClientBuffer( NULL, size_comment, pkg_info.Comment, info->Comment ); + + if (call_info->Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG fCapabilities; + USHORT wVersion; + USHORT wRPCID; + ULONG cbMaxToken; + ULONG Name; + ULONG Comment; + } pkg_info32 = + { + pkg_info.fCapabilities, + pkg_info.wVersion, + pkg_info.wRPCID, + pkg_info.cbMaxToken, + (ULONG_PTR)pkg_info.Name, + (ULONG_PTR)pkg_info.Comment + }; + + return lsa_funcs->CopyToClientBuffer( NULL, sizeof(pkg_info32), *ret, &pkg_info32 ); + } + return lsa_funcs->CopyToClientBuffer( NULL, sizeof(pkg_info), *ret, &pkg_info ); } static NTSTATUS NTAPI kerberos_SpQueryContextAttributes( LSA_SEC_HANDLE context, ULONG attribute, void *buffer ) @@ -697,32 +722,72 @@ static NTSTATUS NTAPI kerberos_SpQueryContextAttributes( LSA_SEC_HANDLE context, #undef X case SECPKG_ATTR_SESSION_KEY: { - SecPkgContext_SessionKey key = { 128 }; + unsigned char tmp[128]; + SecPkgContext_SessionKey key = { 128, tmp }; struct query_context_attributes_params params = { context_handle->handle, attribute, &key }; + SECPKG_CALL_INFO info; NTSTATUS status; - if (!(key.SessionKey = RtlAllocateHeap( GetProcessHeap(), 0, key.SessionKeyLength ))) return STATUS_NO_MEMORY; - if ((status = KRB5_CALL( query_context_attributes, ¶ms ))) - { - RtlFreeHeap( GetProcessHeap(), 0, key.SessionKey ); return status; - } - *(SecPkgContext_SessionKey *)buffer = key; - return SEC_E_OK; + status = lsa_funcs->AllocateClientBuffer( NULL, key.SessionKeyLength, (void **)&key.SessionKey ); + if (status) return status; + lsa_funcs->CopyToClientBuffer( NULL, key.SessionKeyLength, key.SessionKey, tmp ); + + lsa_funcs->GetCallInfo( &info ); + if (info.Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG SessionKeyLength; + ULONG SessionKey; + } key32 = + { + key.SessionKeyLength, + (ULONG_PTR)key.SessionKey + }; + + return lsa_funcs->CopyToClientBuffer( NULL, sizeof(key32), buffer, &key32 ); + } + return lsa_funcs->CopyToClientBuffer( NULL, sizeof(key), buffer, &key ); } case SECPKG_ATTR_SIZES: { - struct query_context_attributes_params params = { context_handle->handle, attribute, buffer }; - return KRB5_CALL( query_context_attributes, ¶ms ); + SecPkgContext_Sizes sizes; + struct query_context_attributes_params params = { context_handle->handle, attribute, &sizes }; + NTSTATUS status; + + status = KRB5_CALL( query_context_attributes, ¶ms ); + if (status) return status; + return lsa_funcs->CopyToClientBuffer( NULL, sizeof(sizes), buffer, &sizes ); } case SECPKG_ATTR_NEGOTIATION_INFO: { - SecPkgContext_NegotiationInfoW *info = (SecPkgContext_NegotiationInfoW *)buffer; - if (!(info->PackageInfo = build_package_info( &infoW ))) return SEC_E_INSUFFICIENT_MEMORY; - info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE; - return SEC_E_OK; + SecPkgContext_NegotiationInfoW info; + SECPKG_CALL_INFO call_info; + NTSTATUS status; + + lsa_funcs->GetCallInfo( &call_info ); + status = build_package_info( &infoW, &info.PackageInfo, &call_info ); + if (status) return status; + info.NegotiationState = SECPKG_NEGOTIATION_COMPLETE; + + if (call_info.Attributes & SECPKG_CALL_WOWCLIENT) + { + struct + { + ULONG PackageInfo; + ULONG NegotiationState; + } info32 = + { + (ULONG_PTR)info.PackageInfo, + info.NegotiationState + }; + + return lsa_funcs->CopyToClientBuffer( NULL, sizeof(info32), buffer, &info32 ); + } + return lsa_funcs->CopyToClientBuffer( NULL, sizeof(info), buffer, &info ); } default: FIXME( "unknown attribute %lu\n", attribute ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11653
participants (2)
-
Piotr Caban -
Piotr Caban (@piotr)