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 IPC {
25
26Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) {
27  memset(&context.overlapped, 0, sizeof(context.overlapped));
28  context.handler = channel;
29}
30
31Channel::ChannelImpl::State::~State() {
32  COMPILE_ASSERT(!offsetof(Channel::ChannelImpl::State, context),
33                 starts_with_io_context);
34}
35
36Channel::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
51Channel::ChannelImpl::~ChannelImpl() {
52  Close();
53}
54
55void 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
83bool 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
107bool 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
116Channel::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
148bool 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
155void 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
180bool Channel::ChannelImpl::DidEmptyInputBuffers() {
181  // We don't need to do anything here.
182  return true;
183}
184
185// static
186const 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
204bool 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
289bool 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
322bool 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
359bool 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
416void 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.
467Channel::Channel(const IPC::ChannelHandle &channel_handle, Mode mode,
468                 Listener* listener)
469    : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) {
470}
471
472Channel::~Channel() {
473  delete channel_impl_;
474}
475
476bool Channel::Connect() {
477  return channel_impl_->Connect();
478}
479
480void Channel::Close() {
481  if (channel_impl_)
482    channel_impl_->Close();
483}
484
485base::ProcessId Channel::peer_pid() const {
486  return channel_impl_->peer_pid();
487}
488
489bool Channel::Send(Message* message) {
490  return channel_impl_->Send(message);
491}
492
493// static
494bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
495  return ChannelImpl::IsNamedServerInitialized(channel_id);
496}
497
498// static
499std::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