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
15namespace sandbox {
16
17// Tests the initializatioin with an invalid token handle.
18TEST(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.
24TEST(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.
63TEST(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.
100TEST(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.
141TEST(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".
174TEST(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".
201TEST(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.
230TEST(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.
266TEST(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.
296TEST(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.
334TEST(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.
352TEST(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.
382TEST(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.
409void 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.
442TEST(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.
458TEST(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.
475TEST(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.
500TEST(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.
517TEST(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".
549TEST(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.
581TEST(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