1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */

17 package org.apache.tomcat.util.net;
18
19 import java.io.IOException;
20 import java.io.Serializable;
21 import java.security.KeyStore;
22 import java.util.HashSet;
23 import java.util.Set;
24
25 import javax.management.ObjectName;
26 import javax.net.ssl.X509KeyManager;
27
28 import org.apache.juli.logging.Log;
29 import org.apache.juli.logging.LogFactory;
30 import org.apache.tomcat.util.net.openssl.ciphers.Authentication;
31 import org.apache.tomcat.util.res.StringManager;
32
33 public class SSLHostConfigCertificate implements Serializable {
34
35     private static final long serialVersionUID = 1L;
36
37     private static final Log log = LogFactory.getLog(SSLHostConfigCertificate.class);
38     private static final StringManager sm = StringManager.getManager(SSLHostConfigCertificate.class);
39
40     public static final Type DEFAULT_TYPE = Type.UNDEFINED;
41
42     static final String DEFAULT_KEYSTORE_PROVIDER =
43             System.getProperty("javax.net.ssl.keyStoreProvider");
44     static final String DEFAULT_KEYSTORE_TYPE =
45             System.getProperty("javax.net.ssl.keyStoreType""JKS");
46
47     // Internal
48     private ObjectName oname;
49
50     // OpenSSL can handle multiple certs in a single config so the reference to
51     // the context is at the virtual host level. JSSE can't so the reference is
52     // held here on the certificate.
53     private transient SSLContext sslContext;
54
55     // Common
56     private final SSLHostConfig sslHostConfig;
57     private final Type type;
58     private String certificateKeyPassword = null;
59
60     // JSSE
61     private String certificateKeyAlias;
62     private String certificateKeystorePassword = "changeit";
63     private String certificateKeystoreFile = System.getProperty("user.home")+"/.keystore";
64     private String certificateKeystoreProvider = DEFAULT_KEYSTORE_PROVIDER;
65     private String certificateKeystoreType = DEFAULT_KEYSTORE_TYPE;
66     private transient KeyStore certificateKeystore = null;
67     private transient X509KeyManager certificateKeyManager = null;
68
69     // OpenSSL
70     private String certificateChainFile;
71     private String certificateFile;
72     private String certificateKeyFile;
73
74     // Certificate store type
75     private StoreType storeType = null;
76
77     public SSLHostConfigCertificate() {
78         this(null, Type.UNDEFINED);
79     }
80
81     public SSLHostConfigCertificate(SSLHostConfig sslHostConfig, Type type) {
82         this.sslHostConfig = sslHostConfig;
83         this.type = type;
84     }
85
86
87     public SSLContext getSslContext() {
88         return sslContext;
89     }
90
91
92     public void setSslContext(SSLContext sslContext) {
93         this.sslContext = sslContext;
94     }
95
96
97     public SSLHostConfig getSSLHostConfig() {
98         return sslHostConfig;
99     }
100
101
102     // Internal
103
104     public ObjectName getObjectName() {
105         return oname;
106     }
107
108
109     public void setObjectName(ObjectName oname) {
110         this.oname = oname;
111     }
112
113
114     // Common
115
116     public Type getType() {
117         return type;
118     }
119
120
121     public String getCertificateKeyPassword() {
122         return certificateKeyPassword;
123     }
124
125
126     public void setCertificateKeyPassword(String certificateKeyPassword) {
127         this.certificateKeyPassword = certificateKeyPassword;
128     }
129
130
131     // JSSE
132
133     public void setCertificateKeyAlias(String certificateKeyAlias) {
134         sslHostConfig.setProperty(
135                 "Certificate.certificateKeyAlias", SSLHostConfig.Type.JSSE);
136         this.certificateKeyAlias = certificateKeyAlias;
137     }
138
139
140     public String getCertificateKeyAlias() {
141         return certificateKeyAlias;
142     }
143
144
145     public void setCertificateKeystoreFile(String certificateKeystoreFile) {
146         sslHostConfig.setProperty(
147                 "Certificate.certificateKeystoreFile", SSLHostConfig.Type.JSSE);
148         setStoreType("Certificate.certificateKeystoreFile", StoreType.KEYSTORE);
149         this.certificateKeystoreFile = certificateKeystoreFile;
150     }
151
152
153     public String getCertificateKeystoreFile() {
154         return certificateKeystoreFile;
155     }
156
157
158     public void setCertificateKeystorePassword(String certificateKeystorePassword) {
159         sslHostConfig.setProperty(
160                 "Certificate.certificateKeystorePassword", SSLHostConfig.Type.JSSE);
161         setStoreType("Certificate.certificateKeystorePassword", StoreType.KEYSTORE);
162         this.certificateKeystorePassword = certificateKeystorePassword;
163     }
164
165
166     public String getCertificateKeystorePassword() {
167         return certificateKeystorePassword;
168     }
169
170
171     public void setCertificateKeystoreProvider(String certificateKeystoreProvider) {
172         sslHostConfig.setProperty(
173                 "Certificate.certificateKeystoreProvider", SSLHostConfig.Type.JSSE);
174         setStoreType("Certificate.certificateKeystoreProvider", StoreType.KEYSTORE);
175         this.certificateKeystoreProvider = certificateKeystoreProvider;
176     }
177
178
179     public String getCertificateKeystoreProvider() {
180         return certificateKeystoreProvider;
181     }
182
183
184     public void setCertificateKeystoreType(String certificateKeystoreType) {
185         sslHostConfig.setProperty(
186                 "Certificate.certificateKeystoreType", SSLHostConfig.Type.JSSE);
187         setStoreType("Certificate.certificateKeystoreType", StoreType.KEYSTORE);
188         this.certificateKeystoreType = certificateKeystoreType;
189     }
190
191
192     public String getCertificateKeystoreType() {
193         return certificateKeystoreType;
194     }
195
196
197     public void setCertificateKeystore(KeyStore certificateKeystore) {
198         this.certificateKeystore = certificateKeystore;
199     }
200
201
202     public KeyStore getCertificateKeystore() throws IOException {
203         KeyStore result = certificateKeystore;
204
205         if (result == null && storeType == StoreType.KEYSTORE) {
206             result = SSLUtilBase.getStore(getCertificateKeystoreType(),
207                     getCertificateKeystoreProvider(), getCertificateKeystoreFile(),
208                     getCertificateKeystorePassword());
209         }
210
211         return result;
212     }
213
214
215     public void setCertificateKeyManager(X509KeyManager certificateKeyManager) {
216         this.certificateKeyManager = certificateKeyManager;
217     }
218
219
220     public X509KeyManager getCertificateKeyManager() {
221         return certificateKeyManager;
222     }
223
224
225     // OpenSSL
226
227     public void setCertificateChainFile(String certificateChainFile) {
228         setStoreType("Certificate.certificateChainFile", StoreType.PEM);
229         this.certificateChainFile = certificateChainFile;
230     }
231
232
233     public String getCertificateChainFile() {
234         return certificateChainFile;
235     }
236
237
238     public void setCertificateFile(String certificateFile) {
239         setStoreType("Certificate.certificateFile", StoreType.PEM);
240         this.certificateFile = certificateFile;
241     }
242
243
244     public String getCertificateFile() {
245         return certificateFile;
246     }
247
248
249     public void setCertificateKeyFile(String certificateKeyFile) {
250         setStoreType("Certificate.certificateKeyFile", StoreType.PEM);
251         this.certificateKeyFile = certificateKeyFile;
252     }
253
254
255     public String getCertificateKeyFile() {
256         return certificateKeyFile;
257     }
258
259
260     private void setStoreType(String name, StoreType type) {
261         if (storeType == null) {
262             storeType = type;
263         } else if (storeType != type) {
264             log.warn(sm.getString("sslHostConfigCertificate.mismatch",
265                     name, sslHostConfig.getHostName(), type, this.storeType));
266         }
267     }
268
269     // Nested types
270
271     public enum Type {
272
273         UNDEFINED,
274         RSA(Authentication.RSA),
275         DSA(Authentication.DSS),
276         EC(Authentication.ECDH, Authentication.ECDSA);
277
278         private final Set<Authentication> compatibleAuthentications;
279
280         private Type(Authentication... authentications) {
281             compatibleAuthentications = new HashSet<>();
282             if (authentications != null) {
283                 for (Authentication authentication : authentications) {
284                     compatibleAuthentications.add(authentication);
285                 }
286             }
287         }
288
289         public boolean isCompatibleWith(Authentication au) {
290             return compatibleAuthentications.contains(au);
291         }
292     }
293
294     enum StoreType {
295         KEYSTORE,
296         PEM
297     }
298 }
299