diff --git a/src/hx/libs/ssl/Build.xml b/src/hx/libs/ssl/Build.xml index 2240f564a..af1f3cbc9 100644 --- a/src/hx/libs/ssl/Build.xml +++ b/src/hx/libs/ssl/Build.xml @@ -23,8 +23,13 @@ - - +
+ + + + + +
diff --git a/src/hx/libs/ssl/SSL.cpp b/src/hx/libs/ssl/SSL.cpp index 36d3897ed..35f17dff6 100644 --- a/src/hx/libs/ssl/SSL.cpp +++ b/src/hx/libs/ssl/SSL.cpp @@ -14,9 +14,12 @@ typedef int SOCKET; #include #include -#if defined(NEKO_MAC) && !defined(IPHONE) && !defined(APPLETV) +#if defined(NEKO_MAC) || defined(IPHONE) || defined(APPLETV) #include #endif +#if defined(IPHONE) || defined(APPLETV) +#include +#endif typedef size_t socket_int; @@ -361,12 +364,12 @@ int _hx_ssl_recv( Dynamic hssl, Array buf, int p, int l ) { HANDLE_EINTR(recv_again); hx::Throw(HX_CSTRING("ssl network error")); } - if( dlen < 0 ) { + if( dlen < 0 ) { if( dlen == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) { mbedtls_ssl_close_notify( ssl->s ); return 0; } - hx::Throw( HX_CSTRING("ssl_recv") ); + hx::Throw( HX_CSTRING("ssl_recv") ); } return dlen; } @@ -463,14 +466,57 @@ void _hx_ssl_conf_close( Dynamic hconf ) { conf->destroy(); } +#if defined(IPHONE) || defined(APPLETV) +static int apple_verify_cb(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { + // use mbedtls validate the chain structure and we validate with the iOS system trust store to replace the missing CA bundle + if (depth != 0) { + *flags = 0; + return 0; + } + + CFDataRef derData = CFDataCreate(NULL, crt->raw.p, crt->raw.len); + if (!derData) return 0; + + SecCertificateRef secCert = SecCertificateCreateWithData(NULL, derData); + CFRelease(derData); + if (!secCert) return 0; + + SecPolicyRef policy = SecPolicyCreateSSL(true, NULL); + CFArrayRef certs = CFArrayCreate(NULL, (const void **)&secCert, 1, &kCFTypeArrayCallBacks); + SecTrustRef trust = NULL; + SecTrustCreateWithCertificates(certs, policy, &trust); + CFRelease(certs); + CFRelease(policy); + CFRelease(secCert); + + CFErrorRef err = NULL; + bool trusted = SecTrustEvaluateWithError(trust, &err); + CFRelease(trust); + if (err) CFRelease(err); + + if (trusted) *flags = 0; + return 0; +} +#endif + void _hx_ssl_conf_set_ca( Dynamic hconf, Dynamic hcert ) { sslconf *conf = val_conf(hconf); +#if defined(IPHONE) || defined(APPLETV) + // always attach Apple system verification callback + mbedtls_ssl_conf_verify(conf->c, apple_verify_cb, NULL); + + sslcert *cert = val_cert(hcert); + // make sure the ca chain is set even if null + mbedtls_ssl_conf_ca_chain(conf->c, cert ? cert->c : NULL, NULL); + +#else if( hconf.mPtr ){ sslcert *cert = val_cert(hcert); mbedtls_ssl_conf_ca_chain( conf->c, cert->c, NULL ); }else{ mbedtls_ssl_conf_ca_chain( conf->c, NULL, NULL ); } +#endif } void _hx_ssl_conf_set_verify( Dynamic hconf, int mode ) { @@ -583,6 +629,10 @@ Dynamic _hx_ssl_cert_load_defaults(){ CFRelease(keychain); if( chain != NULL ) return chain; +#elif defined(IPHONE) || defined(APPLETV) // SystemRootCertificates.keychain doesn't exist on iOS and tvOS so i use a cool workaround + sslcert *chain = new sslcert(); + chain->create(NULL); // creates a ssl cert with only the default ones that iOS or tvOS trust in the os + return chain; #endif return null(); }