mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
1203 lines
38 KiB
C
1203 lines
38 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: Security Account Manager (SAM) Server
|
|
* FILE: reactos/dll/win32/samsrv/setup.c
|
|
* PURPOSE: Registry setup routines
|
|
*
|
|
* PROGRAMMERS: Eric Kohl
|
|
*/
|
|
|
|
#include "samsrv.h"
|
|
|
|
#include <ntsecapi.h>
|
|
|
|
#include "resources.h"
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
#define TICKS_PER_SECOND 10000000LL
|
|
|
|
SID_IDENTIFIER_AUTHORITY SecurityNtAuthority = {SECURITY_NT_AUTHORITY};
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
static BOOL
|
|
SampSetupAddMemberToAlias(HKEY hDomainKey,
|
|
ULONG AliasId,
|
|
PSID MemberSid)
|
|
{
|
|
DWORD dwDisposition;
|
|
LPWSTR MemberSidString = NULL;
|
|
WCHAR szKeyName[256];
|
|
HKEY hMembersKey;
|
|
|
|
ConvertSidToStringSidW(MemberSid, &MemberSidString);
|
|
|
|
swprintf(szKeyName, L"Aliases\\%08lX\\Members", AliasId);
|
|
|
|
if (!RegCreateKeyExW(hDomainKey,
|
|
szKeyName,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hMembersKey,
|
|
&dwDisposition))
|
|
{
|
|
RegSetValueEx(hMembersKey,
|
|
MemberSidString,
|
|
0,
|
|
REG_BINARY,
|
|
(LPVOID)MemberSid,
|
|
RtlLengthSid(MemberSid));
|
|
|
|
RegCloseKey(hMembersKey);
|
|
}
|
|
|
|
swprintf(szKeyName, L"Aliases\\Members\\%s", MemberSidString);
|
|
|
|
if (!RegCreateKeyExW(hDomainKey,
|
|
szKeyName,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hMembersKey,
|
|
&dwDisposition))
|
|
{
|
|
swprintf(szKeyName, L"%08lX", AliasId);
|
|
|
|
RegSetValueEx(hMembersKey,
|
|
szKeyName,
|
|
0,
|
|
REG_BINARY,
|
|
(LPVOID)MemberSid,
|
|
RtlLengthSid(MemberSid));
|
|
|
|
RegCloseKey(hMembersKey);
|
|
}
|
|
|
|
if (MemberSidString != NULL)
|
|
LocalFree(MemberSidString);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
SampSetupCreateAliasAccount(HANDLE hDomainKey,
|
|
LPCWSTR lpAccountName,
|
|
LPCWSTR lpDescription,
|
|
ULONG ulRelativeId)
|
|
{
|
|
WCHAR szAccountKeyName[32];
|
|
HANDLE hAccountKey = NULL;
|
|
HANDLE hNamesKey = NULL;
|
|
PSECURITY_DESCRIPTOR Sd = NULL;
|
|
ULONG SdSize = 0;
|
|
NTSTATUS Status;
|
|
|
|
swprintf(szAccountKeyName, L"Aliases\\%08lX", ulRelativeId);
|
|
|
|
Status = SampRegCreateKey(hDomainKey,
|
|
szAccountKeyName,
|
|
KEY_ALL_ACCESS,
|
|
&hAccountKey);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"Name",
|
|
REG_SZ,
|
|
(LPVOID)lpAccountName,
|
|
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"Description",
|
|
REG_SZ,
|
|
(LPVOID)lpDescription,
|
|
(wcslen(lpDescription) + 1) * sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Create the server SD */
|
|
Status = SampCreateAliasSD(&Sd,
|
|
&SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set SecDesc attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"SecDesc",
|
|
REG_BINARY,
|
|
Sd,
|
|
SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegOpenKey(hDomainKey,
|
|
L"Aliases\\Names",
|
|
KEY_ALL_ACCESS,
|
|
&hNamesKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hNamesKey,
|
|
lpAccountName,
|
|
REG_DWORD,
|
|
(LPVOID)&ulRelativeId,
|
|
sizeof(ULONG));
|
|
|
|
done:
|
|
SampRegCloseKey(&hNamesKey);
|
|
|
|
if (Sd != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
|
|
|
|
if (hAccountKey != NULL)
|
|
{
|
|
SampRegCloseKey(&hAccountKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
SampRegDeleteKey(hDomainKey,
|
|
szAccountKeyName);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
SampSetupAddMemberToGroup(IN HANDLE hDomainKey,
|
|
IN ULONG GroupId,
|
|
IN ULONG MemberId)
|
|
{
|
|
WCHAR szKeyName[256];
|
|
HANDLE hGroupKey = NULL;
|
|
PULONG MembersBuffer = NULL;
|
|
ULONG MembersCount = 0;
|
|
ULONG Length = 0;
|
|
ULONG i;
|
|
NTSTATUS Status;
|
|
|
|
swprintf(szKeyName, L"Groups\\%08lX", GroupId);
|
|
|
|
Status = SampRegOpenKey(hDomainKey,
|
|
szKeyName,
|
|
KEY_ALL_ACCESS,
|
|
&hGroupKey);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
Status = SampRegQueryValue(hGroupKey,
|
|
L"Members",
|
|
NULL,
|
|
NULL,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
goto done;
|
|
|
|
MembersBuffer = midl_user_allocate(Length + sizeof(ULONG));
|
|
if (MembersBuffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
{
|
|
Status = SampRegQueryValue(hGroupKey,
|
|
L"Members",
|
|
NULL,
|
|
MembersBuffer,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
MembersCount = Length / sizeof(ULONG);
|
|
}
|
|
|
|
for (i = 0; i < MembersCount; i++)
|
|
{
|
|
if (MembersBuffer[i] == MemberId)
|
|
{
|
|
Status = STATUS_MEMBER_IN_GROUP;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
MembersBuffer[MembersCount] = MemberId;
|
|
Length += sizeof(ULONG);
|
|
|
|
Status = SampRegSetValue(hGroupKey,
|
|
L"Members",
|
|
REG_BINARY,
|
|
MembersBuffer,
|
|
Length);
|
|
|
|
done:
|
|
if (MembersBuffer != NULL)
|
|
midl_user_free(MembersBuffer);
|
|
|
|
SampRegCloseKey(&hGroupKey);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
SampSetupCreateGroupAccount(HANDLE hDomainKey,
|
|
LPCWSTR lpAccountName,
|
|
LPCWSTR lpComment,
|
|
ULONG ulRelativeId)
|
|
{
|
|
SAM_GROUP_FIXED_DATA FixedGroupData;
|
|
WCHAR szAccountKeyName[32];
|
|
HANDLE hAccountKey = NULL;
|
|
HANDLE hNamesKey = NULL;
|
|
PSECURITY_DESCRIPTOR Sd = NULL;
|
|
ULONG SdSize = 0;
|
|
NTSTATUS Status;
|
|
|
|
/* Initialize fixed group data */
|
|
FixedGroupData.Version = 1;
|
|
FixedGroupData.Reserved = 0;
|
|
FixedGroupData.GroupId = ulRelativeId;
|
|
FixedGroupData.Attributes = 0;
|
|
|
|
swprintf(szAccountKeyName, L"Groups\\%08lX", ulRelativeId);
|
|
|
|
Status = SampRegCreateKey(hDomainKey,
|
|
szAccountKeyName,
|
|
KEY_ALL_ACCESS,
|
|
&hAccountKey);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"F",
|
|
REG_BINARY,
|
|
(LPVOID)&FixedGroupData,
|
|
sizeof(SAM_GROUP_FIXED_DATA));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"Name",
|
|
REG_SZ,
|
|
(LPVOID)lpAccountName,
|
|
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"AdminComment",
|
|
REG_SZ,
|
|
(LPVOID)lpComment,
|
|
(wcslen(lpComment) + 1) * sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Create the security descriptor */
|
|
Status = SampCreateGroupSD(&Sd,
|
|
&SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set the SecDesc attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"SecDesc",
|
|
REG_BINARY,
|
|
Sd,
|
|
SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegOpenKey(hDomainKey,
|
|
L"Groups\\Names",
|
|
KEY_ALL_ACCESS,
|
|
&hNamesKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hNamesKey,
|
|
lpAccountName,
|
|
REG_DWORD,
|
|
(LPVOID)&ulRelativeId,
|
|
sizeof(ULONG));
|
|
|
|
done:
|
|
SampRegCloseKey(&hNamesKey);
|
|
|
|
if (Sd != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
|
|
|
|
if (hAccountKey != NULL)
|
|
{
|
|
SampRegCloseKey(&hAccountKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
SampRegDeleteKey(hDomainKey,
|
|
szAccountKeyName);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
SampSetupCreateUserAccount(HANDLE hDomainKey,
|
|
LPCWSTR lpAccountName,
|
|
LPCWSTR lpComment,
|
|
PSID lpDomainSid,
|
|
ULONG ulRelativeId,
|
|
ULONG UserAccountControl)
|
|
{
|
|
SAM_USER_FIXED_DATA FixedUserData;
|
|
GROUP_MEMBERSHIP GroupMembership;
|
|
UCHAR LogonHours[23];
|
|
LPWSTR lpEmptyString = L"";
|
|
WCHAR szAccountKeyName[32];
|
|
HANDLE hAccountKey = NULL;
|
|
HANDLE hNamesKey = NULL;
|
|
PSECURITY_DESCRIPTOR Sd = NULL;
|
|
ULONG SdSize = 0;
|
|
PSID UserSid = NULL;
|
|
NTSTATUS Status;
|
|
|
|
UserSid = AppendRidToSid(lpDomainSid,
|
|
ulRelativeId);
|
|
|
|
/* Create the security descriptor */
|
|
Status = SampCreateUserSD(UserSid,
|
|
&Sd,
|
|
&SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Initialize fixed user data */
|
|
FixedUserData.Version = 1;
|
|
FixedUserData.Reserved = 0;
|
|
FixedUserData.LastLogon.QuadPart = 0;
|
|
FixedUserData.LastLogoff.QuadPart = 0;
|
|
FixedUserData.PasswordLastSet.QuadPart = 0;
|
|
FixedUserData.AccountExpires.QuadPart = MAXLONGLONG;
|
|
FixedUserData.LastBadPasswordTime.QuadPart = 0;
|
|
FixedUserData.UserId = ulRelativeId;
|
|
FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
|
|
FixedUserData.UserAccountControl = UserAccountControl;
|
|
FixedUserData.CountryCode = 0;
|
|
FixedUserData.CodePage = 0;
|
|
FixedUserData.BadPasswordCount = 0;
|
|
FixedUserData.LogonCount = 0;
|
|
FixedUserData.AdminCount = 0;
|
|
FixedUserData.OperatorCount = 0;
|
|
|
|
swprintf(szAccountKeyName, L"Users\\%08lX", ulRelativeId);
|
|
|
|
Status = SampRegCreateKey(hDomainKey,
|
|
szAccountKeyName,
|
|
KEY_ALL_ACCESS,
|
|
&hAccountKey);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"F",
|
|
REG_BINARY,
|
|
(LPVOID)&FixedUserData,
|
|
sizeof(SAM_USER_FIXED_DATA));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"Name",
|
|
REG_SZ,
|
|
(LPVOID)lpAccountName,
|
|
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"FullName",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"HomeDirectory",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"HomeDirectoryDrive",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"ScriptPath",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"ProfilePath",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"AdminComment",
|
|
REG_SZ,
|
|
(LPVOID)lpComment,
|
|
(wcslen(lpComment) + 1) * sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"UserComment",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"WorkStations",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"Parameters",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set LogonHours attribute*/
|
|
*((PUSHORT)LogonHours) = 168;
|
|
memset(&(LogonHours[2]), 0xff, 21);
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"LogonHours",
|
|
REG_BINARY,
|
|
(LPVOID)LogonHours,
|
|
sizeof(LogonHours));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set Groups attribute*/
|
|
GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
|
|
GroupMembership.Attributes = SE_GROUP_MANDATORY |
|
|
SE_GROUP_ENABLED |
|
|
SE_GROUP_ENABLED_BY_DEFAULT;
|
|
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"Groups",
|
|
REG_BINARY,
|
|
(LPVOID)&GroupMembership,
|
|
sizeof(GROUP_MEMBERSHIP));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set LMPwd attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"LMPwd",
|
|
REG_BINARY,
|
|
(LPVOID)&EmptyLmHash,
|
|
sizeof(ENCRYPTED_LM_OWF_PASSWORD));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set NTPwd attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"NTPwd",
|
|
REG_BINARY,
|
|
(LPVOID)&EmptyNtHash,
|
|
sizeof(ENCRYPTED_NT_OWF_PASSWORD));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set LMPwdHistory attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"LMPwdHistory",
|
|
REG_BINARY,
|
|
NULL,
|
|
0);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set NTPwdHistory attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"NTPwdHistory",
|
|
REG_BINARY,
|
|
NULL,
|
|
0);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set PrivateData attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"PrivateData",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set the SecDesc attribute*/
|
|
Status = SampRegSetValue(hAccountKey,
|
|
L"SecDesc",
|
|
REG_BINARY,
|
|
Sd,
|
|
SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegOpenKey(hDomainKey,
|
|
L"Users\\Names",
|
|
KEY_ALL_ACCESS,
|
|
&hNamesKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hNamesKey,
|
|
lpAccountName,
|
|
REG_DWORD,
|
|
(LPVOID)&ulRelativeId,
|
|
sizeof(ULONG));
|
|
|
|
done:
|
|
SampRegCloseKey(&hNamesKey);
|
|
|
|
if (Sd != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
|
|
|
|
if (UserSid != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
|
|
|
|
if (hAccountKey != NULL)
|
|
{
|
|
SampRegCloseKey(&hAccountKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
SampRegDeleteKey(hDomainKey,
|
|
szAccountKeyName);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
SampSetupCreateDomain(IN HANDLE hServerKey,
|
|
IN LPCWSTR lpKeyName,
|
|
IN LPCWSTR lpDomainName,
|
|
IN PSID lpDomainSid,
|
|
IN BOOLEAN bBuiltinDomain,
|
|
OUT HANDLE *lpDomainKey)
|
|
{
|
|
SAM_DOMAIN_FIXED_DATA FixedData;
|
|
WCHAR szDomainKeyName[32];
|
|
LPWSTR lpEmptyString = L"";
|
|
HANDLE hDomainKey = NULL;
|
|
HANDLE hAliasesKey = NULL;
|
|
HANDLE hGroupsKey = NULL;
|
|
HANDLE hUsersKey = NULL;
|
|
HANDLE hNamesKey = NULL;
|
|
PSECURITY_DESCRIPTOR Sd = NULL;
|
|
ULONG SdSize = 0;
|
|
NTSTATUS Status;
|
|
|
|
if (lpDomainKey != NULL)
|
|
*lpDomainKey = NULL;
|
|
|
|
/* Initialize the fixed domain data */
|
|
memset(&FixedData, 0, sizeof(SAM_DOMAIN_FIXED_DATA));
|
|
FixedData.Version = 1;
|
|
NtQuerySystemTime(&FixedData.CreationTime);
|
|
FixedData.DomainModifiedCount.QuadPart = 0;
|
|
FixedData.MaxPasswordAge.QuadPart = -(6LL * 7LL * 24LL * 60LL * 60LL * TICKS_PER_SECOND); /* 6 weeks */
|
|
FixedData.MinPasswordAge.QuadPart = 0; /* right now */
|
|
FixedData.ForceLogoff.QuadPart = LLONG_MAX; /* very far in the future aka never */
|
|
FixedData.LockoutDuration.QuadPart = -(30LL * 60LL * TICKS_PER_SECOND); /* 30 minutes */
|
|
FixedData.LockoutObservationWindow.QuadPart = -(30LL * 60LL * TICKS_PER_SECOND); /* 30 minutes */
|
|
FixedData.ModifiedCountAtLastPromotion.QuadPart = 0;
|
|
FixedData.NextRid = 1000;
|
|
FixedData.PasswordProperties = 0;
|
|
FixedData.MinPasswordLength = 0;
|
|
FixedData.PasswordHistoryLength = 0;
|
|
FixedData.LockoutThreshold = 0;
|
|
FixedData.DomainServerState = DomainServerEnabled;
|
|
FixedData.DomainServerRole = DomainServerRolePrimary;
|
|
FixedData.UasCompatibilityRequired = TRUE;
|
|
|
|
wcscpy(szDomainKeyName, L"Domains\\");
|
|
wcscat(szDomainKeyName, lpKeyName);
|
|
|
|
Status = SampRegCreateKey(hServerKey,
|
|
szDomainKeyName,
|
|
KEY_ALL_ACCESS,
|
|
&hDomainKey);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
/* Set the fixed data value */
|
|
Status = SampRegSetValue(hDomainKey,
|
|
L"F",
|
|
REG_BINARY,
|
|
(LPVOID)&FixedData,
|
|
sizeof(SAM_DOMAIN_FIXED_DATA));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
if (lpDomainSid != NULL)
|
|
{
|
|
Status = SampRegSetValue(hDomainKey,
|
|
L"Name",
|
|
REG_SZ,
|
|
(LPVOID)lpDomainName,
|
|
(wcslen(lpDomainName) + 1) * sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hDomainKey,
|
|
L"SID",
|
|
REG_BINARY,
|
|
(LPVOID)lpDomainSid,
|
|
RtlLengthSid(lpDomainSid));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
}
|
|
|
|
Status = SampRegSetValue(hDomainKey,
|
|
L"OemInformation",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegSetValue(hDomainKey,
|
|
L"ReplicaSourceNodeName",
|
|
REG_SZ,
|
|
(LPVOID)lpEmptyString,
|
|
sizeof(WCHAR));
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Create the Alias container */
|
|
Status = SampRegCreateKey(hDomainKey,
|
|
L"Aliases",
|
|
KEY_ALL_ACCESS,
|
|
&hAliasesKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegCreateKey(hAliasesKey,
|
|
L"Names",
|
|
KEY_ALL_ACCESS,
|
|
&hNamesKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
SampRegCloseKey(&hNamesKey);
|
|
|
|
/* Create the Groups container */
|
|
Status = SampRegCreateKey(hDomainKey,
|
|
L"Groups",
|
|
KEY_ALL_ACCESS,
|
|
&hGroupsKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegCreateKey(hGroupsKey,
|
|
L"Names",
|
|
KEY_ALL_ACCESS,
|
|
&hNamesKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
SampRegCloseKey(&hNamesKey);
|
|
|
|
/* Create the Users container */
|
|
Status = SampRegCreateKey(hDomainKey,
|
|
L"Users",
|
|
KEY_ALL_ACCESS,
|
|
&hUsersKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
Status = SampRegCreateKey(hUsersKey,
|
|
L"Names",
|
|
KEY_ALL_ACCESS,
|
|
&hNamesKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Create the server SD */
|
|
if (bBuiltinDomain != FALSE)
|
|
Status = SampCreateBuiltinDomainSD(&Sd,
|
|
&SdSize);
|
|
else
|
|
Status = SampCreateAccountDomainSD(&Sd,
|
|
&SdSize);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set SecDesc attribute*/
|
|
Status = SampRegSetValue(hServerKey,
|
|
L"SecDesc",
|
|
REG_BINARY,
|
|
Sd,
|
|
SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
SampRegCloseKey(&hNamesKey);
|
|
|
|
if (lpDomainKey != NULL)
|
|
*lpDomainKey = hDomainKey;
|
|
|
|
done:
|
|
if (Sd != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
|
|
|
|
SampRegCloseKey(&hAliasesKey);
|
|
SampRegCloseKey(&hGroupsKey);
|
|
SampRegCloseKey(&hUsersKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
SampRegCloseKey(&hDomainKey);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
SampSetupCreateServer(IN HANDLE hSamKey,
|
|
OUT HANDLE *lpServerKey)
|
|
{
|
|
HANDLE hServerKey = NULL;
|
|
HANDLE hDomainsKey = NULL;
|
|
PSECURITY_DESCRIPTOR Sd = NULL;
|
|
ULONG SdSize = 0;
|
|
NTSTATUS Status;
|
|
|
|
Status = SampRegCreateKey(hSamKey,
|
|
L"SAM",
|
|
KEY_ALL_ACCESS,
|
|
&hServerKey);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
Status = SampRegCreateKey(hServerKey,
|
|
L"Domains",
|
|
KEY_ALL_ACCESS,
|
|
&hDomainsKey);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Create the server SD */
|
|
Status = SampCreateServerSD(&Sd,
|
|
&SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Set SecDesc attribute*/
|
|
Status = SampRegSetValue(hServerKey,
|
|
L"SecDesc",
|
|
REG_BINARY,
|
|
Sd,
|
|
SdSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
SampRegCloseKey(&hDomainsKey);
|
|
|
|
*lpServerKey = hServerKey;
|
|
|
|
done:
|
|
if (Sd != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SampGetAccountDomainInfo(PPOLICY_ACCOUNT_DOMAIN_INFO *AccountDomainInfo)
|
|
{
|
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|
LSA_HANDLE PolicyHandle;
|
|
NTSTATUS Status;
|
|
|
|
TRACE("SampGetAccountDomainInfo\n");
|
|
|
|
memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
|
|
ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
|
|
|
|
Status = LsaOpenPolicy(NULL,
|
|
&ObjectAttributes,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&PolicyHandle);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
ERR("LsaOpenPolicy failed (Status: 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = LsaQueryInformationPolicy(PolicyHandle,
|
|
PolicyAccountDomainInformation,
|
|
(PVOID *)AccountDomainInfo);
|
|
|
|
LsaClose(PolicyHandle);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SampInitializeSAM(VOID)
|
|
{
|
|
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
|
|
HANDLE hSamKey = NULL;
|
|
HANDLE hServerKey = NULL;
|
|
HANDLE hBuiltinDomainKey = NULL;
|
|
HANDLE hAccountDomainKey = NULL;
|
|
PSID pBuiltinSid = NULL;
|
|
PSID pInteractiveSid = NULL;
|
|
PSID pAuthenticatedUserSid = NULL;
|
|
BOOL bResult = TRUE;
|
|
PSID pSid;
|
|
HINSTANCE hInstance;
|
|
WCHAR szComment[256];
|
|
WCHAR szName[80];
|
|
NTSTATUS Status;
|
|
|
|
TRACE("SampInitializeSAM() called\n");
|
|
|
|
hInstance = GetModuleHandleW(L"samsrv.dll");
|
|
|
|
/* Open the SAM key */
|
|
Status = SampRegOpenKey(NULL,
|
|
L"\\Registry\\Machine\\SAM",
|
|
KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
|
|
&hSamKey);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to open the SAM key (Status: 0x%08lx)\n", Status);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Create the SAM Server object */
|
|
Status = SampSetupCreateServer(hSamKey,
|
|
&hServerKey);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
bResult = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
/* Create and initialize the Builtin Domain SID */
|
|
pBuiltinSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
|
|
if (pBuiltinSid == NULL)
|
|
{
|
|
ERR("Failed to allocate the Builtin Domain SID\n");
|
|
bResult = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
RtlInitializeSid(pBuiltinSid, &SecurityNtAuthority, 1);
|
|
*(RtlSubAuthoritySid(pBuiltinSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
|
|
|
|
/* Create and initialize the Interactive SID */
|
|
pInteractiveSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
|
|
if (pInteractiveSid == NULL)
|
|
{
|
|
ERR("Failed to allocate the Interactive SID\n");
|
|
bResult = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
RtlInitializeSid(pInteractiveSid, &SecurityNtAuthority, 1);
|
|
*(RtlSubAuthoritySid(pInteractiveSid, 0)) = SECURITY_INTERACTIVE_RID;
|
|
|
|
/* Create and initialize the Authenticated User SID */
|
|
pAuthenticatedUserSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
|
|
if (pAuthenticatedUserSid == NULL)
|
|
{
|
|
ERR("Failed to allocate the Authenticated User SID\n");
|
|
bResult = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
RtlInitializeSid(pAuthenticatedUserSid, &SecurityNtAuthority, 1);
|
|
*(RtlSubAuthoritySid(pAuthenticatedUserSid, 0)) = SECURITY_AUTHENTICATED_USER_RID;
|
|
|
|
/* Get account domain information */
|
|
Status = SampGetAccountDomainInfo(&AccountDomainInfo);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("SampGetAccountDomainInfo failed (Status %08lx)\n", Status);
|
|
bResult = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
SampLoadString(hInstance, IDS_DOMAIN_BUILTIN_NAME, szName, 80);
|
|
|
|
/* Create the Builtin domain */
|
|
Status = SampSetupCreateDomain(hServerKey,
|
|
L"Builtin",
|
|
szName,
|
|
pBuiltinSid,
|
|
TRUE,
|
|
&hBuiltinDomainKey);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
bResult = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
/* Create the Administrators alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_ADMINS);
|
|
|
|
/* Create the Users alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_USERS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_USERS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_USERS);
|
|
|
|
/* Create the Guests alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_GUESTS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_GUESTS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_GUESTS);
|
|
|
|
/* Create the Power Users alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_POWER_USERS);
|
|
|
|
if (SampProductType != NtProductWinNt)
|
|
{
|
|
/* Create the Print Operators alias (Server only) */
|
|
SampLoadString(hInstance, IDS_ALIAS_PRINT_OPS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_PRINT_OPS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_PRINT_OPS);
|
|
}
|
|
|
|
/* Create the Backup Operators alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_BACKUP_OPS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_BACKUP_OPS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_BACKUP_OPS);
|
|
|
|
/* Create the Replicator alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_REPLICATOR_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_REPLICATOR_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_REPLICATOR);
|
|
|
|
/* Create the Remote Desktop Users alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_REMOTE_DESKTOP_USERS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_REMOTE_DESKTOP_USERS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS);
|
|
|
|
/* Create the Network Configuration Operators alias */
|
|
SampLoadString(hInstance, IDS_ALIAS_NETWORK_CONFIGURATION_OPS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_NETWORK_CONFIGURATION_OPS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS);
|
|
|
|
if (SampProductType != NtProductWinNt)
|
|
{
|
|
/* Create the Performance Monitor Users alias (Server only) */
|
|
SampLoadString(hInstance, IDS_ALIAS_MONITORING_USERS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_MONITORING_USERS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_MONITORING_USERS);
|
|
|
|
/* Create the Performance Log Users alias (Server only) */
|
|
SampLoadString(hInstance, IDS_ALIAS_LOGGING_USERS_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_ALIAS_LOGGING_USERS_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_ALIAS_RID_LOGGING_USERS);
|
|
}
|
|
|
|
/* Add the Administrator user to the Administrators alias */
|
|
pSid = AppendRidToSid(AccountDomainInfo->DomainSid,
|
|
DOMAIN_USER_RID_ADMIN);
|
|
if (pSid != NULL)
|
|
{
|
|
SampSetupAddMemberToAlias(hBuiltinDomainKey,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
pSid);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
|
|
}
|
|
|
|
/* Add the Guest user to the Guests alias */
|
|
pSid = AppendRidToSid(AccountDomainInfo->DomainSid,
|
|
DOMAIN_USER_RID_GUEST);
|
|
if (pSid != NULL)
|
|
{
|
|
SampSetupAddMemberToAlias(hBuiltinDomainKey,
|
|
DOMAIN_ALIAS_RID_GUESTS,
|
|
pSid);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
|
|
}
|
|
|
|
/* Add the Interactive SID to the Users alias */
|
|
SampSetupAddMemberToAlias(hBuiltinDomainKey,
|
|
DOMAIN_ALIAS_RID_USERS,
|
|
pInteractiveSid);
|
|
|
|
/* Add the Authenticated User SID to the Users alias */
|
|
SampSetupAddMemberToAlias(hBuiltinDomainKey,
|
|
DOMAIN_ALIAS_RID_USERS,
|
|
pAuthenticatedUserSid);
|
|
|
|
/* Create the Account domain */
|
|
Status = SampSetupCreateDomain(hServerKey,
|
|
L"Account",
|
|
L"",
|
|
AccountDomainInfo->DomainSid,
|
|
FALSE,
|
|
&hAccountDomainKey);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
bResult = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
/* Create the None group */
|
|
SampLoadString(hInstance, IDS_GROUP_NONE_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_GROUP_NONE_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateGroupAccount(hAccountDomainKey,
|
|
szName,
|
|
szComment,
|
|
DOMAIN_GROUP_RID_USERS);
|
|
|
|
/* Create the Administrator user */
|
|
SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateUserAccount(hAccountDomainKey,
|
|
szName,
|
|
szComment,
|
|
AccountDomainInfo->DomainSid,
|
|
DOMAIN_USER_RID_ADMIN,
|
|
USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
|
|
|
|
/* Add the Adminitrator user to the Administrators alias */
|
|
SampSetupAddMemberToGroup(hAccountDomainKey,
|
|
DOMAIN_GROUP_RID_USERS,
|
|
DOMAIN_USER_RID_ADMIN);
|
|
|
|
/* Create the Guest user */
|
|
SampLoadString(hInstance, IDS_USER_GUEST_NAME, szName, 80);
|
|
SampLoadString(hInstance, IDS_USER_GUEST_COMMENT, szComment, 256);
|
|
|
|
SampSetupCreateUserAccount(hAccountDomainKey,
|
|
szName,
|
|
szComment,
|
|
AccountDomainInfo->DomainSid,
|
|
DOMAIN_USER_RID_GUEST,
|
|
USER_ACCOUNT_DISABLED | USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
|
|
|
|
/* Add the Guest user to the Guests alias */
|
|
SampSetupAddMemberToGroup(hAccountDomainKey,
|
|
DOMAIN_GROUP_RID_USERS,
|
|
DOMAIN_USER_RID_GUEST);
|
|
|
|
done:
|
|
if (AccountDomainInfo)
|
|
LsaFreeMemory(AccountDomainInfo);
|
|
|
|
if (pAuthenticatedUserSid)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pAuthenticatedUserSid);
|
|
|
|
if (pInteractiveSid)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pInteractiveSid);
|
|
|
|
if (pBuiltinSid)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pBuiltinSid);
|
|
|
|
SampRegCloseKey(&hAccountDomainKey);
|
|
SampRegCloseKey(&hBuiltinDomainKey);
|
|
SampRegCloseKey(&hServerKey);
|
|
SampRegCloseKey(&hSamKey);
|
|
|
|
TRACE("SampInitializeSAM() done\n");
|
|
|
|
return bResult;
|
|
}
|