Coverage Report

Created: 2025-07-01 06:46

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