/src/wget/src/http-ntlm.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* NTLM code. |
2 | | Copyright (C) 2005-2011, 2015, 2018-2023 Free Software Foundation, |
3 | | Inc. |
4 | | Contributed by Daniel Stenberg. |
5 | | |
6 | | This file is part of GNU Wget. |
7 | | |
8 | | GNU Wget is free software; you can redistribute it and/or modify |
9 | | it under the terms of the GNU General Public License as published by |
10 | | the Free Software Foundation; either version 3 of the License, or |
11 | | (at your option) any later version. |
12 | | |
13 | | GNU Wget is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with Wget. If not, see <http://www.gnu.org/licenses/>. |
20 | | |
21 | | Additional permission under GNU GPL version 3 section 7 |
22 | | |
23 | | If you modify this program, or any covered work, by linking or |
24 | | combining it with the OpenSSL project's OpenSSL library (or a |
25 | | modified version of that library), containing parts covered by the |
26 | | terms of the OpenSSL or SSLeay licenses, the Free Software Foundation |
27 | | grants you additional permission to convey the resulting work. |
28 | | Corresponding Source for a non-source form of such a combination |
29 | | shall include the source code for the parts of OpenSSL used as well |
30 | | as that of the covered work. */ |
31 | | |
32 | | #include "wget.h" |
33 | | |
34 | | /* NTLM details: |
35 | | |
36 | | http://davenport.sourceforge.net/ntlm.html |
37 | | http://www.innovation.ch/java/ntlm.html |
38 | | |
39 | | */ |
40 | | |
41 | | #include <stdio.h> |
42 | | #include <string.h> |
43 | | #include <stdlib.h> |
44 | | |
45 | | #include "utils.h" |
46 | | #include "http-ntlm.h" |
47 | | |
48 | | #ifdef HAVE_NETTLE |
49 | | # include <nettle/md4.h> |
50 | | # include <nettle/des.h> |
51 | | #else |
52 | | # include <openssl/des.h> |
53 | | # include <openssl/md4.h> |
54 | | # include <openssl/opensslv.h> |
55 | | |
56 | | # if OPENSSL_VERSION_NUMBER < 0x00907001L |
57 | | # define DES_key_schedule des_key_schedule |
58 | | # define DES_cblock des_cblock |
59 | | # define DES_set_odd_parity des_set_odd_parity |
60 | | # define DES_set_key des_set_key |
61 | | # define DES_ecb_encrypt des_ecb_encrypt |
62 | | |
63 | | /* This is how things were done in the old days */ |
64 | | # define DESKEY(x) x |
65 | | # define DESKEYARG(x) x |
66 | | # else |
67 | | /* Modern version */ |
68 | | # define DESKEYARG(x) *x |
69 | | # define DESKEY(x) &x |
70 | | # endif |
71 | | |
72 | | #endif |
73 | | |
74 | | /* Define this to make the type-3 message include the NT response message */ |
75 | | #define USE_NTRESPONSES 1 |
76 | | |
77 | | |
78 | | /* Flag bits definitions available at on |
79 | | http://davenport.sourceforge.net/ntlm.html */ |
80 | | |
81 | | #define NTLMFLAG_NEGOTIATE_OEM (1<<1) |
82 | | #define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) |
83 | | |
84 | | /* |
85 | | (*) = A "security buffer" is a triplet consisting of two shorts and one |
86 | | long: |
87 | | |
88 | | 1. a 'short' containing the length of the buffer in bytes |
89 | | 2. a 'short' containing the allocated space for the buffer in bytes |
90 | | 3. a 'long' containing the offset to the start of the buffer from the |
91 | | beginning of the NTLM message, in bytes. |
92 | | */ |
93 | | |
94 | | /* return true on success, false otherwise */ |
95 | | bool |
96 | | ntlm_input (struct ntlmdata *ntlm, const char *header) |
97 | 0 | { |
98 | 0 | if (0 != strncmp (header, "NTLM", 4)) |
99 | 0 | return false; |
100 | | |
101 | 0 | header += 4; |
102 | 0 | while (*header && c_isspace(*header)) |
103 | 0 | header++; |
104 | |
|
105 | 0 | if (*header) |
106 | 0 | { |
107 | | /* We got a type-2 message here: |
108 | | |
109 | | Index Description Content |
110 | | 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" |
111 | | (0x4e544c4d53535000) |
112 | | 8 NTLM Message Type long (0x02000000) |
113 | | 12 Target Name security buffer(*) |
114 | | 20 Flags long |
115 | | 24 Challenge 8 bytes |
116 | | (32) Context (optional) 8 bytes (two consecutive longs) |
117 | | (40) Target Information (optional) security buffer(*) |
118 | | 32 (48) start of data block |
119 | | */ |
120 | 0 | ssize_t size; |
121 | 0 | char buffer[48]; // decode 48 bytes needs ((48 + 2) / 3) * 4 + 1 bytes |
122 | |
|
123 | 0 | DEBUGP (("Received a type-2 NTLM message.\n")); |
124 | |
|
125 | 0 | size = wget_base64_decode (header, buffer, sizeof (buffer)); |
126 | 0 | if (size < 0) |
127 | 0 | return false; /* malformed base64 from server */ |
128 | | |
129 | 0 | ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */ |
130 | |
|
131 | 0 | if ((size_t) size >= sizeof (buffer)) |
132 | | /* the nonce of interest is index [24 .. 31], 8 bytes */ |
133 | 0 | memcpy (ntlm->nonce, &buffer[24], 8); |
134 | | |
135 | | /* at index decimal 20, there's a 32bit NTLM flag field */ |
136 | 0 | } |
137 | 0 | else |
138 | 0 | { |
139 | 0 | if (ntlm->state == NTLMSTATE_LAST) |
140 | 0 | { |
141 | 0 | DEBUGP (("NTLM auth restarted.\n")); |
142 | | /* no return, continue */ |
143 | 0 | } |
144 | 0 | else if (ntlm->state == NTLMSTATE_TYPE3) |
145 | 0 | { |
146 | 0 | DEBUGP (("NTLM handshake rejected.\n")); |
147 | 0 | ntlm->state = NTLMSTATE_NONE; |
148 | 0 | return false; |
149 | 0 | } |
150 | 0 | else if (ntlm->state >= NTLMSTATE_TYPE1) |
151 | 0 | { |
152 | 0 | DEBUGP (("Unexpected empty NTLM message.\n")); |
153 | 0 | return false; /* this is an error */ |
154 | 0 | } |
155 | | |
156 | 0 | DEBUGP (("Empty NTLM message, (re)starting transaction.\n")); |
157 | 0 | ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */ |
158 | 0 | } |
159 | | |
160 | 0 | return true; |
161 | 0 | } |
162 | | |
163 | | /* |
164 | | * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The |
165 | | * key schedule ks is also set. |
166 | | */ |
167 | | #ifdef HAVE_NETTLE |
168 | | static void |
169 | | setup_des_key(unsigned char *key_56, |
170 | | struct des_ctx *des) |
171 | 0 | { |
172 | 0 | unsigned char key[8]; |
173 | |
|
174 | 0 | key[0] = key_56[0]; |
175 | 0 | key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); |
176 | 0 | key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); |
177 | 0 | key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); |
178 | 0 | key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); |
179 | 0 | key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); |
180 | 0 | key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); |
181 | 0 | key[7] = (key_56[6] << 1) & 0xFF; |
182 | |
|
183 | 0 | nettle_des_set_key(des, key); |
184 | 0 | } |
185 | | #else |
186 | | static void |
187 | | setup_des_key(unsigned char *key_56, |
188 | | DES_key_schedule DESKEYARG(ks)) |
189 | | { |
190 | | DES_cblock key; |
191 | | |
192 | | key[0] = key_56[0]; |
193 | | key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); |
194 | | key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); |
195 | | key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); |
196 | | key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); |
197 | | key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); |
198 | | key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); |
199 | | key[7] = (key_56[6] << 1) & 0xFF; |
200 | | |
201 | | DES_set_odd_parity(&key); |
202 | | DES_set_key(&key, ks); |
203 | | } |
204 | | #endif |
205 | | |
206 | | /* |
207 | | * takes a 21 byte array and treats it as 3 56-bit DES keys. The |
208 | | * 8 byte plaintext is encrypted with each key and the resulting 24 |
209 | | * bytes are stored in the results array. |
210 | | */ |
211 | | static void |
212 | | calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results) |
213 | 0 | { |
214 | 0 | #ifdef HAVE_NETTLE |
215 | 0 | struct des_ctx des; |
216 | |
|
217 | 0 | setup_des_key(keys, &des); |
218 | 0 | nettle_des_encrypt(&des, 8, results, plaintext); |
219 | |
|
220 | 0 | setup_des_key(keys + 7, &des); |
221 | 0 | nettle_des_encrypt(&des, 8, results + 8, plaintext); |
222 | |
|
223 | 0 | setup_des_key(keys + 14, &des); |
224 | 0 | nettle_des_encrypt(&des, 8, results + 16, plaintext); |
225 | | #else |
226 | | DES_key_schedule ks; |
227 | | |
228 | | setup_des_key(keys, DESKEY(ks)); |
229 | | DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, |
230 | | DESKEY(ks), DES_ENCRYPT); |
231 | | |
232 | | setup_des_key(keys+7, DESKEY(ks)); |
233 | | DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8), |
234 | | DESKEY(ks), DES_ENCRYPT); |
235 | | |
236 | | setup_des_key(keys+14, DESKEY(ks)); |
237 | | DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16), |
238 | | DESKEY(ks), DES_ENCRYPT); |
239 | | #endif |
240 | 0 | } |
241 | | |
242 | | /* |
243 | | * Set up lanmanager and nt hashed passwords |
244 | | */ |
245 | | static void |
246 | | mkhash(const char *password, |
247 | | unsigned char *nonce, /* 8 bytes */ |
248 | | unsigned char *lmresp /* must fit 0x18 bytes */ |
249 | | #ifdef USE_NTRESPONSES |
250 | | , unsigned char *ntresp /* must fit 0x18 bytes */ |
251 | | #endif |
252 | | ) |
253 | 0 | { |
254 | 0 | unsigned char lmbuffer[21]; |
255 | 0 | #ifdef USE_NTRESPONSES |
256 | 0 | unsigned char ntbuffer[21]; |
257 | 0 | #endif |
258 | 0 | unsigned char pw[14]; |
259 | 0 | static const unsigned char magic[] = { |
260 | 0 | 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 |
261 | 0 | }; |
262 | 0 | size_t i, len = strlen(password); |
263 | | |
264 | | /* make it fit at least 14 bytes */ |
265 | |
|
266 | 0 | if (len > sizeof (pw)) |
267 | 0 | len = sizeof (pw); |
268 | |
|
269 | 0 | for (i = 0; i < len; i++) |
270 | 0 | pw[i] = (unsigned char) c_toupper (password[i]); |
271 | |
|
272 | 0 | for (; i < sizeof (pw); i++) |
273 | 0 | pw[i] = 0; |
274 | |
|
275 | 0 | { |
276 | | /* create LanManager hashed password */ |
277 | 0 | #ifdef HAVE_NETTLE |
278 | 0 | struct des_ctx des; |
279 | |
|
280 | 0 | setup_des_key(pw, &des); |
281 | 0 | nettle_des_encrypt(&des, 8, lmbuffer, magic); |
282 | |
|
283 | 0 | setup_des_key(pw + 7, &des); |
284 | 0 | nettle_des_encrypt(&des, 8, lmbuffer + 8, magic); |
285 | | #else |
286 | | DES_key_schedule ks; |
287 | | |
288 | | setup_des_key(pw, DESKEY (ks)); |
289 | | DES_ecb_encrypt((DES_cblock *) magic, (DES_cblock *) lmbuffer, |
290 | | DESKEY (ks), DES_ENCRYPT); |
291 | | |
292 | | setup_des_key(pw+7, DESKEY (ks)); |
293 | | DES_ecb_encrypt((DES_cblock *) magic, (DES_cblock *) (lmbuffer + 8), |
294 | | DESKEY (ks), DES_ENCRYPT); |
295 | | #endif |
296 | |
|
297 | 0 | memset(lmbuffer + 16, 0, 5); |
298 | 0 | } |
299 | | /* create LM responses */ |
300 | 0 | calc_resp(lmbuffer, nonce, lmresp); |
301 | |
|
302 | 0 | #ifdef USE_NTRESPONSES |
303 | 0 | { |
304 | 0 | #ifdef HAVE_NETTLE |
305 | 0 | struct md4_ctx MD4; |
306 | | #else |
307 | | MD4_CTX MD4; |
308 | | #endif |
309 | |
|
310 | 0 | unsigned char pw4[64]; |
311 | |
|
312 | 0 | len = strlen (password); |
313 | |
|
314 | 0 | if (len > sizeof (pw4) / 2) |
315 | 0 | len = sizeof (pw4) / 2; |
316 | |
|
317 | 0 | for (i = 0; i < len; i++) { |
318 | 0 | pw4[2 * i] = (unsigned char) password[i]; |
319 | 0 | pw4[2 * i + 1] = 0; |
320 | 0 | } |
321 | |
|
322 | 0 | #ifdef HAVE_NETTLE |
323 | 0 | nettle_md4_init(&MD4); |
324 | 0 | nettle_md4_update(&MD4, (unsigned) (2 * len), pw4); |
325 | 0 | nettle_md4_digest(&MD4, MD4_DIGEST_SIZE, ntbuffer); |
326 | | #else |
327 | | /* create NT hashed password */ |
328 | | MD4_Init(&MD4); |
329 | | MD4_Update(&MD4, pw4, 2 * len); |
330 | | MD4_Final(ntbuffer, &MD4); |
331 | | #endif |
332 | |
|
333 | 0 | memset(ntbuffer + 16, 0, 5); |
334 | 0 | } |
335 | |
|
336 | 0 | calc_resp(ntbuffer, nonce, ntresp); |
337 | 0 | #endif |
338 | 0 | } |
339 | | |
340 | 0 | #define SHORTPAIR(x) (char) ((x) & 0xff), (char) ((x) >> 8) |
341 | 0 | #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \ |
342 | 0 | (((x) >>16)&0xff), ((x)>>24) |
343 | | |
344 | | /* this is for creating ntlm header output */ |
345 | | char * |
346 | | ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, |
347 | | bool *ready) |
348 | 0 | { |
349 | 0 | const char *domain = ""; /* empty */ |
350 | 0 | const char *host = ""; /* empty */ |
351 | 0 | size_t domlen = strlen(domain); |
352 | 0 | size_t hostlen = strlen(host); |
353 | 0 | size_t hostoff; /* host name offset */ |
354 | 0 | size_t domoff; /* domain name offset */ |
355 | 0 | size_t size; |
356 | 0 | char ntlmbuf[256]; /* enough, unless the host/domain is very long */ |
357 | | |
358 | | /* point to the address of the pointer that holds the string to sent to the |
359 | | server, which is for a plain host or for a HTTP proxy */ |
360 | 0 | char *output = NULL; |
361 | |
|
362 | 0 | *ready = false; |
363 | | |
364 | | /* not set means empty */ |
365 | 0 | if(!user) |
366 | 0 | user=""; |
367 | |
|
368 | 0 | if(!passwd) |
369 | 0 | passwd=""; |
370 | |
|
371 | 0 | switch(ntlm->state) { |
372 | 0 | case NTLMSTATE_TYPE1: |
373 | 0 | case NTLMSTATE_NONE: |
374 | 0 | case NTLMSTATE_LAST: |
375 | 0 | hostoff = 32; |
376 | 0 | domoff = hostoff + hostlen; |
377 | |
|
378 | 0 | DEBUGP (("Creating a type-1 NTLM message.\n")); |
379 | | |
380 | | /* Create and send a type-1 message: |
381 | | |
382 | | Index Description Content |
383 | | 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" |
384 | | (0x4e544c4d53535000) |
385 | | 8 NTLM Message Type long (0x01000000) |
386 | | 12 Flags long |
387 | | 16 Supplied Domain security buffer(*) |
388 | | 24 Supplied Workstation security buffer(*) |
389 | | 32 start of data block |
390 | | |
391 | | */ |
392 | |
|
393 | 0 | snprintf (ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c" |
394 | 0 | "\x01%c%c%c" /* 32-bit type = 1 */ |
395 | 0 | "%c%c%c%c" /* 32-bit NTLM flag field */ |
396 | 0 | "%c%c" /* domain length */ |
397 | 0 | "%c%c" /* domain allocated space */ |
398 | 0 | "%c%c" /* domain name offset */ |
399 | 0 | "%c%c" /* 2 zeroes */ |
400 | 0 | "%c%c" /* host length */ |
401 | 0 | "%c%c" /* host allocated space */ |
402 | 0 | "%c%c" /* host name offset */ |
403 | 0 | "%c%c" /* 2 zeroes */ |
404 | 0 | "%s" /* host name */ |
405 | 0 | "%s", /* domain string */ |
406 | 0 | 0, /* trailing zero */ |
407 | 0 | 0,0,0, /* part of type-1 long */ |
408 | |
|
409 | 0 | LONGQUARTET( |
410 | 0 | NTLMFLAG_NEGOTIATE_OEM| /* 2 */ |
411 | 0 | NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */ |
412 | | /* equals 0x0202 */ |
413 | 0 | ), |
414 | 0 | SHORTPAIR(domlen), |
415 | 0 | SHORTPAIR(domlen), |
416 | 0 | SHORTPAIR(domoff), |
417 | 0 | 0,0, |
418 | 0 | SHORTPAIR(hostlen), |
419 | 0 | SHORTPAIR(hostlen), |
420 | 0 | SHORTPAIR(hostoff), |
421 | 0 | 0,0, |
422 | 0 | host, domain); |
423 | | |
424 | | /* initial packet length */ |
425 | 0 | size = 32 + hostlen + domlen; |
426 | |
|
427 | 0 | output = xmalloc(5 + BASE64_LENGTH (size) + 1); |
428 | 0 | memcpy(output, "NTLM ", 5); |
429 | 0 | wget_base64_encode (ntlmbuf, size, output + 5); |
430 | |
|
431 | 0 | break; |
432 | | |
433 | 0 | case NTLMSTATE_TYPE2: |
434 | | /* We received the type-2 already, create a type-3 message: |
435 | | |
436 | | Index Description Content |
437 | | 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" |
438 | | (0x4e544c4d53535000) |
439 | | 8 NTLM Message Type long (0x03000000) |
440 | | 12 LM/LMv2 Response security buffer(*) |
441 | | 20 NTLM/NTLMv2 Response security buffer(*) |
442 | | 28 Domain Name security buffer(*) |
443 | | 36 User Name security buffer(*) |
444 | | 44 Workstation Name security buffer(*) |
445 | | (52) Session Key (optional) security buffer(*) |
446 | | (60) Flags (optional) long |
447 | | 52 (64) start of data block |
448 | | |
449 | | */ |
450 | |
|
451 | 0 | { |
452 | 0 | size_t lmrespoff; |
453 | 0 | size_t ntrespoff; |
454 | 0 | size_t useroff; |
455 | 0 | unsigned char lmresp[0x18]; /* fixed-size */ |
456 | 0 | #ifdef USE_NTRESPONSES |
457 | 0 | unsigned char ntresp[0x18]; /* fixed-size */ |
458 | 0 | #endif |
459 | 0 | const char *usr; |
460 | 0 | size_t userlen; |
461 | |
|
462 | 0 | DEBUGP (("Creating a type-3 NTLM message.\n")); |
463 | |
|
464 | 0 | usr = strchr(user, '\\'); |
465 | 0 | if(!usr) |
466 | 0 | usr = strchr(user, '/'); |
467 | |
|
468 | 0 | if (usr) { |
469 | 0 | domain = user; |
470 | 0 | domlen = (size_t) (usr - domain); |
471 | 0 | usr++; |
472 | 0 | } |
473 | 0 | else |
474 | 0 | usr = user; |
475 | 0 | userlen = strlen(usr); |
476 | |
|
477 | 0 | mkhash(passwd, &ntlm->nonce[0], lmresp |
478 | 0 | #ifdef USE_NTRESPONSES |
479 | 0 | , ntresp |
480 | 0 | #endif |
481 | 0 | ); |
482 | |
|
483 | 0 | domoff = 64; /* always */ |
484 | 0 | useroff = domoff + domlen; |
485 | 0 | hostoff = useroff + userlen; |
486 | 0 | lmrespoff = hostoff + hostlen; |
487 | 0 | ntrespoff = lmrespoff + 0x18; |
488 | | |
489 | | /* Create the big type-3 message binary blob */ |
490 | |
|
491 | 0 | snprintf (ntlmbuf, sizeof (ntlmbuf), |
492 | 0 | "NTLMSSP%c" |
493 | 0 | "\x03%c%c%c" /* type-3, 32 bits */ |
494 | |
|
495 | 0 | "%c%c%c%c" /* LanManager length + allocated space */ |
496 | 0 | "%c%c" /* LanManager offset */ |
497 | 0 | "%c%c" /* 2 zeroes */ |
498 | |
|
499 | 0 | "%c%c" /* NT-response length */ |
500 | 0 | "%c%c" /* NT-response allocated space */ |
501 | 0 | "%c%c" /* NT-response offset */ |
502 | 0 | "%c%c" /* 2 zeroes */ |
503 | |
|
504 | 0 | "%c%c" /* domain length */ |
505 | 0 | "%c%c" /* domain allocated space */ |
506 | 0 | "%c%c" /* domain name offset */ |
507 | 0 | "%c%c" /* 2 zeroes */ |
508 | |
|
509 | 0 | "%c%c" /* user length */ |
510 | 0 | "%c%c" /* user allocated space */ |
511 | 0 | "%c%c" /* user offset */ |
512 | 0 | "%c%c" /* 2 zeroes */ |
513 | |
|
514 | 0 | "%c%c" /* host length */ |
515 | 0 | "%c%c" /* host allocated space */ |
516 | 0 | "%c%c" /* host offset */ |
517 | 0 | "%c%c%c%c%c%c" /* 6 zeroes */ |
518 | |
|
519 | 0 | "\xff\xff" /* message length */ |
520 | 0 | "%c%c" /* 2 zeroes */ |
521 | |
|
522 | 0 | "\x01\x82" /* flags */ |
523 | 0 | "%c%c" /* 2 zeroes */ |
524 | | |
525 | | /* domain string */ |
526 | | /* user string */ |
527 | | /* host string */ |
528 | | /* LanManager response */ |
529 | | /* NT response */ |
530 | 0 | , |
531 | 0 | 0, /* zero termination */ |
532 | 0 | 0, 0, 0, /* type-3 long, the 24 upper bits */ |
533 | |
|
534 | 0 | SHORTPAIR (0x18), /* LanManager response length, twice */ |
535 | 0 | SHORTPAIR (0x18), |
536 | 0 | SHORTPAIR (lmrespoff), |
537 | 0 | 0x0, 0x0, |
538 | |
|
539 | 0 | #ifdef USE_NTRESPONSES |
540 | 0 | SHORTPAIR (0x18), /* NT-response length, twice */ |
541 | 0 | SHORTPAIR (0x18), |
542 | | #else |
543 | | 0x0, 0x0, |
544 | | 0x0, 0x0, |
545 | | #endif |
546 | 0 | SHORTPAIR (ntrespoff), |
547 | 0 | 0x0, 0x0, |
548 | |
|
549 | 0 | SHORTPAIR (domlen), |
550 | 0 | SHORTPAIR (domlen), |
551 | 0 | SHORTPAIR (domoff), |
552 | 0 | 0x0, 0x0, |
553 | |
|
554 | 0 | SHORTPAIR (userlen), |
555 | 0 | SHORTPAIR (userlen), |
556 | 0 | SHORTPAIR (useroff), |
557 | 0 | 0x0, 0x0, |
558 | |
|
559 | 0 | SHORTPAIR (hostlen), |
560 | 0 | SHORTPAIR (hostlen), |
561 | 0 | SHORTPAIR (hostoff), |
562 | 0 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
563 | |
|
564 | 0 | 0x0, 0x0, |
565 | |
|
566 | 0 | 0x0, 0x0); |
567 | | |
568 | | /* size is now 64 */ |
569 | 0 | size=64; |
570 | 0 | ntlmbuf[62]=ntlmbuf[63]=0; |
571 | | |
572 | | /* Make sure that the user and domain strings fit in the target buffer |
573 | | before we copy them there. */ |
574 | 0 | if((size + userlen + domlen) >= sizeof(ntlmbuf)) |
575 | 0 | return NULL; |
576 | | |
577 | 0 | memcpy(&ntlmbuf[size], domain, domlen); |
578 | 0 | size += domlen; |
579 | |
|
580 | 0 | memcpy(&ntlmbuf[size], usr, userlen); |
581 | 0 | size += userlen; |
582 | | |
583 | | /* we append the binary hashes to the end of the blob */ |
584 | 0 | if(size < (sizeof(ntlmbuf) - 0x18)) { |
585 | 0 | memcpy(&ntlmbuf[size], lmresp, 0x18); |
586 | 0 | size += 0x18; |
587 | 0 | } |
588 | |
|
589 | 0 | #ifdef USE_NTRESPONSES |
590 | 0 | if(size < (sizeof(ntlmbuf) - 0x18)) { |
591 | 0 | memcpy(&ntlmbuf[size], ntresp, 0x18); |
592 | 0 | size += 0x18; |
593 | 0 | } |
594 | 0 | #endif |
595 | |
|
596 | 0 | ntlmbuf[56] = (char) (size & 0xff); |
597 | 0 | ntlmbuf[57] = (char) (size >> 8); |
598 | | |
599 | | /* convert the binary blob into base64 */ |
600 | 0 | output = xmalloc(5 + BASE64_LENGTH (size) + 1); |
601 | 0 | memcpy(output, "NTLM ", 5); |
602 | 0 | wget_base64_encode (ntlmbuf, size, output + 5); |
603 | |
|
604 | 0 | ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ |
605 | 0 | *ready = true; |
606 | 0 | } |
607 | 0 | break; |
608 | | |
609 | 0 | case NTLMSTATE_TYPE3: |
610 | | /* connection is already authenticated, |
611 | | * don't send a header in future requests */ |
612 | 0 | *ready = true; |
613 | 0 | output = NULL; |
614 | 0 | break; |
615 | 0 | } |
616 | | |
617 | 0 | return output; |
618 | 0 | } |