responseOID.equals(OID_NOTICE_OF_DISCONNECTION))
{
Message message = ERR_LDAPAUTH_SERVER_DISCONNECT.
get(extendedResponse.getResultCode(),
extendedResponse.getErrorMessage());
throw new LDAPException(extendedResponse.getResultCode(), message);
}
else
{
Message message = ERR_LDAPAUTH_UNEXPECTED_EXTENDED_RESPONSE.get(
String.valueOf(extendedResponse));
throw new ClientException(LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR,
message);
}
default:
Message message = ERR_LDAPAUTH_UNEXPECTED_RESPONSE.get(
String.valueOf(responseMessage1.getProtocolOp()));
throw new ClientException(
LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR, message);
}
// Make sure that the bind response has the "SASL bind in progress" result
// code.
BindResponseProtocolOp bindResponse1 =
responseMessage1.getBindResponseProtocolOp();
int resultCode1 = bindResponse1.getResultCode();
if (resultCode1 != LDAPResultCode.SASL_BIND_IN_PROGRESS)
{
Message errorMessage = bindResponse1.getErrorMessage();
if (errorMessage == null)
{
errorMessage = Message.EMPTY;
}
Message message = ERR_LDAPAUTH_UNEXPECTED_INITIAL_BIND_RESPONSE.
get(SASL_MECHANISM_CRAM_MD5, resultCode1,
LDAPResultCode.toString(resultCode1), errorMessage);
throw new LDAPException(resultCode1, errorMessage, message,
bindResponse1.getMatchedDN(), null);
}
// Make sure that the bind response contains SASL credentials with the
// challenge to use for the next stage of the bind.
ByteString serverChallenge = bindResponse1.getServerSASLCredentials();
if (serverChallenge == null)
{
Message message = ERR_LDAPAUTH_NO_CRAMMD5_SERVER_CREDENTIALS.get();
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
// Use the provided password and credentials to generate the CRAM-MD5
// response.
StringBuilder buffer = new StringBuilder();
buffer.append(authID);
buffer.append(' ');
buffer.append(generateCRAMMD5Digest(bindPassword, serverChallenge));
// Create and send the second bind request to the server.
BindRequestProtocolOp bindRequest2 =
new BindRequestProtocolOp(bindDN.toByteString(),
SASL_MECHANISM_CRAM_MD5, ByteString.valueOf(buffer.toString()));
LDAPMessage requestMessage2 =
new LDAPMessage(nextMessageID.getAndIncrement(), bindRequest2,
requestControls);
try
{
writer.writeMessage(requestMessage2);
}
catch (IOException ioe)
{
Message message = ERR_LDAPAUTH_CANNOT_SEND_SECOND_SASL_BIND.get(
SASL_MECHANISM_CRAM_MD5, getExceptionMessage(ioe));
throw new ClientException(
LDAPResultCode.CLIENT_SIDE_SERVER_DOWN, message, ioe);
}
catch (Exception e)
{
Message message = ERR_LDAPAUTH_CANNOT_SEND_SECOND_SASL_BIND.get(
SASL_MECHANISM_CRAM_MD5, getExceptionMessage(e));
throw new ClientException(
LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR, message, e);
}
// Read the response from the server.
LDAPMessage responseMessage2;
try
{
responseMessage2 = reader.readMessage();
if (responseMessage2 == null)
{
Message message =
ERR_LDAPAUTH_CONNECTION_CLOSED_WITHOUT_BIND_RESPONSE.get();
throw new ClientException(LDAPResultCode.CLIENT_SIDE_SERVER_DOWN,
message);
}
}
catch (IOException ioe)
{
Message message = ERR_LDAPAUTH_CANNOT_READ_SECOND_BIND_RESPONSE.get(
SASL_MECHANISM_CRAM_MD5, getExceptionMessage(ioe));
throw new ClientException(
LDAPResultCode.CLIENT_SIDE_SERVER_DOWN, message, ioe);
}
catch (ASN1Exception ae)
{
Message message = ERR_LDAPAUTH_CANNOT_READ_SECOND_BIND_RESPONSE.get(
SASL_MECHANISM_CRAM_MD5, getExceptionMessage(ae));
throw new ClientException(LDAPResultCode.CLIENT_SIDE_DECODING_ERROR,
message, ae);
}
catch (LDAPException le)
{
Message message = ERR_LDAPAUTH_CANNOT_READ_SECOND_BIND_RESPONSE.get(
SASL_MECHANISM_CRAM_MD5, getExceptionMessage(le));
throw new ClientException(LDAPResultCode.CLIENT_SIDE_DECODING_ERROR,
message, le);
}
catch (Exception e)
{
Message message = ERR_LDAPAUTH_CANNOT_READ_SECOND_BIND_RESPONSE.get(
SASL_MECHANISM_CRAM_MD5, getExceptionMessage(e));
throw new ClientException(
LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR, message, e);
}
// See if there are any controls in the response. If so, then add them to
// the response controls list.
List<Control> respControls = responseMessage2.getControls();
if ((respControls != null) && (! respControls.isEmpty()))
{
responseControls.addAll(respControls);
}
// Look at the protocol op from the response. If it's a bind response, then
// continue. If it's an extended response, then it could be a notice of
// disconnection so check for that. Otherwise, generate an error.
switch (responseMessage2.getProtocolOpType())
{
case OP_TYPE_BIND_RESPONSE:
// We'll deal with this later.
break;
case OP_TYPE_EXTENDED_RESPONSE:
ExtendedResponseProtocolOp extendedResponse =
responseMessage2.getExtendedResponseProtocolOp();
String responseOID = extendedResponse.getOID();
if ((responseOID != null) &&
responseOID.equals(OID_NOTICE_OF_DISCONNECTION))
{
Message message = ERR_LDAPAUTH_SERVER_DISCONNECT.
get(extendedResponse.getResultCode(),
extendedResponse.getErrorMessage());
throw new LDAPException(extendedResponse.getResultCode(), message);
}
else
{
Message message = ERR_LDAPAUTH_UNEXPECTED_EXTENDED_RESPONSE.get(
String.valueOf(extendedResponse));
throw new ClientException(LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR,
message);
}
default:
Message message = ERR_LDAPAUTH_UNEXPECTED_RESPONSE.get(
String.valueOf(responseMessage2.getProtocolOp()));
throw new ClientException(
LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR, message);
}
BindResponseProtocolOp bindResponse2 =
responseMessage2.getBindResponseProtocolOp();
int resultCode2 = bindResponse2.getResultCode();
if (resultCode2 == LDAPResultCode.SUCCESS)
{
// FIXME -- Need to look for things like password expiration warning,
// reset notice, etc.
return null;
}
// FIXME -- Add support for referrals.
Message message =
ERR_LDAPAUTH_SASL_BIND_FAILED.get(SASL_MECHANISM_CRAM_MD5);
throw new LDAPException(resultCode2, bindResponse2.getErrorMessage(),
message, bindResponse2.getMatchedDN(), null);
}