connkeep(conn, "HTTP/3 default");
return CURLE_OK;
}
+ /* When a QUIC connect attempt fails, the better error explanation is in
+ 'result' and not in errno */
if(result) {
conn->tempsock[i] = CURL_SOCKET_BAD;
error = SOCKERRNO;
char buffer[STRERROR_LEN];
Curl_printable_address(conn->tempaddr[i], ipaddress,
sizeof(ipaddress));
+#ifdef ENABLE_QUIC
+ if(conn->transport == TRNSPRT_QUIC) {
+ infof(data, "connect to %s port %u failed: %s",
+ ipaddress, conn->port, curl_easy_strerror(result));
+ }
+ else
+#endif
infof(data, "connect to %s port %u failed: %s",
ipaddress, conn->port,
Curl_strerror(error, buffer, sizeof(buffer)));
ainext(conn, i, TRUE);
status = trynextip(data, conn, sockindex, i);
if((status != CURLE_COULDNT_CONNECT) ||
- conn->tempsock[other] == CURL_SOCKET_BAD)
+ conn->tempsock[other] == CURL_SOCKET_BAD) {
/* the last attempt failed and no other sockets remain open */
- result = status;
+ if(!result)
+ result = status;
+ }
}
}
}
/* no more addresses to try */
const char *hostname;
char buffer[STRERROR_LEN];
+ CURLcode failreason = result;
/* if the first address family runs out of addresses to try before the
happy eyeball timeout, go ahead and try the next family now */
if(!result)
return result;
+ result = failreason;
+
#ifndef CURL_DISABLE_PROXY
if(conn->bits.socksproxy)
hostname = conn->socks_proxy.host.name;
hostname = conn->host.name;
failf(data, "Failed to connect to %s port %u after "
- "%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
- hostname, conn->port,
- Curl_timediff(now, data->progress.t_startsingle),
- Curl_strerror(error, buffer, sizeof(buffer)));
+ "%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
+ hostname, conn->port,
+ Curl_timediff(now, data->progress.t_startsingle),
+#ifdef ENABLE_QUIC
+ (conn->transport == TRNSPRT_QUIC) ?
+ curl_easy_strerror(result) :
+#endif
+ Curl_strerror(error, buffer, sizeof(buffer)));
Curl_quic_disconnect(data, conn, 0);
Curl_quic_disconnect(data, conn, 1);
#ifdef USE_OPENSSL
#include <openssl/err.h>
#include <ngtcp2/ngtcp2_crypto_openssl.h>
+#include "vtls/openssl.h"
#elif defined(USE_GNUTLS)
#include <ngtcp2/ngtcp2_crypto_gnutls.h>
#endif
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
}
+ {
+ struct connectdata *conn = data->conn;
+ const char * const ssl_cafile = conn->ssl_config.CAfile;
+ const char * const ssl_capath = conn->ssl_config.CApath;
+
+ if(conn->ssl_config.verifypeer) {
+ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+ /* tell OpenSSL where to find CA certificates that are used to verify
+ the server's certificate. */
+ if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return NULL;
+ }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+ }
return ssl_ctx;
}
return sent;
}
-static void ng_has_connected(struct connectdata *conn, int tempindex)
+static CURLcode ng_has_connected(struct Curl_easy *data,
+ struct connectdata *conn, int tempindex)
{
conn->recv[FIRSTSOCKET] = ngh3_stream_recv;
conn->send[FIRSTSOCKET] = ngh3_stream_send;
conn->httpversion = 30;
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
conn->quic = &conn->hequic[tempindex];
+
+#ifdef USE_OPENSSL
+ if(conn->ssl_config.verifyhost) {
+ X509 *server_cert;
+ CURLcode result;
+ server_cert = SSL_get_peer_certificate(conn->quic->ssl);
+ if(!server_cert) {
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ result = Curl_ossl_verifyhost(data, conn, server_cert);
+ X509_free(server_cert);
+ if(result)
+ return result;
+ infof(data, "Verified certificate just fine");
+ }
+ else
+ infof(data, "Skipped certificate verification");
+#else
+ (void)data;
+#endif
+ return CURLE_OK;
}
/*
if(ngtcp2_conn_get_handshake_completed(qs->qconn)) {
*done = TRUE;
- ng_has_connected(conn, sockindex);
+ result = ng_has_connected(data, conn, sockindex);
}
return result;
rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
if(rv) {
/* TODO Send CONNECTION_CLOSE if possible */
+ if(rv == NGTCP2_ERR_CRYPTO)
+ /* this is a "TLS problem", but a failed certificate verification
+ is a common reason for this */
+ return CURLE_PEER_FAILED_VERIFICATION;
return CURLE_RECV_ERROR;
}
}
hostname. In this case, the iPAddress subjectAltName must be present
in the certificate and must exactly match the IP in the URI.
+ This function is now used from ngtcp2 (QUIC) as well.
*/
-static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert)
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
BIO_free(mem);
if(SSL_CONN_CONFIG(verifyhost)) {
- result = verifyhost(data, conn, backend->server_cert);
+ result = Curl_ossl_verifyhost(data, conn, backend->server_cert);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#ifdef USE_OPENSSL
/*
- * This header should only be needed to get included by vtls.c and openssl.c
+ * This header should only be needed to get included by vtls.c, openssl.c
+ * and ngtcp2.c
*/
+#include <openssl/x509v3.h>
#include "urldata.h"
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert);
extern const struct Curl_ssl Curl_ssl_openssl;
#endif /* USE_OPENSSL */