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 |