Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(409)

Side by Side Diff: remoting/host/wts_session_process_launcher_win.cc

Issue 9617027: Chromoting: Implemented security attention sequence (SAS) emulation on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/wts_session_process_launcher_win.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file implements the Windows service controlling Me2Me host processes 5 // This file implements the Windows service controlling Me2Me host processes
6 // running within user sessions. 6 // running within user sessions.
7 7
8 #include "remoting/host/wts_session_process_launcher_win.h" 8 #include "remoting/host/wts_session_process_launcher_win.h"
9 9
10 #include <windows.h> 10 #include <windows.h>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/threading/thread.h"
13 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
14 #include "base/win/scoped_handle.h" 15 #include "base/win/scoped_handle.h"
16 #include "ipc/ipc_channel_proxy.h"
17 #include "ipc/ipc_message.h"
18 #include "ipc/ipc_message_macros.h"
15 19
20 #include "remoting/host/chromoting_session_messages.h"
21 #include "remoting/host/sas_injector_win.h"
16 #include "remoting/host/wts_console_monitor_win.h" 22 #include "remoting/host/wts_console_monitor_win.h"
17 23
18 using base::win::ScopedHandle; 24 using base::win::ScopedHandle;
19 using base::TimeDelta; 25 using base::TimeDelta;
20 26
21 namespace { 27 namespace {
22 28
23 // The minimum and maximum delays between attempts to inject host process into 29 // The minimum and maximum delays between attempts to inject host process into
24 // a session. 30 // a session.
25 const int kMaxLaunchDelaySeconds = 60; 31 const int kMaxLaunchDelaySeconds = 60;
26 const int kMinLaunchDelaySeconds = 1; 32 const int kMinLaunchDelaySeconds = 1;
27 33
28 // Name of the default session desktop. 34 // Name of the default session desktop.
29 const char kDefaultDesktopName[] = "winsta0\\default"; 35 const char kDefaultDesktopName[] = "winsta0\\default";
30 36
37 // Name of the chromoting service IPC channel.
38 const char kChromotingSessionChannelName[] = "chromoting_session";
39
31 // Takes the process token and makes a copy of it. The returned handle will have 40 // Takes the process token and makes a copy of it. The returned handle will have
32 // |desired_access| rights. 41 // |desired_access| rights.
33 bool CopyProcessToken(DWORD desired_access, 42 bool CopyProcessToken(DWORD desired_access,
34 ScopedHandle* token_out) { 43 ScopedHandle* token_out) {
35 44
36 HANDLE handle; 45 HANDLE handle;
37 if (!OpenProcessToken(GetCurrentProcess(), 46 if (!OpenProcessToken(GetCurrentProcess(),
38 TOKEN_DUPLICATE | desired_access, 47 TOKEN_DUPLICATE | desired_access,
39 &handle)) { 48 &handle)) {
40 LOG_GETLASTERROR(ERROR) << "Failed to open process token"; 49 LOG_GETLASTERROR(ERROR) << "Failed to open process token";
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 process_out->set_handle(process_info.hProcess); 157 process_out->set_handle(process_info.hProcess);
149 return true; 158 return true;
150 } 159 }
151 160
152 } // namespace 161 } // namespace
153 162
154 namespace remoting { 163 namespace remoting {
155 164
156 WtsSessionProcessLauncher::WtsSessionProcessLauncher( 165 WtsSessionProcessLauncher::WtsSessionProcessLauncher(
157 WtsConsoleMonitor* monitor, 166 WtsConsoleMonitor* monitor,
158 const FilePath& host_binary) 167 const FilePath& host_binary,
168 base::Thread* io_thread)
159 : host_binary_(host_binary), 169 : host_binary_(host_binary),
170 io_thread_(io_thread),
160 monitor_(monitor), 171 monitor_(monitor),
161 state_(StateDetached) { 172 state_(StateDetached) {
162 monitor_->AddWtsConsoleObserver(this); 173 monitor_->AddWtsConsoleObserver(this);
163 } 174 }
164 175
165 WtsSessionProcessLauncher::~WtsSessionProcessLauncher() { 176 WtsSessionProcessLauncher::~WtsSessionProcessLauncher() {
166 DCHECK(state_ == StateDetached); 177 DCHECK(state_ == StateDetached);
167 DCHECK(!timer_.IsRunning()); 178 DCHECK(!timer_.IsRunning());
168 DCHECK(process_.handle() == NULL); 179 DCHECK(process_.handle() == NULL);
169 DCHECK(process_watcher_.GetWatchedObject() == NULL); 180 DCHECK(process_watcher_.GetWatchedObject() == NULL);
181 DCHECK(chromoting_session_.get() == NULL);
170 182
171 monitor_->RemoveWtsConsoleObserver(this); 183 monitor_->RemoveWtsConsoleObserver(this);
172 } 184 }
173 185
174 void WtsSessionProcessLauncher::LaunchProcess() { 186 void WtsSessionProcessLauncher::LaunchProcess() {
175 DCHECK(state_ == StateStarting); 187 DCHECK(state_ == StateStarting);
176 DCHECK(!timer_.IsRunning()); 188 DCHECK(!timer_.IsRunning());
177 DCHECK(process_.handle() == NULL); 189 DCHECK(process_.handle() == NULL);
178 DCHECK(process_watcher_.GetWatchedObject() == NULL); 190 DCHECK(process_watcher_.GetWatchedObject() == NULL);
191 DCHECK(chromoting_session_.get() == NULL);
192
193 launch_time_ = base::Time::Now();
194
195 // Create the chromoting service IPC channel on the I/O thread.
196 // N.B. IPC::Channel passes NULL as the security attributes pointer to
197 // CreateNamedPipe() so the pipe gets the default security descriptor.
198 // The ACLs in the default security descriptor for a named pipe grant
199 // full control to the LocalSystem account, administrators, and
200 // the creator owner. They also grant read access to members of the
201 // Everyone group and the anonymous account.
202 //
203 // IPC::Channel also specifies the PIPE_ACCESS_DUPLEX mode for
204 // the created pipe. A client has to specify the same duplex mode in
205 // order to connect. Which means that clients with read-only access
206 // (Everyone and anonymous) will not be able to connect.
Wez 2012/03/08 00:01:33 nit: ... to connect, which means ... The comment
alexeypa (please no reviews) 2012/03/08 01:52:54 Actually, there is much more serious problem with
207 chromoting_session_.reset(new IPC::ChannelProxy(
208 kChromotingSessionChannelName,
209 IPC::Channel::MODE_SERVER,
210 this,
211 io_thread_->message_loop_proxy().get()));
179 212
180 // Try to launch the process and attach an object watcher to the returned 213 // Try to launch the process and attach an object watcher to the returned
181 // handle so that we get notified when the process terminates. 214 // handle so that we get notified when the process terminates.
182 launch_time_ = base::Time::Now();
183 if (LaunchProcessAsUser(host_binary_, session_token_, &process_)) { 215 if (LaunchProcessAsUser(host_binary_, session_token_, &process_)) {
184 if (process_watcher_.StartWatching(process_.handle(), this)) { 216 if (process_watcher_.StartWatching(process_.handle(), this)) {
185 state_ = StateAttached; 217 state_ = StateAttached;
186 return; 218 return;
187 } else { 219 } else {
188 LOG(ERROR) << "Failed to arm the process watcher."; 220 LOG(ERROR) << "Failed to arm the process watcher.";
189 process_.Terminate(0); 221 process_.Terminate(0);
190 process_.Close(); 222 process_.Close();
223 chromoting_session_.reset();
191 } 224 }
192 } 225 }
193 226
194 // Something went wrong. Try to launch the host again later. The attempts rate 227 // Something went wrong. Try to launch the host again later. The attempts rate
195 // is limited by exponential backoff. 228 // is limited by exponential backoff.
196 launch_backoff_ = std::max(launch_backoff_ * 2, 229 launch_backoff_ = std::max(launch_backoff_ * 2,
197 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 230 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
198 launch_backoff_ = std::min(launch_backoff_, 231 launch_backoff_ = std::min(launch_backoff_,
199 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); 232 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
200 timer_.Start(FROM_HERE, launch_backoff_, 233 timer_.Start(FROM_HERE, launch_backoff_,
201 this, &WtsSessionProcessLauncher::LaunchProcess); 234 this, &WtsSessionProcessLauncher::LaunchProcess);
202 } 235 }
203 236
204 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) { 237 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) {
205 DCHECK(state_ == StateAttached); 238 DCHECK(state_ == StateAttached);
206 DCHECK(!timer_.IsRunning()); 239 DCHECK(!timer_.IsRunning());
207 DCHECK(process_.handle() != NULL); 240 DCHECK(process_.handle() != NULL);
208 DCHECK(process_watcher_.GetWatchedObject() == NULL); 241 DCHECK(process_watcher_.GetWatchedObject() == NULL);
242 DCHECK(chromoting_session_.get() != NULL);
209 243
210 // The host process has been terminated for some reason. The handle can now be 244 // The host process has been terminated for some reason. The handle can now be
211 // closed. 245 // closed.
212 process_.Close(); 246 process_.Close();
247 chromoting_session_.reset();
213 248
214 // Expand the backoff interval if the process has died quickly or reset it if 249 // Expand the backoff interval if the process has died quickly or reset it if
215 // it was up longer than the maximum backoff delay. 250 // it was up longer than the maximum backoff delay.
216 base::TimeDelta delta = base::Time::Now() - launch_time_; 251 base::TimeDelta delta = base::Time::Now() - launch_time_;
217 if (delta < base::TimeDelta() || 252 if (delta < base::TimeDelta() ||
218 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) { 253 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) {
219 launch_backoff_ = base::TimeDelta(); 254 launch_backoff_ = base::TimeDelta();
220 } else { 255 } else {
221 launch_backoff_ = std::max(launch_backoff_ * 2, 256 launch_backoff_ = std::max(launch_backoff_ * 2,
222 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 257 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
223 launch_backoff_ = std::min(launch_backoff_, 258 launch_backoff_ = std::min(launch_backoff_,
224 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); 259 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
225 } 260 }
226 261
227 // Try to restart the host. 262 // Try to restart the host.
228 state_ = StateStarting; 263 state_ = StateStarting;
229 timer_.Start(FROM_HERE, launch_backoff_, 264 timer_.Start(FROM_HERE, launch_backoff_,
230 this, &WtsSessionProcessLauncher::LaunchProcess); 265 this, &WtsSessionProcessLauncher::LaunchProcess);
231 } 266 }
232 267
268 bool WtsSessionProcessLauncher::OnMessageReceived(const IPC::Message& message) {
269 bool handled = true;
270 IPC_BEGIN_MESSAGE_MAP(WtsSessionProcessLauncher, message)
271 IPC_MESSAGE_HANDLER(ChromotingSessionMsg_SendSasToConsole,
272 OnSendSasToConsole)
273 IPC_MESSAGE_UNHANDLED(handled = false)
274 IPC_END_MESSAGE_MAP()
275 return handled;
276 }
277
278 void WtsSessionProcessLauncher::OnSendSasToConsole() {
279 if (state_ == StateAttached) {
280 if (sas_injector_.get() == NULL) {
281 sas_injector_ = SasInjector::Create();
282 }
283
284 if (sas_injector_.get() != NULL) {
285 sas_injector_->InjectSas();
286 }
287 }
288 }
289
233 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) { 290 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) {
234 DCHECK(state_ == StateDetached); 291 DCHECK(state_ == StateDetached);
235 DCHECK(!timer_.IsRunning()); 292 DCHECK(!timer_.IsRunning());
236 DCHECK(process_.handle() == NULL); 293 DCHECK(process_.handle() == NULL);
237 DCHECK(process_watcher_.GetWatchedObject() == NULL); 294 DCHECK(process_watcher_.GetWatchedObject() == NULL);
295 DCHECK(chromoting_session_.get() == NULL);
238 296
239 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is 297 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is
240 // created as needed and kept for later reuse. 298 // created as needed and kept for later reuse.
241 if (privileged_token_.Get() == NULL) { 299 if (privileged_token_.Get() == NULL) {
242 if (!CreatePrivilegedToken(&privileged_token_)) { 300 if (!CreatePrivilegedToken(&privileged_token_)) {
243 return; 301 return;
244 } 302 }
245 } 303 }
246 304
247 if (!ImpersonateLoggedOnUser(privileged_token_)) { 305 if (!ImpersonateLoggedOnUser(privileged_token_)) {
248 LOG_GETLASTERROR(ERROR) << 306 LOG_GETLASTERROR(ERROR) <<
249 "Failed to impersonate the privileged token"; 307 "Failed to impersonate the privileged token";
250 return; 308 return;
251 } 309 }
252 310
253 // While the SE_TCB_NAME progolege is enabled, create a session token for 311 // While the SE_TCB_NAME privilege is enabled, create a session token for
254 // the launched process. 312 // the launched process.
255 bool result = CreateSessionToken(session_id, &session_token_); 313 bool result = CreateSessionToken(session_id, &session_token_);
256 314
257 // Revert to the default token. The default token is sufficient to call 315 // Revert to the default token. The default token is sufficient to call
258 // CreateProcessAsUser() successfully. 316 // CreateProcessAsUser() successfully.
259 CHECK(RevertToSelf()); 317 CHECK(RevertToSelf());
260 318
261 if (!result) 319 if (!result)
262 return; 320 return;
263 321
264 // Now try to launch the host. 322 // Now try to launch the host.
265 state_ = StateStarting; 323 state_ = StateStarting;
266 LaunchProcess(); 324 LaunchProcess();
267 } 325 }
268 326
269 void WtsSessionProcessLauncher::OnSessionDetached() { 327 void WtsSessionProcessLauncher::OnSessionDetached() {
270 DCHECK(state_ == StateDetached || 328 DCHECK(state_ == StateDetached ||
271 state_ == StateStarting || 329 state_ == StateStarting ||
272 state_ == StateAttached); 330 state_ == StateAttached);
273 331
274 switch (state_) { 332 switch (state_) {
275 case StateDetached: 333 case StateDetached:
276 DCHECK(!timer_.IsRunning()); 334 DCHECK(!timer_.IsRunning());
277 DCHECK(process_.handle() == NULL); 335 DCHECK(process_.handle() == NULL);
278 DCHECK(process_watcher_.GetWatchedObject() == NULL); 336 DCHECK(process_watcher_.GetWatchedObject() == NULL);
337 DCHECK(chromoting_session_.get() == NULL);
279 break; 338 break;
280 339
281 case StateStarting: 340 case StateStarting:
282 DCHECK(timer_.IsRunning()); 341 DCHECK(timer_.IsRunning());
283 DCHECK(process_.handle() == NULL); 342 DCHECK(process_.handle() == NULL);
284 DCHECK(process_watcher_.GetWatchedObject() == NULL); 343 DCHECK(process_watcher_.GetWatchedObject() == NULL);
344 DCHECK(chromoting_session_.get() == NULL);
285 345
286 timer_.Stop(); 346 timer_.Stop();
287 launch_backoff_ = base::TimeDelta(); 347 launch_backoff_ = base::TimeDelta();
288 state_ = StateDetached; 348 state_ = StateDetached;
289 break; 349 break;
290 350
291 case StateAttached: 351 case StateAttached:
292 DCHECK(!timer_.IsRunning()); 352 DCHECK(!timer_.IsRunning());
293 DCHECK(process_.handle() != NULL); 353 DCHECK(process_.handle() != NULL);
294 DCHECK(process_watcher_.GetWatchedObject() != NULL); 354 DCHECK(process_watcher_.GetWatchedObject() != NULL);
355 DCHECK(chromoting_session_.get() != NULL);
295 356
296 process_watcher_.StopWatching(); 357 process_watcher_.StopWatching();
297 process_.Terminate(0); 358 process_.Terminate(0);
298 process_.Close(); 359 process_.Close();
360 chromoting_session_.reset();
299 state_ = StateDetached; 361 state_ = StateDetached;
300 break; 362 break;
301 } 363 }
302 } 364 }
303 365
304 } // namespace remoting 366 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/wts_session_process_launcher_win.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698