You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ad...@apache.org on 2004/02/17 05:30:29 UTC
cvs commit: incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas LoginModuleId.java LocalLoginModule.java LoginModuleCacheObject.java LoginService.java LoginServiceMBean.java RemoteLoginModuleLocalWrapper.java
adc 2004/02/16 20:30:29
Modified: modules/security/src/java/org/apache/geronimo/security/jaas
LocalLoginModule.java LoginModuleCacheObject.java
LoginService.java LoginServiceMBean.java
RemoteLoginModuleLocalWrapper.java
Added: modules/security/src/java/org/apache/geronimo/security/jaas
LoginModuleId.java
Log:
Hashed login module ids should prevent spoofing of ids from naughty
clients.
Revision Changes Path
1.2 +2 -2 incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LocalLoginModule.java
Index: LocalLoginModule.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LocalLoginModule.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- LocalLoginModule.java 17 Feb 2004 00:05:39 -0000 1.1
+++ LocalLoginModule.java 17 Feb 2004 04:30:29 -0000 1.2
@@ -86,7 +86,7 @@
private String kernelName;
private Subject internalSubject = new Subject();
private Subject externalSubject;
- private Long loginModuleId;
+ private LoginModuleId loginModuleId;
LoginServiceMBean loginService;
private CallbackHandler callbackHandler;
1.2 +4 -4 incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleCacheObject.java
Index: LoginModuleCacheObject.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleCacheObject.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- LoginModuleCacheObject.java 17 Feb 2004 00:05:39 -0000 1.1
+++ LoginModuleCacheObject.java 17 Feb 2004 04:30:29 -0000 1.2
@@ -65,7 +65,7 @@
*/
class LoginModuleCacheObject {
- private final Long loginModuleId;
+ private final LoginModuleId loginModuleId;
private String realmName;
private Subject subject;
private LoginModule loginModule;
@@ -73,13 +73,13 @@
private long created;
private boolean done;
- LoginModuleCacheObject(Long loginModuleId) {
+ LoginModuleCacheObject(LoginModuleId loginModuleId) {
this.loginModuleId = loginModuleId;
this.created = System.currentTimeMillis();
this.done = false;
}
- Long getLoginModuleId() {
+ LoginModuleId getLoginModuleId() {
return loginModuleId;
}
1.2 +56 -34 incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LoginService.java
Index: LoginService.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LoginService.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- LoginService.java 17 Feb 2004 00:05:39 -0000 1.1
+++ LoginService.java 17 Feb 2004 04:30:29 -0000 1.2
@@ -70,6 +70,8 @@
import java.io.IOException;
import java.security.AccessController;
import java.security.Principal;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidKeyException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -131,7 +133,7 @@
private Collection loginModules = Collections.EMPTY_SET;
private final static ClassLoader classLoader;
- private Mac mac;
+ private SecretKey key;
private String algorithm;
private String password;
@@ -230,7 +232,7 @@
return null;
}
- public Long allocateLoginModule(String realmName) {
+ public LoginModuleId allocateLoginModule(String realmName) {
LoginModuleCacheObject lm = null;
synchronized (LoginService.class) {
@@ -270,7 +272,7 @@
return lm.getLoginModuleId();
}
- public void removeLoginModule(Long loginModuleId) throws ExpiredLoginModuleException {
+ public void removeLoginModule(LoginModuleId loginModuleId) throws ExpiredLoginModuleException {
LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) throw new ExpiredLoginModuleException();
@@ -278,7 +280,7 @@
log.trace("LoginModule [" + lm.getLoginModuleId() + "] marked done");
}
- public Collection getCallbacks(Long loginModuleId) throws ExpiredLoginModuleException {
+ public Collection getCallbacks(LoginModuleId loginModuleId) throws ExpiredLoginModuleException {
LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) throw new ExpiredLoginModuleException();
@@ -322,7 +324,7 @@
}
}
- public boolean login(Long loginModuleId, Collection callbacks) throws LoginException {
+ public boolean login(LoginModuleId loginModuleId, Collection callbacks) throws LoginException {
LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) throw new ExpiredLoginModuleException();
@@ -334,7 +336,7 @@
return module.login();
}
- public boolean commit(Long loginModuleId) throws LoginException {
+ public boolean commit(LoginModuleId loginModuleId) throws LoginException {
LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) throw new ExpiredLoginModuleException();
@@ -355,20 +357,12 @@
Long id = ContextManager.getSubjectId(lm.getSubject());
- long n = id.longValue();
- byte[] bytes = new byte[8];
- for (int i = 7; i >= 0; i--) {
- bytes[i] = (byte) (n);
- n >>>= 8;
- }
- mac.update(bytes);
-
- subject.getPrincipals().add(new IdentificationPrincipal(id, mac.doFinal()));
+ subject.getPrincipals().add(new IdentificationPrincipal(id, hash(id)));
return true;
}
- public boolean abort(Long loginModuleId) throws LoginException {
+ public boolean abort(LoginModuleId loginModuleId) throws LoginException {
LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) throw new ExpiredLoginModuleException();
@@ -377,7 +371,7 @@
return module.abort();
}
- public boolean logout(Long loginModuleId) throws LoginException {
+ public boolean logout(LoginModuleId loginModuleId) throws LoginException {
LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) throw new ExpiredLoginModuleException();
@@ -388,26 +382,48 @@
return module.logout();
}
- public Subject retrieveSubject(Long loginModuleId) throws LoginException {
+ public Subject retrieveSubject(LoginModuleId loginModuleId) throws LoginException {
LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) throw new ExpiredLoginModuleException();
return lm.getSubject();
}
+ private byte[] hash(Long id) {
+ long n = id.longValue();
+ byte[] bytes = new byte[8];
+ for (int i = 7; i >= 0; i--) {
+ bytes[i] = (byte) (n);
+ n >>>= 8;
+ }
+
+ try {
+ Mac mac = Mac.getInstance(algorithm);
+ mac.init(key);
+ mac.update(bytes);
+
+ return mac.doFinal();
+ } catch (NoSuchAlgorithmException e) {
+ } catch (InvalidKeyException e) {
+ }
+ assert false : "Should never have reached here";
+ return null;
+ }
+
private static long nextLoginModuleId = System.currentTimeMillis();
private LoginModuleCacheObject allocateLoginModuleCacheObject(long maxAge) {
synchronized (loginCache) {
- Long key = new Long(nextLoginModuleId++);
+ Long id = new Long(nextLoginModuleId++);
+ LoginModuleId loginModuleId = new LoginModuleId(id, hash(id));
- LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(key);
+ LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
if (lm == null) {
- lm = new LoginModuleCacheObject(key);
+ lm = new LoginModuleCacheObject(loginModuleId);
- loginCache.put(key, lm);
+ loginCache.put(loginModuleId, lm);
- LoginModuleCacheMonitor cm = new LoginModuleCacheMonitor(key, lm, maxAge);
+ LoginModuleCacheMonitor cm = new LoginModuleCacheMonitor(loginModuleId, lm, maxAge);
cm.clockTicket = clockDaemon.executePeriodically(reclaimPeriod, cm, true);
}
return lm;
@@ -418,12 +434,12 @@
* This class periodically checks one login module.
*/
private class LoginModuleCacheMonitor implements Runnable {
- final Long key;
+ final LoginModuleId key;
final LoginModuleCacheObject loginModule;
Object clockTicket;
final long maxAge;
- LoginModuleCacheMonitor(Long key, LoginModuleCacheObject loginModule, long maxAge) {
+ LoginModuleCacheMonitor(LoginModuleId key, LoginModuleCacheObject loginModule, long maxAge) {
this.key = key;
this.loginModule = loginModule;
this.maxAge = maxAge;
@@ -445,8 +461,14 @@
}
public void doStart() throws WaitingException, Exception {
- SecretKey key = new SecretKeySpec(password.getBytes(), algorithm);
- mac = Mac.getInstance(algorithm);
+ key = new SecretKeySpec(password.getBytes(), algorithm);
+
+ /**
+ * Simple test to make sure that the algorithm and key are fine.
+ * This should stop the service from being started if there is a
+ * problem.
+ */
+ Mac mac = Mac.getInstance(algorithm);
mac.init(key);
log.info("Login server has been started");
@@ -475,12 +497,12 @@
GBeanInfoFactory infoFactory = new GBeanInfoFactory(LoginService.class.getName());
infoFactory.addOperation(new GOperationInfo("getAppConfigurationEntry", new String[]{String.class.getName()}));
infoFactory.addOperation(new GOperationInfo("allocateLoginModule", new String[]{String.class.getName()}));
- infoFactory.addOperation(new GOperationInfo("getCallbacks", new String[]{Long.class.getName()}));
- infoFactory.addOperation(new GOperationInfo("login", new String[]{Long.class.getName(), Collection.class.getName()}));
- infoFactory.addOperation(new GOperationInfo("commit", new String[]{Long.class.getName()}));
- infoFactory.addOperation(new GOperationInfo("abort", new String[]{Long.class.getName()}));
- infoFactory.addOperation(new GOperationInfo("logout", new String[]{Long.class.getName()}));
- infoFactory.addOperation(new GOperationInfo("retrieveSubject", new String[]{Long.class.getName()}));
+ infoFactory.addOperation(new GOperationInfo("getCallbacks", new String[]{LoginModuleId.class.getName()}));
+ infoFactory.addOperation(new GOperationInfo("login", new String[]{LoginModuleId.class.getName(), Collection.class.getName()}));
+ infoFactory.addOperation(new GOperationInfo("commit", new String[]{LoginModuleId.class.getName()}));
+ infoFactory.addOperation(new GOperationInfo("abort", new String[]{LoginModuleId.class.getName()}));
+ infoFactory.addOperation(new GOperationInfo("logout", new String[]{LoginModuleId.class.getName()}));
+ infoFactory.addOperation(new GOperationInfo("retrieveSubject", new String[]{LoginModuleId.class.getName()}));
infoFactory.addAttribute(new GAttributeInfo("Kernel", true));
infoFactory.addAttribute(new GAttributeInfo("ReclaimPeriod", true));
infoFactory.addAttribute(new GAttributeInfo("Algorithm", true));
1.2 +9 -9 incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LoginServiceMBean.java
Index: LoginServiceMBean.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LoginServiceMBean.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- LoginServiceMBean.java 17 Feb 2004 00:05:39 -0000 1.1
+++ LoginServiceMBean.java 17 Feb 2004 04:30:29 -0000 1.2
@@ -81,19 +81,19 @@
SerializableACE getAppConfigurationEntry(String realmName);
- Long allocateLoginModule(String realmName) throws LoginException;
+ LoginModuleId allocateLoginModule(String realmName) throws LoginException;
- void removeLoginModule(Long loginModuleId) throws ExpiredLoginModuleException;
+ void removeLoginModule(LoginModuleId loginModuleId) throws ExpiredLoginModuleException;
- Collection getCallbacks(Long loginModuleId) throws ExpiredLoginModuleException;
+ Collection getCallbacks(LoginModuleId loginModuleId) throws ExpiredLoginModuleException;
- boolean login(Long loginModuleId, Collection callbacks) throws LoginException;
+ boolean login(LoginModuleId loginModuleId, Collection callbacks) throws LoginException;
- boolean commit(Long loginModuleId) throws LoginException;
+ boolean commit(LoginModuleId loginModuleId) throws LoginException;
- boolean abort(Long loginModuleId) throws LoginException;
+ boolean abort(LoginModuleId loginModuleId) throws LoginException;
- boolean logout(Long loginModuleId) throws LoginException;
+ boolean logout(LoginModuleId loginModuleId) throws LoginException;
- Subject retrieveSubject(Long loginModuleId) throws LoginException;
+ Subject retrieveSubject(LoginModuleId loginModuleId) throws LoginException;
}
1.2 +2 -2 incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModuleLocalWrapper.java
Index: RemoteLoginModuleLocalWrapper.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModuleLocalWrapper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RemoteLoginModuleLocalWrapper.java 17 Feb 2004 00:05:39 -0000 1.1
+++ RemoteLoginModuleLocalWrapper.java 17 Feb 2004 04:30:29 -0000 1.2
@@ -80,7 +80,7 @@
*/
public class RemoteLoginModuleLocalWrapper implements LoginModule {
private String realmName;
- private Long loginModuleId;
+ private LoginModuleId loginModuleId;
private Subject internalSubject;
private Subject externalSubject;
private LoginServiceMBean remoteLoginService;
1.1 incubator-geronimo/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleId.java
Index: LoginModuleId.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2004 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Geronimo" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Geronimo", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* ====================================================================
*/
package org.apache.geronimo.security.jaas;
import java.io.Serializable;
/**
* @version $Revision: 1.1 $ $Date: 2004/02/17 04:30:29 $
*/
public class LoginModuleId implements Serializable {
private final Long loginModuleId;
private final byte[] hash;
private transient int hashCode;
private transient String name;
public LoginModuleId(Long loginModuleId, byte[] hash) {
this.loginModuleId = loginModuleId;
this.hash = hash;
}
public Long getLoginModuleId() {
return loginModuleId;
}
public byte[] getHash() {
return hash;
}
public boolean equals(Object obj) {
if (!(obj instanceof LoginModuleId)) return false;
LoginModuleId another = (LoginModuleId) obj;
if (!another.loginModuleId.equals(loginModuleId)) return false;
for (int i = 0; i < hash.length; i++) {
if (another.hash[i] != hash[i]) return false;
}
return true;
}
public String toString() {
if (name == null) {
StringBuffer buffer = new StringBuffer();
buffer.append('[');
buffer.append(loginModuleId);
buffer.append(":0x");
for (int i = 0; i < hash.length; i++) {
buffer.append(HEXCHAR[(hash[i]>>>4)&0x0F]);
buffer.append(HEXCHAR[(hash[i] )&0x0F]);
}
buffer.append(']');
name = buffer.toString();
}
return name;
}
/**
* Returns a hashcode for this LoginModuleId.
*
* @return a hashcode for this LoginModuleId.
*/
public int hashCode() {
if (hashCode == 0) {
for (int i = 0; i < hash.length; i++) {
hashCode ^= hash[i];
}
hashCode ^= loginModuleId.hashCode();
}
return hashCode;
}
private static final char[] HEXCHAR = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
}