Package org.jasig.portal.security.provider

Source Code of org.jasig.portal.security.provider.ChainingSecurityContext$Entry

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a
* copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.jasig.portal.security.provider;

import java.io.Serializable;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Vector;

import org.jasig.portal.properties.PropertiesManager;
import org.jasig.portal.security.IAdditionalDescriptor;
import org.jasig.portal.security.IOpaqueCredentials;
import org.jasig.portal.security.IParentAwareSecurityContext;
import org.jasig.portal.security.IPrincipal;
import org.jasig.portal.security.ISecurityContext;
import org.jasig.portal.security.PortalSecurityException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* <p>This is the basic abstract class for all security contexts that should
* chain to children security contexts.</p>
*
* @author Andrew Newman, newman@yale.edu
* @version $Revision: 20532 $
* @author Don Fracapane (df7@columbia.edu)
* Added a new method named getSubContextNames() that returns an Enumeration of names
* for the subcontexts.
*/
public abstract class ChainingSecurityContext implements ISecurityContext
{
    protected final Log log = LogFactory.getLog(getClass());

  /**
   * Default value for stopWhenAuthenticated.
   * This value will be used when the corresponding property cannot be loaded.
   */
  private static final boolean DEFAULT_STOP_WHEN_AUTHENTICATED = true;
  protected static boolean stopWhenAuthenticated = PropertiesManager.getPropertyAsBoolean("org.jasig.portal.security.provider.ChainingSecurityContext.stopWhenAuthenticated", DEFAULT_STOP_WHEN_AUTHENTICATED);

  protected boolean isauth = false;
  protected Vector mySubContexts;
  protected ChainingPrincipal myPrincipal;
  protected ChainingOpaqueCredentials myOpaqueCredentials;
  protected IAdditionalDescriptor myAdditionalDescriptor;
  protected Comparator myOrder;

  public ChainingSecurityContext() {
    myPrincipal = new ChainingPrincipal();
    myOpaqueCredentials = new ChainingOpaqueCredentials();
    myAdditionalDescriptor = new ChainingAdditionalDescriptor();
    mySubContexts = new Vector();
  }

  public IPrincipal getPrincipalInstance() {
    if (this.isauth)
      return new ChainingPrincipal();
    else
      return this.myPrincipal;
  }

  public IOpaqueCredentials getOpaqueCredentialsInstance() {
    if (this.isauth)
      return new ChainingOpaqueCredentials();
    else
      return this.myOpaqueCredentials;
  }

  /**
   * We walk the chain of subcontext assigning principals and opaquecredentials
   * from the parent. Note that the contexts themselves should resist
   * actually performing the assignment if an assignment has already been made
   * to either the credentials or the UID.
   */

  public synchronized void authenticate()  throws PortalSecurityException {
    int i;
    Enumeration e = mySubContexts.elements();
    boolean error = false;

    while (e.hasMoreElements()) {
      ISecurityContext sctx = ((Entry) e.nextElement()).getCtx();
      // The principal and credential are now set for all subcontexts in Authentication
      try {
          if (sctx instanceof IParentAwareSecurityContext) {
              ((IParentAwareSecurityContext) sctx).authenticate(this);
          } else {
              sctx.authenticate();
          }       
      } catch (Exception ex) {
        error = true;
        log.error("Exception authenticating subcontext " + sctx, ex);
      }
      // Stop attempting to authenticate if authenticated and if the property flag is set
      if(stopWhenAuthenticated && sctx.isAuthenticated()) {
        break;
      }
    }

    // Zero out the actual credentials if it isn't already null
    if (this.myOpaqueCredentials.credentialstring != null){
       for (i = 0; i < this.myOpaqueCredentials.credentialstring.length; i++)
         this.myOpaqueCredentials.credentialstring[i] = 0;
       myOpaqueCredentials.credentialstring = null;
    }
    if (error && !this.isauth) throw new PortalSecurityException("One of the security subcontexts threw an exception");
    return;
  }

  public IPrincipal getPrincipal() {
    if (this.isauth)
      return this.myPrincipal;
    else
      return null;
  }

  public IOpaqueCredentials getOpaqueCredentials() {
    if (this.isauth)
      return this.myOpaqueCredentials;
    else
      return null;
  }

  public IAdditionalDescriptor getAdditionalDescriptor() {
    if (this.isauth)
      return this.myAdditionalDescriptor;
    else
      return null;
  }

  public boolean isAuthenticated() {
    return this.isauth;
  }

  public synchronized ISecurityContext getSubContext(String name) {
    for (int i = 0; i < mySubContexts.size(); i++)
    {
      Entry entry = (Entry) mySubContexts.get(i);
      if (entry.getKey() != null && entry.getKey().equals(name))
      {
        return(entry.getCtx());
      }
    }
    PortalSecurityException ep = new PortalSecurityException("No such subcontext: " + name);
    if (log.isDebugEnabled())
        log.debug("No such subcontext as " + name, ep);
    return(null);
  }

  public synchronized boolean doesSubContextExist(String name) {
    for (int i = 0; i < mySubContexts.size(); i++)
    {
      Entry entry = (Entry)mySubContexts.get(i);
      if (entry.getKey() != null && entry.getKey().equals(name))
      {
        return(true);
      }
    }
    return(false);
  }

  // Return an enumeration of subcontexts by running the vector and
  // creating the enumeration.  All this so the subcontexts will
  // be returned in the order they appeared in the properties file.
  public synchronized Enumeration getSubContexts() {
    Enumeration e = mySubContexts.elements();
    class Adapter implements Enumeration {
        Enumeration base;
        public Adapter(Enumeration e) {
            this.base = e;
        }
        public boolean hasMoreElements() {
           return base.hasMoreElements();
        }
        public Object nextElement() {
           return ((Entry) base.nextElement()).getCtx();
        }
    }
    return new Adapter(e);
  }

  public synchronized void addSubContext(String name, ISecurityContext ctx)
    throws PortalSecurityException {
    // Make sure the subcontext does not already exist in the chain
    if(doesSubContextExist(name))
    {
      PortalSecurityException ep = new PortalSecurityException("Subcontext already exists: " + name);
      log.error("Subcontext already exists:" + name, ep);
      throw(ep);
    }
    else
    {
      mySubContexts.add(new Entry(name, ctx));
    }
  }


  // I 'spose the public class could just implement all of these interfaces
  // but I prefer member classes. -ADN

  protected class ChainingPrincipal implements IPrincipal {
    protected String globalUID;
    protected String UID;
    protected String FullName;

    /**
     * Original, no-arg constructor used by the <code>ChainingSecurityContext</code>.
     *
     */
    public ChainingPrincipal() {}

    /**
     * Creates a new <code>ChainingPrincipal</code> from the specified <code>IPrincipal</code>.
     *
     */
    public ChainingPrincipal(IPrincipal p) {
        this.globalUID = p.getGlobalUID();
        this.UID = p.getUID();
        this.FullName = p.getFullName();
    }

    public String getUID() {
      return this.UID;
    }

    public String getGlobalUID() {
      return this.globalUID;
    }

    // This is supposed to be the person's "human readable" name. We should
    // probably do an account lookup at the very least to return this.

    public String getFullName() {
      return this.FullName;
    }

    public void setUID(String UID) {
      if (this.UID == null)
        this.UID = UID;
    }

    public void setFullName(String FullName) {
      if(this.FullName == null)
         this.FullName = FullName;
    }


  }

  protected class ChainingOpaqueCredentials implements IOpaqueCredentials {

    public byte[] credentialstring;

    // Since we want to explicitly zero our credentials after authenticate,
    // copy the credentials here in case a sub-authenticator doesn't want
    // to perform the operation immediately.

    public void setCredentials(byte[] credentials) {
      int i;

      if (this.credentialstring == null) {
        this.credentialstring = new byte[credentials.length];
        for (i = 0; i < credentials.length; i++)
          this.credentialstring[i] = credentials[i];
      }
    }

    public void setCredentials(String credentials) {
      if (this.credentialstring == null && credentials!=null)
        setCredentials(credentials.getBytes());
    }
  }

  // Returns an Enumeration of the names of the subcontexts.
  public synchronized Enumeration getSubContextNames() {
   Vector scNames = new Vector();
   for (int i = 0; i < mySubContexts.size(); i++)
   {
      Entry entry = (Entry) mySubContexts.get(i);
      if (entry.getKey() != null){
         scNames.add(entry.getKey());
       }
   }
   return scNames.elements();
  }


  /**
   * A default, placeholder implementation of IAdditionalDescriptor an instance of which
   * is the default value for the instance variable "myAdditionalDescriptor" of instances of
   * this class.
   */
  public class ChainingAdditionalDescriptor implements IAdditionalDescriptor {
      // do nothing
  }

// entries in our subcontext list
  private static class Entry implements Serializable {
    String key;
    ISecurityContext ctx;
    public Entry(String key, ISecurityContext ctx) {
        this.key = key;
        this.ctx = ctx;
    }
    public ISecurityContext getCtx() {
        return this.ctx;
    }
    public String getKey() {
        return this.key;
    }
  }
}
TOP

Related Classes of org.jasig.portal.security.provider.ChainingSecurityContext$Entry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.