[NTOS:SE] NtQueryInformationToken: implement TokenGroupsAndPrivileges
authorGeorge Bișoc <george.bisoc@reactos.org>
Sun, 19 Jun 2022 10:39:23 +0000 (12:39 +0200)
committerGeorge Bișoc <george.bisoc@reactos.org>
Sun, 19 Jun 2022 15:22:04 +0000 (17:22 +0200)
TokenGroupsAndPrivileges is the younger sister of two TokenGroups and TokenPrivileges classes. In its purpose there's no huge substantial differences apart that this class comes with its own structure, TOKEN_GROUPS_AND_PRIVILEGES, and that this structure comes with extra information.

ntoskrnl/se/tokencls.c

index 24adad4..8bb5598 100644 (file)
@@ -905,9 +905,83 @@ NtQueryInformationToken(
             }
 
             case TokenGroupsAndPrivileges:
-                DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
-                Status = STATUS_NOT_IMPLEMENTED;
+            {
+                PSID Sid, RestrictedSid;
+                ULONG SidLen, RestrictedSidLen;
+                ULONG UserGroupLength, RestrictedSidLength, PrivilegeLength;
+                PTOKEN_GROUPS_AND_PRIVILEGES GroupsAndPrivs = (PTOKEN_GROUPS_AND_PRIVILEGES)TokenInformation;
+
+                DPRINT("NtQueryInformationToken(TokenGroupsAndPrivileges)\n");
+                UserGroupLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount, Token->UserAndGroups);
+                RestrictedSidLength = RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
+                PrivilegeLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+
+                RequiredLength = sizeof(TOKEN_GROUPS_AND_PRIVILEGES) +
+                                 UserGroupLength + RestrictedSidLength + PrivilegeLength;
+
+                _SEH2_TRY
+                {
+                    if (TokenInformationLength >= RequiredLength)
+                    {
+                        GroupsAndPrivs->SidCount = Token->UserAndGroupCount;
+                        GroupsAndPrivs->SidLength = UserGroupLength;
+                        GroupsAndPrivs->Sids = (PSID_AND_ATTRIBUTES)(GroupsAndPrivs + 1);
+
+                        Sid = (PSID)((ULONG_PTR)GroupsAndPrivs->Sids + (Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES)));
+                        SidLen = UserGroupLength - (Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES));
+                        Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount,
+                                                              Token->UserAndGroups,
+                                                              SidLen,
+                                                              GroupsAndPrivs->Sids,
+                                                              Sid,
+                                                              &Unused.PSid,
+                                                              &Unused.Ulong);
+                        NT_ASSERT(NT_SUCCESS(Status));
+
+                        GroupsAndPrivs->RestrictedSidCount = Token->RestrictedSidCount;
+                        GroupsAndPrivs->RestrictedSidLength = RestrictedSidLength;
+                        GroupsAndPrivs->RestrictedSids = NULL;
+                        if (SeTokenIsRestricted(Token))
+                        {
+                            GroupsAndPrivs->RestrictedSids = (PSID_AND_ATTRIBUTES)((ULONG_PTR)GroupsAndPrivs->Sids + UserGroupLength);
+
+                            RestrictedSid = (PSID)((ULONG_PTR)GroupsAndPrivs->RestrictedSids + (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
+                            RestrictedSidLen = RestrictedSidLength - (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
+                            Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
+                                                                  Token->RestrictedSids,
+                                                                  RestrictedSidLen,
+                                                                  GroupsAndPrivs->RestrictedSids,
+                                                                  RestrictedSid,
+                                                                  &Unused.PSid,
+                                                                  &Unused.Ulong);
+                            NT_ASSERT(NT_SUCCESS(Status));
+                        }
+
+                        GroupsAndPrivs->PrivilegeCount = Token->PrivilegeCount;
+                        GroupsAndPrivs->PrivilegeLength = PrivilegeLength;
+                        GroupsAndPrivs->Privileges = (PLUID_AND_ATTRIBUTES)((ULONG_PTR)(GroupsAndPrivs + 1) +
+                                                     UserGroupLength + RestrictedSidLength);
+                        RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
+                                                      Token->Privileges,
+                                                      GroupsAndPrivs->Privileges);
+
+                        GroupsAndPrivs->AuthenticationId = Token->AuthenticationId;
+                    }
+                    else
+                    {
+                        Status = STATUS_BUFFER_TOO_SMALL;
+                    }
+
+                    *ReturnLength = RequiredLength;
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    Status = _SEH2_GetExceptionCode();
+                }
+                _SEH2_END;
+
                 break;
+            }
 
             case TokenRestrictedSids:
             {