Procházet zdrojové kódy

[eval] Fix ssl cert verification failures on clean windows environments (#11838)

* Use windows api to verify ssl certs

Taken from:
https://github.com/Apprentice-Alchemist/hashlink/commit/4d590124f91e3b142724c215468892481598e804

* Handle error if cert store fails to open

* Fix mscv warnings about invalid arguments

Warning	C6387	'parameters' could be '0':  this does not adhere to the specification for the function 'CertGetCertificateChain'.

Warning	C6387	'policy_parameters' could be '0':  this does not adhere to the specification for the function 'CertVerifyCertificateChainPolicy'.

This also fixes an "incorrect parameter" runtime error.

* Clear errors if certificate loading succeeded

* Perform checks for all calls of verify_callback

We need to do this every time, because if any callback call returns a
non zero flags then the entire verification fails, see:
https://github.com/Mbed-TLS/mbedtls/blob/3aefa5b705846c5d4466ae8747160ae9e5054ea8/library/x509_crt.c#L3031

We don't need to loop through the chain, since mbedtls already loops
through and calls the callback on every certificate in the chain.

* Free handles on certificate verification errors

* Replace existing certificates if they exist

This avoids duplicate certificates in the store

* Propagate CN_MISMATCH ssl cert error

The windows api functions won't check this automatically for us without
further modifications, so it's easiest to just respect mbedtls'
judgement and propagate this error.

* Clarify comment regarding error mapping

* Skip verification callback if no errors were found
tobil4sk před 8 měsíci
rodič
revize
ce475f8524
1 změnil soubory, kde provedl 47 přidání a 0 odebrání
  1. 47 0
      libs/mbedtls/mbedtls_stubs.c

+ 47 - 0
libs/mbedtls/mbedtls_stubs.c

@@ -302,12 +302,59 @@ static struct custom_operations ssl_config_ops = {
 	.deserialize = custom_deserialize_default,
 };
 
+#ifdef _WIN32
+static int verify_callback(void* param, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
+	if (*flags == 0 || *flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
+		return 0;
+	}
+
+	HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL);
+	if(store == NULL) {
+		return MBEDTLS_ERR_X509_FATAL_ERROR;
+	}
+	PCCERT_CONTEXT primary_context = {0};
+	if(!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, crt->raw.p, crt->raw.len, CERT_STORE_ADD_REPLACE_EXISTING, &primary_context)) {
+		CertCloseStore(store, 0);
+		return MBEDTLS_ERR_X509_FATAL_ERROR;
+	}
+	PCCERT_CHAIN_CONTEXT chain_context = {0};
+	CERT_CHAIN_PARA parameters = {0};
+	if(!CertGetCertificateChain(NULL, primary_context, NULL, store, &parameters, 0, NULL, &chain_context)) {
+		CertFreeCertificateContext(primary_context);
+		CertCloseStore(store, 0);
+		return MBEDTLS_ERR_X509_FATAL_ERROR;
+	}
+	CERT_CHAIN_POLICY_PARA policy_parameters = {0};
+	CERT_CHAIN_POLICY_STATUS policy_status = {0};
+	if(!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, chain_context, &policy_parameters, &policy_status)) {
+		CertFreeCertificateChain(chain_context);
+		CertFreeCertificateContext(primary_context);
+		CertCloseStore(store, 0);
+		return MBEDTLS_ERR_X509_FATAL_ERROR;
+	}
+	if(policy_status.dwError == 0) {
+		*flags = 0;
+	} else {
+		// if we ever want to read the verification result,
+		// we need to properly map dwError to flags
+		*flags |= MBEDTLS_X509_BADCERT_OTHER;
+	}
+	CertFreeCertificateChain(chain_context);
+	CertFreeCertificateContext(primary_context);
+	CertCloseStore(store, 0);
+	return 0;
+}
+#endif
+
 CAMLprim value ml_mbedtls_ssl_config_init(void) {
 	CAMLparam0();
 	CAMLlocal1(obj);
 	obj = caml_alloc_custom(&ssl_config_ops, sizeof(mbedtls_ssl_config*), 0, 1);
 	mbedtls_ssl_config* ssl_config = malloc(sizeof(mbedtls_ssl_config));
 	mbedtls_ssl_config_init(ssl_config);
+	#ifdef _WIN32
+	mbedtls_ssl_conf_verify(ssl_config, verify_callback, NULL);
+	#endif
 	Config_val(obj) = ssl_config;
 	CAMLreturn(obj);
 }