source: asp3_tinet_ecnl_arm/trunk/curl-7.57.0/lib/vtls/axtls.c@ 352

Last change on this file since 352 was 352, checked in by coas-nagasima, 6 years ago

arm向けASP3版ECNLを追加

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