/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * PURPOSE: System setup * FILE: dll/win32/syssetup/security.c * PROGRAMER: Eric Kohl */ /* INCLUDES *****************************************************************/ #include "precomp.h" #include #include #include #include #define NDEBUG #include #define TICKS_PER_DAY -864000000000LL #define TICKS_PER_MINUTE -600000000LL /* FUNCTIONS ****************************************************************/ NTSTATUS WINAPI SetAccountsDomainSid( PSID DomainSid, LPCWSTR DomainName) { PPOLICY_ACCOUNT_DOMAIN_INFO OrigInfo = NULL; POLICY_ACCOUNT_DOMAIN_INFO Info; LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle; SAM_HANDLE ServerHandle = NULL; SAM_HANDLE DomainHandle = NULL; DOMAIN_NAME_INFORMATION DomainNameInfo; SIZE_T DomainNameLength = 0; NTSTATUS Status; DPRINT("SYSSETUP: SetAccountsDomainSid\n"); if (DomainName != NULL) { DomainNameLength = wcslen(DomainName); if (DomainNameLength > UNICODE_STRING_MAX_CHARS) { return STATUS_INVALID_PARAMETER; } } memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN, &PolicyHandle); if (Status != STATUS_SUCCESS) { DPRINT("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status); return Status; } Status = LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (PVOID *)&OrigInfo); if (Status == STATUS_SUCCESS && OrigInfo != NULL) { if (DomainName == NULL) { Info.DomainName.Buffer = OrigInfo->DomainName.Buffer; Info.DomainName.Length = OrigInfo->DomainName.Length; Info.DomainName.MaximumLength = OrigInfo->DomainName.MaximumLength; } else { Info.DomainName.Buffer = (LPWSTR)DomainName; Info.DomainName.Length = DomainNameLength * sizeof(WCHAR); Info.DomainName.MaximumLength = Info.DomainName.Length + sizeof(WCHAR); } if (DomainSid == NULL) Info.DomainSid = OrigInfo->DomainSid; else Info.DomainSid = DomainSid; } else { Info.DomainName.Buffer = (LPWSTR)DomainName; Info.DomainName.Length = DomainNameLength * sizeof(WCHAR); Info.DomainName.MaximumLength = Info.DomainName.Length + sizeof(WCHAR); Info.DomainSid = DomainSid; } Status = LsaSetInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (PVOID)&Info); if (Status != STATUS_SUCCESS) { DPRINT("LsaSetInformationPolicy failed (Status: 0x%08lx)\n", Status); } if (OrigInfo != NULL) LsaFreeMemory(OrigInfo); LsaClose(PolicyHandle); DomainNameInfo.DomainName.Length = DomainNameLength * sizeof(WCHAR); DomainNameInfo.DomainName.MaximumLength = DomainNameInfo.DomainName.Length + sizeof(WCHAR); DomainNameInfo.DomainName.Buffer = (LPWSTR)DomainName; Status = SamConnect(NULL, &ServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, NULL); if (NT_SUCCESS(Status)) { Status = SamOpenDomain(ServerHandle, DOMAIN_WRITE_OTHER_PARAMETERS, Info.DomainSid, &DomainHandle); if (NT_SUCCESS(Status)) { Status = SamSetInformationDomain(DomainHandle, DomainNameInformation, &DomainNameInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamSetInformationDomain failed (Status: 0x%08lx)\n", Status); } SamCloseHandle(DomainHandle); } else { DPRINT1("SamOpenDomain failed (Status: 0x%08lx)\n", Status); } SamCloseHandle(ServerHandle); } return Status; } /* Hack */ static NTSTATUS SetPrimaryDomain(LPCWSTR DomainName, PSID DomainSid) { PPOLICY_PRIMARY_DOMAIN_INFO OrigInfo = NULL; POLICY_PRIMARY_DOMAIN_INFO Info; LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle; SIZE_T DomainNameLength = 0; NTSTATUS Status; DPRINT1("SYSSETUP: SetPrimaryDomain()\n"); if (DomainName != NULL) { DomainNameLength = wcslen(DomainName); if (DomainNameLength > UNICODE_STRING_MAX_CHARS) { return STATUS_INVALID_PARAMETER; } } memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN, &PolicyHandle); if (Status != STATUS_SUCCESS) { DPRINT("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status); return Status; } Status = LsaQueryInformationPolicy(PolicyHandle, PolicyPrimaryDomainInformation, (PVOID *)&OrigInfo); if (Status == STATUS_SUCCESS && OrigInfo != NULL) { if (DomainName == NULL) { Info.Name.Buffer = OrigInfo->Name.Buffer; Info.Name.Length = OrigInfo->Name.Length; Info.Name.MaximumLength = OrigInfo->Name.MaximumLength; } else { Info.Name.Buffer = (LPWSTR)DomainName; Info.Name.Length = DomainNameLength * sizeof(WCHAR); Info.Name.MaximumLength = Info.Name.Length + sizeof(WCHAR); } if (DomainSid == NULL) Info.Sid = OrigInfo->Sid; else Info.Sid = DomainSid; } else { Info.Name.Buffer = (LPWSTR)DomainName; Info.Name.Length = DomainNameLength * sizeof(WCHAR); Info.Name.MaximumLength = Info.Name.Length + sizeof(WCHAR); Info.Sid = DomainSid; } Status = LsaSetInformationPolicy(PolicyHandle, PolicyPrimaryDomainInformation, (PVOID)&Info); if (Status != STATUS_SUCCESS) { DPRINT("LsaSetInformationPolicy failed (Status: 0x%08lx)\n", Status); } if (OrigInfo != NULL) LsaFreeMemory(OrigInfo); LsaClose(PolicyHandle); return Status; } static VOID InstallBuiltinAccounts(VOID) { LPWSTR BuiltinAccounts[] = { L"S-1-1-0", /* Everyone */ L"S-1-5-4", /* Interactive */ L"S-1-5-6", /* Service */ L"S-1-5-19", /* Local Service */ L"S-1-5-20", /* Network Service */ L"S-1-5-32-544", /* Administrators */ L"S-1-5-32-545", /* Users */ L"S-1-5-32-547", /* Power Users */ L"S-1-5-32-551", /* Backup Operators */ L"S-1-5-32-555"}; /* Remote Desktop Users */ LSA_OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; LSA_HANDLE PolicyHandle = NULL; LSA_HANDLE AccountHandle = NULL; PSID AccountSid; ULONG i; DPRINT("InstallBuiltinAccounts()\n"); memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_CREATE_ACCOUNT, &PolicyHandle); if (!NT_SUCCESS(Status)) { DPRINT1("LsaOpenPolicy failed (Status %08lx)\n", Status); return; } for (i = 0; i < ARRAYSIZE(BuiltinAccounts); i++) { if (!ConvertStringSidToSid(BuiltinAccounts[i], &AccountSid)) { DPRINT1("ConvertStringSidToSid(%S) failed: %lu\n", BuiltinAccounts[i], GetLastError()); continue; } Status = LsaCreateAccount(PolicyHandle, AccountSid, 0, &AccountHandle); if (NT_SUCCESS(Status)) { LsaClose(AccountHandle); } LocalFree(AccountSid); } LsaClose(PolicyHandle); } static VOID InstallPrivileges( HINF hSecurityInf) { LSA_OBJECT_ATTRIBUTES ObjectAttributes; WCHAR szPrivilegeString[256]; WCHAR szSidString[256]; INFCONTEXT InfContext; DWORD i; PSID AccountSid = NULL; NTSTATUS Status; LSA_HANDLE PolicyHandle = NULL; LSA_UNICODE_STRING RightString, AccountName; PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL; PLSA_TRANSLATED_SID2 Sids = NULL; DPRINT("InstallPrivileges()\n"); memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &PolicyHandle); if (!NT_SUCCESS(Status)) { DPRINT1("LsaOpenPolicy failed (Status %08lx)\n", Status); goto done; } if (!SetupFindFirstLineW(hSecurityInf, L"Privilege Rights", NULL, &InfContext)) { DPRINT1("SetupFindFirstLineW failed\n"); goto done; } do { /* Retrieve the privilege name */ if (!SetupGetStringFieldW(&InfContext, 0, szPrivilegeString, ARRAYSIZE(szPrivilegeString), NULL)) { DPRINT1("SetupGetStringFieldW() failed\n"); goto done; } DPRINT("Privilege: %S\n", szPrivilegeString); for (i = 0; i < SetupGetFieldCount(&InfContext); i++) { if (!SetupGetStringFieldW(&InfContext, i + 1, szSidString, ARRAYSIZE(szSidString), NULL)) { DPRINT1("SetupGetStringFieldW() failed\n"); goto done; } DPRINT("SID: %S\n", szSidString); if (szSidString[0] == UNICODE_NULL) continue; if (szSidString[0] == L'*') { DPRINT("Account Sid: %S\n", &szSidString[1]); if (!ConvertStringSidToSid(&szSidString[1], &AccountSid)) { DPRINT1("ConvertStringSidToSid(%S) failed: %lu\n", szSidString, GetLastError()); continue; } } else { DPRINT("Account name: %S\n", szSidString); ReferencedDomains = NULL; Sids = NULL; RtlInitUnicodeString(&AccountName, szSidString); Status = LsaLookupNames2(PolicyHandle, 0, 1, &AccountName, &ReferencedDomains, &Sids); if (ReferencedDomains != NULL) { LsaFreeMemory(ReferencedDomains); } if (!NT_SUCCESS(Status)) { DPRINT1("LsaLookupNames2() failed (Status 0x%08lx)\n", Status); if (Sids != NULL) { LsaFreeMemory(Sids); Sids = NULL; } continue; } } RtlInitUnicodeString(&RightString, szPrivilegeString); Status = LsaAddAccountRights(PolicyHandle, (AccountSid != NULL) ? AccountSid : Sids[0].Sid, &RightString, 1); if (!NT_SUCCESS(Status)) { DPRINT1("LsaAddAccountRights() failed (Status %08lx)\n", Status); } if (Sids != NULL) { LsaFreeMemory(Sids); Sids = NULL; } if (AccountSid != NULL) { LocalFree(AccountSid); AccountSid = NULL; } } } while (SetupFindNextLine(&InfContext, &InfContext)); done: if (PolicyHandle != NULL) LsaClose(PolicyHandle); } static VOID ApplyRegistryValues( HINF hSecurityInf) { WCHAR szRegistryPath[MAX_PATH]; WCHAR szRootName[MAX_PATH]; WCHAR szKeyName[MAX_PATH]; WCHAR szValueName[MAX_PATH]; INFCONTEXT InfContext; DWORD dwLength, dwType; HKEY hRootKey, hKey; PWSTR Ptr1, Ptr2; DWORD dwError; PVOID pBuffer; DPRINT("ApplyRegistryValues()\n"); if (!SetupFindFirstLineW(hSecurityInf, L"Registry Values", NULL, &InfContext)) { DPRINT1("SetupFindFirstLineW failed\n"); return; } do { /* Retrieve the privilege name */ if (!SetupGetStringFieldW(&InfContext, 0, szRegistryPath, ARRAYSIZE(szRegistryPath), NULL)) { DPRINT1("SetupGetStringFieldW() failed\n"); return; } DPRINT("RegistryPath: %S\n", szRegistryPath); Ptr1 = wcschr(szRegistryPath, L'\\'); Ptr2 = wcsrchr(szRegistryPath, L'\\'); if (Ptr1 != NULL && Ptr2 != NULL && Ptr1 != Ptr2) { dwLength = (DWORD)(((ULONG_PTR)Ptr1 - (ULONG_PTR)szRegistryPath) / sizeof(WCHAR)); wcsncpy(szRootName, szRegistryPath, dwLength); szRootName[dwLength] = UNICODE_NULL; Ptr1++; dwLength = (DWORD)(((ULONG_PTR)Ptr2 - (ULONG_PTR)Ptr1) / sizeof(WCHAR)); wcsncpy(szKeyName, Ptr1, dwLength); szKeyName[dwLength] = UNICODE_NULL; Ptr2++; wcscpy(szValueName, Ptr2); DPRINT("RootName: %S\n", szRootName); DPRINT("KeyName: %S\n", szKeyName); DPRINT("ValueName: %S\n", szValueName); if (_wcsicmp(szRootName, L"Machine") == 0) { hRootKey = HKEY_LOCAL_MACHINE; } else { DPRINT1("Unsupported root key %S\n", szRootName); break; } if (!SetupGetIntField(&InfContext, 1, (PINT)&dwType)) { DPRINT1("Failed to get key type (Error %lu)\n", GetLastError()); break; } if (dwType != REG_SZ && dwType != REG_EXPAND_SZ && dwType != REG_BINARY && dwType != REG_DWORD && dwType != REG_MULTI_SZ) { DPRINT1("Invalid value type %lu\n", dwType); break; } dwLength = 0; switch (dwType) { case REG_SZ: case REG_EXPAND_SZ: SetupGetStringField(&InfContext, 2, NULL, 0, &dwLength); dwLength *= sizeof(WCHAR); break; case REG_BINARY: SetupGetBinaryField(&InfContext, 2, NULL, 0, &dwLength); break; case REG_DWORD: dwLength = sizeof(INT); break; case REG_MULTI_SZ: SetupGetMultiSzField(&InfContext, 2, NULL, 0, &dwLength); dwLength *= sizeof(WCHAR); break; } if (dwLength == 0) { DPRINT1("Failed to determine the required buffer size!\n"); break; } dwError = RegCreateKeyExW(hRootKey, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); if (dwError != ERROR_SUCCESS) { DPRINT1("Failed to create the key %S (Error %lu)\n", szKeyName, dwError); break; } pBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); if (pBuffer) { switch (dwType) { case REG_SZ: case REG_EXPAND_SZ: SetupGetStringField(&InfContext, 2, pBuffer, dwLength / sizeof(WCHAR), &dwLength); dwLength *= sizeof(WCHAR); break; case REG_BINARY: SetupGetBinaryField(&InfContext, 2, pBuffer, dwLength, &dwLength); break; case REG_DWORD: SetupGetIntField(&InfContext, 2, pBuffer); break; case REG_MULTI_SZ: SetupGetMultiSzField(&InfContext, 2, pBuffer, dwLength / sizeof(WCHAR), &dwLength); dwLength *= sizeof(WCHAR); break; } RegSetValueEx(hKey, szValueName, 0, dwType, pBuffer, dwLength); HeapFree(GetProcessHeap(), 0, pBuffer); } RegCloseKey(hKey); } } while (SetupFindNextLine(&InfContext, &InfContext)); } static VOID ApplyEventlogSettings( _In_ HINF hSecurityInf, _In_ PWSTR pszSectionName, _In_ PWSTR pszLogName) { INFCONTEXT InfContext; HKEY hServiceKey = NULL, hLogKey = NULL; DWORD dwValue, dwError; BOOL bValueSet; DPRINT("ApplyEventlogSettings(%p %S %S)\n", hSecurityInf, pszSectionName, pszLogName); dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\Eventlog", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hServiceKey, NULL); if (dwError != ERROR_SUCCESS) { DPRINT1("Failed to create the Eventlog Service key (Error %lu)\n", dwError); return; } dwError = RegCreateKeyExW(hServiceKey, pszLogName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hLogKey, NULL); if (dwError != ERROR_SUCCESS) { DPRINT1("Failed to create the key %S (Error %lu)\n", pszLogName, dwError); RegCloseKey(hServiceKey); return; } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"MaximumLogSize", &InfContext)) { DPRINT("MaximumLogSize\n"); dwValue = 0; SetupGetIntField(&InfContext, 1, (PINT)&dwValue); DPRINT("MaximumLogSize: %lu (kByte)\n", dwValue); if (dwValue >= 64 && dwValue <= 4194240) { dwValue *= 1024; DPRINT("MaxSize: %lu\n", dwValue); RegSetValueEx(hLogKey, L"MaxSize", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); } } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"AuditLogRetentionPeriod", &InfContext)) { bValueSet = FALSE; dwValue = 0; SetupGetIntField(&InfContext, 1, (PINT)&dwValue); if (dwValue == 0) { bValueSet = TRUE; } else if (dwValue == 1) { if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"RetentionDays", &InfContext)) { SetupGetIntField(&InfContext, 1, (PINT)&dwValue); dwValue *= 86400; bValueSet = TRUE; } } else if (dwValue == 2) { dwValue = (DWORD)-1; bValueSet = TRUE; } if (bValueSet) { DPRINT("Retention: %lu\n", dwValue); RegSetValueEx(hLogKey, L"Retention", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); } } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"RestrictGuestAccess", &InfContext)) { dwValue = 0; SetupGetIntField(&InfContext, 1, (PINT)&dwValue); if (dwValue == 0 || dwValue == 1) { DPRINT("RestrictGuestAccess: %lu\n", dwValue); RegSetValueEx(hLogKey, L"RestrictGuestAccess", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); } } RegCloseKey(hLogKey); RegCloseKey(hServiceKey); } static VOID ApplyPasswordSettings( _In_ HINF hSecurityInf, _In_ PWSTR pszSectionName) { INFCONTEXT InfContext; PDOMAIN_PASSWORD_INFORMATION PasswordInfo = NULL; PPOLICY_ACCOUNT_DOMAIN_INFO OrigInfo = NULL; LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle = NULL; SAM_HANDLE ServerHandle = NULL; SAM_HANDLE DomainHandle = NULL; INT nValue; NTSTATUS Status; DPRINT("ApplyPasswordSettings()\n"); memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN, &PolicyHandle); if (Status != STATUS_SUCCESS) { DPRINT1("LsaOpenPolicy() failed (Status: 0x%08lx)\n", Status); return; } Status = LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (PVOID *)&OrigInfo); if (!NT_SUCCESS(Status)) { DPRINT1("LsaQueryInformationPolicy() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamConnect(NULL, &ServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("SamConnect() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamOpenDomain(ServerHandle, DOMAIN_READ_PASSWORD_PARAMETERS | DOMAIN_WRITE_PASSWORD_PARAMS, OrigInfo->DomainSid, &DomainHandle); if (!NT_SUCCESS(Status)) { DPRINT1("SamOpenDomain() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamQueryInformationDomain(DomainHandle, DomainPasswordInformation, (PVOID*)&PasswordInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamQueryInformationDomain() failed (Status %08lx)\n", Status); goto done; } DPRINT("MaximumPasswordAge (OldValue) : 0x%I64x\n", PasswordInfo->MaxPasswordAge.QuadPart); if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"MaximumPasswordAge", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { DPRINT("Value: %ld\n", nValue); if (nValue == -1) { PasswordInfo->MaxPasswordAge.QuadPart = 0x8000000000000000; } else if ((nValue >= 1) && (nValue < 1000)) { PasswordInfo->MaxPasswordAge.QuadPart = (LONGLONG)nValue * TICKS_PER_DAY; } DPRINT("MaximumPasswordAge (NewValue) : 0x%I64x\n", PasswordInfo->MaxPasswordAge.QuadPart); } } DPRINT("MinimumPasswordAge (OldValue) : 0x%I64x\n", PasswordInfo->MinPasswordAge.QuadPart); if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"MinimumPasswordAge", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { DPRINT("Wert: %ld\n", nValue); if ((nValue >= 0) && (nValue < 1000)) { if (PasswordInfo->MaxPasswordAge.QuadPart < (LONGLONG)nValue * TICKS_PER_DAY) PasswordInfo->MinPasswordAge.QuadPart = (LONGLONG)nValue * TICKS_PER_DAY; } DPRINT("MinimumPasswordAge (NewValue) : 0x%I64x\n", PasswordInfo->MinPasswordAge.QuadPart); } } DPRINT("MinimumPasswordLength (OldValue) : %lu\n", PasswordInfo->MinPasswordLength); if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"MinimumPasswordLength", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { DPRINT("Value: %ld\n", nValue); if ((nValue >= 0) && (nValue <= 65535)) { PasswordInfo->MinPasswordLength = nValue; } DPRINT("MinimumPasswordLength (NewValue) : %lu\n", PasswordInfo->MinPasswordLength); } } DPRINT("PasswordHistoryLength (OldValue) : %lu\n", PasswordInfo->PasswordHistoryLength); if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"PasswordHistorySize", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { DPRINT("Value: %ld\n", nValue); if ((nValue >= 0) && (nValue <= 65535)) { PasswordInfo->PasswordHistoryLength = nValue; } DPRINT("PasswordHistoryLength (NewValue) : %lu\n", PasswordInfo->PasswordHistoryLength); } } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"PasswordComplexity", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { if (nValue == 0) { PasswordInfo->PasswordProperties &= ~DOMAIN_PASSWORD_COMPLEX; } else { PasswordInfo->PasswordProperties |= DOMAIN_PASSWORD_COMPLEX; } } } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"ClearTextPassword", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { if (nValue == 0) { PasswordInfo->PasswordProperties &= ~DOMAIN_PASSWORD_STORE_CLEARTEXT; } else { PasswordInfo->PasswordProperties |= DOMAIN_PASSWORD_STORE_CLEARTEXT; } } } /* Windows ignores the RequireLogonToChangePassword option */ Status = SamSetInformationDomain(DomainHandle, DomainPasswordInformation, PasswordInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamSetInformationDomain() failed (Status %08lx)\n", Status); goto done; } done: if (PasswordInfo != NULL) SamFreeMemory(PasswordInfo); if (DomainHandle != NULL) SamCloseHandle(DomainHandle); if (ServerHandle != NULL) SamCloseHandle(ServerHandle); if (OrigInfo != NULL) LsaFreeMemory(OrigInfo); if (PolicyHandle != NULL) LsaClose(PolicyHandle); } static VOID ApplyLockoutSettings( _In_ HINF hSecurityInf, _In_ PWSTR pszSectionName) { INFCONTEXT InfContext; PDOMAIN_LOCKOUT_INFORMATION LockoutInfo = NULL; PPOLICY_ACCOUNT_DOMAIN_INFO OrigInfo = NULL; LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle = NULL; SAM_HANDLE ServerHandle = NULL; SAM_HANDLE DomainHandle = NULL; INT nValue; NTSTATUS Status; DPRINT("ApplyLockoutSettings()\n"); memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN, &PolicyHandle); if (Status != STATUS_SUCCESS) { DPRINT1("LsaOpenPolicy() failed (Status: 0x%08lx)\n", Status); return; } Status = LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (PVOID *)&OrigInfo); if (!NT_SUCCESS(Status)) { DPRINT1("LsaQueryInformationPolicy() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamConnect(NULL, &ServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("SamConnect() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamOpenDomain(ServerHandle, DOMAIN_READ_PASSWORD_PARAMETERS | DOMAIN_WRITE_PASSWORD_PARAMS, OrigInfo->DomainSid, &DomainHandle); if (!NT_SUCCESS(Status)) { DPRINT1("SamOpenDomain() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamQueryInformationDomain(DomainHandle, DomainLockoutInformation, (PVOID*)&LockoutInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamQueryInformationDomain() failed (Status %08lx)\n", Status); goto done; } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"LockoutBadCount", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { if (nValue >= 0) { LockoutInfo->LockoutThreshold = nValue; } } } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"ResetLockoutCount", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { if (nValue >= 0) { LockoutInfo->LockoutObservationWindow.QuadPart = (LONGLONG)nValue * TICKS_PER_MINUTE; } } } if (SetupFindFirstLineW(hSecurityInf, pszSectionName, L"LockoutDuration", &InfContext)) { if (SetupGetIntField(&InfContext, 1, &nValue)) { if (nValue == -1) { LockoutInfo->LockoutDuration.QuadPart = 0x8000000000000000LL; } else if ((nValue >= 0) && (nValue < 100000)) { LockoutInfo->LockoutDuration.QuadPart = (LONGLONG)nValue * TICKS_PER_MINUTE; } } } Status = SamSetInformationDomain(DomainHandle, DomainLockoutInformation, LockoutInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamSetInformationDomain() failed (Status %08lx)\n", Status); goto done; } done: if (LockoutInfo != NULL) SamFreeMemory(LockoutInfo); if (DomainHandle != NULL) SamCloseHandle(DomainHandle); if (ServerHandle != NULL) SamCloseHandle(ServerHandle); if (OrigInfo != NULL) LsaFreeMemory(OrigInfo); if (PolicyHandle != NULL) LsaClose(PolicyHandle); } static VOID SetLsaAnonymousNameLookup( _In_ HINF hSecurityInf, _In_ PWSTR pszSectionName) { #if 0 INFCONTEXT InfContext; INT nValue = 0; DPRINT1("SetLsaAnonymousNameLookup()\n"); if (!SetupFindFirstLineW(hSecurityInf, pszSectionName, L"LSAAnonymousNameLookup", &InfContext)) { return; } if (!SetupGetIntField(&InfContext, 1, &nValue)) { return; } if (nValue == 0) { } else { } #endif } static VOID EnableAccount( _In_ HINF hSecurityInf, _In_ PWSTR pszSectionName, _In_ PWSTR pszValueName, _In_ SAM_HANDLE DomainHandle, _In_ DWORD dwAccountRid) { INFCONTEXT InfContext; SAM_HANDLE UserHandle = NULL; PUSER_CONTROL_INFORMATION ControlInfo = NULL; INT nValue = 0; NTSTATUS Status; DPRINT("EnableAccount()\n"); if (!SetupFindFirstLineW(hSecurityInf, pszSectionName, pszValueName, &InfContext)) return; if (!SetupGetIntField(&InfContext, 1, &nValue)) { DPRINT1("No valid integer value\n"); goto done; } DPRINT("Value: %d\n", nValue); Status = SamOpenUser(DomainHandle, USER_READ_ACCOUNT | USER_WRITE_ACCOUNT, dwAccountRid, &UserHandle); if (!NT_SUCCESS(Status)) { DPRINT1("SamOpenUser() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamQueryInformationUser(UserHandle, UserControlInformation, (PVOID*)&ControlInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamQueryInformationUser() failed (Status: 0x%08lx)\n", Status); goto done; } if (nValue == 0) { ControlInfo->UserAccountControl |= USER_ACCOUNT_DISABLED; } else { ControlInfo->UserAccountControl &= ~USER_ACCOUNT_DISABLED; } Status = SamSetInformationUser(UserHandle, UserControlInformation, ControlInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamSetInformationUser() failed (Status: 0x%08lx)\n", Status); } done: if (ControlInfo != NULL) SamFreeMemory(ControlInfo); if (UserHandle != NULL) SamCloseHandle(UserHandle); } static VOID SetNewAccountName( _In_ HINF hSecurityInf, _In_ PWSTR pszSectionName, _In_ PWSTR pszValueName, _In_ SAM_HANDLE DomainHandle, _In_ DWORD dwAccountRid) { INFCONTEXT InfContext; DWORD dwLength = 0; PWSTR pszName = NULL; SAM_HANDLE UserHandle = NULL; USER_NAME_INFORMATION NameInfo; NTSTATUS Status; DPRINT("SetNewAccountName()\n"); if (!SetupFindFirstLineW(hSecurityInf, pszSectionName, pszValueName, &InfContext)) return; SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength); if (dwLength == 0) return; ASSERT(dwLength <= UNICODE_STRING_MAX_CHARS); pszName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(WCHAR)); if (pszName == NULL) { DPRINT1("HeapAlloc() failed\n"); return; } if (!SetupGetStringFieldW(&InfContext, 1, pszName, dwLength, &dwLength)) { DPRINT1("No valid string value\n"); goto done; } DPRINT("NewAccountName: '%S'\n", pszName); Status = SamOpenUser(DomainHandle, USER_WRITE_ACCOUNT, dwAccountRid, &UserHandle); if (!NT_SUCCESS(Status)) { DPRINT1("SamOpenUser() failed (Status: 0x%08lx)\n", Status); goto done; } NameInfo.UserName.Length = (USHORT)wcslen(pszName) * sizeof(WCHAR); NameInfo.UserName.MaximumLength = NameInfo.UserName.Length + sizeof(WCHAR); NameInfo.UserName.Buffer = pszName; NameInfo.FullName.Length = 0; NameInfo.FullName.MaximumLength = 0; NameInfo.FullName.Buffer = NULL; Status = SamSetInformationUser(UserHandle, UserNameInformation, &NameInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamSetInformationUser() failed (Status: 0x%08lx)\n", Status); } done: if (UserHandle != NULL) SamCloseHandle(UserHandle); if (pszName != NULL) HeapFree(GetProcessHeap(), 0, pszName); } static VOID ApplyAccountSettings( _In_ HINF hSecurityInf, _In_ PWSTR pszSectionName) { PPOLICY_ACCOUNT_DOMAIN_INFO OrigInfo = NULL; LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle = NULL; SAM_HANDLE ServerHandle = NULL; SAM_HANDLE DomainHandle = NULL; NTSTATUS Status; DPRINT("ApplyAccountSettings()\n"); memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN, &PolicyHandle); if (Status != STATUS_SUCCESS) { DPRINT1("LsaOpenPolicy() failed (Status: 0x%08lx)\n", Status); return; } Status = LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (PVOID *)&OrigInfo); if (!NT_SUCCESS(Status)) { DPRINT1("LsaQueryInformationPolicy() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamConnect(NULL, &ServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("SamConnect() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamOpenDomain(ServerHandle, DOMAIN_LOOKUP, OrigInfo->DomainSid, &DomainHandle); if (!NT_SUCCESS(Status)) { DPRINT1("SamOpenDomain() failed (Status: 0x%08lx)\n", Status); goto done; } SetLsaAnonymousNameLookup(hSecurityInf, pszSectionName); EnableAccount(hSecurityInf, pszSectionName, L"EnableAdminAccount", DomainHandle, DOMAIN_USER_RID_ADMIN); EnableAccount(hSecurityInf, pszSectionName, L"EnableGuestAccount", DomainHandle, DOMAIN_USER_RID_GUEST); SetNewAccountName(hSecurityInf, pszSectionName, L"NewAdministratorName", DomainHandle, DOMAIN_USER_RID_ADMIN); SetNewAccountName(hSecurityInf, pszSectionName, L"NewGuestName", DomainHandle, DOMAIN_USER_RID_GUEST); done: if (DomainHandle != NULL) SamCloseHandle(DomainHandle); if (ServerHandle != NULL) SamCloseHandle(ServerHandle); if (OrigInfo != NULL) LsaFreeMemory(OrigInfo); if (PolicyHandle != NULL) LsaClose(PolicyHandle); } static VOID ApplyAuditEvents( _In_ HINF hSecurityInf) { LSA_OBJECT_ATTRIBUTES ObjectAttributes; INFCONTEXT InfContext; WCHAR szOptionName[256]; INT nValue; LSA_HANDLE PolicyHandle = NULL; POLICY_AUDIT_EVENTS_INFO AuditInfo; PULONG AuditOptions = NULL; NTSTATUS Status; DPRINT("ApplyAuditEvents(%p)\n", hSecurityInf); if (!SetupFindFirstLineW(hSecurityInf, L"Event Audit", NULL, &InfContext)) { DPRINT1("SetupFindFirstLineW failed\n"); return; } ZeroMemory(&ObjectAttributes, sizeof(LSA_OBJECT_ATTRIBUTES)); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_SET_AUDIT_REQUIREMENTS, &PolicyHandle); if (!NT_SUCCESS(Status)) { DPRINT1("LsaOpenPolicy failed (Status %08lx)\n", Status); return; } AuditOptions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (AuditCategoryAccountLogon + 1) * sizeof(ULONG)); if (AuditOptions == NULL) { DPRINT1("Failed to allocate the auditiing options array!\n"); goto done; } AuditInfo.AuditingMode = TRUE; AuditInfo.EventAuditingOptions = AuditOptions; AuditInfo.MaximumAuditEventCount = AuditCategoryAccountLogon + 1; do { /* Retrieve the group name */ if (!SetupGetStringFieldW(&InfContext, 0, szOptionName, ARRAYSIZE(szOptionName), NULL)) { DPRINT1("SetupGetStringFieldW() failed\n"); continue; } DPRINT("Option: '%S'\n", szOptionName); if (!SetupGetIntField(&InfContext, 1, &nValue)) { DPRINT1("SetupGetStringFieldW() failed\n"); continue; } DPRINT("Value: %d\n", nValue); if ((nValue < POLICY_AUDIT_EVENT_UNCHANGED) || (nValue > POLICY_AUDIT_EVENT_NONE)) { DPRINT1("Invalid audit option!\n"); continue; } if (_wcsicmp(szOptionName, L"AuditSystemEvents") == 0) { AuditOptions[AuditCategorySystem] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditLogonEvents") == 0) { AuditOptions[AuditCategoryLogon] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditObjectAccess") == 0) { AuditOptions[AuditCategoryObjectAccess] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditPrivilegeUse") == 0) { AuditOptions[AuditCategoryPrivilegeUse] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditProcessTracking") == 0) { AuditOptions[AuditCategoryDetailedTracking] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditPolicyChange") == 0) { AuditOptions[AuditCategoryPolicyChange] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditAccountManage") == 0) { AuditOptions[AuditCategoryAccountManagement] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditDSAccess") == 0) { AuditOptions[AuditCategoryDirectoryServiceAccess] = (ULONG)nValue; } else if (_wcsicmp(szOptionName, L"AuditAccountLogon") == 0) { AuditOptions[AuditCategoryAccountLogon] = (ULONG)nValue; } else { DPRINT1("Invalid auditing option '%S'\n", szOptionName); } } while (SetupFindNextLine(&InfContext, &InfContext)); Status = LsaSetInformationPolicy(PolicyHandle, PolicyAuditEventsInformation, (PVOID)&AuditInfo); if (Status != STATUS_SUCCESS) { DPRINT1("LsaSetInformationPolicy() failed (Status 0x%08lx)\n", Status); } done: if (AuditOptions != NULL) HeapFree(GetProcessHeap(), 0, AuditOptions); if (PolicyHandle != NULL) LsaClose(PolicyHandle); } VOID InstallSecurity(VOID) { HINF hSecurityInf; PWSTR pszSecurityInf; // if (IsServer()) // pszSecurityInf = L"defltsv.inf"; // else pszSecurityInf = L"defltwk.inf"; InstallBuiltinAccounts(); hSecurityInf = SetupOpenInfFileW(pszSecurityInf, NULL, INF_STYLE_WIN4, NULL); if (hSecurityInf != INVALID_HANDLE_VALUE) { InstallPrivileges(hSecurityInf); ApplyRegistryValues(hSecurityInf); ApplyEventlogSettings(hSecurityInf, L"Application Log", L"Application"); ApplyEventlogSettings(hSecurityInf, L"Security Log", L"Security"); ApplyEventlogSettings(hSecurityInf, L"System Log", L"System"); ApplyPasswordSettings(hSecurityInf, L"System Access"); ApplyLockoutSettings(hSecurityInf, L"System Access"); ApplyAccountSettings(hSecurityInf, L"System Access"); ApplyAuditEvents(hSecurityInf); SetupCloseInfFile(hSecurityInf); } /* Hack */ SetPrimaryDomain(L"WORKGROUP", NULL); } NTSTATUS SetAdministratorPassword(LPCWSTR Password) { PPOLICY_ACCOUNT_DOMAIN_INFO OrigInfo = NULL; PUSER_ACCOUNT_NAME_INFORMATION AccountNameInfo = NULL; USER_SET_PASSWORD_INFORMATION PasswordInfo; LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle = NULL; SAM_HANDLE ServerHandle = NULL; SAM_HANDLE DomainHandle = NULL; SAM_HANDLE UserHandle = NULL; NTSTATUS Status; DPRINT("SYSSETUP: SetAdministratorPassword(%p)\n", Password); memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN, &PolicyHandle); if (Status != STATUS_SUCCESS) { DPRINT1("LsaOpenPolicy() failed (Status: 0x%08lx)\n", Status); return Status; } Status = LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (PVOID *)&OrigInfo); if (!NT_SUCCESS(Status)) { DPRINT1("LsaQueryInformationPolicy() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamConnect(NULL, &ServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("SamConnect() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamOpenDomain(ServerHandle, DOMAIN_LOOKUP, OrigInfo->DomainSid, &DomainHandle); if (!NT_SUCCESS(Status)) { DPRINT1("SamOpenDomain() failed (Status: 0x%08lx)\n", Status); goto done; } Status = SamOpenUser(DomainHandle, USER_FORCE_PASSWORD_CHANGE | USER_READ_GENERAL, DOMAIN_USER_RID_ADMIN, &UserHandle); if (!NT_SUCCESS(Status)) { DPRINT1("SamOpenUser() failed (Status %08lx)\n", Status); goto done; } RtlInitUnicodeString(&PasswordInfo.Password, Password); PasswordInfo.PasswordExpired = FALSE; Status = SamSetInformationUser(UserHandle, UserSetPasswordInformation, &PasswordInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamSetInformationUser() failed (Status %08lx)\n", Status); goto done; } Status = SamQueryInformationUser(UserHandle, UserAccountNameInformation, (PVOID*)&AccountNameInfo); if (!NT_SUCCESS(Status)) { DPRINT1("SamQueryInformationUser() failed (Status 0x%08lx)\n", Status); goto done; } AdminInfo.Name = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, AccountNameInfo->UserName.Length + sizeof(WCHAR)); if (AdminInfo.Name != NULL) RtlCopyMemory(AdminInfo.Name, AccountNameInfo->UserName.Buffer, AccountNameInfo->UserName.Length); AdminInfo.Domain = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, OrigInfo->DomainName.Length + sizeof(WCHAR)); if (AdminInfo.Domain != NULL) RtlCopyMemory(AdminInfo.Domain, OrigInfo->DomainName.Buffer, OrigInfo->DomainName.Length); AdminInfo.Password = RtlAllocateHeap(RtlGetProcessHeap(), 0, (wcslen(Password) + 1) * sizeof(WCHAR)); if (AdminInfo.Password != NULL) wcscpy(AdminInfo.Password, Password); DPRINT("Administrator Name: %S\n", AdminInfo.Name); DPRINT("Administrator Domain: %S\n", AdminInfo.Domain); DPRINT("Administrator Password: %S\n", AdminInfo.Password); done: if (AccountNameInfo != NULL) SamFreeMemory(AccountNameInfo); if (OrigInfo != NULL) LsaFreeMemory(OrigInfo); if (PolicyHandle != NULL) LsaClose(PolicyHandle); if (UserHandle != NULL) SamCloseHandle(UserHandle); if (DomainHandle != NULL) SamCloseHandle(DomainHandle); if (ServerHandle != NULL) SamCloseHandle(ServerHandle); DPRINT1("SYSSETUP: SetAdministratorPassword() done (Status %08lx)\n", Status); return Status; } VOID SetAutoAdminLogon(VOID) { WCHAR szAutoAdminLogon[2]; HKEY hKey = NULL; DWORD dwType; DWORD dwSize; LONG lError; lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_READ | KEY_WRITE, &hKey); if (lError != ERROR_SUCCESS) return; dwSize = 2 * sizeof(WCHAR); lError = RegQueryValueExW(hKey, L"AutoAdminLogon", NULL, &dwType, (LPBYTE)szAutoAdminLogon, &dwSize); if (lError != ERROR_SUCCESS) goto done; if (wcscmp(szAutoAdminLogon, L"1") == 0) { RegSetValueExW(hKey, L"DefaultDomainName", 0, REG_SZ, (LPBYTE)AdminInfo.Domain, (wcslen(AdminInfo.Domain) + 1) * sizeof(WCHAR)); RegSetValueExW(hKey, L"DefaultUserName", 0, REG_SZ, (LPBYTE)AdminInfo.Name, (wcslen(AdminInfo.Name) + 1) * sizeof(WCHAR)); RegSetValueExW(hKey, L"DefaultPassword", 0, REG_SZ, (LPBYTE)AdminInfo.Password, (wcslen(AdminInfo.Password) + 1) * sizeof(WCHAR)); } done: if (hKey != NULL) RegCloseKey(hKey); } /* EOF */