NTLM: header inclusion cleanup
[platform/upstream/curl.git] / lib / curl_ntlm_core.c
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  */
101 static 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  */
124 static 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  */
141 static 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  */
156 static 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
197 fail:
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   */
218 void 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  */
263 void 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
320 static 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  */
333 CURLcode 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 */