OpenVPN 3 Core Library
Loading...
Searching...
No Matches
npinfo.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#pragma once
13
14// Get info about named pipe peer
15
16#include <cstdlib> // defines std::abort()
17#include <windows.h>
18#include <sddl.h>
19#include <aclapi.h>
20
27
28namespace openvpn::Win {
30{
31 OPENVPN_EXCEPTION(named_pipe_impersonate);
32
33 NamedPipeImpersonate(const HANDLE pipe)
34 {
35 if (!::ImpersonateNamedPipeClient(pipe))
36 {
37 const Win::LastError err;
38 OPENVPN_THROW(named_pipe_impersonate, "ImpersonateNamedPipeClient failed: " << err.message());
39 }
40 }
41
43 {
44 if (!::RevertToSelf())
45 {
46 OPENVPN_LOG("NamedPipeImpersonate: RevertToSelf failed, must abort");
47 std::abort();
48 }
49 }
50};
51
53{
54 OPENVPN_EXCEPTION(npinfo_error);
55
56 // Get process handle given PID.
57 static Win::ScopedHANDLE get_process(const ULONG pid, const bool limited)
58 {
59 // open process
60 Win::ScopedHANDLE proc(::OpenProcess(
61 limited ? (PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE) : PROCESS_ALL_ACCESS,
62 FALSE,
63 pid));
64 if (!proc.defined())
65 {
66 const Win::LastError err;
67 OPENVPN_THROW(npinfo_error, "OpenProcess failed: " << err.message());
68 }
69 return proc;
70 }
71
72 // Servers must call this method to modify their process
73 // access rights to grant clients the
74 // PROCESS_QUERY_LIMITED_INFORMATION right, so that clients
75 // can validate the server's exe path via get_exe_path().
76 static void allow_client_query()
77 {
79 "D:" // discretionary ACL
80 "(A;OICI;0x101000;;;S-1-1-0)" // grant PROCESS_QUERY_LIMITED_INFORMATION and SYNCHRONIZE access to Everyone
81 ,
82 false,
83 "client query");
84
85 ACL *dacl;
86 BOOL bDaclPresent, bDaclDefaulted;
87 if (!::GetSecurityDescriptorDacl(sa.sa.lpSecurityDescriptor,
88 &bDaclPresent,
89 &dacl,
90 &bDaclDefaulted))
91 {
92 const Win::LastError err;
93 OPENVPN_THROW(npinfo_error, "allow_client_query: GetSecurityDescriptorDacl failed: " << err.message());
94 }
95 if (!bDaclPresent)
96 OPENVPN_THROW(npinfo_error, "allow_client_query: missing DACL");
97 const DWORD ssi_status = ::SetSecurityInfo(
98 ::GetCurrentProcess(),
99 SE_KERNEL_OBJECT,
100 DACL_SECURITY_INFORMATION,
101 NULL,
102 NULL,
103 dacl,
104 NULL);
105 if (ssi_status != ERROR_SUCCESS)
106 {
107 const Win::Error err(ssi_status);
108 OPENVPN_THROW(npinfo_error, "allow_client_query: SetSecurityInfo failed: " << err.message());
109 }
110 }
111
112 // Get PID of process at other end of named pipe
113 static ULONG get_pid(const HANDLE np_handle, const bool client)
114 {
115 ULONG pid = 0;
116 if (client)
117 {
118 if (!::GetNamedPipeClientProcessId(np_handle, &pid))
119 {
120 const Win::LastError err;
121 OPENVPN_THROW(npinfo_error, "GetNamedPipeClientProcessId failed: " << err.message());
122 }
123 }
124 else
125 {
126 if (!::GetNamedPipeServerProcessId(np_handle, &pid))
127 {
128 const Win::LastError err;
129 OPENVPN_THROW(npinfo_error, "GetNamedPipeServerProcessId failed: " << err.message());
130 }
131 }
132 return pid;
133 }
134
135 // Get exe path given process handle.
136 static std::wstring get_exe_path(const HANDLE proc)
137 {
138 // get exe path
139 const size_t exe_cap = 256;
140 wchar_t exe[exe_cap];
141 DWORD exe_size = exe_cap;
142 if (!::QueryFullProcessImageNameW(proc, 0, exe, &exe_size))
143 {
144 const Win::LastError err;
145 OPENVPN_THROW(npinfo_error, "QueryFullProcessImageNameW failed: " << err.message());
146 }
147 return std::wstring(exe, exe_size);
148 }
149};
150
152{
153 NamedPipePeerInfoCS(const HANDLE handle, const bool client)
154 {
155 const ULONG pid = get_pid(handle, client);
156 proc = get_process(pid, !client);
158 }
159
161 std::wstring exe_path;
162};
163
164// Used by server to get info about clients
166{
167 NamedPipePeerInfoClient(const HANDLE handle)
168 : NamedPipePeerInfoCS(handle, true)
169 {
170 }
171};
172
173// Used by clients to get info about the server
175{
176 NamedPipePeerInfoServer(const HANDLE handle)
177 : NamedPipePeerInfoCS(handle, false)
178 {
179 }
180};
181
182} // namespace openvpn::Win
#define OPENVPN_THROW(exc, stuff)
#define OPENVPN_LOG(args)
NamedPipeImpersonate(const HANDLE pipe)
Definition npinfo.hpp:33
OPENVPN_EXCEPTION(named_pipe_impersonate)
NamedPipePeerInfoCS(const HANDLE handle, const bool client)
Definition npinfo.hpp:153
NamedPipePeerInfoClient(const HANDLE handle)
Definition npinfo.hpp:167
NamedPipePeerInfoServer(const HANDLE handle)
Definition npinfo.hpp:176
static std::wstring get_exe_path(const HANDLE proc)
Definition npinfo.hpp:136
static Win::ScopedHANDLE get_process(const ULONG pid, const bool limited)
Definition npinfo.hpp:57
static ULONG get_pid(const HANDLE np_handle, const bool client)
Definition npinfo.hpp:113
static void allow_client_query()
Definition npinfo.hpp:76