>From 0a8c9850fec58760e7491f7382d6d4da01adb51a Mon Sep 17 00:00:00 2001 From: George Popoff Date: Wed, 11 Oct 2017 14:58:09 +0300 Subject: [PATCH 8/8] fix negotiate ssp to choose between kerberberos and ntlm ssp --- wine/dlls/secur32/negotiate.c | 213 +++++++++++++++++++++++++++++++++------ wine/dlls/secur32/secur32_priv.h | 20 +--- 2 files changed, 181 insertions(+), 52 deletions(-) diff --git a/wine/dlls/secur32/negotiate.c b/wine/dlls/secur32/negotiate.c index bf16258..8d63581 100644 --- a/wine/dlls/secur32/negotiate.c +++ b/wine/dlls/secur32/negotiate.c @@ -33,6 +33,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(secur32); +static SEC_WCHAR ntlm_name_W[] = {'N','T','L','M',0}; +static SEC_WCHAR kerberos_name_W[] = {'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', 0}; + +static SecurePackage *ntlm_package; +static SecurePackage *kerberos_package; +static SecureProvider *ntlm_provider; +static SecureProvider *kerberos_provider; + /*********************************************************************** * QueryCredentialsAttributesA */ @@ -61,22 +69,50 @@ static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleW( PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry ) { - static SEC_WCHAR ntlmW[] = {'N','T','L','M',0}; SECURITY_STATUS ret; TRACE("%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p\n", debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse, pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry); - FIXME("forwarding to NTLM\n"); - ret = ntlm_AcquireCredentialsHandleW( pszPrincipal, ntlmW, fCredentialUse, + /* Assume this */ + ret = SEC_E_INTERNAL_ERROR; + + /* First we need to try kerberos */ + + if (kerberos_provider) + { + ret = kerberos_provider->fnTableW. + AcquireCredentialsHandleW(pszPrincipal, kerberos_name_W, fCredentialUse, pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, - phCredential, ptsExpiry ); + phCredential, ptsExpiry); + } + if (ret == SEC_E_OK) { + /* FIXME: create KerberosCredentials */ NtlmCredentials *cred = (NtlmCredentials *)phCredential->dwLower; cred->no_cached_credentials = (pAuthData == NULL); + return ret; + } + + FIXME("Failed to AcquireCredentialHandle via Kerberos.\n"); + + /* Maybe ntlm? */ + if (ntlm_provider) + { + ret = ntlm_provider->fnTableW. + AcquireCredentialsHandleW(pszPrincipal, ntlm_name_W, fCredentialUse, + pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, + phCredential, ptsExpiry ); } + + if (ret == SEC_E_OK) + { + NtlmCredentials *cred = (NtlmCredentials *)phCredential->dwLower; + cred->no_cached_credentials = (pAuthData == NULL); + } + return ret; } @@ -173,15 +209,41 @@ static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextW( PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry ) { + SECURITY_STATUS ret; + TRACE("%p, %p, %s, 0x%08x, %u, %u, %p, %u, %p, %p, %p, %p\n", phCredential, phContext, debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry); - return ntlm_InitializeSecurityContextW( phCredential, phContext, pszTargetName, + /* Assume this */ + ret = SEC_E_INTERNAL_ERROR; + + if (kerberos_provider) + { + ret = kerberos_provider->fnTableW. + InitializeSecurityContextW( phCredential, phContext, pszTargetName, + fContextReq, Reserved1, TargetDataRep, + pInput, Reserved2, phNewContext, + pOutput, pfContextAttr, ptsExpiry ); + } + + if (ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) + { + return ret; + } + + + if (ntlm_provider) + { + ret = ntlm_provider->fnTableW. + InitializeSecurityContextW( phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry ); + } + + return ret; } /*********************************************************************** @@ -227,9 +289,16 @@ static SECURITY_STATUS SEC_ENTRY nego_AcceptSecurityContext( pInput, fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsExpiry); - return ntlm_AcceptSecurityContext( phCredential, phContext, pInput, + /* FIXME: add kerberos invocation */ + if (ntlm_provider) + { + return ntlm_provider->fnTableW. + AcceptSecurityContext( phCredential, phContext, pInput, fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsExpiry ); + } + + return SEC_E_INTERNAL_ERROR; } /*********************************************************************** @@ -259,7 +328,13 @@ static SECURITY_STATUS SEC_ENTRY nego_DeleteSecurityContext(PCtxtHandle phContex { TRACE("%p\n", phContext); - return ntlm_DeleteSecurityContext( phContext ); + if (phContext->dwUpper == KERBEROS_MAGIC && kerberos_provider) + return kerberos_provider->fnTableW.DeleteSecurityContext( phContext ); + + if (ntlm_provider) + return kerberos_provider->fnTableW.DeleteSecurityContext( phContext ); + + return SEC_E_INTERNAL_ERROR; } /*********************************************************************** @@ -288,28 +363,33 @@ static SECURITY_STATUS SEC_ENTRY nego_ApplyControlToken(PCtxtHandle phContext, static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesW( PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer) { + PSecPkgInfoW package_info_w; + SecureProvider *provider; + TRACE("%p, %u, %p\n", phContext, ulAttribute, pBuffer); - switch (ulAttribute) + if (phContext->dwUpper == KERBEROS_MAGIC) { - case SECPKG_ATTR_SIZES: + package_info_w = &kerberos_package->infoW; + provider = kerberos_provider; + } + else { - SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)pBuffer; - sizes->cbMaxToken = 2888; - sizes->cbMaxSignature = 16; - sizes->cbSecurityTrailer = 16; - sizes->cbBlockSize = 0; - return SEC_E_OK; + package_info_w = &ntlm_package->infoW; + provider = ntlm_provider; } + + switch (ulAttribute) + { case SECPKG_ATTR_NEGOTIATION_INFO: { SecPkgContext_NegotiationInfoW *info = (SecPkgContext_NegotiationInfoW *)pBuffer; - info->PackageInfo = ntlm_package_infoW; + info->PackageInfo = package_info_w; info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE; return SEC_E_OK; } default: - return ntlm_QueryContextAttributesW( phContext, ulAttribute, pBuffer ); + return provider->fnTableW.QueryContextAttributesW( phContext, ulAttribute, pBuffer ); } } @@ -319,29 +399,59 @@ static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesW( static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer) { + SECURITY_STATUS ret; + PSecPkgInfoW package_info_W; + PSecPkgInfoA package_info_A; + SecureProvider *provider; + /* int cbSize; */ + TRACE("%p, %u, %p\n", phContext, ulAttribute, pBuffer); - switch (ulAttribute) + if (phContext->dwUpper == KERBEROS_MAGIC) { - case SECPKG_ATTR_SIZES: + package_info_W = &kerberos_package->infoW; + provider = kerberos_provider; + } + else { - SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)pBuffer; - sizes->cbMaxToken = 2888; - sizes->cbMaxSignature = 16; - sizes->cbSecurityTrailer = 16; - sizes->cbBlockSize = 0; - return SEC_E_OK; + package_info_W = &ntlm_package->infoW; + provider = ntlm_provider; } + + /* Convert package info from Widechar to ANSI */ + + /* package_info_A = (PSecPkgInfoA) HeapAlloc(GetProcessHeap(), 0, sizeof(*package_info_A)); + + cbSize = WideCharToMultiByte(CP_ACP, 0, package_info_W->Name, -1, NULL, 0, NULL, NULL); + package_info_A->Name = (SEC_CHAR *) HeapAlloc(GetProcessHeap(), 0, cbSize); + WideCharToMultiByte(CP_ACP, 0, package_info_W->Name, -1, &package_info_A->Name, cbSize, NULL, NULL); + + cbSize = WideCharToMultiByte(CP_ACP, 0, package_info_W->Comment, -1, NULL, 0, NULL, NULL); + package_info_A->Comment = (SEC_CHAR *) HeapAlloc(GetProcessHeap(), 0, cbSize); + WideCharToMultiByte(CP_ACP, 0, package_info_W->Comment, -1, &package_info_A->Comment, cbSize, NULL, NULL); + */ + + switch (ulAttribute) + { case SECPKG_ATTR_NEGOTIATION_INFO: { + /* FIXME: Where we need to free the memory? */ + /* SecurityPackage does not contains ANSI version of info */ + /* Maybe we need to expand SecurityPackage structure? */ SecPkgContext_NegotiationInfoA *info = (SecPkgContext_NegotiationInfoA *)pBuffer; - info->PackageInfo = ntlm_package_infoA; + info->PackageInfo = package_info_A; info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE; - return SEC_E_OK; + return SEC_E_UNSUPPORTED_FUNCTION; } default: - return ntlm_QueryContextAttributesA( phContext, ulAttribute, pBuffer ); + ret = provider->fnTableA.QueryContextAttributesA( phContext, ulAttribute, pBuffer ); } + + HeapFree(GetProcessHeap(), 0, package_info_A->Name); + HeapFree(GetProcessHeap(), 0, package_info_A->Comment); + HeapFree(GetProcessHeap(), 0, package_info_A); + + return ret; } /*********************************************************************** @@ -390,7 +500,10 @@ static SECURITY_STATUS SEC_ENTRY nego_MakeSignature(PCtxtHandle phContext, { TRACE("%p, 0x%08x, %p, %u\n", phContext, fQOP, pMessage, MessageSeqNo); - return ntlm_MakeSignature( phContext, fQOP, pMessage, MessageSeqNo ); + if (ntlm_provider) + return ntlm_provider->fnTableW.MakeSignature( phContext, fQOP, pMessage, MessageSeqNo ); + + return SEC_E_INTERNAL_ERROR; } /*********************************************************************** @@ -401,7 +514,10 @@ static SECURITY_STATUS SEC_ENTRY nego_VerifySignature(PCtxtHandle phContext, { TRACE("%p, %p, %u, %p\n", phContext, pMessage, MessageSeqNo, pfQOP); - return ntlm_VerifySignature( phContext, pMessage, MessageSeqNo, pfQOP ); + if (ntlm_provider) + return ntlm_provider->fnTableW.VerifySignature( phContext, pMessage, MessageSeqNo, pfQOP ); + + return SEC_E_INTERNAL_ERROR; } /*********************************************************************** @@ -411,7 +527,18 @@ static SECURITY_STATUS SEC_ENTRY nego_FreeCredentialsHandle(PCredHandle phCreden { TRACE("%p\n", phCredential); - return ntlm_FreeCredentialsHandle( phCredential ); + if (phCredential->dwUpper == KERBEROS_MAGIC) + { + if (kerberos_provider) + return kerberos_provider->fnTableW.FreeCredentialsHandle( phCredential ); + } + else + { + if (ntlm_provider) + return ntlm_provider->fnTableW.FreeCredentialsHandle( phCredential ); + } + + return SEC_E_INTERNAL_ERROR; } /*********************************************************************** @@ -422,7 +549,10 @@ static SECURITY_STATUS SEC_ENTRY nego_EncryptMessage(PCtxtHandle phContext, { TRACE("%p, 0x%08x, %p, %u\n", phContext, fQOP, pMessage, MessageSeqNo); - return ntlm_EncryptMessage( phContext, fQOP, pMessage, MessageSeqNo ); + if (ntlm_provider) + return ntlm_provider->fnTableW.EncryptMessage( phContext, fQOP, pMessage, MessageSeqNo ); + + return SEC_E_INTERNAL_ERROR; } /*********************************************************************** @@ -433,7 +563,10 @@ static SECURITY_STATUS SEC_ENTRY nego_DecryptMessage(PCtxtHandle phContext, { TRACE("%p, %p, %u, %p\n", phContext, pMessage, MessageSeqNo, pfQOP); - return ntlm_DecryptMessage( phContext, pMessage, MessageSeqNo, pfQOP ); + if (ntlm_provider) + return ntlm_provider->fnTableW.DecryptMessage( phContext, pMessage, MessageSeqNo, pfQOP ); + + return SEC_E_INTERNAL_ERROR; } static const SecurityFunctionTableA negoTableA = { @@ -521,6 +654,7 @@ static CHAR negotiate_comment_A[] = "Microsoft Package Negotiator"; SECPKG_FLAG_LOGON | \ SECPKG_FLAG_RESTRICTED_TOKENS ) + void SECUR32_initNegotiateSP(void) { SecureProvider *provider = SECUR32_addProvider(&negoTableA, &negoTableW, NULL); @@ -530,4 +664,17 @@ void SECUR32_initNegotiateSP(void) const SecPkgInfoA infoA = {CAPS, 1, RPC_C_AUTHN_GSS_NEGOTIATE, NEGO_MAX_TOKEN, nego_name_A, negotiate_comment_A}; SECUR32_addPackages(provider, 1L, &infoA, &infoW); + + ntlm_package = SECUR32_findPackageW(ntlm_name_W); + kerberos_package = SECUR32_findPackageW(kerberos_name_W); + + if (ntlm_package) + ntlm_provider = ntlm_package->provider; + else + FIXME("SECUR32_findPackageW(ntlm) = null\n"); + + if (kerberos_package) + kerberos_provider = kerberos_package->provider; + else + FIXME("SECUR32_findPackageW(kerberos) = null\n"); } diff --git a/wine/dlls/secur32/secur32_priv.h b/wine/dlls/secur32/secur32_priv.h index 9a60d65..212d19c 100644 --- a/wine/dlls/secur32/secur32_priv.h +++ b/wine/dlls/secur32/secur32_priv.h @@ -136,7 +136,6 @@ PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str) DECLSPEC_HIDDEN; void SECUR32_initSchannelSP(void) DECLSPEC_HIDDEN; void SECUR32_initNegotiateSP(void) DECLSPEC_HIDDEN; void SECUR32_initNTLMSP(void) DECLSPEC_HIDDEN; -void SECUR32_initKerberosSP(void) DECLSPEC_HIDDEN; /* Cleanup functions for built-in providers */ void SECUR32_deinitSchannelSP(void) DECLSPEC_HIDDEN; @@ -189,24 +188,7 @@ void SECUR32_arc4Cleanup(arc4_info *a4i) DECLSPEC_HIDDEN; #define NTLMSSP_NEGOTIATE_KEY_EXCHANGE 0x40000000 #define NTLMSSP_NEGOTIATE_56 0x80000000 -SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR *, SEC_WCHAR *, - ULONG, PLUID, PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle, PCtxtHandle, - SEC_WCHAR *, ULONG fContextReq, ULONG, ULONG, PSecBufferDesc, ULONG, PCtxtHandle, - PSecBufferDesc, ULONG *, PTimeStamp) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle, PCtxtHandle, PSecBufferDesc, - ULONG, ULONG, PCtxtHandle, PSecBufferDesc, ULONG *, PTimeStamp) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle, ULONG, void *) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle, ULONG, void *) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle, ULONG, PSecBufferDesc, ULONG) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle, PSecBufferDesc, ULONG, PULONG) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle, ULONG, PSecBufferDesc, ULONG) DECLSPEC_HIDDEN; -SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle, PSecBufferDesc, ULONG, PULONG) DECLSPEC_HIDDEN; - -SecPkgInfoW *ntlm_package_infoW DECLSPEC_HIDDEN; -SecPkgInfoA *ntlm_package_infoA DECLSPEC_HIDDEN; +#define KERBEROS_MAGIC ('K' << 24 | 'E' << 16 | 'R' << 8 | 'B') /* schannel internal interface */ typedef struct schan_imp_session_opaque *schan_imp_session; -- 2.10.4