Chromium Code Reviews| Index: sandbox/win/src/restricted_token.cc |
| diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc |
| index 7fadb2bba61dad4782eb643d3ecef0019f457230..7d0a32ae1067d476f348b38393623523ed3998d0 100644 |
| --- a/sandbox/win/src/restricted_token.cc |
| +++ b/sandbox/win/src/restricted_token.cc |
| @@ -7,47 +7,68 @@ |
| #include <vector> |
| #include "base/logging.h" |
| +#include "base/memory/scoped_ptr.h" |
| #include "sandbox/win/src/acl.h" |
| #include "sandbox/win/src/win_utils.h" |
| +namespace { |
| + |
| +// Calls GetTokenInformation with the desired |info_class| and returns a buffer |
| +// with the result. |
| +scoped_ptr<BYTE[]> GetTokenInfo(const base::win::ScopedHandle& token, |
| + _TOKEN_INFORMATION_CLASS info_class, |
|
rvargas (doing something else)
2015/07/21 20:52:53
will remove the underscore.
|
| + DWORD* error) { |
| + // Get the required buffer size. |
| + DWORD size = 0; |
| + ::GetTokenInformation(token.Get(), info_class, NULL, 0, &size); |
| + if (!size) { |
| + *error = ::GetLastError(); |
| + return nullptr; |
| + } |
| + |
| + scoped_ptr<BYTE[]> buffer(new BYTE[size]); |
| + if (!::GetTokenInformation(token.Get(), info_class, buffer.get(), size, |
| + &size)) { |
| + *error = ::GetLastError(); |
| + return nullptr; |
| + } |
| + |
| + *error = ERROR_SUCCESS; |
| + return buffer.Pass(); |
| +} |
| + |
| +} // namespace |
| + |
| namespace sandbox { |
| RestrictedToken::RestrictedToken() |
| - : effective_token_(NULL), |
| - integrity_level_(INTEGRITY_LEVEL_LAST), |
| + : integrity_level_(INTEGRITY_LEVEL_LAST), |
| init_(false) { |
| } |
| RestrictedToken::~RestrictedToken() { |
| - if (effective_token_) |
| - CloseHandle(effective_token_); |
| } |
| unsigned RestrictedToken::Init(const HANDLE effective_token) { |
| if (init_) |
| return ERROR_ALREADY_INITIALIZED; |
| + HANDLE temp_token; |
| if (effective_token) { |
| // We duplicate the handle to be able to use it even if the original handle |
| // is closed. |
| - HANDLE effective_token_dup; |
| - if (::DuplicateHandle(::GetCurrentProcess(), |
| - effective_token, |
| - ::GetCurrentProcess(), |
| - &effective_token_dup, |
| - 0, |
| - FALSE, |
| - DUPLICATE_SAME_ACCESS)) { |
| - effective_token_ = effective_token_dup; |
| - } else { |
| + if (!::DuplicateHandle(::GetCurrentProcess(), effective_token, |
| + ::GetCurrentProcess(), &temp_token, |
| + 0, FALSE, DUPLICATE_SAME_ACCESS)) { |
| return ::GetLastError(); |
| } |
| } else { |
| - if (!::OpenProcessToken(::GetCurrentProcess(), |
| - TOKEN_ALL_ACCESS, |
| - &effective_token_)) |
| + if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, |
| + &temp_token)) { |
| return ::GetLastError(); |
| + } |
| } |
| + effective_token_.Set(temp_token); |
| init_ = true; |
| return ERROR_SUCCESS; |
| @@ -102,7 +123,7 @@ unsigned RestrictedToken::GetRestrictedToken( |
| // but it appears that in Windows 7 it hints the AppLocker subsystem to |
| // leave us alone. |
| if (deny_size || restrict_size || privileges_size) { |
| - result = ::CreateRestrictedToken(effective_token_, |
| + result = ::CreateRestrictedToken(effective_token_.Get(), |
| SANDBOX_INERT, |
| static_cast<DWORD>(deny_size), |
| deny_only_array, |
| @@ -115,7 +136,7 @@ unsigned RestrictedToken::GetRestrictedToken( |
| // Duplicate the token even if it's not modified at this point |
| // because any subsequent changes to this token would also affect the |
| // current process. |
| - result = ::DuplicateTokenEx(effective_token_, TOKEN_ALL_ACCESS, NULL, |
| + result = ::DuplicateTokenEx(effective_token_.Get(), TOKEN_ALL_ACCESS, NULL, |
| SecurityIdentification, TokenPrimary, |
| &new_token_handle); |
| } |
| @@ -193,27 +214,14 @@ unsigned RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) { |
| if (!init_) |
| return ERROR_NO_TOKEN; |
| - TOKEN_GROUPS *token_groups = NULL; |
| - DWORD size = 0; |
| + DWORD error; |
| + scoped_ptr<BYTE[]> buffer = |
| + GetTokenInfo(effective_token_, TokenGroups, &error); |
| - BOOL result = ::GetTokenInformation(effective_token_, |
| - TokenGroups, |
| - NULL, // No buffer. |
| - 0, // Size is 0. |
| - &size); |
| - if (!size) |
| - return ::GetLastError(); |
| + if (!buffer) |
| + return error; |
| - token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]); |
| - result = ::GetTokenInformation(effective_token_, |
| - TokenGroups, |
| - token_groups, |
| - size, |
| - &size); |
| - if (!result) { |
| - delete[] reinterpret_cast<BYTE*>(token_groups); |
| - return ::GetLastError(); |
| - } |
| + TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get()); |
| // Build the list of the deny only group SIDs |
| for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) { |
| @@ -236,8 +244,6 @@ unsigned RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) { |
| } |
| } |
| - delete[] reinterpret_cast<BYTE*>(token_groups); |
| - |
| return ERROR_SUCCESS; |
| } |
| @@ -256,24 +262,18 @@ unsigned RestrictedToken::AddUserSidForDenyOnly() { |
| return ERROR_NO_TOKEN; |
| DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; |
| - TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]); |
| + scoped_ptr<BYTE[]> buffer(new BYTE[size]); |
| + TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(buffer.get()); |
| - BOOL result = ::GetTokenInformation(effective_token_, |
| - TokenUser, |
| - token_user, |
| - size, |
| - &size); |
| + BOOL result = ::GetTokenInformation(effective_token_.Get(), TokenUser, |
| + token_user, size, &size); |
| - if (!result) { |
| - delete[] reinterpret_cast<BYTE*>(token_user); |
| + if (!result) |
| return ::GetLastError(); |
| - } |
| Sid user = reinterpret_cast<SID*>(token_user->User.Sid); |
| sids_for_deny_only_.push_back(user); |
| - delete[] reinterpret_cast<BYTE*>(token_user); |
| - |
| return ERROR_SUCCESS; |
| } |
| @@ -283,29 +283,15 @@ unsigned RestrictedToken::DeleteAllPrivileges( |
| if (!init_) |
| return ERROR_NO_TOKEN; |
| - // Get the list of privileges in the token |
| - TOKEN_PRIVILEGES *token_privileges = NULL; |
| - DWORD size = 0; |
| + DWORD error; |
| + scoped_ptr<BYTE[]> buffer = |
| + GetTokenInfo(effective_token_, TokenPrivileges, &error); |
| - BOOL result = ::GetTokenInformation(effective_token_, |
| - TokenPrivileges, |
| - NULL, // No buffer. |
| - 0, // Size is 0. |
| - &size); |
| - if (!size) |
| - return ::GetLastError(); |
| - |
| - token_privileges = reinterpret_cast<TOKEN_PRIVILEGES*>(new BYTE[size]); |
| - result = ::GetTokenInformation(effective_token_, |
| - TokenPrivileges, |
| - token_privileges, |
| - size, |
| - &size); |
| - if (!result) { |
| - delete[] reinterpret_cast<BYTE *>(token_privileges); |
| - return ::GetLastError(); |
| - } |
| + if (!buffer) |
| + return error; |
| + TOKEN_PRIVILEGES* token_privileges = |
| + reinterpret_cast<TOKEN_PRIVILEGES*>(buffer.get()); |
| // Build the list of privileges to disable |
| for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) { |
| @@ -326,8 +312,6 @@ unsigned RestrictedToken::DeleteAllPrivileges( |
| } |
| } |
| - delete[] reinterpret_cast<BYTE *>(token_privileges); |
| - |
| return ERROR_SUCCESS; |
| } |
| @@ -359,27 +343,14 @@ unsigned RestrictedToken::AddRestrictingSidLogonSession() { |
| if (!init_) |
| return ERROR_NO_TOKEN; |
| - TOKEN_GROUPS *token_groups = NULL; |
| - DWORD size = 0; |
| + DWORD error; |
| + scoped_ptr<BYTE[]> buffer = |
| + GetTokenInfo(effective_token_, TokenGroups, &error); |
| - BOOL result = ::GetTokenInformation(effective_token_, |
| - TokenGroups, |
| - NULL, // No buffer. |
| - 0, // Size is 0. |
| - &size); |
| - if (!size) |
| - return ::GetLastError(); |
| + if (!buffer) |
| + return error; |
| - token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]); |
| - result = ::GetTokenInformation(effective_token_, |
| - TokenGroups, |
| - token_groups, |
| - size, |
| - &size); |
| - if (!result) { |
| - delete[] reinterpret_cast<BYTE*>(token_groups); |
| - return ::GetLastError(); |
| - } |
| + TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get()); |
| SID *logon_sid = NULL; |
| for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) { |
| @@ -392,8 +363,6 @@ unsigned RestrictedToken::AddRestrictingSidLogonSession() { |
| if (logon_sid) |
| sids_to_restrict_.push_back(logon_sid); |
| - delete[] reinterpret_cast<BYTE*>(token_groups); |
| - |
| return ERROR_SUCCESS; |
| } |
| @@ -403,24 +372,18 @@ unsigned RestrictedToken::AddRestrictingSidCurrentUser() { |
| return ERROR_NO_TOKEN; |
| DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; |
| - TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]); |
| + scoped_ptr<BYTE[]> buffer(new BYTE[size]); |
| + TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(buffer.get()); |
| - BOOL result = ::GetTokenInformation(effective_token_, |
| - TokenUser, |
| - token_user, |
| - size, |
| - &size); |
| + BOOL result = ::GetTokenInformation(effective_token_.Get(), TokenUser, |
| + token_user, size, &size); |
| - if (!result) { |
| - delete[] reinterpret_cast<BYTE*>(token_user); |
| + if (!result) |
| return ::GetLastError(); |
| - } |
| Sid user = reinterpret_cast<SID*>(token_user->User.Sid); |
| sids_to_restrict_.push_back(user); |
| - delete[] reinterpret_cast<BYTE*>(token_user); |
| - |
| return ERROR_SUCCESS; |
| } |
| @@ -430,29 +393,17 @@ unsigned RestrictedToken::AddRestrictingSidAllSids() { |
| return ERROR_NO_TOKEN; |
| // Add the current user to the list. |
| - unsigned error = AddRestrictingSidCurrentUser(); |
| + DWORD error = AddRestrictingSidCurrentUser(); |
| if (ERROR_SUCCESS != error) |
| return error; |
| - TOKEN_GROUPS *token_groups = NULL; |
| - DWORD size = 0; |
| + scoped_ptr<BYTE[]> buffer = |
| + GetTokenInfo(effective_token_, TokenGroups, &error); |
| - // Get the buffer size required. |
| - BOOL result = ::GetTokenInformation(effective_token_, TokenGroups, NULL, 0, |
| - &size); |
| - if (!size) |
| - return ::GetLastError(); |
| + if (!buffer) |
| + return error; |
| - token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]); |
| - result = ::GetTokenInformation(effective_token_, |
| - TokenGroups, |
| - token_groups, |
| - size, |
| - &size); |
| - if (!result) { |
| - delete[] reinterpret_cast<BYTE*>(token_groups); |
| - return ::GetLastError(); |
| - } |
| + TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get()); |
| // Build the list of restricting sids from all groups. |
| for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) { |
| @@ -460,8 +411,6 @@ unsigned RestrictedToken::AddRestrictingSidAllSids() { |
| AddRestrictingSid(reinterpret_cast<SID*>(token_groups->Groups[i].Sid)); |
| } |
| - delete[] reinterpret_cast<BYTE*>(token_groups); |
| - |
| return ERROR_SUCCESS; |
| } |