KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.IOException JavaDoc;
25 import java.rmi.RemoteException JavaDoc;
26 import java.rmi.server.RMIClientSocketFactory JavaDoc;
27 import java.rmi.server.RMIServerSocketFactory JavaDoc;
28 import java.rmi.server.UnicastRemoteObject JavaDoc;
29 import java.security.GeneralSecurityException JavaDoc;
30 import java.security.KeyException JavaDoc;
31 import java.security.NoSuchAlgorithmException JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.Map JavaDoc;
35 import javax.crypto.SealedObject;
36
37 import org.jboss.logging.Logger;
38 import org.jboss.security.Util;
39 import org.jboss.security.srp.SRPVerifierStore.VerifierInfo;
40
41 /** An implementation of the RMI SRPRemoteServerInterface interface.
42
43  @author Scott.Stark@jboss.org
44  @version $Revision: 40096 $
45  */

46 public class SRPRemoteServer extends UnicastRemoteObject JavaDoc implements SRPRemoteServerInterface
47 {
48    private static Logger log = Logger.getLogger(SRPRemoteServer.class);
49    /** The counter used to unique user sessions */
50    private static int userSessionCount = 0;
51    /** A map of <SRPSessionKey, SRPServerSession> for the active sessions */
52    private Map JavaDoc sessionMap = Collections.synchronizedMap(new HashMap JavaDoc());
53
54    /** The store implementation providing the SRP VerifierInfo */
55    private SRPVerifierStore verifierStore;
56    /** The callback interface for SRP session events. */
57    private SRPServerListener listener;
58    /** A flag indicating if the client must supply an aux challenge */
59    private boolean requireAuxChallenge;
60
61    public SRPRemoteServer(SRPVerifierStore verifierStore) throws RemoteException JavaDoc
62    {
63       setVerifierStore(verifierStore);
64    }
65
66    public SRPRemoteServer(SRPVerifierStore verifierStore, int port) throws RemoteException JavaDoc
67    {
68       super(port);
69       setVerifierStore(verifierStore);
70    }
71
72    public SRPRemoteServer(SRPVerifierStore verifierStore, int port, RMIClientSocketFactory JavaDoc csf,
73          RMIServerSocketFactory JavaDoc ssf) throws RemoteException JavaDoc
74    {
75       super(port, csf, ssf);
76       setVerifierStore(verifierStore);
77    }
78
79    /**
80     */

81    public void setVerifierStore(SRPVerifierStore verifierStore)
82    {
83       this.verifierStore = verifierStore;
84       log.info("setVerifierStore, " + verifierStore);
85    }
86
87    public void addSRPServerListener(SRPServerListener listener)
88    {
89       this.listener = listener;
90    }
91
92    public void removeSRPServerListener(SRPServerListener listener)
93    {
94       if (this.listener == listener)
95          this.listener = null;
96    }
97
98    public boolean getRequireAuxChallenge()
99    {
100       return this.requireAuxChallenge;
101    }
102    public void setRequireAuxChallenge(boolean flag)
103    {
104       this.requireAuxChallenge = flag;
105    }
106
107    /** The start of a new client session.
108     */

109    public SRPParameters getSRPParameters(String JavaDoc username)
110          throws KeyException JavaDoc, RemoteException JavaDoc
111    {
112       Object JavaDoc[] params = this.getSRPParameters(username,false);
113       SRPParameters srpParams = (SRPParameters) params[0];
114       return srpParams;
115    }
116
117    public Object JavaDoc[] getSRPParameters(String JavaDoc username, boolean multipleSessions)
118          throws KeyException JavaDoc, RemoteException JavaDoc
119    {
120       boolean trace = log.isTraceEnabled();
121       if( trace )
122          log.trace("getSRPParameters, " + username);
123       SRPParameters params = null;
124       VerifierInfo info = null;
125       try
126       {
127          info = verifierStore.getUserVerifier(username);
128          if (info == null)
129             throw new KeyException JavaDoc("Unknown username: " + username);
130          params = new SRPParameters(info.N, info.g, info.salt,
131             info.hashAlgorithm, info.cipherAlgorithm, info.cipherIV);
132          if (log.isTraceEnabled())
133          {
134             log.trace("Params: " + params);
135             byte[] hn = Util.newDigest().digest(params.N);
136             log.trace("H(N): " + Util.tob64(hn));
137             byte[] hg = Util.newDigest().digest(params.g);
138             log.trace("H(g): " + Util.tob64(hg));
139          }
140       }
141       catch (IOException JavaDoc e)
142       {
143          throw new RemoteException JavaDoc("Error during user info retrieval", e);
144       }
145       catch (KeyException JavaDoc e)
146       {
147          throw e;
148       }
149       catch (Throwable JavaDoc t)
150       {
151          log.error("Unexpected exception in getSRPParameters", t);
152          throw new RemoteException JavaDoc("Unexpected exception in getSRPParameters", t);
153       }
154
155       // Generate a session id if the user may run multiple sessions
156
Integer JavaDoc sessionID = SRPSessionKey.NO_SESSION_ID;
157       if( multipleSessions == true )
158          sessionID = nextSessionID();
159       Object JavaDoc[] sessionInfo = {params, sessionID};
160       // Create an SRP session
161
SRPSessionKey key = new SRPSessionKey(username, sessionID);
162       SRPServerSession session = new SRPServerSession(username, info.verifier,
163             params);
164       sessionMap.put(key, session);
165       if( trace )
166          log.trace("getSRPParameters, completed " + key);
167
168       return sessionInfo;
169    }
170
171    public byte[] init(String JavaDoc username, byte[] A) throws SecurityException JavaDoc,
172          NoSuchAlgorithmException JavaDoc, RemoteException JavaDoc
173    {
174       return this.init(username, A, 0);
175    }
176    public byte[] init(String JavaDoc username, byte[] A, int sessionID) throws SecurityException JavaDoc,
177          NoSuchAlgorithmException JavaDoc, RemoteException JavaDoc
178    {
179       SRPSessionKey key = new SRPSessionKey(username, sessionID);
180       boolean trace = log.isTraceEnabled();
181       if( trace )
182          log.trace("init, " + key);
183       SRPServerSession session = (SRPServerSession) sessionMap.get(key);
184       if (session == null)
185          throw new SecurityException JavaDoc("Failed to find active session for username: " + username);
186
187       byte[] B = session.exponential();
188       session.buildSessionKey(A);
189       if( trace )
190          log.trace("init, completed "+key);
191       return B;
192    }
193
194    public byte[] verify(String JavaDoc username, byte[] M1)
195          throws SecurityException JavaDoc, RemoteException JavaDoc
196    {
197       return this.verify(username, M1, null, 0);
198    }
199    public byte[] verify(String JavaDoc username, byte[] M1, int sessionID)
200          throws SecurityException JavaDoc, RemoteException JavaDoc
201    {
202       return this.verify(username, M1, null, sessionID);
203    }
204
205    /** Verify the session key hash. The client sends their username and M1
206     hash to validate completion of the SRP handshake.
207
208     @param username - the user ID by which the client is known. This is repeated to simplify
209     the server session management.
210     @param M1 - the client hash of the session key; M1 = H(H(N) xor H(g) | H(U) | A | B | K)
211     @param auxChallenge - an arbitrary addition data item that my be used as an additional
212     challenge. One example usage would be to send a hardware generated token that was encrypted
213     with the session private key for validation by the server.
214     @return M2, the server hash of the client challenge; M2 = H(A | M1 | K)
215     @throws SecurityException thrown if M1 cannot be verified by the server
216     @throws RemoteException thrown by remote implementations
217     */

218    public byte[] verify(String JavaDoc username, byte[] M1, Object JavaDoc auxChallenge)
219          throws SecurityException JavaDoc, RemoteException JavaDoc
220    {
221       return this.verify(username, M1, auxChallenge, 0);
222    }
223    public byte[] verify(String JavaDoc username, byte[] M1, Object JavaDoc auxChallenge, int sessionID)
224          throws SecurityException JavaDoc, RemoteException JavaDoc
225    {
226       SRPSessionKey key = new SRPSessionKey(username, sessionID);
227       boolean trace = log.isTraceEnabled();
228       if( trace )
229          log.trace("verify, " + key);
230       SRPServerSession session = (SRPServerSession) sessionMap.get(key);
231       if (session == null)
232          throw new SecurityException JavaDoc("Failed to find active session for username: " + username);
233
234       if (session.verify(M1) == false)
235          throw new SecurityException JavaDoc("Failed to verify M1");
236
237       /* If there is a auxChallenge have the verierStore verify the data
238       */

239       if( auxChallenge != null )
240       {
241          // See if this is an encrypted object
242
if( auxChallenge instanceof SealedObject )
243          {
244             if( trace )
245                log.trace("Decrypting sealed object");
246             SRPParameters params = session.getParameters();
247             Object JavaDoc challenge = null;
248             try
249             {
250                byte[] skey = session.getSessionKey();
251                Object JavaDoc tmpKey = Util.createSecretKey(params.cipherAlgorithm, skey);
252                challenge = Util.accessSealedObject(params.cipherAlgorithm, tmpKey,
253                   params.cipherIV, auxChallenge);
254             }
255             catch (GeneralSecurityException JavaDoc e)
256             {
257                throw new RemoteException JavaDoc("Failed to access SealedObject", e);
258             }
259             auxChallenge = challenge;
260          }
261          if( trace )
262             log.trace("Verifing aux challenge");
263          this.verifierStore.verifyUserChallenge(username, auxChallenge);
264       }
265       else if( requireAuxChallenge == true )
266       {
267          throw new RemoteException JavaDoc("A non-null auxChallenge is required for verification");
268       }
269
270       // Inform the listener the user has been validated
271
if (listener != null)
272          listener.verifiedUser(key, session);
273       if( trace )
274          log.trace("verify, completed " + key);
275
276       return session.getServerResponse();
277    }
278
279    /** Close the SRP session for the given username.
280     */

281    public void close(String JavaDoc username) throws SecurityException JavaDoc, RemoteException JavaDoc
282    {
283       this.close(username, 0);
284    }
285    public void close(String JavaDoc username, int sessionID) throws SecurityException JavaDoc, RemoteException JavaDoc
286    {
287       SRPSessionKey key = new SRPSessionKey(username, sessionID);
288       boolean trace = log.isTraceEnabled();
289       if( trace )
290          log.trace("close, " + key);
291       SRPServerSession session = (SRPServerSession) sessionMap.remove(key);
292       if (session == null)
293          throw new SecurityException JavaDoc("Failed to find active session for username: " + username);
294       if (listener != null)
295          listener.closedUserSession(key);
296       if( trace )
297          log.trace("close, completed " + key);
298    }
299
300    private static synchronized Integer JavaDoc nextSessionID()
301    {
302       return new Integer JavaDoc(userSessionCount ++);
303    }
304 }
305
Popular Tags