KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mq > security > ServerSecurityInterceptor


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mq.security;
23
24 import java.util.HashMap JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Set JavaDoc;
28 import javax.jms.Destination JavaDoc;
29 import javax.jms.JMSException JavaDoc;
30 import javax.jms.JMSSecurityException JavaDoc;
31 import javax.jms.InvalidDestinationException JavaDoc;
32 import javax.jms.TemporaryQueue JavaDoc;
33 import javax.jms.TemporaryTopic JavaDoc;
34 import org.jboss.mq.ConnectionToken;
35 import org.jboss.mq.SpyMessage;
36 import org.jboss.mq.SpyDestination;
37 import org.jboss.mq.SpyTopic;
38 import org.jboss.mq.DurableSubscriptionID;
39 import org.jboss.mq.Subscription;
40 import org.jboss.mq.TransactionRequest;
41 import org.jboss.mq.server.JMSServerInterceptorSupport;
42 /**
43  * ServerSecurityInvoker.java
44  *
45  * @author <a HREF="mailto:pra@tim.se">Peter Antman</a>
46  * @version $Revision: 37742 $
47  */

48 public class ServerSecurityInterceptor extends JMSServerInterceptorSupport
49 {
50    SecurityManager JavaDoc manager;
51
52    /**
53     * The temporary destinations for a connection
54     */

55    private HashMap JavaDoc tempDests = new HashMap JavaDoc();
56
57    public ServerSecurityInterceptor(SecurityManager JavaDoc manager)
58    {
59       super();
60       this.manager = manager;
61    }
62
63    public String JavaDoc authenticate(String JavaDoc name, String JavaDoc password) throws JMSException JavaDoc
64    {
65       log.trace("Authenticating user " + name);
66       return manager.authenticate(name, password);
67    }
68
69    /**
70     * Close connection. Logout user after connection is closed.
71     *
72     * @param dc Description of Parameter
73     * @exception JMSException Description of Exception
74     */

75    public void connectionClosing(ConnectionToken dc) throws JMSException JavaDoc
76    {
77       super.connectionClosing(dc);
78       manager.logout(dc);
79       removeTemporaryDestinations(dc);
80    }
81
82    /*
83     Here is a number of methods that I do no know if we should check access on.
84     
85     createQueue()
86     createTopic()
87
88     unsubscribe() - probably not.
89     */

90    //
91
// Read methods, to check access on
92
//
93
public SpyMessage[] browse(ConnectionToken dc, Destination JavaDoc dest, String JavaDoc selector) throws JMSException JavaDoc
94    {
95       if (log.isTraceEnabled())
96          log.trace("Checking browse authorize on " + dc + " dest=" + dest);
97       if (!authorizeRead(dc, ((SpyDestination) dest).getName()))
98          throw new JMSSecurityException JavaDoc("Connection not authorized to browse to destination: " + dest);
99       return super.browse(dc, dest, selector);
100    }
101
102    // FIXME This might actually be unneeded since a subscribe is
103
// allways done first.
104
// fuck.
105
// If we remove it, remember to remove the getSubscription method
106
public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait) throws JMSException JavaDoc
107    {
108       if (log.isTraceEnabled())
109          log.trace("Checking receive authorize on " + dc + " subId=" + subscriberId);
110       // Another nightmare, how the fck do we get the dest name.
111
Subscription sub = super.getSubscription(dc, subscriberId);
112       String JavaDoc destName = sub.destination.getName();
113       if (!authorizeRead(dc, destName))
114          throw new JMSSecurityException JavaDoc("Connection not authorized to receive from destination: " + destName);
115       return super.receive(dc, subscriberId, wait);
116    }
117
118    // The price we pay for adding this to an implementation not done
119
// for acl's. The method to create a durable susbcriber is this, but
120
// with a durableSubscriptionID in the destination of the subscription.
121
// For all but, durable subscriptions this is a read access thingy.
122
// Even more: if this is a create of a durable sub, or a change of one
123
// or just usage of an existing one, that does basically only JMSTopic (it's new or has changed) and StateManager (its allowed) know of.
124
// The logic has to be this, to not get into trouble: for ALL usage
125
// of a durable sub create access is demanded!
126
//
127
public void subscribe(org.jboss.mq.ConnectionToken dc, org.jboss.mq.Subscription sub) throws JMSException JavaDoc
128    {
129       if (log.isTraceEnabled())
130          log.trace("Checking subscribe authorize on " + dc + " sub=" + sub);
131       // Do some sanity checks
132
if (sub == null)
133          throw new JMSException JavaDoc("The subscription is not allowed to be null");
134       else if (sub.destination == null)
135          throw new InvalidDestinationException JavaDoc("Destination is not allowed to be null");
136       // Check if its a durable sub/ this might actually not be true create
137
// only access to an old one. But we only allow read from durable
138
// if you actually have the rights to create one, or...does this make
139
// preconfigured clientID meaningless.
140
SpyDestination dest = sub.destination;
141       String JavaDoc destName = dest.getName();
142       if (dest instanceof SpyTopic)
143       {
144          // Check durable sub
145
DurableSubscriptionID id = ((SpyTopic) dest).getDurableSubscriptionID();
146          if (id != null)
147          {
148             // Durable sub, check create access.
149
if (!authorizeCreate(dc, destName))
150                throw new JMSSecurityException JavaDoc("Connection not authorized to do durable subscription on topic: "
151                      + destName);
152          }
153       }
154       // We ALLWAYS check read access, even for durables
155
if (!authorizeRead(dc, destName))
156          throw new JMSSecurityException JavaDoc("Connection not authorized to subscribe to destination: " + destName);
157       super.subscribe(dc, sub);
158    }
159
160    //
161
// Write methods, to check access on
162
//
163
public void addMessage(ConnectionToken dc, SpyMessage message) throws JMSException JavaDoc
164    {
165       String JavaDoc dest = ((SpyDestination) message.getJMSDestination()).getName();
166       if (!authorizeWrite(dc, dest))
167          throw new JMSSecurityException JavaDoc("Connection not authorized to addMessages to destination: " + dest);
168       super.addMessage(dc, message);
169    }
170
171    // Check that a transaction request is authorized to send the messages
172
public void transact(ConnectionToken dc, TransactionRequest t) throws JMSException JavaDoc
173    {
174       if (t.messages != null)
175       {
176          // Optimization for common case
177
if (t.messages.length == 1)
178          {
179             String JavaDoc dest = ((SpyDestination) t.messages[0].getJMSDestination()).getName();
180             if (authorizeWrite(dc, dest) == false)
181                throw new JMSSecurityException JavaDoc("Connection not authorized to addMessages to destination: " + dest);
182          }
183          else if (t.messages.length > 0)
184          {
185             HashSet JavaDoc destinations = new HashSet JavaDoc();
186             for (int i = 0; i < t.messages.length; ++i)
187                destinations.add(((SpyDestination) t.messages[i].getJMSDestination()).getName());
188             
189             for (Iterator JavaDoc i = destinations.iterator(); i.hasNext();)
190             {
191                String JavaDoc destinationName = (String JavaDoc) i.next();
192                if (authorizeWrite(dc, destinationName) == false)
193                   throw new JMSSecurityException JavaDoc("Connection not authorized to addMessages to destination: " + destinationName);
194             }
195          }
196       }
197       super.transact(dc, t);
198    }
199    
200    //
201
// Create methods, to check access on
202
//
203
public void destroySubscription(ConnectionToken dc, DurableSubscriptionID id) throws JMSException JavaDoc
204    {
205       // Oh, this fucker is a nightmare. How do we get wich topic the
206
// connection is trying to unsubscribe from
207
SpyTopic t = super.getDurableTopic(id);
208       if (t == null)
209          throw new InvalidDestinationException JavaDoc("No durable topic found for subscription " + id.getSubscriptionName());
210       if (!authorizeCreate(dc, t.getName()))
211          throw new JMSSecurityException JavaDoc("Connection not authorized to unsubscribe from subscription: " + t.getName());
212       super.destroySubscription(dc, id);
213    }
214
215    public TemporaryTopic JavaDoc getTemporaryTopic(ConnectionToken dc) throws JMSException JavaDoc
216    {
217       TemporaryTopic JavaDoc result = super.getTemporaryTopic(dc);
218       addTemporaryDestination(dc, result);
219       return result;
220    }
221
222    public TemporaryQueue JavaDoc getTemporaryQueue(ConnectionToken dc) throws JMSException JavaDoc
223    {
224       TemporaryQueue JavaDoc result = super.getTemporaryQueue(dc);
225       addTemporaryDestination(dc, result);
226       return result;
227    }
228
229    public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination destination) throws JMSException JavaDoc
230    {
231       removeTemporaryDestination(dc, destination);
232       super.deleteTemporaryDestination(dc, destination);
233    }
234
235    //
236
// Security helper methods
237
//
238
public boolean authorizeRead(ConnectionToken dc, String JavaDoc destination) throws JMSException JavaDoc
239    {
240       // First we must get access to the destinations security meta data
241
SecurityMetadata m = manager.getSecurityMetadata(destination);
242       if (m == null)
243       {
244          log.warn("No security configuration avaliable for " + destination);
245          return false;//FIXME, is this OK?
246
}
247       Set JavaDoc readPrincipals = m.getReadPrincipals();
248       if (manager.authorize(dc, readPrincipals))
249          return true;
250       else
251          return false;
252    }
253
254    public boolean authorizeWrite(ConnectionToken dc, String JavaDoc destination) throws JMSException JavaDoc
255    {
256       // First we must get access to the destinations security meta data
257
SecurityMetadata m = manager.getSecurityMetadata(destination);
258       if (m == null)
259       {
260          log.warn("No security configuration avaliable for " + destination);
261          return false;//FIXME, is this OK?
262
}
263       Set JavaDoc writePrincipals = m.getWritePrincipals();
264       if (manager.authorize(dc, writePrincipals))
265          return true;
266       else
267          return false;
268    }
269
270    public boolean authorizeCreate(ConnectionToken dc, String JavaDoc destination) throws JMSException JavaDoc
271    {
272       // First we must get access to the destinations security meta data
273
SecurityMetadata m = manager.getSecurityMetadata(destination);
274       if (m == null)
275       {
276          log.warn("No security configuration avaliable for " + destination);
277          return false;//FIXME, is this OK?
278
}
279       Set JavaDoc createPrincipals = m.getCreatePrincipals();
280       if (manager.authorize(dc, createPrincipals))
281          return true;
282       else
283          return false;
284    }
285
286    /**
287     * Remember the temporary destinations for a connection
288     */

289    public void addTemporaryDestination(ConnectionToken dc, Destination JavaDoc destination)
290    {
291       synchronized (tempDests)
292       {
293          HashSet JavaDoc set = (HashSet JavaDoc) tempDests.get(dc);
294          if (set == null)
295          {
296             set = new HashSet JavaDoc();
297             tempDests.put(dc, set);
298          }
299          set.add(destination);
300       }
301    }
302
303    /**
304     * Remove a temporary destination
305     */

306    public void removeTemporaryDestination(ConnectionToken dc, SpyDestination destination)
307    {
308       synchronized (tempDests)
309       {
310          HashSet JavaDoc set = (HashSet JavaDoc) tempDests.get(dc);
311          if (set == null)
312             return;
313          set.remove(destination);
314       }
315       try
316       {
317          manager.removeDestination(destination.getName());
318       }
319       catch (Exception JavaDoc e)
320       {
321          log.warn("Unable to remove temporary destination " + destination, e);
322       }
323    }
324
325    /**
326     * Remove all temporary destination for a connection
327     */

328    public void removeTemporaryDestinations(ConnectionToken dc)
329    {
330       synchronized (tempDests)
331       {
332          HashSet JavaDoc set = (HashSet JavaDoc) tempDests.remove(dc);
333          if (set == null)
334             return;
335          for (Iterator JavaDoc iterator = set.iterator(); iterator.hasNext();)
336          {
337             SpyDestination destination = (SpyDestination) iterator.next();
338             try
339             {
340                manager.removeDestination(destination.getName());
341             }
342             catch (Exception JavaDoc e)
343             {
344                log.warn("Unable to remove temporary destination " + destination, e);
345             }
346          }
347       }
348    }
349 } // ServerSecurityInvoker
350
Popular Tags