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