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