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

Side by Side Diff: remoting/host/win/host_service.cc

Issue 12378078: Initialize COM and configure security settings in the daemon. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 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
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/win/host_service.h" 8 #include "remoting/host/win/host_service.h"
9 9
10 #include <windows.h> 10 #include <windows.h>
11 #include <wtsapi32.h> 11 #include <wtsapi32.h>
12 12
13 #include "base/base_paths.h" 13 #include "base/base_paths.h"
14 #include "base/base_switches.h" 14 #include "base/base_switches.h"
15 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
18 #include "base/message_loop.h" 18 #include "base/message_loop.h"
19 #include "base/run_loop.h" 19 #include "base/run_loop.h"
20 #include "base/scoped_native_library.h" 20 #include "base/scoped_native_library.h"
21 #include "base/single_thread_task_runner.h" 21 #include "base/single_thread_task_runner.h"
22 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
23 #include "base/utf_string_conversions.h" 23 #include "base/utf_string_conversions.h"
24 #include "base/win/scoped_com_initializer.h"
24 #include "base/win/wrapped_window_proc.h" 25 #include "base/win/wrapped_window_proc.h"
25 #include "remoting/base/auto_thread.h" 26 #include "remoting/base/auto_thread.h"
26 #include "remoting/base/scoped_sc_handle_win.h" 27 #include "remoting/base/scoped_sc_handle_win.h"
27 #include "remoting/base/stoppable.h" 28 #include "remoting/base/stoppable.h"
28 #include "remoting/host/branding.h" 29 #include "remoting/host/branding.h"
29 #include "remoting/host/host_exit_codes.h" 30 #include "remoting/host/host_exit_codes.h"
30 #include "remoting/host/logging.h" 31 #include "remoting/host/logging.h"
32 #include "remoting/host/win/security_descriptor.h"
31 33
32 #if defined(REMOTING_MULTI_PROCESS) 34 #if defined(REMOTING_MULTI_PROCESS)
33 #include "remoting/host/daemon_process.h" 35 #include "remoting/host/daemon_process.h"
34 #endif // defined(REMOTING_MULTI_PROCESS) 36 #endif // defined(REMOTING_MULTI_PROCESS)
35 37
36 #include "remoting/host/win/core_resource.h" 38 #include "remoting/host/win/core_resource.h"
37 #include "remoting/host/win/wts_terminal_observer.h" 39 #include "remoting/host/win/wts_terminal_observer.h"
38 40
39 #if !defined(REMOTING_MULTI_PROCESS) 41 #if !defined(REMOTING_MULTI_PROCESS)
40 #include "remoting/host/win/wts_console_session_process_driver.h" 42 #include "remoting/host/win/wts_console_session_process_driver.h"
41 #endif // !defined(REMOTING_MULTI_PROCESS) 43 #endif // !defined(REMOTING_MULTI_PROCESS)
42 44
45 namespace remoting {
46
43 namespace { 47 namespace {
44 48
45 // Used to query the endpoint of an attached RDP client. 49 // Used to query the endpoint of an attached RDP client.
46 const WINSTATIONINFOCLASS kWinStationRemoteAddress = 50 const WINSTATIONINFOCLASS kWinStationRemoteAddress =
47 static_cast<WINSTATIONINFOCLASS>(29); 51 static_cast<WINSTATIONINFOCLASS>(29);
48 52
49 // Session id that does not represent any session. 53 // Session id that does not represent any session.
50 const uint32 kInvalidSessionId = 0xffffffffu; 54 const uint32 kInvalidSessionId = 0xffffffffu;
51 55
52 const char kIoThreadName[] = "I/O thread"; 56 const char kIoThreadName[] = "I/O thread";
53 57
54 // A window class for the session change notifications window. 58 // A window class for the session change notifications window.
55 const wchar_t kSessionNotificationWindowClass[] = 59 const wchar_t kSessionNotificationWindowClass[] =
56 L"Chromoting_SessionNotificationWindow"; 60 L"Chromoting_SessionNotificationWindow";
57 61
58 // Command line switches: 62 // Command line switches:
59 63
60 // "--console" runs the service interactively for debugging purposes. 64 // "--console" runs the service interactively for debugging purposes.
61 const char kConsoleSwitchName[] = "console"; 65 const char kConsoleSwitchName[] = "console";
62 66
67 // A security descriptor that gives SYSTEM and LocalSystem accounts
68 // COM_RIGHTS_EXECUTE and COM_RIGHTS_EXECUTE_LOCAL rights. The descriptor
69 // specifies a mandatory label with "no execute up" policy for medium integrity
70 // level.
71 const char kComProcessSd[] =
72 "O:SYG:SYD:(A;;0x3;;;SY)(A;;0x3;;;LS)S:(ML;;NX;;;ME)";
jschuh 2013/03/04 21:12:33 SDDL can be pretty impenetrable. Generally, I find
alexeypa (please no reviews) 2013/03/04 21:46:30 Done.
73
74 // Allows incoming calls from clients running under SYSTEM or LocalSystem at
75 // medium integrity level.
76 bool InitializeComSecurity() {
77 // Convert the SDDL description into a security descriptor in absolute format.
78 ScopedSd relative_sd = ConvertSddlToSd(kComProcessSd);
79 if (!relative_sd) {
80 LOG_GETLASTERROR(ERROR) << "Failed to create a security descriptor";
81 return false;
82 }
83 ScopedSd absolute_sd;
84 ScopedAcl dacl;
85 ScopedSid group;
86 ScopedSid owner;
87 ScopedAcl sacl;
88 if (!MakeAbsoluteSd(relative_sd, &absolute_sd, &dacl, &group, &owner,
89 &sacl)) {
90 LOG_GETLASTERROR(ERROR) << "MakeAbsoluteSd() failed";
91 return false;
92 }
93
94 // Apply the security descriptor and the following settings:
95 // - The daemon authenticates that all data received is from the expected
96 // client.
97 // - The daemon can check identity of the client but cannot act on its
98 // behalf.
99 // - Dynamic cloacking is used. DCOM verifies the caller's identify on every
jschuh 2013/03/04 21:12:33 nit: cloaking
alexeypa (please no reviews) 2013/03/04 21:46:30 Done.
100 // call.
101 // - Activations where the activated COM server would run under the daemon's
102 // identify are prohibited.
103 HRESULT result = CoInitializeSecurity(
104 absolute_sd.get(),
105 -1,
106 NULL,
107 NULL,
108 RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
109 RPC_C_IMP_LEVEL_IDENTIFY,
110 NULL,
111 EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA,
112 NULL);
113 if (FAILED(result)) {
114 LOG(ERROR) << "CoInitializeSecurity() failed, result=0x"
115 << std::hex << result << std::dec << ".";
116 return false;
117 }
118
119 return true;
120 }
121
63 } // namespace 122 } // namespace
64 123
65 namespace remoting {
66
67 HostService* HostService::GetInstance() { 124 HostService* HostService::GetInstance() {
68 return Singleton<HostService>::get(); 125 return Singleton<HostService>::get();
69 } 126 }
70 127
71 bool HostService::InitWithCommandLine(const CommandLine* command_line) { 128 bool HostService::InitWithCommandLine(const CommandLine* command_line) {
72 CommandLine::StringVector args = command_line->GetArgs(); 129 CommandLine::StringVector args = command_line->GetArgs();
73 if (!args.empty()) { 130 if (!args.empty()) {
74 LOG(ERROR) << "No positional parameters expected."; 131 LOG(ERROR) << "No positional parameters expected.";
75 return false; 132 return false;
76 } 133 }
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 438
382 // Wait until the service thread completely exited to avoid concurrent 439 // Wait until the service thread completely exited to avoid concurrent
383 // teardown of objects registered with base::AtExitManager and object 440 // teardown of objects registered with base::AtExitManager and object
384 // destoyed by the service thread. 441 // destoyed by the service thread.
385 stopped_event_.Wait(); 442 stopped_event_.Wait();
386 443
387 return kSuccessExitCode; 444 return kSuccessExitCode;
388 } 445 }
389 446
390 void HostService::RunAsServiceImpl() { 447 void HostService::RunAsServiceImpl() {
391 MessageLoop message_loop(MessageLoop::TYPE_DEFAULT); 448 MessageLoop message_loop(MessageLoop::TYPE_UI);
392 base::RunLoop run_loop; 449 base::RunLoop run_loop;
393 main_task_runner_ = message_loop.message_loop_proxy(); 450 main_task_runner_ = message_loop.message_loop_proxy();
394 451
395 // Register the service control handler. 452 // Register the service control handler.
396 service_status_handle_ = RegisterServiceCtrlHandlerExW( 453 service_status_handle_ = RegisterServiceCtrlHandlerExW(
397 kWindowsServiceName, &HostService::ServiceControlHandler, this); 454 kWindowsServiceName, &HostService::ServiceControlHandler, this);
398 if (service_status_handle_ == 0) { 455 if (service_status_handle_ == 0) {
399 LOG_GETLASTERROR(ERROR) 456 LOG_GETLASTERROR(ERROR)
400 << "Failed to register the service control handler"; 457 << "Failed to register the service control handler";
401 return; 458 return;
402 } 459 }
403 460
404 // Report running status of the service. 461 // Report running status of the service.
405 SERVICE_STATUS service_status; 462 SERVICE_STATUS service_status;
406 ZeroMemory(&service_status, sizeof(service_status)); 463 ZeroMemory(&service_status, sizeof(service_status));
407 service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 464 service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
408 service_status.dwCurrentState = SERVICE_RUNNING; 465 service_status.dwCurrentState = SERVICE_RUNNING;
409 service_status.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | 466 service_status.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN |
410 SERVICE_ACCEPT_STOP | 467 SERVICE_ACCEPT_STOP |
411 SERVICE_ACCEPT_SESSIONCHANGE; 468 SERVICE_ACCEPT_SESSIONCHANGE;
412 service_status.dwWin32ExitCode = kSuccessExitCode; 469 service_status.dwWin32ExitCode = kSuccessExitCode;
413 if (!SetServiceStatus(service_status_handle_, &service_status)) { 470 if (!SetServiceStatus(service_status_handle_, &service_status)) {
414 LOG_GETLASTERROR(ERROR) 471 LOG_GETLASTERROR(ERROR)
415 << "Failed to report service status to the service control manager"; 472 << "Failed to report service status to the service control manager";
416 return; 473 return;
417 } 474 }
418 475
476 // Initialize COM.
477 base::win::ScopedCOMInitializer com_initializer;
478 if (!com_initializer.succeeded())
479 return;
480
481 if (!InitializeComSecurity())
482 return;
483
419 CreateLauncher(scoped_refptr<AutoThreadTaskRunner>( 484 CreateLauncher(scoped_refptr<AutoThreadTaskRunner>(
420 new AutoThreadTaskRunner(main_task_runner_, 485 new AutoThreadTaskRunner(main_task_runner_,
421 run_loop.QuitClosure()))); 486 run_loop.QuitClosure())));
422 487
423 // Run the service. 488 // Run the service.
424 run_loop.Run(); 489 run_loop.Run();
425 490
426 // Tell SCM that the service is stopped. 491 // Tell SCM that the service is stopped.
427 service_status.dwCurrentState = SERVICE_STOPPED; 492 service_status.dwCurrentState = SERVICE_STOPPED;
428 service_status.dwControlsAccepted = 0; 493 service_status.dwControlsAccepted = 0;
429 if (!SetServiceStatus(service_status_handle_, &service_status)) { 494 if (!SetServiceStatus(service_status_handle_, &service_status)) {
430 LOG_GETLASTERROR(ERROR) 495 LOG_GETLASTERROR(ERROR)
431 << "Failed to report service status to the service control manager"; 496 << "Failed to report service status to the service control manager";
432 return; 497 return;
433 } 498 }
434 } 499 }
435 500
436 int HostService::RunInConsole() { 501 int HostService::RunInConsole() {
437 MessageLoop message_loop(MessageLoop::TYPE_UI); 502 MessageLoop message_loop(MessageLoop::TYPE_UI);
438 base::RunLoop run_loop; 503 base::RunLoop run_loop;
439 main_task_runner_ = message_loop.message_loop_proxy(); 504 main_task_runner_ = message_loop.message_loop_proxy();
440 505
441 int result = kInitializationFailed; 506 int result = kInitializationFailed;
442 507
508 // Initialize COM.
509 base::win::ScopedCOMInitializer com_initializer;
510 if (!com_initializer.succeeded())
511 return result;
512
513 if (!InitializeComSecurity())
514 return result;
515
443 // Subscribe to Ctrl-C and other console events. 516 // Subscribe to Ctrl-C and other console events.
444 if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) { 517 if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) {
445 LOG_GETLASTERROR(ERROR) 518 LOG_GETLASTERROR(ERROR)
446 << "Failed to set console control handler"; 519 << "Failed to set console control handler";
447 return result; 520 return result;
448 } 521 }
449 522
450 // Create a window for receiving session change notifications. 523 // Create a window for receiving session change notifications.
451 HWND window = NULL; 524 HWND window = NULL;
452 WNDCLASSEX window_class; 525 WNDCLASSEX window_class;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 int DaemonProcessMain() { 658 int DaemonProcessMain() {
586 HostService* service = HostService::GetInstance(); 659 HostService* service = HostService::GetInstance();
587 if (!service->InitWithCommandLine(CommandLine::ForCurrentProcess())) { 660 if (!service->InitWithCommandLine(CommandLine::ForCurrentProcess())) {
588 return kUsageExitCode; 661 return kUsageExitCode;
589 } 662 }
590 663
591 return service->Run(); 664 return service->Run();
592 } 665 }
593 666
594 } // namespace remoting 667 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | remoting/host/win/security_descriptor.h » ('j') | remoting/host/win/security_descriptor.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698