All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.novell.sasl.client.ExternalSaslClient Maven / Gradle / Ivy

/* **************************************************************************
 * $OpenLDAP$
 *
 * Copyright (C) 2002 Novell, Inc. All Rights Reserved.
 *
 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
 * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
 * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
 * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
 * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
 * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
 * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
 * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
 ******************************************************************************/
package com.novell.sasl.client;

import com.novell.security.sasl.*;
import javax.security.auth.callback.*;
import java.security.SecureRandom;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.util.*;
/**
 * Implements the ExternalSaslClient mechanism.
 */
class ExternalSaslClient extends Object implements SaslClient
{
    private String           m_authorizationId = "";
    private String           m_protocol = "";
    private String           m_serverName = "";
    private Map              m_props;
    private CallbackHandler  m_cbh;
    private int              m_state;

    private static final int   STATE_INITIAL = 0;
    private static final int   STATE_VALID_SERVER_RESPONSE = 1;
    private static final int   STATE_INVALID_SERVER_RESPONSE = 2;
    private static final int   STATE_DISPOSED = 3;

    /**
     * Creates an ExternalSaslClient object using the parameters supplied.
     * Assumes that the QOP, STRENGTH, and SERVER_AUTH properties are
     * contained in props
     *
     * @param authorizationId  The possibly null protocol-dependent
     *                     identification to be used for authorization. If
     *                     null or empty, the server derives an authorization
     *                     ID from the client's authentication credentials.
     *                     When the SASL authentication completes
     *                     successfully, the specified entity is granted
     *                     access.
     *
     * @param protocol     The non-null string name of the protocol for which
     *                     the authentication is being performed (e.g. "ldap")
     *
     * @param serverName   The non-null fully qualified host name of the server
     *                     to authenticate to
     *
     * @param props        The possibly null set of properties used to select
     *                     the SASL mechanism and to configure the
     *                     authentication exchange of the selected mechanism.
     *                     See the Sasl class for a list of standard properties.
     *                     Other, possibly mechanism-specific, properties can
     *                     be included. Properties not relevant to the selected
     *                     mechanism are ignored.
     *
     * @param cbh          The possibly null callback handler to used by the
     *                     SASL mechanisms to get further information from the
     *                     application/library to complete the authentication.
     *                     For example, a SASL mechanism might require the
     *                     authentication ID, password and realm from the
     *                     caller. The authentication ID is requested by using
     *                     a NameCallback. The password is requested by using
     *                     a PasswordCallback. The realm is requested by using
     *                     a RealmChoiceCallback if there is a list of realms
     *                     to choose from, and by using a RealmCallback if the
     *                     realm must be entered.
     *
     * @return            A possibly null SaslClient created using the
     *                     parameters supplied. If null, this factory cannot
     *                     produce a SaslClient using the parameters supplied.
     *
     * @exception SaslException  If a SaslClient instance cannot be created
     *                     because of an error
     */
    public static SaslClient getClient(
        String          authorizationId,
        String          protocol,
        String          serverName,
        Map             props,
        CallbackHandler cbh)
    {
        return new ExternalSaslClient(authorizationId, protocol,
                                       serverName, props, cbh);
    }

    /**
     * Creates an ExternalSaslClient object using the parameters supplied.
     * Assumes that the QOP, STRENGTH, and SERVER_AUTH properties are
     * contained in props
     *
     * @param authorizationId  The possibly null protocol-dependent
     *                     identification to be used for authorization. If
     *                     null or empty, the server derives an authorization
     *                     ID from the client's authentication credentials.
     *                     When the SASL authentication completes
     *                     successfully, the specified entity is granted
     *                     access.
     *
     * @param protocol     The non-null string name of the protocol for which
     *                     the authentication is being performed (e.g. "ldap")
     *
     * @param serverName   The non-null fully qualified host name of the server
     *                     to authenticate to
     *
     * @param props        The possibly null set of properties used to select
     *                     the SASL mechanism and to configure the
     *                     authentication exchange of the selected mechanism.
     *                     See the Sasl class for a list of standard properties.
     *                     Other, possibly mechanism-specific, properties can
     *                     be included. Properties not relevant to the selected
     *                     mechanism are ignored.
     *
     * @param cbh          The possibly null callback handler to used by the
     *                     SASL mechanisms to get further information from the
     *                     application/library to complete the authentication.
     *                     For example, a SASL mechanism might require the
     *                     authentication ID, password and realm from the
     *                     caller. The authentication ID is requested by using
     *                     a NameCallback. The password is requested by using
     *                     a PasswordCallback. The realm is requested by using
     *                     a RealmChoiceCallback if there is a list of realms
     *                     to choose from, and by using a RealmCallback if the
     *                     realm must be entered.
     *
     */
    private  ExternalSaslClient(
        String          authorizationId,
        String          protocol,
        String          serverName,
        Map             props,
        CallbackHandler cbh)
    {
        m_authorizationId = authorizationId;
        m_protocol = protocol;
        m_serverName = serverName;
        m_props = props;
        m_cbh = cbh;

        m_state = STATE_INITIAL;
    }

    /**
     * Determines if this mechanism has an optional initial response. If true,
     * caller should call evaluateChallenge() with an empty array to get the
     * initial response.
     *
     * @return  true if this mechanism has an initial response
     */
    public boolean hasInitialResponse()
    {
        return false;
    }

    /**
     * Determines if the authentication exchange has completed. This method
     * may be called at any time, but typically, it will not be called until
     * the caller has received indication from the server (in a protocol-
     * specific manner) that the exchange has completed.
     *
     * @return  true if the authentication exchange has completed;
     *           false otherwise.
     */
    public boolean isComplete()
    {
        if ((m_state == STATE_VALID_SERVER_RESPONSE) ||
            (m_state == STATE_INVALID_SERVER_RESPONSE) ||
            (m_state == STATE_DISPOSED))
            return true;
        else
            return false;
    }

   /**
    * Unwraps a byte array received from the server. This method can be called
    * only after the authentication exchange has completed (i.e., when
    * isComplete() returns true) and only if the authentication exchange has
    * negotiated integrity and/or privacy as the quality of protection;
    * otherwise, an IllegalStateException is thrown.
    *
    * incoming is the contents of the SASL buffer as defined in RFC 2222
    * without the leading four octet field that represents the length.
    * offset and len specify the portion of incoming to use.
    *
    * @param incoming   A non-null byte array containing the encoded bytes
    *                   from the server
    * @param offset     The starting position at incoming of the bytes to use
    *
    * @param len        The number of bytes from incoming to use
    *
    * @return           A non-null byte array containing the decoded bytes
    *
    */
    public byte[] unwrap(
        byte[] incoming,
        int    offset,
        int    len)
            throws SaslException
    {
        throw new IllegalStateException(
         "unwrap: QOP has neither integrity nor privacy>");
    }

   /**
    * Wraps a byte array to be sent to the server. This method can be called
    * only after the authentication exchange has completed (i.e., when
    * isComplete() returns true) and only if the authentication exchange has
    * negotiated integrity and/or privacy as the quality of protection;
    * otherwise, an IllegalStateException is thrown.
    *
    * The result of this method will make up the contents of the SASL buffer as
    * defined in RFC 2222 without the leading four octet field that represents
    * the length. offset and len specify the portion of outgoing to use.
    *
    * @param outgoing   A non-null byte array containing the bytes to encode
    * @param offset     The starting position at outgoing of the bytes to use
    * @param len        The number of bytes from outgoing to use
    *
    * @return A non-null byte array containing the encoded bytes
    *
    * @exception SaslException  if incoming cannot be successfully unwrapped.
    *
    * @exception IllegalStateException   if the authentication exchange has
    *                   not completed, or if the negotiated quality of
    *                   protection has neither integrity nor privacy.
    */
    public byte[] wrap(
        byte[]  outgoing,
        int     offset,
        int     len)
            throws SaslException
    {
        throw new IllegalStateException(
         "wrap: QOP has neither integrity nor privacy>");
    }

    /**
    * Retrieves the negotiated property. This method can be called only after
    * the authentication exchange has completed (i.e., when isComplete()
    * returns true); otherwise, an IllegalStateException is thrown.
    *
    * @param propName   The non-null property name
    *
    * @return  The value of the negotiated property. If null, the property was
    *          not negotiated or is not applicable to this mechanism.
    *
    * @exception IllegalStateException   if this authentication exchange has
    *                                    not completed
    */
    public Object getNegotiatedProperty(
        String propName)
    {
        if (m_state != STATE_VALID_SERVER_RESPONSE)
            throw new IllegalStateException(
             "getNegotiatedProperty: authentication exchange not complete.");

        if (Sasl.QOP.equals(propName))
            return "auth";
        else
            return null;
    }

    /**
     * Disposes of any system resources or security-sensitive information the
     * SaslClient might be using. Invoking this method invalidates the
     * SaslClient instance. This method is idempotent.
     *
     * @exception SaslException - if a problem was encountered while disposing of the resources
     */
    public void dispose()
            throws SaslException
    {
        if (m_state != STATE_DISPOSED)
        {
            m_state = STATE_DISPOSED;
        }
    }

    /**
     * Evaluates the challenge data and generates a response. If a challenge
     * is received from the server during the authentication process, this
     * method is called to prepare an appropriate next response to submit to
     * the server.
     *
     * @param challenge  The non-null challenge sent from the server. The
     *                   challenge array may have zero length.
     *
     * @return    The possibly null reponse to send to the server. It is null
     *            if the challenge accompanied a "SUCCESS" status and the
     *            challenge only contains data for the client to update its
     *            state and no response needs to be sent to the server.
     *            The response is a zero-length byte array if the client is to
     *            send a response with no data.
     *
     * @exception SaslException   If an error occurred while processing the
     *                            challenge or generating a response.
     */
    public byte[] evaluateChallenge(
        byte[] challenge)
            throws SaslException
    {
        byte[] response = null;

        switch (m_state)
        {
        case STATE_INITIAL:
            if (challenge.length != 0)
            {
                m_state = STATE_INVALID_SERVER_RESPONSE;
                throw new SaslException("Unexpected non-zero length response.");
            }
            else
                m_state = STATE_VALID_SERVER_RESPONSE;
            break;
        case STATE_INVALID_SERVER_RESPONSE:
            throw new SaslException("Authentication sequence is complete");
        case STATE_DISPOSED:
            throw new SaslException("Client has been disposed");
        default:
            throw new SaslException("Unknown client state.");
        }

        return response;
    }

    /**
    * Returns the IANA-registered mechanism name of this SASL client.
    *  (e.g. "CRAM-MD5", "GSSAPI")

    * @return  "DIGEST-MD5"the IANA-registered mechanism name of this SASL client.
    */
    public String getMechanismName()
    {
        return "EXTERNAL";
    }

} //end class ExternalSaslClient





© 2015 - 2024 Weber Informatics LLC | Privacy Policy