1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/cpp/platform/named_platform_channel.h"
#include <windows.h>
#include <memory>
// NOTE: This needs to be included *after* windows.h.
#include <sddl.h>
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
namespace mojo {
namespace {
// A DACL to grant:
// GA = Generic All
// access to:
// SY = LOCAL_SYSTEM
// BA = BUILTIN_ADMINISTRATORS
// OW = OWNER_RIGHTS
constexpr base::char16 kDefaultSecurityDescriptor[] =
L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)";
NamedPlatformChannel::ServerName GenerateRandomServerName() {
return base::UTF8ToUTF16(
base::StringPrintf("%lu.%lu.%I64u", ::GetCurrentProcessId(),
::GetCurrentThreadId(), base::RandUint64()));
}
base::string16 GetPipeNameFromServerName(
const NamedPlatformChannel::ServerName& server_name) {
return L"\\\\.\\pipe\\mojo." + server_name;
}
} // namespace
// static
PlatformChannelServerEndpoint NamedPlatformChannel::CreateServerEndpoint(
const Options& options,
ServerName* server_name) {
ServerName name = options.server_name;
if (name.empty())
name = GenerateRandomServerName();
PSECURITY_DESCRIPTOR security_desc = nullptr;
ULONG security_desc_len = 0;
PCHECK(::ConvertStringSecurityDescriptorToSecurityDescriptor(
options.security_descriptor.empty() ? kDefaultSecurityDescriptor
: options.security_descriptor.c_str(),
SDDL_REVISION_1, &security_desc, &security_desc_len));
std::unique_ptr<void, decltype(::LocalFree)*> p(security_desc, ::LocalFree);
SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES),
security_desc, FALSE};
const DWORD kOpenMode = options.enforce_uniqueness
? PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
FILE_FLAG_FIRST_PIPE_INSTANCE
: PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED;
const DWORD kPipeMode =
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS;
base::string16 pipe_name = GetPipeNameFromServerName(name);
PlatformHandle handle(base::win::ScopedHandle(::CreateNamedPipeW(
pipe_name.c_str(), kOpenMode, kPipeMode,
options.enforce_uniqueness ? 1 : 255, // Max instances.
4096, // Out buffer size.
4096, // In buffer size.
5000, // Timeout in milliseconds.
&security_attributes)));
*server_name = name;
return PlatformChannelServerEndpoint(std::move(handle));
}
// static
PlatformChannelEndpoint NamedPlatformChannel::CreateClientEndpoint(
const ServerName& server_name) {
base::string16 pipe_name = GetPipeNameFromServerName(server_name);
// Note: This may block.
if (!::WaitNamedPipeW(pipe_name.c_str(), NMPWAIT_USE_DEFAULT_WAIT))
return PlatformChannelEndpoint();
const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
// The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
// the client.
const DWORD kFlags =
SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED;
PlatformHandle handle(base::win::ScopedHandle(
::CreateFileW(pipe_name.c_str(), kDesiredAccess, 0, nullptr,
OPEN_EXISTING, kFlags, nullptr)));
// The server may have stopped accepting a connection between the
// WaitNamedPipe() and CreateFile(). If this occurs, an invalid handle is
// returned.
DPLOG_IF(ERROR, !handle.is_valid())
<< "Named pipe " << pipe_name
<< " could not be opened after WaitNamedPipe succeeded";
return PlatformChannelEndpoint(std::move(handle));
}
} // namespace mojo
|