use of com.unboundid.ldap.protocol.BindResponseProtocolOp in project ldapsdk by pingidentity.
the class UNBOUNDIDTESTServer method run.
/**
* Performs the processing for this server.
*/
@Override()
public void run() {
try {
serverSocket = new ServerSocket(0);
listenPort = serverSocket.getLocalPort();
while (!stopRequested.get()) {
// Accept a connection from a client.
clientSocket = serverSocket.accept();
final InputStream inputStream = clientSocket.getInputStream();
final OutputStream outputStream = clientSocket.getOutputStream();
final ASN1StreamReader asn1Reader = new ASN1StreamReader(inputStream, 0);
// The client must first send an UNBOUNDID-TEST bind request with no
// credentials.
LDAPMessage requestMessage = LDAPMessage.readFrom(asn1Reader, false);
BindRequestProtocolOp bindRequestOp = requestMessage.getBindRequestProtocolOp();
assertEquals(bindRequestOp.getSASLMechanism(), "UNBOUNDID-TEST");
assertNull(bindRequestOp.getSASLCredentials());
// Return a "SASL bind in progress" response.
LDAPMessage responseMessage = new LDAPMessage(requestMessage.getMessageID(), new BindResponseProtocolOp(ResultCode.SASL_BIND_IN_PROGRESS_INT_VALUE, null, null, null, null));
outputStream.write(responseMessage.encode().encode());
outputStream.flush();
// The next request must be an UNBOUNDID-TEST bind request with
// credentials. We won't do anything to validate the credentials, but
// we will look at the third element to see what QoP the client
// requested.
requestMessage = LDAPMessage.readFrom(asn1Reader, false);
bindRequestOp = requestMessage.getBindRequestProtocolOp();
assertEquals(bindRequestOp.getSASLMechanism(), "UNBOUNDID-TEST");
assertNotNull(bindRequestOp.getSASLCredentials());
final ASN1Sequence credSequence = ASN1Sequence.decodeAsSequence(bindRequestOp.getSASLCredentials().getValue());
final ASN1Element[] credElements = credSequence.elements();
final SASLQualityOfProtection qop = SASLQualityOfProtection.forName(ASN1OctetString.decodeAsOctetString(credElements[2]).stringValue());
assertNotNull(qop);
final boolean qopEncode = ((qop == SASLQualityOfProtection.AUTH_INT) || (qop == SASLQualityOfProtection.AUTH_CONF));
// Return a "success" response. Include server SASL credentials with
// the requested QoP.
responseMessage = new LDAPMessage(requestMessage.getMessageID(), new BindResponseProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null, new ASN1OctetString(qop.toString())));
outputStream.write(responseMessage.encode().encode());
outputStream.flush();
// request.
if (qopEncode) {
for (int i = 0; i < 4; i++) {
inputStream.read();
}
}
requestMessage = LDAPMessage.readFrom(asn1Reader, false);
final SearchRequestProtocolOp searchRequestOp = requestMessage.getSearchRequestProtocolOp();
assertEquals(searchRequestOp.getBaseDN(), "");
assertEquals(searchRequestOp.getScope(), SearchScope.BASE);
assertEquals(searchRequestOp.getFilter(), Filter.createPresenceFilter("objectClass"));
assertEquals(searchRequestOp.getAttributes(), Arrays.asList("1.1"));
// Return a search result entry message with a DN but no attributes.
responseMessage = new LDAPMessage(requestMessage.getMessageID(), new SearchResultEntryProtocolOp("", Collections.<Attribute>emptyList()));
byte[] messageBytes = responseMessage.encode().encode();
if (qopEncode) {
// Since we know it's a tiny response, we know the length will be
// less than 127 bytes, so we can cheat.
outputStream.write(0);
outputStream.write(0);
outputStream.write(0);
outputStream.write(messageBytes.length);
}
outputStream.write(messageBytes);
outputStream.flush();
// Return a "success" search result done message.
responseMessage = new LDAPMessage(requestMessage.getMessageID(), new SearchResultDoneProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null));
messageBytes = responseMessage.encode().encode();
if (qopEncode) {
// Since we know it's a tiny response, we know the length will be
// less than 127 bytes, so we can cheat.
outputStream.write(0);
outputStream.write(0);
outputStream.write(0);
outputStream.write(messageBytes.length);
}
outputStream.write(messageBytes);
outputStream.flush();
// The next request should be an unbind request.
if (qopEncode) {
for (int i = 0; i < 4; i++) {
inputStream.read();
}
}
requestMessage = LDAPMessage.readFrom(asn1Reader, false);
final UnbindRequestProtocolOp unbindRequestOp = requestMessage.getUnbindRequestProtocolOp();
// Close the connection.
try {
asn1Reader.close();
} catch (final Exception e) {
}
try {
outputStream.close();
} catch (final Exception e) {
}
try {
clientSocket.close();
} catch (final Exception e) {
}
clientSocket = null;
}
} catch (final Exception e) {
stopServer();
}
}
use of com.unboundid.ldap.protocol.BindResponseProtocolOp in project ldapsdk by pingidentity.
the class InMemoryRequestHandler method processBindRequest.
/**
* Attempts to process the provided bind request. The attempt will fail if
* any of the following conditions is true:
* <UL>
* <LI>There is a problem with any of the request controls.</LI>
* <LI>The bind request is for a SASL bind for which no SASL mechanism
* handler is defined.</LI>
* <LI>The bind request contains a malformed bind DN.</LI>
* <LI>The bind DN is not the null DN and is not the DN of any entry in the
* data set.</LI>
* <LI>The bind password is empty and the bind DN is not the null DN.</LI>
* <LI>The target user does not have any password value that matches the
* provided bind password.</LI>
* </UL>
*
* @param messageID The message ID of the LDAP message containing the bind
* request.
* @param request The bind request that was included in the LDAP message
* that was received.
* @param controls The set of controls included in the LDAP message. It
* may be empty if there were no controls, but will not be
* {@code null}.
*
* @return The {@link LDAPMessage} containing the response to send to the
* client. The protocol op in the {@code LDAPMessage} must be a
* {@code BindResponseProtocolOp}.
*/
@Override()
@NotNull()
public LDAPMessage processBindRequest(final int messageID, @NotNull final BindRequestProtocolOp request, @NotNull final List<Control> controls) {
synchronized (entryMap) {
// Sleep before processing, if appropriate.
sleepBeforeProcessing();
// If this operation type is not allowed, then reject it.
if (!config.getAllowedOperationTypes().contains(OperationType.BIND)) {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_BIND_NOT_ALLOWED.get(), null, null));
}
authenticatedDN = DN.NULL_DN;
// request, then ensure that the request includes credentials.
if ((authenticatedDN.isNullDN() && config.getAuthenticationRequiredOperationTypes().contains(OperationType.BIND))) {
if ((request.getCredentialsType() == BindRequestProtocolOp.CRED_TYPE_SIMPLE) && ((request.getSimplePassword() == null) || request.getSimplePassword().getValueLength() == 0)) {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.INVALID_CREDENTIALS_INT_VALUE, null, ERR_MEM_HANDLER_BIND_REQUIRES_AUTH.get(), null, null));
}
}
// Get the parsed bind DN.
final DN bindDN;
try {
bindDN = new DN(request.getBindDN(), schemaRef.get());
} catch (final LDAPException le) {
Debug.debugException(le);
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.INVALID_DN_SYNTAX_INT_VALUE, null, ERR_MEM_HANDLER_BIND_MALFORMED_DN.get(request.getBindDN(), le.getMessage()), null, null));
}
// mechanism handler that can be used to process it.
if (request.getCredentialsType() == BindRequestProtocolOp.CRED_TYPE_SASL) {
final String mechanism = request.getSASLMechanism();
final InMemorySASLBindHandler handler = saslBindHandlers.get(mechanism);
if (handler == null) {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.AUTH_METHOD_NOT_SUPPORTED_INT_VALUE, null, ERR_MEM_HANDLER_SASL_MECH_NOT_SUPPORTED.get(mechanism), null, null));
}
try {
final BindResult bindResult = handler.processSASLBind(this, messageID, bindDN, request.getSASLCredentials(), controls);
// unauthenticated, then see if we allow that.
if ((bindResult.getResultCode() == ResultCode.SUCCESS) && (authenticatedDN == DN.NULL_DN) && config.getAuthenticationRequiredOperationTypes().contains(OperationType.BIND)) {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.INVALID_CREDENTIALS_INT_VALUE, null, ERR_MEM_HANDLER_BIND_REQUIRES_AUTH.get(), null, null));
}
return new LDAPMessage(messageID, new BindResponseProtocolOp(bindResult.getResultCode().intValue(), bindResult.getMatchedDN(), bindResult.getDiagnosticMessage(), Arrays.asList(bindResult.getReferralURLs()), bindResult.getServerSASLCredentials()), Arrays.asList(bindResult.getResponseControls()));
} catch (final Exception e) {
Debug.debugException(e);
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_MEM_HANDLER_SASL_BIND_FAILURE.get(StaticUtils.getExceptionMessage(e)), null, null));
}
}
// If we've gotten here, then the bind must use simple authentication.
// Process the provided request controls.
final Map<String, Control> controlMap;
try {
controlMap = RequestControlPreProcessor.processControls(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST, controls);
} catch (final LDAPException le) {
Debug.debugException(le);
return new LDAPMessage(messageID, new BindResponseProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null, null));
}
final ArrayList<Control> responseControls = new ArrayList<>(1);
// If the bind DN is the null DN, then the bind will be considered
// successful as long as the password is also empty.
final ASN1OctetString bindPassword = request.getSimplePassword();
if (bindDN.isNullDN()) {
if (bindPassword.getValueLength() == 0) {
if (controlMap.containsKey(AuthorizationIdentityRequestControl.AUTHORIZATION_IDENTITY_REQUEST_OID)) {
responseControls.add(new AuthorizationIdentityResponseControl(""));
}
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null, null), responseControls);
} else {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.INVALID_CREDENTIALS_INT_VALUE, null, ERR_MEM_HANDLER_BIND_WRONG_PASSWORD.get(request.getBindDN()), null, null));
}
}
// request.
if ((!bindDN.isNullDN()) && (bindPassword.getValueLength() == 0)) {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_BIND_SIMPLE_DN_WITHOUT_PASSWORD.get(), null, null));
}
// See if the bind DN is in the set of additional bind credentials. If
// so, then use the password there.
final byte[] additionalCreds = additionalBindCredentials.get(bindDN);
if (additionalCreds != null) {
if (Arrays.equals(additionalCreds, bindPassword.getValue())) {
authenticatedDN = bindDN;
if (controlMap.containsKey(AuthorizationIdentityRequestControl.AUTHORIZATION_IDENTITY_REQUEST_OID)) {
responseControls.add(new AuthorizationIdentityResponseControl("dn:" + bindDN.toString()));
}
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null, null), responseControls);
} else {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.INVALID_CREDENTIALS_INT_VALUE, null, ERR_MEM_HANDLER_BIND_WRONG_PASSWORD.get(request.getBindDN()), null, null));
}
}
// If the target user doesn't exist, then reject the request.
final ReadOnlyEntry userEntry = entryMap.get(bindDN);
if (userEntry == null) {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.INVALID_CREDENTIALS_INT_VALUE, null, ERR_MEM_HANDLER_BIND_NO_SUCH_USER.get(request.getBindDN()), null, null));
}
// Get a list of the user's passwords, restricted to those that match the
// provided clear-text password. If the list is empty, then the
// authentication failed.
final List<InMemoryDirectoryServerPassword> matchingPasswords = getPasswordsInEntry(userEntry, bindPassword);
if (matchingPasswords.isEmpty()) {
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.INVALID_CREDENTIALS_INT_VALUE, null, ERR_MEM_HANDLER_BIND_WRONG_PASSWORD.get(request.getBindDN()), null, null));
}
// If we've gotten here, then authentication was successful.
authenticatedDN = bindDN;
if (controlMap.containsKey(AuthorizationIdentityRequestControl.AUTHORIZATION_IDENTITY_REQUEST_OID)) {
responseControls.add(new AuthorizationIdentityResponseControl("dn:" + bindDN.toString()));
}
return new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null, null), responseControls);
}
}
use of com.unboundid.ldap.protocol.BindResponseProtocolOp in project ldapsdk by pingidentity.
the class JSONAccessLogRequestHandler method processBindRequest.
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public LDAPMessage processBindRequest(final int messageID, @NotNull final BindRequestProtocolOp request, @NotNull final List<Control> controls) {
final long opID = nextOperationID.getAndIncrement();
final JSONBuffer buffer = getRequestHeader("bind", opID, messageID);
buffer.appendNumber("ldap-version", request.getVersion());
buffer.appendString("dn", request.getBindDN());
switch(request.getCredentialsType()) {
case BindRequestProtocolOp.CRED_TYPE_SIMPLE:
buffer.appendString("authentication-type", "simple");
break;
case BindRequestProtocolOp.CRED_TYPE_SASL:
buffer.appendString("authentication-type", "sasl");
buffer.appendString("sasl-mechanism", request.getSASLMechanism());
break;
}
buffer.endObject();
logHandler.publish(new LogRecord(Level.INFO, buffer.toString()));
logHandler.flush();
final long startTimeNanos = System.nanoTime();
final LDAPMessage responseMessage = requestHandler.processBindRequest(messageID, request, controls);
final long eTimeNanos = System.nanoTime() - startTimeNanos;
final BindResponseProtocolOp protocolOp = responseMessage.getBindResponseProtocolOp();
generateResponse(buffer, "bind", opID, messageID, protocolOp.getResultCode(), protocolOp.getDiagnosticMessage(), protocolOp.getMatchedDN(), protocolOp.getReferralURLs(), eTimeNanos);
buffer.endObject();
logHandler.publish(new LogRecord(Level.INFO, buffer.toString()));
logHandler.flush();
return responseMessage;
}
use of com.unboundid.ldap.protocol.BindResponseProtocolOp in project ldapsdk by pingidentity.
the class LDAPListenerClientConnection method run.
/**
* Operates in a loop, waiting for a request to arrive from the client and
* handing it off to the request handler for processing. This method is for
* internal use only and must not be invoked by external callers.
*/
@InternalUseOnly()
@Override()
public void run() {
try {
while (true) {
final LDAPMessage requestMessage;
try {
requestMessage = LDAPMessage.readFrom(asn1Reader, false);
if (requestMessage == null) {
// so we won't notify the exception handler.
try {
close();
} catch (final IOException ioe) {
Debug.debugException(ioe);
}
return;
}
} catch (final LDAPException le) {
// This indicates that the client sent a malformed request.
Debug.debugException(le);
close(le);
return;
}
try {
final int messageID = requestMessage.getMessageID();
final List<Control> controls = requestMessage.getControls();
LDAPMessage responseMessage;
switch(requestMessage.getProtocolOpType()) {
case LDAPMessage.PROTOCOL_OP_TYPE_ABANDON_REQUEST:
requestHandler.processAbandonRequest(messageID, requestMessage.getAbandonRequestProtocolOp(), controls);
responseMessage = null;
break;
case LDAPMessage.PROTOCOL_OP_TYPE_ADD_REQUEST:
try {
responseMessage = requestHandler.processAddRequest(messageID, requestMessage.getAddRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new AddResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST:
try {
responseMessage = requestHandler.processBindRequest(messageID, requestMessage.getBindRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null, null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_COMPARE_REQUEST:
try {
responseMessage = requestHandler.processCompareRequest(messageID, requestMessage.getCompareRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new CompareResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_DELETE_REQUEST:
try {
responseMessage = requestHandler.processDeleteRequest(messageID, requestMessage.getDeleteRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new DeleteResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST:
try {
responseMessage = requestHandler.processExtendedRequest(messageID, requestMessage.getExtendedRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new ExtendedResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null, null, null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST:
try {
responseMessage = requestHandler.processModifyRequest(messageID, requestMessage.getModifyRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new ModifyResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST:
try {
responseMessage = requestHandler.processModifyDNRequest(messageID, requestMessage.getModifyDNRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_REQUEST:
try {
responseMessage = requestHandler.processSearchRequest(messageID, requestMessage.getSearchRequestProtocolOp(), controls);
} catch (final Exception e) {
Debug.debugException(e);
responseMessage = new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
}
break;
case LDAPMessage.PROTOCOL_OP_TYPE_UNBIND_REQUEST:
requestHandler.processUnbindRequest(messageID, requestMessage.getUnbindRequestProtocolOp(), controls);
close();
return;
default:
close(new LDAPException(ResultCode.PROTOCOL_ERROR, ERR_CONN_INVALID_PROTOCOL_OP_TYPE.get(StaticUtils.toHex(requestMessage.getProtocolOpType()))));
return;
}
if (responseMessage != null) {
try {
sendMessage(responseMessage);
} catch (final LDAPException le) {
Debug.debugException(le);
close(le);
return;
}
}
} catch (final Throwable t) {
close(new LDAPException(ResultCode.LOCAL_ERROR, ERR_CONN_EXCEPTION_IN_REQUEST_HANDLER.get(String.valueOf(requestMessage), StaticUtils.getExceptionMessage(t))));
StaticUtils.throwErrorOrRuntimeException(t);
}
}
} finally {
if (listener != null) {
listener.connectionClosed(this);
}
}
}
use of com.unboundid.ldap.protocol.BindResponseProtocolOp in project ldapsdk by pingidentity.
the class LDAPDebuggerTestCase method testFailedSimpleBind.
/**
* Provides test coverage for a failed simple bind operation.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test(expectedExceptions = { LDAPException.class })
public void testFailedSimpleBind() throws Exception {
TestRequestHandler.setReturnOp(new BindResponseProtocolOp(49, null, null, null, new ASN1OctetString("foo")));
conn.bind("uid=admin,dc=example,dc=com", "password");
}
Aggregations