com.novell.sasl.client.ExternalSaslClient Maven / Gradle / Ivy
/* **************************************************************************
* $OpenLDAP: pkg/jldap/com/novell/sasl/client/ExternalSaslClient.java,v 1.3 2005/01/17 15:00:54 sunilk Exp $
*
* 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 - 2025 Weber Informatics LLC | Privacy Policy