void set( const field_desc_type *fld, const T &v ) { # define VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CppType, TypeName ) \ case field_desc_type::CppType: \ set##TypeName( fld, \ boost::lexical_cast<type_info##TypeName::data_type>(v)); \ break; switch( fld->cpp_type( ) ) { VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_INT32, _int32 ); VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_INT64, _int64 ); VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_UINT32, _uint32 ); VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_UINT64, _uint64 ); VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_FLOAT, _float ); VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_DOUBLE, _double ); VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_STRING, _string ); VTRC_REFLECT_HELPER_DEFINE_CASE_SET( CPPTYPE_BOOL, _bool ); case field_desc_type::CPPTYPE_ENUM: set_enum( fld, boost::lexical_cast<int>(v)); break; default: throw std::runtime_error( "Bad field type" ); } # undef VTRC_REFLECT_HELPER_DEFINE_CASE_SET }
static CURLcode init_environment(struct Curl_easy *data, gsk_handle *envir, const char *appid, const char *file, const char *label, const char *password) { int rc; CURLcode result; gsk_handle h; /* Creates the GSKit environment. */ rc = gsk_environment_open(&h); switch (rc) { case GSK_OK: break; case GSK_INSUFFICIENT_STORAGE: return CURLE_OUT_OF_MEMORY; default: failf(data, "gsk_environment_open(): %s", gsk_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); if(!result && appid) result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); if(!result && file) result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); if(!result && label) result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); if(!result && password) result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); if(!result) { /* Locate CAs, Client certificate and key according to our settings. Note: this call may be blocking for some tenths of seconds. */ result = gskit_status(data, gsk_environment_init(h), "gsk_environment_init()", CURLE_SSL_CERTPROBLEM); if(!result) { *envir = h; return result; } } /* Error: rollback. */ gsk_environment_close(&h); return result; }
static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; gsk_handle envir; CURLcode result; int rc; char *keyringfile; char *keyringpwd; char *keyringlabel; char *sni; unsigned int protoflags; long timeout; Qso_OverlappedIO_t commarea; /* Create SSL environment, start (preferably asynchronous) handshake. */ connssl->handle = (gsk_handle) NULL; connssl->iocport = -1; /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system * level) or by keyring file, password and certificate label. * Local certificate name (CURLOPT_SSLCERT) is used to hold either the * application identifier of the certificate label. * Key password (CURLOPT_KEYPASSWD) holds the keyring password. * It is not possible to have different keyrings for the CAs and the * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify * the keyring file. * If no key password is given and the keyring is the system keyring, * application identifier mode is tried first, as recommended in IBM doc. */ keyringfile = data->set.str[STRING_SSL_CAFILE]; keyringpwd = data->set.str[STRING_KEY_PASSWD]; keyringlabel = data->set.str[STRING_CERT]; envir = (gsk_handle) NULL; if(keyringlabel && *keyringlabel && !keyringpwd && !strcmp(keyringfile, CURL_CA_BUNDLE)) { /* Try application identifier mode. */ init_environment(data, &envir, keyringlabel, (const char *) NULL, (const char *) NULL, (const char *) NULL); } if(!envir) { /* Use keyring mode. */ result = init_environment(data, &envir, (const char *) NULL, keyringfile, keyringlabel, keyringpwd); if(result) return result; } /* Create secure session. */ result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle), "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); gsk_environment_close(&envir); if(result) return result; /* Determine which SSL/TLS version should be enabled. */ protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; sni = conn->host.name; switch (data->set.ssl.version) { case CURL_SSLVERSION_SSLv2: protoflags = CURL_GSKPROTO_SSLV2_MASK; sni = (char *) NULL; break; case CURL_SSLVERSION_SSLv3: protoflags = CURL_GSKPROTO_SSLV3_MASK; sni = (char *) NULL; break; case CURL_SSLVERSION_TLSv1: protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; break; case CURL_SSLVERSION_TLSv1_0: protoflags = CURL_GSKPROTO_TLSV10_MASK; break; case CURL_SSLVERSION_TLSv1_1: protoflags = CURL_GSKPROTO_TLSV11_MASK; break; case CURL_SSLVERSION_TLSv1_2: protoflags = CURL_GSKPROTO_TLSV12_MASK; break; } /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ if(sni) { result = set_buffer(data, connssl->handle, GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); if(result == CURLE_UNSUPPORTED_PROTOCOL) result = CURLE_OK; } /* Set session parameters. */ if(!result) { /* Compute the handshake timeout. Since GSKit granularity is 1 second, we round up the required value. */ timeout = Curl_timeleft(data, NULL, TRUE); if(timeout < 0) result = CURLE_OPERATION_TIMEDOUT; else result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT, (timeout + 999) / 1000); } if(!result) result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); if(!result) result = set_ciphers(data, connssl->handle, &protoflags); if(!protoflags) { failf(data, "No SSL protocol/cipher combination enabled"); result = CURLE_SSL_CIPHER; } if(!result) result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2, (protoflags & CURL_GSKPROTO_SSLV2_MASK)? GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); if(!result) result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3, (protoflags & CURL_GSKPROTO_SSLV3_MASK)? GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); if(!result) result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1, (protoflags & CURL_GSKPROTO_TLSV10_MASK)? GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); if(!result) { result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11, (protoflags & CURL_GSKPROTO_TLSV11_MASK)? GSK_TRUE: GSK_FALSE, TRUE); if(result == CURLE_UNSUPPORTED_PROTOCOL) { result = CURLE_OK; if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { failf(data, "TLS 1.1 not yet supported"); result = CURLE_SSL_CIPHER; } } } if(!result) { result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12, (protoflags & CURL_GSKPROTO_TLSV12_MASK)? GSK_TRUE: GSK_FALSE, TRUE); if(result == CURLE_UNSUPPORTED_PROTOCOL) { result = CURLE_OK; if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { failf(data, "TLS 1.2 not yet supported"); result = CURLE_SSL_CIPHER; } } } if(!result) result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL: GSK_SERVER_AUTH_PASSTHRU, FALSE); if(!result) { /* Start handshake. Try asynchronous first. */ memset(&commarea, 0, sizeof commarea); connssl->iocport = QsoCreateIOCompletionPort(); if(connssl->iocport != -1) { result = gskit_status(data, gsk_secure_soc_startInit(connssl->handle, connssl->iocport, &commarea), "gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR); if(!result) { connssl->connecting_state = ssl_connect_2; return CURLE_OK; } else close_async_handshake(connssl); } else if(errno != ENOBUFS) result = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); else { /* No more completion port available. Use synchronous IO. */ result = gskit_status(data, gsk_secure_soc_init(connssl->handle), "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); if(!result) { connssl->connecting_state = ssl_connect_3; return CURLE_OK; } } } /* Error: rollback. */ close_one(connssl, data); return result; }
static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; gsk_handle envir; CURLcode result; int rc; const char * const keyringfile = SSL_CONN_CONFIG(CAfile); const char * const keyringpwd = SSL_SET_OPTION(key_passwd); const char * const keyringlabel = SSL_SET_OPTION(cert); const long int ssl_version = SSL_CONN_CONFIG(version); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: conn->host.name; const char *sni; unsigned int protoflags; long timeout; Qso_OverlappedIO_t commarea; int sockpair[2]; static const int sobufsize = CURL_MAX_WRITE_SIZE; /* Create SSL environment, start (preferably asynchronous) handshake. */ connssl->handle = (gsk_handle) NULL; connssl->iocport = -1; connssl->localfd = -1; connssl->remotefd = -1; /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system * level) or by keyring file, password and certificate label. * Local certificate name (CURLOPT_SSLCERT) is used to hold either the * application identifier of the certificate label. * Key password (CURLOPT_KEYPASSWD) holds the keyring password. * It is not possible to have different keyrings for the CAs and the * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify * the keyring file. * If no key password is given and the keyring is the system keyring, * application identifier mode is tried first, as recommended in IBM doc. */ envir = (gsk_handle) NULL; if(keyringlabel && *keyringlabel && !keyringpwd && !strcmp(keyringfile, CURL_CA_BUNDLE)) { /* Try application identifier mode. */ init_environment(data, &envir, keyringlabel, (const char *) NULL, (const char *) NULL, (const char *) NULL); } if(!envir) { /* Use keyring mode. */ result = init_environment(data, &envir, (const char *) NULL, keyringfile, keyringlabel, keyringpwd); if(result) return result; } /* Create secure session. */ result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle), "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); gsk_environment_close(&envir); if(result) return result; /* Establish a pipelining socket pair for SSL over SSL. */ if(conn->proxy_ssl[sockindex].use) { if(inetsocketpair(sockpair)) return CURLE_SSL_CONNECT_ERROR; connssl->localfd = sockpair[0]; connssl->remotefd = sockpair[1]; setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF, (void *) sobufsize, sizeof sobufsize); setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF, (void *) sobufsize, sizeof sobufsize); setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF, (void *) sobufsize, sizeof sobufsize); setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF, (void *) sobufsize, sizeof sobufsize); curlx_nonblock(connssl->localfd, TRUE); curlx_nonblock(connssl->remotefd, TRUE); } /* Determine which SSL/TLS version should be enabled. */ sni = hostname; switch (ssl_version) { case CURL_SSLVERSION_SSLv2: protoflags = CURL_GSKPROTO_SSLV2_MASK; sni = NULL; break; case CURL_SSLVERSION_SSLv3: protoflags = CURL_GSKPROTO_SSLV3_MASK; sni = NULL; break; case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; break; case CURL_SSLVERSION_TLSv1_0: protoflags = CURL_GSKPROTO_TLSV10_MASK; break; case CURL_SSLVERSION_TLSv1_1: protoflags = CURL_GSKPROTO_TLSV11_MASK; break; case CURL_SSLVERSION_TLSv1_2: protoflags = CURL_GSKPROTO_TLSV12_MASK; break; case CURL_SSLVERSION_TLSv1_3: failf(data, "GSKit: TLS 1.3 is not yet supported"); return CURLE_SSL_CONNECT_ERROR; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ if(sni) { result = set_buffer(data, connssl->handle, GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); if(result == CURLE_UNSUPPORTED_PROTOCOL) result = CURLE_OK; } /* Set session parameters. */ if(!result) { /* Compute the handshake timeout. Since GSKit granularity is 1 second, we round up the required value. */ timeout = Curl_timeleft(data, NULL, TRUE); if(timeout < 0) result = CURLE_OPERATION_TIMEDOUT; else result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT, (timeout + 999) / 1000); } if(!result) result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1); if(!result) result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0? connssl->localfd: conn->sock[sockindex]); if(!result) result = set_ciphers(conn, connssl->handle, &protoflags); if(!protoflags) { failf(data, "No SSL protocol/cipher combination enabled"); result = CURLE_SSL_CIPHER; } if(!result) result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2, (protoflags & CURL_GSKPROTO_SSLV2_MASK)? GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); if(!result) result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3, (protoflags & CURL_GSKPROTO_SSLV3_MASK)? GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); if(!result) result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1, (protoflags & CURL_GSKPROTO_TLSV10_MASK)? GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); if(!result) { result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11, (protoflags & CURL_GSKPROTO_TLSV11_MASK)? GSK_TRUE: GSK_FALSE, TRUE); if(result == CURLE_UNSUPPORTED_PROTOCOL) { result = CURLE_OK; if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { failf(data, "TLS 1.1 not yet supported"); result = CURLE_SSL_CIPHER; } } } if(!result) { result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12, (protoflags & CURL_GSKPROTO_TLSV12_MASK)? GSK_TRUE: GSK_FALSE, TRUE); if(result == CURLE_UNSUPPORTED_PROTOCOL) { result = CURLE_OK; if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { failf(data, "TLS 1.2 not yet supported"); result = CURLE_SSL_CIPHER; } } } if(!result) result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, verifypeer? GSK_SERVER_AUTH_FULL: GSK_SERVER_AUTH_PASSTHRU, FALSE); if(!result) { /* Start handshake. Try asynchronous first. */ memset(&commarea, 0, sizeof commarea); connssl->iocport = QsoCreateIOCompletionPort(); if(connssl->iocport != -1) { result = gskit_status(data, gsk_secure_soc_startInit(connssl->handle, connssl->iocport, &commarea), "gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR); if(!result) { connssl->connecting_state = ssl_connect_2; return CURLE_OK; } else close_async_handshake(connssl); } else if(errno != ENOBUFS) result = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); else if(conn->proxy_ssl[sockindex].use) { /* Cannot pipeline while handshaking synchronously. */ result = CURLE_SSL_CONNECT_ERROR; } else { /* No more completion port available. Use synchronous IO. */ result = gskit_status(data, gsk_secure_soc_init(connssl->handle), "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); if(!result) { connssl->connecting_state = ssl_connect_3; return CURLE_OK; } } } /* Error: rollback. */ close_one(connssl, conn, sockindex); return result; }
static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex) { struct SessionHandle * data = conn->data; struct ssl_connect_data * connssl = &conn->ssl[sockindex]; gsk_handle envir; CURLcode cc; int rc; char * keyringfile; char * keyringpwd; char * keyringlabel; char * v2ciphers; char * v3ciphers; char * sni; bool sslv2enable, sslv3enable, tlsv1enable; long timeout; Qso_OverlappedIO_t commarea; /* Create SSL environment, start (preferably asynchronous) handshake. */ connssl->handle = (gsk_handle) NULL; connssl->iocport = -1; /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system * level) or by keyring file, password and certificate label. * Local certificate name (CURLOPT_SSLCERT) is used to hold either the * application identifier of the certificate label. * Key password (CURLOPT_KEYPASSWD) holds the keyring password. * It is not possible to have different keyrings for the CAs and the * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify * the keyring file. * If no key password is given and the keyring is the system keyring, * application identifier mode is tried first, as recommended in IBM doc. */ keyringfile = data->set.str[STRING_SSL_CAFILE]; keyringpwd = data->set.str[STRING_KEY_PASSWD]; keyringlabel = data->set.str[STRING_CERT]; envir = (gsk_handle) NULL; if(keyringlabel && *keyringlabel && !keyringpwd && !strcmp(keyringfile, CURL_CA_BUNDLE)) { /* Try application identifier mode. */ init_environment(data, &envir, keyringlabel, (const char *) NULL, (const char *) NULL, (const char *) NULL); } if(!envir) { /* Use keyring mode. */ cc = init_environment(data, &envir, (const char *) NULL, keyringfile, keyringlabel, keyringpwd); if(cc != CURLE_OK) return cc; } /* Create secure session. */ cc = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle), "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR); gsk_environment_close(&envir); if(cc != CURLE_OK) return cc; /* Determine which SSL/TLS version should be enabled. */ sslv2enable = sslv3enable = tlsv1enable = false; sni = conn->host.name; switch (data->set.ssl.version) { case CURL_SSLVERSION_SSLv2: sslv2enable = true; sni = (char *) NULL; break; case CURL_SSLVERSION_SSLv3: sslv3enable = true; sni = (char *) NULL; break; case CURL_SSLVERSION_TLSv1: tlsv1enable = true; break; default: /* CURL_SSLVERSION_DEFAULT. */ sslv3enable = true; tlsv1enable = true; break; } /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ if(sni) { rc = gsk_attribute_set_buffer(connssl->handle, GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, 0); switch (rc) { case GSK_OK: case GSK_ATTRIBUTE_INVALID_ID: break; case GSK_ERROR_IO: failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); cc = CURLE_SSL_CONNECT_ERROR; break; default: failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); cc = CURLE_SSL_CONNECT_ERROR; break; } } /* Set session parameters. */ if(cc == CURLE_OK) { /* Compute the handshake timeout. Since GSKit granularity is 1 second, we round up the required value. */ timeout = Curl_timeleft(data, NULL, TRUE); if(timeout < 0) cc = CURLE_OPERATION_TIMEDOUT; else cc = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT, (timeout + 999) / 1000); } if(cc == CURLE_OK) cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); if(cc == CURLE_OK) cc = set_ciphers(data, connssl->handle); if(cc == CURLE_OK) cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2, sslv2enable? GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF); if(cc == CURLE_OK) cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3, sslv3enable? GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF); if(cc == CURLE_OK) cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1, sslv3enable? GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF); if(cc == CURLE_OK) cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL: GSK_SERVER_AUTH_PASSTHRU); if(cc == CURLE_OK) { /* Start handshake. Try asynchronous first. */ memset(&commarea, 0, sizeof commarea); connssl->iocport = QsoCreateIOCompletionPort(); if(connssl->iocport != -1) { cc = gskit_status(data, gsk_secure_soc_startInit(connssl->handle, connssl->iocport, &commarea), "gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR); if(cc == CURLE_OK) { connssl->connecting_state = ssl_connect_2; return CURLE_OK; } else close_async_handshake(connssl); } else if(errno != ENOBUFS) cc = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); else { /* No more completion port available. Use synchronous IO. */ cc = gskit_status(data, gsk_secure_soc_init(connssl->handle), "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR); if(cc == CURLE_OK) { connssl->connecting_state = ssl_connect_3; return CURLE_OK; } } } /* Error: rollback. */ close_one(connssl, data); return cc; }