1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
9 * Copyright (C) 2010 - 2016, 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
50
51/* Global axTLS init, called from Curl_ssl_init() */
52int 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
60int Curl_axtls_cleanup(void)
61{
62  /* axTLS has no global cleanup.  Perhaps can move this to axtls.h. */
63  return 1;
64}
65
66static 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
118static Curl_recv axtls_recv;
119static Curl_send axtls_send;
120
121static 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 */
138static 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 */
285static 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 */
403CURLcode 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 */
470CURLcode
471Curl_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 */
518static 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
538void 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 */
558int 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
611static 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 */
658int 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
668void 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
676size_t Curl_axtls_version(char *buffer, size_t size)
677{
678  return snprintf(buffer, size, "axTLS/%s", ssl_version());
679}
680
681int 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