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