rustls: add support for CERTINFO

This allows you to use the `certs` and `num_certs` writeout variables in
the curl tool, and getting information about the server certificates
using CURLINFO_CERTINFO.

Closes #16459
This commit is contained in:
Yedaya Katsman 2025-02-24 21:40:19 +02:00 committed by Daniel Stenberg
parent 3175984ab2
commit a55b5b7c62
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
8 changed files with 53 additions and 12 deletions

View File

@ -62,7 +62,7 @@ The variables available are:
## `certs`
Output the certificate chain with details. Supported only by the OpenSSL,
GnuTLS, Schannel and Secure Transport backends. (Added in 7.88.0)
GnuTLS, Schannel, Rustls, and Secure Transport backends. (Added in 7.88.0)
## `conn_id`
The connection identifier last used by the transfer. The connection id is
@ -128,7 +128,7 @@ The http method used in the most recent HTTP request. (Added in 7.72.0)
## `num_certs`
Number of server certificates received in the TLS handshake. Supported only by
the OpenSSL, GnuTLS, Schannel and Secure Transport backends.
the OpenSSL, GnuTLS, Schannel, Rustls and Secure Transport backends.
(Added in 7.88.0)
## `num_connects`

View File

@ -15,6 +15,7 @@ TLS-backend:
- GnuTLS
- Schannel
- Secure Transport
- rustls
Added-in: 7.19.1
---

View File

@ -17,6 +17,7 @@ TLS-backend:
- GnuTLS
- Schannel
- Secure Transport
- rustls
Added-in: 7.19.1
---

View File

@ -43,6 +43,7 @@
#include "connect.h" /* for the connect timeout */
#include "cipher_suite.h"
#include "rand.h"
#include "x509asn1.h"
struct rustls_ssl_backend_data
{
@ -845,6 +846,43 @@ cr_connect(struct Curl_cfilter *cf,
infof(data, "rustls: handshake complete, %s, cipher: %s",
ver, buf);
}
if(data->set.ssl.certinfo) {
size_t num_certs = 0;
while(rustls_connection_get_peer_certificate(rconn, (int)num_certs)) {
num_certs++;
}
result = Curl_ssl_init_certinfo(data, (int)num_certs);
if(result)
return result;
for(size_t i = 0; i < num_certs; i++) {
const rustls_certificate *cert;
const unsigned char *der_data;
size_t der_len;
rustls_result rresult = RUSTLS_RESULT_OK;
cert = rustls_connection_get_peer_certificate(rconn, i);
DEBUGASSERT(cert); /* Should exist since we counted already */
rresult = rustls_certificate_get_der(cert, &der_data, &der_len);
if(rresult != RUSTLS_RESULT_OK) {
char errorbuf[255];
size_t errorlen;
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
failf(data,
"Failed getting DER of server certificate #%ld: %.*s", i,
(int)errorlen, errorbuf);
return map_error(rresult);
}
{
const char *beg;
const char *end;
beg = (const char *)der_data;
end = (const char *)(der_data + der_len);
result = Curl_extract_certinfo(data, (int)i, beg, end);
if(result)
return result;
}
}
}
connssl->state = ssl_connection_complete;
*done = TRUE;
return CURLE_OK;
@ -1011,7 +1049,8 @@ const struct Curl_ssl Curl_ssl_rustls = {
SSLSUPP_CAINFO_BLOB | /* supports */
SSLSUPP_HTTPS_PROXY |
SSLSUPP_CIPHER_LIST |
SSLSUPP_TLS13_CIPHERSUITES,
SSLSUPP_TLS13_CIPHERSUITES |
SSLSUPP_CERTINFO,
sizeof(struct rustls_ssl_backend_data),
NULL, /* init */

View File

@ -26,15 +26,15 @@
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_WOLFSSL)
defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_RUSTLS)
#define WANT_PARSEX509 /* uses Curl_parseX509() */
#endif
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */
#endif
@ -1277,4 +1277,5 @@ done:
#endif /* WANT_EXTRACT_CERTINFO */
#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP
or USE_MBEDTLS or USE_RUSTLS */

View File

@ -29,7 +29,7 @@
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#include "cfilters.h"
#include "urldata.h"
@ -80,7 +80,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data,
#ifdef UNITTESTS
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
/* used by unit1656.c */
CURLcode Curl_x509_GTime2str(struct dynbuf *store,
@ -91,5 +91,6 @@ CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
#endif
#endif
#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP
or USE_MBEDTLS or USE_RUSTLS */
#endif /* HEADER_CURL_X509ASN1_H */

View File

@ -20,7 +20,6 @@ HTTP GET
<features>
SSL
!bearssl
!rustls
!wolfssl
</features>
<server>

View File

@ -25,7 +25,6 @@ SSL
!wolfssl
!bearssl
!mbedtls
!rustls
</features>
<server>
http