diff options
Diffstat (limited to 'private/newsam/client/tmachine.c')
-rw-r--r-- | private/newsam/client/tmachine.c | 902 |
1 files changed, 902 insertions, 0 deletions
diff --git a/private/newsam/client/tmachine.c b/private/newsam/client/tmachine.c new file mode 100644 index 000000000..32b91a1d2 --- /dev/null +++ b/private/newsam/client/tmachine.c @@ -0,0 +1,902 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + tmachine.c + +Abstract: + + This module tests the machine account creation facilities + of SAM. + +Author: + + Jim Kelly (JimK) 7-Feb-1994 + +Environment: + + User Mode - Win32 + +Revision History: + + +--*/ + + + + + + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Includes // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include <nt.h> +#include <ntsam.h> +#include <ntsamp.h> +#include <ntlsa.h> +#include <ntrpcp.h> // prototypes for MIDL user functions +#include <seopaque.h> +#include <string.h> + + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Macros // +// // +/////////////////////////////////////////////////////////////////////////////// + + +#ifndef SHIFT +#define SHIFT(c,v) {c--; v++;} +#endif //SHIFT + + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Routines // +// // +/////////////////////////////////////////////////////////////////////////////// + + +NTSTATUS +TSampGetLsaDomainInfo( + IN PUNICODE_STRING ServerName, + OUT PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo + ) + +/*++ + +Routine Description: + + This routine retrieves ACCOUNT domain information from the LSA + policy database. + + +Arguments: + + ServerName - name of machine to get account domain information + from. + + PolicyAccountDomainInfo - Receives a pointer to a + POLICY_ACCOUNT_DOMAIN_INFO structure containing the account + domain info. + + +Return Value: + + STATUS_SUCCESS - Succeeded. + + Other status values that may be returned from: + + LsaOpenPolicy() + LsaQueryInformationPolicy() +--*/ + +{ + NTSTATUS + NtStatus, + IgnoreStatus; + + LSA_HANDLE + PolicyHandle; + + OBJECT_ATTRIBUTES + PolicyObjectAttributes; + + // + // Open the policy database + // + + InitializeObjectAttributes( &PolicyObjectAttributes, + NULL, // Name + 0, // Attributes + NULL, // Root + NULL ); // Security Descriptor + + NtStatus = LsaOpenPolicy( ServerName, + &PolicyObjectAttributes, + POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle ); + + if ( NT_SUCCESS(NtStatus) ) { + + // + // Query the account domain information + // + + NtStatus = LsaQueryInformationPolicy( PolicyHandle, + PolicyAccountDomainInformation, + (PVOID *)PolicyAccountDomainInfo ); + + + IgnoreStatus = LsaClose( PolicyHandle ); + ASSERT(NT_SUCCESS(IgnoreStatus)); + } + + return(NtStatus); +} + + +NTSTATUS +TSampConnectToServer( + IN PUNICODE_STRING ServerName, + IN ACCESS_MASK DomainAccess, + OUT PHANDLE ServerHandle, + OUT PHANDLE DomainHandle, + OUT PSID *DomainSid + ) + +/*++ + +Routine Description: + + Open a handle to the SAM server on the specified server + and then open the account domain on that same server. + +Arguments: + + ServerName - Name of server to connect to. + + DomainAccess - accesses needed to the account domain. + + ServerHandle - Receives a handle to the SAM server on the specified + system. + + DomainHandle - Receives a handle to the account domain. + + DomainSid - Receives a pointer to the SID of the account domain. + + +Return Value: + + + + +--*/ +{ + NTSTATUS + NtStatus; + + OBJECT_ATTRIBUTES + ObjectAttributes; + + PPOLICY_ACCOUNT_DOMAIN_INFO + AccountDomainInfo; + + // + // get account domain info + // + + NtStatus = TSampGetLsaDomainInfo( ServerName, + &AccountDomainInfo); + + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Failed to get lsa domain info...\n" + " Completion status is 0x%lx\n", NtStatus); + return(NtStatus); + } + printf("SAM TEST: Target domain is %wZ\n", &AccountDomainInfo->DomainName); + + (*DomainSid) = AccountDomainInfo->DomainSid; + + InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL ); + + + NtStatus = SamConnect( + ServerName, + ServerHandle, + SAM_SERVER_READ | SAM_SERVER_EXECUTE, + &ObjectAttributes + ); + + + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Failed to connect...\n" + " Completion status is 0x%lx\n", NtStatus); + return(NtStatus); + } + + + NtStatus = SamOpenDomain( + (*ServerHandle), + DomainAccess, + *DomainSid, + DomainHandle + ); + + if (!NT_SUCCESS(NtStatus)) { + printf("Failed account domain open\n" + " Completion status is 0x%lx\n", NtStatus); + return(NtStatus); + } + + return(STATUS_SUCCESS); + + +} + + +BOOLEAN +TSampEnableMachinePrivilege( VOID ) + +/*++ + +Routine Description: + + This function enabled the SeMachineAccountPrivilege privilege. + +Arguments: + + None. + +Return Value: + + TRUE if privilege successfully enabled. + FALSE if not successfully enabled. + +--*/ +{ + + NTSTATUS Status; + HANDLE Token; + LUID SecurityPrivilege; + PTOKEN_PRIVILEGES NewState; + ULONG ReturnLength; + + + // + // Open our own token + // + + Status = NtOpenProcessToken( + NtCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES, + &Token + ); + if (!NT_SUCCESS(Status)) { + printf("SAM TEST: Can't open process token to enable Privilege.\n" + " Completion status of NtOpenProcessToken() is: 0x%lx\n", Status); + return(FALSE); + } + + + // + // Initialize the adjustment structure + // + + SecurityPrivilege = + RtlConvertLongToLargeInteger(SE_MACHINE_ACCOUNT_PRIVILEGE); + + ASSERT( (sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)) < 100); + NewState = RtlAllocateHeap( RtlProcessHeap(), 0, 100 ); + + NewState->PrivilegeCount = 1; + NewState->Privileges[0].Luid = SecurityPrivilege; + NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + + // + // Set the state of the privilege to ENABLED. + // + + Status = NtAdjustPrivilegesToken( + Token, // TokenHandle + FALSE, // DisableAllPrivileges + NewState, // NewState + 0, // BufferLength + NULL, // PreviousState (OPTIONAL) + &ReturnLength // ReturnLength + ); + // don't use NT_SUCCESS here because STATUS_NOT_ALL_ASSIGNED is a success status + if (Status != STATUS_SUCCESS) { + return(FALSE); + } + + + // + // Clean up some stuff before returning + // + + RtlFreeHeap( RtlProcessHeap(), 0, NewState ); + Status = NtClose( Token ); + ASSERT(NT_SUCCESS(Status)); + + + return TRUE; + +} + + +NTSTATUS +TSampCreateMachine( + IN SAM_HANDLE DomainHandle, + IN PUNICODE_STRING AccountName + ) + +/*++ + +Routine Description: + + This routine attempts to create a machine account. + + One of two cases may be tested: + + 1) DomainHandle is open for DOMAIN_CREATE_USER, + or + 2) DomainHandle is open for DOMAIN_LOOKUP and + the SeMachineAccountPrivilege privilege is + enabled. + + It is the caller's responsibility to establish the + correct case criteria before calling. + +Arguments: + + DomainHandle - handle to domain to create account in. + + AccountName - Name of the account to create. + + +Return Value: + +--*/ + +{ + NTSTATUS + NtStatus, + IgnoreStatus; + + SAM_HANDLE + UserHandle; + + ACCESS_MASK + GrantedAccess; + + ULONG + Rid; + + NtStatus = SamCreateUser2InDomain( DomainHandle, + AccountName, + USER_WORKSTATION_TRUST_ACCOUNT, + MAXIMUM_ALLOWED, + &UserHandle, + &GrantedAccess, + &Rid); + + if (NT_SUCCESS(NtStatus)) { + IgnoreStatus = SamCloseHandle( UserHandle ); + ASSERT(NT_SUCCESS(IgnoreStatus)); + printf("SAM TEST: Machine account created.\n" + " GrantedAccess: 0x%lx\n" + " Rid: %d (0x%lx)\n", + GrantedAccess, Rid, Rid); + } else { + printf("SAM TEST: Machine account creation failed.\n" + " Status: 0x%lx\n", NtStatus); + } + + + return(NtStatus); + + +} + + +NTSTATUS +TSampSetPasswordMachine( + IN SAM_HANDLE DomainHandle, + IN PUNICODE_STRING AccountName, + IN PUNICODE_STRING Password + ) + +/*++ + +Routine Description: + + This routine attempts to set the password of a machine account. + + +Arguments: + + DomainHandle - handle to domain account is in. + + AccountName - Name of the account to set password. + + Password - New password. + +Return Value: + +--*/ + +{ + NTSTATUS + NtStatus; + + SAM_HANDLE + UserHandle; + + PULONG + RelativeIds; + + PSID_NAME_USE + Use; + + USER_SET_PASSWORD_INFORMATION + PasswordInfo; + + + PasswordInfo.Password = (*Password); + PasswordInfo.PasswordExpired = FALSE; + + NtStatus = SamLookupNamesInDomain( DomainHandle, + 1, + AccountName, + &RelativeIds, + &Use); + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Couldn't find account to set password.\n" + " Lookup status: 0x%lx\n", NtStatus); + return(NtStatus); + } + + + NtStatus = SamOpenUser( DomainHandle, + USER_FORCE_PASSWORD_CHANGE, + RelativeIds[0], + &UserHandle); + + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Couldn't open user account for FORCE_PASSWORD_CHANGE.\n" + " Lookup status: 0x%lx\n", NtStatus); + return(NtStatus); + } + + NtStatus = SamSetInformationUser( UserHandle, + UserSetPasswordInformation, + &PasswordInfo + ); + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Couldn't set password on user account.\n" + " Set Info status: 0x%lx\n", NtStatus); + return(NtStatus); + } + + + return(STATUS_SUCCESS); + + +} + + +NTSTATUS +TSampDeleteMachine( + IN SAM_HANDLE DomainHandle, + IN PUNICODE_STRING AccountName + ) + +/*++ + +Routine Description: + + This routine attempts to delete a machine account. + + +Arguments: + + DomainHandle - handle to domain to delete account from. + + AccountName - Name of the account to delete. + + +Return Value: + +--*/ + +{ + NTSTATUS + NtStatus; + + SAM_HANDLE + UserHandle; + + PULONG + RelativeIds; + + PSID_NAME_USE + Use; + + NtStatus = SamLookupNamesInDomain( DomainHandle, + 1, + AccountName, + &RelativeIds, + &Use); + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Couldn't find account to delete.\n" + " Lookup status: 0x%lx\n", NtStatus); + return(NtStatus); + } + + + NtStatus = SamOpenUser( DomainHandle, + DELETE, + RelativeIds[0], + &UserHandle); + + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Couldn't open user account for delete.\n" + " Open status: 0x%lx\n", NtStatus); + return(NtStatus); + } + + NtStatus = SamDeleteUser( UserHandle ); + if (!NT_SUCCESS(NtStatus)) { + printf("SAM TEST: Couldn't delete user account.\n" + " DeleteUser status: 0x%lx\n", NtStatus); + return(NtStatus); + } + + + return(STATUS_SUCCESS); + + +} + + +VOID +TSampPrintYesOrNo( + IN BOOLEAN b + ) +{ + if (b) { + printf("Yes\n"); + } else { + printf("No\n"); + } +} + + + +VOID +TSampUsage( VOID ) +{ + + printf("\n\n Command format:\n"); + printf(" tmachine [/c] [/p] [/d] <account-name> <machine> [<password>]\n"); + printf("\n"); + printf(" Switches\n"); + printf(" /c - create account\n"); + printf(" /p - set password on account\n"); + printf(" /d - delete account\n"); + printf("\n"); + printf(" if multiple switches are specified, they are attempted in\n"); + printf(" the order listed above. An error in any attempt will prevent\n"); + printf(" any further attempts.\n"); + printf("\n"); + return; +} + + +VOID +main (c,v) +int c; +char **v; + +/*++ + +Routine Description: + + This is the main entry routine for this test. + +Arguments: + + Argv[1] - account name to create or delete + + Argv[2] - domain controller machine name + + Argv[3] - 'D' to delete account, otherwise account is created. + + + +Return Value: + + + + +--*/ +{ + NTSTATUS + NtStatus, + IgnoreStatus; + + UNICODE_STRING + AccountName, + ControllerName, + Password; + + WCHAR + AccountNameBuffer[80], + ControllerNameBuffer[80], + PasswordBuffer[80]; + + ANSI_STRING + AnsiString; + + SAM_HANDLE + ServerHandle, + ServerHandle2, + DomainHandle, + DomainHandle2; + + PSID + DomainSid; + + BOOLEAN + Create = FALSE, + SetPassword = FALSE, + Delete = FALSE; + + ULONG + ArgNum = 0; + + PCHAR + p; + + CHAR + ch; + + AccountName.Length = 0; + ControllerName.Length = 0; + Password.Length = 0; + + + + // + // Command format: + // + // tmachine [/c] [/p] [/d] <account-name> <machine> [<password>] + // + // Switches + // /c - create account + // /p - set password on account + // /d - delete account + // + // if multiple switches are specified, they are attempted in + // the order listed above. An error in any attempt will prevent + // any further attempts. + // + + SHIFT (c,v); + while ((c > 0) && ((ch = *v[0]))) { + p = *v; + if (ch == '/') { + while (*++p != '\0') { + if ((*p == 'c') || (*p == 'C')) { + Create = TRUE; +// printf("Create\n"); + } else if ((*p == 'p') || (*p == 'P')) { + SetPassword = TRUE; +// printf("SetPassword\n"); + } else if ((*p == 'd') || (*p == 'D')) { + Delete = TRUE; +// printf("Delete\n"); + } else { + TSampUsage(); + return; + } + } + } else { + + switch (ArgNum) { + case 0: + + // + // collecting account name + // + + AccountName.Buffer = AccountNameBuffer; + AccountName.MaximumLength = sizeof(AccountNameBuffer); + RtlInitAnsiString(&AnsiString, (*v)); + RtlAnsiStringToUnicodeString(&AccountName, &AnsiString, FALSE); + +// printf("account: %wZ\n", &AccountName); + break; + + case 1: + + // + // collecting machine name + // + + ControllerName.Buffer = ControllerNameBuffer; + ControllerName.MaximumLength = sizeof(ControllerNameBuffer); + RtlInitAnsiString(&AnsiString, (*v)); + RtlAnsiStringToUnicodeString(&ControllerName, &AnsiString, FALSE); + +// printf("machine: %wZ\n", &ControllerName); + break; + + + case 2: + + // + // collecting password name + // + + Password.Buffer = PasswordBuffer; + Password.MaximumLength = sizeof(PasswordBuffer); + RtlInitAnsiString(&AnsiString, (*v)); + RtlAnsiStringToUnicodeString(&Password, &AnsiString, FALSE); + +// printf("password: %wZ\n", &Password); + break; + + default: + + // + // collecting garbage. + // + + break; + } + + ArgNum++; + } + SHIFT(c,v); + } + + + + printf("parameters:\n"); + printf(" Create Account: "); TSampPrintYesOrNo( Create ); + printf(" Set Password : "); TSampPrintYesOrNo( SetPassword ); + printf(" Delete Account: "); TSampPrintYesOrNo( Delete ); + printf(" Account : *%wZ*\n", &AccountName); + printf(" Machine : *%wZ*\n", &ControllerName); + printf(" Password : *%wZ*\n", &Password); + + + // + // Make sure we don't have conflicting parameters + // + // Rules: + // + // 1) account name is always required. + // 2) password and machine are required if /P was specified. + // 3) machine is optional if /P not specified. + // + // + + if ( (AccountName.Length == 0) || + ( SetPassword && (ControllerName.Length == 0) ) || + ( SetPassword && (Password.Length == 0) ) ) { + TSampUsage(); + return; + } + + + // + // Open the server and the account domain + // + + NtStatus = TSampConnectToServer(&ControllerName, + DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS, + &ServerHandle, + &DomainHandle, + &DomainSid); + + + if (Create) { + // + // try to create the machine account with privilege. + // + + + printf("SAM TEST: Creating machine account with privilege.\n"); + TSampEnableMachinePrivilege(); + NtStatus = TSampCreateMachine( DomainHandle, &AccountName ); + if (NT_SUCCESS(NtStatus)) { + printf(" Status: successful\n"); + } else { + + if (NtStatus == STATUS_ACCESS_DENIED) { + // + // We didn't have the privilege, and didn't have + // the domain open so that it would work without + // the privilege. + // + + printf(" Couldn't create account with privilege (0x%lx)\n" + " Attempting normal creation (without privilege)\n" + , NtStatus); + NtStatus = TSampConnectToServer(&ControllerName, + DOMAIN_LOOKUP | + DOMAIN_READ_PASSWORD_PARAMETERS | + DOMAIN_CREATE_USER, + &ServerHandle2, + &DomainHandle2, + &DomainSid); + if (!NT_SUCCESS(NtStatus)) { + printf(" Can't open domain for CREATE_USER access (0x%lx)\n", NtStatus); + } else { + NtStatus = TSampCreateMachine( DomainHandle2, + &AccountName ); + if (NT_SUCCESS(NtStatus)) { + printf(" Status: successful\n"); + } else { + printf(" Failed: 0x%lx\n", NtStatus); + } + + IgnoreStatus = SamCloseHandle( DomainHandle2 ); + + } + } + if (!NT_SUCCESS(NtStatus)) { + printf(" Status: 0x%lx", NtStatus); + return; + } + } + } + + + if (SetPassword) { + + // + // Try to set the password on the account + // + + printf("SAM TEST: Setting password of account ...\n"); + NtStatus = TSampSetPasswordMachine( DomainHandle, &AccountName, &Password ); + if (NT_SUCCESS(NtStatus)) { + printf(" Status: successful\n"); + } else { + printf(" Status: 0x%lx", NtStatus); + return; + } + } + + + if (Delete) { + + printf("SAM TEST: Deleting account ...\n"); + NtStatus = TSampDeleteMachine( DomainHandle, &AccountName ); + if (NT_SUCCESS(NtStatus)) { + printf(" Status: successful\n"); + } else { + printf(" Status: 0x%lx", NtStatus); + return; + } + } + + + return; +} + |