- Ensure that account names are not in use when a new alias, group or user is created. Return a proper status code if the account name is alread in use.
- Initialize logon/password  related data for new user account objects.
- Add missing prototypes and user account control bits to ntsam.h

svn path=/trunk/; revision=56936
This commit is contained in:
Eric Kohl 2012-07-22 15:12:00 +00:00
parent d62e513aad
commit 611b08e507
5 changed files with 104 additions and 132 deletions

View file

@ -484,10 +484,10 @@ SampCloseDbObject(PSAM_DB_OBJECT DbObject)
NTSTATUS NTSTATUS
SampSetDbObjectNameAlias(IN PSAM_DB_OBJECT DomainObject, SampSetAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
IN LPCWSTR lpContainerName, IN LPCWSTR lpContainerName,
IN LPCWSTR lpAliasName, IN LPCWSTR lpAccountName,
IN ULONG ulAliasValue) IN ULONG ulRelativeId)
{ {
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName; UNICODE_STRING KeyName;
@ -496,6 +496,8 @@ SampSetDbObjectNameAlias(IN PSAM_DB_OBJECT DomainObject,
HANDLE NamesKeyHandle = NULL; HANDLE NamesKeyHandle = NULL;
NTSTATUS Status; NTSTATUS Status;
TRACE("SampSetAccountNameInDomain()\n");
/* Open the container key */ /* Open the container key */
RtlInitUnicodeString(&KeyName, lpContainerName); RtlInitUnicodeString(&KeyName, lpContainerName);
@ -527,13 +529,13 @@ SampSetDbObjectNameAlias(IN PSAM_DB_OBJECT DomainObject,
goto done; goto done;
/* Set the alias value */ /* Set the alias value */
RtlInitUnicodeString(&ValueName, lpAliasName); RtlInitUnicodeString(&ValueName, lpAccountName);
Status = NtSetValueKey(NamesKeyHandle, Status = NtSetValueKey(NamesKeyHandle,
&ValueName, &ValueName,
0, 0,
REG_DWORD, REG_DWORD,
(LPVOID)&ulAliasValue, (LPVOID)&ulRelativeId,
sizeof(ULONG)); sizeof(ULONG));
done: done:
@ -547,87 +549,6 @@ done:
} }
NTSTATUS
SampCheckDbObjectNameAlias(IN PSAM_DB_OBJECT DomainObject,
IN LPCWSTR lpContainerName,
IN LPCWSTR lpAliasName,
OUT PBOOL bAliasExists)
{
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
HANDLE ContainerKeyHandle = NULL;
HANDLE NamesKeyHandle = NULL;
ULONG BufferLength = sizeof(ULONG);
NTSTATUS Status;
/* Open the container key */
RtlInitUnicodeString(&KeyName, lpContainerName);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
DomainObject->KeyHandle,
NULL);
Status = NtOpenKey(&ContainerKeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
return Status;
/* Open the 'Names' key */
RtlInitUnicodeString(&KeyName, L"Names");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ContainerKeyHandle,
NULL);
Status = NtOpenKey(&NamesKeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
goto done;
/* Get the alias value */
RtlInitUnicodeString(&ValueName, lpAliasName);
BufferLength += FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
/* Allocate memory for the value */
ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
if (ValueInfo == NULL)
return STATUS_NO_MEMORY;
/* Query the value */
Status = ZwQueryValueKey(NamesKeyHandle,
&ValueName,
KeyValuePartialInformation,
ValueInfo,
BufferLength,
&BufferLength);
*bAliasExists = (Status != STATUS_OBJECT_NAME_NOT_FOUND);
Status = STATUS_SUCCESS;
/* Free the memory and return status */
RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
done:
if (NamesKeyHandle)
NtClose(NamesKeyHandle);
if (ContainerKeyHandle)
NtClose(ContainerKeyHandle);
return Status;
}
NTSTATUS NTSTATUS
SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject, SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
IN LPWSTR lpAccountName) IN LPWSTR lpAccountName)
@ -636,7 +557,7 @@ SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
HANDLE NamesKey; HANDLE NamesKey;
NTSTATUS Status; NTSTATUS Status;
TRACE("SampCheckNameInDomain()\n"); TRACE("SampCheckAccountNameInDomain()\n");
Status = SampRegOpenKey(DomainObject->KeyHandle, Status = SampRegOpenKey(DomainObject->KeyHandle,
L"Aliases", L"Aliases",
@ -656,11 +577,12 @@ SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
NULL, NULL,
NULL); NULL);
if (Status == STATUS_SUCCESS) if (Status == STATUS_SUCCESS)
{
SampRegCloseKey(NamesKey);
Status = STATUS_ALIAS_EXISTS; Status = STATUS_ALIAS_EXISTS;
}
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
SampRegCloseKey(NamesKey);
} }
SampRegCloseKey(AccountKey); SampRegCloseKey(AccountKey);
@ -690,11 +612,12 @@ SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
NULL, NULL,
NULL); NULL);
if (Status == STATUS_SUCCESS) if (Status == STATUS_SUCCESS)
{
SampRegCloseKey(NamesKey);
Status = STATUS_ALIAS_EXISTS; Status = STATUS_ALIAS_EXISTS;
}
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
SampRegCloseKey(NamesKey);
} }
SampRegCloseKey(AccountKey); SampRegCloseKey(AccountKey);
@ -724,11 +647,12 @@ SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
NULL, NULL,
NULL); NULL);
if (Status == STATUS_SUCCESS) if (Status == STATUS_SUCCESS)
{
SampRegCloseKey(NamesKey);
Status = STATUS_ALIAS_EXISTS; Status = STATUS_ALIAS_EXISTS;
}
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
SampRegCloseKey(NamesKey);
} }
SampRegCloseKey(AccountKey); SampRegCloseKey(AccountKey);

View file

@ -1622,11 +1622,11 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
return Status; return Status;
} }
/* Add the name alias for the user object */ /* Add the account name of the user object */
Status = SampSetDbObjectNameAlias(DomainObject, Status = SampSetAccountNameInDomain(DomainObject,
L"Groups", L"Groups",
Name->Buffer, Name->Buffer,
ulRid); ulRid);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
TRACE("failed with status 0x%08lx\n", Status); TRACE("failed with status 0x%08lx\n", Status);
@ -1723,6 +1723,13 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n", TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
DomainHandle, Name, DesiredAccess, UserHandle, RelativeId); DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
if (Name == NULL ||
Name->Length == 0 ||
Name->Buffer == NULL ||
UserHandle == NULL ||
RelativeId == NULL)
return STATUS_INVALID_PARAMETER;
/* Validate the domain handle */ /* Validate the domain handle */
Status = SampValidateDbObject(DomainHandle, Status = SampValidateDbObject(DomainHandle,
SamDbDomainObject, SamDbDomainObject,
@ -1791,11 +1798,11 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
return Status; return Status;
} }
/* Add the name alias for the user object */ /* Add the account name for the user object */
Status = SampSetDbObjectNameAlias(DomainObject, Status = SampSetAccountNameInDomain(DomainObject,
L"Users", L"Users",
Name->Buffer, Name->Buffer,
ulRid); ulRid);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
TRACE("failed with status 0x%08lx\n", Status); TRACE("failed with status 0x%08lx\n", Status);
@ -1805,12 +1812,17 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
/* Initialize fixed user data */ /* Initialize fixed user data */
memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA)); memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
FixedUserData.Version = 1; FixedUserData.Version = 1;
FixedUserData.LastLogon.QuadPart = 0;
FixedUserData.LastLogoff.QuadPart = 0;
FixedUserData.PasswordLastSet.QuadPart = 0;
FixedUserData.AccountExpires.LowPart = MAXULONG;
FixedUserData.AccountExpires.HighPart = MAXLONG;
FixedUserData.LastBadPasswordTime.QuadPart = 0;
FixedUserData.UserId = ulRid; FixedUserData.UserId = ulRid;
FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS; FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
// FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED | FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
// USER_PASSWORD_NOT_REQUIRED || USER_PASSWORD_NOT_REQUIRED |
// USER_NORMAL_ACCOUNT; USER_NORMAL_ACCOUNT;
/* Set fixed user data attribute */ /* Set fixed user data attribute */
Status = SampSetObjectAttribute(UserObject, Status = SampSetObjectAttribute(UserObject,
@ -2050,11 +2062,11 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
return Status; return Status;
} }
/* Add the name alias for the user object */ /* Add the account name for the alias object */
Status = SampSetDbObjectNameAlias(DomainObject, Status = SampSetAccountNameInDomain(DomainObject,
L"Aliases", L"Aliases",
AccountName->Buffer, AccountName->Buffer,
ulRid); ulRid);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
TRACE("failed with status 0x%08lx\n", Status); TRACE("failed with status 0x%08lx\n", Status);

View file

@ -138,22 +138,16 @@ SampValidateDbObject(SAMPR_HANDLE Handle,
NTSTATUS NTSTATUS
SampCloseDbObject(PSAM_DB_OBJECT DbObject); SampCloseDbObject(PSAM_DB_OBJECT DbObject);
NTSTATUS
SampSetDbObjectNameAlias(IN PSAM_DB_OBJECT DomainObject,
IN LPCWSTR lpContainerName,
IN LPCWSTR lpAliasName,
IN DWORD dwAliasValue);
NTSTATUS
SampCheckDbObjectNameAlias(IN PSAM_DB_OBJECT DomainObject,
IN LPCWSTR lpContainerName,
IN LPCWSTR lpAliasName,
OUT PBOOL bAliasExists);
NTSTATUS NTSTATUS
SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject, SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
IN LPWSTR lpAccountName); IN LPWSTR lpAccountName);
NTSTATUS
SampSetAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject,
IN LPCWSTR lpContainerName,
IN LPCWSTR lpAccountName,
IN ULONG ulRelativeId);
NTSTATUS NTSTATUS
SampSetObjectAttribute(PSAM_DB_OBJECT DbObject, SampSetObjectAttribute(PSAM_DB_OBJECT DbObject,
LPWSTR AttributeName, LPWSTR AttributeName,

View file

@ -163,6 +163,31 @@ extern "C" {
USER_READ_GROUP_INFORMATION |\ USER_READ_GROUP_INFORMATION |\
USER_WRITE_GROUP_INFORMATION) USER_WRITE_GROUP_INFORMATION)
/* User account control bits */
#define USER_ACCOUNT_DISABLED 0x00000001
#define USER_HOME_DIRECTORY_REQUIRED 0x00000002
#define USER_PASSWORD_NOT_REQUIRED 0x00000004
#define USER_TEMP_DUPLICATE_ACCOUNT 0x00000008
#define USER_NORMAL_ACCOUNT 0x00000010
#define USER_MNS_LOGON_ACCOUNT 0x00000020
#define USER_INTERDOMAIN_TRUST_ACCOUNT 0x00000040
#define USER_WORKSTATION_TRUST_ACCOUNT 0x00000080
#define USER_SERVER_TRUST_ACCOUNT 0x00000100
#define USER_DONT_EXPIRE_PASSWORD 0x00000200
#define USER_ACCOUNT_AUTO_LOCKED 0x00000400
#define USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED 0x00000800
#define USER_SMARTCARD_REQUIRED 0x00001000
#define USER_TRUSTED_FOR_DELEGATION 0x00002000
#define USER_NOT_DELEGATED 0x00004000
#define USER_USE_DES_KEY_ONLY 0x00008000
#define USER_DONT_REQUIRE_PREAUTH 0x00010000
#define USER_PASSWORD_EXPIRED 0x00020000
#define USER_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION 0x00040000
#define USER_NO_AUTH_DATA_REQUIRED 0x00080000
#define USER_PARTIAL_SECRETS_ACCOUNT 0x00100000
#define USER_USE_AES_KEYS 0x00200000
typedef PVOID SAM_HANDLE, *PSAM_HANDLE; typedef PVOID SAM_HANDLE, *PSAM_HANDLE;
typedef ULONG SAM_ENUMERATE_HANDLE, *PSAM_ENUMERATE_HANDLE; typedef ULONG SAM_ENUMERATE_HANDLE, *PSAM_ENUMERATE_HANDLE;
@ -291,6 +316,12 @@ NTAPI
SamAddMemberToAlias(IN SAM_HANDLE AliasHandle, SamAddMemberToAlias(IN SAM_HANDLE AliasHandle,
IN PSID MemberId); IN PSID MemberId);
NTSTATUS
NTAPI
SamAddMemberToGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId,
IN ULONG Attributes);
NTSTATUS NTSTATUS
NTAPI NTAPI
SamCloseHandle(IN SAM_HANDLE SamHandle); SamCloseHandle(IN SAM_HANDLE SamHandle);
@ -414,6 +445,12 @@ SamQueryInformationDomain(IN SAM_HANDLE DomainHandle,
IN DOMAIN_INFORMATION_CLASS DomainInformationClass, IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
OUT PVOID *Buffer); OUT PVOID *Buffer);
NTSTATUS
NTAPI
SamQueryInformationGroup(IN SAM_HANDLE GroupHandle,
IN GROUP_INFORMATION_CLASS GroupInformationClass,
OUT PVOID *Buffer);
NTSTATUS NTSTATUS
NTAPI NTAPI
SamQueryInformationUser(IN SAM_HANDLE UserHandle, SamQueryInformationUser(IN SAM_HANDLE UserHandle,
@ -435,7 +472,13 @@ NTSTATUS
NTAPI NTAPI
SamSetInformationDomain(IN SAM_HANDLE DomainHandle, SamSetInformationDomain(IN SAM_HANDLE DomainHandle,
IN DOMAIN_INFORMATION_CLASS DomainInformationClass, IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
IN PVOID DomainInformation); IN PVOID Buffer);
NTSTATUS
NTAPI
SamSetInformationGroup(IN SAM_HANDLE GroupHandle,
IN GROUP_INFORMATION_CLASS GroupInformationClass,
IN PVOID Buffer);
NTSTATUS NTSTATUS
NTAPI NTAPI
@ -447,7 +490,6 @@ NTSTATUS
NTAPI NTAPI
SamShutdownSamServer(IN SAM_HANDLE ServerHandle); SamShutdownSamServer(IN SAM_HANDLE ServerHandle);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -628,9 +628,9 @@ typedef struct _SAMPR_USER_INTERNAL1_INFORMATION
{ {
ENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword; ENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword;
ENCRYPTED_LM_OWF_PASSWORD EncryptedLmOwfPassword; ENCRYPTED_LM_OWF_PASSWORD EncryptedLmOwfPassword;
unsigned char NtPasswordPresent; BOOLEAN NtPasswordPresent;
unsigned char LmPasswordPresent; BOOLEAN LmPasswordPresent;
unsigned char PasswordExpired; BOOLEAN PasswordExpired;
} SAMPR_USER_INTERNAL1_INFORMATION, *PSAMPR_USER_INTERNAL1_INFORMATION; } SAMPR_USER_INTERNAL1_INFORMATION, *PSAMPR_USER_INTERNAL1_INFORMATION;
typedef struct _SAMPR_USER_INTERNAL4_INFORMATION typedef struct _SAMPR_USER_INTERNAL4_INFORMATION
@ -648,13 +648,13 @@ typedef struct _SAMPR_USER_INTERNAL4_INFORMATION_NEW
typedef struct _SAMPR_USER_INTERNAL5_INFORMATION typedef struct _SAMPR_USER_INTERNAL5_INFORMATION
{ {
SAMPR_ENCRYPTED_USER_PASSWORD UserPassword; SAMPR_ENCRYPTED_USER_PASSWORD UserPassword;
unsigned char PasswordExpired; BOOLEAN PasswordExpired;
} SAMPR_USER_INTERNAL5_INFORMATION, *PSAMPR_USER_INTERNAL5_INFORMATION; } SAMPR_USER_INTERNAL5_INFORMATION, *PSAMPR_USER_INTERNAL5_INFORMATION;
typedef struct _SAMPR_USER_INTERNAL5_INFORMATION_NEW typedef struct _SAMPR_USER_INTERNAL5_INFORMATION_NEW
{ {
SAMPR_ENCRYPTED_USER_PASSWORD_NEW UserPassword; SAMPR_ENCRYPTED_USER_PASSWORD_NEW UserPassword;
unsigned char PasswordExpired; BOOLEAN PasswordExpired;
} SAMPR_USER_INTERNAL5_INFORMATION_NEW, *PSAMPR_USER_INTERNAL5_INFORMATION_NEW; } SAMPR_USER_INTERNAL5_INFORMATION_NEW, *PSAMPR_USER_INTERNAL5_INFORMATION_NEW;
cpp_quote("#ifndef _NTSAM_") cpp_quote("#ifndef _NTSAM_")