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