Home | History | Annotate | Download | only in vtls
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu (at) directv.com>.
      9  * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al.
     10  *
     11  * This software is licensed as described in the file COPYING, which
     12  * you should have received as part of this distribution. The terms
     13  * are also available at https://curl.haxx.se/docs/copyright.html.
     14  *
     15  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     16  * copies of the Software, and permit persons to whom the Software is
     17  * furnished to do so, under the terms of the COPYING file.
     18  *
     19  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     20  * KIND, either express or implied.
     21  *
     22  ***************************************************************************/
     23 
     24 /*
     25  * Source file for all axTLS-specific code for the TLS/SSL layer. No code
     26  * but vtls.c should ever call or use these functions.
     27  */
     28 
     29 #include "curl_setup.h"
     30 
     31 #ifdef USE_AXTLS
     32 #include <axTLS/config.h>
     33 #include <axTLS/ssl.h>
     34 #include "axtls.h"
     35 
     36 #include "sendf.h"
     37 #include "inet_pton.h"
     38 #include "vtls.h"
     39 #include "parsedate.h"
     40 #include "connect.h" /* for the connect timeout */
     41 #include "select.h"
     42 #include "curl_printf.h"
     43 #include "hostcheck.h"
     44 #include <unistd.h>
     45 
     46 /* The last #include files should be: */
     47 #include "curl_memory.h"
     48 #include "memdebug.h"
     49 
     50 struct ssl_backend_data {
     51   SSL_CTX* ssl_ctx;
     52   SSL*     ssl;
     53 };
     54 
     55 #define BACKEND connssl->backend
     56 
     57 static CURLcode map_error_to_curl(int axtls_err)
     58 {
     59   switch(axtls_err) {
     60   case SSL_ERROR_NOT_SUPPORTED:
     61   case SSL_ERROR_INVALID_VERSION:
     62   case -70:                       /* protocol version alert from server */
     63     return CURLE_UNSUPPORTED_PROTOCOL;
     64     break;
     65   case SSL_ERROR_NO_CIPHER:
     66     return CURLE_SSL_CIPHER;
     67     break;
     68   case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
     69   case SSL_ERROR_NO_CERT_DEFINED:
     70   case -42:                       /* bad certificate alert from server */
     71   case -43:                       /* unsupported cert alert from server */
     72   case -44:                       /* cert revoked alert from server */
     73   case -45:                       /* cert expired alert from server */
     74   case -46:                       /* cert unknown alert from server */
     75     return CURLE_SSL_CERTPROBLEM;
     76     break;
     77   case SSL_X509_ERROR(X509_NOT_OK):
     78   case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
     79   case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
     80   case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
     81   case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
     82   case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
     83   case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
     84   case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
     85   case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
     86     return CURLE_PEER_FAILED_VERIFICATION;
     87     break;
     88   case -48:                       /* unknown ca alert from server */
     89     return CURLE_SSL_CACERT;
     90     break;
     91   case -49:                       /* access denied alert from server */
     92     return CURLE_REMOTE_ACCESS_DENIED;
     93     break;
     94   case SSL_ERROR_CONN_LOST:
     95   case SSL_ERROR_SOCK_SETUP_FAILURE:
     96   case SSL_ERROR_INVALID_HANDSHAKE:
     97   case SSL_ERROR_INVALID_PROT_MSG:
     98   case SSL_ERROR_INVALID_HMAC:
     99   case SSL_ERROR_INVALID_SESSION:
    100   case SSL_ERROR_INVALID_KEY:     /* it's too bad this doesn't map better */
    101   case SSL_ERROR_FINISHED_INVALID:
    102   case SSL_ERROR_NO_CLIENT_RENOG:
    103   default:
    104     return CURLE_SSL_CONNECT_ERROR;
    105     break;
    106   }
    107 }
    108 
    109 static Curl_recv axtls_recv;
    110 static Curl_send axtls_send;
    111 
    112 static void free_ssl_structs(struct ssl_connect_data *connssl)
    113 {
    114   if(BACKEND->ssl) {
    115     ssl_free(BACKEND->ssl);
    116     BACKEND->ssl = NULL;
    117   }
    118   if(BACKEND->ssl_ctx) {
    119     ssl_ctx_free(BACKEND->ssl_ctx);
    120     BACKEND->ssl_ctx = NULL;
    121   }
    122 }
    123 
    124 /*
    125  * For both blocking and non-blocking connects, this function sets up the
    126  * ssl context and state.  This function is called after the TCP connect
    127  * has completed.
    128  */
    129 static CURLcode connect_prep(struct connectdata *conn, int sockindex)
    130 {
    131   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    132   struct Curl_easy *data = conn->data;
    133   SSL_CTX *ssl_ctx;
    134   SSL *ssl = NULL;
    135   int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
    136   int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
    137   int i, ssl_fcn_return;
    138 
    139   /* Assuming users will not compile in custom key/cert to axTLS.
    140   *  Also, even for blocking connects, use axTLS non-blocking feature.
    141   */
    142   uint32_t client_option = SSL_NO_DEFAULT_KEY |
    143     SSL_SERVER_VERIFY_LATER |
    144     SSL_CONNECT_IN_PARTS;
    145 
    146   if(connssl->state == ssl_connection_complete)
    147     /* to make us tolerant against being called more than once for the
    148        same connection */
    149     return CURLE_OK;
    150 
    151   if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
    152     failf(data, "axtls does not support CURL_SSLVERSION_MAX");
    153     return CURLE_SSL_CONNECT_ERROR;
    154   }
    155 
    156 
    157   /* axTLS only supports TLSv1 */
    158   /* check to see if we've been told to use an explicit SSL/TLS version */
    159   switch(SSL_CONN_CONFIG(version)) {
    160   case CURL_SSLVERSION_DEFAULT:
    161   case CURL_SSLVERSION_TLSv1:
    162     break;
    163   default:
    164     failf(data, "axTLS only supports TLS 1.0 and 1.1, "
    165           "and it cannot be specified which one to use");
    166     return CURLE_SSL_CONNECT_ERROR;
    167   }
    168 
    169 #ifdef  AXTLSDEBUG
    170   client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
    171 #endif /* AXTLSDEBUG */
    172 
    173   /* Allocate an SSL_CTX struct */
    174   ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
    175   if(ssl_ctx == NULL) {
    176     failf(data, "unable to create client SSL context");
    177     return CURLE_SSL_CONNECT_ERROR;
    178   }
    179 
    180   BACKEND->ssl_ctx = ssl_ctx;
    181   BACKEND->ssl = NULL;
    182 
    183   /* Load the trusted CA cert bundle file */
    184   if(SSL_CONN_CONFIG(CAfile)) {
    185     if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
    186                     SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
    187       infof(data, "error reading ca cert file %s \n",
    188             SSL_CONN_CONFIG(CAfile));
    189       if(SSL_CONN_CONFIG(verifypeer)) {
    190         return CURLE_SSL_CACERT_BADFILE;
    191       }
    192     }
    193     else
    194       infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
    195   }
    196 
    197   /* gtls.c tasks we're skipping for now:
    198    * 1) certificate revocation list checking
    199    * 2) dns name assignment to host
    200    * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
    201    * 4) set certificate priority.  axTLS ignores type and sends certs in
    202    *  order added.  can probably ignore this.
    203    */
    204 
    205   /* Load client certificate */
    206   if(SSL_SET_OPTION(cert)) {
    207     i = 0;
    208     /* Instead of trying to analyze cert type here, let axTLS try them all. */
    209     while(cert_types[i] != 0) {
    210       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
    211                                     SSL_SET_OPTION(cert), NULL);
    212       if(ssl_fcn_return == SSL_OK) {
    213         infof(data, "successfully read cert file %s \n",
    214               SSL_SET_OPTION(cert));
    215         break;
    216       }
    217       i++;
    218     }
    219     /* Tried all cert types, none worked. */
    220     if(cert_types[i] == 0) {
    221       failf(data, "%s is not x509 or pkcs12 format",
    222             SSL_SET_OPTION(cert));
    223       return CURLE_SSL_CERTPROBLEM;
    224     }
    225   }
    226 
    227   /* Load client key.
    228      If a pkcs12 file successfully loaded a cert, then there's nothing to do
    229      because the key has already been loaded. */
    230   if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
    231     i = 0;
    232     /* Instead of trying to analyze key type here, let axTLS try them all. */
    233     while(key_types[i] != 0) {
    234       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
    235                                     SSL_SET_OPTION(key), NULL);
    236       if(ssl_fcn_return == SSL_OK) {
    237         infof(data, "successfully read key file %s \n",
    238               SSL_SET_OPTION(key));
    239         break;
    240       }
    241       i++;
    242     }
    243     /* Tried all key types, none worked. */
    244     if(key_types[i] == 0) {
    245       failf(data, "Failure: %s is not a supported key file",
    246             SSL_SET_OPTION(key));
    247       return CURLE_SSL_CONNECT_ERROR;
    248     }
    249   }
    250 
    251   /* gtls.c does more here that is being left out for now
    252    * 1) set session credentials.  can probably ignore since axtls puts this
    253    *    info in the ssl_ctx struct
    254    * 2) setting up callbacks.  these seem gnutls specific
    255    */
    256 
    257   if(SSL_SET_OPTION(primary.sessionid)) {
    258     const uint8_t *ssl_sessionid;
    259     size_t ssl_idsize;
    260 
    261     /* In axTLS, handshaking happens inside ssl_client_new. */
    262     Curl_ssl_sessionid_lock(conn);
    263     if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
    264                               sockindex)) {
    265       /* we got a session id, use it! */
    266       infof(data, "SSL re-using session ID\n");
    267       ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
    268                            ssl_sessionid, (uint8_t)ssl_idsize, NULL);
    269     }
    270     Curl_ssl_sessionid_unlock(conn);
    271   }
    272 
    273   if(!ssl)
    274     ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
    275 
    276   BACKEND->ssl = ssl;
    277   return CURLE_OK;
    278 }
    279 
    280 static void Curl_axtls_close(struct connectdata *conn, int sockindex)
    281 {
    282   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    283 
    284   infof(conn->data, "  Curl_axtls_close\n");
    285 
    286     /* line from openssl.c: (void)SSL_shutdown(BACKEND->ssl);
    287        axTLS compat layer does nothing for SSL_shutdown */
    288 
    289     /* The following line is from openssl.c.  There seems to be no axTLS
    290        equivalent.  ssl_free and ssl_ctx_free close things.
    291        SSL_set_connect_state(connssl->handle); */
    292 
    293   free_ssl_structs(connssl);
    294 }
    295 
    296 /*
    297  * For both blocking and non-blocking connects, this function finalizes the
    298  * SSL connection.
    299  */
    300 static CURLcode connect_finish(struct connectdata *conn, int sockindex)
    301 {
    302   struct Curl_easy *data = conn->data;
    303   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    304   SSL *ssl = BACKEND->ssl;
    305   const char *peer_CN;
    306   uint32_t dns_altname_index;
    307   const char *dns_altname;
    308   int8_t found_subject_alt_names = 0;
    309   int8_t found_subject_alt_name_matching_conn = 0;
    310   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    311     conn->host.name;
    312   const char * const dispname = SSL_IS_PROXY() ?
    313     conn->http_proxy.host.dispname : conn->host.dispname;
    314 
    315   /* Here, gtls.c gets the peer certificates and fails out depending on
    316    * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
    317    */
    318 
    319   /* Verify server's certificate */
    320   if(SSL_CONN_CONFIG(verifypeer)) {
    321     if(ssl_verify_cert(ssl) != SSL_OK) {
    322       Curl_axtls_close(conn, sockindex);
    323       failf(data, "server cert verify failed");
    324       return CURLE_PEER_FAILED_VERIFICATION;
    325     }
    326   }
    327   else
    328     infof(data, "\t server certificate verification SKIPPED\n");
    329 
    330   /* Here, gtls.c does issuer verification. axTLS has no straightforward
    331    * equivalent, so omitting for now.*/
    332 
    333   /* Here, gtls.c does the following
    334    * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
    335    *    it seems useful. This is now implemented, by Oscar Koeroo
    336    * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
    337    * 3) displays a bunch of cert information.  axTLS doesn't support most of
    338    *    this, but a couple fields are available.
    339    */
    340 
    341   /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
    342      risk of an inifite loop */
    343   for(dns_altname_index = 0; ; dns_altname_index++) {
    344     dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
    345     if(dns_altname == NULL) {
    346       break;
    347     }
    348     found_subject_alt_names = 1;
    349 
    350     infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
    351           dns_altname, hostname);
    352     if(Curl_cert_hostcheck(dns_altname, hostname)) {
    353       found_subject_alt_name_matching_conn = 1;
    354       break;
    355     }
    356   }
    357 
    358   /* RFC2818 checks */
    359   if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
    360     if(SSL_CONN_CONFIG(verifyhost)) {
    361       /* Break connection ! */
    362       Curl_axtls_close(conn, sockindex);
    363       failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
    364       return CURLE_PEER_FAILED_VERIFICATION;
    365     }
    366     else
    367       infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
    368   }
    369   else if(found_subject_alt_names == 0) {
    370     /* Per RFC2818, when no Subject Alt Names were available, examine the peer
    371        CN as a legacy fallback */
    372     peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
    373     if(peer_CN == NULL) {
    374       if(SSL_CONN_CONFIG(verifyhost)) {
    375         Curl_axtls_close(conn, sockindex);
    376         failf(data, "unable to obtain common name from peer certificate");
    377         return CURLE_PEER_FAILED_VERIFICATION;
    378       }
    379       else
    380         infof(data, "unable to obtain common name from peer certificate");
    381     }
    382     else {
    383       if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
    384         if(SSL_CONN_CONFIG(verifyhost)) {
    385           /* Break connection ! */
    386           Curl_axtls_close(conn, sockindex);
    387           failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
    388                 peer_CN, dispname);
    389           return CURLE_PEER_FAILED_VERIFICATION;
    390         }
    391         else
    392           infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
    393                 peer_CN, dispname);
    394       }
    395     }
    396   }
    397 
    398   /* General housekeeping */
    399   connssl->state = ssl_connection_complete;
    400   conn->recv[sockindex] = axtls_recv;
    401   conn->send[sockindex] = axtls_send;
    402 
    403   /* Put our freshly minted SSL session in cache */
    404   if(SSL_SET_OPTION(primary.sessionid)) {
    405     const uint8_t *ssl_sessionid = ssl_get_session_id(ssl);
    406     size_t ssl_idsize = ssl_get_session_id_size(ssl);
    407     Curl_ssl_sessionid_lock(conn);
    408     if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
    409                              sockindex) != CURLE_OK)
    410       infof(data, "failed to add session to cache\n");
    411     Curl_ssl_sessionid_unlock(conn);
    412   }
    413 
    414   return CURLE_OK;
    415 }
    416 
    417 /*
    418  * Use axTLS's non-blocking connection feature to open an SSL connection.
    419  * This is called after a TCP connection is already established.
    420  */
    421 static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
    422                                                int sockindex, bool *done)
    423 {
    424   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    425   CURLcode conn_step;
    426   int ssl_fcn_return;
    427   int i;
    428 
    429  *done = FALSE;
    430   /* connectdata is calloc'd and connecting_state is only changed in this
    431      function, so this is safe, as the state is effectively initialized. */
    432   if(connssl->connecting_state == ssl_connect_1) {
    433     conn_step = connect_prep(conn, sockindex);
    434     if(conn_step != CURLE_OK) {
    435       Curl_axtls_close(conn, sockindex);
    436       return conn_step;
    437     }
    438     connssl->connecting_state = ssl_connect_2;
    439   }
    440 
    441   if(connssl->connecting_state == ssl_connect_2) {
    442     /* Check to make sure handshake was ok. */
    443     if(ssl_handshake_status(BACKEND->ssl) != SSL_OK) {
    444       /* Loop to perform more work in between sleeps. This is work around the
    445          fact that axtls does not expose any knowledge about when work needs
    446          to be performed. This can save ~25% of time on SSL handshakes. */
    447       for(i = 0; i<5; i++) {
    448         ssl_fcn_return = ssl_read(BACKEND->ssl, NULL);
    449         if(ssl_fcn_return < 0) {
    450           Curl_axtls_close(conn, sockindex);
    451           ssl_display_error(ssl_fcn_return); /* goes to stdout. */
    452           return map_error_to_curl(ssl_fcn_return);
    453         }
    454         return CURLE_OK;
    455       }
    456     }
    457     infof(conn->data, "handshake completed successfully\n");
    458     connssl->connecting_state = ssl_connect_3;
    459   }
    460 
    461   if(connssl->connecting_state == ssl_connect_3) {
    462     conn_step = connect_finish(conn, sockindex);
    463     if(conn_step != CURLE_OK) {
    464       Curl_axtls_close(conn, sockindex);
    465       return conn_step;
    466     }
    467 
    468     /* Reset connect state */
    469     connssl->connecting_state = ssl_connect_1;
    470 
    471     *done = TRUE;
    472     return CURLE_OK;
    473   }
    474 
    475   /* Unrecognized state.  Things are very bad. */
    476   connssl->state  = ssl_connection_none;
    477   connssl->connecting_state = ssl_connect_1;
    478   /* Return value perhaps not strictly correct, but distinguishes the issue.*/
    479   return CURLE_BAD_FUNCTION_ARGUMENT;
    480 }
    481 
    482 
    483 /*
    484  * This function is called after the TCP connect has completed. Setup the TLS
    485  * layer and do all necessary magic for a blocking connect.
    486  */
    487 static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex)
    488 {
    489   struct Curl_easy *data = conn->data;
    490   CURLcode conn_step = connect_prep(conn, sockindex);
    491   int ssl_fcn_return;
    492   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    493   SSL *ssl = BACKEND->ssl;
    494   long timeout_ms;
    495 
    496   if(conn_step != CURLE_OK) {
    497     Curl_axtls_close(conn, sockindex);
    498     return conn_step;
    499   }
    500 
    501   /* Check to make sure handshake was ok. */
    502   while(ssl_handshake_status(ssl) != SSL_OK) {
    503     /* check allowed time left */
    504     timeout_ms = Curl_timeleft(data, NULL, TRUE);
    505 
    506     if(timeout_ms < 0) {
    507       /* no need to continue if time already is up */
    508       failf(data, "SSL connection timeout");
    509       return CURLE_OPERATION_TIMEDOUT;
    510     }
    511 
    512     ssl_fcn_return = ssl_read(ssl, NULL);
    513     if(ssl_fcn_return < 0) {
    514       Curl_axtls_close(conn, sockindex);
    515       ssl_display_error(ssl_fcn_return); /* goes to stdout. */
    516       return map_error_to_curl(ssl_fcn_return);
    517     }
    518     /* TODO: avoid polling */
    519     Curl_wait_ms(10);
    520   }
    521   infof(conn->data, "handshake completed successfully\n");
    522 
    523   conn_step = connect_finish(conn, sockindex);
    524   if(conn_step != CURLE_OK) {
    525     Curl_axtls_close(conn, sockindex);
    526     return conn_step;
    527   }
    528 
    529   return CURLE_OK;
    530 }
    531 
    532 /* return number of sent (non-SSL) bytes */
    533 static ssize_t axtls_send(struct connectdata *conn,
    534                           int sockindex,
    535                           const void *mem,
    536                           size_t len,
    537                           CURLcode *err)
    538 {
    539   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    540   /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
    541   int rc = ssl_write(BACKEND->ssl, mem, (int)len);
    542 
    543   infof(conn->data, "  axtls_send\n");
    544 
    545   if(rc < 0) {
    546     *err = map_error_to_curl(rc);
    547     rc = -1; /* generic error code for send failure */
    548   }
    549 
    550   *err = CURLE_OK;
    551   return rc;
    552 }
    553 
    554 /*
    555  * This function is called to shut down the SSL layer but keep the
    556  * socket open (CCC - Clear Command Channel)
    557  */
    558 static int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
    559 {
    560   /* Outline taken from openssl.c since functions are in axTLS compat layer.
    561      axTLS's error set is much smaller, so a lot of error-handling was removed.
    562    */
    563   int retval = 0;
    564   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    565   struct Curl_easy *data = conn->data;
    566   uint8_t *buf;
    567   ssize_t nread;
    568 
    569   infof(conn->data, "  Curl_axtls_shutdown\n");
    570 
    571   /* This has only been tested on the proftpd server, and the mod_tls code
    572      sends a close notify alert without waiting for a close notify alert in
    573      response. Thus we wait for a close notify alert from the server, but
    574      we do not send one. Let's hope other servers do the same... */
    575 
    576   /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
    577   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
    578       (void)SSL_shutdown(BACKEND->ssl);
    579   */
    580 
    581   if(BACKEND->ssl) {
    582     int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
    583     if(what > 0) {
    584       /* Something to read, let's do it and hope that it is the close
    585          notify alert from the server.  buf is managed internally by
    586          axTLS and will be released upon calling ssl_free via
    587          free_ssl_structs. */
    588       nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
    589 
    590       if(nread < SSL_OK) {
    591         failf(data, "close notify alert not received during shutdown");
    592         retval = -1;
    593       }
    594     }
    595     else if(0 == what) {
    596       /* timeout */
    597       failf(data, "SSL shutdown timeout");
    598     }
    599     else {
    600       /* anything that gets here is fatally bad */
    601       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
    602       retval = -1;
    603     }
    604 
    605     free_ssl_structs(connssl);
    606   }
    607   return retval;
    608 }
    609 
    610 static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
    611                           int num,                  /* socketindex */
    612                           char *buf,                /* store read data here */
    613                           size_t buffersize,        /* max amount to read */
    614                           CURLcode *err)
    615 {
    616   struct ssl_connect_data *connssl = &conn->ssl[num];
    617   ssize_t ret = 0;
    618   uint8_t *read_buf;
    619 
    620   infof(conn->data, "  axtls_recv\n");
    621 
    622   *err = CURLE_OK;
    623   if(connssl) {
    624     ret = ssl_read(BACKEND->ssl, &read_buf);
    625     if(ret > SSL_OK) {
    626       /* ssl_read returns SSL_OK if there is more data to read, so if it is
    627          larger, then all data has been read already.  */
    628       memcpy(buf, read_buf,
    629              (size_t)ret > buffersize ? buffersize : (size_t)ret);
    630     }
    631     else if(ret == SSL_OK) {
    632       /* more data to be read, signal caller to call again */
    633       *err = CURLE_AGAIN;
    634       ret = -1;
    635     }
    636     else if(ret == -3) {
    637       /* With patched axTLS, SSL_CLOSE_NOTIFY=-3.  Hard-coding until axTLS
    638          team approves proposed fix. */
    639       Curl_axtls_close(conn, num);
    640     }
    641     else {
    642       failf(conn->data, "axTLS recv error (%d)", ret);
    643       *err = map_error_to_curl((int) ret);
    644       ret = -1;
    645     }
    646   }
    647 
    648   return ret;
    649 }
    650 
    651 /*
    652  * Return codes:
    653  *     1 means the connection is still in place
    654  *     0 means the connection has been closed
    655  *    -1 means the connection status is unknown
    656  */
    657 static int Curl_axtls_check_cxn(struct connectdata *conn)
    658 {
    659   /* openssl.c line:
    660      rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1);
    661      axTLS compat layer always returns the last argument, so connection is
    662      always alive? */
    663 
    664   infof(conn->data, "  Curl_axtls_check_cxn\n");
    665    return 1; /* connection still in place */
    666 }
    667 
    668 static void Curl_axtls_session_free(void *ptr)
    669 {
    670   (void)ptr;
    671   /* free the ID */
    672   /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
    673      compatibility layer does nothing, so we do nothing too. */
    674 }
    675 
    676 static size_t Curl_axtls_version(char *buffer, size_t size)
    677 {
    678   return snprintf(buffer, size, "axTLS/%s", ssl_version());
    679 }
    680 
    681 static CURLcode Curl_axtls_random(struct Curl_easy *data,
    682                                   unsigned char *entropy, size_t length)
    683 {
    684   static bool ssl_seeded = FALSE;
    685   (void)data;
    686   if(!ssl_seeded) {
    687     ssl_seeded = TRUE;
    688     /* Initialize the seed if not already done. This call is not exactly thread
    689      * safe (and neither is the ssl_seeded check), but the worst effect of a
    690      * race condition is that some global resources will leak. */
    691     RNG_initialize();
    692   }
    693   get_random((int)length, entropy);
    694   return CURLE_OK;
    695 }
    696 
    697 static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
    698                                       CURLINFO info UNUSED_PARAM)
    699 {
    700   (void)info;
    701   return BACKEND->ssl;
    702 }
    703 
    704 const struct Curl_ssl Curl_ssl_axtls = {
    705   { CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
    706 
    707   0, /* have_ca_path */
    708   0, /* have_certinfo */
    709   0, /* have_pinnedpubkey */
    710   0, /* have_ssl_ctx */
    711   0, /* support_https_proxy */
    712 
    713   sizeof(struct ssl_backend_data),
    714 
    715   /*
    716    * axTLS has no global init.  Everything is done through SSL and SSL_CTX
    717    * structs stored in connectdata structure.
    718    */
    719   Curl_none_init,                 /* init */
    720   /* axTLS has no global cleanup. */
    721   Curl_none_cleanup,              /* cleanup */
    722   Curl_axtls_version,             /* version */
    723   Curl_axtls_check_cxn,           /* check_cxn */
    724   Curl_axtls_shutdown,            /* shutdown */
    725   Curl_none_data_pending,         /* data_pending */
    726   Curl_axtls_random,              /* random */
    727   Curl_none_cert_status_request,  /* cert_status_request */
    728   Curl_axtls_connect,             /* connect */
    729   Curl_axtls_connect_nonblocking, /* connect_nonblocking */
    730   Curl_axtls_get_internals,       /* get_internals */
    731   Curl_axtls_close,               /* close_one */
    732   Curl_none_close_all,            /* close_all */
    733   Curl_axtls_session_free,        /* session_free */
    734   Curl_none_set_engine,           /* set_engine */
    735   Curl_none_set_engine_default,   /* set_engine_default */
    736   Curl_none_engines_list,         /* engines_list */
    737   Curl_none_false_start,          /* false_start */
    738   Curl_none_md5sum,               /* md5sum */
    739   NULL                            /* sha256sum */
    740 };
    741 
    742 #endif /* USE_AXTLS */
    743