Coverage Report

Created: 2023-09-25 06:56

/src/FreeRDP/winpr/libwinpr/sspi/sspi_winpr.c
Line
Count
Source (jump to first uncovered line)
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
#include <winpr/config.h>
22
#include <winpr/assert.h>
23
#include <winpr/windows.h>
24
25
#include <winpr/crt.h>
26
#include <winpr/sspi.h>
27
#include <winpr/ssl.h>
28
#include <winpr/print.h>
29
30
#include "sspi.h"
31
32
#include "sspi_winpr.h"
33
34
#include "../log.h"
35
#define TAG WINPR_TAG("sspi")
36
37
/* Authentication Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731/ */
38
39
#include "NTLM/ntlm_export.h"
40
#include "CredSSP/credssp.h"
41
#include "Kerberos/kerberos.h"
42
#include "Negotiate/negotiate.h"
43
#include "Schannel/schannel.h"
44
45
static const SecPkgInfoA* SecPkgInfoA_LIST[] = { &NTLM_SecPkgInfoA, &KERBEROS_SecPkgInfoA,
46
                                               &NEGOTIATE_SecPkgInfoA, &CREDSSP_SecPkgInfoA,
47
                                               &SCHANNEL_SecPkgInfoA };
48
49
static const SecPkgInfoW* SecPkgInfoW_LIST[] = { &NTLM_SecPkgInfoW, &KERBEROS_SecPkgInfoW,
50
                                               &NEGOTIATE_SecPkgInfoW, &CREDSSP_SecPkgInfoW,
51
                                               &SCHANNEL_SecPkgInfoW };
52
53
static SecurityFunctionTableA winpr_SecurityFunctionTableA;
54
static SecurityFunctionTableW winpr_SecurityFunctionTableW;
55
56
typedef struct
57
{
58
  const SEC_CHAR* Name;
59
  const SecurityFunctionTableA* SecurityFunctionTable;
60
} SecurityFunctionTableA_NAME;
61
62
typedef struct
63
{
64
  const SEC_WCHAR* Name;
65
  const SecurityFunctionTableW* SecurityFunctionTable;
66
} SecurityFunctionTableW_NAME;
67
68
static const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = {
69
  { "NTLM", &NTLM_SecurityFunctionTableA },
70
  { "Kerberos", &KERBEROS_SecurityFunctionTableA },
71
  { "Negotiate", &NEGOTIATE_SecurityFunctionTableA },
72
  { "CREDSSP", &CREDSSP_SecurityFunctionTableA },
73
  { "Schannel", &SCHANNEL_SecurityFunctionTableA }
74
};
75
76
static const WCHAR _NTLM_NAME_W[] = { 'N', 'T', 'L', 'M', '\0' };
77
static const WCHAR _KERBEROS_NAME_W[] = { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', '\0' };
78
static const WCHAR _NEGOTIATE_NAME_W[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' };
79
static const WCHAR _CREDSSP_NAME_W[] = { 'C', 'r', 'e', 'd', 'S', 'S', 'P', '\0' };
80
static const WCHAR _SCHANNEL_NAME_W[] = { 'S', 'c', 'h', 'a', 'n', 'n', 'e', 'l', '\0' };
81
82
static const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = {
83
  { _NTLM_NAME_W, &NTLM_SecurityFunctionTableW },
84
  { _KERBEROS_NAME_W, &KERBEROS_SecurityFunctionTableW },
85
  { _NEGOTIATE_NAME_W, &NEGOTIATE_SecurityFunctionTableW },
86
  { _CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW },
87
  { _SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW }
88
};
89
90
#define SecHandle_LOWER_MAX 0xFFFFFFFF
91
#define SecHandle_UPPER_MAX 0xFFFFFFFE
92
93
typedef struct
94
{
95
  void* contextBuffer;
96
  UINT32 allocatorIndex;
97
} CONTEXT_BUFFER_ALLOC_ENTRY;
98
99
typedef struct
100
{
101
  UINT32 cEntries;
102
  UINT32 cMaxEntries;
103
  CONTEXT_BUFFER_ALLOC_ENTRY* entries;
104
} CONTEXT_BUFFER_ALLOC_TABLE;
105
106
static CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable = { 0 };
107
108
static int sspi_ContextBufferAllocTableNew(void)
109
0
{
110
0
  size_t size;
111
0
  ContextBufferAllocTable.entries = NULL;
112
0
  ContextBufferAllocTable.cEntries = 0;
113
0
  ContextBufferAllocTable.cMaxEntries = 4;
114
0
  size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
115
0
  ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)calloc(1, size);
116
117
0
  if (!ContextBufferAllocTable.entries)
118
0
    return -1;
119
120
0
  return 1;
121
0
}
122
123
static int sspi_ContextBufferAllocTableGrow(void)
124
0
{
125
0
  size_t size;
126
0
  CONTEXT_BUFFER_ALLOC_ENTRY* entries;
127
0
  ContextBufferAllocTable.cEntries = 0;
128
0
  ContextBufferAllocTable.cMaxEntries *= 2;
129
0
  size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
130
131
0
  if (!size)
132
0
    return -1;
133
134
0
  entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)realloc(ContextBufferAllocTable.entries, size);
135
136
0
  if (!entries)
137
0
  {
138
0
    free(ContextBufferAllocTable.entries);
139
0
    return -1;
140
0
  }
141
142
0
  ContextBufferAllocTable.entries = entries;
143
0
  ZeroMemory((void*)&ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2],
144
0
             size / 2);
145
0
  return 1;
146
0
}
147
148
static void sspi_ContextBufferAllocTableFree(void)
149
0
{
150
0
  if (ContextBufferAllocTable.cEntries != 0)
151
0
    WLog_ERR(TAG, "ContextBufferAllocTable.entries == %" PRIu32,
152
0
             ContextBufferAllocTable.cEntries);
153
154
0
  ContextBufferAllocTable.cEntries = ContextBufferAllocTable.cMaxEntries = 0;
155
0
  free(ContextBufferAllocTable.entries);
156
0
  ContextBufferAllocTable.entries = NULL;
157
0
}
158
159
static void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
160
0
{
161
0
  UINT32 index;
162
0
  void* contextBuffer;
163
164
0
  for (index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
165
0
  {
166
0
    if (!ContextBufferAllocTable.entries[index].contextBuffer)
167
0
    {
168
0
      contextBuffer = calloc(1, size);
169
170
0
      if (!contextBuffer)
171
0
        return NULL;
172
173
0
      ContextBufferAllocTable.cEntries++;
174
0
      ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer;
175
0
      ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex;
176
0
      return ContextBufferAllocTable.entries[index].contextBuffer;
177
0
    }
178
0
  }
179
180
  /* no available entry was found, the table needs to be grown */
181
182
0
  if (sspi_ContextBufferAllocTableGrow() < 0)
183
0
    return NULL;
184
185
  /* the next call to sspi_ContextBufferAlloc() should now succeed */
186
0
  return sspi_ContextBufferAlloc(allocatorIndex, size);
187
0
}
188
189
SSPI_CREDENTIALS* sspi_CredentialsNew(void)
190
0
{
191
0
  SSPI_CREDENTIALS* credentials;
192
0
  credentials = (SSPI_CREDENTIALS*)calloc(1, sizeof(SSPI_CREDENTIALS));
193
0
  return credentials;
194
0
}
195
196
void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
197
0
{
198
0
  size_t userLength = 0;
199
0
  size_t domainLength = 0;
200
0
  size_t passwordLength = 0;
201
202
0
  if (!credentials)
203
0
    return;
204
205
0
  if (credentials->ntlmSettings.samFile)
206
0
    free(credentials->ntlmSettings.samFile);
207
208
0
  userLength = credentials->identity.UserLength;
209
0
  domainLength = credentials->identity.DomainLength;
210
0
  passwordLength = credentials->identity.PasswordLength;
211
212
0
  if (passwordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET) /* [pth] */
213
0
    passwordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
214
215
0
  if (credentials->identity.Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
216
0
  {
217
0
    userLength *= 2;
218
0
    domainLength *= 2;
219
0
    passwordLength *= 2;
220
0
  }
221
222
0
  if (credentials->identity.User)
223
0
    memset(credentials->identity.User, 0, userLength);
224
0
  if (credentials->identity.Domain)
225
0
    memset(credentials->identity.Domain, 0, domainLength);
226
0
  if (credentials->identity.Password)
227
0
    memset(credentials->identity.Password, 0, passwordLength);
228
0
  free(credentials->identity.User);
229
0
  free(credentials->identity.Domain);
230
0
  free(credentials->identity.Password);
231
0
  free(credentials);
232
0
}
233
234
void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size)
235
0
{
236
0
  if (!SecBuffer)
237
0
    return NULL;
238
239
0
  SecBuffer->pvBuffer = calloc(1, size);
240
241
0
  if (!SecBuffer->pvBuffer)
242
0
    return NULL;
243
244
0
  SecBuffer->cbBuffer = size;
245
0
  return SecBuffer->pvBuffer;
246
0
}
247
248
void sspi_SecBufferFree(PSecBuffer SecBuffer)
249
0
{
250
0
  if (!SecBuffer)
251
0
    return;
252
253
0
  if (SecBuffer->pvBuffer)
254
0
    memset(SecBuffer->pvBuffer, 0, SecBuffer->cbBuffer);
255
256
0
  free(SecBuffer->pvBuffer);
257
0
  SecBuffer->pvBuffer = NULL;
258
0
  SecBuffer->cbBuffer = 0;
259
0
}
260
261
SecHandle* sspi_SecureHandleAlloc(void)
262
0
{
263
0
  SecHandle* handle = (SecHandle*)calloc(1, sizeof(SecHandle));
264
265
0
  if (!handle)
266
0
    return NULL;
267
268
0
  SecInvalidateHandle(handle);
269
0
  return handle;
270
0
}
271
272
void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
273
0
{
274
0
  void* pointer;
275
276
0
  if (!handle || !SecIsValidHandle(handle) || !handle->dwLower)
277
0
    return NULL;
278
279
0
  pointer = (void*)~((size_t)handle->dwLower);
280
0
  return pointer;
281
0
}
282
283
void sspi_SecureHandleInvalidate(SecHandle* handle)
284
0
{
285
0
  if (!handle)
286
0
    return;
287
288
0
  handle->dwLower = 0;
289
0
  handle->dwUpper = 0;
290
0
}
291
292
void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer)
293
0
{
294
0
  if (!handle)
295
0
    return;
296
297
0
  handle->dwLower = (ULONG_PTR)(~((size_t)pointer));
298
0
}
299
300
void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
301
0
{
302
0
  void* pointer;
303
304
0
  if (!handle || !SecIsValidHandle(handle) || !handle->dwUpper)
305
0
    return NULL;
306
307
0
  pointer = (void*)~((size_t)handle->dwUpper);
308
0
  return pointer;
309
0
}
310
311
void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer)
312
0
{
313
0
  if (!handle)
314
0
    return;
315
316
0
  handle->dwUpper = (ULONG_PTR)(~((size_t)pointer));
317
0
}
318
319
void sspi_SecureHandleFree(SecHandle* handle)
320
0
{
321
0
  free(handle);
322
0
}
323
324
int sspi_SetAuthIdentityW(SEC_WINNT_AUTH_IDENTITY* identity, const WCHAR* user, const WCHAR* domain,
325
                          const WCHAR* password)
326
0
{
327
0
  return sspi_SetAuthIdentityWithLengthW(identity, user, user ? _wcslen(user) : 0, domain,
328
0
                                         domain ? _wcslen(domain) : 0, password,
329
0
                                         password ? _wcslen(password) : 0);
330
0
}
331
332
static BOOL copy(WCHAR** dst, ULONG* dstLen, const WCHAR* what, size_t len)
333
0
{
334
0
  WINPR_ASSERT(dst);
335
0
  WINPR_ASSERT(dstLen);
336
337
0
  *dst = NULL;
338
0
  *dstLen = 0;
339
340
0
  *dst = calloc(sizeof(WCHAR), len + 1);
341
0
  if (!*dst)
342
0
    return FALSE;
343
0
  memcpy(*dst, what, len * sizeof(WCHAR));
344
0
  *dstLen = len;
345
0
  return TRUE;
346
0
}
347
348
int sspi_SetAuthIdentityWithLengthW(SEC_WINNT_AUTH_IDENTITY* identity, const WCHAR* user,
349
                                    size_t userLen, const WCHAR* domain, size_t domainLen,
350
                                    const WCHAR* password, size_t passwordLen)
351
0
{
352
0
  WINPR_ASSERT(identity);
353
0
  sspi_FreeAuthIdentity(identity);
354
0
  identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
355
0
  identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
356
357
0
  if (!copy(&identity->User, &identity->UserLength, user, userLen))
358
0
    return -1;
359
360
0
  if (!copy(&identity->Domain, &identity->DomainLength, domain, domainLen))
361
0
    return -1;
362
363
0
  if (!copy(&identity->Password, &identity->PasswordLength, password, passwordLen))
364
0
    return -1;
365
366
0
  return 1;
367
0
}
368
369
static void zfree(WCHAR* str, size_t len)
370
0
{
371
0
  if (str)
372
0
    memset(str, 0, len * sizeof(WCHAR));
373
0
  free(str);
374
0
}
375
376
int sspi_SetAuthIdentityA(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain,
377
                          const char* password)
378
0
{
379
0
  int rc;
380
0
  size_t unicodeUserLenW = 0;
381
0
  size_t unicodeDomainLenW = 0;
382
0
  size_t unicodePasswordLenW = 0;
383
0
  LPWSTR unicodeUser = ConvertUtf8ToWCharAlloc(user, &unicodeUserLenW);
384
0
  LPWSTR unicodeDomain = ConvertUtf8ToWCharAlloc(domain, &unicodeDomainLenW);
385
0
  LPWSTR unicodePassword = ConvertUtf8ToWCharAlloc(password, &unicodePasswordLenW);
386
387
0
  rc = sspi_SetAuthIdentityWithLengthW(identity, unicodeUser, unicodeUserLenW, unicodeDomain,
388
0
                                       unicodeDomainLenW, unicodePassword, unicodePasswordLenW);
389
390
0
  zfree(unicodeUser, unicodeUserLenW);
391
0
  zfree(unicodeDomain, unicodeDomainLenW);
392
0
  zfree(unicodePassword, unicodePasswordLenW);
393
0
  return rc;
394
0
}
395
396
UINT32 sspi_GetAuthIdentityVersion(const void* identity)
397
0
{
398
0
  UINT32 version;
399
400
0
  if (!identity)
401
0
    return 0;
402
403
0
  version = *((const UINT32*)identity);
404
405
0
  if ((version == SEC_WINNT_AUTH_IDENTITY_VERSION) ||
406
0
      (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2))
407
0
  {
408
0
    return version;
409
0
  }
410
411
0
  return 0; // SEC_WINNT_AUTH_IDENTITY (no version)
412
0
}
413
414
UINT32 sspi_GetAuthIdentityFlags(const void* identity)
415
0
{
416
0
  UINT32 version;
417
0
  UINT32 flags = 0;
418
419
0
  if (!identity)
420
0
    return 0;
421
422
0
  version = sspi_GetAuthIdentityVersion(identity);
423
424
0
  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
425
0
  {
426
0
    flags = ((const SEC_WINNT_AUTH_IDENTITY_EX*)identity)->Flags;
427
0
  }
428
0
  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
429
0
  {
430
0
    flags = ((const SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->Flags;
431
0
  }
432
0
  else // SEC_WINNT_AUTH_IDENTITY
433
0
  {
434
0
    flags = ((const SEC_WINNT_AUTH_IDENTITY*)identity)->Flags;
435
0
  }
436
437
0
  return flags;
438
0
}
439
440
BOOL sspi_GetAuthIdentityUserDomainW(const void* identity, const WCHAR** pUser, UINT32* pUserLength,
441
                                     const WCHAR** pDomain, UINT32* pDomainLength)
442
0
{
443
0
  UINT32 version;
444
445
0
  if (!identity)
446
0
    return FALSE;
447
448
0
  version = sspi_GetAuthIdentityVersion(identity);
449
450
0
  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
451
0
  {
452
0
    const SEC_WINNT_AUTH_IDENTITY_EXW* id = (const SEC_WINNT_AUTH_IDENTITY_EXW*)identity;
453
0
    *pUser = (const WCHAR*)id->User;
454
0
    *pUserLength = id->UserLength;
455
0
    *pDomain = (const WCHAR*)id->Domain;
456
0
    *pDomainLength = id->DomainLength;
457
0
  }
458
0
  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
459
0
  {
460
0
    const SEC_WINNT_AUTH_IDENTITY_EX2* id = (const SEC_WINNT_AUTH_IDENTITY_EX2*)identity;
461
0
    UINT32 UserOffset = id->UserOffset;
462
0
    UINT32 DomainOffset = id->DomainOffset;
463
0
    *pUser = (const WCHAR*)&((const uint8_t*)identity)[UserOffset];
464
0
    *pUserLength = id->UserLength / 2;
465
0
    *pDomain = (const WCHAR*)&((const uint8_t*)identity)[DomainOffset];
466
0
    *pDomainLength = id->DomainLength / 2;
467
0
  }
468
0
  else // SEC_WINNT_AUTH_IDENTITY
469
0
  {
470
0
    const SEC_WINNT_AUTH_IDENTITY_W* id = (const SEC_WINNT_AUTH_IDENTITY_W*)identity;
471
0
    *pUser = (const WCHAR*)id->User;
472
0
    *pUserLength = id->UserLength;
473
0
    *pDomain = (const WCHAR*)id->Domain;
474
0
    *pDomainLength = id->DomainLength;
475
0
  }
476
477
0
  return TRUE;
478
0
}
479
480
BOOL sspi_GetAuthIdentityUserDomainA(const void* identity, const char** pUser, UINT32* pUserLength,
481
                                     const char** pDomain, UINT32* pDomainLength)
482
0
{
483
0
  UINT32 version;
484
485
0
  if (!identity)
486
0
    return FALSE;
487
488
0
  version = sspi_GetAuthIdentityVersion(identity);
489
490
0
  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
491
0
  {
492
0
    const SEC_WINNT_AUTH_IDENTITY_EXA* id = (const SEC_WINNT_AUTH_IDENTITY_EXA*)identity;
493
0
    *pUser = (const char*)id->User;
494
0
    *pUserLength = id->UserLength;
495
0
    *pDomain = (const char*)id->Domain;
496
0
    *pDomainLength = id->DomainLength;
497
0
  }
498
0
  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
499
0
  {
500
0
    const SEC_WINNT_AUTH_IDENTITY_EX2* id = (const SEC_WINNT_AUTH_IDENTITY_EX2*)identity;
501
0
    UINT32 UserOffset = id->UserOffset;
502
0
    UINT32 DomainOffset = id->DomainOffset;
503
0
    *pUser = (const char*)&((const uint8_t*)identity)[UserOffset];
504
0
    *pUserLength = id->UserLength;
505
0
    *pDomain = (const char*)&((const uint8_t*)identity)[DomainOffset];
506
0
    *pDomainLength = id->DomainLength;
507
0
  }
508
0
  else // SEC_WINNT_AUTH_IDENTITY
509
0
  {
510
0
    const SEC_WINNT_AUTH_IDENTITY_A* id = (const SEC_WINNT_AUTH_IDENTITY_A*)identity;
511
0
    *pUser = (const char*)id->User;
512
0
    *pUserLength = id->UserLength;
513
0
    *pDomain = (const char*)id->Domain;
514
0
    *pDomainLength = id->DomainLength;
515
0
  }
516
517
0
  return TRUE;
518
0
}
519
520
BOOL sspi_GetAuthIdentityPasswordW(const void* identity, const WCHAR** pPassword,
521
                                   UINT32* pPasswordLength)
522
0
{
523
0
  UINT32 version;
524
525
0
  if (!identity)
526
0
    return FALSE;
527
528
0
  version = sspi_GetAuthIdentityVersion(identity);
529
530
0
  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
531
0
  {
532
0
    const SEC_WINNT_AUTH_IDENTITY_EXW* id = (const SEC_WINNT_AUTH_IDENTITY_EXW*)identity;
533
0
    *pPassword = (const WCHAR*)id->Password;
534
0
    *pPasswordLength = id->PasswordLength;
535
0
  }
536
0
  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
537
0
  {
538
0
    return FALSE; // TODO: packed credentials
539
0
  }
540
0
  else // SEC_WINNT_AUTH_IDENTITY
541
0
  {
542
0
    const SEC_WINNT_AUTH_IDENTITY_W* id = (const SEC_WINNT_AUTH_IDENTITY_W*)identity;
543
0
    *pPassword = (const WCHAR*)id->Password;
544
0
    *pPasswordLength = id->PasswordLength;
545
0
  }
546
547
0
  return TRUE;
548
0
}
549
550
BOOL sspi_GetAuthIdentityPasswordA(const void* identity, const char** pPassword,
551
                                   UINT32* pPasswordLength)
552
0
{
553
0
  UINT32 version;
554
555
0
  if (!identity)
556
0
    return FALSE;
557
558
0
  version = sspi_GetAuthIdentityVersion(identity);
559
560
0
  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
561
0
  {
562
0
    const SEC_WINNT_AUTH_IDENTITY_EXA* id = (const SEC_WINNT_AUTH_IDENTITY_EXA*)identity;
563
0
    *pPassword = (const char*)id->Password;
564
0
    *pPasswordLength = id->PasswordLength;
565
0
  }
566
0
  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
567
0
  {
568
0
    return FALSE; // TODO: packed credentials
569
0
  }
570
0
  else // SEC_WINNT_AUTH_IDENTITY
571
0
  {
572
0
    const SEC_WINNT_AUTH_IDENTITY_A* id = (const SEC_WINNT_AUTH_IDENTITY_A*)identity;
573
0
    *pPassword = (const char*)id->Password;
574
0
    *pPasswordLength = id->PasswordLength;
575
0
  }
576
577
0
  return TRUE;
578
0
}
579
580
BOOL sspi_CopyAuthIdentityFieldsA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pUser,
581
                                  char** pDomain, char** pPassword)
582
0
{
583
0
  BOOL success = FALSE;
584
0
  const char* UserA = NULL;
585
0
  const char* DomainA = NULL;
586
0
  const char* PasswordA = NULL;
587
0
  const WCHAR* UserW = NULL;
588
0
  const WCHAR* DomainW = NULL;
589
0
  const WCHAR* PasswordW = NULL;
590
0
  UINT32 UserLength = 0;
591
0
  UINT32 DomainLength = 0;
592
0
  UINT32 PasswordLength = 0;
593
594
0
  if (!identity || !pUser || !pDomain || !pPassword)
595
0
    return FALSE;
596
597
0
  *pUser = *pDomain = *pPassword = NULL;
598
599
0
  UINT32 identityFlags = sspi_GetAuthIdentityFlags(identity);
600
601
0
  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
602
0
  {
603
0
    if (!sspi_GetAuthIdentityUserDomainA(identity, &UserA, &UserLength, &DomainA,
604
0
                                         &DomainLength))
605
0
      goto cleanup;
606
607
0
    if (!sspi_GetAuthIdentityPasswordA(identity, &PasswordA, &PasswordLength))
608
0
      goto cleanup;
609
610
0
    if (UserA && UserLength)
611
0
    {
612
0
      *pUser = _strdup(UserA);
613
614
0
      if (!(*pUser))
615
0
        goto cleanup;
616
0
    }
617
618
0
    if (DomainA && DomainLength)
619
0
    {
620
0
      *pDomain = _strdup(DomainA);
621
622
0
      if (!(*pDomain))
623
0
        goto cleanup;
624
0
    }
625
626
0
    if (PasswordA && PasswordLength)
627
0
    {
628
0
      *pPassword = _strdup(PasswordA);
629
630
0
      if (!(*pPassword))
631
0
        goto cleanup;
632
0
    }
633
634
0
    success = TRUE;
635
0
  }
636
0
  else
637
0
  {
638
0
    if (!sspi_GetAuthIdentityUserDomainW(identity, &UserW, &UserLength, &DomainW,
639
0
                                         &DomainLength))
640
0
      goto cleanup;
641
642
0
    if (!sspi_GetAuthIdentityPasswordW(identity, &PasswordW, &PasswordLength))
643
0
      goto cleanup;
644
645
0
    if (UserW && (UserLength > 0))
646
0
    {
647
0
      *pUser = ConvertWCharNToUtf8Alloc(UserW, UserLength, NULL);
648
0
      if (!(*pUser))
649
0
        goto cleanup;
650
0
    }
651
652
0
    if (DomainW && (DomainLength > 0))
653
0
    {
654
0
      *pDomain = ConvertWCharNToUtf8Alloc(DomainW, DomainLength, NULL);
655
0
      if (!(*pDomain))
656
0
        goto cleanup;
657
0
    }
658
659
0
    if (PasswordW && (PasswordLength > 0))
660
0
    {
661
0
      *pPassword = ConvertWCharNToUtf8Alloc(PasswordW, PasswordLength, NULL);
662
0
      if (!(*pPassword))
663
0
        goto cleanup;
664
0
    }
665
666
0
    success = TRUE;
667
0
  }
668
669
0
cleanup:
670
0
  return success;
671
0
}
672
673
BOOL sspi_CopyAuthIdentityFieldsW(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, WCHAR** pUser,
674
                                  WCHAR** pDomain, WCHAR** pPassword)
675
0
{
676
0
  BOOL success = FALSE;
677
0
  const char* UserA = NULL;
678
0
  const char* DomainA = NULL;
679
0
  const char* PasswordA = NULL;
680
0
  const WCHAR* UserW = NULL;
681
0
  const WCHAR* DomainW = NULL;
682
0
  const WCHAR* PasswordW = NULL;
683
0
  UINT32 UserLength = 0;
684
0
  UINT32 DomainLength = 0;
685
0
  UINT32 PasswordLength = 0;
686
687
0
  if (!identity || !pUser || !pDomain || !pPassword)
688
0
    return FALSE;
689
690
0
  *pUser = *pDomain = *pPassword = NULL;
691
692
0
  UINT32 identityFlags = sspi_GetAuthIdentityFlags(identity);
693
694
0
  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
695
0
  {
696
0
    if (!sspi_GetAuthIdentityUserDomainA(identity, &UserA, &UserLength, &DomainA,
697
0
                                         &DomainLength))
698
0
      goto cleanup;
699
700
0
    if (!sspi_GetAuthIdentityPasswordA(identity, &PasswordA, &PasswordLength))
701
0
      goto cleanup;
702
703
0
    if (UserA && (UserLength > 0))
704
0
    {
705
0
      WCHAR* ptr = ConvertUtf8NToWCharAlloc(UserA, UserLength, NULL);
706
0
      *pUser = ptr;
707
708
0
      if (!ptr)
709
0
        goto cleanup;
710
0
    }
711
712
0
    if (DomainA && (DomainLength > 0))
713
0
    {
714
0
      WCHAR* ptr = ConvertUtf8NToWCharAlloc(DomainA, DomainLength, NULL);
715
0
      *pDomain = ptr;
716
0
      if (!ptr)
717
0
        goto cleanup;
718
0
    }
719
720
0
    if (PasswordA && (PasswordLength > 0))
721
0
    {
722
0
      WCHAR* ptr = ConvertUtf8NToWCharAlloc(PasswordA, PasswordLength, NULL);
723
724
0
      *pPassword = ptr;
725
0
      if (!ptr)
726
0
        goto cleanup;
727
0
    }
728
729
0
    success = TRUE;
730
0
  }
731
0
  else
732
0
  {
733
0
    if (!sspi_GetAuthIdentityUserDomainW(identity, &UserW, &UserLength, &DomainW,
734
0
                                         &DomainLength))
735
0
      goto cleanup;
736
737
0
    if (!sspi_GetAuthIdentityPasswordW(identity, &PasswordW, &PasswordLength))
738
0
      goto cleanup;
739
740
0
    if (UserW && UserLength)
741
0
    {
742
0
      *pUser = _wcsdup(UserW);
743
744
0
      if (!(*pUser))
745
0
        goto cleanup;
746
0
    }
747
748
0
    if (DomainW && DomainLength)
749
0
    {
750
0
      *pDomain = _wcsdup(DomainW);
751
752
0
      if (!(*pDomain))
753
0
        goto cleanup;
754
0
    }
755
756
0
    if (PasswordW && PasswordLength)
757
0
    {
758
0
      *pPassword = _wcsdup(PasswordW);
759
760
0
      if (!(*pPassword))
761
0
        goto cleanup;
762
0
    }
763
764
0
    success = TRUE;
765
0
  }
766
767
0
cleanup:
768
0
  return success;
769
0
}
770
771
BOOL sspi_CopyAuthPackageListA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pPackageList)
772
0
{
773
0
  UINT32 version;
774
0
  UINT32 identityFlags;
775
0
  char* PackageList = NULL;
776
0
  const char* PackageListA = NULL;
777
0
  const WCHAR* PackageListW = NULL;
778
0
  UINT32 PackageListLength = 0;
779
0
  UINT32 PackageListOffset = 0;
780
0
  const void* pAuthData = (const void*)identity;
781
782
0
  if (!pAuthData)
783
0
    return FALSE;
784
785
0
  version = sspi_GetAuthIdentityVersion(pAuthData);
786
0
  identityFlags = sspi_GetAuthIdentityFlags(pAuthData);
787
788
0
  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
789
0
  {
790
0
    if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
791
0
    {
792
0
      const SEC_WINNT_AUTH_IDENTITY_EXA* ad = (const SEC_WINNT_AUTH_IDENTITY_EXA*)pAuthData;
793
0
      PackageListA = (const char*)ad->PackageList;
794
0
      PackageListLength = ad->PackageListLength;
795
0
    }
796
797
0
    if (PackageListA && PackageListLength)
798
0
    {
799
0
      PackageList = _strdup(PackageListA);
800
0
    }
801
0
  }
802
0
  else
803
0
  {
804
0
    if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
805
0
    {
806
0
      const SEC_WINNT_AUTH_IDENTITY_EXW* ad = (const SEC_WINNT_AUTH_IDENTITY_EXW*)pAuthData;
807
0
      PackageListW = (const WCHAR*)ad->PackageList;
808
0
      PackageListLength = ad->PackageListLength;
809
0
    }
810
0
    else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
811
0
    {
812
0
      const SEC_WINNT_AUTH_IDENTITY_EX2* ad = (const SEC_WINNT_AUTH_IDENTITY_EX2*)pAuthData;
813
0
      PackageListOffset = ad->PackageListOffset;
814
0
      PackageListW = (const WCHAR*)&((const uint8_t*)pAuthData)[PackageListOffset];
815
0
      PackageListLength = ad->PackageListLength / 2;
816
0
    }
817
818
0
    if (PackageListW && (PackageListLength > 0))
819
0
      PackageList = ConvertWCharNToUtf8Alloc(PackageListW, PackageListLength, NULL);
820
0
  }
821
822
0
  if (PackageList)
823
0
  {
824
0
    *pPackageList = PackageList;
825
0
    return TRUE;
826
0
  }
827
828
0
  return FALSE;
829
0
}
830
831
int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
832
                          const SEC_WINNT_AUTH_IDENTITY_INFO* srcIdentity)
833
0
{
834
0
  int status;
835
0
  UINT32 identityFlags;
836
0
  const char* UserA = NULL;
837
0
  const char* DomainA = NULL;
838
0
  const char* PasswordA = NULL;
839
0
  const WCHAR* UserW = NULL;
840
0
  const WCHAR* DomainW = NULL;
841
0
  const WCHAR* PasswordW = NULL;
842
0
  UINT32 UserLength = 0;
843
0
  UINT32 DomainLength = 0;
844
0
  UINT32 PasswordLength = 0;
845
846
0
  sspi_FreeAuthIdentity(identity);
847
848
0
  identityFlags = sspi_GetAuthIdentityFlags(srcIdentity);
849
850
0
  identity->Flags = identityFlags;
851
852
0
  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
853
0
  {
854
0
    if (!sspi_GetAuthIdentityUserDomainA(srcIdentity, &UserA, &UserLength, &DomainA,
855
0
                                         &DomainLength))
856
0
    {
857
0
      return -1;
858
0
    }
859
860
0
    if (!sspi_GetAuthIdentityPasswordA(srcIdentity, &PasswordA, &PasswordLength))
861
0
    {
862
0
      return -1;
863
0
    }
864
865
0
    status = sspi_SetAuthIdentity(identity, UserA, DomainA, PasswordA);
866
867
0
    if (status <= 0)
868
0
      return -1;
869
870
0
    identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
871
0
    identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
872
0
    return 1;
873
0
  }
874
875
0
  identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
876
877
0
  if (!sspi_GetAuthIdentityUserDomainW(srcIdentity, &UserW, &UserLength, &DomainW, &DomainLength))
878
0
  {
879
0
    return -1;
880
0
  }
881
882
0
  if (!sspi_GetAuthIdentityPasswordW(srcIdentity, &PasswordW, &PasswordLength))
883
0
  {
884
0
    return -1;
885
0
  }
886
887
  /* login/password authentication */
888
0
  identity->UserLength = UserLength;
889
890
0
  if (identity->UserLength > 0)
891
0
  {
892
0
    identity->User = (UINT16*)calloc((identity->UserLength + 1), sizeof(WCHAR));
893
894
0
    if (!identity->User)
895
0
      return -1;
896
897
0
    CopyMemory(identity->User, UserW, identity->UserLength * sizeof(WCHAR));
898
0
    identity->User[identity->UserLength] = 0;
899
0
  }
900
901
0
  identity->DomainLength = DomainLength;
902
903
0
  if (identity->DomainLength > 0)
904
0
  {
905
0
    identity->Domain = (UINT16*)calloc((identity->DomainLength + 1), sizeof(WCHAR));
906
907
0
    if (!identity->Domain)
908
0
      return -1;
909
910
0
    CopyMemory(identity->Domain, DomainW, identity->DomainLength * sizeof(WCHAR));
911
0
    identity->Domain[identity->DomainLength] = 0;
912
0
  }
913
914
0
  identity->PasswordLength = PasswordLength;
915
916
0
  if (identity->PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
917
0
    identity->PasswordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
918
919
0
  if (PasswordW)
920
0
  {
921
0
    identity->Password = (UINT16*)calloc((identity->PasswordLength + 1), sizeof(WCHAR));
922
923
0
    if (!identity->Password)
924
0
      return -1;
925
926
0
    CopyMemory(identity->Password, PasswordW, identity->PasswordLength * sizeof(WCHAR));
927
0
    identity->Password[identity->PasswordLength] = 0;
928
0
  }
929
930
0
  identity->PasswordLength = PasswordLength;
931
  /* End of login/password authentication */
932
0
  return 1;
933
0
}
934
935
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType)
936
0
{
937
0
  ULONG index;
938
0
  PSecBuffer pSecBuffer = NULL;
939
940
0
  for (index = 0; index < pMessage->cBuffers; index++)
941
0
  {
942
0
    if (pMessage->pBuffers[index].BufferType == BufferType)
943
0
    {
944
0
      pSecBuffer = &pMessage->pBuffers[index];
945
0
      break;
946
0
    }
947
0
  }
948
949
0
  return pSecBuffer;
950
0
}
951
952
static BOOL CALLBACK sspi_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context)
953
0
{
954
0
  winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
955
0
  sspi_ContextBufferAllocTableNew();
956
0
  return TRUE;
957
0
}
958
959
void sspi_GlobalInit(void)
960
0
{
961
0
  static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
962
0
  DWORD flags = 0;
963
0
  InitOnceExecuteOnce(&once, sspi_init, &flags, NULL);
964
0
}
965
966
void sspi_GlobalFinish(void)
967
0
{
968
0
  sspi_ContextBufferAllocTableFree();
969
0
}
970
971
static const SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name)
972
0
{
973
0
  int index;
974
0
  UINT32 cPackages;
975
0
  cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
976
977
0
  for (index = 0; index < (int)cPackages; index++)
978
0
  {
979
0
    if (strcmp(Name, SecurityFunctionTableA_NAME_LIST[index].Name) == 0)
980
0
    {
981
0
      return (const SecurityFunctionTableA*)SecurityFunctionTableA_NAME_LIST[index]
982
0
          .SecurityFunctionTable;
983
0
    }
984
0
  }
985
986
0
  return NULL;
987
0
}
988
989
static const SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name)
990
0
{
991
0
  int index;
992
0
  UINT32 cPackages;
993
0
  cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
994
995
0
  for (index = 0; index < (int)cPackages; index++)
996
0
  {
997
0
    if (_wcscmp(Name, SecurityFunctionTableW_NAME_LIST[index].Name) == 0)
998
0
    {
999
0
      return (const SecurityFunctionTableW*)SecurityFunctionTableW_NAME_LIST[index]
1000
0
          .SecurityFunctionTable;
1001
0
    }
1002
0
  }
1003
1004
0
  return NULL;
1005
0
}
1006
1007
static const SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name)
1008
0
{
1009
0
  SEC_WCHAR* NameW = NULL;
1010
0
  const SecurityFunctionTableW* table = NULL;
1011
1012
0
  if (!Name)
1013
0
    return NULL;
1014
1015
0
  NameW = ConvertUtf8ToWCharAlloc(Name, NULL);
1016
1017
0
  if (!NameW)
1018
0
    return NULL;
1019
1020
0
  table = sspi_GetSecurityFunctionTableWByNameW(NameW);
1021
0
  free(NameW);
1022
0
  return table;
1023
0
}
1024
1025
static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
1026
static void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
1027
1028
static void sspi_ContextBufferFree(void* contextBuffer)
1029
0
{
1030
0
  UINT32 index;
1031
0
  UINT32 allocatorIndex;
1032
1033
0
  for (index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
1034
0
  {
1035
0
    if (contextBuffer == ContextBufferAllocTable.entries[index].contextBuffer)
1036
0
    {
1037
0
      contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer;
1038
0
      allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex;
1039
0
      ContextBufferAllocTable.cEntries--;
1040
0
      ContextBufferAllocTable.entries[index].allocatorIndex = 0;
1041
0
      ContextBufferAllocTable.entries[index].contextBuffer = NULL;
1042
1043
0
      switch (allocatorIndex)
1044
0
      {
1045
0
        case EnumerateSecurityPackagesIndex:
1046
0
          FreeContextBuffer_EnumerateSecurityPackages(contextBuffer);
1047
0
          break;
1048
1049
0
        case QuerySecurityPackageInfoIndex:
1050
0
          FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer);
1051
0
          break;
1052
0
      }
1053
0
    }
1054
0
  }
1055
0
}
1056
1057
/**
1058
 * Standard SSPI API
1059
 */
1060
1061
/* Package Management */
1062
1063
static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages,
1064
                                                                  PSecPkgInfoW* ppPackageInfo)
1065
0
{
1066
0
  int index;
1067
0
  size_t size;
1068
0
  UINT32 cPackages;
1069
0
  SecPkgInfoW* pPackageInfo;
1070
0
  cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
1071
0
  size = sizeof(SecPkgInfoW) * cPackages;
1072
0
  pPackageInfo = (SecPkgInfoW*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
1073
1074
0
  if (!pPackageInfo)
1075
0
    return SEC_E_INSUFFICIENT_MEMORY;
1076
1077
0
  for (index = 0; index < (int)cPackages; index++)
1078
0
  {
1079
0
    pPackageInfo[index].fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
1080
0
    pPackageInfo[index].wVersion = SecPkgInfoW_LIST[index]->wVersion;
1081
0
    pPackageInfo[index].wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
1082
0
    pPackageInfo[index].cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
1083
0
    pPackageInfo[index].Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
1084
0
    pPackageInfo[index].Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
1085
0
  }
1086
1087
0
  *(pcPackages) = cPackages;
1088
0
  *(ppPackageInfo) = pPackageInfo;
1089
0
  return SEC_E_OK;
1090
0
}
1091
1092
static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages,
1093
                                                                  PSecPkgInfoA* ppPackageInfo)
1094
0
{
1095
0
  int index;
1096
0
  size_t size;
1097
0
  UINT32 cPackages;
1098
0
  SecPkgInfoA* pPackageInfo;
1099
0
  cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
1100
0
  size = sizeof(SecPkgInfoA) * cPackages;
1101
0
  pPackageInfo = (SecPkgInfoA*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
1102
1103
0
  if (!pPackageInfo)
1104
0
    return SEC_E_INSUFFICIENT_MEMORY;
1105
1106
0
  for (index = 0; index < (int)cPackages; index++)
1107
0
  {
1108
0
    pPackageInfo[index].fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
1109
0
    pPackageInfo[index].wVersion = SecPkgInfoA_LIST[index]->wVersion;
1110
0
    pPackageInfo[index].wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
1111
0
    pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
1112
0
    pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name);
1113
0
    pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
1114
1115
0
    if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment)
1116
0
    {
1117
0
      sspi_ContextBufferFree(pPackageInfo);
1118
0
      return SEC_E_INSUFFICIENT_MEMORY;
1119
0
    }
1120
0
  }
1121
1122
0
  *(pcPackages) = cPackages;
1123
0
  *(ppPackageInfo) = pPackageInfo;
1124
0
  return SEC_E_OK;
1125
0
}
1126
1127
static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer)
1128
0
{
1129
0
  int index;
1130
0
  UINT32 cPackages;
1131
0
  SecPkgInfoA* pPackageInfo = (SecPkgInfoA*)contextBuffer;
1132
0
  cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
1133
1134
0
  if (!pPackageInfo)
1135
0
    return;
1136
1137
0
  for (index = 0; index < (int)cPackages; index++)
1138
0
  {
1139
0
    free(pPackageInfo[index].Name);
1140
0
    free(pPackageInfo[index].Comment);
1141
0
  }
1142
1143
0
  free(pPackageInfo);
1144
0
}
1145
1146
SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void)
1147
0
{
1148
0
  return &winpr_SecurityFunctionTableW;
1149
0
}
1150
1151
SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void)
1152
0
{
1153
0
  return &winpr_SecurityFunctionTableA;
1154
0
}
1155
1156
static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
1157
                                                                 PSecPkgInfoW* ppPackageInfo)
1158
0
{
1159
0
  int index;
1160
0
  size_t size;
1161
0
  UINT32 cPackages;
1162
0
  SecPkgInfoW* pPackageInfo;
1163
0
  cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
1164
1165
0
  for (index = 0; index < (int)cPackages; index++)
1166
0
  {
1167
0
    if (_wcscmp(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
1168
0
    {
1169
0
      size = sizeof(SecPkgInfoW);
1170
0
      pPackageInfo =
1171
0
          (SecPkgInfoW*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
1172
1173
0
      if (!pPackageInfo)
1174
0
        return SEC_E_INSUFFICIENT_MEMORY;
1175
1176
0
      pPackageInfo->fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
1177
0
      pPackageInfo->wVersion = SecPkgInfoW_LIST[index]->wVersion;
1178
0
      pPackageInfo->wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
1179
0
      pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
1180
0
      pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
1181
0
      pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
1182
0
      *(ppPackageInfo) = pPackageInfo;
1183
0
      return SEC_E_OK;
1184
0
    }
1185
0
  }
1186
1187
0
  *(ppPackageInfo) = NULL;
1188
0
  return SEC_E_SECPKG_NOT_FOUND;
1189
0
}
1190
1191
static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
1192
                                                                 PSecPkgInfoA* ppPackageInfo)
1193
0
{
1194
0
  int index;
1195
0
  size_t size;
1196
0
  UINT32 cPackages;
1197
0
  SecPkgInfoA* pPackageInfo;
1198
0
  cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
1199
1200
0
  for (index = 0; index < (int)cPackages; index++)
1201
0
  {
1202
0
    if (strcmp(pszPackageName, SecPkgInfoA_LIST[index]->Name) == 0)
1203
0
    {
1204
0
      size = sizeof(SecPkgInfoA);
1205
0
      pPackageInfo =
1206
0
          (SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
1207
1208
0
      if (!pPackageInfo)
1209
0
        return SEC_E_INSUFFICIENT_MEMORY;
1210
1211
0
      pPackageInfo->fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
1212
0
      pPackageInfo->wVersion = SecPkgInfoA_LIST[index]->wVersion;
1213
0
      pPackageInfo->wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
1214
0
      pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
1215
0
      pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name);
1216
0
      pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
1217
1218
0
      if (!pPackageInfo->Name || !pPackageInfo->Comment)
1219
0
      {
1220
0
        sspi_ContextBufferFree(pPackageInfo);
1221
0
        return SEC_E_INSUFFICIENT_MEMORY;
1222
0
      }
1223
1224
0
      *(ppPackageInfo) = pPackageInfo;
1225
0
      return SEC_E_OK;
1226
0
    }
1227
0
  }
1228
1229
0
  *(ppPackageInfo) = NULL;
1230
0
  return SEC_E_SECPKG_NOT_FOUND;
1231
0
}
1232
1233
void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer)
1234
0
{
1235
0
  SecPkgInfo* pPackageInfo = (SecPkgInfo*)contextBuffer;
1236
1237
0
  if (!pPackageInfo)
1238
0
    return;
1239
1240
0
  free(pPackageInfo->Name);
1241
0
  free(pPackageInfo->Comment);
1242
0
  free(pPackageInfo);
1243
0
}
1244
1245
/* Credential Management */
1246
1247
static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(
1248
    SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
1249
    void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
1250
    PTimeStamp ptsExpiry)
1251
0
{
1252
0
  SECURITY_STATUS status;
1253
0
  const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
1254
1255
0
  if (!table)
1256
0
    return SEC_E_SECPKG_NOT_FOUND;
1257
1258
0
  if (!table->AcquireCredentialsHandleW)
1259
0
  {
1260
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1261
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1262
0
  }
1263
1264
0
  status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
1265
0
                                            pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
1266
0
                                            ptsExpiry);
1267
1268
0
  if (IsSecurityStatusError(status))
1269
0
  {
1270
0
    WLog_WARN(TAG, "AcquireCredentialsHandleW status %s [0x%08" PRIX32 "]",
1271
0
              GetSecurityStatusString(status), status);
1272
0
  }
1273
1274
0
  return status;
1275
0
}
1276
1277
static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(
1278
    SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
1279
    void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
1280
    PTimeStamp ptsExpiry)
1281
0
{
1282
0
  SECURITY_STATUS status;
1283
0
  const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
1284
1285
0
  if (!table)
1286
0
    return SEC_E_SECPKG_NOT_FOUND;
1287
1288
0
  if (!table->AcquireCredentialsHandleA)
1289
0
  {
1290
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1291
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1292
0
  }
1293
1294
0
  status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
1295
0
                                            pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
1296
0
                                            ptsExpiry);
1297
1298
0
  if (IsSecurityStatusError(status))
1299
0
  {
1300
0
    WLog_WARN(TAG, "AcquireCredentialsHandleA status %s [0x%08" PRIX32 "]",
1301
0
              GetSecurityStatusString(status), status);
1302
0
  }
1303
1304
0
  return status;
1305
0
}
1306
1307
static SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
1308
                                                             PSecBuffer pPackedContext,
1309
                                                             HANDLE* pToken)
1310
0
{
1311
0
  SEC_CHAR* Name;
1312
0
  SECURITY_STATUS status;
1313
0
  const SecurityFunctionTableW* table;
1314
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1315
1316
0
  if (!Name)
1317
0
    return SEC_E_SECPKG_NOT_FOUND;
1318
1319
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1320
1321
0
  if (!table)
1322
0
    return SEC_E_SECPKG_NOT_FOUND;
1323
1324
0
  if (!table->ExportSecurityContext)
1325
0
  {
1326
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1327
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1328
0
  }
1329
1330
0
  status = table->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
1331
1332
0
  if (IsSecurityStatusError(status))
1333
0
  {
1334
0
    WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08" PRIX32 "]",
1335
0
              GetSecurityStatusString(status), status);
1336
0
  }
1337
1338
0
  return status;
1339
0
}
1340
1341
static SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
1342
0
{
1343
0
  char* Name;
1344
0
  SECURITY_STATUS status;
1345
0
  const SecurityFunctionTableA* table;
1346
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1347
1348
0
  if (!Name)
1349
0
    return SEC_E_SECPKG_NOT_FOUND;
1350
1351
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1352
1353
0
  if (!table)
1354
0
    return SEC_E_SECPKG_NOT_FOUND;
1355
1356
0
  if (!table->FreeCredentialsHandle)
1357
0
  {
1358
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1359
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1360
0
  }
1361
1362
0
  status = table->FreeCredentialsHandle(phCredential);
1363
1364
0
  if (IsSecurityStatusError(status))
1365
0
  {
1366
0
    WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08" PRIX32 "]",
1367
0
              GetSecurityStatusString(status), status);
1368
0
  }
1369
1370
0
  return status;
1371
0
}
1372
1373
static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage,
1374
                                                              PSecBuffer pPackedContext,
1375
                                                              HANDLE pToken, PCtxtHandle phContext)
1376
0
{
1377
0
  SEC_CHAR* Name;
1378
0
  SECURITY_STATUS status;
1379
0
  const SecurityFunctionTableW* table;
1380
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1381
1382
0
  if (!Name)
1383
0
    return SEC_E_SECPKG_NOT_FOUND;
1384
1385
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1386
1387
0
  if (!table)
1388
0
    return SEC_E_SECPKG_NOT_FOUND;
1389
1390
0
  if (!table->ImportSecurityContextW)
1391
0
  {
1392
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1393
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1394
0
  }
1395
1396
0
  status = table->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
1397
1398
0
  if (IsSecurityStatusError(status))
1399
0
  {
1400
0
    WLog_WARN(TAG, "ImportSecurityContextW status %s [0x%08" PRIX32 "]",
1401
0
              GetSecurityStatusString(status), status);
1402
0
  }
1403
1404
0
  return status;
1405
0
}
1406
1407
static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage,
1408
                                                              PSecBuffer pPackedContext,
1409
                                                              HANDLE pToken, PCtxtHandle phContext)
1410
0
{
1411
0
  char* Name = NULL;
1412
0
  SECURITY_STATUS status;
1413
0
  const SecurityFunctionTableA* table;
1414
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1415
1416
0
  if (!Name)
1417
0
    return SEC_E_SECPKG_NOT_FOUND;
1418
1419
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1420
1421
0
  if (!table)
1422
0
    return SEC_E_SECPKG_NOT_FOUND;
1423
1424
0
  if (!table->ImportSecurityContextA)
1425
0
  {
1426
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1427
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1428
0
  }
1429
1430
0
  status = table->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
1431
1432
0
  if (IsSecurityStatusError(status))
1433
0
  {
1434
0
    WLog_WARN(TAG, "ImportSecurityContextA status %s [0x%08" PRIX32 "]",
1435
0
              GetSecurityStatusString(status), status);
1436
0
  }
1437
1438
0
  return status;
1439
0
}
1440
1441
static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential,
1442
                                                                   ULONG ulAttribute, void* pBuffer)
1443
0
{
1444
0
  SEC_WCHAR* Name;
1445
0
  SECURITY_STATUS status;
1446
0
  const SecurityFunctionTableW* table;
1447
0
  Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1448
1449
0
  if (!Name)
1450
0
    return SEC_E_SECPKG_NOT_FOUND;
1451
1452
0
  table = sspi_GetSecurityFunctionTableWByNameW(Name);
1453
1454
0
  if (!table)
1455
0
    return SEC_E_SECPKG_NOT_FOUND;
1456
1457
0
  if (!table->QueryCredentialsAttributesW)
1458
0
  {
1459
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1460
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1461
0
  }
1462
1463
0
  status = table->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
1464
1465
0
  if (IsSecurityStatusError(status))
1466
0
  {
1467
0
    WLog_WARN(TAG, "QueryCredentialsAttributesW status %s [0x%08" PRIX32 "]",
1468
0
              GetSecurityStatusString(status), status);
1469
0
  }
1470
1471
0
  return status;
1472
0
}
1473
1474
static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential,
1475
                                                                   ULONG ulAttribute, void* pBuffer)
1476
0
{
1477
0
  char* Name;
1478
0
  SECURITY_STATUS status;
1479
0
  const SecurityFunctionTableA* table;
1480
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1481
1482
0
  if (!Name)
1483
0
    return SEC_E_SECPKG_NOT_FOUND;
1484
1485
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1486
1487
0
  if (!table)
1488
0
    return SEC_E_SECPKG_NOT_FOUND;
1489
1490
0
  if (!table->QueryCredentialsAttributesA)
1491
0
  {
1492
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1493
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1494
0
  }
1495
1496
0
  status = table->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
1497
1498
0
  if (IsSecurityStatusError(status))
1499
0
  {
1500
0
    WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08" PRIX32 "]",
1501
0
              GetSecurityStatusString(status), status);
1502
0
  }
1503
1504
0
  return status;
1505
0
}
1506
1507
static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesW(PCredHandle phCredential,
1508
                                                                 ULONG ulAttribute, void* pBuffer,
1509
                                                                 ULONG cbBuffer)
1510
0
{
1511
0
  SEC_WCHAR* Name;
1512
0
  SECURITY_STATUS status;
1513
0
  const SecurityFunctionTableW* table;
1514
0
  Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1515
1516
0
  if (!Name)
1517
0
    return SEC_E_SECPKG_NOT_FOUND;
1518
1519
0
  table = sspi_GetSecurityFunctionTableWByNameW(Name);
1520
1521
0
  if (!table)
1522
0
    return SEC_E_SECPKG_NOT_FOUND;
1523
1524
0
  if (!table->SetCredentialsAttributesW)
1525
0
  {
1526
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1527
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1528
0
  }
1529
1530
0
  status = table->SetCredentialsAttributesW(phCredential, ulAttribute, pBuffer, cbBuffer);
1531
1532
0
  if (IsSecurityStatusError(status))
1533
0
  {
1534
0
    WLog_WARN(TAG, "SetCredentialsAttributesW status %s [0x%08" PRIX32 "]",
1535
0
              GetSecurityStatusString(status), status);
1536
0
  }
1537
1538
0
  return status;
1539
0
}
1540
1541
static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesA(PCredHandle phCredential,
1542
                                                                 ULONG ulAttribute, void* pBuffer,
1543
                                                                 ULONG cbBuffer)
1544
0
{
1545
0
  char* Name;
1546
0
  SECURITY_STATUS status;
1547
0
  const SecurityFunctionTableA* table;
1548
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1549
1550
0
  if (!Name)
1551
0
    return SEC_E_SECPKG_NOT_FOUND;
1552
1553
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1554
1555
0
  if (!table)
1556
0
    return SEC_E_SECPKG_NOT_FOUND;
1557
1558
0
  if (!table->SetCredentialsAttributesA)
1559
0
  {
1560
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1561
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1562
0
  }
1563
1564
0
  status = table->SetCredentialsAttributesA(phCredential, ulAttribute, pBuffer, cbBuffer);
1565
1566
0
  if (IsSecurityStatusError(status))
1567
0
  {
1568
0
    WLog_WARN(TAG, "SetCredentialsAttributesA status %s [0x%08" PRIX32 "]",
1569
0
              GetSecurityStatusString(status), status);
1570
0
  }
1571
1572
0
  return status;
1573
0
}
1574
1575
/* Context Management */
1576
1577
static SECURITY_STATUS SEC_ENTRY
1578
winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
1579
                            ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
1580
                            PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
1581
0
{
1582
0
  char* Name;
1583
0
  SECURITY_STATUS status;
1584
0
  const SecurityFunctionTableA* table;
1585
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1586
1587
0
  if (!Name)
1588
0
    return SEC_E_SECPKG_NOT_FOUND;
1589
1590
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1591
1592
0
  if (!table)
1593
0
    return SEC_E_SECPKG_NOT_FOUND;
1594
1595
0
  if (!table->AcceptSecurityContext)
1596
0
  {
1597
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1598
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1599
0
  }
1600
1601
0
  status =
1602
0
      table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
1603
0
                                   phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
1604
1605
0
  if (IsSecurityStatusError(status))
1606
0
  {
1607
0
    WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08" PRIX32 "]",
1608
0
              GetSecurityStatusString(status), status);
1609
0
  }
1610
1611
0
  return status;
1612
0
}
1613
1614
static SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext,
1615
                                                         PSecBufferDesc pInput)
1616
0
{
1617
0
  char* Name = NULL;
1618
0
  SECURITY_STATUS status;
1619
0
  const SecurityFunctionTableA* table;
1620
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1621
1622
0
  if (!Name)
1623
0
    return SEC_E_SECPKG_NOT_FOUND;
1624
1625
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1626
1627
0
  if (!table)
1628
0
    return SEC_E_SECPKG_NOT_FOUND;
1629
1630
0
  if (!table->ApplyControlToken)
1631
0
  {
1632
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1633
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1634
0
  }
1635
1636
0
  status = table->ApplyControlToken(phContext, pInput);
1637
1638
0
  if (IsSecurityStatusError(status))
1639
0
  {
1640
0
    WLog_WARN(TAG, "ApplyControlToken status %s [0x%08" PRIX32 "]",
1641
0
              GetSecurityStatusString(status), status);
1642
0
  }
1643
1644
0
  return status;
1645
0
}
1646
1647
static SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext,
1648
                                                         PSecBufferDesc pToken)
1649
0
{
1650
0
  char* Name = NULL;
1651
0
  SECURITY_STATUS status;
1652
0
  const SecurityFunctionTableA* table;
1653
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1654
1655
0
  if (!Name)
1656
0
    return SEC_E_SECPKG_NOT_FOUND;
1657
1658
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1659
1660
0
  if (!table)
1661
0
    return SEC_E_SECPKG_NOT_FOUND;
1662
1663
0
  if (!table->CompleteAuthToken)
1664
0
  {
1665
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1666
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1667
0
  }
1668
1669
0
  status = table->CompleteAuthToken(phContext, pToken);
1670
1671
0
  if (IsSecurityStatusError(status))
1672
0
  {
1673
0
    WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08" PRIX32 "]",
1674
0
              GetSecurityStatusString(status), status);
1675
0
  }
1676
1677
0
  return status;
1678
0
}
1679
1680
static SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
1681
0
{
1682
0
  const char* Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1683
1684
0
  if (!Name)
1685
0
    return SEC_E_SECPKG_NOT_FOUND;
1686
1687
0
  const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1688
1689
0
  if (!table)
1690
0
    return SEC_E_SECPKG_NOT_FOUND;
1691
1692
0
  if (!table->DeleteSecurityContext)
1693
0
  {
1694
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1695
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1696
0
  }
1697
1698
0
  const UINT32 status = table->DeleteSecurityContext(phContext);
1699
1700
0
  if (IsSecurityStatusError(status))
1701
0
  {
1702
0
    WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08" PRIX32 "]",
1703
0
              GetSecurityStatusString(status), status);
1704
0
  }
1705
1706
0
  return status;
1707
0
}
1708
1709
static SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer)
1710
0
{
1711
0
  if (!pvContextBuffer)
1712
0
    return SEC_E_INVALID_HANDLE;
1713
1714
0
  sspi_ContextBufferFree(pvContextBuffer);
1715
0
  return SEC_E_OK;
1716
0
}
1717
1718
static SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext)
1719
0
{
1720
0
  SEC_CHAR* Name;
1721
0
  SECURITY_STATUS status;
1722
0
  const SecurityFunctionTableW* table;
1723
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1724
1725
0
  if (!Name)
1726
0
    return SEC_E_SECPKG_NOT_FOUND;
1727
1728
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1729
1730
0
  if (!table)
1731
0
    return SEC_E_SECPKG_NOT_FOUND;
1732
1733
0
  if (!table->ImpersonateSecurityContext)
1734
0
  {
1735
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1736
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1737
0
  }
1738
1739
0
  status = table->ImpersonateSecurityContext(phContext);
1740
1741
0
  if (IsSecurityStatusError(status))
1742
0
  {
1743
0
    WLog_WARN(TAG, "ImpersonateSecurityContext status %s [0x%08" PRIX32 "]",
1744
0
              GetSecurityStatusString(status), status);
1745
0
  }
1746
1747
0
  return status;
1748
0
}
1749
1750
static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(
1751
    PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
1752
    ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1753
    PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1754
0
{
1755
0
  SEC_CHAR* Name;
1756
0
  SECURITY_STATUS status;
1757
0
  const SecurityFunctionTableW* table;
1758
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1759
1760
0
  if (!Name)
1761
0
    return SEC_E_SECPKG_NOT_FOUND;
1762
1763
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1764
1765
0
  if (!table)
1766
0
    return SEC_E_SECPKG_NOT_FOUND;
1767
1768
0
  if (!table->InitializeSecurityContextW)
1769
0
  {
1770
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1771
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1772
0
  }
1773
1774
0
  status = table->InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq,
1775
0
                                             Reserved1, TargetDataRep, pInput, Reserved2,
1776
0
                                             phNewContext, pOutput, pfContextAttr, ptsExpiry);
1777
1778
0
  if (IsSecurityStatusError(status))
1779
0
  {
1780
0
    WLog_WARN(TAG, "InitializeSecurityContextW status %s [0x%08" PRIX32 "]",
1781
0
              GetSecurityStatusString(status), status);
1782
0
  }
1783
1784
0
  return status;
1785
0
}
1786
1787
static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(
1788
    PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
1789
    ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1790
    PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1791
0
{
1792
0
  SEC_CHAR* Name;
1793
0
  SECURITY_STATUS status;
1794
0
  const SecurityFunctionTableA* table;
1795
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1796
1797
0
  if (!Name)
1798
0
    return SEC_E_SECPKG_NOT_FOUND;
1799
1800
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1801
1802
0
  if (!table)
1803
0
    return SEC_E_SECPKG_NOT_FOUND;
1804
1805
0
  if (!table->InitializeSecurityContextA)
1806
0
  {
1807
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1808
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1809
0
  }
1810
1811
0
  status = table->InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq,
1812
0
                                             Reserved1, TargetDataRep, pInput, Reserved2,
1813
0
                                             phNewContext, pOutput, pfContextAttr, ptsExpiry);
1814
1815
0
  if (IsSecurityStatusError(status))
1816
0
  {
1817
0
    WLog_WARN(TAG, "InitializeSecurityContextA status %s [0x%08" PRIX32 "]",
1818
0
              GetSecurityStatusString(status), status);
1819
0
  }
1820
1821
0
  return status;
1822
0
}
1823
1824
static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext,
1825
                                                               ULONG ulAttribute, void* pBuffer)
1826
0
{
1827
0
  SEC_CHAR* Name;
1828
0
  SECURITY_STATUS status;
1829
0
  const SecurityFunctionTableW* table;
1830
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1831
1832
0
  if (!Name)
1833
0
    return SEC_E_SECPKG_NOT_FOUND;
1834
1835
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1836
1837
0
  if (!table)
1838
0
    return SEC_E_SECPKG_NOT_FOUND;
1839
1840
0
  if (!table->QueryContextAttributesW)
1841
0
  {
1842
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1843
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1844
0
  }
1845
1846
0
  status = table->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
1847
1848
0
  if (IsSecurityStatusError(status))
1849
0
  {
1850
0
    WLog_WARN(TAG, "QueryContextAttributesW status %s [0x%08" PRIX32 "]",
1851
0
              GetSecurityStatusString(status), status);
1852
0
  }
1853
1854
0
  return status;
1855
0
}
1856
1857
static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext,
1858
                                                               ULONG ulAttribute, void* pBuffer)
1859
0
{
1860
0
  SEC_CHAR* Name;
1861
0
  SECURITY_STATUS status;
1862
0
  const SecurityFunctionTableA* table;
1863
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1864
1865
0
  if (!Name)
1866
0
    return SEC_E_SECPKG_NOT_FOUND;
1867
1868
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1869
1870
0
  if (!table)
1871
0
    return SEC_E_SECPKG_NOT_FOUND;
1872
1873
0
  if (!table->QueryContextAttributesA)
1874
0
  {
1875
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1876
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1877
0
  }
1878
1879
0
  status = table->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
1880
1881
0
  if (IsSecurityStatusError(status))
1882
0
  {
1883
0
    WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08" PRIX32 "]",
1884
0
              GetSecurityStatusString(status), status);
1885
0
  }
1886
1887
0
  return status;
1888
0
}
1889
1890
static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext,
1891
                                                                 HANDLE* phToken)
1892
0
{
1893
0
  SEC_CHAR* Name;
1894
0
  SECURITY_STATUS status;
1895
0
  const SecurityFunctionTableW* table;
1896
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1897
1898
0
  if (!Name)
1899
0
    return SEC_E_SECPKG_NOT_FOUND;
1900
1901
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1902
1903
0
  if (!table)
1904
0
    return SEC_E_SECPKG_NOT_FOUND;
1905
1906
0
  if (!table->QuerySecurityContextToken)
1907
0
  {
1908
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1909
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1910
0
  }
1911
1912
0
  status = table->QuerySecurityContextToken(phContext, phToken);
1913
1914
0
  if (IsSecurityStatusError(status))
1915
0
  {
1916
0
    WLog_WARN(TAG, "QuerySecurityContextToken status %s [0x%08" PRIX32 "]",
1917
0
              GetSecurityStatusString(status), status);
1918
0
  }
1919
1920
0
  return status;
1921
0
}
1922
1923
static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext,
1924
                                                             ULONG ulAttribute, void* pBuffer,
1925
                                                             ULONG cbBuffer)
1926
0
{
1927
0
  SEC_CHAR* Name;
1928
0
  SECURITY_STATUS status;
1929
0
  const SecurityFunctionTableW* table;
1930
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1931
1932
0
  if (!Name)
1933
0
    return SEC_E_SECPKG_NOT_FOUND;
1934
1935
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1936
1937
0
  if (!table)
1938
0
    return SEC_E_SECPKG_NOT_FOUND;
1939
1940
0
  if (!table->SetContextAttributesW)
1941
0
  {
1942
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1943
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1944
0
  }
1945
1946
0
  status = table->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
1947
1948
0
  if (IsSecurityStatusError(status))
1949
0
  {
1950
0
    WLog_WARN(TAG, "SetContextAttributesW status %s [0x%08" PRIX32 "]",
1951
0
              GetSecurityStatusString(status), status);
1952
0
  }
1953
1954
0
  return status;
1955
0
}
1956
1957
static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext,
1958
                                                             ULONG ulAttribute, void* pBuffer,
1959
                                                             ULONG cbBuffer)
1960
0
{
1961
0
  char* Name;
1962
0
  SECURITY_STATUS status;
1963
0
  const SecurityFunctionTableA* table;
1964
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1965
1966
0
  if (!Name)
1967
0
    return SEC_E_SECPKG_NOT_FOUND;
1968
1969
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1970
1971
0
  if (!table)
1972
0
    return SEC_E_SECPKG_NOT_FOUND;
1973
1974
0
  if (!table->SetContextAttributesA)
1975
0
  {
1976
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
1977
0
    return SEC_E_UNSUPPORTED_FUNCTION;
1978
0
  }
1979
1980
0
  status = table->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
1981
1982
0
  if (IsSecurityStatusError(status))
1983
0
  {
1984
0
    WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08" PRIX32 "]",
1985
0
              GetSecurityStatusString(status), status);
1986
0
  }
1987
1988
0
  return status;
1989
0
}
1990
1991
static SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
1992
0
{
1993
0
  SEC_CHAR* Name;
1994
0
  SECURITY_STATUS status;
1995
0
  const SecurityFunctionTableW* table;
1996
0
  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1997
1998
0
  if (!Name)
1999
0
    return SEC_E_SECPKG_NOT_FOUND;
2000
2001
0
  table = sspi_GetSecurityFunctionTableWByNameA(Name);
2002
2003
0
  if (!table)
2004
0
    return SEC_E_SECPKG_NOT_FOUND;
2005
2006
0
  if (!table->RevertSecurityContext)
2007
0
  {
2008
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
2009
0
    return SEC_E_UNSUPPORTED_FUNCTION;
2010
0
  }
2011
2012
0
  status = table->RevertSecurityContext(phContext);
2013
2014
0
  if (IsSecurityStatusError(status))
2015
0
  {
2016
0
    WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08" PRIX32 "]",
2017
0
              GetSecurityStatusString(status), status);
2018
0
  }
2019
2020
0
  return status;
2021
0
}
2022
2023
/* Message Support */
2024
2025
static SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext,
2026
                                                      PSecBufferDesc pMessage, ULONG MessageSeqNo,
2027
                                                      PULONG pfQOP)
2028
0
{
2029
0
  char* Name;
2030
0
  SECURITY_STATUS status;
2031
0
  const SecurityFunctionTableA* table;
2032
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2033
2034
0
  if (!Name)
2035
0
    return SEC_E_SECPKG_NOT_FOUND;
2036
2037
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2038
2039
0
  if (!table)
2040
0
    return SEC_E_SECPKG_NOT_FOUND;
2041
2042
0
  if (!table->DecryptMessage)
2043
0
  {
2044
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
2045
0
    return SEC_E_UNSUPPORTED_FUNCTION;
2046
0
  }
2047
2048
0
  status = table->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
2049
2050
0
  if (IsSecurityStatusError(status))
2051
0
  {
2052
0
    WLog_WARN(TAG, "DecryptMessage status %s [0x%08" PRIX32 "]",
2053
0
              GetSecurityStatusString(status), status);
2054
0
  }
2055
2056
0
  return status;
2057
0
}
2058
2059
static SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
2060
                                                      PSecBufferDesc pMessage, ULONG MessageSeqNo)
2061
0
{
2062
0
  char* Name;
2063
0
  SECURITY_STATUS status;
2064
0
  const SecurityFunctionTableA* table;
2065
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2066
2067
0
  if (!Name)
2068
0
    return SEC_E_SECPKG_NOT_FOUND;
2069
2070
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2071
2072
0
  if (!table)
2073
0
    return SEC_E_SECPKG_NOT_FOUND;
2074
2075
0
  if (!table->EncryptMessage)
2076
0
  {
2077
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
2078
0
    return SEC_E_UNSUPPORTED_FUNCTION;
2079
0
  }
2080
2081
0
  status = table->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
2082
2083
0
  if (status != SEC_E_OK)
2084
0
  {
2085
0
    WLog_ERR(TAG, "EncryptMessage status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
2086
0
             status);
2087
0
  }
2088
2089
0
  return status;
2090
0
}
2091
2092
static SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
2093
                                                     PSecBufferDesc pMessage, ULONG MessageSeqNo)
2094
0
{
2095
0
  char* Name;
2096
0
  SECURITY_STATUS status;
2097
0
  const SecurityFunctionTableA* table;
2098
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2099
2100
0
  if (!Name)
2101
0
    return SEC_E_SECPKG_NOT_FOUND;
2102
2103
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2104
2105
0
  if (!table)
2106
0
    return SEC_E_SECPKG_NOT_FOUND;
2107
2108
0
  if (!table->MakeSignature)
2109
0
  {
2110
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
2111
0
    return SEC_E_UNSUPPORTED_FUNCTION;
2112
0
  }
2113
2114
0
  status = table->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
2115
2116
0
  if (IsSecurityStatusError(status))
2117
0
  {
2118
0
    WLog_WARN(TAG, "MakeSignature status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
2119
0
              status);
2120
0
  }
2121
2122
0
  return status;
2123
0
}
2124
2125
static SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext,
2126
                                                       PSecBufferDesc pMessage, ULONG MessageSeqNo,
2127
                                                       PULONG pfQOP)
2128
0
{
2129
0
  char* Name;
2130
0
  SECURITY_STATUS status;
2131
0
  const SecurityFunctionTableA* table;
2132
0
  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2133
2134
0
  if (!Name)
2135
0
    return SEC_E_SECPKG_NOT_FOUND;
2136
2137
0
  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2138
2139
0
  if (!table)
2140
0
    return SEC_E_SECPKG_NOT_FOUND;
2141
2142
0
  if (!table->VerifySignature)
2143
0
  {
2144
0
    WLog_WARN(TAG, "Security module does not provide an implementation");
2145
0
    return SEC_E_UNSUPPORTED_FUNCTION;
2146
0
  }
2147
2148
0
  status = table->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
2149
2150
0
  if (IsSecurityStatusError(status))
2151
0
  {
2152
0
    WLog_WARN(TAG, "VerifySignature status %s [0x%08" PRIX32 "]",
2153
0
              GetSecurityStatusString(status), status);
2154
0
  }
2155
2156
0
  return status;
2157
0
}
2158
2159
static SecurityFunctionTableA winpr_SecurityFunctionTableA = {
2160
  3,                                 /* dwVersion */
2161
  winpr_EnumerateSecurityPackagesA,  /* EnumerateSecurityPackages */
2162
  winpr_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
2163
  winpr_AcquireCredentialsHandleA,   /* AcquireCredentialsHandle */
2164
  winpr_FreeCredentialsHandle,       /* FreeCredentialsHandle */
2165
  NULL,                              /* Reserved2 */
2166
  winpr_InitializeSecurityContextA,  /* InitializeSecurityContext */
2167
  winpr_AcceptSecurityContext,       /* AcceptSecurityContext */
2168
  winpr_CompleteAuthToken,           /* CompleteAuthToken */
2169
  winpr_DeleteSecurityContext,       /* DeleteSecurityContext */
2170
  winpr_ApplyControlToken,           /* ApplyControlToken */
2171
  winpr_QueryContextAttributesA,     /* QueryContextAttributes */
2172
  winpr_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
2173
  winpr_RevertSecurityContext,       /* RevertSecurityContext */
2174
  winpr_MakeSignature,               /* MakeSignature */
2175
  winpr_VerifySignature,             /* VerifySignature */
2176
  winpr_FreeContextBuffer,           /* FreeContextBuffer */
2177
  winpr_QuerySecurityPackageInfoA,   /* QuerySecurityPackageInfo */
2178
  NULL,                              /* Reserved3 */
2179
  NULL,                              /* Reserved4 */
2180
  winpr_ExportSecurityContext,       /* ExportSecurityContext */
2181
  winpr_ImportSecurityContextA,      /* ImportSecurityContext */
2182
  NULL,                              /* AddCredentials */
2183
  NULL,                              /* Reserved8 */
2184
  winpr_QuerySecurityContextToken,   /* QuerySecurityContextToken */
2185
  winpr_EncryptMessage,              /* EncryptMessage */
2186
  winpr_DecryptMessage,              /* DecryptMessage */
2187
  winpr_SetContextAttributesA,       /* SetContextAttributes */
2188
  winpr_SetCredentialsAttributesA,   /* SetCredentialsAttributes */
2189
};
2190
2191
static SecurityFunctionTableW winpr_SecurityFunctionTableW = {
2192
  3,                                 /* dwVersion */
2193
  winpr_EnumerateSecurityPackagesW,  /* EnumerateSecurityPackages */
2194
  winpr_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
2195
  winpr_AcquireCredentialsHandleW,   /* AcquireCredentialsHandle */
2196
  winpr_FreeCredentialsHandle,       /* FreeCredentialsHandle */
2197
  NULL,                              /* Reserved2 */
2198
  winpr_InitializeSecurityContextW,  /* InitializeSecurityContext */
2199
  winpr_AcceptSecurityContext,       /* AcceptSecurityContext */
2200
  winpr_CompleteAuthToken,           /* CompleteAuthToken */
2201
  winpr_DeleteSecurityContext,       /* DeleteSecurityContext */
2202
  winpr_ApplyControlToken,           /* ApplyControlToken */
2203
  winpr_QueryContextAttributesW,     /* QueryContextAttributes */
2204
  winpr_ImpersonateSecurityContext,  /* ImpersonateSecurityContext */
2205
  winpr_RevertSecurityContext,       /* RevertSecurityContext */
2206
  winpr_MakeSignature,               /* MakeSignature */
2207
  winpr_VerifySignature,             /* VerifySignature */
2208
  winpr_FreeContextBuffer,           /* FreeContextBuffer */
2209
  winpr_QuerySecurityPackageInfoW,   /* QuerySecurityPackageInfo */
2210
  NULL,                              /* Reserved3 */
2211
  NULL,                              /* Reserved4 */
2212
  winpr_ExportSecurityContext,       /* ExportSecurityContext */
2213
  winpr_ImportSecurityContextW,      /* ImportSecurityContext */
2214
  NULL,                              /* AddCredentials */
2215
  NULL,                              /* Reserved8 */
2216
  winpr_QuerySecurityContextToken,   /* QuerySecurityContextToken */
2217
  winpr_EncryptMessage,              /* EncryptMessage */
2218
  winpr_DecryptMessage,              /* DecryptMessage */
2219
  winpr_SetContextAttributesW,       /* SetContextAttributes */
2220
  winpr_SetCredentialsAttributesW,   /* SetCredentialsAttributes */
2221
};