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