]>
Commit | Line | Data |
---|---|---|
0545caaa | 1 | /* |
5b74111a | 2 | * Copyright (C) 1996-2018 The Squid Software Foundation and contributors |
0545caaa AJ |
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 | */ | |
1b52df9a | 8 | |
f7f3304a | 9 | #include "squid.h" |
d6054896 AJ |
10 | #include "base64.h" |
11 | #include "ntlmauth/ntlmauth.h" | |
6e785d85 | 12 | #include "sspwin32.h" |
d6054896 | 13 | #include "util.h" |
6e785d85 | 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 PVOID pClientBuf = NULL; | |
35 | static PVOID 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) | |
26ac0430 | 60 | _DeleteSecurityContext(&NTLM_asServer.hctxt); |
6e785d85 | 61 | if (NTLM_asServer.fHaveCredHandle) |
62 | _FreeCredentialsHandle(&NTLM_asServer.hcred); | |
63 | ||
64 | if (hModule) | |
26ac0430 | 65 | FreeLibrary(hModule); |
6e785d85 | 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 | ||
d6054896 | 84 | HMODULE LoadSecurityDll(int mode, const char * SSP_Package) |
6e785d85 | 85 | { |
86 | TCHAR lpszDLL[MAX_PATH]; | |
87 | OSVERSIONINFO VerInfo; | |
88 | PSecPkgInfo pSPI = NULL; | |
89 | ||
26ac0430 AJ |
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 | */ | |
6e785d85 | 96 | hModule = NULL; |
97 | if ((mode != SSP_BASIC) && (mode != SSP_NTLM)) | |
26ac0430 | 98 | return hModule; |
6e785d85 | 99 | NTLM_mode = mode; |
100 | VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); | |
101 | if (!GetVersionEx (&VerInfo)) { /* If this fails, something has gone wrong */ | |
26ac0430 | 102 | return hModule; |
6e785d85 | 103 | } |
104 | if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && | |
26ac0430 AJ |
105 | VerInfo.dwMajorVersion == 4 && |
106 | VerInfo.dwMinorVersion == 0) { | |
107 | lstrcpy (lpszDLL, _T(WINNT_SECURITY_DLL)); | |
6e785d85 | 108 | } else { |
26ac0430 | 109 | lstrcpy (lpszDLL, _T(WIN2K_SECURITY_DLL)); |
6e785d85 | 110 | } |
111 | hModule = LoadLibrary(lpszDLL); | |
112 | if (!hModule) | |
26ac0430 AJ |
113 | return hModule; |
114 | _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN) | |
115 | GetProcAddress(hModule, "AcceptSecurityContext"); | |
6e785d85 | 116 | if (!_AcceptSecurityContext) { |
26ac0430 AJ |
117 | UnloadSecurityDll(); |
118 | hModule = NULL; | |
119 | return hModule; | |
6e785d85 | 120 | } |
121 | #ifdef UNICODE | |
122 | _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) | |
26ac0430 | 123 | GetProcAddress(hModule, "AcquireCredentialsHandleW"); |
6e785d85 | 124 | #else |
125 | _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) | |
26ac0430 | 126 | GetProcAddress(hModule, "AcquireCredentialsHandleA"); |
6e785d85 | 127 | #endif |
128 | if (!_AcquireCredentialsHandle) { | |
26ac0430 AJ |
129 | UnloadSecurityDll(); |
130 | hModule = NULL; | |
131 | return hModule; | |
6e785d85 | 132 | } |
26ac0430 AJ |
133 | _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN) |
134 | GetProcAddress(hModule, "CompleteAuthToken"); | |
6e785d85 | 135 | if (!_CompleteAuthToken) { |
26ac0430 AJ |
136 | UnloadSecurityDll(); |
137 | hModule = NULL; | |
138 | return hModule; | |
6e785d85 | 139 | } |
26ac0430 AJ |
140 | _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN) |
141 | GetProcAddress(hModule, "DeleteSecurityContext"); | |
6e785d85 | 142 | if (!_DeleteSecurityContext) { |
26ac0430 AJ |
143 | UnloadSecurityDll(); |
144 | hModule = NULL; | |
145 | return hModule; | |
6e785d85 | 146 | } |
26ac0430 AJ |
147 | _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN) |
148 | GetProcAddress(hModule, "FreeContextBuffer"); | |
6e785d85 | 149 | if (!_FreeContextBuffer) { |
26ac0430 AJ |
150 | UnloadSecurityDll(); |
151 | hModule = NULL; | |
152 | return hModule; | |
6e785d85 | 153 | } |
26ac0430 AJ |
154 | _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN) |
155 | GetProcAddress(hModule, "FreeCredentialsHandle"); | |
6e785d85 | 156 | if (!_FreeCredentialsHandle) { |
26ac0430 AJ |
157 | UnloadSecurityDll(); |
158 | hModule = NULL; | |
159 | return hModule; | |
6e785d85 | 160 | } |
161 | #ifdef UNICODE | |
162 | _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) | |
26ac0430 | 163 | GetProcAddress(hModule, "InitializeSecurityContextW"); |
6e785d85 | 164 | #else |
26ac0430 AJ |
165 | _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) |
166 | GetProcAddress(hModule, "InitializeSecurityContextA"); | |
6e785d85 | 167 | #endif |
168 | if (!_InitializeSecurityContext) { | |
26ac0430 AJ |
169 | UnloadSecurityDll(); |
170 | hModule = NULL; | |
171 | return hModule; | |
6e785d85 | 172 | } |
173 | #ifdef UNICODE | |
26ac0430 AJ |
174 | _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) |
175 | GetProcAddress(hModule, "QuerySecurityPackageInfoW"); | |
6e785d85 | 176 | #else |
177 | _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) | |
26ac0430 | 178 | GetProcAddress(hModule, "QuerySecurityPackageInfoA"); |
6e785d85 | 179 | #endif |
180 | if (!_QuerySecurityPackageInfo) { | |
26ac0430 AJ |
181 | UnloadSecurityDll(); |
182 | hModule = NULL; | |
6e785d85 | 183 | } |
184 | ||
185 | #ifdef UNICODE | |
26ac0430 AJ |
186 | _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_W) |
187 | GetProcAddress(hModule, "QueryContextAttributesW"); | |
6e785d85 | 188 | #else |
189 | _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_A) | |
26ac0430 | 190 | GetProcAddress(hModule, "QueryContextAttributesA"); |
6e785d85 | 191 | #endif |
192 | if (!_QueryContextAttributes) { | |
26ac0430 AJ |
193 | UnloadSecurityDll(); |
194 | hModule = NULL; | |
6e785d85 | 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 = xcalloc(cbMaxToken, sizeof(char)); | |
204 | pServerBuf = xcalloc(cbMaxToken, sizeof(char)); | |
205 | SSP_Package_InUse = xstrdup(SSP_Package); | |
206 | ||
207 | return hModule; | |
208 | } | |
209 | ||
6e785d85 | 210 | BOOL GenClientContext(PAUTH_SEQ pAS, PSEC_WINNT_AUTH_IDENTITY pAuthIdentity, |
26ac0430 | 211 | PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone) |
6e785d85 | 212 | { |
26ac0430 AJ |
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 | */ | |
6e785d85 | 223 | TimeStamp tsExpiry; |
224 | SecBufferDesc sbdOut; | |
225 | SecBuffer sbOut; | |
226 | SecBufferDesc sbdIn; | |
227 | SecBuffer sbIn; | |
228 | ULONG fContextAttr; | |
229 | ||
230 | if (!pAS->fInitialized) { | |
26ac0430 AJ |
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; | |
6e785d85 | 237 | } |
26ac0430 | 238 | |
6e785d85 | 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; | |
26ac0430 | 246 | |
6e785d85 | 247 | /* Prepare input buffer */ |
248 | if (pAS->fInitialized) { | |
26ac0430 AJ |
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; | |
6e785d85 | 255 | } |
26ac0430 AJ |
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; | |
6e785d85 | 262 | pAS->fHaveCtxtHandle = TRUE; |
26ac0430 | 263 | |
6e785d85 | 264 | /* If necessary, complete token */ |
265 | if (SecurityStatus == SEC_I_COMPLETE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE) { | |
26ac0430 AJ |
266 | SecurityStatus = _CompleteAuthToken(&pAS->hctxt, &sbdOut); |
267 | if (SecurityStatus < 0) | |
268 | return FALSE; | |
6e785d85 | 269 | } |
270 | *pcbOut = sbOut.cbBuffer; | |
271 | if (!pAS->fInitialized) | |
26ac0430 AJ |
272 | pAS->fInitialized = TRUE; |
273 | *pfDone = !(SecurityStatus == SEC_I_CONTINUE_NEEDED | |
274 | || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE ); | |
6e785d85 | 275 | return TRUE; |
276 | } | |
277 | ||
26ac0430 AJ |
278 | BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut, |
279 | PDWORD pcbOut, PBOOL pfDone, char * credentials) | |
6e785d85 | 280 | { |
26ac0430 AJ |
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 | */ | |
6e785d85 | 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) { | |
26ac0430 AJ |
301 | SecurityStatus = _AcquireCredentialsHandle(NULL, (SEC_CHAR*) _T(SSP_Package_InUse), |
302 | SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred, | |
303 | &pAS->hcredLifeTime); | |
6e785d85 | 304 | #if SSP_DEBUG |
305 | fprintf(stderr, "AcquireCredentialsHandle returned: %x\n", SecurityStatus); | |
306 | #endif | |
26ac0430 | 307 | if (SecurityStatus < 0) { |
6e785d85 | 308 | #if SSP_DEBUG |
309 | fprintf(stderr, "AcquireCredentialsHandle failed: %x\n", SecurityStatus); | |
310 | #endif | |
26ac0430 | 311 | return FALSE; |
6e785d85 | 312 | } |
26ac0430 | 313 | pAS->fHaveCredHandle = TRUE; |
6e785d85 | 314 | } |
26ac0430 | 315 | |
6e785d85 | 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; | |
26ac0430 AJ |
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); | |
6e785d85 | 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 | |
26ac0430 | 342 | return FALSE; |
6e785d85 | 343 | } |
344 | pAS->fHaveCtxtHandle = TRUE; | |
26ac0430 | 345 | |
6e785d85 | 346 | /* If necessary, complete token */ |
347 | if (SecurityStatus == SEC_I_COMPLETE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE) { | |
26ac0430 | 348 | SecurityStatus = _CompleteAuthToken(&pAS->hctxt, &sbdOut); |
6e785d85 | 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 | |
26ac0430 | 356 | return FALSE; |
6e785d85 | 357 | } |
358 | } | |
359 | ||
26ac0430 AJ |
360 | if ((credentials != NULL) && |
361 | !(SecurityStatus == SEC_I_CONTINUE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE)) { | |
6e785d85 | 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 | |
26ac0430 | 370 | return FALSE; |
6e785d85 | 371 | } |
372 | strncpy(credentials, namebuffer.sUserName, SSP_MAX_CRED_LEN); | |
373 | } | |
374 | ||
375 | *pcbOut = sbOut.cbBuffer; | |
376 | if (!pAS->fInitialized) | |
26ac0430 AJ |
377 | pAS->fInitialized = TRUE; |
378 | *pfDone = !(SecurityStatus == SEC_I_CONTINUE_NEEDED | |
379 | || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE); | |
6e785d85 | 380 | return TRUE; |
381 | } | |
382 | ||
26ac0430 | 383 | BOOL WINAPI SSP_LogonUser(PTSTR szUser, PTSTR szPassword, PTSTR szDomain) |
6e785d85 | 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; | |
26ac0430 | 391 | |
6e785d85 | 392 | SEC_WINNT_AUTH_IDENTITY ai; |
393 | ||
394 | do { | |
26ac0430 AJ |
395 | if (!hModule) |
396 | break; | |
6e785d85 | 397 | |
398 | /* Initialize auth identity structure */ | |
26ac0430 | 399 | ZeroMemory(&ai, sizeof(ai)); |
308f92d7 | 400 | ai.Domain = (unsigned char *)szDomain; |
26ac0430 | 401 | ai.DomainLength = lstrlen(szDomain); |
308f92d7 | 402 | ai.User = (unsigned char *)szUser; |
26ac0430 | 403 | ai.UserLength = lstrlen(szUser); |
308f92d7 | 404 | ai.Password = (unsigned char *)szPassword; |
26ac0430 | 405 | ai.PasswordLength = lstrlen(szPassword); |
6e785d85 | 406 | #if defined(UNICODE) || defined(_UNICODE) |
26ac0430 AJ |
407 | ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; |
408 | #else | |
409 | ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; | |
6e785d85 | 410 | #endif |
411 | ||
26ac0430 AJ |
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; | |
6e785d85 | 435 | |
26ac0430 AJ |
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); | |
6e785d85 | 444 | |
445 | /* Clean up resources */ | |
446 | if (asClient.fHaveCtxtHandle) | |
26ac0430 | 447 | _DeleteSecurityContext(&asClient.hctxt); |
6e785d85 | 448 | if (asClient.fHaveCredHandle) |
26ac0430 | 449 | _FreeCredentialsHandle(&asClient.hcred); |
6e785d85 | 450 | if (asServer.fHaveCtxtHandle) |
26ac0430 | 451 | _DeleteSecurityContext(&asServer.hctxt); |
6e785d85 | 452 | if (asServer.fHaveCredHandle) |
26ac0430 | 453 | _FreeCredentialsHandle(&asServer.hcred); |
6e785d85 | 454 | |
455 | return fResult; | |
456 | } | |
457 | ||
6e785d85 | 458 | const char * WINAPI SSP_MakeChallenge(PVOID PNegotiateBuf, int NegotiateLen) |
459 | { | |
460 | BOOL fDone = FALSE; | |
461 | PVOID fResult = NULL; | |
462 | DWORD cbOut = 0; | |
463 | DWORD cbIn = 0; | |
464 | ntlm_challenge * challenge; | |
6e785d85 | 465 | |
466 | if (NTLM_asServer.fHaveCtxtHandle) | |
26ac0430 | 467 | _DeleteSecurityContext(&NTLM_asServer.hctxt); |
6e785d85 | 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 { | |
26ac0430 AJ |
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); | |
6e785d85 | 488 | if (fResult != NULL) { |
489 | challenge = (ntlm_challenge *) fResult; | |
d6054896 AJ |
490 | Use_Unicode = NTLM_NEGOTIATE_UNICODE & challenge->flags; |
491 | NTLM_LocalCall = NTLM_NEGOTIATE_THIS_IS_LOCAL_CALL & challenge->flags; | |
2dc09715 AJ |
492 | struct base64_encode_ctx ctx; |
493 | base64_encode_init(&ctx); | |
494 | static uint8_t 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 reinterpret_cast<char *>(encoded); | |
6e785d85 | 501 | } |
2dc09715 | 502 | return NULL; |
6e785d85 | 503 | } |
504 | ||
6e785d85 | 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 { | |
26ac0430 AJ |
515 | if (!hModule) |
516 | break; | |
6e785d85 | 517 | |
518 | /* Prepare server message (authentication) */ | |
519 | cbIn = AutenticateLen; | |
26ac0430 AJ |
520 | cbOut = cbMaxToken; |
521 | if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut, | |
522 | &fDone, credentials)) | |
523 | break; | |
524 | fResult = TRUE; | |
525 | } while (0); | |
6e785d85 | 526 | |
527 | return fResult; | |
528 | } | |
529 | ||
6e785d85 | 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; | |
6e785d85 | 534 | |
535 | if (NTLM_asServer.fHaveCtxtHandle) | |
26ac0430 | 536 | _DeleteSecurityContext(&NTLM_asServer.hctxt); |
6e785d85 | 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 { | |
26ac0430 AJ |
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; | |
6e785d85 | 554 | } |
26ac0430 AJ |
555 | *Status = SSP_OK; |
556 | } while (0); | |
2dc09715 AJ |
557 | if (pServerBuf != NULL && cbOut > 0) { |
558 | struct base64_encode_ctx ctx; | |
559 | base64_encode_init(&ctx); | |
560 | static uint8_t 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 reinterpret_cast<char *>(encoded); | |
567 | } | |
568 | return NULL; | |
6e785d85 | 569 | } |
570 | ||
6e785d85 | 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; | |
6e785d85 | 575 | |
576 | memcpy(pClientBuf, PAutenticateBuf, AutenticateLen); | |
577 | ZeroMemory(pServerBuf, cbMaxToken); | |
578 | do { | |
26ac0430 AJ |
579 | if (!hModule) |
580 | break; | |
6e785d85 | 581 | |
582 | /* Prepare server message (authentication) */ | |
583 | cbIn = AutenticateLen; | |
26ac0430 AJ |
584 | cbOut = cbMaxToken; |
585 | if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut, | |
586 | fDone, credentials)) { | |
587 | *Status = SSP_ERROR; | |
588 | break; | |
6e785d85 | 589 | } |
26ac0430 AJ |
590 | *Status = SSP_OK; |
591 | } while (0); | |
2dc09715 AJ |
592 | if (pServerBuf != NULL && cbOut > 0) { |
593 | struct base64_encode_ctx ctx; | |
594 | base64_encode_init(&ctx); | |
595 | static uint8_t 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 reinterpret_cast<char *>(encoded); | |
602 | } | |
603 | return NULL; | |
6e785d85 | 604 | } |
f53969cc | 605 |