|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
autologon.c
Abstract:
This is a command-line utility munges that settings related to the Windows NT/2000 Autologon functionality
if PRIVATE_VERSION is defined, password info will be displayed on the output For general distribution, this should not be defined
Author: Jason Garms (jasong) 12 October 2000
History: Cristian Ilac (crisilac) 11 November 2001 Made spec changes Jason Garms (jasong) 12 October 2000 Created --*/
#include "common.h"
#include <wincred.h>
//+----------------------------------------------------------------------------
//
// Prototypes
//
//+----------------------------------------------------------------------------
//+----------------------------------------------------------------------------
//
// Command functions
//
//+----------------------------------------------------------------------------
typedef DWORD (*CommandFn)();
DWORD DumpCmd();
DWORD MigratePassword();
DWORD Delete();
DWORD EnableAutoLogon();
#ifdef PRIVATE_VERSION
DWORD DumpAutoLogonInfo(); #endif
//+----------------------------------------------------------------------------
//
// Data/Options set functions
//
//+----------------------------------------------------------------------------
DWORD SetCommand( UINT uCommand);
DWORD SetQuietMode( WCHAR* pszData);
DWORD SetUserName( WCHAR* pszData);
DWORD SetCount( WCHAR* pszData);
#ifdef PRIVATE_VERSION
DWORD SetMachineName( WCHAR* pszData);
#endif
//+----------------------------------------------------------------------------
//
// Other functions
//
//+----------------------------------------------------------------------------
DWORD CheckWinVersion();
DWORD GetPassword();
//+----------------------------------------------------------------------------
//
// Global command table
//
//+----------------------------------------------------------------------------
#define COMMAND_HELP 0
#define COMMAND_MIGRATE 1
#define COMMAND_LSA_DELETE 2
#define COMMAND_LSA_ENABLE 3
#ifdef PRIVATE_VERSION
#define COMMAND_DUMP 4
#define COMMAND_NOT_SET 5
#else
#define COMMAND_NOT_SET 4
#endif
#define COMMAND_SIZE COMMAND_NOT_SET
CommandFn g_Commands[COMMAND_SIZE] = { DumpCmd, MigratePassword, Delete, EnableAutoLogon, #ifdef PRIVATE_VERSION
DumpAutoLogonInfo #endif
};
//+----------------------------------------------------------------------------//
//
// Global data
//
//+----------------------------------------------------------------------------
WCHAR g_UserName[MAX_STRING] = {0};
WCHAR g_DomainName[MAX_STRING] = {0};
WCHAR g_Password[MAX_STRING] = {0};
DWORD g_AutoLogonCount = 0;
WCHAR g_TempString[MAX_STRING] = {0}; WCHAR g_ErrorString[MAX_STRING] = {0}; WCHAR g_FailureLocation[MAX_STRING] = {0};
BOOL g_QuietMode = FALSE; BOOL g_FullHelp = FALSE;
BOOL g_SetDefaultPIN = FALSE;
UINT g_uCommand = COMMAND_NOT_SET;
#ifdef PRIVATE_VERSION
BOOL g_RemoteOperation = FALSE; WCHAR g_RemoteComputerName[MAX_STRING] = {0}; #endif
// various strings
WCHAR g_PasswordSecretName[] = L"DefaultPassword"; WCHAR g_PinSecretName[] = L"DefaultPIN"; WCHAR g_AutoAdminLogonName[] = L"AutoAdminLogon"; WCHAR g_DefaultUserName[] = L"DefaultUserName"; WCHAR g_DefaultDomainName[] = L"DefaultDomainName"; WCHAR g_AutoLogonCountName[] = L"AutoLogonCount";
//+----------------------------------------------------------------------------
//
// Functions
//
//+----------------------------------------------------------------------------
int __cdecl wmain( int argc, WCHAR *argv[] ) { UINT uCommandPosition = 0;
DWORD dwRetCode = ERROR_SUCCESS;
//
// loop through all command line arguments and check for known ones
// - if one argument is identified continue the loop
// - if unknown arguments are passed break the loop and fail
//
while( ++uCommandPosition < (UINT)argc ) { if( !_wcsicmp(argv[uCommandPosition], L"/?") ) { g_FullHelp = TRUE; dwRetCode = SetCommand(COMMAND_HELP); if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsicmp(argv[uCommandPosition], L"/Q") || !_wcsicmp(argv[uCommandPosition], L"/Quiet") ) { dwRetCode = SetQuietMode(argv[uCommandPosition]); if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsicmp(argv[uCommandPosition], L"/M") || !_wcsicmp(argv[uCommandPosition], L"/Migrate") ) { dwRetCode = SetCommand(COMMAND_MIGRATE); if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsicmp(argv[uCommandPosition], L"/D") || !_wcsicmp(argv[uCommandPosition], L"/Delete") ) { dwRetCode = SetCommand(COMMAND_LSA_DELETE); if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsicmp(argv[uCommandPosition], L"/S") || !_wcsicmp(argv[uCommandPosition], L"/Set") ) { dwRetCode = SetCommand(COMMAND_LSA_ENABLE); if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsnicmp(argv[uCommandPosition], L"/U:", wcslen(L"/U:")) || !_wcsicmp(argv[uCommandPosition], L"/U") || !_wcsnicmp(argv[uCommandPosition], L"/UserName:", wcslen(L"/UserName:")) || !_wcsicmp(argv[uCommandPosition], L"/Username") ) { dwRetCode = SetUserName(argv[uCommandPosition]); if( ERROR_FILE_NOT_FOUND == dwRetCode ) { //
// it may be because there was a column followed by spaces
// Try to recover
//
if( uCommandPosition + 1 < (UINT)argc ) { //
// only if not another parameter
//
if( argv[uCommandPosition + 1][0] != '/' ) { dwRetCode = SetUserName(argv[++uCommandPosition]); } else { DisplayMessage(L"Command line: Missing Username.\n"); } } }
if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsnicmp(argv[uCommandPosition], L"/C:", wcslen(L"/C:")) || !_wcsicmp(argv[uCommandPosition], L"/C") || !_wcsnicmp(argv[uCommandPosition], L"/Count:", wcslen(L"/Count:")) || !_wcsicmp(argv[uCommandPosition], L"/Count") ) { dwRetCode = SetCount(argv[uCommandPosition]); if( ERROR_FILE_NOT_FOUND == dwRetCode ) { //
// it may be because there was no column or a column
// followed by spaces. Try to recover by moving on.
//
if( uCommandPosition + 1 < (UINT)argc ) { //
// only if not another parameter
//
if( argv[uCommandPosition + 1][0] != '/' ) { dwRetCode = SetCount(argv[++uCommandPosition]); } else { DisplayMessage(L"Command line: Missing count.\n"); } } } if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsicmp(argv[uCommandPosition], L"/P") || !_wcsicmp(argv[uCommandPosition], L"/Pin") ) { g_SetDefaultPIN = TRUE; dwRetCode = SetCommand(COMMAND_LSA_ENABLE); if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
#ifdef PRIVATE_VERSION
if( !_wcsnicmp(argv[uCommandPosition], L"/T:", wcslen(L"/T:")) || !_wcsicmp(argv[uCommandPosition], L"/T") || !_wcsnicmp(argv[uCommandPosition], L"/Target:", wcslen(L"/Target:")) || !_wcsicmp(argv[uCommandPosition], L"/Target") ) { dwRetCode = SetMachineName(argv[uCommandPosition]); if( ERROR_FILE_NOT_FOUND == dwRetCode ) { //
// it may be because there was no column or a column
// followed by spaces. Try to recover by moving on.
//
if( uCommandPosition + 1 < (UINT)argc ) { //
// only if not another parameter
//
if( argv[uCommandPosition + 1][0] != '/' ) { dwRetCode = SetMachineName(argv[++uCommandPosition]); } else { DisplayMessage(L"Command line: Missing machine name.\n"); } } } if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } }
if( !_wcsicmp(argv[uCommandPosition], L"/L") || !_wcsicmp(argv[uCommandPosition], L"/List") ) { dwRetCode = SetCommand(COMMAND_DUMP); if( ERROR_SUCCESS == dwRetCode ) { continue; } else { break; } } #endif
//
// unknown argument, set the help as command and break
// we have to use this parameter as the command might
// have already been set
//
_snwprintf(g_TempString, MAX_STRING - 1, L"Invalid command: %s\n", argv[uCommandPosition]); DisplayMessage(g_TempString);
SetCommand(COMMAND_NOT_SET); break; }
//
// Display usage if no command switch is present
//
if( ERROR_SUCCESS != dwRetCode ) { DumpCmd(); } else { if( COMMAND_NOT_SET == g_uCommand ) { SetCommand(COMMAND_HELP); }
dwRetCode = g_Commands[g_uCommand]();
//
// bad arguments passed to the command, display help
//
if( ERROR_BAD_ARGUMENTS == dwRetCode ) { DumpCmd(); } } return dwRetCode; }
//+----------------------------------------------------------------------------
//
// MigratePassword
//
// - reads the registry password, deletes it and sets the LSA secret
// - works only on certain win versions
// - if no password present fails
// - if any ops fail does not roll back
// - if pwd read fails - nothing happens
// - if LSA secret set fails - pretty much nothing happens as well.
// - if RegDelete fails - there is no need to delete the LSA secret...
//
//+----------------------------------------------------------------------------
DWORD MigratePassword() { WCHAR Password[MAX_STRING]; DWORD dwRetCode = ERROR_SUCCESS; BOOL fMigratedPIN = FALSE;
if( ERROR_SUCCESS != CheckWinVersion() ) { dwRetCode = ERROR_OLD_WIN_VERSION; goto cleanup; }
//
// get the DefaultPIN registry key from the local
// or remote system and store it in a local string
// As this is not something we document we do not display any errors
// We also do not display any success messages. The only case where
// we have to display smth PIN related is when we can migrate the PIN
// but there is no password. We can't fail and we have to display something.
//
dwRetCode = GetRegValueSZ(g_PinSecretName, Password, MAX_STRING - 1); if( ERROR_SUCCESS != dwRetCode ) { //
// we won't migrate the PIN and silently move on
// this is something we do not document for the tool
//
#ifdef PRIVATE_VERSION
if( ERROR_FILE_NOT_FOUND != dwRetCode ) { DisplayMessage(L"Migrate: DefaultPIN key cannot be read.\n"); } #endif
dwRetCode = ERROR_SUCCESS; goto MigratePassword; }
//
// Set the DefaultPassword LSASecret to the value we retrieved
// from the registry
//
dwRetCode = SetSecret(Password, FALSE, g_PinSecretName); if( ERROR_SUCCESS != dwRetCode ) { #ifdef PRIVATE_VERSION
_snwprintf(g_TempString, MAX_STRING - 1, L"Migrate: Could not set DefaultPIN LSASecret: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); #endif
dwRetCode = ERROR_SUCCESS; goto MigratePassword; }
// Delete the DefaultPassword registry key
dwRetCode = ClearRegValue(g_PinSecretName); if( ERROR_SUCCESS != dwRetCode ) { //
// delete the secret if could not remove the password.
//
(void)SetSecret(NULL, TRUE, g_PinSecretName);
#ifdef PRIVATE_VERSION
_snwprintf(g_TempString, MAX_STRING - 1, L"Migrate: Could not delete DefaultPIN key: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); #endif
dwRetCode = ERROR_SUCCESS; goto MigratePassword; }
#ifdef PRIVATE_VERSION
DisplayMessage(L"Pin migrated from Registry to LSASecret\n"); #endif
fMigratedPIN = TRUE;
MigratePassword: // Get the DefaultPassword registry key from the local
// or remote system and store it in a local string
dwRetCode = GetRegValueSZ(g_PasswordSecretName, Password, MAX_STRING - 1); if( ERROR_FILE_NOT_FOUND == dwRetCode ) { if( fMigratedPIN ) { DisplayMessage(L"Migrate: Migrated PIN, DefaultPassword does not exist.\n"); dwRetCode = ERROR_SUCCESS; } else { DisplayMessage(L"Migrate failed: DefaultPassword does not exist.\n"); } goto cleanup; }
if( ERROR_SUCCESS != dwRetCode ) { _snwprintf(g_TempString, MAX_STRING - 1, L"Migrate failed: Could not read DefaultPassword: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
//
// Set the DefaultPassword LSASecret to the value we retrieved
// from the registry
//
dwRetCode = SetSecret(Password, FALSE, g_PasswordSecretName); if( ERROR_SUCCESS != dwRetCode ) { _snwprintf(g_TempString, MAX_STRING - 1, L"Migrate failed: Could not set DefaultPassword LSASecret: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
// Delete the DefaultPassword registry key
dwRetCode = ClearRegValue(g_PasswordSecretName); if( ERROR_SUCCESS != dwRetCode ) { //
// delete the secret if could not remove the password.
//
(void)SetSecret(NULL, TRUE, g_PasswordSecretName);
_snwprintf(g_TempString, MAX_STRING - 1, L"Migrate Failed: Could not delete DefaultPassword key: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
DisplayMessage(L"Password migrated from Registry to LSASecret\n");
cleanup: // zero out the password so it's not left in memory
SecureZeroMemory(Password, MAX_STRING * sizeof(WCHAR)); return dwRetCode; }
//+----------------------------------------------------------------------------
//
// Delete
//
// - Deletes the secret and the autoadmin logon value
// - Silently ignores the file not found cases
//
//+----------------------------------------------------------------------------
DWORD Delete() { DWORD dwRetCode = ERROR_SUCCESS;
//
// make sure we're running against a correct version of NT
//
if (CheckWinVersion() != ERROR_SUCCESS) { dwRetCode = ERROR_OLD_WIN_VERSION; goto cleanup; }
dwRetCode = ClearRegValue(g_PasswordSecretName);
if( (ERROR_SUCCESS != dwRetCode) && (ERROR_FILE_NOT_FOUND != dwRetCode) ) { _snwprintf(g_TempString, MAX_STRING - 1, L"Delete: Registry default password delete failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
dwRetCode = SetSecret(NULL, TRUE, g_PasswordSecretName); if( (ERROR_SUCCESS != dwRetCode) && (ERROR_FILE_NOT_FOUND != dwRetCode) ) { _snwprintf(g_TempString, MAX_STRING - 1, L"Delete: LSA Secret delete failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
dwRetCode = ClearRegValue(g_PinSecretName); if( (ERROR_SUCCESS != dwRetCode) && (ERROR_FILE_NOT_FOUND != dwRetCode) ) { #ifdef PRIVATE_VERSION
_snwprintf(g_TempString, MAX_STRING - 1, L"Delete: Registry default pin delete failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); #endif
}
dwRetCode = SetSecret(NULL, TRUE, g_PinSecretName); if( (ERROR_SUCCESS != dwRetCode) && (ERROR_FILE_NOT_FOUND != dwRetCode) ) { #ifdef PRIVATE_VERSION
_snwprintf(g_TempString, MAX_STRING - 1, L"Delete: LSA Secret(PIN) delete failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); #endif
}
//
// disable the autologon - if it fails don't recover - the autologon
// will pretty much fail anyway
//
dwRetCode = SetRegValueSZ(g_AutoAdminLogonName, L"0"); if( ERROR_SUCCESS != dwRetCode ) { _snwprintf(g_TempString, MAX_STRING - 1, L"Delete: AutoAdminLogon reg value reset failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
dwRetCode = ClearRegValue(g_AutoLogonCountName); if( (ERROR_SUCCESS != dwRetCode) && (ERROR_FILE_NOT_FOUND != dwRetCode) ) { _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : Set Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
dwRetCode = ERROR_SUCCESS; DisplayMessage(L"AutoAdminLogon disabled.\n");
cleanup: return dwRetCode; }
//+----------------------------------------------------------------------------
//
// EnableAutoLogon
//
// - gets the username/pwd
// - sets the username/domain
// - sets the autlogon count if specified and != 0
// - sets the LSA secret
// - sets the autoadminlogon
// - if autoadminlogon fails then tries to delete the LSA secret
//
//+----------------------------------------------------------------------------
DWORD EnableAutoLogon() { DWORD dwRetCode = ERROR_SUCCESS; WCHAR* pBackSlash = NULL; WCHAR* pAtSign = NULL;
//
// make sure we're running against a correct version of NT
//
if (CheckWinVersion() != ERROR_SUCCESS) { dwRetCode = ERROR_OLD_WIN_VERSION; goto cleanup; }
//
// fill in the user name: try both NameUserPrincipal and NameSamCompatible
//
if( !*g_UserName ) { ULONG uSize = MAX_STRING - 1; if( !GetUserNameEx(NameUserPrincipal, g_UserName, &uSize) ) { uSize = MAX_STRING - 1; if( !GetUserNameEx(NameSamCompatible, g_UserName, &uSize) ) { dwRetCode = GetLastError(); _snwprintf(g_TempString, MAX_STRING - 1, L"Set: Could not get the logged on user name: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; } } }
//
// Make sure we have correct information passed in
//
if( !g_SetDefaultPIN && !*g_UserName ) { DisplayMessage(L"Set: Failed: Username does not exist.\n"); dwRetCode = ERROR_BAD_ARGUMENTS; goto cleanup; }
//
// this call uses CredMan on XP
//
dwRetCode = GetPassword(); if( ERROR_SUCCESS != dwRetCode ) { _snwprintf(g_TempString, MAX_STRING - 1, L"Set: Failed to get the password: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
if( !g_SetDefaultPIN ) { //
// if a domain specified in the form of domain\username extract it
// Proper formats are
// Case 1: /username:JohnDoe
// Case 2: /username: [email protected]
// Case 3: /username:Domain\JohnDoe
//
//
// is '\' present?
//
pBackSlash = wcschr(g_UserName, '\\'); if( NULL != pBackSlash ) { //
// Case 3, copy into both user and domain buffer
// Domain is first as we don't want to overwrite the buffer
// Yes, wcsncpy works from beggining to the end ;-)
//
wcsncpy(g_DomainName, g_UserName, __min(MAX_STRING - 1, (pBackSlash - g_UserName)) ); g_DomainName[MAX_STRING - 1] = 0;
wcsncpy(g_UserName, pBackSlash + 1, MAX_STRING - 1); g_UserName[MAX_STRING - 1] = 0; } else { //
// if we have @ in the user name delete the domain
//
pAtSign = wcschr(g_UserName, '@'); g_DomainName[0] = 0; } }
//
// Deletes the reg password value
//
if( g_SetDefaultPIN ) { dwRetCode = ClearRegValue(g_PinSecretName); } else { dwRetCode = ClearRegValue(g_PasswordSecretName); }
if( (ERROR_SUCCESS != dwRetCode) && (ERROR_FILE_NOT_FOUND != dwRetCode) ) { _snwprintf(g_TempString, MAX_STRING - 1, L"RegPassword : Reset Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
if( !g_SetDefaultPIN ) { //
// sets the username
//
dwRetCode = SetRegValueSZ(g_DefaultUserName, g_UserName); if( ERROR_SUCCESS != dwRetCode ) { _snwprintf(g_TempString, MAX_STRING - 1, L"UserName : Set Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
_snwprintf(g_TempString, MAX_STRING - 1, L"UserName : %s\n", g_UserName); DisplayMessage(g_TempString); }
if( !g_SetDefaultPIN ) { //
// sets the domain, if any or pAtSign is not NULL
//
if( *g_DomainName || pAtSign ) { SetRegValueSZ(g_DefaultDomainName, g_DomainName); if( ERROR_SUCCESS != dwRetCode ) { _snwprintf(g_TempString, MAX_STRING - 1, L"DomainName : Set Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; } _snwprintf(g_TempString, MAX_STRING - 1, L"DomainName : %s\n", g_DomainName); DisplayMessage(g_TempString); } }
//
// set the AutoLogonCount if not 0
//
if( g_AutoLogonCount ) { dwRetCode = SetRegValueDWORD(g_AutoLogonCountName, g_AutoLogonCount);
if( ERROR_SUCCESS != dwRetCode ) { _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : Set Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; } _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : %#x\n", g_AutoLogonCount); DisplayMessage(g_TempString); } else { dwRetCode = ClearRegValue(g_AutoLogonCountName);
if( (ERROR_SUCCESS != dwRetCode) && (ERROR_FILE_NOT_FOUND != dwRetCode) ) { _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : Clear Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; } _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : (Disabled)\n"); DisplayMessage(g_TempString); }
//
// set the password
//
if( g_SetDefaultPIN ) { dwRetCode = SetSecret(g_Password, FALSE, g_PinSecretName); } else { dwRetCode = SetSecret(g_Password, FALSE, g_PasswordSecretName); }
if( ERROR_SUCCESS != dwRetCode) { _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret : Set Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
#ifdef PRIVATE_VERSION
_snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret : %s\n", g_Password); #else
_snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret : (set)\n"); #endif
DisplayMessage(g_TempString);
if( !g_SetDefaultPIN ) { //
// set the AutoAdminLogon regvalue to 1
//
dwRetCode = SetRegValueSZ(g_AutoAdminLogonName, L"1"); if( ERROR_SUCCESS != dwRetCode ) { //
// (try to) clear the secret if this fails
//
(void)SetSecret(NULL, TRUE, g_PasswordSecretName);
_snwprintf(g_TempString, MAX_STRING - 1, L"AutoAdminLogon: Set Failed: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
DisplayMessage(L"AutoAdminLogon : 1\n"); }
cleanup: SecureZeroMemory(g_Password, MAX_STRING * sizeof(WCHAR)); return dwRetCode; }
//+----------------------------------------------------------------------------
//
// DumpCmd
//
// - Help
//
//+----------------------------------------------------------------------------
DWORD DumpCmd() { if (g_QuietMode) { return ERROR_SUCCESS; }
wprintf(L"\nAUTOLOGON v1.00 : (c) 2001, Microsoft Corporation\n\n"); wprintf(L"DESCRIPTION:\n"); wprintf(L" Used to configure encrypted autologon functionality\n\n"); wprintf(L"USAGE:\n"); wprintf(L" AUTOLOGON [/?] [/Quiet] [/Migrate] [/Delete] [/Set]\n"); wprintf(L" [/Username:username] [/Count:count]\n"); wprintf(L" Options:\n"); wprintf(L" /? Display complete help documentation\n"); wprintf(L" /Quiet Enable quiet mode, which supresses all output\n"); wprintf(L" /Migrate Migrate cleartext password from registry to LSASecret\n"); wprintf(L" /Delete Deletes the default password and disable AutoAdminLogon \n"); wprintf(L" /Set Set the DefaultPassword LSASecret and enable AutoAdminLogon\n"); wprintf(L" /Username The username to set in Default UserName.\n"); wprintf(L" /Count Set the logoncount\n"); #ifdef PRIVATE_VERSION
wprintf(L" /Pin Set the DefaultPin LSASecret\n"); wprintf(L" /List List autologon settings\n"); wprintf(L" /Target The remote computer name\n"); #endif
if( g_FullHelp ) { wprintf(L"\nNOTES:\n"); wprintf(L" 1.The /Migrate /Delete /Set commands are exclusive.\n"); wprintf(L" You will always be prompted for a password.\n"); wprintf(L" If a username is not specified the currently logged on user is assumed.\n"); wprintf(L" If no count is specified a count of 0 is implicitely assumed.\n\n"); wprintf(L" 2.You need to be running as a member of the local administrators group for\n"); wprintf(L" this utility to work properly.\n\n"); wprintf(L" 3.When setting a password that has special characters in it, such as \"|>&\n"); wprintf(L" make sure that you escape these characters. Also, passwords with spaces \n"); wprintf(L" should be enclosed in double quotes.\n\n"); wprintf(L" 4.Setting the logoncount to 0 means an autologon will be performed until\n"); wprintf(L" the secret is deleted.\n\n"); } return ERROR_SUCCESS; }
//+----------------------------------------------------------------------------
//
// DumpAutoLogonInfo
//
// - Dumps relevant data
//
//+----------------------------------------------------------------------------
#ifdef PRIVATE_VERSION
DWORD DumpAutoLogonInfo() { WCHAR wcsTempString[MAX_STRING]; DWORD dwRetCode = ERROR_SUCCESS;
//
// make sure we're running against a correct version of NT
//
if (CheckWinVersion() != ERROR_SUCCESS) { dwRetCode = ERROR_OLD_WIN_VERSION; goto cleanup; }
//
// Get the username
//
dwRetCode = GetRegValueSZ(g_DefaultUserName, wcsTempString, MAX_STRING - 1); switch (dwRetCode) { // catch this case and continue
case ERROR_FILE_NOT_FOUND: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultUserName : (regvalue does not exist)\n"); DisplayMessage(g_TempString); break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultUserName : %s\n", wcsTempString); DisplayMessage(g_TempString); break;
// catch all the generic errors and end
default: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultUserName : Failed to query regkey: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
//
// Get the DefaultDomainName
//
dwRetCode = GetRegValueSZ(g_DefaultDomainName, wcsTempString, MAX_STRING - 1); switch (dwRetCode) { // catch this case and continue
case ERROR_FILE_NOT_FOUND: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultDomainName: (regvalue does not exist)\n"); DisplayMessage(g_TempString); break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultDomainName: %s\n", wcsTempString); DisplayMessage(g_TempString); break;
// catch all the generic errors and end
default: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultDomainName: Failed to query regkey: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
//
// Get the DefaultPassword
//
dwRetCode = GetRegValueSZ(g_PasswordSecretName, wcsTempString, MAX_STRING - 1); switch (dwRetCode) { // catch this case and continue
case ERROR_FILE_NOT_FOUND: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultPassword : (regvalue does not exist)\n"); DisplayMessage(g_TempString); break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultPassword : %s\n", wcsTempString); DisplayMessage(g_TempString); break;
// catch all the generic errors and end
default: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultPassword : Failed to query regkey: %s\n", GetErrorString(dwRetCode)); goto cleanup; }
//
// Get the DefaultPin - display it only if there
//
dwRetCode = GetRegValueSZ(g_PinSecretName, wcsTempString, MAX_STRING - 1); switch (dwRetCode) { // catch this case and continue
case ERROR_FILE_NOT_FOUND: break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"DefaultPIN : %s\n", wcsTempString); DisplayMessage(g_TempString); break;
// catch all the generic errors and continue
default: break; }
//
// Get the AutoAdminLogonCount
//
dwRetCode = GetRegValueDWORD(g_AutoLogonCountName, &g_AutoLogonCount); switch (dwRetCode) { // catch this case and continue
case ERROR_FILE_NOT_FOUND: _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : (regvalue does not exist)\n"); DisplayMessage(g_TempString); break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : %#x\n", g_AutoLogonCount); DisplayMessage(g_TempString); break;
// catch all the generic errors and end
default: _snwprintf(g_TempString, MAX_STRING - 1, L"AutoLogonCount : Failed to query regkey: %s\n", GetErrorString(dwRetCode)); goto cleanup; }
//
// Get the LSASecret DefaultPassword
//
dwRetCode = GetSecret(wcsTempString, MAX_STRING - 1, g_PasswordSecretName); switch (dwRetCode) { // catch this case and continue
case STATUS_OBJECT_NAME_NOT_FOUND: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret : (secret does not exist)\n"); DisplayMessage(g_TempString); break;
// catch this case and continue
case ERROR_ACCESS_DENIED: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret : (access denied)\n"); DisplayMessage(g_TempString); break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret : %s\n", wcsTempString); DisplayMessage(g_TempString); break;
// catch all the generic errors and end
default: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret : Failed to query LSASecret: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
//
// Get the LSASecret DefaultPin
//
dwRetCode = GetSecret(wcsTempString, MAX_STRING - 1, g_PinSecretName); switch (dwRetCode) { // catch this case and continue
case STATUS_OBJECT_NAME_NOT_FOUND: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret(PIN) : (secret does not exist)\n"); DisplayMessage(g_TempString); break;
// catch this case and continue
case ERROR_ACCESS_DENIED: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret(PIN) : (access denied)\n"); DisplayMessage(g_TempString); break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret(PIN) : %s\n", wcsTempString); DisplayMessage(g_TempString); break;
// catch all the generic errors and end
default: _snwprintf(g_TempString, MAX_STRING - 1, L"LSASecret(PIN) : Failed to query LSASecret: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); goto cleanup; }
//
// Get the AutoAdminLogon
//
dwRetCode = GetRegValueSZ(g_AutoAdminLogonName, wcsTempString, MAX_STRING - 1); switch (dwRetCode) { // catch this case and continue
case ERROR_FILE_NOT_FOUND: _snwprintf(g_TempString, MAX_STRING - 1, L"AutoAdminLogon : (regvalue does not exist)\n"); DisplayMessage(g_TempString); break;
// On success, print the regkey and continue to next item
case ERROR_SUCCESS: _snwprintf(g_TempString, MAX_STRING - 1, L"AutoAdminLogon : %s\n", wcsTempString); DisplayMessage(g_TempString); break;
// catch all the generic errors and end
default: _snwprintf(g_TempString, MAX_STRING - 1, L"AutoAdminLogon : Failed to query regkey: %s\n", GetErrorString(dwRetCode)); goto cleanup; }
cleanup: SecureZeroMemory(g_TempString, MAX_STRING * sizeof(WCHAR)); SecureZeroMemory(wcsTempString, MAX_STRING * sizeof(WCHAR)); return dwRetCode;
} #endif
//+----------------------------------------------------------------------------
//
// SetCommand
//
// - Sets the command
// - if there are two successive calls to this it will fail - as in two
// commands passed in the command line
// - a call greater with than COMMAND line resets the command to COMMAND_HELP
//
//+----------------------------------------------------------------------------
DWORD SetCommand(UINT uCommand) { DWORD dwRetCode = ERROR_SUCCESS; if( COMMAND_NOT_SET == uCommand ) { g_uCommand = COMMAND_NOT_SET; goto cleanup; }
//
// if already set, fail
//
if( COMMAND_NOT_SET != g_uCommand ) { dwRetCode = ERROR_BAD_ARGUMENTS; goto cleanup; }
if( g_uCommand > COMMAND_SIZE ) { //
// assert?
//
g_uCommand = COMMAND_HELP; } else { g_uCommand = uCommand; }
cleanup: return dwRetCode; }
//+----------------------------------------------------------------------------
//
// SetQuietMode
//
//+----------------------------------------------------------------------------
DWORD SetQuietMode(WCHAR* pszData) { UNREFERENCED_PARAMETER(pszData);
g_QuietMode = TRUE; return ERROR_SUCCESS; }
//+----------------------------------------------------------------------------
//
// SetUserName
//
// - Sets the username
// - Proper formats are combinations of
// /username:"user name"
// /username username
// /username: " user name"
//
// - returns ERROR_FILE_NOT_FOUND when the arg is missing so the caller can
// move on to the next parameter
//+----------------------------------------------------------------------------
DWORD SetUserName(WCHAR* pszData) { DWORD dwRetCode = ERROR_SUCCESS; WCHAR* pCh = NULL;
//
// is ":" present?
//
pCh = wcschr(pszData, ':'); if( NULL == pCh ) { pCh = pszData; } else { pCh++; }
//
// scan past any leading spaces - we KNOW this is NULL terminated
//
while( iswspace(*pCh) ) { pCh++; }
//
// column followed by spaces only
//
if( !*pCh ) { dwRetCode = ERROR_FILE_NOT_FOUND; goto cleanup; }
//
// if we're still at the leading '/' then it means we have the
// /U username case
//
if( '/' == *pCh ) { dwRetCode = ERROR_FILE_NOT_FOUND; goto cleanup; }
wcsncpy(g_UserName, pCh, MAX_STRING - 1); g_UserName[MAX_STRING - 1] = 0;
cleanup: return dwRetCode; }
#ifdef PRIVATE_VERSION
//+----------------------------------------------------------------------------
//
// SetMachineName
//
//+----------------------------------------------------------------------------
DWORD SetMachineName(WCHAR* pszData) { DWORD dwRetCode = ERROR_SUCCESS; WCHAR* pCh = NULL;
//
// is ":" present?
//
pCh = wcschr(pszData, ':'); if( NULL == pCh ) { pCh = pszData; } else { pCh++; }
//
// scan past any leading spaces - we KNOW this is NULL terminated
//
while( iswspace(*pCh) ) { pCh++; }
//
// column followed by spaces only
//
if( !*pCh ) { dwRetCode = ERROR_FILE_NOT_FOUND; goto cleanup; }
//
// if we're still at the leading '/' then it means we have the
// /U username case
//
if( '/' == *pCh ) { dwRetCode = ERROR_FILE_NOT_FOUND; goto cleanup; }
g_RemoteOperation = TRUE; wcsncpy(g_RemoteComputerName, pCh, MAX_STRING - 1); g_RemoteComputerName[MAX_STRING - 1] = 0;
cleanup: return dwRetCode; } #endif
//+----------------------------------------------------------------------------
//
// SetCount
//
// - Sets the count
// - Proper formats are combinations of
// /Count:300
// /Count 300
// /Count: 300
//
// - returns ERROR_FILE_NOT_FOUND when the arg is missing so the caller can
// move on to the next parameter
//+----------------------------------------------------------------------------
DWORD SetCount(WCHAR* pszData) { DWORD dwRetCode = ERROR_SUCCESS; WCHAR* pEndString = NULL; UINT Count = 0;
//
// is ":" present?
//
WCHAR* pCh = wcschr(pszData, ':'); if( NULL == pCh ) { pCh = pszData; } else { pCh++; }
//
// scan past any leading spaces - we KNOW this is NULL terminated
//
while ( iswspace(*pCh) ) { pCh++; }
//
// column followed by spaces only
//
if( !*pCh ) { dwRetCode = ERROR_FILE_NOT_FOUND; goto cleanup;
}
Count = wcstoul(pCh, &pEndString, 0); if( *pEndString ) { if( pEndString != pCh ) { //
// If the input is incorrect
//
dwRetCode = ERROR_BAD_ARGUMENTS; DisplayMessage(L"Count: Failed: Not a number.\n"); } else { //
// this means we run into a "/C 100" case and we have to move
// to the next argument
//
dwRetCode = ERROR_FILE_NOT_FOUND; } goto cleanup; }
//
// Ignore if 0
//
if( Count ) { g_AutoLogonCount = (DWORD)Count; }
cleanup: return dwRetCode; }
//+----------------------------------------------------------------------------
//
// CredMan call data
//
// We have to dinamically load the dll and call into it as it is not present
// Win2k, NT4
//
//+----------------------------------------------------------------------------
//
// CredMan function
//
typedef DWORD (*PCredUIFunction) ( PCTSTR pszTargetName, PCtxtHandle Reserved, DWORD dwAuthError, PCTSTR pszUserName, ULONG ulUserNameMaxChars, PCTSTR pszPassword, ULONG ulPasswordMaxChars, PBOOL pfSave, DWORD dwFlags );
//+----------------------------------------------------------------------------
//
// GetPassword
//
// - tries to load credui dll and if not there
// falls back on regular console functions
//
//+----------------------------------------------------------------------------
DWORD GetPassword() { DWORD dwRetCode = ERROR_INVALID_FUNCTION; BOOL fSave = FALSE; PCredUIFunction pCredUICmdLinePromptForCredentials = NULL; HMODULE hModule = NULL;
do { //
// Try see if CredMan is present
//
hModule = LoadLibrary(L"credui.dll");
if( NULL == hModule ) { break; }
//
// get function pointer
//
pCredUICmdLinePromptForCredentials = (PCredUIFunction)GetProcAddress( hModule, "CredUICmdLinePromptForCredentialsW");
if( NULL == pCredUICmdLinePromptForCredentials ) { break; }
//
// CREDUI_FLAGS_DO_NOT_PERSIST - autologon pwd should not be persisted
// CREDUI_FLAGS_VALIDATE_USERNAME - just a precaution
// CREDUI_FLAGS_EXCLUDE_CERTIFICATES - we don't want this for autologon
// CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS - prevents 'connect to'
// string to be displayed and since target is AutoAdminLogon
// it boils down to a nice prompt. Note that this flag will skip
// the user name, but we assume the username is already filled in
//
dwRetCode = pCredUICmdLinePromptForCredentials( L"AutoAdminLogon", // PCTSTR pszTargetName
NULL, // PCtxtHandle Reserved
NO_ERROR, // DWORD dwAuthError
g_UserName, // PCTSTR pszUserName
MAX_STRING - 1, // ULONG ulUserNameMaxChars
g_Password, // PCTSTR pszPassword
MAX_STRING - 1, // ULONG ulPasswordMaxChars
&fSave, // PBOOL pfSave,
// DWORD dwFlags
CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_VALIDATE_USERNAME | CREDUI_FLAGS_EXCLUDE_CERTIFICATES | CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS );
} while( FALSE );
//
// if CredMan is not present then just try the console input;
// pass similar strings (though non localized)
//
if( ERROR_INVALID_FUNCTION == dwRetCode ) { //
// if user has not been specified
//
if( !*g_UserName ) { dwRetCode = GetConsoleStr(g_UserName, MAX_STRING - 1, FALSE, L"Enter the user name for AutoAdminLogon: ", NULL); if( ERROR_SUCCESS != dwRetCode ) { goto cleanup; } }
dwRetCode = GetConsoleStr(g_Password, MAX_STRING - 1, TRUE, L"Enter the password for AutoAdminLogon: ", NULL); if( ERROR_SUCCESS != dwRetCode ) { goto cleanup; } } goto cleanup;
cleanup: if( hModule ) { FreeLibrary(hModule); } return dwRetCode; }
//+----------------------------------------------------------------------------
//
// CheckWinVersion
// - currently any OS post NT4/SP7 supports this.
// - the remote case (which we do not support yet) assumes remote NT4
// as being pre-SP7...
//
//+----------------------------------------------------------------------------
DWORD CheckWinVersion() { DWORD dwMachineVerNumber = 0; DWORD dwRetCode = ERROR_SUCCESS; OSVERSIONINFOEX versionInfoEx; NET_API_STATUS status;
// Make sure it's a Win2k box
#ifdef PRIVATE_VERSION
if (g_RemoteOperation) { status = GetMajorNTVersion(&dwMachineVerNumber, g_RemoteComputerName); } else #endif
{ status = GetMajorNTVersion(&dwMachineVerNumber, NULL); }
switch (dwMachineVerNumber) { case 3: dwRetCode = ERROR_OLD_WIN_VERSION; _snwprintf(g_TempString, MAX_STRING - 1, L"Error: Running NT3.x\n"); DisplayMessage(g_TempString); break; case 4: //
// Verify SP7 - only locally for now
//
#ifdef PRIVATE_VERSION
if( !g_RemoteOperation ) #endif
{ //
// GetVersionInfoEx call for getting the SP information
//
SecureZeroMemory(&versionInfoEx, sizeof(OSVERSIONINFOEX)); versionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !GetVersionEx((LPOSVERSIONINFO)(&versionInfoEx)) ) { dwRetCode = GetLastError(); _snwprintf(g_TempString, MAX_STRING - 1, L"Error: Running NT4, can't query SP version: %s\n", GetErrorString(dwRetCode)); DisplayMessage(g_TempString); }
if( versionInfoEx.wServicePackMajor < 7 ) { dwRetCode = ERROR_OLD_WIN_VERSION; _snwprintf(g_TempString, MAX_STRING - 1, L"Error: Running NT4 pre SP7\n"); DisplayMessage(g_TempString); break; } }
break; case 5: break; default: _snwprintf(g_TempString, MAX_STRING - 1, L"Error: Unknown target machine version (%#x).\n", status); DisplayMessage(g_TempString); dwRetCode = ERROR_OLD_WIN_VERSION; break; }
return dwRetCode; }
|