restricted_token_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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. // This file contains unit tests for the RestrictedToken.
  5. #include "sandbox/win/src/restricted_token.h"
  6. #include <vector>
  7. #include "base/win/access_token.h"
  8. #include "base/win/atl.h"
  9. #include "base/win/scoped_handle.h"
  10. #include "base/win/sid.h"
  11. #include "base/win/windows_version.h"
  12. #include "sandbox/win/src/acl.h"
  13. #include "sandbox/win/src/security_capabilities.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. namespace sandbox {
  17. namespace {
  18. void TestDefaultDalc(bool restricted_required, bool additional_sid_required) {
  19. RestrictedToken token;
  20. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  21. if (!restricted_required)
  22. token.SetLockdownDefaultDacl();
  23. ATL::CSid additional_sid = ATL::Sids::Guests();
  24. ATL::CSid additional_sid2 = ATL::Sids::Batch();
  25. if (additional_sid_required) {
  26. token.AddDefaultDaclSid(
  27. *base::win::Sid::FromPSID(const_cast<SID*>(additional_sid.GetPSID())),
  28. SecurityAccessMode::kGrant, READ_CONTROL);
  29. token.AddDefaultDaclSid(
  30. *base::win::Sid::FromPSID(const_cast<SID*>(additional_sid2.GetPSID())),
  31. SecurityAccessMode::kDeny, GENERIC_ALL);
  32. }
  33. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  34. token.AddRestrictingSid(base::win::WellKnownSid::kWorld));
  35. base::win::ScopedHandle handle;
  36. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  37. token.GetRestrictedToken(&handle));
  38. ATL::CAccessToken restricted_token;
  39. restricted_token.Attach(handle.Take());
  40. ATL::CDacl dacl;
  41. ASSERT_TRUE(restricted_token.GetDefaultDacl(&dacl));
  42. ATL::CSid logon_sid;
  43. ASSERT_TRUE(restricted_token.GetLogonSid(&logon_sid));
  44. bool restricted_found = false;
  45. bool logon_sid_found = false;
  46. bool additional_sid_found = false;
  47. bool additional_sid2_found = false;
  48. unsigned int ace_count = dacl.GetAceCount();
  49. for (unsigned int i = 0; i < ace_count; ++i) {
  50. ATL::CSid sid;
  51. ACCESS_MASK mask = 0;
  52. BYTE ace_type = 0;
  53. dacl.GetAclEntry(i, &sid, &mask, &ace_type);
  54. if (sid == ATL::Sids::RestrictedCode() && mask == GENERIC_ALL) {
  55. restricted_found = true;
  56. } else if (sid == logon_sid) {
  57. logon_sid_found = true;
  58. } else if (sid == additional_sid && mask == READ_CONTROL &&
  59. ace_type == ACCESS_ALLOWED_ACE_TYPE) {
  60. additional_sid_found = true;
  61. } else if (sid == additional_sid2 && mask == GENERIC_ALL &&
  62. ace_type == ACCESS_DENIED_ACE_TYPE) {
  63. additional_sid2_found = true;
  64. }
  65. }
  66. ASSERT_EQ(restricted_required, restricted_found);
  67. ASSERT_EQ(additional_sid_required, additional_sid_found);
  68. ASSERT_EQ(additional_sid_required, additional_sid2_found);
  69. if (!restricted_required)
  70. ASSERT_FALSE(logon_sid_found);
  71. }
  72. void CheckDaclForPackageSid(const base::win::ScopedHandle& token,
  73. PSECURITY_CAPABILITIES security_capabilities,
  74. bool package_sid_required) {
  75. DWORD length_needed = 0;
  76. ::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION, nullptr, 0,
  77. &length_needed);
  78. ASSERT_EQ(::GetLastError(), DWORD{ERROR_INSUFFICIENT_BUFFER});
  79. std::vector<char> security_desc_buffer(length_needed);
  80. SECURITY_DESCRIPTOR* security_desc =
  81. reinterpret_cast<SECURITY_DESCRIPTOR*>(security_desc_buffer.data());
  82. ASSERT_TRUE(::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION,
  83. security_desc, length_needed,
  84. &length_needed));
  85. ATL::CSecurityDesc token_sd(*security_desc);
  86. ATL::CDacl dacl;
  87. ASSERT_TRUE(token_sd.GetDacl(&dacl));
  88. base::win::Sid package_sid =
  89. *base::win::Sid::FromPSID(security_capabilities->AppContainerSid);
  90. base::win::Sid all_package_sid = *base::win::Sid::FromKnownSid(
  91. base::win::WellKnownSid::kAllApplicationPackages);
  92. unsigned int ace_count = dacl.GetAceCount();
  93. for (unsigned int i = 0; i < ace_count; ++i) {
  94. ATL::CSid sid;
  95. ACCESS_MASK mask = 0;
  96. BYTE type = 0;
  97. dacl.GetAclEntry(i, &sid, &mask, &type);
  98. if (mask != TOKEN_ALL_ACCESS || type != ACCESS_ALLOWED_ACE_TYPE)
  99. continue;
  100. PSID psid = const_cast<SID*>(sid.GetPSID());
  101. if (package_sid.Equal(psid))
  102. EXPECT_TRUE(package_sid_required);
  103. else if (all_package_sid.Equal(psid))
  104. EXPECT_FALSE(package_sid_required);
  105. }
  106. }
  107. void CheckLowBoxToken(const base::win::ScopedHandle& lowbox_token,
  108. bool impersonation,
  109. PSECURITY_CAPABILITIES security_capabilities) {
  110. auto token = base::win::AccessToken::FromToken(lowbox_token.Get());
  111. ASSERT_TRUE(token);
  112. EXPECT_TRUE(token->IsAppContainer());
  113. EXPECT_EQ(impersonation, token->IsImpersonation());
  114. EXPECT_FALSE(token->IsIdentification());
  115. auto package_sid = token->AppContainerSid();
  116. ASSERT_TRUE(package_sid);
  117. EXPECT_TRUE(package_sid->Equal(security_capabilities->AppContainerSid));
  118. auto capabilities = token->Capabilities();
  119. ASSERT_EQ(capabilities.size(), security_capabilities->CapabilityCount);
  120. for (size_t index = 0; index < capabilities.size(); ++index) {
  121. EXPECT_EQ(capabilities[index].GetAttributes(),
  122. security_capabilities->Capabilities[index].Attributes);
  123. EXPECT_TRUE(capabilities[index].GetSid().Equal(
  124. security_capabilities->Capabilities[index].Sid));
  125. }
  126. CheckDaclForPackageSid(lowbox_token, security_capabilities, true);
  127. }
  128. // Checks if a sid is in the restricting list of the restricted token.
  129. // Asserts if it's not the case. If count is a positive number, the number of
  130. // elements in the restricting sids list has to be equal.
  131. void CheckRestrictingSid(const base::win::AccessToken& token,
  132. const base::win::Sid& sid,
  133. int count) {
  134. auto restricted_sids = token.RestrictedSids();
  135. if (count >= 0)
  136. ASSERT_EQ(static_cast<unsigned>(count), restricted_sids.size());
  137. bool present = false;
  138. for (const base::win::AccessToken::Group& group : restricted_sids) {
  139. if (group.GetSid() == sid) {
  140. present = true;
  141. break;
  142. }
  143. }
  144. ASSERT_TRUE(present);
  145. }
  146. void CheckRestrictingSid(const base::win::AccessToken& token,
  147. base::win::WellKnownSid known_sid,
  148. int count) {
  149. CheckRestrictingSid(token, *base::win::Sid::FromKnownSid(known_sid), count);
  150. }
  151. void CheckRestrictingSid(HANDLE restricted_token,
  152. base::win::WellKnownSid known_sid,
  153. int count) {
  154. auto token = base::win::AccessToken::FromToken(restricted_token);
  155. ASSERT_TRUE(token);
  156. CheckRestrictingSid(*token, known_sid, count);
  157. }
  158. } // namespace
  159. // Tests the initializatioin with an invalid token handle.
  160. TEST(RestrictedTokenTest, InvalidHandle) {
  161. RestrictedToken token;
  162. ASSERT_EQ(static_cast<DWORD>(ERROR_INVALID_HANDLE),
  163. token.Init(reinterpret_cast<HANDLE>(0x5555)));
  164. }
  165. // Tests the initialization with nullptr as parameter.
  166. TEST(RestrictedTokenTest, DefaultInit) {
  167. // Get the current process token.
  168. absl::optional<base::win::AccessToken> access_token =
  169. base::win::AccessToken::FromCurrentProcess();
  170. ASSERT_TRUE(access_token);
  171. // Create the token using the current token.
  172. RestrictedToken token_default;
  173. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token_default.Init(nullptr));
  174. // Get the handle to the restricted token.
  175. base::win::ScopedHandle restricted_token_handle;
  176. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  177. token_default.GetRestrictedToken(&restricted_token_handle));
  178. auto restricted_token =
  179. base::win::AccessToken::FromToken(restricted_token_handle.Get());
  180. ASSERT_TRUE(restricted_token);
  181. // Check if both token have the same owner and user.
  182. EXPECT_EQ(restricted_token->User(), access_token->User());
  183. EXPECT_EQ(restricted_token->Owner(), access_token->Owner());
  184. }
  185. // Tests the initialization with a custom token as parameter.
  186. TEST(RestrictedTokenTest, CustomInit) {
  187. CAccessToken access_token;
  188. ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
  189. // Change the primary group.
  190. access_token.SetPrimaryGroup(ATL::Sids::World());
  191. // Create the token using the current token.
  192. RestrictedToken token;
  193. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  194. token.Init(access_token.GetHandle()));
  195. base::win::ScopedHandle restricted_token_handle;
  196. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  197. token.GetRestrictedToken(&restricted_token_handle));
  198. auto restricted_token =
  199. base::win::AccessToken::FromToken(restricted_token_handle.Get());
  200. ASSERT_TRUE(restricted_token);
  201. ATL::CSid sid_default;
  202. ASSERT_TRUE(access_token.GetPrimaryGroup(&sid_default));
  203. // Check if both token have the same primary grou.
  204. ASSERT_TRUE(restricted_token->PrimaryGroup().Equal(
  205. const_cast<SID*>(sid_default.GetPSID())));
  206. }
  207. // Verifies that the token created by the object are valid.
  208. TEST(RestrictedTokenTest, ResultToken) {
  209. RestrictedToken token;
  210. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  211. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  212. token.AddRestrictingSid(base::win::WellKnownSid::kWorld));
  213. base::win::ScopedHandle restricted_token;
  214. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  215. token.GetRestrictedToken(&restricted_token));
  216. auto primary = base::win::AccessToken::FromToken(restricted_token.Get());
  217. ASSERT_TRUE(primary);
  218. EXPECT_TRUE(primary->IsRestricted());
  219. EXPECT_FALSE(primary->IsImpersonation());
  220. base::win::ScopedHandle impersonation_token;
  221. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  222. token.GetRestrictedTokenForImpersonation(&impersonation_token));
  223. auto impersonation =
  224. base::win::AccessToken::FromToken(impersonation_token.Get());
  225. ASSERT_TRUE(impersonation);
  226. ASSERT_TRUE(impersonation->IsRestricted());
  227. ASSERT_TRUE(impersonation->IsImpersonation());
  228. ASSERT_FALSE(impersonation->IsIdentification());
  229. }
  230. // Verifies that the token created has "Restricted" in its default dacl.
  231. TEST(RestrictedTokenTest, DefaultDacl) {
  232. TestDefaultDalc(true, false);
  233. }
  234. // Verifies that the token created does not have "Restricted" in its default
  235. // dacl.
  236. TEST(RestrictedTokenTest, DefaultDaclLockdown) {
  237. TestDefaultDalc(false, false);
  238. }
  239. // Verifies that the token created has an additional SID in its default dacl.
  240. TEST(RestrictedTokenTest, DefaultDaclWithAddition) {
  241. TestDefaultDalc(true, true);
  242. }
  243. // Verifies that the token created does not have "Restricted" in its default
  244. // dacl and also has an additional SID.
  245. TEST(RestrictedTokenTest, DefaultDaclLockdownWithAddition) {
  246. TestDefaultDalc(false, true);
  247. }
  248. // Tests the method "AddSidForDenyOnly".
  249. TEST(RestrictedTokenTest, DenySid) {
  250. RestrictedToken token;
  251. base::win::ScopedHandle token_handle;
  252. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  253. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  254. token.AddSidForDenyOnly(base::win::WellKnownSid::kWorld));
  255. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  256. token.GetRestrictedToken(&token_handle));
  257. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  258. ASSERT_TRUE(restricted_token);
  259. auto sid = base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld);
  260. bool found_sid = false;
  261. for (const auto& group : restricted_token->Groups()) {
  262. if (sid == group.GetSid()) {
  263. ASSERT_TRUE(group.IsDenyOnly());
  264. found_sid = true;
  265. }
  266. }
  267. ASSERT_TRUE(found_sid);
  268. }
  269. // Tests the method "AddAllSidsForDenyOnly".
  270. TEST(RestrictedTokenTest, DenySids) {
  271. RestrictedToken token;
  272. base::win::ScopedHandle token_handle;
  273. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  274. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddAllSidsForDenyOnly({}));
  275. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  276. token.GetRestrictedToken(&token_handle));
  277. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  278. ASSERT_TRUE(restricted_token);
  279. bool found_sid = false;
  280. // Verify that all sids are really gone.
  281. for (const auto& group : restricted_token->Groups()) {
  282. if (group.IsLogonId() || group.IsIntegrity())
  283. continue;
  284. ASSERT_TRUE(group.IsDenyOnly());
  285. found_sid = true;
  286. }
  287. // Check we at least found one SID.
  288. ASSERT_TRUE(found_sid);
  289. }
  290. // Tests the method "AddAllSidsForDenyOnly" using an exception list.
  291. TEST(RestrictedTokenTest, DenySidsException) {
  292. RestrictedToken token;
  293. base::win::ScopedHandle token_handle;
  294. std::vector<base::win::Sid> sids_exception;
  295. auto sid = base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld);
  296. ASSERT_TRUE(sid);
  297. sids_exception.push_back(sid->Clone());
  298. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  299. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  300. token.AddAllSidsForDenyOnly(sids_exception));
  301. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  302. token.GetRestrictedToken(&token_handle));
  303. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  304. ASSERT_TRUE(restricted_token);
  305. bool found_sid = false;
  306. // Verify that all sids are really gone.
  307. for (const auto& group : restricted_token->Groups()) {
  308. if (group.IsLogonId() || group.IsIntegrity())
  309. continue;
  310. if (sid == group.GetSid()) {
  311. ASSERT_FALSE(group.IsDenyOnly());
  312. // Check we at least found one SID.
  313. found_sid = true;
  314. } else {
  315. ASSERT_TRUE(group.IsDenyOnly());
  316. }
  317. }
  318. ASSERT_TRUE(found_sid);
  319. }
  320. // Tests test method AddOwnerSidForDenyOnly.
  321. TEST(RestrictedTokenTest, DenyOwnerSid) {
  322. RestrictedToken token;
  323. base::win::ScopedHandle token_handle;
  324. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  325. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly());
  326. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  327. token.GetRestrictedToken(&token_handle));
  328. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  329. ASSERT_TRUE(restricted_token);
  330. EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly());
  331. }
  332. // Tests test method AddOwnerSidForDenyOnly with a custom effective token.
  333. TEST(RestrictedTokenTest, DenyOwnerSidCustom) {
  334. CAccessToken access_token;
  335. ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
  336. RestrictedToken token;
  337. base::win::ScopedHandle token_handle;
  338. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  339. token.Init(access_token.GetHandle()));
  340. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly());
  341. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  342. token.GetRestrictedToken(&token_handle));
  343. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  344. ASSERT_TRUE(restricted_token);
  345. EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly());
  346. }
  347. // Tests the method DeleteAllPrivileges.
  348. TEST(RestrictedTokenTest, DeleteAllPrivileges) {
  349. RestrictedToken token;
  350. base::win::ScopedHandle token_handle;
  351. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  352. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  353. token.DeleteAllPrivileges(/*remove_traversal_privilege=*/true));
  354. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  355. token.GetRestrictedToken(&token_handle));
  356. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  357. ASSERT_TRUE(restricted_token);
  358. EXPECT_TRUE(restricted_token->Privileges().empty());
  359. }
  360. // Tests the method DeleteAllPrivileges with an exception list.
  361. TEST(RestrictedTokenTest, DeleteAllPrivilegesException) {
  362. RestrictedToken token;
  363. base::win::ScopedHandle token_handle;
  364. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  365. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  366. token.DeleteAllPrivileges(/*remove_traversal_privilege=*/false));
  367. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  368. token.GetRestrictedToken(&token_handle));
  369. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  370. ASSERT_TRUE(restricted_token);
  371. auto privileges = restricted_token->Privileges();
  372. ASSERT_EQ(1U, privileges.size());
  373. EXPECT_EQ(privileges[0].GetName(), SE_CHANGE_NOTIFY_NAME);
  374. }
  375. // Tests the method AddRestrictingSid.
  376. TEST(RestrictedTokenTest, AddRestrictingSid) {
  377. RestrictedToken token;
  378. base::win::ScopedHandle token_handle;
  379. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  380. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  381. token.AddRestrictingSid(base::win::WellKnownSid::kWorld));
  382. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  383. token.GetRestrictedToken(&token_handle));
  384. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  385. ASSERT_TRUE(restricted_token);
  386. CheckRestrictingSid(*restricted_token, base::win::WellKnownSid::kWorld, 1);
  387. }
  388. // Tests the method AddRestrictingSidCurrentUser.
  389. TEST(RestrictedTokenTest, AddRestrictingSidCurrentUser) {
  390. RestrictedToken token;
  391. base::win::ScopedHandle token_handle;
  392. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  393. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  394. token.AddRestrictingSidCurrentUser());
  395. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  396. token.GetRestrictedToken(&token_handle));
  397. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  398. ASSERT_TRUE(restricted_token);
  399. CheckRestrictingSid(*restricted_token, restricted_token->User(), 1);
  400. }
  401. // Tests the method AddRestrictingSidCurrentUser with a custom effective token.
  402. TEST(RestrictedTokenTest, AddRestrictingSidCurrentUserCustom) {
  403. CAccessToken access_token;
  404. ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
  405. RestrictedToken token;
  406. base::win::ScopedHandle token_handle;
  407. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  408. token.Init(access_token.GetHandle()));
  409. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  410. token.AddRestrictingSidCurrentUser());
  411. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  412. token.GetRestrictedToken(&token_handle));
  413. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  414. ASSERT_TRUE(restricted_token);
  415. CheckRestrictingSid(*restricted_token, restricted_token->User(), 1);
  416. }
  417. // Tests the method AddRestrictingSidLogonSession.
  418. TEST(RestrictedTokenTest, AddRestrictingSidLogonSession) {
  419. RestrictedToken token;
  420. base::win::ScopedHandle token_handle;
  421. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  422. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  423. token.AddRestrictingSidLogonSession());
  424. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  425. token.GetRestrictedToken(&token_handle));
  426. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  427. ASSERT_TRUE(restricted_token);
  428. auto session = restricted_token->LogonId();
  429. if (!session) {
  430. ASSERT_EQ(static_cast<DWORD>(ERROR_NOT_FOUND), ::GetLastError());
  431. return;
  432. }
  433. CheckRestrictingSid(*restricted_token, *session, 1);
  434. }
  435. // Tests adding a lot of restricting sids.
  436. TEST(RestrictedTokenTest, AddMultipleRestrictingSids) {
  437. RestrictedToken token;
  438. base::win::ScopedHandle token_handle;
  439. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  440. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  441. token.AddRestrictingSidCurrentUser());
  442. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  443. token.AddRestrictingSidLogonSession());
  444. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  445. token.AddRestrictingSid(base::win::WellKnownSid::kWorld));
  446. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  447. token.GetRestrictedToken(&token_handle));
  448. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  449. ASSERT_TRUE(restricted_token);
  450. ASSERT_EQ(3u, restricted_token->RestrictedSids().size());
  451. }
  452. // Tests the method "AddRestrictingSidAllSids".
  453. TEST(RestrictedTokenTest, AddAllSidToRestrictingSids) {
  454. RestrictedToken token;
  455. base::win::ScopedHandle token_handle;
  456. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  457. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  458. token.AddRestrictingSidAllSids());
  459. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
  460. token.GetRestrictedToken(&token_handle));
  461. auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
  462. ASSERT_TRUE(restricted_token);
  463. auto groups = restricted_token->Groups();
  464. // Verify that all group sids are in the restricting sid list.
  465. for (const auto& group : groups) {
  466. if (!group.IsIntegrity())
  467. CheckRestrictingSid(*restricted_token, group.GetSid(), -1);
  468. }
  469. CheckRestrictingSid(*restricted_token, restricted_token->User(), -1);
  470. }
  471. // Checks the error code when the object is initialized twice.
  472. TEST(RestrictedTokenTest, DoubleInit) {
  473. RestrictedToken token;
  474. ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
  475. ASSERT_EQ(static_cast<DWORD>(ERROR_ALREADY_INITIALIZED), token.Init(nullptr));
  476. }
  477. TEST(RestrictedTokenTest, LockdownDefaultDaclNoLogonSid) {
  478. ATL::CAccessToken anonymous_token;
  479. ASSERT_TRUE(::ImpersonateAnonymousToken(::GetCurrentThread()));
  480. ASSERT_TRUE(anonymous_token.GetThreadToken(TOKEN_ALL_ACCESS));
  481. ::RevertToSelf();
  482. ATL::CSid logon_sid;
  483. // Verify that the anonymous token doesn't have the logon sid.
  484. ASSERT_FALSE(anonymous_token.GetLogonSid(&logon_sid));
  485. RestrictedToken token;
  486. ASSERT_EQ(DWORD{ERROR_SUCCESS}, token.Init(anonymous_token.GetHandle()));
  487. token.SetLockdownDefaultDacl();
  488. base::win::ScopedHandle handle;
  489. ASSERT_EQ(DWORD{ERROR_SUCCESS}, token.GetRestrictedToken(&handle));
  490. }
  491. TEST(RestrictedTokenTest, LowBoxToken) {
  492. if (base::win::GetVersion() < base::win::Version::WIN8)
  493. return;
  494. base::win::ScopedHandle token;
  495. auto package_sid = base::win::Sid::FromSddlString(L"S-1-15-2-1-2-3-4-5-6-7");
  496. ASSERT_TRUE(package_sid);
  497. SecurityCapabilities caps_no_capabilities(*package_sid);
  498. ASSERT_EQ(
  499. DWORD{ERROR_INVALID_PARAMETER},
  500. CreateLowBoxToken(nullptr, PRIMARY, &caps_no_capabilities, nullptr));
  501. ASSERT_EQ(DWORD{ERROR_SUCCESS},
  502. CreateLowBoxToken(nullptr, PRIMARY, &caps_no_capabilities, &token));
  503. ASSERT_TRUE(token.IsValid());
  504. CheckLowBoxToken(token, false, &caps_no_capabilities);
  505. ASSERT_TRUE(ReplacePackageSidInDacl(token.Get(), SecurityObjectType::kKernel,
  506. *package_sid, TOKEN_ALL_ACCESS));
  507. CheckDaclForPackageSid(token, &caps_no_capabilities, false);
  508. ASSERT_EQ(
  509. DWORD{ERROR_SUCCESS},
  510. CreateLowBoxToken(nullptr, IMPERSONATION, &caps_no_capabilities, &token));
  511. ASSERT_TRUE(token.IsValid());
  512. CheckLowBoxToken(token, true, &caps_no_capabilities);
  513. auto capabilities = base::win::Sid::FromKnownCapabilityVector(
  514. {base::win::WellKnownCapability::kInternetClient,
  515. base::win::WellKnownCapability::kPrivateNetworkClientServer});
  516. ASSERT_TRUE(capabilities);
  517. SecurityCapabilities caps_with_capabilities(*package_sid, *capabilities);
  518. ASSERT_EQ(
  519. DWORD{ERROR_SUCCESS},
  520. CreateLowBoxToken(nullptr, PRIMARY, &caps_with_capabilities, &token));
  521. ASSERT_TRUE(token.IsValid());
  522. CheckLowBoxToken(token, false, &caps_with_capabilities);
  523. RestrictedToken restricted_token;
  524. base::win::ScopedHandle token_handle;
  525. ASSERT_EQ(DWORD{ERROR_SUCCESS}, restricted_token.Init(nullptr));
  526. ASSERT_EQ(DWORD{ERROR_SUCCESS}, restricted_token.AddRestrictingSid(
  527. base::win::WellKnownSid::kWorld));
  528. ASSERT_EQ(DWORD{ERROR_SUCCESS},
  529. restricted_token.GetRestrictedToken(&token_handle));
  530. ASSERT_EQ(DWORD{ERROR_SUCCESS},
  531. CreateLowBoxToken(token_handle.Get(), PRIMARY,
  532. &caps_with_capabilities, &token));
  533. ASSERT_TRUE(token.IsValid());
  534. CheckLowBoxToken(token, false, &caps_with_capabilities);
  535. CheckRestrictingSid(token.Get(), base::win::WellKnownSid::kWorld, 1);
  536. }
  537. // Checks the functionality of CanLowIntegrityAccessDesktop
  538. TEST(RestrictedTokenTest, MediumIlDesktop) {
  539. ASSERT_TRUE(CanLowIntegrityAccessDesktop());
  540. // Create a desktop using the default security descriptor (the last parameter)
  541. // which doesn't allow low IL to access it in practice.
  542. HDESK hdesk = ::CreateDesktopW(L"medium_il_desktop", nullptr, nullptr, 0,
  543. GENERIC_ALL, nullptr);
  544. ASSERT_TRUE(hdesk);
  545. HDESK old_hdesk = ::GetThreadDesktop(::GetCurrentThreadId());
  546. ASSERT_TRUE(hdesk);
  547. ASSERT_TRUE(::SetThreadDesktop(hdesk));
  548. ASSERT_FALSE(CanLowIntegrityAccessDesktop());
  549. ASSERT_TRUE(::SetThreadDesktop(old_hdesk));
  550. ASSERT_TRUE(::CloseDesktop(hdesk));
  551. }
  552. } // namespace sandbox