Coverage Report

Created: 2024-05-20 06:11

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