curl_ntlm_msgs.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2014, 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. #include "curl_setup.h"
  23. #ifdef USE_NTLM
  24. /*
  25. * NTLM details:
  26. *
  27. * http://davenport.sourceforge.net/ntlm.html
  28. * http://www.innovation.ch/java/ntlm.html
  29. */
  30. #define DEBUG_ME 0
  31. #include "urldata.h"
  32. #include "non-ascii.h"
  33. #include "sendf.h"
  34. #include "curl_base64.h"
  35. #include "curl_ntlm_core.h"
  36. #include "curl_gethostname.h"
  37. #include "curl_multibyte.h"
  38. #include "warnless.h"
  39. #include "curl_memory.h"
  40. #ifdef USE_WINDOWS_SSPI
  41. # include "curl_sspi.h"
  42. #endif
  43. #include "vtls/vtls.h"
  44. #define BUILDING_CURL_NTLM_MSGS_C
  45. #include "curl_ntlm_msgs.h"
  46. #define _MPRINTF_REPLACE /* use our functions only */
  47. #include <curl/mprintf.h>
  48. /* The last #include file should be: */
  49. #include "memdebug.h"
  50. /* "NTLMSSP" signature is always in ASCII regardless of the platform */
  51. #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
  52. #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
  53. #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
  54. (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
  55. #if DEBUG_ME
  56. # define DEBUG_OUT(x) x
  57. static void ntlm_print_flags(FILE *handle, unsigned long flags)
  58. {
  59. if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
  60. fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
  61. if(flags & NTLMFLAG_NEGOTIATE_OEM)
  62. fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
  63. if(flags & NTLMFLAG_REQUEST_TARGET)
  64. fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
  65. if(flags & (1<<3))
  66. fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
  67. if(flags & NTLMFLAG_NEGOTIATE_SIGN)
  68. fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
  69. if(flags & NTLMFLAG_NEGOTIATE_SEAL)
  70. fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
  71. if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
  72. fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
  73. if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
  74. fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
  75. if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
  76. fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
  77. if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
  78. fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
  79. if(flags & (1<<10))
  80. fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
  81. if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
  82. fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
  83. if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
  84. fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
  85. if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
  86. fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
  87. if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
  88. fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
  89. if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
  90. fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
  91. if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
  92. fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
  93. if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
  94. fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
  95. if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
  96. fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
  97. if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
  98. fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
  99. if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
  100. fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
  101. if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
  102. fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
  103. if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
  104. fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
  105. if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
  106. fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
  107. if(flags & (1<<24))
  108. fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
  109. if(flags & (1<<25))
  110. fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
  111. if(flags & (1<<26))
  112. fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
  113. if(flags & (1<<27))
  114. fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
  115. if(flags & (1<<28))
  116. fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
  117. if(flags & NTLMFLAG_NEGOTIATE_128)
  118. fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
  119. if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
  120. fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
  121. if(flags & NTLMFLAG_NEGOTIATE_56)
  122. fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
  123. }
  124. static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
  125. {
  126. const char *p = buf;
  127. (void)handle;
  128. fprintf(stderr, "0x");
  129. while(len-- > 0)
  130. fprintf(stderr, "%02.2x", (unsigned int)*p++);
  131. }
  132. #else
  133. # define DEBUG_OUT(x) Curl_nop_stmt
  134. #endif
  135. #ifndef USE_WINDOWS_SSPI
  136. /*
  137. * This function converts from the little endian format used in the
  138. * incoming package to whatever endian format we're using natively.
  139. * Argument is a pointer to a 4 byte buffer.
  140. */
  141. static unsigned int readint_le(unsigned char *buf)
  142. {
  143. return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
  144. ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
  145. }
  146. /*
  147. * This function converts from the little endian format used in the incoming
  148. * package to whatever endian format we're using natively. Argument is a
  149. * pointer to a 2 byte buffer.
  150. */
  151. static unsigned int readshort_le(unsigned char *buf)
  152. {
  153. return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8);
  154. }
  155. /*
  156. * Curl_ntlm_decode_type2_target()
  157. *
  158. * This is used to decode the "target info" in the ntlm type-2 message
  159. * received.
  160. *
  161. * Parameters:
  162. *
  163. * data [in] - Pointer to the session handle
  164. * buffer [in] - The decoded base64 ntlm header of Type 2
  165. * size [in] - The input buffer size, atleast 32 bytes
  166. * ntlm [in] - Pointer to ntlm data struct being used and modified.
  167. *
  168. * Returns CURLE_OK on success.
  169. */
  170. CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data,
  171. unsigned char *buffer,
  172. size_t size,
  173. struct ntlmdata *ntlm)
  174. {
  175. unsigned int target_info_len = 0;
  176. unsigned int target_info_offset = 0;
  177. Curl_safefree(ntlm->target_info);
  178. ntlm->target_info_len = 0;
  179. if(size >= 48) {
  180. target_info_len = readshort_le(&buffer[40]);
  181. target_info_offset = readint_le(&buffer[44]);
  182. if(target_info_len > 0) {
  183. if(((target_info_offset + target_info_len) > size) ||
  184. (target_info_offset < 48)) {
  185. infof(data, "NTLM handshake failure (bad type-2 message). "
  186. "Target Info Offset Len is set incorrect by the peer\n");
  187. return CURLE_REMOTE_ACCESS_DENIED;
  188. }
  189. ntlm->target_info = malloc(target_info_len);
  190. if(!ntlm->target_info)
  191. return CURLE_OUT_OF_MEMORY;
  192. memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
  193. ntlm->target_info_len = target_info_len;
  194. }
  195. }
  196. return CURLE_OK;
  197. }
  198. #endif
  199. /*
  200. NTLM message structure notes:
  201. A 'short' is a 'network short', a little-endian 16-bit unsigned value.
  202. A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
  203. A 'security buffer' represents a triplet used to point to a buffer,
  204. consisting of two shorts and one long:
  205. 1. A 'short' containing the length of the buffer content in bytes.
  206. 2. A 'short' containing the allocated space for the buffer in bytes.
  207. 3. A 'long' containing the offset to the start of the buffer in bytes,
  208. from the beginning of the NTLM message.
  209. */
  210. /*
  211. * Curl_ntlm_decode_type2_message()
  212. *
  213. * This is used to decode a ntlm type-2 message received from a HTTP or SASL
  214. * based (such as SMTP, POP3 or IMAP) server. The message is first decoded
  215. * from a base64 string into a raw ntlm message and checked for validity
  216. * before the appropriate data for creating a type-3 message is written to
  217. * the given ntlm data structure.
  218. *
  219. * Parameters:
  220. *
  221. * data [in] - Pointer to session handle.
  222. * header [in] - Pointer to the input buffer.
  223. * ntlm [in] - Pointer to ntlm data struct being used and modified.
  224. *
  225. * Returns CURLE_OK on success.
  226. */
  227. CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
  228. const char *header,
  229. struct ntlmdata *ntlm)
  230. {
  231. #ifndef USE_WINDOWS_SSPI
  232. static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
  233. #endif
  234. /* NTLM type-2 message structure:
  235. Index Description Content
  236. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  237. (0x4e544c4d53535000)
  238. 8 NTLM Message Type long (0x02000000)
  239. 12 Target Name security buffer
  240. 20 Flags long
  241. 24 Challenge 8 bytes
  242. (32) Context 8 bytes (two consecutive longs) (*)
  243. (40) Target Information security buffer (*)
  244. (48) OS Version Structure 8 bytes (*)
  245. 32 (48) (56) Start of data block (*)
  246. (*) -> Optional
  247. */
  248. size_t size = 0;
  249. unsigned char *buffer = NULL;
  250. CURLcode error;
  251. #if defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_WINDOWS_SSPI)
  252. (void)data;
  253. #endif
  254. error = Curl_base64_decode(header, &buffer, &size);
  255. if(error)
  256. return error;
  257. if(!buffer) {
  258. infof(data, "NTLM handshake failure (unhandled condition)\n");
  259. return CURLE_REMOTE_ACCESS_DENIED;
  260. }
  261. #ifdef USE_WINDOWS_SSPI
  262. ntlm->type_2 = malloc(size + 1);
  263. if(ntlm->type_2 == NULL) {
  264. free(buffer);
  265. return CURLE_OUT_OF_MEMORY;
  266. }
  267. ntlm->n_type_2 = curlx_uztoul(size);
  268. memcpy(ntlm->type_2, buffer, size);
  269. #else
  270. ntlm->flags = 0;
  271. if((size < 32) ||
  272. (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
  273. (memcmp(buffer + 8, type2_marker, sizeof(type2_marker)) != 0)) {
  274. /* This was not a good enough type-2 message */
  275. free(buffer);
  276. infof(data, "NTLM handshake failure (bad type-2 message)\n");
  277. return CURLE_REMOTE_ACCESS_DENIED;
  278. }
  279. ntlm->flags = readint_le(&buffer[20]);
  280. memcpy(ntlm->nonce, &buffer[24], 8);
  281. if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
  282. error = Curl_ntlm_decode_type2_target(data, buffer, size, ntlm);
  283. if(error) {
  284. free(buffer);
  285. infof(data, "NTLM handshake failure (bad type-2 message)\n");
  286. return error;
  287. }
  288. }
  289. DEBUG_OUT({
  290. fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
  291. ntlm_print_flags(stderr, ntlm->flags);
  292. fprintf(stderr, "\n nonce=");
  293. ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
  294. fprintf(stderr, "\n****\n");
  295. fprintf(stderr, "**** Header %s\n ", header);
  296. });
  297. #endif
  298. free(buffer);
  299. return CURLE_OK;
  300. }
  301. #ifdef USE_WINDOWS_SSPI
  302. void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm)
  303. {
  304. Curl_safefree(ntlm->type_2);
  305. if(ntlm->has_handles) {
  306. s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
  307. s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
  308. ntlm->has_handles = 0;
  309. }
  310. if(ntlm->p_identity) {
  311. Curl_safefree(ntlm->identity.User);
  312. Curl_safefree(ntlm->identity.Password);
  313. Curl_safefree(ntlm->identity.Domain);
  314. ntlm->p_identity = NULL;
  315. }
  316. }
  317. #endif
  318. #ifndef USE_WINDOWS_SSPI
  319. /* copy the source to the destination and fill in zeroes in every
  320. other destination byte! */
  321. static void unicodecpy(unsigned char *dest, const char *src, size_t length)
  322. {
  323. size_t i;
  324. for(i = 0; i < length; i++) {
  325. dest[2 * i] = (unsigned char)src[i];
  326. dest[2 * i + 1] = '\0';
  327. }
  328. }
  329. #endif
  330. /*
  331. * Curl_ntlm_create_type1_message()
  332. *
  333. * This is used to generate an already encoded NTLM type-1 message ready for
  334. * sending to the recipient, be it a HTTP or SASL based (such as SMTP, POP3
  335. * or IMAP) server, using the appropriate compile time crypo API.
  336. *
  337. * Parameters:
  338. *
  339. * userp [in] - The user name in the format User or Domain\User.
  340. * passdwp [in] - The user's password.
  341. * ntlm [in/out] - The ntlm data struct being used and modified.
  342. * outptr [in/out] - The address where a pointer to newly allocated memory
  343. * holding the result will be stored upon completion.
  344. * outlen [out] - The length of the output message.
  345. *
  346. * Returns CURLE_OK on success.
  347. */
  348. CURLcode Curl_ntlm_create_type1_message(const char *userp,
  349. const char *passwdp,
  350. struct ntlmdata *ntlm,
  351. char **outptr,
  352. size_t *outlen)
  353. {
  354. /* NTLM type-1 message structure:
  355. Index Description Content
  356. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  357. (0x4e544c4d53535000)
  358. 8 NTLM Message Type long (0x01000000)
  359. 12 Flags long
  360. (16) Supplied Domain security buffer (*)
  361. (24) Supplied Workstation security buffer (*)
  362. (32) OS Version Structure 8 bytes (*)
  363. (32) (40) Start of data block (*)
  364. (*) -> Optional
  365. */
  366. unsigned char ntlmbuf[NTLM_BUFSIZE];
  367. size_t size;
  368. #ifdef USE_WINDOWS_SSPI
  369. SecBuffer buf;
  370. SecBufferDesc desc;
  371. SECURITY_STATUS status;
  372. unsigned long attrs;
  373. xcharp_u useranddomain;
  374. xcharp_u user, dup_user;
  375. xcharp_u domain, dup_domain;
  376. xcharp_u passwd, dup_passwd;
  377. size_t domlen = 0;
  378. TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
  379. domain.const_tchar_ptr = TEXT("");
  380. Curl_ntlm_sspi_cleanup(ntlm);
  381. if(userp && *userp) {
  382. /* null initialize ntlm identity's data to allow proper cleanup */
  383. ntlm->p_identity = &ntlm->identity;
  384. memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
  385. useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp);
  386. if(!useranddomain.tchar_ptr)
  387. return CURLE_OUT_OF_MEMORY;
  388. user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\'));
  389. if(!user.const_tchar_ptr)
  390. user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/'));
  391. if(user.tchar_ptr) {
  392. domain.tchar_ptr = useranddomain.tchar_ptr;
  393. domlen = user.tchar_ptr - useranddomain.tchar_ptr;
  394. user.tchar_ptr++;
  395. }
  396. else {
  397. user.tchar_ptr = useranddomain.tchar_ptr;
  398. domain.const_tchar_ptr = TEXT("");
  399. domlen = 0;
  400. }
  401. /* setup ntlm identity's user and length */
  402. dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
  403. if(!dup_user.tchar_ptr) {
  404. Curl_unicodefree(useranddomain.tchar_ptr);
  405. return CURLE_OUT_OF_MEMORY;
  406. }
  407. ntlm->identity.User = dup_user.tbyte_ptr;
  408. ntlm->identity.UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr));
  409. dup_user.tchar_ptr = NULL;
  410. /* setup ntlm identity's domain and length */
  411. dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
  412. if(!dup_domain.tchar_ptr) {
  413. Curl_unicodefree(useranddomain.tchar_ptr);
  414. return CURLE_OUT_OF_MEMORY;
  415. }
  416. _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
  417. *(dup_domain.tchar_ptr + domlen) = TEXT('\0');
  418. ntlm->identity.Domain = dup_domain.tbyte_ptr;
  419. ntlm->identity.DomainLength = curlx_uztoul(domlen);
  420. dup_domain.tchar_ptr = NULL;
  421. Curl_unicodefree(useranddomain.tchar_ptr);
  422. /* setup ntlm identity's password and length */
  423. passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp);
  424. if(!passwd.tchar_ptr)
  425. return CURLE_OUT_OF_MEMORY;
  426. dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
  427. if(!dup_passwd.tchar_ptr) {
  428. Curl_unicodefree(passwd.tchar_ptr);
  429. return CURLE_OUT_OF_MEMORY;
  430. }
  431. ntlm->identity.Password = dup_passwd.tbyte_ptr;
  432. ntlm->identity.PasswordLength =
  433. curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
  434. dup_passwd.tchar_ptr = NULL;
  435. Curl_unicodefree(passwd.tchar_ptr);
  436. /* setup ntlm identity's flags */
  437. ntlm->identity.Flags = SECFLAG_WINNT_AUTH_IDENTITY;
  438. }
  439. else
  440. ntlm->p_identity = NULL;
  441. status = s_pSecFn->AcquireCredentialsHandle(NULL,
  442. (TCHAR *) TEXT("NTLM"),
  443. SECPKG_CRED_OUTBOUND, NULL,
  444. ntlm->p_identity, NULL, NULL,
  445. &ntlm->handle, &tsDummy);
  446. if(status != SEC_E_OK)
  447. return CURLE_OUT_OF_MEMORY;
  448. desc.ulVersion = SECBUFFER_VERSION;
  449. desc.cBuffers = 1;
  450. desc.pBuffers = &buf;
  451. buf.cbBuffer = NTLM_BUFSIZE;
  452. buf.BufferType = SECBUFFER_TOKEN;
  453. buf.pvBuffer = ntlmbuf;
  454. status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL,
  455. (TCHAR *) TEXT(""),
  456. ISC_REQ_CONFIDENTIALITY |
  457. ISC_REQ_REPLAY_DETECT |
  458. ISC_REQ_CONNECTION,
  459. 0, SECURITY_NETWORK_DREP,
  460. NULL, 0,
  461. &ntlm->c_handle, &desc,
  462. &attrs, &tsDummy);
  463. if(status == SEC_I_COMPLETE_AND_CONTINUE ||
  464. status == SEC_I_CONTINUE_NEEDED)
  465. s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
  466. else if(status != SEC_E_OK) {
  467. s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
  468. return CURLE_RECV_ERROR;
  469. }
  470. ntlm->has_handles = 1;
  471. size = buf.cbBuffer;
  472. #else
  473. const char *host = ""; /* empty */
  474. const char *domain = ""; /* empty */
  475. size_t hostlen = 0;
  476. size_t domlen = 0;
  477. size_t hostoff = 0;
  478. size_t domoff = hostoff + hostlen; /* This is 0: remember that host and
  479. domain are empty */
  480. (void)userp;
  481. (void)passwdp;
  482. (void)ntlm;
  483. #if USE_NTLM2SESSION
  484. #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
  485. #else
  486. #define NTLM2FLAG 0
  487. #endif
  488. snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
  489. NTLMSSP_SIGNATURE "%c"
  490. "\x01%c%c%c" /* 32-bit type = 1 */
  491. "%c%c%c%c" /* 32-bit NTLM flag field */
  492. "%c%c" /* domain length */
  493. "%c%c" /* domain allocated space */
  494. "%c%c" /* domain name offset */
  495. "%c%c" /* 2 zeroes */
  496. "%c%c" /* host length */
  497. "%c%c" /* host allocated space */
  498. "%c%c" /* host name offset */
  499. "%c%c" /* 2 zeroes */
  500. "%s" /* host name */
  501. "%s", /* domain string */
  502. 0, /* trailing zero */
  503. 0, 0, 0, /* part of type-1 long */
  504. LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
  505. NTLMFLAG_REQUEST_TARGET |
  506. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  507. NTLM2FLAG |
  508. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
  509. SHORTPAIR(domlen),
  510. SHORTPAIR(domlen),
  511. SHORTPAIR(domoff),
  512. 0, 0,
  513. SHORTPAIR(hostlen),
  514. SHORTPAIR(hostlen),
  515. SHORTPAIR(hostoff),
  516. 0, 0,
  517. host, /* this is empty */
  518. domain /* this is empty */);
  519. /* Initial packet length */
  520. size = 32 + hostlen + domlen;
  521. #endif
  522. DEBUG_OUT({
  523. fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
  524. "0x%08.8x ",
  525. LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
  526. NTLMFLAG_REQUEST_TARGET |
  527. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  528. NTLM2FLAG |
  529. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
  530. NTLMFLAG_NEGOTIATE_OEM |
  531. NTLMFLAG_REQUEST_TARGET |
  532. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  533. NTLM2FLAG |
  534. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
  535. ntlm_print_flags(stderr,
  536. NTLMFLAG_NEGOTIATE_OEM |
  537. NTLMFLAG_REQUEST_TARGET |
  538. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  539. NTLM2FLAG |
  540. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
  541. fprintf(stderr, "\n****\n");
  542. });
  543. /* Return with binary blob encoded into base64 */
  544. return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
  545. }
  546. /*
  547. * Curl_ntlm_create_type3_message()
  548. *
  549. * This is used to generate an already encoded NTLM type-3 message ready for
  550. * sending to the recipient, be it a HTTP or SASL based (such as SMTP, POP3
  551. * or IMAP) server, using the appropriate compile time crypo API.
  552. *
  553. * Parameters:
  554. *
  555. * data [in] - The session handle.
  556. * userp [in] - The user name in the format User or Domain\User.
  557. * passdwp [in] - The user's password.
  558. * ntlm [in/out] - The ntlm data struct being used and modified.
  559. * outptr [in/out] - The address where a pointer to newly allocated memory
  560. * holding the result will be stored upon completion.
  561. * outlen [out] - The length of the output message.
  562. *
  563. * Returns CURLE_OK on success.
  564. */
  565. CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
  566. const char *userp,
  567. const char *passwdp,
  568. struct ntlmdata *ntlm,
  569. char **outptr,
  570. size_t *outlen)
  571. {
  572. /* NTLM type-3 message structure:
  573. Index Description Content
  574. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  575. (0x4e544c4d53535000)
  576. 8 NTLM Message Type long (0x03000000)
  577. 12 LM/LMv2 Response security buffer
  578. 20 NTLM/NTLMv2 Response security buffer
  579. 28 Target Name security buffer
  580. 36 User Name security buffer
  581. 44 Workstation Name security buffer
  582. (52) Session Key security buffer (*)
  583. (60) Flags long (*)
  584. (64) OS Version Structure 8 bytes (*)
  585. 52 (64) (72) Start of data block
  586. (*) -> Optional
  587. */
  588. unsigned char ntlmbuf[NTLM_BUFSIZE];
  589. size_t size;
  590. #ifdef USE_WINDOWS_SSPI
  591. SecBuffer type_2;
  592. SecBuffer type_3;
  593. SecBufferDesc type_2_desc;
  594. SecBufferDesc type_3_desc;
  595. SECURITY_STATUS status;
  596. unsigned long attrs;
  597. TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
  598. (void)passwdp;
  599. (void)userp;
  600. (void)data;
  601. type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
  602. type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
  603. type_2_desc.pBuffers = &type_2;
  604. type_3_desc.pBuffers = &type_3;
  605. type_2.BufferType = SECBUFFER_TOKEN;
  606. type_2.pvBuffer = ntlm->type_2;
  607. type_2.cbBuffer = ntlm->n_type_2;
  608. type_3.BufferType = SECBUFFER_TOKEN;
  609. type_3.pvBuffer = ntlmbuf;
  610. type_3.cbBuffer = NTLM_BUFSIZE;
  611. status = s_pSecFn->InitializeSecurityContext(&ntlm->handle,
  612. &ntlm->c_handle,
  613. (TCHAR *) TEXT(""),
  614. ISC_REQ_CONFIDENTIALITY |
  615. ISC_REQ_REPLAY_DETECT |
  616. ISC_REQ_CONNECTION,
  617. 0, SECURITY_NETWORK_DREP,
  618. &type_2_desc,
  619. 0, &ntlm->c_handle,
  620. &type_3_desc,
  621. &attrs, &tsDummy);
  622. if(status != SEC_E_OK)
  623. return CURLE_RECV_ERROR;
  624. size = type_3.cbBuffer;
  625. Curl_ntlm_sspi_cleanup(ntlm);
  626. #else
  627. int lmrespoff;
  628. unsigned char lmresp[24]; /* fixed-size */
  629. #if USE_NTRESPONSES
  630. int ntrespoff;
  631. unsigned int ntresplen = 24;
  632. unsigned char ntresp[24]; /* fixed-size */
  633. unsigned char *ptr_ntresp = &ntresp[0];
  634. unsigned char *ntlmv2resp = NULL;
  635. #endif
  636. bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
  637. char host[HOSTNAME_MAX + 1] = "";
  638. const char *user;
  639. const char *domain = "";
  640. size_t hostoff = 0;
  641. size_t useroff = 0;
  642. size_t domoff = 0;
  643. size_t hostlen = 0;
  644. size_t userlen = 0;
  645. size_t domlen = 0;
  646. CURLcode res = CURLE_OK;
  647. user = strchr(userp, '\\');
  648. if(!user)
  649. user = strchr(userp, '/');
  650. if(user) {
  651. domain = userp;
  652. domlen = (user - domain);
  653. user++;
  654. }
  655. else
  656. user = userp;
  657. if(user)
  658. userlen = strlen(user);
  659. /* Get the machine's un-qualified host name as NTLM doesn't like the fully
  660. qualified domain name */
  661. if(Curl_gethostname(host, sizeof(host))) {
  662. infof(data, "gethostname() failed, continuing without!\n");
  663. hostlen = 0;
  664. }
  665. else {
  666. hostlen = strlen(host);
  667. }
  668. #if USE_NTRESPONSES
  669. if(ntlm->target_info_len) {
  670. unsigned char ntbuffer[0x18];
  671. unsigned char entropy[8];
  672. unsigned char ntlmv2hash[0x18];
  673. #if defined(DEBUGBUILD)
  674. /* Use static client nonce in debug (Test Suite) builds */
  675. memcpy(entropy, "12345678", sizeof(entropy));
  676. #else
  677. /* Create an 8 byte random client nonce */
  678. Curl_ssl_random(data, entropy, sizeof(entropy));
  679. #endif
  680. res = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
  681. if(res)
  682. return res;
  683. res = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
  684. ntbuffer, ntlmv2hash);
  685. if(res)
  686. return res;
  687. /* LMv2 response */
  688. res = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, &ntlm->nonce[0],
  689. lmresp);
  690. if(res)
  691. return res;
  692. /* NTLMv2 response */
  693. res = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, ntlm, &ntlmv2resp,
  694. &ntresplen);
  695. if(res)
  696. return res;
  697. ptr_ntresp = ntlmv2resp;
  698. }
  699. else
  700. #endif
  701. #if USE_NTLM2SESSION
  702. /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
  703. if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
  704. unsigned char ntbuffer[0x18];
  705. unsigned char tmp[0x18];
  706. unsigned char md5sum[MD5_DIGEST_LENGTH];
  707. unsigned char entropy[8];
  708. /* Need to create 8 bytes random data */
  709. Curl_ssl_random(data, entropy, sizeof(entropy));
  710. /* 8 bytes random data as challenge in lmresp */
  711. memcpy(lmresp, entropy, 8);
  712. /* Pad with zeros */
  713. memset(lmresp + 8, 0, 0x10);
  714. /* Fill tmp with challenge(nonce?) + entropy */
  715. memcpy(tmp, &ntlm->nonce[0], 8);
  716. memcpy(tmp + 8, entropy, 8);
  717. Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
  718. /* We shall only use the first 8 bytes of md5sum, but the des
  719. code in Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
  720. if(CURLE_OUT_OF_MEMORY ==
  721. Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
  722. return CURLE_OUT_OF_MEMORY;
  723. Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
  724. /* End of NTLM2 Session code */
  725. }
  726. else
  727. #endif
  728. {
  729. #if USE_NTRESPONSES
  730. unsigned char ntbuffer[0x18];
  731. #endif
  732. unsigned char lmbuffer[0x18];
  733. #if USE_NTRESPONSES
  734. if(CURLE_OUT_OF_MEMORY ==
  735. Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
  736. return CURLE_OUT_OF_MEMORY;
  737. Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
  738. #endif
  739. Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
  740. Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
  741. /* A safer but less compatible alternative is:
  742. * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
  743. * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
  744. }
  745. if(unicode) {
  746. domlen = domlen * 2;
  747. userlen = userlen * 2;
  748. hostlen = hostlen * 2;
  749. }
  750. lmrespoff = 64; /* size of the message header */
  751. #if USE_NTRESPONSES
  752. ntrespoff = lmrespoff + 0x18;
  753. domoff = ntrespoff + ntresplen;
  754. #else
  755. domoff = lmrespoff + 0x18;
  756. #endif
  757. useroff = domoff + domlen;
  758. hostoff = useroff + userlen;
  759. /* Create the big type-3 message binary blob */
  760. size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
  761. NTLMSSP_SIGNATURE "%c"
  762. "\x03%c%c%c" /* 32-bit type = 3 */
  763. "%c%c" /* LanManager length */
  764. "%c%c" /* LanManager allocated space */
  765. "%c%c" /* LanManager offset */
  766. "%c%c" /* 2 zeroes */
  767. "%c%c" /* NT-response length */
  768. "%c%c" /* NT-response allocated space */
  769. "%c%c" /* NT-response offset */
  770. "%c%c" /* 2 zeroes */
  771. "%c%c" /* domain length */
  772. "%c%c" /* domain allocated space */
  773. "%c%c" /* domain name offset */
  774. "%c%c" /* 2 zeroes */
  775. "%c%c" /* user length */
  776. "%c%c" /* user allocated space */
  777. "%c%c" /* user offset */
  778. "%c%c" /* 2 zeroes */
  779. "%c%c" /* host length */
  780. "%c%c" /* host allocated space */
  781. "%c%c" /* host offset */
  782. "%c%c" /* 2 zeroes */
  783. "%c%c" /* session key length (unknown purpose) */
  784. "%c%c" /* session key allocated space (unknown purpose) */
  785. "%c%c" /* session key offset (unknown purpose) */
  786. "%c%c" /* 2 zeroes */
  787. "%c%c%c%c", /* flags */
  788. /* domain string */
  789. /* user string */
  790. /* host string */
  791. /* LanManager response */
  792. /* NT response */
  793. 0, /* zero termination */
  794. 0, 0, 0, /* type-3 long, the 24 upper bits */
  795. SHORTPAIR(0x18), /* LanManager response length, twice */
  796. SHORTPAIR(0x18),
  797. SHORTPAIR(lmrespoff),
  798. 0x0, 0x0,
  799. #if USE_NTRESPONSES
  800. SHORTPAIR(ntresplen), /* NT-response length, twice */
  801. SHORTPAIR(ntresplen),
  802. SHORTPAIR(ntrespoff),
  803. 0x0, 0x0,
  804. #else
  805. 0x0, 0x0,
  806. 0x0, 0x0,
  807. 0x0, 0x0,
  808. 0x0, 0x0,
  809. #endif
  810. SHORTPAIR(domlen),
  811. SHORTPAIR(domlen),
  812. SHORTPAIR(domoff),
  813. 0x0, 0x0,
  814. SHORTPAIR(userlen),
  815. SHORTPAIR(userlen),
  816. SHORTPAIR(useroff),
  817. 0x0, 0x0,
  818. SHORTPAIR(hostlen),
  819. SHORTPAIR(hostlen),
  820. SHORTPAIR(hostoff),
  821. 0x0, 0x0,
  822. 0x0, 0x0,
  823. 0x0, 0x0,
  824. 0x0, 0x0,
  825. 0x0, 0x0,
  826. LONGQUARTET(ntlm->flags));
  827. DEBUGASSERT(size == 64);
  828. DEBUGASSERT(size == (size_t)lmrespoff);
  829. /* We append the binary hashes */
  830. if(size < (NTLM_BUFSIZE - 0x18)) {
  831. memcpy(&ntlmbuf[size], lmresp, 0x18);
  832. size += 0x18;
  833. }
  834. DEBUG_OUT({
  835. fprintf(stderr, "**** TYPE3 header lmresp=");
  836. ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
  837. });
  838. #if USE_NTRESPONSES
  839. if(size < (NTLM_BUFSIZE - ntresplen)) {
  840. DEBUGASSERT(size == (size_t)ntrespoff);
  841. memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
  842. size += ntresplen;
  843. }
  844. DEBUG_OUT({
  845. fprintf(stderr, "\n ntresp=");
  846. ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
  847. });
  848. Curl_safefree(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
  849. #endif
  850. DEBUG_OUT({
  851. fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
  852. LONGQUARTET(ntlm->flags), ntlm->flags);
  853. ntlm_print_flags(stderr, ntlm->flags);
  854. fprintf(stderr, "\n****\n");
  855. });
  856. /* Make sure that the domain, user and host strings fit in the
  857. buffer before we copy them there. */
  858. if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
  859. failf(data, "user + domain + host name too big");
  860. return CURLE_OUT_OF_MEMORY;
  861. }
  862. DEBUGASSERT(size == domoff);
  863. if(unicode)
  864. unicodecpy(&ntlmbuf[size], domain, domlen / 2);
  865. else
  866. memcpy(&ntlmbuf[size], domain, domlen);
  867. size += domlen;
  868. DEBUGASSERT(size == useroff);
  869. if(unicode)
  870. unicodecpy(&ntlmbuf[size], user, userlen / 2);
  871. else
  872. memcpy(&ntlmbuf[size], user, userlen);
  873. size += userlen;
  874. DEBUGASSERT(size == hostoff);
  875. if(unicode)
  876. unicodecpy(&ntlmbuf[size], host, hostlen / 2);
  877. else
  878. memcpy(&ntlmbuf[size], host, hostlen);
  879. size += hostlen;
  880. /* Convert domain, user, and host to ASCII but leave the rest as-is */
  881. res = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
  882. size - domoff);
  883. if(res)
  884. return CURLE_CONV_FAILED;
  885. #endif
  886. /* Return with binary blob encoded into base64 */
  887. return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
  888. }
  889. #endif /* USE_NTLM */