openMSX
SspiNegotiateServer.cc
Go to the documentation of this file.
1#ifdef _WIN32
2
4#include "MSXException.hh"
5#include "one_of.hh"
6#include "openmsx.hh"
7
8namespace openmsx {
9
10using namespace sspiutils;
11
12SspiNegotiateServer::SspiNegotiateServer(StreamWrapper& serverStream)
13 : SspiPackageBase(serverStream, NEGOSSP_NAME_W)
14{
15 // We should probably cache the security descriptor, but this
16 // isn't exactly a performance-sensitive part of the code
17 psd = CreateCurrentUserSecurityDescriptor();
18 if (!psd) {
19 throw MSXException("CreateCurrentUserSecurityDescriptor failed");
20 }
21}
22
23SspiNegotiateServer::~SspiNegotiateServer()
24{
25 LocalFree(psd);
26}
27
28bool SspiNegotiateServer::Authenticate()
29{
30 TimeStamp tsCredsExpiry;
31 SECURITY_STATUS ss = AcquireCredentialsHandleW(
32 nullptr,
33 const_cast<SEC_WCHAR*>(NEGOSSP_NAME_W),
34 SECPKG_CRED_INBOUND,
35 nullptr,
36 nullptr,
37 nullptr,
38 nullptr,
39 &hCreds,
40 &tsCredsExpiry);
41
42 DebugPrintSecurityStatus("AcquireCredentialsHandleW", ss);
43 if (ss != SEC_E_OK) {
44 return false;
45 }
46
47 SecBufferDesc secClientBufferDesc, secServerBufferDesc;
48 SecBuffer secClientBuffer, secServerBuffer;
49 InitTokenContextBuffer(&secClientBufferDesc, &secClientBuffer);
50 InitTokenContextBuffer(&secServerBufferDesc, &secServerBuffer);
51
52 std::vector<char> buffer;
53 PCtxtHandle phContext = nullptr;
54 while (true) {
55 // Receive another buffer from the client
56 bool ret = RecvChunk(stream, buffer, cbMaxTokenSize);
57 if (!ret) return false;
58
59 secClientBuffer.cbBuffer = static_cast<unsigned long>(buffer.size());
60 secClientBuffer.pvBuffer = &buffer[0];
61
62 ULONG fContextAttr;
63 TimeStamp tsContextExpiry;
64 ss = AcceptSecurityContext(
65 &hCreds,
66 phContext,
67 &secClientBufferDesc,
68 ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_CONNECTION,
69 SECURITY_NETWORK_DREP,
70 &hContext,
71 &secServerBufferDesc,
72 &fContextAttr,
73 &tsContextExpiry);
74
75 DebugPrintSecurityStatus("AcceptSecurityContext", ss);
76 if (ss != one_of(SEC_E_OK, SEC_I_CONTINUE_NEEDED)) {
77 return false;
78 }
79
80 // If we have something for the client, send it
81 if (secServerBuffer.cbBuffer) {
82 ret = SendChunk(stream, secServerBuffer.pvBuffer, secServerBuffer.cbBuffer);
83 ClearContextBuffers(&secServerBufferDesc);
84 if (!ret) return false;
85 }
86
87 // SEC_E_OK means that we're done
88 if (ss == SEC_E_OK) {
89 DebugPrintSecurityPackageName(&hContext);
90 DebugPrintSecurityPrincipalName(&hContext);
91 return true;
92 }
93
94 // Another time around the loop
95 phContext = &hContext;
96 }
97}
98
99bool SspiNegotiateServer::Authorize()
100{
101#ifdef __GNUC__
102 // MinGW32's headers do not define QuerySecurityContextToken,
103 // nor does its import library provide an export for it.
104 // So when building with MinGW32, we load the export by hand.
105 HMODULE secur32 = GetModuleHandleW(L"secur32.dll");
106 if (!secur32) {
107 return false;
108 }
109 auto QuerySecurityContextToken = reinterpret_cast<QUERY_SECURITY_CONTEXT_TOKEN_FN>(
110 GetProcAddress(secur32, "QuerySecurityContextToken"));
111 if (!QuerySecurityContextToken) {
112 return false;
113 }
114#endif
115
116 HANDLE hClientToken;
117 SECURITY_STATUS ss = QuerySecurityContextToken(&hContext, &hClientToken);
118 DebugPrintSecurityStatus("QuerySecurityContextToken", ss);
119 if (ss != SEC_E_OK) {
120 return false;
121 }
122
123 PRIVILEGE_SET privilegeSet;
124 DWORD dwPrivSetSize = sizeof(privilegeSet);
125 DWORD dwGranted;
126 BOOL fAccess;
127 BOOL ret = AccessCheck(
128 psd,
129 hClientToken,
130 ACCESS_ALL,
131 const_cast<PGENERIC_MAPPING>(&mapping),
132 &privilegeSet,
133 &dwPrivSetSize,
134 &dwGranted,
135 &fAccess);
136
137 DebugPrintSecurityBool("AccessCheck", ret);
138 DebugPrintSecurityPrincipalName(&hContext);
139
140 CloseHandle(hClientToken);
141
142 return ret && fAccess;
143}
144
145} // namespace openmsx
146
147#endif
This file implemented 3 utility functions:
Definition Autofire.cc:11