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; |
} |