http_ntlm.c 34 KB

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