X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fhttp-ntlm.c;h=591bfb514b9a1619b62a95da31ffac3a0a4ca46e;hp=ce7dd9848d9bf6e25333edbc5527e98e2709812b;hb=320cfdcb658e8d6556ae9dfd902c2db1db866a6b;hpb=52ad80309f8c9a5c1498f6ff6b3e11d8997290d7 diff --git a/src/http-ntlm.c b/src/http-ntlm.c index ce7dd984..591bfb51 100644 --- a/src/http-ntlm.c +++ b/src/http-ntlm.c @@ -1,12 +1,13 @@ /* NTLM code. - Copyright (C) 2005 Free Software Foundation, Inc. - Donated by Daniel Stenberg. + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software + Foundation, Inc. + Contributed by Daniel Stenberg. This file is part of GNU Wget. GNU Wget is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Wget is distributed in the hope that it will be useful, @@ -15,63 +16,63 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Wget; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +along with Wget. If not, see . -In addition, as a special exception, the Free Software Foundation -gives permission to link the code of its release of Wget with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. */ +Additional permission under GNU GPL version 3 section 7 -#include +If you modify this program, or any covered work, by linking or +combining it with the OpenSSL project's OpenSSL library (or a +modified version of that library), containing parts covered by the +terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +grants you additional permission to convey the resulting work. +Corresponding Source for a non-source form of such a combination +shall include the source code for the parts of OpenSSL used as well +as that of the covered work. */ + +#include "wget.h" /* NTLM details: - + http://davenport.sourceforge.net/ntlm.html http://www.innovation.ch/java/ntlm.html */ -/* -- WIN32 approved -- */ #include -#ifdef HAVE_STRING_H -# include -#else -# include -#endif +#include #include -#include -#include -#include - -#include "wget.h" #include "utils.h" #include "http-ntlm.h" -#if OPENSSL_VERSION_NUMBER < 0x00907001L -#define DES_key_schedule des_key_schedule -#define DES_cblock des_cblock -#define DES_set_odd_parity des_set_odd_parity -#define DES_set_key des_set_key -#define DES_ecb_encrypt des_ecb_encrypt +#ifdef HAVE_NETTLE +# include +# include +#else +# include +# include +# include + +# if OPENSSL_VERSION_NUMBER < 0x00907001L +# define DES_key_schedule des_key_schedule +# define DES_cblock des_cblock +# define DES_set_odd_parity des_set_odd_parity +# define DES_set_key des_set_key +# define DES_ecb_encrypt des_ecb_encrypt /* This is how things were done in the old days */ -#define DESKEY(x) x -#define DESKEYARG(x) x -#else +# define DESKEY(x) x +# define DESKEYARG(x) x +# else /* Modern version */ -#define DESKEYARG(x) *x -#define DESKEY(x) &x +# define DESKEYARG(x) *x +# define DESKEY(x) &x +# endif + #endif /* Define this to make the type-3 message include the NT response message */ -#undef USE_NTRESPONSES +#define USE_NTRESPONSES 1 /* Flag bits definitions available at on http://davenport.sourceforge.net/ntlm.html */ @@ -119,14 +120,15 @@ so, delete this exception statement from your version. */ beginning of the NTLM message, in bytes. */ -/* return 1 on success, 0 otherwise */ -int ntlm_input (struct ntlmdata *ntlm, const char *header) +/* return true on success, false otherwise */ +bool +ntlm_input (struct ntlmdata *ntlm, const char *header) { if (0 != strncmp (header, "NTLM", 4)) - return 0; + return false; header += 4; - while (*header && ISSPACE(*header)) + while (*header && c_isspace(*header)) header++; if (*header) @@ -145,11 +147,13 @@ int ntlm_input (struct ntlmdata *ntlm, const char *header) 32 (48) start of data block */ int size; - unsigned char *buffer = (unsigned char *) alloca (strlen (header)); + char *buffer = (char *) alloca (strlen (header)); + + DEBUGP (("Received a type-2 NTLM message.\n")); size = base64_decode (header, buffer); if (size < 0) - return 0; /* malformed base64 from server */ + return false; /* malformed base64 from server */ ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */ @@ -162,20 +166,44 @@ int ntlm_input (struct ntlmdata *ntlm, const char *header) else { if (ntlm->state >= NTLMSTATE_TYPE1) - return 0; /* this is an error */ + { + DEBUGP (("Unexpected empty NTLM message.\n")); + return false; /* this is an error */ + } + DEBUGP (("Empty NTLM message, starting transaction.\n")); ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */ } - return 1; + return true; } /* * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The * key schedule ks is also set. */ -static void setup_des_key(unsigned char *key_56, - DES_key_schedule DESKEYARG(ks)) +#ifdef HAVE_NETTLE +static void +setup_des_key(unsigned char *key_56, + struct des_ctx *des) +{ + unsigned char key[8]; + + key[0] = key_56[0]; + key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); + key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); + key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); + key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); + key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); + key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); + key[7] = (key_56[6] << 1) & 0xFF; + + nettle_des_set_key(des, key); +} +#else +static void +setup_des_key(unsigned char *key_56, + DES_key_schedule DESKEYARG(ks)) { DES_cblock key; @@ -191,16 +219,28 @@ static void setup_des_key(unsigned char *key_56, DES_set_odd_parity(&key); DES_set_key(&key, ks); } +#endif /* * takes a 21 byte array and treats it as 3 56-bit DES keys. The * 8 byte plaintext is encrypted with each key and the resulting 24 * bytes are stored in the results array. */ -static void calc_resp(unsigned char *keys, - unsigned char *plaintext, - unsigned char *results) +static void +calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results) { +#ifdef HAVE_NETTLE + struct des_ctx des; + + setup_des_key(keys, &des); + nettle_des_encrypt(&des, 8, results, plaintext); + + setup_des_key(keys + 7, &des); + nettle_des_encrypt(&des, 8, results + 8, plaintext); + + setup_des_key(keys + 14, &des); + nettle_des_encrypt(&des, 8, results + 16, plaintext); +#else DES_key_schedule ks; setup_des_key(keys, DESKEY(ks)); @@ -214,16 +254,18 @@ static void calc_resp(unsigned char *keys, setup_des_key(keys+14, DESKEY(ks)); DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16), DESKEY(ks), DES_ENCRYPT); +#endif } /* * Set up lanmanager and nt hashed passwords */ -static void mkhash(const char *password, - unsigned char *nonce, /* 8 bytes */ - unsigned char *lmresp /* must fit 0x18 bytes */ +static void +mkhash(const char *password, + unsigned char *nonce, /* 8 bytes */ + unsigned char *lmresp /* must fit 0x18 bytes */ #ifdef USE_NTRESPONSES - , unsigned char *ntresp /* must fit 0x18 bytes */ + , unsigned char *ntresp /* must fit 0x18 bytes */ #endif ) { @@ -243,24 +285,34 @@ static void mkhash(const char *password, if (len > 14) len = 14; - + for (i=0; i>16)&0xff), ((x)>>24) /* this is for creating ntlm header output */ -char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, - int *ready) +char * +ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, + bool *ready) { const char *domain=""; /* empty */ const char *host=""; /* empty */ @@ -306,13 +369,13 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, int domoff; /* domain name offset */ int size; char *base64; - unsigned char ntlmbuf[256]; /* enough, unless the host/domain is very long */ + char ntlmbuf[256]; /* enough, unless the host/domain is very long */ /* point to the address of the pointer that holds the string to sent to the server, which is for a plain host or for a HTTP proxy */ char *output; - *ready = 0; + *ready = false; /* not set means empty */ if(!user) @@ -320,13 +383,15 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, if(!passwd) passwd=""; - + switch(ntlm->state) { case NTLMSTATE_TYPE1: default: /* for the weird cases we (re)start here */ hostoff = 32; domoff = hostoff + hostlen; - + + DEBUGP (("Creating a type-1 NTLM message.\n")); + /* Create and send a type-1 message: Index Description Content @@ -340,46 +405,46 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, */ - snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c" - "\x01%c%c%c" /* 32-bit type = 1 */ - "%c%c%c%c" /* 32-bit NTLM flag field */ - "%c%c" /* domain length */ - "%c%c" /* domain allocated space */ - "%c%c" /* domain name offset */ - "%c%c" /* 2 zeroes */ - "%c%c" /* host length */ - "%c%c" /* host allocated space */ - "%c%c" /* host name offset */ - "%c%c" /* 2 zeroes */ - "%s" /* host name */ - "%s", /* domain string */ - 0, /* trailing zero */ - 0,0,0, /* part of type-1 long */ - - LONGQUARTET( - NTLMFLAG_NEGOTIATE_OEM| /* 2 */ - NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */ - /* equals 0x0202 */ - ), - SHORTPAIR(domlen), - SHORTPAIR(domlen), - SHORTPAIR(domoff), - 0,0, - SHORTPAIR(hostlen), - SHORTPAIR(hostlen), - SHORTPAIR(hostoff), - 0,0, - host, domain); + snprintf (ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c" + "\x01%c%c%c" /* 32-bit type = 1 */ + "%c%c%c%c" /* 32-bit NTLM flag field */ + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host name offset */ + "%c%c" /* 2 zeroes */ + "%s" /* host name */ + "%s", /* domain string */ + 0, /* trailing zero */ + 0,0,0, /* part of type-1 long */ + + LONGQUARTET( + NTLMFLAG_NEGOTIATE_OEM| /* 2 */ + NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */ + /* equals 0x0202 */ + ), + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0,0, + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0,0, + host, domain); /* initial packet length */ size = 32 + hostlen + domlen; base64 = (char *) alloca (BASE64_LENGTH (size) + 1); - base64_encode (ntlmbuf, base64, size); + base64_encode (ntlmbuf, size, base64); output = concat_strings ("NTLM ", base64, (char *) 0); break; - + case NTLMSTATE_TYPE2: /* We received the type-2 already, create a type-3 message: @@ -397,7 +462,7 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, 52 (64) start of data block */ - + { int lmrespoff; int ntrespoff; @@ -409,12 +474,14 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, const char *usr; int userlen; + DEBUGP (("Creating a type-3 NTLM message.\n")); + usr = strchr(user, '\\'); if(!usr) usr = strchr(user, '/'); if (usr) { - domain = usr; + domain = user; domlen = usr - domain; usr++; } @@ -435,87 +502,93 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, ntrespoff = lmrespoff + 0x18; /* Create the big type-3 message binary blob */ - size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf), - "NTLMSSP%c" - "\x03%c%c%c" /* type-3, 32 bits */ - - "%c%c%c%c" /* LanManager length + allocated space */ - "%c%c" /* LanManager offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* NT-response length */ - "%c%c" /* NT-response allocated space */ - "%c%c" /* NT-response offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* domain length */ - "%c%c" /* domain allocated space */ - "%c%c" /* domain name offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* user length */ - "%c%c" /* user allocated space */ - "%c%c" /* user offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* host length */ - "%c%c" /* host allocated space */ - "%c%c" /* host offset */ - "%c%c%c%c%c%c" /* 6 zeroes */ - - "\xff\xff" /* message length */ - "%c%c" /* 2 zeroes */ - - "\x01\x82" /* flags */ - "%c%c" /* 2 zeroes */ - - /* domain string */ - /* user string */ - /* host string */ - /* LanManager response */ - /* NT response */ - , - 0, /* zero termination */ - 0,0,0, /* type-3 long, the 24 upper bits */ - - SHORTPAIR(0x18), /* LanManager response length, twice */ - SHORTPAIR(0x18), - SHORTPAIR(lmrespoff), - 0x0, 0x0, - + + size = snprintf (ntlmbuf, sizeof(ntlmbuf), + "NTLMSSP%c" + "\x03%c%c%c" /* type-3, 32 bits */ + + "%c%c%c%c" /* LanManager length + allocated space */ + "%c%c" /* LanManager offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* NT-response length */ + "%c%c" /* NT-response allocated space */ + "%c%c" /* NT-response offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* user length */ + "%c%c" /* user allocated space */ + "%c%c" /* user offset */ + "%c%c" /* 2 zeroes */ + + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host offset */ + "%c%c%c%c%c%c" /* 6 zeroes */ + + "\xff\xff" /* message length */ + "%c%c" /* 2 zeroes */ + + "\x01\x82" /* flags */ + "%c%c" /* 2 zeroes */ + + /* domain string */ + /* user string */ + /* host string */ + /* LanManager response */ + /* NT response */ + , + 0, /* zero termination */ + 0,0,0, /* type-3 long, the 24 upper bits */ + + SHORTPAIR(0x18), /* LanManager response length, twice */ + SHORTPAIR(0x18), + SHORTPAIR(lmrespoff), + 0x0, 0x0, + #ifdef USE_NTRESPONSES - SHORTPAIR(0x18), /* NT-response length, twice */ - SHORTPAIR(0x18), + SHORTPAIR(0x18), /* NT-response length, twice */ + SHORTPAIR(0x18), #else - 0x0, 0x0, - 0x0, 0x0, + 0x0, 0x0, + 0x0, 0x0, #endif - SHORTPAIR(ntrespoff), - 0x0, 0x0, - - SHORTPAIR(domlen), - SHORTPAIR(domlen), - SHORTPAIR(domoff), - 0x0, 0x0, - - SHORTPAIR(userlen), - SHORTPAIR(userlen), - SHORTPAIR(useroff), - 0x0, 0x0, - - SHORTPAIR(hostlen), - SHORTPAIR(hostlen), - SHORTPAIR(hostoff), - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - 0x0, 0x0, - - 0x0, 0x0); + SHORTPAIR(ntrespoff), + 0x0, 0x0, + + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0x0, 0x0, + + SHORTPAIR(userlen), + SHORTPAIR(userlen), + SHORTPAIR(useroff), + 0x0, 0x0, + + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + + 0x0, 0x0, + + 0x0, 0x0); /* size is now 64 */ size=64; ntlmbuf[62]=ntlmbuf[63]=0; + /* Make sure that the user and domain strings fit in the target buffer + before we copy them there. */ + if(((size_t) size + userlen + domlen) >= sizeof(ntlmbuf)) + return NULL; + memcpy(&ntlmbuf[size], domain, domlen); size += domlen; @@ -529,7 +602,7 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, } #ifdef USE_NTRESPONSES - if(size < ((int)sizeof(ntlmbuf) - 0x18)) { + if(size < ((int)sizeof(ntlmbuf) - 0x18)) { memcpy(&ntlmbuf[size], ntresp, 0x18); size += 0x18; } @@ -540,19 +613,19 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, /* convert the binary blob into base64 */ base64 = (char *) alloca (BASE64_LENGTH (size) + 1); - base64_encode (ntlmbuf, base64, size); + base64_encode (ntlmbuf, size, base64); output = concat_strings ("NTLM ", base64, (char *) 0); ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ - *ready = 1; + *ready = true; } break; case NTLMSTATE_TYPE3: /* connection is already authenticated, * don't send a header in future requests */ - *ready = 1; + *ready = true; output = NULL; break; }