Coverage Report

Created: 2026-01-10 06:30

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