http_ntlm.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2007, Daniel Stenberg, <[email protected]>, 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. * $Id$
  22. ***************************************************************************/
  23. #include "setup.h"
  24. /* NTLM details:
  25. http://davenport.sourceforge.net/ntlm.html
  26. http://www.innovation.ch/java/ntlm.html
  27. Another implementation:
  28. http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp
  29. */
  30. #ifndef CURL_DISABLE_HTTP
  31. #ifdef USE_NTLM
  32. #define DEBUG_ME 0
  33. /* -- WIN32 approved -- */
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <stdarg.h>
  37. #include <stdlib.h>
  38. #include <ctype.h>
  39. #ifdef HAVE_UNISTD_H
  40. #include <unistd.h>
  41. #endif
  42. #include "urldata.h"
  43. #include "easyif.h" /* for Curl_convert_... prototypes */
  44. #include "sendf.h"
  45. #include "strequal.h"
  46. #include "base64.h"
  47. #include "http_ntlm.h"
  48. #include "url.h"
  49. #include "memory.h"
  50. #include "ssluse.h"
  51. #define _MPRINTF_REPLACE /* use our functions only */
  52. #include <curl/mprintf.h>
  53. /* "NTLMSSP" signature is always in ASCII regardless of the platform */
  54. #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
  55. #ifndef USE_WINDOWS_SSPI
  56. #include <openssl/des.h>
  57. #include <openssl/md4.h>
  58. #include <openssl/md5.h>
  59. #include <openssl/ssl.h>
  60. #include <openssl/rand.h>
  61. #if OPENSSL_VERSION_NUMBER < 0x00907001L
  62. #define DES_key_schedule des_key_schedule
  63. #define DES_cblock des_cblock
  64. #define DES_set_odd_parity des_set_odd_parity
  65. #define DES_set_key des_set_key
  66. #define DES_ecb_encrypt des_ecb_encrypt
  67. /* This is how things were done in the old days */
  68. #define DESKEY(x) x
  69. #define DESKEYARG(x) x
  70. #else
  71. /* Modern version */
  72. #define DESKEYARG(x) *x
  73. #define DESKEY(x) &x
  74. #endif
  75. #else
  76. #include <rpc.h>
  77. /* Handle of security.dll or secur32.dll, depending on Windows version */
  78. static HMODULE s_hSecDll = NULL;
  79. /* Pointer to SSPI dispatch table */
  80. static PSecurityFunctionTable s_pSecFn = NULL;
  81. #endif
  82. /* The last #include file should be: */
  83. #include "memdebug.h"
  84. /* Define this to make the type-3 message include the NT response message */
  85. #define USE_NTRESPONSES 1
  86. /* Define this to make the type-3 message include the NTLM2Session response
  87. message, requires USE_NTRESPONSES. */
  88. #define USE_NTLM2SESSION 1
  89. #ifndef USE_WINDOWS_SSPI
  90. /* this function converts from the little endian format used in the incoming
  91. package to whatever endian format we're using natively */
  92. static unsigned int readint_le(unsigned char *buf) /* must point to a
  93. 4 bytes buffer*/
  94. {
  95. return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
  96. ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
  97. }
  98. #endif
  99. #if DEBUG_ME
  100. # define DEBUG_OUT(x) x
  101. static void print_flags(FILE *handle, unsigned long flags)
  102. {
  103. if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
  104. fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
  105. if(flags & NTLMFLAG_NEGOTIATE_OEM)
  106. fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
  107. if(flags & NTLMFLAG_REQUEST_TARGET)
  108. fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
  109. if(flags & (1<<3))
  110. fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
  111. if(flags & NTLMFLAG_NEGOTIATE_SIGN)
  112. fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
  113. if(flags & NTLMFLAG_NEGOTIATE_SEAL)
  114. fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
  115. if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
  116. fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
  117. if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
  118. fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
  119. if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
  120. fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
  121. if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
  122. fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
  123. if(flags & (1<<10))
  124. fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
  125. if(flags & (1<<11))
  126. fprintf(handle, "NTLMFLAG_UNKNOWN_11 ");
  127. if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
  128. fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
  129. if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
  130. fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
  131. if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
  132. fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
  133. if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
  134. fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
  135. if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
  136. fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
  137. if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
  138. fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
  139. if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
  140. fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
  141. if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
  142. fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
  143. if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
  144. fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
  145. if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
  146. fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
  147. if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
  148. fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
  149. if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
  150. fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
  151. if(flags & (1<<24))
  152. fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
  153. if(flags & (1<<25))
  154. fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
  155. if(flags & (1<<26))
  156. fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
  157. if(flags & (1<<27))
  158. fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
  159. if(flags & (1<<28))
  160. fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
  161. if(flags & NTLMFLAG_NEGOTIATE_128)
  162. fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
  163. if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
  164. fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
  165. if(flags & NTLMFLAG_NEGOTIATE_56)
  166. fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
  167. }
  168. static void print_hex(FILE *handle, const char *buf, size_t len)
  169. {
  170. const char *p = buf;
  171. fprintf(stderr, "0x");
  172. while (len-- > 0)
  173. fprintf(stderr, "%02.2x", (unsigned int)*p++);
  174. }
  175. #else
  176. # define DEBUG_OUT(x)
  177. #endif
  178. /*
  179. (*) = A "security buffer" is a triplet consisting of two shorts and one
  180. long:
  181. 1. a 'short' containing the length of the buffer in bytes
  182. 2. a 'short' containing the allocated space for the buffer in bytes
  183. 3. a 'long' containing the offset to the start of the buffer from the
  184. beginning of the NTLM message, in bytes.
  185. */
  186. CURLntlm Curl_input_ntlm(struct connectdata *conn,
  187. bool proxy, /* if proxy or not */
  188. char *header) /* rest of the www-authenticate:
  189. header */
  190. {
  191. /* point to the correct struct with this */
  192. struct ntlmdata *ntlm;
  193. #ifndef USE_WINDOWS_SSPI
  194. static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
  195. #endif
  196. ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
  197. /* skip initial whitespaces */
  198. while(*header && ISSPACE(*header))
  199. header++;
  200. if(checkprefix("NTLM", header)) {
  201. header += strlen("NTLM");
  202. while(*header && ISSPACE(*header))
  203. header++;
  204. if(*header) {
  205. /* We got a type-2 message here:
  206. Index Description Content
  207. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  208. (0x4e544c4d53535000)
  209. 8 NTLM Message Type long (0x02000000)
  210. 12 Target Name security buffer(*)
  211. 20 Flags long
  212. 24 Challenge 8 bytes
  213. (32) Context (optional) 8 bytes (two consecutive longs)
  214. (40) Target Information (optional) security buffer(*)
  215. 32 (48) start of data block
  216. */
  217. size_t size;
  218. unsigned char *buffer;
  219. size = Curl_base64_decode(header, &buffer);
  220. if(!buffer)
  221. return CURLNTLM_BAD;
  222. ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
  223. #ifdef USE_WINDOWS_SSPI
  224. ntlm->type_2 = malloc(size+1);
  225. if (ntlm->type_2 == NULL) {
  226. free(buffer);
  227. return CURLE_OUT_OF_MEMORY;
  228. }
  229. ntlm->n_type_2 = size;
  230. memcpy(ntlm->type_2, buffer, size);
  231. #else
  232. ntlm->flags = 0;
  233. if((size < 32) ||
  234. (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
  235. (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
  236. /* This was not a good enough type-2 message */
  237. free(buffer);
  238. return CURLNTLM_BAD;
  239. }
  240. ntlm->flags = readint_le(&buffer[20]);
  241. memcpy(ntlm->nonce, &buffer[24], 8);
  242. DEBUG_OUT({
  243. fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
  244. print_flags(stderr, ntlm->flags);
  245. fprintf(stderr, "\n nonce=");
  246. print_hex(stderr, (char *)ntlm->nonce, 8);
  247. fprintf(stderr, "\n****\n");
  248. fprintf(stderr, "**** Header %s\n ", header);
  249. });
  250. free(buffer);
  251. #endif
  252. }
  253. else {
  254. if(ntlm->state >= NTLMSTATE_TYPE1)
  255. return CURLNTLM_BAD;
  256. ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
  257. }
  258. }
  259. return CURLNTLM_FINE;
  260. }
  261. #ifndef USE_WINDOWS_SSPI
  262. /*
  263. * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
  264. * key schedule ks is also set.
  265. */
  266. static void setup_des_key(unsigned char *key_56,
  267. DES_key_schedule DESKEYARG(ks))
  268. {
  269. DES_cblock key;
  270. key[0] = key_56[0];
  271. key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
  272. key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
  273. key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
  274. key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
  275. key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
  276. key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
  277. key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
  278. DES_set_odd_parity(&key);
  279. DES_set_key(&key, ks);
  280. }
  281. /*
  282. * takes a 21 byte array and treats it as 3 56-bit DES keys. The
  283. * 8 byte plaintext is encrypted with each key and the resulting 24
  284. * bytes are stored in the results array.
  285. */
  286. static void lm_resp(unsigned char *keys,
  287. unsigned char *plaintext,
  288. unsigned char *results)
  289. {
  290. DES_key_schedule ks;
  291. setup_des_key(keys, DESKEY(ks));
  292. DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
  293. DESKEY(ks), DES_ENCRYPT);
  294. setup_des_key(keys+7, DESKEY(ks));
  295. DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
  296. DESKEY(ks), DES_ENCRYPT);
  297. setup_des_key(keys+14, DESKEY(ks));
  298. DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
  299. DESKEY(ks), DES_ENCRYPT);
  300. }
  301. /*
  302. * Set up lanmanager hashed password
  303. */
  304. static void mk_lm_hash(struct SessionHandle *data,
  305. char *password,
  306. unsigned char *lmbuffer /* 21 bytes */)
  307. {
  308. unsigned char pw[14];
  309. static const unsigned char magic[] = {
  310. 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
  311. };
  312. unsigned int i;
  313. size_t len = strlen(password);
  314. if (len > 14)
  315. len = 14;
  316. for (i=0; i<len; i++)
  317. pw[i] = (unsigned char)toupper(password[i]);
  318. for (; i<14; i++)
  319. pw[i] = 0;
  320. #ifdef CURL_DOES_CONVERSIONS
  321. /*
  322. * The LanManager hashed password needs to be created using the
  323. * password in the network encoding not the host encoding.
  324. */
  325. if(data)
  326. Curl_convert_to_network(data, (char *)pw, 14);
  327. #else
  328. (void)data;
  329. #endif
  330. {
  331. /* Create LanManager hashed password. */
  332. DES_key_schedule ks;
  333. setup_des_key(pw, DESKEY(ks));
  334. DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
  335. DESKEY(ks), DES_ENCRYPT);
  336. setup_des_key(pw+7, DESKEY(ks));
  337. DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
  338. DESKEY(ks), DES_ENCRYPT);
  339. memset(lmbuffer + 16, 0, 21 - 16);
  340. }
  341. }
  342. #if USE_NTRESPONSES
  343. static void utf8_to_unicode_le(unsigned char *dest, const char *src,
  344. size_t srclen)
  345. {
  346. size_t i;
  347. for (i=0; i<srclen; i++) {
  348. dest[2*i] = (unsigned char)src[i];
  349. dest[2*i+1] = '\0';
  350. }
  351. }
  352. /*
  353. * Set up nt hashed passwords
  354. */
  355. static void mk_nt_hash(struct SessionHandle *data,
  356. char *password,
  357. unsigned char *ntbuffer /* 21 bytes */)
  358. {
  359. size_t len = strlen(password);
  360. unsigned char *pw = malloc(len*2);
  361. utf8_to_unicode_le(pw, password, len);
  362. #ifdef CURL_DOES_CONVERSIONS
  363. /*
  364. * The NT hashed password needs to be created using the
  365. * password in the network encoding not the host encoding.
  366. */
  367. if(data)
  368. Curl_convert_to_network(data, (char *)pw, len*2);
  369. #else
  370. (void)data;
  371. #endif
  372. {
  373. /* Create NT hashed password. */
  374. MD4_CTX MD4;
  375. MD4_Init(&MD4);
  376. MD4_Update(&MD4, pw, 2*len);
  377. MD4_Final(ntbuffer, &MD4);
  378. memset(ntbuffer + 16, 0, 21 - 16);
  379. }
  380. free(pw);
  381. }
  382. #endif
  383. #endif
  384. #ifdef USE_WINDOWS_SSPI
  385. static void
  386. ntlm_sspi_cleanup(struct ntlmdata *ntlm)
  387. {
  388. if (ntlm->type_2) {
  389. free(ntlm->type_2);
  390. ntlm->type_2 = NULL;
  391. }
  392. if (ntlm->has_handles) {
  393. s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
  394. s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
  395. ntlm->has_handles = 0;
  396. }
  397. if (ntlm->p_identity) {
  398. if (ntlm->identity.User) free(ntlm->identity.User);
  399. if (ntlm->identity.Password) free(ntlm->identity.Password);
  400. if (ntlm->identity.Domain) free(ntlm->identity.Domain);
  401. ntlm->p_identity = NULL;
  402. }
  403. }
  404. #endif
  405. #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
  406. #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
  407. (((x) >>16)&0xff), (((x)>>24) & 0xff)
  408. #define HOSTNAME_MAX 1024
  409. /* this is for creating ntlm header output */
  410. CURLcode Curl_output_ntlm(struct connectdata *conn,
  411. bool proxy)
  412. {
  413. const char *domain=""; /* empty */
  414. char host [HOSTNAME_MAX+ 1] = ""; /* empty */
  415. #ifndef USE_WINDOWS_SSPI
  416. size_t domlen = strlen(domain);
  417. size_t hostlen = strlen(host);
  418. size_t hostoff; /* host name offset */
  419. size_t domoff; /* domain name offset */
  420. #endif
  421. size_t size;
  422. char *base64=NULL;
  423. unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
  424. long */
  425. /* point to the address of the pointer that holds the string to sent to the
  426. server, which is for a plain host or for a HTTP proxy */
  427. char **allocuserpwd;
  428. /* point to the name and password for this */
  429. char *userp;
  430. char *passwdp;
  431. /* point to the correct struct with this */
  432. struct ntlmdata *ntlm;
  433. struct auth *authp;
  434. curlassert(conn);
  435. curlassert(conn->data);
  436. if(proxy) {
  437. allocuserpwd = &conn->allocptr.proxyuserpwd;
  438. userp = conn->proxyuser;
  439. passwdp = conn->proxypasswd;
  440. ntlm = &conn->proxyntlm;
  441. authp = &conn->data->state.authproxy;
  442. }
  443. else {
  444. allocuserpwd = &conn->allocptr.userpwd;
  445. userp = conn->user;
  446. passwdp = conn->passwd;
  447. ntlm = &conn->ntlm;
  448. authp = &conn->data->state.authhost;
  449. }
  450. authp->done = FALSE;
  451. /* not set means empty */
  452. if(!userp)
  453. userp=(char *)"";
  454. if(!passwdp)
  455. passwdp=(char *)"";
  456. #ifdef USE_WINDOWS_SSPI
  457. /* If security interface is not yet initialized try to do this */
  458. if (s_hSecDll == NULL) {
  459. /* Determine Windows version. Security functions are located in
  460. * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
  461. * contain both these DLLs (security.dll just forwards calls to
  462. * secur32.dll)
  463. */
  464. OSVERSIONINFO osver;
  465. osver.dwOSVersionInfoSize = sizeof(osver);
  466. GetVersionEx(&osver);
  467. if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT
  468. && osver.dwMajorVersion == 4)
  469. s_hSecDll = LoadLibrary("security.dll");
  470. else
  471. s_hSecDll = LoadLibrary("secur32.dll");
  472. if (s_hSecDll != NULL) {
  473. INIT_SECURITY_INTERFACE pInitSecurityInterface;
  474. pInitSecurityInterface =
  475. (INIT_SECURITY_INTERFACE)GetProcAddress(s_hSecDll,
  476. "InitSecurityInterfaceA");
  477. if (pInitSecurityInterface != NULL)
  478. s_pSecFn = pInitSecurityInterface();
  479. }
  480. }
  481. if (s_pSecFn == NULL)
  482. return CURLE_RECV_ERROR;
  483. #endif
  484. switch(ntlm->state) {
  485. case NTLMSTATE_TYPE1:
  486. default: /* for the weird cases we (re)start here */
  487. #ifdef USE_WINDOWS_SSPI
  488. {
  489. SecBuffer buf;
  490. SecBufferDesc desc;
  491. SECURITY_STATUS status;
  492. ULONG attrs;
  493. const char *user;
  494. int domlen;
  495. TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
  496. ntlm_sspi_cleanup(ntlm);
  497. user = strchr(userp, '\\');
  498. if (!user)
  499. user = strchr(userp, '/');
  500. if (user) {
  501. domain = userp;
  502. domlen = user - userp;
  503. user++;
  504. }
  505. else {
  506. user = userp;
  507. domain = "";
  508. domlen = 0;
  509. }
  510. if (user && *user) {
  511. /* note: initialize all of this before doing the mallocs so that
  512. * it can be cleaned up later without leaking memory.
  513. */
  514. ntlm->p_identity = &ntlm->identity;
  515. memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
  516. if ((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL)
  517. return CURLE_OUT_OF_MEMORY;
  518. ntlm->identity.UserLength = strlen(user);
  519. if ((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL)
  520. return CURLE_OUT_OF_MEMORY;
  521. ntlm->identity.PasswordLength = strlen(passwdp);
  522. if ((ntlm->identity.Domain = malloc(domlen+1)) == NULL)
  523. return CURLE_OUT_OF_MEMORY;
  524. strncpy((char *)ntlm->identity.Domain, domain, domlen);
  525. ntlm->identity.Domain[domlen] = '\0';
  526. ntlm->identity.DomainLength = domlen;
  527. ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
  528. }
  529. else {
  530. ntlm->p_identity = NULL;
  531. }
  532. if (s_pSecFn->AcquireCredentialsHandle(
  533. NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
  534. NULL, NULL, &ntlm->handle, &tsDummy
  535. ) != SEC_E_OK) {
  536. return CURLE_OUT_OF_MEMORY;
  537. }
  538. desc.ulVersion = SECBUFFER_VERSION;
  539. desc.cBuffers = 1;
  540. desc.pBuffers = &buf;
  541. buf.cbBuffer = sizeof(ntlmbuf);
  542. buf.BufferType = SECBUFFER_TOKEN;
  543. buf.pvBuffer = ntlmbuf;
  544. status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL,
  545. (char *) host,
  546. ISC_REQ_CONFIDENTIALITY |
  547. ISC_REQ_REPLAY_DETECT |
  548. ISC_REQ_CONNECTION,
  549. 0, SECURITY_NETWORK_DREP,
  550. NULL, 0,
  551. &ntlm->c_handle, &desc,
  552. &attrs, &tsDummy);
  553. if (status == SEC_I_COMPLETE_AND_CONTINUE ||
  554. status == SEC_I_CONTINUE_NEEDED) {
  555. s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
  556. }
  557. else if (status != SEC_E_OK) {
  558. s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
  559. return CURLE_RECV_ERROR;
  560. }
  561. ntlm->has_handles = 1;
  562. size = buf.cbBuffer;
  563. }
  564. #else
  565. hostoff = 0;
  566. domoff = hostoff + hostlen; /* This is 0: remember that host and domain
  567. are empty */
  568. /* Create and send a type-1 message:
  569. Index Description Content
  570. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  571. (0x4e544c4d53535000)
  572. 8 NTLM Message Type long (0x01000000)
  573. 12 Flags long
  574. 16 Supplied Domain security buffer(*)
  575. 24 Supplied Workstation security buffer(*)
  576. 32 start of data block
  577. */
  578. #if USE_NTLM2SESSION
  579. #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
  580. #else
  581. #define NTLM2FLAG 0
  582. #endif
  583. snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c"
  584. "\x01%c%c%c" /* 32-bit type = 1 */
  585. "%c%c%c%c" /* 32-bit NTLM flag field */
  586. "%c%c" /* domain length */
  587. "%c%c" /* domain allocated space */
  588. "%c%c" /* domain name offset */
  589. "%c%c" /* 2 zeroes */
  590. "%c%c" /* host length */
  591. "%c%c" /* host allocated space */
  592. "%c%c" /* host name offset */
  593. "%c%c" /* 2 zeroes */
  594. "%s" /* host name */
  595. "%s", /* domain string */
  596. 0, /* trailing zero */
  597. 0,0,0, /* part of type-1 long */
  598. LONGQUARTET(
  599. NTLMFLAG_NEGOTIATE_OEM|
  600. NTLMFLAG_REQUEST_TARGET|
  601. NTLMFLAG_NEGOTIATE_NTLM_KEY|
  602. NTLM2FLAG|
  603. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
  604. ),
  605. SHORTPAIR(domlen),
  606. SHORTPAIR(domlen),
  607. SHORTPAIR(domoff),
  608. 0,0,
  609. SHORTPAIR(hostlen),
  610. SHORTPAIR(hostlen),
  611. SHORTPAIR(hostoff),
  612. 0,0,
  613. host /* this is empty */, domain /* this is empty */);
  614. /* initial packet length */
  615. size = 32 + hostlen + domlen;
  616. #endif
  617. DEBUG_OUT({
  618. fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
  619. LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
  620. NTLMFLAG_REQUEST_TARGET|
  621. NTLMFLAG_NEGOTIATE_NTLM_KEY|
  622. NTLM2FLAG|
  623. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
  624. NTLMFLAG_NEGOTIATE_OEM|
  625. NTLMFLAG_REQUEST_TARGET|
  626. NTLMFLAG_NEGOTIATE_NTLM_KEY|
  627. NTLM2FLAG|
  628. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
  629. print_flags(stderr,
  630. NTLMFLAG_NEGOTIATE_OEM|
  631. NTLMFLAG_REQUEST_TARGET|
  632. NTLMFLAG_NEGOTIATE_NTLM_KEY|
  633. NTLM2FLAG|
  634. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
  635. fprintf(stderr, "\n****\n");
  636. });
  637. /* now size is the size of the base64 encoded package size */
  638. size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
  639. if(size >0 ) {
  640. Curl_safefree(*allocuserpwd);
  641. *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
  642. proxy?"Proxy-":"",
  643. base64);
  644. DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
  645. free(base64);
  646. }
  647. else
  648. return CURLE_OUT_OF_MEMORY; /* FIX TODO */
  649. break;
  650. case NTLMSTATE_TYPE2:
  651. /* We received the type-2 message already, create a type-3 message:
  652. Index Description Content
  653. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  654. (0x4e544c4d53535000)
  655. 8 NTLM Message Type long (0x03000000)
  656. 12 LM/LMv2 Response security buffer(*)
  657. 20 NTLM/NTLMv2 Response security buffer(*)
  658. 28 Domain Name security buffer(*)
  659. 36 User Name security buffer(*)
  660. 44 Workstation Name security buffer(*)
  661. (52) Session Key (optional) security buffer(*)
  662. (60) Flags (optional) long
  663. 52 (64) start of data block
  664. */
  665. {
  666. #ifdef USE_WINDOWS_SSPI
  667. SecBuffer type_2, type_3;
  668. SecBufferDesc type_2_desc, type_3_desc;
  669. SECURITY_STATUS status;
  670. ULONG attrs;
  671. TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
  672. type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
  673. type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
  674. type_2_desc.pBuffers = &type_2;
  675. type_3_desc.pBuffers = &type_3;
  676. type_2.BufferType = SECBUFFER_TOKEN;
  677. type_2.pvBuffer = ntlm->type_2;
  678. type_2.cbBuffer = ntlm->n_type_2;
  679. type_3.BufferType = SECBUFFER_TOKEN;
  680. type_3.pvBuffer = ntlmbuf;
  681. type_3.cbBuffer = sizeof(ntlmbuf);
  682. status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, &ntlm->c_handle,
  683. (char *) host,
  684. ISC_REQ_CONFIDENTIALITY |
  685. ISC_REQ_REPLAY_DETECT |
  686. ISC_REQ_CONNECTION,
  687. 0, SECURITY_NETWORK_DREP, &type_2_desc,
  688. 0, &ntlm->c_handle, &type_3_desc,
  689. &attrs, &tsDummy);
  690. if (status != SEC_E_OK)
  691. return CURLE_RECV_ERROR;
  692. size = type_3.cbBuffer;
  693. ntlm_sspi_cleanup(ntlm);
  694. #else
  695. int lmrespoff;
  696. unsigned char lmresp[24]; /* fixed-size */
  697. #if USE_NTRESPONSES
  698. int ntrespoff;
  699. unsigned char ntresp[24]; /* fixed-size */
  700. #endif
  701. size_t useroff;
  702. const char *user;
  703. size_t userlen;
  704. user = strchr(userp, '\\');
  705. if(!user)
  706. user = strchr(userp, '/');
  707. if (user) {
  708. domain = userp;
  709. domlen = (user - domain);
  710. user++;
  711. }
  712. else
  713. user = userp;
  714. userlen = strlen(user);
  715. if (gethostname(host, HOSTNAME_MAX)) {
  716. infof(conn->data, "gethostname() failed, continuing without!");
  717. hostlen = 0;
  718. }
  719. else {
  720. /* If the workstation if configured with a full DNS name (i.e.
  721. * workstation.somewhere.net) gethostname() returns the fully qualified
  722. * name, which NTLM doesn't like.
  723. */
  724. char *dot = strchr(host, '.');
  725. if (dot)
  726. *dot = '\0';
  727. hostlen = strlen(host);
  728. }
  729. #if USE_NTLM2SESSION
  730. /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
  731. if (ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
  732. unsigned char ntbuffer[0x18];
  733. unsigned char tmp[0x18];
  734. unsigned char md5sum[MD5_DIGEST_LENGTH];
  735. MD5_CTX MD5;
  736. unsigned char random[8];
  737. /* Need to create 8 bytes random data */
  738. Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
  739. RAND_bytes(random,8);
  740. /* 8 bytes random data as challenge in lmresp */
  741. memcpy(lmresp,random,8);
  742. /* Pad with zeros */
  743. memset(lmresp+8,0,0x10);
  744. /* Fill tmp with challenge(nonce?) + random */
  745. memcpy(tmp,&ntlm->nonce[0],8);
  746. memcpy(tmp+8,random,8);
  747. MD5_Init(&MD5);
  748. MD5_Update(&MD5, tmp, 16);
  749. MD5_Final(md5sum, &MD5);
  750. /* We shall only use the first 8 bytes of md5sum,
  751. but the des code in lm_resp only encrypt the first 8 bytes */
  752. mk_nt_hash(conn->data, passwdp, ntbuffer);
  753. lm_resp(ntbuffer, md5sum, ntresp);
  754. /* End of NTLM2 Session code */
  755. }
  756. else {
  757. #endif
  758. #if USE_NTRESPONSES
  759. unsigned char ntbuffer[0x18];
  760. #endif
  761. unsigned char lmbuffer[0x18];
  762. #if USE_NTRESPONSES
  763. mk_nt_hash(conn->data, passwdp, ntbuffer);
  764. lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
  765. #endif
  766. mk_lm_hash(conn->data, passwdp, lmbuffer);
  767. lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
  768. /* A safer but less compatible alternative is:
  769. * lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
  770. * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
  771. #if USE_NTLM2SESSION
  772. }
  773. #endif
  774. lmrespoff = 64; /* size of the message header */
  775. #if USE_NTRESPONSES
  776. ntrespoff = lmrespoff + 0x18;
  777. domoff = ntrespoff + 0x18;
  778. #else
  779. domoff = lmrespoff + 0x18;
  780. #endif
  781. useroff = domoff + domlen;
  782. hostoff = useroff + userlen;
  783. /* Create the big type-3 message binary blob */
  784. size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
  785. NTLMSSP_SIGNATURE "%c"
  786. "\x03%c%c%c" /* type-3, 32 bits */
  787. "%c%c" /* LanManager length */
  788. "%c%c" /* LanManager allocated space */
  789. "%c%c" /* LanManager offset */
  790. "%c%c" /* 2 zeroes */
  791. "%c%c" /* NT-response length */
  792. "%c%c" /* NT-response allocated space */
  793. "%c%c" /* NT-response offset */
  794. "%c%c" /* 2 zeroes */
  795. "%c%c" /* domain length */
  796. "%c%c" /* domain allocated space */
  797. "%c%c" /* domain name offset */
  798. "%c%c" /* 2 zeroes */
  799. "%c%c" /* user length */
  800. "%c%c" /* user allocated space */
  801. "%c%c" /* user offset */
  802. "%c%c" /* 2 zeroes */
  803. "%c%c" /* host length */
  804. "%c%c" /* host allocated space */
  805. "%c%c" /* host offset */
  806. "%c%c" /* 2 zeroes */
  807. "%c%c" /* session key length (unknown purpose) */
  808. "%c%c" /* session key allocated space (unknown purpose) */
  809. "%c%c" /* session key offset (unknown purpose) */
  810. "%c%c" /* 2 zeroes */
  811. "%c%c%c%c" /* flags */
  812. /* domain string */
  813. /* user string */
  814. /* host string */
  815. /* LanManager response */
  816. /* NT response */
  817. ,
  818. 0, /* zero termination */
  819. 0,0,0, /* type-3 long, the 24 upper bits */
  820. SHORTPAIR(0x18), /* LanManager response length, twice */
  821. SHORTPAIR(0x18),
  822. SHORTPAIR(lmrespoff),
  823. 0x0, 0x0,
  824. #if USE_NTRESPONSES
  825. SHORTPAIR(0x18), /* NT-response length, twice */
  826. SHORTPAIR(0x18),
  827. SHORTPAIR(ntrespoff),
  828. 0x0, 0x0,
  829. #else
  830. 0x0, 0x0,
  831. 0x0, 0x0,
  832. 0x0, 0x0,
  833. 0x0, 0x0,
  834. #endif
  835. SHORTPAIR(domlen),
  836. SHORTPAIR(domlen),
  837. SHORTPAIR(domoff),
  838. 0x0, 0x0,
  839. SHORTPAIR(userlen),
  840. SHORTPAIR(userlen),
  841. SHORTPAIR(useroff),
  842. 0x0, 0x0,
  843. SHORTPAIR(hostlen),
  844. SHORTPAIR(hostlen),
  845. SHORTPAIR(hostoff),
  846. 0x0, 0x0,
  847. 0x0, 0x0,
  848. 0x0, 0x0,
  849. 0x0, 0x0,
  850. 0x0, 0x0,
  851. LONGQUARTET(ntlm->flags));
  852. DEBUG_OUT(assert(size==64));
  853. DEBUG_OUT(assert(size == lmrespoff));
  854. /* We append the binary hashes */
  855. if(size < (sizeof(ntlmbuf) - 0x18)) {
  856. memcpy(&ntlmbuf[size], lmresp, 0x18);
  857. size += 0x18;
  858. }
  859. DEBUG_OUT({
  860. fprintf(stderr, "**** TYPE3 header lmresp=");
  861. print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
  862. });
  863. #if USE_NTRESPONSES
  864. if(size < (sizeof(ntlmbuf) - 0x18)) {
  865. DEBUG_OUT(assert(size == ntrespoff));
  866. memcpy(&ntlmbuf[size], ntresp, 0x18);
  867. size += 0x18;
  868. }
  869. DEBUG_OUT({
  870. fprintf(stderr, "\n ntresp=");
  871. print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
  872. });
  873. #endif
  874. DEBUG_OUT({
  875. fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
  876. LONGQUARTET(ntlm->flags), ntlm->flags);
  877. print_flags(stderr, ntlm->flags);
  878. fprintf(stderr, "\n****\n");
  879. });
  880. /* Make sure that the domain, user and host strings fit in the target
  881. buffer before we copy them there. */
  882. if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
  883. failf(conn->data, "user + domain + host name too big");
  884. return CURLE_OUT_OF_MEMORY;
  885. }
  886. curlassert(size == domoff);
  887. memcpy(&ntlmbuf[size], domain, domlen);
  888. size += domlen;
  889. curlassert(size == useroff);
  890. memcpy(&ntlmbuf[size], user, userlen);
  891. size += userlen;
  892. curlassert(size == hostoff);
  893. memcpy(&ntlmbuf[size], host, hostlen);
  894. size += hostlen;
  895. #ifdef CURL_DOES_CONVERSIONS
  896. /* convert domain, user, and host to ASCII but leave the rest as-is */
  897. if(CURLE_OK != Curl_convert_to_network(conn->data,
  898. (char *)&ntlmbuf[domoff],
  899. size-domoff)) {
  900. return CURLE_CONV_FAILED;
  901. }
  902. #endif /* CURL_DOES_CONVERSIONS */
  903. #endif
  904. /* convert the binary blob into base64 */
  905. size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
  906. if(size >0 ) {
  907. Curl_safefree(*allocuserpwd);
  908. *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
  909. proxy?"Proxy-":"",
  910. base64);
  911. DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
  912. free(base64);
  913. }
  914. else
  915. return CURLE_OUT_OF_MEMORY; /* FIX TODO */
  916. ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
  917. authp->done = TRUE;
  918. }
  919. break;
  920. case NTLMSTATE_TYPE3:
  921. /* connection is already authenticated,
  922. * don't send a header in future requests */
  923. if(*allocuserpwd) {
  924. free(*allocuserpwd);
  925. *allocuserpwd=NULL;
  926. }
  927. authp->done = TRUE;
  928. break;
  929. }
  930. return CURLE_OK;
  931. }
  932. void
  933. Curl_ntlm_cleanup(struct connectdata *conn)
  934. {
  935. #ifdef USE_WINDOWS_SSPI
  936. ntlm_sspi_cleanup(&conn->ntlm);
  937. ntlm_sspi_cleanup(&conn->proxyntlm);
  938. if (s_hSecDll != NULL) {
  939. FreeLibrary(s_hSecDll);
  940. s_hSecDll = NULL;
  941. s_pSecFn = NULL;
  942. }
  943. #else
  944. (void)conn;
  945. #endif
  946. }
  947. #endif /* USE_NTLM */
  948. #endif /* !CURL_DISABLE_HTTP */