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