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#include "ipc/ipc_channel_win.h" 6 7#include <windows.h> 8 9#include "base/auto_reset.h" 10#include "base/bind.h" 11#include "base/compiler_specific.h" 12#include "base/logging.h" 13#include "base/pickle.h" 14#include "base/process/process_handle.h" 15#include "base/rand_util.h" 16#include "base/strings/string_number_conversions.h" 17#include "base/strings/utf_string_conversions.h" 18#include "base/threading/thread_checker.h" 19#include "base/win/scoped_handle.h" 20#include "ipc/ipc_listener.h" 21#include "ipc/ipc_logging.h" 22#include "ipc/ipc_message_utils.h" 23 24namespace { 25 26enum DebugFlags { 27 INIT_DONE = 1 << 0, 28 CALLED_CONNECT = 1 << 1, 29 PENDING_CONNECT = 1 << 2, 30 CONNECT_COMPLETED = 1 << 3, 31 PIPE_CONNECTED = 1 << 4, 32 WRITE_MSG = 1 << 5, 33 READ_MSG = 1 << 6, 34 WRITE_COMPLETED = 1 << 7, 35 READ_COMPLETED = 1 << 8, 36 CLOSED = 1 << 9, 37 WAIT_FOR_READ = 1 << 10, 38 WAIT_FOR_WRITE = 1 << 11, 39 WAIT_FOR_READ_COMPLETE = 1 << 12, 40 WAIT_FOR_WRITE_COMPLETE = 1 << 13 41}; 42 43} // namespace 44 45namespace IPC { 46 47ChannelWin::State::State(ChannelWin* channel) : is_pending(false) { 48 memset(&context.overlapped, 0, sizeof(context.overlapped)); 49 context.handler = channel; 50} 51 52ChannelWin::State::~State() { 53 COMPILE_ASSERT(!offsetof(ChannelWin::State, context), 54 starts_with_io_context); 55} 56 57ChannelWin::ChannelWin(const IPC::ChannelHandle &channel_handle, 58 Mode mode, Listener* listener) 59 : ChannelReader(listener), 60 input_state_(this), 61 output_state_(this), 62 peer_pid_(base::kNullProcessId), 63 waiting_connect_(mode & MODE_SERVER_FLAG), 64 processing_incoming_(false), 65 validate_client_(false), 66 writing_(false), 67 debug_flags_(0), 68 write_error_(0), 69 last_write_error_(0), 70 write_size_(0), 71 client_secret_(0), 72 weak_factory_(this) { 73 CreatePipe(channel_handle, mode); 74} 75 76ChannelWin::~ChannelWin() { 77 Close(); 78} 79 80void ChannelWin::Close() { 81 if (thread_check_.get()) { 82 DCHECK(thread_check_->CalledOnValidThread()); 83 } 84 debug_flags_ |= CLOSED; 85 86 if (input_state_.is_pending || output_state_.is_pending) 87 CancelIo(pipe_.Get()); 88 89 // Closing the handle at this point prevents us from issuing more requests 90 // form OnIOCompleted(). 91 if (pipe_.IsValid()) 92 pipe_.Close(); 93 94 if (input_state_.is_pending) 95 debug_flags_ |= WAIT_FOR_READ; 96 97 if (output_state_.is_pending) 98 debug_flags_ |= WAIT_FOR_WRITE; 99 100 // Make sure all IO has completed. 101 base::Time start = base::Time::Now(); 102 while (input_state_.is_pending || output_state_.is_pending) { 103 base::MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); 104 } 105 106 while (!output_queue_.empty()) { 107 Message* m = output_queue_.front(); 108 output_queue_.pop(); 109 delete m; 110 } 111} 112 113bool ChannelWin::Send(Message* message) { 114 DCHECK(thread_check_->CalledOnValidThread()); 115 DVLOG(2) << "sending message @" << message << " on channel @" << this 116 << " with type " << message->type() 117 << " (" << output_queue_.size() << " in queue)"; 118 119#ifdef IPC_MESSAGE_LOG_ENABLED 120 Logging::GetInstance()->OnSendMessage(message, ""); 121#endif 122 123 message->TraceMessageBegin(); 124 output_queue_.push(message); 125 // ensure waiting to write 126 if (!waiting_connect_) { 127 if (!output_state_.is_pending) { 128 if (!ProcessOutgoingMessages(NULL, 0)) 129 return false; 130 } 131 } 132 133 return true; 134} 135 136base::ProcessId ChannelWin::GetPeerPID() const { 137 return peer_pid_; 138} 139 140base::ProcessId ChannelWin::GetSelfPID() const { 141 return GetCurrentProcessId(); 142} 143 144// static 145bool ChannelWin::IsNamedServerInitialized( 146 const std::string& channel_id) { 147 if (WaitNamedPipe(PipeName(channel_id, NULL).c_str(), 1)) 148 return true; 149 // If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another 150 // connection. 151 return GetLastError() == ERROR_SEM_TIMEOUT; 152} 153 154ChannelWin::ReadState ChannelWin::ReadData( 155 char* buffer, 156 int buffer_len, 157 int* /* bytes_read */) { 158 if (!pipe_.IsValid()) 159 return READ_FAILED; 160 161 debug_flags_ |= READ_MSG; 162 DWORD bytes_read = 0; 163 BOOL ok = ReadFile(pipe_.Get(), buffer, buffer_len, 164 &bytes_read, &input_state_.context.overlapped); 165 if (!ok) { 166 DWORD err = GetLastError(); 167 if (err == ERROR_IO_PENDING) { 168 input_state_.is_pending = true; 169 return READ_PENDING; 170 } 171 LOG(ERROR) << "pipe error: " << err; 172 return READ_FAILED; 173 } 174 175 // We could return READ_SUCCEEDED here. But the way that this code is 176 // structured we instead go back to the message loop. Our completion port 177 // will be signalled even in the "synchronously completed" state. 178 // 179 // This allows us to potentially process some outgoing messages and 180 // interleave other work on this thread when we're getting hammered with 181 // input messages. Potentially, this could be tuned to be more efficient 182 // with some testing. 183 input_state_.is_pending = true; 184 return READ_PENDING; 185} 186 187bool ChannelWin::WillDispatchInputMessage(Message* msg) { 188 // Make sure we get a hello when client validation is required. 189 if (validate_client_) 190 return IsHelloMessage(*msg); 191 return true; 192} 193 194void ChannelWin::HandleInternalMessage(const Message& msg) { 195 DCHECK_EQ(msg.type(), static_cast<unsigned>(Channel::HELLO_MESSAGE_TYPE)); 196 // The hello message contains one parameter containing the PID. 197 PickleIterator it(msg); 198 int32 claimed_pid; 199 bool failed = !it.ReadInt(&claimed_pid); 200 201 if (!failed && validate_client_) { 202 int32 secret; 203 failed = it.ReadInt(&secret) ? (secret != client_secret_) : true; 204 } 205 206 if (failed) { 207 NOTREACHED(); 208 Close(); 209 listener()->OnChannelError(); 210 return; 211 } 212 213 peer_pid_ = claimed_pid; 214 // Validation completed. 215 validate_client_ = false; 216 listener()->OnChannelConnected(claimed_pid); 217} 218 219bool ChannelWin::DidEmptyInputBuffers() { 220 // We don't need to do anything here. 221 return true; 222} 223 224// static 225const base::string16 ChannelWin::PipeName( 226 const std::string& channel_id, int32* secret) { 227 std::string name("\\\\.\\pipe\\chrome."); 228 229 // Prevent the shared secret from ending up in the pipe name. 230 size_t index = channel_id.find_first_of('\\'); 231 if (index != std::string::npos) { 232 if (secret) // Retrieve the secret if asked for. 233 base::StringToInt(channel_id.substr(index + 1), secret); 234 return base::ASCIIToWide(name.append(channel_id.substr(0, index - 1))); 235 } 236 237 // This case is here to support predictable named pipes in tests. 238 if (secret) 239 *secret = 0; 240 return base::ASCIIToWide(name.append(channel_id)); 241} 242 243bool ChannelWin::CreatePipe(const IPC::ChannelHandle &channel_handle, 244 Mode mode) { 245 DCHECK(!pipe_.IsValid()); 246 base::string16 pipe_name; 247 // If we already have a valid pipe for channel just copy it. 248 if (channel_handle.pipe.handle) { 249 // TODO(rvargas) crbug.com/415294: ChannelHandle should either go away in 250 // favor of two independent entities (name/file), or it should be a move- 251 // only type with a base::File member. In any case, this code should not 252 // call DuplicateHandle. 253 DCHECK(channel_handle.name.empty()); 254 pipe_name = L"Not Available"; // Just used for LOG 255 // Check that the given pipe confirms to the specified mode. We can 256 // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the 257 // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0. 258 DWORD flags = 0; 259 GetNamedPipeInfo(channel_handle.pipe.handle, &flags, NULL, NULL, NULL); 260 DCHECK(!(flags & PIPE_TYPE_MESSAGE)); 261 if (((mode & MODE_SERVER_FLAG) && !(flags & PIPE_SERVER_END)) || 262 ((mode & MODE_CLIENT_FLAG) && (flags & PIPE_SERVER_END))) { 263 LOG(WARNING) << "Inconsistent open mode. Mode :" << mode; 264 return false; 265 } 266 HANDLE local_handle; 267 if (!DuplicateHandle(GetCurrentProcess(), 268 channel_handle.pipe.handle, 269 GetCurrentProcess(), 270 &local_handle, 271 0, 272 FALSE, 273 DUPLICATE_SAME_ACCESS)) { 274 LOG(WARNING) << "DuplicateHandle failed. Error :" << GetLastError(); 275 return false; 276 } 277 pipe_.Set(local_handle); 278 } else if (mode & MODE_SERVER_FLAG) { 279 DCHECK(!channel_handle.pipe.handle); 280 const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | 281 FILE_FLAG_FIRST_PIPE_INSTANCE; 282 pipe_name = PipeName(channel_handle.name, &client_secret_); 283 validate_client_ = !!client_secret_; 284 pipe_.Set(CreateNamedPipeW(pipe_name.c_str(), 285 open_mode, 286 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 287 1, 288 Channel::kReadBufferSize, 289 Channel::kReadBufferSize, 290 5000, 291 NULL)); 292 } else if (mode & MODE_CLIENT_FLAG) { 293 DCHECK(!channel_handle.pipe.handle); 294 pipe_name = PipeName(channel_handle.name, &client_secret_); 295 pipe_.Set(CreateFileW(pipe_name.c_str(), 296 GENERIC_READ | GENERIC_WRITE, 297 0, 298 NULL, 299 OPEN_EXISTING, 300 SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | 301 FILE_FLAG_OVERLAPPED, 302 NULL)); 303 } else { 304 NOTREACHED(); 305 } 306 307 if (!pipe_.IsValid()) { 308 // If this process is being closed, the pipe may be gone already. 309 PLOG(WARNING) << "Unable to create pipe \"" << pipe_name << "\" in " 310 << (mode & MODE_SERVER_FLAG ? "server" : "client") << " mode"; 311 return false; 312 } 313 314 // Create the Hello message to be sent when Connect is called 315 scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE, 316 HELLO_MESSAGE_TYPE, 317 IPC::Message::PRIORITY_NORMAL)); 318 319 // Don't send the secret to the untrusted process, and don't send a secret 320 // if the value is zero (for IPC backwards compatability). 321 int32 secret = validate_client_ ? 0 : client_secret_; 322 if (!m->WriteInt(GetCurrentProcessId()) || 323 (secret && !m->WriteUInt32(secret))) { 324 pipe_.Close(); 325 return false; 326 } 327 328 debug_flags_ |= INIT_DONE; 329 330 output_queue_.push(m.release()); 331 return true; 332} 333 334bool ChannelWin::Connect() { 335 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; 336 337 if (!thread_check_.get()) 338 thread_check_.reset(new base::ThreadChecker()); 339 340 if (!pipe_.IsValid()) 341 return false; 342 343 base::MessageLoopForIO::current()->RegisterIOHandler(pipe_.Get(), this); 344 345 // Check to see if there is a client connected to our pipe... 346 if (waiting_connect_) 347 ProcessConnection(); 348 349 if (!input_state_.is_pending) { 350 // Complete setup asynchronously. By not setting input_state_.is_pending 351 // to true, we indicate to OnIOCompleted that this is the special 352 // initialization signal. 353 base::MessageLoopForIO::current()->PostTask( 354 FROM_HERE, 355 base::Bind(&ChannelWin::OnIOCompleted, 356 weak_factory_.GetWeakPtr(), 357 &input_state_.context, 358 0, 359 0)); 360 } 361 362 if (!waiting_connect_) 363 ProcessOutgoingMessages(NULL, 0); 364 return true; 365} 366 367bool ChannelWin::ProcessConnection() { 368 DCHECK(thread_check_->CalledOnValidThread()); 369 if (input_state_.is_pending) 370 input_state_.is_pending = false; 371 372 // Do we have a client connected to our pipe? 373 if (!pipe_.IsValid()) 374 return false; 375 376 BOOL ok = ConnectNamedPipe(pipe_.Get(), &input_state_.context.overlapped); 377 debug_flags_ |= CALLED_CONNECT; 378 379 DWORD err = GetLastError(); 380 if (ok) { 381 // Uhm, the API documentation says that this function should never 382 // return success when used in overlapped mode. 383 NOTREACHED(); 384 return false; 385 } 386 387 switch (err) { 388 case ERROR_IO_PENDING: 389 input_state_.is_pending = true; 390 debug_flags_ |= PENDING_CONNECT; 391 break; 392 case ERROR_PIPE_CONNECTED: 393 debug_flags_ |= PIPE_CONNECTED; 394 waiting_connect_ = false; 395 break; 396 case ERROR_NO_DATA: 397 // The pipe is being closed. 398 return false; 399 default: 400 NOTREACHED(); 401 return false; 402 } 403 404 return true; 405} 406 407bool ChannelWin::ProcessOutgoingMessages( 408 base::MessageLoopForIO::IOContext* context, 409 DWORD bytes_written) { 410 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 411 // no connection? 412 DCHECK(thread_check_->CalledOnValidThread()); 413 414 if (output_state_.is_pending) { 415 DCHECK(context); 416 output_state_.is_pending = false; 417 if (!context || bytes_written == 0) { 418 DWORD err = GetLastError(); 419 LOG(ERROR) << "pipe error: " << err; 420 return false; 421 } 422 // Message was sent. 423 CHECK(!output_queue_.empty()); 424 Message* m = output_queue_.front(); 425 output_queue_.pop(); 426 delete m; 427 } 428 429 if (output_queue_.empty()) 430 return true; 431 432 if (!pipe_.IsValid()) 433 return false; 434 435 // Write to pipe... 436 Message* m = output_queue_.front(); 437 DCHECK(m->size() <= INT_MAX); 438 debug_flags_ |= WRITE_MSG; 439 CHECK(!writing_); 440 writing_ = true; 441 write_size_ = static_cast<uint32>(m->size()); 442 write_error_ = 0; 443 BOOL ok = WriteFile(pipe_.Get(), 444 m->data(), 445 write_size_, 446 NULL, 447 &output_state_.context.overlapped); 448 if (!ok) { 449 write_error_ = GetLastError(); 450 if (write_error_ == ERROR_IO_PENDING) { 451 output_state_.is_pending = true; 452 453 DVLOG(2) << "sent pending message @" << m << " on channel @" << this 454 << " with type " << m->type(); 455 456 return true; 457 } 458 writing_ = false; 459 last_write_error_ = write_error_; 460 LOG(ERROR) << "pipe error: " << write_error_; 461 return false; 462 } 463 464 DVLOG(2) << "sent message @" << m << " on channel @" << this 465 << " with type " << m->type(); 466 467 output_state_.is_pending = true; 468 return true; 469} 470 471void ChannelWin::OnIOCompleted( 472 base::MessageLoopForIO::IOContext* context, 473 DWORD bytes_transfered, 474 DWORD error) { 475 bool ok = true; 476 DCHECK(thread_check_->CalledOnValidThread()); 477 if (context == &input_state_.context) { 478 if (waiting_connect_) { 479 debug_flags_ |= CONNECT_COMPLETED; 480 if (!ProcessConnection()) 481 return; 482 // We may have some messages queued up to send... 483 if (!output_queue_.empty() && !output_state_.is_pending) 484 ProcessOutgoingMessages(NULL, 0); 485 if (input_state_.is_pending) 486 return; 487 // else, fall-through and look for incoming messages... 488 } 489 490 // We don't support recursion through OnMessageReceived yet! 491 DCHECK(!processing_incoming_); 492 base::AutoReset<bool> auto_reset_processing_incoming( 493 &processing_incoming_, true); 494 495 // Process the new data. 496 if (input_state_.is_pending) { 497 // This is the normal case for everything except the initialization step. 498 debug_flags_ |= READ_COMPLETED; 499 if (debug_flags_ & WAIT_FOR_READ) { 500 CHECK(!(debug_flags_ & WAIT_FOR_READ_COMPLETE)); 501 debug_flags_ |= WAIT_FOR_READ_COMPLETE; 502 } 503 input_state_.is_pending = false; 504 if (!bytes_transfered) 505 ok = false; 506 else if (pipe_.IsValid()) 507 ok = AsyncReadComplete(bytes_transfered); 508 } else { 509 DCHECK(!bytes_transfered); 510 } 511 512 // Request more data. 513 if (ok) 514 ok = ProcessIncomingMessages(); 515 } else { 516 DCHECK(context == &output_state_.context); 517 CHECK(writing_); 518 CHECK(output_state_.is_pending); 519 writing_ = false; 520 debug_flags_ |= WRITE_COMPLETED; 521 if (debug_flags_ & WAIT_FOR_WRITE) { 522 CHECK(!(debug_flags_ & WAIT_FOR_WRITE_COMPLETE)); 523 debug_flags_ |= WAIT_FOR_WRITE_COMPLETE; 524 } 525 ok = ProcessOutgoingMessages(context, bytes_transfered); 526 } 527 if (!ok && pipe_.IsValid()) { 528 // We don't want to re-enter Close(). 529 Close(); 530 listener()->OnChannelError(); 531 } 532} 533 534//------------------------------------------------------------------------------ 535// Channel's methods 536 537// static 538scoped_ptr<Channel> Channel::Create( 539 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) { 540 return scoped_ptr<Channel>( 541 new ChannelWin(channel_handle, mode, listener)); 542} 543 544// static 545bool Channel::IsNamedServerInitialized(const std::string& channel_id) { 546 return ChannelWin::IsNamedServerInitialized(channel_id); 547} 548 549// static 550std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) { 551 // Windows pipes can be enumerated by low-privileged processes. So, we 552 // append a strong random value after the \ character. This value is not 553 // included in the pipe name, but sent as part of the client hello, to 554 // hijacking the pipe name to spoof the client. 555 556 std::string id = prefix; 557 if (!id.empty()) 558 id.append("."); 559 560 int secret; 561 do { // Guarantee we get a non-zero value. 562 secret = base::RandInt(0, std::numeric_limits<int>::max()); 563 } while (secret == 0); 564 565 id.append(GenerateUniqueRandomChannelID()); 566 return id.append(base::StringPrintf("\\%d", secret)); 567} 568 569} // namespace IPC 570