Author: ekohl
Date: Tue Nov 26 16:56:33 2013
New Revision: 61103
URL:
http://svn.reactos.org/svn/reactos?rev=61103&view=rev
Log:
[NETAPI32]
BuildUserInfoBuffer: Set the UF_PASSWD_CANT_CHANGE account control flag if the user does
not have the USER_CHANGE_PASSWORD access right for his own account data.
Modified:
trunk/reactos/dll/win32/netapi32/user.c
Modified: trunk/reactos/dll/win32/netapi32/user.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/netapi32/user.c?…
==============================================================================
--- trunk/reactos/dll/win32/netapi32/user.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/netapi32/user.c [iso-8859-1] Tue Nov 26 16:56:33 2013
@@ -66,10 +66,76 @@
static
+NTSTATUS
+GetAllowedWorldAce(IN PACL Acl,
+ OUT PACCESS_ALLOWED_ACE *Ace)
+{
+ SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
+ ULONG WorldSid[sizeof(SID) / sizeof(ULONG) + SID_MAX_SUB_AUTHORITIES];
+ ACL_SIZE_INFORMATION AclSize;
+ PVOID LocalAce = NULL;
+ ULONG i;
+ NTSTATUS Status;
+
+ *Ace = NULL;
+
+ RtlInitializeSid((PSID)WorldSid,
+ &WorldAuthority,
+ 1);
+ *(RtlSubAuthoritySid((PSID)WorldSid, 0)) = SECURITY_WORLD_RID;
+
+ Status = RtlQueryInformationAcl(Acl,
+ &AclSize,
+ sizeof(AclSize),
+ AclSizeInformation);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ for (i = 0; i < AclSize.AceCount; i++)
+ {
+ Status = RtlGetAce(Acl, i, &LocalAce);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ if (((PACE_HEADER)LocalAce)->AceType != ACCESS_ALLOWED_ACE_TYPE)
+ continue;
+
+ if (RtlEqualSid((PSID)WorldSid,
+ (PSID)&((PACCESS_ALLOWED_ACE)LocalAce)->SidStart))
+ {
+ *Ace = (PACCESS_ALLOWED_ACE)LocalAce;
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+static
ULONG
-GetAccountFlags(ULONG AccountControl)
+GetAccountFlags(ULONG AccountControl,
+ PACL Dacl)
{
+ PACCESS_ALLOWED_ACE Ace = NULL;
ULONG Flags = UF_SCRIPT;
+ NTSTATUS Status;
+
+ if (Dacl != NULL)
+ {
+ Status = GetAllowedWorldAce(Dacl, &Ace);
+ if (NT_SUCCESS(Status))
+ {
+ if (Ace == NULL)
+ {
+ Flags |= UF_PASSWD_CANT_CHANGE;
+ }
+ else if ((Ace->Mask & USER_CHANGE_PASSWORD) == 0)
+ {
+ Flags |= UF_PASSWD_CANT_CHANGE;
+ }
+ }
+ }
if (AccountControl & USER_ACCOUNT_DISABLED)
Flags |= UF_ACCOUNTDISABLE;
@@ -79,8 +145,6 @@
if (AccountControl & USER_PASSWORD_NOT_REQUIRED)
Flags |= UF_PASSWD_NOTREQD;
-
-// UF_PASSWD_CANT_CHANGE
if (AccountControl & USER_ACCOUNT_AUTO_LOCKED)
Flags |= UF_LOCKOUT;
@@ -185,6 +249,87 @@
static
+NET_API_STATUS
+GetUserDacl(IN SAM_HANDLE UserHandle,
+ OUT PACL *Dacl)
+{
+ PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+ PACL SamDacl;
+ PACL LocalDacl;
+ BOOLEAN Defaulted;
+ BOOLEAN Present;
+ ACL_SIZE_INFORMATION AclSize;
+ NET_API_STATUS ApiStatus;
+ NTSTATUS Status;
+
+ TRACE("(%p %p)\n", UserHandle, Dacl);
+
+ *Dacl = NULL;
+
+ Status = SamQuerySecurityObject(UserHandle,
+ DACL_SECURITY_INFORMATION,
+ &SecurityDescriptor);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SamQuerySecurityObject() failed (Status 0x%08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
+ &Present,
+ &SamDacl,
+ &Defaulted);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("RtlGetDaclSecurityDescriptor() failed (Status 0x%08lx)\n",
Status);
+ ApiStatus = NERR_InternalError;
+ goto done;
+ }
+
+ if (Present == FALSE)
+ {
+ TRACE("No DACL present\n");
+ ApiStatus = NERR_Success;
+ goto done;
+ }
+
+ Status = RtlQueryInformationAcl(SamDacl,
+ &AclSize,
+ sizeof(AclSize),
+ AclSizeInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("RtlQueryInformationAcl() failed (Status 0x%08lx)\n", Status);
+ ApiStatus = NERR_InternalError;
+ goto done;
+ }
+
+ LocalDacl = HeapAlloc(GetProcessHeap(), 0, AclSize.AclBytesInUse);
+ if (LocalDacl == NULL)
+ {
+ TRACE("Memory allocation failed\n");
+ ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ RtlCopyMemory(LocalDacl, SamDacl, AclSize.AclBytesInUse);
+
+ *Dacl = LocalDacl;
+
+ ApiStatus = NERR_Success;
+
+done:
+ if (SecurityDescriptor != NULL)
+ SamFreeMemory(SecurityDescriptor);
+
+ TRACE("done (ApiStatus: 0x%08lx)\n", ApiStatus);
+
+ return ApiStatus;
+}
+
+
+static
VOID
FreeUserInfo(PUSER_ALL_INFORMATION UserInfo)
{
@@ -238,6 +383,7 @@
UNICODE_STRING LogonServer = RTL_CONSTANT_STRING(L"\\\\*");
PUSER_ALL_INFORMATION UserInfo = NULL;
LPVOID LocalBuffer = NULL;
+ PACL Dacl = NULL;
PUSER_INFO_0 UserInfo0;
PUSER_INFO_1 UserInfo1;
PUSER_INFO_2 UserInfo2;
@@ -264,6 +410,14 @@
goto done;
}
+ if ((level == 1) || (level == 2) || (level == 3) ||
+ (level == 4) || (level == 20) || (level == 23))
+ {
+ ApiStatus = GetUserDacl(UserHandle, &Dacl);
+ if (ApiStatus != NERR_Success)
+ goto done;
+ }
+
switch (level)
{
case 0:
@@ -531,7 +685,8 @@
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length +
sizeof(WCHAR));
}
- UserInfo1->usri1_flags =
GetAccountFlags(UserInfo->UserAccountControl);
+ UserInfo1->usri1_flags = GetAccountFlags(UserInfo->UserAccountControl,
+ Dacl);
if (UserInfo->ScriptPath.Length > 0)
{
@@ -586,7 +741,8 @@
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length +
sizeof(WCHAR));
}
- UserInfo2->usri2_flags =
GetAccountFlags(UserInfo->UserAccountControl);
+ UserInfo2->usri2_flags = GetAccountFlags(UserInfo->UserAccountControl,
+ Dacl);
if (UserInfo->ScriptPath.Length > 0)
{
@@ -734,7 +890,8 @@
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length +
sizeof(WCHAR));
}
- UserInfo3->usri3_flags =
GetAccountFlags(UserInfo->UserAccountControl);
+ UserInfo3->usri3_flags = GetAccountFlags(UserInfo->UserAccountControl,
+ Dacl);
if (UserInfo->ScriptPath.Length > 0)
{
@@ -911,7 +1068,8 @@
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length +
sizeof(WCHAR));
}
- UserInfo4->usri4_flags =
GetAccountFlags(UserInfo->UserAccountControl);
+ UserInfo4->usri4_flags = GetAccountFlags(UserInfo->UserAccountControl,
+ Dacl);
if (UserInfo->ScriptPath.Length > 0)
{
@@ -1267,7 +1425,8 @@
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length +
sizeof(WCHAR));
}
- UserInfo20->usri20_flags =
GetAccountFlags(UserInfo->UserAccountControl);
+ UserInfo20->usri20_flags =
GetAccountFlags(UserInfo->UserAccountControl,
+ Dacl);
UserInfo20->usri20_user_id = RelativeId;
break;
@@ -1310,7 +1469,8 @@
Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length +
sizeof(WCHAR));
}
- UserInfo23->usri23_flags =
GetAccountFlags(UserInfo->UserAccountControl);
+ UserInfo23->usri23_flags =
GetAccountFlags(UserInfo->UserAccountControl,
+ Dacl);
/* FIXME: usri23_user_sid */
break;
@@ -1319,6 +1479,9 @@
done:
if (UserInfo != NULL)
FreeUserInfo(UserInfo);
+
+ if (Dacl != NULL)
+ HeapFree(GetProcessHeap(), 0, Dacl);
if (ApiStatus == NERR_Success)
{
@@ -2530,7 +2693,7 @@
TRACE("RID: %lu\n", CurrentUser->RelativeId);
Status = SamOpenUser(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
- USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON
| USER_READ_ACCOUNT,
+ READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES |
USER_READ_LOGON | USER_READ_ACCOUNT,
CurrentUser->RelativeId,
&UserHandle);
if (!NT_SUCCESS(Status))
@@ -2861,7 +3024,7 @@
/* Open the user object */
Status = SamOpenUser(AccountDomainHandle,
- USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON |
USER_READ_ACCOUNT,
+ READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES |
USER_READ_LOGON | USER_READ_ACCOUNT,
RelativeIds[0],
&UserHandle);
if (!NT_SUCCESS(Status))