gskit.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 #include "curl_setup.h"
00024 
00025 #ifdef USE_GSKIT
00026 
00027 #include <gskssl.h>
00028 #include <qsoasync.h>
00029 
00030 /* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
00031 #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
00032 #define GSK_SSL_EXTN_SERVERNAME_REQUEST         230
00033 #endif
00034 
00035 #ifndef GSK_TLSV10_CIPHER_SPECS
00036 #define GSK_TLSV10_CIPHER_SPECS                 236
00037 #endif
00038 
00039 #ifndef GSK_TLSV11_CIPHER_SPECS
00040 #define GSK_TLSV11_CIPHER_SPECS                 237
00041 #endif
00042 
00043 #ifndef GSK_TLSV12_CIPHER_SPECS
00044 #define GSK_TLSV12_CIPHER_SPECS                 238
00045 #endif
00046 
00047 #ifndef GSK_PROTOCOL_TLSV11
00048 #define GSK_PROTOCOL_TLSV11                     437
00049 #endif
00050 
00051 #ifndef GSK_PROTOCOL_TLSV12
00052 #define GSK_PROTOCOL_TLSV12                     438
00053 #endif
00054 
00055 #ifndef GSK_FALSE
00056 #define GSK_FALSE                               0
00057 #endif
00058 
00059 #ifndef GSK_TRUE
00060 #define GSK_TRUE                                1
00061 #endif
00062 
00063 
00064 #ifdef HAVE_LIMITS_H
00065 #  include <limits.h>
00066 #endif
00067 
00068 #include <curl/curl.h>
00069 #include "urldata.h"
00070 #include "sendf.h"
00071 #include "gskit.h"
00072 #include "vtls.h"
00073 #include "connect.h" /* for the connect timeout */
00074 #include "select.h"
00075 #include "strcase.h"
00076 #include "x509asn1.h"
00077 #include "curl_printf.h"
00078 
00079 #include "curl_memory.h"
00080 /* The last #include file should be: */
00081 #include "memdebug.h"
00082 
00083 
00084 /* Directions. */
00085 #define SOS_READ        0x01
00086 #define SOS_WRITE       0x02
00087 
00088 /* SSL version flags. */
00089 #define CURL_GSKPROTO_SSLV2     0
00090 #define CURL_GSKPROTO_SSLV2_MASK        (1 << CURL_GSKPROTO_SSLV2)
00091 #define CURL_GSKPROTO_SSLV3     1
00092 #define CURL_GSKPROTO_SSLV3_MASK        (1 << CURL_GSKPROTO_SSLV3)
00093 #define CURL_GSKPROTO_TLSV10    2
00094 #define CURL_GSKPROTO_TLSV10_MASK        (1 << CURL_GSKPROTO_TLSV10)
00095 #define CURL_GSKPROTO_TLSV11    3
00096 #define CURL_GSKPROTO_TLSV11_MASK        (1 << CURL_GSKPROTO_TLSV11)
00097 #define CURL_GSKPROTO_TLSV12    4
00098 #define CURL_GSKPROTO_TLSV12_MASK        (1 << CURL_GSKPROTO_TLSV12)
00099 #define CURL_GSKPROTO_LAST      5
00100 
00101 
00102 /* Supported ciphers. */
00103 typedef struct {
00104   const char *name;            /* Cipher name. */
00105   const char *gsktoken;        /* Corresponding token for GSKit String. */
00106   unsigned int versions;       /* SSL version flags. */
00107 }  gskit_cipher;
00108 
00109 static const gskit_cipher  ciphertable[] = {
00110   { "null-md5",         "01",
00111       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00112       CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00113   { "null-sha",         "02",
00114       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00115       CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00116   { "exp-rc4-md5",      "03",
00117       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
00118   { "rc4-md5",          "04",
00119       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00120       CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00121   { "rc4-sha",          "05",
00122       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00123       CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00124   { "exp-rc2-cbc-md5",  "06",
00125       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
00126   { "exp-des-cbc-sha",  "09",
00127       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00128       CURL_GSKPROTO_TLSV11_MASK },
00129   { "des-cbc3-sha",     "0A",
00130       CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00131       CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00132   { "aes128-sha",       "2F",
00133       CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
00134       CURL_GSKPROTO_TLSV12_MASK },
00135   { "aes256-sha",       "35",
00136       CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
00137       CURL_GSKPROTO_TLSV12_MASK },
00138   { "null-sha256",      "3B",   CURL_GSKPROTO_TLSV12_MASK },
00139   { "aes128-sha256",    "3C",   CURL_GSKPROTO_TLSV12_MASK },
00140   { "aes256-sha256",    "3D",   CURL_GSKPROTO_TLSV12_MASK },
00141   { "aes128-gcm-sha256",
00142                         "9C",   CURL_GSKPROTO_TLSV12_MASK },
00143   { "aes256-gcm-sha384",
00144                         "9D",   CURL_GSKPROTO_TLSV12_MASK },
00145   { "rc4-md5",          "1",    CURL_GSKPROTO_SSLV2_MASK },
00146   { "exp-rc4-md5",      "2",    CURL_GSKPROTO_SSLV2_MASK },
00147   { "rc2-md5",          "3",    CURL_GSKPROTO_SSLV2_MASK },
00148   { "exp-rc2-md5",      "4",    CURL_GSKPROTO_SSLV2_MASK },
00149   { "des-cbc-md5",      "6",    CURL_GSKPROTO_SSLV2_MASK },
00150   { "des-cbc3-md5",     "7",    CURL_GSKPROTO_SSLV2_MASK },
00151   { (const char *) NULL, (const char *) NULL, 0       }
00152 };
00153 
00154 
00155 static bool is_separator(char c)
00156 {
00157   /* Return whether character is a cipher list separator. */
00158   switch(c) {
00159   case ' ':
00160   case '\t':
00161   case ':':
00162   case ',':
00163   case ';':
00164     return true;
00165   }
00166   return false;
00167 }
00168 
00169 
00170 static CURLcode gskit_status(struct Curl_easy *data, int rc,
00171                              const char *procname, CURLcode defcode)
00172 {
00173   /* Process GSKit status and map it to a CURLcode. */
00174   switch(rc) {
00175   case GSK_OK:
00176   case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
00177     return CURLE_OK;
00178   case GSK_KEYRING_OPEN_ERROR:
00179   case GSK_OS400_ERROR_NO_ACCESS:
00180     return CURLE_SSL_CACERT_BADFILE;
00181   case GSK_INSUFFICIENT_STORAGE:
00182     return CURLE_OUT_OF_MEMORY;
00183   case GSK_ERROR_BAD_V2_CIPHER:
00184   case GSK_ERROR_BAD_V3_CIPHER:
00185   case GSK_ERROR_NO_CIPHERS:
00186     return CURLE_SSL_CIPHER;
00187   case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
00188   case GSK_ERROR_CERT_VALIDATION:
00189     return CURLE_PEER_FAILED_VERIFICATION;
00190   case GSK_OS400_ERROR_TIMED_OUT:
00191     return CURLE_OPERATION_TIMEDOUT;
00192   case GSK_WOULD_BLOCK:
00193     return CURLE_AGAIN;
00194   case GSK_OS400_ERROR_NOT_REGISTERED:
00195     break;
00196   case GSK_ERROR_IO:
00197     switch(errno) {
00198     case ENOMEM:
00199       return CURLE_OUT_OF_MEMORY;
00200     default:
00201       failf(data, "%s I/O error: %s", procname, strerror(errno));
00202       break;
00203     }
00204     break;
00205   default:
00206     failf(data, "%s: %s", procname, gsk_strerror(rc));
00207     break;
00208   }
00209   return defcode;
00210 }
00211 
00212 
00213 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
00214                 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
00215 {
00216   int rc = gsk_attribute_set_enum(h, id, value);
00217 
00218   switch(rc) {
00219   case GSK_OK:
00220     return CURLE_OK;
00221   case GSK_ERROR_IO:
00222     failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
00223     break;
00224   case GSK_ATTRIBUTE_INVALID_ID:
00225     if(unsupported_ok)
00226       return CURLE_UNSUPPORTED_PROTOCOL;
00227   default:
00228     failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
00229     break;
00230   }
00231   return CURLE_SSL_CONNECT_ERROR;
00232 }
00233 
00234 
00235 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
00236                         GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
00237 {
00238   int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
00239 
00240   switch(rc) {
00241   case GSK_OK:
00242     return CURLE_OK;
00243   case GSK_ERROR_IO:
00244     failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
00245     break;
00246   case GSK_ATTRIBUTE_INVALID_ID:
00247     if(unsupported_ok)
00248       return CURLE_UNSUPPORTED_PROTOCOL;
00249   default:
00250     failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
00251     break;
00252   }
00253   return CURLE_SSL_CONNECT_ERROR;
00254 }
00255 
00256 
00257 static CURLcode set_numeric(struct Curl_easy *data,
00258                             gsk_handle h, GSK_NUM_ID id, int value)
00259 {
00260   int rc = gsk_attribute_set_numeric_value(h, id, value);
00261 
00262   switch(rc) {
00263   case GSK_OK:
00264     return CURLE_OK;
00265   case GSK_ERROR_IO:
00266     failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
00267           strerror(errno));
00268     break;
00269   default:
00270     failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
00271     break;
00272   }
00273   return CURLE_SSL_CONNECT_ERROR;
00274 }
00275 
00276 
00277 static CURLcode set_callback(struct Curl_easy *data,
00278                              gsk_handle h, GSK_CALLBACK_ID id, void *info)
00279 {
00280   int rc = gsk_attribute_set_callback(h, id, info);
00281 
00282   switch(rc) {
00283   case GSK_OK:
00284     return CURLE_OK;
00285   case GSK_ERROR_IO:
00286     failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
00287     break;
00288   default:
00289     failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
00290     break;
00291   }
00292   return CURLE_SSL_CONNECT_ERROR;
00293 }
00294 
00295 
00296 static CURLcode set_ciphers(struct connectdata *conn,
00297                                         gsk_handle h, unsigned int *protoflags)
00298 {
00299   struct Curl_easy *data = conn->data;
00300   const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
00301   const char *clp;
00302   const gskit_cipher *ctp;
00303   int i;
00304   int l;
00305   bool unsupported;
00306   CURLcode result;
00307   struct {
00308     char *buf;
00309     char *ptr;
00310   } ciphers[CURL_GSKPROTO_LAST];
00311 
00312   /* Compile cipher list into GSKit-compatible cipher lists. */
00313 
00314   if(!cipherlist)
00315     return CURLE_OK;
00316   while(is_separator(*cipherlist))     /* Skip initial separators. */
00317     cipherlist++;
00318   if(!*cipherlist)
00319     return CURLE_OK;
00320 
00321   /* We allocate GSKit buffers of the same size as the input string: since
00322      GSKit tokens are always shorter than their cipher names, allocated buffers
00323      will always be large enough to accomodate the result. */
00324   l = strlen(cipherlist) + 1;
00325   memset((char *) ciphers, 0, sizeof ciphers);
00326   for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
00327     ciphers[i].buf = malloc(l);
00328     if(!ciphers[i].buf) {
00329       while(i--)
00330         free(ciphers[i].buf);
00331       return CURLE_OUT_OF_MEMORY;
00332     }
00333     ciphers[i].ptr = ciphers[i].buf;
00334     *ciphers[i].ptr = '\0';
00335   }
00336 
00337   /* Process each cipher in input string. */
00338   unsupported = FALSE;
00339   result = CURLE_OK;
00340   for(;;) {
00341     for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
00342       cipherlist++;
00343     l = cipherlist - clp;
00344     if(!l)
00345       break;
00346     /* Search the cipher in our table. */
00347     for(ctp = ciphertable; ctp->name; ctp++)
00348       if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
00349         break;
00350     if(!ctp->name) {
00351       failf(data, "Unknown cipher %.*s", l, clp);
00352       result = CURLE_SSL_CIPHER;
00353     }
00354     else {
00355       unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
00356                         CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
00357       for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
00358         if(ctp->versions & (1 << i)) {
00359           strcpy(ciphers[i].ptr, ctp->gsktoken);
00360           ciphers[i].ptr += strlen(ctp->gsktoken);
00361         }
00362       }
00363     }
00364 
00365    /* Advance to next cipher name or end of string. */
00366     while(is_separator(*cipherlist))
00367       cipherlist++;
00368   }
00369 
00370   /* Disable protocols with empty cipher lists. */
00371   for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
00372     if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
00373       *protoflags &= ~(1 << i);
00374       ciphers[i].buf[0] = '\0';
00375     }
00376   }
00377 
00378   /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
00379   if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
00380     result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
00381                         ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
00382     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00383       result = CURLE_OK;
00384       if(unsupported) {
00385         failf(data, "TLSv1.1-only ciphers are not yet supported");
00386         result = CURLE_SSL_CIPHER;
00387       }
00388     }
00389   }
00390   if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
00391     result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
00392                         ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
00393     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00394       result = CURLE_OK;
00395       if(unsupported) {
00396         failf(data, "TLSv1.2-only ciphers are not yet supported");
00397         result = CURLE_SSL_CIPHER;
00398       }
00399     }
00400   }
00401 
00402   /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
00403      the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
00404   if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
00405     result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
00406                         ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
00407     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00408       result = CURLE_OK;
00409       strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
00410              ciphers[CURL_GSKPROTO_TLSV10].ptr);
00411     }
00412   }
00413 
00414   /* Set-up other ciphers. */
00415   if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
00416     result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
00417                         ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
00418   if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
00419     result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
00420                         ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
00421 
00422   /* Clean-up. */
00423   for(i = 0; i < CURL_GSKPROTO_LAST; i++)
00424     free(ciphers[i].buf);
00425 
00426   return result;
00427 }
00428 
00429 
00430 int Curl_gskit_init(void)
00431 {
00432   /* No initialisation needed. */
00433 
00434   return 1;
00435 }
00436 
00437 
00438 void Curl_gskit_cleanup(void)
00439 {
00440   /* Nothing to do. */
00441 }
00442 
00443 
00444 static CURLcode init_environment(struct Curl_easy *data,
00445                                  gsk_handle *envir, const char *appid,
00446                                  const char *file, const char *label,
00447                                  const char *password)
00448 {
00449   int rc;
00450   CURLcode result;
00451   gsk_handle h;
00452 
00453   /* Creates the GSKit environment. */
00454 
00455   rc = gsk_environment_open(&h);
00456   switch(rc) {
00457   case GSK_OK:
00458     break;
00459   case GSK_INSUFFICIENT_STORAGE:
00460     return CURLE_OUT_OF_MEMORY;
00461   default:
00462     failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
00463     return CURLE_SSL_CONNECT_ERROR;
00464   }
00465 
00466   result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
00467   if(!result && appid)
00468     result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
00469   if(!result && file)
00470     result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
00471   if(!result && label)
00472     result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
00473   if(!result && password)
00474     result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
00475 
00476   if(!result) {
00477     /* Locate CAs, Client certificate and key according to our settings.
00478        Note: this call may be blocking for some tenths of seconds. */
00479     result = gskit_status(data, gsk_environment_init(h),
00480                           "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
00481     if(!result) {
00482       *envir = h;
00483       return result;
00484     }
00485   }
00486   /* Error: rollback. */
00487   gsk_environment_close(&h);
00488   return result;
00489 }
00490 
00491 
00492 static void cancel_async_handshake(struct connectdata *conn, int sockindex)
00493 {
00494   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00495   Qso_OverlappedIO_t cstat;
00496 
00497   if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
00498     QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
00499 }
00500 
00501 
00502 static void close_async_handshake(struct ssl_connect_data *connssl)
00503 {
00504   QsoDestroyIOCompletionPort(connssl->iocport);
00505   connssl->iocport = -1;
00506 }
00507 
00508 /* SSL over SSL
00509  * Problems:
00510  * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
00511  *    pipe an SSL stream into another, it is therefore needed to have a pair
00512  *    of such communicating sockets and handle the pipelining explicitly.
00513  * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
00514  *    be used to produce the pipeline.
00515  * The solution is to simulate socketpair() for AF_INET with low-level API
00516  *    listen(), bind() and connect().
00517  */
00518 
00519 static int
00520 inetsocketpair(int sv[2])
00521 {
00522   int lfd;      /* Listening socket. */
00523   int sfd;      /* Server socket. */
00524   int cfd;      /* Client socket. */
00525   int len;
00526   struct sockaddr_in addr1;
00527   struct sockaddr_in addr2;
00528 
00529   /* Create listening socket on a local dynamic port. */
00530   lfd = socket(AF_INET, SOCK_STREAM, 0);
00531   if(lfd < 0)
00532     return -1;
00533   memset((char *) &addr1, 0, sizeof addr1);
00534   addr1.sin_family = AF_INET;
00535   addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00536   addr1.sin_port = 0;
00537   if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
00538      listen(lfd, 2) < 0) {
00539     close(lfd);
00540     return -1;
00541   }
00542 
00543   /* Get the allocated port. */
00544   len = sizeof addr1;
00545   if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
00546     close(lfd);
00547     return -1;
00548   }
00549 
00550   /* Create the client socket. */
00551   cfd = socket(AF_INET, SOCK_STREAM, 0);
00552   if(cfd < 0) {
00553     close(lfd);
00554     return -1;
00555   }
00556 
00557   /* Request unblocking connection to the listening socket. */
00558   curlx_nonblock(cfd, TRUE);
00559   if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
00560      errno != EINPROGRESS) {
00561     close(lfd);
00562     close(cfd);
00563     return -1;
00564   }
00565 
00566   /* Get the client dynamic port for intrusion check below. */
00567   len = sizeof addr2;
00568   if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
00569     close(lfd);
00570     close(cfd);
00571     return -1;
00572   }
00573 
00574   /* Accept the incoming connection and get the server socket. */
00575   curlx_nonblock(lfd, TRUE);
00576   for(;;) {
00577     len = sizeof addr1;
00578     sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
00579     if(sfd < 0) {
00580       close(lfd);
00581       close(cfd);
00582       return -1;
00583     }
00584 
00585     /* Check for possible intrusion from an external process. */
00586     if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
00587        addr1.sin_port == addr2.sin_port)
00588       break;
00589 
00590     /* Intrusion: reject incoming connection. */
00591     close(sfd);
00592   }
00593 
00594   /* Done, return sockets and succeed. */
00595   close(lfd);
00596   curlx_nonblock(cfd, FALSE);
00597   sv[0] = cfd;
00598   sv[1] = sfd;
00599   return 0;
00600 }
00601 
00602 static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
00603                            int directions)
00604 {
00605   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00606   struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
00607   fd_set fds_read;
00608   fd_set fds_write;
00609   int n;
00610   int m;
00611   int i;
00612   int ret = 0;
00613   struct timeval tv = {0, 0};
00614   char buf[CURL_MAX_WRITE_SIZE];
00615 
00616   if(!connssl->use || !connproxyssl->use)
00617     return 0;   /* No SSL over SSL: OK. */
00618 
00619   FD_ZERO(&fds_read);
00620   FD_ZERO(&fds_write);
00621   n = -1;
00622   if(directions & SOS_READ) {
00623     FD_SET(connssl->remotefd, &fds_write);
00624     n = connssl->remotefd;
00625   }
00626   if(directions & SOS_WRITE) {
00627     FD_SET(connssl->remotefd, &fds_read);
00628     n = connssl->remotefd;
00629     FD_SET(conn->sock[sockindex], &fds_write);
00630     if(n < conn->sock[sockindex])
00631       n = conn->sock[sockindex];
00632   }
00633   i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
00634   if(i < 0)
00635     return -1;  /* Select error. */
00636 
00637   if(FD_ISSET(connssl->remotefd, &fds_write)) {
00638     /* Try getting data from HTTPS proxy and pipe it upstream. */
00639     n = 0;
00640     i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
00641     switch(i) {
00642     case GSK_OK:
00643       if(n) {
00644         i = write(connssl->remotefd, buf, n);
00645         if(i < 0)
00646           return -1;
00647         ret = 1;
00648       }
00649       break;
00650     case GSK_OS400_ERROR_TIMED_OUT:
00651     case GSK_WOULD_BLOCK:
00652       break;
00653     default:
00654       return -1;
00655     }
00656   }
00657 
00658   if(FD_ISSET(connssl->remotefd, &fds_read) &&
00659      FD_ISSET(conn->sock[sockindex], &fds_write)) {
00660     /* Pipe data to HTTPS proxy. */
00661     n = read(connssl->remotefd, buf, sizeof buf);
00662     if(n < 0)
00663       return -1;
00664     if(n) {
00665       i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
00666       if(i != GSK_OK || n != m)
00667         return -1;
00668       ret = 1;
00669     }
00670   }
00671 
00672   return ret;  /* OK */
00673 }
00674 
00675 
00676 static void close_one(struct ssl_connect_data *connssl,
00677                       struct connectdata *conn, int sockindex)
00678 {
00679   if(connssl->handle) {
00680     gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
00681               "gsk_secure_soc_close()", 0);
00682     /* Last chance to drain output. */
00683     while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
00684       ;
00685     connssl->handle = (gsk_handle) NULL;
00686     if(connssl->localfd >= 0) {
00687       close(connssl->localfd);
00688       connssl->localfd = -1;
00689     }
00690     if(connssl->remotefd >= 0) {
00691       close(connssl->remotefd);
00692       connssl->remotefd = -1;
00693     }
00694   }
00695   if(connssl->iocport >= 0)
00696     close_async_handshake(connssl);
00697 }
00698 
00699 
00700 static ssize_t gskit_send(struct connectdata *conn, int sockindex,
00701                            const void *mem, size_t len, CURLcode *curlcode)
00702 {
00703   struct Curl_easy *data = conn->data;
00704   CURLcode cc = CURLE_SEND_ERROR;
00705   int written;
00706 
00707   if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
00708     cc = gskit_status(data,
00709                       gsk_secure_soc_write(conn->ssl[sockindex].handle,
00710                                            (char *) mem, (int) len, &written),
00711                       "gsk_secure_soc_write()", CURLE_SEND_ERROR);
00712     if(cc == CURLE_OK)
00713       if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
00714         cc = CURLE_SEND_ERROR;
00715   }
00716   if(cc != CURLE_OK) {
00717     *curlcode = cc;
00718     written = -1;
00719   }
00720   return (ssize_t) written; /* number of bytes */
00721 }
00722 
00723 
00724 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
00725                            size_t buffersize, CURLcode *curlcode)
00726 {
00727   struct Curl_easy *data = conn->data;
00728   int buffsize;
00729   int nread;
00730   CURLcode cc = CURLE_RECV_ERROR;
00731 
00732   if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
00733     buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
00734     cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
00735                                                 buf, buffsize, &nread),
00736                       "gsk_secure_soc_read()", CURLE_RECV_ERROR);
00737   }
00738   switch(cc) {
00739   case CURLE_OK:
00740     break;
00741   case CURLE_OPERATION_TIMEDOUT:
00742     cc = CURLE_AGAIN;
00743   default:
00744     *curlcode = cc;
00745     nread = -1;
00746     break;
00747   }
00748   return (ssize_t) nread;
00749 }
00750 
00751 
00752 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
00753 {
00754   struct Curl_easy *data = conn->data;
00755   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00756   gsk_handle envir;
00757   CURLcode result;
00758   int rc;
00759   const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
00760   const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
00761   const char * const keyringlabel = SSL_SET_OPTION(cert);
00762   const long int ssl_version = SSL_CONN_CONFIG(version);
00763   const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
00764   const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
00765     conn->host.name;
00766   const char *sni;
00767   unsigned int protoflags;
00768   long timeout;
00769   Qso_OverlappedIO_t commarea;
00770   int sockpair[2];
00771   static const int sobufsize = CURL_MAX_WRITE_SIZE;
00772 
00773   /* Create SSL environment, start (preferably asynchronous) handshake. */
00774 
00775   connssl->handle = (gsk_handle) NULL;
00776   connssl->iocport = -1;
00777   connssl->localfd = -1;
00778   connssl->remotefd = -1;
00779 
00780   /* GSKit supports two ways of specifying an SSL context: either by
00781    *  application identifier (that should have been defined at the system
00782    *  level) or by keyring file, password and certificate label.
00783    * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
00784    *  application identifier of the certificate label.
00785    * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
00786    * It is not possible to have different keyrings for the CAs and the
00787    *  local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
00788    *  the keyring file.
00789    * If no key password is given and the keyring is the system keyring,
00790    *  application identifier mode is tried first, as recommended in IBM doc.
00791    */
00792 
00793   envir = (gsk_handle) NULL;
00794 
00795   if(keyringlabel && *keyringlabel && !keyringpwd &&
00796       !strcmp(keyringfile, CURL_CA_BUNDLE)) {
00797     /* Try application identifier mode. */
00798     init_environment(data, &envir, keyringlabel, (const char *) NULL,
00799                      (const char *) NULL, (const char *) NULL);
00800   }
00801 
00802   if(!envir) {
00803     /* Use keyring mode. */
00804     result = init_environment(data, &envir, (const char *) NULL,
00805                               keyringfile, keyringlabel, keyringpwd);
00806     if(result)
00807       return result;
00808   }
00809 
00810   /* Create secure session. */
00811   result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
00812                         "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
00813   gsk_environment_close(&envir);
00814   if(result)
00815     return result;
00816 
00817   /* Establish a pipelining socket pair for SSL over SSL. */
00818   if(conn->proxy_ssl[sockindex].use) {
00819     if(inetsocketpair(sockpair))
00820       return CURLE_SSL_CONNECT_ERROR;
00821     connssl->localfd = sockpair[0];
00822     connssl->remotefd = sockpair[1];
00823     setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
00824                (void *) sobufsize, sizeof sobufsize);
00825     setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
00826                (void *) sobufsize, sizeof sobufsize);
00827     setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
00828                (void *) sobufsize, sizeof sobufsize);
00829     setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
00830                (void *) sobufsize, sizeof sobufsize);
00831     curlx_nonblock(connssl->localfd, TRUE);
00832     curlx_nonblock(connssl->remotefd, TRUE);
00833   }
00834 
00835   /* Determine which SSL/TLS version should be enabled. */
00836   sni = hostname;
00837   switch(ssl_version) {
00838   case CURL_SSLVERSION_SSLv2:
00839     protoflags = CURL_GSKPROTO_SSLV2_MASK;
00840     sni = NULL;
00841     break;
00842   case CURL_SSLVERSION_SSLv3:
00843     protoflags = CURL_GSKPROTO_SSLV3_MASK;
00844     sni = NULL;
00845     break;
00846   case CURL_SSLVERSION_DEFAULT:
00847   case CURL_SSLVERSION_TLSv1:
00848     protoflags = CURL_GSKPROTO_TLSV10_MASK |
00849                  CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
00850     break;
00851   case CURL_SSLVERSION_TLSv1_0:
00852     protoflags = CURL_GSKPROTO_TLSV10_MASK;
00853     break;
00854   case CURL_SSLVERSION_TLSv1_1:
00855     protoflags = CURL_GSKPROTO_TLSV11_MASK;
00856     break;
00857   case CURL_SSLVERSION_TLSv1_2:
00858     protoflags = CURL_GSKPROTO_TLSV12_MASK;
00859     break;
00860   case CURL_SSLVERSION_TLSv1_3:
00861     failf(data, "GSKit: TLS 1.3 is not yet supported");
00862     return CURLE_SSL_CONNECT_ERROR;
00863   default:
00864     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
00865     return CURLE_SSL_CONNECT_ERROR;
00866   }
00867 
00868   /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
00869   if(sni) {
00870     result = set_buffer(data, connssl->handle,
00871                         GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
00872     if(result == CURLE_UNSUPPORTED_PROTOCOL)
00873       result = CURLE_OK;
00874   }
00875 
00876   /* Set session parameters. */
00877   if(!result) {
00878     /* Compute the handshake timeout. Since GSKit granularity is 1 second,
00879        we round up the required value. */
00880     timeout = Curl_timeleft(data, NULL, TRUE);
00881     if(timeout < 0)
00882       result = CURLE_OPERATION_TIMEDOUT;
00883     else
00884       result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
00885                            (timeout + 999) / 1000);
00886   }
00887   if(!result)
00888     result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
00889   if(!result)
00890     result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
00891                          connssl->localfd: conn->sock[sockindex]);
00892   if(!result)
00893     result = set_ciphers(conn, connssl->handle, &protoflags);
00894   if(!protoflags) {
00895     failf(data, "No SSL protocol/cipher combination enabled");
00896     result = CURLE_SSL_CIPHER;
00897   }
00898   if(!result)
00899     result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
00900                       (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
00901                       GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
00902   if(!result)
00903     result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
00904                       (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
00905                       GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
00906   if(!result)
00907     result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
00908                       (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
00909                       GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
00910   if(!result) {
00911     result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
00912                       (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
00913                       GSK_TRUE: GSK_FALSE, TRUE);
00914     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00915       result = CURLE_OK;
00916       if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
00917         failf(data, "TLS 1.1 not yet supported");
00918         result = CURLE_SSL_CIPHER;
00919       }
00920     }
00921   }
00922   if(!result) {
00923     result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
00924                       (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
00925                       GSK_TRUE: GSK_FALSE, TRUE);
00926     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00927       result = CURLE_OK;
00928       if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
00929         failf(data, "TLS 1.2 not yet supported");
00930         result = CURLE_SSL_CIPHER;
00931       }
00932     }
00933   }
00934   if(!result)
00935     result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
00936                       verifypeer? GSK_SERVER_AUTH_FULL:
00937                       GSK_SERVER_AUTH_PASSTHRU, FALSE);
00938 
00939   if(!result) {
00940     /* Start handshake. Try asynchronous first. */
00941     memset(&commarea, 0, sizeof commarea);
00942     connssl->iocport = QsoCreateIOCompletionPort();
00943     if(connssl->iocport != -1) {
00944       result = gskit_status(data,
00945                             gsk_secure_soc_startInit(connssl->handle,
00946                                                      connssl->iocport,
00947                                                      &commarea),
00948                             "gsk_secure_soc_startInit()",
00949                             CURLE_SSL_CONNECT_ERROR);
00950       if(!result) {
00951         connssl->connecting_state = ssl_connect_2;
00952         return CURLE_OK;
00953       }
00954       else
00955         close_async_handshake(connssl);
00956     }
00957     else if(errno != ENOBUFS)
00958       result = gskit_status(data, GSK_ERROR_IO,
00959                             "QsoCreateIOCompletionPort()", 0);
00960     else if(conn->proxy_ssl[sockindex].use) {
00961       /* Cannot pipeline while handshaking synchronously. */
00962       result = CURLE_SSL_CONNECT_ERROR;
00963     }
00964     else {
00965       /* No more completion port available. Use synchronous IO. */
00966       result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
00967                             "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
00968       if(!result) {
00969         connssl->connecting_state = ssl_connect_3;
00970         return CURLE_OK;
00971       }
00972     }
00973   }
00974 
00975   /* Error: rollback. */
00976   close_one(connssl, conn, sockindex);
00977   return result;
00978 }
00979 
00980 
00981 static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
00982                                     bool nonblocking)
00983 {
00984   struct Curl_easy *data = conn->data;
00985   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00986   Qso_OverlappedIO_t cstat;
00987   long timeout_ms;
00988   struct timeval stmv;
00989   CURLcode result;
00990 
00991   /* Poll or wait for end of SSL asynchronous handshake. */
00992 
00993   for(;;) {
00994     timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
00995     if(timeout_ms < 0)
00996       timeout_ms = 0;
00997     stmv.tv_sec = timeout_ms / 1000;
00998     stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
00999     switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
01000     case 1:             /* Operation complete. */
01001       break;
01002     case -1:            /* An error occurred: handshake still in progress. */
01003       if(errno == EINTR) {
01004         if(nonblocking)
01005           return CURLE_OK;
01006         continue;       /* Retry. */
01007       }
01008       if(errno != ETIME) {
01009         failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
01010         cancel_async_handshake(conn, sockindex);
01011         close_async_handshake(connssl);
01012         return CURLE_SSL_CONNECT_ERROR;
01013       }
01014       /* FALL INTO... */
01015     case 0:             /* Handshake in progress, timeout occurred. */
01016       if(nonblocking)
01017         return CURLE_OK;
01018       cancel_async_handshake(conn, sockindex);
01019       close_async_handshake(connssl);
01020       return CURLE_OPERATION_TIMEDOUT;
01021     }
01022     break;
01023   }
01024   result = gskit_status(data, cstat.returnValue, "SSL handshake",
01025                         CURLE_SSL_CONNECT_ERROR);
01026   if(!result)
01027     connssl->connecting_state = ssl_connect_3;
01028   close_async_handshake(connssl);
01029   return result;
01030 }
01031 
01032 
01033 static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
01034 {
01035   struct Curl_easy *data = conn->data;
01036   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01037   const gsk_cert_data_elem *cdev;
01038   int cdec;
01039   const gsk_cert_data_elem *p;
01040   const char *cert = (const char *) NULL;
01041   const char *certend;
01042   const char *ptr;
01043   int i;
01044   CURLcode result;
01045 
01046   /* SSL handshake done: gather certificate info and verify host. */
01047 
01048   if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
01049                                                     GSK_PARTNER_CERT_INFO,
01050                                                     &cdev, &cdec),
01051                   "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
01052      CURLE_OK) {
01053     infof(data, "Server certificate:\n");
01054     p = cdev;
01055     for(i = 0; i++ < cdec; p++)
01056       switch(p->cert_data_id) {
01057       case CERT_BODY_DER:
01058         cert = p->cert_data_p;
01059         certend = cert + cdev->cert_data_l;
01060         break;
01061       case CERT_DN_PRINTABLE:
01062         infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
01063         break;
01064       case CERT_ISSUER_DN_PRINTABLE:
01065         infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
01066         break;
01067       case CERT_VALID_FROM:
01068         infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
01069         break;
01070       case CERT_VALID_TO:
01071         infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
01072         break;
01073     }
01074   }
01075 
01076   /* Verify host. */
01077   result = Curl_verifyhost(conn, cert, certend);
01078   if(result)
01079     return result;
01080 
01081   /* The only place GSKit can get the whole CA chain is a validation
01082      callback where no user data pointer is available. Therefore it's not
01083      possible to copy this chain into our structures for CAINFO.
01084      However the server certificate may be available, thus we can return
01085      info about it. */
01086   if(data->set.ssl.certinfo) {
01087     result = Curl_ssl_init_certinfo(data, 1);
01088     if(result)
01089       return result;
01090 
01091     if(cert) {
01092       result = Curl_extract_certinfo(conn, 0, cert, certend);
01093       if(result)
01094         return result;
01095     }
01096   }
01097 
01098   /* Check pinned public key. */
01099   ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
01100                          data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
01101   if(!result && ptr) {
01102     curl_X509certificate x509;
01103     curl_asn1Element *p;
01104 
01105     if(Curl_parseX509(&x509, cert, certend))
01106       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
01107     p = &x509.subjectPublicKeyInfo;
01108     result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
01109     if(result) {
01110       failf(data, "SSL: public key does not match pinned public key!");
01111       return result;
01112     }
01113   }
01114 
01115   connssl->connecting_state = ssl_connect_done;
01116   return CURLE_OK;
01117 }
01118 
01119 
01120 static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
01121                                      bool nonblocking, bool *done)
01122 {
01123   struct Curl_easy *data = conn->data;
01124   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01125   long timeout_ms;
01126   Qso_OverlappedIO_t cstat;
01127   CURLcode result = CURLE_OK;
01128 
01129   *done = connssl->state == ssl_connection_complete;
01130   if(*done)
01131     return CURLE_OK;
01132 
01133   /* Step 1: create session, start handshake. */
01134   if(connssl->connecting_state == ssl_connect_1) {
01135     /* check allowed time left */
01136     timeout_ms = Curl_timeleft(data, NULL, TRUE);
01137 
01138     if(timeout_ms < 0) {
01139       /* no need to continue if time already is up */
01140       failf(data, "SSL connection timeout");
01141       result = CURLE_OPERATION_TIMEDOUT;
01142     }
01143     else
01144       result = gskit_connect_step1(conn, sockindex);
01145   }
01146 
01147   /* Handle handshake pipelining. */
01148   if(!result)
01149     if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
01150       result = CURLE_SSL_CONNECT_ERROR;
01151 
01152   /* Step 2: check if handshake is over. */
01153   if(!result && connssl->connecting_state == ssl_connect_2) {
01154     /* check allowed time left */
01155     timeout_ms = Curl_timeleft(data, NULL, TRUE);
01156 
01157     if(timeout_ms < 0) {
01158       /* no need to continue if time already is up */
01159       failf(data, "SSL connection timeout");
01160       result = CURLE_OPERATION_TIMEDOUT;
01161     }
01162     else
01163       result = gskit_connect_step2(conn, sockindex, nonblocking);
01164   }
01165 
01166   /* Handle handshake pipelining. */
01167   if(!result)
01168     if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
01169       result = CURLE_SSL_CONNECT_ERROR;
01170 
01171   /* Step 3: gather certificate info, verify host. */
01172   if(!result && connssl->connecting_state == ssl_connect_3)
01173     result = gskit_connect_step3(conn, sockindex);
01174 
01175   if(result)
01176     close_one(connssl, conn, sockindex);
01177   else if(connssl->connecting_state == ssl_connect_done) {
01178     connssl->state = ssl_connection_complete;
01179     connssl->connecting_state = ssl_connect_1;
01180     conn->recv[sockindex] = gskit_recv;
01181     conn->send[sockindex] = gskit_send;
01182     *done = TRUE;
01183   }
01184 
01185   return result;
01186 }
01187 
01188 
01189 CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
01190                                         int sockindex,
01191                                         bool *done)
01192 {
01193   CURLcode result;
01194 
01195   result = gskit_connect_common(conn, sockindex, TRUE, done);
01196   if(*done || result)
01197     conn->ssl[sockindex].connecting_state = ssl_connect_1;
01198   return result;
01199 }
01200 
01201 
01202 CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
01203 {
01204   CURLcode result;
01205   bool done;
01206 
01207   conn->ssl[sockindex].connecting_state = ssl_connect_1;
01208   result = gskit_connect_common(conn, sockindex, FALSE, &done);
01209   if(result)
01210     return result;
01211 
01212   DEBUGASSERT(done);
01213 
01214   return CURLE_OK;
01215 }
01216 
01217 
01218 void Curl_gskit_close(struct connectdata *conn, int sockindex)
01219 {
01220   close_one(&conn->ssl[sockindex], conn, sockindex);
01221   close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
01222 }
01223 
01224 
01225 int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
01226 {
01227   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01228   struct Curl_easy *data = conn->data;
01229   ssize_t nread;
01230   int what;
01231   int rc;
01232   char buf[120];
01233 
01234   if(!connssl->handle)
01235     return 0;
01236 
01237   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
01238     return 0;
01239 
01240   close_one(connssl, conn, sockindex);
01241   rc = 0;
01242   what = SOCKET_READABLE(conn->sock[sockindex],
01243                          SSL_SHUTDOWN_TIMEOUT);
01244 
01245   for(;;) {
01246     if(what < 0) {
01247       /* anything that gets here is fatally bad */
01248       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
01249       rc = -1;
01250       break;
01251     }
01252 
01253     if(!what) {                                /* timeout */
01254       failf(data, "SSL shutdown timeout");
01255       break;
01256     }
01257 
01258     /* Something to read, let's do it and hope that it is the close
01259        notify alert from the server. No way to gsk_secure_soc_read() now, so
01260        use read(). */
01261 
01262     nread = read(conn->sock[sockindex], buf, sizeof(buf));
01263 
01264     if(nread < 0) {
01265       failf(data, "read: %s", strerror(errno));
01266       rc = -1;
01267     }
01268 
01269     if(nread <= 0)
01270       break;
01271 
01272     what = SOCKET_READABLE(conn->sock[sockindex], 0);
01273   }
01274 
01275   return rc;
01276 }
01277 
01278 
01279 size_t Curl_gskit_version(char *buffer, size_t size)
01280 {
01281   strncpy(buffer, "GSKit", size);
01282   return strlen(buffer);
01283 }
01284 
01285 
01286 int Curl_gskit_check_cxn(struct connectdata *cxn)
01287 {
01288   int err;
01289   int errlen;
01290 
01291   /* The only thing that can be tested here is at the socket level. */
01292 
01293   if(!cxn->ssl[FIRSTSOCKET].handle)
01294     return 0; /* connection has been closed */
01295 
01296   err = 0;
01297   errlen = sizeof err;
01298 
01299   if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
01300                  (unsigned char *) &err, &errlen) ||
01301      errlen != sizeof err || err)
01302     return 0; /* connection has been closed */
01303 
01304   return -1;  /* connection status unknown */
01305 }
01306 
01307 #endif /* USE_GSKIT */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:03