OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "remoting/host/it2me/it2me_native_messaging_host_main.h" | 5 #include "remoting/host/it2me/it2me_native_messaging_host_main.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/at_exit.h" | 9 #include "base/at_exit.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 | 30 |
31 #include "base/linux_util.h" | 31 #include "base/linux_util.h" |
32 #endif // defined(OS_LINUX) | 32 #endif // defined(OS_LINUX) |
33 | 33 |
34 #if defined(OS_MACOSX) | 34 #if defined(OS_MACOSX) |
35 #include "base/mac/scoped_nsautorelease_pool.h" | 35 #include "base/mac/scoped_nsautorelease_pool.h" |
36 #endif // defined(OS_MACOSX) | 36 #endif // defined(OS_MACOSX) |
37 | 37 |
38 #if defined(OS_WIN) | 38 #if defined(OS_WIN) |
39 #include <commctrl.h> | 39 #include <commctrl.h> |
40 | |
41 #include "remoting/host/switches.h" | |
42 #include "remoting/host/win/elevation_helpers.h" | |
40 #endif // defined(OS_WIN) | 43 #endif // defined(OS_WIN) |
41 | 44 |
42 namespace remoting { | 45 namespace remoting { |
43 | 46 |
44 // Creates a It2MeNativeMessagingHost instance, attaches it to stdin/stdout and | 47 // Creates a It2MeNativeMessagingHost instance, attaches it to stdin/stdout and |
45 // runs the message loop until It2MeNativeMessagingHost signals shutdown. | 48 // runs the message loop until It2MeNativeMessagingHost signals shutdown. |
46 int StartIt2MeNativeMessagingHost() { | 49 int StartIt2MeNativeMessagingHost() { |
47 #if defined(OS_MACOSX) | 50 #if defined(OS_MACOSX) |
48 // Needed so we don't leak objects when threads are created. | 51 // Needed so we don't leak objects when threads are created. |
49 base::mac::ScopedNSAutoreleasePool pool; | 52 base::mac::ScopedNSAutoreleasePool pool; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 | 86 |
84 // Need to prime the host OS version value for linux to prevent IO on the | 87 // Need to prime the host OS version value for linux to prevent IO on the |
85 // network thread. base::GetLinuxDistro() caches the result. | 88 // network thread. base::GetLinuxDistro() caches the result. |
86 base::GetLinuxDistro(); | 89 base::GetLinuxDistro(); |
87 #endif // OS_LINUX | 90 #endif // OS_LINUX |
88 | 91 |
89 // Enable support for SSL server sockets, which must be done while still | 92 // Enable support for SSL server sockets, which must be done while still |
90 // single-threaded. | 93 // single-threaded. |
91 net::EnableSSLServerSockets(); | 94 net::EnableSSLServerSockets(); |
92 | 95 |
96 base::File read_file; | |
97 base::File write_file; | |
98 bool needs_elevation = false; | |
99 | |
93 #if defined(OS_WIN) | 100 #if defined(OS_WIN) |
94 // GetStdHandle() returns pseudo-handles for stdin and stdout even if | |
95 // the hosting executable specifies "Windows" subsystem. However the returned | |
96 // handles are invalid in that case unless standard input and output are | |
97 // redirected to a pipe or file. | |
98 base::File read_file(GetStdHandle(STD_INPUT_HANDLE)); | |
99 base::File write_file(GetStdHandle(STD_OUTPUT_HANDLE)); | |
100 | 101 |
101 // After the native messaging channel starts the native messaging reader | 102 const base::CommandLine* command_line = |
102 // will keep doing blocking read operations on the input named pipe. | 103 base::CommandLine::ForCurrentProcess(); |
103 // If any other thread tries to perform any operation on STDIN, it will also | 104 |
104 // block because the input named pipe is synchronous (non-overlapped). | 105 if (command_line->HasSwitch(kElevateSwitchName)) { |
105 // It is pretty common for a DLL to query the device info (GetFileType) of | 106 #if defined(OFFICIAL_BUILD) |
106 // the STD* handles at startup. So any LoadLibrary request can potentially | 107 // Unofficial builds won't have 'UiAccess' since it requires signing. |
107 // be blocked. To prevent that from happening we close STDIN and STDOUT | 108 CHECK(CurrentProcessHasUiAccess()); |
Sergey Ulanov
2016/09/02 23:21:14
Do we actually need to crash the process in this c
joedow
2016/09/06 22:51:59
I chose to use a CHECK here as this functionality
| |
108 // handles as soon as we retrieve the corresponding file handles. | 109 #endif // defined(OFFICIAL_BUILD) |
109 SetStdHandle(STD_INPUT_HANDLE, nullptr); | 110 |
110 SetStdHandle(STD_OUTPUT_HANDLE, nullptr); | 111 // The UiAccess binary should always have the "input" and "output" switches |
112 // specified, they represent the name of the named pipes that should be used | |
113 // in place of stdin and stdout. | |
114 DCHECK(command_line->HasSwitch(kInputSwitchName)); | |
115 DCHECK(command_line->HasSwitch(kOutputSwitchName)); | |
116 | |
117 // presubmit: allow wstring | |
118 std::wstring input_pipe_name = | |
119 command_line->GetSwitchValueNative(kInputSwitchName); | |
120 // presubmit: allow wstring | |
121 std::wstring output_pipe_name = | |
122 command_line->GetSwitchValueNative(kOutputSwitchName); | |
123 | |
124 // A NULL SECURITY_ATTRIBUTES signifies that the handle can't be inherited. | |
125 read_file = | |
126 base::File(CreateFile(input_pipe_name.c_str(), GENERIC_READ, 0, nullptr, | |
127 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)); | |
128 if (!read_file.IsValid()) { | |
129 PLOG(ERROR) << "CreateFile failed on '" << input_pipe_name << "'"; | |
130 return kInitializationFailed; | |
131 } | |
132 | |
133 write_file = base::File(CreateFile(output_pipe_name.c_str(), GENERIC_WRITE, | |
134 0, nullptr, OPEN_EXISTING, | |
135 FILE_ATTRIBUTE_NORMAL, nullptr)); | |
136 if (!write_file.IsValid()) { | |
137 PLOG(ERROR) << "CreateFile failed on '" << output_pipe_name << "'"; | |
138 return kInitializationFailed; | |
139 } | |
140 } else { | |
141 needs_elevation = true; | |
142 | |
143 // GetStdHandle() returns pseudo-handles for stdin and stdout even if | |
144 // the hosting executable specifies "Windows" subsystem. However the | |
145 // returned handles are invalid in that case unless standard input and | |
146 // output are redirected to a pipe or file. | |
147 read_file = base::File(GetStdHandle(STD_INPUT_HANDLE)); | |
148 write_file = base::File(GetStdHandle(STD_OUTPUT_HANDLE)); | |
149 | |
150 // After the native messaging channel starts the native messaging reader | |
151 // will keep doing blocking read operations on the input named pipe. | |
152 // If any other thread tries to perform any operation on STDIN, it will also | |
153 // block because the input named pipe is synchronous (non-overlapped). | |
154 // It is pretty common for a DLL to query the device info (GetFileType) of | |
155 // the STD* handles at startup. So any LoadLibrary request can potentially | |
156 // be blocked. To prevent that from happening we close STDIN and STDOUT | |
157 // handles as soon as we retrieve the corresponding file handles. | |
158 SetStdHandle(STD_INPUT_HANDLE, nullptr); | |
159 SetStdHandle(STD_OUTPUT_HANDLE, nullptr); | |
160 } | |
111 #elif defined(OS_POSIX) | 161 #elif defined(OS_POSIX) |
112 // The files are automatically closed. | 162 // The files are automatically closed. |
113 base::File read_file(STDIN_FILENO); | 163 read_file = base::File(STDIN_FILENO); |
114 base::File write_file(STDOUT_FILENO); | 164 write_file = base::File(STDOUT_FILENO); |
115 #else | 165 #else |
116 #error Not implemented. | 166 #error Not implemented. |
117 #endif | 167 #endif |
118 | 168 |
119 base::MessageLoopForUI message_loop; | 169 base::MessageLoopForUI message_loop; |
120 base::RunLoop run_loop; | 170 base::RunLoop run_loop; |
121 | 171 |
122 std::unique_ptr<It2MeHostFactory> factory(new It2MeHostFactory()); | 172 std::unique_ptr<It2MeHostFactory> factory(new It2MeHostFactory()); |
123 | 173 |
124 std::unique_ptr<NativeMessagingPipe> native_messaging_pipe( | 174 std::unique_ptr<NativeMessagingPipe> native_messaging_pipe( |
125 new NativeMessagingPipe()); | 175 new NativeMessagingPipe()); |
126 | 176 |
127 // Set up the native messaging channel. | 177 // Set up the native messaging channel. |
128 std::unique_ptr<extensions::NativeMessagingChannel> channel( | 178 std::unique_ptr<extensions::NativeMessagingChannel> channel( |
129 new PipeMessagingChannel(std::move(read_file), std::move(write_file))); | 179 new PipeMessagingChannel(std::move(read_file), std::move(write_file))); |
130 | 180 |
131 std::unique_ptr<ChromotingHostContext> context = | 181 std::unique_ptr<ChromotingHostContext> context = |
132 ChromotingHostContext::Create(new remoting::AutoThreadTaskRunner( | 182 ChromotingHostContext::Create(new remoting::AutoThreadTaskRunner( |
133 message_loop.task_runner(), run_loop.QuitClosure())); | 183 message_loop.task_runner(), run_loop.QuitClosure())); |
134 std::unique_ptr<extensions::NativeMessageHost> host( | 184 std::unique_ptr<extensions::NativeMessageHost> host( |
135 new It2MeNativeMessagingHost(std::move(context), std::move(factory))); | 185 new It2MeNativeMessagingHost(needs_elevation, /*policy_service=*/nullptr, |
186 std::move(context), std::move(factory))); | |
136 | 187 |
137 host->Start(native_messaging_pipe.get()); | 188 host->Start(native_messaging_pipe.get()); |
138 | 189 |
139 native_messaging_pipe->Start(std::move(host), std::move(channel)); | 190 native_messaging_pipe->Start(std::move(host), std::move(channel)); |
140 | 191 |
141 // Run the loop until channel is alive. | 192 // Run the loop until channel is alive. |
142 run_loop.Run(); | 193 run_loop.Run(); |
143 | 194 |
144 return kSuccessExitCode; | 195 return kSuccessExitCode; |
145 } | 196 } |
146 | 197 |
147 int It2MeNativeMessagingHostMain(int argc, char** argv) { | 198 int It2MeNativeMessagingHostMain(int argc, char** argv) { |
148 // This object instance is required by Chrome code (such as MessageLoop). | 199 // This object instance is required by Chrome code (such as MessageLoop). |
149 base::AtExitManager exit_manager; | 200 base::AtExitManager exit_manager; |
150 | 201 |
151 base::CommandLine::Init(argc, argv); | 202 base::CommandLine::Init(argc, argv); |
152 remoting::InitHostLogging(); | 203 remoting::InitHostLogging(); |
153 | 204 |
154 return StartIt2MeNativeMessagingHost(); | 205 return StartIt2MeNativeMessagingHost(); |
155 } | 206 } |
156 | 207 |
157 } // namespace remoting | 208 } // namespace remoting |
OLD | NEW |