Source code: org/activemq/security/jassjacc/JassJaccSecurityAdapter.java
1 /**
2 *
3 * Copyright 2004 Hiram Chirino
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.activemq.security.jassjacc;
19
20 import java.security.AccessControlContext;
21 import java.security.AccessControlException;
22 import java.security.AccessController;
23 import java.security.Permission;
24 import java.security.PrivilegedAction;
25 import java.util.Iterator;
26
27 import javax.jms.JMSException;
28 import javax.security.auth.Subject;
29 import javax.security.auth.login.LoginContext;
30 import javax.security.jacc.PolicyConfiguration;
31 import javax.security.jacc.PolicyConfigurationFactory;
32 import javax.security.jacc.PolicyContext;
33 import javax.security.jacc.PolicyContextException;
34
35 import org.activemq.broker.BrokerClient;
36 import org.activemq.message.ActiveMQDestination;
37 import org.activemq.message.ActiveMQMessage;
38 import org.activemq.message.ConnectionInfo;
39 import org.activemq.message.ConsumerInfo;
40 import org.activemq.message.ProducerInfo;
41 import org.activemq.security.SecurityAdapter;
42
43 /**
44 * Implements SecurityAdapter that uses JASS to authenticate and
45 * JACC to authorize the user operations.
46 *
47 * @version $Revision: 1.1.1.1 $
48 */
49 public class JassJaccSecurityAdapter implements SecurityAdapter {
50
51 private String jassConfiguration;
52
53 /**
54 * @param jassConfiguration
55 */
56 public JassJaccSecurityAdapter(String jassConfiguration) {
57 this.jassConfiguration = jassConfiguration;
58 }
59
60
61 protected AccessControlContext getAccessControlContext(BrokerClient client) {
62
63 Subject subject = client.getSubject();
64 if (subject == null) throw new IllegalArgumentException("Subject must not be null");
65
66 AccessControlContext acc = (AccessControlContext) Subject.doAsPrivileged(subject, new PrivilegedAction() {
67 public Object run() {
68 return AccessController.getContext();
69 }
70 }, null);
71
72 return acc;
73 }
74
75 static protected String getBrokerName(BrokerClient client) {
76 return client.getBrokerConnector().getBrokerInfo().getBrokerName();
77 }
78
79 public void authorizeConnection(BrokerClient client, ConnectionInfo info) throws JMSException {
80
81 // Set the TCCL since it seems JAAS needs it to find the login module classes.
82 Thread.currentThread().setContextClassLoader(JassJaccSecurityAdapter.class.getClassLoader());
83
84 // Do the login.
85 Subject subject = doJassLogin(info);
86 client.setSubject(subject);
87
88 // Can the user really use the broker?
89 PolicyContext.setContextID(getBrokerPoicyContextId(client));
90 AccessControlContext accessContext = getAccessControlContext(client);
91 if (accessContext != null) {
92 Permission permission = new JMSBrokerPermission(getBrokerName(client),JMSBrokerPermission.CONNECT_ACTION);
93 accessContext.checkPermission(permission);
94 }
95 }
96
97 /**
98 * @param client
99 * @return
100 */
101 static private String getBrokerPoicyContextId(BrokerClient client) {
102 return getBrokerPolicyContextId(getBrokerName(client));
103 }
104
105 /**
106 * @param client
107 * @return
108 */
109 static private String getBrokerPolicyContextId(String brokerName) {
110 return "org.activemq.broker:"+brokerName;
111 }
112
113 /**
114 * @param info
115 * @param subject
116 * @return
117 */
118 private Subject doJassLogin(ConnectionInfo info) throws JMSException {
119 try {
120 LoginContext lc = new LoginContext(jassConfiguration,
121 new UsernamePasswordCallback(info.getUserName(), info
122 .getPassword()));
123 lc.login();
124 return lc.getSubject();
125 } catch (Exception e) {
126 throw (JMSException)new JMSException("Login failed: "+e.getMessage()).initCause(e);
127 }
128 }
129
130 public void authorizeConsumer(BrokerClient client, ConsumerInfo info) throws JMSException {
131 PolicyContext.setContextID(getDestinationPoicyContextId(client, info.getDestination()));
132 AccessControlContext accessContext = getAccessControlContext(client);
133 if (accessContext != null) {
134 Permission permission = new JMSDestinationPermission(info.getDestination().getPhysicalName(),JMSDestinationPermission.CONSUME_ACTION);
135 accessContext.checkPermission(permission);
136 }
137 }
138
139 public boolean authorizeReceive(BrokerClient client, ActiveMQMessage message) {
140 try {
141 PolicyContext.setContextID(getDestinationPoicyContextId(client, message.getJMSActiveMQDestination()));
142 AccessControlContext accessContext = getAccessControlContext(client);
143 if (accessContext != null) {
144 Permission permission = new JMSDestinationPermission(message.getJMSActiveMQDestination().getPhysicalName(),JMSDestinationPermission.CONSUME_ACTION);
145 accessContext.checkPermission(permission);
146 }
147 }
148 catch (AccessControlException e) {
149 return false;
150 }
151 return true;
152 }
153
154
155 /**
156 * @param client
157 * @param destination
158 * @return
159 */
160 static private String getDestinationPoicyContextId(BrokerClient client, ActiveMQDestination destination) {
161 return getDestinationPoicyContextId(getBrokerName(client), destination);
162 }
163
164 static private String getDestinationPoicyContextId(String brokerName, ActiveMQDestination destination) {
165 ActiveMQDestination activeMQDestination = ((ActiveMQDestination)destination);
166 return (activeMQDestination.isTopic()?"org.activemq.topic:":"org.activemq.queue:")+brokerName+":"+activeMQDestination.getPhysicalName();
167 }
168
169 public void authorizeProducer(BrokerClient client, ProducerInfo info) throws JMSException {
170 PolicyContext.setContextID(getDestinationPoicyContextId(client, info.getDestination()));
171 AccessControlContext accessContext = getAccessControlContext(client);
172 if (accessContext != null) {
173 Permission permission = new JMSDestinationPermission(info.getDestination().getPhysicalName(),JMSDestinationPermission.PRODUCE_ACTION);
174 accessContext.checkPermission(permission);
175 }
176 }
177
178 public void authorizeSendMessage(BrokerClient client, ActiveMQMessage message) throws JMSException {
179 PolicyContext.setContextID(getDestinationPoicyContextId(client, message.getJMSActiveMQDestination()));
180 AccessControlContext accessContext = getAccessControlContext(client);
181 if (accessContext != null) {
182 String physicalName = ((ActiveMQDestination)message.getJMSDestination()).getPhysicalName();
183 Permission permission = new JMSDestinationPermission(message.getJMSActiveMQDestination().getPhysicalName(),JMSDestinationPermission.SEND_ACTION);
184 accessContext.checkPermission(permission);
185 }
186 }
187
188 /**
189 * Creates a JACC PolicyConfiguration for the broker security.
190 *
191 * @param brokerSecurity
192 */
193 static public void secure(BrokerSecurityConfig brokerSecurity) {
194
195 try {
196
197 PolicyConfigurationFactory factory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
198 PolicyConfiguration policyConfiguration = factory.getPolicyConfiguration(
199 getBrokerPolicyContextId(brokerSecurity.getBrokerName()), true);
200
201 for (Iterator iter = brokerSecurity.getConnectRoles().iterator(); iter.hasNext();) {
202 String role = (String) iter.next();
203 policyConfiguration.addToRole(role, new JMSBrokerPermission(
204 brokerSecurity.getBrokerName(), JMSBrokerPermission.CONNECT_ACTION));
205 }
206
207 policyConfiguration.commit();
208
209 } catch (ClassNotFoundException e) {
210 e.printStackTrace();
211 } catch (PolicyContextException e) {
212 e.printStackTrace();
213 }
214
215 }
216
217 /**
218 * Creates a JACC PolicyConfiguration for the broker security.
219 *
220 * @param brokerSecurity
221 */
222 static public void secure(DestinationSecurityConfig destinationSecurity) {
223
224 try {
225
226 String policyId = getDestinationPoicyContextId(destinationSecurity.getBrokerName(), destinationSecurity.getDestination());
227 PolicyConfigurationFactory factory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
228 PolicyConfiguration policyConfiguration = factory.getPolicyConfiguration(policyId, true);
229
230 for (Iterator iter = destinationSecurity.getConsumeRoles().iterator(); iter.hasNext();) {
231 String role = (String) iter.next();
232 policyConfiguration.addToRole(role, new JMSDestinationPermission(
233 destinationSecurity.getDestination().getPhysicalName(), JMSDestinationPermission.CONSUME_ACTION));
234 }
235 for (Iterator iter = destinationSecurity.getProduceRoles().iterator(); iter.hasNext();) {
236 String role = (String) iter.next();
237 policyConfiguration.addToRole(role, new JMSDestinationPermission(
238 destinationSecurity.getDestination().getPhysicalName(), JMSDestinationPermission.PRODUCE_ACTION));
239 }
240 for (Iterator iter = destinationSecurity.getSendRoles().iterator(); iter.hasNext();) {
241 String role = (String) iter.next();
242 policyConfiguration.addToRole(role, new JMSDestinationPermission(
243 destinationSecurity.getDestination().getPhysicalName(), JMSDestinationPermission.SEND_ACTION));
244 }
245
246 policyConfiguration.commit();
247
248 } catch (ClassNotFoundException e) {
249 e.printStackTrace();
250 } catch (PolicyContextException e) {
251 e.printStackTrace();
252 }
253
254 }
255
256 }