Return to mesalink.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / vtls |
1.1 ! misho 1: /*************************************************************************** ! 2: * _ _ ____ _ ! 3: * Project ___| | | | _ \| | ! 4: * / __| | | | |_) | | ! 5: * | (__| |_| | _ <| |___ ! 6: * \___|\___/|_| \_\_____| ! 7: * ! 8: * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com> ! 9: * Copyright (C) 1998 - 2019, 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 MesaLink-specific code for the TLS/SSL layer. No code ! 26: * but vtls.c should ever call or use these functions. ! 27: * ! 28: */ ! 29: ! 30: /* ! 31: * Based upon the CyaSSL implementation in cyassl.c and cyassl.h: ! 32: * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. ! 33: * ! 34: * Thanks for code and inspiration! ! 35: */ ! 36: ! 37: #include "curl_setup.h" ! 38: ! 39: #ifdef USE_MESALINK ! 40: ! 41: #include <mesalink/options.h> ! 42: #include <mesalink/version.h> ! 43: ! 44: #include "urldata.h" ! 45: #include "sendf.h" ! 46: #include "inet_pton.h" ! 47: #include "vtls.h" ! 48: #include "parsedate.h" ! 49: #include "connect.h" /* for the connect timeout */ ! 50: #include "select.h" ! 51: #include "strcase.h" ! 52: #include "x509asn1.h" ! 53: #include "curl_printf.h" ! 54: ! 55: #include "mesalink.h" ! 56: #include <mesalink/openssl/ssl.h> ! 57: #include <mesalink/openssl/err.h> ! 58: ! 59: /* The last #include files should be: */ ! 60: #include "curl_memory.h" ! 61: #include "memdebug.h" ! 62: ! 63: #define MESALINK_MAX_ERROR_SZ 80 ! 64: ! 65: struct ssl_backend_data ! 66: { ! 67: SSL_CTX *ctx; ! 68: SSL *handle; ! 69: }; ! 70: ! 71: #define BACKEND connssl->backend ! 72: ! 73: static Curl_recv mesalink_recv; ! 74: static Curl_send mesalink_send; ! 75: ! 76: static int do_file_type(const char *type) ! 77: { ! 78: if(!type || !type[0]) ! 79: return SSL_FILETYPE_PEM; ! 80: if(strcasecompare(type, "PEM")) ! 81: return SSL_FILETYPE_PEM; ! 82: if(strcasecompare(type, "DER")) ! 83: return SSL_FILETYPE_ASN1; ! 84: return -1; ! 85: } ! 86: ! 87: /* ! 88: * This function loads all the client/CA certificates and CRLs. Setup the TLS ! 89: * layer and do all necessary magic. ! 90: */ ! 91: static CURLcode ! 92: mesalink_connect_step1(struct connectdata *conn, int sockindex) ! 93: { ! 94: char *ciphers; ! 95: struct Curl_easy *data = conn->data; ! 96: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 97: struct in_addr addr4; ! 98: #ifdef ENABLE_IPV6 ! 99: struct in6_addr addr6; ! 100: #endif ! 101: const char *const hostname = ! 102: SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; ! 103: size_t hostname_len = strlen(hostname); ! 104: ! 105: SSL_METHOD *req_method = NULL; ! 106: curl_socket_t sockfd = conn->sock[sockindex]; ! 107: ! 108: if(connssl->state == ssl_connection_complete) ! 109: return CURLE_OK; ! 110: ! 111: if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { ! 112: failf(data, "MesaLink does not support to set maximum SSL/TLS version"); ! 113: return CURLE_SSL_CONNECT_ERROR; ! 114: } ! 115: ! 116: switch(SSL_CONN_CONFIG(version)) { ! 117: case CURL_SSLVERSION_SSLv3: ! 118: case CURL_SSLVERSION_TLSv1: ! 119: case CURL_SSLVERSION_TLSv1_0: ! 120: case CURL_SSLVERSION_TLSv1_1: ! 121: failf(data, "MesaLink does not support SSL 3.0, TLS 1.0, or TLS 1.1"); ! 122: return CURLE_NOT_BUILT_IN; ! 123: case CURL_SSLVERSION_DEFAULT: ! 124: case CURL_SSLVERSION_TLSv1_2: ! 125: req_method = TLSv1_2_client_method(); ! 126: break; ! 127: case CURL_SSLVERSION_TLSv1_3: ! 128: req_method = TLSv1_3_client_method(); ! 129: break; ! 130: case CURL_SSLVERSION_SSLv2: ! 131: failf(data, "MesaLink does not support SSLv2"); ! 132: return CURLE_SSL_CONNECT_ERROR; ! 133: default: ! 134: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); ! 135: return CURLE_SSL_CONNECT_ERROR; ! 136: } ! 137: ! 138: if(!req_method) { ! 139: failf(data, "SSL: couldn't create a method!"); ! 140: return CURLE_OUT_OF_MEMORY; ! 141: } ! 142: ! 143: if(BACKEND->ctx) ! 144: SSL_CTX_free(BACKEND->ctx); ! 145: BACKEND->ctx = SSL_CTX_new(req_method); ! 146: ! 147: if(!BACKEND->ctx) { ! 148: failf(data, "SSL: couldn't create a context!"); ! 149: return CURLE_OUT_OF_MEMORY; ! 150: } ! 151: ! 152: SSL_CTX_set_verify( ! 153: BACKEND->ctx, SSL_CONN_CONFIG(verifypeer) ? ! 154: SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); ! 155: ! 156: if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath)) { ! 157: if(!SSL_CTX_load_verify_locations(BACKEND->ctx, SSL_CONN_CONFIG(CAfile), ! 158: SSL_CONN_CONFIG(CApath))) { ! 159: if(SSL_CONN_CONFIG(verifypeer)) { ! 160: failf(data, ! 161: "error setting certificate verify locations:\n" ! 162: " CAfile: %s\n CApath: %s", ! 163: SSL_CONN_CONFIG(CAfile) ? ! 164: SSL_CONN_CONFIG(CAfile) : "none", ! 165: SSL_CONN_CONFIG(CApath) ? ! 166: SSL_CONN_CONFIG(CApath) : "none"); ! 167: return CURLE_SSL_CACERT_BADFILE; ! 168: } ! 169: infof(data, ! 170: "error setting certificate verify locations," ! 171: " continuing anyway:\n"); ! 172: } ! 173: else { ! 174: infof(data, "successfully set certificate verify locations:\n"); ! 175: } ! 176: infof(data, ! 177: " CAfile: %s\n" ! 178: " CApath: %s\n", ! 179: SSL_CONN_CONFIG(CAfile)? ! 180: SSL_CONN_CONFIG(CAfile): "none", ! 181: SSL_CONN_CONFIG(CApath)? ! 182: SSL_CONN_CONFIG(CApath): "none"); ! 183: } ! 184: ! 185: if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { ! 186: int file_type = do_file_type(SSL_SET_OPTION(cert_type)); ! 187: ! 188: if(SSL_CTX_use_certificate_chain_file(BACKEND->ctx, SSL_SET_OPTION(cert), ! 189: file_type) != 1) { ! 190: failf(data, "unable to use client certificate (no key or wrong pass" ! 191: " phrase?)"); ! 192: return CURLE_SSL_CONNECT_ERROR; ! 193: } ! 194: ! 195: file_type = do_file_type(SSL_SET_OPTION(key_type)); ! 196: if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key), ! 197: file_type) != 1) { ! 198: failf(data, "unable to set private key"); ! 199: return CURLE_SSL_CONNECT_ERROR; ! 200: } ! 201: infof(data, ! 202: "client cert: %s\n", ! 203: SSL_CONN_CONFIG(clientcert)? ! 204: SSL_CONN_CONFIG(clientcert): "none"); ! 205: } ! 206: ! 207: ciphers = SSL_CONN_CONFIG(cipher_list); ! 208: if(ciphers) { ! 209: #ifdef MESALINK_HAVE_CIPHER ! 210: if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { ! 211: failf(data, "failed setting cipher list: %s", ciphers); ! 212: return CURLE_SSL_CIPHER; ! 213: } ! 214: #endif ! 215: infof(data, "Cipher selection: %s\n", ciphers); ! 216: } ! 217: ! 218: if(BACKEND->handle) ! 219: SSL_free(BACKEND->handle); ! 220: BACKEND->handle = SSL_new(BACKEND->ctx); ! 221: if(!BACKEND->handle) { ! 222: failf(data, "SSL: couldn't create a context (handle)!"); ! 223: return CURLE_OUT_OF_MEMORY; ! 224: } ! 225: ! 226: if((hostname_len < USHRT_MAX) && ! 227: (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) ! 228: #ifdef ENABLE_IPV6 ! 229: && (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) ! 230: #endif ! 231: ) { ! 232: /* hostname is not a valid IP address */ ! 233: if(SSL_set_tlsext_host_name(BACKEND->handle, hostname) != SSL_SUCCESS) { ! 234: failf(data, ! 235: "WARNING: failed to configure server name indication (SNI) " ! 236: "TLS extension\n"); ! 237: return CURLE_SSL_CONNECT_ERROR; ! 238: } ! 239: } ! 240: else { ! 241: #ifdef CURLDEBUG ! 242: /* Check if the hostname is 127.0.0.1 or [::1]; ! 243: * otherwise reject because MesaLink always wants a valid DNS Name ! 244: * specified in RFC 5280 Section 7.2 */ ! 245: if(strncmp(hostname, "127.0.0.1", 9) == 0 ! 246: #ifdef ENABLE_IPV6 ! 247: || strncmp(hostname, "[::1]", 5) == 0 ! 248: #endif ! 249: ) { ! 250: SSL_set_tlsext_host_name(BACKEND->handle, "localhost"); ! 251: } ! 252: else ! 253: #endif ! 254: { ! 255: failf(data, ! 256: "ERROR: MesaLink does not accept an IP address as a hostname\n"); ! 257: return CURLE_SSL_CONNECT_ERROR; ! 258: } ! 259: } ! 260: ! 261: #ifdef MESALINK_HAVE_SESSION ! 262: if(SSL_SET_OPTION(primary.sessionid)) { ! 263: void *ssl_sessionid = NULL; ! 264: ! 265: Curl_ssl_sessionid_lock(conn); ! 266: if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { ! 267: /* we got a session id, use it! */ ! 268: if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { ! 269: Curl_ssl_sessionid_unlock(conn); ! 270: failf( ! 271: data, ! 272: "SSL: SSL_set_session failed: %s", ! 273: ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer)); ! 274: return CURLE_SSL_CONNECT_ERROR; ! 275: } ! 276: /* Informational message */ ! 277: infof(data, "SSL re-using session ID\n"); ! 278: } ! 279: Curl_ssl_sessionid_unlock(conn); ! 280: } ! 281: #endif /* MESALINK_HAVE_SESSION */ ! 282: ! 283: if(SSL_set_fd(BACKEND->handle, (int)sockfd) != SSL_SUCCESS) { ! 284: failf(data, "SSL: SSL_set_fd failed"); ! 285: return CURLE_SSL_CONNECT_ERROR; ! 286: } ! 287: ! 288: connssl->connecting_state = ssl_connect_2; ! 289: return CURLE_OK; ! 290: } ! 291: ! 292: static CURLcode ! 293: mesalink_connect_step2(struct connectdata *conn, int sockindex) ! 294: { ! 295: int ret = -1; ! 296: struct Curl_easy *data = conn->data; ! 297: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 298: ! 299: conn->recv[sockindex] = mesalink_recv; ! 300: conn->send[sockindex] = mesalink_send; ! 301: ! 302: ret = SSL_connect(BACKEND->handle); ! 303: if(ret != SSL_SUCCESS) { ! 304: int detail = SSL_get_error(BACKEND->handle, ret); ! 305: ! 306: if(SSL_ERROR_WANT_CONNECT == detail || SSL_ERROR_WANT_READ == detail) { ! 307: connssl->connecting_state = ssl_connect_2_reading; ! 308: return CURLE_OK; ! 309: } ! 310: else { ! 311: char error_buffer[MESALINK_MAX_ERROR_SZ]; ! 312: failf(data, ! 313: "SSL_connect failed with error %d: %s", ! 314: detail, ! 315: ERR_error_string_n(detail, error_buffer, sizeof(error_buffer))); ! 316: ERR_print_errors_fp(stderr); ! 317: if(detail && SSL_CONN_CONFIG(verifypeer)) { ! 318: detail &= ~0xFF; ! 319: if(detail == TLS_ERROR_WEBPKI_ERRORS) { ! 320: failf(data, "Cert verify failed"); ! 321: return CURLE_PEER_FAILED_VERIFICATION; ! 322: } ! 323: } ! 324: return CURLE_SSL_CONNECT_ERROR; ! 325: } ! 326: } ! 327: ! 328: connssl->connecting_state = ssl_connect_3; ! 329: infof(data, ! 330: "SSL connection using %s / %s\n", ! 331: SSL_get_version(BACKEND->handle), ! 332: SSL_get_cipher_name(BACKEND->handle)); ! 333: ! 334: return CURLE_OK; ! 335: } ! 336: ! 337: static CURLcode ! 338: mesalink_connect_step3(struct connectdata *conn, int sockindex) ! 339: { ! 340: CURLcode result = CURLE_OK; ! 341: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 342: ! 343: DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); ! 344: ! 345: #ifdef MESALINK_HAVE_SESSION ! 346: if(SSL_SET_OPTION(primary.sessionid)) { ! 347: bool incache; ! 348: SSL_SESSION *our_ssl_sessionid; ! 349: void *old_ssl_sessionid = NULL; ! 350: ! 351: our_ssl_sessionid = SSL_get_session(BACKEND->handle); ! 352: ! 353: Curl_ssl_sessionid_lock(conn); ! 354: incache = ! 355: !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)); ! 356: if(incache) { ! 357: if(old_ssl_sessionid != our_ssl_sessionid) { ! 358: infof(data, "old SSL session ID is stale, removing\n"); ! 359: Curl_ssl_delsessionid(conn, old_ssl_sessionid); ! 360: incache = FALSE; ! 361: } ! 362: } ! 363: ! 364: if(!incache) { ! 365: result = Curl_ssl_addsessionid( ! 366: conn, our_ssl_sessionid, 0 /* unknown size */, sockindex); ! 367: if(result) { ! 368: Curl_ssl_sessionid_unlock(conn); ! 369: failf(data, "failed to store ssl session"); ! 370: return result; ! 371: } ! 372: } ! 373: Curl_ssl_sessionid_unlock(conn); ! 374: } ! 375: #endif /* MESALINK_HAVE_SESSION */ ! 376: ! 377: connssl->connecting_state = ssl_connect_done; ! 378: ! 379: return result; ! 380: } ! 381: ! 382: static ssize_t ! 383: mesalink_send(struct connectdata *conn, int sockindex, const void *mem, ! 384: size_t len, CURLcode *curlcode) ! 385: { ! 386: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 387: char error_buffer[MESALINK_MAX_ERROR_SZ]; ! 388: int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; ! 389: int rc = SSL_write(BACKEND->handle, mem, memlen); ! 390: ! 391: if(rc < 0) { ! 392: int err = SSL_get_error(BACKEND->handle, rc); ! 393: switch(err) { ! 394: case SSL_ERROR_WANT_READ: ! 395: case SSL_ERROR_WANT_WRITE: ! 396: /* there's data pending, re-invoke SSL_write() */ ! 397: *curlcode = CURLE_AGAIN; ! 398: return -1; ! 399: default: ! 400: failf(conn->data, ! 401: "SSL write: %s, errno %d", ! 402: ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), ! 403: SOCKERRNO); ! 404: *curlcode = CURLE_SEND_ERROR; ! 405: return -1; ! 406: } ! 407: } ! 408: return rc; ! 409: } ! 410: ! 411: static void ! 412: Curl_mesalink_close(struct connectdata *conn, int sockindex) ! 413: { ! 414: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 415: ! 416: if(BACKEND->handle) { ! 417: (void)SSL_shutdown(BACKEND->handle); ! 418: SSL_free(BACKEND->handle); ! 419: BACKEND->handle = NULL; ! 420: } ! 421: if(BACKEND->ctx) { ! 422: SSL_CTX_free(BACKEND->ctx); ! 423: BACKEND->ctx = NULL; ! 424: } ! 425: } ! 426: ! 427: static ssize_t ! 428: mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, ! 429: CURLcode *curlcode) ! 430: { ! 431: struct ssl_connect_data *connssl = &conn->ssl[num]; ! 432: char error_buffer[MESALINK_MAX_ERROR_SZ]; ! 433: int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; ! 434: int nread = SSL_read(BACKEND->handle, buf, buffsize); ! 435: ! 436: if(nread <= 0) { ! 437: int err = SSL_get_error(BACKEND->handle, nread); ! 438: ! 439: switch(err) { ! 440: case SSL_ERROR_ZERO_RETURN: /* no more data */ ! 441: case IO_ERROR_CONNECTION_ABORTED: ! 442: break; ! 443: case SSL_ERROR_WANT_READ: ! 444: case SSL_ERROR_WANT_WRITE: ! 445: /* there's data pending, re-invoke SSL_read() */ ! 446: *curlcode = CURLE_AGAIN; ! 447: return -1; ! 448: default: ! 449: failf(conn->data, ! 450: "SSL read: %s, errno %d", ! 451: ERR_error_string_n(err, error_buffer, sizeof(error_buffer)), ! 452: SOCKERRNO); ! 453: *curlcode = CURLE_RECV_ERROR; ! 454: return -1; ! 455: } ! 456: } ! 457: return nread; ! 458: } ! 459: ! 460: static size_t ! 461: Curl_mesalink_version(char *buffer, size_t size) ! 462: { ! 463: return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING); ! 464: } ! 465: ! 466: static int ! 467: Curl_mesalink_init(void) ! 468: { ! 469: return (SSL_library_init() == SSL_SUCCESS); ! 470: } ! 471: ! 472: /* ! 473: * This function is called to shut down the SSL layer but keep the ! 474: * socket open (CCC - Clear Command Channel) ! 475: */ ! 476: static int ! 477: Curl_mesalink_shutdown(struct connectdata *conn, int sockindex) ! 478: { ! 479: int retval = 0; ! 480: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 481: ! 482: if(BACKEND->handle) { ! 483: SSL_free(BACKEND->handle); ! 484: BACKEND->handle = NULL; ! 485: } ! 486: return retval; ! 487: } ! 488: ! 489: static CURLcode ! 490: mesalink_connect_common(struct connectdata *conn, int sockindex, ! 491: bool nonblocking, bool *done) ! 492: { ! 493: CURLcode result; ! 494: struct Curl_easy *data = conn->data; ! 495: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 496: curl_socket_t sockfd = conn->sock[sockindex]; ! 497: timediff_t timeout_ms; ! 498: int what; ! 499: ! 500: /* check if the connection has already been established */ ! 501: if(ssl_connection_complete == connssl->state) { ! 502: *done = TRUE; ! 503: return CURLE_OK; ! 504: } ! 505: ! 506: if(ssl_connect_1 == connssl->connecting_state) { ! 507: /* Find out how much more time we're allowed */ ! 508: timeout_ms = Curl_timeleft(data, NULL, TRUE); ! 509: ! 510: if(timeout_ms < 0) { ! 511: /* no need to continue if time already is up */ ! 512: failf(data, "SSL connection timeout"); ! 513: return CURLE_OPERATION_TIMEDOUT; ! 514: } ! 515: ! 516: result = mesalink_connect_step1(conn, sockindex); ! 517: if(result) ! 518: return result; ! 519: } ! 520: ! 521: while(ssl_connect_2 == connssl->connecting_state || ! 522: ssl_connect_2_reading == connssl->connecting_state || ! 523: ssl_connect_2_writing == connssl->connecting_state) { ! 524: ! 525: /* check allowed time left */ ! 526: timeout_ms = Curl_timeleft(data, NULL, TRUE); ! 527: ! 528: if(timeout_ms < 0) { ! 529: /* no need to continue if time already is up */ ! 530: failf(data, "SSL connection timeout"); ! 531: return CURLE_OPERATION_TIMEDOUT; ! 532: } ! 533: ! 534: /* if ssl is expecting something, check if it's available. */ ! 535: if(connssl->connecting_state == ssl_connect_2_reading || ! 536: connssl->connecting_state == ssl_connect_2_writing) { ! 537: ! 538: curl_socket_t writefd = ! 539: ssl_connect_2_writing == connssl->connecting_state ? sockfd ! 540: : CURL_SOCKET_BAD; ! 541: curl_socket_t readfd = ssl_connect_2_reading == connssl->connecting_state ! 542: ? sockfd ! 543: : CURL_SOCKET_BAD; ! 544: ! 545: what = Curl_socket_check( ! 546: readfd, CURL_SOCKET_BAD, writefd, ! 547: nonblocking ? 0 : (time_t)timeout_ms); ! 548: if(what < 0) { ! 549: /* fatal error */ ! 550: failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); ! 551: return CURLE_SSL_CONNECT_ERROR; ! 552: } ! 553: else if(0 == what) { ! 554: if(nonblocking) { ! 555: *done = FALSE; ! 556: return CURLE_OK; ! 557: } ! 558: else { ! 559: /* timeout */ ! 560: failf(data, "SSL connection timeout"); ! 561: return CURLE_OPERATION_TIMEDOUT; ! 562: } ! 563: } ! 564: /* socket is readable or writable */ ! 565: } ! 566: ! 567: /* Run transaction, and return to the caller if it failed or if ! 568: * this connection is part of a multi handle and this loop would ! 569: * execute again. This permits the owner of a multi handle to ! 570: * abort a connection attempt before step2 has completed while ! 571: * ensuring that a client using select() or epoll() will always ! 572: * have a valid fdset to wait on. ! 573: */ ! 574: result = mesalink_connect_step2(conn, sockindex); ! 575: ! 576: if(result || ! 577: (nonblocking && (ssl_connect_2 == connssl->connecting_state || ! 578: ssl_connect_2_reading == connssl->connecting_state || ! 579: ssl_connect_2_writing == connssl->connecting_state))) { ! 580: return result; ! 581: } ! 582: } /* repeat step2 until all transactions are done. */ ! 583: ! 584: if(ssl_connect_3 == connssl->connecting_state) { ! 585: result = mesalink_connect_step3(conn, sockindex); ! 586: if(result) ! 587: return result; ! 588: } ! 589: ! 590: if(ssl_connect_done == connssl->connecting_state) { ! 591: connssl->state = ssl_connection_complete; ! 592: conn->recv[sockindex] = mesalink_recv; ! 593: conn->send[sockindex] = mesalink_send; ! 594: *done = TRUE; ! 595: } ! 596: else ! 597: *done = FALSE; ! 598: ! 599: /* Reset our connect state machine */ ! 600: connssl->connecting_state = ssl_connect_1; ! 601: ! 602: return CURLE_OK; ! 603: } ! 604: ! 605: static CURLcode ! 606: Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex, ! 607: bool *done) ! 608: { ! 609: return mesalink_connect_common(conn, sockindex, TRUE, done); ! 610: } ! 611: ! 612: static CURLcode ! 613: Curl_mesalink_connect(struct connectdata *conn, int sockindex) ! 614: { ! 615: CURLcode result; ! 616: bool done = FALSE; ! 617: ! 618: result = mesalink_connect_common(conn, sockindex, FALSE, &done); ! 619: if(result) ! 620: return result; ! 621: ! 622: DEBUGASSERT(done); ! 623: ! 624: return CURLE_OK; ! 625: } ! 626: ! 627: static void * ! 628: Curl_mesalink_get_internals(struct ssl_connect_data *connssl, ! 629: CURLINFO info UNUSED_PARAM) ! 630: { ! 631: (void)info; ! 632: return BACKEND->handle; ! 633: } ! 634: ! 635: const struct Curl_ssl Curl_ssl_mesalink = { ! 636: { CURLSSLBACKEND_MESALINK, "MesaLink" }, /* info */ ! 637: ! 638: SSLSUPP_SSL_CTX, ! 639: ! 640: sizeof(struct ssl_backend_data), ! 641: ! 642: Curl_mesalink_init, /* init */ ! 643: Curl_none_cleanup, /* cleanup */ ! 644: Curl_mesalink_version, /* version */ ! 645: Curl_none_check_cxn, /* check_cxn */ ! 646: Curl_mesalink_shutdown, /* shutdown */ ! 647: Curl_none_data_pending, /* data_pending */ ! 648: Curl_none_random, /* random */ ! 649: Curl_none_cert_status_request, /* cert_status_request */ ! 650: Curl_mesalink_connect, /* connect */ ! 651: Curl_mesalink_connect_nonblocking, /* connect_nonblocking */ ! 652: Curl_mesalink_get_internals, /* get_internals */ ! 653: Curl_mesalink_close, /* close_one */ ! 654: Curl_none_close_all, /* close_all */ ! 655: Curl_none_session_free, /* session_free */ ! 656: Curl_none_set_engine, /* set_engine */ ! 657: Curl_none_set_engine_default, /* set_engine_default */ ! 658: Curl_none_engines_list, /* engines_list */ ! 659: Curl_none_false_start, /* false_start */ ! 660: Curl_none_md5sum, /* md5sum */ ! 661: NULL /* sha256sum */ ! 662: }; ! 663: ! 664: #endif