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