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'
      };
  }