2 * Copyright (C) 2007-2012 Mathieu Baudier
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 public class SecuredActiveMqConnectionFactory
implements ConnectionFactory
,
42 InitializingBean
, DisposableBean
{
44 public final static String AUTHMODE_UI
= "ui";
45 public final static String AUTHMODE_OS
= "os";
46 public final static String AUTHMODE_DEFAULT
= AUTHMODE_OS
;
47 // private final static String LOGIN_CONFIG_PROPERTY =
48 // "java.security.auth.login.config";
50 private final static Log log
= LogFactory
51 .getLog(SecuredActiveMqConnectionFactory
.class);
53 private String keyStorePassword
;
54 private Resource keyStore
;
55 private String keyStoreType
= "JKS";// "PKCS12"
56 private String brokerURL
;
58 private String authenticationMode
;
60 private CachingConnectionFactory cachingConnectionFactory
;
62 public Connection
createConnection() throws JMSException
{
63 return cachingConnectionFactory
.createConnection();
66 public Connection
createConnection(String userName
, String password
)
68 throw new UnsupportedOperationException();
71 public void afterPropertiesSet() throws Exception
{
72 ActiveMQSslConnectionFactory activeMQSslConnectionFactory
= new ActiveMQSslConnectionFactory();
73 prepareActiveMqSslConnectionFactory(activeMQSslConnectionFactory
);
74 activeMQSslConnectionFactory
.setBrokerURL(brokerURL
);
75 UserCredentialsConnectionFactoryAdapter uccfa
= new UserCredentialsConnectionFactoryAdapter();
76 uccfa
.setTargetConnectionFactory(activeMQSslConnectionFactory
);
77 cachingConnectionFactory
= new CachingConnectionFactory();
78 cachingConnectionFactory
.setTargetConnectionFactory(uccfa
);
79 cachingConnectionFactory
.setCacheConsumers(false);
81 initConnectionFactoryCredentials(uccfa
);
82 cachingConnectionFactory
.initConnection();
83 log
.info("Connected to " + brokerURL
);
84 uccfa
.setUsername(null);
85 uccfa
.setPassword(null);
89 protected void initConnectionFactoryCredentials(
90 final UserCredentialsConnectionFactoryAdapter uccfa
) {
91 if (authenticationMode
== null)
92 authenticationMode
= AUTHMODE_DEFAULT
;
94 if (AUTHMODE_OS
.equals(authenticationMode
)) {
96 // // Cache previous value of login conf location
97 // String oldLoginConfLocation = System
98 // .getProperty(LOGIN_CONFIG_PROPERTY);
100 // String osName = System.getProperty("os.name");
101 // final String auth;
102 // if (osName.startsWith("Windows"))
104 // else if (osName.startsWith("SunOS")
105 // || osName.startsWith("Solaris"))
111 // // see http://old.nabble.com/osgi-and-jaas-td23485885.html
112 // ClassLoader ccl = Thread.currentThread()
113 // .getContextClassLoader();
115 // Thread.currentThread().setContextClassLoader(
116 // getClass().getClassLoader());
117 // URL url = getClass().getResource(
118 // "/org/argeo/security/activemq/osLogin.conf");
120 // System.setProperty(LOGIN_CONFIG_PROPERTY, url.toString());
121 // LoginContext lc = new LoginContext(auth);
123 // subject = lc.getSubject();
124 // } catch (LoginException le) {
125 // throw new ArgeoException("OS authentication failed", le);
127 // if (oldLoginConfLocation != null)
128 // System.setProperty(LOGIN_CONFIG_PROPERTY,
129 // oldLoginConfLocation);
130 // Thread.currentThread().setContextClassLoader(ccl);
132 // // Extract user name
133 // String osUsername = null;
134 // for (Principal principal : subject.getPrincipals()) {
135 // String className = principal.getClass().getName();
136 // if ("Unix".equals(auth)
137 // && "com.sun.security.auth.UnixPrincipal"
138 // .equals(className))
139 // osUsername = principal.getName();
140 // else if ("Windows".equals(auth)
141 // && "com.sun.security.auth.NTUserPrincipal"
142 // .equals(className))
143 // osUsername = principal.getName();
144 // else if ("Solaris".equals(auth)
145 // && "com.sun.security.auth.SolarisPrincipal"
146 // .equals(className))
147 // osUsername = principal.getName();
150 // if (osUsername == null)
151 // throw new ArgeoException("Could not find OS user name");
154 uccfa
.setUsername(System
.getProperty("user.name"));
155 uccfa
.setPassword(null);
157 } else if (AUTHMODE_UI
.equals(authenticationMode
)) {
159 UIManager
.setLookAndFeel(new MetalLookAndFeel());
160 } catch (UnsupportedLookAndFeelException e
) {
161 throw new ArgeoException("Cannot load look and feel", e
);
163 UIManager
.put("ClassLoader", getClass().getClassLoader());
164 UserPasswordDialog dialog
= new UserPasswordDialog() {
165 private static final long serialVersionUID
= -891646559691412088L;
167 protected void useCredentials(String username
, char[] password
) {
168 uccfa
.setUsername(username
);
169 uccfa
.setPassword(new String(password
));
172 dialog
.setVisible(true);
174 throw new ArgeoException("Authentication mode '"
175 + authenticationMode
+ "' is not supported");
180 protected void prepareActiveMqSslConnectionFactory(
181 ActiveMQSslConnectionFactory connectionFactory
) {
183 KeyStore keyStoreKs
= KeyStore
.getInstance(keyStoreType
);
185 InputStream keyInput
= keyStore
.getInputStream();
186 keyStoreKs
.load(keyInput
,
187 keyStorePassword
!= null ? keyStorePassword
.toCharArray()
191 TrustManagerFactory tmf
= TrustManagerFactory
192 .getInstance(TrustManagerFactory
.getDefaultAlgorithm());
193 tmf
.init(keyStoreKs
);
195 KeyManagerFactory keyManagerFactory
= KeyManagerFactory
196 .getInstance(KeyManagerFactory
.getDefaultAlgorithm());
197 keyManagerFactory
.init(keyStoreKs
, keyStorePassword
.toCharArray());
199 connectionFactory
.setKeyAndTrustManagers(
200 keyManagerFactory
.getKeyManagers(), tmf
.getTrustManagers(),
202 } catch (Exception e
) {
203 throw new ArgeoException(
204 "Cannot initialize JMS connection factory", e
);
209 public void destroy() throws Exception
{
210 if (cachingConnectionFactory
!= null)
211 cachingConnectionFactory
.destroy();
214 public void setKeyStorePassword(String keyStorePassword
) {
215 this.keyStorePassword
= keyStorePassword
;
218 public void setKeyStore(Resource keyStore
) {
219 this.keyStore
= keyStore
;
222 public void setKeyStoreType(String keyStoreType
) {
223 this.keyStoreType
= keyStoreType
;
226 public void setBrokerURL(String brokerUrl
) {
227 this.brokerURL
= brokerUrl
;
230 public void setAuthenticationMode(String authenticationMode
) {
231 this.authenticationMode
= authenticationMode
;