1 // Copyright (c) 2006-2010 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 #include "sandbox/win/tests/common/test_utils.h"
6
7 #include <stddef.h>
8 #include <winioctl.h>
9
10 #include "base/numerics/safe_conversions.h"
11
12 namespace sandbox {
13
14 typedef struct _REPARSE_DATA_BUFFER {
15 ULONG ReparseTag;
16 USHORT ReparseDataLength;
17 USHORT Reserved;
18 union {
19 struct {
20 USHORT SubstituteNameOffset;
21 USHORT SubstituteNameLength;
22 USHORT PrintNameOffset;
23 USHORT PrintNameLength;
24 ULONG Flags;
25 WCHAR PathBuffer[1];
26 } SymbolicLinkReparseBuffer;
27 struct {
28 USHORT SubstituteNameOffset;
29 USHORT SubstituteNameLength;
30 USHORT PrintNameOffset;
31 USHORT PrintNameLength;
32 WCHAR PathBuffer[1];
33 } MountPointReparseBuffer;
34 struct {
35 UCHAR DataBuffer[1];
36 } GenericReparseBuffer;
37 };
38 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
39
40 // Sets a reparse point. |source| will now point to |target|. Returns true if
41 // the call succeeds, false otherwise.
SetReparsePoint(HANDLE source,const wchar_t * target)42 bool SetReparsePoint(HANDLE source, const wchar_t* target) {
43 USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]);
44
45 char buffer[2000] = {0};
46 DWORD returned;
47
48 REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
49
50 data->ReparseTag = 0xa0000003;
51 memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
52 data->MountPointReparseBuffer.SubstituteNameLength = size_target;
53 data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
54 data->ReparseDataLength = size_target + 4 + 8;
55
56 int data_size = data->ReparseDataLength + 8;
57
58 if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size,
59 NULL, 0, &returned, NULL)) {
60 return false;
61 }
62 return true;
63 }
64
65 // Delete the reparse point referenced by |source|. Returns true if the call
66 // succeeds, false otherwise.
DeleteReparsePoint(HANDLE source)67 bool DeleteReparsePoint(HANDLE source) {
68 DWORD returned;
69 REPARSE_DATA_BUFFER data = {0};
70 data.ReparseTag = 0xa0000003;
71 if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
72 &returned, NULL)) {
73 return false;
74 }
75
76 return true;
77 }
78
SidAndAttributes(const SID_AND_ATTRIBUTES & sid_and_attributes)79 SidAndAttributes::SidAndAttributes(const SID_AND_ATTRIBUTES& sid_and_attributes)
80 : attributes_(sid_and_attributes.Attributes),
81 sid_(sid_and_attributes.Sid) {}
82
GetPSID() const83 PSID SidAndAttributes::GetPSID() const {
84 return sid_.GetPSID();
85 }
86
GetAttributes() const87 DWORD SidAndAttributes::GetAttributes() const {
88 return attributes_;
89 }
90
GetTokenAppContainerSid(HANDLE token,std::unique_ptr<sandbox::Sid> * app_container_sid)91 bool GetTokenAppContainerSid(HANDLE token,
92 std::unique_ptr<sandbox::Sid>* app_container_sid) {
93 std::vector<char> app_container_info(sizeof(TOKEN_APPCONTAINER_INFORMATION) +
94 SECURITY_MAX_SID_SIZE);
95 DWORD return_length;
96
97 if (!::GetTokenInformation(
98 token, TokenAppContainerSid, app_container_info.data(),
99 base::checked_cast<DWORD>(app_container_info.size()),
100 &return_length)) {
101 return false;
102 }
103
104 PTOKEN_APPCONTAINER_INFORMATION info =
105 reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(
106 app_container_info.data());
107 if (!info->TokenAppContainer)
108 return false;
109 *app_container_sid = std::make_unique<sandbox::Sid>(info->TokenAppContainer);
110 return true;
111 }
112
GetTokenGroups(HANDLE token,TOKEN_INFORMATION_CLASS information_class,std::vector<SidAndAttributes> * token_groups)113 bool GetTokenGroups(HANDLE token,
114 TOKEN_INFORMATION_CLASS information_class,
115 std::vector<SidAndAttributes>* token_groups) {
116 if (information_class != ::TokenCapabilities &&
117 information_class != ::TokenGroups &&
118 information_class != ::TokenRestrictedSids) {
119 return false;
120 }
121
122 std::vector<char> groups_buf;
123 if (!GetVariableTokenInformation(token, information_class, &groups_buf))
124 return false;
125
126 PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(groups_buf.data());
127
128 if (groups->GroupCount > 0) {
129 token_groups->insert(token_groups->begin(), groups->Groups,
130 groups->Groups + groups->GroupCount);
131 }
132
133 return true;
134 }
135
GetVariableTokenInformation(HANDLE token,TOKEN_INFORMATION_CLASS information_class,std::vector<char> * information)136 bool GetVariableTokenInformation(HANDLE token,
137 TOKEN_INFORMATION_CLASS information_class,
138 std::vector<char>* information) {
139 DWORD return_length;
140 if (!::GetTokenInformation(token, information_class, nullptr, 0,
141 &return_length)) {
142 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
143 return false;
144 }
145
146 information->resize(return_length);
147 return !!::GetTokenInformation(token, information_class, information->data(),
148 return_length, &return_length);
149 }
150
151 } // namespace sandbox
152