Home | History | Annotate | Download | only in host
      1 // Copyright 2013 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 "remoting/host/ipc_util.h"
      6 
      7 #include "base/files/file.h"
      8 #include "base/logging.h"
      9 #include "base/single_thread_task_runner.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/win/scoped_handle.h"
     13 #include "base/win/win_util.h"
     14 #include "ipc/ipc_channel.h"
     15 #include "ipc/ipc_channel_proxy.h"
     16 #include "remoting/host/win/security_descriptor.h"
     17 
     18 using base::win::ScopedHandle;
     19 
     20 namespace remoting {
     21 
     22 // Pipe name prefix used by Chrome IPC channels to convert a channel name into
     23 // a pipe name.
     24 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome.";
     25 
     26 bool CreateConnectedIpcChannel(
     27     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     28     IPC::Listener* listener,
     29     base::File* client_out,
     30     scoped_ptr<IPC::ChannelProxy>* server_out) {
     31   // presubmit: allow wstring
     32   std::wstring user_sid;
     33   if (!base::win::GetUserSidString(&user_sid)) {
     34     LOG(ERROR) << "Failed to query the current user SID.";
     35     return false;
     36   }
     37 
     38   // Create a security descriptor that will be used to protect the named pipe in
     39   // between CreateNamedPipe() and CreateFile() calls before it will be passed
     40   // to the network process. It gives full access to the account that
     41   // the calling code is running under and  denies access by anyone else.
     42   std::string security_descriptor = base::StringPrintf(
     43       "O:%1$sG:%1$sD:(A;;GA;;;%1$s)", base::WideToUTF8(user_sid).c_str());
     44 
     45   // Generate a unique name for the channel.
     46   std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID();
     47 
     48   // Create the server end of the channel.
     49   ScopedHandle pipe;
     50   if (!CreateIpcChannel(channel_name, security_descriptor, &pipe)) {
     51     return false;
     52   }
     53 
     54   // Wrap the pipe into an IPC channel.
     55   scoped_ptr<IPC::ChannelProxy> server =
     56       IPC::ChannelProxy::Create(IPC::ChannelHandle(pipe),
     57                                 IPC::Channel::MODE_SERVER,
     58                                 listener,
     59                                 io_task_runner);
     60 
     61   // Convert the channel name to the pipe name.
     62   std::string pipe_name(kChromePipeNamePrefix);
     63   pipe_name.append(channel_name);
     64 
     65   SECURITY_ATTRIBUTES security_attributes = {0};
     66   security_attributes.nLength = sizeof(security_attributes);
     67   security_attributes.lpSecurityDescriptor = NULL;
     68   security_attributes.bInheritHandle = TRUE;
     69 
     70   // Create the client end of the channel. This code should match the code in
     71   // IPC::Channel.
     72   base::File client(CreateFile(base::UTF8ToUTF16(pipe_name).c_str(),
     73                                GENERIC_READ | GENERIC_WRITE,
     74                                0,
     75                                &security_attributes,
     76                                OPEN_EXISTING,
     77                                SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
     78                                    FILE_FLAG_OVERLAPPED,
     79                                NULL));
     80   if (!client.IsValid()) {
     81     PLOG(ERROR) << "Failed to connect to '" << pipe_name << "'";
     82     return false;
     83   }
     84 
     85   *client_out = client.Pass();
     86   *server_out = server.Pass();
     87   return true;
     88 }
     89 
     90 bool CreateIpcChannel(
     91     const std::string& channel_name,
     92     const std::string& pipe_security_descriptor,
     93     base::win::ScopedHandle* pipe_out) {
     94   // Create security descriptor for the channel.
     95   ScopedSd sd = ConvertSddlToSd(pipe_security_descriptor);
     96   if (!sd) {
     97     PLOG(ERROR) << "Failed to create a security descriptor for the Chromoting "
     98                    "IPC channel";
     99     return false;
    100   }
    101 
    102   SECURITY_ATTRIBUTES security_attributes = {0};
    103   security_attributes.nLength = sizeof(security_attributes);
    104   security_attributes.lpSecurityDescriptor = sd.get();
    105   security_attributes.bInheritHandle = FALSE;
    106 
    107   // Convert the channel name to the pipe name.
    108   std::string pipe_name(kChromePipeNamePrefix);
    109   pipe_name.append(channel_name);
    110 
    111   // Create the server end of the pipe. This code should match the code in
    112   // IPC::Channel with exception of passing a non-default security descriptor.
    113   base::win::ScopedHandle pipe;
    114   pipe.Set(CreateNamedPipe(
    115       base::UTF8ToUTF16(pipe_name).c_str(),
    116       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
    117       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
    118       1,
    119       IPC::Channel::kReadBufferSize,
    120       IPC::Channel::kReadBufferSize,
    121       5000,
    122       &security_attributes));
    123   if (!pipe.IsValid()) {
    124     PLOG(ERROR)
    125         << "Failed to create the server end of the Chromoting IPC channel";
    126     return false;
    127   }
    128 
    129   *pipe_out = pipe.Pass();
    130   return true;
    131 }
    132 
    133 } // namespace remoting
    134