1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
9 * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@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
50struct ssl_backend_data {
51  SSL_CTX* ssl_ctx;
52  SSL*     ssl;
53};
54
55#define BACKEND connssl->backend
56
57static 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
109static Curl_recv axtls_recv;
110static Curl_send axtls_send;
111
112static 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 */
129static 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
280static 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 */
300static 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 */
421static 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 */
487static 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 */
533static 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 */
558static 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
610static 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 */
657static 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
668static 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
676static size_t Curl_axtls_version(char *buffer, size_t size)
677{
678  return snprintf(buffer, size, "axTLS/%s", ssl_version());
679}
680
681static 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
697static 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
704const 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