1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, 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.haxx.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 23 #include "curl_setup.h" 24 25 #ifdef USE_GSKIT 26 27 #include <gskssl.h> 28 #include <qsoasync.h> 29 30 /* Some symbols are undefined/unsupported on OS400 versions < V7R1. */ 31 #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST 32 #define GSK_SSL_EXTN_SERVERNAME_REQUEST 230 33 #endif 34 35 #ifndef GSK_TLSV10_CIPHER_SPECS 36 #define GSK_TLSV10_CIPHER_SPECS 236 37 #endif 38 39 #ifndef GSK_TLSV11_CIPHER_SPECS 40 #define GSK_TLSV11_CIPHER_SPECS 237 41 #endif 42 43 #ifndef GSK_TLSV12_CIPHER_SPECS 44 #define GSK_TLSV12_CIPHER_SPECS 238 45 #endif 46 47 #ifndef GSK_PROTOCOL_TLSV11 48 #define GSK_PROTOCOL_TLSV11 437 49 #endif 50 51 #ifndef GSK_PROTOCOL_TLSV12 52 #define GSK_PROTOCOL_TLSV12 438 53 #endif 54 55 #ifndef GSK_FALSE 56 #define GSK_FALSE 0 57 #endif 58 59 #ifndef GSK_TRUE 60 #define GSK_TRUE 1 61 #endif 62 63 64 #include <limits.h> 65 66 #include <curl/curl.h> 67 #include "urldata.h" 68 #include "sendf.h" 69 #include "gskit.h" 70 #include "vtls.h" 71 #include "connect.h" /* for the connect timeout */ 72 #include "select.h" 73 #include "strcase.h" 74 #include "x509asn1.h" 75 #include "curl_printf.h" 76 77 #include "curl_memory.h" 78 /* The last #include file should be: */ 79 #include "memdebug.h" 80 81 82 /* Directions. */ 83 #define SOS_READ 0x01 84 #define SOS_WRITE 0x02 85 86 /* SSL version flags. */ 87 #define CURL_GSKPROTO_SSLV2 0 88 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) 89 #define CURL_GSKPROTO_SSLV3 1 90 #define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3) 91 #define CURL_GSKPROTO_TLSV10 2 92 #define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10) 93 #define CURL_GSKPROTO_TLSV11 3 94 #define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11) 95 #define CURL_GSKPROTO_TLSV12 4 96 #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12) 97 #define CURL_GSKPROTO_LAST 5 98 99 struct ssl_backend_data { 100 gsk_handle handle; 101 int iocport; 102 int localfd; 103 int remotefd; 104 }; 105 106 #define BACKEND connssl->backend 107 108 /* Supported ciphers. */ 109 typedef struct { 110 const char *name; /* Cipher name. */ 111 const char *gsktoken; /* Corresponding token for GSKit String. */ 112 unsigned int versions; /* SSL version flags. */ 113 } gskit_cipher; 114 115 static const gskit_cipher ciphertable[] = { 116 { "null-md5", "01", 117 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 118 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 119 { "null-sha", "02", 120 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 121 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 122 { "exp-rc4-md5", "03", 123 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, 124 { "rc4-md5", "04", 125 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 126 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 127 { "rc4-sha", "05", 128 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 129 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 130 { "exp-rc2-cbc-md5", "06", 131 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, 132 { "exp-des-cbc-sha", "09", 133 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 134 CURL_GSKPROTO_TLSV11_MASK }, 135 { "des-cbc3-sha", "0A", 136 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 137 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 138 { "aes128-sha", "2F", 139 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | 140 CURL_GSKPROTO_TLSV12_MASK }, 141 { "aes256-sha", "35", 142 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | 143 CURL_GSKPROTO_TLSV12_MASK }, 144 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK }, 145 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK }, 146 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, 147 { "aes128-gcm-sha256", 148 "9C", CURL_GSKPROTO_TLSV12_MASK }, 149 { "aes256-gcm-sha384", 150 "9D", CURL_GSKPROTO_TLSV12_MASK }, 151 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK }, 152 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK }, 153 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK }, 154 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK }, 155 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK }, 156 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK }, 157 { (const char *) NULL, (const char *) NULL, 0 } 158 }; 159 160 161 static bool is_separator(char c) 162 { 163 /* Return whether character is a cipher list separator. */ 164 switch(c) { 165 case ' ': 166 case '\t': 167 case ':': 168 case ',': 169 case ';': 170 return true; 171 } 172 return false; 173 } 174 175 176 static CURLcode gskit_status(struct Curl_easy *data, int rc, 177 const char *procname, CURLcode defcode) 178 { 179 /* Process GSKit status and map it to a CURLcode. */ 180 switch(rc) { 181 case GSK_OK: 182 case GSK_OS400_ASYNCHRONOUS_SOC_INIT: 183 return CURLE_OK; 184 case GSK_KEYRING_OPEN_ERROR: 185 case GSK_OS400_ERROR_NO_ACCESS: 186 return CURLE_SSL_CACERT_BADFILE; 187 case GSK_INSUFFICIENT_STORAGE: 188 return CURLE_OUT_OF_MEMORY; 189 case GSK_ERROR_BAD_V2_CIPHER: 190 case GSK_ERROR_BAD_V3_CIPHER: 191 case GSK_ERROR_NO_CIPHERS: 192 return CURLE_SSL_CIPHER; 193 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT: 194 case GSK_ERROR_CERT_VALIDATION: 195 return CURLE_PEER_FAILED_VERIFICATION; 196 case GSK_OS400_ERROR_TIMED_OUT: 197 return CURLE_OPERATION_TIMEDOUT; 198 case GSK_WOULD_BLOCK: 199 return CURLE_AGAIN; 200 case GSK_OS400_ERROR_NOT_REGISTERED: 201 break; 202 case GSK_ERROR_IO: 203 switch(errno) { 204 case ENOMEM: 205 return CURLE_OUT_OF_MEMORY; 206 default: 207 failf(data, "%s I/O error: %s", procname, strerror(errno)); 208 break; 209 } 210 break; 211 default: 212 failf(data, "%s: %s", procname, gsk_strerror(rc)); 213 break; 214 } 215 return defcode; 216 } 217 218 219 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, 220 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) 221 { 222 int rc = gsk_attribute_set_enum(h, id, value); 223 224 switch(rc) { 225 case GSK_OK: 226 return CURLE_OK; 227 case GSK_ERROR_IO: 228 failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); 229 break; 230 case GSK_ATTRIBUTE_INVALID_ID: 231 if(unsupported_ok) 232 return CURLE_UNSUPPORTED_PROTOCOL; 233 default: 234 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc)); 235 break; 236 } 237 return CURLE_SSL_CONNECT_ERROR; 238 } 239 240 241 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, 242 GSK_BUF_ID id, const char *buffer, bool unsupported_ok) 243 { 244 int rc = gsk_attribute_set_buffer(h, id, buffer, 0); 245 246 switch(rc) { 247 case GSK_OK: 248 return CURLE_OK; 249 case GSK_ERROR_IO: 250 failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); 251 break; 252 case GSK_ATTRIBUTE_INVALID_ID: 253 if(unsupported_ok) 254 return CURLE_UNSUPPORTED_PROTOCOL; 255 default: 256 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); 257 break; 258 } 259 return CURLE_SSL_CONNECT_ERROR; 260 } 261 262 263 static CURLcode set_numeric(struct Curl_easy *data, 264 gsk_handle h, GSK_NUM_ID id, int value) 265 { 266 int rc = gsk_attribute_set_numeric_value(h, id, value); 267 268 switch(rc) { 269 case GSK_OK: 270 return CURLE_OK; 271 case GSK_ERROR_IO: 272 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s", 273 strerror(errno)); 274 break; 275 default: 276 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc)); 277 break; 278 } 279 return CURLE_SSL_CONNECT_ERROR; 280 } 281 282 283 static CURLcode set_callback(struct Curl_easy *data, 284 gsk_handle h, GSK_CALLBACK_ID id, void *info) 285 { 286 int rc = gsk_attribute_set_callback(h, id, info); 287 288 switch(rc) { 289 case GSK_OK: 290 return CURLE_OK; 291 case GSK_ERROR_IO: 292 failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno)); 293 break; 294 default: 295 failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc)); 296 break; 297 } 298 return CURLE_SSL_CONNECT_ERROR; 299 } 300 301 302 static CURLcode set_ciphers(struct connectdata *conn, 303 gsk_handle h, unsigned int *protoflags) 304 { 305 struct Curl_easy *data = conn->data; 306 const char *cipherlist = SSL_CONN_CONFIG(cipher_list); 307 const char *clp; 308 const gskit_cipher *ctp; 309 int i; 310 int l; 311 bool unsupported; 312 CURLcode result; 313 struct { 314 char *buf; 315 char *ptr; 316 } ciphers[CURL_GSKPROTO_LAST]; 317 318 /* Compile cipher list into GSKit-compatible cipher lists. */ 319 320 if(!cipherlist) 321 return CURLE_OK; 322 while(is_separator(*cipherlist)) /* Skip initial separators. */ 323 cipherlist++; 324 if(!*cipherlist) 325 return CURLE_OK; 326 327 /* We allocate GSKit buffers of the same size as the input string: since 328 GSKit tokens are always shorter than their cipher names, allocated buffers 329 will always be large enough to accommodate the result. */ 330 l = strlen(cipherlist) + 1; 331 memset((char *) ciphers, 0, sizeof ciphers); 332 for(i = 0; i < CURL_GSKPROTO_LAST; i++) { 333 ciphers[i].buf = malloc(l); 334 if(!ciphers[i].buf) { 335 while(i--) 336 free(ciphers[i].buf); 337 return CURLE_OUT_OF_MEMORY; 338 } 339 ciphers[i].ptr = ciphers[i].buf; 340 *ciphers[i].ptr = '\0'; 341 } 342 343 /* Process each cipher in input string. */ 344 unsupported = FALSE; 345 result = CURLE_OK; 346 for(;;) { 347 for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);) 348 cipherlist++; 349 l = cipherlist - clp; 350 if(!l) 351 break; 352 /* Search the cipher in our table. */ 353 for(ctp = ciphertable; ctp->name; ctp++) 354 if(strncasecompare(ctp->name, clp, l) && !ctp->name[l]) 355 break; 356 if(!ctp->name) { 357 failf(data, "Unknown cipher %.*s", l, clp); 358 result = CURLE_SSL_CIPHER; 359 } 360 else { 361 unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK | 362 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK)); 363 for(i = 0; i < CURL_GSKPROTO_LAST; i++) { 364 if(ctp->versions & (1 << i)) { 365 strcpy(ciphers[i].ptr, ctp->gsktoken); 366 ciphers[i].ptr += strlen(ctp->gsktoken); 367 } 368 } 369 } 370 371 /* Advance to next cipher name or end of string. */ 372 while(is_separator(*cipherlist)) 373 cipherlist++; 374 } 375 376 /* Disable protocols with empty cipher lists. */ 377 for(i = 0; i < CURL_GSKPROTO_LAST; i++) { 378 if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) { 379 *protoflags &= ~(1 << i); 380 ciphers[i].buf[0] = '\0'; 381 } 382 } 383 384 /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */ 385 if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) { 386 result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS, 387 ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE); 388 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 389 result = CURLE_OK; 390 if(unsupported) { 391 failf(data, "TLSv1.1-only ciphers are not yet supported"); 392 result = CURLE_SSL_CIPHER; 393 } 394 } 395 } 396 if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) { 397 result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS, 398 ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE); 399 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 400 result = CURLE_OK; 401 if(unsupported) { 402 failf(data, "TLSv1.2-only ciphers are not yet supported"); 403 result = CURLE_SSL_CIPHER; 404 } 405 } 406 } 407 408 /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to 409 the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */ 410 if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) { 411 result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS, 412 ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE); 413 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 414 result = CURLE_OK; 415 strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr, 416 ciphers[CURL_GSKPROTO_TLSV10].ptr); 417 } 418 } 419 420 /* Set-up other ciphers. */ 421 if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK)) 422 result = set_buffer(data, h, GSK_V3_CIPHER_SPECS, 423 ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE); 424 if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK)) 425 result = set_buffer(data, h, GSK_V2_CIPHER_SPECS, 426 ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE); 427 428 /* Clean-up. */ 429 for(i = 0; i < CURL_GSKPROTO_LAST; i++) 430 free(ciphers[i].buf); 431 432 return result; 433 } 434 435 436 static int Curl_gskit_init(void) 437 { 438 /* No initialisation needed. */ 439 440 return 1; 441 } 442 443 444 static void Curl_gskit_cleanup(void) 445 { 446 /* Nothing to do. */ 447 } 448 449 450 static CURLcode init_environment(struct Curl_easy *data, 451 gsk_handle *envir, const char *appid, 452 const char *file, const char *label, 453 const char *password) 454 { 455 int rc; 456 CURLcode result; 457 gsk_handle h; 458 459 /* Creates the GSKit environment. */ 460 461 rc = gsk_environment_open(&h); 462 switch(rc) { 463 case GSK_OK: 464 break; 465 case GSK_INSUFFICIENT_STORAGE: 466 return CURLE_OUT_OF_MEMORY; 467 default: 468 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc)); 469 return CURLE_SSL_CONNECT_ERROR; 470 } 471 472 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); 473 if(!result && appid) 474 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); 475 if(!result && file) 476 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); 477 if(!result && label) 478 result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); 479 if(!result && password) 480 result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); 481 482 if(!result) { 483 /* Locate CAs, Client certificate and key according to our settings. 484 Note: this call may be blocking for some tenths of seconds. */ 485 result = gskit_status(data, gsk_environment_init(h), 486 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM); 487 if(!result) { 488 *envir = h; 489 return result; 490 } 491 } 492 /* Error: rollback. */ 493 gsk_environment_close(&h); 494 return result; 495 } 496 497 498 static void cancel_async_handshake(struct connectdata *conn, int sockindex) 499 { 500 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 501 Qso_OverlappedIO_t cstat; 502 503 if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) 504 QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL); 505 } 506 507 508 static void close_async_handshake(struct ssl_connect_data *connssl) 509 { 510 QsoDestroyIOCompletionPort(BACKEND->iocport); 511 BACKEND->iocport = -1; 512 } 513 514 /* SSL over SSL 515 * Problems: 516 * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To 517 * pipe an SSL stream into another, it is therefore needed to have a pair 518 * of such communicating sockets and handle the pipelining explicitly. 519 * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot 520 * be used to produce the pipeline. 521 * The solution is to simulate socketpair() for AF_INET with low-level API 522 * listen(), bind() and connect(). 523 */ 524 525 static int 526 inetsocketpair(int sv[2]) 527 { 528 int lfd; /* Listening socket. */ 529 int sfd; /* Server socket. */ 530 int cfd; /* Client socket. */ 531 int len; 532 struct sockaddr_in addr1; 533 struct sockaddr_in addr2; 534 535 /* Create listening socket on a local dynamic port. */ 536 lfd = socket(AF_INET, SOCK_STREAM, 0); 537 if(lfd < 0) 538 return -1; 539 memset((char *) &addr1, 0, sizeof addr1); 540 addr1.sin_family = AF_INET; 541 addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 542 addr1.sin_port = 0; 543 if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) || 544 listen(lfd, 2) < 0) { 545 close(lfd); 546 return -1; 547 } 548 549 /* Get the allocated port. */ 550 len = sizeof addr1; 551 if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) { 552 close(lfd); 553 return -1; 554 } 555 556 /* Create the client socket. */ 557 cfd = socket(AF_INET, SOCK_STREAM, 0); 558 if(cfd < 0) { 559 close(lfd); 560 return -1; 561 } 562 563 /* Request unblocking connection to the listening socket. */ 564 curlx_nonblock(cfd, TRUE); 565 if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 && 566 errno != EINPROGRESS) { 567 close(lfd); 568 close(cfd); 569 return -1; 570 } 571 572 /* Get the client dynamic port for intrusion check below. */ 573 len = sizeof addr2; 574 if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) { 575 close(lfd); 576 close(cfd); 577 return -1; 578 } 579 580 /* Accept the incoming connection and get the server socket. */ 581 curlx_nonblock(lfd, TRUE); 582 for(;;) { 583 len = sizeof addr1; 584 sfd = accept(lfd, (struct sockaddr *) &addr1, &len); 585 if(sfd < 0) { 586 close(lfd); 587 close(cfd); 588 return -1; 589 } 590 591 /* Check for possible intrusion from an external process. */ 592 if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr && 593 addr1.sin_port == addr2.sin_port) 594 break; 595 596 /* Intrusion: reject incoming connection. */ 597 close(sfd); 598 } 599 600 /* Done, return sockets and succeed. */ 601 close(lfd); 602 curlx_nonblock(cfd, FALSE); 603 sv[0] = cfd; 604 sv[1] = sfd; 605 return 0; 606 } 607 608 static int pipe_ssloverssl(struct connectdata *conn, int sockindex, 609 int directions) 610 { 611 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 612 struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; 613 fd_set fds_read; 614 fd_set fds_write; 615 int n; 616 int m; 617 int i; 618 int ret = 0; 619 struct timeval tv = {0, 0}; 620 char buf[CURL_MAX_WRITE_SIZE]; 621 622 if(!connssl->use || !connproxyssl->use) 623 return 0; /* No SSL over SSL: OK. */ 624 625 FD_ZERO(&fds_read); 626 FD_ZERO(&fds_write); 627 n = -1; 628 if(directions & SOS_READ) { 629 FD_SET(BACKEND->remotefd, &fds_write); 630 n = BACKEND->remotefd; 631 } 632 if(directions & SOS_WRITE) { 633 FD_SET(BACKEND->remotefd, &fds_read); 634 n = BACKEND->remotefd; 635 FD_SET(conn->sock[sockindex], &fds_write); 636 if(n < conn->sock[sockindex]) 637 n = conn->sock[sockindex]; 638 } 639 i = select(n + 1, &fds_read, &fds_write, NULL, &tv); 640 if(i < 0) 641 return -1; /* Select error. */ 642 643 if(FD_ISSET(BACKEND->remotefd, &fds_write)) { 644 /* Try getting data from HTTPS proxy and pipe it upstream. */ 645 n = 0; 646 i = gsk_secure_soc_read(connproxyssl->backend->handle, 647 buf, sizeof buf, &n); 648 switch(i) { 649 case GSK_OK: 650 if(n) { 651 i = write(BACKEND->remotefd, buf, n); 652 if(i < 0) 653 return -1; 654 ret = 1; 655 } 656 break; 657 case GSK_OS400_ERROR_TIMED_OUT: 658 case GSK_WOULD_BLOCK: 659 break; 660 default: 661 return -1; 662 } 663 } 664 665 if(FD_ISSET(BACKEND->remotefd, &fds_read) && 666 FD_ISSET(conn->sock[sockindex], &fds_write)) { 667 /* Pipe data to HTTPS proxy. */ 668 n = read(BACKEND->remotefd, buf, sizeof buf); 669 if(n < 0) 670 return -1; 671 if(n) { 672 i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m); 673 if(i != GSK_OK || n != m) 674 return -1; 675 ret = 1; 676 } 677 } 678 679 return ret; /* OK */ 680 } 681 682 683 static void close_one(struct ssl_connect_data *connssl, 684 struct connectdata *conn, int sockindex) 685 { 686 if(BACKEND->handle) { 687 gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle), 688 "gsk_secure_soc_close()", 0); 689 /* Last chance to drain output. */ 690 while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) 691 ; 692 BACKEND->handle = (gsk_handle) NULL; 693 if(BACKEND->localfd >= 0) { 694 close(BACKEND->localfd); 695 BACKEND->localfd = -1; 696 } 697 if(BACKEND->remotefd >= 0) { 698 close(BACKEND->remotefd); 699 BACKEND->remotefd = -1; 700 } 701 } 702 if(BACKEND->iocport >= 0) 703 close_async_handshake(connssl); 704 } 705 706 707 static ssize_t gskit_send(struct connectdata *conn, int sockindex, 708 const void *mem, size_t len, CURLcode *curlcode) 709 { 710 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 711 struct Curl_easy *data = conn->data; 712 CURLcode cc = CURLE_SEND_ERROR; 713 int written; 714 715 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) { 716 cc = gskit_status(data, 717 gsk_secure_soc_write(BACKEND->handle, 718 (char *) mem, (int) len, &written), 719 "gsk_secure_soc_write()", CURLE_SEND_ERROR); 720 if(cc == CURLE_OK) 721 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0) 722 cc = CURLE_SEND_ERROR; 723 } 724 if(cc != CURLE_OK) { 725 *curlcode = cc; 726 written = -1; 727 } 728 return (ssize_t) written; /* number of bytes */ 729 } 730 731 732 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, 733 size_t buffersize, CURLcode *curlcode) 734 { 735 struct ssl_connect_data *connssl = &conn->ssl[num]; 736 struct Curl_easy *data = conn->data; 737 int buffsize; 738 int nread; 739 CURLcode cc = CURLE_RECV_ERROR; 740 741 if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { 742 buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; 743 cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle, 744 buf, buffsize, &nread), 745 "gsk_secure_soc_read()", CURLE_RECV_ERROR); 746 } 747 switch(cc) { 748 case CURLE_OK: 749 break; 750 case CURLE_OPERATION_TIMEDOUT: 751 cc = CURLE_AGAIN; 752 default: 753 *curlcode = cc; 754 nread = -1; 755 break; 756 } 757 return (ssize_t) nread; 758 } 759 760 static CURLcode 761 set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn) 762 { 763 struct Curl_easy *data = conn->data; 764 long ssl_version = SSL_CONN_CONFIG(version); 765 long ssl_version_max = SSL_CONN_CONFIG(version_max); 766 long i = ssl_version; 767 switch(ssl_version_max) { 768 case CURL_SSLVERSION_MAX_NONE: 769 ssl_version_max = ssl_version; 770 break; 771 case CURL_SSLVERSION_MAX_DEFAULT: 772 ssl_version_max = CURL_SSLVERSION_TLSv1_2; 773 break; 774 } 775 for(; i <= (ssl_version_max >> 16); ++i) { 776 switch(i) { 777 case CURL_SSLVERSION_TLSv1_0: 778 *protoflags |= CURL_GSKPROTO_TLSV10_MASK; 779 break; 780 case CURL_SSLVERSION_TLSv1_1: 781 *protoflags |= CURL_GSKPROTO_TLSV11_MASK; 782 break; 783 case CURL_SSLVERSION_TLSv1_2: 784 *protoflags |= CURL_GSKPROTO_TLSV11_MASK; 785 break; 786 case CURL_SSLVERSION_TLSv1_3: 787 failf(data, "GSKit: TLS 1.3 is not yet supported"); 788 return CURLE_SSL_CONNECT_ERROR; 789 } 790 } 791 792 return CURLE_OK; 793 } 794 795 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) 796 { 797 struct Curl_easy *data = conn->data; 798 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 799 gsk_handle envir; 800 CURLcode result; 801 int rc; 802 const char * const keyringfile = SSL_CONN_CONFIG(CAfile); 803 const char * const keyringpwd = SSL_SET_OPTION(key_passwd); 804 const char * const keyringlabel = SSL_SET_OPTION(cert); 805 const long int ssl_version = SSL_CONN_CONFIG(version); 806 const bool verifypeer = SSL_CONN_CONFIG(verifypeer); 807 const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: 808 conn->host.name; 809 const char *sni; 810 unsigned int protoflags = 0; 811 long timeout; 812 Qso_OverlappedIO_t commarea; 813 int sockpair[2]; 814 static const int sobufsize = CURL_MAX_WRITE_SIZE; 815 816 /* Create SSL environment, start (preferably asynchronous) handshake. */ 817 818 BACKEND->handle = (gsk_handle) NULL; 819 BACKEND->iocport = -1; 820 BACKEND->localfd = -1; 821 BACKEND->remotefd = -1; 822 823 /* GSKit supports two ways of specifying an SSL context: either by 824 * application identifier (that should have been defined at the system 825 * level) or by keyring file, password and certificate label. 826 * Local certificate name (CURLOPT_SSLCERT) is used to hold either the 827 * application identifier of the certificate label. 828 * Key password (CURLOPT_KEYPASSWD) holds the keyring password. 829 * It is not possible to have different keyrings for the CAs and the 830 * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify 831 * the keyring file. 832 * If no key password is given and the keyring is the system keyring, 833 * application identifier mode is tried first, as recommended in IBM doc. 834 */ 835 836 envir = (gsk_handle) NULL; 837 838 if(keyringlabel && *keyringlabel && !keyringpwd && 839 !strcmp(keyringfile, CURL_CA_BUNDLE)) { 840 /* Try application identifier mode. */ 841 init_environment(data, &envir, keyringlabel, (const char *) NULL, 842 (const char *) NULL, (const char *) NULL); 843 } 844 845 if(!envir) { 846 /* Use keyring mode. */ 847 result = init_environment(data, &envir, (const char *) NULL, 848 keyringfile, keyringlabel, keyringpwd); 849 if(result) 850 return result; 851 } 852 853 /* Create secure session. */ 854 result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle), 855 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); 856 gsk_environment_close(&envir); 857 if(result) 858 return result; 859 860 /* Establish a pipelining socket pair for SSL over SSL. */ 861 if(conn->proxy_ssl[sockindex].use) { 862 if(inetsocketpair(sockpair)) 863 return CURLE_SSL_CONNECT_ERROR; 864 BACKEND->localfd = sockpair[0]; 865 BACKEND->remotefd = sockpair[1]; 866 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF, 867 (void *) sobufsize, sizeof sobufsize); 868 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF, 869 (void *) sobufsize, sizeof sobufsize); 870 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF, 871 (void *) sobufsize, sizeof sobufsize); 872 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF, 873 (void *) sobufsize, sizeof sobufsize); 874 curlx_nonblock(BACKEND->localfd, TRUE); 875 curlx_nonblock(BACKEND->remotefd, TRUE); 876 } 877 878 /* Determine which SSL/TLS version should be enabled. */ 879 sni = hostname; 880 switch(ssl_version) { 881 case CURL_SSLVERSION_SSLv2: 882 protoflags = CURL_GSKPROTO_SSLV2_MASK; 883 sni = NULL; 884 break; 885 case CURL_SSLVERSION_SSLv3: 886 protoflags = CURL_GSKPROTO_SSLV3_MASK; 887 sni = NULL; 888 break; 889 case CURL_SSLVERSION_DEFAULT: 890 case CURL_SSLVERSION_TLSv1: 891 protoflags = CURL_GSKPROTO_TLSV10_MASK | 892 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; 893 break; 894 case CURL_SSLVERSION_TLSv1_0: 895 case CURL_SSLVERSION_TLSv1_1: 896 case CURL_SSLVERSION_TLSv1_2: 897 case CURL_SSLVERSION_TLSv1_3: 898 result = set_ssl_version_min_max(&protoflags, conn); 899 if(result != CURLE_OK) 900 return result; 901 break; 902 default: 903 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 904 return CURLE_SSL_CONNECT_ERROR; 905 } 906 907 /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ 908 if(sni) { 909 result = set_buffer(data, BACKEND->handle, 910 GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); 911 if(result == CURLE_UNSUPPORTED_PROTOCOL) 912 result = CURLE_OK; 913 } 914 915 /* Set session parameters. */ 916 if(!result) { 917 /* Compute the handshake timeout. Since GSKit granularity is 1 second, 918 we round up the required value. */ 919 timeout = Curl_timeleft(data, NULL, TRUE); 920 if(timeout < 0) 921 result = CURLE_OPERATION_TIMEDOUT; 922 else 923 result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT, 924 (timeout + 999) / 1000); 925 } 926 if(!result) 927 result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1); 928 if(!result) 929 result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? 930 BACKEND->localfd: conn->sock[sockindex]); 931 if(!result) 932 result = set_ciphers(conn, BACKEND->handle, &protoflags); 933 if(!protoflags) { 934 failf(data, "No SSL protocol/cipher combination enabled"); 935 result = CURLE_SSL_CIPHER; 936 } 937 if(!result) 938 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2, 939 (protoflags & CURL_GSKPROTO_SSLV2_MASK)? 940 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); 941 if(!result) 942 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3, 943 (protoflags & CURL_GSKPROTO_SSLV3_MASK)? 944 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); 945 if(!result) 946 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1, 947 (protoflags & CURL_GSKPROTO_TLSV10_MASK)? 948 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); 949 if(!result) { 950 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11, 951 (protoflags & CURL_GSKPROTO_TLSV11_MASK)? 952 GSK_TRUE: GSK_FALSE, TRUE); 953 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 954 result = CURLE_OK; 955 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { 956 failf(data, "TLS 1.1 not yet supported"); 957 result = CURLE_SSL_CIPHER; 958 } 959 } 960 } 961 if(!result) { 962 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12, 963 (protoflags & CURL_GSKPROTO_TLSV12_MASK)? 964 GSK_TRUE: GSK_FALSE, TRUE); 965 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 966 result = CURLE_OK; 967 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { 968 failf(data, "TLS 1.2 not yet supported"); 969 result = CURLE_SSL_CIPHER; 970 } 971 } 972 } 973 if(!result) 974 result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE, 975 verifypeer? GSK_SERVER_AUTH_FULL: 976 GSK_SERVER_AUTH_PASSTHRU, FALSE); 977 978 if(!result) { 979 /* Start handshake. Try asynchronous first. */ 980 memset(&commarea, 0, sizeof commarea); 981 BACKEND->iocport = QsoCreateIOCompletionPort(); 982 if(BACKEND->iocport != -1) { 983 result = gskit_status(data, 984 gsk_secure_soc_startInit(BACKEND->handle, 985 BACKEND->iocport, 986 &commarea), 987 "gsk_secure_soc_startInit()", 988 CURLE_SSL_CONNECT_ERROR); 989 if(!result) { 990 connssl->connecting_state = ssl_connect_2; 991 return CURLE_OK; 992 } 993 else 994 close_async_handshake(connssl); 995 } 996 else if(errno != ENOBUFS) 997 result = gskit_status(data, GSK_ERROR_IO, 998 "QsoCreateIOCompletionPort()", 0); 999 else if(conn->proxy_ssl[sockindex].use) { 1000 /* Cannot pipeline while handshaking synchronously. */ 1001 result = CURLE_SSL_CONNECT_ERROR; 1002 } 1003 else { 1004 /* No more completion port available. Use synchronous IO. */ 1005 result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle), 1006 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); 1007 if(!result) { 1008 connssl->connecting_state = ssl_connect_3; 1009 return CURLE_OK; 1010 } 1011 } 1012 } 1013 1014 /* Error: rollback. */ 1015 close_one(connssl, conn, sockindex); 1016 return result; 1017 } 1018 1019 1020 static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, 1021 bool nonblocking) 1022 { 1023 struct Curl_easy *data = conn->data; 1024 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1025 Qso_OverlappedIO_t cstat; 1026 long timeout_ms; 1027 struct timeval stmv; 1028 CURLcode result; 1029 1030 /* Poll or wait for end of SSL asynchronous handshake. */ 1031 1032 for(;;) { 1033 timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); 1034 if(timeout_ms < 0) 1035 timeout_ms = 0; 1036 stmv.tv_sec = timeout_ms / 1000; 1037 stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; 1038 switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) { 1039 case 1: /* Operation complete. */ 1040 break; 1041 case -1: /* An error occurred: handshake still in progress. */ 1042 if(errno == EINTR) { 1043 if(nonblocking) 1044 return CURLE_OK; 1045 continue; /* Retry. */ 1046 } 1047 if(errno != ETIME) { 1048 failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); 1049 cancel_async_handshake(conn, sockindex); 1050 close_async_handshake(connssl); 1051 return CURLE_SSL_CONNECT_ERROR; 1052 } 1053 /* FALL INTO... */ 1054 case 0: /* Handshake in progress, timeout occurred. */ 1055 if(nonblocking) 1056 return CURLE_OK; 1057 cancel_async_handshake(conn, sockindex); 1058 close_async_handshake(connssl); 1059 return CURLE_OPERATION_TIMEDOUT; 1060 } 1061 break; 1062 } 1063 result = gskit_status(data, cstat.returnValue, "SSL handshake", 1064 CURLE_SSL_CONNECT_ERROR); 1065 if(!result) 1066 connssl->connecting_state = ssl_connect_3; 1067 close_async_handshake(connssl); 1068 return result; 1069 } 1070 1071 1072 static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) 1073 { 1074 struct Curl_easy *data = conn->data; 1075 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1076 const gsk_cert_data_elem *cdev; 1077 int cdec; 1078 const gsk_cert_data_elem *p; 1079 const char *cert = (const char *) NULL; 1080 const char *certend; 1081 const char *ptr; 1082 int i; 1083 CURLcode result; 1084 1085 /* SSL handshake done: gather certificate info and verify host. */ 1086 1087 if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle, 1088 GSK_PARTNER_CERT_INFO, 1089 &cdev, &cdec), 1090 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == 1091 CURLE_OK) { 1092 infof(data, "Server certificate:\n"); 1093 p = cdev; 1094 for(i = 0; i++ < cdec; p++) 1095 switch(p->cert_data_id) { 1096 case CERT_BODY_DER: 1097 cert = p->cert_data_p; 1098 certend = cert + cdev->cert_data_l; 1099 break; 1100 case CERT_DN_PRINTABLE: 1101 infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p); 1102 break; 1103 case CERT_ISSUER_DN_PRINTABLE: 1104 infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p); 1105 break; 1106 case CERT_VALID_FROM: 1107 infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p); 1108 break; 1109 case CERT_VALID_TO: 1110 infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p); 1111 break; 1112 } 1113 } 1114 1115 /* Verify host. */ 1116 result = Curl_verifyhost(conn, cert, certend); 1117 if(result) 1118 return result; 1119 1120 /* The only place GSKit can get the whole CA chain is a validation 1121 callback where no user data pointer is available. Therefore it's not 1122 possible to copy this chain into our structures for CAINFO. 1123 However the server certificate may be available, thus we can return 1124 info about it. */ 1125 if(data->set.ssl.certinfo) { 1126 result = Curl_ssl_init_certinfo(data, 1); 1127 if(result) 1128 return result; 1129 1130 if(cert) { 1131 result = Curl_extract_certinfo(conn, 0, cert, certend); 1132 if(result) 1133 return result; 1134 } 1135 } 1136 1137 /* Check pinned public key. */ 1138 ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : 1139 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; 1140 if(!result && ptr) { 1141 curl_X509certificate x509; 1142 curl_asn1Element *p; 1143 1144 if(Curl_parseX509(&x509, cert, certend)) 1145 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 1146 p = &x509.subjectPublicKeyInfo; 1147 result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header); 1148 if(result) { 1149 failf(data, "SSL: public key does not match pinned public key!"); 1150 return result; 1151 } 1152 } 1153 1154 connssl->connecting_state = ssl_connect_done; 1155 return CURLE_OK; 1156 } 1157 1158 1159 static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, 1160 bool nonblocking, bool *done) 1161 { 1162 struct Curl_easy *data = conn->data; 1163 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1164 long timeout_ms; 1165 Qso_OverlappedIO_t cstat; 1166 CURLcode result = CURLE_OK; 1167 1168 *done = connssl->state == ssl_connection_complete; 1169 if(*done) 1170 return CURLE_OK; 1171 1172 /* Step 1: create session, start handshake. */ 1173 if(connssl->connecting_state == ssl_connect_1) { 1174 /* check allowed time left */ 1175 timeout_ms = Curl_timeleft(data, NULL, TRUE); 1176 1177 if(timeout_ms < 0) { 1178 /* no need to continue if time already is up */ 1179 failf(data, "SSL connection timeout"); 1180 result = CURLE_OPERATION_TIMEDOUT; 1181 } 1182 else 1183 result = gskit_connect_step1(conn, sockindex); 1184 } 1185 1186 /* Handle handshake pipelining. */ 1187 if(!result) 1188 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) 1189 result = CURLE_SSL_CONNECT_ERROR; 1190 1191 /* Step 2: check if handshake is over. */ 1192 if(!result && connssl->connecting_state == ssl_connect_2) { 1193 /* check allowed time left */ 1194 timeout_ms = Curl_timeleft(data, NULL, TRUE); 1195 1196 if(timeout_ms < 0) { 1197 /* no need to continue if time already is up */ 1198 failf(data, "SSL connection timeout"); 1199 result = CURLE_OPERATION_TIMEDOUT; 1200 } 1201 else 1202 result = gskit_connect_step2(conn, sockindex, nonblocking); 1203 } 1204 1205 /* Handle handshake pipelining. */ 1206 if(!result) 1207 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) 1208 result = CURLE_SSL_CONNECT_ERROR; 1209 1210 /* Step 3: gather certificate info, verify host. */ 1211 if(!result && connssl->connecting_state == ssl_connect_3) 1212 result = gskit_connect_step3(conn, sockindex); 1213 1214 if(result) 1215 close_one(connssl, conn, sockindex); 1216 else if(connssl->connecting_state == ssl_connect_done) { 1217 connssl->state = ssl_connection_complete; 1218 connssl->connecting_state = ssl_connect_1; 1219 conn->recv[sockindex] = gskit_recv; 1220 conn->send[sockindex] = gskit_send; 1221 *done = TRUE; 1222 } 1223 1224 return result; 1225 } 1226 1227 1228 static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, 1229 int sockindex, bool *done) 1230 { 1231 CURLcode result; 1232 1233 result = gskit_connect_common(conn, sockindex, TRUE, done); 1234 if(*done || result) 1235 conn->ssl[sockindex].connecting_state = ssl_connect_1; 1236 return result; 1237 } 1238 1239 1240 static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) 1241 { 1242 CURLcode result; 1243 bool done; 1244 1245 conn->ssl[sockindex].connecting_state = ssl_connect_1; 1246 result = gskit_connect_common(conn, sockindex, FALSE, &done); 1247 if(result) 1248 return result; 1249 1250 DEBUGASSERT(done); 1251 1252 return CURLE_OK; 1253 } 1254 1255 1256 static void Curl_gskit_close(struct connectdata *conn, int sockindex) 1257 { 1258 close_one(&conn->ssl[sockindex], conn, sockindex); 1259 close_one(&conn->proxy_ssl[sockindex], conn, sockindex); 1260 } 1261 1262 1263 static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) 1264 { 1265 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1266 struct Curl_easy *data = conn->data; 1267 ssize_t nread; 1268 int what; 1269 int rc; 1270 char buf[120]; 1271 1272 if(!BACKEND->handle) 1273 return 0; 1274 1275 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) 1276 return 0; 1277 1278 close_one(connssl, conn, sockindex); 1279 rc = 0; 1280 what = SOCKET_READABLE(conn->sock[sockindex], 1281 SSL_SHUTDOWN_TIMEOUT); 1282 1283 for(;;) { 1284 if(what < 0) { 1285 /* anything that gets here is fatally bad */ 1286 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1287 rc = -1; 1288 break; 1289 } 1290 1291 if(!what) { /* timeout */ 1292 failf(data, "SSL shutdown timeout"); 1293 break; 1294 } 1295 1296 /* Something to read, let's do it and hope that it is the close 1297 notify alert from the server. No way to gsk_secure_soc_read() now, so 1298 use read(). */ 1299 1300 nread = read(conn->sock[sockindex], buf, sizeof(buf)); 1301 1302 if(nread < 0) { 1303 failf(data, "read: %s", strerror(errno)); 1304 rc = -1; 1305 } 1306 1307 if(nread <= 0) 1308 break; 1309 1310 what = SOCKET_READABLE(conn->sock[sockindex], 0); 1311 } 1312 1313 return rc; 1314 } 1315 1316 1317 static size_t Curl_gskit_version(char *buffer, size_t size) 1318 { 1319 strncpy(buffer, "GSKit", size); 1320 return strlen(buffer); 1321 } 1322 1323 1324 static int Curl_gskit_check_cxn(struct connectdata *cxn) 1325 { 1326 struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET]; 1327 int err; 1328 int errlen; 1329 1330 /* The only thing that can be tested here is at the socket level. */ 1331 1332 if(!BACKEND->handle) 1333 return 0; /* connection has been closed */ 1334 1335 err = 0; 1336 errlen = sizeof err; 1337 1338 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, 1339 (unsigned char *) &err, &errlen) || 1340 errlen != sizeof err || err) 1341 return 0; /* connection has been closed */ 1342 1343 return -1; /* connection status unknown */ 1344 } 1345 1346 static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl, 1347 CURLINFO info UNUSED_PARAM) 1348 { 1349 (void)info; 1350 return BACKEND->handle; 1351 } 1352 1353 const struct Curl_ssl Curl_ssl_gskit = { 1354 { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */ 1355 1356 0, /* have_ca_path */ 1357 1, /* have_certinfo */ 1358 0, /* have_pinnedpubkey */ 1359 0, /* have_ssl_ctx */ 1360 /* TODO: convert to 1 and fix test #1014 (if need) */ 1361 0, /* support_https_proxy */ 1362 1363 sizeof(struct ssl_backend_data), 1364 1365 Curl_gskit_init, /* init */ 1366 Curl_gskit_cleanup, /* cleanup */ 1367 Curl_gskit_version, /* version */ 1368 Curl_gskit_check_cxn, /* check_cxn */ 1369 Curl_gskit_shutdown, /* shutdown */ 1370 Curl_none_data_pending, /* data_pending */ 1371 Curl_none_random, /* random */ 1372 Curl_none_cert_status_request, /* cert_status_request */ 1373 Curl_gskit_connect, /* connect */ 1374 Curl_gskit_connect_nonblocking, /* connect_nonblocking */ 1375 Curl_gskit_get_internals, /* get_internals */ 1376 Curl_gskit_close, /* close_one */ 1377 Curl_none_close_all, /* close_all */ 1378 /* No session handling for GSKit */ 1379 Curl_none_session_free, /* session_free */ 1380 Curl_none_set_engine, /* set_engine */ 1381 Curl_none_set_engine_default, /* set_engine_default */ 1382 Curl_none_engines_list, /* engines_list */ 1383 Curl_none_false_start, /* false_start */ 1384 Curl_none_md5sum, /* md5sum */ 1385 NULL /* sha256sum */ 1386 }; 1387 1388 #endif /* USE_GSKIT */ 1389