1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/win/src/window.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,142 @@ 1.4 +// Copyright (c) 2011 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "sandbox/win/src/window.h" 1.9 + 1.10 +#include <aclapi.h> 1.11 + 1.12 +#include "base/logging.h" 1.13 +#include "base/memory/scoped_ptr.h" 1.14 + 1.15 +namespace { 1.16 + 1.17 +// Gets the security attributes of a window object referenced by |handle|. The 1.18 +// lpSecurityDescriptor member of the SECURITY_ATTRIBUTES parameter returned 1.19 +// must be freed using LocalFree by the caller. 1.20 +bool GetSecurityAttributes(HANDLE handle, SECURITY_ATTRIBUTES* attributes) { 1.21 + attributes->bInheritHandle = FALSE; 1.22 + attributes->nLength = sizeof(SECURITY_ATTRIBUTES); 1.23 + 1.24 + PACL dacl = NULL; 1.25 + DWORD result = ::GetSecurityInfo(handle, SE_WINDOW_OBJECT, 1.26 + DACL_SECURITY_INFORMATION, NULL, NULL, &dacl, 1.27 + NULL, &attributes->lpSecurityDescriptor); 1.28 + if (ERROR_SUCCESS == result) 1.29 + return true; 1.30 + 1.31 + return false; 1.32 +} 1.33 + 1.34 +} 1.35 + 1.36 +namespace sandbox { 1.37 + 1.38 +ResultCode CreateAltWindowStation(HWINSTA* winsta) { 1.39 + // Get the security attributes from the current window station; we will 1.40 + // use this as the base security attributes for the new window station. 1.41 + SECURITY_ATTRIBUTES attributes = {0}; 1.42 + if (!GetSecurityAttributes(::GetProcessWindowStation(), &attributes)) { 1.43 + return SBOX_ERROR_CANNOT_CREATE_WINSTATION; 1.44 + } 1.45 + 1.46 + // Create the window station using NULL for the name to ask the os to 1.47 + // generate it. 1.48 + // TODO(nsylvain): don't ask for WINSTA_ALL_ACCESS if we don't need to. 1.49 + *winsta = ::CreateWindowStationW(NULL, 0, WINSTA_ALL_ACCESS, &attributes); 1.50 + LocalFree(attributes.lpSecurityDescriptor); 1.51 + 1.52 + if (*winsta) 1.53 + return SBOX_ALL_OK; 1.54 + 1.55 + return SBOX_ERROR_CANNOT_CREATE_WINSTATION; 1.56 +} 1.57 + 1.58 +ResultCode CreateAltDesktop(HWINSTA winsta, HDESK* desktop) { 1.59 + std::wstring desktop_name = L"sbox_alternate_desktop_"; 1.60 + 1.61 + // Append the current PID to the desktop name. 1.62 + wchar_t buffer[16]; 1.63 + _snwprintf_s(buffer, sizeof(buffer) / sizeof(wchar_t), L"0x%X", 1.64 + ::GetCurrentProcessId()); 1.65 + desktop_name += buffer; 1.66 + 1.67 + // Get the security attributes from the current desktop, we will use this as 1.68 + // the base security attributes for the new desktop. 1.69 + SECURITY_ATTRIBUTES attributes = {0}; 1.70 + if (!GetSecurityAttributes(GetThreadDesktop(GetCurrentThreadId()), 1.71 + &attributes)) { 1.72 + return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 1.73 + } 1.74 + 1.75 + // Back up the current window station, in case we need to switch it. 1.76 + HWINSTA current_winsta = ::GetProcessWindowStation(); 1.77 + 1.78 + if (winsta) { 1.79 + // We need to switch to the alternate window station before creating the 1.80 + // desktop. 1.81 + if (!::SetProcessWindowStation(winsta)) { 1.82 + ::LocalFree(attributes.lpSecurityDescriptor); 1.83 + return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 1.84 + } 1.85 + } 1.86 + 1.87 + // Create the destkop. 1.88 + // TODO(nsylvain): don't ask for GENERIC_ALL if we don't need to. 1.89 + *desktop = ::CreateDesktop(desktop_name.c_str(), NULL, NULL, 0, GENERIC_ALL, 1.90 + &attributes); 1.91 + ::LocalFree(attributes.lpSecurityDescriptor); 1.92 + 1.93 + if (winsta) { 1.94 + // Revert to the right window station. 1.95 + if (!::SetProcessWindowStation(current_winsta)) { 1.96 + return SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION; 1.97 + } 1.98 + } 1.99 + 1.100 + if (*desktop) 1.101 + return SBOX_ALL_OK; 1.102 + 1.103 + return SBOX_ERROR_CANNOT_CREATE_DESKTOP; 1.104 +} 1.105 + 1.106 +std::wstring GetWindowObjectName(HANDLE handle) { 1.107 + // Get the size of the name. 1.108 + DWORD size = 0; 1.109 + ::GetUserObjectInformation(handle, UOI_NAME, NULL, 0, &size); 1.110 + 1.111 + if (!size) { 1.112 + NOTREACHED(); 1.113 + return std::wstring(); 1.114 + } 1.115 + 1.116 + // Create the buffer that will hold the name. 1.117 + scoped_ptr<wchar_t[]> name_buffer(new wchar_t[size]); 1.118 + 1.119 + // Query the name of the object. 1.120 + if (!::GetUserObjectInformation(handle, UOI_NAME, name_buffer.get(), size, 1.121 + &size)) { 1.122 + NOTREACHED(); 1.123 + return std::wstring(); 1.124 + } 1.125 + 1.126 + return std::wstring(name_buffer.get()); 1.127 +} 1.128 + 1.129 +std::wstring GetFullDesktopName(HWINSTA winsta, HDESK desktop) { 1.130 + if (!desktop) { 1.131 + NOTREACHED(); 1.132 + return std::wstring(); 1.133 + } 1.134 + 1.135 + std::wstring name; 1.136 + if (winsta) { 1.137 + name = GetWindowObjectName(winsta); 1.138 + name += L'\\'; 1.139 + } 1.140 + 1.141 + name += GetWindowObjectName(desktop); 1.142 + return name; 1.143 +} 1.144 + 1.145 +} // namespace sandbox