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 if (crlPath != null) { 102 if (trustStoreAlgorithm.equalsIgnoreCase("PKIX")) { 103 Collection<? extends CRL> crlList = loadCRL(); 104 105 if (crlList != null) { 106 PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(ks, null); 107 pkixParams.setRevocationEnabled(true); 108 pkixParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(crlList))); 109 tmf.init(new CertPathTrustManagerParameters(pkixParams)); 110 } 111 } else { 112 LOG.warn("Revocation checking is only supported with 'trustStoreAlgorithm=\"PKIX\"'. Ignoring CRL: " + crlPath); 113 } 114 } else { 115 tmf.init(ks); 116 } 117 return Arrays.asList(tmf.getTrustManagers()); 118 } 119 120 private Collection<KeyManager> createKeyManagers() throws Exception { 121 KeyStore ks = createKeyManagerKeyStore(); 122 if( ks ==null ) { 123 return new ArrayList<KeyManager>(0); 124 } 125 126 KeyManagerFactory tmf = KeyManagerFactory.getInstance(keyStoreAlgorithm); 127 tmf.init(ks, keyStoreKeyPassword == null ? (keyStorePassword==null? null : keyStorePassword.toCharArray()) : keyStoreKeyPassword.toCharArray()); 128 return Arrays.asList(tmf.getKeyManagers()); 129 } 130 131 private KeyStore createTrustManagerKeyStore() throws Exception { 132 if( trustStore ==null ) { 133 return null; 134 } 135 136 KeyStore ks = KeyStore.getInstance(trustStoreType); 137 InputStream is=Utils.resourceFromString(trustStore).getInputStream(); 138 try { 139 ks.load(is, trustStorePassword==null? null : trustStorePassword.toCharArray()); 140 } finally { 141 is.close(); 142 } 143 return ks; 144 } 145 146 private KeyStore createKeyManagerKeyStore() throws Exception { 147 if( keyStore ==null ) { 148 return null; 149 } 150 151 KeyStore ks = KeyStore.getInstance(keyStoreType); 152 InputStream is=Utils.resourceFromString(keyStore).getInputStream(); 153 try { 154 ks.load(is, keyStorePassword==null? null : keyStorePassword.toCharArray()); 155 } finally { 156 is.close(); 157 } 158 return ks; 159 } 160 161 public String getTrustStoreType() { 162 return trustStoreType; 163 } 164 165 public String getKeyStoreType() { 166 return keyStoreType; 167 } 168 169 public String getKeyStore() { 170 return keyStore; 171 } 172 173 public void setKeyStore(String keyStore) throws MalformedURLException { 174 this.keyStore = keyStore; 175 } 176 177 public String getTrustStore() { 178 return trustStore; 179 } 180 181 public void setTrustStore(String trustStore) throws MalformedURLException { 182 this.trustStore = trustStore; 183 } 184 185 public String getKeyStoreAlgorithm() { 186 return keyStoreAlgorithm; 187 } 188 189 public void setKeyStoreAlgorithm(String keyAlgorithm) { 190 this.keyStoreAlgorithm = keyAlgorithm; 191 } 192 193 public String getTrustStoreAlgorithm() { 194 return trustStoreAlgorithm; 195 } 196 197 public void setTrustStoreAlgorithm(String trustAlgorithm) { 198 this.trustStoreAlgorithm = trustAlgorithm; 199 } 200 201 public String getKeyStoreKeyPassword() { 202 return keyStoreKeyPassword; 203 } 204 205 public void setKeyStoreKeyPassword(String keyPassword) { 206 this.keyStoreKeyPassword = keyPassword; 207 } 208 209 public String getKeyStorePassword() { 210 return keyStorePassword; 211 } 212 213 public void setKeyStorePassword(String keyPassword) { 214 this.keyStorePassword = keyPassword; 215 } 216 217 public String getTrustStorePassword() { 218 return trustStorePassword; 219 } 220 221 public void setTrustStorePassword(String trustPassword) { 222 this.trustStorePassword = trustPassword; 223 } 224 225 public void setKeyStoreType(String keyType) { 226 this.keyStoreType = keyType; 227 } 228 229 public void setTrustStoreType(String trustType) { 230 this.trustStoreType = trustType; 231 } 232 233 public String getSecureRandomAlgorithm() { 234 return secureRandomAlgorithm; 235 } 236 237 public void setSecureRandomAlgorithm(String secureRandomAlgorithm) { 238 this.secureRandomAlgorithm = secureRandomAlgorithm; 239 } 240 241 public String getCrlPath() { 242 return crlPath; 243 } 244 245 public void setCrlPath(String crlPath) { 246 this.crlPath = crlPath; 247 } 248 249 private Collection<? extends CRL> loadCRL() throws Exception { 250 if (crlPath == null) { 251 return null; 252 } 253 Resource resource = Utils.resourceFromString(crlPath); 254 InputStream is = resource.getInputStream(); 255 try { 256 return CertificateFactory.getInstance("X.509").generateCRLs(is); 257 } finally { 258 is.close(); 259 } 260 } 261 262}