Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file contains unit tests for the RestrictedToken.
      6 
      7 #define _ATL_NO_EXCEPTIONS
      8 #include <atlbase.h>
      9 #include <atlsecurity.h>
     10 #include <vector>
     11 #include "sandbox/win/src/restricted_token.h"
     12 #include "sandbox/win/src/sid.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace sandbox {
     16 
     17 // Tests the initializatioin with an invalid token handle.
     18 TEST(RestrictedTokenTest, InvalidHandle) {
     19   RestrictedToken token;
     20   ASSERT_EQ(ERROR_INVALID_HANDLE, token.Init(reinterpret_cast<HANDLE>(0x5555)));
     21 }
     22 
     23 // Tests the initialization with NULL as parameter.
     24 TEST(RestrictedTokenTest, DefaultInit) {
     25   // Get the current process token.
     26   HANDLE token_handle = INVALID_HANDLE_VALUE;
     27   ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
     28                                  &token_handle));
     29 
     30   ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
     31 
     32   ATL::CAccessToken access_token;
     33   access_token.Attach(token_handle);
     34 
     35   // Create the token using the current token.
     36   RestrictedToken token_default;
     37   ASSERT_EQ(ERROR_SUCCESS, token_default.Init(NULL));
     38 
     39   // Get the handle to the restricted token.
     40 
     41   HANDLE restricted_token_handle = NULL;
     42   ASSERT_EQ(ERROR_SUCCESS,
     43       token_default.GetRestrictedTokenHandle(&restricted_token_handle));
     44 
     45   ATL::CAccessToken restricted_token;
     46   restricted_token.Attach(restricted_token_handle);
     47 
     48   ATL::CSid sid_user_restricted;
     49   ATL::CSid sid_user_default;
     50   ATL::CSid sid_owner_restricted;
     51   ATL::CSid sid_owner_default;
     52   ASSERT_TRUE(restricted_token.GetUser(&sid_user_restricted));
     53   ASSERT_TRUE(access_token.GetUser(&sid_user_default));
     54   ASSERT_TRUE(restricted_token.GetOwner(&sid_owner_restricted));
     55   ASSERT_TRUE(access_token.GetOwner(&sid_owner_default));
     56 
     57   // Check if both token have the same owner and user.
     58   ASSERT_EQ(sid_user_restricted, sid_user_default);
     59   ASSERT_EQ(sid_owner_restricted, sid_owner_default);
     60 }
     61 
     62 // Tests the initialization with a custom token as parameter.
     63 TEST(RestrictedTokenTest, CustomInit) {
     64   // Get the current process token.
     65   HANDLE token_handle = INVALID_HANDLE_VALUE;
     66   ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
     67                                  &token_handle));
     68 
     69   ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
     70 
     71   ATL::CAccessToken access_token;
     72   access_token.Attach(token_handle);
     73 
     74   // Change the primary group.
     75   access_token.SetPrimaryGroup(ATL::Sids::World());
     76 
     77   // Create the token using the current token.
     78   RestrictedToken token;
     79   ASSERT_EQ(ERROR_SUCCESS, token.Init(access_token.GetHandle()));
     80 
     81   // Get the handle to the restricted token.
     82 
     83   HANDLE restricted_token_handle = NULL;
     84   ASSERT_EQ(ERROR_SUCCESS,
     85       token.GetRestrictedTokenHandle(&restricted_token_handle));
     86 
     87   ATL::CAccessToken restricted_token;
     88   restricted_token.Attach(restricted_token_handle);
     89 
     90   ATL::CSid sid_restricted;
     91   ATL::CSid sid_default;
     92   ASSERT_TRUE(restricted_token.GetPrimaryGroup(&sid_restricted));
     93   ASSERT_TRUE(access_token.GetPrimaryGroup(&sid_default));
     94 
     95   // Check if both token have the same owner.
     96   ASSERT_EQ(sid_restricted, sid_default);
     97 }
     98 
     99 // Verifies that the token created by the object are valid.
    100 TEST(RestrictedTokenTest, ResultToken) {
    101   RestrictedToken token;
    102   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    103 
    104   ASSERT_EQ(ERROR_SUCCESS,
    105             token.AddRestrictingSid(ATL::Sids::World().GetPSID()));
    106 
    107   HANDLE restricted_token;
    108   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&restricted_token));
    109 
    110   ASSERT_TRUE(::IsTokenRestricted(restricted_token));
    111 
    112   DWORD length = 0;
    113   TOKEN_TYPE type;
    114   ASSERT_TRUE(::GetTokenInformation(restricted_token,
    115                                     ::TokenType,
    116                                     &type,
    117                                     sizeof(type),
    118                                     &length));
    119 
    120   ASSERT_EQ(type, TokenPrimary);
    121 
    122   HANDLE impersonation_token;
    123   ASSERT_EQ(ERROR_SUCCESS,
    124       token.GetRestrictedTokenHandleForImpersonation(&impersonation_token));
    125 
    126   ASSERT_TRUE(::IsTokenRestricted(impersonation_token));
    127 
    128   ASSERT_TRUE(::GetTokenInformation(impersonation_token,
    129                                     ::TokenType,
    130                                     &type,
    131                                     sizeof(type),
    132                                     &length));
    133 
    134   ASSERT_EQ(type, TokenImpersonation);
    135 
    136   ::CloseHandle(impersonation_token);
    137   ::CloseHandle(restricted_token);
    138 }
    139 
    140 // Verifies that the token created has "Restricted" in its default dacl.
    141 TEST(RestrictedTokenTest, DefaultDacl) {
    142   RestrictedToken token;
    143   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    144 
    145   ASSERT_EQ(ERROR_SUCCESS,
    146             token.AddRestrictingSid(ATL::Sids::World().GetPSID()));
    147 
    148   HANDLE handle;
    149   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&handle));
    150 
    151   ATL::CAccessToken restricted_token;
    152   restricted_token.Attach(handle);
    153 
    154   ATL::CDacl dacl;
    155   ASSERT_TRUE(restricted_token.GetDefaultDacl(&dacl));
    156 
    157   bool restricted_found = false;
    158 
    159   unsigned int ace_count = dacl.GetAceCount();
    160   for (unsigned int i = 0; i < ace_count ; ++i) {
    161     ATL::CSid sid;
    162     ACCESS_MASK mask = 0;
    163     dacl.GetAclEntry(i, &sid, &mask);
    164     if (sid == ATL::Sids::RestrictedCode() && mask == GENERIC_ALL) {
    165       restricted_found = true;
    166       break;
    167     }
    168   }
    169 
    170   ASSERT_TRUE(restricted_found);
    171 }
    172 
    173 // Tests the method "AddSidForDenyOnly".
    174 TEST(RestrictedTokenTest, DenySid) {
    175   RestrictedToken token;
    176   HANDLE token_handle = NULL;
    177 
    178   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    179   ASSERT_EQ(ERROR_SUCCESS, token.AddSidForDenyOnly(Sid(WinWorldSid)));
    180   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    181 
    182   ATL::CAccessToken restricted_token;
    183   restricted_token.Attach(token_handle);
    184 
    185   ATL::CTokenGroups groups;
    186   ASSERT_TRUE(restricted_token.GetGroups(&groups));
    187 
    188   ATL::CSid::CSidArray sids;
    189   ATL::CAtlArray<DWORD> attributes;
    190   groups.GetSidsAndAttributes(&sids, &attributes);
    191 
    192   for (unsigned int i = 0; i < sids.GetCount(); i++) {
    193     if (ATL::Sids::World() == sids[i]) {
    194       ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY,
    195                 attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
    196     }
    197   }
    198 }
    199 
    200 // Tests the method "AddAllSidsForDenyOnly".
    201 TEST(RestrictedTokenTest, DenySids) {
    202   RestrictedToken token;
    203   HANDLE token_handle = NULL;
    204 
    205   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    206   ASSERT_EQ(ERROR_SUCCESS, token.AddAllSidsForDenyOnly(NULL));
    207   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    208 
    209   ATL::CAccessToken restricted_token;
    210   restricted_token.Attach(token_handle);
    211 
    212   ATL::CTokenGroups groups;
    213   ASSERT_TRUE(restricted_token.GetGroups(&groups));
    214 
    215   ATL::CSid::CSidArray sids;
    216   ATL::CAtlArray<DWORD> attributes;
    217   groups.GetSidsAndAttributes(&sids, &attributes);
    218 
    219   // Verify that all sids are really gone.
    220   for (unsigned int i = 0; i < sids.GetCount(); i++) {
    221     if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 &&
    222         (attributes[i] & SE_GROUP_INTEGRITY) == 0) {
    223       ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY,
    224                 attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
    225     }
    226   }
    227 }
    228 
    229 // Tests the method "AddAllSidsForDenyOnly" using an exception list.
    230 TEST(RestrictedTokenTest, DenySidsException) {
    231   RestrictedToken token;
    232   HANDLE token_handle = NULL;
    233 
    234   std::vector<Sid> sids_exception;
    235   sids_exception.push_back(Sid(WinWorldSid));
    236 
    237   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    238   ASSERT_EQ(ERROR_SUCCESS, token.AddAllSidsForDenyOnly(&sids_exception));
    239   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    240 
    241   ATL::CAccessToken restricted_token;
    242   restricted_token.Attach(token_handle);
    243 
    244   ATL::CTokenGroups groups;
    245   ASSERT_TRUE(restricted_token.GetGroups(&groups));
    246 
    247   ATL::CSid::CSidArray sids;
    248   ATL::CAtlArray<DWORD> attributes;
    249   groups.GetSidsAndAttributes(&sids, &attributes);
    250 
    251   // Verify that all sids are really gone.
    252   for (unsigned int i = 0; i < sids.GetCount(); i++) {
    253     if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 &&
    254         (attributes[i] & SE_GROUP_INTEGRITY) == 0) {
    255       if (ATL::Sids::World() == sids[i]) {
    256         ASSERT_EQ(NULL, attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
    257       } else {
    258         ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY,
    259                   attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
    260       }
    261     }
    262   }
    263 }
    264 
    265 // Tests test method AddOwnerSidForDenyOnly.
    266 TEST(RestrictedTokenTest, DenyOwnerSid) {
    267   RestrictedToken token;
    268   HANDLE token_handle = NULL;
    269 
    270   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    271   ASSERT_EQ(ERROR_SUCCESS, token.AddUserSidForDenyOnly());
    272   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    273 
    274   ATL::CAccessToken restricted_token;
    275   restricted_token.Attach(token_handle);
    276 
    277   ATL::CTokenGroups groups;
    278   ASSERT_TRUE(restricted_token.GetGroups(&groups));
    279 
    280   ATL::CSid::CSidArray sids;
    281   ATL::CAtlArray<DWORD> attributes;
    282   groups.GetSidsAndAttributes(&sids, &attributes);
    283 
    284   ATL::CSid user_sid;
    285   ASSERT_TRUE(restricted_token.GetUser(&user_sid));
    286 
    287   for (unsigned int i = 0; i < sids.GetCount(); ++i) {
    288     if (user_sid == sids[i]) {
    289       ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY,
    290                 attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
    291     }
    292   }
    293 }
    294 
    295 // Tests test method AddOwnerSidForDenyOnly with a custom effective token.
    296 TEST(RestrictedTokenTest, DenyOwnerSidCustom) {
    297   // Get the current process token.
    298   HANDLE token_handle = INVALID_HANDLE_VALUE;
    299   ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
    300                                  &token_handle));
    301 
    302   ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
    303 
    304   ATL::CAccessToken access_token;
    305   access_token.Attach(token_handle);
    306 
    307   RestrictedToken token;
    308   ASSERT_EQ(ERROR_SUCCESS, token.Init(access_token.GetHandle()));
    309   ASSERT_EQ(ERROR_SUCCESS, token.AddUserSidForDenyOnly());
    310   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    311 
    312   ATL::CAccessToken restricted_token;
    313   restricted_token.Attach(token_handle);
    314 
    315   ATL::CTokenGroups groups;
    316   ASSERT_TRUE(restricted_token.GetGroups(&groups));
    317 
    318   ATL::CSid::CSidArray sids;
    319   ATL::CAtlArray<DWORD> attributes;
    320   groups.GetSidsAndAttributes(&sids, &attributes);
    321 
    322   ATL::CSid user_sid;
    323   ASSERT_TRUE(restricted_token.GetUser(&user_sid));
    324 
    325   for (unsigned int i = 0; i < sids.GetCount(); ++i) {
    326     if (user_sid == sids[i]) {
    327       ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY,
    328                 attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
    329     }
    330   }
    331 }
    332 
    333 // Tests the method DeleteAllPrivileges.
    334 TEST(RestrictedTokenTest, DeleteAllPrivileges) {
    335   RestrictedToken token;
    336   HANDLE token_handle = NULL;
    337 
    338   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    339   ASSERT_EQ(ERROR_SUCCESS, token.DeleteAllPrivileges(NULL));
    340   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    341 
    342   ATL::CAccessToken restricted_token;
    343   restricted_token.Attach(token_handle);
    344 
    345   ATL::CTokenPrivileges privileges;
    346   ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
    347 
    348   ASSERT_EQ(0, privileges.GetCount());
    349 }
    350 
    351 // Tests the method DeleteAllPrivileges with an exception list.
    352 TEST(RestrictedTokenTest, DeleteAllPrivilegesException) {
    353   RestrictedToken token;
    354   HANDLE token_handle = NULL;
    355 
    356   std::vector<base::string16> exceptions;
    357   exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
    358 
    359   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    360   ASSERT_EQ(ERROR_SUCCESS, token.DeleteAllPrivileges(&exceptions));
    361   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    362 
    363   ATL::CAccessToken restricted_token;
    364   restricted_token.Attach(token_handle);
    365 
    366   ATL::CTokenPrivileges privileges;
    367   ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
    368 
    369   ATL::CTokenPrivileges::CNames privilege_names;
    370   ATL::CTokenPrivileges::CAttributes privilege_name_attributes;
    371   privileges.GetNamesAndAttributes(&privilege_names,
    372                                    &privilege_name_attributes);
    373 
    374   ASSERT_EQ(1, privileges.GetCount());
    375 
    376   for (unsigned int i = 0; i < privileges.GetCount(); ++i) {
    377     ASSERT_EQ(privilege_names[i], SE_CHANGE_NOTIFY_NAME);
    378   }
    379 }
    380 
    381 // Tests the method DeletePrivilege.
    382 TEST(RestrictedTokenTest, DeletePrivilege) {
    383   RestrictedToken token;
    384   HANDLE token_handle = NULL;
    385 
    386   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    387   ASSERT_EQ(ERROR_SUCCESS, token.DeletePrivilege(SE_CHANGE_NOTIFY_NAME));
    388   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    389 
    390   ATL::CAccessToken restricted_token;
    391   restricted_token.Attach(token_handle);
    392 
    393   ATL::CTokenPrivileges privileges;
    394   ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
    395 
    396   ATL::CTokenPrivileges::CNames privilege_names;
    397   ATL::CTokenPrivileges::CAttributes privilege_name_attributes;
    398   privileges.GetNamesAndAttributes(&privilege_names,
    399                                    &privilege_name_attributes);
    400 
    401   for (unsigned int i = 0; i < privileges.GetCount(); ++i) {
    402     ASSERT_NE(privilege_names[i], SE_CHANGE_NOTIFY_NAME);
    403   }
    404 }
    405 
    406 // Checks if a sid is in the restricting list of the restricted token.
    407 // Asserts if it's not the case. If count is a positive number, the number of
    408 // elements in the restricting sids list has to be equal.
    409 void CheckRestrictingSid(const ATL::CAccessToken &restricted_token,
    410                          ATL::CSid sid, int count) {
    411   DWORD length = 1000;
    412   BYTE *memory = new BYTE[1000];
    413   TOKEN_GROUPS *groups = reinterpret_cast<TOKEN_GROUPS*>(memory);
    414   ASSERT_TRUE(::GetTokenInformation(restricted_token.GetHandle(),
    415                                     TokenRestrictedSids,
    416                                     groups,
    417                                     length,
    418                                     &length));
    419 
    420   ATL::CTokenGroups atl_groups(*groups);
    421   delete[] memory;
    422 
    423   if (count >= 0)
    424     ASSERT_EQ(count, atl_groups.GetCount());
    425 
    426   ATL::CSid::CSidArray sids;
    427   ATL::CAtlArray<DWORD> attributes;
    428   atl_groups.GetSidsAndAttributes(&sids, &attributes);
    429 
    430   bool present = false;
    431   for (unsigned int i = 0; i < sids.GetCount(); ++i) {
    432     if (sids[i] == sid) {
    433       present = true;
    434       break;
    435     }
    436   }
    437 
    438   ASSERT_TRUE(present);
    439 }
    440 
    441 // Tests the method AddRestrictingSid.
    442 TEST(RestrictedTokenTest, AddRestrictingSid) {
    443   RestrictedToken token;
    444   HANDLE token_handle = NULL;
    445 
    446   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    447   ASSERT_EQ(ERROR_SUCCESS,
    448             token.AddRestrictingSid(ATL::Sids::World().GetPSID()));
    449   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    450 
    451   ATL::CAccessToken restricted_token;
    452   restricted_token.Attach(token_handle);
    453 
    454   CheckRestrictingSid(restricted_token, ATL::Sids::World(), 1);
    455 }
    456 
    457 // Tests the method AddRestrictingSidCurrentUser.
    458 TEST(RestrictedTokenTest, AddRestrictingSidCurrentUser) {
    459   RestrictedToken token;
    460   HANDLE token_handle = NULL;
    461 
    462   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    463   ASSERT_EQ(ERROR_SUCCESS, token.AddRestrictingSidCurrentUser());
    464   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    465 
    466   ATL::CAccessToken restricted_token;
    467   restricted_token.Attach(token_handle);
    468   ATL::CSid user;
    469   restricted_token.GetUser(&user);
    470 
    471   CheckRestrictingSid(restricted_token, user, 1);
    472 }
    473 
    474 // Tests the method AddRestrictingSidCurrentUser with a custom effective token.
    475 TEST(RestrictedTokenTest, AddRestrictingSidCurrentUserCustom) {
    476   // Get the current process token.
    477   HANDLE token_handle = INVALID_HANDLE_VALUE;
    478   ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
    479                                  &token_handle));
    480 
    481   ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
    482 
    483   ATL::CAccessToken access_token;
    484   access_token.Attach(token_handle);
    485 
    486   RestrictedToken token;
    487   ASSERT_EQ(ERROR_SUCCESS, token.Init(access_token.GetHandle()));
    488   ASSERT_EQ(ERROR_SUCCESS, token.AddRestrictingSidCurrentUser());
    489   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    490 
    491   ATL::CAccessToken restricted_token;
    492   restricted_token.Attach(token_handle);
    493   ATL::CSid user;
    494   restricted_token.GetUser(&user);
    495 
    496   CheckRestrictingSid(restricted_token, user, 1);
    497 }
    498 
    499 // Tests the method AddRestrictingSidLogonSession.
    500 TEST(RestrictedTokenTest, AddRestrictingSidLogonSession) {
    501   RestrictedToken token;
    502   HANDLE token_handle = NULL;
    503 
    504   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    505   ASSERT_EQ(ERROR_SUCCESS, token.AddRestrictingSidLogonSession());
    506   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    507 
    508   ATL::CAccessToken restricted_token;
    509   restricted_token.Attach(token_handle);
    510   ATL::CSid session;
    511   restricted_token.GetLogonSid(&session);
    512 
    513   CheckRestrictingSid(restricted_token, session, 1);
    514 }
    515 
    516 // Tests adding a lot of restricting sids.
    517 TEST(RestrictedTokenTest, AddMultipleRestrictingSids) {
    518   RestrictedToken token;
    519   HANDLE token_handle = NULL;
    520 
    521   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    522   ASSERT_EQ(ERROR_SUCCESS, token.AddRestrictingSidCurrentUser());
    523   ASSERT_EQ(ERROR_SUCCESS, token.AddRestrictingSidLogonSession());
    524   ASSERT_EQ(ERROR_SUCCESS,
    525             token.AddRestrictingSid(ATL::Sids::World().GetPSID()));
    526   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    527 
    528   ATL::CAccessToken restricted_token;
    529   restricted_token.Attach(token_handle);
    530   ATL::CSid session;
    531   restricted_token.GetLogonSid(&session);
    532 
    533   DWORD length = 1000;
    534   BYTE *memory = new BYTE[1000];
    535   TOKEN_GROUPS *groups = reinterpret_cast<TOKEN_GROUPS*>(memory);
    536   ASSERT_TRUE(::GetTokenInformation(restricted_token.GetHandle(),
    537                                     TokenRestrictedSids,
    538                                     groups,
    539                                     length,
    540                                     &length));
    541 
    542   ATL::CTokenGroups atl_groups(*groups);
    543   delete[] memory;
    544 
    545   ASSERT_EQ(3, atl_groups.GetCount());
    546 }
    547 
    548 // Tests the method "AddRestrictingSidAllSids".
    549 TEST(RestrictedTokenTest, AddAllSidToRestrictingSids) {
    550   RestrictedToken token;
    551   HANDLE token_handle = NULL;
    552 
    553   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    554   ASSERT_EQ(ERROR_SUCCESS, token.AddRestrictingSidAllSids());
    555   ASSERT_EQ(ERROR_SUCCESS, token.GetRestrictedTokenHandle(&token_handle));
    556 
    557   ATL::CAccessToken restricted_token;
    558   restricted_token.Attach(token_handle);
    559 
    560   ATL::CTokenGroups groups;
    561   ASSERT_TRUE(restricted_token.GetGroups(&groups));
    562 
    563   ATL::CSid::CSidArray sids;
    564   ATL::CAtlArray<DWORD> attributes;
    565   groups.GetSidsAndAttributes(&sids, &attributes);
    566 
    567   // Verify that all group sids are in the restricting sid list.
    568   for (unsigned int i = 0; i < sids.GetCount(); i++) {
    569     if ((attributes[i] & SE_GROUP_INTEGRITY) == 0) {
    570       CheckRestrictingSid(restricted_token, sids[i], -1);
    571     }
    572   }
    573 
    574   // Verify that the user is in the restricting sid list.
    575   ATL::CSid user;
    576   restricted_token.GetUser(&user);
    577   CheckRestrictingSid(restricted_token, user, -1);
    578 }
    579 
    580 // Test to be executed only in release because they are triggering DCHECKs.
    581 #ifndef _DEBUG
    582 
    583 // Checks the error code when the object is initialized twice.
    584 TEST(RestrictedTokenTest, DoubleInit) {
    585   RestrictedToken token;
    586   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
    587 
    588   ASSERT_EQ(ERROR_ALREADY_INITIALIZED, token.Init(NULL));
    589 }
    590 
    591 #endif
    592 
    593 }  // namespace sandbox
    594