001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.spring; 018 019import java.io.InputStream; 020import java.net.MalformedURLException; 021import java.security.KeyStore; 022import java.security.NoSuchAlgorithmException; 023import java.security.SecureRandom; 024import java.security.cert.*; 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collection; 028 029import javax.annotation.PostConstruct; 030import javax.net.ssl.*; 031 032import org.apache.activemq.broker.SslContext; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035import org.springframework.core.io.Resource; 036 037/** 038 * Extends the SslContext so that it's easier to configure from spring. 039 * 040 * @org.apache.xbean.XBean element="sslContext" 041 * 042 * 043 */ 044public class SpringSslContext extends SslContext { 045 046 private static final transient Logger LOG = LoggerFactory.getLogger(SpringSslContext.class); 047 048 private String keyStoreType="jks"; 049 private String trustStoreType="jks"; 050 051 private String secureRandomAlgorithm="SHA1PRNG"; 052 private String keyStoreAlgorithm=KeyManagerFactory.getDefaultAlgorithm(); 053 private String trustStoreAlgorithm=TrustManagerFactory.getDefaultAlgorithm(); 054 055 private String keyStore; 056 private String trustStore; 057 058 private String keyStoreKeyPassword; 059 private String keyStorePassword; 060 private String trustStorePassword; 061 062 private String crlPath; 063 064 /** 065 * JSR-250 callback wrapper; converts checked exceptions to runtime exceptions 066 * 067 * delegates to afterPropertiesSet, done to prevent backwards incompatible signature change. 068 */ 069 @PostConstruct 070 private void postConstruct() { 071 try { 072 afterPropertiesSet(); 073 } catch (Exception ex) { 074 throw new RuntimeException(ex); 075 } 076 } 077 078 /** 079 * 080 * @throws Exception 081 * @org.apache.xbean.InitMethod 082 */ 083 public void afterPropertiesSet() throws Exception { 084 keyManagers.addAll(createKeyManagers()); 085 trustManagers.addAll(createTrustManagers()); 086 if( secureRandom == null ) { 087 secureRandom = createSecureRandom(); 088 } 089 } 090 091 private SecureRandom createSecureRandom() throws NoSuchAlgorithmException { 092 return SecureRandom.getInstance(secureRandomAlgorithm); 093 } 094 095 private Collection<TrustManager> createTrustManagers() throws Exception { 096 KeyStore ks = createTrustManagerKeyStore(); 097 if( ks ==null ) { 098 return new ArrayList<TrustManager>(0); 099 } 100 TrustManagerFactory tmf = TrustManagerFactory.getInstance(trustStoreAlgorithm); 101 boolean initialized = false; 102 if (crlPath != null) { 103 if (trustStoreAlgorithm.equalsIgnoreCase("PKIX")) { 104 Collection<? extends CRL> crlList = loadCRL(); 105 106 if (crlList != null) { 107 PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(ks, null); 108 pkixParams.setRevocationEnabled(true); 109 pkixParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(crlList))); 110 tmf.init(new CertPathTrustManagerParameters(pkixParams)); 111 initialized = true; 112 } 113 114 } else { 115 LOG.warn("Revocation checking is only supported with 'trustStoreAlgorithm=\"PKIX\"'. Ignoring CRL: " + crlPath); 116 } 117 } 118 119 if (!initialized) { 120 tmf.init(ks); 121 } 122 123 return Arrays.asList(tmf.getTrustManagers()); 124 } 125 126 private Collection<KeyManager> createKeyManagers() throws Exception { 127 KeyStore ks = createKeyManagerKeyStore(); 128 if( ks ==null ) { 129 return new ArrayList<KeyManager>(0); 130 } 131 132 KeyManagerFactory tmf = KeyManagerFactory.getInstance(keyStoreAlgorithm); 133 tmf.init(ks, keyStoreKeyPassword == null ? (keyStorePassword==null? null : keyStorePassword.toCharArray()) : keyStoreKeyPassword.toCharArray()); 134 return Arrays.asList(tmf.getKeyManagers()); 135 } 136 137 private KeyStore createTrustManagerKeyStore() throws Exception { 138 if( trustStore ==null ) { 139 return null; 140 } 141 142 KeyStore ks = KeyStore.getInstance(trustStoreType); 143 InputStream is=Utils.resourceFromString(trustStore).getInputStream(); 144 try { 145 ks.load(is, trustStorePassword==null? null : trustStorePassword.toCharArray()); 146 } finally { 147 is.close(); 148 } 149 return ks; 150 } 151 152 private KeyStore createKeyManagerKeyStore() throws Exception { 153 if( keyStore ==null ) { 154 return null; 155 } 156 157 KeyStore ks = KeyStore.getInstance(keyStoreType); 158 InputStream is=Utils.resourceFromString(keyStore).getInputStream(); 159 try { 160 ks.load(is, keyStorePassword==null? null : keyStorePassword.toCharArray()); 161 } finally { 162 is.close(); 163 } 164 return ks; 165 } 166 167 public String getTrustStoreType() { 168 return trustStoreType; 169 } 170 171 public String getKeyStoreType() { 172 return keyStoreType; 173 } 174 175 public String getKeyStore() { 176 return keyStore; 177 } 178 179 public void setKeyStore(String keyStore) throws MalformedURLException { 180 this.keyStore = keyStore; 181 } 182 183 public String getTrustStore() { 184 return trustStore; 185 } 186 187 public void setTrustStore(String trustStore) throws MalformedURLException { 188 this.trustStore = trustStore; 189 } 190 191 public String getKeyStoreAlgorithm() { 192 return keyStoreAlgorithm; 193 } 194 195 public void setKeyStoreAlgorithm(String keyAlgorithm) { 196 this.keyStoreAlgorithm = keyAlgorithm; 197 } 198 199 public String getTrustStoreAlgorithm() { 200 return trustStoreAlgorithm; 201 } 202 203 public void setTrustStoreAlgorithm(String trustAlgorithm) { 204 this.trustStoreAlgorithm = trustAlgorithm; 205 } 206 207 public String getKeyStoreKeyPassword() { 208 return keyStoreKeyPassword; 209 } 210 211 public void setKeyStoreKeyPassword(String keyPassword) { 212 this.keyStoreKeyPassword = keyPassword; 213 } 214 215 public String getKeyStorePassword() { 216 return keyStorePassword; 217 } 218 219 public void setKeyStorePassword(String keyPassword) { 220 this.keyStorePassword = keyPassword; 221 } 222 223 public String getTrustStorePassword() { 224 return trustStorePassword; 225 } 226 227 public void setTrustStorePassword(String trustPassword) { 228 this.trustStorePassword = trustPassword; 229 } 230 231 public void setKeyStoreType(String keyType) { 232 this.keyStoreType = keyType; 233 } 234 235 public void setTrustStoreType(String trustType) { 236 this.trustStoreType = trustType; 237 } 238 239 public String getSecureRandomAlgorithm() { 240 return secureRandomAlgorithm; 241 } 242 243 public void setSecureRandomAlgorithm(String secureRandomAlgorithm) { 244 this.secureRandomAlgorithm = secureRandomAlgorithm; 245 } 246 247 public String getCrlPath() { 248 return crlPath; 249 } 250 251 public void setCrlPath(String crlPath) { 252 this.crlPath = crlPath; 253 } 254 255 private Collection<? extends CRL> loadCRL() throws Exception { 256 if (crlPath == null) { 257 return null; 258 } 259 Resource resource = Utils.resourceFromString(crlPath); 260 InputStream is = resource.getInputStream(); 261 try { 262 return CertificateFactory.getInstance("X.509").generateCRLs(is); 263 } finally { 264 is.close(); 265 } 266 } 267 268}