- add sources.
[platform/framework/web/crosswalk.git] / src / remoting / host / ipc_util_win.cc
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/logging.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/win/scoped_handle.h"
12 #include "base/win/win_util.h"
13 #include "ipc/ipc_channel.h"
14 #include "ipc/ipc_channel_proxy.h"
15 #include "remoting/host/win/security_descriptor.h"
16
17 using base::win::ScopedHandle;
18
19 namespace remoting {
20
21 // Pipe name prefix used by Chrome IPC channels to convert a channel name into
22 // a pipe name.
23 const char kChromePipeNamePrefix[] = "\\\\.\\pipe\\chrome.";
24
25 bool CreateConnectedIpcChannel(
26     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
27     IPC::Listener* listener,
28     IPC::PlatformFileForTransit* client_out,
29     scoped_ptr<IPC::ChannelProxy>* server_out) {
30   // presubmit: allow wstring
31   std::wstring user_sid;
32   if (!base::win::GetUserSidString(&user_sid)) {
33     LOG(ERROR) << "Failed to query the current user SID.";
34     return false;
35   }
36
37   // Create a security descriptor that will be used to protect the named pipe in
38   // between CreateNamedPipe() and CreateFile() calls before it will be passed
39   // to the network process. It gives full access to the account that
40   // the calling code is running under and  denies access by anyone else.
41   std::string security_descriptor = base::StringPrintf(
42       "O:%1$sG:%1$sD:(A;;GA;;;%1$s)", WideToUTF8(user_sid).c_str());
43
44   // Generate a unique name for the channel.
45   std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID();
46
47   // Create the server end of the channel.
48   ScopedHandle pipe;
49   if (!CreateIpcChannel(channel_name, security_descriptor, &pipe)) {
50     return false;
51   }
52
53   // Wrap the pipe into an IPC channel.
54   scoped_ptr<IPC::ChannelProxy> server(new IPC::ChannelProxy(
55       IPC::ChannelHandle(pipe),
56       IPC::Channel::MODE_SERVER,
57       listener,
58       io_task_runner));
59
60   // Convert the channel name to the pipe name.
61   std::string pipe_name(kChromePipeNamePrefix);
62   pipe_name.append(channel_name);
63
64   SECURITY_ATTRIBUTES security_attributes = {0};
65   security_attributes.nLength = sizeof(security_attributes);
66   security_attributes.lpSecurityDescriptor = NULL;
67   security_attributes.bInheritHandle = TRUE;
68
69   // Create the client end of the channel. This code should match the code in
70   // IPC::Channel.
71   ScopedHandle client;
72   client.Set(CreateFile(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     LOG_GETLASTERROR(ERROR) << "Failed to connect to '" << pipe_name << "'";
82     return false;
83   }
84
85   *client_out = client.Take();
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     LOG_GETLASTERROR(ERROR) <<
98         "Failed to create a security descriptor for the Chromoting 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       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     LOG_GETLASTERROR(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