Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

893 lines
23 KiB

#include <common.h>
//
// from autlogon.c
//
extern BOOL g_QuietMode;
extern WCHAR g_TempString[];
extern WCHAR g_ErrorString[];
extern WCHAR g_FailureLocation[];
#ifdef PRIVATE_VERSION
extern BOOL g_RemoteOperation;
extern WCHAR g_RemoteComputerName[];
#endif
//+----------------------------------------------------------------------------
//
// Wow64 stuff
//
//+----------------------------------------------------------------------------
#ifdef _X86_
typedef BOOL (*PFNISWOW64PROCESS)(HANDLE, PBOOL);
#endif
//+----------------------------------------------------------------------------
//
// DisplayMessage
//
//+----------------------------------------------------------------------------
VOID
DisplayMessage(
WCHAR *MessageText)
{
if (!g_QuietMode)
{
wprintf(L"%s", MessageText);
}
}
//+----------------------------------------------------------------------------
//
// GetErrorString
//
//+----------------------------------------------------------------------------
WCHAR*
GetErrorString(
DWORD dwErrorCode)
{
LPVOID lpMsgBuf=NULL;
SecureZeroMemory(g_ErrorString, MAX_STRING * sizeof(WCHAR));
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL);
// Free the bufferoa
if (lpMsgBuf != NULL)
{
wcsncpy(g_ErrorString, lpMsgBuf, MAX_STRING - 1);
LocalFree(lpMsgBuf);
}
return g_ErrorString;
}
DWORD
GetRegValueSZ(
WCHAR *ValueName,
WCHAR *RegValue,
size_t RegValueLength)
{
DWORD dwRetCode = ERROR_SUCCESS;
HKEY hKey=NULL;
DWORD dwMaxValueData = (MAX_STRING * sizeof(WCHAR)); // Longest Value data
HANDLE hHeap=NULL;
BYTE *bData=NULL;
DWORD cbData;
DWORD dwType;
// get a handle to the local or remote computer
// (as specified by our global flag)
dwRetCode = GetRegistryHandle(&hKey, KEY_READ);
if( ERROR_SUCCESS != dwRetCode )
{
goto cleanup;
}
// create a heap
hHeap = HeapCreate(0, 0, 0);
if( NULL == hHeap )
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: HeapCreate: %s\n",
GetErrorString(dwRetCode));
goto cleanup;
}
// allocate some space on the heap for our regvalue we'll read in
bData = (BYTE*)HeapAlloc(hHeap, 0, dwMaxValueData);
if (bData == NULL)
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: HeapAlloc: %s\n",
GetErrorString(dwRetCode));
goto cleanup;
}
cbData = dwMaxValueData;
// read the regkey using the handle we open above
dwRetCode = RegQueryValueEx(
hKey,
ValueName,
NULL,
&dwType,
bData,
&cbData);
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: RegQueryValueEx: %s",
GetErrorString(dwRetCode));
goto cleanup;
}
// if it's not a type reg_sz, then something's wrong, so
// report the error, which will cause us to stop.
if( dwType != REG_SZ )
{
dwRetCode = ERROR_BADKEY;
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: RegQueryValueEx: %s: %s\n",
ValueName,
GetErrorString(dwRetCode));
goto cleanup;
}
//
// copy the (0 terminated) buffer to the registry value
// If empty, just 0 the buffer for the caller
//
if( cbData )
{
if( cbData / sizeof(WCHAR) > RegValueLength )
{
*RegValue = 0;
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
wcscpy(RegValue, (WCHAR *)bData);
}
}
else
{
*RegValue = 0;
}
cleanup:
if( NULL != bData )
{
SecureZeroMemory(bData, sizeof(bData));
if( NULL != hHeap )
{
HeapFree(hHeap, 0, bData);
HeapDestroy(hHeap);
}
}
if( NULL != hKey )
{
RegCloseKey(hKey);
}
return dwRetCode;
}
DWORD
GetRegValueDWORD(
WCHAR* ValueName,
DWORD* RegValue)
{
DWORD dwRetCode = ERROR_SUCCESS;
HKEY hKey=NULL;
DWORD dwMaxValueData = (MAX_STRING * sizeof(WCHAR)); // Longest Value data
HANDLE hHeap=NULL;
BYTE *bData=NULL;
DWORD cbData;
DWORD dwType;
// get a handle to the local or remote computer
// (as specified by our global flag)
dwRetCode = GetRegistryHandle(&hKey, KEY_READ);
if( ERROR_SUCCESS != dwRetCode )
{
goto cleanup;
}
// create a heap
hHeap = HeapCreate(0, 0, 0);
if( NULL == hHeap )
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: HeapCreate: %s\n",
GetErrorString(dwRetCode));
goto cleanup;
}
// allocate some space on the heap for our regvalue we'll read in
bData = (BYTE*)HeapAlloc(hHeap, 0, dwMaxValueData);
if (bData == NULL)
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: HeapAlloc: %s\n",
GetErrorString(dwRetCode));
goto cleanup;
}
cbData = dwMaxValueData;
// read the regkey using the handle we open above
dwRetCode = RegQueryValueEx(
hKey,
ValueName,
NULL,
&dwType,
bData,
&cbData);
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: RegQueryValueEx: %s",
GetErrorString(dwRetCode));
goto cleanup;
}
// if it's not a type reg_sz, then something's wrong, so
// report the error, which will cause us to stop.
if( dwType != REG_DWORD )
{
dwRetCode = ERROR_BADKEY;
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegValueSZ: RegQueryValueEx: %s: %s\n",
ValueName,
GetErrorString(dwRetCode));
goto cleanup;
}
//
// copy the buffer to the registry value
// If empty, just 0 the buffer for the caller
//
*RegValue = *(DWORD*)bData;
cleanup:
if( NULL != bData )
{
SecureZeroMemory(bData, sizeof(bData));
if( NULL != hHeap )
{
HeapFree(hHeap, 0, bData);
HeapDestroy(hHeap);
}
}
if( NULL != hKey )
{
RegCloseKey(hKey);
}
return dwRetCode;
}
DWORD
ClearRegValue(
WCHAR* ValueName)
{
DWORD dwRetCode = ERROR_SUCCESS;
HKEY hKey=NULL;
dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
if( ERROR_SUCCESS != dwRetCode )
{
goto cleanup;
}
dwRetCode = RegDeleteValue(hKey, ValueName);
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"ClearRegPassword: RegDeleteValue: %s: %s\n",
ValueName,
GetErrorString(dwRetCode));
goto cleanup;
}
cleanup:
if( NULL != hKey)
{
RegCloseKey(hKey);
}
return dwRetCode;
}
DWORD
SetRegValueSZ(
WCHAR *ValueName,
WCHAR *ValueData)
{
DWORD dwRetCode = ERROR_SUCCESS;
HKEY hKey=NULL;
dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
if( ERROR_SUCCESS != dwRetCode )
{
goto cleanup;
}
dwRetCode = RegSetValueEx(
hKey,
ValueName,
0,
REG_SZ,
(LPSTR) ValueData,
wcslen(ValueData)*sizeof(WCHAR));
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"SetRegValueSZ: RegSetValueEx: %s: %s\n",
ValueName,
GetErrorString(dwRetCode));
goto cleanup;
}
cleanup:
if( NULL != hKey)
{
RegCloseKey(hKey);
}
return dwRetCode;
}
DWORD
SetRegValueDWORD(
WCHAR *ValueName,
DWORD ValueData)
{
DWORD dwRetCode = ERROR_SUCCESS;
HKEY hKey=NULL;
dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
if( ERROR_SUCCESS != dwRetCode )
{
goto cleanup;
}
dwRetCode = RegSetValueEx(
hKey,
ValueName,
0,
REG_DWORD,
(const BYTE*) (&ValueData),
sizeof(DWORD));
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"SetRegValueSZ: RegSetValueEx: %s: %s\n",
ValueName,
GetErrorString(dwRetCode));
goto cleanup;
}
cleanup:
if( NULL != hKey)
{
RegCloseKey(hKey);
}
return dwRetCode;
}
DWORD
GetRegistryHandle(
HKEY *phKey,
REGSAM samDesired)
{
#ifdef PRIVATE_VERSION
HKEY RemoteRegistryHandle = NULL;
#endif
DWORD dwRetCode = ERROR_SUCCESS;
#ifdef _X86_
//
// if we run this tool on a 64bit system, we may need to write to
// the 64bit hive
//
static PFNISWOW64PROCESS pfnIsWow64Process = NULL;
static BOOL fIsWow64Process = FALSE;
if( pfnIsWow64Process == NULL )
{
HINSTANCE hInstDLL = LoadLibrary(L"kernel32.dll");
if( hInstDLL )
{
pfnIsWow64Process =
(PFNISWOW64PROCESS)GetProcAddress(hInstDLL, "IsWow64Process");
if( pfnIsWow64Process )
{
pfnIsWow64Process(GetCurrentProcess(),
&fIsWow64Process);
}
// else we assume we run on a downlevel platform
FreeLibrary(hInstDLL);
}
}
if( fIsWow64Process )
{
samDesired |= KEY_WOW64_64KEY;
}
#endif
//
// If not PRIVATE mode, ignore the access requested passed in and
// request all access, even though we don't need it. This will force the
// caller to need to be admin to use this tool. We don't want someone using
// this tool to view the autologon passwords of all machines across the domain
// as a normal domain user...
//
#ifndef PRIVATE_VERSION
samDesired = KEY_ALL_ACCESS;
#endif
#ifdef PRIVATE_VERSION
//
// If we're connecting against a remote computer
//
if( g_RemoteOperation )
{
// open a handle to the remote registry
dwRetCode = RegConnectRegistry(g_RemoteComputerName,
HKEY_LOCAL_MACHINE,
&RemoteRegistryHandle);
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegistryHandle: RegConnectRegistry: %s: %s\n",
g_RemoteComputerName,
GetErrorString(dwRetCode));
goto cleanup;
}
// open the WINLOGON key on the remote machine
dwRetCode = RegOpenKeyEx(RemoteRegistryHandle,
WINLOGON_REGKEY,
0,
samDesired,
phKey);
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegistryHandle: RegOpenKeyEx: %s: %s\n",
g_RemoteComputerName,
GetErrorString(dwRetCode));
goto cleanup;
}
}
else
#endif
{
// open the WINLOGON key on the local machine
dwRetCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WINLOGON_REGKEY,
0,
samDesired,
phKey);
if( ERROR_SUCCESS != dwRetCode )
{
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetRegistryHandle: RegOpenKeyEx: %s\n",
GetErrorString(dwRetCode));
goto cleanup;
}
}
cleanup:
#ifdef PRIVATE_VERSION
if( NULL != RemoteRegistryHandle )
{
RegCloseKey(RemoteRegistryHandle);
}
#endif
return dwRetCode;
}
//+---------------------------------------------------------------------------------------------------------
//
// LSASecret munging routines
//
//+---------------------------------------------------------------------------------------------------------
DWORD
GetPolicyHandle(LSA_HANDLE *LsaPolicyHandle)
{
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS ntsResult;
#ifdef PRIVATE_VERSION
LSA_UNICODE_STRING TargetMachine;
USHORT TargetMachineLength;
#endif
DWORD dwRetCode = ERROR_SUCCESS;
// Object attributes are reserved, so initialize to zeroes.
SecureZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
#ifdef PRIVATE_VERSION
if( g_RemoteOperation )
{
//Initialize an LSA_UNICODE_STRING
TargetMachineLength = (USHORT)wcslen(g_RemoteComputerName);
TargetMachine.Buffer = g_RemoteComputerName;
TargetMachine.Length = TargetMachineLength * sizeof(WCHAR);
TargetMachine.MaximumLength = (TargetMachineLength+1) * sizeof(WCHAR);
// Get a handle to the Policy object.
ntsResult = LsaOpenPolicy(
&TargetMachine, //local machine
&ObjectAttributes,
POLICY_CREATE_SECRET | POLICY_GET_PRIVATE_INFORMATION,
LsaPolicyHandle);
}
else
#endif
{
// Get a handle to the Policy object.
ntsResult = LsaOpenPolicy(
NULL, //local machine
&ObjectAttributes,
POLICY_CREATE_SECRET | POLICY_GET_PRIVATE_INFORMATION,
LsaPolicyHandle);
}
if( STATUS_SUCCESS != ntsResult )
{
// An error occurred. Display it as a win32 error code.
dwRetCode = LsaNtStatusToWinError(ntsResult);
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetPolicyHandle: LsaOpenPolicy: %s\n",
GetErrorString(dwRetCode));
goto cleanup;
}
cleanup:
return dwRetCode;
}
DWORD
SetSecret(
WCHAR *Secret,
BOOL bClearSecret,
WCHAR* SecretName)
{
DWORD dwRetCode = ERROR_SUCCESS;
NTSTATUS ntsResult;
USHORT SecretNameLength, SecretDataLength;
LSA_HANDLE LsaPolicyHandle=NULL;
LSA_UNICODE_STRING lusSecretName, lusSecretData;
//Initialize an LSA_UNICODE_STRING
SecretNameLength = (USHORT)wcslen(SecretName);
lusSecretName.Buffer = SecretName;
lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
lusSecretName.MaximumLength = (SecretNameLength+1) * sizeof(WCHAR);
dwRetCode = GetPolicyHandle(&LsaPolicyHandle);
if( ERROR_SUCCESS != dwRetCode )
{
goto cleanup;
}
// if bClearSecret is set, then delete the secret
// otherwise set the secret to Secret
if( bClearSecret )
{
ntsResult = LsaStorePrivateData(
LsaPolicyHandle,
&lusSecretName,
NULL);
if( STATUS_SUCCESS != ntsResult ) {
dwRetCode = LsaNtStatusToWinError(ntsResult);
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"SetSecret: LsaStorePrivateData: %s\n",
GetErrorString(dwRetCode));
goto cleanup;
}
}
else
{
//Initialize the Secret LSA_UNICODE_STRING
SecretDataLength = (USHORT)wcslen(Secret);
lusSecretData.Buffer = Secret;
lusSecretData.Length = SecretDataLength * sizeof(WCHAR);
lusSecretData.MaximumLength = (SecretDataLength+1) * sizeof(WCHAR);
ntsResult = LsaStorePrivateData(
LsaPolicyHandle,
&lusSecretName,
&lusSecretData);
if( STATUS_SUCCESS != ntsResult ) {
dwRetCode = LsaNtStatusToWinError(ntsResult);
goto cleanup;
}
}
cleanup:
if( NULL != LsaPolicyHandle )
{
LsaClose(LsaPolicyHandle);
}
return dwRetCode;
}
DWORD
GetSecret(
WCHAR* Secret,
size_t SecretLength,
WCHAR* SecretName)
{
DWORD dwRetCode = ERROR_SUCCESS;
NTSTATUS ntsResult;
USHORT SecretNameLength;
LSA_HANDLE LsaPolicyHandle=NULL;
LSA_UNICODE_STRING lusSecretName;
LSA_UNICODE_STRING *PrivateData=NULL;
//Initialize an LSA_UNICODE_STRING
SecretNameLength = (USHORT)wcslen(SecretName);
lusSecretName.Buffer = SecretName;
lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
lusSecretName.MaximumLength= (SecretNameLength+1) * sizeof(WCHAR);
dwRetCode = GetPolicyHandle(&LsaPolicyHandle);
if( ERROR_SUCCESS != dwRetCode )
{
goto cleanup;
}
ntsResult = LsaRetrievePrivateData(
LsaPolicyHandle,
&lusSecretName,
&PrivateData);
if( STATUS_SUCCESS != ntsResult )
{
if( STATUS_OBJECT_NAME_NOT_FOUND == ntsResult)
{
dwRetCode = ntsResult;
goto cleanup;
}
else
{
dwRetCode = LsaNtStatusToWinError(ntsResult);
_snwprintf(g_FailureLocation, MAX_STRING - 1,
L"GetSecret: LsaRetrievePrivateData: %s \n",
GetErrorString(dwRetCode));
goto cleanup;
}
}
// copy the (not 0 terminated) buffer data to Secret
if( (PrivateData->Length)/sizeof(WCHAR) < SecretLength )
{
wcsncpy(Secret, PrivateData->Buffer, (PrivateData->Length)/sizeof(WCHAR));
Secret[(PrivateData->Length)/sizeof(WCHAR)] = 0;
}
else
{
Secret[0] = 0;
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
}
cleanup:
if( NULL != PrivateData )
{
SecureZeroMemory(PrivateData->Buffer, PrivateData->Length);
LsaFreeMemory(PrivateData);
}
if( NULL != LsaPolicyHandle )
{
LsaClose(LsaPolicyHandle);
}
return dwRetCode;
}
//+----------------------------------------------------------------------------
//
// Other helpers
//
//+----------------------------------------------------------------------------
NET_API_STATUS
GetMajorNTVersion(
DWORD* Version,
WCHAR* Server)
{
SERVER_INFO_101* pInf;
NET_API_STATUS status;
status = NetServerGetInfo(Server, 101, (BYTE**)&pInf);
if(!status)
{
if(pInf->sv101_platform_id == PLATFORM_ID_NT)
{
*Version = pInf->sv101_version_major;
}
else
{
*Version = 0;
}
NetApiBufferFree(pInf);
}
else
{
*Version = 0;
}
return status;
}
//+----------------------------------------------------------------------------
//
// GetConsoleStr - reads a console string and other stuff...
//
// "borrowed" from ds\netapi\netcmd\common\mutil.c
//
//+----------------------------------------------------------------------------
#define CR 0xD
#define LF 0xA
#define BACKSPACE 0x8
DWORD
GetConsoleStr(
WCHAR* buf,
DWORD buflen,
BOOL hide,
WCHAR* message,
PDWORD len
)
{
WCHAR ch;
WCHAR *bufPtr = buf;
DWORD c;
BOOL err;
DWORD mode;
DWORD cchBuffer;
DWORD dwRetCode = ERROR_SUCCESS;
DWORD dwLen = 0;
BOOL hidden = FALSE;
if( hide )
{
//
// Init mode in case GetConsoleMode() fails
//
mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT |
ENABLE_MOUSE_INPUT;
if( !GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode) )
{
dwRetCode = GetLastError();
goto cleanup;
}
if( !SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
(~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode) )
{
dwRetCode = GetLastError();
goto cleanup;
}
hidden = TRUE;
}
//
// prints the message
//
if( message )
{
if( !WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
message, wcslen(message),
&cchBuffer, NULL) )
{
dwRetCode = GetLastError();
goto cleanup;
}
}
while (TRUE)
{
err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0);
if (!err || c != 1)
{
ch = 0xffff;
}
if ((ch == CR) || (ch == 0xffff)) /* end of the line */
{
if( (ch == CR) && !hide)
{
//
// LF comes when echo enabled. Ignore it
//
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0);
}
break;
}
if (ch == BACKSPACE) /* back up one or two */
{
/*
* IF bufPtr == buf then the next two lines are
* a no op.
*/
if (bufPtr != buf)
{
bufPtr--;
dwLen--;
}
}
else
{
*bufPtr = ch;
if (dwLen < buflen)
bufPtr++ ; /* don't overflow buf */
dwLen++; /* always increment len */
}
}
if( hidden )
{
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
}
//
// NULL terminate
//
*bufPtr = 0;
if( hide )
{
//
// fake the echo for CR/LF
//
putchar(L'\n');
}
if( dwLen > buflen )
{
dwRetCode = ERROR_INSUFFICIENT_BUFFER;
goto cleanup;
}
//
// set the optional out parameter
//
if( len )
{
*len = dwLen;
}
cleanup:
return dwRetCode;
}