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?rev=61103&r1=61102&r2=61103&view=diff
==============================================================================
--- 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))


Reply via email to