in libs/curl/lib/vtls/sectransp.c [1944:2271]
static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
struct st_ssl_backend_data *backend =
(struct st_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
OSStatus err;
SSLCipherSuite cipher;
SSLProtocol protocol = 0;
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state);
DEBUGASSERT(backend);
CURL_TRC_CF(data, cf, "connect_step2");
/* Here goes nothing: */
check_handshake:
connssl->io_need = CURL_SSL_IO_NEED_NONE;
err = SSLHandshake(backend->ssl_ctx);
if(err != noErr) {
switch(err) {
case errSSLWouldBlock: /* they are not done with us yet */
connssl->io_need = backend->ssl_direction ?
CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
return CURLE_OK;
/* The below is errSSLServerAuthCompleted; it is not defined in
Leopard's headers */
case -9841:
if((conn_config->CAfile || conn_config->ca_info_blob) &&
conn_config->verifypeer) {
CURLcode result = verify_cert(cf, data, conn_config->CAfile,
conn_config->ca_info_blob,
backend->ssl_ctx);
if(result)
return result;
}
/* the documentation says we need to call SSLHandshake() again */
goto check_handshake;
/* Problem with encrypt / decrypt */
case errSSLPeerDecodeError:
failf(data, "Decode failed");
break;
case errSSLDecryptionFail:
case errSSLPeerDecryptionFail:
failf(data, "Decryption failed");
break;
case errSSLPeerDecryptError:
failf(data, "A decryption error occurred");
break;
case errSSLBadCipherSuite:
failf(data, "A bad SSL cipher suite was encountered");
break;
case errSSLCrypto:
failf(data, "An underlying cryptographic error was encountered");
break;
#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
case errSSLWeakPeerEphemeralDHKey:
failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
break;
#endif
/* Problem with the message record validation */
case errSSLBadRecordMac:
case errSSLPeerBadRecordMac:
failf(data, "A record with a bad message authentication code (MAC) "
"was encountered");
break;
case errSSLRecordOverflow:
case errSSLPeerRecordOverflow:
failf(data, "A record overflow occurred");
break;
/* Problem with zlib decompression */
case errSSLPeerDecompressFail:
failf(data, "Decompression failed");
break;
/* Problem with access */
case errSSLPeerAccessDenied:
failf(data, "Access was denied");
break;
case errSSLPeerInsufficientSecurity:
failf(data, "There is insufficient security for this operation");
break;
/* These are all certificate problems with the server: */
case errSSLXCertChainInvalid:
failf(data, "SSL certificate problem: Invalid certificate chain");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLUnknownRootCert:
failf(data, "SSL certificate problem: Untrusted root certificate");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLNoRootCert:
failf(data, "SSL certificate problem: No root certificate");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLCertNotYetValid:
failf(data, "SSL certificate problem: The certificate chain had a "
"certificate that is not yet valid");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLCertExpired:
case errSSLPeerCertExpired:
failf(data, "SSL certificate problem: Certificate chain had an "
"expired certificate");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLBadCert:
case errSSLPeerBadCert:
failf(data, "SSL certificate problem: Couldn't understand the server "
"certificate format");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLPeerUnsupportedCert:
failf(data, "SSL certificate problem: An unsupported certificate "
"format was encountered");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLPeerCertRevoked:
failf(data, "SSL certificate problem: The certificate was revoked");
return CURLE_PEER_FAILED_VERIFICATION;
case errSSLPeerCertUnknown:
failf(data, "SSL certificate problem: The certificate is unknown");
return CURLE_PEER_FAILED_VERIFICATION;
/* These are all certificate problems with the client: */
case errSecAuthFailed:
failf(data, "SSL authentication failed");
break;
case errSSLPeerHandshakeFail:
failf(data, "SSL peer handshake failed, the server most likely "
"requires a client certificate to connect");
break;
case errSSLPeerUnknownCA:
failf(data, "SSL server rejected the client certificate due to "
"the certificate being signed by an unknown certificate "
"authority");
break;
/* This error is raised if the server's cert did not match the server's
hostname: */
case errSSLHostNameMismatch:
failf(data, "SSL certificate peer verification failed, the "
"certificate did not match \"%s\"\n", connssl->peer.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
/* Problem with SSL / TLS negotiation */
case errSSLNegotiation:
failf(data, "Could not negotiate an SSL cipher suite with the server");
break;
case errSSLBadConfiguration:
failf(data, "A configuration error occurred");
break;
case errSSLProtocol:
failf(data, "SSL protocol error");
break;
case errSSLPeerProtocolVersion:
failf(data, "A bad protocol version was encountered");
break;
case errSSLPeerNoRenegotiation:
failf(data, "No renegotiation is allowed");
break;
/* Generic handshake errors: */
case errSSLConnectionRefused:
failf(data, "Server dropped the connection during the SSL handshake");
break;
case errSSLClosedAbort:
failf(data, "Server aborted the SSL handshake");
break;
case errSSLClosedGraceful:
failf(data, "The connection closed gracefully");
break;
case errSSLClosedNoNotify:
failf(data, "The server closed the session with no notification");
break;
/* Sometimes paramErr happens with buggy ciphers: */
case paramErr:
case errSSLInternal:
case errSSLPeerInternalError:
failf(data, "Internal SSL engine error encountered during the "
"SSL handshake");
break;
case errSSLFatalAlert:
failf(data, "Fatal SSL engine error encountered during the SSL "
"handshake");
break;
/* Unclassified error */
case errSSLBufferOverflow:
failf(data, "An insufficient buffer was provided");
break;
case errSSLIllegalParam:
failf(data, "An illegal parameter was encountered");
break;
case errSSLModuleAttach:
failf(data, "Module attach failure");
break;
case errSSLSessionNotFound:
failf(data, "An attempt to restore an unknown session failed");
break;
case errSSLPeerExportRestriction:
failf(data, "An export restriction occurred");
break;
case errSSLPeerUserCancelled:
failf(data, "The user canceled the operation");
break;
case errSSLPeerUnexpectedMsg:
failf(data, "Peer rejected unexpected message");
break;
#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
/* Treating non-fatal error as fatal like before */
case errSSLClientHelloReceived:
failf(data, "A non-fatal result for providing a server name "
"indication");
break;
#endif
/* Error codes defined in the enum but should never be returned.
We list them here just in case. */
#if CURL_BUILD_MAC_10_6
/* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
case errSSLClientCertRequested:
failf(data, "Server requested a client certificate during the "
"handshake");
return CURLE_SSL_CLIENTCERT;
#endif
#if CURL_BUILD_MAC_10_9
/* Alias for errSSLLast, end of error range */
case errSSLUnexpectedRecord:
failf(data, "Unexpected (skipped) record in DTLS");
break;
#endif
default:
/* May also return codes listed in Security Framework Result Codes */
failf(data, "Unknown SSL protocol error in connection to %s:%d",
connssl->peer.hostname, err);
break;
}
return CURLE_SSL_CONNECT_ERROR;
}
else {
char cipher_str[64];
/* we have been connected fine, we are not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
#ifdef SECTRANSP_PINNEDPUBKEY
if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
CURLcode result =
pkp_pin_peer_pubkey(data, backend->ssl_ctx,
data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
if(result) {
failf(data, "SSL: public key does not match pinned public key");
return result;
}
}
#endif /* SECTRANSP_PINNEDPUBKEY */
/* Informational message */
(void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
(void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
sectransp_cipher_suite_get_str((uint16_t) cipher, cipher_str,
sizeof(cipher_str), true);
switch(protocol) {
case kSSLProtocol2:
infof(data, "SSL 2.0 connection using %s", cipher_str);
break;
case kSSLProtocol3:
infof(data, "SSL 3.0 connection using %s", cipher_str);
break;
case kTLSProtocol1:
infof(data, "TLS 1.0 connection using %s", cipher_str);
break;
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
case kTLSProtocol11:
infof(data, "TLS 1.1 connection using %s", cipher_str);
break;
case kTLSProtocol12:
infof(data, "TLS 1.2 connection using %s", cipher_str);
break;
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
case kTLSProtocol13:
infof(data, "TLS 1.3 connection using %s", cipher_str);
break;
#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
default:
infof(data, "Unknown protocol connection");
break;
}
#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && \
defined(HAVE_BUILTIN_AVAILABLE)
if(connssl->alpn) {
if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
CFArrayRef alpnArr = NULL;
CFStringRef chosenProtocol = NULL;
err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
#ifdef USE_HTTP2
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
cf->conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
cf->conn->alpn = CURL_HTTP_VERSION_1_1;
}
else
infof(data, VTLS_INFOF_NO_ALPN);
Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
/* chosenProtocol is a reference to the string within alpnArr
and does not need to be freed separately */
if(alpnArr)
CFRelease(alpnArr);
}
}
#endif
return CURLE_OK;
}
}