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() */
Curl_axtls_init(void)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 
Curl_axtls_cleanup(void)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 
map_error_to_curl(int axtls_err)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 
free_ssl_structs(struct ssl_connect_data * connssl)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  */
connect_prep(struct connectdata * conn,int sockindex)138 static 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  */
connect_finish(struct connectdata * conn,int sockindex)285 static 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  */
Curl_axtls_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)403 CURLcode 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  */
470 CURLcode
Curl_axtls_connect(struct connectdata * conn,int sockindex)471 Curl_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 */
axtls_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * err)518 static 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 
Curl_axtls_close(struct connectdata * conn,int sockindex)538 void 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  */
Curl_axtls_shutdown(struct connectdata * conn,int sockindex)558 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(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 
axtls_recv(struct connectdata * conn,int num,char * buf,size_t buffersize,CURLcode * err)611 static 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  */
Curl_axtls_check_cxn(struct connectdata * conn)658 int 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 
Curl_axtls_session_free(void * ptr)668 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 
Curl_axtls_version(char * buffer,size_t size)676 size_t Curl_axtls_version(char *buffer, size_t size)
677 {
678   return snprintf(buffer, size, "axTLS/%s", ssl_version());
679 }
680 
Curl_axtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)681 int 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