1
1
/*
2
- * Copyright (c) 2019, 2019 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2019, 2021 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
24
24
*/
25
25
package com .oracle .svm .core .jdk ;
26
26
27
+ import java .io .File ;
27
28
import java .security .KeyStore ;
28
29
import java .security .cert .X509Certificate ;
29
30
import java .util .Set ;
32
33
import org .graalvm .nativeimage .hosted .Feature ;
33
34
import org .graalvm .nativeimage .hosted .RuntimeClassInitialization ;
34
35
36
+ import com .oracle .svm .core .annotate .Alias ;
35
37
import com .oracle .svm .core .annotate .AutomaticFeature ;
36
38
import com .oracle .svm .core .annotate .Delete ;
39
+ import com .oracle .svm .core .annotate .RecomputeFieldValue ;
37
40
import com .oracle .svm .core .annotate .Substitute ;
38
41
import com .oracle .svm .core .annotate .TargetClass ;
39
42
import com .oracle .svm .core .util .VMError ;
40
43
import com .oracle .svm .util .ReflectionUtil ;
41
44
45
+ // Checkstyle: stop
46
+ import sun .security .ssl .SSLLogger ;
47
+ // Checkstyle: resume
48
+
42
49
/**
43
- * Native image uses the principle of "immutable security" for the root certificates: They are fixed
44
- * at image build time based on the the certificate configuration used for the image generator. This
45
- * avoids shipping a `cacerts` file or requiring to set a system property to set up root
46
- * certificates that are provided by the OS where the image runs.
50
+ * Root certificates in native image are fixed/embedded into the image, at image build time, based
51
+ * on the certificate configuration used for the image generator. This avoids the need to ship a
52
+ * `cacerts` file alongside the image executable.
47
53
*
48
- * As a consequence, system properties such as `javax.net.ssl.trustStore` do not have an effect at
49
- * run time. They need to be provided at image build time.
54
+ * <p>
55
+ * Users are also allowed to override the embedded root certificate at run time by setting the
56
+ * `javax.net.ssl.trustStore*` system properties. For more details about both buildtime and runtime
57
+ * certificate management, please refer to <a href=
58
+ * "https://www.graalvm.org/reference-manual/native-image/CertificateManagement/">CertificateManagement.md</a>.
50
59
*
51
- * The implementation "freezes" the return values of TrustStoreManager managers by invoking them at
52
- * image build time (using reflection because the class is non-public) and returning the frozen
53
- * values using a substitution.
60
+ * <p>
61
+ * For embedding the build time root certificates, the implementation "freezes" the return values of
62
+ * TrustStoreManager managers by invoking them at image build time (using reflection because the
63
+ * class is non-public) and returning the frozen values using a substitution.
54
64
*/
55
65
@ AutomaticFeature
56
66
final class TrustStoreManagerFeature implements Feature {
@@ -73,48 +83,164 @@ public void afterRegistration(AfterRegistrationAccess access) {
73
83
/*
74
84
* The class initializer of UntrustedCertificates loads the file
75
85
* lib/security/blacklisted.certs, so this class must be initialized at image build time.
76
- * This is the default anyway for code JDK classes, but since this this class is relevant
77
- * for security we spell it out explicitly.
86
+ * This is the default anyway for code JDK classes, but since this class is relevant for
87
+ * security we spell it out explicitly.
88
+ *
89
+ * Note when a runtime certificate file is specified, we still honor/use the build time
90
+ * lib/security/blacklisted.certs file
78
91
*/
79
92
RuntimeClassInitialization .initializeAtBuildTime (sun .security .util .UntrustedCertificates .class );
80
- RuntimeClassInitialization .initializeAtBuildTime (org .jcp .xml .dsig .internal .dom .XMLDSigRI .class );
81
93
}
82
94
}
83
95
84
96
final class TrustStoreManagerSupport {
85
- final Set <X509Certificate > trustedCerts ;
86
- final KeyStore trustedKeyStore ;
87
97
88
- TrustStoreManagerSupport (Set <X509Certificate > trustedCerts , KeyStore trustedKeyStore ) {
89
- this .trustedCerts = trustedCerts ;
90
- this .trustedKeyStore = trustedKeyStore ;
98
+ final Set <X509Certificate > buildtimeTrustedCerts ;
99
+ final KeyStore buildtimeTrustedKeyStore ;
100
+
101
+ TrustStoreManagerSupport (Set <X509Certificate > buildtimeTrustedCerts , KeyStore buildtimeTrustedKeyStore ) {
102
+ this .buildtimeTrustedCerts = buildtimeTrustedCerts ;
103
+ this .buildtimeTrustedKeyStore = buildtimeTrustedKeyStore ;
91
104
}
105
+
106
+ /**
107
+ * This method creates a TrustStoreDescriptor if any of the "javax.net.ssl.trustStore*"
108
+ * properties are set, or otherwise returns null.
109
+ */
110
+ static Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor getRuntimeTrustStoreDescriptor () {
111
+ /* First read current system properties. */
112
+ String storePropName = System .getProperty ("javax.net.ssl.trustStore" );
113
+ String storePropType = System .getProperty ("javax.net.ssl.trustStoreType" );
114
+ String storePropProvider = System .getProperty ("javax.net.ssl.trustStoreProvider" );
115
+ String storePropPassword = System .getProperty ("javax.net.ssl.trustStorePassword" );
116
+
117
+ /*
118
+ * Check if any of the properties are set. If not, then should not attempt to create a trust
119
+ * store descriptor.
120
+ */
121
+ if (storePropName == null && storePropType == null && storePropProvider == null && storePropPassword == null ) {
122
+ return null ;
123
+ }
124
+
125
+ if (storePropName == null ) {
126
+ throw VMError .unsupportedFeature (
127
+ "System property javax.net.ssl.trustStore must be also set if any of javax.net.ssl.trustStore(Type|Provider|Password) are set." +
128
+ "See https://www.graalvm.org/reference-manual/native-image/CertificateManagement#runtime-options for more details about runtime certificate management." );
129
+ }
130
+
131
+ /* Setting remaining properties to defaults if unset. */
132
+ if (storePropType == null ) {
133
+ storePropType = KeyStore .getDefaultType ();
134
+ }
135
+ if (storePropProvider == null ) {
136
+ storePropProvider = "" ;
137
+ }
138
+ if (storePropPassword == null ) {
139
+ storePropPassword = "" ;
140
+ }
141
+
142
+ /* Creating TrustStoreDescriptor. */
143
+ Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor descriptor = createTrustStoreDescriptor (storePropName , storePropType , storePropProvider ,
144
+ storePropPassword );
145
+
146
+ /*
147
+ * Checking if TrustStoreDescriptor was able to find a valid trust store.
148
+ */
149
+ if (descriptor == null ) {
150
+ throw VMError .unsupportedFeature ("Inaccessible trust store: " + storePropName +
151
+ " See https://www.graalvm.org/reference-manual/native-image/CertificateManagement#runtime-options for more details about runtime certificate management." );
152
+ }
153
+
154
+ return descriptor ;
155
+ }
156
+
157
+ /**
158
+ * Creates a new TrustStoreDescriptor object.
159
+ *
160
+ * @return A new TrustStoreDescriptor or {@code null} if an appropriate descriptor for the
161
+ * provided parameters could not be found.
162
+ */
163
+ private static Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor createTrustStoreDescriptor (String storePropName , String storePropType , String storePropProvider ,
164
+ String storePropPassword ) {
165
+ /* This code is largely taken from the JDK. */
166
+ String temporaryName = "" ;
167
+ File temporaryFile = null ;
168
+ long temporaryTime = 0L ;
169
+ if (!"NONE" .equals (storePropName )) {
170
+ File f = new File (storePropName );
171
+ if (f .isFile () && f .canRead ()) {
172
+ temporaryName = storePropName ;
173
+ temporaryFile = f ;
174
+ temporaryTime = f .lastModified ();
175
+ } else {
176
+ // The file is inaccessible.
177
+ if (SSLLogger .isOn && SSLLogger .isOn ("trustmanager" )) {
178
+ SSLLogger .fine ("Inaccessible trust store: " + storePropName );
179
+ }
180
+
181
+ return null ;
182
+ }
183
+ } else {
184
+ temporaryName = storePropName ;
185
+ }
186
+
187
+ return new Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor (
188
+ temporaryName , storePropType , storePropProvider ,
189
+ storePropPassword , temporaryFile , temporaryTime );
190
+ }
191
+
92
192
}
93
193
94
194
@ TargetClass (className = TrustStoreManagerFeature .TRUST_STORE_MANAGER_CLASS_NAME )
95
195
final class Target_sun_security_ssl_TrustStoreManager {
196
+ /*
197
+ * This singleton object caches the last retrieved trusted KeyStore and set of trusted
198
+ * certificates.
199
+ */
200
+ @ Alias @ RecomputeFieldValue (kind = RecomputeFieldValue .Kind .NewInstance , declClassName = TrustStoreManagerFeature .TRUST_STORE_MANAGER_CLASS_NAME +
201
+ "$TrustAnchorManager" ) private static Target_sun_security_ssl_TrustStoreManager_TrustAnchorManager tam ;
96
202
97
203
@ Substitute
98
204
private static Set <X509Certificate > getTrustedCerts () throws Exception {
99
- return ImageSingletons .lookup (TrustStoreManagerSupport .class ).trustedCerts ;
205
+ Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor runtimeDescriptor = TrustStoreManagerSupport .getRuntimeTrustStoreDescriptor ();
206
+ if (runtimeDescriptor == null ) {
207
+ return ImageSingletons .lookup (TrustStoreManagerSupport .class ).buildtimeTrustedCerts ;
208
+ }
209
+ return tam .getTrustedCerts (runtimeDescriptor );
100
210
}
101
211
102
212
@ Substitute
103
213
private static KeyStore getTrustedKeyStore () throws Exception {
104
- return ImageSingletons .lookup (TrustStoreManagerSupport .class ).trustedKeyStore ;
214
+ Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor runtimeDescriptor = TrustStoreManagerSupport .getRuntimeTrustStoreDescriptor ();
215
+ if (runtimeDescriptor == null ) {
216
+ return ImageSingletons .lookup (TrustStoreManagerSupport .class ).buildtimeTrustedKeyStore ;
217
+ }
218
+ return tam .getKeyStore (runtimeDescriptor );
105
219
}
106
220
}
107
221
108
- /*
109
- * The internal classes to describe and load root certificates must not be reachable at run time.
110
- */
111
-
112
- @ Delete
113
222
@ TargetClass (className = TrustStoreManagerFeature .TRUST_STORE_MANAGER_CLASS_NAME , innerClass = "TrustStoreDescriptor" )
114
223
final class Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor {
224
+ @ Delete private static String defaultStorePath ;
225
+ @ Delete private static String defaultStore ;
226
+ @ Delete private static String jsseDefaultStore ;
227
+
228
+ @ Delete
229
+ static native Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor createInstance ();
230
+
231
+ @ Alias
232
+ @ SuppressWarnings ("unused" )
233
+ Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor (String storeName , String storeType , String storeProvider , String storePassword , File storeFile , long lastModified ) {
234
+ throw VMError .shouldNotReachHere ("This is an alias to the original constructor in the target class, so this code is unreachable" );
235
+ }
115
236
}
116
237
117
- @ Delete
118
238
@ TargetClass (className = TrustStoreManagerFeature .TRUST_STORE_MANAGER_CLASS_NAME , innerClass = "TrustAnchorManager" )
119
239
final class Target_sun_security_ssl_TrustStoreManager_TrustAnchorManager {
240
+
241
+ @ Alias
242
+ native Set <X509Certificate > getTrustedCerts (Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor descriptor ) throws Exception ;
243
+
244
+ @ Alias
245
+ native KeyStore getKeyStore (Target_sun_security_ssl_TrustStoreManager_TrustStoreDescriptor descriptor ) throws Exception ;
120
246
}
0 commit comments