2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
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.
17 package org
.argeo
.security
.activemq
;
19 import java
.io
.InputStream
;
20 import java
.security
.KeyStore
;
21 import java
.security
.SecureRandom
;
23 import javax
.jms
.Connection
;
24 import javax
.jms
.ConnectionFactory
;
25 import javax
.jms
.JMSException
;
26 import javax
.net
.ssl
.KeyManagerFactory
;
27 import javax
.net
.ssl
.TrustManagerFactory
;
28 import javax
.swing
.UIManager
;
29 import javax
.swing
.UnsupportedLookAndFeelException
;
30 import javax
.swing
.plaf
.metal
.MetalLookAndFeel
;
32 import org
.apache
.activemq
.ActiveMQSslConnectionFactory
;
33 import org
.apache
.commons
.logging
.Log
;
34 import org
.apache
.commons
.logging
.LogFactory
;
35 import org
.argeo
.ArgeoException
;
36 import org
.argeo
.security
.core
.UserPasswordDialog
;
37 import org
.springframework
.beans
.factory
.DisposableBean
;
38 import org
.springframework
.beans
.factory
.InitializingBean
;
39 import org
.springframework
.core
.io
.Resource
;
40 import org
.springframework
.jms
.connection
.CachingConnectionFactory
;
41 import org
.springframework
.jms
.connection
.UserCredentialsConnectionFactoryAdapter
;
43 public class SecuredActiveMqConnectionFactory
implements ConnectionFactory
,
44 InitializingBean
, DisposableBean
{
46 public final static String AUTHMODE_UI
= "ui";
47 public final static String AUTHMODE_OS
= "os";
48 public final static String AUTHMODE_DEFAULT
= AUTHMODE_OS
;
49 // private final static String LOGIN_CONFIG_PROPERTY =
50 // "java.security.auth.login.config";
52 private final static Log log
= LogFactory
53 .getLog(SecuredActiveMqConnectionFactory
.class);
55 private String keyStorePassword
;
56 private Resource keyStore
;
57 private String keyStoreType
= "JKS";// "PKCS12"
58 private String brokerURL
;
60 private String authenticationMode
;
62 private CachingConnectionFactory cachingConnectionFactory
;
64 public Connection
createConnection() throws JMSException
{
65 return cachingConnectionFactory
.createConnection();
68 public Connection
createConnection(String userName
, String password
)
70 throw new UnsupportedOperationException();
73 public void afterPropertiesSet() throws Exception
{
74 ActiveMQSslConnectionFactory activeMQSslConnectionFactory
= new ActiveMQSslConnectionFactory();
75 prepareActiveMqSslConnectionFactory(activeMQSslConnectionFactory
);
76 activeMQSslConnectionFactory
.setBrokerURL(brokerURL
);
77 UserCredentialsConnectionFactoryAdapter uccfa
= new UserCredentialsConnectionFactoryAdapter();
78 uccfa
.setTargetConnectionFactory(activeMQSslConnectionFactory
);
79 cachingConnectionFactory
= new CachingConnectionFactory();
80 cachingConnectionFactory
.setTargetConnectionFactory(uccfa
);
81 cachingConnectionFactory
.setCacheConsumers(false);
83 initConnectionFactoryCredentials(uccfa
);
84 cachingConnectionFactory
.initConnection();
85 log
.info("Connected to " + brokerURL
);
86 uccfa
.setUsername(null);
87 uccfa
.setPassword(null);
91 protected void initConnectionFactoryCredentials(
92 final UserCredentialsConnectionFactoryAdapter uccfa
) {
93 if (authenticationMode
== null)
94 authenticationMode
= AUTHMODE_DEFAULT
;
96 if (AUTHMODE_OS
.equals(authenticationMode
)) {
98 // // Cache previous value of login conf location
99 // String oldLoginConfLocation = System
100 // .getProperty(LOGIN_CONFIG_PROPERTY);
102 // String osName = System.getProperty("os.name");
103 // final String auth;
104 // if (osName.startsWith("Windows"))
106 // else if (osName.startsWith("SunOS")
107 // || osName.startsWith("Solaris"))
113 // // see http://old.nabble.com/osgi-and-jaas-td23485885.html
114 // ClassLoader ccl = Thread.currentThread()
115 // .getContextClassLoader();
117 // Thread.currentThread().setContextClassLoader(
118 // getClass().getClassLoader());
119 // URL url = getClass().getResource(
120 // "/org/argeo/security/activemq/osLogin.conf");
122 // System.setProperty(LOGIN_CONFIG_PROPERTY, url.toString());
123 // LoginContext lc = new LoginContext(auth);
125 // subject = lc.getSubject();
126 // } catch (LoginException le) {
127 // throw new ArgeoException("OS authentication failed", le);
129 // if (oldLoginConfLocation != null)
130 // System.setProperty(LOGIN_CONFIG_PROPERTY,
131 // oldLoginConfLocation);
132 // Thread.currentThread().setContextClassLoader(ccl);
134 // // Extract user name
135 // String osUsername = null;
136 // for (Principal principal : subject.getPrincipals()) {
137 // String className = principal.getClass().getName();
138 // if ("Unix".equals(auth)
139 // && "com.sun.security.auth.UnixPrincipal"
140 // .equals(className))
141 // osUsername = principal.getName();
142 // else if ("Windows".equals(auth)
143 // && "com.sun.security.auth.NTUserPrincipal"
144 // .equals(className))
145 // osUsername = principal.getName();
146 // else if ("Solaris".equals(auth)
147 // && "com.sun.security.auth.SolarisPrincipal"
148 // .equals(className))
149 // osUsername = principal.getName();
152 // if (osUsername == null)
153 // throw new ArgeoException("Could not find OS user name");
156 uccfa
.setUsername(System
.getProperty("user.name"));
157 uccfa
.setPassword(null);
159 } else if (AUTHMODE_UI
.equals(authenticationMode
)) {
161 UIManager
.setLookAndFeel(new MetalLookAndFeel());
162 } catch (UnsupportedLookAndFeelException e
) {
163 throw new ArgeoException("Cannot load look and feel", e
);
165 UIManager
.put("ClassLoader", getClass().getClassLoader());
166 UserPasswordDialog dialog
= new UserPasswordDialog() {
167 private static final long serialVersionUID
= -891646559691412088L;
169 protected void useCredentials(String username
, char[] password
) {
170 uccfa
.setUsername(username
);
171 uccfa
.setPassword(new String(password
));
174 dialog
.setVisible(true);
176 throw new ArgeoException("Authentication mode '"
177 + authenticationMode
+ "' is not supported");
182 protected void prepareActiveMqSslConnectionFactory(
183 ActiveMQSslConnectionFactory connectionFactory
) {
185 KeyStore keyStoreKs
= KeyStore
.getInstance(keyStoreType
);
187 InputStream keyInput
= keyStore
.getInputStream();
188 keyStoreKs
.load(keyInput
,
189 keyStorePassword
!= null ? keyStorePassword
.toCharArray()
193 TrustManagerFactory tmf
= TrustManagerFactory
194 .getInstance(TrustManagerFactory
.getDefaultAlgorithm());
195 tmf
.init(keyStoreKs
);
197 KeyManagerFactory keyManagerFactory
= KeyManagerFactory
198 .getInstance(KeyManagerFactory
.getDefaultAlgorithm());
199 keyManagerFactory
.init(keyStoreKs
, keyStorePassword
.toCharArray());
201 connectionFactory
.setKeyAndTrustManagers(keyManagerFactory
202 .getKeyManagers(), tmf
.getTrustManagers(),
204 } catch (Exception e
) {
205 throw new ArgeoException(
206 "Cannot initialize JMS connection factory", e
);
211 public void destroy() throws Exception
{
212 if (cachingConnectionFactory
!= null)
213 cachingConnectionFactory
.destroy();
216 public void setKeyStorePassword(String keyStorePassword
) {
217 this.keyStorePassword
= keyStorePassword
;
220 public void setKeyStore(Resource keyStore
) {
221 this.keyStore
= keyStore
;
224 public void setKeyStoreType(String keyStoreType
) {
225 this.keyStoreType
= keyStoreType
;
228 public void setBrokerURL(String brokerUrl
) {
229 this.brokerURL
= brokerUrl
;
232 public void setAuthenticationMode(String authenticationMode
) {
233 this.authenticationMode
= authenticationMode
;