1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller (at) compuserve.com> 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.haxx.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 ***************************************************************************/ 23 24 #include "curl_setup.h" 25 26 #if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY) 27 28 #include "urldata.h" 29 #include "sendf.h" 30 #include "connect.h" 31 #include "strerror.h" 32 #include "timeval.h" 33 #include "socks.h" 34 #include "curl_sspi.h" 35 #include "curl_multibyte.h" 36 #include "warnless.h" 37 #include "strdup.h" 38 /* The last 3 #include files should be in this order */ 39 #include "curl_printf.h" 40 #include "curl_memory.h" 41 #include "memdebug.h" 42 43 /* 44 * Helper sspi error functions. 45 */ 46 static int check_sspi_err(struct connectdata *conn, 47 SECURITY_STATUS status, 48 const char *function) 49 { 50 if(status != SEC_E_OK && 51 status != SEC_I_COMPLETE_AND_CONTINUE && 52 status != SEC_I_COMPLETE_NEEDED && 53 status != SEC_I_CONTINUE_NEEDED) { 54 failf(conn->data, "SSPI error: %s failed: %s", function, 55 Curl_sspi_strerror(conn, status)); 56 return 1; 57 } 58 return 0; 59 } 60 61 /* This is the SSPI-using version of this function */ 62 CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, 63 struct connectdata *conn) 64 { 65 struct Curl_easy *data = conn->data; 66 curl_socket_t sock = conn->sock[sockindex]; 67 CURLcode code; 68 ssize_t actualread; 69 ssize_t written; 70 int result; 71 /* Needs GSS-API authentication */ 72 SECURITY_STATUS status; 73 unsigned long sspi_ret_flags = 0; 74 unsigned char gss_enc; 75 SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3]; 76 SecBufferDesc input_desc, output_desc, wrap_desc; 77 SecPkgContext_Sizes sspi_sizes; 78 CredHandle cred_handle; 79 CtxtHandle sspi_context; 80 PCtxtHandle context_handle = NULL; 81 SecPkgCredentials_Names names; 82 TimeStamp expiry; 83 char *service_name = NULL; 84 unsigned short us_length; 85 unsigned long qop; 86 unsigned char socksreq[4]; /* room for GSS-API exchange header only */ 87 const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ? 88 data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; 89 const size_t service_length = strlen(service); 90 91 /* GSS-API request looks like 92 * +----+------+-----+----------------+ 93 * |VER | MTYP | LEN | TOKEN | 94 * +----+------+----------------------+ 95 * | 1 | 1 | 2 | up to 2^16 - 1 | 96 * +----+------+-----+----------------+ 97 */ 98 99 /* prepare service name */ 100 if(strchr(service, '/')) { 101 service_name = strdup(service); 102 if(!service_name) 103 return CURLE_OUT_OF_MEMORY; 104 } 105 else { 106 service_name = malloc(service_length + 107 strlen(conn->socks_proxy.host.name) + 2); 108 if(!service_name) 109 return CURLE_OUT_OF_MEMORY; 110 snprintf(service_name, service_length + 111 strlen(conn->socks_proxy.host.name) + 2, "%s/%s", 112 service, conn->socks_proxy.host.name); 113 } 114 115 input_desc.cBuffers = 1; 116 input_desc.pBuffers = &sspi_recv_token; 117 input_desc.ulVersion = SECBUFFER_VERSION; 118 119 sspi_recv_token.BufferType = SECBUFFER_TOKEN; 120 sspi_recv_token.cbBuffer = 0; 121 sspi_recv_token.pvBuffer = NULL; 122 123 output_desc.cBuffers = 1; 124 output_desc.pBuffers = &sspi_send_token; 125 output_desc.ulVersion = SECBUFFER_VERSION; 126 127 sspi_send_token.BufferType = SECBUFFER_TOKEN; 128 sspi_send_token.cbBuffer = 0; 129 sspi_send_token.pvBuffer = NULL; 130 131 wrap_desc.cBuffers = 3; 132 wrap_desc.pBuffers = sspi_w_token; 133 wrap_desc.ulVersion = SECBUFFER_VERSION; 134 135 cred_handle.dwLower = 0; 136 cred_handle.dwUpper = 0; 137 138 status = s_pSecFn->AcquireCredentialsHandle(NULL, 139 (TCHAR *) TEXT("Kerberos"), 140 SECPKG_CRED_OUTBOUND, 141 NULL, 142 NULL, 143 NULL, 144 NULL, 145 &cred_handle, 146 &expiry); 147 148 if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) { 149 failf(data, "Failed to acquire credentials."); 150 free(service_name); 151 s_pSecFn->FreeCredentialsHandle(&cred_handle); 152 return CURLE_COULDNT_CONNECT; 153 } 154 155 /* As long as we need to keep sending some context info, and there's no */ 156 /* errors, keep sending it... */ 157 for(;;) { 158 TCHAR *sname; 159 160 sname = Curl_convert_UTF8_to_tchar(service_name); 161 if(!sname) 162 return CURLE_OUT_OF_MEMORY; 163 164 status = s_pSecFn->InitializeSecurityContext(&cred_handle, 165 context_handle, 166 sname, 167 ISC_REQ_MUTUAL_AUTH | 168 ISC_REQ_ALLOCATE_MEMORY | 169 ISC_REQ_CONFIDENTIALITY | 170 ISC_REQ_REPLAY_DETECT, 171 0, 172 SECURITY_NATIVE_DREP, 173 &input_desc, 174 0, 175 &sspi_context, 176 &output_desc, 177 &sspi_ret_flags, 178 &expiry); 179 180 Curl_unicodefree(sname); 181 182 if(sspi_recv_token.pvBuffer) { 183 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); 184 sspi_recv_token.pvBuffer = NULL; 185 sspi_recv_token.cbBuffer = 0; 186 } 187 188 if(check_sspi_err(conn, status, "InitializeSecurityContext")) { 189 free(service_name); 190 s_pSecFn->FreeCredentialsHandle(&cred_handle); 191 s_pSecFn->DeleteSecurityContext(&sspi_context); 192 if(sspi_recv_token.pvBuffer) 193 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); 194 failf(data, "Failed to initialise security context."); 195 return CURLE_COULDNT_CONNECT; 196 } 197 198 if(sspi_send_token.cbBuffer != 0) { 199 socksreq[0] = 1; /* GSS-API subnegotiation version */ 200 socksreq[1] = 1; /* authentication message type */ 201 us_length = htons((short)sspi_send_token.cbBuffer); 202 memcpy(socksreq + 2, &us_length, sizeof(short)); 203 204 code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); 205 if(code || (4 != written)) { 206 failf(data, "Failed to send SSPI authentication request."); 207 free(service_name); 208 if(sspi_send_token.pvBuffer) 209 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); 210 if(sspi_recv_token.pvBuffer) 211 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); 212 s_pSecFn->FreeCredentialsHandle(&cred_handle); 213 s_pSecFn->DeleteSecurityContext(&sspi_context); 214 return CURLE_COULDNT_CONNECT; 215 } 216 217 code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, 218 sspi_send_token.cbBuffer, &written); 219 if(code || (sspi_send_token.cbBuffer != (size_t)written)) { 220 failf(data, "Failed to send SSPI authentication token."); 221 free(service_name); 222 if(sspi_send_token.pvBuffer) 223 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); 224 if(sspi_recv_token.pvBuffer) 225 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); 226 s_pSecFn->FreeCredentialsHandle(&cred_handle); 227 s_pSecFn->DeleteSecurityContext(&sspi_context); 228 return CURLE_COULDNT_CONNECT; 229 } 230 231 } 232 233 if(sspi_send_token.pvBuffer) { 234 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); 235 sspi_send_token.pvBuffer = NULL; 236 } 237 sspi_send_token.cbBuffer = 0; 238 239 if(sspi_recv_token.pvBuffer) { 240 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); 241 sspi_recv_token.pvBuffer = NULL; 242 } 243 sspi_recv_token.cbBuffer = 0; 244 245 if(status != SEC_I_CONTINUE_NEEDED) 246 break; 247 248 /* analyse response */ 249 250 /* GSS-API response looks like 251 * +----+------+-----+----------------+ 252 * |VER | MTYP | LEN | TOKEN | 253 * +----+------+----------------------+ 254 * | 1 | 1 | 2 | up to 2^16 - 1 | 255 * +----+------+-----+----------------+ 256 */ 257 258 result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); 259 if(result || (actualread != 4)) { 260 failf(data, "Failed to receive SSPI authentication response."); 261 free(service_name); 262 s_pSecFn->FreeCredentialsHandle(&cred_handle); 263 s_pSecFn->DeleteSecurityContext(&sspi_context); 264 return CURLE_COULDNT_CONNECT; 265 } 266 267 /* ignore the first (VER) byte */ 268 if(socksreq[1] == 255) { /* status / message type */ 269 failf(data, "User was rejected by the SOCKS5 server (%u %u).", 270 (unsigned int)socksreq[0], (unsigned int)socksreq[1]); 271 free(service_name); 272 s_pSecFn->FreeCredentialsHandle(&cred_handle); 273 s_pSecFn->DeleteSecurityContext(&sspi_context); 274 return CURLE_COULDNT_CONNECT; 275 } 276 277 if(socksreq[1] != 1) { /* status / messgae type */ 278 failf(data, "Invalid SSPI authentication response type (%u %u).", 279 (unsigned int)socksreq[0], (unsigned int)socksreq[1]); 280 free(service_name); 281 s_pSecFn->FreeCredentialsHandle(&cred_handle); 282 s_pSecFn->DeleteSecurityContext(&sspi_context); 283 return CURLE_COULDNT_CONNECT; 284 } 285 286 memcpy(&us_length, socksreq + 2, sizeof(short)); 287 us_length = ntohs(us_length); 288 289 sspi_recv_token.cbBuffer = us_length; 290 sspi_recv_token.pvBuffer = malloc(us_length); 291 292 if(!sspi_recv_token.pvBuffer) { 293 free(service_name); 294 s_pSecFn->FreeCredentialsHandle(&cred_handle); 295 s_pSecFn->DeleteSecurityContext(&sspi_context); 296 return CURLE_OUT_OF_MEMORY; 297 } 298 result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer, 299 sspi_recv_token.cbBuffer, &actualread); 300 301 if(result || (actualread != us_length)) { 302 failf(data, "Failed to receive SSPI authentication token."); 303 free(service_name); 304 if(sspi_recv_token.pvBuffer) 305 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); 306 s_pSecFn->FreeCredentialsHandle(&cred_handle); 307 s_pSecFn->DeleteSecurityContext(&sspi_context); 308 return CURLE_COULDNT_CONNECT; 309 } 310 311 context_handle = &sspi_context; 312 } 313 314 free(service_name); 315 316 /* Everything is good so far, user was authenticated! */ 317 status = s_pSecFn->QueryCredentialsAttributes(&cred_handle, 318 SECPKG_CRED_ATTR_NAMES, 319 &names); 320 s_pSecFn->FreeCredentialsHandle(&cred_handle); 321 if(check_sspi_err(conn, status, "QueryCredentialAttributes")) { 322 s_pSecFn->DeleteSecurityContext(&sspi_context); 323 s_pSecFn->FreeContextBuffer(names.sUserName); 324 failf(data, "Failed to determine user name."); 325 return CURLE_COULDNT_CONNECT; 326 } 327 infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n", 328 names.sUserName); 329 s_pSecFn->FreeContextBuffer(names.sUserName); 330 331 /* Do encryption */ 332 socksreq[0] = 1; /* GSS-API subnegotiation version */ 333 socksreq[1] = 2; /* encryption message type */ 334 335 gss_enc = 0; /* no data protection */ 336 /* do confidentiality protection if supported */ 337 if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY) 338 gss_enc = 2; 339 /* else do integrity protection */ 340 else if(sspi_ret_flags & ISC_REQ_INTEGRITY) 341 gss_enc = 1; 342 343 infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", 344 (gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") ); 345 /* force to no data protection, avoid encryption/decryption for now */ 346 gss_enc = 0; 347 /* 348 * Sending the encryption type in clear seems wrong. It should be 349 * protected with gss_seal()/gss_wrap(). See RFC1961 extract below 350 * The NEC reference implementations on which this is based is 351 * therefore at fault 352 * 353 * +------+------+------+.......................+ 354 * + ver | mtyp | len | token | 355 * +------+------+------+.......................+ 356 * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | 357 * +------+------+------+.......................+ 358 * 359 * Where: 360 * 361 * - "ver" is the protocol version number, here 1 to represent the 362 * first version of the SOCKS/GSS-API protocol 363 * 364 * - "mtyp" is the message type, here 2 to represent a protection 365 * -level negotiation message 366 * 367 * - "len" is the length of the "token" field in octets 368 * 369 * - "token" is the GSS-API encapsulated protection level 370 * 371 * The token is produced by encapsulating an octet containing the 372 * required protection level using gss_seal()/gss_wrap() with conf_req 373 * set to FALSE. The token is verified using gss_unseal()/ 374 * gss_unwrap(). 375 * 376 */ 377 378 if(data->set.socks5_gssapi_nec) { 379 us_length = htons((short)1); 380 memcpy(socksreq + 2, &us_length, sizeof(short)); 381 } 382 else { 383 status = s_pSecFn->QueryContextAttributes(&sspi_context, 384 SECPKG_ATTR_SIZES, 385 &sspi_sizes); 386 if(check_sspi_err(conn, status, "QueryContextAttributes")) { 387 s_pSecFn->DeleteSecurityContext(&sspi_context); 388 failf(data, "Failed to query security context attributes."); 389 return CURLE_COULDNT_CONNECT; 390 } 391 392 sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer; 393 sspi_w_token[0].BufferType = SECBUFFER_TOKEN; 394 sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer); 395 396 if(!sspi_w_token[0].pvBuffer) { 397 s_pSecFn->DeleteSecurityContext(&sspi_context); 398 return CURLE_OUT_OF_MEMORY; 399 } 400 401 sspi_w_token[1].cbBuffer = 1; 402 sspi_w_token[1].pvBuffer = malloc(1); 403 if(!sspi_w_token[1].pvBuffer) { 404 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 405 s_pSecFn->DeleteSecurityContext(&sspi_context); 406 return CURLE_OUT_OF_MEMORY; 407 } 408 409 memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1); 410 sspi_w_token[2].BufferType = SECBUFFER_PADDING; 411 sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize; 412 sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize); 413 if(!sspi_w_token[2].pvBuffer) { 414 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 415 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); 416 s_pSecFn->DeleteSecurityContext(&sspi_context); 417 return CURLE_OUT_OF_MEMORY; 418 } 419 status = s_pSecFn->EncryptMessage(&sspi_context, 420 KERB_WRAP_NO_ENCRYPT, 421 &wrap_desc, 422 0); 423 if(check_sspi_err(conn, status, "EncryptMessage")) { 424 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 425 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); 426 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); 427 s_pSecFn->DeleteSecurityContext(&sspi_context); 428 failf(data, "Failed to query security context attributes."); 429 return CURLE_COULDNT_CONNECT; 430 } 431 sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer 432 + sspi_w_token[1].cbBuffer 433 + sspi_w_token[2].cbBuffer; 434 sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer); 435 if(!sspi_send_token.pvBuffer) { 436 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 437 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); 438 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); 439 s_pSecFn->DeleteSecurityContext(&sspi_context); 440 return CURLE_OUT_OF_MEMORY; 441 } 442 443 memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer, 444 sspi_w_token[0].cbBuffer); 445 memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer, 446 sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); 447 memcpy((PUCHAR) sspi_send_token.pvBuffer 448 + sspi_w_token[0].cbBuffer 449 + sspi_w_token[1].cbBuffer, 450 sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer); 451 452 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 453 sspi_w_token[0].pvBuffer = NULL; 454 sspi_w_token[0].cbBuffer = 0; 455 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); 456 sspi_w_token[1].pvBuffer = NULL; 457 sspi_w_token[1].cbBuffer = 0; 458 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); 459 sspi_w_token[2].pvBuffer = NULL; 460 sspi_w_token[2].cbBuffer = 0; 461 462 us_length = htons((short)sspi_send_token.cbBuffer); 463 memcpy(socksreq + 2, &us_length, sizeof(short)); 464 } 465 466 code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); 467 if(code || (4 != written)) { 468 failf(data, "Failed to send SSPI encryption request."); 469 if(sspi_send_token.pvBuffer) 470 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); 471 s_pSecFn->DeleteSecurityContext(&sspi_context); 472 return CURLE_COULDNT_CONNECT; 473 } 474 475 if(data->set.socks5_gssapi_nec) { 476 memcpy(socksreq, &gss_enc, 1); 477 code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); 478 if(code || (1 != written)) { 479 failf(data, "Failed to send SSPI encryption type."); 480 s_pSecFn->DeleteSecurityContext(&sspi_context); 481 return CURLE_COULDNT_CONNECT; 482 } 483 } 484 else { 485 code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, 486 sspi_send_token.cbBuffer, &written); 487 if(code || (sspi_send_token.cbBuffer != (size_t)written)) { 488 failf(data, "Failed to send SSPI encryption type."); 489 if(sspi_send_token.pvBuffer) 490 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); 491 s_pSecFn->DeleteSecurityContext(&sspi_context); 492 return CURLE_COULDNT_CONNECT; 493 } 494 if(sspi_send_token.pvBuffer) 495 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); 496 } 497 498 result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread); 499 if(result || (actualread != 4)) { 500 failf(data, "Failed to receive SSPI encryption response."); 501 s_pSecFn->DeleteSecurityContext(&sspi_context); 502 return CURLE_COULDNT_CONNECT; 503 } 504 505 /* ignore the first (VER) byte */ 506 if(socksreq[1] == 255) { /* status / message type */ 507 failf(data, "User was rejected by the SOCKS5 server (%u %u).", 508 (unsigned int)socksreq[0], (unsigned int)socksreq[1]); 509 s_pSecFn->DeleteSecurityContext(&sspi_context); 510 return CURLE_COULDNT_CONNECT; 511 } 512 513 if(socksreq[1] != 2) { /* status / message type */ 514 failf(data, "Invalid SSPI encryption response type (%u %u).", 515 (unsigned int)socksreq[0], (unsigned int)socksreq[1]); 516 s_pSecFn->DeleteSecurityContext(&sspi_context); 517 return CURLE_COULDNT_CONNECT; 518 } 519 520 memcpy(&us_length, socksreq + 2, sizeof(short)); 521 us_length = ntohs(us_length); 522 523 sspi_w_token[0].cbBuffer = us_length; 524 sspi_w_token[0].pvBuffer = malloc(us_length); 525 if(!sspi_w_token[0].pvBuffer) { 526 s_pSecFn->DeleteSecurityContext(&sspi_context); 527 return CURLE_OUT_OF_MEMORY; 528 } 529 530 result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer, 531 sspi_w_token[0].cbBuffer, &actualread); 532 533 if(result || (actualread != us_length)) { 534 failf(data, "Failed to receive SSPI encryption type."); 535 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 536 s_pSecFn->DeleteSecurityContext(&sspi_context); 537 return CURLE_COULDNT_CONNECT; 538 } 539 540 541 if(!data->set.socks5_gssapi_nec) { 542 wrap_desc.cBuffers = 2; 543 sspi_w_token[0].BufferType = SECBUFFER_STREAM; 544 sspi_w_token[1].BufferType = SECBUFFER_DATA; 545 sspi_w_token[1].cbBuffer = 0; 546 sspi_w_token[1].pvBuffer = NULL; 547 548 status = s_pSecFn->DecryptMessage(&sspi_context, 549 &wrap_desc, 550 0, 551 &qop); 552 553 if(check_sspi_err(conn, status, "DecryptMessage")) { 554 if(sspi_w_token[0].pvBuffer) 555 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 556 if(sspi_w_token[1].pvBuffer) 557 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); 558 s_pSecFn->DeleteSecurityContext(&sspi_context); 559 failf(data, "Failed to query security context attributes."); 560 return CURLE_COULDNT_CONNECT; 561 } 562 563 if(sspi_w_token[1].cbBuffer != 1) { 564 failf(data, "Invalid SSPI encryption response length (%lu).", 565 (unsigned long)sspi_w_token[1].cbBuffer); 566 if(sspi_w_token[0].pvBuffer) 567 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 568 if(sspi_w_token[1].pvBuffer) 569 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); 570 s_pSecFn->DeleteSecurityContext(&sspi_context); 571 return CURLE_COULDNT_CONNECT; 572 } 573 574 memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); 575 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 576 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); 577 } 578 else { 579 if(sspi_w_token[0].cbBuffer != 1) { 580 failf(data, "Invalid SSPI encryption response length (%lu).", 581 (unsigned long)sspi_w_token[0].cbBuffer); 582 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 583 s_pSecFn->DeleteSecurityContext(&sspi_context); 584 return CURLE_COULDNT_CONNECT; 585 } 586 memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer); 587 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); 588 } 589 590 infof(data, "SOCKS5 access with%s protection granted.\n", 591 (socksreq[0] == 0)?"out GSS-API data": 592 ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); 593 594 /* For later use if encryption is required 595 conn->socks5_gssapi_enctype = socksreq[0]; 596 if(socksreq[0] != 0) 597 conn->socks5_sspi_context = sspi_context; 598 else { 599 s_pSecFn->DeleteSecurityContext(&sspi_context); 600 conn->socks5_sspi_context = sspi_context; 601 } 602 */ 603 return CURLE_OK; 604 } 605 #endif 606