windows-nt/Source/XPSP1/NT/ds/security/base/lsa/server/param.cxx
2020-09-26 16:20:57 +08:00

638 lines
14 KiB
C++

//+-----------------------------------------------------------------------
//
// File: PARAM.C
//
// Contents: Parameter code
//
//
// History: 28 Feb 92 RichardW Created
//
//------------------------------------------------------------------------
#include <lsapch.hxx>
extern "C"
{
extern PWSTR pszPreferred;
}
#define MACHINERIDKEY L"MACHINERID"
WCHAR szLsaPath[] = L"System\\CurrentControlSet\\Control\\Lsa";
WCHAR szOthersValue[] = L"Security Packages";
WCHAR szOldValue[] = L"Authentication Packages";
WCHAR szNonceLagValue[] = L"Clock Skew";
WCHAR szHowMuchValue[] = L"How Much";
WCHAR szDisableSupPopups[] = L"DisablePopups";
WCHAR szPreferredPackage[] = L"Preferred";
WCHAR szGeneralThreadLifespan[] = L"GeneralThreadLifespan";
WCHAR szDedicatedThreadLifespan[] = L"DedicatedThreadLifespan";
HKEY hDSKey;
HANDLE hRegNotifyEvent;
PVOID pvParamScav;
PWSTR ppszDefault[] = {L"Kerberos", L"NTLM", NULL};
// Will build an argv style array of DLLs to load as packages here:
extern PWSTR * ppszPackages;
extern PWSTR * ppszOldPkgs;
extern PWSTR pszPreferred;
#if DBG
extern DWORD BreakFlags;
extern DWORD NoUnload;
#endif
SECURITY_STRING ssMachineRid;
//+-------------------------------------------------------------------------
//
// Function: GetRegistryString
//
// Synopsis: Gets a string from the registry
//
// Effects: If type is REG_EXPAND_SZ, string is expanded.
// If type is REG_MULTI_SZ, string is (left alone?)
//
// Arguments: hRootKey -- HKEY to start at
// pszSubKey -- Key to look at
// pszValue -- Value to look at
// pszData -- Buffer to place string
// pcbData -- Size (in/out) of buffer
//
// Requires:
//
// Returns:
//
// Notes:
//
//--------------------------------------------------------------------------
NTSTATUS
GetRegistryString( HKEY hRootKey,
PWSTR pszSubkey,
PWSTR pszValue,
PWSTR pszData,
PDWORD pcbData)
{
HKEY hKey;
int Status;
ULONG type;
DWORD dwSize = *pcbData;
Status = RegOpenKey(hRootKey, pszSubkey, &hKey);
if (Status != ERROR_SUCCESS)
{
DebugLog((DEB_ERROR, "Open of %ws failed, %d\n", pszSubkey, Status));
return(STATUS_OBJECT_NAME_NOT_FOUND);
}
// First, call query value and make sure this is a correct type
Status = RegQueryValueEx( hKey,
pszValue,
NULL,
&type,
NULL,
&dwSize);
if ((Status != ERROR_SUCCESS) && (Status != ERROR_MORE_DATA))
{
DebugLog((DEB_TRACE, "QueryValueEx of %ws failed, %d\n", pszValue, Status));
(void) RegCloseKey(hKey);
if (Status == ERROR_FILE_NOT_FOUND)
{
return(STATUS_OBJECT_NAME_NOT_FOUND);
}
return(STATUS_UNSUCCESSFUL);
}
if ((type != REG_SZ) && (type != REG_MULTI_SZ) && (type != REG_EXPAND_SZ) )
{
DebugLog((DEB_ERROR, "Type = %d, returning now\n", type));
(void) RegCloseKey(hKey);
return(STATUS_UNSUCCESSFUL);
}
Status = RegQueryValueEx( hKey,
pszValue,
NULL,
&type,
(PBYTE) pszData,
pcbData);
(void) RegCloseKey(hKey);
if (Status != ERROR_SUCCESS)
{
if (Status == ERROR_INSUFFICIENT_BUFFER)
{
return(STATUS_BUFFER_TOO_SMALL);
}
DebugLog((DEB_ERROR, "QueryValueEx of %ws returned %d\n", pszValue, Status));
return(STATUS_UNSUCCESSFUL);
}
if (type == REG_EXPAND_SZ)
{
*pcbData = ExpandEnvironmentStrings(pszData, pszData, dwSize);
}
return(STATUS_SUCCESS);
}
//+---------------------------------------------------------------------------
//
// Function: GetRegistryDword
//
// Synopsis: Gets a DWORD from the registry
//
// Effects:
//
// Arguments: [hPrimaryKey] -- Key to start from
// [pszKey] -- Name of the subkey
// [pszValue] -- Name of the value
// [pdwValue] -- returned DWORD
//
// Returns: S_OK, or SEC_E_INVALID_HANDLE
//
// History: 3-31-93 RichardW Created
//
//----------------------------------------------------------------------------
HRESULT
GetRegistryDword(HKEY hPrimaryKey,
PWSTR pszKey,
PWSTR pszValue,
DWORD * pdwValue)
{
HKEY hKey;
DWORD cbDword = sizeof(DWORD);
DWORD dwType;
int err;
err = RegOpenKey(hPrimaryKey, pszKey, &hKey);
if (err) {
return(SEC_E_INVALID_HANDLE);
}
err = RegQueryValueEx( hKey,
pszValue,
NULL,
&dwType,
(PBYTE) pdwValue,
&cbDword);
(void) RegCloseKey(hKey);
if (err || (dwType != REG_DWORD))
{
return(SEC_E_INVALID_HANDLE);
}
return(S_OK);
}
HRESULT
SpmGetMachineName(void)
{
HRESULT hr = S_OK;
WCHAR wszMachName [MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
if (!GetComputerName(
wszMachName,
&dwSize))
{
return(STATUS_UNSUCCESSFUL);
}
MachineName.Buffer = (LPWSTR) LsapAllocateLsaHeap((wcslen(wszMachName)+1) * sizeof(WCHAR));
if (MachineName.Buffer == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
wcscpy(MachineName.Buffer, wszMachName);
RtlInitUnicodeString(
&MachineName,
MachineName.Buffer
);
return(STATUS_SUCCESS);
}
//+---------------------------------------------------------------------------
//
// Function: ParameterNotify
//
// Synopsis: Function called when the registry key for DS is changed
//
// Arguments: [pvEntry] -- ignored
//
// History: 6-08-93 RichardW Created
//
//----------------------------------------------------------------------------
DWORD
ParameterNotify(PVOID pvEntry)
{
ULONG NewState;
HANDLE hThread = 0;
DWORD tid;
int err;
err = RegNotifyChangeKeyValue( hDSKey, FALSE,
REG_NOTIFY_CHANGE_LAST_SET,
hRegNotifyEvent,
TRUE);
if (err)
{
DebugLog((DEB_WARN, "Got %d from trying to start RegNotifyChangeKeyValue again\n",
err));
}
return(0);
}
//+---------------------------------------------------------------------------
//
// Function: LoadParameters
//
// Synopsis: Loads operating parameters from the registry
//
// Effects:
//
// Arguments: [void] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: 3-31-93 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS
LoadParameters(
VOID
)
{
int lcPackages = 0;
int cOldPkgs = 0;
int iPackage = 0;
PWSTR pszAlternate;
PWSTR pszOldPkgs;
PWSTR pszScan;
DWORD dwBuffer = 64;
HRESULT scRet;
//
// Get the parameters that can change during a boot.
//
//
// Get the machine name
//
scRet = SpmGetMachineName();
if (!NT_SUCCESS(scRet)) {
return(scRet);
}
//
// Get the preferred package
//
dwBuffer = 128 ;
pszPreferred = (PWSTR) LsapAllocateLsaHeap( dwBuffer );
if ( !pszPreferred )
{
dwBuffer = 0 ;
}
scRet = GetRegistryString( HKEY_LOCAL_MACHINE,
szLsaPath,
szPreferredPackage,
pszPreferred,
&dwBuffer);
if (scRet == STATUS_BUFFER_TOO_SMALL)
{
LsapFreeLsaHeap(pszPreferred);
pszPreferred = (PWSTR)LsapAllocateLsaHeap(dwBuffer);
if ( pszPreferred )
{
scRet = GetRegistryString( HKEY_LOCAL_MACHINE,
szLsaPath,
szPreferredPackage,
pszPreferred,
&dwBuffer);
}
}
else
{
if ( pszPreferred )
{
LsapFreeLsaHeap( pszPreferred );
pszPreferred = NULL ;
}
}
//
// Set the default packages
//
ppszPackages = ppszDefault;
//
// Now, find out all the other ones. First, NT5 packages:
//
dwBuffer = 128;
pszAlternate = (PWSTR)LsapAllocateLsaHeap(dwBuffer);
if (!pszAlternate)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
*pszAlternate = L'\0';
scRet = GetRegistryString( HKEY_LOCAL_MACHINE,
szLsaPath,
szOthersValue,
pszAlternate,
&dwBuffer);
if (scRet == STATUS_BUFFER_TOO_SMALL)
{
LsapFreeLsaHeap(pszAlternate);
pszAlternate = (PWSTR)LsapAllocateLsaHeap(dwBuffer);
if (!pszAlternate)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
*pszAlternate = L'\0';
scRet = GetRegistryString( HKEY_LOCAL_MACHINE,
szLsaPath,
szOthersValue,
pszAlternate,
&dwBuffer);
if (FAILED(scRet)) {
return(scRet);
}
}
if (NT_SUCCESS(scRet))
{
pszScan = pszAlternate;
while (*pszScan)
{
while (*pszScan) {
pszScan++;
}
lcPackages++;
pszScan++;
}
} else if (scRet != STATUS_OBJECT_NAME_NOT_FOUND) {
LsapFreeLsaHeap(pszAlternate);
pszAlternate = NULL;
return(scRet);
} else {
LsapFreeLsaHeap(pszAlternate);
pszAlternate = NULL;
}
dwBuffer = 128;
pszOldPkgs = (PWSTR)LsapAllocateLsaHeap(dwBuffer);
if (!pszOldPkgs)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
*pszOldPkgs = L'\0';
scRet = GetRegistryString( HKEY_LOCAL_MACHINE,
szLsaPath,
szOldValue,
pszOldPkgs,
&dwBuffer);
if (scRet == STATUS_BUFFER_TOO_SMALL)
{
LsapFreeLsaHeap(pszOldPkgs);
pszOldPkgs = (PWSTR)LsapAllocateLsaHeap(dwBuffer);
if (!pszOldPkgs)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
*pszOldPkgs = L'\0';
scRet = GetRegistryString( HKEY_LOCAL_MACHINE,
szLsaPath,
szOldValue,
pszOldPkgs,
&dwBuffer);
if (!NT_SUCCESS(scRet)) {
return(scRet);
}
}
if (NT_SUCCESS(scRet))
{
pszScan = pszOldPkgs;
while (*pszScan)
{
while (*pszScan) {
pszScan++;
}
cOldPkgs++;
pszScan++;
}
} else if (scRet != STATUS_OBJECT_NAME_NOT_FOUND) {
LsapFreeLsaHeap(pszOldPkgs);
pszOldPkgs = NULL;
return(scRet);
} else {
LsapFreeLsaHeap(pszOldPkgs);
pszOldPkgs = NULL;
}
ppszPackages = (PWSTR *)LsapAllocateLsaHeap((lcPackages + 1) * sizeof(PWSTR));
if (!ppszPackages)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
//
// Add any alternate packages
//
if (pszAlternate != NULL)
{
pszScan = pszAlternate;
while (*pszScan)
{
ppszPackages[iPackage++] = pszScan;
while (*pszScan++);
}
}
ppszPackages[iPackage] = NULL;
//
// Note: we don't allocate one extra, since we don't actually include
// the MSV package name here (we simulate the package in msvlayer.c)
//
ppszOldPkgs = (PWSTR *)LsapAllocateLsaHeap((cOldPkgs+1) * sizeof(PWSTR));
if (!ppszOldPkgs)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
iPackage = 0;
if (pszOldPkgs != NULL)
{
pszScan = pszOldPkgs;
while (*pszScan)
{
ppszOldPkgs[iPackage++] = pszScan;
while (*pszScan++);
}
}
cOldPkgs = iPackage;
ppszOldPkgs[iPackage] = NULL;
return(S_OK);
}
BOOL
AddPackageToRegistry(
PSECURITY_STRING Package
)
{
PWSTR Buffer;
DWORD Length;
DWORD Type;
int err;
HKEY hKey;
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
szLsaPath,
0,
KEY_READ | KEY_WRITE,
&hKey );
if ( err )
{
return( FALSE );
}
Length = 0;
err = RegQueryValueEx( hKey,
szOthersValue,
0,
&Type,
NULL,
&Length );
Buffer = (PWSTR) LsapAllocateLsaHeap( Length + Package->Length + 2 );
if ( !Buffer )
{
RegCloseKey( hKey );
return FALSE ;
}
RegQueryValueEx( hKey,
szOthersValue,
0,
&Type,
(PUCHAR) Buffer,
&Length );
CopyMemory( &Buffer[Length + 1],
Package->Buffer,
Package->Length + 2 );
Length = Length + Package->Length + 2;
RegSetValueEx( hKey,
szOthersValue,
0,
REG_MULTI_SZ,
(PUCHAR) Buffer,
Length );
RegCloseKey( hKey );
return( TRUE );
}