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 = "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
);
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(keyManagerFactory
200 .getKeyManagers(), tmf
.getTrustManagers(),
202 } catch (Exception e
) {
203 throw new ArgeoException(
204 "Cannot initailize JMS conneciton 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
;