KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > security > srp > SRPService


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.security.srp;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.lang.reflect.Proxy JavaDoc;
27 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
28 import java.rmi.server.RMIClientSocketFactory JavaDoc;
29 import java.rmi.server.RMIServerSocketFactory JavaDoc;
30 import java.util.Collections JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Map JavaDoc;
33 import javax.naming.InitialContext JavaDoc;
34 import javax.naming.Name JavaDoc;
35 import javax.naming.NamingException JavaDoc;
36
37 import org.jboss.invocation.Invocation;
38 import org.jboss.invocation.MarshalledInvocation;
39 import org.jboss.naming.NonSerializableFactory;
40 import org.jboss.security.srp.SRPRemoteServer;
41 import org.jboss.security.srp.SRPServerListener;
42 import org.jboss.security.srp.SRPServerInterface;
43 import org.jboss.security.srp.SRPServerSession;
44 import org.jboss.security.srp.SRPVerifierStore;
45 import org.jboss.system.ServiceMBeanSupport;
46 import org.jboss.util.CachePolicy;
47 import org.jboss.util.TimedCachePolicy;
48
49 /** The JMX mbean interface for the SRP service. This mbean sets up an
50  RMI implementation of the 'Secure Remote Password' cryptographic authentication
51  system described in RFC2945.
52  
53  @author Scott.Stark@jboss.org
54  @version $Revision: 40096 $
55  */

56 public class SRPService extends ServiceMBeanSupport
57    implements SRPServiceMBean, SRPServerListener
58 {
59    /**
60     * @supplierRole RMI Access
61     * @supplierCardinality 1
62     * @clientCardinality 1
63     * @clientRole service mangement
64     */

65    private SRPRemoteServer server;
66    private int serverPort = 10099;
67
68    /**
69     * @supplierRole password store
70     * @supplierCardinality 1
71     * @clientRole configures
72     */

73    private SRPVerifierStore verifierStore;
74    private String JavaDoc verifierSourceJndiName = "srp/DefaultVerifierSource";
75    private String JavaDoc serverJndiName = "srp/SRPServerInterface";
76    private String JavaDoc cacheJndiName = "srp/AuthenticationCache";
77    private CachePolicy cachePolicy;
78    private int cacheTimeout = 1800;
79    private int cacheResolution = 60;
80    /** A flag indicating if a successful user auth for an existing session
81     should overwrite the current session.
82     */

83    private boolean overwriteSessions;
84    /** A flag indicating if an aux challenge must be presented in verify */
85    private boolean requireAuxChallenge;
86    /** An optional custom client socket factory */
87    private RMIClientSocketFactory JavaDoc clientSocketFactory;
88    /** An optional custom server socket factory */
89    private RMIServerSocketFactory JavaDoc serverSocketFactory;
90    /** The class name of the optional custom client socket factory */
91    private String JavaDoc clientSocketFactoryName;
92    /** The class name of the optional custom server socket factory */
93    private String JavaDoc serverSocketFactoryName;
94    /** A <Long,Method> mapping of the SRPRemoteServerInterface */
95    private Map JavaDoc marshalledInvocationMapping = new HashMap JavaDoc();
96
97 // --- Begin SRPServiceMBean interface methods
98
/** Get the jndi name for the SRPVerifierSource implementation binding.
99     */

100    public String JavaDoc getVerifierSourceJndiName()
101    {
102       return verifierSourceJndiName;
103    }
104    /** set the jndi name for the SRPVerifierSource implementation binding.
105     */

106    public void setVerifierSourceJndiName(String JavaDoc jndiName)
107    {
108       this.verifierSourceJndiName = jndiName;
109    }
110    /** Get the jndi name under which the SRPServerInterface proxy should be bound
111     */

112    public String JavaDoc getJndiName()
113    {
114       return serverJndiName;
115    }
116    /** Set the jndi name under which the SRPServerInterface proxy should be bound
117     */

118    public void setJndiName(String JavaDoc jndiName)
119    {
120       this.serverJndiName = jndiName;
121    }
122    /** Get the jndi name under which the SRPServerInterface proxy should be bound
123     */

124    public String JavaDoc getAuthenticationCacheJndiName()
125    {
126       return cacheJndiName;
127    }
128    /** Set the jndi name under which the SRPServerInterface proxy should be bound
129     */

130    public void setAuthenticationCacheJndiName(String JavaDoc jndiName)
131    {
132       this.cacheJndiName = jndiName;
133    }
134    
135    /** Get the auth cache timeout period in seconds
136     */

137    public int getAuthenticationCacheTimeout()
138    {
139       return cacheTimeout;
140    }
141    /** Set the auth cache timeout period in seconds
142     */

143    public void setAuthenticationCacheTimeout(int timeoutInSecs)
144    {
145       this.cacheTimeout = timeoutInSecs;
146    }
147    /** Get the auth cache resolution period in seconds
148     */

149    public int getAuthenticationCacheResolution()
150    {
151       return cacheResolution;
152    }
153    /** Set the auth cache resolution period in seconds
154     */

155    public void setAuthenticationCacheResolution(int resInSecs)
156    {
157       this.cacheResolution = resInSecs;
158    }
159
160    public boolean getRequireAuxChallenge()
161    {
162       return this.requireAuxChallenge;
163    }
164    public void setRequireAuxChallenge(boolean flag)
165    {
166       this.requireAuxChallenge = flag;
167    }
168
169    public boolean getOverwriteSessions()
170    {
171       return this.overwriteSessions;
172    }
173    public void setOverwriteSessions(boolean flag)
174    {
175       this.overwriteSessions = flag;
176    }
177
178    /** Get the RMIClientSocketFactory implementation class. If null the default
179     RMI client socket factory implementation is used.
180     */

181    public String JavaDoc getClientSocketFactory()
182    {
183       return serverSocketFactoryName;
184    }
185    /** Set the RMIClientSocketFactory implementation class. If null the default
186     RMI client socket factory implementation is used.
187     */

188    public void setClientSocketFactory(String JavaDoc factoryClassName)
189       throws ClassNotFoundException JavaDoc, InstantiationException JavaDoc, IllegalAccessException JavaDoc
190    {
191       this.clientSocketFactoryName = factoryClassName;
192       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
193       Class JavaDoc clazz = loader.loadClass(clientSocketFactoryName);
194       clientSocketFactory = (RMIClientSocketFactory JavaDoc) clazz.newInstance();
195    }
196    
197    /** Get the RMIServerSocketFactory implementation class. If null the default
198     RMI server socket factory implementation is used.
199     */

200    public String JavaDoc getServerSocketFactory()
201    {
202       return serverSocketFactoryName;
203    }
204    /** Set the RMIServerSocketFactory implementation class. If null the default
205     RMI server socket factory implementation is used.
206     */

207    public void setServerSocketFactory(String JavaDoc factoryClassName)
208       throws ClassNotFoundException JavaDoc, InstantiationException JavaDoc, IllegalAccessException JavaDoc
209    {
210       this.serverSocketFactoryName = factoryClassName;
211       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
212       Class JavaDoc clazz = loader.loadClass(serverSocketFactoryName);
213       serverSocketFactory = (RMIServerSocketFactory JavaDoc) clazz.newInstance();
214    }
215    /** Get the RMI port for the SRPServerInterface
216     */

217    public int getServerPort()
218    {
219       return serverPort;
220    }
221    /** Get the RMI port for the SRPServerInterface
222     */

223    public void setServerPort(int serverPort)
224    {
225       this.serverPort = serverPort;
226    }
227 // --- End SRPServiceMBean interface methods
228

229    /** Called when username has sucessfully completed the SRP login. This
230     places the SRP session into the credential cache using a
231     SimplePrincipal based on the username as the key.
232     */

233    public void verifiedUser(SRPSessionKey key, SRPServerSession session)
234    {
235       try
236       {
237          synchronized( cachePolicy )
238          {
239             // We only insert a principal if there is no current entry.
240
if( cachePolicy.peek(key) == null )
241             {
242                cachePolicy.insert(key, session);
243                log.trace("Cached SRP session for user="+key);
244             }
245             else if( overwriteSessions )
246             {
247                cachePolicy.remove(key);
248                cachePolicy.insert(key, session);
249                log.trace("Replaced SRP session for user="+key);
250             }
251             else
252             {
253                log.debug("Ignoring SRP session due to existing session for user="+key);
254             }
255          }
256       }
257       catch(Exception JavaDoc e)
258       {
259          log.error("Failed to update SRP cache for user="+key, e);
260       }
261    }
262    public void closedUserSession(SRPSessionKey key)
263    {
264       try
265       {
266          synchronized( cachePolicy )
267          {
268             // We only insert a principal if there is no current entry.
269
if( cachePolicy.peek(key) == null )
270             {
271                log.warn("No SRP session found for user="+key);
272             }
273             cachePolicy.remove(key);
274          }
275       }
276       catch(Exception JavaDoc e)
277       {
278          log.error("Failed to update SRP cache for user="+key, e);
279       }
280    }
281
282    public String JavaDoc getName()
283    {
284       return "SRPService";
285    }
286
287    public Object JavaDoc invoke(Invocation invocation) throws Exception JavaDoc
288    {
289       // Set the method hash to Method mapping
290
if (invocation instanceof MarshalledInvocation)
291       {
292          MarshalledInvocation mi = (MarshalledInvocation) invocation;
293          mi.setMethodMap(marshalledInvocationMapping);
294       }
295       // Invoke the SRPRemoteServer method via reflection
296
Method JavaDoc method = invocation.getMethod();
297       Object JavaDoc[] args = invocation.getArguments();
298       Object JavaDoc value = null;
299       try
300       {
301          value = method.invoke(server, args);
302       }
303       catch(InvocationTargetException JavaDoc e)
304       {
305          Throwable JavaDoc t = e.getTargetException();
306          if( t instanceof Exception JavaDoc )
307             throw (Exception JavaDoc) t;
308          else
309             throw new UndeclaredThrowableException JavaDoc(t, method.toString());
310       }
311
312       return value;
313    }
314
315    protected void startService() throws Exception JavaDoc
316    {
317       loadStore();
318       server = new SRPRemoteServer(verifierStore, serverPort,
319       clientSocketFactory, serverSocketFactory);
320       server.addSRPServerListener(this);
321       server.setRequireAuxChallenge(this.requireAuxChallenge);
322
323       // Bind a proxy to the SRPRemoteServer into jndi
324
InitialContext JavaDoc ctx = new InitialContext JavaDoc();
325       if( serverJndiName != null && serverJndiName.length() > 0 )
326       {
327          SRPServerProxy proxyHandler = new SRPServerProxy(server);
328          ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
329          Class JavaDoc[] interfaces = {SRPServerInterface.class};
330          Object JavaDoc proxy = Proxy.newProxyInstance(loader, interfaces, proxyHandler);
331          org.jboss.naming.Util.rebind(ctx, serverJndiName, proxy);
332          log.debug("Bound SRPServerProxy at "+serverJndiName);
333       }
334
335       // First check for an existing CachePolicy binding
336
try
337       {
338          cachePolicy = (CachePolicy) ctx.lookup(cacheJndiName);
339          log.debug("Found AuthenticationCache at: "+cacheJndiName);
340       }
341       catch(Exception JavaDoc e)
342       {
343          log.trace("Failed to find existing cache at: "+cacheJndiName, e);
344          // Not found, default to a TimedCachePolicy
345
cachePolicy = new TimedCachePolicy(cacheTimeout, true, cacheResolution);
346          cachePolicy.create();
347          cachePolicy.start();
348          // Bind a reference to store using NonSerializableFactory as the ObjectFactory
349
Name JavaDoc name = ctx.getNameParser("").parse(cacheJndiName);
350          NonSerializableFactory.rebind(name, cachePolicy, true);
351          log.debug("Bound AuthenticationCache at "+cacheJndiName);
352       }
353
354       // Build the SRPRemoteServerInterface method map
355
HashMap JavaDoc tmpMap = new HashMap JavaDoc(13);
356       Method JavaDoc[] methods = SRPRemoteServerInterface.class.getMethods();
357       for(int m = 0; m < methods.length; m ++)
358       {
359          Method JavaDoc method = methods[m];
360          Long JavaDoc hash = new Long JavaDoc(MarshalledInvocation.calculateHash(method));
361          tmpMap.put(hash, method);
362       }
363       marshalledInvocationMapping = Collections.unmodifiableMap(tmpMap);
364    }
365
366    protected void stopService() throws Exception JavaDoc
367    {
368       // Bind a reference to store using NonSerializableFactory as the ObjectFactory
369
InitialContext JavaDoc ctx = new InitialContext JavaDoc();
370       ctx.unbind(serverJndiName);
371       log.debug("Unbound SRPServerProxy at "+serverJndiName);
372       NonSerializableFactory.unbind(cacheJndiName);
373       ctx.unbind(cacheJndiName);
374       log.debug("Unbound AuthenticationCache at "+cacheJndiName);
375    }
376
377    private void loadStore() throws NamingException JavaDoc
378    {
379       InitialContext JavaDoc ctx = new InitialContext JavaDoc();
380       // Get the SRPVerifierStore implementation
381
verifierStore = (SRPVerifierStore) ctx.lookup(verifierSourceJndiName);
382       if( server != null )
383       {
384          server.setVerifierStore(verifierStore);
385       }
386    }
387    
388 }
389
Popular Tags