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() */ 51int 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 59int Curl_axtls_cleanup(void) 60{ 61 /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */ 62 return 1; 63} 64 65static 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 117static Curl_recv axtls_recv; 118static Curl_send axtls_send; 119 120static 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 */ 137static 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 */ 278static 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 */ 394CURLcode 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 */ 461CURLcode 462Curl_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 } 485 infof (conn->data, "handshake completed successfully\n"); 486 487 conn_step = connect_finish(conn, sockindex); 488 if(conn_step != CURLE_OK) { 489 Curl_axtls_close(conn, sockindex); 490 return conn_step; 491 } 492 493 return CURLE_OK; 494} 495 496/* return number of sent (non-SSL) bytes */ 497static ssize_t axtls_send(struct connectdata *conn, 498 int sockindex, 499 const void *mem, 500 size_t len, 501 CURLcode *err) 502{ 503 /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ 504 int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); 505 506 infof(conn->data, " axtls_send\n"); 507 508 if(rc < 0 ) { 509 *err = map_error_to_curl(rc); 510 rc = -1; /* generic error code for send failure */ 511 } 512 513 *err = CURLE_OK; 514 return rc; 515} 516 517void Curl_axtls_close_all(struct SessionHandle *data) 518{ 519 (void)data; 520 infof(data, " Curl_axtls_close_all\n"); 521} 522 523void Curl_axtls_close(struct connectdata *conn, int sockindex) 524{ 525 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 526 527 infof(conn->data, " Curl_axtls_close\n"); 528 529 /* line from openssl.c: (void)SSL_shutdown(connssl->ssl); 530 axTLS compat layer does nothing for SSL_shutdown */ 531 532 /* The following line is from openssl.c. There seems to be no axTLS 533 equivalent. ssl_free and ssl_ctx_free close things. 534 SSL_set_connect_state(connssl->handle); */ 535 536 free_ssl_structs(connssl); 537} 538 539/* 540 * This function is called to shut down the SSL layer but keep the 541 * socket open (CCC - Clear Command Channel) 542 */ 543int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) 544{ 545 /* Outline taken from openssl.c since functions are in axTLS compat layer. 546 axTLS's error set is much smaller, so a lot of error-handling was removed. 547 */ 548 int retval = 0; 549 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 550 struct SessionHandle *data = conn->data; 551 uint8_t *buf; 552 ssize_t nread; 553 554 infof(conn->data, " Curl_axtls_shutdown\n"); 555 556 /* This has only been tested on the proftpd server, and the mod_tls code 557 sends a close notify alert without waiting for a close notify alert in 558 response. Thus we wait for a close notify alert from the server, but 559 we do not send one. Let's hope other servers do the same... */ 560 561 /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too 562 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 563 (void)SSL_shutdown(connssl->ssl); 564 */ 565 566 if(connssl->ssl) { 567 int what = Curl_socket_ready(conn->sock[sockindex], 568 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); 569 if(what > 0) { 570 /* Something to read, let's do it and hope that it is the close 571 notify alert from the server. buf is managed internally by 572 axTLS and will be released upon calling ssl_free via 573 free_ssl_structs. */ 574 nread = (ssize_t)ssl_read(connssl->ssl, &buf); 575 576 if(nread < SSL_OK) { 577 failf(data, "close notify alert not received during shutdown"); 578 retval = -1; 579 } 580 } 581 else if(0 == what) { 582 /* timeout */ 583 failf(data, "SSL shutdown timeout"); 584 } 585 else { 586 /* anything that gets here is fatally bad */ 587 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 588 retval = -1; 589 } 590 591 free_ssl_structs(connssl); 592 } 593 return retval; 594} 595 596static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ 597 int num, /* socketindex */ 598 char *buf, /* store read data here */ 599 size_t buffersize, /* max amount to read */ 600 CURLcode *err) 601{ 602 struct ssl_connect_data *connssl = &conn->ssl[num]; 603 ssize_t ret = 0; 604 uint8_t *read_buf; 605 606 infof(conn->data, " axtls_recv\n"); 607 608 *err = CURLE_OK; 609 if(connssl) { 610 ret = ssl_read(connssl->ssl, &read_buf); 611 if(ret > SSL_OK) { 612 /* ssl_read returns SSL_OK if there is more data to read, so if it is 613 larger, then all data has been read already. */ 614 memcpy(buf, read_buf, 615 (size_t)ret > buffersize ? buffersize : (size_t)ret); 616 } 617 else if(ret == SSL_OK) { 618 /* more data to be read, signal caller to call again */ 619 *err = CURLE_AGAIN; 620 ret = -1; 621 } 622 else if(ret == -3) { 623 /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS 624 team approves proposed fix. */ 625 Curl_axtls_close(conn, num); 626 } 627 else { 628 failf(conn->data, "axTLS recv error (%d)", ret); 629 *err = map_error_to_curl((int) ret); 630 ret = -1; 631 } 632 } 633 634 return ret; 635} 636 637/* 638 * Return codes: 639 * 1 means the connection is still in place 640 * 0 means the connection has been closed 641 * -1 means the connection status is unknown 642 */ 643int Curl_axtls_check_cxn(struct connectdata *conn) 644{ 645 /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); 646 axTLS compat layer always returns the last argument, so connection is 647 always alive? */ 648 649 infof(conn->data, " Curl_axtls_check_cxn\n"); 650 return 1; /* connection still in place */ 651} 652 653void Curl_axtls_session_free(void *ptr) 654{ 655 (void)ptr; 656 /* free the ID */ 657 /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL 658 compatibility layer does nothing, so we do nothing too. */ 659} 660 661size_t Curl_axtls_version(char *buffer, size_t size) 662{ 663 return snprintf(buffer, size, "axTLS/%s", ssl_version()); 664} 665 666#endif /* USE_AXTLS */ 667