ntlm.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2021, 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 https://curl.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. #if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
  24. /*
  25. * NTLM details:
  26. *
  27. * https://davenport.sourceforge.io/ntlm.html
  28. * https://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_ntlm_core.h"
  35. #include "curl_gethostname.h"
  36. #include "curl_multibyte.h"
  37. #include "curl_md5.h"
  38. #include "warnless.h"
  39. #include "rand.h"
  40. #include "vtls/vtls.h"
  41. /* SSL backend-specific #if branches in this file must be kept in the order
  42. documented in curl_ntlm_core. */
  43. #if defined(NTLM_NEEDS_NSS_INIT)
  44. #include "vtls/nssg.h" /* for Curl_nss_force_init() */
  45. #endif
  46. #define BUILDING_CURL_NTLM_MSGS_C
  47. #include "vauth/vauth.h"
  48. #include "vauth/ntlm.h"
  49. #include "curl_endian.h"
  50. #include "curl_printf.h"
  51. /* The last #include files should be: */
  52. #include "curl_memory.h"
  53. #include "memdebug.h"
  54. /* "NTLMSSP" signature is always in ASCII regardless of the platform */
  55. #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
  56. #if DEBUG_ME
  57. # define DEBUG_OUT(x) x
  58. static void ntlm_print_flags(FILE *handle, unsigned long flags)
  59. {
  60. if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
  61. fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
  62. if(flags & NTLMFLAG_NEGOTIATE_OEM)
  63. fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
  64. if(flags & NTLMFLAG_REQUEST_TARGET)
  65. fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
  66. if(flags & (1<<3))
  67. fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
  68. if(flags & NTLMFLAG_NEGOTIATE_SIGN)
  69. fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
  70. if(flags & NTLMFLAG_NEGOTIATE_SEAL)
  71. fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
  72. if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
  73. fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
  74. if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
  75. fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
  76. if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
  77. fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
  78. if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
  79. fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
  80. if(flags & (1<<10))
  81. fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
  82. if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
  83. fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
  84. if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
  85. fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
  86. if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
  87. fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
  88. if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
  89. fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
  90. if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
  91. fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
  92. if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
  93. fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
  94. if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
  95. fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
  96. if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
  97. fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
  98. if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
  99. fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
  100. if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
  101. fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
  102. if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
  103. fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
  104. if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
  105. fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
  106. if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
  107. fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
  108. if(flags & (1<<24))
  109. fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
  110. if(flags & (1<<25))
  111. fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
  112. if(flags & (1<<26))
  113. fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
  114. if(flags & (1<<27))
  115. fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
  116. if(flags & (1<<28))
  117. fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
  118. if(flags & NTLMFLAG_NEGOTIATE_128)
  119. fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
  120. if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
  121. fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
  122. if(flags & NTLMFLAG_NEGOTIATE_56)
  123. fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
  124. }
  125. static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
  126. {
  127. const char *p = buf;
  128. (void) handle;
  129. fprintf(stderr, "0x");
  130. while(len-- > 0)
  131. fprintf(stderr, "%02.2x", (unsigned int)*p++);
  132. }
  133. #else
  134. # define DEBUG_OUT(x) Curl_nop_stmt
  135. #endif
  136. /*
  137. * ntlm_decode_type2_target()
  138. *
  139. * This is used to decode the "target info" in the NTLM type-2 message
  140. * received.
  141. *
  142. * Parameters:
  143. *
  144. * data [in] - The session handle.
  145. * type2ref [in] - The type-2 message.
  146. * ntlm [in/out] - The NTLM data struct being used and modified.
  147. *
  148. * Returns CURLE_OK on success.
  149. */
  150. static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
  151. const struct bufref *type2ref,
  152. struct ntlmdata *ntlm)
  153. {
  154. unsigned short target_info_len = 0;
  155. unsigned int target_info_offset = 0;
  156. const unsigned char *type2 = Curl_bufref_ptr(type2ref);
  157. size_t type2len = Curl_bufref_len(type2ref);
  158. #if defined(CURL_DISABLE_VERBOSE_STRINGS)
  159. (void) data;
  160. #endif
  161. if(type2len >= 48) {
  162. target_info_len = Curl_read16_le(&type2[40]);
  163. target_info_offset = Curl_read32_le(&type2[44]);
  164. if(target_info_len > 0) {
  165. if((target_info_offset > type2len) ||
  166. (target_info_offset + target_info_len) > type2len ||
  167. target_info_offset < 48) {
  168. infof(data, "NTLM handshake failure (bad type-2 message). "
  169. "Target Info Offset Len is set incorrect by the peer");
  170. return CURLE_BAD_CONTENT_ENCODING;
  171. }
  172. free(ntlm->target_info); /* replace any previous data */
  173. ntlm->target_info = malloc(target_info_len);
  174. if(!ntlm->target_info)
  175. return CURLE_OUT_OF_MEMORY;
  176. memcpy(ntlm->target_info, &type2[target_info_offset], target_info_len);
  177. }
  178. }
  179. ntlm->target_info_len = target_info_len;
  180. return CURLE_OK;
  181. }
  182. /*
  183. NTLM message structure notes:
  184. A 'short' is a 'network short', a little-endian 16-bit unsigned value.
  185. A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
  186. A 'security buffer' represents a triplet used to point to a buffer,
  187. consisting of two shorts and one long:
  188. 1. A 'short' containing the length of the buffer content in bytes.
  189. 2. A 'short' containing the allocated space for the buffer in bytes.
  190. 3. A 'long' containing the offset to the start of the buffer in bytes,
  191. from the beginning of the NTLM message.
  192. */
  193. /*
  194. * Curl_auth_is_ntlm_supported()
  195. *
  196. * This is used to evaluate if NTLM is supported.
  197. *
  198. * Parameters: None
  199. *
  200. * Returns TRUE as NTLM as handled by libcurl.
  201. */
  202. bool Curl_auth_is_ntlm_supported(void)
  203. {
  204. return TRUE;
  205. }
  206. /*
  207. * Curl_auth_decode_ntlm_type2_message()
  208. *
  209. * This is used to decode an NTLM type-2 message. The raw NTLM message is
  210. * checked * for validity before the appropriate data for creating a type-3
  211. * message is * written to the given NTLM data structure.
  212. *
  213. * Parameters:
  214. *
  215. * data [in] - The session handle.
  216. * type2ref [in] - The type-2 message.
  217. * ntlm [in/out] - The NTLM data struct being used and modified.
  218. *
  219. * Returns CURLE_OK on success.
  220. */
  221. CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
  222. const struct bufref *type2ref,
  223. struct ntlmdata *ntlm)
  224. {
  225. static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
  226. /* NTLM type-2 message structure:
  227. Index Description Content
  228. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  229. (0x4e544c4d53535000)
  230. 8 NTLM Message Type long (0x02000000)
  231. 12 Target Name security buffer
  232. 20 Flags long
  233. 24 Challenge 8 bytes
  234. (32) Context 8 bytes (two consecutive longs) (*)
  235. (40) Target Information security buffer (*)
  236. (48) OS Version Structure 8 bytes (*)
  237. 32 (48) (56) Start of data block (*)
  238. (*) -> Optional
  239. */
  240. CURLcode result = CURLE_OK;
  241. const unsigned char *type2 = Curl_bufref_ptr(type2ref);
  242. size_t type2len = Curl_bufref_len(type2ref);
  243. #if defined(NTLM_NEEDS_NSS_INIT)
  244. /* Make sure the crypto backend is initialized */
  245. result = Curl_nss_force_init(data);
  246. if(result)
  247. return result;
  248. #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
  249. (void)data;
  250. #endif
  251. ntlm->flags = 0;
  252. if((type2len < 32) ||
  253. (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
  254. (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
  255. /* This was not a good enough type-2 message */
  256. infof(data, "NTLM handshake failure (bad type-2 message)");
  257. return CURLE_BAD_CONTENT_ENCODING;
  258. }
  259. ntlm->flags = Curl_read32_le(&type2[20]);
  260. memcpy(ntlm->nonce, &type2[24], 8);
  261. if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
  262. result = ntlm_decode_type2_target(data, type2ref, ntlm);
  263. if(result) {
  264. infof(data, "NTLM handshake failure (bad type-2 message)");
  265. return result;
  266. }
  267. }
  268. DEBUG_OUT({
  269. fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
  270. ntlm_print_flags(stderr, ntlm->flags);
  271. fprintf(stderr, "\n nonce=");
  272. ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
  273. fprintf(stderr, "\n****\n");
  274. fprintf(stderr, "**** Header %s\n ", header);
  275. });
  276. return result;
  277. }
  278. /* copy the source to the destination and fill in zeroes in every
  279. other destination byte! */
  280. static void unicodecpy(unsigned char *dest, const char *src, size_t length)
  281. {
  282. size_t i;
  283. for(i = 0; i < length; i++) {
  284. dest[2 * i] = (unsigned char)src[i];
  285. dest[2 * i + 1] = '\0';
  286. }
  287. }
  288. /*
  289. * Curl_auth_create_ntlm_type1_message()
  290. *
  291. * This is used to generate an NTLM type-1 message ready for sending to the
  292. * recipient using the appropriate compile time crypto API.
  293. *
  294. * Parameters:
  295. *
  296. * data [in] - The session handle.
  297. * userp [in] - The user name in the format User or Domain\User.
  298. * passwdp [in] - The user's password.
  299. * service [in] - The service type such as http, smtp, pop or imap.
  300. * host [in] - The host name.
  301. * ntlm [in/out] - The NTLM data struct being used and modified.
  302. * out [out] - The result storage.
  303. *
  304. * Returns CURLE_OK on success.
  305. */
  306. CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
  307. const char *userp,
  308. const char *passwdp,
  309. const char *service,
  310. const char *hostname,
  311. struct ntlmdata *ntlm,
  312. struct bufref *out)
  313. {
  314. /* NTLM type-1 message structure:
  315. Index Description Content
  316. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  317. (0x4e544c4d53535000)
  318. 8 NTLM Message Type long (0x01000000)
  319. 12 Flags long
  320. (16) Supplied Domain security buffer (*)
  321. (24) Supplied Workstation security buffer (*)
  322. (32) OS Version Structure 8 bytes (*)
  323. (32) (40) Start of data block (*)
  324. (*) -> Optional
  325. */
  326. size_t size;
  327. char *ntlmbuf;
  328. const char *host = ""; /* empty */
  329. const char *domain = ""; /* empty */
  330. size_t hostlen = 0;
  331. size_t domlen = 0;
  332. size_t hostoff = 0;
  333. size_t domoff = hostoff + hostlen; /* This is 0: remember that host and
  334. domain are empty */
  335. (void)data;
  336. (void)userp;
  337. (void)passwdp;
  338. (void)service,
  339. (void)hostname,
  340. /* Clean up any former leftovers and initialise to defaults */
  341. Curl_auth_cleanup_ntlm(ntlm);
  342. #if defined(USE_NTRESPONSES) && \
  343. (defined(USE_NTLM2SESSION) || defined(USE_NTLM_V2))
  344. #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
  345. #else
  346. #define NTLM2FLAG 0
  347. #endif
  348. ntlmbuf = aprintf(NTLMSSP_SIGNATURE "%c"
  349. "\x01%c%c%c" /* 32-bit type = 1 */
  350. "%c%c%c%c" /* 32-bit NTLM flag field */
  351. "%c%c" /* domain length */
  352. "%c%c" /* domain allocated space */
  353. "%c%c" /* domain name offset */
  354. "%c%c" /* 2 zeroes */
  355. "%c%c" /* host length */
  356. "%c%c" /* host allocated space */
  357. "%c%c" /* host name offset */
  358. "%c%c" /* 2 zeroes */
  359. "%s" /* host name */
  360. "%s", /* domain string */
  361. 0, /* trailing zero */
  362. 0, 0, 0, /* part of type-1 long */
  363. LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
  364. NTLMFLAG_REQUEST_TARGET |
  365. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  366. NTLM2FLAG |
  367. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
  368. SHORTPAIR(domlen),
  369. SHORTPAIR(domlen),
  370. SHORTPAIR(domoff),
  371. 0, 0,
  372. SHORTPAIR(hostlen),
  373. SHORTPAIR(hostlen),
  374. SHORTPAIR(hostoff),
  375. 0, 0,
  376. host, /* this is empty */
  377. domain /* this is empty */);
  378. if(!ntlmbuf)
  379. return CURLE_OUT_OF_MEMORY;
  380. /* Initial packet length */
  381. size = 32 + hostlen + domlen;
  382. DEBUG_OUT({
  383. fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
  384. "0x%08.8x ",
  385. LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
  386. NTLMFLAG_REQUEST_TARGET |
  387. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  388. NTLM2FLAG |
  389. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
  390. NTLMFLAG_NEGOTIATE_OEM |
  391. NTLMFLAG_REQUEST_TARGET |
  392. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  393. NTLM2FLAG |
  394. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
  395. ntlm_print_flags(stderr,
  396. NTLMFLAG_NEGOTIATE_OEM |
  397. NTLMFLAG_REQUEST_TARGET |
  398. NTLMFLAG_NEGOTIATE_NTLM_KEY |
  399. NTLM2FLAG |
  400. NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
  401. fprintf(stderr, "\n****\n");
  402. });
  403. Curl_bufref_set(out, ntlmbuf, size, curl_free);
  404. return CURLE_OK;
  405. }
  406. /*
  407. * Curl_auth_create_ntlm_type3_message()
  408. *
  409. * This is used to generate an already encoded NTLM type-3 message ready for
  410. * sending to the recipient using the appropriate compile time crypto API.
  411. *
  412. * Parameters:
  413. *
  414. * data [in] - The session handle.
  415. * userp [in] - The user name in the format User or Domain\User.
  416. * passwdp [in] - The user's password.
  417. * ntlm [in/out] - The NTLM data struct being used and modified.
  418. * out [out] - The result storage.
  419. *
  420. * Returns CURLE_OK on success.
  421. */
  422. CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
  423. const char *userp,
  424. const char *passwdp,
  425. struct ntlmdata *ntlm,
  426. struct bufref *out)
  427. {
  428. /* NTLM type-3 message structure:
  429. Index Description Content
  430. 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
  431. (0x4e544c4d53535000)
  432. 8 NTLM Message Type long (0x03000000)
  433. 12 LM/LMv2 Response security buffer
  434. 20 NTLM/NTLMv2 Response security buffer
  435. 28 Target Name security buffer
  436. 36 User Name security buffer
  437. 44 Workstation Name security buffer
  438. (52) Session Key security buffer (*)
  439. (60) Flags long (*)
  440. (64) OS Version Structure 8 bytes (*)
  441. 52 (64) (72) Start of data block
  442. (*) -> Optional
  443. */
  444. CURLcode result = CURLE_OK;
  445. size_t size;
  446. unsigned char ntlmbuf[NTLM_BUFSIZE];
  447. int lmrespoff;
  448. unsigned char lmresp[24]; /* fixed-size */
  449. #ifdef USE_NTRESPONSES
  450. int ntrespoff;
  451. unsigned int ntresplen = 24;
  452. unsigned char ntresp[24]; /* fixed-size */
  453. unsigned char *ptr_ntresp = &ntresp[0];
  454. unsigned char *ntlmv2resp = NULL;
  455. #endif
  456. bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
  457. char host[HOSTNAME_MAX + 1] = "";
  458. const char *user;
  459. const char *domain = "";
  460. size_t hostoff = 0;
  461. size_t useroff = 0;
  462. size_t domoff = 0;
  463. size_t hostlen = 0;
  464. size_t userlen = 0;
  465. size_t domlen = 0;
  466. user = strchr(userp, '\\');
  467. if(!user)
  468. user = strchr(userp, '/');
  469. if(user) {
  470. domain = userp;
  471. domlen = (user - domain);
  472. user++;
  473. }
  474. else
  475. user = userp;
  476. userlen = strlen(user);
  477. /* Get the machine's un-qualified host name as NTLM doesn't like the fully
  478. qualified domain name */
  479. if(Curl_gethostname(host, sizeof(host))) {
  480. infof(data, "gethostname() failed, continuing without!");
  481. hostlen = 0;
  482. }
  483. else {
  484. hostlen = strlen(host);
  485. }
  486. #if defined(USE_NTRESPONSES) && \
  487. (defined(USE_NTLM2SESSION) || defined(USE_NTLM_V2))
  488. /* We don't support NTLM2 or extended security if we don't have
  489. USE_NTRESPONSES */
  490. if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
  491. # if defined(USE_NTLM_V2)
  492. unsigned char ntbuffer[0x18];
  493. unsigned char entropy[8];
  494. unsigned char ntlmv2hash[0x18];
  495. /* Full NTLM version 2
  496. Although this cannot be negotiated, it is used here if available, as
  497. servers featuring extended security are likely supporting also
  498. NTLMv2. */
  499. result = Curl_rand(data, entropy, 8);
  500. if(result)
  501. return result;
  502. result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
  503. if(result)
  504. return result;
  505. result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
  506. ntbuffer, ntlmv2hash);
  507. if(result)
  508. return result;
  509. /* LMv2 response */
  510. result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
  511. &ntlm->nonce[0], lmresp);
  512. if(result)
  513. return result;
  514. /* NTLMv2 response */
  515. result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
  516. ntlm, &ntlmv2resp, &ntresplen);
  517. if(result)
  518. return result;
  519. ptr_ntresp = ntlmv2resp;
  520. # else /* defined(USE_NTLM_V2) */
  521. unsigned char ntbuffer[0x18];
  522. unsigned char tmp[0x18];
  523. unsigned char md5sum[MD5_DIGEST_LEN];
  524. unsigned char entropy[8];
  525. /* NTLM version 1 with extended security. */
  526. /* Need to create 8 bytes random data */
  527. result = Curl_rand(data, entropy, 8);
  528. if(result)
  529. return result;
  530. /* 8 bytes random data as challenge in lmresp */
  531. memcpy(lmresp, entropy, 8);
  532. /* Pad with zeros */
  533. memset(lmresp + 8, 0, 0x10);
  534. /* Fill tmp with challenge(nonce?) + entropy */
  535. memcpy(tmp, &ntlm->nonce[0], 8);
  536. memcpy(tmp + 8, entropy, 8);
  537. Curl_md5it(md5sum, tmp, 16);
  538. /* We shall only use the first 8 bytes of md5sum, but the des code in
  539. Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
  540. result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
  541. if(result)
  542. return result;
  543. Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
  544. /* End of NTLM2 Session code */
  545. /* NTLM v2 session security is a misnomer because it is not NTLM v2.
  546. It is NTLM v1 using the extended session security that is also
  547. in NTLM v2 */
  548. # endif /* defined(USE_NTLM_V2) */
  549. }
  550. else
  551. #endif
  552. {
  553. #ifdef USE_NTRESPONSES
  554. unsigned char ntbuffer[0x18];
  555. #endif
  556. unsigned char lmbuffer[0x18];
  557. /* NTLM version 1 */
  558. #ifdef USE_NTRESPONSES
  559. result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
  560. if(result)
  561. return result;
  562. Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
  563. #endif
  564. result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
  565. if(result)
  566. return result;
  567. Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
  568. ntlm->flags &= ~NTLMFLAG_NEGOTIATE_NTLM2_KEY;
  569. /* A safer but less compatible alternative is:
  570. * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
  571. * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */
  572. }
  573. if(unicode) {
  574. domlen = domlen * 2;
  575. userlen = userlen * 2;
  576. hostlen = hostlen * 2;
  577. }
  578. lmrespoff = 64; /* size of the message header */
  579. #ifdef USE_NTRESPONSES
  580. ntrespoff = lmrespoff + 0x18;
  581. domoff = ntrespoff + ntresplen;
  582. #else
  583. domoff = lmrespoff + 0x18;
  584. #endif
  585. useroff = domoff + domlen;
  586. hostoff = useroff + userlen;
  587. /* Create the big type-3 message binary blob */
  588. size = msnprintf((char *)ntlmbuf, NTLM_BUFSIZE,
  589. NTLMSSP_SIGNATURE "%c"
  590. "\x03%c%c%c" /* 32-bit type = 3 */
  591. "%c%c" /* LanManager length */
  592. "%c%c" /* LanManager allocated space */
  593. "%c%c" /* LanManager offset */
  594. "%c%c" /* 2 zeroes */
  595. "%c%c" /* NT-response length */
  596. "%c%c" /* NT-response allocated space */
  597. "%c%c" /* NT-response offset */
  598. "%c%c" /* 2 zeroes */
  599. "%c%c" /* domain length */
  600. "%c%c" /* domain allocated space */
  601. "%c%c" /* domain name offset */
  602. "%c%c" /* 2 zeroes */
  603. "%c%c" /* user length */
  604. "%c%c" /* user allocated space */
  605. "%c%c" /* user offset */
  606. "%c%c" /* 2 zeroes */
  607. "%c%c" /* host length */
  608. "%c%c" /* host allocated space */
  609. "%c%c" /* host offset */
  610. "%c%c" /* 2 zeroes */
  611. "%c%c" /* session key length (unknown purpose) */
  612. "%c%c" /* session key allocated space (unknown purpose) */
  613. "%c%c" /* session key offset (unknown purpose) */
  614. "%c%c" /* 2 zeroes */
  615. "%c%c%c%c", /* flags */
  616. /* domain string */
  617. /* user string */
  618. /* host string */
  619. /* LanManager response */
  620. /* NT response */
  621. 0, /* zero termination */
  622. 0, 0, 0, /* type-3 long, the 24 upper bits */
  623. SHORTPAIR(0x18), /* LanManager response length, twice */
  624. SHORTPAIR(0x18),
  625. SHORTPAIR(lmrespoff),
  626. 0x0, 0x0,
  627. #ifdef USE_NTRESPONSES
  628. SHORTPAIR(ntresplen), /* NT-response length, twice */
  629. SHORTPAIR(ntresplen),
  630. SHORTPAIR(ntrespoff),
  631. 0x0, 0x0,
  632. #else
  633. 0x0, 0x0,
  634. 0x0, 0x0,
  635. 0x0, 0x0,
  636. 0x0, 0x0,
  637. #endif
  638. SHORTPAIR(domlen),
  639. SHORTPAIR(domlen),
  640. SHORTPAIR(domoff),
  641. 0x0, 0x0,
  642. SHORTPAIR(userlen),
  643. SHORTPAIR(userlen),
  644. SHORTPAIR(useroff),
  645. 0x0, 0x0,
  646. SHORTPAIR(hostlen),
  647. SHORTPAIR(hostlen),
  648. SHORTPAIR(hostoff),
  649. 0x0, 0x0,
  650. 0x0, 0x0,
  651. 0x0, 0x0,
  652. 0x0, 0x0,
  653. 0x0, 0x0,
  654. LONGQUARTET(ntlm->flags));
  655. DEBUGASSERT(size == 64);
  656. DEBUGASSERT(size == (size_t)lmrespoff);
  657. /* We append the binary hashes */
  658. if(size < (NTLM_BUFSIZE - 0x18)) {
  659. memcpy(&ntlmbuf[size], lmresp, 0x18);
  660. size += 0x18;
  661. }
  662. DEBUG_OUT({
  663. fprintf(stderr, "**** TYPE3 header lmresp=");
  664. ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
  665. });
  666. #ifdef USE_NTRESPONSES
  667. /* ntresplen + size should not be risking an integer overflow here */
  668. if(ntresplen + size > sizeof(ntlmbuf)) {
  669. failf(data, "incoming NTLM message too big");
  670. return CURLE_OUT_OF_MEMORY;
  671. }
  672. DEBUGASSERT(size == (size_t)ntrespoff);
  673. memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
  674. size += ntresplen;
  675. DEBUG_OUT({
  676. fprintf(stderr, "\n ntresp=");
  677. ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
  678. });
  679. free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
  680. #endif
  681. DEBUG_OUT({
  682. fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
  683. LONGQUARTET(ntlm->flags), ntlm->flags);
  684. ntlm_print_flags(stderr, ntlm->flags);
  685. fprintf(stderr, "\n****\n");
  686. });
  687. /* Make sure that the domain, user and host strings fit in the
  688. buffer before we copy them there. */
  689. if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
  690. failf(data, "user + domain + host name too big");
  691. return CURLE_OUT_OF_MEMORY;
  692. }
  693. DEBUGASSERT(size == domoff);
  694. if(unicode)
  695. unicodecpy(&ntlmbuf[size], domain, domlen / 2);
  696. else
  697. memcpy(&ntlmbuf[size], domain, domlen);
  698. size += domlen;
  699. DEBUGASSERT(size == useroff);
  700. if(unicode)
  701. unicodecpy(&ntlmbuf[size], user, userlen / 2);
  702. else
  703. memcpy(&ntlmbuf[size], user, userlen);
  704. size += userlen;
  705. DEBUGASSERT(size == hostoff);
  706. if(unicode)
  707. unicodecpy(&ntlmbuf[size], host, hostlen / 2);
  708. else
  709. memcpy(&ntlmbuf[size], host, hostlen);
  710. size += hostlen;
  711. /* Convert domain, user, and host to ASCII but leave the rest as-is */
  712. result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
  713. size - domoff);
  714. if(result)
  715. return CURLE_CONV_FAILED;
  716. /* Return the binary blob. */
  717. result = Curl_bufref_memdup(out, ntlmbuf, size);
  718. Curl_auth_cleanup_ntlm(ntlm);
  719. return result;
  720. }
  721. /*
  722. * Curl_auth_cleanup_ntlm()
  723. *
  724. * This is used to clean up the NTLM specific data.
  725. *
  726. * Parameters:
  727. *
  728. * ntlm [in/out] - The NTLM data struct being cleaned up.
  729. *
  730. */
  731. void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm)
  732. {
  733. /* Free the target info */
  734. Curl_safefree(ntlm->target_info);
  735. /* Reset any variables */
  736. ntlm->target_info_len = 0;
  737. }
  738. #endif /* USE_NTLM && !USE_WINDOWS_SSPI */