1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@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 78#define _MPRINTF_REPLACE /* use our functions only */ 79#include <curl/mprintf.h> 80 81#include "curl_memory.h" 82/* The last #include file should be: */ 83#include "memdebug.h" 84 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 100/* Supported ciphers. */ 101typedef struct { 102 const char *name; /* Cipher name. */ 103 const char *gsktoken; /* Corresponding token for GSKit String. */ 104 unsigned int versions; /* SSL version flags. */ 105} gskit_cipher; 106 107static const gskit_cipher ciphertable[] = { 108 { "null-md5", "01", 109 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 110 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 111 { "null-sha", "02", 112 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 113 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 114 { "exp-rc4-md5", "03", 115 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, 116 { "rc4-md5", "04", 117 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 118 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 119 { "rc4-sha", "05", 120 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 121 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 122 { "exp-rc2-cbc-md5", "06", 123 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, 124 { "exp-des-cbc-sha", "09", 125 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 126 CURL_GSKPROTO_TLSV11_MASK }, 127 { "des-cbc3-sha", "0A", 128 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 129 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, 130 { "aes128-sha", "2F", 131 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | 132 CURL_GSKPROTO_TLSV12_MASK }, 133 { "aes256-sha", "35", 134 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | 135 CURL_GSKPROTO_TLSV12_MASK }, 136 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK }, 137 { "aes128-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, 138 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, 139 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK }, 140 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK }, 141 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK }, 142 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK }, 143 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK }, 144 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK }, 145 { (const char *) NULL, (const char *) NULL, 0 } 146}; 147 148 149static bool is_separator(char c) 150{ 151 /* Return whether character is a cipher list separator. */ 152 switch (c) { 153 case ' ': 154 case '\t': 155 case ':': 156 case ',': 157 case ';': 158 return true; 159 } 160 return false; 161} 162 163 164static CURLcode gskit_status(struct SessionHandle *data, int rc, 165 const char *procname, CURLcode defcode) 166{ 167 CURLcode cc; 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 209static 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 231static 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 253static 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 273static 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 292static 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 cc; 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 cc = 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 cc = 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 cc = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS, 376 ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE); 377 if(cc == CURLE_UNSUPPORTED_PROTOCOL) { 378 cc = CURLE_OK; 379 if(unsupported) { 380 failf(data, "TLSv1.1-only ciphers are not yet supported"); 381 cc = CURLE_SSL_CIPHER; 382 } 383 } 384 } 385 if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) { 386 cc = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS, 387 ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE); 388 if(cc == CURLE_UNSUPPORTED_PROTOCOL) { 389 cc = CURLE_OK; 390 if(unsupported) { 391 failf(data, "TLSv1.2-only ciphers are not yet supported"); 392 cc = 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(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) { 400 cc = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS, 401 ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE); 402 if(cc == CURLE_UNSUPPORTED_PROTOCOL) { 403 cc = 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(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV3_MASK)) 411 cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS, 412 ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE); 413 if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV2_MASK)) 414 cc = 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 cc; 422} 423 424 425int Curl_gskit_init(void) 426{ 427 /* No initialisation needed. */ 428 429 return 1; 430} 431 432 433void Curl_gskit_cleanup(void) 434{ 435 /* Nothing to do. */ 436} 437 438 439static 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 c; 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 c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); 462 if(c == CURLE_OK && appid) 463 c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); 464 if(c == CURLE_OK && file) 465 c = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); 466 if(c == CURLE_OK && label) 467 c = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); 468 if(c == CURLE_OK && password) 469 c = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); 470 471 if(c == CURLE_OK) { 472 /* Locate CAs, Client certificate and key according to our settings. 473 Note: this call may be blocking for some tenths of seconds. */ 474 c = gskit_status(data, gsk_environment_init(h), 475 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM); 476 if(c == CURLE_OK) { 477 *envir = h; 478 return c; 479 } 480 } 481 /* Error: rollback. */ 482 gsk_environment_close(&h); 483 return c; 484} 485 486 487static 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 497static void close_async_handshake(struct ssl_connect_data *connssl) 498{ 499 QsoDestroyIOCompletionPort(connssl->iocport); 500 connssl->iocport = -1; 501} 502 503 504static 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 517static 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 536static 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 556static 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 cc; 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 cc = init_environment(data, &envir, (const char *) NULL, 604 keyringfile, keyringlabel, keyringpwd); 605 if(cc != CURLE_OK) 606 return cc; 607 } 608 609 /* Create secure session. */ 610 cc = 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(cc != CURLE_OK) 614 return cc; 615 616 /* Determine which SSL/TLS version should be enabled. */ 617 protoflags = CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | 618 CURL_GSKPROTO_TLSV11_MASK | 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_SSLV2_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 cc = set_buffer(data, connssl->handle, 647 GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); 648 if(cc == CURLE_UNSUPPORTED_PROTOCOL) 649 cc = CURLE_OK; 650 } 651 652 /* Set session parameters. */ 653 if(cc == CURLE_OK) { 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 cc = CURLE_OPERATION_TIMEDOUT; 659 else 660 cc = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT, 661 (timeout + 999) / 1000); 662 } 663 if(cc == CURLE_OK) 664 cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); 665 if(cc == CURLE_OK) 666 cc = set_ciphers(data, connssl->handle, &protoflags); 667 if(!protoflags) { 668 failf(data, "No SSL protocol/cipher combination enabled"); 669 cc = CURLE_SSL_CIPHER; 670 } 671 if(cc == CURLE_OK) 672 cc = 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(cc == CURLE_OK) 676 cc = 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(cc == CURLE_OK) 680 cc = 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(cc == CURLE_OK) { 684 cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11, 685 (protoflags & CURL_GSKPROTO_TLSV11_MASK)? 686 GSK_TRUE: GSK_FALSE, TRUE); 687 if(cc == CURLE_UNSUPPORTED_PROTOCOL) { 688 cc = CURLE_OK; 689 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { 690 failf(data, "TLS 1.1 not yet supported"); 691 cc = CURLE_SSL_CIPHER; 692 } 693 } 694 } 695 if(cc == CURLE_OK) { 696 cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12, 697 (protoflags & CURL_GSKPROTO_TLSV12_MASK)? 698 GSK_TRUE: GSK_FALSE, TRUE); 699 if(cc == CURLE_UNSUPPORTED_PROTOCOL) { 700 cc = CURLE_OK; 701 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { 702 failf(data, "TLS 1.2 not yet supported"); 703 cc = CURLE_SSL_CIPHER; 704 } 705 } 706 } 707 if(cc == CURLE_OK) 708 cc = 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(cc == CURLE_OK) { 713 /* Start handshake. Try asynchronous first. */ 714 memset(&commarea, 0, sizeof commarea); 715 connssl->iocport = QsoCreateIOCompletionPort(); 716 if(connssl->iocport != -1) { 717 cc = gskit_status(data, gsk_secure_soc_startInit(connssl->handle, 718 connssl->iocport, &commarea), 719 "gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR); 720 if(cc == CURLE_OK) { 721 connssl->connecting_state = ssl_connect_2; 722 return CURLE_OK; 723 } 724 else 725 close_async_handshake(connssl); 726 } 727 else if(errno != ENOBUFS) 728 cc = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); 729 else { 730 /* No more completion port available. Use synchronous IO. */ 731 cc = gskit_status(data, gsk_secure_soc_init(connssl->handle), 732 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); 733 if(cc == CURLE_OK) { 734 connssl->connecting_state = ssl_connect_3; 735 return CURLE_OK; 736 } 737 } 738 } 739 740 /* Error: rollback. */ 741 close_one(connssl, data); 742 return cc; 743} 744 745 746static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, 747 bool nonblocking) 748{ 749 struct SessionHandle *data = conn->data; 750 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 751 Qso_OverlappedIO_t cstat; 752 long timeout_ms; 753 struct timeval stmv; 754 CURLcode cc; 755 756 /* Poll or wait for end of SSL asynchronous handshake. */ 757 758 for(;;) { 759 timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE); 760 if(timeout_ms < 0) 761 timeout_ms = 0; 762 stmv.tv_sec = timeout_ms / 1000; 763 stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; 764 switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) { 765 case 1: /* Operation complete. */ 766 break; 767 case -1: /* An error occurred: handshake still in progress. */ 768 if(errno == EINTR) { 769 if(nonblocking) 770 return CURLE_OK; 771 continue; /* Retry. */ 772 } 773 if(errno != ETIME) { 774 failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); 775 cancel_async_handshake(conn, sockindex); 776 close_async_handshake(connssl); 777 return CURLE_SSL_CONNECT_ERROR; 778 } 779 /* FALL INTO... */ 780 case 0: /* Handshake in progress, timeout occurred. */ 781 if(nonblocking) 782 return CURLE_OK; 783 cancel_async_handshake(conn, sockindex); 784 close_async_handshake(connssl); 785 return CURLE_OPERATION_TIMEDOUT; 786 } 787 break; 788 } 789 cc = gskit_status(data, cstat.returnValue, "SSL handshake", 790 CURLE_SSL_CONNECT_ERROR); 791 if(cc == CURLE_OK) 792 connssl->connecting_state = ssl_connect_3; 793 close_async_handshake(connssl); 794 return cc; 795} 796 797 798static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) 799{ 800 struct SessionHandle *data = conn->data; 801 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 802 const gsk_cert_data_elem *cdev; 803 int cdec; 804 const gsk_cert_data_elem *p; 805 const char *cert = (const char *) NULL; 806 const char *certend; 807 int i; 808 CURLcode cc; 809 810 /* SSL handshake done: gather certificate info and verify host. */ 811 812 if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle, 813 GSK_PARTNER_CERT_INFO, 814 &cdev, &cdec), 815 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) == 816 CURLE_OK) { 817 infof(data, "Server certificate:\n"); 818 p = cdev; 819 for(i = 0; i++ < cdec; p++) 820 switch (p->cert_data_id) { 821 case CERT_BODY_DER: 822 cert = p->cert_data_p; 823 certend = cert + cdev->cert_data_l; 824 break; 825 case CERT_DN_PRINTABLE: 826 infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p); 827 break; 828 case CERT_ISSUER_DN_PRINTABLE: 829 infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p); 830 break; 831 case CERT_VALID_FROM: 832 infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p); 833 break; 834 case CERT_VALID_TO: 835 infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p); 836 break; 837 } 838 } 839 840 /* Verify host. */ 841 cc = Curl_verifyhost(conn, cert, certend); 842 if(cc != CURLE_OK) 843 return cc; 844 845 /* The only place GSKit can get the whole CA chain is a validation 846 callback where no user data pointer is available. Therefore it's not 847 possible to copy this chain into our structures for CAINFO. 848 However the server certificate may be available, thus we can return 849 info about it. */ 850 if(data->set.ssl.certinfo) { 851 if(Curl_ssl_init_certinfo(data, 1)) 852 return CURLE_OUT_OF_MEMORY; 853 if(cert) { 854 cc = Curl_extract_certinfo(conn, 0, cert, certend); 855 if(cc != CURLE_OK) 856 return cc; 857 } 858 } 859 860 connssl->connecting_state = ssl_connect_done; 861 return CURLE_OK; 862} 863 864 865static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, 866 bool nonblocking, bool *done) 867{ 868 struct SessionHandle *data = conn->data; 869 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 870 long timeout_ms; 871 Qso_OverlappedIO_t cstat; 872 CURLcode cc = CURLE_OK; 873 874 *done = connssl->state == ssl_connection_complete; 875 if(*done) 876 return CURLE_OK; 877 878 /* Step 1: create session, start handshake. */ 879 if(connssl->connecting_state == ssl_connect_1) { 880 /* check allowed time left */ 881 timeout_ms = Curl_timeleft(data, NULL, TRUE); 882 883 if(timeout_ms < 0) { 884 /* no need to continue if time already is up */ 885 failf(data, "SSL connection timeout"); 886 cc = CURLE_OPERATION_TIMEDOUT; 887 } 888 else 889 cc = gskit_connect_step1(conn, sockindex); 890 } 891 892 /* Step 2: check if handshake is over. */ 893 if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_2) { 894 /* check allowed time left */ 895 timeout_ms = Curl_timeleft(data, NULL, TRUE); 896 897 if(timeout_ms < 0) { 898 /* no need to continue if time already is up */ 899 failf(data, "SSL connection timeout"); 900 cc = CURLE_OPERATION_TIMEDOUT; 901 } 902 else 903 cc = gskit_connect_step2(conn, sockindex, nonblocking); 904 } 905 906 /* Step 3: gather certificate info, verify host. */ 907 if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_3) 908 cc = gskit_connect_step3(conn, sockindex); 909 910 if(cc != CURLE_OK) 911 close_one(connssl, data); 912 else if(connssl->connecting_state == ssl_connect_done) { 913 connssl->state = ssl_connection_complete; 914 connssl->connecting_state = ssl_connect_1; 915 conn->recv[sockindex] = gskit_recv; 916 conn->send[sockindex] = gskit_send; 917 *done = TRUE; 918 } 919 920 return cc; 921} 922 923 924CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn, 925 int sockindex, 926 bool *done) 927{ 928 CURLcode cc; 929 930 cc = gskit_connect_common(conn, sockindex, TRUE, done); 931 if(*done || cc != CURLE_OK) 932 conn->ssl[sockindex].connecting_state = ssl_connect_1; 933 return cc; 934} 935 936 937CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) 938{ 939 CURLcode retcode; 940 bool done; 941 942 conn->ssl[sockindex].connecting_state = ssl_connect_1; 943 retcode = gskit_connect_common(conn, sockindex, FALSE, &done); 944 if(retcode) 945 return retcode; 946 947 DEBUGASSERT(done); 948 949 return CURLE_OK; 950} 951 952 953void Curl_gskit_close(struct connectdata *conn, int sockindex) 954{ 955 struct SessionHandle *data = conn->data; 956 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 957 958 if(connssl->use) 959 close_one(connssl, data); 960} 961 962 963int Curl_gskit_close_all(struct SessionHandle *data) 964{ 965 /* Unimplemented. */ 966 (void) data; 967 return 0; 968} 969 970 971int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) 972{ 973 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 974 struct SessionHandle *data = conn->data; 975 ssize_t nread; 976 int what; 977 int rc; 978 char buf[120]; 979 980 if(!connssl->handle) 981 return 0; 982 983 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) 984 return 0; 985 986 close_one(connssl, data); 987 rc = 0; 988 what = Curl_socket_ready(conn->sock[sockindex], 989 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); 990 991 for(;;) { 992 if(what < 0) { 993 /* anything that gets here is fatally bad */ 994 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 995 rc = -1; 996 break; 997 } 998 999 if(!what) { /* timeout */ 1000 failf(data, "SSL shutdown timeout"); 1001 break; 1002 } 1003 1004 /* Something to read, let's do it and hope that it is the close 1005 notify alert from the server. No way to gsk_secure_soc_read() now, so 1006 use read(). */ 1007 1008 nread = read(conn->sock[sockindex], buf, sizeof(buf)); 1009 1010 if(nread < 0) { 1011 failf(data, "read: %s", strerror(errno)); 1012 rc = -1; 1013 } 1014 1015 if(nread <= 0) 1016 break; 1017 1018 what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0); 1019 } 1020 1021 return rc; 1022} 1023 1024 1025size_t Curl_gskit_version(char *buffer, size_t size) 1026{ 1027 strncpy(buffer, "GSKit", size); 1028 return strlen(buffer); 1029} 1030 1031 1032int Curl_gskit_check_cxn(struct connectdata *cxn) 1033{ 1034 int err; 1035 int errlen; 1036 1037 /* The only thing that can be tested here is at the socket level. */ 1038 1039 if(!cxn->ssl[FIRSTSOCKET].handle) 1040 return 0; /* connection has been closed */ 1041 1042 err = 0; 1043 errlen = sizeof err; 1044 1045 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, 1046 (unsigned char *) &err, &errlen) || 1047 errlen != sizeof err || err) 1048 return 0; /* connection has been closed */ 1049 1050 return -1; /* connection status unknown */ 1051} 1052 1053#endif /* USE_GSKIT */ 1054