Home | History | Annotate | Download | only in vtls
      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