source: UsbWattMeter/trunk/curl-7.47.1/lib/vtls/axtls.c@ 167

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

MIMEにSJISを設定

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc; charset=SHIFT_JIS
File size: 21.9 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 - 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() */
52int Curl_axtls_init(void)
53{
54/* axTLS has no global init. Everything is done through SSL and SSL_CTX
55 * structs stored in connectdata structure. Perhaps can move to axtls.h.
56 */
57 return 1;
58}
59
60int Curl_axtls_cleanup(void)
61{
62 /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */
63 return 1;
64}
65
66static CURLcode map_error_to_curl(int axtls_err)
67{
68 switch (axtls_err) {
69 case SSL_ERROR_NOT_SUPPORTED:
70 case SSL_ERROR_INVALID_VERSION:
71 case -70: /* protocol version alert from server */
72 return CURLE_UNSUPPORTED_PROTOCOL;
73 break;
74 case SSL_ERROR_NO_CIPHER:
75 return CURLE_SSL_CIPHER;
76 break;
77 case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
78 case SSL_ERROR_NO_CERT_DEFINED:
79 case -42: /* bad certificate alert from server */
80 case -43: /* unsupported cert alert from server */
81 case -44: /* cert revoked alert from server */
82 case -45: /* cert expired alert from server */
83 case -46: /* cert unknown alert from server */
84 return CURLE_SSL_CERTPROBLEM;
85 break;
86 case SSL_X509_ERROR(X509_NOT_OK):
87 case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
88 case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
89 case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
90 case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
91 case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
92 case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
93 case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
94 case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
95 return CURLE_PEER_FAILED_VERIFICATION;
96 break;
97 case -48: /* unknown ca alert from server */
98 return CURLE_SSL_CACERT;
99 break;
100 case -49: /* access denied alert from server */
101 return CURLE_REMOTE_ACCESS_DENIED;
102 break;
103 case SSL_ERROR_CONN_LOST:
104 case SSL_ERROR_SOCK_SETUP_FAILURE:
105 case SSL_ERROR_INVALID_HANDSHAKE:
106 case SSL_ERROR_INVALID_PROT_MSG:
107 case SSL_ERROR_INVALID_HMAC:
108 case SSL_ERROR_INVALID_SESSION:
109 case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */
110 case SSL_ERROR_FINISHED_INVALID:
111 case SSL_ERROR_NO_CLIENT_RENOG:
112 default:
113 return CURLE_SSL_CONNECT_ERROR;
114 break;
115 }
116}
117
118static Curl_recv axtls_recv;
119static Curl_send axtls_send;
120
121static void free_ssl_structs(struct ssl_connect_data *connssl)
122{
123 if(connssl->ssl) {
124 ssl_free (connssl->ssl);
125 connssl->ssl = NULL;
126 }
127 if(connssl->ssl_ctx) {
128 ssl_ctx_free(connssl->ssl_ctx);
129 connssl->ssl_ctx = NULL;
130 }
131}
132
133/*
134 * For both blocking and non-blocking connects, this function sets up the
135 * ssl context and state. This function is called after the TCP connect
136 * has completed.
137 */
138static CURLcode connect_prep(struct connectdata *conn, int sockindex)
139{
140 struct 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 */
279static 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 */
395CURLcode 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 */
462CURLcode
463Curl_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 */
510static 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
530void 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 */
550int 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
603static 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 */
650int 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
660void 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
668size_t Curl_axtls_version(char *buffer, size_t size)
669{
670 return snprintf(buffer, size, "axTLS/%s", ssl_version());
671}
672
673int 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 */
Note: See TracBrowser for help on using the repository browser.