https://git.reactos.org/?p=reactos.git;a=commitdiff;h=646ab9286c35cabb5da85…
commit 646ab9286c35cabb5da854a775ac227f103a2c6b
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Sun Mar 17 12:34:49 2019 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Sun Mar 17 12:34:49 2019 +0100
[NETAPI32] NetUserEnum, NetUserGetInfo: Get the user privileges and auth flags for
info levels 1, 2, 3, 4 and 11.
---
dll/win32/netapi32/user.c | 268 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 244 insertions(+), 24 deletions(-)
diff --git a/dll/win32/netapi32/user.c b/dll/win32/netapi32/user.c
index 1d2b8e299e..a867b786ec 100644
--- a/dll/win32/netapi32/user.c
+++ b/dll/win32/netapi32/user.c
@@ -39,6 +39,7 @@ typedef struct _ENUM_CONTEXT
SAM_HANDLE ServerHandle;
SAM_HANDLE BuiltinDomainHandle;
SAM_HANDLE AccountDomainHandle;
+ PSID BuiltinDomainSid;
PSID AccountDomainSid;
SAM_ENUMERATE_HANDLE EnumerationContext;
@@ -400,16 +401,159 @@ FreeUserInfo(PUSER_ALL_INFORMATION UserInfo)
static
NET_API_STATUS
-BuildUserInfoBuffer(SAM_HANDLE UserHandle,
- PSID AccountDomainSid,
- DWORD level,
- ULONG RelativeId,
- LPVOID *Buffer)
+GetUserPrivileges(
+ _In_ SAM_HANDLE BuiltinDomainHandle,
+ _In_ SAM_HANDLE UserHandle,
+ _In_ PSID AccountDomainSid,
+ _In_ ULONG RelativeId,
+ _Out_ PDWORD Priv,
+ _Out_ PDWORD AuthFlags)
+{
+ PGROUP_MEMBERSHIP GroupMembership = NULL;
+ ULONG GroupCount, SidCount, AliasCount, i;
+ PSID *SidArray = NULL;
+ PULONG AliasArray = NULL;
+ BOOL bAdmin = FALSE, bUser = FALSE;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status;
+
+ FIXME("GetUserPrivileges(%p)\n", UserHandle);
+
+ /* Get the users group memberships */
+ Status = SamGetGroupsForUser(UserHandle,
+ &GroupMembership,
+ &GroupCount);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamGetGroupsForUser() failed (Status 0x%08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Allocate the SID array */
+ ApiStatus = NetApiBufferAllocate((GroupCount + 1) * sizeof(PSID),
+ (PVOID*)&SidArray);
+ if (ApiStatus != NERR_Success)
+ {
+ goto done;
+ }
+
+ /* Add the user to the SID array */
+ SidCount = 0;
+ ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
+ RelativeId,
+ &SidArray[0]);
+ if (ApiStatus != NERR_Success)
+ {
+ goto done;
+ }
+
+ SidCount++;
+
+ /* Add the groups to the SID array */
+ for (i = 0; i < GroupCount; i++)
+ {
+ ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
+ GroupMembership[i].RelativeId,
+ &SidArray[i + 1]);
+ if (ApiStatus != NERR_Success)
+ {
+ goto done;
+ }
+
+ SidCount++;
+ }
+
+ /* Get aliases for the user and his groups */
+ Status = SamGetAliasMembership(BuiltinDomainHandle,
+ SidCount,
+ SidArray,
+ &AliasCount,
+ &AliasArray);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamGetAliasMembership() failed (Status 0x%08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ *AuthFlags = 0;
+
+ /* Set the AuthFlags */
+ for (i = 0; i < AliasCount; i++)
+ {
+ switch (AliasArray[i])
+ {
+ case DOMAIN_ALIAS_RID_ADMINS:
+ bAdmin = TRUE;
+ break;
+
+ case DOMAIN_ALIAS_RID_USERS:
+ bUser = TRUE;
+ break;
+
+ case DOMAIN_ALIAS_RID_ACCOUNT_OPS:
+ *AuthFlags |= AF_OP_ACCOUNTS;
+ break;
+
+ case DOMAIN_ALIAS_RID_SYSTEM_OPS:
+ *AuthFlags |= AF_OP_SERVER;
+ break;
+
+ case DOMAIN_ALIAS_RID_PRINT_OPS:
+ *AuthFlags |= AF_OP_PRINT;
+ break;
+ }
+ }
+
+ /* Set the prvileges */
+ if (bAdmin)
+ {
+ *Priv = USER_PRIV_ADMIN;
+ }
+ else if (bUser)
+ {
+ *Priv = USER_PRIV_USER;
+ }
+ else
+ {
+ *Priv = USER_PRIV_GUEST;
+ }
+
+done:
+ if (AliasArray != NULL)
+ SamFreeMemory(AliasArray);
+
+ if (SidArray != NULL)
+ {
+ for (i = 0; i < SidCount; i++)
+ NetApiBufferFree(SidArray[i]);
+
+ NetApiBufferFree(SidArray);
+ }
+
+ if (GroupMembership != NULL)
+ SamFreeMemory(GroupMembership);
+
+ return ApiStatus;
+}
+
+
+static
+NET_API_STATUS
+BuildUserInfoBuffer(
+ _In_ SAM_HANDLE BuiltinDomainHandle,
+ _In_ SAM_HANDLE UserHandle,
+ _In_ PSID AccountDomainSid,
+ _In_ ULONG RelativeId,
+ _In_ DWORD level,
+ _Out_ LPVOID *Buffer)
{
UNICODE_STRING LogonServer = RTL_CONSTANT_STRING(L"\\\\*");
PUSER_ALL_INFORMATION UserInfo = NULL;
LPVOID LocalBuffer = NULL;
PACL Dacl = NULL;
+ DWORD Priv = 0, AuthFlags = 0;
PUSER_INFO_0 UserInfo0;
PUSER_INFO_1 UserInfo1;
PUSER_INFO_2 UserInfo2;
@@ -444,6 +588,19 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
goto done;
}
+ if ((level == 1) || (level == 2) || (level == 3) ||
+ (level == 4) || (level == 11))
+ {
+ ApiStatus = GetUserPrivileges(BuiltinDomainHandle,
+ UserHandle,
+ AccountDomainSid,
+ RelativeId,
+ &Priv,
+ &AuthFlags);
+ if (ApiStatus != NERR_Success)
+ goto done;
+ }
+
switch (level)
{
case 0:
@@ -595,7 +752,7 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo1->usri1_password = NULL;
UserInfo1->usri1_password_age =
GetPasswordAge(&UserInfo->PasswordLastSet);
- /* FIXME: usri1_priv */
+ UserInfo1->usri1_priv = Priv;
UserInfo1->usri1_home_dir = Ptr;
memcpy(UserInfo1->usri1_home_dir,
@@ -638,7 +795,7 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo2->usri2_password = NULL;
UserInfo2->usri2_password_age =
GetPasswordAge(&UserInfo->PasswordLastSet);
- /* FIXME: usri2_priv */
+ UserInfo2->usri2_priv = Priv;
UserInfo2->usri2_home_dir = Ptr;
memcpy(UserInfo2->usri2_home_dir,
@@ -664,7 +821,7 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo2->usri2_script_path[UserInfo->ScriptPath.Length /
sizeof(WCHAR)] = UNICODE_NULL;
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length +
sizeof(WCHAR));
- /* FIXME: usri2_auth_flags */
+ UserInfo2->usri2_auth_flags = AuthFlags;
UserInfo2->usri2_full_name = Ptr;
memcpy(UserInfo2->usri2_full_name,
@@ -757,7 +914,7 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo3->usri3_password = NULL;
UserInfo3->usri3_password_age =
GetPasswordAge(&UserInfo->PasswordLastSet);
- /* FIXME: usri3_priv */
+ UserInfo3->usri3_priv = Priv;
UserInfo3->usri3_home_dir = Ptr;
memcpy(UserInfo3->usri3_home_dir,
@@ -783,7 +940,7 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo3->usri3_script_path[UserInfo->ScriptPath.Length /
sizeof(WCHAR)] = UNICODE_NULL;
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length +
sizeof(WCHAR));
- /* FIXME: usri3_auth_flags */
+ UserInfo3->usri3_auth_flags = AuthFlags;
UserInfo3->usri3_full_name = Ptr;
memcpy(UserInfo3->usri3_full_name,
@@ -894,7 +1051,7 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo4->usri4_password = NULL;
UserInfo4->usri4_password_age =
GetPasswordAge(&UserInfo->PasswordLastSet);
- /* FIXME: usri4_priv */
+ UserInfo4->usri4_priv = Priv;
UserInfo4->usri4_home_dir = Ptr;
memcpy(UserInfo4->usri4_home_dir,
@@ -920,7 +1077,7 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo4->usri4_script_path[UserInfo->ScriptPath.Length /
sizeof(WCHAR)] = UNICODE_NULL;
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length +
sizeof(WCHAR));
- /* FIXME: usri4_auth_flags */
+ UserInfo4->usri4_auth_flags = AuthFlags;
UserInfo4->usri4_full_name = Ptr;
memcpy(UserInfo4->usri4_full_name,
@@ -1088,8 +1245,8 @@ BuildUserInfoBuffer(SAM_HANDLE UserHandle,
UserInfo11->usri11_full_name[UserInfo->FullName.Length / sizeof(WCHAR)]
= UNICODE_NULL;
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length +
sizeof(WCHAR));
- /* FIXME: usri11_priv */
- /* FIXME: usri11_auth_flags */
+ UserInfo11->usri11_priv = Priv;
+ UserInfo11->usri11_auth_flags = AuthFlags;
UserInfo11->usri11_password_age =
GetPasswordAge(&UserInfo->PasswordLastSet);
@@ -2526,6 +2683,7 @@ NetUserEnum(LPCWSTR servername,
LPVOID Buffer = NULL;
ULONG i;
SAM_HANDLE UserHandle = NULL;
+ ACCESS_MASK DesiredAccess;
NET_API_STATUS ApiStatus = NERR_Success;
NTSTATUS Status = STATUS_SUCCESS;
@@ -2588,12 +2746,27 @@ NetUserEnum(LPCWSTR servername,
goto done;
}
- Status = OpenBuiltinDomain(EnumContext->ServerHandle,
- DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
- &EnumContext->BuiltinDomainHandle);
+ /* Get the Builtin Domain SID */
+ Status = GetBuiltinDomainSid(&EnumContext->BuiltinDomainSid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ DesiredAccess = DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP;
+ if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level ==
11))
+ DesiredAccess |= DOMAIN_GET_ALIAS_MEMBERSHIP;
+
+ /* Open the Builtin Domain */
+ Status = SamOpenDomain(EnumContext->ServerHandle,
+ DesiredAccess,
+ EnumContext->BuiltinDomainSid,
+ &EnumContext->BuiltinDomainHandle);
if (!NT_SUCCESS(Status))
{
- ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ERR("SamOpenDomain failed (Status %08lx)\n", Status);
ApiStatus = NetpNtStatusToApiStatus(Status);
goto done;
}
@@ -2648,8 +2821,12 @@ NetUserEnum(LPCWSTR servername,
TRACE("RID: %lu\n", CurrentUser->RelativeId);
+ DesiredAccess = READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES |
USER_READ_LOGON | USER_READ_ACCOUNT;
+ if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level ==
11))
+ DesiredAccess |= USER_LIST_GROUPS;
+
Status = SamOpenUser(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
- READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES |
USER_READ_LOGON | USER_READ_ACCOUNT,
+ DesiredAccess,
CurrentUser->RelativeId,
&UserHandle);
if (!NT_SUCCESS(Status))
@@ -2659,10 +2836,11 @@ NetUserEnum(LPCWSTR servername,
goto done;
}
- ApiStatus = BuildUserInfoBuffer(UserHandle,
+ ApiStatus = BuildUserInfoBuffer(EnumContext->BuiltinDomainHandle,
+ UserHandle,
EnumContext->AccountDomainSid,
- level,
CurrentUser->RelativeId,
+ level,
&Buffer);
if (ApiStatus != NERR_Success)
{
@@ -2695,6 +2873,9 @@ done:
if (EnumContext->AccountDomainHandle != NULL)
SamCloseHandle(EnumContext->AccountDomainHandle);
+ if (EnumContext->BuiltinDomainSid != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, EnumContext->BuiltinDomainSid);
+
if (EnumContext->AccountDomainSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, EnumContext->AccountDomainSid);
@@ -2909,11 +3090,14 @@ NetUserGetInfo(LPCWSTR servername,
UNICODE_STRING UserName;
SAM_HANDLE ServerHandle = NULL;
SAM_HANDLE AccountDomainHandle = NULL;
+ SAM_HANDLE BuiltinDomainHandle = NULL;
SAM_HANDLE UserHandle = NULL;
PULONG RelativeIds = NULL;
PSID_NAME_USE Use = NULL;
LPVOID Buffer = NULL;
PSID AccountDomainSid = NULL;
+ PSID BuiltinDomainSid = NULL;
+ ACCESS_MASK DesiredAccess;
NET_API_STATUS ApiStatus = NERR_Success;
NTSTATUS Status = STATUS_SUCCESS;
@@ -2937,6 +3121,31 @@ NetUserGetInfo(LPCWSTR servername,
goto done;
}
+ /* Get the Builtin Domain SID */
+ Status = GetBuiltinDomainSid(&BuiltinDomainSid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ DesiredAccess = DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP;
+ if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
+ DesiredAccess |= DOMAIN_GET_ALIAS_MEMBERSHIP;
+
+ /* Open the Builtin Domain */
+ Status = SamOpenDomain(ServerHandle,
+ DesiredAccess,
+ BuiltinDomainSid,
+ &BuiltinDomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamOpenDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
/* Get the Account Domain SID */
Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
&AccountDomainSid);
@@ -2985,9 +3194,13 @@ NetUserGetInfo(LPCWSTR servername,
TRACE("RID: %lu\n", RelativeIds[0]);
+ DesiredAccess = READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES |
USER_READ_LOGON | USER_READ_ACCOUNT;
+ if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
+ DesiredAccess |= USER_LIST_GROUPS;
+
/* Open the user object */
Status = SamOpenUser(AccountDomainHandle,
- READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES |
USER_READ_LOGON | USER_READ_ACCOUNT,
+ DesiredAccess,
RelativeIds[0],
&UserHandle);
if (!NT_SUCCESS(Status))
@@ -2997,10 +3210,11 @@ NetUserGetInfo(LPCWSTR servername,
goto done;
}
- ApiStatus = BuildUserInfoBuffer(UserHandle,
+ ApiStatus = BuildUserInfoBuffer(BuiltinDomainHandle,
+ UserHandle,
AccountDomainSid,
- level,
RelativeIds[0],
+ level,
&Buffer);
if (ApiStatus != NERR_Success)
{
@@ -3024,6 +3238,12 @@ done:
if (AccountDomainSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
+ if (BuiltinDomainHandle != NULL)
+ SamCloseHandle(BuiltinDomainHandle);
+
+ if (BuiltinDomainSid != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, BuiltinDomainSid);
+
if (ServerHandle != NULL)
SamCloseHandle(ServerHandle);