| OLD | NEW |
| 1 | 1 |
| 2 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
| 4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
| 5 // | 5 // |
| 6 // This file implements the Windows service controlling Me2Me host processes | 6 // This file implements the Windows service controlling Me2Me host processes |
| 7 // running within user sessions. | 7 // running within user sessions. |
| 8 | 8 |
| 9 #include "remoting/host/win/unprivileged_process_delegate.h" | 9 #include "remoting/host/win/unprivileged_process_delegate.h" |
| 10 | 10 |
| 11 #include <sddl.h> | 11 #include <sddl.h> |
| 12 | 12 |
| 13 #include <utility> | 13 #include <utility> |
| 14 | 14 |
| 15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 16 #include "base/files/file.h" | 16 #include "base/files/file.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/rand_util.h" | 18 #include "base/rand_util.h" |
| 19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
| 20 #include "base/strings/string16.h" | 20 #include "base/strings/string16.h" |
| 21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
| 22 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 23 #include "base/synchronization/lock.h" | 23 #include "base/synchronization/lock.h" |
| 24 #include "base/win/scoped_handle.h" | 24 #include "base/win/scoped_handle.h" |
| 25 #include "base/win/windows_version.h" | |
| 26 #include "ipc/attachment_broker.h" | 25 #include "ipc/attachment_broker.h" |
| 27 #include "ipc/ipc_channel.h" | 26 #include "ipc/ipc_channel.h" |
| 28 #include "ipc/ipc_channel_proxy.h" | 27 #include "ipc/ipc_channel_proxy.h" |
| 29 #include "ipc/ipc_message.h" | 28 #include "ipc/ipc_message.h" |
| 30 #include "remoting/base/typed_buffer.h" | 29 #include "remoting/base/typed_buffer.h" |
| 31 #include "remoting/host/ipc_util.h" | 30 #include "remoting/host/ipc_util.h" |
| 32 #include "remoting/host/switches.h" | 31 #include "remoting/host/switches.h" |
| 33 #include "remoting/host/win/launch_process_with_token.h" | 32 #include "remoting/host/win/launch_process_with_token.h" |
| 34 #include "remoting/host/win/security_descriptor.h" | 33 #include "remoting/host/win/security_descriptor.h" |
| 35 #include "remoting/host/win/window_station_and_desktop.h" | 34 #include "remoting/host/win/window_station_and_desktop.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_DEFAULT, | 84 LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_DEFAULT, |
| 86 &temp_handle)) { | 85 &temp_handle)) { |
| 87 return false; | 86 return false; |
| 88 } | 87 } |
| 89 ScopedHandle token(temp_handle); | 88 ScopedHandle token(temp_handle); |
| 90 | 89 |
| 91 sandbox::RestrictedToken restricted_token; | 90 sandbox::RestrictedToken restricted_token; |
| 92 if (restricted_token.Init(token.Get()) != ERROR_SUCCESS) | 91 if (restricted_token.Init(token.Get()) != ERROR_SUCCESS) |
| 93 return false; | 92 return false; |
| 94 | 93 |
| 95 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 94 // "SeChangeNotifyPrivilege" is needed to access the machine certificate |
| 96 // "SeChangeNotifyPrivilege" is needed to access the machine certificate | 95 // (including its private key) in the "Local Machine" cert store. This is |
| 97 // (including its private key) in the "Local Machine" cert store. This is | 96 // needed for HTTPS client third-party authentication . But the presence of |
| 98 // needed for HTTPS client third-party authentication . But the presence of | 97 // "SeChangeNotifyPrivilege" also allows it to open and manipulate objects |
| 99 // "SeChangeNotifyPrivilege" also allows it to open and manipulate objects | 98 // owned by the same user. This risk is only mitigated by setting the |
| 100 // owned by the same user. This risk is only mitigated by setting the | 99 // process integrity level to Low. |
| 101 // process integrity level to Low, which is why it is unsafe to enable | 100 std::vector<base::string16> exceptions; |
| 102 // "SeChangeNotifyPrivilege" on Windows XP where we don't have process | 101 exceptions.push_back(base::string16(L"SeChangeNotifyPrivilege")); |
| 103 // integrity to protect us. | |
| 104 std::vector<base::string16> exceptions; | |
| 105 exceptions.push_back(base::string16(L"SeChangeNotifyPrivilege")); | |
| 106 | 102 |
| 107 // Remove privileges in the token. | 103 // Remove privileges in the token. |
| 108 if (restricted_token.DeleteAllPrivileges(&exceptions) != ERROR_SUCCESS) | 104 if (restricted_token.DeleteAllPrivileges(&exceptions) != ERROR_SUCCESS) |
| 109 return false; | 105 return false; |
| 110 | 106 |
| 111 // Set low integrity level if supported by the OS. | 107 // Set low integrity level. |
| 112 if (restricted_token.SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW) | 108 if (restricted_token.SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW) != |
| 113 != ERROR_SUCCESS) { | 109 ERROR_SUCCESS) { |
| 114 return false; | 110 return false; |
| 115 } | |
| 116 } else { | |
| 117 // Remove all privileges in the token. | |
| 118 // Since "SeChangeNotifyPrivilege" is among the privileges being removed, | |
| 119 // the network process won't be able to acquire certificates from the local | |
| 120 // machine store. This means third-party authentication won't work. | |
| 121 if (restricted_token.DeleteAllPrivileges(nullptr) != ERROR_SUCCESS) | |
| 122 return false; | |
| 123 } | 111 } |
| 124 | 112 |
| 125 // Return the resulting token. | 113 // Return the resulting token. |
| 126 DWORD result = restricted_token.GetRestrictedToken(token_out); | 114 DWORD result = restricted_token.GetRestrictedToken(token_out); |
| 127 if (result != ERROR_SUCCESS) { | 115 if (result != ERROR_SUCCESS) { |
| 128 LOG(ERROR) << "Failed to get the restricted token: " << result; | 116 LOG(ERROR) << "Failed to get the restricted token: " << result; |
| 129 return false; | 117 return false; |
| 130 } | 118 } |
| 131 | 119 |
| 132 return true; | 120 return true; |
| 133 } | 121 } |
| 134 | 122 |
| 135 // Creates a window station with a given name and the default desktop giving | 123 // Creates a window station with a given name and the default desktop giving |
| 136 // the complete access to |logon_sid|. | 124 // the complete access to |logon_sid|. |
| 137 bool CreateWindowStationAndDesktop(ScopedSid logon_sid, | 125 bool CreateWindowStationAndDesktop(ScopedSid logon_sid, |
| 138 WindowStationAndDesktop* handles_out) { | 126 WindowStationAndDesktop* handles_out) { |
| 139 // Convert the logon SID into a string. | 127 // Convert the logon SID into a string. |
| 140 std::string logon_sid_string = ConvertSidToString(logon_sid.get()); | 128 std::string logon_sid_string = ConvertSidToString(logon_sid.get()); |
| 141 if (logon_sid_string.empty()) { | 129 if (logon_sid_string.empty()) { |
| 142 PLOG(ERROR) << "Failed to convert a SID to string"; | 130 PLOG(ERROR) << "Failed to convert a SID to string"; |
| 143 return false; | 131 return false; |
| 144 } | 132 } |
| 145 | 133 |
| 146 // Format the security descriptors in SDDL form. | 134 // Format the security descriptors in SDDL form. |
| 147 std::string desktop_sddl = | 135 std::string desktop_sddl = |
| 148 base::StringPrintf(kDesktopSdFormat, logon_sid_string.c_str()); | 136 base::StringPrintf(kDesktopSdFormat, logon_sid_string.c_str()) + |
| 137 kLowIntegrityMandatoryLabel; |
| 149 std::string window_station_sddl = | 138 std::string window_station_sddl = |
| 150 base::StringPrintf(kWindowStationSdFormat, logon_sid_string.c_str(), | 139 base::StringPrintf(kWindowStationSdFormat, logon_sid_string.c_str(), |
| 151 logon_sid_string.c_str()); | 140 logon_sid_string.c_str()) + |
| 152 | 141 kLowIntegrityMandatoryLabel; |
| 153 // The worker runs at low integrity level. Make sure it will be able to attach | |
| 154 // to the window station and desktop. | |
| 155 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | |
| 156 desktop_sddl += kLowIntegrityMandatoryLabel; | |
| 157 window_station_sddl += kLowIntegrityMandatoryLabel; | |
| 158 } | |
| 159 | 142 |
| 160 // Create the desktop and window station security descriptors. | 143 // Create the desktop and window station security descriptors. |
| 161 ScopedSd desktop_sd = ConvertSddlToSd(desktop_sddl); | 144 ScopedSd desktop_sd = ConvertSddlToSd(desktop_sddl); |
| 162 ScopedSd window_station_sd = ConvertSddlToSd(window_station_sddl); | 145 ScopedSd window_station_sd = ConvertSddlToSd(window_station_sddl); |
| 163 if (!desktop_sd || !window_station_sd) { | 146 if (!desktop_sd || !window_station_sd) { |
| 164 PLOG(ERROR) << "Failed to create a security descriptor."; | 147 PLOG(ERROR) << "Failed to create a security descriptor."; |
| 165 return false; | 148 return false; |
| 166 } | 149 } |
| 167 | 150 |
| 168 // GetProcessWindowStation() returns the current handle which does not need to | 151 // GetProcessWindowStation() returns the current handle which does not need to |
| 169 // be freed. | 152 // be freed. |
| 170 HWINSTA current_window_station = GetProcessWindowStation(); | 153 HWINSTA current_window_station = GetProcessWindowStation(); |
| 171 | 154 |
| 172 // Generate a unique window station name. | 155 // Generate a unique window station name. |
| 173 std::string window_station_name = base::StringPrintf( | 156 std::string window_station_name = base::StringPrintf( |
| 174 "chromoting-%d-%d", | 157 "chromoting-%d-%d", |
| 175 base::GetCurrentProcId(), | 158 base::GetCurrentProcId(), |
| 176 base::RandInt(1, std::numeric_limits<int>::max())); | 159 base::RandInt(1, std::numeric_limits<int>::max())); |
| 177 | 160 |
| 178 // Make sure that a new window station will be created instead of opening | 161 // Make sure that a new window station will be created instead of opening |
| 179 // an existing one. | 162 // an existing one. |
| 180 DWORD window_station_flags = 0; | 163 DWORD window_station_flags = CWF_CREATE_ONLY; |
| 181 if (base::win::GetVersion() >= base::win::VERSION_VISTA) | |
| 182 window_station_flags = CWF_CREATE_ONLY; | |
| 183 | 164 |
| 184 // Request full access because this handle will be inherited by the worker | 165 // Request full access because this handle will be inherited by the worker |
| 185 // process which needs full access in order to attach to the window station. | 166 // process which needs full access in order to attach to the window station. |
| 186 DWORD desired_access = | 167 DWORD desired_access = |
| 187 WINSTA_ALL_ACCESS | DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER; | 168 WINSTA_ALL_ACCESS | DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER; |
| 188 | 169 |
| 189 SECURITY_ATTRIBUTES security_attributes = {0}; | 170 SECURITY_ATTRIBUTES security_attributes = {0}; |
| 190 security_attributes.nLength = sizeof(security_attributes); | 171 security_attributes.nLength = sizeof(security_attributes); |
| 191 security_attributes.lpSecurityDescriptor = window_station_sd.get(); | 172 security_attributes.lpSecurityDescriptor = window_station_sd.get(); |
| 192 security_attributes.bInheritHandle = TRUE; | 173 security_attributes.bInheritHandle = TRUE; |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 PLOG(ERROR) << "Failed to duplicate a handle"; | 413 PLOG(ERROR) << "Failed to duplicate a handle"; |
| 433 ReportFatalError(); | 414 ReportFatalError(); |
| 434 return; | 415 return; |
| 435 } | 416 } |
| 436 ScopedHandle limited_handle(temp_handle); | 417 ScopedHandle limited_handle(temp_handle); |
| 437 | 418 |
| 438 event_handler_->OnProcessLaunched(std::move(limited_handle)); | 419 event_handler_->OnProcessLaunched(std::move(limited_handle)); |
| 439 } | 420 } |
| 440 | 421 |
| 441 } // namespace remoting | 422 } // namespace remoting |
| OLD | NEW |