*pder_len = (size_t)chain->certs[i].size;
return CURLE_OK;
}
+#endif /* USE_APPLE_SECTRUST */
-static CURLcode glts_apple_verify(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct ssl_peer *peer,
- struct gtls_cert_chain *chain,
- bool *pverified)
+/* This function verifies the peer's certificate and returns CURLE_OK on
+ success or an appropriate CURLcode on error. The certificate verification
+ status bitmask (trusted, invalid etc.) is stored in
+ ssl_config->certverifyresult as one or more gnutls_certificate_status_t
+ enumerated elements bitwise or'd. */
+static CURLcode gtls_verify_cert(struct Curl_easy *data,
+ struct ssl_primary_config *config,
+ struct ssl_config_data *ssl_config,
+ gnutls_session_t session,
+ struct Curl_cfilter *cf,
+ struct ssl_peer *peer,
+ struct gtls_cert_chain *chain)
{
- CURLcode result;
+ bool verified = FALSE;
+ unsigned int verify_status = 0;
+ long * const certverifyresult = &ssl_config->certverifyresult;
+ int rc = gnutls_certificate_verify_peers2(session, &verify_status);
+ if(rc < 0) {
+ failf(data, "server cert verify failed: %d", rc);
+ *certverifyresult = rc;
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ *certverifyresult = verify_status;
+ verified = !(verify_status & GNUTLS_CERT_INVALID);
+ if(verified)
+ infof(data, " SSL certificate verified by GnuTLS");
- result = Curl_vtls_apple_verify(cf, data, peer, chain->num_certs,
- gtls_chain_get_der, chain, NULL, 0);
- *pverified = !result;
- return result;
+#ifdef USE_APPLE_SECTRUST
+ if(!verified && ssl_config->native_ca_store) {
+ CURLcode result =
+ Curl_vtls_apple_verify(cf, data, peer, chain->num_certs,
+ gtls_chain_get_der, chain, NULL, 0);
+ if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
+ return result; /* unexpected error */
+ verified = !result;
+ if(verified) {
+ infof(data, "SSL certificate verified via Apple SecTrust.");
+ *certverifyresult = 0;
+ }
+ }
+#else
+ (void)cf;
+ (void)peer;
+ (void)chain;
+#endif
+
+ if(!verified) {
+ /* verify_status is a bitmask of gnutls_certificate_status bits */
+ const char *cause = "certificate error, no details available";
+ if(verify_status & GNUTLS_CERT_EXPIRED)
+ cause = "certificate has expired";
+ else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ cause = "certificate signer not trusted";
+ else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
+ cause = "certificate uses insecure algorithm";
+ else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
+ cause = "attached OCSP status response is invalid";
+ failf(data, "SSL certificate verification failed: %s. (CAfile: %s "
+ "CRLfile: %s)", cause,
+ config->CAfile ? config->CAfile : "none",
+ ssl_config->primary.CRLfile ?
+ ssl_config->primary.CRLfile : "none");
+
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ return CURLE_OK;
}
-#endif /* USE_APPLE_SECTRUST */
CURLcode Curl_gtls_verifyserver(struct Curl_cfilter *cf,
struct Curl_easy *data,
}
if(config->verifypeer) {
- bool verified = FALSE;
- unsigned int verify_status = 0;
- /* This function tries to verify the peer's certificate and return
- its status (trusted, invalid etc.). The value of status should be
- one or more of the gnutls_certificate_status_t enumerated elements
- bitwise or'd. To avoid denial of service attacks some default
- upper limits regarding the certificate key size and chain size
- are set. To override them use
- gnutls_certificate_set_verify_limits(). */
- rc = gnutls_certificate_verify_peers2(session, &verify_status);
- if(rc < 0) {
- failf(data, "server cert verify failed: %d", rc);
- *certverifyresult = rc;
- result = CURLE_SSL_CONNECT_ERROR;
- goto out;
- }
- *certverifyresult = verify_status;
- verified = !(verify_status & GNUTLS_CERT_INVALID);
- if(verified)
- infof(data, " SSL certificate verified by GnuTLS");
-
-#ifdef USE_APPLE_SECTRUST
- if(!verified && ssl_config->native_ca_store) {
- result = glts_apple_verify(cf, data, peer, &chain, &verified);
- if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
- goto out; /* unexpected error */
- if(verified) {
- infof(data, "SSL certificate verified via Apple SecTrust.");
- *certverifyresult = 0;
- }
- }
-#endif
-
- if(!verified) {
- /* verify_status is a bitmask of gnutls_certificate_status bits */
- const char *cause = "certificate error, no details available";
- if(verify_status & GNUTLS_CERT_EXPIRED)
- cause = "certificate has expired";
- else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
- cause = "certificate signer not trusted";
- else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
- cause = "certificate uses insecure algorithm";
- else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
- cause = "attached OCSP status response is invalid";
- failf(data, "SSL certificate verification failed: %s. (CAfile: %s "
- "CRLfile: %s)", cause,
- config->CAfile ? config->CAfile : "none",
- ssl_config->primary.CRLfile ?
- ssl_config->primary.CRLfile : "none");
- result = CURLE_PEER_FAILED_VERIFICATION;
+ result = gtls_verify_cert(data, config, ssl_config, session,
+ cf, peer, &chain);
+ if(result)
goto out;
- }
}
else
infof(data, " SSL certificate verification SKIPPED");