2014-08-30 21:31:32 +00:00
|
|
|
/* Copyright (C) 2004 Juan Lang
|
|
|
|
*
|
|
|
|
* This file implements loading of SSP DLLs.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2013-01-24 23:00:42 +00:00
|
|
|
#include "precomp.h"
|
2005-10-12 22:04:07 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
#include <assert.h>
|
2015-11-28 18:49:34 +00:00
|
|
|
#include <lsass/lsass.h>
|
2014-08-30 21:31:32 +00:00
|
|
|
|
|
|
|
#include <wine/debug.h>
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
|
2005-10-12 22:04:07 +00:00
|
|
|
|
2015-11-28 18:49:34 +00:00
|
|
|
#define UNLEN 256
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
typedef struct _SecurePackageTable
|
|
|
|
{
|
|
|
|
DWORD numPackages;
|
|
|
|
DWORD numAllocated;
|
|
|
|
struct list table;
|
|
|
|
} SecurePackageTable;
|
|
|
|
|
|
|
|
typedef struct _SecureProviderTable
|
|
|
|
{
|
|
|
|
DWORD numProviders;
|
|
|
|
DWORD numAllocated;
|
|
|
|
struct list table;
|
|
|
|
} SecureProviderTable;
|
|
|
|
|
2014-10-12 16:19:45 +00:00
|
|
|
static void SECUR32_initializeProviders(void);
|
[SECUR32]: As an interim step towards a proper NTLM implementation that is done by Samuel Serapion, I temporarily commit Wine's NTLM code layer around Samba's "ntlm_auth" utility. In addition I add the kerberos & negotiate stubs too.
This is not a problem on Wine, because they run on Linux distributions, most of which have Samba available. But this is not the case on Windows / ReactOS, so few adaptations were needed: in the dispatcher.c code, the fork_helper function was partially rewritten around CreateProcess to start the ntlm_auth utility (I try to use maximally the CRT to not have to rewrite other functions). This works great.
But then, to make this NTLM layer working on ReactOS, one has to find a Windows build of Samba. Here is one: http://smithii.com/samba . This is a Samba 3.0.23c build. You need to follow *exactly* the manual installation steps to make it work (actually, everything up to "Step 6" included, i.e. running smbsetup.cmd). This means in particular to copy Samba into C:\Program Files\samba, as this path is also hardcoded into the executables.
As the Wine's NTLM layer expects Samba 3.0.25+, I manually downgraded the expected version, which appears to still work nice for the needs of Office 2010 installation.
You can now play with it and try to install Office 2010.
CORE-12601 #comment Wine's NTLM layer committed in r73868 as an interim step towards a proper implementation.
CORE-12279
svn path=/trunk/; revision=73868
2017-02-20 22:28:07 +00:00
|
|
|
/* static */ void SECUR32_freeProviders(void);
|
2014-10-12 16:19:45 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
static CRITICAL_SECTION cs;
|
|
|
|
static CRITICAL_SECTION_DEBUG cs_debug =
|
|
|
|
{
|
|
|
|
0, 0, &cs,
|
|
|
|
{ &cs_debug.ProcessLocksList, &cs_debug.ProcessLocksList },
|
|
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": cs") }
|
|
|
|
};
|
|
|
|
static CRITICAL_SECTION cs = { &cs_debug, -1, 0, 0, 0, 0 };
|
|
|
|
static SecurePackageTable *packageTable = NULL;
|
|
|
|
static SecureProviderTable *providerTable = NULL;
|
2008-12-30 08:06:39 +00:00
|
|
|
|
2015-11-28 18:49:34 +00:00
|
|
|
static SecurityFunctionTableA securityFunctionTableA = {
|
2008-12-30 08:06:39 +00:00
|
|
|
SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
|
|
|
|
EnumerateSecurityPackagesA,
|
|
|
|
QueryCredentialsAttributesA,
|
|
|
|
AcquireCredentialsHandleA,
|
|
|
|
FreeCredentialsHandle,
|
|
|
|
NULL, /* Reserved2 */
|
|
|
|
InitializeSecurityContextA,
|
|
|
|
AcceptSecurityContext,
|
|
|
|
CompleteAuthToken,
|
|
|
|
DeleteSecurityContext,
|
2014-08-30 21:31:32 +00:00
|
|
|
ApplyControlToken,
|
2008-12-30 08:06:39 +00:00
|
|
|
QueryContextAttributesA,
|
|
|
|
ImpersonateSecurityContext,
|
|
|
|
RevertSecurityContext,
|
|
|
|
MakeSignature,
|
|
|
|
VerifySignature,
|
|
|
|
FreeContextBuffer,
|
|
|
|
QuerySecurityPackageInfoA,
|
|
|
|
EncryptMessage, /* Reserved3 */
|
|
|
|
DecryptMessage, /* Reserved4 */
|
|
|
|
ExportSecurityContext,
|
|
|
|
ImportSecurityContextA,
|
|
|
|
AddCredentialsA,
|
|
|
|
NULL, /* Reserved8 */
|
|
|
|
QuerySecurityContextToken,
|
|
|
|
EncryptMessage,
|
|
|
|
DecryptMessage,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2015-11-28 18:49:34 +00:00
|
|
|
static SecurityFunctionTableW securityFunctionTableW = {
|
2008-12-30 08:06:39 +00:00
|
|
|
SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
|
|
|
|
EnumerateSecurityPackagesW,
|
|
|
|
QueryCredentialsAttributesW,
|
|
|
|
AcquireCredentialsHandleW,
|
|
|
|
FreeCredentialsHandle,
|
|
|
|
NULL, /* Reserved2 */
|
|
|
|
InitializeSecurityContextW,
|
|
|
|
AcceptSecurityContext,
|
|
|
|
CompleteAuthToken,
|
|
|
|
DeleteSecurityContext,
|
2014-08-30 21:31:32 +00:00
|
|
|
ApplyControlToken,
|
2008-12-30 08:06:39 +00:00
|
|
|
QueryContextAttributesW,
|
|
|
|
ImpersonateSecurityContext,
|
|
|
|
RevertSecurityContext,
|
|
|
|
MakeSignature,
|
|
|
|
VerifySignature,
|
|
|
|
FreeContextBuffer,
|
|
|
|
QuerySecurityPackageInfoW,
|
|
|
|
EncryptMessage, /* Reserved3 */
|
|
|
|
DecryptMessage, /* Reserved4 */
|
|
|
|
ExportSecurityContext,
|
|
|
|
ImportSecurityContextW,
|
|
|
|
AddCredentialsW,
|
|
|
|
NULL, /* Reserved8 */
|
|
|
|
QuerySecurityContextToken,
|
|
|
|
EncryptMessage,
|
|
|
|
DecryptMessage,
|
|
|
|
NULL
|
|
|
|
};
|
2005-10-12 22:04:07 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
/***********************************************************************
|
2015-11-28 18:49:34 +00:00
|
|
|
* InitSecurityInterfaceA (SECUR32.@)
|
2014-08-30 21:31:32 +00:00
|
|
|
*/
|
2015-11-28 18:49:34 +00:00
|
|
|
PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
|
2005-10-12 22:04:07 +00:00
|
|
|
{
|
2015-11-28 18:49:34 +00:00
|
|
|
TRACE("InitSecurityInterfaceA() called\n");
|
|
|
|
return &securityFunctionTableA;
|
2005-10-12 22:04:07 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
/***********************************************************************
|
2015-11-28 18:49:34 +00:00
|
|
|
* InitSecurityInterfaceW (SECUR32.@)
|
2014-08-30 21:31:32 +00:00
|
|
|
*/
|
2015-11-28 18:49:34 +00:00
|
|
|
PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
|
2006-07-05 06:43:46 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
TRACE("InitSecurityInterfaceW() called\n");
|
2008-12-30 08:06:39 +00:00
|
|
|
return &securityFunctionTableW;
|
2006-07-05 06:43:46 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
static PWSTR SECUR32_strdupW(PCWSTR str)
|
2006-07-05 06:43:46 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
PWSTR ret;
|
|
|
|
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR));
|
|
|
|
if (ret)
|
|
|
|
lstrcpyW(ret, str);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
return ret;
|
2006-07-05 06:43:46 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
|
2007-07-20 13:49:41 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
PWSTR ret;
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (charsNeeded)
|
|
|
|
{
|
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded * sizeof(WCHAR));
|
|
|
|
if (ret)
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
return ret;
|
2007-07-20 13:49:41 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
|
2006-07-05 06:43:46 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
PSTR ret;
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
|
2015-11-28 18:49:34 +00:00
|
|
|
NULL, NULL);
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (charsNeeded)
|
|
|
|
{
|
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded);
|
|
|
|
if (ret)
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
|
2015-11-28 18:49:34 +00:00
|
|
|
NULL, NULL);
|
2014-08-30 21:31:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
return ret;
|
2006-07-05 06:43:46 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
|
|
|
|
const SecurityFunctionTableA *inFnTableA,
|
|
|
|
const SecurityFunctionTableW *inFnTableW)
|
2006-01-09 15:08:35 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
if (fnTableA)
|
|
|
|
{
|
|
|
|
if (inFnTableA)
|
|
|
|
{
|
|
|
|
/* The size of the version 1 table is based on platform sdk's
|
|
|
|
* sspi.h, though the sample ssp also provided with platform sdk
|
|
|
|
* implies only functions through QuerySecurityPackageInfoA are
|
|
|
|
* implemented (yikes)
|
|
|
|
*/
|
|
|
|
size_t tableSize = inFnTableA->dwVersion == 1 ?
|
|
|
|
(const BYTE *)&inFnTableA->SetContextAttributesA -
|
|
|
|
(const BYTE *)inFnTableA : sizeof(SecurityFunctionTableA);
|
|
|
|
|
|
|
|
memcpy(fnTableA, inFnTableA, tableSize);
|
|
|
|
/* override this, since we can do it internally anyway */
|
|
|
|
fnTableA->QuerySecurityPackageInfoA =
|
|
|
|
QuerySecurityPackageInfoA;
|
|
|
|
}
|
|
|
|
else if (inFnTableW)
|
|
|
|
{
|
|
|
|
/* functions with thunks */
|
|
|
|
if (inFnTableW->AcquireCredentialsHandleW)
|
|
|
|
fnTableA->AcquireCredentialsHandleA =
|
|
|
|
thunk_AcquireCredentialsHandleA;
|
|
|
|
if (inFnTableW->InitializeSecurityContextW)
|
|
|
|
fnTableA->InitializeSecurityContextA =
|
|
|
|
thunk_InitializeSecurityContextA;
|
|
|
|
if (inFnTableW->ImportSecurityContextW)
|
|
|
|
fnTableA->ImportSecurityContextA =
|
|
|
|
thunk_ImportSecurityContextA;
|
|
|
|
if (inFnTableW->AddCredentialsW)
|
|
|
|
fnTableA->AddCredentialsA =
|
|
|
|
thunk_AddCredentialsA;
|
|
|
|
if (inFnTableW->QueryCredentialsAttributesW)
|
|
|
|
fnTableA->QueryCredentialsAttributesA =
|
|
|
|
thunk_QueryCredentialsAttributesA;
|
|
|
|
if (inFnTableW->QueryContextAttributesW)
|
|
|
|
fnTableA->QueryContextAttributesA =
|
|
|
|
thunk_QueryContextAttributesA;
|
|
|
|
if (inFnTableW->SetContextAttributesW)
|
|
|
|
fnTableA->SetContextAttributesA =
|
|
|
|
thunk_SetContextAttributesA;
|
|
|
|
/* this can't be thunked, there's no extra param to know which
|
|
|
|
* package to forward to */
|
|
|
|
fnTableA->EnumerateSecurityPackagesA = NULL;
|
|
|
|
/* functions with no thunks needed */
|
|
|
|
fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
|
|
|
|
fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
|
|
|
|
fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
|
|
|
|
fnTableA->ImpersonateSecurityContext =
|
|
|
|
inFnTableW->ImpersonateSecurityContext;
|
|
|
|
fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
|
|
|
|
fnTableA->MakeSignature = inFnTableW->MakeSignature;
|
|
|
|
fnTableA->VerifySignature = inFnTableW->VerifySignature;
|
|
|
|
fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
|
|
|
|
fnTableA->QuerySecurityPackageInfoA =
|
|
|
|
QuerySecurityPackageInfoA;
|
|
|
|
fnTableA->ExportSecurityContext =
|
|
|
|
inFnTableW->ExportSecurityContext;
|
|
|
|
fnTableA->QuerySecurityContextToken =
|
|
|
|
inFnTableW->QuerySecurityContextToken;
|
|
|
|
fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
|
|
|
|
fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
|
|
|
|
}
|
|
|
|
}
|
2006-01-09 15:08:35 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
|
|
|
|
const SecurityFunctionTableA *inFnTableA,
|
|
|
|
const SecurityFunctionTableW *inFnTableW)
|
2006-07-05 06:43:46 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
if (fnTableW)
|
|
|
|
{
|
|
|
|
if (inFnTableW)
|
|
|
|
{
|
|
|
|
/* The size of the version 1 table is based on platform sdk's
|
|
|
|
* sspi.h, though the sample ssp also provided with platform sdk
|
|
|
|
* implies only functions through QuerySecurityPackageInfoA are
|
|
|
|
* implemented (yikes)
|
|
|
|
*/
|
|
|
|
size_t tableSize = inFnTableW->dwVersion == 1 ?
|
|
|
|
(const BYTE *)&inFnTableW->SetContextAttributesW -
|
|
|
|
(const BYTE *)inFnTableW : sizeof(SecurityFunctionTableW);
|
|
|
|
|
|
|
|
memcpy(fnTableW, inFnTableW, tableSize);
|
|
|
|
/* override this, since we can do it internally anyway */
|
|
|
|
fnTableW->QuerySecurityPackageInfoW =
|
|
|
|
QuerySecurityPackageInfoW;
|
|
|
|
}
|
|
|
|
else if (inFnTableA)
|
|
|
|
{
|
|
|
|
/* functions with thunks */
|
|
|
|
if (inFnTableA->AcquireCredentialsHandleA)
|
|
|
|
fnTableW->AcquireCredentialsHandleW =
|
|
|
|
thunk_AcquireCredentialsHandleW;
|
|
|
|
if (inFnTableA->InitializeSecurityContextA)
|
|
|
|
fnTableW->InitializeSecurityContextW =
|
|
|
|
thunk_InitializeSecurityContextW;
|
|
|
|
if (inFnTableA->ImportSecurityContextA)
|
|
|
|
fnTableW->ImportSecurityContextW =
|
|
|
|
thunk_ImportSecurityContextW;
|
|
|
|
if (inFnTableA->AddCredentialsA)
|
|
|
|
fnTableW->AddCredentialsW =
|
|
|
|
thunk_AddCredentialsW;
|
|
|
|
if (inFnTableA->QueryCredentialsAttributesA)
|
|
|
|
fnTableW->QueryCredentialsAttributesW =
|
|
|
|
thunk_QueryCredentialsAttributesW;
|
|
|
|
if (inFnTableA->QueryContextAttributesA)
|
|
|
|
fnTableW->QueryContextAttributesW =
|
|
|
|
thunk_QueryContextAttributesW;
|
|
|
|
if (inFnTableA->SetContextAttributesA)
|
|
|
|
fnTableW->SetContextAttributesW =
|
|
|
|
thunk_SetContextAttributesW;
|
|
|
|
/* this can't be thunked, there's no extra param to know which
|
|
|
|
* package to forward to */
|
|
|
|
fnTableW->EnumerateSecurityPackagesW = NULL;
|
|
|
|
/* functions with no thunks needed */
|
|
|
|
fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
|
|
|
|
fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
|
|
|
|
fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
|
|
|
|
fnTableW->ImpersonateSecurityContext =
|
|
|
|
inFnTableA->ImpersonateSecurityContext;
|
|
|
|
fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
|
|
|
|
fnTableW->MakeSignature = inFnTableA->MakeSignature;
|
|
|
|
fnTableW->VerifySignature = inFnTableA->VerifySignature;
|
|
|
|
fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
|
|
|
|
fnTableW->QuerySecurityPackageInfoW =
|
|
|
|
QuerySecurityPackageInfoW;
|
|
|
|
fnTableW->ExportSecurityContext =
|
|
|
|
inFnTableA->ExportSecurityContext;
|
|
|
|
fnTableW->QuerySecurityContextToken =
|
|
|
|
inFnTableA->QuerySecurityContextToken;
|
|
|
|
fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
|
|
|
|
fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
|
|
|
|
}
|
|
|
|
}
|
2006-07-05 06:43:46 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
|
|
|
|
const SecPkgInfoW *inInfoW)
|
2007-11-23 09:10:32 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
if (info && (inInfoA || inInfoW))
|
|
|
|
{
|
|
|
|
/* odd, I know, but up until Name and Comment the structures are
|
|
|
|
* identical
|
|
|
|
*/
|
|
|
|
memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
|
|
|
|
if (inInfoW)
|
|
|
|
{
|
|
|
|
info->Name = SECUR32_strdupW(inInfoW->Name);
|
|
|
|
info->Comment = SECUR32_strdupW(inInfoW->Comment);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
|
|
|
|
info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
|
|
|
|
}
|
|
|
|
}
|
2007-11-23 09:10:32 +00:00
|
|
|
}
|
2006-07-05 06:43:46 +00:00
|
|
|
|
[SECUR32]: As an interim step towards a proper NTLM implementation that is done by Samuel Serapion, I temporarily commit Wine's NTLM code layer around Samba's "ntlm_auth" utility. In addition I add the kerberos & negotiate stubs too.
This is not a problem on Wine, because they run on Linux distributions, most of which have Samba available. But this is not the case on Windows / ReactOS, so few adaptations were needed: in the dispatcher.c code, the fork_helper function was partially rewritten around CreateProcess to start the ntlm_auth utility (I try to use maximally the CRT to not have to rewrite other functions). This works great.
But then, to make this NTLM layer working on ReactOS, one has to find a Windows build of Samba. Here is one: http://smithii.com/samba . This is a Samba 3.0.23c build. You need to follow *exactly* the manual installation steps to make it work (actually, everything up to "Step 6" included, i.e. running smbsetup.cmd). This means in particular to copy Samba into C:\Program Files\samba, as this path is also hardcoded into the executables.
As the Wine's NTLM layer expects Samba 3.0.25+, I manually downgraded the expected version, which appears to still work nice for the needs of Office 2010 installation.
You can now play with it and try to install Office 2010.
CORE-12601 #comment Wine's NTLM layer committed in r73868 as an interim step towards a proper implementation.
CORE-12279
svn path=/trunk/; revision=73868
2017-02-20 22:28:07 +00:00
|
|
|
// static
|
2014-08-30 21:31:32 +00:00
|
|
|
SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
|
|
|
|
const SecurityFunctionTableW *fnTableW, PCWSTR moduleName)
|
2006-01-09 15:08:35 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
SecureProvider *ret;
|
2007-07-20 13:49:41 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
EnterCriticalSection(&cs);
|
2007-07-20 13:49:41 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (!providerTable)
|
|
|
|
{
|
|
|
|
providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
|
|
|
|
if (!providerTable)
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-07-20 13:49:41 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
list_init(&providerTable->table);
|
|
|
|
}
|
2007-07-20 13:49:41 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
|
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-05-31 12:49:25 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
list_add_tail(&providerTable->table, &ret->entry);
|
|
|
|
ret->lib = NULL;
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (fnTableA || fnTableW)
|
|
|
|
{
|
|
|
|
ret->moduleName = moduleName ? SECUR32_strdupW(moduleName) : NULL;
|
|
|
|
_makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
|
|
|
|
_makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
|
|
|
|
ret->loaded = !moduleName;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret->moduleName = SECUR32_strdupW(moduleName);
|
|
|
|
ret->loaded = FALSE;
|
|
|
|
}
|
2015-11-28 18:49:34 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
return ret;
|
2008-05-31 12:49:25 +00:00
|
|
|
}
|
|
|
|
|
[SECUR32]: As an interim step towards a proper NTLM implementation that is done by Samuel Serapion, I temporarily commit Wine's NTLM code layer around Samba's "ntlm_auth" utility. In addition I add the kerberos & negotiate stubs too.
This is not a problem on Wine, because they run on Linux distributions, most of which have Samba available. But this is not the case on Windows / ReactOS, so few adaptations were needed: in the dispatcher.c code, the fork_helper function was partially rewritten around CreateProcess to start the ntlm_auth utility (I try to use maximally the CRT to not have to rewrite other functions). This works great.
But then, to make this NTLM layer working on ReactOS, one has to find a Windows build of Samba. Here is one: http://smithii.com/samba . This is a Samba 3.0.23c build. You need to follow *exactly* the manual installation steps to make it work (actually, everything up to "Step 6" included, i.e. running smbsetup.cmd). This means in particular to copy Samba into C:\Program Files\samba, as this path is also hardcoded into the executables.
As the Wine's NTLM layer expects Samba 3.0.25+, I manually downgraded the expected version, which appears to still work nice for the needs of Office 2010 installation.
You can now play with it and try to install Office 2010.
CORE-12601 #comment Wine's NTLM layer committed in r73868 as an interim step towards a proper implementation.
CORE-12279
svn path=/trunk/; revision=73868
2017-02-20 22:28:07 +00:00
|
|
|
// static
|
2014-08-30 21:31:32 +00:00
|
|
|
void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
|
|
|
|
const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
|
2008-05-31 12:49:25 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
ULONG i;
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
assert(provider);
|
|
|
|
assert(infoA || infoW);
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
EnterCriticalSection(&cs);
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (!packageTable)
|
|
|
|
{
|
|
|
|
packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
|
|
|
|
if (!packageTable)
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
return;
|
|
|
|
}
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
packageTable->numPackages = 0;
|
|
|
|
list_init(&packageTable->table);
|
|
|
|
}
|
2015-11-28 18:49:34 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
for (i = 0; i < toAdd; i++)
|
|
|
|
{
|
|
|
|
SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
|
|
|
|
if (!package)
|
|
|
|
continue;
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
list_add_tail(&packageTable->table, &package->entry);
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
package->provider = provider;
|
|
|
|
_copyPackageInfo(&package->infoW,
|
|
|
|
infoA ? &infoA[i] : NULL,
|
|
|
|
infoW ? &infoW[i] : NULL);
|
|
|
|
}
|
|
|
|
packageTable->numPackages += toAdd;
|
|
|
|
|
|
|
|
LeaveCriticalSection(&cs);
|
2008-11-27 08:40:47 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
static void _tryLoadProvider(PWSTR moduleName)
|
2008-11-27 08:40:47 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
HMODULE lib = LoadLibraryW(moduleName);
|
|
|
|
|
|
|
|
if (lib)
|
|
|
|
{
|
|
|
|
INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
|
|
|
|
(INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIW);
|
|
|
|
INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
|
|
|
|
(INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIA);
|
|
|
|
|
2015-11-28 18:49:34 +00:00
|
|
|
TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
|
|
|
|
debugstr_w(moduleName), pInitSecurityInterfaceA,
|
2014-08-30 21:31:32 +00:00
|
|
|
pInitSecurityInterfaceW);
|
|
|
|
if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
|
|
|
|
{
|
|
|
|
PSecurityFunctionTableA fnTableA = NULL;
|
|
|
|
PSecurityFunctionTableW fnTableW = NULL;
|
|
|
|
ULONG toAdd = 0;
|
|
|
|
PSecPkgInfoA infoA = NULL;
|
|
|
|
PSecPkgInfoW infoW = NULL;
|
|
|
|
SECURITY_STATUS ret = SEC_E_OK;
|
|
|
|
|
|
|
|
if (pInitSecurityInterfaceA)
|
|
|
|
fnTableA = pInitSecurityInterfaceA();
|
|
|
|
if (pInitSecurityInterfaceW)
|
|
|
|
fnTableW = pInitSecurityInterfaceW();
|
|
|
|
if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
|
|
|
|
{
|
|
|
|
if (fnTableW != &securityFunctionTableW)
|
|
|
|
ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
|
|
|
|
else
|
2015-11-28 18:49:34 +00:00
|
|
|
TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
|
2014-08-30 21:31:32 +00:00
|
|
|
}
|
|
|
|
else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
|
|
|
|
{
|
|
|
|
if (fnTableA != &securityFunctionTableA)
|
|
|
|
ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
|
|
|
|
else
|
2015-11-28 18:49:34 +00:00
|
|
|
TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
|
2014-08-30 21:31:32 +00:00
|
|
|
}
|
|
|
|
if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
|
|
|
|
{
|
|
|
|
SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
|
|
|
|
moduleName);
|
|
|
|
|
|
|
|
if (provider)
|
|
|
|
SECUR32_addPackages(provider, toAdd, infoA, infoW);
|
|
|
|
if (infoW)
|
|
|
|
fnTableW->FreeContextBuffer(infoW);
|
|
|
|
else
|
|
|
|
fnTableA->FreeContextBuffer(infoA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FreeLibrary(lib);
|
|
|
|
}
|
|
|
|
else
|
2015-11-28 18:49:34 +00:00
|
|
|
WARN("failed to load %s\n", debugstr_w(moduleName));
|
2008-11-27 08:40:47 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
static const WCHAR securityProvidersKeyW[] = {
|
|
|
|
'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
|
|
|
|
'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
|
|
|
|
'i','t','y','P','r','o','v','i','d','e','r','s','\0'
|
|
|
|
};
|
|
|
|
static const WCHAR securityProvidersW[] = {
|
|
|
|
'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
|
|
|
|
};
|
|
|
|
|
|
|
|
static void SECUR32_initializeProviders(void)
|
2008-11-27 08:40:47 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
HKEY key;
|
|
|
|
LSTATUS apiRet;
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
/* Now load providers from registry */
|
|
|
|
apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
|
|
|
|
KEY_READ, &key);
|
|
|
|
if (apiRet == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
|
2016-10-09 20:58:08 +00:00
|
|
|
DWORD size = sizeof(securityPkgNames), type;
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
|
|
|
|
(PBYTE)securityPkgNames, &size);
|
|
|
|
if (apiRet == ERROR_SUCCESS && type == REG_SZ)
|
|
|
|
{
|
|
|
|
WCHAR *ptr;
|
|
|
|
|
|
|
|
size = size / sizeof(WCHAR);
|
|
|
|
for (ptr = securityPkgNames;
|
|
|
|
ptr < securityPkgNames + size; )
|
|
|
|
{
|
|
|
|
WCHAR *comma;
|
|
|
|
|
|
|
|
for (comma = ptr; *comma && *comma != ','; comma++)
|
|
|
|
;
|
|
|
|
if (*comma == ',')
|
|
|
|
*comma = '\0';
|
|
|
|
for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
|
|
|
|
ptr++)
|
|
|
|
;
|
|
|
|
if (*ptr)
|
|
|
|
_tryLoadProvider(ptr);
|
|
|
|
ptr += lstrlenW(ptr) + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey(key);
|
|
|
|
}
|
[SECUR32]: As an interim step towards a proper NTLM implementation that is done by Samuel Serapion, I temporarily commit Wine's NTLM code layer around Samba's "ntlm_auth" utility. In addition I add the kerberos & negotiate stubs too.
This is not a problem on Wine, because they run on Linux distributions, most of which have Samba available. But this is not the case on Windows / ReactOS, so few adaptations were needed: in the dispatcher.c code, the fork_helper function was partially rewritten around CreateProcess to start the ntlm_auth utility (I try to use maximally the CRT to not have to rewrite other functions). This works great.
But then, to make this NTLM layer working on ReactOS, one has to find a Windows build of Samba. Here is one: http://smithii.com/samba . This is a Samba 3.0.23c build. You need to follow *exactly* the manual installation steps to make it work (actually, everything up to "Step 6" included, i.e. running smbsetup.cmd). This means in particular to copy Samba into C:\Program Files\samba, as this path is also hardcoded into the executables.
As the Wine's NTLM layer expects Samba 3.0.25+, I manually downgraded the expected version, which appears to still work nice for the needs of Office 2010 installation.
You can now play with it and try to install Office 2010.
CORE-12601 #comment Wine's NTLM layer committed in r73868 as an interim step towards a proper implementation.
CORE-12279
svn path=/trunk/; revision=73868
2017-02-20 22:28:07 +00:00
|
|
|
|
|
|
|
/* Now load the built-in providers (in Wine, this is done before the registry loading) */
|
|
|
|
#ifdef __REACTOS__
|
|
|
|
/// FIXME: Interim Wine code until we get Samuel's rewrite!
|
|
|
|
/* First load built-in providers */
|
|
|
|
SECUR32_initNTLMSP();
|
|
|
|
SECUR32_initKerberosSP();
|
|
|
|
/* Load the Negotiate provider last so apps stumble over the working NTLM
|
|
|
|
* provider first. Attempting to fix bug #16905 while keeping the
|
|
|
|
* application reported on wine-users on 2006-09-12 working. */
|
|
|
|
SECUR32_initNegotiateSP();
|
|
|
|
#endif
|
|
|
|
|
2008-11-27 08:40:47 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
|
2008-11-27 08:40:47 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
SecurePackage *ret = NULL;
|
|
|
|
BOOL matched = FALSE;
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-10-12 16:19:45 +00:00
|
|
|
#ifdef __REACTOS__
|
2014-08-30 21:31:32 +00:00
|
|
|
if (!packageTable)
|
|
|
|
SECUR32_initializeProviders();
|
2014-10-12 16:19:45 +00:00
|
|
|
#endif
|
2008-12-31 08:11:43 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (packageTable && packageName)
|
|
|
|
{
|
|
|
|
LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
|
|
|
|
{
|
|
|
|
matched = !lstrcmpiW(ret->infoW.Name, packageName);
|
2015-11-28 18:49:34 +00:00
|
|
|
if (matched)
|
|
|
|
break;
|
2014-08-30 21:31:32 +00:00
|
|
|
}
|
2015-11-28 18:49:34 +00:00
|
|
|
|
|
|
|
if (!matched)
|
|
|
|
return NULL;
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2015-11-28 18:49:34 +00:00
|
|
|
if (ret->provider && !ret->provider->loaded)
|
2014-08-30 21:31:32 +00:00
|
|
|
{
|
|
|
|
ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
|
|
|
|
if (ret->provider->lib)
|
|
|
|
{
|
|
|
|
INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
|
2015-11-28 18:49:34 +00:00
|
|
|
(INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIW);
|
2014-08-30 21:31:32 +00:00
|
|
|
INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
|
2015-11-28 18:49:34 +00:00
|
|
|
(INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIA);
|
2014-08-30 21:31:32 +00:00
|
|
|
PSecurityFunctionTableA fnTableA = NULL;
|
|
|
|
PSecurityFunctionTableW fnTableW = NULL;
|
|
|
|
|
|
|
|
if (pInitSecurityInterfaceA)
|
|
|
|
fnTableA = pInitSecurityInterfaceA();
|
|
|
|
if (pInitSecurityInterfaceW)
|
|
|
|
fnTableW = pInitSecurityInterfaceW();
|
|
|
|
/* don't update built-in SecurityFunctionTable */
|
|
|
|
if (fnTableA != &securityFunctionTableA)
|
|
|
|
_makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
|
|
|
|
if (fnTableW != &securityFunctionTableW)
|
|
|
|
_makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
|
|
|
|
ret->provider->loaded = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
2008-11-27 08:40:47 +00:00
|
|
|
}
|
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
SecurePackage *SECUR32_findPackageA(PCSTR packageName)
|
2008-11-27 08:40:47 +00:00
|
|
|
{
|
2014-08-30 21:31:32 +00:00
|
|
|
SecurePackage *ret;
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
if (packageName)
|
|
|
|
{
|
|
|
|
UNICODE_STRING package;
|
2008-11-27 08:40:47 +00:00
|
|
|
|
2014-08-30 21:31:32 +00:00
|
|
|
RtlCreateUnicodeStringFromAsciiz(&package, packageName);
|
|
|
|
ret = SECUR32_findPackageW(package.Buffer);
|
|
|
|
RtlFreeUnicodeString(&package);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
return ret;
|
2008-11-27 08:40:47 +00:00
|
|
|
}
|
2015-11-28 18:49:34 +00:00
|
|
|
|
[SECUR32]: As an interim step towards a proper NTLM implementation that is done by Samuel Serapion, I temporarily commit Wine's NTLM code layer around Samba's "ntlm_auth" utility. In addition I add the kerberos & negotiate stubs too.
This is not a problem on Wine, because they run on Linux distributions, most of which have Samba available. But this is not the case on Windows / ReactOS, so few adaptations were needed: in the dispatcher.c code, the fork_helper function was partially rewritten around CreateProcess to start the ntlm_auth utility (I try to use maximally the CRT to not have to rewrite other functions). This works great.
But then, to make this NTLM layer working on ReactOS, one has to find a Windows build of Samba. Here is one: http://smithii.com/samba . This is a Samba 3.0.23c build. You need to follow *exactly* the manual installation steps to make it work (actually, everything up to "Step 6" included, i.e. running smbsetup.cmd). This means in particular to copy Samba into C:\Program Files\samba, as this path is also hardcoded into the executables.
As the Wine's NTLM layer expects Samba 3.0.25+, I manually downgraded the expected version, which appears to still work nice for the needs of Office 2010 installation.
You can now play with it and try to install Office 2010.
CORE-12601 #comment Wine's NTLM layer committed in r73868 as an interim step towards a proper implementation.
CORE-12279
svn path=/trunk/; revision=73868
2017-02-20 22:28:07 +00:00
|
|
|
/* static */ void SECUR32_freeProviders(void)
|
|
|
|
{
|
|
|
|
TRACE("\n");
|
|
|
|
EnterCriticalSection(&cs);
|
|
|
|
|
|
|
|
#ifndef __REACTOS__
|
|
|
|
SECUR32_deinitSchannelSP();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (packageTable)
|
|
|
|
{
|
|
|
|
SecurePackage *package, *package_next;
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(package, package_next, &packageTable->table,
|
|
|
|
SecurePackage, entry)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, package->infoW.Name);
|
|
|
|
HeapFree(GetProcessHeap(), 0, package->infoW.Comment);
|
|
|
|
HeapFree(GetProcessHeap(), 0, package);
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, packageTable);
|
|
|
|
packageTable = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (providerTable)
|
|
|
|
{
|
|
|
|
SecureProvider *provider, *provider_next;
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(provider, provider_next, &providerTable->table,
|
|
|
|
SecureProvider, entry)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, provider->moduleName);
|
|
|
|
if (provider->lib)
|
|
|
|
FreeLibrary(provider->lib);
|
|
|
|
HeapFree(GetProcessHeap(), 0, provider);
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, providerTable);
|
|
|
|
providerTable = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
DeleteCriticalSection(&cs);
|
|
|
|
}
|
|
|
|
|
2015-11-28 18:49:34 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* FreeContextBuffer (SECUR32.@)
|
|
|
|
*
|
|
|
|
* Doh--if pv was allocated by a crypto package, this may not be correct.
|
|
|
|
* The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
|
|
|
|
* be any guarantee, nor is there an alloc function in secur32.
|
|
|
|
*/
|
|
|
|
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, pv);
|
|
|
|
|
|
|
|
return SEC_E_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* EnumerateSecurityPackagesW (SECUR32.@)
|
|
|
|
*/
|
|
|
|
SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
|
|
|
|
PSecPkgInfoW *ppPackageInfo)
|
|
|
|
{
|
|
|
|
SECURITY_STATUS ret = SEC_E_OK;
|
|
|
|
|
|
|
|
TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
|
|
|
|
|
|
|
|
#ifdef __REACTOS__
|
|
|
|
if (!packageTable)
|
|
|
|
SECUR32_initializeProviders();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
|
|
|
|
*pcPackages = 0;
|
|
|
|
EnterCriticalSection(&cs);
|
|
|
|
if (packageTable)
|
|
|
|
{
|
|
|
|
SecurePackage *package;
|
|
|
|
size_t bytesNeeded;
|
|
|
|
|
|
|
|
bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
|
|
|
|
LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
|
|
|
|
{
|
|
|
|
if (package->infoW.Name)
|
|
|
|
bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
|
|
|
|
if (package->infoW.Comment)
|
|
|
|
bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
if (bytesNeeded)
|
|
|
|
{
|
|
|
|
*ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
|
|
|
|
if (*ppPackageInfo)
|
|
|
|
{
|
|
|
|
ULONG i = 0;
|
|
|
|
PWSTR nextString;
|
|
|
|
|
|
|
|
*pcPackages = packageTable->numPackages;
|
|
|
|
nextString = (PWSTR)((PBYTE)*ppPackageInfo +
|
|
|
|
packageTable->numPackages * sizeof(SecPkgInfoW));
|
|
|
|
LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
|
|
|
|
{
|
|
|
|
PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
|
|
|
|
|
|
|
|
*pkgInfo = package->infoW;
|
|
|
|
if (package->infoW.Name)
|
|
|
|
{
|
|
|
|
TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
|
|
|
|
pkgInfo->Name = nextString;
|
|
|
|
lstrcpyW(nextString, package->infoW.Name);
|
|
|
|
nextString += lstrlenW(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Name = NULL;
|
|
|
|
if (package->infoW.Comment)
|
|
|
|
{
|
|
|
|
TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
|
|
|
|
pkgInfo->Comment = nextString;
|
|
|
|
lstrcpyW(nextString, package->infoW.Comment);
|
|
|
|
nextString += lstrlenW(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Comment = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = SEC_E_INSUFFICIENT_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
TRACE("<-- 0x%08x\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
|
|
|
|
* structures) into an array of SecPkgInfoA structures, which it returns.
|
|
|
|
*/
|
|
|
|
static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
|
|
|
|
const SecPkgInfoW *info)
|
|
|
|
{
|
|
|
|
PSecPkgInfoA ret;
|
|
|
|
|
|
|
|
if (info)
|
|
|
|
{
|
|
|
|
size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
|
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for (i = 0; i < cPackages; i++)
|
|
|
|
{
|
|
|
|
if (info[i].Name)
|
|
|
|
bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
|
|
|
|
-1, NULL, 0, NULL, NULL);
|
|
|
|
if (info[i].Comment)
|
|
|
|
bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
|
|
|
|
-1, NULL, 0, NULL, NULL);
|
|
|
|
}
|
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
PSTR nextString;
|
|
|
|
|
|
|
|
nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
|
|
|
|
for (i = 0; i < cPackages; i++)
|
|
|
|
{
|
|
|
|
PSecPkgInfoA pkgInfo = ret + i;
|
|
|
|
int bytes;
|
|
|
|
|
|
|
|
memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
|
|
|
|
if (info[i].Name)
|
|
|
|
{
|
|
|
|
pkgInfo->Name = nextString;
|
|
|
|
/* just repeat back to WideCharToMultiByte how many bytes
|
|
|
|
* it requires, since we asked it earlier
|
|
|
|
*/
|
|
|
|
bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
|
|
|
|
pkgInfo->Name, bytes, NULL, NULL);
|
|
|
|
nextString += lstrlenA(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Name = NULL;
|
|
|
|
if (info[i].Comment)
|
|
|
|
{
|
|
|
|
pkgInfo->Comment = nextString;
|
|
|
|
/* just repeat back to WideCharToMultiByte how many bytes
|
|
|
|
* it requires, since we asked it earlier
|
|
|
|
*/
|
|
|
|
bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
|
|
|
|
pkgInfo->Comment, bytes, NULL, NULL);
|
|
|
|
nextString += lstrlenA(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Comment = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* EnumerateSecurityPackagesA (SECUR32.@)
|
|
|
|
*/
|
|
|
|
SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
|
|
|
|
PSecPkgInfoA *ppPackageInfo)
|
|
|
|
{
|
|
|
|
SECURITY_STATUS ret;
|
|
|
|
PSecPkgInfoW info;
|
|
|
|
|
|
|
|
ret = EnumerateSecurityPackagesW(pcPackages, &info);
|
|
|
|
if (ret == SEC_E_OK && *pcPackages && info)
|
|
|
|
{
|
|
|
|
*ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
|
|
|
|
if (*pcPackages && !*ppPackageInfo)
|
|
|
|
{
|
|
|
|
*pcPackages = 0;
|
|
|
|
ret = SEC_E_INSUFFICIENT_MEMORY;
|
|
|
|
}
|
|
|
|
FreeContextBuffer(info);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetComputerObjectNameA (SECUR32.@)
|
|
|
|
*
|
|
|
|
* Get the local computer's name using the format specified.
|
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* NameFormat [I] The format for the name.
|
|
|
|
* lpNameBuffer [O] Pointer to buffer to receive the name.
|
|
|
|
* nSize [I/O] Size in characters of buffer.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* TRUE If the name was written to lpNameBuffer.
|
|
|
|
* FALSE If the name couldn't be written.
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
* If lpNameBuffer is NULL, then the size of the buffer needed to hold the
|
|
|
|
* name will be returned in *nSize.
|
|
|
|
*
|
|
|
|
* nSize returns the number of characters written when lpNameBuffer is not
|
|
|
|
* NULL or the size of the buffer needed to hold the name when the buffer
|
|
|
|
* is too short or lpNameBuffer is NULL.
|
|
|
|
*
|
|
|
|
* It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
|
|
|
|
*/
|
|
|
|
BOOLEAN WINAPI GetComputerObjectNameA(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
|
|
|
BOOLEAN rc;
|
|
|
|
LPWSTR bufferW = NULL;
|
|
|
|
ULONG sizeW = *nSize;
|
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
|
|
|
if (lpNameBuffer) {
|
|
|
|
bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
|
|
|
|
if (bufferW == NULL) {
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
|
|
|
|
if (rc && bufferW) {
|
|
|
|
ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
|
|
|
|
*nSize = len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*nSize = sizeW;
|
|
|
|
HeapFree(GetProcessHeap(), 0, bufferW);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetComputerObjectNameW (SECUR32.@)
|
|
|
|
*/
|
|
|
|
BOOLEAN WINAPI GetComputerObjectNameW(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
|
|
|
LSA_HANDLE policyHandle;
|
|
|
|
LSA_OBJECT_ATTRIBUTES objectAttributes;
|
|
|
|
PPOLICY_DNS_DOMAIN_INFO domainInfo;
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
BOOLEAN status;
|
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
|
|
|
|
|
|
|
if (NameFormat == NameUnknown)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZeroMemory(&objectAttributes, sizeof(objectAttributes));
|
|
|
|
objectAttributes.Length = sizeof(objectAttributes);
|
|
|
|
|
|
|
|
ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
|
|
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
|
|
&policyHandle);
|
|
|
|
if (ntStatus != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
SetLastError(LsaNtStatusToWinError(ntStatus));
|
|
|
|
WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ntStatus = LsaQueryInformationPolicy(policyHandle,
|
|
|
|
PolicyDnsDomainInformation,
|
|
|
|
(PVOID *)&domainInfo);
|
|
|
|
if (ntStatus != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
SetLastError(LsaNtStatusToWinError(ntStatus));
|
|
|
|
WARN("LsaQueryInformationPolicy failed with NT status %u\n",
|
|
|
|
GetLastError());
|
|
|
|
LsaClose(policyHandle);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (domainInfo->Sid)
|
|
|
|
{
|
|
|
|
switch (NameFormat)
|
|
|
|
{
|
|
|
|
case NameSamCompatible:
|
|
|
|
{
|
|
|
|
WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
|
|
|
|
DWORD size = sizeof(name)/sizeof(name[0]);
|
|
|
|
if (GetComputerNameW(name, &size))
|
|
|
|
{
|
|
|
|
DWORD len = domainInfo->Name.Length + size + 3;
|
|
|
|
if (lpNameBuffer)
|
|
|
|
{
|
|
|
|
if (*nSize < len)
|
|
|
|
{
|
|
|
|
*nSize = len;
|
|
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WCHAR bs[] = { '\\', 0 };
|
|
|
|
WCHAR ds[] = { '$', 0 };
|
|
|
|
lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
|
|
|
|
lstrcatW(lpNameBuffer, bs);
|
|
|
|
lstrcatW(lpNameBuffer, name);
|
|
|
|
lstrcatW(lpNameBuffer, ds);
|
|
|
|
status = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* just requesting length required */
|
|
|
|
{
|
|
|
|
*nSize = len;
|
|
|
|
status = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INTERNAL_ERROR);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NameFullyQualifiedDN:
|
|
|
|
case NameDisplay:
|
|
|
|
case NameUniqueId:
|
|
|
|
case NameCanonical:
|
|
|
|
case NameUserPrincipal:
|
|
|
|
case NameCanonicalEx:
|
|
|
|
case NameServicePrincipal:
|
|
|
|
case NameDnsDomain:
|
|
|
|
FIXME("NameFormat %d not implemented\n", NameFormat);
|
|
|
|
SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
|
|
|
|
status = FALSE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
LsaFreeMemory(domainInfo);
|
|
|
|
LsaClose(policyHandle);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetUserNameExA (SECUR32.@)
|
|
|
|
*/
|
|
|
|
BOOLEAN WINAPI GetUserNameExA(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
|
|
|
BOOLEAN rc;
|
|
|
|
LPWSTR bufferW = NULL;
|
|
|
|
ULONG sizeW = *nSize;
|
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
|
|
|
if (lpNameBuffer) {
|
|
|
|
bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
|
|
|
|
if (bufferW == NULL) {
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = GetUserNameExW(NameFormat, bufferW, &sizeW);
|
|
|
|
if (rc) {
|
|
|
|
ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
|
|
|
|
if (len <= *nSize)
|
|
|
|
{
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
|
|
|
|
*nSize = len - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*nSize = len;
|
|
|
|
rc = FALSE;
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*nSize = sizeW;
|
|
|
|
HeapFree(GetProcessHeap(), 0, bufferW);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN WINAPI GetUserNameExW(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
|
|
|
|
|
|
|
switch (NameFormat)
|
|
|
|
{
|
|
|
|
case NameSamCompatible:
|
|
|
|
{
|
|
|
|
WCHAR samname[UNLEN + 1 + MAX_COMPUTERNAME_LENGTH + 1];
|
|
|
|
LPWSTR out;
|
|
|
|
DWORD len;
|
|
|
|
|
|
|
|
/* This assumes the current user is always a local account */
|
|
|
|
len = MAX_COMPUTERNAME_LENGTH + 1;
|
|
|
|
if (GetComputerNameW(samname, &len))
|
|
|
|
{
|
|
|
|
out = samname + lstrlenW(samname);
|
|
|
|
*out++ = '\\';
|
|
|
|
len = UNLEN + 1;
|
|
|
|
if (GetUserNameW(out, &len))
|
|
|
|
{
|
|
|
|
if (lstrlenW(samname) < *nSize)
|
|
|
|
{
|
|
|
|
lstrcpyW(lpNameBuffer, samname);
|
|
|
|
*nSize = lstrlenW(samname);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
*nSize = lstrlenW(samname) + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NameUnknown:
|
|
|
|
case NameFullyQualifiedDN:
|
|
|
|
case NameDisplay:
|
|
|
|
case NameUniqueId:
|
|
|
|
case NameCanonical:
|
|
|
|
case NameUserPrincipal:
|
|
|
|
case NameCanonicalEx:
|
|
|
|
case NameServicePrincipal:
|
|
|
|
case NameDnsDomain:
|
|
|
|
SetLastError(ERROR_NONE_MAPPED);
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN WINAPI TranslateNameA(
|
|
|
|
LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
|
|
|
|
EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
|
|
|
|
PULONG nSize)
|
|
|
|
{
|
|
|
|
FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
|
|
|
|
DesiredNameFormat, lpTranslatedName, nSize);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN WINAPI TranslateNameW(
|
|
|
|
LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
|
|
|
|
EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
|
|
|
|
PULONG nSize)
|
|
|
|
{
|
|
|
|
FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
|
|
|
|
DesiredNameFormat, lpTranslatedName, nSize);
|
|
|
|
return FALSE;
|
|
|
|
}
|