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  * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <winpr/windows.h>
26 
27 #include <winpr/crt.h>
28 #include <winpr/sspi.h>
29 #include <winpr/ssl.h>
30 #include <winpr/print.h>
31 
32 #include "sspi.h"
33 
34 #include "sspi_winpr.h"
35 
36 #include "../log.h"
37 #define TAG WINPR_TAG("sspi")
38 
39 /* Authentication Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731/ */
40 
41 extern const SecPkgInfoA NTLM_SecPkgInfoA;
42 extern const SecPkgInfoW NTLM_SecPkgInfoW;
43 extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
44 extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
45 
46 extern const SecPkgInfoA KERBEROS_SecPkgInfoA;
47 extern const SecPkgInfoW KERBEROS_SecPkgInfoW;
48 extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA;
49 extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW;
50 
51 extern const SecPkgInfoA NEGOTIATE_SecPkgInfoA;
52 extern const SecPkgInfoW NEGOTIATE_SecPkgInfoW;
53 extern const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA;
54 extern const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW;
55 
56 extern const SecPkgInfoA CREDSSP_SecPkgInfoA;
57 extern const SecPkgInfoW CREDSSP_SecPkgInfoW;
58 extern const SecurityFunctionTableA CREDSSP_SecurityFunctionTableA;
59 extern const SecurityFunctionTableW CREDSSP_SecurityFunctionTableW;
60 
61 extern const SecPkgInfoA SCHANNEL_SecPkgInfoA;
62 extern const SecPkgInfoW SCHANNEL_SecPkgInfoW;
63 extern const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA;
64 extern const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW;
65 
66 static const SecPkgInfoA* SecPkgInfoA_LIST[] = { &NTLM_SecPkgInfoA, &KERBEROS_SecPkgInfoA,
67 	                                             &NEGOTIATE_SecPkgInfoA, &CREDSSP_SecPkgInfoA,
68 	                                             &SCHANNEL_SecPkgInfoA };
69 
70 static const SecPkgInfoW* SecPkgInfoW_LIST[] = { &NTLM_SecPkgInfoW, &KERBEROS_SecPkgInfoW,
71 	                                             &NEGOTIATE_SecPkgInfoW, &CREDSSP_SecPkgInfoW,
72 	                                             &SCHANNEL_SecPkgInfoW };
73 
74 static SecurityFunctionTableA winpr_SecurityFunctionTableA;
75 static SecurityFunctionTableW winpr_SecurityFunctionTableW;
76 
77 struct _SecurityFunctionTableA_NAME
78 {
79 	const SEC_CHAR* Name;
80 	const SecurityFunctionTableA* SecurityFunctionTable;
81 };
82 typedef struct _SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME;
83 
84 struct _SecurityFunctionTableW_NAME
85 {
86 	const SEC_WCHAR* Name;
87 	const SecurityFunctionTableW* SecurityFunctionTable;
88 };
89 typedef struct _SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME;
90 
91 static const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = {
92 	{ "NTLM", &NTLM_SecurityFunctionTableA },
93 	{ "Kerberos", &KERBEROS_SecurityFunctionTableA },
94 	{ "Negotiate", &NEGOTIATE_SecurityFunctionTableA },
95 	{ "CREDSSP", &CREDSSP_SecurityFunctionTableA },
96 	{ "Schannel", &SCHANNEL_SecurityFunctionTableA }
97 };
98 
99 static const WCHAR NTLM_NAME_W[] = { 'N', 'T', 'L', 'M', '\0' };
100 static const WCHAR KERBEROS_NAME_W[] = { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', '\0' };
101 static const WCHAR NEGOTIATE_NAME_W[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' };
102 static const WCHAR CREDSSP_NAME_W[] = { 'C', 'r', 'e', 'd', 'S', 'S', 'P', '\0' };
103 static const WCHAR SCHANNEL_NAME_W[] = { 'S', 'c', 'h', 'a', 'n', 'n', 'e', 'l', '\0' };
104 
105 static const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = {
106 	{ NTLM_NAME_W, &NTLM_SecurityFunctionTableW },
107 	{ KERBEROS_NAME_W, &KERBEROS_SecurityFunctionTableW },
108 	{ NEGOTIATE_NAME_W, &NEGOTIATE_SecurityFunctionTableW },
109 	{ CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW },
110 	{ SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW }
111 };
112 
113 #define SecHandle_LOWER_MAX 0xFFFFFFFF
114 #define SecHandle_UPPER_MAX 0xFFFFFFFE
115 
116 struct _CONTEXT_BUFFER_ALLOC_ENTRY
117 {
118 	void* contextBuffer;
119 	UINT32 allocatorIndex;
120 };
121 typedef struct _CONTEXT_BUFFER_ALLOC_ENTRY CONTEXT_BUFFER_ALLOC_ENTRY;
122 
123 struct _CONTEXT_BUFFER_ALLOC_TABLE
124 {
125 	UINT32 cEntries;
126 	UINT32 cMaxEntries;
127 	CONTEXT_BUFFER_ALLOC_ENTRY* entries;
128 };
129 typedef struct _CONTEXT_BUFFER_ALLOC_TABLE CONTEXT_BUFFER_ALLOC_TABLE;
130 
131 static CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable = { 0 };
132 
sspi_ContextBufferAllocTableNew(void)133 static int sspi_ContextBufferAllocTableNew(void)
134 {
135 	size_t size;
136 	ContextBufferAllocTable.entries = NULL;
137 	ContextBufferAllocTable.cEntries = 0;
138 	ContextBufferAllocTable.cMaxEntries = 4;
139 	size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
140 	ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)calloc(1, size);
141 
142 	if (!ContextBufferAllocTable.entries)
143 		return -1;
144 
145 	return 1;
146 }
147 
sspi_ContextBufferAllocTableGrow(void)148 static int sspi_ContextBufferAllocTableGrow(void)
149 {
150 	size_t size;
151 	CONTEXT_BUFFER_ALLOC_ENTRY* entries;
152 	ContextBufferAllocTable.cEntries = 0;
153 	ContextBufferAllocTable.cMaxEntries *= 2;
154 	size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
155 
156 	if (!size)
157 		return -1;
158 
159 	entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)realloc(ContextBufferAllocTable.entries, size);
160 
161 	if (!entries)
162 	{
163 		free(ContextBufferAllocTable.entries);
164 		return -1;
165 	}
166 
167 	ContextBufferAllocTable.entries = entries;
168 	ZeroMemory((void*)&ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2],
169 	           size / 2);
170 	return 1;
171 }
172 
sspi_ContextBufferAllocTableFree(void)173 static void sspi_ContextBufferAllocTableFree(void)
174 {
175 	if (ContextBufferAllocTable.cEntries != 0)
176 		WLog_ERR(TAG, "ContextBufferAllocTable.entries == %" PRIu32,
177 		         ContextBufferAllocTable.cEntries);
178 
179 	ContextBufferAllocTable.cEntries = ContextBufferAllocTable.cMaxEntries = 0;
180 	free(ContextBufferAllocTable.entries);
181 	ContextBufferAllocTable.entries = NULL;
182 }
183 
sspi_ContextBufferAlloc(UINT32 allocatorIndex,size_t size)184 static void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
185 {
186 	UINT32 index;
187 	void* contextBuffer;
188 
189 	for (index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
190 	{
191 		if (!ContextBufferAllocTable.entries[index].contextBuffer)
192 		{
193 			contextBuffer = calloc(1, size);
194 
195 			if (!contextBuffer)
196 				return NULL;
197 
198 			ContextBufferAllocTable.cEntries++;
199 			ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer;
200 			ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex;
201 			return ContextBufferAllocTable.entries[index].contextBuffer;
202 		}
203 	}
204 
205 	/* no available entry was found, the table needs to be grown */
206 
207 	if (sspi_ContextBufferAllocTableGrow() < 0)
208 		return NULL;
209 
210 	/* the next call to sspi_ContextBufferAlloc() should now succeed */
211 	return sspi_ContextBufferAlloc(allocatorIndex, size);
212 }
213 
sspi_CredentialsNew(void)214 SSPI_CREDENTIALS* sspi_CredentialsNew(void)
215 {
216 	SSPI_CREDENTIALS* credentials;
217 	credentials = (SSPI_CREDENTIALS*)calloc(1, sizeof(SSPI_CREDENTIALS));
218 	return credentials;
219 }
220 
sspi_CredentialsFree(SSPI_CREDENTIALS * credentials)221 void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
222 {
223 	size_t userLength = 0;
224 	size_t domainLength = 0;
225 	size_t passwordLength = 0;
226 
227 	if (!credentials)
228 		return;
229 
230 	userLength = credentials->identity.UserLength;
231 	domainLength = credentials->identity.DomainLength;
232 	passwordLength = credentials->identity.PasswordLength;
233 
234 	if (passwordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET) /* [pth] */
235 		passwordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
236 
237 	if (credentials->identity.Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
238 	{
239 		userLength *= 2;
240 		domainLength *= 2;
241 		passwordLength *= 2;
242 	}
243 
244 	if (credentials->identity.User)
245 		memset(credentials->identity.User, 0, userLength);
246 	if (credentials->identity.Domain)
247 		memset(credentials->identity.Domain, 0, domainLength);
248 	if (credentials->identity.Password)
249 		memset(credentials->identity.Password, 0, passwordLength);
250 	free(credentials->identity.User);
251 	free(credentials->identity.Domain);
252 	free(credentials->identity.Password);
253 	free(credentials);
254 }
255 
sspi_SecBufferAlloc(PSecBuffer SecBuffer,ULONG size)256 void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size)
257 {
258 	if (!SecBuffer)
259 		return NULL;
260 
261 	SecBuffer->pvBuffer = calloc(1, size);
262 
263 	if (!SecBuffer->pvBuffer)
264 		return NULL;
265 
266 	SecBuffer->cbBuffer = size;
267 	return SecBuffer->pvBuffer;
268 }
269 
sspi_SecBufferFree(PSecBuffer SecBuffer)270 void sspi_SecBufferFree(PSecBuffer SecBuffer)
271 {
272 	if (!SecBuffer)
273 		return;
274 
275 	if (SecBuffer->pvBuffer)
276 		memset(SecBuffer->pvBuffer, 0, SecBuffer->cbBuffer);
277 
278 	free(SecBuffer->pvBuffer);
279 	SecBuffer->pvBuffer = NULL;
280 	SecBuffer->cbBuffer = 0;
281 }
282 
sspi_SecureHandleAlloc(void)283 SecHandle* sspi_SecureHandleAlloc(void)
284 {
285 	SecHandle* handle = (SecHandle*)calloc(1, sizeof(SecHandle));
286 
287 	if (!handle)
288 		return NULL;
289 
290 	SecInvalidateHandle(handle);
291 	return handle;
292 }
293 
sspi_SecureHandleGetLowerPointer(SecHandle * handle)294 void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
295 {
296 	void* pointer;
297 
298 	if (!handle || !SecIsValidHandle(handle) || !handle->dwLower)
299 		return NULL;
300 
301 	pointer = (void*)~((size_t)handle->dwLower);
302 	return pointer;
303 }
304 
sspi_SecureHandleInvalidate(SecHandle * handle)305 void sspi_SecureHandleInvalidate(SecHandle* handle)
306 {
307 	if (!handle)
308 		return;
309 
310 	handle->dwLower = 0;
311 	handle->dwUpper = 0;
312 }
313 
sspi_SecureHandleSetLowerPointer(SecHandle * handle,void * pointer)314 void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer)
315 {
316 	if (!handle)
317 		return;
318 
319 	handle->dwLower = (ULONG_PTR)(~((size_t)pointer));
320 }
321 
sspi_SecureHandleGetUpperPointer(SecHandle * handle)322 void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
323 {
324 	void* pointer;
325 
326 	if (!handle || !SecIsValidHandle(handle) || !handle->dwUpper)
327 		return NULL;
328 
329 	pointer = (void*)~((size_t)handle->dwUpper);
330 	return pointer;
331 }
332 
sspi_SecureHandleSetUpperPointer(SecHandle * handle,void * pointer)333 void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer)
334 {
335 	if (!handle)
336 		return;
337 
338 	handle->dwUpper = (ULONG_PTR)(~((size_t)pointer));
339 }
340 
sspi_SecureHandleFree(SecHandle * handle)341 void sspi_SecureHandleFree(SecHandle* handle)
342 {
343 	free(handle);
344 }
345 
sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY * identity,const char * user,const char * domain,const char * password)346 int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain,
347                          const char* password)
348 {
349 	int rc;
350 	int unicodePasswordLenW;
351 	LPWSTR unicodePassword = NULL;
352 	unicodePasswordLenW = ConvertToUnicode(CP_UTF8, 0, password, -1, &unicodePassword, 0);
353 
354 	if (unicodePasswordLenW <= 0)
355 		return -1;
356 
357 	rc = sspi_SetAuthIdentityWithUnicodePassword(identity, user, domain, unicodePassword,
358 	                                             (ULONG)(unicodePasswordLenW - 1));
359 	free(unicodePassword);
360 	return rc;
361 }
362 
sspi_SetAuthIdentityWithUnicodePassword(SEC_WINNT_AUTH_IDENTITY * identity,const char * user,const char * domain,LPWSTR password,ULONG passwordLength)363 int sspi_SetAuthIdentityWithUnicodePassword(SEC_WINNT_AUTH_IDENTITY* identity, const char* user,
364                                             const char* domain, LPWSTR password,
365                                             ULONG passwordLength)
366 {
367 	int status;
368 	identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
369 	free(identity->User);
370 	identity->User = (UINT16*)NULL;
371 	identity->UserLength = 0;
372 
373 	if (user)
374 	{
375 		status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*)&(identity->User), 0);
376 
377 		if (status <= 0)
378 			return -1;
379 
380 		identity->UserLength = (ULONG)(status - 1);
381 	}
382 
383 	free(identity->Domain);
384 	identity->Domain = (UINT16*)NULL;
385 	identity->DomainLength = 0;
386 
387 	if (domain)
388 	{
389 		status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*)&(identity->Domain), 0);
390 
391 		if (status <= 0)
392 			return -1;
393 
394 		identity->DomainLength = (ULONG)(status - 1);
395 	}
396 
397 	free(identity->Password);
398 	identity->Password = (UINT16*)calloc(1, (passwordLength + 1) * sizeof(WCHAR));
399 
400 	if (!identity->Password)
401 		return -1;
402 
403 	CopyMemory(identity->Password, password, passwordLength * sizeof(WCHAR));
404 	identity->PasswordLength = passwordLength;
405 	return 1;
406 }
407 
sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY * identity,SEC_WINNT_AUTH_IDENTITY * srcIdentity)408 int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity)
409 {
410 	int status;
411 
412 	if (srcIdentity->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
413 	{
414 		status = sspi_SetAuthIdentity(identity, (char*)srcIdentity->User,
415 		                              (char*)srcIdentity->Domain, (char*)srcIdentity->Password);
416 
417 		if (status <= 0)
418 			return -1;
419 
420 		identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
421 		identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
422 		return 1;
423 	}
424 
425 	identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
426 	/* login/password authentication */
427 	identity->User = identity->Domain = identity->Password = NULL;
428 	identity->UserLength = srcIdentity->UserLength;
429 
430 	if (identity->UserLength > 0)
431 	{
432 		identity->User = (UINT16*)calloc((identity->UserLength + 1), sizeof(WCHAR));
433 
434 		if (!identity->User)
435 			return -1;
436 
437 		CopyMemory(identity->User, srcIdentity->User, identity->UserLength * sizeof(WCHAR));
438 		identity->User[identity->UserLength] = 0;
439 	}
440 
441 	identity->DomainLength = srcIdentity->DomainLength;
442 
443 	if (identity->DomainLength > 0)
444 	{
445 		identity->Domain = (UINT16*)calloc((identity->DomainLength + 1), sizeof(WCHAR));
446 
447 		if (!identity->Domain)
448 			return -1;
449 
450 		CopyMemory(identity->Domain, srcIdentity->Domain, identity->DomainLength * sizeof(WCHAR));
451 		identity->Domain[identity->DomainLength] = 0;
452 	}
453 
454 	identity->PasswordLength = srcIdentity->PasswordLength;
455 
456 	if (identity->PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
457 		identity->PasswordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
458 
459 	if (srcIdentity->Password)
460 	{
461 		identity->Password = (UINT16*)calloc((identity->PasswordLength + 1), sizeof(WCHAR));
462 
463 		if (!identity->Password)
464 			return -1;
465 
466 		CopyMemory(identity->Password, srcIdentity->Password,
467 		           identity->PasswordLength * sizeof(WCHAR));
468 		identity->Password[identity->PasswordLength] = 0;
469 	}
470 
471 	identity->PasswordLength = srcIdentity->PasswordLength;
472 	/* End of login/password authentication */
473 	return 1;
474 }
475 
sspi_FindSecBuffer(PSecBufferDesc pMessage,ULONG BufferType)476 PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType)
477 {
478 	ULONG index;
479 	PSecBuffer pSecBuffer = NULL;
480 
481 	for (index = 0; index < pMessage->cBuffers; index++)
482 	{
483 		if (pMessage->pBuffers[index].BufferType == BufferType)
484 		{
485 			pSecBuffer = &pMessage->pBuffers[index];
486 			break;
487 		}
488 	}
489 
490 	return pSecBuffer;
491 }
492 
sspi_init(PINIT_ONCE InitOnce,PVOID Parameter,PVOID * Context)493 static BOOL CALLBACK sspi_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context)
494 {
495 	winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
496 	sspi_ContextBufferAllocTableNew();
497 	return TRUE;
498 }
499 
sspi_GlobalInit(void)500 void sspi_GlobalInit(void)
501 {
502 	static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
503 	DWORD flags = 0;
504 	InitOnceExecuteOnce(&once, sspi_init, &flags, NULL);
505 }
506 
sspi_GlobalFinish(void)507 void sspi_GlobalFinish(void)
508 {
509 	sspi_ContextBufferAllocTableFree();
510 }
511 
sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR * Name)512 static SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name)
513 {
514 	int index;
515 	UINT32 cPackages;
516 	cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
517 
518 	for (index = 0; index < (int)cPackages; index++)
519 	{
520 		if (strcmp(Name, SecurityFunctionTableA_NAME_LIST[index].Name) == 0)
521 		{
522 			return (SecurityFunctionTableA*)SecurityFunctionTableA_NAME_LIST[index]
523 			    .SecurityFunctionTable;
524 		}
525 	}
526 
527 	return NULL;
528 }
529 
sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR * Name)530 static SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name)
531 {
532 	int index;
533 	UINT32 cPackages;
534 	cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
535 
536 	for (index = 0; index < (int)cPackages; index++)
537 	{
538 		if (lstrcmpW(Name, SecurityFunctionTableW_NAME_LIST[index].Name) == 0)
539 		{
540 			return (SecurityFunctionTableW*)SecurityFunctionTableW_NAME_LIST[index]
541 			    .SecurityFunctionTable;
542 		}
543 	}
544 
545 	return NULL;
546 }
547 
sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR * Name)548 static SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name)
549 {
550 	int status;
551 	SEC_WCHAR* NameW = NULL;
552 	SecurityFunctionTableW* table;
553 	status = ConvertToUnicode(CP_UTF8, 0, Name, -1, &NameW, 0);
554 
555 	if (status <= 0)
556 		return NULL;
557 
558 	table = sspi_GetSecurityFunctionTableWByNameW(NameW);
559 	free(NameW);
560 	return table;
561 }
562 
563 static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
564 static void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
565 
sspi_ContextBufferFree(void * contextBuffer)566 static void sspi_ContextBufferFree(void* contextBuffer)
567 {
568 	UINT32 index;
569 	UINT32 allocatorIndex;
570 
571 	for (index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
572 	{
573 		if (contextBuffer == ContextBufferAllocTable.entries[index].contextBuffer)
574 		{
575 			contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer;
576 			allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex;
577 			ContextBufferAllocTable.cEntries--;
578 			ContextBufferAllocTable.entries[index].allocatorIndex = 0;
579 			ContextBufferAllocTable.entries[index].contextBuffer = NULL;
580 
581 			switch (allocatorIndex)
582 			{
583 				case EnumerateSecurityPackagesIndex:
584 					FreeContextBuffer_EnumerateSecurityPackages(contextBuffer);
585 					break;
586 
587 				case QuerySecurityPackageInfoIndex:
588 					FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer);
589 					break;
590 			}
591 		}
592 	}
593 }
594 
595 /**
596  * Standard SSPI API
597  */
598 
599 /* Package Management */
600 
winpr_EnumerateSecurityPackagesW(ULONG * pcPackages,PSecPkgInfoW * ppPackageInfo)601 static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages,
602                                                                   PSecPkgInfoW* ppPackageInfo)
603 {
604 	int index;
605 	size_t size;
606 	UINT32 cPackages;
607 	SecPkgInfoW* pPackageInfo;
608 	cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
609 	size = sizeof(SecPkgInfoW) * cPackages;
610 	pPackageInfo = (SecPkgInfoW*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
611 
612 	if (!pPackageInfo)
613 		return SEC_E_INSUFFICIENT_MEMORY;
614 
615 	for (index = 0; index < (int)cPackages; index++)
616 	{
617 		pPackageInfo[index].fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
618 		pPackageInfo[index].wVersion = SecPkgInfoW_LIST[index]->wVersion;
619 		pPackageInfo[index].wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
620 		pPackageInfo[index].cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
621 		pPackageInfo[index].Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
622 		pPackageInfo[index].Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
623 	}
624 
625 	*(pcPackages) = cPackages;
626 	*(ppPackageInfo) = pPackageInfo;
627 	return SEC_E_OK;
628 }
629 
winpr_EnumerateSecurityPackagesA(ULONG * pcPackages,PSecPkgInfoA * ppPackageInfo)630 static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages,
631                                                                   PSecPkgInfoA* ppPackageInfo)
632 {
633 	int index;
634 	size_t size;
635 	UINT32 cPackages;
636 	SecPkgInfoA* pPackageInfo;
637 	cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
638 	size = sizeof(SecPkgInfoA) * cPackages;
639 	pPackageInfo = (SecPkgInfoA*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
640 
641 	if (!pPackageInfo)
642 		return SEC_E_INSUFFICIENT_MEMORY;
643 
644 	for (index = 0; index < (int)cPackages; index++)
645 	{
646 		pPackageInfo[index].fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
647 		pPackageInfo[index].wVersion = SecPkgInfoA_LIST[index]->wVersion;
648 		pPackageInfo[index].wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
649 		pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
650 		pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name);
651 		pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
652 
653 		if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment)
654 		{
655 			sspi_ContextBufferFree(pPackageInfo);
656 			return SEC_E_INSUFFICIENT_MEMORY;
657 		}
658 	}
659 
660 	*(pcPackages) = cPackages;
661 	*(ppPackageInfo) = pPackageInfo;
662 	return SEC_E_OK;
663 }
664 
FreeContextBuffer_EnumerateSecurityPackages(void * contextBuffer)665 static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer)
666 {
667 	int index;
668 	UINT32 cPackages;
669 	SecPkgInfoA* pPackageInfo = (SecPkgInfoA*)contextBuffer;
670 	cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
671 
672 	if (!pPackageInfo)
673 		return;
674 
675 	for (index = 0; index < (int)cPackages; index++)
676 	{
677 		free(pPackageInfo[index].Name);
678 		free(pPackageInfo[index].Comment);
679 	}
680 
681 	free(pPackageInfo);
682 }
683 
winpr_InitSecurityInterfaceW(void)684 SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void)
685 {
686 	return &winpr_SecurityFunctionTableW;
687 }
688 
winpr_InitSecurityInterfaceA(void)689 SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void)
690 {
691 	return &winpr_SecurityFunctionTableA;
692 }
693 
winpr_QuerySecurityPackageInfoW(SEC_WCHAR * pszPackageName,PSecPkgInfoW * ppPackageInfo)694 static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
695                                                                  PSecPkgInfoW* ppPackageInfo)
696 {
697 	int index;
698 	size_t size;
699 	UINT32 cPackages;
700 	SecPkgInfoW* pPackageInfo;
701 	cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
702 
703 	for (index = 0; index < (int)cPackages; index++)
704 	{
705 		if (lstrcmpW(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
706 		{
707 			size = sizeof(SecPkgInfoW);
708 			pPackageInfo =
709 			    (SecPkgInfoW*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
710 
711 			if (!pPackageInfo)
712 				return SEC_E_INSUFFICIENT_MEMORY;
713 
714 			pPackageInfo->fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
715 			pPackageInfo->wVersion = SecPkgInfoW_LIST[index]->wVersion;
716 			pPackageInfo->wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
717 			pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
718 			pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
719 			pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
720 			*(ppPackageInfo) = pPackageInfo;
721 			return SEC_E_OK;
722 		}
723 	}
724 
725 	*(ppPackageInfo) = NULL;
726 	return SEC_E_SECPKG_NOT_FOUND;
727 }
728 
winpr_QuerySecurityPackageInfoA(SEC_CHAR * pszPackageName,PSecPkgInfoA * ppPackageInfo)729 static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
730                                                                  PSecPkgInfoA* ppPackageInfo)
731 {
732 	int index;
733 	size_t size;
734 	UINT32 cPackages;
735 	SecPkgInfoA* pPackageInfo;
736 	cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
737 
738 	for (index = 0; index < (int)cPackages; index++)
739 	{
740 		if (strcmp(pszPackageName, SecPkgInfoA_LIST[index]->Name) == 0)
741 		{
742 			size = sizeof(SecPkgInfoA);
743 			pPackageInfo =
744 			    (SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
745 
746 			if (!pPackageInfo)
747 				return SEC_E_INSUFFICIENT_MEMORY;
748 
749 			pPackageInfo->fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
750 			pPackageInfo->wVersion = SecPkgInfoA_LIST[index]->wVersion;
751 			pPackageInfo->wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
752 			pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
753 			pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name);
754 			pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
755 
756 			if (!pPackageInfo->Name || !pPackageInfo->Comment)
757 			{
758 				sspi_ContextBufferFree(pPackageInfo);
759 				return SEC_E_INSUFFICIENT_MEMORY;
760 			}
761 
762 			*(ppPackageInfo) = pPackageInfo;
763 			return SEC_E_OK;
764 		}
765 	}
766 
767 	*(ppPackageInfo) = NULL;
768 	return SEC_E_SECPKG_NOT_FOUND;
769 }
770 
FreeContextBuffer_QuerySecurityPackageInfo(void * contextBuffer)771 void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer)
772 {
773 	SecPkgInfo* pPackageInfo = (SecPkgInfo*)contextBuffer;
774 
775 	if (!pPackageInfo)
776 		return;
777 
778 	free(pPackageInfo->Name);
779 	free(pPackageInfo->Comment);
780 	free(pPackageInfo);
781 }
782 
783 /* Credential Management */
784 
winpr_AcquireCredentialsHandleW(SEC_WCHAR * pszPrincipal,SEC_WCHAR * pszPackage,ULONG fCredentialUse,void * pvLogonID,void * pAuthData,SEC_GET_KEY_FN pGetKeyFn,void * pvGetKeyArgument,PCredHandle phCredential,PTimeStamp ptsExpiry)785 static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(
786     SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
787     void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
788     PTimeStamp ptsExpiry)
789 {
790 	SECURITY_STATUS status;
791 	SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
792 
793 	if (!table)
794 		return SEC_E_SECPKG_NOT_FOUND;
795 
796 	if (!table->AcquireCredentialsHandleW)
797 	{
798 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
799 		return SEC_E_UNSUPPORTED_FUNCTION;
800 	}
801 
802 	status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
803 	                                          pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
804 	                                          ptsExpiry);
805 
806 	if (IsSecurityStatusError(status))
807 	{
808 		WLog_WARN(TAG, "AcquireCredentialsHandleW status %s [0x%08" PRIX32 "]",
809 		          GetSecurityStatusString(status), status);
810 	}
811 
812 	return status;
813 }
814 
winpr_AcquireCredentialsHandleA(SEC_CHAR * pszPrincipal,SEC_CHAR * pszPackage,ULONG fCredentialUse,void * pvLogonID,void * pAuthData,SEC_GET_KEY_FN pGetKeyFn,void * pvGetKeyArgument,PCredHandle phCredential,PTimeStamp ptsExpiry)815 static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(
816     SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
817     void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
818     PTimeStamp ptsExpiry)
819 {
820 	SECURITY_STATUS status;
821 	SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
822 
823 	if (!table)
824 		return SEC_E_SECPKG_NOT_FOUND;
825 
826 	if (!table->AcquireCredentialsHandleA)
827 	{
828 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
829 		return SEC_E_UNSUPPORTED_FUNCTION;
830 	}
831 
832 	status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
833 	                                          pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
834 	                                          ptsExpiry);
835 
836 	if (IsSecurityStatusError(status))
837 	{
838 		WLog_WARN(TAG, "AcquireCredentialsHandleA status %s [0x%08" PRIX32 "]",
839 		          GetSecurityStatusString(status), status);
840 	}
841 
842 	return status;
843 }
844 
winpr_ExportSecurityContext(PCtxtHandle phContext,ULONG fFlags,PSecBuffer pPackedContext,HANDLE * pToken)845 static SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
846                                                              PSecBuffer pPackedContext,
847                                                              HANDLE* pToken)
848 {
849 	SEC_CHAR* Name;
850 	SECURITY_STATUS status;
851 	SecurityFunctionTableW* table;
852 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
853 
854 	if (!Name)
855 		return SEC_E_SECPKG_NOT_FOUND;
856 
857 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
858 
859 	if (!table)
860 		return SEC_E_SECPKG_NOT_FOUND;
861 
862 	if (!table->ExportSecurityContext)
863 	{
864 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
865 		return SEC_E_UNSUPPORTED_FUNCTION;
866 	}
867 
868 	status = table->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
869 
870 	if (IsSecurityStatusError(status))
871 	{
872 		WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08" PRIX32 "]",
873 		          GetSecurityStatusString(status), status);
874 	}
875 
876 	return status;
877 }
878 
winpr_FreeCredentialsHandle(PCredHandle phCredential)879 static SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
880 {
881 	char* Name;
882 	SECURITY_STATUS status;
883 	SecurityFunctionTableA* table;
884 	Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
885 
886 	if (!Name)
887 		return SEC_E_SECPKG_NOT_FOUND;
888 
889 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
890 
891 	if (!table)
892 		return SEC_E_SECPKG_NOT_FOUND;
893 
894 	if (!table->FreeCredentialsHandle)
895 	{
896 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
897 		return SEC_E_UNSUPPORTED_FUNCTION;
898 	}
899 
900 	status = table->FreeCredentialsHandle(phCredential);
901 
902 	if (IsSecurityStatusError(status))
903 	{
904 		WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08" PRIX32 "]",
905 		          GetSecurityStatusString(status), status);
906 	}
907 
908 	return status;
909 }
910 
winpr_ImportSecurityContextW(SEC_WCHAR * pszPackage,PSecBuffer pPackedContext,HANDLE pToken,PCtxtHandle phContext)911 static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage,
912                                                               PSecBuffer pPackedContext,
913                                                               HANDLE pToken, PCtxtHandle phContext)
914 {
915 	SEC_CHAR* Name;
916 	SECURITY_STATUS status;
917 	SecurityFunctionTableW* table;
918 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
919 
920 	if (!Name)
921 		return SEC_E_SECPKG_NOT_FOUND;
922 
923 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
924 
925 	if (!table)
926 		return SEC_E_SECPKG_NOT_FOUND;
927 
928 	if (!table->ImportSecurityContextW)
929 	{
930 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
931 		return SEC_E_UNSUPPORTED_FUNCTION;
932 	}
933 
934 	status = table->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
935 
936 	if (IsSecurityStatusError(status))
937 	{
938 		WLog_WARN(TAG, "ImportSecurityContextW status %s [0x%08" PRIX32 "]",
939 		          GetSecurityStatusString(status), status);
940 	}
941 
942 	return status;
943 }
944 
winpr_ImportSecurityContextA(SEC_CHAR * pszPackage,PSecBuffer pPackedContext,HANDLE pToken,PCtxtHandle phContext)945 static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage,
946                                                               PSecBuffer pPackedContext,
947                                                               HANDLE pToken, PCtxtHandle phContext)
948 {
949 	char* Name = NULL;
950 	SECURITY_STATUS status;
951 	SecurityFunctionTableA* table;
952 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
953 
954 	if (!Name)
955 		return SEC_E_SECPKG_NOT_FOUND;
956 
957 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
958 
959 	if (!table)
960 		return SEC_E_SECPKG_NOT_FOUND;
961 
962 	if (!table->ImportSecurityContextA)
963 	{
964 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
965 		return SEC_E_UNSUPPORTED_FUNCTION;
966 	}
967 
968 	status = table->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
969 
970 	if (IsSecurityStatusError(status))
971 	{
972 		WLog_WARN(TAG, "ImportSecurityContextA status %s [0x%08" PRIX32 "]",
973 		          GetSecurityStatusString(status), status);
974 	}
975 
976 	return status;
977 }
978 
winpr_QueryCredentialsAttributesW(PCredHandle phCredential,ULONG ulAttribute,void * pBuffer)979 static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential,
980                                                                    ULONG ulAttribute, void* pBuffer)
981 {
982 	SEC_WCHAR* Name;
983 	SECURITY_STATUS status;
984 	SecurityFunctionTableW* table;
985 	Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
986 
987 	if (!Name)
988 		return SEC_E_SECPKG_NOT_FOUND;
989 
990 	table = sspi_GetSecurityFunctionTableWByNameW(Name);
991 
992 	if (!table)
993 		return SEC_E_SECPKG_NOT_FOUND;
994 
995 	if (!table->QueryCredentialsAttributesW)
996 	{
997 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
998 		return SEC_E_UNSUPPORTED_FUNCTION;
999 	}
1000 
1001 	status = table->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
1002 
1003 	if (IsSecurityStatusError(status))
1004 	{
1005 		WLog_WARN(TAG, "QueryCredentialsAttributesW status %s [0x%08" PRIX32 "]",
1006 		          GetSecurityStatusString(status), status);
1007 	}
1008 
1009 	return status;
1010 }
1011 
winpr_QueryCredentialsAttributesA(PCredHandle phCredential,ULONG ulAttribute,void * pBuffer)1012 static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential,
1013                                                                    ULONG ulAttribute, void* pBuffer)
1014 {
1015 	char* Name;
1016 	SECURITY_STATUS status;
1017 	SecurityFunctionTableA* table;
1018 	Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1019 
1020 	if (!Name)
1021 		return SEC_E_SECPKG_NOT_FOUND;
1022 
1023 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1024 
1025 	if (!table)
1026 		return SEC_E_SECPKG_NOT_FOUND;
1027 
1028 	if (!table->QueryCredentialsAttributesA)
1029 	{
1030 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1031 		return SEC_E_UNSUPPORTED_FUNCTION;
1032 	}
1033 
1034 	status = table->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
1035 
1036 	if (IsSecurityStatusError(status))
1037 	{
1038 		WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08" PRIX32 "]",
1039 		          GetSecurityStatusString(status), status);
1040 	}
1041 
1042 	return status;
1043 }
1044 
1045 /* Context Management */
1046 
1047 static SECURITY_STATUS SEC_ENTRY
winpr_AcceptSecurityContext(PCredHandle phCredential,PCtxtHandle phContext,PSecBufferDesc pInput,ULONG fContextReq,ULONG TargetDataRep,PCtxtHandle phNewContext,PSecBufferDesc pOutput,PULONG pfContextAttr,PTimeStamp ptsTimeStamp)1048 winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
1049                             ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
1050                             PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
1051 {
1052 	char* Name;
1053 	SECURITY_STATUS status;
1054 	SecurityFunctionTableA* table;
1055 	Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1056 
1057 	if (!Name)
1058 		return SEC_E_SECPKG_NOT_FOUND;
1059 
1060 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1061 
1062 	if (!table)
1063 		return SEC_E_SECPKG_NOT_FOUND;
1064 
1065 	if (!table->AcceptSecurityContext)
1066 	{
1067 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1068 		return SEC_E_UNSUPPORTED_FUNCTION;
1069 	}
1070 
1071 	status =
1072 	    table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
1073 	                                 phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
1074 
1075 	if (IsSecurityStatusError(status))
1076 	{
1077 		WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08" PRIX32 "]",
1078 		          GetSecurityStatusString(status), status);
1079 	}
1080 
1081 	return status;
1082 }
1083 
winpr_ApplyControlToken(PCtxtHandle phContext,PSecBufferDesc pInput)1084 static SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext,
1085                                                          PSecBufferDesc pInput)
1086 {
1087 	char* Name = NULL;
1088 	SECURITY_STATUS status;
1089 	SecurityFunctionTableA* table;
1090 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1091 
1092 	if (!Name)
1093 		return SEC_E_SECPKG_NOT_FOUND;
1094 
1095 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1096 
1097 	if (!table)
1098 		return SEC_E_SECPKG_NOT_FOUND;
1099 
1100 	if (!table->ApplyControlToken)
1101 	{
1102 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1103 		return SEC_E_UNSUPPORTED_FUNCTION;
1104 	}
1105 
1106 	status = table->ApplyControlToken(phContext, pInput);
1107 
1108 	if (IsSecurityStatusError(status))
1109 	{
1110 		WLog_WARN(TAG, "ApplyControlToken status %s [0x%08" PRIX32 "]",
1111 		          GetSecurityStatusString(status), status);
1112 	}
1113 
1114 	return status;
1115 }
1116 
winpr_CompleteAuthToken(PCtxtHandle phContext,PSecBufferDesc pToken)1117 static SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext,
1118                                                          PSecBufferDesc pToken)
1119 {
1120 	char* Name = NULL;
1121 	SECURITY_STATUS status;
1122 	SecurityFunctionTableA* table;
1123 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1124 
1125 	if (!Name)
1126 		return SEC_E_SECPKG_NOT_FOUND;
1127 
1128 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1129 
1130 	if (!table)
1131 		return SEC_E_SECPKG_NOT_FOUND;
1132 
1133 	if (!table->CompleteAuthToken)
1134 	{
1135 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1136 		return SEC_E_UNSUPPORTED_FUNCTION;
1137 	}
1138 
1139 	status = table->CompleteAuthToken(phContext, pToken);
1140 
1141 	if (IsSecurityStatusError(status))
1142 	{
1143 		WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08" PRIX32 "]",
1144 		          GetSecurityStatusString(status), status);
1145 	}
1146 
1147 	return status;
1148 }
1149 
winpr_DeleteSecurityContext(PCtxtHandle phContext)1150 static SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
1151 {
1152 	char* Name = NULL;
1153 	SECURITY_STATUS status;
1154 	SecurityFunctionTableA* table;
1155 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1156 
1157 	if (!Name)
1158 		return SEC_E_SECPKG_NOT_FOUND;
1159 
1160 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1161 
1162 	if (!table)
1163 		return SEC_E_SECPKG_NOT_FOUND;
1164 
1165 	if (!table->DeleteSecurityContext)
1166 	{
1167 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1168 		return SEC_E_UNSUPPORTED_FUNCTION;
1169 	}
1170 
1171 	status = table->DeleteSecurityContext(phContext);
1172 
1173 	if (IsSecurityStatusError(status))
1174 	{
1175 		WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08" PRIX32 "]",
1176 		          GetSecurityStatusString(status), status);
1177 	}
1178 
1179 	return status;
1180 }
1181 
winpr_FreeContextBuffer(void * pvContextBuffer)1182 static SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer)
1183 {
1184 	if (!pvContextBuffer)
1185 		return SEC_E_INVALID_HANDLE;
1186 
1187 	sspi_ContextBufferFree(pvContextBuffer);
1188 	return SEC_E_OK;
1189 }
1190 
winpr_ImpersonateSecurityContext(PCtxtHandle phContext)1191 static SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext)
1192 {
1193 	SEC_CHAR* Name;
1194 	SECURITY_STATUS status;
1195 	SecurityFunctionTableW* table;
1196 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1197 
1198 	if (!Name)
1199 		return SEC_E_SECPKG_NOT_FOUND;
1200 
1201 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
1202 
1203 	if (!table)
1204 		return SEC_E_SECPKG_NOT_FOUND;
1205 
1206 	if (!table->ImpersonateSecurityContext)
1207 	{
1208 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1209 		return SEC_E_UNSUPPORTED_FUNCTION;
1210 	}
1211 
1212 	status = table->ImpersonateSecurityContext(phContext);
1213 
1214 	if (IsSecurityStatusError(status))
1215 	{
1216 		WLog_WARN(TAG, "ImpersonateSecurityContext status %s [0x%08" PRIX32 "]",
1217 		          GetSecurityStatusString(status), status);
1218 	}
1219 
1220 	return status;
1221 }
1222 
winpr_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)1223 static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(
1224     PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
1225     ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1226     PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1227 {
1228 	SEC_CHAR* Name;
1229 	SECURITY_STATUS status;
1230 	SecurityFunctionTableW* table;
1231 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1232 
1233 	if (!Name)
1234 		return SEC_E_SECPKG_NOT_FOUND;
1235 
1236 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
1237 
1238 	if (!table)
1239 		return SEC_E_SECPKG_NOT_FOUND;
1240 
1241 	if (!table->InitializeSecurityContextW)
1242 	{
1243 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1244 		return SEC_E_UNSUPPORTED_FUNCTION;
1245 	}
1246 
1247 	status = table->InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq,
1248 	                                           Reserved1, TargetDataRep, pInput, Reserved2,
1249 	                                           phNewContext, pOutput, pfContextAttr, ptsExpiry);
1250 
1251 	if (IsSecurityStatusError(status))
1252 	{
1253 		WLog_WARN(TAG, "InitializeSecurityContextW status %s [0x%08" PRIX32 "]",
1254 		          GetSecurityStatusString(status), status);
1255 	}
1256 
1257 	return status;
1258 }
1259 
winpr_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)1260 static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(
1261     PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
1262     ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1263     PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1264 {
1265 	SEC_CHAR* Name;
1266 	SECURITY_STATUS status;
1267 	SecurityFunctionTableA* table;
1268 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1269 
1270 	if (!Name)
1271 		return SEC_E_SECPKG_NOT_FOUND;
1272 
1273 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1274 
1275 	if (!table)
1276 		return SEC_E_SECPKG_NOT_FOUND;
1277 
1278 	if (!table->InitializeSecurityContextA)
1279 	{
1280 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1281 		return SEC_E_UNSUPPORTED_FUNCTION;
1282 	}
1283 
1284 	status = table->InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq,
1285 	                                           Reserved1, TargetDataRep, pInput, Reserved2,
1286 	                                           phNewContext, pOutput, pfContextAttr, ptsExpiry);
1287 
1288 	if (IsSecurityStatusError(status))
1289 	{
1290 		WLog_WARN(TAG, "InitializeSecurityContextA status %s [0x%08" PRIX32 "]",
1291 		          GetSecurityStatusString(status), status);
1292 	}
1293 
1294 	return status;
1295 }
1296 
winpr_QueryContextAttributesW(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer)1297 static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext,
1298                                                                ULONG ulAttribute, void* pBuffer)
1299 {
1300 	SEC_CHAR* Name;
1301 	SECURITY_STATUS status;
1302 	SecurityFunctionTableW* table;
1303 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1304 
1305 	if (!Name)
1306 		return SEC_E_SECPKG_NOT_FOUND;
1307 
1308 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
1309 
1310 	if (!table)
1311 		return SEC_E_SECPKG_NOT_FOUND;
1312 
1313 	if (!table->QueryContextAttributesW)
1314 	{
1315 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1316 		return SEC_E_UNSUPPORTED_FUNCTION;
1317 	}
1318 
1319 	status = table->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
1320 
1321 	if (IsSecurityStatusError(status))
1322 	{
1323 		WLog_WARN(TAG, "QueryContextAttributesW status %s [0x%08" PRIX32 "]",
1324 		          GetSecurityStatusString(status), status);
1325 	}
1326 
1327 	return status;
1328 }
1329 
winpr_QueryContextAttributesA(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer)1330 static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext,
1331                                                                ULONG ulAttribute, void* pBuffer)
1332 {
1333 	SEC_CHAR* Name;
1334 	SECURITY_STATUS status;
1335 	SecurityFunctionTableA* table;
1336 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1337 
1338 	if (!Name)
1339 		return SEC_E_SECPKG_NOT_FOUND;
1340 
1341 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1342 
1343 	if (!table)
1344 		return SEC_E_SECPKG_NOT_FOUND;
1345 
1346 	if (!table->QueryContextAttributesA)
1347 	{
1348 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1349 		return SEC_E_UNSUPPORTED_FUNCTION;
1350 	}
1351 
1352 	status = table->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
1353 
1354 	if (IsSecurityStatusError(status))
1355 	{
1356 		WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08" PRIX32 "]",
1357 		          GetSecurityStatusString(status), status);
1358 	}
1359 
1360 	return status;
1361 }
1362 
winpr_QuerySecurityContextToken(PCtxtHandle phContext,HANDLE * phToken)1363 static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext,
1364                                                                  HANDLE* phToken)
1365 {
1366 	SEC_CHAR* Name;
1367 	SECURITY_STATUS status;
1368 	SecurityFunctionTableW* table;
1369 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1370 
1371 	if (!Name)
1372 		return SEC_E_SECPKG_NOT_FOUND;
1373 
1374 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
1375 
1376 	if (!table)
1377 		return SEC_E_SECPKG_NOT_FOUND;
1378 
1379 	if (!table->QuerySecurityContextToken)
1380 	{
1381 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1382 		return SEC_E_UNSUPPORTED_FUNCTION;
1383 	}
1384 
1385 	status = table->QuerySecurityContextToken(phContext, phToken);
1386 
1387 	if (IsSecurityStatusError(status))
1388 	{
1389 		WLog_WARN(TAG, "QuerySecurityContextToken status %s [0x%08" PRIX32 "]",
1390 		          GetSecurityStatusString(status), status);
1391 	}
1392 
1393 	return status;
1394 }
1395 
winpr_SetContextAttributesW(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer,ULONG cbBuffer)1396 static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext,
1397                                                              ULONG ulAttribute, void* pBuffer,
1398                                                              ULONG cbBuffer)
1399 {
1400 	SEC_CHAR* Name;
1401 	SECURITY_STATUS status;
1402 	SecurityFunctionTableW* table;
1403 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1404 
1405 	if (!Name)
1406 		return SEC_E_SECPKG_NOT_FOUND;
1407 
1408 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
1409 
1410 	if (!table)
1411 		return SEC_E_SECPKG_NOT_FOUND;
1412 
1413 	if (!table->SetContextAttributesW)
1414 	{
1415 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1416 		return SEC_E_UNSUPPORTED_FUNCTION;
1417 	}
1418 
1419 	status = table->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
1420 
1421 	if (IsSecurityStatusError(status))
1422 	{
1423 		WLog_WARN(TAG, "SetContextAttributesW status %s [0x%08" PRIX32 "]",
1424 		          GetSecurityStatusString(status), status);
1425 	}
1426 
1427 	return status;
1428 }
1429 
winpr_SetContextAttributesA(PCtxtHandle phContext,ULONG ulAttribute,void * pBuffer,ULONG cbBuffer)1430 static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext,
1431                                                              ULONG ulAttribute, void* pBuffer,
1432                                                              ULONG cbBuffer)
1433 {
1434 	char* Name;
1435 	SECURITY_STATUS status;
1436 	SecurityFunctionTableA* table;
1437 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1438 
1439 	if (!Name)
1440 		return SEC_E_SECPKG_NOT_FOUND;
1441 
1442 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1443 
1444 	if (!table)
1445 		return SEC_E_SECPKG_NOT_FOUND;
1446 
1447 	if (!table->SetContextAttributesA)
1448 	{
1449 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1450 		return SEC_E_UNSUPPORTED_FUNCTION;
1451 	}
1452 
1453 	status = table->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
1454 
1455 	if (IsSecurityStatusError(status))
1456 	{
1457 		WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08" PRIX32 "]",
1458 		          GetSecurityStatusString(status), status);
1459 	}
1460 
1461 	return status;
1462 }
1463 
winpr_RevertSecurityContext(PCtxtHandle phContext)1464 static SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
1465 {
1466 	SEC_CHAR* Name;
1467 	SECURITY_STATUS status;
1468 	SecurityFunctionTableW* table;
1469 	Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1470 
1471 	if (!Name)
1472 		return SEC_E_SECPKG_NOT_FOUND;
1473 
1474 	table = sspi_GetSecurityFunctionTableWByNameA(Name);
1475 
1476 	if (!table)
1477 		return SEC_E_SECPKG_NOT_FOUND;
1478 
1479 	if (!table->RevertSecurityContext)
1480 	{
1481 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1482 		return SEC_E_UNSUPPORTED_FUNCTION;
1483 	}
1484 
1485 	status = table->RevertSecurityContext(phContext);
1486 
1487 	if (IsSecurityStatusError(status))
1488 	{
1489 		WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08" PRIX32 "]",
1490 		          GetSecurityStatusString(status), status);
1491 	}
1492 
1493 	return status;
1494 }
1495 
1496 /* Message Support */
1497 
winpr_DecryptMessage(PCtxtHandle phContext,PSecBufferDesc pMessage,ULONG MessageSeqNo,PULONG pfQOP)1498 static SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext,
1499                                                       PSecBufferDesc pMessage, ULONG MessageSeqNo,
1500                                                       PULONG pfQOP)
1501 {
1502 	char* Name;
1503 	SECURITY_STATUS status;
1504 	SecurityFunctionTableA* table;
1505 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1506 
1507 	if (!Name)
1508 		return SEC_E_SECPKG_NOT_FOUND;
1509 
1510 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1511 
1512 	if (!table)
1513 		return SEC_E_SECPKG_NOT_FOUND;
1514 
1515 	if (!table->DecryptMessage)
1516 	{
1517 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1518 		return SEC_E_UNSUPPORTED_FUNCTION;
1519 	}
1520 
1521 	status = table->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
1522 
1523 	if (IsSecurityStatusError(status))
1524 	{
1525 		WLog_WARN(TAG, "DecryptMessage status %s [0x%08" PRIX32 "]",
1526 		          GetSecurityStatusString(status), status);
1527 	}
1528 
1529 	return status;
1530 }
1531 
winpr_EncryptMessage(PCtxtHandle phContext,ULONG fQOP,PSecBufferDesc pMessage,ULONG MessageSeqNo)1532 static SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
1533                                                       PSecBufferDesc pMessage, ULONG MessageSeqNo)
1534 {
1535 	char* Name;
1536 	SECURITY_STATUS status;
1537 	SecurityFunctionTableA* table;
1538 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1539 
1540 	if (!Name)
1541 		return SEC_E_SECPKG_NOT_FOUND;
1542 
1543 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1544 
1545 	if (!table)
1546 		return SEC_E_SECPKG_NOT_FOUND;
1547 
1548 	if (!table->EncryptMessage)
1549 	{
1550 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1551 		return SEC_E_UNSUPPORTED_FUNCTION;
1552 	}
1553 
1554 	status = table->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
1555 
1556 	if (status != SEC_E_OK)
1557 	{
1558 		WLog_ERR(TAG, "EncryptMessage status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
1559 		         status);
1560 	}
1561 
1562 	return status;
1563 }
1564 
winpr_MakeSignature(PCtxtHandle phContext,ULONG fQOP,PSecBufferDesc pMessage,ULONG MessageSeqNo)1565 static SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
1566                                                      PSecBufferDesc pMessage, ULONG MessageSeqNo)
1567 {
1568 	char* Name;
1569 	SECURITY_STATUS status;
1570 	SecurityFunctionTableA* table;
1571 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1572 
1573 	if (!Name)
1574 		return SEC_E_SECPKG_NOT_FOUND;
1575 
1576 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1577 
1578 	if (!table)
1579 		return SEC_E_SECPKG_NOT_FOUND;
1580 
1581 	if (!table->MakeSignature)
1582 	{
1583 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1584 		return SEC_E_UNSUPPORTED_FUNCTION;
1585 	}
1586 
1587 	status = table->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
1588 
1589 	if (IsSecurityStatusError(status))
1590 	{
1591 		WLog_WARN(TAG, "MakeSignature status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
1592 		          status);
1593 	}
1594 
1595 	return status;
1596 }
1597 
winpr_VerifySignature(PCtxtHandle phContext,PSecBufferDesc pMessage,ULONG MessageSeqNo,PULONG pfQOP)1598 static SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext,
1599                                                        PSecBufferDesc pMessage, ULONG MessageSeqNo,
1600                                                        PULONG pfQOP)
1601 {
1602 	char* Name;
1603 	SECURITY_STATUS status;
1604 	SecurityFunctionTableA* table;
1605 	Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1606 
1607 	if (!Name)
1608 		return SEC_E_SECPKG_NOT_FOUND;
1609 
1610 	table = sspi_GetSecurityFunctionTableAByNameA(Name);
1611 
1612 	if (!table)
1613 		return SEC_E_SECPKG_NOT_FOUND;
1614 
1615 	if (!table->VerifySignature)
1616 	{
1617 		WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__);
1618 		return SEC_E_UNSUPPORTED_FUNCTION;
1619 	}
1620 
1621 	status = table->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
1622 
1623 	if (IsSecurityStatusError(status))
1624 	{
1625 		WLog_WARN(TAG, "VerifySignature status %s [0x%08" PRIX32 "]",
1626 		          GetSecurityStatusString(status), status);
1627 	}
1628 
1629 	return status;
1630 }
1631 
1632 static SecurityFunctionTableA winpr_SecurityFunctionTableA = {
1633 	1,                                 /* dwVersion */
1634 	winpr_EnumerateSecurityPackagesA,  /* EnumerateSecurityPackages */
1635 	winpr_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
1636 	winpr_AcquireCredentialsHandleA,   /* AcquireCredentialsHandle */
1637 	winpr_FreeCredentialsHandle,       /* FreeCredentialsHandle */
1638 	NULL,                              /* Reserved2 */
1639 	winpr_InitializeSecurityContextA,  /* InitializeSecurityContext */
1640 	winpr_AcceptSecurityContext,       /* AcceptSecurityContext */
1641 	winpr_CompleteAuthToken,           /* CompleteAuthToken */
1642 	winpr_DeleteSecurityContext,       /* DeleteSecurityContext */
1643 	winpr_ApplyControlToken,           /* ApplyControlToken */
1644 	winpr_QueryContextAttributesA,     /* QueryContextAttributes */
1645 	winpr_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
1646 	winpr_RevertSecurityContext,       /* RevertSecurityContext */
1647 	winpr_MakeSignature,               /* MakeSignature */
1648 	winpr_VerifySignature,             /* VerifySignature */
1649 	winpr_FreeContextBuffer,           /* FreeContextBuffer */
1650 	winpr_QuerySecurityPackageInfoA,   /* QuerySecurityPackageInfo */
1651 	NULL,                              /* Reserved3 */
1652 	NULL,                              /* Reserved4 */
1653 	winpr_ExportSecurityContext,       /* ExportSecurityContext */
1654 	winpr_ImportSecurityContextA,      /* ImportSecurityContext */
1655 	NULL,                              /* AddCredentials */
1656 	NULL,                              /* Reserved8 */
1657 	winpr_QuerySecurityContextToken,   /* QuerySecurityContextToken */
1658 	winpr_EncryptMessage,              /* EncryptMessage */
1659 	winpr_DecryptMessage,              /* DecryptMessage */
1660 	winpr_SetContextAttributesA,       /* SetContextAttributes */
1661 };
1662 
1663 static SecurityFunctionTableW winpr_SecurityFunctionTableW = {
1664 	1,                                 /* dwVersion */
1665 	winpr_EnumerateSecurityPackagesW,  /* EnumerateSecurityPackages */
1666 	winpr_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
1667 	winpr_AcquireCredentialsHandleW,   /* AcquireCredentialsHandle */
1668 	winpr_FreeCredentialsHandle,       /* FreeCredentialsHandle */
1669 	NULL,                              /* Reserved2 */
1670 	winpr_InitializeSecurityContextW,  /* InitializeSecurityContext */
1671 	winpr_AcceptSecurityContext,       /* AcceptSecurityContext */
1672 	winpr_CompleteAuthToken,           /* CompleteAuthToken */
1673 	winpr_DeleteSecurityContext,       /* DeleteSecurityContext */
1674 	winpr_ApplyControlToken,           /* ApplyControlToken */
1675 	winpr_QueryContextAttributesW,     /* QueryContextAttributes */
1676 	winpr_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
1677 	winpr_RevertSecurityContext,       /* RevertSecurityContext */
1678 	winpr_MakeSignature,               /* MakeSignature */
1679 	winpr_VerifySignature,             /* VerifySignature */
1680 	winpr_FreeContextBuffer,           /* FreeContextBuffer */
1681 	winpr_QuerySecurityPackageInfoW,   /* QuerySecurityPackageInfo */
1682 	NULL,                              /* Reserved3 */
1683 	NULL,                              /* Reserved4 */
1684 	winpr_ExportSecurityContext,       /* ExportSecurityContext */
1685 	winpr_ImportSecurityContextW,      /* ImportSecurityContext */
1686 	NULL,                              /* AddCredentials */
1687 	NULL,                              /* Reserved8 */
1688 	winpr_QuerySecurityContextToken,   /* QuerySecurityContextToken */
1689 	winpr_EncryptMessage,              /* EncryptMessage */
1690 	winpr_DecryptMessage,              /* DecryptMessage */
1691 	winpr_SetContextAttributesW,       /* SetContextAttributes */
1692 };
1693