• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
TEST(RestrictedTokenTest,InvalidHandle)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.
TEST(RestrictedTokenTest,DefaultInit)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.
TEST(RestrictedTokenTest,CustomInit)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.
TEST(RestrictedTokenTest,ResultToken)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.
TEST(RestrictedTokenTest,DefaultDacl)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".
TEST(RestrictedTokenTest,DenySid)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".
TEST(RestrictedTokenTest,DenySids)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.
TEST(RestrictedTokenTest,DenySidsException)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.
TEST(RestrictedTokenTest,DenyOwnerSid)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.
TEST(RestrictedTokenTest,DenyOwnerSidCustom)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.
TEST(RestrictedTokenTest,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.
TEST(RestrictedTokenTest,DeleteAllPrivilegesException)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.
TEST(RestrictedTokenTest,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.
CheckRestrictingSid(const ATL::CAccessToken & restricted_token,ATL::CSid sid,int count)409 void CheckRestrictingSid(const ATL::CAccessToken &restricted_token,
410                          ATL::CSid sid, int count) {
411   DWORD length = 8192;
412   BYTE *memory = new BYTE[length];
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.
TEST(RestrictedTokenTest,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.
TEST(RestrictedTokenTest,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.
TEST(RestrictedTokenTest,AddRestrictingSidCurrentUserCustom)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.
TEST(RestrictedTokenTest,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.
TEST(RestrictedTokenTest,AddMultipleRestrictingSids)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 = 8192;
534   BYTE *memory = new BYTE[length];
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".
TEST(RestrictedTokenTest,AddAllSidToRestrictingSids)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 // Checks the error code when the object is initialized twice.
TEST(RestrictedTokenTest,DoubleInit)581 TEST(RestrictedTokenTest, DoubleInit) {
582   RestrictedToken token;
583   ASSERT_EQ(ERROR_SUCCESS, token.Init(NULL));
584 
585   ASSERT_EQ(ERROR_ALREADY_INITIALIZED, token.Init(NULL));
586 }
587 
588 }  // namespace sandbox
589