[SAMLIB][SAMSRV]

- Implement SamCreateUserInDomain and SamrCreateUserInDomain.
- SamOpenDomain: Use the correct object types when trying to open a domain object.

svn path=/trunk/; revision=56672
This commit is contained in:
Eric Kohl 2012-05-28 22:47:52 +00:00
parent bf77113125
commit 5e6927ddd1
6 changed files with 314 additions and 5 deletions

View file

@ -431,6 +431,36 @@ SamConnect(IN OUT PUNICODE_STRING ServerName,
return Status; return Status;
} }
NTSTATUS
NTAPI
SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
IN PUNICODE_STRING AccountName,
IN ACCESS_MASK DesiredAccess,
OUT PSAM_HANDLE UserHandle,
OUT PULONG RelativeId)
{
NTSTATUS Status;
TRACE("SamCreateUserInDomain(%p,%p,0x%08x,%p,%p)\n",
DomainHandle, AccountName, DesiredAccess, UserHandle, RelativeId);
RpcTryExcept
{
Status = SamrCreateUserInDomain((SAMPR_HANDLE)DomainHandle,
(PRPC_UNICODE_STRING)AccountName,
DesiredAccess,
(SAMPR_HANDLE *)UserHandle,
RelativeId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
SamOpenDomain(IN SAM_HANDLE ServerHandle, SamOpenDomain(IN SAM_HANDLE ServerHandle,

View file

@ -10,7 +10,7 @@
@ stub SamCreateAliasInDomain @ stub SamCreateAliasInDomain
@ stub SamCreateGroupInDomain @ stub SamCreateGroupInDomain
@ stub SamCreateUser2InDomain @ stub SamCreateUser2InDomain
@ stub SamCreateUserInDomain @ stdcall SamCreateUserInDomain(ptr ptr long ptr ptr)
@ stub SamDeleteAlias @ stub SamDeleteAlias
@ stub SamDeleteGroup @ stub SamDeleteGroup
@ stub SamDeleteUser @ stub SamDeleteUser

View file

@ -602,6 +602,151 @@ SampCloseDbObject(PSAM_DB_OBJECT DbObject)
} }
NTSTATUS
SampSetDbObjectNameAlias(IN PSAM_DB_OBJECT DomainObject,
IN LPCWSTR lpContainerName,
IN LPCWSTR lpAliasName,
IN ULONG ulAliasValue)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
HANDLE ContainerKeyHandle = NULL;
HANDLE NamesKeyHandle = NULL;
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;
/* Set the alias value */
RtlInitUnicodeString(&ValueName, lpAliasName);
Status = NtSetValueKey(NamesKeyHandle,
&ValueName,
0,
REG_DWORD,
(LPVOID)&ulAliasValue,
sizeof(ULONG));
done:
if (NamesKeyHandle)
NtClose(NamesKeyHandle);
if (ContainerKeyHandle)
NtClose(ContainerKeyHandle);
return Status;
}
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
SampSetObjectAttribute(PSAM_DB_OBJECT DbObject, SampSetObjectAttribute(PSAM_DB_OBJECT DbObject,
LPWSTR AttributeName, LPWSTR AttributeName,

View file

@ -193,6 +193,7 @@ SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
TRACE("SamrOpenDomain(%p %lx %p %p)\n", TRACE("SamrOpenDomain(%p %lx %p %p)\n",
ServerHandle, DesiredAccess, DomainId, DomainHandle); ServerHandle, DesiredAccess, DomainId, DomainHandle);
/* Validate the server handle */
Status = SampValidateDbObject(ServerHandle, Status = SampValidateDbObject(ServerHandle,
SamDbServerObject, SamDbServerObject,
SAM_SERVER_LOOKUP_DOMAIN, SAM_SERVER_LOOKUP_DOMAIN,
@ -216,7 +217,7 @@ SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
Status = SampOpenDbObject(ServerObject, Status = SampOpenDbObject(ServerObject,
L"Domains", L"Domains",
L"Builtin", L"Builtin",
SamDbServerObject, SamDbDomainObject,
DesiredAccess, DesiredAccess,
&DomainObject); &DomainObject);
} }
@ -231,7 +232,7 @@ SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
Status = SampOpenDbObject(ServerObject, Status = SampOpenDbObject(ServerObject,
L"Domains", L"Domains",
L"Account", L"Account",
SamDbServerObject, SamDbDomainObject,
DesiredAccess, DesiredAccess,
&DomainObject); &DomainObject);
} }
@ -306,8 +307,116 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
OUT SAMPR_HANDLE *UserHandle, OUT SAMPR_HANDLE *UserHandle,
OUT unsigned long *RelativeId) OUT unsigned long *RelativeId)
{ {
UNIMPLEMENTED; PSAM_DB_OBJECT DomainObject;
return STATUS_NOT_IMPLEMENTED; PSAM_DB_OBJECT UserObject;
ULONG ulSize;
ULONG ulRid;
WCHAR szRid[9];
BOOL bAliasExists = FALSE;
NTSTATUS Status;
TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
/* Validate the domain handle */
Status = SampValidateDbObject(DomainHandle,
SamDbDomainObject,
DOMAIN_CREATE_USER,
&DomainObject);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
return Status;
}
/* Get the NextRID attribute */
ulSize = sizeof(ULONG);
Status = SampGetObjectAttribute(DomainObject,
L"NextRID",
NULL,
(LPVOID)&ulRid,
&ulSize);
if (!NT_SUCCESS(Status))
ulRid = DOMAIN_USER_RID_MAX;
TRACE("RID: %lx\n", ulRid);
/* Convert the RID into a string (hex) */
_ultow(ulRid, szRid, 16);
/* Check whether the user name is already in use */
Status = SampCheckDbObjectNameAlias(DomainObject,
L"Users",
Name->Buffer,
&bAliasExists);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
return Status;
}
if (bAliasExists)
{
TRACE("The user account %S already exists!\n", Name->Buffer);
return STATUS_USER_EXISTS;
}
/* Create the user object */
Status = SampCreateDbObject(DomainObject,
L"Users",
szRid,
SamDbUserObject,
DesiredAccess,
&UserObject);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
return Status;
}
/* Add the name alias for the user object */
Status = SampSetDbObjectNameAlias(DomainObject,
L"Users",
Name->Buffer,
ulRid);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
return Status;
}
/* Set the account name attribute */
Status = SampSetObjectAttribute(UserObject,
L"AccountName",
REG_SZ,
(LPVOID)Name->Buffer,
Name->MaximumLength);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
return Status;
}
/* FIXME: Set default user attributes */
if (NT_SUCCESS(Status))
{
*UserHandle = (SAMPR_HANDLE)UserObject;
*RelativeId = ulRid;
}
/* Increment the NextRID attribute */
ulRid++;
ulSize = sizeof(ULONG);
SampSetObjectAttribute(DomainObject,
L"NextRID",
REG_DWORD,
(LPVOID)&ulRid,
ulSize);
TRACE("returns with status 0x%08lx\n", Status);
return Status;
} }
/* Function 13 */ /* Function 13 */

View file

@ -7,6 +7,7 @@
* PROGRAMMERS: Eric Kohl * PROGRAMMERS: Eric Kohl
*/ */
#include <stdlib.h>
#define WIN32_NO_STATUS #define WIN32_NO_STATUS
#include <windows.h> #include <windows.h>
#define NTOS_MODE_USER #define NTOS_MODE_USER
@ -75,6 +76,18 @@ 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
SampSetObjectAttribute(PSAM_DB_OBJECT DbObject, SampSetObjectAttribute(PSAM_DB_OBJECT DbObject,
LPWSTR AttributeName, LPWSTR AttributeName,

View file

@ -6,6 +6,18 @@
extern "C" { extern "C" {
#endif #endif
#define DOMAIN_READ_PASSWORD_PARAMETERS 1
#define DOMAIN_WRITE_PASSWORD_PARAMS 2
#define DOMAIN_READ_OTHER_PARAMETERS 4
#define DOMAIN_WRITE_OTHER_PARAMETERS 8
#define DOMAIN_CREATE_USER 16
#define DOMAIN_CREATE_GROUP 32
#define DOMAIN_CREATE_ALIAS 64
#define DOMAIN_GET_ALIAS_MEMBERSHIP 128
#define DOMAIN_LIST_ACCOUNTS 256
#define DOMAIN_LOOKUP 512
#define DOMAIN_ADMINISTER_SERVER 1024
#define SAM_SERVER_CONNECT 1 #define SAM_SERVER_CONNECT 1
#define SAM_SERVER_SHUTDOWN 2 #define SAM_SERVER_SHUTDOWN 2
#define SAM_SERVER_INITIALIZE 4 #define SAM_SERVER_INITIALIZE 4