diff options
Diffstat (limited to 'sandbox/src/restricted_token_utils.cc')
-rw-r--r-- | sandbox/src/restricted_token_utils.cc | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/sandbox/src/restricted_token_utils.cc b/sandbox/src/restricted_token_utils.cc deleted file mode 100644 index df30b40..0000000 --- a/sandbox/src/restricted_token_utils.cc +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <aclapi.h> -#include <sddl.h> -#include <vector> - -#include "sandbox/src/restricted_token_utils.h" - -#include "base/logging.h" -#include "base/win/scoped_handle.h" -#include "base/win/scoped_process_information.h" -#include "base/win/windows_version.h" -#include "sandbox/src/job.h" -#include "sandbox/src/restricted_token.h" -#include "sandbox/src/security_level.h" -#include "sandbox/src/sid.h" - -namespace sandbox { - -DWORD CreateRestrictedToken(HANDLE *token_handle, - TokenLevel security_level, - IntegrityLevel integrity_level, - TokenType token_type) { - if (!token_handle) - return ERROR_BAD_ARGUMENTS; - - RestrictedToken restricted_token; - restricted_token.Init(NULL); // Initialized with the current process token - - std::vector<std::wstring> privilege_exceptions; - std::vector<Sid> sid_exceptions; - - bool deny_sids = true; - bool remove_privileges = true; - - switch (security_level) { - case USER_UNPROTECTED: { - deny_sids = false; - remove_privileges = false; - break; - } - case USER_RESTRICTED_SAME_ACCESS: { - deny_sids = false; - remove_privileges = false; - - unsigned err_code = restricted_token.AddRestrictingSidAllSids(); - if (ERROR_SUCCESS != err_code) - return err_code; - - break; - } - case USER_NON_ADMIN: { - sid_exceptions.push_back(WinBuiltinUsersSid); - sid_exceptions.push_back(WinWorldSid); - sid_exceptions.push_back(WinInteractiveSid); - sid_exceptions.push_back(WinAuthenticatedUserSid); - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - break; - } - case USER_INTERACTIVE: { - sid_exceptions.push_back(WinBuiltinUsersSid); - sid_exceptions.push_back(WinWorldSid); - sid_exceptions.push_back(WinInteractiveSid); - sid_exceptions.push_back(WinAuthenticatedUserSid); - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - restricted_token.AddRestrictingSid(WinBuiltinUsersSid); - restricted_token.AddRestrictingSid(WinWorldSid); - restricted_token.AddRestrictingSid(WinRestrictedCodeSid); - restricted_token.AddRestrictingSidCurrentUser(); - restricted_token.AddRestrictingSidLogonSession(); - break; - } - case USER_LIMITED: { - sid_exceptions.push_back(WinBuiltinUsersSid); - sid_exceptions.push_back(WinWorldSid); - sid_exceptions.push_back(WinInteractiveSid); - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - restricted_token.AddRestrictingSid(WinBuiltinUsersSid); - restricted_token.AddRestrictingSid(WinWorldSid); - restricted_token.AddRestrictingSid(WinRestrictedCodeSid); - - // This token has to be able to create objects in BNO. - // Unfortunately, on vista, it needs the current logon sid - // in the token to achieve this. You should also set the process to be - // low integrity level so it can't access object created by other - // processes. - if (base::win::GetVersion() >= base::win::VERSION_VISTA) - restricted_token.AddRestrictingSidLogonSession(); - break; - } - case USER_RESTRICTED: { - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - restricted_token.AddUserSidForDenyOnly(); - restricted_token.AddRestrictingSid(WinRestrictedCodeSid); - break; - } - case USER_LOCKDOWN: { - restricted_token.AddUserSidForDenyOnly(); - restricted_token.AddRestrictingSid(WinNullSid); - break; - } - default: { - return ERROR_BAD_ARGUMENTS; - } - } - - DWORD err_code = ERROR_SUCCESS; - if (deny_sids) { - err_code = restricted_token.AddAllSidsForDenyOnly(&sid_exceptions); - if (ERROR_SUCCESS != err_code) - return err_code; - } - - if (remove_privileges) { - err_code = restricted_token.DeleteAllPrivileges(&privilege_exceptions); - if (ERROR_SUCCESS != err_code) - return err_code; - } - - restricted_token.SetIntegrityLevel(integrity_level); - - switch (token_type) { - case PRIMARY: { - err_code = restricted_token.GetRestrictedTokenHandle(token_handle); - break; - } - case IMPERSONATION: { - err_code = restricted_token.GetRestrictedTokenHandleForImpersonation( - token_handle); - break; - } - default: { - err_code = ERROR_BAD_ARGUMENTS; - break; - } - } - - return err_code; -} - -DWORD StartRestrictedProcessInJob(wchar_t *command_line, - TokenLevel primary_level, - TokenLevel impersonation_level, - JobLevel job_level, - HANDLE *const job_handle_ret) { - Job job; - DWORD err_code = job.Init(job_level, NULL, 0); - if (ERROR_SUCCESS != err_code) - return err_code; - - if (JOB_UNPROTECTED != job_level) { - // Share the Desktop handle to be able to use MessageBox() in the sandboxed - // application. - err_code = job.UserHandleGrantAccess(GetDesktopWindow()); - if (ERROR_SUCCESS != err_code) - return err_code; - } - - // Create the primary (restricted) token for the process - HANDLE primary_token_handle = NULL; - err_code = CreateRestrictedToken(&primary_token_handle, - primary_level, - INTEGRITY_LEVEL_LAST, - PRIMARY); - if (ERROR_SUCCESS != err_code) { - return err_code; - } - base::win::ScopedHandle primary_token(primary_token_handle); - - // Create the impersonation token (restricted) to be able to start the - // process. - HANDLE impersonation_token_handle; - err_code = CreateRestrictedToken(&impersonation_token_handle, - impersonation_level, - INTEGRITY_LEVEL_LAST, - IMPERSONATION); - if (ERROR_SUCCESS != err_code) { - return err_code; - } - base::win::ScopedHandle impersonation_token(impersonation_token_handle); - - // Start the process - STARTUPINFO startup_info = {0}; - base::win::ScopedProcessInformation process_info; - DWORD flags = CREATE_SUSPENDED; - - if (base::win::GetVersion() < base::win::VERSION_WIN8) { - // Windows 8 implements nested jobs, but for older systems we need to - // break out of any job we're in to enforce our restrictions. - flags |= CREATE_BREAKAWAY_FROM_JOB; - } - - if (!::CreateProcessAsUser(primary_token.Get(), - NULL, // No application name. - command_line, - NULL, // No security attribute. - NULL, // No thread attribute. - FALSE, // Do not inherit handles. - flags, - NULL, // Use the environment of the caller. - NULL, // Use current directory of the caller. - &startup_info, - process_info.Receive())) { - return ::GetLastError(); - } - - // Change the token of the main thread of the new process for the - // impersonation token with more rights. - { - HANDLE temp_thread = process_info.thread_handle(); - if (!::SetThreadToken(&temp_thread, impersonation_token.Get())) { - ::TerminateProcess(process_info.process_handle(), - 0); // exit code - return ::GetLastError(); - } - } - - err_code = job.AssignProcessToJob(process_info.process_handle()); - if (ERROR_SUCCESS != err_code) { - ::TerminateProcess(process_info.process_handle(), - 0); // exit code - return ::GetLastError(); - } - - // Start the application - ::ResumeThread(process_info.thread_handle()); - - (*job_handle_ret) = job.Detach(); - - return ERROR_SUCCESS; -} - -DWORD SetObjectIntegrityLabel(HANDLE handle, SE_OBJECT_TYPE type, - const wchar_t* ace_access, - const wchar_t* integrity_level_sid) { - // Build the SDDL string for the label. - std::wstring sddl = L"S:("; // SDDL for a SACL. - sddl += SDDL_MANDATORY_LABEL; // Ace Type is "Mandatory Label". - sddl += L";;"; // No Ace Flags. - sddl += ace_access; // Add the ACE access. - sddl += L";;;"; // No ObjectType and Inherited Object Type. - sddl += integrity_level_sid; // Trustee Sid. - sddl += L")"; - - DWORD error = ERROR_SUCCESS; - PSECURITY_DESCRIPTOR sec_desc = NULL; - - PACL sacl = NULL; - BOOL sacl_present = FALSE; - BOOL sacl_defaulted = FALSE; - - if (::ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl.c_str(), - SDDL_REVISION, - &sec_desc, NULL)) { - if (::GetSecurityDescriptorSacl(sec_desc, &sacl_present, &sacl, - &sacl_defaulted)) { - error = ::SetSecurityInfo(handle, type, - LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, - sacl); - } else { - error = ::GetLastError(); - } - - ::LocalFree(sec_desc); - } else { - return::GetLastError(); - } - - return error; -} - -const wchar_t* GetIntegrityLevelString(IntegrityLevel integrity_level) { - switch (integrity_level) { - case INTEGRITY_LEVEL_SYSTEM: - return L"S-1-16-16384"; - case INTEGRITY_LEVEL_HIGH: - return L"S-1-16-12288"; - case INTEGRITY_LEVEL_MEDIUM: - return L"S-1-16-8192"; - case INTEGRITY_LEVEL_MEDIUM_LOW: - return L"S-1-16-6144"; - case INTEGRITY_LEVEL_LOW: - return L"S-1-16-4096"; - case INTEGRITY_LEVEL_BELOW_LOW: - return L"S-1-16-2048"; - case INTEGRITY_LEVEL_UNTRUSTED: - return L"S-1-16-0"; - case INTEGRITY_LEVEL_LAST: - return NULL; - } - - NOTREACHED(); - return NULL; -} -DWORD SetTokenIntegrityLevel(HANDLE token, IntegrityLevel integrity_level) { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return ERROR_SUCCESS; - - const wchar_t* integrity_level_str = GetIntegrityLevelString(integrity_level); - if (!integrity_level_str) { - // No mandatory level specified, we don't change it. - return ERROR_SUCCESS; - } - - PSID integrity_sid = NULL; - if (!::ConvertStringSidToSid(integrity_level_str, &integrity_sid)) - return ::GetLastError(); - - TOKEN_MANDATORY_LABEL label = {0}; - label.Label.Attributes = SE_GROUP_INTEGRITY; - label.Label.Sid = integrity_sid; - - DWORD size = sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(integrity_sid); - BOOL result = ::SetTokenInformation(token, TokenIntegrityLevel, &label, - size); - ::LocalFree(integrity_sid); - - return result ? ERROR_SUCCESS : ::GetLastError(); -} - -DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level) { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return ERROR_SUCCESS; - - // We don't check for an invalid level here because we'll just let it - // fail on the SetTokenIntegrityLevel call later on. - if (integrity_level == INTEGRITY_LEVEL_LAST) { - // No mandatory level specified, we don't change it. - return ERROR_SUCCESS; - } - - HANDLE token_handle; - if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT, - &token_handle)) - return ::GetLastError(); - - base::win::ScopedHandle token(token_handle); - - return SetTokenIntegrityLevel(token.Get(), integrity_level); -} - -} // namespace sandbox |