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.
5 #include "remoting/host/ipc_util.h"
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"
18 using base::win::ScopedHandle
;
22 // Pipe name prefix used by Chrome IPC channels to convert a channel name into
24 const char kChromePipeNamePrefix
[] = "\\\\.\\pipe\\chrome.";
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.";
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 user_sid_utf8
= base::WideToUTF8(user_sid
);
43 std::string security_descriptor
=
44 base::StringPrintf("O:%sG:%sD:(A;;GA;;;%s)", user_sid_utf8
.c_str(),
45 user_sid_utf8
.c_str(), user_sid_utf8
.c_str());
47 // Generate a unique name for the channel.
48 std::string channel_name
= IPC::Channel::GenerateUniqueRandomChannelID();
50 // Create the server end of the channel.
52 if (!CreateIpcChannel(channel_name
, security_descriptor
, &pipe
)) {
56 // Wrap the pipe into an IPC channel.
57 scoped_ptr
<IPC::ChannelProxy
> server
=
58 IPC::ChannelProxy::Create(IPC::ChannelHandle(pipe
.Get()),
59 IPC::Channel::MODE_SERVER
,
64 // Convert the channel name to the pipe name.
65 std::string
pipe_name(kChromePipeNamePrefix
);
66 pipe_name
.append(channel_name
);
68 SECURITY_ATTRIBUTES security_attributes
= {0};
69 security_attributes
.nLength
= sizeof(security_attributes
);
70 security_attributes
.lpSecurityDescriptor
= nullptr;
71 security_attributes
.bInheritHandle
= TRUE
;
73 // Create the client end of the channel. This code should match the code in
75 base::File
client(CreateFile(base::UTF8ToUTF16(pipe_name
).c_str(),
76 GENERIC_READ
| GENERIC_WRITE
,
80 SECURITY_SQOS_PRESENT
| SECURITY_IDENTIFICATION
|
83 if (!client
.IsValid()) {
84 PLOG(ERROR
) << "Failed to connect to '" << pipe_name
<< "'";
88 *client_out
= client
.Pass();
89 *server_out
= server
.Pass();
93 bool CreateIpcChannel(
94 const std::string
& channel_name
,
95 const std::string
& pipe_security_descriptor
,
96 base::win::ScopedHandle
* pipe_out
) {
97 // Create security descriptor for the channel.
98 ScopedSd sd
= ConvertSddlToSd(pipe_security_descriptor
);
100 PLOG(ERROR
) << "Failed to create a security descriptor for the Chromoting "
105 SECURITY_ATTRIBUTES security_attributes
= {0};
106 security_attributes
.nLength
= sizeof(security_attributes
);
107 security_attributes
.lpSecurityDescriptor
= sd
.get();
108 security_attributes
.bInheritHandle
= FALSE
;
110 // Convert the channel name to the pipe name.
111 std::string
pipe_name(kChromePipeNamePrefix
);
112 pipe_name
.append(channel_name
);
114 // Create the server end of the pipe. This code should match the code in
115 // IPC::Channel with exception of passing a non-default security descriptor.
116 base::win::ScopedHandle pipe
;
117 pipe
.Set(CreateNamedPipe(
118 base::UTF8ToUTF16(pipe_name
).c_str(),
119 PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
| FILE_FLAG_FIRST_PIPE_INSTANCE
,
120 PIPE_TYPE_BYTE
| PIPE_READMODE_BYTE
,
122 IPC::Channel::kReadBufferSize
,
123 IPC::Channel::kReadBufferSize
,
125 &security_attributes
));
126 if (!pipe
.IsValid()) {
128 << "Failed to create the server end of the Chromoting IPC channel";
132 *pipe_out
= pipe
.Pass();
136 } // namespace remoting