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