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

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

Issue 2152953002: Refactoring Native Messaging Host process launching code into its own file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: bugfix and cleanup Created 4 years, 4 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
OLDNEW
(Empty)
1 // Copyright 2016 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 #include "remoting/host/win/launch_native_messaging_host_process.h"
6
7 #include <windows.h>
8 #include <shellapi.h>
9
10 #include <cstdint>
11 #include <string>
12
13 #include "base/command_line.h"
14 #include "base/files/file_path.h"
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/win/win_util.h"
20 #include "ipc/ipc_channel.h"
21 #include "remoting/host/switches.h"
22 #include "remoting/host/win/security_descriptor.h"
23
24 namespace {
25
26 // Windows will use default buffer size when 0 is passed to CreateNamedPipeW().
27 const uint32_t kBufferSize = 0;
28 const int kTimeOutMilliseconds = 2000;
29 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome_remote_desktop.";
30
31 const uint32_t kProcessLaunched = 0;
32 const uint32_t kSecurityDescriptorCreationFailed = 1;
Sergey Ulanov 2016/07/28 23:57:15 This special error code is not mentioned in the he
joedow 2016/07/29 03:32:56 Done.
33
34 uint32_t CreateNamedPipe(const std::string& pipe_name,
35 const remoting::ScopedSd& security_descriptor,
36 uint32_t open_mode,
37 base::win::ScopedHandle* file_handle) {
38 DCHECK(file_handle);
39
40 SECURITY_ATTRIBUTES security_attributes = {0};
41 security_attributes.nLength = sizeof(security_attributes);
42 security_attributes.lpSecurityDescriptor = security_descriptor.get();
43 security_attributes.bInheritHandle = FALSE;
44
45 base::win::ScopedHandle temp_handle(::CreateNamedPipe(
46 base::ASCIIToUTF16(pipe_name).c_str(),
47 open_mode,
48 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS,
49 1,
50 kBufferSize,
51 kBufferSize,
52 kTimeOutMilliseconds,
53 &security_attributes));
54
55 if (!temp_handle.IsValid()) {
56 uint32_t error = GetLastError();
57 PLOG(ERROR) << "Failed to create named pipe '" << pipe_name << "'";
58 return error;
59 }
60
61 file_handle->Set(temp_handle.Take());
62 return 0;
63 }
64
65 } // namespace
66
67 namespace remoting {
68
69 uint32_t LaunchNativeMessagingHostProcess(
70 const base::FilePath& binary_path,
71 intptr_t parent_window_handle,
72 bool elevate_process,
73 base::win::ScopedHandle* read_handle,
74 base::win::ScopedHandle* write_handle) {
75 DCHECK(read_handle);
76 DCHECK(write_handle);
77
78 // presubmit: allow wstring
79 std::wstring user_sid;
80 if (!base::win::GetUserSidString(&user_sid)) {
81 LOG(ERROR) << "Failed to query the current user SID.";
82 return kSecurityDescriptorCreationFailed;
83 }
84
85 // Create a security descriptor that gives full access to the caller and
86 // BUILTIN_ADMINISTRATORS and denies access by anyone else.
87 // Local admins need access because the privileged host process will run
88 // as a local admin which may not be the same user as the current user.
89 std::string user_sid_ascii = base::UTF16ToASCII(user_sid);
90 std::string security_descriptor = base::StringPrintf(
91 "O:%sG:%sD:(A;;GA;;;%s)(A;;GA;;;BA)", user_sid_ascii.c_str(),
92 user_sid_ascii.c_str(), user_sid_ascii.c_str());
93
94 ScopedSd sd = ConvertSddlToSd(security_descriptor);
95 if (!sd) {
96 PLOG(ERROR) << "Failed to create a security descriptor.";
97 return kSecurityDescriptorCreationFailed;
98 }
99
100 uint32_t result;
101 std::string input_pipe_name(kChromePipeNamePrefix);
102 input_pipe_name.append(IPC::Channel::GenerateUniqueRandomChannelID());
103 base::win::ScopedHandle temp_write_handle;
104 result = CreateNamedPipe(input_pipe_name, sd, PIPE_ACCESS_OUTBOUND,
105 &temp_write_handle);
106 if (!temp_write_handle.IsValid()) {
107 return result;
108 }
109
110 std::string output_pipe_name(kChromePipeNamePrefix);
111 output_pipe_name.append(IPC::Channel::GenerateUniqueRandomChannelID());
112 base::win::ScopedHandle temp_read_handle;
113 result = CreateNamedPipe(output_pipe_name, sd, PIPE_ACCESS_INBOUND,
114 &temp_read_handle);
115 if (!temp_read_handle.IsValid()) {
116 return result;
117 }
118
119 const base::CommandLine* current_command_line =
120 base::CommandLine::ForCurrentProcess();
121 const base::CommandLine::SwitchMap& switches =
122 current_command_line->GetSwitches();
123 base::CommandLine::StringVector args = current_command_line->GetArgs();
124
125 // Create the child process command line by copying switches from the current
126 // command line.
127 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
128
129 if (elevate_process) {
130 DCHECK(!current_command_line->HasSwitch(kElevateSwitchName));
131 command_line.AppendSwitch(kElevateSwitchName);
132 }
133 command_line.AppendSwitchASCII(kInputSwitchName, input_pipe_name);
134 command_line.AppendSwitchASCII(kOutputSwitchName, output_pipe_name);
135
136 for (base::CommandLine::SwitchMap::const_iterator i = switches.begin();
137 i != switches.end(); ++i) {
138 command_line.AppendSwitchNative(i->first, i->second);
139 }
140 for (base::CommandLine::StringVector::const_iterator i = args.begin();
Sergey Ulanov 2016/07/28 23:57:15 for (const auto& arg : args) ...
joedow 2016/07/29 03:32:56 Good call.
141 i != args.end(); ++i) {
142 command_line.AppendArgNative(*i);
143 }
144
145 // Get the parameters for the binary to launch.
146 base::CommandLine::StringType params = command_line.GetCommandLineString();
147
148 // Launch the child process, requesting elevation if needed.
149 SHELLEXECUTEINFO info;
150 memset(&info, 0, sizeof(info));
151 info.cbSize = sizeof(info);
152 info.hwnd = reinterpret_cast<HWND>(parent_window_handle);
153 info.lpFile = binary_path.value().c_str();
154 info.lpParameters = params.c_str();
155 info.nShow = SW_HIDE;
156
157 if (elevate_process) {
158 info.lpVerb = L"runas";
159 }
160
161 if (!ShellExecuteEx(&info)) {
162 uint32_t error = GetLastError();
163 PLOG(ERROR) << "Unable to launch '" << binary_path.value() << "'";
164 return error;
165 }
166
167 if (!ConnectNamedPipe(temp_write_handle.Get(), nullptr)) {
168 uint32_t error = GetLastError();
169 if (error != ERROR_PIPE_CONNECTED) {
170 PLOG(ERROR) << "Unable to connect '" << output_pipe_name << "'";
171 return error;
172 }
173 }
174
175 if (!ConnectNamedPipe(temp_read_handle.Get(), nullptr)) {
176 uint32_t error = GetLastError();
177 if (error != ERROR_PIPE_CONNECTED) {
178 PLOG(ERROR) << "Unable to connect '" << input_pipe_name << "'";
179 return error;
180 }
181 }
182
183 read_handle->Set(temp_read_handle.Take());
184 write_handle->Set(temp_write_handle.Take());
185 return kProcessLaunched;
186 }
187
188 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698