| /* Copyright (C) 2004 Juan Lang | |
| * | |
| * This file implements thunks between wide char and multibyte functions for | |
| * SSPs that only provide one or the other. | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winnls.h" | |
| #include "winternl.h" | |
| #include "sspi.h" | |
| #include "secur32_priv.h" | |
| #include "thunks.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(secur32); | |
| SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleA( | |
| SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialsUse, | |
| PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, | |
| PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%s %s %d %p %p %p %p %p %p\n", debugstr_a(pszPrincipal), | |
| debugstr_a(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, | |
| pvGetKeyArgument, phCredential, ptsExpiry); | |
| if (pszPackage) | |
| { | |
| UNICODE_STRING principal, package; | |
| RtlCreateUnicodeStringFromAsciiz(&principal, pszPrincipal); | |
| RtlCreateUnicodeStringFromAsciiz(&package, pszPackage); | |
| ret = AcquireCredentialsHandleW(principal.Buffer, package.Buffer, | |
| fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, | |
| phCredential, ptsExpiry); | |
| RtlFreeUnicodeString(&principal); | |
| RtlFreeUnicodeString(&package); | |
| } | |
| else | |
| ret = SEC_E_SECPKG_NOT_FOUND; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleW( | |
| SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, | |
| PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, | |
| PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%s %s %d %p %p %p %p %p %p\n", debugstr_w(pszPrincipal), | |
| debugstr_w(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, | |
| pvGetKeyArgument, phCredential, ptsExpiry); | |
| if (pszPackage) | |
| { | |
| PSTR principal, package; | |
| principal = SECUR32_AllocMultiByteFromWide(pszPrincipal); | |
| package = SECUR32_AllocMultiByteFromWide(pszPackage); | |
| ret = AcquireCredentialsHandleA(principal, package, fCredentialsUse, | |
| pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, | |
| ptsExpiry); | |
| HeapFree(GetProcessHeap(), 0, principal); | |
| HeapFree(GetProcessHeap(), 0, package); | |
| } | |
| else | |
| ret = SEC_E_SECPKG_NOT_FOUND; | |
| return ret; | |
| } | |
| /* thunking is pretty dicey for these--the output type depends on ulAttribute, | |
| * so we have to know about every type the caller does | |
| */ | |
| SECURITY_STATUS SEC_ENTRY thunk_QueryCredentialsAttributesA( | |
| PCredHandle phCredential, ULONG ulAttribute, void *pBuffer) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %d %p\n", phCredential, ulAttribute, pBuffer); | |
| if (phCredential) | |
| { | |
| SecurePackage *package = (SecurePackage *)phCredential->dwUpper; | |
| PCredHandle cred = (PCredHandle)phCredential->dwLower; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableW.QueryCredentialsAttributesW) | |
| { | |
| ret = package->provider->fnTableW.QueryCredentialsAttributesW( | |
| cred, ulAttribute, pBuffer); | |
| if (ret == SEC_E_OK) | |
| { | |
| switch (ulAttribute) | |
| { | |
| case SECPKG_CRED_ATTR_NAMES: | |
| { | |
| PSecPkgCredentials_NamesW names = | |
| (PSecPkgCredentials_NamesW)pBuffer; | |
| SEC_WCHAR *oldUser = names->sUserName; | |
| if (oldUser) | |
| { | |
| names->sUserName = | |
| (PWSTR)SECUR32_AllocMultiByteFromWide(oldUser); | |
| package->provider->fnTableW.FreeContextBuffer( | |
| oldUser); | |
| } | |
| break; | |
| } | |
| default: | |
| WARN("attribute type %d unknown\n", ulAttribute); | |
| ret = SEC_E_INTERNAL_ERROR; | |
| } | |
| } | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_QueryCredentialsAttributesW( | |
| PCredHandle phCredential, ULONG ulAttribute, void *pBuffer) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %d %p\n", phCredential, ulAttribute, pBuffer); | |
| if (phCredential) | |
| { | |
| SecurePackage *package = (SecurePackage *)phCredential->dwUpper; | |
| PCredHandle cred = (PCredHandle)phCredential->dwLower; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableA.QueryCredentialsAttributesA) | |
| { | |
| ret = package->provider->fnTableA.QueryCredentialsAttributesA( | |
| cred, ulAttribute, pBuffer); | |
| if (ret == SEC_E_OK) | |
| { | |
| switch (ulAttribute) | |
| { | |
| case SECPKG_CRED_ATTR_NAMES: | |
| { | |
| PSecPkgCredentials_NamesA names = | |
| (PSecPkgCredentials_NamesA)pBuffer; | |
| SEC_CHAR *oldUser = names->sUserName; | |
| if (oldUser) | |
| { | |
| names->sUserName = | |
| (PSTR)SECUR32_AllocWideFromMultiByte(oldUser); | |
| package->provider->fnTableA.FreeContextBuffer( | |
| oldUser); | |
| } | |
| break; | |
| } | |
| default: | |
| WARN("attribute type %d unknown\n", ulAttribute); | |
| ret = SEC_E_INTERNAL_ERROR; | |
| } | |
| } | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_InitializeSecurityContextA( | |
| PCredHandle phCredential, PCtxtHandle phContext, | |
| SEC_CHAR *pszTargetName, ULONG fContextReq, | |
| ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, | |
| ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, | |
| ULONG *pfContextAttr, PTimeStamp ptsExpiry) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext, | |
| debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, | |
| Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry); | |
| if (phCredential) | |
| { | |
| SecurePackage *package = (SecurePackage *)phCredential->dwUpper; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableW.InitializeSecurityContextW) | |
| { | |
| UNICODE_STRING target; | |
| RtlCreateUnicodeStringFromAsciiz(&target, pszTargetName); | |
| ret = package->provider->fnTableW.InitializeSecurityContextW( | |
| phCredential, phContext, target.Buffer, fContextReq, Reserved1, | |
| TargetDataRep, pInput, Reserved2, phNewContext, pOutput, | |
| pfContextAttr, ptsExpiry); | |
| RtlFreeUnicodeString(&target); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_InitializeSecurityContextW( | |
| PCredHandle phCredential, PCtxtHandle phContext, | |
| SEC_WCHAR *pszTargetName, ULONG fContextReq, | |
| ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, | |
| ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, | |
| ULONG *pfContextAttr, PTimeStamp ptsExpiry) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext, | |
| debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, | |
| Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry); | |
| if (phCredential) | |
| { | |
| SecurePackage *package = (SecurePackage *)phCredential->dwUpper; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableA.InitializeSecurityContextA) | |
| { | |
| PSTR target = SECUR32_AllocMultiByteFromWide(pszTargetName); | |
| ret = package->provider->fnTableA.InitializeSecurityContextA( | |
| phCredential, phContext, target, fContextReq, Reserved1, | |
| TargetDataRep, pInput, Reserved2, phNewContext, pOutput, | |
| pfContextAttr, ptsExpiry); | |
| HeapFree(GetProcessHeap(), 0, target); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_AddCredentialsA(PCredHandle hCredentials, | |
| SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse, | |
| void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, | |
| PTimeStamp ptsExpiry) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %s %s %d %p %p %p %p\n", hCredentials, debugstr_a(pszPrincipal), | |
| debugstr_a(pszPackage), fCredentialUse, pAuthData, pGetKeyFn, | |
| pvGetKeyArgument, ptsExpiry); | |
| if (hCredentials) | |
| { | |
| SecurePackage *package = (SecurePackage *)hCredentials->dwUpper; | |
| PCredHandle cred = (PCtxtHandle)hCredentials->dwLower; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableW.AddCredentialsW) | |
| { | |
| UNICODE_STRING szPrincipal, szPackage; | |
| RtlCreateUnicodeStringFromAsciiz(&szPrincipal, pszPrincipal); | |
| RtlCreateUnicodeStringFromAsciiz(&szPackage, pszPackage); | |
| ret = package->provider->fnTableW.AddCredentialsW( | |
| cred, szPrincipal.Buffer, szPackage.Buffer, fCredentialUse, | |
| pAuthData, pGetKeyFn, pvGetKeyArgument, ptsExpiry); | |
| RtlFreeUnicodeString(&szPrincipal); | |
| RtlFreeUnicodeString(&szPackage); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_AddCredentialsW(PCredHandle hCredentials, | |
| SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse, | |
| void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, | |
| PTimeStamp ptsExpiry) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %s %s %d %p %p %p %p\n", hCredentials, debugstr_w(pszPrincipal), | |
| debugstr_w(pszPackage), fCredentialUse, pAuthData, pGetKeyFn, | |
| pvGetKeyArgument, ptsExpiry); | |
| if (hCredentials) | |
| { | |
| SecurePackage *package = (SecurePackage *)hCredentials->dwUpper; | |
| PCredHandle cred = (PCtxtHandle)hCredentials->dwLower; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableA.AddCredentialsA) | |
| { | |
| PSTR szPrincipal = SECUR32_AllocMultiByteFromWide(pszPrincipal); | |
| PSTR szPackage = SECUR32_AllocMultiByteFromWide(pszPackage); | |
| ret = package->provider->fnTableA.AddCredentialsA( | |
| cred, szPrincipal, szPackage, fCredentialUse, pAuthData, | |
| pGetKeyFn, pvGetKeyArgument, ptsExpiry); | |
| HeapFree(GetProcessHeap(), 0, szPrincipal); | |
| HeapFree(GetProcessHeap(), 0, szPackage); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| static PSecPkgInfoA _copyPackageInfoFlatWToA(const SecPkgInfoW *infoW) | |
| { | |
| PSecPkgInfoA ret; | |
| if (infoW) | |
| { | |
| size_t bytesNeeded = sizeof(SecPkgInfoA); | |
| int nameLen = 0, commentLen = 0; | |
| if (infoW->Name) | |
| { | |
| nameLen = WideCharToMultiByte(CP_ACP, 0, infoW->Name, -1, | |
| NULL, 0, NULL, NULL); | |
| bytesNeeded += nameLen; | |
| } | |
| if (infoW->Comment) | |
| { | |
| commentLen = WideCharToMultiByte(CP_ACP, 0, infoW->Comment, -1, | |
| NULL, 0, NULL, NULL); | |
| bytesNeeded += commentLen; | |
| } | |
| ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded); | |
| if (ret) | |
| { | |
| PSTR nextString = (PSTR)((PBYTE)ret + sizeof(SecPkgInfoA)); | |
| memcpy(ret, infoW, sizeof(SecPkgInfoA)); | |
| if (infoW->Name) | |
| { | |
| ret->Name = nextString; | |
| WideCharToMultiByte(CP_ACP, 0, infoW->Name, -1, nextString, | |
| nameLen, NULL, NULL); | |
| nextString += nameLen; | |
| } | |
| else | |
| ret->Name = NULL; | |
| if (infoW->Comment) | |
| { | |
| ret->Comment = nextString; | |
| WideCharToMultiByte(CP_ACP, 0, infoW->Comment, -1, nextString, | |
| nameLen, NULL, NULL); | |
| } | |
| else | |
| ret->Comment = NULL; | |
| } | |
| } | |
| else | |
| ret = NULL; | |
| return ret; | |
| } | |
| static SECURITY_STATUS thunk_ContextAttributesWToA(SecurePackage *package, | |
| ULONG ulAttribute, void *pBuffer) | |
| { | |
| SECURITY_STATUS ret = SEC_E_OK; | |
| if (package && pBuffer) | |
| { | |
| switch (ulAttribute) | |
| { | |
| case SECPKG_ATTR_NAMES: | |
| { | |
| PSecPkgContext_NamesW names = (PSecPkgContext_NamesW)pBuffer; | |
| SEC_WCHAR *oldUser = names->sUserName; | |
| if (oldUser) | |
| { | |
| names->sUserName = | |
| (PWSTR)SECUR32_AllocMultiByteFromWide(oldUser); | |
| package->provider->fnTableW.FreeContextBuffer(oldUser); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_AUTHORITY: | |
| { | |
| PSecPkgContext_AuthorityW names = | |
| (PSecPkgContext_AuthorityW)pBuffer; | |
| SEC_WCHAR *oldAuth = names->sAuthorityName; | |
| if (oldAuth) | |
| { | |
| names->sAuthorityName = | |
| (PWSTR)SECUR32_AllocMultiByteFromWide(oldAuth); | |
| package->provider->fnTableW.FreeContextBuffer(oldAuth); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_KEY_INFO: | |
| { | |
| PSecPkgContext_KeyInfoW info = (PSecPkgContext_KeyInfoW)pBuffer; | |
| SEC_WCHAR *oldSigAlgName = info->sSignatureAlgorithmName; | |
| SEC_WCHAR *oldEncAlgName = info->sEncryptAlgorithmName; | |
| if (oldSigAlgName) | |
| { | |
| info->sSignatureAlgorithmName = | |
| (PWSTR)SECUR32_AllocMultiByteFromWide(oldSigAlgName); | |
| package->provider->fnTableW.FreeContextBuffer( | |
| oldSigAlgName); | |
| } | |
| if (oldEncAlgName) | |
| { | |
| info->sEncryptAlgorithmName = | |
| (PWSTR)SECUR32_AllocMultiByteFromWide(oldEncAlgName); | |
| package->provider->fnTableW.FreeContextBuffer( | |
| oldEncAlgName); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_PACKAGE_INFO: | |
| { | |
| PSecPkgContext_PackageInfoW info = | |
| (PSecPkgContext_PackageInfoW)pBuffer; | |
| PSecPkgInfoW oldPkgInfo = info->PackageInfo; | |
| if (oldPkgInfo) | |
| { | |
| info->PackageInfo = (PSecPkgInfoW) | |
| _copyPackageInfoFlatWToA(oldPkgInfo); | |
| package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_NEGOTIATION_INFO: | |
| { | |
| PSecPkgContext_NegotiationInfoW info = | |
| (PSecPkgContext_NegotiationInfoW)pBuffer; | |
| PSecPkgInfoW oldPkgInfo = info->PackageInfo; | |
| if (oldPkgInfo) | |
| { | |
| info->PackageInfo = (PSecPkgInfoW) | |
| _copyPackageInfoFlatWToA(oldPkgInfo); | |
| package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_NATIVE_NAMES: | |
| { | |
| PSecPkgContext_NativeNamesW names = | |
| (PSecPkgContext_NativeNamesW)pBuffer; | |
| PWSTR oldClient = names->sClientName; | |
| PWSTR oldServer = names->sServerName; | |
| if (oldClient) | |
| { | |
| names->sClientName = (PWSTR)SECUR32_AllocMultiByteFromWide( | |
| oldClient); | |
| package->provider->fnTableW.FreeContextBuffer(oldClient); | |
| } | |
| if (oldServer) | |
| { | |
| names->sServerName = (PWSTR)SECUR32_AllocMultiByteFromWide( | |
| oldServer); | |
| package->provider->fnTableW.FreeContextBuffer(oldServer); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_CREDENTIAL_NAME: | |
| { | |
| PSecPkgContext_CredentialNameW name = | |
| (PSecPkgContext_CredentialNameW)pBuffer; | |
| PWSTR oldCred = name->sCredentialName; | |
| if (oldCred) | |
| { | |
| name->sCredentialName = | |
| (PWSTR)SECUR32_AllocMultiByteFromWide(oldCred); | |
| package->provider->fnTableW.FreeContextBuffer(oldCred); | |
| } | |
| break; | |
| } | |
| /* no thunking needed: */ | |
| case SECPKG_ATTR_ACCESS_TOKEN: | |
| case SECPKG_ATTR_DCE_INFO: | |
| case SECPKG_ATTR_FLAGS: | |
| case SECPKG_ATTR_LIFESPAN: | |
| case SECPKG_ATTR_PASSWORD_EXPIRY: | |
| case SECPKG_ATTR_SESSION_KEY: | |
| case SECPKG_ATTR_SIZES: | |
| case SECPKG_ATTR_STREAM_SIZES: | |
| case SECPKG_ATTR_TARGET_INFORMATION: | |
| break; | |
| default: | |
| WARN("attribute type %d unknown\n", ulAttribute); | |
| ret = SEC_E_INTERNAL_ERROR; | |
| } | |
| } | |
| else | |
| ret = SEC_E_INVALID_TOKEN; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_QueryContextAttributesA(PCtxtHandle phContext, | |
| ULONG ulAttribute, void *pBuffer) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %d %p\n", phContext, ulAttribute, pBuffer); | |
| if (phContext) | |
| { | |
| SecurePackage *package = (SecurePackage *)phContext->dwUpper; | |
| PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableW.QueryContextAttributesW) | |
| { | |
| ret = package->provider->fnTableW.QueryContextAttributesW( | |
| ctxt, ulAttribute, pBuffer); | |
| if (ret == SEC_E_OK) | |
| ret = thunk_ContextAttributesWToA(package, ulAttribute, | |
| pBuffer); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| static PSecPkgInfoW _copyPackageInfoFlatAToW(const SecPkgInfoA *infoA) | |
| { | |
| PSecPkgInfoW ret; | |
| if (infoA) | |
| { | |
| size_t bytesNeeded = sizeof(SecPkgInfoW); | |
| int nameLen = 0, commentLen = 0; | |
| if (infoA->Name) | |
| { | |
| nameLen = MultiByteToWideChar(CP_ACP, 0, infoA->Name, -1, | |
| NULL, 0); | |
| bytesNeeded += nameLen * sizeof(WCHAR); | |
| } | |
| if (infoA->Comment) | |
| { | |
| commentLen = MultiByteToWideChar(CP_ACP, 0, infoA->Comment, -1, | |
| NULL, 0); | |
| bytesNeeded += commentLen * sizeof(WCHAR); | |
| } | |
| ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded); | |
| if (ret) | |
| { | |
| PWSTR nextString = (PWSTR)((PBYTE)ret + sizeof(SecPkgInfoW)); | |
| memcpy(ret, infoA, sizeof(SecPkgInfoA)); | |
| if (infoA->Name) | |
| { | |
| ret->Name = nextString; | |
| MultiByteToWideChar(CP_ACP, 0, infoA->Name, -1, nextString, | |
| nameLen); | |
| nextString += nameLen; | |
| } | |
| else | |
| ret->Name = NULL; | |
| if (infoA->Comment) | |
| { | |
| ret->Comment = nextString; | |
| MultiByteToWideChar(CP_ACP, 0, infoA->Comment, -1, nextString, | |
| commentLen); | |
| } | |
| else | |
| ret->Comment = NULL; | |
| } | |
| } | |
| else | |
| ret = NULL; | |
| return ret; | |
| } | |
| static SECURITY_STATUS thunk_ContextAttributesAToW(SecurePackage *package, | |
| ULONG ulAttribute, void *pBuffer) | |
| { | |
| SECURITY_STATUS ret = SEC_E_OK; | |
| if (package && pBuffer) | |
| { | |
| switch (ulAttribute) | |
| { | |
| case SECPKG_ATTR_NAMES: | |
| { | |
| PSecPkgContext_NamesA names = (PSecPkgContext_NamesA)pBuffer; | |
| SEC_CHAR *oldUser = names->sUserName; | |
| if (oldUser) | |
| { | |
| names->sUserName = | |
| (PSTR)SECUR32_AllocWideFromMultiByte(oldUser); | |
| package->provider->fnTableW.FreeContextBuffer(oldUser); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_AUTHORITY: | |
| { | |
| PSecPkgContext_AuthorityA names = | |
| (PSecPkgContext_AuthorityA)pBuffer; | |
| SEC_CHAR *oldAuth = names->sAuthorityName; | |
| if (oldAuth) | |
| { | |
| names->sAuthorityName = | |
| (PSTR)SECUR32_AllocWideFromMultiByte(oldAuth); | |
| package->provider->fnTableW.FreeContextBuffer(oldAuth); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_KEY_INFO: | |
| { | |
| PSecPkgContext_KeyInfoA info = (PSecPkgContext_KeyInfoA)pBuffer; | |
| SEC_CHAR *oldSigAlgName = info->sSignatureAlgorithmName; | |
| SEC_CHAR *oldEncAlgName = info->sEncryptAlgorithmName; | |
| if (oldSigAlgName) | |
| { | |
| info->sSignatureAlgorithmName = | |
| (PSTR)SECUR32_AllocWideFromMultiByte(oldSigAlgName); | |
| package->provider->fnTableW.FreeContextBuffer( | |
| oldSigAlgName); | |
| } | |
| if (oldEncAlgName) | |
| { | |
| info->sEncryptAlgorithmName = | |
| (PSTR)SECUR32_AllocWideFromMultiByte( | |
| oldEncAlgName); | |
| package->provider->fnTableW.FreeContextBuffer( | |
| oldEncAlgName); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_PACKAGE_INFO: | |
| { | |
| PSecPkgContext_PackageInfoA info = | |
| (PSecPkgContext_PackageInfoA)pBuffer; | |
| PSecPkgInfoA oldPkgInfo = info->PackageInfo; | |
| if (oldPkgInfo) | |
| { | |
| info->PackageInfo = (PSecPkgInfoA) | |
| _copyPackageInfoFlatAToW(oldPkgInfo); | |
| package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_NEGOTIATION_INFO: | |
| { | |
| PSecPkgContext_NegotiationInfoA info = | |
| (PSecPkgContext_NegotiationInfoA)pBuffer; | |
| PSecPkgInfoA oldPkgInfo = info->PackageInfo; | |
| if (oldPkgInfo) | |
| { | |
| info->PackageInfo = (PSecPkgInfoA) | |
| _copyPackageInfoFlatAToW(oldPkgInfo); | |
| package->provider->fnTableW.FreeContextBuffer(oldPkgInfo); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_NATIVE_NAMES: | |
| { | |
| PSecPkgContext_NativeNamesA names = | |
| (PSecPkgContext_NativeNamesA)pBuffer; | |
| PSTR oldClient = names->sClientName; | |
| PSTR oldServer = names->sServerName; | |
| if (oldClient) | |
| { | |
| names->sClientName = (PSTR)SECUR32_AllocWideFromMultiByte( | |
| oldClient); | |
| package->provider->fnTableW.FreeContextBuffer(oldClient); | |
| } | |
| if (oldServer) | |
| { | |
| names->sServerName = (PSTR)SECUR32_AllocWideFromMultiByte( | |
| oldServer); | |
| package->provider->fnTableW.FreeContextBuffer(oldServer); | |
| } | |
| break; | |
| } | |
| case SECPKG_ATTR_CREDENTIAL_NAME: | |
| { | |
| PSecPkgContext_CredentialNameA name = | |
| (PSecPkgContext_CredentialNameA)pBuffer; | |
| PSTR oldCred = name->sCredentialName; | |
| if (oldCred) | |
| { | |
| name->sCredentialName = | |
| (PSTR)SECUR32_AllocWideFromMultiByte(oldCred); | |
| package->provider->fnTableW.FreeContextBuffer(oldCred); | |
| } | |
| break; | |
| } | |
| /* no thunking needed: */ | |
| case SECPKG_ATTR_ACCESS_TOKEN: | |
| case SECPKG_ATTR_DCE_INFO: | |
| case SECPKG_ATTR_FLAGS: | |
| case SECPKG_ATTR_LIFESPAN: | |
| case SECPKG_ATTR_PASSWORD_EXPIRY: | |
| case SECPKG_ATTR_SESSION_KEY: | |
| case SECPKG_ATTR_SIZES: | |
| case SECPKG_ATTR_STREAM_SIZES: | |
| case SECPKG_ATTR_TARGET_INFORMATION: | |
| break; | |
| default: | |
| WARN("attribute type %d unknown\n", ulAttribute); | |
| ret = SEC_E_INTERNAL_ERROR; | |
| } | |
| } | |
| else | |
| ret = SEC_E_INVALID_TOKEN; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_QueryContextAttributesW(PCtxtHandle phContext, | |
| ULONG ulAttribute, void *pBuffer) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %d %p\n", phContext, ulAttribute, pBuffer); | |
| if (phContext) | |
| { | |
| SecurePackage *package = (SecurePackage *)phContext->dwUpper; | |
| PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; | |
| if (package && package->provider) | |
| { | |
| if (package->provider->fnTableA.QueryContextAttributesA) | |
| { | |
| ret = package->provider->fnTableA.QueryContextAttributesA( | |
| ctxt, ulAttribute, pBuffer); | |
| if (ret == SEC_E_OK) | |
| ret = thunk_ContextAttributesAToW(package, ulAttribute, | |
| pBuffer); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_SetContextAttributesA(PCtxtHandle phContext, | |
| ULONG ulAttribute, void *pBuffer, ULONG cbBuffer) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %d %p %d\n", phContext, ulAttribute, pBuffer, cbBuffer); | |
| if (phContext) | |
| { | |
| SecurePackage *package = (SecurePackage *)phContext->dwUpper; | |
| PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; | |
| if (package && package->provider && pBuffer && cbBuffer) | |
| { | |
| if (package->provider->fnTableW.SetContextAttributesW) | |
| { | |
| /* TODO: gotta validate size too! */ | |
| ret = thunk_ContextAttributesWToA(package, ulAttribute, | |
| pBuffer); | |
| if (ret == SEC_E_OK) | |
| ret = package->provider->fnTableW.SetContextAttributesW( | |
| ctxt, ulAttribute, pBuffer, cbBuffer); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_SetContextAttributesW(PCtxtHandle phContext, | |
| ULONG ulAttribute, void *pBuffer, ULONG cbBuffer) | |
| { | |
| SECURITY_STATUS ret; | |
| TRACE("%p %d %p %d\n", phContext, ulAttribute, pBuffer, cbBuffer); | |
| if (phContext) | |
| { | |
| SecurePackage *package = (SecurePackage *)phContext->dwUpper; | |
| PCtxtHandle ctxt = (PCtxtHandle)phContext->dwLower; | |
| if (package && package->provider && pBuffer && cbBuffer) | |
| { | |
| if (package->provider->fnTableA.SetContextAttributesA) | |
| { | |
| /* TODO: gotta validate size too! */ | |
| ret = thunk_ContextAttributesAToW(package, ulAttribute, | |
| pBuffer); | |
| if (ret == SEC_E_OK) | |
| ret = package->provider->fnTableA.SetContextAttributesA( | |
| ctxt, ulAttribute, pBuffer, cbBuffer); | |
| } | |
| else | |
| ret = SEC_E_UNSUPPORTED_FUNCTION; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| } | |
| else | |
| ret = SEC_E_INVALID_HANDLE; | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_ImportSecurityContextA( | |
| SEC_CHAR *pszPackage, PSecBuffer pPackedContext, void *Token, | |
| PCtxtHandle phContext) | |
| { | |
| SECURITY_STATUS ret; | |
| UNICODE_STRING package; | |
| TRACE("%s %p %p %p\n", debugstr_a(pszPackage), pPackedContext, Token, | |
| phContext); | |
| RtlCreateUnicodeStringFromAsciiz(&package, pszPackage); | |
| ret = ImportSecurityContextW(package.Buffer, pPackedContext, Token, | |
| phContext); | |
| RtlFreeUnicodeString(&package); | |
| return ret; | |
| } | |
| SECURITY_STATUS SEC_ENTRY thunk_ImportSecurityContextW( | |
| SEC_WCHAR *pszPackage, PSecBuffer pPackedContext, void *Token, | |
| PCtxtHandle phContext) | |
| { | |
| SECURITY_STATUS ret; | |
| PSTR package = SECUR32_AllocMultiByteFromWide(pszPackage); | |
| TRACE("%s %p %p %p\n", debugstr_w(pszPackage), pPackedContext, Token, | |
| phContext); | |
| ret = ImportSecurityContextA(package, pPackedContext, Token, phContext); | |
| HeapFree(GetProcessHeap(), 0, package); | |
| return ret; | |
| } |