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 - 2016, 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 
     51 /* Global axTLS init, called from Curl_ssl_init() */
     52 int Curl_axtls_init(void)
     53 {
     54 /* axTLS has no global init.  Everything is done through SSL and SSL_CTX
     55  * structs stored in connectdata structure.  Perhaps can move to axtls.h.
     56  */
     57   return 1;
     58 }
     59 
     60 int Curl_axtls_cleanup(void)
     61 {
     62   /* axTLS has no global cleanup.  Perhaps can move this to axtls.h. */
     63   return 1;
     64 }
     65 
     66 static CURLcode map_error_to_curl(int axtls_err)
     67 {
     68   switch (axtls_err) {
     69   case SSL_ERROR_NOT_SUPPORTED:
     70   case SSL_ERROR_INVALID_VERSION:
     71   case -70:                       /* protocol version alert from server */
     72     return CURLE_UNSUPPORTED_PROTOCOL;
     73     break;
     74   case SSL_ERROR_NO_CIPHER:
     75     return CURLE_SSL_CIPHER;
     76     break;
     77   case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
     78   case SSL_ERROR_NO_CERT_DEFINED:
     79   case -42:                       /* bad certificate alert from server */
     80   case -43:                       /* unsupported cert alert from server */
     81   case -44:                       /* cert revoked alert from server */
     82   case -45:                       /* cert expired alert from server */
     83   case -46:                       /* cert unknown alert from server */
     84     return CURLE_SSL_CERTPROBLEM;
     85     break;
     86   case SSL_X509_ERROR(X509_NOT_OK):
     87   case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
     88   case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
     89   case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
     90   case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
     91   case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
     92   case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
     93   case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
     94   case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
     95     return CURLE_PEER_FAILED_VERIFICATION;
     96     break;
     97   case -48:                       /* unknown ca alert from server */
     98     return CURLE_SSL_CACERT;
     99     break;
    100   case -49:                       /* access denied alert from server */
    101     return CURLE_REMOTE_ACCESS_DENIED;
    102     break;
    103   case SSL_ERROR_CONN_LOST:
    104   case SSL_ERROR_SOCK_SETUP_FAILURE:
    105   case SSL_ERROR_INVALID_HANDSHAKE:
    106   case SSL_ERROR_INVALID_PROT_MSG:
    107   case SSL_ERROR_INVALID_HMAC:
    108   case SSL_ERROR_INVALID_SESSION:
    109   case SSL_ERROR_INVALID_KEY:     /* it's too bad this doesn't map better */
    110   case SSL_ERROR_FINISHED_INVALID:
    111   case SSL_ERROR_NO_CLIENT_RENOG:
    112   default:
    113     return CURLE_SSL_CONNECT_ERROR;
    114     break;
    115   }
    116 }
    117 
    118 static Curl_recv axtls_recv;
    119 static Curl_send axtls_send;
    120 
    121 static void free_ssl_structs(struct ssl_connect_data *connssl)
    122 {
    123   if(connssl->ssl) {
    124     ssl_free (connssl->ssl);
    125     connssl->ssl = NULL;
    126   }
    127   if(connssl->ssl_ctx) {
    128     ssl_ctx_free(connssl->ssl_ctx);
    129     connssl->ssl_ctx = NULL;
    130   }
    131 }
    132 
    133 /*
    134  * For both blocking and non-blocking connects, this function sets up the
    135  * ssl context and state.  This function is called after the TCP connect
    136  * has completed.
    137  */
    138 static CURLcode connect_prep(struct connectdata *conn, int sockindex)
    139 {
    140   struct Curl_easy *data = conn->data;
    141   SSL_CTX *ssl_ctx;
    142   SSL *ssl = NULL;
    143   int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
    144   int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
    145   int i, ssl_fcn_return;
    146 
    147   /* Assuming users will not compile in custom key/cert to axTLS.
    148   *  Also, even for blocking connects, use axTLS non-blocking feature.
    149   */
    150   uint32_t client_option = SSL_NO_DEFAULT_KEY |
    151     SSL_SERVER_VERIFY_LATER |
    152     SSL_CONNECT_IN_PARTS;
    153 
    154   if(conn->ssl[sockindex].state == ssl_connection_complete)
    155     /* to make us tolerant against being called more than once for the
    156        same connection */
    157     return CURLE_OK;
    158 
    159   /* axTLS only supports TLSv1 */
    160   /* check to see if we've been told to use an explicit SSL/TLS version */
    161   switch(data->set.ssl.version) {
    162   case CURL_SSLVERSION_DEFAULT:
    163   case CURL_SSLVERSION_TLSv1:
    164     break;
    165   default:
    166     failf(data, "axTLS only supports TLS 1.0 and 1.1, "
    167           "and it cannot be specified which one to use");
    168     return CURLE_SSL_CONNECT_ERROR;
    169   }
    170 
    171 #ifdef  AXTLSDEBUG
    172   client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
    173 #endif /* AXTLSDEBUG */
    174 
    175   /* Allocate an SSL_CTX struct */
    176   ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
    177   if(ssl_ctx == NULL) {
    178     failf(data, "unable to create client SSL context");
    179     return CURLE_SSL_CONNECT_ERROR;
    180   }
    181 
    182   conn->ssl[sockindex].ssl_ctx = ssl_ctx;
    183   conn->ssl[sockindex].ssl = NULL;
    184 
    185   /* Load the trusted CA cert bundle file */
    186   if(data->set.ssl.CAfile) {
    187     if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
    188        != SSL_OK) {
    189       infof(data, "error reading ca cert file %s \n",
    190             data->set.ssl.CAfile);
    191       if(data->set.ssl.verifypeer) {
    192         return CURLE_SSL_CACERT_BADFILE;
    193       }
    194     }
    195     else
    196       infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
    197   }
    198 
    199   /* gtls.c tasks we're skipping for now:
    200    * 1) certificate revocation list checking
    201    * 2) dns name assignment to host
    202    * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
    203    * 4) set certificate priority.  axTLS ignores type and sends certs in
    204    *  order added.  can probably ignore this.
    205    */
    206 
    207   /* Load client certificate */
    208   if(data->set.str[STRING_CERT]) {
    209     i=0;
    210     /* Instead of trying to analyze cert type here, let axTLS try them all. */
    211     while(cert_types[i] != 0) {
    212       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
    213                                     data->set.str[STRING_CERT], NULL);
    214       if(ssl_fcn_return == SSL_OK) {
    215         infof(data, "successfully read cert file %s \n",
    216               data->set.str[STRING_CERT]);
    217         break;
    218       }
    219       i++;
    220     }
    221     /* Tried all cert types, none worked. */
    222     if(cert_types[i] == 0) {
    223       failf(data, "%s is not x509 or pkcs12 format",
    224             data->set.str[STRING_CERT]);
    225       return CURLE_SSL_CERTPROBLEM;
    226     }
    227   }
    228 
    229   /* Load client key.
    230      If a pkcs12 file successfully loaded a cert, then there's nothing to do
    231      because the key has already been loaded. */
    232   if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
    233     i=0;
    234     /* Instead of trying to analyze key type here, let axTLS try them all. */
    235     while(key_types[i] != 0) {
    236       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
    237                                     data->set.str[STRING_KEY], NULL);
    238       if(ssl_fcn_return == SSL_OK) {
    239         infof(data, "successfully read key file %s \n",
    240               data->set.str[STRING_KEY]);
    241         break;
    242       }
    243       i++;
    244     }
    245     /* Tried all key types, none worked. */
    246     if(key_types[i] == 0) {
    247       failf(data, "Failure: %s is not a supported key file",
    248             data->set.str[STRING_KEY]);
    249       return CURLE_SSL_CONNECT_ERROR;
    250     }
    251   }
    252 
    253   /* gtls.c does more here that is being left out for now
    254    * 1) set session credentials.  can probably ignore since axtls puts this
    255    *    info in the ssl_ctx struct
    256    * 2) setting up callbacks.  these seem gnutls specific
    257    */
    258 
    259   if(conn->ssl_config.sessionid) {
    260     const uint8_t *ssl_sessionid;
    261     size_t ssl_idsize;
    262 
    263     /* In axTLS, handshaking happens inside ssl_client_new. */
    264     Curl_ssl_sessionid_lock(conn);
    265     if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
    266       /* we got a session id, use it! */
    267       infof (data, "SSL re-using session ID\n");
    268       ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
    269                            ssl_sessionid, (uint8_t)ssl_idsize);
    270     }
    271     Curl_ssl_sessionid_unlock(conn);
    272   }
    273 
    274   if(!ssl)
    275     ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
    276 
    277   conn->ssl[sockindex].ssl = ssl;
    278   return CURLE_OK;
    279 }
    280 
    281 /*
    282  * For both blocking and non-blocking connects, this function finalizes the
    283  * SSL connection.
    284  */
    285 static CURLcode connect_finish(struct connectdata *conn, int sockindex)
    286 {
    287   struct Curl_easy *data = conn->data;
    288   SSL *ssl = conn->ssl[sockindex].ssl;
    289   const char *peer_CN;
    290   uint32_t dns_altname_index;
    291   const char *dns_altname;
    292   int8_t found_subject_alt_names = 0;
    293   int8_t found_subject_alt_name_matching_conn = 0;
    294 
    295   /* Here, gtls.c gets the peer certificates and fails out depending on
    296    * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
    297    */
    298 
    299   /* Verify server's certificate */
    300   if(data->set.ssl.verifypeer) {
    301     if(ssl_verify_cert(ssl) != SSL_OK) {
    302       Curl_axtls_close(conn, sockindex);
    303       failf(data, "server cert verify failed");
    304       return CURLE_PEER_FAILED_VERIFICATION;
    305     }
    306   }
    307   else
    308     infof(data, "\t server certificate verification SKIPPED\n");
    309 
    310   /* Here, gtls.c does issuer verification. axTLS has no straightforward
    311    * equivalent, so omitting for now.*/
    312 
    313   /* Here, gtls.c does the following
    314    * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
    315    *    it seems useful. This is now implemented, by Oscar Koeroo
    316    * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
    317    * 3) displays a bunch of cert information.  axTLS doesn't support most of
    318    *    this, but a couple fields are available.
    319    */
    320 
    321   /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
    322      risk of an inifite loop */
    323   for(dns_altname_index = 0; ; dns_altname_index++) {
    324     dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
    325     if(dns_altname == NULL) {
    326       break;
    327     }
    328     found_subject_alt_names = 1;
    329 
    330     infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
    331           dns_altname, conn->host.name);
    332     if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
    333       found_subject_alt_name_matching_conn = 1;
    334       break;
    335     }
    336   }
    337 
    338   /* RFC2818 checks */
    339   if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
    340     if(data->set.ssl.verifyhost) {
    341       /* Break connection ! */
    342       Curl_axtls_close(conn, sockindex);
    343       failf(data, "\tsubjectAltName(s) do not match %s\n",
    344             conn->host.dispname);
    345       return CURLE_PEER_FAILED_VERIFICATION;
    346     }
    347     else
    348       infof(data, "\tsubjectAltName(s) do not match %s\n",
    349             conn->host.dispname);
    350   }
    351   else if(found_subject_alt_names == 0) {
    352     /* Per RFC2818, when no Subject Alt Names were available, examine the peer
    353        CN as a legacy fallback */
    354     peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
    355     if(peer_CN == NULL) {
    356       if(data->set.ssl.verifyhost) {
    357         Curl_axtls_close(conn, sockindex);
    358         failf(data, "unable to obtain common name from peer certificate");
    359         return CURLE_PEER_FAILED_VERIFICATION;
    360       }
    361       else
    362         infof(data, "unable to obtain common name from peer certificate");
    363     }
    364     else {
    365       if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
    366         if(data->set.ssl.verifyhost) {
    367           /* Break connection ! */
    368           Curl_axtls_close(conn, sockindex);
    369           failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
    370                 peer_CN, conn->host.dispname);
    371           return CURLE_PEER_FAILED_VERIFICATION;
    372         }
    373         else
    374           infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
    375                 peer_CN, conn->host.dispname);
    376       }
    377     }
    378   }
    379 
    380   /* General housekeeping */
    381   conn->ssl[sockindex].state = ssl_connection_complete;
    382   conn->recv[sockindex] = axtls_recv;
    383   conn->send[sockindex] = axtls_send;
    384 
    385   /* Put our freshly minted SSL session in cache */
    386   if(conn->ssl_config.sessionid) {
    387     const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl);
    388     size_t ssl_idsize = ssl_get_session_id(ssl);
    389     Curl_ssl_sessionid_lock(conn);
    390     if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
    391        != CURLE_OK)
    392       infof (data, "failed to add session to cache\n");
    393     Curl_ssl_sessionid_unlock(conn);
    394   }
    395 
    396   return CURLE_OK;
    397 }
    398 
    399 /*
    400  * Use axTLS's non-blocking connection feature to open an SSL connection.
    401  * This is called after a TCP connection is already established.
    402  */
    403 CURLcode Curl_axtls_connect_nonblocking(
    404     struct connectdata *conn,
    405     int sockindex,
    406     bool *done)
    407 {
    408   CURLcode conn_step;
    409   int ssl_fcn_return;
    410   int i;
    411 
    412  *done = FALSE;
    413   /* connectdata is calloc'd and connecting_state is only changed in this
    414      function, so this is safe, as the state is effectively initialized. */
    415   if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
    416     conn_step = connect_prep(conn, sockindex);
    417     if(conn_step != CURLE_OK) {
    418       Curl_axtls_close(conn, sockindex);
    419       return conn_step;
    420     }
    421     conn->ssl[sockindex].connecting_state = ssl_connect_2;
    422   }
    423 
    424   if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
    425     /* Check to make sure handshake was ok. */
    426     if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
    427       /* Loop to perform more work in between sleeps. This is work around the
    428          fact that axtls does not expose any knowledge about when work needs
    429          to be performed. This can save ~25% of time on SSL handshakes. */
    430       for(i=0; i<5; i++) {
    431         ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
    432         if(ssl_fcn_return < 0) {
    433           Curl_axtls_close(conn, sockindex);
    434           ssl_display_error(ssl_fcn_return); /* goes to stdout. */
    435           return map_error_to_curl(ssl_fcn_return);
    436         }
    437         return CURLE_OK;
    438       }
    439     }
    440     infof (conn->data, "handshake completed successfully\n");
    441     conn->ssl[sockindex].connecting_state = ssl_connect_3;
    442   }
    443 
    444   if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
    445     conn_step = connect_finish(conn, sockindex);
    446     if(conn_step != CURLE_OK) {
    447       Curl_axtls_close(conn, sockindex);
    448       return conn_step;
    449     }
    450 
    451     /* Reset connect state */
    452     conn->ssl[sockindex].connecting_state = ssl_connect_1;
    453 
    454     *done = TRUE;
    455     return CURLE_OK;
    456   }
    457 
    458   /* Unrecognized state.  Things are very bad. */
    459   conn->ssl[sockindex].state  = ssl_connection_none;
    460   conn->ssl[sockindex].connecting_state = ssl_connect_1;
    461   /* Return value perhaps not strictly correct, but distinguishes the issue.*/
    462   return CURLE_BAD_FUNCTION_ARGUMENT;
    463 }
    464 
    465 
    466 /*
    467  * This function is called after the TCP connect has completed. Setup the TLS
    468  * layer and do all necessary magic for a blocking connect.
    469  */
    470 CURLcode
    471 Curl_axtls_connect(struct connectdata *conn,
    472                   int sockindex)
    473 
    474 {
    475   struct Curl_easy *data = conn->data;
    476   CURLcode conn_step = connect_prep(conn, sockindex);
    477   int ssl_fcn_return;
    478   SSL *ssl = conn->ssl[sockindex].ssl;
    479   long timeout_ms;
    480 
    481   if(conn_step != CURLE_OK) {
    482     Curl_axtls_close(conn, sockindex);
    483     return conn_step;
    484   }
    485 
    486   /* Check to make sure handshake was ok. */
    487   while(ssl_handshake_status(ssl) != SSL_OK) {
    488     /* check allowed time left */
    489     timeout_ms = Curl_timeleft(data, NULL, TRUE);
    490 
    491     if(timeout_ms < 0) {
    492       /* no need to continue if time already is up */
    493       failf(data, "SSL connection timeout");
    494       return CURLE_OPERATION_TIMEDOUT;
    495     }
    496 
    497     ssl_fcn_return = ssl_read(ssl, NULL);
    498     if(ssl_fcn_return < 0) {
    499       Curl_axtls_close(conn, sockindex);
    500       ssl_display_error(ssl_fcn_return); /* goes to stdout. */
    501       return map_error_to_curl(ssl_fcn_return);
    502     }
    503     /* TODO: avoid polling */
    504     Curl_wait_ms(10);
    505   }
    506   infof (conn->data, "handshake completed successfully\n");
    507 
    508   conn_step = connect_finish(conn, sockindex);
    509   if(conn_step != CURLE_OK) {
    510     Curl_axtls_close(conn, sockindex);
    511     return conn_step;
    512   }
    513 
    514   return CURLE_OK;
    515 }
    516 
    517 /* return number of sent (non-SSL) bytes */
    518 static ssize_t axtls_send(struct connectdata *conn,
    519                           int sockindex,
    520                           const void *mem,
    521                           size_t len,
    522                           CURLcode *err)
    523 {
    524   /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
    525   int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
    526 
    527   infof(conn->data, "  axtls_send\n");
    528 
    529   if(rc < 0) {
    530     *err = map_error_to_curl(rc);
    531     rc = -1; /* generic error code for send failure */
    532   }
    533 
    534   *err = CURLE_OK;
    535   return rc;
    536 }
    537 
    538 void Curl_axtls_close(struct connectdata *conn, int sockindex)
    539 {
    540   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    541 
    542   infof(conn->data, "  Curl_axtls_close\n");
    543 
    544     /* line from openssl.c: (void)SSL_shutdown(connssl->ssl);
    545        axTLS compat layer does nothing for SSL_shutdown */
    546 
    547     /* The following line is from openssl.c.  There seems to be no axTLS
    548        equivalent.  ssl_free and ssl_ctx_free close things.
    549        SSL_set_connect_state(connssl->handle); */
    550 
    551   free_ssl_structs(connssl);
    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 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(connssl->ssl);
    579   */
    580 
    581   if(connssl->ssl) {
    582     int what = Curl_socket_ready(conn->sock[sockindex],
    583                                  CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
    584     if(what > 0) {
    585       /* Something to read, let's do it and hope that it is the close
    586          notify alert from the server.  buf is managed internally by
    587          axTLS and will be released upon calling ssl_free via
    588          free_ssl_structs. */
    589       nread = (ssize_t)ssl_read(connssl->ssl, &buf);
    590 
    591       if(nread < SSL_OK) {
    592         failf(data, "close notify alert not received during shutdown");
    593         retval = -1;
    594       }
    595     }
    596     else if(0 == what) {
    597       /* timeout */
    598       failf(data, "SSL shutdown timeout");
    599     }
    600     else {
    601       /* anything that gets here is fatally bad */
    602       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
    603       retval = -1;
    604     }
    605 
    606     free_ssl_structs(connssl);
    607   }
    608   return retval;
    609 }
    610 
    611 static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
    612                           int num,                  /* socketindex */
    613                           char *buf,                /* store read data here */
    614                           size_t buffersize,        /* max amount to read */
    615                           CURLcode *err)
    616 {
    617   struct ssl_connect_data *connssl = &conn->ssl[num];
    618   ssize_t ret = 0;
    619   uint8_t *read_buf;
    620 
    621   infof(conn->data, "  axtls_recv\n");
    622 
    623   *err = CURLE_OK;
    624   if(connssl) {
    625     ret = ssl_read(connssl->ssl, &read_buf);
    626     if(ret > SSL_OK) {
    627       /* ssl_read returns SSL_OK if there is more data to read, so if it is
    628          larger, then all data has been read already.  */
    629       memcpy(buf, read_buf,
    630              (size_t)ret > buffersize ? buffersize : (size_t)ret);
    631     }
    632     else if(ret == SSL_OK) {
    633       /* more data to be read, signal caller to call again */
    634       *err = CURLE_AGAIN;
    635       ret = -1;
    636     }
    637     else if(ret == -3) {
    638       /* With patched axTLS, SSL_CLOSE_NOTIFY=-3.  Hard-coding until axTLS
    639          team approves proposed fix. */
    640       Curl_axtls_close(conn, num);
    641     }
    642     else {
    643       failf(conn->data, "axTLS recv error (%d)", ret);
    644       *err = map_error_to_curl((int) ret);
    645       ret = -1;
    646     }
    647   }
    648 
    649   return ret;
    650 }
    651 
    652 /*
    653  * Return codes:
    654  *     1 means the connection is still in place
    655  *     0 means the connection has been closed
    656  *    -1 means the connection status is unknown
    657  */
    658 int Curl_axtls_check_cxn(struct connectdata *conn)
    659 {
    660   /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].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 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 size_t Curl_axtls_version(char *buffer, size_t size)
    677 {
    678   return snprintf(buffer, size, "axTLS/%s", ssl_version());
    679 }
    680 
    681 int Curl_axtls_random(struct Curl_easy *data,
    682                       unsigned char *entropy,
    683                       size_t length)
    684 {
    685   static bool ssl_seeded = FALSE;
    686   (void)data;
    687   if(!ssl_seeded) {
    688     ssl_seeded = TRUE;
    689     /* Initialize the seed if not already done. This call is not exactly thread
    690      * safe (and neither is the ssl_seeded check), but the worst effect of a
    691      * race condition is that some global resources will leak. */
    692     RNG_initialize();
    693   }
    694   get_random((int)length, entropy);
    695   return 0;
    696 }
    697 
    698 #endif /* USE_AXTLS */
    699