Index: sandbox/src/restricted_token_utils.cc |
diff --git a/sandbox/src/restricted_token_utils.cc b/sandbox/src/restricted_token_utils.cc |
deleted file mode 100644 |
index df30b4049ad3831369151762853f8d7ec5bffd18..0000000000000000000000000000000000000000 |
--- 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 |