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

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: 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
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_service_messages.h"
21 #include "remoting/host/sas_sender_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 kChromotingServiceChannelName[] = "chromoting_service";
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_service_.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_service_.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 security attributes pointer to
197 // CreateNamedPipe() so the pipe gets a 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.
Wez 2012/03/07 01:56:13 nit: Clarify why read access is not an issue?
alexeypa (please no reviews) 2012/03/07 19:59:08 See PIPE_ACCESS_DUPLEX below
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.
Wez 2012/03/07 01:56:13 nit: How is this comment relevant to "the result",
alexeypa (please no reviews) 2012/03/07 19:59:08 Yes. I rephrased the comment to articulate it bett
206 //
207 // In our case the result is that only processes running under
208 // LocalSystem account will be able to connect to this channel.
209 chromoting_service_.reset(new IPC::ChannelProxy(
210 kChromotingServiceChannelName,
211 IPC::Channel::MODE_SERVER,
212 this,
213 io_thread_->message_loop_proxy().get()));
179 214
180 // Try to launch the process and attach an object watcher to the returned 215 // Try to launch the process and attach an object watcher to the returned
181 // handle so that we get notified when the process terminates. 216 // handle so that we get notified when the process terminates.
182 launch_time_ = base::Time::Now();
183 if (LaunchProcessAsUser(host_binary_, session_token_, &process_)) { 217 if (LaunchProcessAsUser(host_binary_, session_token_, &process_)) {
184 if (process_watcher_.StartWatching(process_.handle(), this)) { 218 if (process_watcher_.StartWatching(process_.handle(), this)) {
185 state_ = StateAttached; 219 state_ = StateAttached;
186 return; 220 return;
187 } else { 221 } else {
188 LOG(ERROR) << "Failed to arm the process watcher."; 222 LOG(ERROR) << "Failed to arm the process watcher.";
189 process_.Terminate(0); 223 process_.Terminate(0);
190 process_.Close(); 224 process_.Close();
225 chromoting_service_.reset();
191 } 226 }
192 } 227 }
193 228
194 // Something went wrong. Try to launch the host again later. The attempts rate 229 // Something went wrong. Try to launch the host again later. The attempts rate
195 // is limited by exponential backoff. 230 // is limited by exponential backoff.
196 launch_backoff_ = std::max(launch_backoff_ * 2, 231 launch_backoff_ = std::max(launch_backoff_ * 2,
197 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 232 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
198 launch_backoff_ = std::min(launch_backoff_, 233 launch_backoff_ = std::min(launch_backoff_,
199 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); 234 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
200 timer_.Start(FROM_HERE, launch_backoff_, 235 timer_.Start(FROM_HERE, launch_backoff_,
201 this, &WtsSessionProcessLauncher::LaunchProcess); 236 this, &WtsSessionProcessLauncher::LaunchProcess);
202 } 237 }
203 238
204 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) { 239 void WtsSessionProcessLauncher::OnObjectSignaled(HANDLE object) {
205 DCHECK(state_ == StateAttached); 240 DCHECK(state_ == StateAttached);
206 DCHECK(!timer_.IsRunning()); 241 DCHECK(!timer_.IsRunning());
207 DCHECK(process_.handle() != NULL); 242 DCHECK(process_.handle() != NULL);
208 DCHECK(process_watcher_.GetWatchedObject() == NULL); 243 DCHECK(process_watcher_.GetWatchedObject() == NULL);
244 DCHECK(chromoting_service_.get() != NULL);
209 245
210 // The host process has been terminated for some reason. The handle can now be 246 // The host process has been terminated for some reason. The handle can now be
211 // closed. 247 // closed.
212 process_.Close(); 248 process_.Close();
249 chromoting_service_.reset();
213 250
214 // Expand the backoff interval if the process has died quickly or reset it if 251 // Expand the backoff interval if the process has died quickly or reset it if
215 // it was up longer than the maximum backoff delay. 252 // it was up longer than the maximum backoff delay.
216 base::TimeDelta delta = base::Time::Now() - launch_time_; 253 base::TimeDelta delta = base::Time::Now() - launch_time_;
217 if (delta < base::TimeDelta() || 254 if (delta < base::TimeDelta() ||
218 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) { 255 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) {
219 launch_backoff_ = base::TimeDelta(); 256 launch_backoff_ = base::TimeDelta();
220 } else { 257 } else {
221 launch_backoff_ = std::max(launch_backoff_ * 2, 258 launch_backoff_ = std::max(launch_backoff_ * 2,
222 TimeDelta::FromSeconds(kMinLaunchDelaySeconds)); 259 TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
223 launch_backoff_ = std::min(launch_backoff_, 260 launch_backoff_ = std::min(launch_backoff_,
224 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); 261 TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
225 } 262 }
226 263
227 // Try to restart the host. 264 // Try to restart the host.
228 state_ = StateStarting; 265 state_ = StateStarting;
229 timer_.Start(FROM_HERE, launch_backoff_, 266 timer_.Start(FROM_HERE, launch_backoff_,
230 this, &WtsSessionProcessLauncher::LaunchProcess); 267 this, &WtsSessionProcessLauncher::LaunchProcess);
231 } 268 }
232 269
270 bool WtsSessionProcessLauncher::OnMessageReceived(const IPC::Message& message) {
271 bool handled = true;
272 IPC_BEGIN_MESSAGE_MAP(WtsSessionProcessLauncher, message)
273 IPC_MESSAGE_HANDLER(ChromotingServiceMsg_SendSas, OnSendSas)
274 IPC_MESSAGE_UNHANDLED(handled = false)
275 IPC_END_MESSAGE_MAP()
276 return handled;
277 }
278
279 void WtsSessionProcessLauncher::OnSendSas() {
280 if (state_ == StateAttached) {
281 if (sas_sender_.get() == NULL) {
282 sas_sender_ = SasSender::Create();
283 }
284
285 if (sas_sender_.get() != NULL) {
286 sas_sender_->Send();
287 }
288 }
289 }
290
233 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) { 291 void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) {
234 DCHECK(state_ == StateDetached); 292 DCHECK(state_ == StateDetached);
235 DCHECK(!timer_.IsRunning()); 293 DCHECK(!timer_.IsRunning());
236 DCHECK(process_.handle() == NULL); 294 DCHECK(process_.handle() == NULL);
237 DCHECK(process_watcher_.GetWatchedObject() == NULL); 295 DCHECK(process_watcher_.GetWatchedObject() == NULL);
296 DCHECK(chromoting_service_.get() == NULL);
238 297
239 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is 298 // Temporarily enable the SE_TCB_NAME privilege. The privileged token is
240 // created as needed and kept for later reuse. 299 // created as needed and kept for later reuse.
241 if (privileged_token_.Get() == NULL) { 300 if (privileged_token_.Get() == NULL) {
242 if (!CreatePrivilegedToken(&privileged_token_)) { 301 if (!CreatePrivilegedToken(&privileged_token_)) {
243 return; 302 return;
244 } 303 }
245 } 304 }
246 305
247 if (!ImpersonateLoggedOnUser(privileged_token_)) { 306 if (!ImpersonateLoggedOnUser(privileged_token_)) {
248 LOG_GETLASTERROR(ERROR) << 307 LOG_GETLASTERROR(ERROR) <<
249 "Failed to impersonate the privileged token"; 308 "Failed to impersonate the privileged token";
250 return; 309 return;
251 } 310 }
252 311
253 // While the SE_TCB_NAME progolege is enabled, create a session token for 312 // While the SE_TCB_NAME privilege is enabled, create a session token for
254 // the launched process. 313 // the launched process.
255 bool result = CreateSessionToken(session_id, &session_token_); 314 bool result = CreateSessionToken(session_id, &session_token_);
256 315
257 // Revert to the default token. The default token is sufficient to call 316 // Revert to the default token. The default token is sufficient to call
258 // CreateProcessAsUser() successfully. 317 // CreateProcessAsUser() successfully.
259 CHECK(RevertToSelf()); 318 CHECK(RevertToSelf());
260 319
261 if (!result) 320 if (!result)
262 return; 321 return;
263 322
264 // Now try to launch the host. 323 // Now try to launch the host.
265 state_ = StateStarting; 324 state_ = StateStarting;
266 LaunchProcess(); 325 LaunchProcess();
267 } 326 }
268 327
269 void WtsSessionProcessLauncher::OnSessionDetached() { 328 void WtsSessionProcessLauncher::OnSessionDetached() {
270 DCHECK(state_ == StateDetached || 329 DCHECK(state_ == StateDetached ||
271 state_ == StateStarting || 330 state_ == StateStarting ||
272 state_ == StateAttached); 331 state_ == StateAttached);
273 332
274 switch (state_) { 333 switch (state_) {
275 case StateDetached: 334 case StateDetached:
276 DCHECK(!timer_.IsRunning()); 335 DCHECK(!timer_.IsRunning());
277 DCHECK(process_.handle() == NULL); 336 DCHECK(process_.handle() == NULL);
278 DCHECK(process_watcher_.GetWatchedObject() == NULL); 337 DCHECK(process_watcher_.GetWatchedObject() == NULL);
338 DCHECK(chromoting_service_.get() == NULL);
279 break; 339 break;
280 340
281 case StateStarting: 341 case StateStarting:
282 DCHECK(timer_.IsRunning()); 342 DCHECK(timer_.IsRunning());
283 DCHECK(process_.handle() == NULL); 343 DCHECK(process_.handle() == NULL);
284 DCHECK(process_watcher_.GetWatchedObject() == NULL); 344 DCHECK(process_watcher_.GetWatchedObject() == NULL);
345 DCHECK(chromoting_service_.get() == NULL);
285 346
286 timer_.Stop(); 347 timer_.Stop();
287 launch_backoff_ = base::TimeDelta(); 348 launch_backoff_ = base::TimeDelta();
288 state_ = StateDetached; 349 state_ = StateDetached;
289 break; 350 break;
290 351
291 case StateAttached: 352 case StateAttached:
292 DCHECK(!timer_.IsRunning()); 353 DCHECK(!timer_.IsRunning());
293 DCHECK(process_.handle() != NULL); 354 DCHECK(process_.handle() != NULL);
294 DCHECK(process_watcher_.GetWatchedObject() != NULL); 355 DCHECK(process_watcher_.GetWatchedObject() != NULL);
356 DCHECK(chromoting_service_.get() != NULL);
295 357
296 process_watcher_.StopWatching(); 358 process_watcher_.StopWatching();
297 process_.Terminate(0); 359 process_.Terminate(0);
298 process_.Close(); 360 process_.Close();
361 chromoting_service_.reset();
299 state_ = StateDetached; 362 state_ = StateDetached;
300 break; 363 break;
301 } 364 }
302 } 365 }
303 366
304 } // namespace remoting 367 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698