]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/sspwin32.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / lib / sspwin32.cc
1 /*
2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "base64.h"
11 #include "ntlmauth/ntlmauth.h"
12 #include "sspwin32.h"
13 #include "util.h"
14
15 typedef struct _AUTH_SEQ {
16 BOOL fInitialized;
17 BOOL fHaveCredHandle;
18 BOOL fHaveCtxtHandle;
19 CredHandle hcred;
20 TimeStamp hcredLifeTime;
21 struct _SecHandle hctxt;
22 TimeStamp hctxtLifeTime;
23 } AUTH_SEQ, *PAUTH_SEQ;
24
25 BOOL GenClientContext(PAUTH_SEQ, PSEC_WINNT_AUTH_IDENTITY, PVOID, DWORD, PVOID, PDWORD, PBOOL);
26 BOOL GenServerContext(PAUTH_SEQ, PVOID, DWORD, PVOID, PDWORD, PBOOL, char *);
27
28 static HMODULE hModule;
29 static int NTLM_mode = SSP_BASIC;
30 static char * SSP_Package_InUse;
31 SECURITY_STATUS SecurityStatus = SEC_E_OK;
32
33 static DWORD cbMaxToken = 0;
34 static uint8_t * pClientBuf = NULL;
35 static uint8_t * pServerBuf = NULL;
36
37 static AUTH_SEQ NTLM_asServer = {0};
38
39 BOOL Use_Unicode = FALSE;
40 BOOL NTLM_LocalCall = FALSE;
41
42 /* Function pointers */
43 ACCEPT_SECURITY_CONTEXT_FN _AcceptSecurityContext = NULL;
44 ACQUIRE_CREDENTIALS_HANDLE_FN _AcquireCredentialsHandle = NULL;
45 COMPLETE_AUTH_TOKEN_FN _CompleteAuthToken = NULL;
46 DELETE_SECURITY_CONTEXT_FN _DeleteSecurityContext = NULL;
47 FREE_CONTEXT_BUFFER_FN _FreeContextBuffer = NULL;
48 FREE_CREDENTIALS_HANDLE_FN _FreeCredentialsHandle = NULL;
49 INITIALIZE_SECURITY_CONTEXT_FN _InitializeSecurityContext = NULL;
50 QUERY_SECURITY_PACKAGE_INFO_FN _QuerySecurityPackageInfo = NULL;
51 #ifdef UNICODE
52 QUERY_CONTEXT_ATTRIBUTES_FN_W _QueryContextAttributes = NULL;
53 #else
54 QUERY_CONTEXT_ATTRIBUTES_FN_A _QueryContextAttributes = NULL;
55 #endif
56
57 void UnloadSecurityDll(void)
58 {
59 if (NTLM_asServer.fHaveCtxtHandle)
60 _DeleteSecurityContext(&NTLM_asServer.hctxt);
61 if (NTLM_asServer.fHaveCredHandle)
62 _FreeCredentialsHandle(&NTLM_asServer.hcred);
63
64 if (hModule)
65 FreeLibrary(hModule);
66
67 xfree(SSP_Package_InUse);
68 xfree(pClientBuf);
69 xfree(pServerBuf);
70
71 _AcceptSecurityContext = NULL;
72 _AcquireCredentialsHandle = NULL;
73 _CompleteAuthToken = NULL;
74 _DeleteSecurityContext = NULL;
75 _FreeContextBuffer = NULL;
76 _FreeCredentialsHandle = NULL;
77 _InitializeSecurityContext = NULL;
78 _QuerySecurityPackageInfo = NULL;
79 _QueryContextAttributes = NULL;
80
81 hModule = NULL;
82 }
83
84 HMODULE LoadSecurityDll(int mode, const char * SSP_Package)
85 {
86 TCHAR lpszDLL[MAX_PATH];
87 OSVERSIONINFO VerInfo;
88 PSecPkgInfo pSPI = NULL;
89
90 /*
91 * Find out which security DLL to use, depending on
92 * whether we are on NT or 2000 or XP or 2003 Server
93 * We have to use security.dll on Windows NT 4.0.
94 * All other operating systems, we have to use Secur32.dll
95 */
96 hModule = NULL;
97 if ((mode != SSP_BASIC) && (mode != SSP_NTLM))
98 return hModule;
99 NTLM_mode = mode;
100 VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
101 if (!GetVersionEx (&VerInfo)) { /* If this fails, something has gone wrong */
102 return hModule;
103 }
104 if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
105 VerInfo.dwMajorVersion == 4 &&
106 VerInfo.dwMinorVersion == 0) {
107 lstrcpy (lpszDLL, _T(WINNT_SECURITY_DLL));
108 } else {
109 lstrcpy (lpszDLL, _T(WIN2K_SECURITY_DLL));
110 }
111 hModule = LoadLibrary(lpszDLL);
112 if (!hModule)
113 return hModule;
114 _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN)
115 GetProcAddress(hModule, "AcceptSecurityContext");
116 if (!_AcceptSecurityContext) {
117 UnloadSecurityDll();
118 hModule = NULL;
119 return hModule;
120 }
121 #ifdef UNICODE
122 _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)
123 GetProcAddress(hModule, "AcquireCredentialsHandleW");
124 #else
125 _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)
126 GetProcAddress(hModule, "AcquireCredentialsHandleA");
127 #endif
128 if (!_AcquireCredentialsHandle) {
129 UnloadSecurityDll();
130 hModule = NULL;
131 return hModule;
132 }
133 _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN)
134 GetProcAddress(hModule, "CompleteAuthToken");
135 if (!_CompleteAuthToken) {
136 UnloadSecurityDll();
137 hModule = NULL;
138 return hModule;
139 }
140 _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN)
141 GetProcAddress(hModule, "DeleteSecurityContext");
142 if (!_DeleteSecurityContext) {
143 UnloadSecurityDll();
144 hModule = NULL;
145 return hModule;
146 }
147 _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN)
148 GetProcAddress(hModule, "FreeContextBuffer");
149 if (!_FreeContextBuffer) {
150 UnloadSecurityDll();
151 hModule = NULL;
152 return hModule;
153 }
154 _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN)
155 GetProcAddress(hModule, "FreeCredentialsHandle");
156 if (!_FreeCredentialsHandle) {
157 UnloadSecurityDll();
158 hModule = NULL;
159 return hModule;
160 }
161 #ifdef UNICODE
162 _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)
163 GetProcAddress(hModule, "InitializeSecurityContextW");
164 #else
165 _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)
166 GetProcAddress(hModule, "InitializeSecurityContextA");
167 #endif
168 if (!_InitializeSecurityContext) {
169 UnloadSecurityDll();
170 hModule = NULL;
171 return hModule;
172 }
173 #ifdef UNICODE
174 _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)
175 GetProcAddress(hModule, "QuerySecurityPackageInfoW");
176 #else
177 _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)
178 GetProcAddress(hModule, "QuerySecurityPackageInfoA");
179 #endif
180 if (!_QuerySecurityPackageInfo) {
181 UnloadSecurityDll();
182 hModule = NULL;
183 }
184
185 #ifdef UNICODE
186 _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_W)
187 GetProcAddress(hModule, "QueryContextAttributesW");
188 #else
189 _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_A)
190 GetProcAddress(hModule, "QueryContextAttributesA");
191 #endif
192 if (!_QueryContextAttributes) {
193 UnloadSecurityDll();
194 hModule = NULL;
195 }
196
197 /* Get max token size */
198 _QuerySecurityPackageInfo((SEC_CHAR*)_T(SSP_Package), &pSPI);
199 cbMaxToken = pSPI->cbMaxToken;
200 _FreeContextBuffer(pSPI);
201
202 /* Allocate buffers for client and server messages */
203 pClientBuf = static_cast<uint8_t *>(xcalloc(cbMaxToken, sizeof(char)));
204 pServerBuf = static_cast<uint8_t *>(xcalloc(cbMaxToken, sizeof(char)));
205 SSP_Package_InUse = xstrdup(SSP_Package);
206
207 return hModule;
208 }
209
210 BOOL GenClientContext(PAUTH_SEQ pAS, PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
211 PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone)
212 {
213 /*
214 * Routine Description:
215 *
216 * Optionally takes an input buffer coming from the server and returns
217 * a buffer of information to send back to the server. Also returns
218 * an indication of whether or not the context is complete.
219 *
220 * Return Value:
221 * Returns TRUE if successful; otherwise FALSE.
222 */
223 TimeStamp tsExpiry;
224 SecBufferDesc sbdOut;
225 SecBuffer sbOut;
226 SecBufferDesc sbdIn;
227 SecBuffer sbIn;
228 ULONG fContextAttr;
229
230 if (!pAS->fInitialized) {
231 SecurityStatus = _AcquireCredentialsHandle(NULL, (SEC_CHAR*) _T(SSP_Package_InUse),
232 SECPKG_CRED_OUTBOUND, NULL, (NTLM_mode == SSP_NTLM) ? NULL : pAuthIdentity, NULL, NULL,
233 &pAS->hcred, &tsExpiry);
234 if (SecurityStatus < 0)
235 return FALSE;
236 pAS->fHaveCredHandle = TRUE;
237 }
238
239 /* Prepare output buffer */
240 sbdOut.ulVersion = 0;
241 sbdOut.cBuffers = 1;
242 sbdOut.pBuffers = &sbOut;
243 sbOut.cbBuffer = *pcbOut;
244 sbOut.BufferType = SECBUFFER_TOKEN;
245 sbOut.pvBuffer = pOut;
246
247 /* Prepare input buffer */
248 if (pAS->fInitialized) {
249 sbdIn.ulVersion = 0;
250 sbdIn.cBuffers = 1;
251 sbdIn.pBuffers = &sbIn;
252 sbIn.cbBuffer = cbIn;
253 sbIn.BufferType = SECBUFFER_TOKEN;
254 sbIn.pvBuffer = pIn;
255 }
256 SecurityStatus = _InitializeSecurityContext(&pAS->hcred,
257 pAS->fInitialized ? &pAS->hctxt : NULL, NULL, 0, 0,
258 SECURITY_NATIVE_DREP, pAS->fInitialized ? &sbdIn : NULL,
259 0, &pAS->hctxt, &sbdOut, &fContextAttr, &tsExpiry);
260 if (SecurityStatus < 0)
261 return FALSE;
262 pAS->fHaveCtxtHandle = TRUE;
263
264 /* If necessary, complete token */
265 if (SecurityStatus == SEC_I_COMPLETE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE) {
266 SecurityStatus = _CompleteAuthToken(&pAS->hctxt, &sbdOut);
267 if (SecurityStatus < 0)
268 return FALSE;
269 }
270 *pcbOut = sbOut.cbBuffer;
271 if (!pAS->fInitialized)
272 pAS->fInitialized = TRUE;
273 *pfDone = !(SecurityStatus == SEC_I_CONTINUE_NEEDED
274 || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE );
275 return TRUE;
276 }
277
278 BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut,
279 PDWORD pcbOut, PBOOL pfDone, char * credentials)
280 {
281 /*
282 * Routine Description:
283 *
284 * Takes an input buffer coming from the client and returns a buffer
285 * to be sent to the client. Also returns an indication of whether or
286 * not the context is complete.
287 *
288 * Return Value:
289 *
290 * Returns TRUE if successful; otherwise FALSE.
291 */
292
293 SecBufferDesc sbdOut;
294 SecBuffer sbOut;
295 SecBufferDesc sbdIn;
296 SecBuffer sbIn;
297 ULONG fContextAttr;
298 SecPkgContext_Names namebuffer;
299
300 if (!pAS->fInitialized) {
301 SecurityStatus = _AcquireCredentialsHandle(NULL, (SEC_CHAR*) _T(SSP_Package_InUse),
302 SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred,
303 &pAS->hcredLifeTime);
304 #if SSP_DEBUG
305 fprintf(stderr, "AcquireCredentialsHandle returned: %x\n", SecurityStatus);
306 #endif
307 if (SecurityStatus < 0) {
308 #if SSP_DEBUG
309 fprintf(stderr, "AcquireCredentialsHandle failed: %x\n", SecurityStatus);
310 #endif
311 return FALSE;
312 }
313 pAS->fHaveCredHandle = TRUE;
314 }
315
316 /* Prepare output buffer */
317 sbdOut.ulVersion = 0;
318 sbdOut.cBuffers = 1;
319 sbdOut.pBuffers = &sbOut;
320 sbOut.cbBuffer = *pcbOut;
321 sbOut.BufferType = SECBUFFER_TOKEN;
322 sbOut.pvBuffer = pOut;
323
324 /* Prepare input buffer */
325 sbdIn.ulVersion = 0;
326 sbdIn.cBuffers = 1;
327 sbdIn.pBuffers = &sbIn;
328 sbIn.cbBuffer = cbIn;
329 sbIn.BufferType = SECBUFFER_TOKEN;
330 sbIn.pvBuffer = pIn;
331 SecurityStatus = _AcceptSecurityContext(&pAS->hcred,
332 pAS->fInitialized ? &pAS->hctxt : NULL, &sbdIn, (NTLM_mode == SSP_NTLM) ? ASC_REQ_DELEGATE : 0,
333 SECURITY_NATIVE_DREP, &pAS->hctxt, &sbdOut, &fContextAttr,
334 &pAS->hctxtLifeTime);
335 #if SSP_DEBUG
336 fprintf(stderr, "AcceptSecurityContext returned: %x\n", SecurityStatus);
337 #endif
338 if (SecurityStatus < 0) {
339 #if SSP_DEBUG
340 fprintf(stderr, "AcceptSecurityContext failed: %x\n", SecurityStatus);
341 #endif
342 return FALSE;
343 }
344 pAS->fHaveCtxtHandle = TRUE;
345
346 /* If necessary, complete token */
347 if (SecurityStatus == SEC_I_COMPLETE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE) {
348 SecurityStatus = _CompleteAuthToken(&pAS->hctxt, &sbdOut);
349 #if SSP_DEBUG
350 fprintf(stderr, "CompleteAuthToken returned: %x\n", SecurityStatus);
351 #endif
352 if (SecurityStatus < 0) {
353 #if SSP_DEBUG
354 fprintf(stderr, "CompleteAuthToken failed: %x\n", SecurityStatus);
355 #endif
356 return FALSE;
357 }
358 }
359
360 if ((credentials != NULL) &&
361 !(SecurityStatus == SEC_I_CONTINUE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE)) {
362 SecurityStatus = _QueryContextAttributes(&pAS->hctxt, SECPKG_ATTR_NAMES, &namebuffer);
363 #if SSP_DEBUG
364 fprintf(stderr, "QueryContextAttributes returned: %x\n", SecurityStatus);
365 #endif
366 if (SecurityStatus < 0) {
367 #if SSP_DEBUG
368 fprintf(stderr, "QueryContextAttributes failed: %x\n", SecurityStatus);
369 #endif
370 return FALSE;
371 }
372 strncpy(credentials, namebuffer.sUserName, SSP_MAX_CRED_LEN);
373 }
374
375 *pcbOut = sbOut.cbBuffer;
376 if (!pAS->fInitialized)
377 pAS->fInitialized = TRUE;
378 *pfDone = !(SecurityStatus == SEC_I_CONTINUE_NEEDED
379 || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE);
380 return TRUE;
381 }
382
383 BOOL WINAPI SSP_LogonUser(PTSTR szUser, PTSTR szPassword, PTSTR szDomain)
384 {
385 AUTH_SEQ asServer = {0};
386 AUTH_SEQ asClient = {0};
387 BOOL fDone = FALSE;
388 BOOL fResult = FALSE;
389 DWORD cbOut = 0;
390 DWORD cbIn = 0;
391
392 SEC_WINNT_AUTH_IDENTITY ai;
393
394 do {
395 if (!hModule)
396 break;
397
398 /* Initialize auth identity structure */
399 ZeroMemory(&ai, sizeof(ai));
400 ai.Domain = (unsigned char *)szDomain;
401 ai.DomainLength = lstrlen(szDomain);
402 ai.User = (unsigned char *)szUser;
403 ai.UserLength = lstrlen(szUser);
404 ai.Password = (unsigned char *)szPassword;
405 ai.PasswordLength = lstrlen(szPassword);
406 #if defined(UNICODE) || defined(_UNICODE)
407 ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
408 #else
409 ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
410 #endif
411
412 /* Prepare client message (negotiate) */
413 cbOut = cbMaxToken;
414 if (!GenClientContext(&asClient, &ai, NULL, 0, pClientBuf, &cbOut, &fDone))
415 break;
416
417 /* Prepare server message (challenge) */
418 cbIn = cbOut;
419 cbOut = cbMaxToken;
420 if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
421 &fDone, NULL))
422 break;
423 /* Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED
424 * in the case of bad szUser or szPassword.
425 * Unexpected Result: Logon will succeed if you pass in a bad szUser and
426 * the guest account is enabled in the specified domain.
427 */
428
429 /* Prepare client message (authenticate) */
430 cbIn = cbOut;
431 cbOut = cbMaxToken;
432 if (!GenClientContext(&asClient, &ai, pServerBuf, cbIn, pClientBuf, &cbOut,
433 &fDone))
434 break;
435
436 /* Prepare server message (authentication) */
437 cbIn = cbOut;
438 cbOut = cbMaxToken;
439 if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
440 &fDone, NULL))
441 break;
442 fResult = TRUE;
443 } while (0);
444
445 /* Clean up resources */
446 if (asClient.fHaveCtxtHandle)
447 _DeleteSecurityContext(&asClient.hctxt);
448 if (asClient.fHaveCredHandle)
449 _FreeCredentialsHandle(&asClient.hcred);
450 if (asServer.fHaveCtxtHandle)
451 _DeleteSecurityContext(&asServer.hctxt);
452 if (asServer.fHaveCredHandle)
453 _FreeCredentialsHandle(&asServer.hcred);
454
455 return fResult;
456 }
457
458 const char * WINAPI SSP_MakeChallenge(PVOID PNegotiateBuf, int NegotiateLen)
459 {
460 BOOL fDone = FALSE;
461 uint8_t * fResult = NULL;
462 DWORD cbOut = 0;
463 DWORD cbIn = 0;
464 ntlm_challenge * challenge;
465
466 if (NTLM_asServer.fHaveCtxtHandle)
467 _DeleteSecurityContext(&NTLM_asServer.hctxt);
468 if (NTLM_asServer.fHaveCredHandle)
469 _FreeCredentialsHandle(&NTLM_asServer.hcred);
470
471 NTLM_LocalCall = FALSE;
472 Use_Unicode = FALSE;
473 memcpy(pClientBuf, PNegotiateBuf, NegotiateLen);
474 ZeroMemory(pServerBuf, cbMaxToken);
475 ZeroMemory(&NTLM_asServer, sizeof(NTLM_asServer));
476 do {
477 if (!hModule)
478 break;
479
480 /* Prepare server message (challenge) */
481 cbIn = NegotiateLen;
482 cbOut = cbMaxToken;
483 if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
484 &fDone, NULL))
485 break;
486 fResult = pServerBuf;
487 } while (0);
488 if (fResult != NULL) {
489 challenge = (ntlm_challenge *) fResult;
490 Use_Unicode = NTLM_NEGOTIATE_UNICODE & challenge->flags;
491 NTLM_LocalCall = NTLM_NEGOTIATE_THIS_IS_LOCAL_CALL & challenge->flags;
492 struct base64_encode_ctx ctx;
493 base64_encode_init(&ctx);
494 static char encoded[8192];
495 size_t dstLen = base64_encode_update(&ctx, encoded, cbOut, reinterpret_cast<const uint8_t*>(fResult));
496 assert(dstLen < sizeof(encoded));
497 dstLen += base64_encode_final(&ctx, encoded+dstLen);
498 assert(dstLen < sizeof(encoded));
499 encoded[dstLen] = '\0';
500 return encoded;
501 }
502 return NULL;
503 }
504
505 BOOL WINAPI SSP_ValidateNTLMCredentials(PVOID PAutenticateBuf, int AutenticateLen, char * credentials)
506 {
507 BOOL fDone = FALSE;
508 BOOL fResult = FALSE;
509 DWORD cbOut = 0;
510 DWORD cbIn = 0;
511
512 memcpy(pClientBuf, PAutenticateBuf, AutenticateLen);
513 ZeroMemory(pServerBuf, cbMaxToken);
514 do {
515 if (!hModule)
516 break;
517
518 /* Prepare server message (authentication) */
519 cbIn = AutenticateLen;
520 cbOut = cbMaxToken;
521 if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
522 &fDone, credentials))
523 break;
524 fResult = TRUE;
525 } while (0);
526
527 return fResult;
528 }
529
530 const char * WINAPI SSP_MakeNegotiateBlob(PVOID PNegotiateBuf, int NegotiateLen, PBOOL fDone, int * Status, char * credentials)
531 {
532 DWORD cbOut = 0;
533 DWORD cbIn = 0;
534
535 if (NTLM_asServer.fHaveCtxtHandle)
536 _DeleteSecurityContext(&NTLM_asServer.hctxt);
537 if (NTLM_asServer.fHaveCredHandle)
538 _FreeCredentialsHandle(&NTLM_asServer.hcred);
539
540 memcpy(pClientBuf, PNegotiateBuf, NegotiateLen);
541 ZeroMemory(pServerBuf, cbMaxToken);
542 ZeroMemory(&NTLM_asServer, sizeof(NTLM_asServer));
543 do {
544 if (!hModule)
545 break;
546
547 /* Prepare server message (challenge) */
548 cbIn = NegotiateLen;
549 cbOut = cbMaxToken;
550 if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
551 fDone, credentials)) {
552 *Status = SSP_ERROR;
553 break;
554 }
555 *Status = SSP_OK;
556 } while (0);
557 if (pServerBuf != NULL && cbOut > 0) {
558 struct base64_encode_ctx ctx;
559 base64_encode_init(&ctx);
560 static char encoded[8192];
561 size_t dstLen = base64_encode_update(&ctx, encoded, cbOut, reinterpret_cast<const uint8_t*>(pServerBuf));
562 assert(dstLen < sizeof(encoded));
563 dstLen += base64_encode_final(&ctx, encoded+dstLen);
564 assert(dstLen < sizeof(encoded));
565 encoded[dstLen] = '\0';
566 return encoded;
567 }
568 return NULL;
569 }
570
571 const char * WINAPI SSP_ValidateNegotiateCredentials(PVOID PAutenticateBuf, int AutenticateLen, PBOOL fDone, int * Status, char * credentials)
572 {
573 DWORD cbOut = 0;
574 DWORD cbIn = 0;
575
576 memcpy(pClientBuf, PAutenticateBuf, AutenticateLen);
577 ZeroMemory(pServerBuf, cbMaxToken);
578 do {
579 if (!hModule)
580 break;
581
582 /* Prepare server message (authentication) */
583 cbIn = AutenticateLen;
584 cbOut = cbMaxToken;
585 if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
586 fDone, credentials)) {
587 *Status = SSP_ERROR;
588 break;
589 }
590 *Status = SSP_OK;
591 } while (0);
592 if (pServerBuf != NULL && cbOut > 0) {
593 struct base64_encode_ctx ctx;
594 base64_encode_init(&ctx);
595 static char encoded[8192];
596 size_t dstLen = base64_encode_update(&ctx, encoded, cbOut, reinterpret_cast<const uint8_t*>(pServerBuf));
597 assert(dstLen < sizeof(encoded));
598 dstLen += base64_encode_final(&ctx, encoded+dstLen);
599 assert(dstLen < sizeof(encoded));
600 encoded[dstLen] = '\0';
601 return encoded;
602 }
603 return NULL;
604 }
605