File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / vtls / gskit.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>