2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.security
.activemq
;
18 import java
.io
.InputStream
;
19 import java
.security
.KeyStore
;
20 import java
.security
.SecureRandom
;
22 import javax
.jms
.Connection
;
23 import javax
.jms
.ConnectionFactory
;
24 import javax
.jms
.JMSException
;
25 import javax
.net
.ssl
.KeyManagerFactory
;
26 import javax
.net
.ssl
.TrustManagerFactory
;
27 import javax
.swing
.UIManager
;
28 import javax
.swing
.UnsupportedLookAndFeelException
;
29 import javax
.swing
.plaf
.metal
.MetalLookAndFeel
;
31 import org
.apache
.activemq
.ActiveMQSslConnectionFactory
;
32 import org
.apache
.commons
.logging
.Log
;
33 import org
.apache
.commons
.logging
.LogFactory
;
34 import org
.argeo
.ArgeoException
;
35 import org
.springframework
.beans
.factory
.DisposableBean
;
36 import org
.springframework
.beans
.factory
.InitializingBean
;
37 import org
.springframework
.core
.io
.Resource
;
38 import org
.springframework
.jms
.connection
.CachingConnectionFactory
;
39 import org
.springframework
.jms
.connection
.UserCredentialsConnectionFactoryAdapter
;
41 /** An ActiveMQ connection factory managing secure connections. */
42 public class SecuredActiveMqConnectionFactory
implements ConnectionFactory
,
43 InitializingBean
, DisposableBean
{
45 public final static String AUTHMODE_UI
= "ui";
46 public final static String AUTHMODE_OS
= "os";
47 public final static String AUTHMODE_DEFAULT
= AUTHMODE_OS
;
48 // private final static String LOGIN_CONFIG_PROPERTY =
49 // "java.security.auth.login.config";
51 private final static Log log
= LogFactory
52 .getLog(SecuredActiveMqConnectionFactory
.class);
54 private String keyStorePassword
;
55 private Resource keyStore
;
56 private String keyStoreType
= "JKS";// "PKCS12"
57 private String brokerURL
;
59 private String authenticationMode
;
61 private CachingConnectionFactory cachingConnectionFactory
;
63 public Connection
createConnection() throws JMSException
{
64 return cachingConnectionFactory
.createConnection();
67 public Connection
createConnection(String userName
, String password
)
69 throw new UnsupportedOperationException();
72 public void afterPropertiesSet() throws Exception
{
73 ActiveMQSslConnectionFactory activeMQSslConnectionFactory
= new ActiveMQSslConnectionFactory();
74 prepareActiveMqSslConnectionFactory(activeMQSslConnectionFactory
);
75 activeMQSslConnectionFactory
.setBrokerURL(brokerURL
);
76 UserCredentialsConnectionFactoryAdapter uccfa
= new UserCredentialsConnectionFactoryAdapter();
77 uccfa
.setTargetConnectionFactory(activeMQSslConnectionFactory
);
78 cachingConnectionFactory
= new CachingConnectionFactory();
79 cachingConnectionFactory
.setTargetConnectionFactory(uccfa
);
80 cachingConnectionFactory
.setCacheConsumers(false);
82 initConnectionFactoryCredentials(uccfa
);
83 cachingConnectionFactory
.initConnection();
84 log
.info("Connected to " + brokerURL
);
85 uccfa
.setUsername(null);
86 uccfa
.setPassword(null);
90 protected void initConnectionFactoryCredentials(
91 final UserCredentialsConnectionFactoryAdapter uccfa
) {
92 if (authenticationMode
== null)
93 authenticationMode
= AUTHMODE_DEFAULT
;
95 if (AUTHMODE_OS
.equals(authenticationMode
)) {
97 // // Cache previous value of login conf location
98 // String oldLoginConfLocation = System
99 // .getProperty(LOGIN_CONFIG_PROPERTY);
101 // String osName = System.getProperty("os.name");
102 // final String auth;
103 // if (osName.startsWith("Windows"))
105 // else if (osName.startsWith("SunOS")
106 // || osName.startsWith("Solaris"))
112 // // see http://old.nabble.com/osgi-and-jaas-td23485885.html
113 // ClassLoader ccl = Thread.currentThread()
114 // .getContextClassLoader();
116 // Thread.currentThread().setContextClassLoader(
117 // getClass().getClassLoader());
118 // URL url = getClass().getResource(
119 // "/org/argeo/security/activemq/osLogin.conf");
121 // System.setProperty(LOGIN_CONFIG_PROPERTY, url.toString());
122 // LoginContext lc = new LoginContext(auth);
124 // subject = lc.getSubject();
125 // } catch (LoginException le) {
126 // throw new ArgeoException("OS authentication failed", le);
128 // if (oldLoginConfLocation != null)
129 // System.setProperty(LOGIN_CONFIG_PROPERTY,
130 // oldLoginConfLocation);
131 // Thread.currentThread().setContextClassLoader(ccl);
133 // // Extract user name
134 // String osUsername = null;
135 // for (Principal principal : subject.getPrincipals()) {
136 // String className = principal.getClass().getName();
137 // if ("Unix".equals(auth)
138 // && "com.sun.security.auth.UnixPrincipal"
139 // .equals(className))
140 // osUsername = principal.getName();
141 // else if ("Windows".equals(auth)
142 // && "com.sun.security.auth.NTUserPrincipal"
143 // .equals(className))
144 // osUsername = principal.getName();
145 // else if ("Solaris".equals(auth)
146 // && "com.sun.security.auth.SolarisPrincipal"
147 // .equals(className))
148 // osUsername = principal.getName();
151 // if (osUsername == null)
152 // throw new ArgeoException("Could not find OS user name");
155 uccfa
.setUsername(System
.getProperty("user.name"));
156 uccfa
.setPassword(null);
158 } else if (AUTHMODE_UI
.equals(authenticationMode
)) {
160 UIManager
.setLookAndFeel(new MetalLookAndFeel());
161 } catch (UnsupportedLookAndFeelException e
) {
162 throw new ArgeoException("Cannot load look and feel", e
);
164 UIManager
.put("ClassLoader", getClass().getClassLoader());
165 UserPasswordDialog dialog
= new UserPasswordDialog() {
166 private static final long serialVersionUID
= -891646559691412088L;
168 protected void useCredentials(String username
, char[] password
) {
169 uccfa
.setUsername(username
);
170 uccfa
.setPassword(new String(password
));
173 dialog
.setVisible(true);
175 throw new ArgeoException("Authentication mode '"
176 + authenticationMode
+ "' is not supported");
181 protected void prepareActiveMqSslConnectionFactory(
182 ActiveMQSslConnectionFactory connectionFactory
) {
184 KeyStore keyStoreKs
= KeyStore
.getInstance(keyStoreType
);
186 InputStream keyInput
= keyStore
.getInputStream();
187 keyStoreKs
.load(keyInput
,
188 keyStorePassword
!= null ? keyStorePassword
.toCharArray()
192 TrustManagerFactory tmf
= TrustManagerFactory
193 .getInstance(TrustManagerFactory
.getDefaultAlgorithm());
194 tmf
.init(keyStoreKs
);
196 KeyManagerFactory keyManagerFactory
= KeyManagerFactory
197 .getInstance(KeyManagerFactory
.getDefaultAlgorithm());
198 keyManagerFactory
.init(keyStoreKs
, keyStorePassword
.toCharArray());
200 connectionFactory
.setKeyAndTrustManagers(
201 keyManagerFactory
.getKeyManagers(), tmf
.getTrustManagers(),
203 } catch (Exception e
) {
204 throw new ArgeoException(
205 "Cannot initialize JMS connection factory", e
);
210 public void destroy() throws Exception
{
211 if (cachingConnectionFactory
!= null)
212 cachingConnectionFactory
.destroy();
215 public void setKeyStorePassword(String keyStorePassword
) {
216 this.keyStorePassword
= keyStorePassword
;
219 public void setKeyStore(Resource keyStore
) {
220 this.keyStore
= keyStore
;
223 public void setKeyStoreType(String keyStoreType
) {
224 this.keyStoreType
= keyStoreType
;
227 public void setBrokerURL(String brokerUrl
) {
228 this.brokerURL
= brokerUrl
;
231 public void setAuthenticationMode(String authenticationMode
) {
232 this.authenticationMode
= authenticationMode
;