/* **************************************************************************

  $Archive: /njcl_v2/src/com/novell/service/security/NdsIdentity.java $
  $Revision: 21 $
  $Modtime: 3/18/03 12:37p $

  Copyright (c) 1997-1998 Novell, Inc.  All Rights Reserved.

  THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL PROPRIETARY
  AND TRADE SECRET INFORMATION OF NOVELL, INC. ACCESS  TO  THIS  WORK IS
  RESTRICTED TO (I) NOVELL, INC.  EMPLOYEES WHO HAVE A NEED TO  KNOW HOW
  TO  PERFORM  TASKS WITHIN  THE SCOPE  OF  THEIR   ASSIGNMENTS AND (II)
  ENTITIES OTHER  THAN  NOVELL, INC.  WHO  HAVE ENTERED INTO APPROPRIATE
  LICENSE   AGREEMENTS.  NO  PART  OF  THIS WORK MAY BE USED, PRACTICED,
  PERFORMED COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED,  RECAST, TRANSFORMED
  OR ADAPTED  WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC.  ANY USE
  OR EXPLOITATION  OF  THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT THE
  PERPETRATOR  TO CRIMINAL AND CIVIL LIABILITY.

****************************************************************************/

package com.novell.service.security;

import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

import com.novell.java.security.Identity;
import com.novell.java.security.IdentityScope;
import com.novell.java.security.KeyManagementException;
import com.novell.java.security.PublicKey;
import com.novell.java.util.Debug;
import com.novell.service.session.SessionManager;

/**
 * Represents an authenticatable entity in NDS, such as a user, an
 * administrator, and so forth. Every NdsIdentity is associated with
 * an identity scope that is typically an NDS context. The NDS context
 * is in turn, associated with an NDS tree, which, is then associated
 * with the NDS administrative domain scope. The tree domain scope is
 * a child of the administrative domain scope. The context domain scope
 * is a child of the tree domain scope. There may be many context domain
 * scopes. A user identity is a child of the context domain scope.
 *
 * <p>For example, to construct a user named Karah in a subcontext called
 * Java in a context called Engineering in an NDS tree called KARAH_CORP
 * you can do the following:
 * <code>
 * <pre>
 * IdentityScope administrativeDomain  = new NdsIdentityScope();
 * IdentityScope tree                  = new NdsIdentityScope("KARAH_CORP",administrativeDomain);
 * IdentityScope context               = new NdsIdentityScope("Engineering",tree);
 * IdentityScope subcontext            = new NdsIdentityScope("Java",context);
 * Identity      user                  = new NdsIdentity("Karah",subcontext);
 * </pre>
 * </code>
 *
 * <p><b>Important:</b> If you are using NAS login capability (getUseNAS is 
 * TRUE), the name parameter cannot be fully-qualified.
 *
 * @see NdsIdentityScope
 * @see BinderyIdentity
 */
public class NdsIdentity extends XplatIdentity implements PasswordIdentityFactory
{
   //Set if you want to use the new extended characters in passwords support
   boolean useExtendedCharacterPasswords;
   
   //These 3 members are only used if the user wants the new NAS login.
   boolean useNAS;
   int nmasID;
   String authenticatedFDN;
   
   /**
	 * Construct an identity with the specified user name and no scope.
	 *
	 * @param name                The user name of the identity.
	 */
   public NdsIdentity (
         String name)
   {
      super (name);
	} // NDSIdentity ()

   /**
	 * Construct an identity with the specified user name and scope as Strings.
	 *
	 * @param name                The user name of the identity.
	 * @param scope               The scope of the identity (the domain).
    * @exception KeyManagementException When an error occurs.
	 */
   public NdsIdentity (
         String name,
         String scope)
      throws KeyManagementException
   {
      super (name, new NdsIdentityScope (scope));
	} // NDSIdentity ()

   /**
	 * Construct an identity with the specified user name as a String and scope
    * as an IdentityScope.
	 *
	 * @param name                The user name of the identity.
	 * @param scope               The scope of the identity (the domain).
    * @exception KeyManagementException When an error occurs.
	 */
   public NdsIdentity (
         String name,
         IdentityScope scope)
      throws KeyManagementException
   {
      super (name, scope);
	} // NDSIdentity ()

   /**
	 * Constructs an identity from another specified identity.
	 *
    * <p>The name and parent scope are copied from the existing identity.
    * If the identity is an XplatIdentity, the session and session manager are
    * also copied. If the identity is an NDS identity, its context handle is
    * also copied.
    * </p>
    *
	 * @param identity            The identity to copy.
    * @exception KeyManagementException When an error occurs.
	 */
	public NdsIdentity (
         Identity identity)
		throws KeyManagementException
	{
		super (identity);
      if (identity instanceof NdsIdentity)
      {
         setUseExtendedCharacterPasswords(((NdsIdentity)identity).getUseExtendedCharacterPasswords());
         setUseNAS(((NdsIdentity)identity).getUseNAS());
         setNMASID(((NdsIdentity)identity).getNMASID());
         setAuthenticatedFDN(((NdsIdentity)identity).getAuthenticatedFDN());
      }
	} // NDSIdentity ()

   // XplatIdentity methods ==================================================
   /**
	 * Get the administrative domain string.
	 *
	 * @return                    The administrative domain identifier,
    *                            "[NDS]".
	 */
   public String getAdministrativeDomain ()
   {
      return (NdsIdentityScope.ADMINISTRATIVE_DOMAIN_NAME);
   } // getAdministrativeDomain ()

   /**
	 * Return the user name.
	 *
	 * @return                    The String name of the user domain.
	 */
   public String getUsername ()
	{
      return (getUsername (this));
	}  // getUsername ()

   /**
	 * Returns the user domain as a String.
	 *
	 * @return                    The String containing the user domain.
	 */
   public String getUserDomain ()
   {
      return (getUserDomain (this));
   } // getUserDomain ()

   // PasswordIdentityFactory methods ========================================
   /**
    * Instantiate a password identity class.
    *
    * @return                    The appropriate PasswordIdentity.
    */
   public PasswordIdentity getPasswordIdentityInstance ()
   {
      try
      {
         return (new NdsPasswordIdentity (this));
      } catch (KeyManagementException e)
      {
         return (null);
      }
   } // getPasswordIdentityInstance ()

   // Helper methods =========================================================
   /**
	 * Parses the identity to create a user name string (static version).
	 *
	 * @param identity            The identity whose name is to be parsed.
	 * @return                    The user name string.
	 */
   static String getUsername (
         Identity identity)
   {
	   IdentityScope scope = identity.getScope ();
	   if (scope == null)
         return "";

      IdentityScope nextScope = scope.getScope ();
      if (nextScope == null)
      {
	      String name = scope.getName ();
	      if (name.equalsIgnoreCase (NdsIdentityScope.ADMINISTRATIVE_DOMAIN_NAME))
	         return "";
	      else
	         return identity.getName ();
      }

      IdentityScope nextNextScope = nextScope.getScope ();
      if (nextNextScope == null)
      {
	      String name = nextScope.getName ();
         if ((0 == scope.getName ().length ()) ||
             (name.equalsIgnoreCase(NdsIdentityScope.ADMINISTRATIVE_DOMAIN_NAME)))
	         return identity.getName ();
	      else
	         return identity.getName () + "." + scope.getName ();
      }

      return identity.getName () + "." + getUsername (scope);
   } // getUsername ()

   /**
	 * Parses an identity to create a user domain string.
	 *
	 * @param identity            The identity whose domain is to be parsed.
	 * @return                    The user domain String.
	 */
   static String getUserDomain (
         Identity identity)
   {
	   IdentityScope scope = identity.getScope ();
	   if (scope == null)
	   {
	      String name = identity.getName ();
	      if (name.equalsIgnoreCase (NdsIdentityScope.ADMINISTRATIVE_DOMAIN_NAME))
	         return "";
	      else
	         return name;
	   }

      IdentityScope nextScope = scope.getScope ();
      if (nextScope == null)
      {
	      String name = scope.getName ();
	      if(name.equalsIgnoreCase(NdsIdentityScope.ADMINISTRATIVE_DOMAIN_NAME))
	         return identity.getName();
	      else
	         return name;
      }
      // else recurse
      return getUserDomain(scope);
   } // getUserDomain ()

   public String toString()
   {
      StringBuffer ret = new StringBuffer(super.toString());
      ret.append(".  useNAS:" + getUseNAS() + ". nmasID:" + getNMASID() + ". authenticatedFDN:" + getAuthenticatedFDN() + 
         ". UseExtendedCharacterPasswords:" + getUseExtendedCharacterPasswords());
      return ret.toString();
   }

   //the following functions are if the user want to use the new extended character password support
   /**
    * Determines whether to use the new extended character password support.
    *
    * @return                    TRUE if the new extended character password support is used.
    */
   public boolean getUseExtendedCharacterPasswords()
   {
      return useExtendedCharacterPasswords;
   }
   
   /**
    * Sets whether to use the new extended character password support.
    *
    * @param useExtendedCharacterPassword
    */
   public void setUseExtendedCharacterPasswords(boolean useExtendedCharacterPassword)
   {
      this.useExtendedCharacterPasswords = useExtendedCharacterPassword;
   }

   //the following functions are if the user want to use the new NAS login
   /**
    * Determines whether Network Attached Storage (NAS) login capability is being used.
    *
    * @return                    TRUE if NAS login capability is being used.
    */
   public boolean getUseNAS()
   {
      return useNAS;
   }
   
   /**
    * Turns NAS authentication on or off. For NAS boxes only.
    *
    * @param useNAS   TRUE to turn on NAS authentication; FALSE to turn it off.
    */
   public void setUseNAS(boolean useNAS)
   {
      this.useNAS = useNAS;
   }

   /**
    * Gets the NMAS ID of an object when NAS is in use. This is only valid when 
    * getUseNAS is TRUE. For more about NMAS, see 
    * <a href="../../../../../../../nmas/nmas_enu/data/a30l2t8.html">NMAS documentation</a>.
    *
    * @return    The NMAS ID.
    */
   public int getNMASID()
   {
      return nmasID;
   }

   /**
    * @exclude
    *
    * Sets the NMAS ID of an object. Typically done by the constructor.
    *
    * @param     The NMAS ID.
    */
   public void setNMASID(int id)
   {
      nmasID = id;
   }

   /**
    * Gets the fully distinguished name of an object when NAS is in use. This is only valid
    * when getUseNAS is TRUE.
    *
    * @return      The DN of the object.
    */
   public String getAuthenticatedFDN()
   {
      return authenticatedFDN;
   }

   /**
    * @exclude
    *
    * Sets the fully distinguished name of an object. Typically done by the constructor.
    *
    * @param                    The DN.
    */
   public void setAuthenticatedFDN(String authFDN)
   {
      authenticatedFDN = authFDN;
   }
} // class NdsIdentity
