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.
 
 
 
 
 
 

1785 lines
52 KiB

/*++
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;
}