View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.wss4j.common.crypto;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.nio.file.Files;
25  import java.nio.file.Paths;
26  import java.security.KeyStore;
27  import java.security.cert.CertStore;
28  import java.security.cert.CertificateFactory;
29  import java.security.cert.CollectionCertStoreParameters;
30  import java.security.cert.X509CRL;
31  import java.util.Collections;
32  import java.util.Properties;
33  
34  import org.apache.wss4j.common.ext.WSSecurityException;
35  
36  /**
37   * A Crypto implementation based on two Java KeyStore objects, one being the keystore, and one
38   * being the truststore. This Crypto implementation extends the default Merlin implementation by
39   * allowing loading of keystores using a null InputStream - for example on a smart-card device.
40   */
41  public class MerlinDevice extends Merlin {
42  
43      private static final org.slf4j.Logger LOG =
44          org.slf4j.LoggerFactory.getLogger(MerlinDevice.class);
45  
46      public MerlinDevice() {
47          super();
48      }
49  
50      public MerlinDevice(Properties properties, ClassLoader loader, PasswordEncryptor passwordEncryptor)
51          throws WSSecurityException, IOException {
52          super(properties, loader, passwordEncryptor);
53      }
54  
55      @Override
56      public void loadProperties(Properties properties, ClassLoader loader, PasswordEncryptor passwordEncryptor)
57          throws WSSecurityException, IOException {
58          if (properties == null) {
59              return;
60          }
61          this.properties = properties;
62          this.passwordEncryptor = passwordEncryptor;
63  
64          String prefix = PREFIX;
65          for (Object key : properties.keySet()) {
66              if (key instanceof String) {
67                  String propKey = (String)key;
68                  if (propKey.startsWith(PREFIX)) {
69                      break;
70                  } else if (propKey.startsWith(OLD_PREFIX)) {
71                      prefix = OLD_PREFIX;
72                      break;
73                  }
74              }
75          }
76  
77          //
78          // Load the provider(s)
79          //
80          String provider = properties.getProperty(prefix + CRYPTO_KEYSTORE_PROVIDER);
81          if (provider != null) {
82              provider = provider.trim();
83          }
84          String certProvider = properties.getProperty(prefix + CRYPTO_CERT_PROVIDER);
85          if (certProvider != null) {
86              setCryptoProvider(certProvider);
87          }
88          //
89          // Load the KeyStore
90          //
91          String alias = properties.getProperty(prefix + KEYSTORE_ALIAS);
92          if (alias != null) {
93              alias = alias.trim();
94              setDefaultX509Identifier(alias);
95          }
96          String keyStoreLocation = properties.getProperty(prefix + KEYSTORE_FILE);
97          if (keyStoreLocation == null) {
98              keyStoreLocation = properties.getProperty(prefix + OLD_KEYSTORE_FILE);
99          }
100         String keyStorePassword = properties.getProperty(prefix + KEYSTORE_PASSWORD);
101         if (keyStorePassword != null) {
102             keyStorePassword = keyStorePassword.trim();
103             keyStorePassword = decryptPassword(keyStorePassword, passwordEncryptor);
104         }
105         String keyStoreType = properties.getProperty(prefix + KEYSTORE_TYPE, KeyStore.getDefaultType());
106         if (keyStoreType != null) {
107             keyStoreType = keyStoreType.trim();
108         }
109         if (keyStoreLocation != null) {
110             keyStoreLocation = keyStoreLocation.trim();
111 
112             try (InputStream is = loadInputStream(loader, keyStoreLocation)) {
113                 keystore = load(is, keyStorePassword, provider, keyStoreType);
114                 LOG.debug(
115                     "The KeyStore {} of type {} has been loaded", keyStoreLocation, keyStoreType
116                 );
117             }
118         } else {
119             keystore = load(null, keyStorePassword, provider, keyStoreType);
120         }
121 
122         //
123         // Load the TrustStore
124         //
125         String trustStorePassword = properties.getProperty(prefix + TRUSTSTORE_PASSWORD);
126         if (trustStorePassword != null) {
127             trustStorePassword = trustStorePassword.trim();
128             trustStorePassword = decryptPassword(trustStorePassword, passwordEncryptor);
129         }
130         String trustStoreType = properties.getProperty(prefix + TRUSTSTORE_TYPE, KeyStore.getDefaultType());
131         if (trustStoreType != null) {
132             trustStoreType = trustStoreType.trim();
133         }
134         String loadCacerts = properties.getProperty(prefix + LOAD_CA_CERTS, "false");
135         if (loadCacerts != null) {
136             loadCacerts = loadCacerts.trim();
137         }
138         String trustStoreLocation = properties.getProperty(prefix + TRUSTSTORE_FILE);
139         if (trustStoreLocation != null) {
140             trustStoreLocation = trustStoreLocation.trim();
141 
142             try (InputStream is = loadInputStream(loader, trustStoreLocation)) {
143                 truststore = load(is, trustStorePassword, provider, trustStoreType);
144                 LOG.debug(
145                     "The TrustStore {} of type {} has been loaded", trustStoreLocation, trustStoreType
146                 );
147                 loadCACerts = false;
148             }
149         } else if (Boolean.valueOf(loadCacerts)) {
150             String cacertsPath = (System.getProperty("java.home") + "/lib/security/cacerts").trim();
151             try (InputStream is = Files.newInputStream(Paths.get(cacertsPath))) {
152                 String cacertsPasswd = properties.getProperty(prefix + TRUSTSTORE_PASSWORD, "changeit");
153                 if (cacertsPasswd != null) {
154                     cacertsPasswd = cacertsPasswd.trim();
155                     cacertsPasswd = decryptPassword(cacertsPasswd, passwordEncryptor);
156                 }
157                 truststore = load(is, cacertsPasswd, null, KeyStore.getDefaultType());
158                 LOG.debug("CA certs have been loaded");
159                 loadCACerts = true;
160             }
161         } else {
162             truststore = load(null, trustStorePassword, provider, trustStoreType);
163         }
164         //
165         // Load the CRL file
166         //
167         String crlLocation = properties.getProperty(prefix + X509_CRL_FILE);
168         if (crlLocation != null) {
169             crlLocation = crlLocation.trim();
170 
171             try (InputStream is = loadInputStream(loader, crlLocation)) {
172                 CertificateFactory cf = getCertificateFactory();
173                 X509CRL crl = (X509CRL)cf.generateCRL(is);
174 
175                 if (provider == null || provider.length() == 0) {
176                     crlCertStore =
177                         CertStore.getInstance(
178                             "Collection",
179                             new CollectionCertStoreParameters(Collections.singletonList(crl))
180                         );
181                 } else {
182                     crlCertStore =
183                         CertStore.getInstance(
184                             "Collection",
185                             new CollectionCertStoreParameters(Collections.singletonList(crl)),
186                             provider
187                         );
188                 }
189                 LOG.debug("The CRL {} has been loaded", crlLocation);
190             } catch (Exception e) {
191                 LOG.debug(e.getMessage(), e);
192                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "failedCredentialLoad");
193             }
194         }
195     }
196 
197 }