1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23#include "setup.h" 24 25#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) 26 27/* 28 * NTLM details: 29 * 30 * http://davenport.sourceforge.net/ntlm.html 31 * http://www.innovation.ch/java/ntlm.html 32 */ 33 34#ifdef USE_SSLEAY 35 36# ifdef USE_OPENSSL 37# include <openssl/des.h> 38# ifndef OPENSSL_NO_MD4 39# include <openssl/md4.h> 40# endif 41# include <openssl/md5.h> 42# include <openssl/ssl.h> 43# include <openssl/rand.h> 44# else 45# include <des.h> 46# ifndef OPENSSL_NO_MD4 47# include <md4.h> 48# endif 49# include <md5.h> 50# include <ssl.h> 51# include <rand.h> 52# endif 53# if (OPENSSL_VERSION_NUMBER < 0x00907001L) 54# define DES_key_schedule des_key_schedule 55# define DES_cblock des_cblock 56# define DES_set_odd_parity des_set_odd_parity 57# define DES_set_key des_set_key 58# define DES_ecb_encrypt des_ecb_encrypt 59# define DESKEY(x) x 60# define DESKEYARG(x) x 61# else 62# define DESKEYARG(x) *x 63# define DESKEY(x) &x 64# endif 65 66#elif defined(USE_GNUTLS) 67 68# include <gcrypt.h> 69# define MD5_DIGEST_LENGTH 16 70# define MD4_DIGEST_LENGTH 16 71 72#elif defined(USE_NSS) 73 74# include <nss.h> 75# include <pk11pub.h> 76# include <hasht.h> 77# include "curl_md4.h" 78# define MD5_DIGEST_LENGTH MD5_LENGTH 79 80#else 81# error "Can't compile NTLM support without a crypto library." 82#endif 83 84#include "urldata.h" 85#include "non-ascii.h" 86#include "rawstr.h" 87#include "curl_memory.h" 88#include "curl_ntlm_core.h" 89 90#define _MPRINTF_REPLACE /* use our functions only */ 91#include <curl/mprintf.h> 92 93/* The last #include file should be: */ 94#include "memdebug.h" 95 96#ifdef USE_SSLEAY 97/* 98 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The 99 * key schedule ks is also set. 100 */ 101static void setup_des_key(const unsigned char *key_56, 102 DES_key_schedule DESKEYARG(ks)) 103{ 104 DES_cblock key; 105 106 key[0] = key_56[0]; 107 key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); 108 key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); 109 key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); 110 key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); 111 key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); 112 key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); 113 key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); 114 115 DES_set_odd_parity(&key); 116 DES_set_key(&key, ks); 117} 118 119#else /* defined(USE_SSLEAY) */ 120 121/* 122 * Turns a 56 bit key into the 64 bit, odd parity key. Used by GnuTLS and NSS. 123 */ 124static void extend_key_56_to_64(const unsigned char *key_56, char *key) 125{ 126 key[0] = key_56[0]; 127 key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); 128 key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); 129 key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); 130 key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); 131 key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); 132 key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); 133 key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); 134} 135 136#if defined(USE_GNUTLS) 137 138/* 139 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. 140 */ 141static void setup_des_key(const unsigned char *key_56, 142 gcry_cipher_hd_t *des) 143{ 144 char key[8]; 145 extend_key_56_to_64(key_56, key); 146 gcry_cipher_setkey(*des, key, 8); 147} 148 149#elif defined(USE_NSS) 150 151/* 152 * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using 153 * the expanded key. The caller is responsible for giving 64 bit of valid 154 * data is IN and (at least) 64 bit large buffer as OUT. 155 */ 156static bool encrypt_des(const unsigned char *in, unsigned char *out, 157 const unsigned char *key_56) 158{ 159 const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */ 160 PK11SlotInfo *slot = NULL; 161 char key[8]; /* expanded 64 bit key */ 162 SECItem key_item; 163 PK11SymKey *symkey = NULL; 164 SECItem *param = NULL; 165 PK11Context *ctx = NULL; 166 int out_len; /* not used, required by NSS */ 167 bool rv = FALSE; 168 169 /* use internal slot for DES encryption (requires NSS to be initialized) */ 170 slot = PK11_GetInternalKeySlot(); 171 if(!slot) 172 return FALSE; 173 174 /* expand the 56 bit key to 64 bit and wrap by NSS */ 175 extend_key_56_to_64(key_56, key); 176 key_item.data = (unsigned char *)key; 177 key_item.len = /* hard-wired */ 8; 178 symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT, 179 &key_item, NULL); 180 if(!symkey) 181 goto fail; 182 183 /* create DES encryption context */ 184 param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL); 185 if(!param) 186 goto fail; 187 ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param); 188 if(!ctx) 189 goto fail; 190 191 /* perform the encryption */ 192 if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8, 193 (unsigned char *)in, /* inbuflen */ 8) 194 && SECSuccess == PK11_Finalize(ctx)) 195 rv = /* all OK */ TRUE; 196 197fail: 198 /* cleanup */ 199 if(ctx) 200 PK11_DestroyContext(ctx, PR_TRUE); 201 if(symkey) 202 PK11_FreeSymKey(symkey); 203 if(param) 204 SECITEM_FreeItem(param, PR_TRUE); 205 PK11_FreeSlot(slot); 206 return rv; 207} 208 209#endif /* defined(USE_NSS) */ 210 211#endif /* defined(USE_SSLEAY) */ 212 213 /* 214 * takes a 21 byte array and treats it as 3 56-bit DES keys. The 215 * 8 byte plaintext is encrypted with each key and the resulting 24 216 * bytes are stored in the results array. 217 */ 218void Curl_ntlm_core_lm_resp(const unsigned char *keys, 219 const unsigned char *plaintext, 220 unsigned char *results) 221{ 222#ifdef USE_SSLEAY 223 DES_key_schedule ks; 224 225 setup_des_key(keys, DESKEY(ks)); 226 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, 227 DESKEY(ks), DES_ENCRYPT); 228 229 setup_des_key(keys + 7, DESKEY(ks)); 230 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8), 231 DESKEY(ks), DES_ENCRYPT); 232 233 setup_des_key(keys + 14, DESKEY(ks)); 234 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16), 235 DESKEY(ks), DES_ENCRYPT); 236#elif defined(USE_GNUTLS) 237 gcry_cipher_hd_t des; 238 239 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 240 setup_des_key(keys, &des); 241 gcry_cipher_encrypt(des, results, 8, plaintext, 8); 242 gcry_cipher_close(des); 243 244 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 245 setup_des_key(keys + 7, &des); 246 gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8); 247 gcry_cipher_close(des); 248 249 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 250 setup_des_key(keys + 14, &des); 251 gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); 252 gcry_cipher_close(des); 253#elif defined(USE_NSS) 254 encrypt_des(plaintext, results, keys); 255 encrypt_des(plaintext, results + 8, keys + 7); 256 encrypt_des(plaintext, results + 16, keys + 14); 257#endif 258} 259 260/* 261 * Set up lanmanager hashed password 262 */ 263void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data, 264 const char *password, 265 unsigned char *lmbuffer /* 21 bytes */) 266{ 267 CURLcode res; 268 unsigned char pw[14]; 269 static const unsigned char magic[] = { 270 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ 271 }; 272 size_t len = CURLMIN(strlen(password), 14); 273 274 Curl_strntoupper((char *)pw, password, len); 275 memset(&pw[len], 0, 14 - len); 276 277 /* 278 * The LanManager hashed password needs to be created using the 279 * password in the network encoding not the host encoding. 280 */ 281 res = Curl_convert_to_network(data, (char *)pw, 14); 282 if(res) 283 return; 284 285 { 286 /* Create LanManager hashed password. */ 287 288#ifdef USE_SSLEAY 289 DES_key_schedule ks; 290 291 setup_des_key(pw, DESKEY(ks)); 292 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, 293 DESKEY(ks), DES_ENCRYPT); 294 295 setup_des_key(pw + 7, DESKEY(ks)); 296 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8), 297 DESKEY(ks), DES_ENCRYPT); 298#elif defined(USE_GNUTLS) 299 gcry_cipher_hd_t des; 300 301 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 302 setup_des_key(pw, &des); 303 gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8); 304 gcry_cipher_close(des); 305 306 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 307 setup_des_key(pw + 7, &des); 308 gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); 309 gcry_cipher_close(des); 310#elif defined(USE_NSS) 311 encrypt_des(magic, lmbuffer, pw); 312 encrypt_des(magic, lmbuffer + 8, pw + 7); 313#endif 314 315 memset(lmbuffer + 16, 0, 21 - 16); 316 } 317} 318 319#if USE_NTRESPONSES 320static void ascii_to_unicode_le(unsigned char *dest, const char *src, 321 size_t srclen) 322{ 323 size_t i; 324 for(i = 0; i < srclen; i++) { 325 dest[2 * i] = (unsigned char)src[i]; 326 dest[2 * i + 1] = '\0'; 327 } 328} 329 330/* 331 * Set up nt hashed passwords 332 */ 333CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, 334 const char *password, 335 unsigned char *ntbuffer /* 21 bytes */) 336{ 337 size_t len = strlen(password); 338 unsigned char *pw = malloc(len * 2); 339 CURLcode result; 340 if(!pw) 341 return CURLE_OUT_OF_MEMORY; 342 343 ascii_to_unicode_le(pw, password, len); 344 345 /* 346 * The NT hashed password needs to be created using the password in the 347 * network encoding not the host encoding. 348 */ 349 result = Curl_convert_to_network(data, (char *)pw, len * 2); 350 if(result) 351 return result; 352 353 { 354 /* Create NT hashed password. */ 355#ifdef USE_SSLEAY 356 MD4_CTX MD4pw; 357 MD4_Init(&MD4pw); 358 MD4_Update(&MD4pw, pw, 2 * len); 359 MD4_Final(ntbuffer, &MD4pw); 360#elif defined(USE_GNUTLS) 361 gcry_md_hd_t MD4pw; 362 gcry_md_open(&MD4pw, GCRY_MD_MD4, 0); 363 gcry_md_write(MD4pw, pw, 2 * len); 364 memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH); 365 gcry_md_close(MD4pw); 366#elif defined(USE_NSS) 367 Curl_md4it(ntbuffer, pw, 2 * len); 368#endif 369 370 memset(ntbuffer + 16, 0, 21 - 16); 371 } 372 373 free(pw); 374 375 return CURLE_OK; 376} 377#endif /* USE_NTRESPONSES */ 378 379#endif /* USE_NTLM && !USE_WINDOWS_SSPI */ 380