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 3 // found in the LICENSE file. 4 // 5 // This file implements the Windows service controlling Me2Me host processes 6 // running within user sessions. 7 8 #include "remoting/host/win/wts_session_process_delegate.h" 9 10 #include "base/bind.h" 11 #include "base/command_line.h" 12 #include "base/files/file_path.h" 13 #include "base/logging.h" 14 #include "base/message_loop/message_loop.h" 15 #include "base/single_thread_task_runner.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "base/thread_task_runner_handle.h" 18 #include "base/win/scoped_handle.h" 19 #include "base/win/windows_version.h" 20 #include "ipc/ipc_channel.h" 21 #include "ipc/ipc_channel_proxy.h" 22 #include "ipc/ipc_listener.h" 23 #include "ipc/ipc_message.h" 24 #include "remoting/host/host_main.h" 25 #include "remoting/host/ipc_constants.h" 26 #include "remoting/host/ipc_util.h" 27 #include "remoting/host/win/launch_process_with_token.h" 28 #include "remoting/host/win/worker_process_launcher.h" 29 #include "remoting/host/win/wts_terminal_monitor.h" 30 #include "remoting/host/worker_process_ipc_delegate.h" 31 32 using base::win::ScopedHandle; 33 34 // Name of the default session desktop. 35 const char kDefaultDesktopName[] = "winsta0\\default"; 36 37 namespace remoting { 38 39 // A private class actually implementing the functionality provided by 40 // |WtsSessionProcessDelegate|. This class is ref-counted and implements 41 // asynchronous fire-and-forget shutdown. 42 class WtsSessionProcessDelegate::Core 43 : public base::RefCountedThreadSafe<Core>, 44 public base::MessagePumpForIO::IOHandler, 45 public IPC::Listener { 46 public: 47 Core(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 48 scoped_ptr<CommandLine> target, 49 bool launch_elevated, 50 const std::string& channel_security); 51 52 // Initializes the object returning true on success. 53 bool Initialize(uint32 session_id); 54 55 // Stops the object asynchronously. 56 void Stop(); 57 58 // Mirrors WorkerProcessLauncher::Delegate. 59 void LaunchProcess(WorkerProcessLauncher* event_handler); 60 void Send(IPC::Message* message); 61 void CloseChannel(); 62 void KillProcess(); 63 64 private: 65 friend class base::RefCountedThreadSafe<Core>; 66 virtual ~Core(); 67 68 // base::MessagePumpForIO::IOHandler implementation. 69 virtual void OnIOCompleted(base::MessagePumpForIO::IOContext* context, 70 DWORD bytes_transferred, 71 DWORD error) OVERRIDE; 72 73 // IPC::Listener implementation. 74 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 75 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; 76 virtual void OnChannelError() OVERRIDE; 77 78 // The actual implementation of LaunchProcess() 79 void DoLaunchProcess(); 80 81 // Drains the completion port queue to make sure that all job object 82 // notifications have been received. 83 void DrainJobNotifications(); 84 85 // Notified that the completion port queue has been drained. 86 void DrainJobNotificationsCompleted(); 87 88 // Creates and initializes the job object that will sandbox the launched child 89 // processes. 90 void InitializeJob(scoped_ptr<base::win::ScopedHandle> job); 91 92 // Notified that the job object initialization is complete. 93 void InitializeJobCompleted(scoped_ptr<base::win::ScopedHandle> job); 94 95 // Called when the number of processes running in the job reaches zero. 96 void OnActiveProcessZero(); 97 98 void ReportFatalError(); 99 void ReportProcessLaunched(base::win::ScopedHandle worker_process); 100 101 // The task runner all public methods of this class should be called on. 102 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; 103 104 // The task runner serving job object notifications. 105 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 106 107 // The server end of the IPC channel used to communicate to the worker 108 // process. 109 scoped_ptr<IPC::ChannelProxy> channel_; 110 111 // Security descriptor (as SDDL) to be applied to |channel_|. 112 std::string channel_security_; 113 114 WorkerProcessLauncher* event_handler_; 115 116 // Pointer to GetNamedPipeClientProcessId() API if it is available. 117 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*); 118 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_; 119 120 // The job object used to control the lifetime of child processes. 121 base::win::ScopedHandle job_; 122 123 // True if the worker process should be launched elevated. 124 bool launch_elevated_; 125 126 // True if a laucnh attemp is pending. 127 bool launch_pending_; 128 129 // The named pipe used as the transport by |channel_|. 130 base::win::ScopedHandle pipe_; 131 132 // The token to be used to launch a process in a different session. 133 base::win::ScopedHandle session_token_; 134 135 // Command line of the launched process. 136 scoped_ptr<CommandLine> target_command_; 137 138 // The handle of the worker process, if launched. 139 base::win::ScopedHandle worker_process_; 140 141 DISALLOW_COPY_AND_ASSIGN(Core); 142 }; 143 144 WtsSessionProcessDelegate::Core::Core( 145 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 146 scoped_ptr<CommandLine> target_command, 147 bool launch_elevated, 148 const std::string& channel_security) 149 : caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), 150 io_task_runner_(io_task_runner), 151 channel_security_(channel_security), 152 event_handler_(NULL), 153 get_named_pipe_client_pid_(NULL), 154 launch_elevated_(launch_elevated), 155 launch_pending_(false), 156 target_command_(target_command.Pass()) { 157 } 158 159 bool WtsSessionProcessDelegate::Core::Initialize(uint32 session_id) { 160 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 161 162 // Windows XP does not support elevation. 163 if (base::win::GetVersion() < base::win::VERSION_VISTA) 164 launch_elevated_ = false; 165 166 if (launch_elevated_) { 167 // GetNamedPipeClientProcessId() is available starting from Vista. 168 HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll"); 169 CHECK(kernel32 != NULL); 170 171 get_named_pipe_client_pid_ = 172 reinterpret_cast<GetNamedPipeClientProcessIdFn>( 173 GetProcAddress(kernel32, "GetNamedPipeClientProcessId")); 174 CHECK(get_named_pipe_client_pid_ != NULL); 175 176 ScopedHandle job; 177 job.Set(CreateJobObject(NULL, NULL)); 178 if (!job.IsValid()) { 179 PLOG(ERROR) << "Failed to create a job object"; 180 return false; 181 } 182 183 // Limit the number of active processes in the job to two (the helper 184 // process performing elevation and the worker process itself) and make sure 185 // that all processes will be killed once the job object is destroyed. 186 JOBOBJECT_EXTENDED_LIMIT_INFORMATION info; 187 memset(&info, 0, sizeof(info)); 188 info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS | 189 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; 190 info.BasicLimitInformation.ActiveProcessLimit = 2; 191 if (!SetInformationJobObject(job, 192 JobObjectExtendedLimitInformation, 193 &info, 194 sizeof(info))) { 195 PLOG(ERROR) << "Failed to set limits on the job object"; 196 return false; 197 } 198 199 // ScopedHandle is not compatible with base::Passed, so we wrap it to 200 // a scoped pointer. 201 scoped_ptr<ScopedHandle> job_wrapper(new ScopedHandle()); 202 *job_wrapper = job.Pass(); 203 204 // To receive job object notifications the job object is registered with 205 // the completion port represented by |io_task_runner|. The registration has 206 // to be done on the I/O thread because 207 // MessageLoopForIO::RegisterJobObject() can only be called via 208 // MessageLoopForIO::current(). 209 io_task_runner_->PostTask( 210 FROM_HERE, 211 base::Bind(&Core::InitializeJob, this, base::Passed(&job_wrapper))); 212 } 213 214 // Create a session token for the launched process. 215 return CreateSessionToken(session_id, &session_token_); 216 } 217 218 void WtsSessionProcessDelegate::Core::Stop() { 219 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 220 221 KillProcess(); 222 223 // Drain the completion queue to make sure all job object notifications have 224 // been received. 225 DrainJobNotificationsCompleted(); 226 } 227 228 void WtsSessionProcessDelegate::Core::LaunchProcess( 229 WorkerProcessLauncher* event_handler) { 230 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 231 DCHECK(!event_handler_); 232 233 event_handler_ = event_handler; 234 DoLaunchProcess(); 235 } 236 237 void WtsSessionProcessDelegate::Core::Send(IPC::Message* message) { 238 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 239 240 if (channel_) { 241 channel_->Send(message); 242 } else { 243 delete message; 244 } 245 } 246 247 void WtsSessionProcessDelegate::Core::CloseChannel() { 248 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 249 250 channel_.reset(); 251 pipe_.Close(); 252 } 253 254 void WtsSessionProcessDelegate::Core::KillProcess() { 255 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 256 257 channel_.reset(); 258 event_handler_ = NULL; 259 launch_pending_ = false; 260 pipe_.Close(); 261 262 if (launch_elevated_) { 263 if (job_.IsValid()) 264 TerminateJobObject(job_, CONTROL_C_EXIT); 265 } else { 266 if (worker_process_.IsValid()) 267 TerminateProcess(worker_process_, CONTROL_C_EXIT); 268 } 269 270 worker_process_.Close(); 271 } 272 273 WtsSessionProcessDelegate::Core::~Core() { 274 DCHECK(!channel_); 275 DCHECK(!event_handler_); 276 DCHECK(!pipe_.IsValid()); 277 DCHECK(!worker_process_.IsValid()); 278 } 279 280 void WtsSessionProcessDelegate::Core::OnIOCompleted( 281 base::MessagePumpForIO::IOContext* context, 282 DWORD bytes_transferred, 283 DWORD error) { 284 DCHECK(io_task_runner_->BelongsToCurrentThread()); 285 286 // |bytes_transferred| is used in job object notifications to supply 287 // the message ID; |context| carries process ID. 288 if (bytes_transferred == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) { 289 caller_task_runner_->PostTask(FROM_HERE, 290 base::Bind(&Core::OnActiveProcessZero, this)); 291 } 292 } 293 294 bool WtsSessionProcessDelegate::Core::OnMessageReceived( 295 const IPC::Message& message) { 296 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 297 298 return event_handler_->OnMessageReceived(message); 299 } 300 301 void WtsSessionProcessDelegate::Core::OnChannelConnected(int32 peer_pid) { 302 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 303 304 // Report the worker PID now if the worker process is launched indirectly. 305 // Note that in this case the pipe's security descriptor is the only 306 // protection against a malicious processed connecting to the pipe. 307 if (launch_elevated_) { 308 DWORD pid; 309 if (!get_named_pipe_client_pid_(pipe_, &pid)) { 310 PLOG(ERROR) << "Failed to retrive PID of the client"; 311 ReportFatalError(); 312 return; 313 } 314 315 if (pid != static_cast<DWORD>(peer_pid)) { 316 LOG(ERROR) << "The actual client PID " << pid 317 << " does not match the one reported by the client: " 318 << peer_pid; 319 ReportFatalError(); 320 return; 321 } 322 323 DWORD desired_access = 324 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; 325 ScopedHandle worker_process(OpenProcess(desired_access, false, pid)); 326 if (!worker_process.IsValid()) { 327 PLOG(ERROR) << "Failed to open process " << pid; 328 ReportFatalError(); 329 return; 330 } 331 332 ReportProcessLaunched(worker_process.Pass()); 333 } 334 335 if (event_handler_) 336 event_handler_->OnChannelConnected(peer_pid); 337 } 338 339 void WtsSessionProcessDelegate::Core::OnChannelError() { 340 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 341 342 event_handler_->OnChannelError(); 343 } 344 345 void WtsSessionProcessDelegate::Core::DoLaunchProcess() { 346 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 347 DCHECK(!channel_); 348 DCHECK(!pipe_.IsValid()); 349 DCHECK(!worker_process_.IsValid()); 350 351 base::CommandLine command_line(target_command_->argv()); 352 if (launch_elevated_) { 353 // The job object is not ready. Retry starting the host process later. 354 if (!job_.IsValid()) { 355 launch_pending_ = true; 356 return; 357 } 358 359 // Construct the helper binary name. 360 base::FilePath helper_binary; 361 if (!GetInstalledBinaryPath(kHostBinaryName, &helper_binary)) { 362 ReportFatalError(); 363 return; 364 } 365 366 // Create the command line passing the name of the IPC channel to use and 367 // copying known switches from the caller's command line. 368 command_line.SetProgram(helper_binary); 369 command_line.AppendSwitchPath(kElevateSwitchName, 370 target_command_->GetProgram()); 371 } 372 373 // Create the server end of the IPC channel. 374 std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID(); 375 ScopedHandle pipe; 376 if (!CreateIpcChannel(channel_name, channel_security_, &pipe)) { 377 ReportFatalError(); 378 return; 379 } 380 381 // Wrap the pipe into an IPC channel. 382 scoped_ptr<IPC::ChannelProxy> channel( 383 IPC::ChannelProxy::Create(IPC::ChannelHandle(pipe), 384 IPC::Channel::MODE_SERVER, 385 this, 386 io_task_runner_)); 387 388 // Pass the name of the IPC channel to use. 389 command_line.AppendSwitchNative(kDaemonPipeSwitchName, 390 base::UTF8ToWide(channel_name)); 391 392 // Try to launch the process. 393 ScopedHandle worker_process; 394 ScopedHandle worker_thread; 395 if (!LaunchProcessWithToken(command_line.GetProgram(), 396 command_line.GetCommandLineString(), 397 session_token_, 398 NULL, 399 NULL, 400 false, 401 CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, 402 base::UTF8ToUTF16(kDefaultDesktopName).c_str(), 403 &worker_process, 404 &worker_thread)) { 405 ReportFatalError(); 406 return; 407 } 408 409 if (launch_elevated_) { 410 if (!AssignProcessToJobObject(job_, worker_process)) { 411 PLOG(ERROR) << "Failed to assign the worker to the job object"; 412 ReportFatalError(); 413 return; 414 } 415 } 416 417 if (!ResumeThread(worker_thread)) { 418 PLOG(ERROR) << "Failed to resume the worker thread"; 419 ReportFatalError(); 420 return; 421 } 422 423 channel_ = channel.Pass(); 424 pipe_ = pipe.Pass(); 425 426 // Report success if the worker process is lauched directly. Otherwise, PID of 427 // the client connected to the pipe will be used later. See 428 // OnChannelConnected(). 429 if (!launch_elevated_) 430 ReportProcessLaunched(worker_process.Pass()); 431 } 432 433 void WtsSessionProcessDelegate::Core::DrainJobNotifications() { 434 DCHECK(io_task_runner_->BelongsToCurrentThread()); 435 436 // DrainJobNotifications() is posted after the job object is destroyed, so 437 // by this time all notifications from the job object have been processed 438 // already. Let the main thread know that the queue has been drained. 439 caller_task_runner_->PostTask(FROM_HERE, base::Bind( 440 &Core::DrainJobNotificationsCompleted, this)); 441 } 442 443 void WtsSessionProcessDelegate::Core::DrainJobNotificationsCompleted() { 444 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 445 446 if (job_.IsValid()) { 447 job_.Close(); 448 449 // Drain the completion queue to make sure all job object notification have 450 // been received. 451 io_task_runner_->PostTask(FROM_HERE, base::Bind( 452 &Core::DrainJobNotifications, this)); 453 } 454 } 455 456 void WtsSessionProcessDelegate::Core::InitializeJob( 457 scoped_ptr<base::win::ScopedHandle> job) { 458 DCHECK(io_task_runner_->BelongsToCurrentThread()); 459 460 // Register to receive job notifications via the I/O thread's completion port. 461 if (!base::MessageLoopForIO::current()->RegisterJobObject(job->Get(), this)) { 462 PLOG(ERROR) << "Failed to associate the job object with a completion port"; 463 return; 464 } 465 466 // Let the main thread know that initialization is complete. 467 caller_task_runner_->PostTask(FROM_HERE, base::Bind( 468 &Core::InitializeJobCompleted, this, base::Passed(&job))); 469 } 470 471 void WtsSessionProcessDelegate::Core::InitializeJobCompleted( 472 scoped_ptr<ScopedHandle> job) { 473 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 474 DCHECK(!job_.IsValid()); 475 476 job_ = job->Pass(); 477 478 if (launch_pending_) 479 DoLaunchProcess(); 480 } 481 482 void WtsSessionProcessDelegate::Core::OnActiveProcessZero() { 483 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 484 485 if (launch_pending_) { 486 LOG(ERROR) << "The worker process exited before connecting via IPC."; 487 launch_pending_ = false; 488 ReportFatalError(); 489 } 490 } 491 492 void WtsSessionProcessDelegate::Core::ReportFatalError() { 493 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 494 495 channel_.reset(); 496 pipe_.Close(); 497 498 WorkerProcessLauncher* event_handler = event_handler_; 499 event_handler_ = NULL; 500 event_handler->OnFatalError(); 501 } 502 503 void WtsSessionProcessDelegate::Core::ReportProcessLaunched( 504 base::win::ScopedHandle worker_process) { 505 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 506 DCHECK(!worker_process_.IsValid()); 507 508 worker_process_ = worker_process.Pass(); 509 510 // Report a handle that can be used to wait for the worker process completion, 511 // query information about the process and duplicate handles. 512 DWORD desired_access = 513 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; 514 HANDLE temp_handle; 515 if (!DuplicateHandle(GetCurrentProcess(), 516 worker_process_, 517 GetCurrentProcess(), 518 &temp_handle, 519 desired_access, 520 FALSE, 521 0)) { 522 PLOG(ERROR) << "Failed to duplicate a handle"; 523 ReportFatalError(); 524 return; 525 } 526 ScopedHandle limited_handle(temp_handle); 527 528 event_handler_->OnProcessLaunched(limited_handle.Pass()); 529 } 530 531 WtsSessionProcessDelegate::WtsSessionProcessDelegate( 532 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 533 scoped_ptr<CommandLine> target_command, 534 bool launch_elevated, 535 const std::string& channel_security) { 536 core_ = new Core(io_task_runner, 537 target_command.Pass(), 538 launch_elevated, 539 channel_security); 540 } 541 542 WtsSessionProcessDelegate::~WtsSessionProcessDelegate() { 543 core_->Stop(); 544 } 545 546 bool WtsSessionProcessDelegate::Initialize(uint32 session_id) { 547 return core_->Initialize(session_id); 548 } 549 550 void WtsSessionProcessDelegate::LaunchProcess( 551 WorkerProcessLauncher* event_handler) { 552 core_->LaunchProcess(event_handler); 553 } 554 555 void WtsSessionProcessDelegate::Send(IPC::Message* message) { 556 core_->Send(message); 557 } 558 559 void WtsSessionProcessDelegate::CloseChannel() { 560 core_->CloseChannel(); 561 } 562 563 void WtsSessionProcessDelegate::KillProcess() { 564 core_->KillProcess(); 565 } 566 567 } // namespace remoting 568