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