1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2015, 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 http://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 #ifdef HAVE_LIMITS_H 65 # include <limits.h> 66 #endif 67 68 #include <curl/curl.h> 69 #include "urldata.h" 70 #include "sendf.h" 71 #include "gskit.h" 72 #include "vtls.h" 73 #include "connect.h" /* for the connect timeout */ 74 #include "select.h" 75 #include "strequal.h" 76 #include "x509asn1.h" 77 #include "curl_printf.h" 78 79 #include "curl_memory.h" 80 /* The last #include file should be: */ 81 #include "memdebug.h" 82 83 84 /* SSL version flags. */ 85 #define CURL_GSKPROTO_SSLV2 0 86 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) 87 #define CURL_GSKPROTO_SSLV3 1 88 #define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3) 89 #define CURL_GSKPROTO_TLSV10 2 90 #define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10) 91 #define CURL_GSKPROTO_TLSV11 3 92 #define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11) 93 #define CURL_GSKPROTO_TLSV12 4 94 #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12) 95 #define CURL_GSKPROTO_LAST 5 96 97 98 /* Supported ciphers. */ 99 typedef struct { 100 const char *name; /* Cipher name. */ 101 const char *gsktoken; /* Corresponding token for GSKit String. */ 102 unsigned int versions; /* SSL version flags. */ 103 } gskit_cipher; 104 105 static const gskit_cipher ciphertable[] = { 106 { "null-md5", "01", 107 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 108 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 109 { "null-sha", "02", 110 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 111 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 112 { "exp-rc4-md5", "03", 113 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, 114 { "rc4-md5", "04", 115 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 116 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 117 { "rc4-sha", "05", 118 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 119 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 120 { "exp-rc2-cbc-md5", "06", 121 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, 122 { "exp-des-cbc-sha", "09", 123 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 124 CURL_GSKPROTO_TLSV11_MASK }, 125 { "des-cbc3-sha", "0A", 126 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 127 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 128 { "aes128-sha", "2F", 129 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | 130 CURL_GSKPROTO_TLSV12_MASK }, 131 { "aes256-sha", "35", 132 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | 133 CURL_GSKPROTO_TLSV12_MASK }, 134 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK }, 135 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK }, 136 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, 137 { "aes128-gcm-sha256", 138 "9C", CURL_GSKPROTO_TLSV12_MASK }, 139 { "aes256-gcm-sha384", 140 "9D", CURL_GSKPROTO_TLSV12_MASK }, 141 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK }, 142 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK }, 143 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK }, 144 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK }, 145 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK }, 146 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK }, 147 { (const char *) NULL, (const char *) NULL, 0 } 148 }; 149 150 151 static bool is_separator(char c) 152 { 153 /* Return whether character is a cipher list separator. */ 154 switch (c) { 155 case ' ': 156 case '\t': 157 case ':': 158 case ',': 159 case ';': 160 return true; 161 } 162 return false; 163 } 164 165 166 static CURLcode gskit_status(struct SessionHandle *data, int rc, 167 const char *procname, CURLcode defcode) 168 { 169 /* Process GSKit status and map it to a CURLcode. */ 170 switch (rc) { 171 case GSK_OK: 172 case GSK_OS400_ASYNCHRONOUS_SOC_INIT: 173 return CURLE_OK; 174 case GSK_KEYRING_OPEN_ERROR: 175 case GSK_OS400_ERROR_NO_ACCESS: 176 return CURLE_SSL_CACERT_BADFILE; 177 case GSK_INSUFFICIENT_STORAGE: 178 return CURLE_OUT_OF_MEMORY; 179 case GSK_ERROR_BAD_V2_CIPHER: 180 case GSK_ERROR_BAD_V3_CIPHER: 181 case GSK_ERROR_NO_CIPHERS: 182 return CURLE_SSL_CIPHER; 183 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT: 184 case GSK_ERROR_CERT_VALIDATION: 185 return CURLE_PEER_FAILED_VERIFICATION; 186 case GSK_OS400_ERROR_TIMED_OUT: 187 return CURLE_OPERATION_TIMEDOUT; 188 case GSK_WOULD_BLOCK: 189 return CURLE_AGAIN; 190 case GSK_OS400_ERROR_NOT_REGISTERED: 191 break; 192 case GSK_ERROR_IO: 193 switch (errno) { 194 case ENOMEM: 195 return CURLE_OUT_OF_MEMORY; 196 default: 197 failf(data, "%s I/O error: %s", procname, strerror(errno)); 198 break; 199 } 200 break; 201 default: 202 failf(data, "%s: %s", procname, gsk_strerror(rc)); 203 break; 204 } 205 return defcode; 206 } 207 208 209 static CURLcode set_enum(struct SessionHandle *data, gsk_handle h, 210 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) 211 { 212 int rc = gsk_attribute_set_enum(h, id, value); 213 214 switch (rc) { 215 case GSK_OK: 216 return CURLE_OK; 217 case GSK_ERROR_IO: 218 failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); 219 break; 220 case GSK_ATTRIBUTE_INVALID_ID: 221 if(unsupported_ok) 222 return CURLE_UNSUPPORTED_PROTOCOL; 223 default: 224 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc)); 225 break; 226 } 227 return CURLE_SSL_CONNECT_ERROR; 228 } 229 230 231 static CURLcode set_buffer(struct SessionHandle *data, gsk_handle h, 232 GSK_BUF_ID id, const char *buffer, bool unsupported_ok) 233 { 234 int rc = gsk_attribute_set_buffer(h, id, buffer, 0); 235 236 switch (rc) { 237 case GSK_OK: 238 return CURLE_OK; 239 case GSK_ERROR_IO: 240 failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); 241 break; 242 case GSK_ATTRIBUTE_INVALID_ID: 243 if(unsupported_ok) 244 return CURLE_UNSUPPORTED_PROTOCOL; 245 default: 246 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); 247 break; 248 } 249 return CURLE_SSL_CONNECT_ERROR; 250 } 251 252 253 static CURLcode set_numeric(struct SessionHandle *data, 254 gsk_handle h, GSK_NUM_ID id, int value) 255 { 256 int rc = gsk_attribute_set_numeric_value(h, id, value); 257 258 switch (rc) { 259 case GSK_OK: 260 return CURLE_OK; 261 case GSK_ERROR_IO: 262 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s", 263 strerror(errno)); 264 break; 265 default: 266 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc)); 267 break; 268 } 269 return CURLE_SSL_CONNECT_ERROR; 270 } 271 272 273 static CURLcode set_callback(struct SessionHandle *data, 274 gsk_handle h, GSK_CALLBACK_ID id, void *info) 275 { 276 int rc = gsk_attribute_set_callback(h, id, info); 277 278 switch (rc) { 279 case GSK_OK: 280 return CURLE_OK; 281 case GSK_ERROR_IO: 282 failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno)); 283 break; 284 default: 285 failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc)); 286 break; 287 } 288 return CURLE_SSL_CONNECT_ERROR; 289 } 290 291 292 static CURLcode set_ciphers(struct SessionHandle *data, 293 gsk_handle h, unsigned int *protoflags) 294 { 295 const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST]; 296 const char *clp; 297 const gskit_cipher *ctp; 298 int i; 299 int l; 300 bool unsupported; 301 CURLcode result; 302 struct { 303 char *buf; 304 char *ptr; 305 } ciphers[CURL_GSKPROTO_LAST]; 306 307 /* Compile cipher list into GSKit-compatible cipher lists. */ 308 309 if(!cipherlist) 310 return CURLE_OK; 311 while(is_separator(*cipherlist)) /* Skip initial separators. */ 312 cipherlist++; 313 if(!*cipherlist) 314 return CURLE_OK; 315 316 /* We allocate GSKit buffers of the same size as the input string: since 317 GSKit tokens are always shorter than their cipher names, allocated buffers 318 will always be large enough to accomodate the result. */ 319 l = strlen(cipherlist) + 1; 320 memset((char *) ciphers, 0, sizeof ciphers); 321 for(i = 0; i < CURL_GSKPROTO_LAST; i++) { 322 ciphers[i].buf = malloc(l); 323 if(!ciphers[i].buf) { 324 while(i--) 325 free(ciphers[i].buf); 326 return CURLE_OUT_OF_MEMORY; 327 } 328 ciphers[i].ptr = ciphers[i].buf; 329 *ciphers[i].ptr = '\0'; 330 } 331 332 /* Process each cipher in input string. */ 333 unsupported = FALSE; 334 result = CURLE_OK; 335 for(;;) { 336 for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);) 337 cipherlist++; 338 l = cipherlist - clp; 339 if(!l) 340 break; 341 /* Search the cipher in our table. */ 342 for(ctp = ciphertable; ctp->name; ctp++) 343 if(strnequal(ctp->name, clp, l) && !ctp->name[l]) 344 break; 345 if(!ctp->name) { 346 failf(data, "Unknown cipher %.*s", l, clp); 347 result = CURLE_SSL_CIPHER; 348 } 349 else { 350 unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK | 351 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK)); 352 for(i = 0; i < CURL_GSKPROTO_LAST; i++) { 353 if(ctp->versions & (1 << i)) { 354 strcpy(ciphers[i].ptr, ctp->gsktoken); 355 ciphers[i].ptr += strlen(ctp->gsktoken); 356 } 357 } 358 } 359 360 /* Advance to next cipher name or end of string. */ 361 while(is_separator(*cipherlist)) 362 cipherlist++; 363 } 364 365 /* Disable protocols with empty cipher lists. */ 366 for(i = 0; i < CURL_GSKPROTO_LAST; i++) { 367 if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) { 368 *protoflags &= ~(1 << i); 369 ciphers[i].buf[0] = '\0'; 370 } 371 } 372 373 /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */ 374 if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) { 375 result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS, 376 ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE); 377 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 378 result = CURLE_OK; 379 if(unsupported) { 380 failf(data, "TLSv1.1-only ciphers are not yet supported"); 381 result = CURLE_SSL_CIPHER; 382 } 383 } 384 } 385 if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) { 386 result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS, 387 ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE); 388 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 389 result = CURLE_OK; 390 if(unsupported) { 391 failf(data, "TLSv1.2-only ciphers are not yet supported"); 392 result = CURLE_SSL_CIPHER; 393 } 394 } 395 } 396 397 /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to 398 the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */ 399 if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) { 400 result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS, 401 ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE); 402 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 403 result = CURLE_OK; 404 strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr, 405 ciphers[CURL_GSKPROTO_TLSV10].ptr); 406 } 407 } 408 409 /* Set-up other ciphers. */ 410 if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK)) 411 result = set_buffer(data, h, GSK_V3_CIPHER_SPECS, 412 ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE); 413 if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK)) 414 result = set_buffer(data, h, GSK_V2_CIPHER_SPECS, 415 ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE); 416 417 /* Clean-up. */ 418 for(i = 0; i < CURL_GSKPROTO_LAST; i++) 419 free(ciphers[i].buf); 420 421 return result; 422 } 423 424 425 int Curl_gskit_init(void) 426 { 427 /* No initialisation needed. */ 428 429 return 1; 430 } 431 432 433 void Curl_gskit_cleanup(void) 434 { 435 /* Nothing to do. */ 436 } 437 438 439 static CURLcode init_environment(struct SessionHandle *data, 440 gsk_handle *envir, const char *appid, 441 const char *file, const char *label, 442 const char *password) 443 { 444 int rc; 445 CURLcode result; 446 gsk_handle h; 447 448 /* Creates the GSKit environment. */ 449 450 rc = gsk_environment_open(&h); 451 switch (rc) { 452 case GSK_OK: 453 break; 454 case GSK_INSUFFICIENT_STORAGE: 455 return CURLE_OUT_OF_MEMORY; 456 default: 457 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc)); 458 return CURLE_SSL_CONNECT_ERROR; 459 } 460 461 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); 462 if(!result && appid) 463 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); 464 if(!result && file) 465 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); 466 if(!result && label) 467 result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); 468 if(!result && password) 469 result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); 470 471 if(!result) { 472 /* Locate CAs, Client certificate and key according to our settings. 473 Note: this call may be blocking for some tenths of seconds. */ 474 result = gskit_status(data, gsk_environment_init(h), 475 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM); 476 if(!result) { 477 *envir = h; 478 return result; 479 } 480 } 481 /* Error: rollback. */ 482 gsk_environment_close(&h); 483 return result; 484 } 485 486 487 static void cancel_async_handshake(struct connectdata *conn, int sockindex) 488 { 489 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 490 Qso_OverlappedIO_t cstat; 491 492 if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) 493 QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL); 494 } 495 496 497 static void close_async_handshake(struct ssl_connect_data *connssl) 498 { 499 QsoDestroyIOCompletionPort(connssl->iocport); 500 connssl->iocport = -1; 501 } 502 503 504 static void close_one(struct ssl_connect_data *conn, 505 struct SessionHandle *data) 506 { 507 if(conn->handle) { 508 gskit_status(data, gsk_secure_soc_close(&conn->handle), 509 "gsk_secure_soc_close()", 0); 510 conn->handle = (gsk_handle) NULL; 511 } 512 if(conn->iocport >= 0) 513 close_async_handshake(conn); 514 } 515 516 517 static ssize_t gskit_send(struct connectdata *conn, int sockindex, 518 const void *mem, size_t len, CURLcode *curlcode) 519 { 520 struct SessionHandle *data = conn->data; 521 CURLcode cc; 522 int written; 523 524 cc = gskit_status(data, 525 gsk_secure_soc_write(conn->ssl[sockindex].handle, 526 (char *) mem, (int) len, &written), 527 "gsk_secure_soc_write()", CURLE_SEND_ERROR); 528 if(cc != CURLE_OK) { 529 *curlcode = cc; 530 written = -1; 531 } 532 return (ssize_t) written; /* number of bytes */ 533 } 534 535 536 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, 537 size_t buffersize, CURLcode *curlcode) 538 { 539 struct SessionHandle *data = conn->data; 540 int buffsize; 541 int nread; 542 CURLcode cc; 543 544 buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; 545 cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle, 546 buf, buffsize, &nread), 547 "gsk_secure_soc_read()", CURLE_RECV_ERROR); 548 if(cc != CURLE_OK) { 549 *curlcode = cc; 550 nread = -1; 551 } 552 return (ssize_t) nread; 553 } 554 555 556 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) 557 { 558 struct SessionHandle *data = conn->data; 559 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 560 gsk_handle envir; 561 CURLcode result; 562 int rc; 563 char *keyringfile; 564 char *keyringpwd; 565 char *keyringlabel; 566 char *sni; 567 unsigned int protoflags; 568 long timeout; 569 Qso_OverlappedIO_t commarea; 570 571 /* Create SSL environment, start (preferably asynchronous) handshake. */ 572 573 connssl->handle = (gsk_handle) NULL; 574 connssl->iocport = -1; 575 576 /* GSKit supports two ways of specifying an SSL context: either by 577 * application identifier (that should have been defined at the system 578 * level) or by keyring file, password and certificate label. 579 * Local certificate name (CURLOPT_SSLCERT) is used to hold either the 580 * application identifier of the certificate label. 581 * Key password (CURLOPT_KEYPASSWD) holds the keyring password. 582 * It is not possible to have different keyrings for the CAs and the 583 * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify 584 * the keyring file. 585 * If no key password is given and the keyring is the system keyring, 586 * application identifier mode is tried first, as recommended in IBM doc. 587 */ 588 589 keyringfile = data->set.str[STRING_SSL_CAFILE]; 590 keyringpwd = data->set.str[STRING_KEY_PASSWD]; 591 keyringlabel = data->set.str[STRING_CERT]; 592 envir = (gsk_handle) NULL; 593 594 if(keyringlabel && *keyringlabel && !keyringpwd && 595 !strcmp(keyringfile, CURL_CA_BUNDLE)) { 596 /* Try application identifier mode. */ 597 init_environment(data, &envir, keyringlabel, (const char *) NULL, 598 (const char *) NULL, (const char *) NULL); 599 } 600 601 if(!envir) { 602 /* Use keyring mode. */ 603 result = init_environment(data, &envir, (const char *) NULL, 604 keyringfile, keyringlabel, keyringpwd); 605 if(result) 606 return result; 607 } 608 609 /* Create secure session. */ 610 result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle), 611 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); 612 gsk_environment_close(&envir); 613 if(result) 614 return result; 615 616 /* Determine which SSL/TLS version should be enabled. */ 617 protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | 618 CURL_GSKPROTO_TLSV12_MASK; 619 sni = conn->host.name; 620 switch (data->set.ssl.version) { 621 case CURL_SSLVERSION_SSLv2: 622 protoflags = CURL_GSKPROTO_SSLV2_MASK; 623 sni = (char *) NULL; 624 break; 625 case CURL_SSLVERSION_SSLv3: 626 protoflags = CURL_GSKPROTO_SSLV3_MASK; 627 sni = (char *) NULL; 628 break; 629 case CURL_SSLVERSION_TLSv1: 630 protoflags = CURL_GSKPROTO_TLSV10_MASK | 631 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; 632 break; 633 case CURL_SSLVERSION_TLSv1_0: 634 protoflags = CURL_GSKPROTO_TLSV10_MASK; 635 break; 636 case CURL_SSLVERSION_TLSv1_1: 637 protoflags = CURL_GSKPROTO_TLSV11_MASK; 638 break; 639 case CURL_SSLVERSION_TLSv1_2: 640 protoflags = CURL_GSKPROTO_TLSV12_MASK; 641 break; 642 } 643 644 /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ 645 if(sni) { 646 result = set_buffer(data, connssl->handle, 647 GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); 648 if(result == CURLE_UNSUPPORTED_PROTOCOL) 649 result = CURLE_OK; 650 } 651 652 /* Set session parameters. */ 653 if(!result) { 654 /* Compute the handshake timeout. Since GSKit granularity is 1 second, 655 we round up the required value. */ 656 timeout = Curl_timeleft(data, NULL, TRUE); 657 if(timeout < 0) 658 result = CURLE_OPERATION_TIMEDOUT; 659 else 660 result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT, 661 (timeout + 999) / 1000); 662 } 663 if(!result) 664 result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); 665 if(!result) 666 result = set_ciphers(data, connssl->handle, &protoflags); 667 if(!protoflags) { 668 failf(data, "No SSL protocol/cipher combination enabled"); 669 result = CURLE_SSL_CIPHER; 670 } 671 if(!result) 672 result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2, 673 (protoflags & CURL_GSKPROTO_SSLV2_MASK)? 674 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); 675 if(!result) 676 result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3, 677 (protoflags & CURL_GSKPROTO_SSLV3_MASK)? 678 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); 679 if(!result) 680 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1, 681 (protoflags & CURL_GSKPROTO_TLSV10_MASK)? 682 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); 683 if(!result) { 684 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11, 685 (protoflags & CURL_GSKPROTO_TLSV11_MASK)? 686 GSK_TRUE: GSK_FALSE, TRUE); 687 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 688 result = CURLE_OK; 689 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { 690 failf(data, "TLS 1.1 not yet supported"); 691 result = CURLE_SSL_CIPHER; 692 } 693 } 694 } 695 if(!result) { 696 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12, 697 (protoflags & CURL_GSKPROTO_TLSV12_MASK)? 698 GSK_TRUE: GSK_FALSE, TRUE); 699 if(result == CURLE_UNSUPPORTED_PROTOCOL) { 700 result = CURLE_OK; 701 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { 702 failf(data, "TLS 1.2 not yet supported"); 703 result = CURLE_SSL_CIPHER; 704 } 705 } 706 } 707 if(!result) 708 result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, 709 data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL: 710 GSK_SERVER_AUTH_PASSTHRU, FALSE); 711 712 if(!result) { 713 /* Start handshake. Try asynchronous first. */ 714 memset(&commarea, 0, sizeof commarea); 715 connssl->iocport = QsoCreateIOCompletionPort(); 716 if(connssl->iocport != -1) { 717 result = gskit_status(data, 718 gsk_secure_soc_startInit(connssl->handle, 719 connssl->iocport, 720 &commarea), 721 "gsk_secure_soc_startInit()", 722 CURLE_SSL_CONNECT_ERROR); 723 if(!result) { 724 connssl->connecting_state = ssl_connect_2; 725 return CURLE_OK; 726 } 727 else 728 close_async_handshake(connssl); 729 } 730 else if(errno != ENOBUFS) 731 result = gskit_status(data, GSK_ERROR_IO, 732 "QsoCreateIOCompletionPort()", 0); 733 else { 734 /* No more completion port available. Use synchronous IO. */ 735 result = gskit_status(data, gsk_secure_soc_init(connssl->handle), 736 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); 737 if(!result) { 738 connssl->connecting_state = ssl_connect_3; 739 return CURLE_OK; 740 } 741 } 742 } 743 744 /* Error: rollback. */ 745 close_one(connssl, data); 746 return result; 747 } 748 749 750 static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, 751 bool nonblocking) 752 { 753 struct SessionHandle *data = conn->data; 754 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 755 Qso_OverlappedIO_t cstat; 756 long timeout_ms; 757 struct timeval stmv; 758 CURLcode result; 759 760 /* Poll or wait for end of SSL asynchronous handshake. */ 761 762 for(;;) { 763 timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); 764 if(timeout_ms < 0) 765 timeout_ms = 0; 766 stmv.tv_sec = timeout_ms / 1000; 767 stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; 768 switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) { 769 case 1: /* Operation complete. */ 770 break; 771 case -1: /* An error occurred: handshake still in progress. */ 772 if(errno == EINTR) { 773 if(nonblocking) 774 return CURLE_OK; 775 continue; /* Retry. */ 776 } 777 if(errno != ETIME) { 778 failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); 779 cancel_async_handshake(conn, sockindex); 780 close_async_handshake(connssl); 781 return CURLE_SSL_CONNECT_ERROR; 782 } 783 /* FALL INTO... */ 784 case 0: /* Handshake in progress, timeout occurred. */ 785 if(nonblocking) 786 return CURLE_OK; 787 cancel_async_handshake(conn, sockindex); 788 close_async_handshake(connssl); 789 return CURLE_OPERATION_TIMEDOUT; 790 } 791 break; 792 } 793 result = gskit_status(data, cstat.returnValue, "SSL handshake", 794 CURLE_SSL_CONNECT_ERROR); 795 if(!result) 796 connssl->connecting_state = ssl_connect_3; 797 close_async_handshake(connssl); 798 return result; 799 } 800 801 802 static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) 803 { 804 struct SessionHandle *data = conn->data; 805 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 806 const gsk_cert_data_elem *cdev; 807 int cdec; 808 const gsk_cert_data_elem *p; 809 const char *cert = (const char *) NULL; 810 const char *certend; 811 const char *ptr; 812 int i; 813 CURLcode result; 814 815 /* SSL handshake done: gather certificate info and verify host. */ 816 817 if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle, 818 GSK_PARTNER_CERT_INFO, 819 &cdev, &cdec), 820 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == 821 CURLE_OK) { 822 infof(data, "Server certificate:\n"); 823 p = cdev; 824 for(i = 0; i++ < cdec; p++) 825 switch (p->cert_data_id) { 826 case CERT_BODY_DER: 827 cert = p->cert_data_p; 828 certend = cert + cdev->cert_data_l; 829 break; 830 case CERT_DN_PRINTABLE: 831 infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p); 832 break; 833 case CERT_ISSUER_DN_PRINTABLE: 834 infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p); 835 break; 836 case CERT_VALID_FROM: 837 infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p); 838 break; 839 case CERT_VALID_TO: 840 infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p); 841 break; 842 } 843 } 844 845 /* Verify host. */ 846 result = Curl_verifyhost(conn, cert, certend); 847 if(result) 848 return result; 849 850 /* The only place GSKit can get the whole CA chain is a validation 851 callback where no user data pointer is available. Therefore it's not 852 possible to copy this chain into our structures for CAINFO. 853 However the server certificate may be available, thus we can return 854 info about it. */ 855 if(data->set.ssl.certinfo) { 856 result = Curl_ssl_init_certinfo(data, 1); 857 if(result) 858 return result; 859 860 if(cert) { 861 result = Curl_extract_certinfo(conn, 0, cert, certend); 862 if(result) 863 return result; 864 } 865 } 866 867 /* Check pinned public key. */ 868 ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 869 if(!result && ptr) { 870 curl_X509certificate x509; 871 curl_asn1Element *p; 872 873 if(!cert) 874 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 875 Curl_parseX509(&x509, cert, certend); 876 p = &x509.subjectPublicKeyInfo; 877 result = Curl_pin_peer_pubkey(ptr, p->header, p->end - p->header); 878 if(result) { 879 failf(data, "SSL: public key does not match pinned public key!"); 880 return result; 881 } 882 } 883 884 connssl->connecting_state = ssl_connect_done; 885 return CURLE_OK; 886 } 887 888 889 static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, 890 bool nonblocking, bool *done) 891 { 892 struct SessionHandle *data = conn->data; 893 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 894 long timeout_ms; 895 Qso_OverlappedIO_t cstat; 896 CURLcode result = CURLE_OK; 897 898 *done = connssl->state == ssl_connection_complete; 899 if(*done) 900 return CURLE_OK; 901 902 /* Step 1: create session, start handshake. */ 903 if(connssl->connecting_state == ssl_connect_1) { 904 /* check allowed time left */ 905 timeout_ms = Curl_timeleft(data, NULL, TRUE); 906 907 if(timeout_ms < 0) { 908 /* no need to continue if time already is up */ 909 failf(data, "SSL connection timeout"); 910 result = CURLE_OPERATION_TIMEDOUT; 911 } 912 else 913 result = gskit_connect_step1(conn, sockindex); 914 } 915 916 /* Step 2: check if handshake is over. */ 917 if(!result && connssl->connecting_state == ssl_connect_2) { 918 /* check allowed time left */ 919 timeout_ms = Curl_timeleft(data, NULL, TRUE); 920 921 if(timeout_ms < 0) { 922 /* no need to continue if time already is up */ 923 failf(data, "SSL connection timeout"); 924 result = CURLE_OPERATION_TIMEDOUT; 925 } 926 else 927 result = gskit_connect_step2(conn, sockindex, nonblocking); 928 } 929 930 /* Step 3: gather certificate info, verify host. */ 931 if(!result && connssl->connecting_state == ssl_connect_3) 932 result = gskit_connect_step3(conn, sockindex); 933 934 if(result) 935 close_one(connssl, data); 936 else if(connssl->connecting_state == ssl_connect_done) { 937 connssl->state = ssl_connection_complete; 938 connssl->connecting_state = ssl_connect_1; 939 conn->recv[sockindex] = gskit_recv; 940 conn->send[sockindex] = gskit_send; 941 *done = TRUE; 942 } 943 944 return result; 945 } 946 947 948 CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, 949 int sockindex, 950 bool *done) 951 { 952 CURLcode result; 953 954 result = gskit_connect_common(conn, sockindex, TRUE, done); 955 if(*done || result) 956 conn->ssl[sockindex].connecting_state = ssl_connect_1; 957 return result; 958 } 959 960 961 CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) 962 { 963 CURLcode result; 964 bool done; 965 966 conn->ssl[sockindex].connecting_state = ssl_connect_1; 967 result = gskit_connect_common(conn, sockindex, FALSE, &done); 968 if(result) 969 return result; 970 971 DEBUGASSERT(done); 972 973 return CURLE_OK; 974 } 975 976 977 void Curl_gskit_close(struct connectdata *conn, int sockindex) 978 { 979 struct SessionHandle *data = conn->data; 980 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 981 982 if(connssl->use) 983 close_one(connssl, data); 984 } 985 986 987 int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) 988 { 989 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 990 struct SessionHandle *data = conn->data; 991 ssize_t nread; 992 int what; 993 int rc; 994 char buf[120]; 995 996 if(!connssl->handle) 997 return 0; 998 999 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) 1000 return 0; 1001 1002 close_one(connssl, data); 1003 rc = 0; 1004 what = Curl_socket_ready(conn->sock[sockindex], 1005 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); 1006 1007 for(;;) { 1008 if(what < 0) { 1009 /* anything that gets here is fatally bad */ 1010 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1011 rc = -1; 1012 break; 1013 } 1014 1015 if(!what) { /* timeout */ 1016 failf(data, "SSL shutdown timeout"); 1017 break; 1018 } 1019 1020 /* Something to read, let's do it and hope that it is the close 1021 notify alert from the server. No way to gsk_secure_soc_read() now, so 1022 use read(). */ 1023 1024 nread = read(conn->sock[sockindex], buf, sizeof(buf)); 1025 1026 if(nread < 0) { 1027 failf(data, "read: %s", strerror(errno)); 1028 rc = -1; 1029 } 1030 1031 if(nread <= 0) 1032 break; 1033 1034 what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0); 1035 } 1036 1037 return rc; 1038 } 1039 1040 1041 size_t Curl_gskit_version(char *buffer, size_t size) 1042 { 1043 strncpy(buffer, "GSKit", size); 1044 return strlen(buffer); 1045 } 1046 1047 1048 int Curl_gskit_check_cxn(struct connectdata *cxn) 1049 { 1050 int err; 1051 int errlen; 1052 1053 /* The only thing that can be tested here is at the socket level. */ 1054 1055 if(!cxn->ssl[FIRSTSOCKET].handle) 1056 return 0; /* connection has been closed */ 1057 1058 err = 0; 1059 errlen = sizeof err; 1060 1061 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, 1062 (unsigned char *) &err, &errlen) || 1063 errlen != sizeof err || err) 1064 return 0; /* connection has been closed */ 1065 1066 return -1; /* connection status unknown */ 1067 } 1068 1069 #endif /* USE_GSKIT */ 1070