axtls.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
00009  * Copyright (C) 2010 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00010  *
00011  * This software is licensed as described in the file COPYING, which
00012  * you should have received as part of this distribution. The terms
00013  * are also available at https://curl.haxx.se/docs/copyright.html.
00014  *
00015  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00016  * copies of the Software, and permit persons to whom the Software is
00017  * furnished to do so, under the terms of the COPYING file.
00018  *
00019  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00020  * KIND, either express or implied.
00021  *
00022  ***************************************************************************/
00023 
00024 /*
00025  * Source file for all axTLS-specific code for the TLS/SSL layer. No code
00026  * but vtls.c should ever call or use these functions.
00027  */
00028 
00029 #include "curl_setup.h"
00030 
00031 #ifdef USE_AXTLS
00032 #include <axTLS/config.h>
00033 #include <axTLS/ssl.h>
00034 #include "axtls.h"
00035 
00036 #include "sendf.h"
00037 #include "inet_pton.h"
00038 #include "vtls.h"
00039 #include "parsedate.h"
00040 #include "connect.h" /* for the connect timeout */
00041 #include "select.h"
00042 #include "curl_printf.h"
00043 #include "hostcheck.h"
00044 #include <unistd.h>
00045 
00046 /* The last #include files should be: */
00047 #include "curl_memory.h"
00048 #include "memdebug.h"
00049 
00050 
00051 /* Global axTLS init, called from Curl_ssl_init() */
00052 int Curl_axtls_init(void)
00053 {
00054 /* axTLS has no global init.  Everything is done through SSL and SSL_CTX
00055  * structs stored in connectdata structure.  Perhaps can move to axtls.h.
00056  */
00057   return 1;
00058 }
00059 
00060 int Curl_axtls_cleanup(void)
00061 {
00062   /* axTLS has no global cleanup.  Perhaps can move this to axtls.h. */
00063   return 1;
00064 }
00065 
00066 static CURLcode map_error_to_curl(int axtls_err)
00067 {
00068   switch(axtls_err) {
00069   case SSL_ERROR_NOT_SUPPORTED:
00070   case SSL_ERROR_INVALID_VERSION:
00071   case -70:                       /* protocol version alert from server */
00072     return CURLE_UNSUPPORTED_PROTOCOL;
00073     break;
00074   case SSL_ERROR_NO_CIPHER:
00075     return CURLE_SSL_CIPHER;
00076     break;
00077   case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
00078   case SSL_ERROR_NO_CERT_DEFINED:
00079   case -42:                       /* bad certificate alert from server */
00080   case -43:                       /* unsupported cert alert from server */
00081   case -44:                       /* cert revoked alert from server */
00082   case -45:                       /* cert expired alert from server */
00083   case -46:                       /* cert unknown alert from server */
00084     return CURLE_SSL_CERTPROBLEM;
00085     break;
00086   case SSL_X509_ERROR(X509_NOT_OK):
00087   case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
00088   case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
00089   case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
00090   case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
00091   case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
00092   case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
00093   case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
00094   case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
00095     return CURLE_PEER_FAILED_VERIFICATION;
00096     break;
00097   case -48:                       /* unknown ca alert from server */
00098     return CURLE_SSL_CACERT;
00099     break;
00100   case -49:                       /* access denied alert from server */
00101     return CURLE_REMOTE_ACCESS_DENIED;
00102     break;
00103   case SSL_ERROR_CONN_LOST:
00104   case SSL_ERROR_SOCK_SETUP_FAILURE:
00105   case SSL_ERROR_INVALID_HANDSHAKE:
00106   case SSL_ERROR_INVALID_PROT_MSG:
00107   case SSL_ERROR_INVALID_HMAC:
00108   case SSL_ERROR_INVALID_SESSION:
00109   case SSL_ERROR_INVALID_KEY:     /* it's too bad this doesn't map better */
00110   case SSL_ERROR_FINISHED_INVALID:
00111   case SSL_ERROR_NO_CLIENT_RENOG:
00112   default:
00113     return CURLE_SSL_CONNECT_ERROR;
00114     break;
00115   }
00116 }
00117 
00118 static Curl_recv axtls_recv;
00119 static Curl_send axtls_send;
00120 
00121 static void free_ssl_structs(struct ssl_connect_data *connssl)
00122 {
00123   if(connssl->ssl) {
00124     ssl_free(connssl->ssl);
00125     connssl->ssl = NULL;
00126   }
00127   if(connssl->ssl_ctx) {
00128     ssl_ctx_free(connssl->ssl_ctx);
00129     connssl->ssl_ctx = NULL;
00130   }
00131 }
00132 
00133 /*
00134  * For both blocking and non-blocking connects, this function sets up the
00135  * ssl context and state.  This function is called after the TCP connect
00136  * has completed.
00137  */
00138 static CURLcode connect_prep(struct connectdata *conn, int sockindex)
00139 {
00140   struct Curl_easy *data = conn->data;
00141   SSL_CTX *ssl_ctx;
00142   SSL *ssl = NULL;
00143   int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
00144   int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
00145   int i, ssl_fcn_return;
00146 
00147   /* Assuming users will not compile in custom key/cert to axTLS.
00148   *  Also, even for blocking connects, use axTLS non-blocking feature.
00149   */
00150   uint32_t client_option = SSL_NO_DEFAULT_KEY |
00151     SSL_SERVER_VERIFY_LATER |
00152     SSL_CONNECT_IN_PARTS;
00153 
00154   if(conn->ssl[sockindex].state == ssl_connection_complete)
00155     /* to make us tolerant against being called more than once for the
00156        same connection */
00157     return CURLE_OK;
00158 
00159   /* axTLS only supports TLSv1 */
00160   /* check to see if we've been told to use an explicit SSL/TLS version */
00161   switch(SSL_CONN_CONFIG(version)) {
00162   case CURL_SSLVERSION_DEFAULT:
00163   case CURL_SSLVERSION_TLSv1:
00164     break;
00165   default:
00166     failf(data, "axTLS only supports TLS 1.0 and 1.1, "
00167           "and it cannot be specified which one to use");
00168     return CURLE_SSL_CONNECT_ERROR;
00169   }
00170 
00171 #ifdef  AXTLSDEBUG
00172   client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
00173 #endif /* AXTLSDEBUG */
00174 
00175   /* Allocate an SSL_CTX struct */
00176   ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
00177   if(ssl_ctx == NULL) {
00178     failf(data, "unable to create client SSL context");
00179     return CURLE_SSL_CONNECT_ERROR;
00180   }
00181 
00182   conn->ssl[sockindex].ssl_ctx = ssl_ctx;
00183   conn->ssl[sockindex].ssl = NULL;
00184 
00185   /* Load the trusted CA cert bundle file */
00186   if(SSL_CONN_CONFIG(CAfile)) {
00187     if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
00188                     SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
00189       infof(data, "error reading ca cert file %s \n",
00190             SSL_CONN_CONFIG(CAfile));
00191       if(SSL_CONN_CONFIG(verifypeer)) {
00192         return CURLE_SSL_CACERT_BADFILE;
00193       }
00194     }
00195     else
00196       infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
00197   }
00198 
00199   /* gtls.c tasks we're skipping for now:
00200    * 1) certificate revocation list checking
00201    * 2) dns name assignment to host
00202    * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
00203    * 4) set certificate priority.  axTLS ignores type and sends certs in
00204    *  order added.  can probably ignore this.
00205    */
00206 
00207   /* Load client certificate */
00208   if(SSL_SET_OPTION(cert)) {
00209     i=0;
00210     /* Instead of trying to analyze cert type here, let axTLS try them all. */
00211     while(cert_types[i] != 0) {
00212       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
00213                                     SSL_SET_OPTION(cert), NULL);
00214       if(ssl_fcn_return == SSL_OK) {
00215         infof(data, "successfully read cert file %s \n",
00216               SSL_SET_OPTION(cert));
00217         break;
00218       }
00219       i++;
00220     }
00221     /* Tried all cert types, none worked. */
00222     if(cert_types[i] == 0) {
00223       failf(data, "%s is not x509 or pkcs12 format",
00224             SSL_SET_OPTION(cert));
00225       return CURLE_SSL_CERTPROBLEM;
00226     }
00227   }
00228 
00229   /* Load client key.
00230      If a pkcs12 file successfully loaded a cert, then there's nothing to do
00231      because the key has already been loaded. */
00232   if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
00233     i=0;
00234     /* Instead of trying to analyze key type here, let axTLS try them all. */
00235     while(key_types[i] != 0) {
00236       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
00237                                     SSL_SET_OPTION(key), NULL);
00238       if(ssl_fcn_return == SSL_OK) {
00239         infof(data, "successfully read key file %s \n",
00240               SSL_SET_OPTION(key));
00241         break;
00242       }
00243       i++;
00244     }
00245     /* Tried all key types, none worked. */
00246     if(key_types[i] == 0) {
00247       failf(data, "Failure: %s is not a supported key file",
00248             SSL_SET_OPTION(key));
00249       return CURLE_SSL_CONNECT_ERROR;
00250     }
00251   }
00252 
00253   /* gtls.c does more here that is being left out for now
00254    * 1) set session credentials.  can probably ignore since axtls puts this
00255    *    info in the ssl_ctx struct
00256    * 2) setting up callbacks.  these seem gnutls specific
00257    */
00258 
00259   if(data->set.general_ssl.sessionid) {
00260     const uint8_t *ssl_sessionid;
00261     size_t ssl_idsize;
00262 
00263     /* In axTLS, handshaking happens inside ssl_client_new. */
00264     Curl_ssl_sessionid_lock(conn);
00265     if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
00266                               sockindex)) {
00267       /* we got a session id, use it! */
00268       infof(data, "SSL re-using session ID\n");
00269       ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
00270                            ssl_sessionid, (uint8_t)ssl_idsize);
00271     }
00272     Curl_ssl_sessionid_unlock(conn);
00273   }
00274 
00275   if(!ssl)
00276     ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
00277 
00278   conn->ssl[sockindex].ssl = ssl;
00279   return CURLE_OK;
00280 }
00281 
00282 /*
00283  * For both blocking and non-blocking connects, this function finalizes the
00284  * SSL connection.
00285  */
00286 static CURLcode connect_finish(struct connectdata *conn, int sockindex)
00287 {
00288   struct Curl_easy *data = conn->data;
00289   SSL *ssl = conn->ssl[sockindex].ssl;
00290   const char *peer_CN;
00291   uint32_t dns_altname_index;
00292   const char *dns_altname;
00293   int8_t found_subject_alt_names = 0;
00294   int8_t found_subject_alt_name_matching_conn = 0;
00295   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
00296     conn->host.name;
00297   const char * const dispname = SSL_IS_PROXY() ?
00298     conn->http_proxy.host.dispname : conn->host.dispname;
00299 
00300   /* Here, gtls.c gets the peer certificates and fails out depending on
00301    * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
00302    */
00303 
00304   /* Verify server's certificate */
00305   if(SSL_CONN_CONFIG(verifypeer)) {
00306     if(ssl_verify_cert(ssl) != SSL_OK) {
00307       Curl_axtls_close(conn, sockindex);
00308       failf(data, "server cert verify failed");
00309       return CURLE_PEER_FAILED_VERIFICATION;
00310     }
00311   }
00312   else
00313     infof(data, "\t server certificate verification SKIPPED\n");
00314 
00315   /* Here, gtls.c does issuer verification. axTLS has no straightforward
00316    * equivalent, so omitting for now.*/
00317 
00318   /* Here, gtls.c does the following
00319    * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
00320    *    it seems useful. This is now implemented, by Oscar Koeroo
00321    * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
00322    * 3) displays a bunch of cert information.  axTLS doesn't support most of
00323    *    this, but a couple fields are available.
00324    */
00325 
00326   /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
00327      risk of an inifite loop */
00328   for(dns_altname_index = 0; ; dns_altname_index++) {
00329     dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
00330     if(dns_altname == NULL) {
00331       break;
00332     }
00333     found_subject_alt_names = 1;
00334 
00335     infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
00336           dns_altname, hostname);
00337     if(Curl_cert_hostcheck(dns_altname, hostname)) {
00338       found_subject_alt_name_matching_conn = 1;
00339       break;
00340     }
00341   }
00342 
00343   /* RFC2818 checks */
00344   if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
00345     if(SSL_CONN_CONFIG(verifyhost)) {
00346       /* Break connection ! */
00347       Curl_axtls_close(conn, sockindex);
00348       failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
00349       return CURLE_PEER_FAILED_VERIFICATION;
00350     }
00351     else
00352       infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
00353   }
00354   else if(found_subject_alt_names == 0) {
00355     /* Per RFC2818, when no Subject Alt Names were available, examine the peer
00356        CN as a legacy fallback */
00357     peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
00358     if(peer_CN == NULL) {
00359       if(SSL_CONN_CONFIG(verifyhost)) {
00360         Curl_axtls_close(conn, sockindex);
00361         failf(data, "unable to obtain common name from peer certificate");
00362         return CURLE_PEER_FAILED_VERIFICATION;
00363       }
00364       else
00365         infof(data, "unable to obtain common name from peer certificate");
00366     }
00367     else {
00368       if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
00369         if(SSL_CONN_CONFIG(verifyhost)) {
00370           /* Break connection ! */
00371           Curl_axtls_close(conn, sockindex);
00372           failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
00373                 peer_CN, dispname);
00374           return CURLE_PEER_FAILED_VERIFICATION;
00375         }
00376         else
00377           infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
00378                 peer_CN, dispname);
00379       }
00380     }
00381   }
00382 
00383   /* General housekeeping */
00384   conn->ssl[sockindex].state = ssl_connection_complete;
00385   conn->recv[sockindex] = axtls_recv;
00386   conn->send[sockindex] = axtls_send;
00387 
00388   /* Put our freshly minted SSL session in cache */
00389   if(data->set.general_ssl.sessionid) {
00390     const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl);
00391     size_t ssl_idsize = ssl_get_session_id(ssl);
00392     Curl_ssl_sessionid_lock(conn);
00393     if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
00394                              sockindex) != CURLE_OK)
00395       infof(data, "failed to add session to cache\n");
00396     Curl_ssl_sessionid_unlock(conn);
00397   }
00398 
00399   return CURLE_OK;
00400 }
00401 
00402 /*
00403  * Use axTLS's non-blocking connection feature to open an SSL connection.
00404  * This is called after a TCP connection is already established.
00405  */
00406 CURLcode Curl_axtls_connect_nonblocking(
00407     struct connectdata *conn,
00408     int sockindex,
00409     bool *done)
00410 {
00411   CURLcode conn_step;
00412   int ssl_fcn_return;
00413   int i;
00414 
00415  *done = FALSE;
00416   /* connectdata is calloc'd and connecting_state is only changed in this
00417      function, so this is safe, as the state is effectively initialized. */
00418   if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
00419     conn_step = connect_prep(conn, sockindex);
00420     if(conn_step != CURLE_OK) {
00421       Curl_axtls_close(conn, sockindex);
00422       return conn_step;
00423     }
00424     conn->ssl[sockindex].connecting_state = ssl_connect_2;
00425   }
00426 
00427   if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
00428     /* Check to make sure handshake was ok. */
00429     if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
00430       /* Loop to perform more work in between sleeps. This is work around the
00431          fact that axtls does not expose any knowledge about when work needs
00432          to be performed. This can save ~25% of time on SSL handshakes. */
00433       for(i=0; i<5; i++) {
00434         ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
00435         if(ssl_fcn_return < 0) {
00436           Curl_axtls_close(conn, sockindex);
00437           ssl_display_error(ssl_fcn_return); /* goes to stdout. */
00438           return map_error_to_curl(ssl_fcn_return);
00439         }
00440         return CURLE_OK;
00441       }
00442     }
00443     infof(conn->data, "handshake completed successfully\n");
00444     conn->ssl[sockindex].connecting_state = ssl_connect_3;
00445   }
00446 
00447   if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
00448     conn_step = connect_finish(conn, sockindex);
00449     if(conn_step != CURLE_OK) {
00450       Curl_axtls_close(conn, sockindex);
00451       return conn_step;
00452     }
00453 
00454     /* Reset connect state */
00455     conn->ssl[sockindex].connecting_state = ssl_connect_1;
00456 
00457     *done = TRUE;
00458     return CURLE_OK;
00459   }
00460 
00461   /* Unrecognized state.  Things are very bad. */
00462   conn->ssl[sockindex].state  = ssl_connection_none;
00463   conn->ssl[sockindex].connecting_state = ssl_connect_1;
00464   /* Return value perhaps not strictly correct, but distinguishes the issue.*/
00465   return CURLE_BAD_FUNCTION_ARGUMENT;
00466 }
00467 
00468 
00469 /*
00470  * This function is called after the TCP connect has completed. Setup the TLS
00471  * layer and do all necessary magic for a blocking connect.
00472  */
00473 CURLcode
00474 Curl_axtls_connect(struct connectdata *conn,
00475                   int sockindex)
00476 
00477 {
00478   struct Curl_easy *data = conn->data;
00479   CURLcode conn_step = connect_prep(conn, sockindex);
00480   int ssl_fcn_return;
00481   SSL *ssl = conn->ssl[sockindex].ssl;
00482   long timeout_ms;
00483 
00484   if(conn_step != CURLE_OK) {
00485     Curl_axtls_close(conn, sockindex);
00486     return conn_step;
00487   }
00488 
00489   /* Check to make sure handshake was ok. */
00490   while(ssl_handshake_status(ssl) != SSL_OK) {
00491     /* check allowed time left */
00492     timeout_ms = Curl_timeleft(data, NULL, TRUE);
00493 
00494     if(timeout_ms < 0) {
00495       /* no need to continue if time already is up */
00496       failf(data, "SSL connection timeout");
00497       return CURLE_OPERATION_TIMEDOUT;
00498     }
00499 
00500     ssl_fcn_return = ssl_read(ssl, NULL);
00501     if(ssl_fcn_return < 0) {
00502       Curl_axtls_close(conn, sockindex);
00503       ssl_display_error(ssl_fcn_return); /* goes to stdout. */
00504       return map_error_to_curl(ssl_fcn_return);
00505     }
00506     /* TODO: avoid polling */
00507     Curl_wait_ms(10);
00508   }
00509   infof(conn->data, "handshake completed successfully\n");
00510 
00511   conn_step = connect_finish(conn, sockindex);
00512   if(conn_step != CURLE_OK) {
00513     Curl_axtls_close(conn, sockindex);
00514     return conn_step;
00515   }
00516 
00517   return CURLE_OK;
00518 }
00519 
00520 /* return number of sent (non-SSL) bytes */
00521 static ssize_t axtls_send(struct connectdata *conn,
00522                           int sockindex,
00523                           const void *mem,
00524                           size_t len,
00525                           CURLcode *err)
00526 {
00527   /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
00528   int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
00529 
00530   infof(conn->data, "  axtls_send\n");
00531 
00532   if(rc < 0) {
00533     *err = map_error_to_curl(rc);
00534     rc = -1; /* generic error code for send failure */
00535   }
00536 
00537   *err = CURLE_OK;
00538   return rc;
00539 }
00540 
00541 void Curl_axtls_close(struct connectdata *conn, int sockindex)
00542 {
00543   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00544 
00545   infof(conn->data, "  Curl_axtls_close\n");
00546 
00547     /* line from openssl.c: (void)SSL_shutdown(connssl->ssl);
00548        axTLS compat layer does nothing for SSL_shutdown */
00549 
00550     /* The following line is from openssl.c.  There seems to be no axTLS
00551        equivalent.  ssl_free and ssl_ctx_free close things.
00552        SSL_set_connect_state(connssl->handle); */
00553 
00554   free_ssl_structs(connssl);
00555 }
00556 
00557 /*
00558  * This function is called to shut down the SSL layer but keep the
00559  * socket open (CCC - Clear Command Channel)
00560  */
00561 int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
00562 {
00563   /* Outline taken from openssl.c since functions are in axTLS compat layer.
00564      axTLS's error set is much smaller, so a lot of error-handling was removed.
00565    */
00566   int retval = 0;
00567   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00568   struct Curl_easy *data = conn->data;
00569   uint8_t *buf;
00570   ssize_t nread;
00571 
00572   infof(conn->data, "  Curl_axtls_shutdown\n");
00573 
00574   /* This has only been tested on the proftpd server, and the mod_tls code
00575      sends a close notify alert without waiting for a close notify alert in
00576      response. Thus we wait for a close notify alert from the server, but
00577      we do not send one. Let's hope other servers do the same... */
00578 
00579   /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
00580   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
00581       (void)SSL_shutdown(connssl->ssl);
00582   */
00583 
00584   if(connssl->ssl) {
00585     int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
00586     if(what > 0) {
00587       /* Something to read, let's do it and hope that it is the close
00588          notify alert from the server.  buf is managed internally by
00589          axTLS and will be released upon calling ssl_free via
00590          free_ssl_structs. */
00591       nread = (ssize_t)ssl_read(connssl->ssl, &buf);
00592 
00593       if(nread < SSL_OK) {
00594         failf(data, "close notify alert not received during shutdown");
00595         retval = -1;
00596       }
00597     }
00598     else if(0 == what) {
00599       /* timeout */
00600       failf(data, "SSL shutdown timeout");
00601     }
00602     else {
00603       /* anything that gets here is fatally bad */
00604       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
00605       retval = -1;
00606     }
00607 
00608     free_ssl_structs(connssl);
00609   }
00610   return retval;
00611 }
00612 
00613 static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
00614                           int num,                  /* socketindex */
00615                           char *buf,                /* store read data here */
00616                           size_t buffersize,        /* max amount to read */
00617                           CURLcode *err)
00618 {
00619   struct ssl_connect_data *connssl = &conn->ssl[num];
00620   ssize_t ret = 0;
00621   uint8_t *read_buf;
00622 
00623   infof(conn->data, "  axtls_recv\n");
00624 
00625   *err = CURLE_OK;
00626   if(connssl) {
00627     ret = ssl_read(connssl->ssl, &read_buf);
00628     if(ret > SSL_OK) {
00629       /* ssl_read returns SSL_OK if there is more data to read, so if it is
00630          larger, then all data has been read already.  */
00631       memcpy(buf, read_buf,
00632              (size_t)ret > buffersize ? buffersize : (size_t)ret);
00633     }
00634     else if(ret == SSL_OK) {
00635       /* more data to be read, signal caller to call again */
00636       *err = CURLE_AGAIN;
00637       ret = -1;
00638     }
00639     else if(ret == -3) {
00640       /* With patched axTLS, SSL_CLOSE_NOTIFY=-3.  Hard-coding until axTLS
00641          team approves proposed fix. */
00642       Curl_axtls_close(conn, num);
00643     }
00644     else {
00645       failf(conn->data, "axTLS recv error (%d)", ret);
00646       *err = map_error_to_curl((int) ret);
00647       ret = -1;
00648     }
00649   }
00650 
00651   return ret;
00652 }
00653 
00654 /*
00655  * Return codes:
00656  *     1 means the connection is still in place
00657  *     0 means the connection has been closed
00658  *    -1 means the connection status is unknown
00659  */
00660 int Curl_axtls_check_cxn(struct connectdata *conn)
00661 {
00662   /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
00663      axTLS compat layer always returns the last argument, so connection is
00664      always alive? */
00665 
00666   infof(conn->data, "  Curl_axtls_check_cxn\n");
00667    return 1; /* connection still in place */
00668 }
00669 
00670 void Curl_axtls_session_free(void *ptr)
00671 {
00672   (void)ptr;
00673   /* free the ID */
00674   /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
00675      compatibility layer does nothing, so we do nothing too. */
00676 }
00677 
00678 size_t Curl_axtls_version(char *buffer, size_t size)
00679 {
00680   return snprintf(buffer, size, "axTLS/%s", ssl_version());
00681 }
00682 
00683 int Curl_axtls_random(struct Curl_easy *data,
00684                       unsigned char *entropy,
00685                       size_t length)
00686 {
00687   static bool ssl_seeded = FALSE;
00688   (void)data;
00689   if(!ssl_seeded) {
00690     ssl_seeded = TRUE;
00691     /* Initialize the seed if not already done. This call is not exactly thread
00692      * safe (and neither is the ssl_seeded check), but the worst effect of a
00693      * race condition is that some global resources will leak. */
00694     RNG_initialize();
00695   }
00696   get_random((int)length, entropy);
00697   return 0;
00698 }
00699 
00700 #endif /* USE_AXTLS */


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