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