@@ -48,6 +48,13 @@ internal override IMonoSslStream CreateSslStreamInternal (
48
48
return new UnityTlsStream ( innerStream , leaveInnerStreamOpen , sslStream , settings , this ) ;
49
49
}
50
50
51
+ static UnityTls . unitytls_x509verify_result x509verify_callback ( void * userData , UnityTls . unitytls_x509_ref cert , UnityTls . unitytls_x509verify_result result , UnityTls . unitytls_errorstate * errorState )
52
+ {
53
+ if ( userData != null )
54
+ UnityTls . NativeInterface . unitytls_x509list_append ( ( UnityTls . unitytls_x509list * ) userData , cert , errorState ) ;
55
+ return result ;
56
+ }
57
+
51
58
internal override bool ValidateCertificate (
52
59
ICertificateValidator2 validator , string targetHost , bool serverMode ,
53
60
X509CertificateCollection certificates , bool wantsChain , ref X509Chain chain ,
@@ -62,9 +69,6 @@ internal override bool ValidateCertificate (
62
69
errors |= MonoSslPolicyErrors . RemoteCertificateNotAvailable ;
63
70
return false ;
64
71
}
65
-
66
- if ( wantsChain )
67
- chain = MNS . SystemCertificateValidator . CreateX509Chain ( certificates ) ;
68
72
}
69
73
else
70
74
{
@@ -85,6 +89,7 @@ internal override bool ValidateCertificate (
85
89
// convert cert to native or extract from unityTlsChainImpl.
86
90
var result = UnityTls . unitytls_x509verify_result . UNITYTLS_X509VERIFY_NOT_DONE ;
87
91
UnityTls . unitytls_x509list * certificatesNative = null ;
92
+ UnityTls . unitytls_x509list * finalCertificateChainNative = UnityTls . NativeInterface . unitytls_x509list_create ( & errorState ) ;
88
93
try
89
94
{
90
95
// Things the validator provides that we might want to make use of here:
@@ -114,29 +119,42 @@ internal override bool ValidateCertificate (
114
119
var trustCAnativeRef = UnityTls . NativeInterface . unitytls_x509list_get_ref ( trustCAnative , & errorState ) ;
115
120
116
121
fixed ( byte * targetHostUtf8Ptr = targetHostUtf8 ) {
117
- result = UnityTls . NativeInterface . unitytls_x509verify_explicit_ca ( certificatesNativeRef , trustCAnativeRef , targetHostUtf8Ptr , ( size_t ) targetHostUtf8 . Length , null , null , & errorState ) ;
122
+ result = UnityTls . NativeInterface . unitytls_x509verify_explicit_ca (
123
+ certificatesNativeRef , trustCAnativeRef , targetHostUtf8Ptr , ( size_t ) targetHostUtf8 . Length , x509verify_callback , finalCertificateChainNative , & errorState ) ;
118
124
}
119
125
}
120
126
finally {
121
127
UnityTls . NativeInterface . unitytls_x509list_free ( trustCAnative ) ;
122
128
}
123
129
} else {
124
130
fixed ( byte * targetHostUtf8Ptr = targetHostUtf8 ) {
125
- result = UnityTls . NativeInterface . unitytls_x509verify_default_ca ( certificatesNativeRef , targetHostUtf8Ptr , ( size_t ) targetHostUtf8 . Length , null , null , & errorState ) ;
131
+ result = UnityTls . NativeInterface . unitytls_x509verify_default_ca (
132
+ certificatesNativeRef , targetHostUtf8Ptr , ( size_t ) targetHostUtf8 . Length , x509verify_callback , finalCertificateChainNative , & errorState ) ;
126
133
}
127
134
}
128
135
}
136
+ catch {
137
+ UnityTls . NativeInterface . unitytls_x509list_free ( finalCertificateChainNative ) ;
138
+ throw ;
139
+ }
129
140
finally {
130
141
UnityTls . NativeInterface . unitytls_x509list_free ( certificatesNative ) ;
131
142
}
132
143
144
+ chain ? . Dispose ( ) ;
145
+ var chainImpl = new X509ChainImplUnityTls (
146
+ UnityTls . NativeInterface . unitytls_x509list_get_ref ( finalCertificateChainNative , & errorState ) ,
147
+ reverseOrder : true // the verify callback starts with the root and ends with the leaf. That's the opposite of chain ordering.
148
+ ) ;
149
+ chain = new X509Chain ( chainImpl ) ;
150
+
133
151
errors = UnityTlsConversions . VerifyResultToPolicyErrror ( result ) ;
134
152
// There should be a status per certificate, but once again we're following closely the BTLS implementation
135
153
// https://github.com/mono/mono/blob/1553889bc54f87060158febca7e6b8b9910975f8/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs#L180
136
154
// which also provides only a single status for the entire chain.
137
155
// It is notoriously tricky to implement in OpenSSL to get a status for all invididual certificates without finishing the handshake in the process.
138
156
// This is partially the reason why unitytls_x509verify_X doesn't expose it (TODO!) and likely the reason Mono's BTLS impl ignores this.
139
- unityTlsChainImpl ? . AddStatus ( UnityTlsConversions . VerifyResultToChainStatus ( result ) ) ;
157
+ chainImpl . AddStatus ( UnityTlsConversions . VerifyResultToChainStatus ( result ) ) ;
140
158
return result == UnityTls . unitytls_x509verify_result . UNITYTLS_X509VERIFY_SUCCESS &&
141
159
errorState . code == UnityTls . unitytls_error_code . UNITYTLS_SUCCESS ;
142
160
}
0 commit comments