OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sandbox/win/src/restricted_token.h" | 5 #include "sandbox/win/src/restricted_token.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "sandbox/win/src/acl.h" | 10 #include "sandbox/win/src/acl.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 if (!::OpenProcessToken(::GetCurrentProcess(), | 46 if (!::OpenProcessToken(::GetCurrentProcess(), |
47 TOKEN_ALL_ACCESS, | 47 TOKEN_ALL_ACCESS, |
48 &effective_token_)) | 48 &effective_token_)) |
49 return ::GetLastError(); | 49 return ::GetLastError(); |
50 } | 50 } |
51 | 51 |
52 init_ = true; | 52 init_ = true; |
53 return ERROR_SUCCESS; | 53 return ERROR_SUCCESS; |
54 } | 54 } |
55 | 55 |
56 unsigned RestrictedToken::GetRestrictedTokenHandle(HANDLE *token_handle) const { | 56 unsigned RestrictedToken::GetRestrictedToken( |
| 57 base::win::ScopedHandle* token) const { |
57 DCHECK(init_); | 58 DCHECK(init_); |
58 if (!init_) | 59 if (!init_) |
59 return ERROR_NO_TOKEN; | 60 return ERROR_NO_TOKEN; |
60 | 61 |
61 size_t deny_size = sids_for_deny_only_.size(); | 62 size_t deny_size = sids_for_deny_only_.size(); |
62 size_t restrict_size = sids_to_restrict_.size(); | 63 size_t restrict_size = sids_to_restrict_.size(); |
63 size_t privileges_size = privileges_to_disable_.size(); | 64 size_t privileges_size = privileges_to_disable_.size(); |
64 | 65 |
65 SID_AND_ATTRIBUTES *deny_only_array = NULL; | 66 SID_AND_ATTRIBUTES *deny_only_array = NULL; |
66 if (deny_size) { | 67 if (deny_size) { |
(...skipping 21 matching lines...) Expand all Loading... |
88 if (privileges_size) { | 89 if (privileges_size) { |
89 privileges_to_disable_array = new LUID_AND_ATTRIBUTES[privileges_size]; | 90 privileges_to_disable_array = new LUID_AND_ATTRIBUTES[privileges_size]; |
90 | 91 |
91 for (unsigned int i = 0; i < privileges_size; ++i) { | 92 for (unsigned int i = 0; i < privileges_size; ++i) { |
92 privileges_to_disable_array[i].Attributes = 0; | 93 privileges_to_disable_array[i].Attributes = 0; |
93 privileges_to_disable_array[i].Luid = privileges_to_disable_[i]; | 94 privileges_to_disable_array[i].Luid = privileges_to_disable_[i]; |
94 } | 95 } |
95 } | 96 } |
96 | 97 |
97 BOOL result = TRUE; | 98 BOOL result = TRUE; |
98 HANDLE new_token = NULL; | 99 HANDLE new_token_handle = NULL; |
99 // The SANDBOX_INERT flag did nothing in XP and it was just a way to tell | 100 // The SANDBOX_INERT flag did nothing in XP and it was just a way to tell |
100 // if a token has ben restricted given the limiations of IsTokenRestricted() | 101 // if a token has ben restricted given the limiations of IsTokenRestricted() |
101 // but it appears that in Windows 7 it hints the AppLocker subsystem to | 102 // but it appears that in Windows 7 it hints the AppLocker subsystem to |
102 // leave us alone. | 103 // leave us alone. |
103 if (deny_size || restrict_size || privileges_size) { | 104 if (deny_size || restrict_size || privileges_size) { |
104 result = ::CreateRestrictedToken(effective_token_, | 105 result = ::CreateRestrictedToken(effective_token_, |
105 SANDBOX_INERT, | 106 SANDBOX_INERT, |
106 static_cast<DWORD>(deny_size), | 107 static_cast<DWORD>(deny_size), |
107 deny_only_array, | 108 deny_only_array, |
108 static_cast<DWORD>(privileges_size), | 109 static_cast<DWORD>(privileges_size), |
109 privileges_to_disable_array, | 110 privileges_to_disable_array, |
110 static_cast<DWORD>(restrict_size), | 111 static_cast<DWORD>(restrict_size), |
111 sids_to_restrict_array, | 112 sids_to_restrict_array, |
112 &new_token); | 113 &new_token_handle); |
113 } else { | 114 } else { |
114 // Duplicate the token even if it's not modified at this point | 115 // Duplicate the token even if it's not modified at this point |
115 // because any subsequent changes to this token would also affect the | 116 // because any subsequent changes to this token would also affect the |
116 // current process. | 117 // current process. |
117 result = ::DuplicateTokenEx(effective_token_, TOKEN_ALL_ACCESS, NULL, | 118 result = ::DuplicateTokenEx(effective_token_, TOKEN_ALL_ACCESS, NULL, |
118 SecurityIdentification, TokenPrimary, | 119 SecurityIdentification, TokenPrimary, |
119 &new_token); | 120 &new_token_handle); |
120 } | 121 } |
121 | 122 |
122 if (deny_only_array) | 123 if (deny_only_array) |
123 delete[] deny_only_array; | 124 delete[] deny_only_array; |
124 | 125 |
125 if (sids_to_restrict_array) | 126 if (sids_to_restrict_array) |
126 delete[] sids_to_restrict_array; | 127 delete[] sids_to_restrict_array; |
127 | 128 |
128 if (privileges_to_disable_array) | 129 if (privileges_to_disable_array) |
129 delete[] privileges_to_disable_array; | 130 delete[] privileges_to_disable_array; |
130 | 131 |
131 if (!result) | 132 if (!result) |
132 return ::GetLastError(); | 133 return ::GetLastError(); |
133 | 134 |
| 135 base::win::ScopedHandle new_token(new_token_handle); |
| 136 |
134 // Modify the default dacl on the token to contain Restricted and the user. | 137 // Modify the default dacl on the token to contain Restricted and the user. |
135 if (!AddSidToDefaultDacl(new_token, WinRestrictedCodeSid, GENERIC_ALL)) | 138 if (!AddSidToDefaultDacl(new_token.Get(), WinRestrictedCodeSid, GENERIC_ALL)) |
136 return ::GetLastError(); | 139 return ::GetLastError(); |
137 | 140 |
138 if (!AddUserSidToDefaultDacl(new_token, GENERIC_ALL)) | 141 if (!AddUserSidToDefaultDacl(new_token.Get(), GENERIC_ALL)) |
139 return ::GetLastError(); | 142 return ::GetLastError(); |
140 | 143 |
141 DWORD error = SetTokenIntegrityLevel(new_token, integrity_level_); | 144 DWORD error = SetTokenIntegrityLevel(new_token.Get(), integrity_level_); |
142 if (ERROR_SUCCESS != error) | 145 if (ERROR_SUCCESS != error) |
143 return error; | 146 return error; |
144 | 147 |
145 BOOL status = ::DuplicateHandle(::GetCurrentProcess(), | 148 HANDLE token_handle; |
146 new_token, | 149 if (!::DuplicateHandle(::GetCurrentProcess(), new_token.Get(), |
147 ::GetCurrentProcess(), | 150 ::GetCurrentProcess(), &token_handle, |
148 token_handle, | 151 TOKEN_ALL_ACCESS, FALSE, // Don't inherit. |
149 TOKEN_ALL_ACCESS, | 152 0)) { |
150 FALSE, // Don't inherit. | 153 return ::GetLastError(); |
151 0); | 154 } |
152 | 155 |
153 if (new_token != effective_token_) | 156 token->Set(token_handle); |
154 ::CloseHandle(new_token); | |
155 | |
156 if (!status) | |
157 return ::GetLastError(); | |
158 | |
159 return ERROR_SUCCESS; | 157 return ERROR_SUCCESS; |
160 } | 158 } |
161 | 159 |
162 unsigned RestrictedToken::GetRestrictedTokenHandleForImpersonation( | 160 unsigned RestrictedToken::GetRestrictedTokenForImpersonation( |
163 HANDLE *token_handle) const { | 161 base::win::ScopedHandle* token) const { |
164 DCHECK(init_); | 162 DCHECK(init_); |
165 if (!init_) | 163 if (!init_) |
166 return ERROR_NO_TOKEN; | 164 return ERROR_NO_TOKEN; |
167 | 165 |
168 HANDLE restricted_token_handle; | 166 base::win::ScopedHandle restricted_token; |
169 unsigned err_code = GetRestrictedTokenHandle(&restricted_token_handle); | 167 unsigned err_code = GetRestrictedToken(&restricted_token); |
170 if (ERROR_SUCCESS != err_code) | 168 if (ERROR_SUCCESS != err_code) |
171 return err_code; | 169 return err_code; |
172 | 170 |
173 HANDLE impersonation_token; | 171 HANDLE impersonation_token_handle; |
174 if (!::DuplicateToken(restricted_token_handle, | 172 if (!::DuplicateToken(restricted_token.Get(), |
175 SecurityImpersonation, | 173 SecurityImpersonation, |
176 &impersonation_token)) { | 174 &impersonation_token_handle)) { |
177 ::CloseHandle(restricted_token_handle); | 175 return ::GetLastError(); |
| 176 } |
| 177 base::win::ScopedHandle impersonation_token(impersonation_token_handle); |
| 178 |
| 179 HANDLE token_handle; |
| 180 if (!::DuplicateHandle(::GetCurrentProcess(), impersonation_token.Get(), |
| 181 ::GetCurrentProcess(), &token_handle, |
| 182 TOKEN_ALL_ACCESS, FALSE, // Don't inherit. |
| 183 0)) { |
178 return ::GetLastError(); | 184 return ::GetLastError(); |
179 } | 185 } |
180 | 186 |
181 ::CloseHandle(restricted_token_handle); | 187 token->Set(token_handle); |
182 | |
183 BOOL status = ::DuplicateHandle(::GetCurrentProcess(), | |
184 impersonation_token, | |
185 ::GetCurrentProcess(), | |
186 token_handle, | |
187 TOKEN_ALL_ACCESS, | |
188 FALSE, // Don't inherit. | |
189 0); | |
190 | |
191 ::CloseHandle(impersonation_token); | |
192 | |
193 if (!status) | |
194 return ::GetLastError(); | |
195 | |
196 return ERROR_SUCCESS; | 188 return ERROR_SUCCESS; |
197 } | 189 } |
198 | 190 |
199 unsigned RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) { | 191 unsigned RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) { |
200 DCHECK(init_); | 192 DCHECK(init_); |
201 if (!init_) | 193 if (!init_) |
202 return ERROR_NO_TOKEN; | 194 return ERROR_NO_TOKEN; |
203 | 195 |
204 TOKEN_GROUPS *token_groups = NULL; | 196 TOKEN_GROUPS *token_groups = NULL; |
205 DWORD size = 0; | 197 DWORD size = 0; |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 | 464 |
473 return ERROR_SUCCESS; | 465 return ERROR_SUCCESS; |
474 } | 466 } |
475 | 467 |
476 unsigned RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) { | 468 unsigned RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) { |
477 integrity_level_ = integrity_level; | 469 integrity_level_ = integrity_level; |
478 return ERROR_SUCCESS; | 470 return ERROR_SUCCESS; |
479 } | 471 } |
480 | 472 |
481 } // namespace sandbox | 473 } // namespace sandbox |
OLD | NEW |