1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Security Support Provider Interface (SSPI)
4  *
5  * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #define _NO_KSECDD_IMPORT_ 1
25 
26 #include <winpr/sspi.h>
27 
28 #include <winpr/crt.h>
29 #include <winpr/synch.h>
30 #include <winpr/wlog.h>
31 #include <winpr/library.h>
32 #include <winpr/environment.h>
33 
34 #include "sspi.h"
35 
36 static wLog* g_Log = NULL;
37 
38 static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
39 #if defined(WITH_NATIVE_SSPI)
40 static HMODULE g_SspiModule = NULL;
41 #endif
42 
43 static SecurityFunctionTableW* g_SspiW = NULL;
44 static SecurityFunctionTableA* g_SspiA = NULL;
45 
46 #if defined(WITH_NATIVE_SSPI)
47 static BOOL ShouldUseNativeSspi(void);
48 static BOOL InitializeSspiModule_Native(void);
49 #endif
50 
51 #if defined(WITH_NATIVE_SSPI)
ShouldUseNativeSspi(void)52 BOOL ShouldUseNativeSspi(void)
53 {
54 	BOOL status = FALSE;
55 #ifdef _WIN32
56 	LPCSTR sspi = "WINPR_NATIVE_SSPI";
57 	DWORD nSize;
58 	char* env = NULL;
59 	nSize = GetEnvironmentVariableA(sspi, NULL, 0);
60 
61 	if (!nSize)
62 		return TRUE;
63 
64 	env = (LPSTR)malloc(nSize);
65 
66 	if (!env)
67 		return TRUE;
68 
69 	if (GetEnvironmentVariableA(sspi, env, nSize) != nSize - 1)
70 	{
71 		free(env);
72 		return TRUE;
73 	}
74 
75 	if (strcmp(env, "0") == 0)
76 		status = FALSE;
77 	else
78 		status = TRUE;
79 
80 	free(env);
81 #endif
82 	return status;
83 }
84 #endif
85 
86 #if defined(WITH_NATIVE_SSPI)
InitializeSspiModule_Native(void)87 BOOL InitializeSspiModule_Native(void)
88 {
89 	INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW;
90 	INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA;
91 	g_SspiModule = LoadLibraryA("secur32.dll");
92 
93 	if (!g_SspiModule)
94 		g_SspiModule = LoadLibraryA("security.dll");
95 
96 	if (!g_SspiModule)
97 		return FALSE;
98 
99 	pInitSecurityInterfaceW =
100 	    (INIT_SECURITY_INTERFACE_W)GetProcAddress(g_SspiModule, "InitSecurityInterfaceW");
101 	pInitSecurityInterfaceA =
102 	    (INIT_SECURITY_INTERFACE_A)GetProcAddress(g_SspiModule, "InitSecurityInterfaceA");
103 
104 	if (pInitSecurityInterfaceW)
105 		g_SspiW = pInitSecurityInterfaceW();
106 
107 	if (pInitSecurityInterfaceA)
108 		g_SspiA = pInitSecurityInterfaceA();
109 
110 	return TRUE;
111 }
112 #endif
113 
InitializeSspiModuleInt(PINIT_ONCE once,PVOID param,PVOID * context)114 static BOOL CALLBACK InitializeSspiModuleInt(PINIT_ONCE once, PVOID param, PVOID* context)
115 {
116 	BOOL status = FALSE;
117 #if defined(WITH_NATIVE_SSPI)
118 	DWORD flags = 0;
119 
120 	if (param)
121 		flags = *(DWORD*)param;
122 
123 #endif
124 	sspi_GlobalInit();
125 	g_Log = WLog_Get("com.winpr.sspi");
126 #if defined(WITH_NATIVE_SSPI)
127 
128 	if (flags && (flags & SSPI_INTERFACE_NATIVE))
129 	{
130 		status = InitializeSspiModule_Native();
131 	}
132 	else if (flags && (flags & SSPI_INTERFACE_WINPR))
133 	{
134 		g_SspiW = winpr_InitSecurityInterfaceW();
135 		g_SspiA = winpr_InitSecurityInterfaceA();
136 		status = TRUE;
137 	}
138 
139 	if (!status && ShouldUseNativeSspi())
140 	{
141 		status = InitializeSspiModule_Native();
142 	}
143 
144 #endif
145 
146 	if (!status)
147 	{
148 		g_SspiW = winpr_InitSecurityInterfaceW();
149 		g_SspiA = winpr_InitSecurityInterfaceA();
150 	}
151 
152 	return TRUE;
153 }
154 
GetSecurityStatusString(SECURITY_STATUS status)155 const char* GetSecurityStatusString(SECURITY_STATUS status)
156 {
157 	switch (status)
158 	{
159 		case SEC_E_OK:
160 			return "SEC_E_OK";
161 
162 		case SEC_E_INSUFFICIENT_MEMORY:
163 			return "SEC_E_INSUFFICIENT_MEMORY";
164 
165 		case SEC_E_INVALID_HANDLE:
166 			return "SEC_E_INVALID_HANDLE";
167 
168 		case SEC_E_UNSUPPORTED_FUNCTION:
169 			return "SEC_E_UNSUPPORTED_FUNCTION";
170 
171 		case SEC_E_TARGET_UNKNOWN:
172 			return "SEC_E_TARGET_UNKNOWN";
173 
174 		case SEC_E_INTERNAL_ERROR:
175 			return "SEC_E_INTERNAL_ERROR";
176 
177 		case SEC_E_SECPKG_NOT_FOUND:
178 			return "SEC_E_SECPKG_NOT_FOUND";
179 
180 		case SEC_E_NOT_OWNER:
181 			return "SEC_E_NOT_OWNER";
182 
183 		case SEC_E_CANNOT_INSTALL:
184 			return "SEC_E_CANNOT_INSTALL";
185 
186 		case SEC_E_INVALID_TOKEN:
187 			return "SEC_E_INVALID_TOKEN";
188 
189 		case SEC_E_CANNOT_PACK:
190 			return "SEC_E_CANNOT_PACK";
191 
192 		case SEC_E_QOP_NOT_SUPPORTED:
193 			return "SEC_E_QOP_NOT_SUPPORTED";
194 
195 		case SEC_E_NO_IMPERSONATION:
196 			return "SEC_E_NO_IMPERSONATION";
197 
198 		case SEC_E_LOGON_DENIED:
199 			return "SEC_E_LOGON_DENIED";
200 
201 		case SEC_E_UNKNOWN_CREDENTIALS:
202 			return "SEC_E_UNKNOWN_CREDENTIALS";
203 
204 		case SEC_E_NO_CREDENTIALS:
205 			return "SEC_E_NO_CREDENTIALS";
206 
207 		case SEC_E_MESSAGE_ALTERED:
208 			return "SEC_E_MESSAGE_ALTERED";
209 
210 		case SEC_E_OUT_OF_SEQUENCE:
211 			return "SEC_E_OUT_OF_SEQUENCE";
212 
213 		case SEC_E_NO_AUTHENTICATING_AUTHORITY:
214 			return "SEC_E_NO_AUTHENTICATING_AUTHORITY";
215 
216 		case SEC_E_BAD_PKGID:
217 			return "SEC_E_BAD_PKGID";
218 
219 		case SEC_E_CONTEXT_EXPIRED:
220 			return "SEC_E_CONTEXT_EXPIRED";
221 
222 		case SEC_E_INCOMPLETE_MESSAGE:
223 			return "SEC_E_INCOMPLETE_MESSAGE";
224 
225 		case SEC_E_INCOMPLETE_CREDENTIALS:
226 			return "SEC_E_INCOMPLETE_CREDENTIALS";
227 
228 		case SEC_E_BUFFER_TOO_SMALL:
229 			return "SEC_E_BUFFER_TOO_SMALL";
230 
231 		case SEC_E_WRONG_PRINCIPAL:
232 			return "SEC_E_WRONG_PRINCIPAL";
233 
234 		case SEC_E_TIME_SKEW:
235 			return "SEC_E_TIME_SKEW";
236 
237 		case SEC_E_UNTRUSTED_ROOT:
238 			return "SEC_E_UNTRUSTED_ROOT";
239 
240 		case SEC_E_ILLEGAL_MESSAGE:
241 			return "SEC_E_ILLEGAL_MESSAGE";
242 
243 		case SEC_E_CERT_UNKNOWN:
244 			return "SEC_E_CERT_UNKNOWN";
245 
246 		case SEC_E_CERT_EXPIRED:
247 			return "SEC_E_CERT_EXPIRED";
248 
249 		case SEC_E_ENCRYPT_FAILURE:
250 			return "SEC_E_ENCRYPT_FAILURE";
251 
252 		case SEC_E_DECRYPT_FAILURE:
253 			return "SEC_E_DECRYPT_FAILURE";
254 
255 		case SEC_E_ALGORITHM_MISMATCH:
256 			return "SEC_E_ALGORITHM_MISMATCH";
257 
258 		case SEC_E_SECURITY_QOS_FAILED:
259 			return "SEC_E_SECURITY_QOS_FAILED";
260 
261 		case SEC_E_UNFINISHED_CONTEXT_DELETED:
262 			return "SEC_E_UNFINISHED_CONTEXT_DELETED";
263 
264 		case SEC_E_NO_TGT_REPLY:
265 			return "SEC_E_NO_TGT_REPLY";
266 
267 		case SEC_E_NO_IP_ADDRESSES:
268 			return "SEC_E_NO_IP_ADDRESSES";
269 
270 		case SEC_E_WRONG_CREDENTIAL_HANDLE:
271 			return "SEC_E_WRONG_CREDENTIAL_HANDLE";
272 
273 		case SEC_E_CRYPTO_SYSTEM_INVALID:
274 			return "SEC_E_CRYPTO_SYSTEM_INVALID";
275 
276 		case SEC_E_MAX_REFERRALS_EXCEEDED:
277 			return "SEC_E_MAX_REFERRALS_EXCEEDED";
278 
279 		case SEC_E_MUST_BE_KDC:
280 			return "SEC_E_MUST_BE_KDC";
281 
282 		case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
283 			return "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED";
284 
285 		case SEC_E_TOO_MANY_PRINCIPALS:
286 			return "SEC_E_TOO_MANY_PRINCIPALS";
287 
288 		case SEC_E_NO_PA_DATA:
289 			return "SEC_E_NO_PA_DATA";
290 
291 		case SEC_E_PKINIT_NAME_MISMATCH:
292 			return "SEC_E_PKINIT_NAME_MISMATCH";
293 
294 		case SEC_E_SMARTCARD_LOGON_REQUIRED:
295 			return "SEC_E_SMARTCARD_LOGON_REQUIRED";
296 
297 		case SEC_E_SHUTDOWN_IN_PROGRESS:
298 			return "SEC_E_SHUTDOWN_IN_PROGRESS";
299 
300 		case SEC_E_KDC_INVALID_REQUEST:
301 			return "SEC_E_KDC_INVALID_REQUEST";
302 
303 		case SEC_E_KDC_UNABLE_TO_REFER:
304 			return "SEC_E_KDC_UNABLE_TO_REFER";
305 
306 		case SEC_E_KDC_UNKNOWN_ETYPE:
307 			return "SEC_E_KDC_UNKNOWN_ETYPE";
308 
309 		case SEC_E_UNSUPPORTED_PREAUTH:
310 			return "SEC_E_UNSUPPORTED_PREAUTH";
311 
312 		case SEC_E_DELEGATION_REQUIRED:
313 			return "SEC_E_DELEGATION_REQUIRED";
314 
315 		case SEC_E_BAD_BINDINGS:
316 			return "SEC_E_BAD_BINDINGS";
317 
318 		case SEC_E_MULTIPLE_ACCOUNTS:
319 			return "SEC_E_MULTIPLE_ACCOUNTS";
320 
321 		case SEC_E_NO_KERB_KEY:
322 			return "SEC_E_NO_KERB_KEY";
323 
324 		case SEC_E_CERT_WRONG_USAGE:
325 			return "SEC_E_CERT_WRONG_USAGE";
326 
327 		case SEC_E_DOWNGRADE_DETECTED:
328 			return "SEC_E_DOWNGRADE_DETECTED";
329 
330 		case SEC_E_SMARTCARD_CERT_REVOKED:
331 			return "SEC_E_SMARTCARD_CERT_REVOKED";
332 
333 		case SEC_E_ISSUING_CA_UNTRUSTED:
334 			return "SEC_E_ISSUING_CA_UNTRUSTED";
335 
336 		case SEC_E_REVOCATION_OFFLINE_C:
337 			return "SEC_E_REVOCATION_OFFLINE_C";
338 
339 		case SEC_E_PKINIT_CLIENT_FAILURE:
340 			return "SEC_E_PKINIT_CLIENT_FAILURE";
341 
342 		case SEC_E_SMARTCARD_CERT_EXPIRED:
343 			return "SEC_E_SMARTCARD_CERT_EXPIRED";
344 
345 		case SEC_E_NO_S4U_PROT_SUPPORT:
346 			return "SEC_E_NO_S4U_PROT_SUPPORT";
347 
348 		case SEC_E_CROSSREALM_DELEGATION_FAILURE:
349 			return "SEC_E_CROSSREALM_DELEGATION_FAILURE";
350 
351 		case SEC_E_REVOCATION_OFFLINE_KDC:
352 			return "SEC_E_REVOCATION_OFFLINE_KDC";
353 
354 		case SEC_E_ISSUING_CA_UNTRUSTED_KDC:
355 			return "SEC_E_ISSUING_CA_UNTRUSTED_KDC";
356 
357 		case SEC_E_KDC_CERT_EXPIRED:
358 			return "SEC_E_KDC_CERT_EXPIRED";
359 
360 		case SEC_E_KDC_CERT_REVOKED:
361 			return "SEC_E_KDC_CERT_REVOKED";
362 
363 		case SEC_E_INVALID_PARAMETER:
364 			return "SEC_E_INVALID_PARAMETER";
365 
366 		case SEC_E_DELEGATION_POLICY:
367 			return "SEC_E_DELEGATION_POLICY";
368 
369 		case SEC_E_POLICY_NLTM_ONLY:
370 			return "SEC_E_POLICY_NLTM_ONLY";
371 
372 		case SEC_E_NO_CONTEXT:
373 			return "SEC_E_NO_CONTEXT";
374 
375 		case SEC_E_PKU2U_CERT_FAILURE:
376 			return "SEC_E_PKU2U_CERT_FAILURE";
377 
378 		case SEC_E_MUTUAL_AUTH_FAILED:
379 			return "SEC_E_MUTUAL_AUTH_FAILED";
380 
381 		case SEC_I_CONTINUE_NEEDED:
382 			return "SEC_I_CONTINUE_NEEDED";
383 
384 		case SEC_I_COMPLETE_NEEDED:
385 			return "SEC_I_COMPLETE_NEEDED";
386 
387 		case SEC_I_COMPLETE_AND_CONTINUE:
388 			return "SEC_I_COMPLETE_AND_CONTINUE";
389 
390 		case SEC_I_LOCAL_LOGON:
391 			return "SEC_I_LOCAL_LOGON";
392 
393 		case SEC_I_CONTEXT_EXPIRED:
394 			return "SEC_I_CONTEXT_EXPIRED";
395 
396 		case SEC_I_INCOMPLETE_CREDENTIALS:
397 			return "SEC_I_INCOMPLETE_CREDENTIALS";
398 
399 		case SEC_I_RENEGOTIATE:
400 			return "SEC_I_RENEGOTIATE";
401 
402 		case SEC_I_NO_LSA_CONTEXT:
403 			return "SEC_I_NO_LSA_CONTEXT";
404 
405 		case SEC_I_SIGNATURE_NEEDED:
406 			return "SEC_I_SIGNATURE_NEEDED";
407 
408 		case SEC_I_NO_RENEGOTIATION:
409 			return "SEC_I_NO_RENEGOTIATION";
410 	}
411 
412 	return NtStatus2Tag(status);
413 }
414 
IsSecurityStatusError(SECURITY_STATUS status)415 BOOL IsSecurityStatusError(SECURITY_STATUS status)
416 {
417 	BOOL error = TRUE;
418 
419 	switch (status)
420 	{
421 		case SEC_E_OK:
422 		case SEC_I_CONTINUE_NEEDED:
423 		case SEC_I_COMPLETE_NEEDED:
424 		case SEC_I_COMPLETE_AND_CONTINUE:
425 		case SEC_I_LOCAL_LOGON:
426 		case SEC_I_CONTEXT_EXPIRED:
427 		case SEC_I_INCOMPLETE_CREDENTIALS:
428 		case SEC_I_RENEGOTIATE:
429 		case SEC_I_NO_LSA_CONTEXT:
430 		case SEC_I_SIGNATURE_NEEDED:
431 		case SEC_I_NO_RENEGOTIATION:
432 			error = FALSE;
433 			break;
434 	}
435 
436 	return error;
437 }
438 
InitSecurityInterfaceExW(DWORD flags)439 SecurityFunctionTableW* SEC_ENTRY InitSecurityInterfaceExW(DWORD flags)
440 {
441 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, &flags, NULL);
442 	WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceExW");
443 	return g_SspiW;
444 }
445 
InitSecurityInterfaceExA(DWORD flags)446 SecurityFunctionTableA* SEC_ENTRY InitSecurityInterfaceExA(DWORD flags)
447 {
448 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, &flags, NULL);
449 	WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceExA");
450 	return g_SspiA;
451 }
452 
453 /**
454  * Standard SSPI API
455  */
456 
457 /* Package Management */
458 
sspi_EnumerateSecurityPackagesW(ULONG * pcPackages,PSecPkgInfoW * ppPackageInfo)459 SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesW(ULONG* pcPackages,
460                                                           PSecPkgInfoW* ppPackageInfo)
461 {
462 	SECURITY_STATUS status;
463 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
464 
465 	if (!(g_SspiW && g_SspiW->EnumerateSecurityPackagesW))
466 	{
467 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
468 		           __FUNCTION__);
469 		return SEC_E_UNSUPPORTED_FUNCTION;
470 	}
471 
472 	status = g_SspiW->EnumerateSecurityPackagesW(pcPackages, ppPackageInfo);
473 	WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesW: %s (0x%08" PRIX32 ")",
474 	           GetSecurityStatusString(status), status);
475 	return status;
476 }
477 
sspi_EnumerateSecurityPackagesA(ULONG * pcPackages,PSecPkgInfoA * ppPackageInfo)478 SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesA(ULONG* pcPackages,
479                                                           PSecPkgInfoA* ppPackageInfo)
480 {
481 	SECURITY_STATUS status;
482 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
483 
484 	if (!(g_SspiA && g_SspiA->EnumerateSecurityPackagesA))
485 	{
486 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
487 		           __FUNCTION__);
488 		return SEC_E_UNSUPPORTED_FUNCTION;
489 	}
490 
491 	status = g_SspiA->EnumerateSecurityPackagesA(pcPackages, ppPackageInfo);
492 	WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesA: %s (0x%08" PRIX32 ")",
493 	           GetSecurityStatusString(status), status);
494 	return status;
495 }
496 
sspi_InitSecurityInterfaceW(void)497 SecurityFunctionTableW* SEC_ENTRY sspi_InitSecurityInterfaceW(void)
498 {
499 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
500 	WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceW");
501 	return g_SspiW;
502 }
503 
sspi_InitSecurityInterfaceA(void)504 SecurityFunctionTableA* SEC_ENTRY sspi_InitSecurityInterfaceA(void)
505 {
506 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
507 	WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceA");
508 	return g_SspiA;
509 }
510 
sspi_QuerySecurityPackageInfoW(SEC_WCHAR * pszPackageName,PSecPkgInfoW * ppPackageInfo)511 SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
512                                                          PSecPkgInfoW* ppPackageInfo)
513 {
514 	SECURITY_STATUS status;
515 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
516 
517 	if (!(g_SspiW && g_SspiW->QuerySecurityPackageInfoW))
518 	{
519 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
520 		           __FUNCTION__);
521 		return SEC_E_UNSUPPORTED_FUNCTION;
522 	}
523 
524 	status = g_SspiW->QuerySecurityPackageInfoW(pszPackageName, ppPackageInfo);
525 	WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoW: %s (0x%08" PRIX32 ")",
526 	           GetSecurityStatusString(status), status);
527 	return status;
528 }
529 
sspi_QuerySecurityPackageInfoA(SEC_CHAR * pszPackageName,PSecPkgInfoA * ppPackageInfo)530 SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
531                                                          PSecPkgInfoA* ppPackageInfo)
532 {
533 	SECURITY_STATUS status;
534 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
535 
536 	if (!(g_SspiA && g_SspiA->QuerySecurityPackageInfoA))
537 	{
538 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
539 		           __FUNCTION__);
540 		return SEC_E_UNSUPPORTED_FUNCTION;
541 	}
542 
543 	status = g_SspiA->QuerySecurityPackageInfoA(pszPackageName, ppPackageInfo);
544 	WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoA: %s (0x%08" PRIX32 ")",
545 	           GetSecurityStatusString(status), status);
546 	return status;
547 }
548 
549 /* Credential Management */
550 
sspi_AcquireCredentialsHandleW(SEC_WCHAR * pszPrincipal,SEC_WCHAR * pszPackage,ULONG fCredentialUse,void * pvLogonID,void * pAuthData,SEC_GET_KEY_FN pGetKeyFn,void * pvGetKeyArgument,PCredHandle phCredential,PTimeStamp ptsExpiry)551 SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleW(
552     SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
553     void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
554     PTimeStamp ptsExpiry)
555 {
556 	SECURITY_STATUS status;
557 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
558 
559 	if (!(g_SspiW && g_SspiW->AcquireCredentialsHandleW))
560 	{
561 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
562 		           __FUNCTION__);
563 		return SEC_E_UNSUPPORTED_FUNCTION;
564 	}
565 
566 	status = g_SspiW->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
567 	                                            pAuthData, pGetKeyFn, pvGetKeyArgument,
568 	                                            phCredential, ptsExpiry);
569 	WLog_Print(g_Log, WLOG_DEBUG, "AcquireCredentialsHandleW: %s (0x%08" PRIX32 ")",
570 	           GetSecurityStatusString(status), status);
571 	return status;
572 }
573 
sspi_AcquireCredentialsHandleA(SEC_CHAR * pszPrincipal,SEC_CHAR * pszPackage,ULONG fCredentialUse,void * pvLogonID,void * pAuthData,SEC_GET_KEY_FN pGetKeyFn,void * pvGetKeyArgument,PCredHandle phCredential,PTimeStamp ptsExpiry)574 SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleA(
575     SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
576     void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
577     PTimeStamp ptsExpiry)
578 {
579 	SECURITY_STATUS status;
580 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
581 
582 	if (!(g_SspiA && g_SspiA->AcquireCredentialsHandleA))
583 	{
584 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
585 		           __FUNCTION__);
586 		return SEC_E_UNSUPPORTED_FUNCTION;
587 	}
588 
589 	status = g_SspiA->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
590 	                                            pAuthData, pGetKeyFn, pvGetKeyArgument,
591 	                                            phCredential, ptsExpiry);
592 	WLog_Print(g_Log, WLOG_DEBUG, "AcquireCredentialsHandleA: %s (0x%08" PRIX32 ")",
593 	           GetSecurityStatusString(status), status);
594 	return status;
595 }
596 
sspi_ExportSecurityContext(PCtxtHandle phContext,ULONG fFlags,PSecBuffer pPackedContext,HANDLE * pToken)597 SECURITY_STATUS SEC_ENTRY sspi_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
598                                                      PSecBuffer pPackedContext, HANDLE* pToken)
599 {
600 	SECURITY_STATUS status;
601 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
602 
603 	if (!(g_SspiW && g_SspiW->ExportSecurityContext))
604 	{
605 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
606 		           __FUNCTION__);
607 		return SEC_E_UNSUPPORTED_FUNCTION;
608 	}
609 
610 	status = g_SspiW->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
611 	WLog_Print(g_Log, WLOG_DEBUG, "ExportSecurityContext: %s (0x%08" PRIX32 ")",
612 	           GetSecurityStatusString(status), status);
613 	return status;
614 }
615 
sspi_FreeCredentialsHandle(PCredHandle phCredential)616 SECURITY_STATUS SEC_ENTRY sspi_FreeCredentialsHandle(PCredHandle phCredential)
617 {
618 	SECURITY_STATUS status;
619 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
620 
621 	if (!(g_SspiW && g_SspiW->FreeCredentialsHandle))
622 	{
623 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
624 		           __FUNCTION__);
625 		return SEC_E_UNSUPPORTED_FUNCTION;
626 	}
627 
628 	status = g_SspiW->FreeCredentialsHandle(phCredential);
629 	WLog_Print(g_Log, WLOG_DEBUG, "FreeCredentialsHandle: %s (0x%08" PRIX32 ")",
630 	           GetSecurityStatusString(status), status);
631 	return status;
632 }
633 
sspi_ImportSecurityContextW(SEC_WCHAR * pszPackage,PSecBuffer pPackedContext,HANDLE pToken,PCtxtHandle phContext)634 SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextW(SEC_WCHAR* pszPackage,
635                                                       PSecBuffer pPackedContext, HANDLE pToken,
636                                                       PCtxtHandle phContext)
637 {
638 	SECURITY_STATUS status;
639 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
640 
641 	if (!(g_SspiW && g_SspiW->ImportSecurityContextW))
642 	{
643 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
644 		           __FUNCTION__);
645 		return SEC_E_UNSUPPORTED_FUNCTION;
646 	}
647 
648 	status = g_SspiW->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
649 	WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextW: %s (0x%08" PRIX32 ")",
650 	           GetSecurityStatusString(status), status);
651 	return status;
652 }
653 
sspi_ImportSecurityContextA(SEC_CHAR * pszPackage,PSecBuffer pPackedContext,HANDLE pToken,PCtxtHandle phContext)654 SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextA(SEC_CHAR* pszPackage,
655                                                       PSecBuffer pPackedContext, HANDLE pToken,
656                                                       PCtxtHandle phContext)
657 {
658 	SECURITY_STATUS status;
659 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
660 
661 	if (!(g_SspiA && g_SspiA->ImportSecurityContextA))
662 	{
663 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
664 		           __FUNCTION__);
665 		return SEC_E_UNSUPPORTED_FUNCTION;
666 	}
667 
668 	status = g_SspiA->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
669 	WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextA: %s (0x%08" PRIX32 ")",
670 	           GetSecurityStatusString(status), status);
671 	return status;
672 }
673 
sspi_QueryCredentialsAttributesW(PCredHandle phCredential,ULONG ulAttribute,void * pBuffer)674 SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesW(PCredHandle phCredential,
675                                                            ULONG ulAttribute, void* pBuffer)
676 {
677 	SECURITY_STATUS status;
678 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
679 
680 	if (!(g_SspiW && g_SspiW->QueryCredentialsAttributesW))
681 	{
682 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
683 		           __FUNCTION__);
684 		return SEC_E_UNSUPPORTED_FUNCTION;
685 	}
686 
687 	status = g_SspiW->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
688 	WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesW: %s (0x%08" PRIX32 ")",
689 	           GetSecurityStatusString(status), status);
690 	return status;
691 }
692 
sspi_QueryCredentialsAttributesA(PCredHandle phCredential,ULONG ulAttribute,void * pBuffer)693 SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesA(PCredHandle phCredential,
694                                                            ULONG ulAttribute, void* pBuffer)
695 {
696 	SECURITY_STATUS status;
697 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
698 
699 	if (!(g_SspiA && g_SspiA->QueryCredentialsAttributesA))
700 	{
701 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
702 		           __FUNCTION__);
703 		return SEC_E_UNSUPPORTED_FUNCTION;
704 	}
705 
706 	status = g_SspiA->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
707 	WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesA: %s (0x%08" PRIX32 ")",
708 	           GetSecurityStatusString(status), status);
709 	return status;
710 }
711 
712 /* Context Management */
713 
sspi_AcceptSecurityContext(PCredHandle phCredential,PCtxtHandle phContext,PSecBufferDesc pInput,ULONG fContextReq,ULONG TargetDataRep,PCtxtHandle phNewContext,PSecBufferDesc pOutput,PULONG pfContextAttr,PTimeStamp ptsTimeStamp)714 SECURITY_STATUS SEC_ENTRY sspi_AcceptSecurityContext(PCredHandle phCredential,
715                                                      PCtxtHandle phContext, PSecBufferDesc pInput,
716                                                      ULONG fContextReq, ULONG TargetDataRep,
717                                                      PCtxtHandle phNewContext,
718                                                      PSecBufferDesc pOutput, PULONG pfContextAttr,
719                                                      PTimeStamp ptsTimeStamp)
720 {
721 	SECURITY_STATUS status;
722 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
723 
724 	if (!(g_SspiW && g_SspiW->AcceptSecurityContext))
725 	{
726 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
727 		           __FUNCTION__);
728 		return SEC_E_UNSUPPORTED_FUNCTION;
729 	}
730 
731 	status =
732 	    g_SspiW->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
733 	                                   phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
734 	WLog_Print(g_Log, WLOG_DEBUG, "AcceptSecurityContext: %s (0x%08" PRIX32 ")",
735 	           GetSecurityStatusString(status), status);
736 	return status;
737 }
738 
sspi_ApplyControlToken(PCtxtHandle phContext,PSecBufferDesc pInput)739 SECURITY_STATUS SEC_ENTRY sspi_ApplyControlToken(PCtxtHandle phContext, PSecBufferDesc pInput)
740 {
741 	SECURITY_STATUS status;
742 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
743 
744 	if (!(g_SspiW && g_SspiW->ApplyControlToken))
745 	{
746 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
747 		           __FUNCTION__);
748 		return SEC_E_UNSUPPORTED_FUNCTION;
749 	}
750 
751 	status = g_SspiW->ApplyControlToken(phContext, pInput);
752 	WLog_Print(g_Log, WLOG_DEBUG, "ApplyControlToken: %s (0x%08" PRIX32 ")",
753 	           GetSecurityStatusString(status), status);
754 	return status;
755 }
756 
sspi_CompleteAuthToken(PCtxtHandle phContext,PSecBufferDesc pToken)757 SECURITY_STATUS SEC_ENTRY sspi_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
758 {
759 	SECURITY_STATUS status;
760 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
761 
762 	if (!(g_SspiW && g_SspiW->CompleteAuthToken))
763 	{
764 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
765 		           __FUNCTION__);
766 		return SEC_E_UNSUPPORTED_FUNCTION;
767 	}
768 
769 	status = g_SspiW->CompleteAuthToken(phContext, pToken);
770 	WLog_Print(g_Log, WLOG_DEBUG, "CompleteAuthToken: %s (0x%08" PRIX32 ")",
771 	           GetSecurityStatusString(status), status);
772 	return status;
773 }
774 
sspi_DeleteSecurityContext(PCtxtHandle phContext)775 SECURITY_STATUS SEC_ENTRY sspi_DeleteSecurityContext(PCtxtHandle phContext)
776 {
777 	SECURITY_STATUS status;
778 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
779 
780 	if (!(g_SspiW && g_SspiW->DeleteSecurityContext))
781 	{
782 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
783 		           __FUNCTION__);
784 		return SEC_E_UNSUPPORTED_FUNCTION;
785 	}
786 
787 	status = g_SspiW->DeleteSecurityContext(phContext);
788 	WLog_Print(g_Log, WLOG_DEBUG, "DeleteSecurityContext: %s (0x%08" PRIX32 ")",
789 	           GetSecurityStatusString(status), status);
790 	return status;
791 }
792 
sspi_FreeContextBuffer(void * pvContextBuffer)793 SECURITY_STATUS SEC_ENTRY sspi_FreeContextBuffer(void* pvContextBuffer)
794 {
795 	SECURITY_STATUS status;
796 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
797 
798 	if (!(g_SspiW && g_SspiW->FreeContextBuffer))
799 	{
800 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
801 		           __FUNCTION__);
802 		return SEC_E_UNSUPPORTED_FUNCTION;
803 	}
804 
805 	status = g_SspiW->FreeContextBuffer(pvContextBuffer);
806 	WLog_Print(g_Log, WLOG_DEBUG, "FreeContextBuffer: %s (0x%08" PRIX32 ")",
807 	           GetSecurityStatusString(status), status);
808 	return status;
809 }
810 
sspi_ImpersonateSecurityContext(PCtxtHandle phContext)811 SECURITY_STATUS SEC_ENTRY sspi_ImpersonateSecurityContext(PCtxtHandle phContext)
812 {
813 	SECURITY_STATUS status;
814 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
815 
816 	if (!(g_SspiW && g_SspiW->ImpersonateSecurityContext))
817 	{
818 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
819 		           __FUNCTION__);
820 		return SEC_E_UNSUPPORTED_FUNCTION;
821 	}
822 
823 	status = g_SspiW->ImpersonateSecurityContext(phContext);
824 	WLog_Print(g_Log, WLOG_DEBUG, "ImpersonateSecurityContext: %s (0x%08" PRIX32 ")",
825 	           GetSecurityStatusString(status), status);
826 	return status;
827 }
828 
sspi_InitializeSecurityContextW(PCredHandle phCredential,PCtxtHandle phContext,SEC_WCHAR * pszTargetName,ULONG fContextReq,ULONG Reserved1,ULONG TargetDataRep,PSecBufferDesc pInput,ULONG Reserved2,PCtxtHandle phNewContext,PSecBufferDesc pOutput,PULONG pfContextAttr,PTimeStamp ptsExpiry)829 SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextW(
830     PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
831     ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
832     PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
833 {
834 	SECURITY_STATUS status;
835 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
836 
837 	if (!(g_SspiW && g_SspiW->InitializeSecurityContextW))
838 	{
839 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
840 		           __FUNCTION__);
841 		return SEC_E_UNSUPPORTED_FUNCTION;
842 	}
843 
844 	status = g_SspiW->InitializeSecurityContextW(
845 	    phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
846 	    Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
847 	WLog_Print(g_Log, WLOG_DEBUG, "InitializeSecurityContextW: %s (0x%08" PRIX32 ")",
848 	           GetSecurityStatusString(status), status);
849 	return status;
850 }
851 
sspi_InitializeSecurityContextA(PCredHandle phCredential,PCtxtHandle phContext,SEC_CHAR * pszTargetName,ULONG fContextReq,ULONG Reserved1,ULONG TargetDataRep,PSecBufferDesc pInput,ULONG Reserved2,PCtxtHandle phNewContext,PSecBufferDesc pOutput,PULONG pfContextAttr,PTimeStamp ptsExpiry)852 SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextA(
853     PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
854     ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
855     PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
856 {
857 	SECURITY_STATUS status;
858 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
859 
860 	if (!(g_SspiA && g_SspiA->InitializeSecurityContextA))
861 	{
862 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
863 		           __FUNCTION__);
864 		return SEC_E_UNSUPPORTED_FUNCTION;
865 	}
866 
867 	status = g_SspiA->InitializeSecurityContextA(
868 	    phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
869 	    Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
870 	WLog_Print(g_Log, WLOG_DEBUG, "InitializeSecurityContextA: %s (0x%08" PRIX32 ")",
871 	           GetSecurityStatusString(status), status);
872 	return status;
873 }
874 
sspi_QueryContextAttributesW(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer)875 SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
876                                                        void* pBuffer)
877 {
878 	SECURITY_STATUS status;
879 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
880 
881 	if (!(g_SspiW && g_SspiW->QueryContextAttributesW))
882 	{
883 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
884 		           __FUNCTION__);
885 		return SEC_E_UNSUPPORTED_FUNCTION;
886 	}
887 
888 	status = g_SspiW->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
889 	WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesW: %s (0x%08" PRIX32 ")",
890 	           GetSecurityStatusString(status), status);
891 	return status;
892 }
893 
sspi_QueryContextAttributesA(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer)894 SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
895                                                        void* pBuffer)
896 {
897 	SECURITY_STATUS status;
898 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
899 
900 	if (!(g_SspiA && g_SspiA->QueryContextAttributesA))
901 	{
902 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
903 		           __FUNCTION__);
904 		return SEC_E_UNSUPPORTED_FUNCTION;
905 	}
906 
907 	status = g_SspiA->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
908 	WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesA: %s (0x%08" PRIX32 ")",
909 	           GetSecurityStatusString(status), status);
910 	return status;
911 }
912 
sspi_QuerySecurityContextToken(PCtxtHandle phContext,HANDLE * phToken)913 SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityContextToken(PCtxtHandle phContext, HANDLE* phToken)
914 {
915 	SECURITY_STATUS status;
916 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
917 
918 	if (!(g_SspiW && g_SspiW->QuerySecurityContextToken))
919 	{
920 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
921 		           __FUNCTION__);
922 		return SEC_E_UNSUPPORTED_FUNCTION;
923 	}
924 
925 	status = g_SspiW->QuerySecurityContextToken(phContext, phToken);
926 	WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityContextToken: %s (0x%08" PRIX32 ")",
927 	           GetSecurityStatusString(status), status);
928 	return status;
929 }
930 
sspi_SetContextAttributesW(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer,ULONG cbBuffer)931 SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
932                                                      void* pBuffer, ULONG cbBuffer)
933 {
934 	SECURITY_STATUS status;
935 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
936 
937 	if (!(g_SspiW && g_SspiW->SetContextAttributesW))
938 	{
939 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
940 		           __FUNCTION__);
941 		return SEC_E_UNSUPPORTED_FUNCTION;
942 	}
943 
944 	status = g_SspiW->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
945 	WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesW: %s (0x%08" PRIX32 ")",
946 	           GetSecurityStatusString(status), status);
947 	return status;
948 }
949 
sspi_SetContextAttributesA(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer,ULONG cbBuffer)950 SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
951                                                      void* pBuffer, ULONG cbBuffer)
952 {
953 	SECURITY_STATUS status;
954 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
955 
956 	if (!(g_SspiA && g_SspiA->SetContextAttributesA))
957 	{
958 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
959 		           __FUNCTION__);
960 		return SEC_E_UNSUPPORTED_FUNCTION;
961 	}
962 
963 	status = g_SspiA->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
964 	WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesA: %s (0x%08" PRIX32 ")",
965 	           GetSecurityStatusString(status), status);
966 	return status;
967 }
968 
sspi_RevertSecurityContext(PCtxtHandle phContext)969 SECURITY_STATUS SEC_ENTRY sspi_RevertSecurityContext(PCtxtHandle phContext)
970 {
971 	SECURITY_STATUS status;
972 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
973 
974 	if (!(g_SspiW && g_SspiW->RevertSecurityContext))
975 	{
976 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
977 		           __FUNCTION__);
978 		return SEC_E_UNSUPPORTED_FUNCTION;
979 	}
980 
981 	status = g_SspiW->RevertSecurityContext(phContext);
982 	WLog_Print(g_Log, WLOG_DEBUG, "RevertSecurityContext: %s (0x%08" PRIX32 ")",
983 	           GetSecurityStatusString(status), status);
984 	return status;
985 }
986 
987 /* Message Support */
988 
sspi_DecryptMessage(PCtxtHandle phContext,PSecBufferDesc pMessage,ULONG MessageSeqNo,PULONG pfQOP)989 SECURITY_STATUS SEC_ENTRY sspi_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage,
990                                               ULONG MessageSeqNo, PULONG pfQOP)
991 {
992 	SECURITY_STATUS status;
993 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
994 
995 	if (!(g_SspiW && g_SspiW->DecryptMessage))
996 	{
997 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
998 		           __FUNCTION__);
999 		return SEC_E_UNSUPPORTED_FUNCTION;
1000 	}
1001 
1002 	status = g_SspiW->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
1003 	WLog_Print(g_Log, WLOG_DEBUG, "DecryptMessage: %s (0x%08" PRIX32 ")",
1004 	           GetSecurityStatusString(status), status);
1005 	return status;
1006 }
1007 
sspi_EncryptMessage(PCtxtHandle phContext,ULONG fQOP,PSecBufferDesc pMessage,ULONG MessageSeqNo)1008 SECURITY_STATUS SEC_ENTRY sspi_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
1009                                               PSecBufferDesc pMessage, ULONG MessageSeqNo)
1010 {
1011 	SECURITY_STATUS status;
1012 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1013 
1014 	if (!(g_SspiW && g_SspiW->EncryptMessage))
1015 	{
1016 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
1017 		           __FUNCTION__);
1018 		return SEC_E_UNSUPPORTED_FUNCTION;
1019 	}
1020 
1021 	status = g_SspiW->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
1022 	WLog_Print(g_Log, WLOG_DEBUG, "EncryptMessage: %s (0x%08" PRIX32 ")",
1023 	           GetSecurityStatusString(status), status);
1024 	return status;
1025 }
1026 
sspi_MakeSignature(PCtxtHandle phContext,ULONG fQOP,PSecBufferDesc pMessage,ULONG MessageSeqNo)1027 SECURITY_STATUS SEC_ENTRY sspi_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
1028                                              PSecBufferDesc pMessage, ULONG MessageSeqNo)
1029 {
1030 	SECURITY_STATUS status;
1031 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1032 
1033 	if (!(g_SspiW && g_SspiW->MakeSignature))
1034 	{
1035 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
1036 		           __FUNCTION__);
1037 		return SEC_E_UNSUPPORTED_FUNCTION;
1038 	}
1039 
1040 	status = g_SspiW->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
1041 	WLog_Print(g_Log, WLOG_DEBUG, "MakeSignature: %s (0x%08" PRIX32 ")",
1042 	           GetSecurityStatusString(status), status);
1043 	return status;
1044 }
1045 
sspi_VerifySignature(PCtxtHandle phContext,PSecBufferDesc pMessage,ULONG MessageSeqNo,PULONG pfQOP)1046 SECURITY_STATUS SEC_ENTRY sspi_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage,
1047                                                ULONG MessageSeqNo, PULONG pfQOP)
1048 {
1049 	SECURITY_STATUS status;
1050 	InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1051 
1052 	if (!(g_SspiW && g_SspiW->VerifySignature))
1053 	{
1054 		WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation",
1055 		           __FUNCTION__);
1056 		return SEC_E_UNSUPPORTED_FUNCTION;
1057 	}
1058 
1059 	status = g_SspiW->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
1060 	WLog_Print(g_Log, WLOG_DEBUG, "VerifySignature: %s (0x%08" PRIX32 ")",
1061 	           GetSecurityStatusString(status), status);
1062 	return status;
1063 }
1064 
1065 SecurityFunctionTableA sspi_SecurityFunctionTableA = {
1066 	1,                                /* dwVersion */
1067 	sspi_EnumerateSecurityPackagesA,  /* EnumerateSecurityPackages */
1068 	sspi_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
1069 	sspi_AcquireCredentialsHandleA,   /* AcquireCredentialsHandle */
1070 	sspi_FreeCredentialsHandle,       /* FreeCredentialsHandle */
1071 	NULL,                             /* Reserved2 */
1072 	sspi_InitializeSecurityContextA,  /* InitializeSecurityContext */
1073 	sspi_AcceptSecurityContext,       /* AcceptSecurityContext */
1074 	sspi_CompleteAuthToken,           /* CompleteAuthToken */
1075 	sspi_DeleteSecurityContext,       /* DeleteSecurityContext */
1076 	sspi_ApplyControlToken,           /* ApplyControlToken */
1077 	sspi_QueryContextAttributesA,     /* QueryContextAttributes */
1078 	sspi_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
1079 	sspi_RevertSecurityContext,       /* RevertSecurityContext */
1080 	sspi_MakeSignature,               /* MakeSignature */
1081 	sspi_VerifySignature,             /* VerifySignature */
1082 	sspi_FreeContextBuffer,           /* FreeContextBuffer */
1083 	sspi_QuerySecurityPackageInfoA,   /* QuerySecurityPackageInfo */
1084 	NULL,                             /* Reserved3 */
1085 	NULL,                             /* Reserved4 */
1086 	sspi_ExportSecurityContext,       /* ExportSecurityContext */
1087 	sspi_ImportSecurityContextA,      /* ImportSecurityContext */
1088 	NULL,                             /* AddCredentials */
1089 	NULL,                             /* Reserved8 */
1090 	sspi_QuerySecurityContextToken,   /* QuerySecurityContextToken */
1091 	sspi_EncryptMessage,              /* EncryptMessage */
1092 	sspi_DecryptMessage,              /* DecryptMessage */
1093 	sspi_SetContextAttributesA,       /* SetContextAttributes */
1094 };
1095 
1096 SecurityFunctionTableW sspi_SecurityFunctionTableW = {
1097 	1,                                /* dwVersion */
1098 	sspi_EnumerateSecurityPackagesW,  /* EnumerateSecurityPackages */
1099 	sspi_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
1100 	sspi_AcquireCredentialsHandleW,   /* AcquireCredentialsHandle */
1101 	sspi_FreeCredentialsHandle,       /* FreeCredentialsHandle */
1102 	NULL,                             /* Reserved2 */
1103 	sspi_InitializeSecurityContextW,  /* InitializeSecurityContext */
1104 	sspi_AcceptSecurityContext,       /* AcceptSecurityContext */
1105 	sspi_CompleteAuthToken,           /* CompleteAuthToken */
1106 	sspi_DeleteSecurityContext,       /* DeleteSecurityContext */
1107 	sspi_ApplyControlToken,           /* ApplyControlToken */
1108 	sspi_QueryContextAttributesW,     /* QueryContextAttributes */
1109 	sspi_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
1110 	sspi_RevertSecurityContext,       /* RevertSecurityContext */
1111 	sspi_MakeSignature,               /* MakeSignature */
1112 	sspi_VerifySignature,             /* VerifySignature */
1113 	sspi_FreeContextBuffer,           /* FreeContextBuffer */
1114 	sspi_QuerySecurityPackageInfoW,   /* QuerySecurityPackageInfo */
1115 	NULL,                             /* Reserved3 */
1116 	NULL,                             /* Reserved4 */
1117 	sspi_ExportSecurityContext,       /* ExportSecurityContext */
1118 	sspi_ImportSecurityContextW,      /* ImportSecurityContext */
1119 	NULL,                             /* AddCredentials */
1120 	NULL,                             /* Reserved8 */
1121 	sspi_QuerySecurityContextToken,   /* QuerySecurityContextToken */
1122 	sspi_EncryptMessage,              /* EncryptMessage */
1123 	sspi_DecryptMessage,              /* DecryptMessage */
1124 	sspi_SetContextAttributesW,       /* SetContextAttributes */
1125 };
1126