socks_sspi.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
  9. * Copyright (C) Markus Moeller, <[email protected]>
  10. *
  11. * This software is licensed as described in the file COPYING, which
  12. * you should have received as part of this distribution. The terms
  13. * are also available at https://curl.se/docs/copyright.html.
  14. *
  15. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  16. * copies of the Software, and permit persons to whom the Software is
  17. * furnished to do so, under the terms of the COPYING file.
  18. *
  19. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  20. * KIND, either express or implied.
  21. *
  22. * SPDX-License-Identifier: curl
  23. *
  24. ***************************************************************************/
  25. #include "curl_setup.h"
  26. #if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY)
  27. #include "urldata.h"
  28. #include "sendf.h"
  29. #include "cfilters.h"
  30. #include "connect.h"
  31. #include "strerror.h"
  32. #include "curlx/timeval.h"
  33. #include "socks.h"
  34. #include "curl_sspi.h"
  35. #include "curlx/multibyte.h"
  36. #include "curlx/warnless.h"
  37. /* The last 2 #include files should be in this order */
  38. #include "curl_memory.h"
  39. #include "memdebug.h"
  40. /*
  41. * Helper sspi error functions.
  42. */
  43. static int check_sspi_err(struct Curl_easy *data,
  44. SECURITY_STATUS status,
  45. const char *function)
  46. {
  47. if(status != SEC_E_OK &&
  48. status != SEC_I_COMPLETE_AND_CONTINUE &&
  49. status != SEC_I_COMPLETE_NEEDED &&
  50. status != SEC_I_CONTINUE_NEEDED) {
  51. char buffer[STRERROR_LEN];
  52. failf(data, "SSPI error: %s failed: %s", function,
  53. Curl_sspi_strerror(status, buffer, sizeof(buffer)));
  54. return 1;
  55. }
  56. return 0;
  57. }
  58. /* This is the SSPI-using version of this function */
  59. CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
  60. struct Curl_easy *data)
  61. {
  62. struct connectdata *conn = cf->conn;
  63. curl_socket_t sock = conn->sock[cf->sockindex];
  64. CURLcode code;
  65. size_t actualread;
  66. size_t written;
  67. CURLcode result;
  68. /* Needs GSS-API authentication */
  69. SECURITY_STATUS status;
  70. unsigned long sspi_ret_flags = 0;
  71. unsigned char gss_enc;
  72. SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
  73. SecBufferDesc input_desc, output_desc, wrap_desc;
  74. SecPkgContext_Sizes sspi_sizes;
  75. CredHandle cred_handle;
  76. CtxtHandle sspi_context;
  77. PCtxtHandle context_handle = NULL;
  78. SecPkgCredentials_Names names;
  79. char *service_name = NULL;
  80. unsigned short us_length;
  81. unsigned long qop;
  82. unsigned char socksreq[4]; /* room for GSS-API exchange header only */
  83. const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
  84. data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
  85. char *etbuf;
  86. size_t etbuf_size;
  87. /* GSS-API request looks like
  88. * +----+------+-----+----------------+
  89. * |VER | MTYP | LEN | TOKEN |
  90. * +----+------+----------------------+
  91. * | 1 | 1 | 2 | up to 2^16 - 1 |
  92. * +----+------+-----+----------------+
  93. */
  94. /* prepare service name */
  95. if(strchr(service, '/'))
  96. service_name = strdup(service);
  97. else
  98. service_name = curl_maprintf("%s/%s",
  99. service, conn->socks_proxy.host.name);
  100. if(!service_name)
  101. return CURLE_OUT_OF_MEMORY;
  102. input_desc.cBuffers = 1;
  103. input_desc.pBuffers = &sspi_recv_token;
  104. input_desc.ulVersion = SECBUFFER_VERSION;
  105. sspi_recv_token.BufferType = SECBUFFER_TOKEN;
  106. sspi_recv_token.cbBuffer = 0;
  107. sspi_recv_token.pvBuffer = NULL;
  108. output_desc.cBuffers = 1;
  109. output_desc.pBuffers = &sspi_send_token;
  110. output_desc.ulVersion = SECBUFFER_VERSION;
  111. sspi_send_token.BufferType = SECBUFFER_TOKEN;
  112. sspi_send_token.cbBuffer = 0;
  113. sspi_send_token.pvBuffer = NULL;
  114. sspi_w_token[0].pvBuffer =
  115. sspi_w_token[1].pvBuffer =
  116. sspi_w_token[2].pvBuffer = NULL;
  117. wrap_desc.cBuffers = 3;
  118. wrap_desc.pBuffers = sspi_w_token;
  119. wrap_desc.ulVersion = SECBUFFER_VERSION;
  120. memset(&cred_handle, 0, sizeof(cred_handle));
  121. memset(&sspi_context, 0, sizeof(sspi_context));
  122. names.sUserName = NULL;
  123. etbuf = NULL;
  124. etbuf_size = 0;
  125. status =
  126. Curl_pSecFn->AcquireCredentialsHandle(NULL,
  127. (TCHAR *)CURL_UNCONST(TEXT("Kerberos")),
  128. SECPKG_CRED_OUTBOUND,
  129. NULL, NULL, NULL, NULL,
  130. &cred_handle, NULL);
  131. if(check_sspi_err(data, status, "AcquireCredentialsHandle")) {
  132. failf(data, "Failed to acquire credentials.");
  133. result = CURLE_COULDNT_CONNECT;
  134. goto error;
  135. }
  136. (void)curlx_nonblock(sock, FALSE);
  137. /* As long as we need to keep sending some context info, and there is no */
  138. /* errors, keep sending it... */
  139. for(;;) {
  140. TCHAR *sname;
  141. sname = curlx_convert_UTF8_to_tchar(service_name);
  142. if(!sname) {
  143. result = CURLE_OUT_OF_MEMORY;
  144. goto error;
  145. }
  146. status =
  147. Curl_pSecFn->InitializeSecurityContext(&cred_handle, context_handle,
  148. sname,
  149. ISC_REQ_MUTUAL_AUTH |
  150. ISC_REQ_ALLOCATE_MEMORY |
  151. ISC_REQ_CONFIDENTIALITY |
  152. ISC_REQ_REPLAY_DETECT,
  153. 0, SECURITY_NATIVE_DREP,
  154. &input_desc, 0,
  155. &sspi_context,
  156. &output_desc,
  157. &sspi_ret_flags, NULL);
  158. curlx_unicodefree(sname);
  159. Curl_safefree(sspi_recv_token.pvBuffer);
  160. sspi_recv_token.cbBuffer = 0;
  161. if(check_sspi_err(data, status, "InitializeSecurityContext")) {
  162. failf(data, "Failed to initialise security context.");
  163. result = CURLE_COULDNT_CONNECT;
  164. goto error;
  165. }
  166. if(sspi_send_token.cbBuffer) {
  167. socksreq[0] = 1; /* GSS-API subnegotiation version */
  168. socksreq[1] = 1; /* authentication message type */
  169. if(sspi_send_token.cbBuffer > 0xffff) {
  170. /* needs to fit in an unsigned 16 bit field */
  171. result = CURLE_COULDNT_CONNECT;
  172. goto error;
  173. }
  174. us_length = htons((unsigned short)sspi_send_token.cbBuffer);
  175. memcpy(socksreq + 2, &us_length, sizeof(short));
  176. code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
  177. &written);
  178. if(code || (written != 4)) {
  179. failf(data, "Failed to send SSPI authentication request.");
  180. result = CURLE_COULDNT_CONNECT;
  181. goto error;
  182. }
  183. code = Curl_conn_cf_send(cf->next, data,
  184. (char *)sspi_send_token.pvBuffer,
  185. sspi_send_token.cbBuffer, FALSE, &written);
  186. if(code || (sspi_send_token.cbBuffer != written)) {
  187. failf(data, "Failed to send SSPI authentication token.");
  188. result = CURLE_COULDNT_CONNECT;
  189. goto error;
  190. }
  191. }
  192. if(sspi_send_token.pvBuffer) {
  193. Curl_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
  194. sspi_send_token.pvBuffer = NULL;
  195. }
  196. sspi_send_token.cbBuffer = 0;
  197. Curl_safefree(sspi_recv_token.pvBuffer);
  198. sspi_recv_token.cbBuffer = 0;
  199. if(status != SEC_I_CONTINUE_NEEDED)
  200. break;
  201. /* analyse response */
  202. /* GSS-API response looks like
  203. * +----+------+-----+----------------+
  204. * |VER | MTYP | LEN | TOKEN |
  205. * +----+------+----------------------+
  206. * | 1 | 1 | 2 | up to 2^16 - 1 |
  207. * +----+------+-----+----------------+
  208. */
  209. result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
  210. if(result || (actualread != 4)) {
  211. failf(data, "Failed to receive SSPI authentication response.");
  212. if(!result)
  213. result = CURLE_COULDNT_CONNECT;
  214. goto error;
  215. }
  216. /* ignore the first (VER) byte */
  217. if(socksreq[1] == 255) { /* status / message type */
  218. failf(data, "User was rejected by the SOCKS5 server (%u %u).",
  219. (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
  220. result = CURLE_COULDNT_CONNECT;
  221. goto error;
  222. }
  223. if(socksreq[1] != 1) { /* status / message type */
  224. failf(data, "Invalid SSPI authentication response type (%u %u).",
  225. (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
  226. result = CURLE_COULDNT_CONNECT;
  227. goto error;
  228. }
  229. memcpy(&us_length, socksreq + 2, sizeof(short));
  230. us_length = ntohs(us_length);
  231. sspi_recv_token.cbBuffer = us_length;
  232. sspi_recv_token.pvBuffer = malloc(us_length);
  233. if(!sspi_recv_token.pvBuffer) {
  234. result = CURLE_OUT_OF_MEMORY;
  235. goto error;
  236. }
  237. result = Curl_blockread_all(cf, data, (char *)sspi_recv_token.pvBuffer,
  238. sspi_recv_token.cbBuffer, &actualread);
  239. if(result || (actualread != us_length)) {
  240. failf(data, "Failed to receive SSPI authentication token.");
  241. if(!result)
  242. result = CURLE_COULDNT_CONNECT;
  243. goto error;
  244. }
  245. context_handle = &sspi_context;
  246. }
  247. Curl_safefree(service_name);
  248. /* Everything is good so far, user was authenticated! */
  249. status = Curl_pSecFn->QueryCredentialsAttributes(&cred_handle,
  250. SECPKG_CRED_ATTR_NAMES,
  251. &names);
  252. if(check_sspi_err(data, status, "QueryCredentialAttributes")) {
  253. failf(data, "Failed to determine username.");
  254. result = CURLE_COULDNT_CONNECT;
  255. goto error;
  256. }
  257. else {
  258. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  259. char *user_utf8 = curlx_convert_tchar_to_UTF8(names.sUserName);
  260. infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
  261. (user_utf8 ? user_utf8 : "(unknown)"));
  262. curlx_unicodefree(user_utf8);
  263. #endif
  264. Curl_pSecFn->FreeContextBuffer(names.sUserName);
  265. names.sUserName = NULL;
  266. }
  267. /* Do encryption */
  268. socksreq[0] = 1; /* GSS-API subnegotiation version */
  269. socksreq[1] = 2; /* encryption message type */
  270. gss_enc = 0; /* no data protection */
  271. /* do confidentiality protection if supported */
  272. if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
  273. gss_enc = 2;
  274. /* else do integrity protection */
  275. else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
  276. gss_enc = 1;
  277. infof(data, "SOCKS5 server supports GSS-API %s data protection.",
  278. (gss_enc == 0) ? "no" :
  279. ((gss_enc == 1) ? "integrity":"confidentiality") );
  280. /*
  281. * Sending the encryption type in clear seems wrong. It should be
  282. * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
  283. * The NEC reference implementations on which this is based is
  284. * therefore at fault
  285. *
  286. * +------+------+------+.......................+
  287. * + ver | mtyp | len | token |
  288. * +------+------+------+.......................+
  289. * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
  290. * +------+------+------+.......................+
  291. *
  292. * Where:
  293. *
  294. * - "ver" is the protocol version number, here 1 to represent the
  295. * first version of the SOCKS/GSS-API protocol
  296. *
  297. * - "mtyp" is the message type, here 2 to represent a protection
  298. * -level negotiation message
  299. *
  300. * - "len" is the length of the "token" field in octets
  301. *
  302. * - "token" is the GSS-API encapsulated protection level
  303. *
  304. * The token is produced by encapsulating an octet containing the
  305. * required protection level using gss_seal()/gss_wrap() with conf_req
  306. * set to FALSE. The token is verified using gss_unseal()/
  307. * gss_unwrap().
  308. *
  309. */
  310. if(data->set.socks5_gssapi_nec) {
  311. us_length = htons((unsigned short)1);
  312. memcpy(socksreq + 2, &us_length, sizeof(short));
  313. }
  314. else {
  315. status = Curl_pSecFn->QueryContextAttributes(&sspi_context,
  316. SECPKG_ATTR_SIZES,
  317. &sspi_sizes);
  318. if(check_sspi_err(data, status, "QueryContextAttributes")) {
  319. failf(data, "Failed to query security context attributes.");
  320. result = CURLE_COULDNT_CONNECT;
  321. goto error;
  322. }
  323. sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
  324. sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
  325. sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer);
  326. if(!sspi_w_token[0].pvBuffer) {
  327. result = CURLE_OUT_OF_MEMORY;
  328. goto error;
  329. }
  330. sspi_w_token[1].cbBuffer = 1;
  331. sspi_w_token[1].pvBuffer = malloc(1);
  332. if(!sspi_w_token[1].pvBuffer) {
  333. result = CURLE_OUT_OF_MEMORY;
  334. goto error;
  335. }
  336. memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1);
  337. sspi_w_token[2].BufferType = SECBUFFER_PADDING;
  338. sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
  339. sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize);
  340. if(!sspi_w_token[2].pvBuffer) {
  341. result = CURLE_OUT_OF_MEMORY;
  342. goto error;
  343. }
  344. status = Curl_pSecFn->EncryptMessage(&sspi_context,
  345. KERB_WRAP_NO_ENCRYPT,
  346. &wrap_desc, 0);
  347. if(check_sspi_err(data, status, "EncryptMessage")) {
  348. failf(data, "Failed to query security context attributes.");
  349. result = CURLE_COULDNT_CONNECT;
  350. goto error;
  351. }
  352. etbuf_size = sspi_w_token[0].cbBuffer + sspi_w_token[1].cbBuffer +
  353. sspi_w_token[2].cbBuffer;
  354. if(etbuf_size > 0xffff) {
  355. /* needs to fit in an unsigned 16 bit field */
  356. result = CURLE_COULDNT_CONNECT;
  357. goto error;
  358. }
  359. etbuf = malloc(etbuf_size);
  360. if(!etbuf) {
  361. result = CURLE_OUT_OF_MEMORY;
  362. goto error;
  363. }
  364. memcpy(etbuf, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
  365. memcpy(etbuf + sspi_w_token[0].cbBuffer,
  366. sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
  367. memcpy(etbuf + sspi_w_token[0].cbBuffer + sspi_w_token[1].cbBuffer,
  368. sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
  369. Curl_safefree(sspi_w_token[0].pvBuffer);
  370. sspi_w_token[0].cbBuffer = 0;
  371. Curl_safefree(sspi_w_token[1].pvBuffer);
  372. sspi_w_token[1].cbBuffer = 0;
  373. Curl_safefree(sspi_w_token[2].pvBuffer);
  374. sspi_w_token[2].cbBuffer = 0;
  375. us_length = htons((unsigned short)etbuf_size);
  376. memcpy(socksreq + 2, &us_length, sizeof(short));
  377. }
  378. code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE,
  379. &written);
  380. if(code || (written != 4)) {
  381. failf(data, "Failed to send SSPI encryption request.");
  382. result = CURLE_COULDNT_CONNECT;
  383. goto error;
  384. }
  385. if(data->set.socks5_gssapi_nec) {
  386. memcpy(socksreq, &gss_enc, 1);
  387. code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE,
  388. &written);
  389. if(code || (written != 1)) {
  390. failf(data, "Failed to send SSPI encryption type.");
  391. result = CURLE_COULDNT_CONNECT;
  392. goto error;
  393. }
  394. }
  395. else {
  396. code = Curl_conn_cf_send(cf->next, data, etbuf, etbuf_size,
  397. FALSE, &written);
  398. if(code || (etbuf_size != written)) {
  399. failf(data, "Failed to send SSPI encryption type.");
  400. result = CURLE_COULDNT_CONNECT;
  401. goto error;
  402. }
  403. Curl_safefree(etbuf);
  404. }
  405. result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
  406. if(result || (actualread != 4)) {
  407. failf(data, "Failed to receive SSPI encryption response.");
  408. if(!result)
  409. result = CURLE_COULDNT_CONNECT;
  410. goto error;
  411. }
  412. /* ignore the first (VER) byte */
  413. if(socksreq[1] == 255) { /* status / message type */
  414. failf(data, "User was rejected by the SOCKS5 server (%u %u).",
  415. (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
  416. result = CURLE_COULDNT_CONNECT;
  417. goto error;
  418. }
  419. if(socksreq[1] != 2) { /* status / message type */
  420. failf(data, "Invalid SSPI encryption response type (%u %u).",
  421. (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
  422. result = CURLE_COULDNT_CONNECT;
  423. goto error;
  424. }
  425. memcpy(&us_length, socksreq + 2, sizeof(short));
  426. us_length = ntohs(us_length);
  427. sspi_w_token[0].cbBuffer = us_length;
  428. sspi_w_token[0].pvBuffer = malloc(us_length);
  429. if(!sspi_w_token[0].pvBuffer) {
  430. result = CURLE_OUT_OF_MEMORY;
  431. goto error;
  432. }
  433. result = Curl_blockread_all(cf, data, (char *)sspi_w_token[0].pvBuffer,
  434. sspi_w_token[0].cbBuffer, &actualread);
  435. if(result || (actualread != us_length)) {
  436. failf(data, "Failed to receive SSPI encryption type.");
  437. if(!result)
  438. result = CURLE_COULDNT_CONNECT;
  439. goto error;
  440. }
  441. if(!data->set.socks5_gssapi_nec) {
  442. wrap_desc.cBuffers = 2;
  443. sspi_w_token[0].BufferType = SECBUFFER_STREAM;
  444. sspi_w_token[1].BufferType = SECBUFFER_DATA;
  445. sspi_w_token[1].cbBuffer = 0;
  446. sspi_w_token[1].pvBuffer = NULL;
  447. status = Curl_pSecFn->DecryptMessage(&sspi_context, &wrap_desc,
  448. 0, &qop);
  449. /* since sspi_w_token[1].pvBuffer is allocated by the SSPI in this case, it
  450. must be freed in this block using FreeContextBuffer() instead of
  451. potentially in error cleanup using free(). */
  452. if(check_sspi_err(data, status, "DecryptMessage")) {
  453. failf(data, "Failed to query security context attributes.");
  454. if(sspi_w_token[1].pvBuffer) {
  455. Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
  456. sspi_w_token[1].pvBuffer = NULL;
  457. }
  458. result = CURLE_COULDNT_CONNECT;
  459. goto error;
  460. }
  461. if(sspi_w_token[1].cbBuffer != 1) {
  462. failf(data, "Invalid SSPI encryption response length (%lu).",
  463. (unsigned long)sspi_w_token[1].cbBuffer);
  464. if(sspi_w_token[1].pvBuffer) {
  465. Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
  466. sspi_w_token[1].pvBuffer = NULL;
  467. }
  468. result = CURLE_COULDNT_CONNECT;
  469. goto error;
  470. }
  471. memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
  472. Curl_safefree(sspi_w_token[0].pvBuffer);
  473. sspi_w_token[0].cbBuffer = 0;
  474. Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
  475. sspi_w_token[1].pvBuffer = NULL;
  476. sspi_w_token[1].cbBuffer = 0;
  477. }
  478. else {
  479. if(sspi_w_token[0].cbBuffer != 1) {
  480. failf(data, "Invalid SSPI encryption response length (%lu).",
  481. (unsigned long)sspi_w_token[0].cbBuffer);
  482. result = CURLE_COULDNT_CONNECT;
  483. goto error;
  484. }
  485. memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
  486. Curl_safefree(sspi_w_token[0].pvBuffer);
  487. sspi_w_token[0].cbBuffer = 0;
  488. }
  489. (void)curlx_nonblock(sock, TRUE);
  490. infof(data, "SOCKS5 access with%s protection granted BUT NOT USED.",
  491. (socksreq[0] == 0) ? "out GSS-API data":
  492. ((socksreq[0] == 1) ? " GSS-API integrity" :
  493. " GSS-API confidentiality"));
  494. /* For later use if encryption is required
  495. conn->socks5_gssapi_enctype = socksreq[0];
  496. if(socksreq[0] != 0)
  497. conn->socks5_sspi_context = sspi_context;
  498. else {
  499. Curl_pSecFn->DeleteSecurityContext(&sspi_context);
  500. conn->socks5_sspi_context = sspi_context;
  501. }
  502. */
  503. Curl_pSecFn->DeleteSecurityContext(&sspi_context);
  504. Curl_pSecFn->FreeCredentialsHandle(&cred_handle);
  505. return CURLE_OK;
  506. error:
  507. (void)curlx_nonblock(sock, TRUE);
  508. free(service_name);
  509. Curl_pSecFn->DeleteSecurityContext(&sspi_context);
  510. Curl_pSecFn->FreeCredentialsHandle(&cred_handle);
  511. free(sspi_recv_token.pvBuffer);
  512. if(sspi_send_token.pvBuffer)
  513. Curl_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
  514. if(names.sUserName)
  515. Curl_pSecFn->FreeContextBuffer(names.sUserName);
  516. if(sspi_w_token[0].pvBuffer)
  517. Curl_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
  518. if(sspi_w_token[1].pvBuffer)
  519. Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
  520. if(sspi_w_token[2].pvBuffer)
  521. Curl_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
  522. free(etbuf);
  523. return result;
  524. }
  525. #endif