Imported Upstream version 7.48.0
[platform/upstream/curl.git] / lib / vtls / axtls.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
9  * Copyright (C) 2010 - 2015, 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() */
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 SessionHandle *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   const uint8_t *ssl_sessionid;
147   size_t ssl_idsize;
148
149   /* Assuming users will not compile in custom key/cert to axTLS.
150   *  Also, even for blocking connects, use axTLS non-blocking feature.
151   */
152   uint32_t client_option = SSL_NO_DEFAULT_KEY |
153     SSL_SERVER_VERIFY_LATER |
154     SSL_CONNECT_IN_PARTS;
155
156   if(conn->ssl[sockindex].state == ssl_connection_complete)
157     /* to make us tolerant against being called more than once for the
158        same connection */
159     return CURLE_OK;
160
161   /* axTLS only supports TLSv1 */
162   /* check to see if we've been told to use an explicit SSL/TLS version */
163   switch(data->set.ssl.version) {
164   case CURL_SSLVERSION_DEFAULT:
165   case CURL_SSLVERSION_TLSv1:
166     break;
167   default:
168     failf(data, "axTLS only supports TLS 1.0 and 1.1, "
169           "and it cannot be specified which one to use");
170     return CURLE_SSL_CONNECT_ERROR;
171   }
172
173 #ifdef  AXTLSDEBUG
174   client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
175 #endif /* AXTLSDEBUG */
176
177   /* Allocate an SSL_CTX struct */
178   ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
179   if(ssl_ctx == NULL) {
180     failf(data, "unable to create client SSL context");
181     return CURLE_SSL_CONNECT_ERROR;
182   }
183
184   conn->ssl[sockindex].ssl_ctx = ssl_ctx;
185   conn->ssl[sockindex].ssl = NULL;
186
187   /* Load the trusted CA cert bundle file */
188   if(data->set.ssl.CAfile) {
189     if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
190        != SSL_OK) {
191       infof(data, "error reading ca cert file %s \n",
192             data->set.ssl.CAfile);
193       if(data->set.ssl.verifypeer) {
194         return CURLE_SSL_CACERT_BADFILE;
195       }
196     }
197     else
198       infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
199   }
200
201   /* gtls.c tasks we're skipping for now:
202    * 1) certificate revocation list checking
203    * 2) dns name assignment to host
204    * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
205    * 4) set certificate priority.  axTLS ignores type and sends certs in
206    *  order added.  can probably ignore this.
207    */
208
209   /* Load client certificate */
210   if(data->set.str[STRING_CERT]) {
211     i=0;
212     /* Instead of trying to analyze cert type here, let axTLS try them all. */
213     while(cert_types[i] != 0) {
214       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
215                                     data->set.str[STRING_CERT], NULL);
216       if(ssl_fcn_return == SSL_OK) {
217         infof(data, "successfully read cert file %s \n",
218               data->set.str[STRING_CERT]);
219         break;
220       }
221       i++;
222     }
223     /* Tried all cert types, none worked. */
224     if(cert_types[i] == 0) {
225       failf(data, "%s is not x509 or pkcs12 format",
226             data->set.str[STRING_CERT]);
227       return CURLE_SSL_CERTPROBLEM;
228     }
229   }
230
231   /* Load client key.
232      If a pkcs12 file successfully loaded a cert, then there's nothing to do
233      because the key has already been loaded. */
234   if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
235     i=0;
236     /* Instead of trying to analyze key type here, let axTLS try them all. */
237     while(key_types[i] != 0) {
238       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
239                                     data->set.str[STRING_KEY], NULL);
240       if(ssl_fcn_return == SSL_OK) {
241         infof(data, "successfully read key file %s \n",
242               data->set.str[STRING_KEY]);
243         break;
244       }
245       i++;
246     }
247     /* Tried all key types, none worked. */
248     if(key_types[i] == 0) {
249       failf(data, "Failure: %s is not a supported key file",
250             data->set.str[STRING_KEY]);
251       return CURLE_SSL_CONNECT_ERROR;
252     }
253   }
254
255   /* gtls.c does more here that is being left out for now
256    * 1) set session credentials.  can probably ignore since axtls puts this
257    *    info in the ssl_ctx struct
258    * 2) setting up callbacks.  these seem gnutls specific
259    */
260
261   /* In axTLS, handshaking happens inside ssl_client_new. */
262   if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
263     /* we got a session id, use it! */
264     infof (data, "SSL re-using session ID\n");
265     ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
266                          ssl_sessionid, (uint8_t)ssl_idsize);
267   }
268   else
269     ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
270
271   conn->ssl[sockindex].ssl = ssl;
272   return CURLE_OK;
273 }
274
275 /*
276  * For both blocking and non-blocking connects, this function finalizes the
277  * SSL connection.
278  */
279 static CURLcode connect_finish(struct connectdata *conn, int sockindex)
280 {
281   struct SessionHandle *data = conn->data;
282   SSL *ssl = conn->ssl[sockindex].ssl;
283   const uint8_t *ssl_sessionid;
284   size_t ssl_idsize;
285   const char *peer_CN;
286   uint32_t dns_altname_index;
287   const char *dns_altname;
288   int8_t found_subject_alt_names = 0;
289   int8_t found_subject_alt_name_matching_conn = 0;
290
291   /* Here, gtls.c gets the peer certificates and fails out depending on
292    * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
293    */
294
295   /* Verify server's certificate */
296   if(data->set.ssl.verifypeer) {
297     if(ssl_verify_cert(ssl) != SSL_OK) {
298       Curl_axtls_close(conn, sockindex);
299       failf(data, "server cert verify failed");
300       return CURLE_PEER_FAILED_VERIFICATION;
301     }
302   }
303   else
304     infof(data, "\t server certificate verification SKIPPED\n");
305
306   /* Here, gtls.c does issuer verification. axTLS has no straightforward
307    * equivalent, so omitting for now.*/
308
309   /* Here, gtls.c does the following
310    * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
311    *    it seems useful. This is now implemented, by Oscar Koeroo
312    * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
313    * 3) displays a bunch of cert information.  axTLS doesn't support most of
314    *    this, but a couple fields are available.
315    */
316
317   /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
318      risk of an inifite loop */
319   for(dns_altname_index = 0; ; dns_altname_index++) {
320     dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
321     if(dns_altname == NULL) {
322       break;
323     }
324     found_subject_alt_names = 1;
325
326     infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
327           dns_altname, conn->host.name);
328     if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
329       found_subject_alt_name_matching_conn = 1;
330       break;
331     }
332   }
333
334   /* RFC2818 checks */
335   if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
336     if(data->set.ssl.verifyhost) {
337       /* Break connection ! */
338       Curl_axtls_close(conn, sockindex);
339       failf(data, "\tsubjectAltName(s) do not match %s\n",
340             conn->host.dispname);
341       return CURLE_PEER_FAILED_VERIFICATION;
342     }
343     else
344       infof(data, "\tsubjectAltName(s) do not match %s\n",
345             conn->host.dispname);
346   }
347   else if(found_subject_alt_names == 0) {
348     /* Per RFC2818, when no Subject Alt Names were available, examine the peer
349        CN as a legacy fallback */
350     peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
351     if(peer_CN == NULL) {
352       if(data->set.ssl.verifyhost) {
353         Curl_axtls_close(conn, sockindex);
354         failf(data, "unable to obtain common name from peer certificate");
355         return CURLE_PEER_FAILED_VERIFICATION;
356       }
357       else
358         infof(data, "unable to obtain common name from peer certificate");
359     }
360     else {
361       if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
362         if(data->set.ssl.verifyhost) {
363           /* Break connection ! */
364           Curl_axtls_close(conn, sockindex);
365           failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
366                 peer_CN, conn->host.dispname);
367           return CURLE_PEER_FAILED_VERIFICATION;
368         }
369         else
370           infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
371                 peer_CN, conn->host.dispname);
372       }
373     }
374   }
375
376   /* General housekeeping */
377   conn->ssl[sockindex].state = ssl_connection_complete;
378   conn->recv[sockindex] = axtls_recv;
379   conn->send[sockindex] = axtls_send;
380
381   /* Put our freshly minted SSL session in cache */
382   ssl_idsize = ssl_get_session_id_size(ssl);
383   ssl_sessionid = ssl_get_session_id(ssl);
384   if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
385      != CURLE_OK)
386     infof (data, "failed to add session to cache\n");
387
388   return CURLE_OK;
389 }
390
391 /*
392  * Use axTLS's non-blocking connection feature to open an SSL connection.
393  * This is called after a TCP connection is already established.
394  */
395 CURLcode Curl_axtls_connect_nonblocking(
396     struct connectdata *conn,
397     int sockindex,
398     bool *done)
399 {
400   CURLcode conn_step;
401   int ssl_fcn_return;
402   int i;
403
404  *done = FALSE;
405   /* connectdata is calloc'd and connecting_state is only changed in this
406      function, so this is safe, as the state is effectively initialized. */
407   if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
408     conn_step = connect_prep(conn, sockindex);
409     if(conn_step != CURLE_OK) {
410       Curl_axtls_close(conn, sockindex);
411       return conn_step;
412     }
413     conn->ssl[sockindex].connecting_state = ssl_connect_2;
414   }
415
416   if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
417     /* Check to make sure handshake was ok. */
418     if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
419       /* Loop to perform more work in between sleeps. This is work around the
420          fact that axtls does not expose any knowledge about when work needs
421          to be performed. This can save ~25% of time on SSL handshakes. */
422       for(i=0; i<5; i++) {
423         ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
424         if(ssl_fcn_return < 0) {
425           Curl_axtls_close(conn, sockindex);
426           ssl_display_error(ssl_fcn_return); /* goes to stdout. */
427           return map_error_to_curl(ssl_fcn_return);
428         }
429         return CURLE_OK;
430       }
431     }
432     infof (conn->data, "handshake completed successfully\n");
433     conn->ssl[sockindex].connecting_state = ssl_connect_3;
434   }
435
436   if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
437     conn_step = connect_finish(conn, sockindex);
438     if(conn_step != CURLE_OK) {
439       Curl_axtls_close(conn, sockindex);
440       return conn_step;
441     }
442
443     /* Reset connect state */
444     conn->ssl[sockindex].connecting_state = ssl_connect_1;
445
446     *done = TRUE;
447     return CURLE_OK;
448   }
449
450   /* Unrecognized state.  Things are very bad. */
451   conn->ssl[sockindex].state  = ssl_connection_none;
452   conn->ssl[sockindex].connecting_state = ssl_connect_1;
453   /* Return value perhaps not strictly correct, but distinguishes the issue.*/
454   return CURLE_BAD_FUNCTION_ARGUMENT;
455 }
456
457
458 /*
459  * This function is called after the TCP connect has completed. Setup the TLS
460  * layer and do all necessary magic for a blocking connect.
461  */
462 CURLcode
463 Curl_axtls_connect(struct connectdata *conn,
464                   int sockindex)
465
466 {
467   struct SessionHandle *data = conn->data;
468   CURLcode conn_step = connect_prep(conn, sockindex);
469   int ssl_fcn_return;
470   SSL *ssl = conn->ssl[sockindex].ssl;
471   long timeout_ms;
472
473   if(conn_step != CURLE_OK) {
474     Curl_axtls_close(conn, sockindex);
475     return conn_step;
476   }
477
478   /* Check to make sure handshake was ok. */
479   while(ssl_handshake_status(ssl) != SSL_OK) {
480     /* check allowed time left */
481     timeout_ms = Curl_timeleft(data, NULL, TRUE);
482
483     if(timeout_ms < 0) {
484       /* no need to continue if time already is up */
485       failf(data, "SSL connection timeout");
486       return CURLE_OPERATION_TIMEDOUT;
487     }
488
489     ssl_fcn_return = ssl_read(ssl, NULL);
490     if(ssl_fcn_return < 0) {
491       Curl_axtls_close(conn, sockindex);
492       ssl_display_error(ssl_fcn_return); /* goes to stdout. */
493       return map_error_to_curl(ssl_fcn_return);
494     }
495     /* TODO: avoid polling */
496     usleep(10000);
497   }
498   infof (conn->data, "handshake completed successfully\n");
499
500   conn_step = connect_finish(conn, sockindex);
501   if(conn_step != CURLE_OK) {
502     Curl_axtls_close(conn, sockindex);
503     return conn_step;
504   }
505
506   return CURLE_OK;
507 }
508
509 /* return number of sent (non-SSL) bytes */
510 static ssize_t axtls_send(struct connectdata *conn,
511                           int sockindex,
512                           const void *mem,
513                           size_t len,
514                           CURLcode *err)
515 {
516   /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
517   int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
518
519   infof(conn->data, "  axtls_send\n");
520
521   if(rc < 0 ) {
522     *err = map_error_to_curl(rc);
523     rc = -1; /* generic error code for send failure */
524   }
525
526   *err = CURLE_OK;
527   return rc;
528 }
529
530 void Curl_axtls_close(struct connectdata *conn, int sockindex)
531 {
532   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
533
534   infof(conn->data, "  Curl_axtls_close\n");
535
536     /* line from openssl.c: (void)SSL_shutdown(connssl->ssl);
537        axTLS compat layer does nothing for SSL_shutdown */
538
539     /* The following line is from openssl.c.  There seems to be no axTLS
540        equivalent.  ssl_free and ssl_ctx_free close things.
541        SSL_set_connect_state(connssl->handle); */
542
543   free_ssl_structs(connssl);
544 }
545
546 /*
547  * This function is called to shut down the SSL layer but keep the
548  * socket open (CCC - Clear Command Channel)
549  */
550 int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
551 {
552   /* Outline taken from openssl.c since functions are in axTLS compat layer.
553      axTLS's error set is much smaller, so a lot of error-handling was removed.
554    */
555   int retval = 0;
556   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
557   struct SessionHandle *data = conn->data;
558   uint8_t *buf;
559   ssize_t nread;
560
561   infof(conn->data, "  Curl_axtls_shutdown\n");
562
563   /* This has only been tested on the proftpd server, and the mod_tls code
564      sends a close notify alert without waiting for a close notify alert in
565      response. Thus we wait for a close notify alert from the server, but
566      we do not send one. Let's hope other servers do the same... */
567
568   /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
569   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
570       (void)SSL_shutdown(connssl->ssl);
571   */
572
573   if(connssl->ssl) {
574     int what = Curl_socket_ready(conn->sock[sockindex],
575                                  CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
576     if(what > 0) {
577       /* Something to read, let's do it and hope that it is the close
578          notify alert from the server.  buf is managed internally by
579          axTLS and will be released upon calling ssl_free via
580          free_ssl_structs. */
581       nread = (ssize_t)ssl_read(connssl->ssl, &buf);
582
583       if(nread < SSL_OK) {
584         failf(data, "close notify alert not received during shutdown");
585         retval = -1;
586       }
587     }
588     else if(0 == what) {
589       /* timeout */
590       failf(data, "SSL shutdown timeout");
591     }
592     else {
593       /* anything that gets here is fatally bad */
594       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
595       retval = -1;
596     }
597
598     free_ssl_structs(connssl);
599   }
600   return retval;
601 }
602
603 static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
604                           int num,                  /* socketindex */
605                           char *buf,                /* store read data here */
606                           size_t buffersize,        /* max amount to read */
607                           CURLcode *err)
608 {
609   struct ssl_connect_data *connssl = &conn->ssl[num];
610   ssize_t ret = 0;
611   uint8_t *read_buf;
612
613   infof(conn->data, "  axtls_recv\n");
614
615   *err = CURLE_OK;
616   if(connssl) {
617     ret = ssl_read(connssl->ssl, &read_buf);
618     if(ret > SSL_OK) {
619       /* ssl_read returns SSL_OK if there is more data to read, so if it is
620          larger, then all data has been read already.  */
621       memcpy(buf, read_buf,
622              (size_t)ret > buffersize ? buffersize : (size_t)ret);
623     }
624     else if(ret == SSL_OK) {
625       /* more data to be read, signal caller to call again */
626       *err = CURLE_AGAIN;
627       ret = -1;
628     }
629     else if(ret == -3) {
630       /* With patched axTLS, SSL_CLOSE_NOTIFY=-3.  Hard-coding until axTLS
631          team approves proposed fix. */
632       Curl_axtls_close(conn, num);
633     }
634     else {
635       failf(conn->data, "axTLS recv error (%d)", ret);
636       *err = map_error_to_curl((int) ret);
637       ret = -1;
638     }
639   }
640
641   return ret;
642 }
643
644 /*
645  * Return codes:
646  *     1 means the connection is still in place
647  *     0 means the connection has been closed
648  *    -1 means the connection status is unknown
649  */
650 int Curl_axtls_check_cxn(struct connectdata *conn)
651 {
652   /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
653      axTLS compat layer always returns the last argument, so connection is
654      always alive? */
655
656   infof(conn->data, "  Curl_axtls_check_cxn\n");
657    return 1; /* connection still in place */
658 }
659
660 void Curl_axtls_session_free(void *ptr)
661 {
662   (void)ptr;
663   /* free the ID */
664   /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
665      compatibility layer does nothing, so we do nothing too. */
666 }
667
668 size_t Curl_axtls_version(char *buffer, size_t size)
669 {
670   return snprintf(buffer, size, "axTLS/%s", ssl_version());
671 }
672
673 int Curl_axtls_random(struct SessionHandle *data,
674                       unsigned char *entropy,
675                       size_t length)
676 {
677   static bool ssl_seeded = FALSE;
678   (void)data;
679   if(!ssl_seeded) {
680     ssl_seeded = TRUE;
681     /* Initialize the seed if not already done. This call is not exactly thread
682      * safe (and neither is the ssl_seeded check), but the worst effect of a
683      * race condition is that some global resources will leak. */
684     RNG_initialize();
685   }
686   get_random((int)length, entropy);
687   return 0;
688 }
689
690 #endif /* USE_AXTLS */