From 22094368c2865dcfb6daf8366425212b721a4657 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Thu, 05 Feb 2009 17:42:14 +0000
Subject: [PATCH] Merge ASN1 branch to trunk
---
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java | 2814 +++++++++++++++++++++++++----------------------------------
1 files changed, 1,200 insertions(+), 1,614 deletions(-)
diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index df57bde..fa7b7aa 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -22,17 +22,25 @@
* CDDL HEADER END
*
*
- * Copyright 2006-2008 Sun Microsystems, Inc.
+ * Copyright 2006-2009 Sun Microsystems, Inc.
*/
package org.opends.server.protocols.ldap;
+import static org.opends.messages.ProtocolMessages.*;
+import static org.opends.server.loggers.AccessLogger.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.protocols.ldap.LDAPConstants.*;
+import static org.opends.server.types.OperationType.*;
+import static org.opends.server.util.StaticUtils.*;
+
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
-import java.util.ArrayList;
+import java.security.cert.Certificate;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -44,7 +52,6 @@
import org.opends.messages.MessageBuilder;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
-import org.opends.server.api.ConnectionSecurityProvider;
import org.opends.server.core.AbandonOperationBasis;
import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.BindOperationBasis;
@@ -60,15 +67,18 @@
import org.opends.server.core.SearchOperationBasis;
import org.opends.server.core.UnbindOperationBasis;
import org.opends.server.core.networkgroups.NetworkGroup;
-import org.opends.server.extensions.NullConnectionSecurityProvider;
+import org.opends.server.extensions.ConnectionSecurityProvider;
+import org.opends.server.extensions.RedirectingByteChannel;
+import org.opends.server.extensions.TLSByteChannel;
import org.opends.server.extensions.TLSCapableConnection;
-import org.opends.server.extensions.TLSConnectionSecurityProvider;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.monitors.OperationMonitor;
-import org.opends.server.protocols.asn1.ASN1Element;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.asn1.ASN1Sequence;
+import org.opends.server.protocols.asn1.ASN1;
+import org.opends.server.protocols.asn1.ASN1ByteChannelReader;
+import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringBuilder;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
@@ -83,151 +93,113 @@
import org.opends.server.types.SearchResultReference;
import org.opends.server.util.TimeThread;
-import static org.opends.messages.ProtocolMessages.*;
-import static org.opends.server.loggers.AccessLogger.logDisconnect;
-import static org.opends.server.loggers.ErrorLogger.logError;
-import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import static org.opends.server.loggers.debug.DebugLogger.getTracer;
-import static org.opends.server.protocols.ldap.LDAPConstants.*;
-import static org.opends.server.util.StaticUtils.getExceptionMessage;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
-import static org.opends.server.types.OperationType.*;
-
/**
- * This class defines an LDAP client connection, which is a type of client
- * connection that will be accepted by an instance of the LDAP connection
- * handler and have its requests decoded by an LDAP request handler.
+ * This class defines an LDAP client connection, which is a type of
+ * client connection that will be accepted by an instance of the LDAP
+ * connection handler and have its requests decoded by an LDAP request
+ * handler.
*/
-public class LDAPClientConnection
- extends ClientConnection
- implements TLSCapableConnection
+
+public class LDAPClientConnection extends ClientConnection implements
+ TLSCapableConnection
{
/**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
-
-
// The time that the last operation was completed.
- private AtomicLong lastCompletionTime;
+ private final AtomicLong lastCompletionTime;
// The next operation ID that should be used for this connection.
- private AtomicLong nextOperationID;
+ private final AtomicLong nextOperationID;
// The selector that may be used for write operations.
- private AtomicReference<Selector> writeSelector;
+ private final AtomicReference<Selector> writeSelector;
- // Indicates whether the Directory Server believes this connection to be
- // valid and available for communication.
+ // Indicates whether the Directory Server believes this connection to
+ // be valid and available for communication.
private boolean connectionValid;
- // Indicates whether this connection is about to be closed. This will be used
- // to prevent accepting new requests while a disconnect is in progress.
+ // Indicates whether this connection is about to be closed. This will
+ // be used to prevent accepting new requests while a disconnect is in
+ // progress.
private boolean disconnectRequested;
- // Indicates whether the connection should keep statistics regarding the
- // operations that it is performing.
- private boolean keepStats;
-
- // The BER type for the ASN.1 element that is in the process of being read.
- private byte elementType;
-
- // The encoded value for the ASN.1 element that is in the process of being
- // read.
- private byte[] elementValue;
+ // Indicates whether the connection should keep statistics regarding
+ // the operations that it is performing.
+ private final boolean keepStats;
// The set of all operations currently in progress on this connection.
- private ConcurrentHashMap<Integer,Operation> operationsInProgress;
+ private final ConcurrentHashMap<Integer, Operation> operationsInProgress;
// The number of operations performed on this connection.
// Used to compare with the resource limits of the network group.
private long operationsPerformed;
// Lock on the number of operations
- private Object operationsPerformedLock;
-
- // The connection security provider that was in use for the client connection
- // before switching to a TLS-based provider.
- private ConnectionSecurityProvider clearSecurityProvider;
-
- // The connection security provider for this client connection.
- private ConnectionSecurityProvider securityProvider;
+ private final Object operationsPerformedLock;
// The port on the client from which this connection originated.
- private int clientPort;
+ private final int clientPort;
- // The number of bytes contained in the value for the ASN.1 element that is in
- // the process of being read.
- private int elementLength;
-
- // The number of bytes in the multi-byte length that are still needed to fully
- // decode the length of the ASN.1 element in process.
- private int elementLengthBytesNeeded;
-
- // The current state for the data read for the ASN.1 element in progress.
- private int elementReadState;
-
- // The number of bytes that have already been read for the ASN.1 element
- // value in progress.
- private int elementValueBytesRead;
-
- // The number of bytes that are still needed to fully decode the value of the
- // ASN.1 element in progress.
- private int elementValueBytesNeeded;
-
- // The LDAP version that the client is using to communicate with the server.
+ // The LDAP version that the client is using to communicate with the
+ // server.
private int ldapVersion;
// The port on the server to which this client has connected.
- private int serverPort;
+ private final int serverPort;
- // The reference to the connection handler that accepted this connection.
- private LDAPConnectionHandler connectionHandler;
+ // The reference to the connection handler that accepted this
+ // connection.
+ private final LDAPConnectionHandler connectionHandler;
// The reference to the request handler with which this connection is
// associated.
- private LDAPRequestHandler requestHandler;
+ private final LDAPRequestHandler requestHandler;
// The statistics tracker associated with this client connection.
- private LDAPStatistics statTracker;
+ private final LDAPStatistics statTracker;
// The connectionHandler statistic tracker.
- private LDAPStatistics parentTracker;
+ private final LDAPStatistics parentTracker;
// The connection ID assigned to this connection.
- private long connectionID;
+ private final long connectionID;
- // The lock used to provide threadsafe access to the set of operations in
- // progress.
- private Object opsInProgressLock;
+ // The lock used to provide threadsafe access to the set of operations
+ // in progress.
+ private final Object opsInProgressLock;
- // The lock used to provide threadsafe access when sending data to the client.
- private Object transmitLock;
+ // The lock used to provide threadsafe access when sending data to the
+ // client.
+ private final Object transmitLock;
// The socket channel with which this client connection is associated.
- private SocketChannel clientChannel;
+ private final SocketChannel clientChannel;
// The string representation of the address of the client.
- private String clientAddress;
+ private final String clientAddress;
- // The name of the protocol that the client is using to communicate with the
- // server.
- private String protocol;
+ // The name of the protocol that the client is using to communicate
+ // with the server.
+ private final String protocol;
- // The string representation of the address of the server to which the client
- // has connected.
- private String serverAddress;
+ // The string representation of the address of the server to which the
+ // client has connected.
+ private final String serverAddress;
- // The TLS connection security provider that may be used for this connection
- // if StartTLS is requested.
- private TLSConnectionSecurityProvider tlsSecurityProvider;
+ private final ThreadLocal<WriterBuffer> cachedBuffers;
- //The SASL connection provider used if confidentiality/integrity is negotiated
- //during a SASL bind (GSSAPI and DIGEST-MD5 only).
- private ConnectionSecurityProvider saslSecurityProvider;
+ private ASN1ByteChannelReader asn1Reader;
+
+ private final RedirectingByteChannel saslChannel;
+ private final RedirectingByteChannel tlsChannel;
+ private ConnectionSecurityProvider activeProvider = null;
+ private ConnectionSecurityProvider tlsPendingProvider = null;
+ private ConnectionSecurityProvider saslPendingProvider = null;
// Statistics for the processed operations
private OperationMonitor addMonitor;
@@ -241,64 +213,67 @@
private OperationMonitor moddnMonitor;
private OperationMonitor unbindMonitor;
+
+
+ /**
+ * This class wraps the byte string buffer and ASN1 writer.
+ */
+ private static class WriterBuffer
+ {
+ ASN1Writer writer;
+ ByteStringBuilder buffer;
+ }
+
+
+
/**
* Creates a new LDAP client connection with the provided information.
*
- * @param connectionHandler The connection handler that accepted this
- * connection.
- * @param clientChannel The socket channel that may be used to
- * communicate with the client.
+ * @param connectionHandler
+ * The connection handler that accepted this connection.
+ * @param clientChannel
+ * The socket channel that may be used to communicate with
+ * the client.
*/
public LDAPClientConnection(LDAPConnectionHandler connectionHandler,
- SocketChannel clientChannel)
+ SocketChannel clientChannel)
{
super();
-
- this.connectionHandler = connectionHandler;
- if (connectionHandler.isAdminConnectionHandler()) {
+ this.connectionHandler = connectionHandler;
+ if (connectionHandler.isAdminConnectionHandler())
+ {
setNetworkGroup(NetworkGroup.getAdminNetworkGroup());
}
- this.clientChannel = clientChannel;
- this.securityProvider = null;
- this.clearSecurityProvider = null;
-
+ this.clientChannel = clientChannel;
opsInProgressLock = new Object();
- transmitLock = new Object();
-
- elementReadState = ELEMENT_READ_STATE_NEED_TYPE;
- elementType = 0x00;
- elementLength = 0;
- elementLengthBytesNeeded = 0;
- elementValue = null;
- elementValueBytesRead = 0;
- elementValueBytesNeeded = 0;
-
- ldapVersion = 3;
- requestHandler = null;
- lastCompletionTime = new AtomicLong(TimeThread.getTime());
- nextOperationID = new AtomicLong(0);
- connectionValid = true;
- disconnectRequested = false;
- operationsInProgress = new ConcurrentHashMap<Integer,Operation>();
+ transmitLock = new Object();
+ ldapVersion = 3;
+ requestHandler = null;
+ lastCompletionTime = new AtomicLong(TimeThread.getTime());
+ nextOperationID = new AtomicLong(0);
+ connectionValid = true;
+ disconnectRequested = false;
+ operationsInProgress = new ConcurrentHashMap<Integer, Operation>();
operationsPerformed = 0;
operationsPerformedLock = new Object();
- keepStats = connectionHandler.keepStats();
- protocol = "LDAP";
- writeSelector = new AtomicReference<Selector>();
-
- clientAddress = clientChannel.socket().getInetAddress().getHostAddress();
- clientPort = clientChannel.socket().getPort();
- serverAddress = clientChannel.socket().getLocalAddress().getHostAddress();
- serverPort = clientChannel.socket().getLocalPort();
-
+ keepStats = connectionHandler.keepStats();
+ protocol = "LDAP";
+ writeSelector = new AtomicReference<Selector>();
+ clientAddress =
+ clientChannel.socket().getInetAddress().getHostAddress();
+ clientPort = clientChannel.socket().getPort();
+ serverAddress =
+ clientChannel.socket().getLocalAddress().getHostAddress();
+ serverPort = clientChannel.socket().getLocalPort();
parentTracker = connectionHandler.getStatTracker();
- String instanceName = parentTracker.getMonitorInstanceName() +
- " for " + toString();
+ String instanceName =
+ parentTracker.getMonitorInstanceName() + " for " + toString();
this.initializeOperationMonitors();
- statTracker = new LDAPStatistics(connectionHandler,
- instanceName, parentTracker);
+ statTracker =
+ new LDAPStatistics(connectionHandler, instanceName,
+ parentTracker);
if (keepStats)
{
@@ -309,8 +284,16 @@
if (connectionID < 0)
{
disconnect(DisconnectReason.ADMIN_LIMIT_EXCEEDED, true,
- ERR_LDAP_CONNHANDLER_REJECTED_BY_SERVER.get());
+ ERR_LDAP_CONNHANDLER_REJECTED_BY_SERVER.get());
}
+ cachedBuffers = new ThreadLocal<WriterBuffer>();
+ tlsChannel =
+ RedirectingByteChannel.getRedirectingByteChannel(clientChannel);
+ saslChannel =
+ RedirectingByteChannel.getRedirectingByteChannel(tlsChannel);
+ this.asn1Reader =
+ ASN1.getReader(saslChannel, 4096, connectionHandler
+ .getMaxRequestSize());
}
@@ -318,8 +301,9 @@
/**
* Retrieves the connection ID assigned to this connection.
*
- * @return The connection ID assigned to this connection.
+ * @return The connection ID assigned to this connection.
*/
+ @Override
public long getConnectionID()
{
return connectionID;
@@ -328,10 +312,13 @@
/**
- * Retrieves the connection handler that accepted this client connection.
+ * Retrieves the connection handler that accepted this client
+ * connection.
*
- * @return The connection handler that accepted this client connection.
+ * @return The connection handler that accepted this client
+ * connection.
*/
+ @Override
public ConnectionHandler<?> getConnectionHandler()
{
return connectionHandler;
@@ -340,11 +327,12 @@
/**
- * Retrieves the request handler that will read requests for this client
- * connection.
+ * Retrieves the request handler that will read requests for this
+ * client connection.
*
- * @return The request handler that will read requests for this client
- * connection, or <CODE>null</CODE> if none has been assigned yet.
+ * @return The request handler that will read requests for this client
+ * connection, or <CODE>null</CODE> if none has been assigned
+ * yet.
*/
public LDAPRequestHandler getRequestHandler()
{
@@ -354,25 +342,11 @@
/**
- * Specifies the request handler that will read requests for this client
- * connection.
+ * Retrieves the socket channel that can be used to communicate with
+ * the client.
*
- * @param requestHandler The request handler that will read requests for
- * this client connection.
- */
- public void setRequestHandler(LDAPRequestHandler requestHandler)
- {
- this.requestHandler = requestHandler;
- }
-
-
-
- /**
- * Retrieves the socket channel that can be used to communicate with the
- * client.
- *
- * @return The socket channel that can be used to communicate with the
- * client.
+ * @return The socket channel that can be used to communicate with the
+ * client.
*/
public SocketChannel getSocketChannel()
{
@@ -382,12 +356,13 @@
/**
- * Retrieves the protocol that the client is using to communicate with the
- * Directory Server.
+ * Retrieves the protocol that the client is using to communicate with
+ * the Directory Server.
*
- * @return The protocol that the client is using to communicate with the
- * Directory Server.
+ * @return The protocol that the client is using to communicate with
+ * the Directory Server.
*/
+ @Override
public String getProtocol()
{
return protocol;
@@ -398,8 +373,9 @@
/**
* Retrieves a string representation of the address of the client.
*
- * @return A string representation of the address of the client.
+ * @return A string representation of the address of the client.
*/
+ @Override
public String getClientAddress()
{
return clientAddress;
@@ -410,8 +386,9 @@
/**
* Retrieves the port number for this connection on the client system.
*
- * @return The port number for this connection on the client system.
+ * @return The port number for this connection on the client system.
*/
+ @Override
public int getClientPort()
{
return clientPort;
@@ -420,12 +397,13 @@
/**
- * Retrieves a string representation of the address on the server to which the
- * client connected.
+ * Retrieves a string representation of the address on the server to
+ * which the client connected.
*
- * @return A string representation of the address on the server to which the
- * client connected.
+ * @return A string representation of the address on the server to
+ * which the client connected.
*/
+ @Override
public String getServerAddress()
{
return serverAddress;
@@ -436,8 +414,9 @@
/**
* Retrieves the port number for this connection on the server system.
*
- * @return The port number for this connection on the server system.
+ * @return The port number for this connection on the server system.
*/
+ @Override
public int getServerPort()
{
return serverPort;
@@ -446,13 +425,14 @@
/**
- * Retrieves the <CODE>java.net.InetAddress</CODE> associated with the remote
- * client system.
+ * Retrieves the <CODE>java.net.InetAddress</CODE> associated with the
+ * remote client system.
*
- * @return The <CODE>java.net.InetAddress</CODE> associated with the remote
- * client system. It may be <CODE>null</CODE> if the client is not
- * connected over an IP-based connection.
+ * @return The <CODE>java.net.InetAddress</CODE> associated with the
+ * remote client system. It may be <CODE>null</CODE> if the
+ * client is not connected over an IP-based connection.
*/
+ @Override
public InetAddress getRemoteAddress()
{
return clientChannel.socket().getInetAddress();
@@ -461,14 +441,15 @@
/**
- * Retrieves the <CODE>java.net.InetAddress</CODE> for the Directory Server
- * system to which the client has established the connection.
+ * Retrieves the <CODE>java.net.InetAddress</CODE> for the Directory
+ * Server system to which the client has established the connection.
*
- * @return The <CODE>java.net.InetAddress</CODE> for the Directory Server
- * system to which the client has established the connection. It may
- * be <CODE>null</CODE> if the client is not connected over an
- * IP-based connection.
+ * @return The <CODE>java.net.InetAddress</CODE> for the Directory
+ * Server system to which the client has established the
+ * connection. It may be <CODE>null</CODE> if the client is
+ * not connected over an IP-based connection.
*/
+ @Override
public InetAddress getLocalAddress()
{
return clientChannel.socket().getLocalAddress();
@@ -477,92 +458,34 @@
/**
- * Indicates whether this client connection is currently using a secure
- * mechanism to communicate with the server. Note that this may change over
- * time based on operations performed by the client or server (e.g., it may go
- * from <CODE>false</CODE> to <CODE>true</CODE> if the client uses the
- * StartTLS extended operation).
+ * Indicates whether this client connection is currently using a
+ * secure mechanism to communicate with the server. Note that this may
+ * change over time based on operations performed by the client or
+ * server (e.g., it may go from <CODE>false</CODE> to
+ * <CODE>true</CODE> if the client uses the StartTLS extended
+ * operation).
*
- * @return <CODE>true</CODE> if the client connection is currently using a
- * secure mechanism to communicate with the server, or
- * <CODE>false</CODE> if not.
+ * @return <CODE>true</CODE> if the client connection is currently
+ * using a secure mechanism to communicate with the server, or
+ * <CODE>false</CODE> if not.
*/
+ @Override
public boolean isSecure()
{
- return securityProvider.isSecure();
- }
-
-
-
- /**
- * Retrieves the connection security provider for this client connection.
- *
- * @return The connection security provider for this client connection.
- */
- public ConnectionSecurityProvider getConnectionSecurityProvider()
- {
- if(saslSecurityProvider != null && saslSecurityProvider.isActive())
- securityProvider = saslSecurityProvider;
- return securityProvider;
- }
-
-
-
- /**
- * Set the security provider to be used to process SASL (DIGEST-MD5, GSSAPI)
- * confidentiality/integrity messages.
- *
- * @param secProvider The security provider to use.
- */
- public void
- setSASLConnectionSecurityProvider(ConnectionSecurityProvider secProvider) {
- saslSecurityProvider = secProvider;
- }
-
-
-
- /**
- * Specifies the connection security provider for this client connection.
- *
- * @param securityProvider The connection security provider to use for
- * communication on this client connection.
- */
- public void setConnectionSecurityProvider(ConnectionSecurityProvider
- securityProvider)
- {
- this.securityProvider = securityProvider;
-
- if (securityProvider.isSecure())
- {
- protocol = "LDAP+" + securityProvider.getSecurityMechanismName();
- }
+ if (activeProvider != null)
+ return activeProvider.isSecure();
else
- {
- protocol = "LDAP";
- }
+ return false;
}
/**
- * Retrieves the human-readable name of the security mechanism that is used to
- * protect communication with this client.
+ * Retrieves the next operation ID that should be used for this
+ * connection.
*
- * @return The human-readable name of the security mechanism that is used to
- * protect communication with this client, or <CODE>null</CODE> if no
- * security is in place.
- */
- public String getSecurityMechanism()
- {
- return securityProvider.getSecurityMechanismName();
- }
-
-
-
- /**
- * Retrieves the next operation ID that should be used for this connection.
- *
- * @return The next operation ID that should be used for this connection.
+ * @return The next operation ID that should be used for this
+ * connection.
*/
public long nextOperationID()
{
@@ -572,57 +495,56 @@
/**
- * Sends a response to the client based on the information in the provided
- * operation.
+ * Sends a response to the client based on the information in the
+ * provided operation.
*
- * @param operation The operation for which to send the response.
+ * @param operation
+ * The operation for which to send the response.
*/
+ @Override
public void sendResponse(Operation operation)
{
- // Since this is the final response for this operation, we can go ahead and
- // remove it from the "operations in progress" list. It can't be canceled
- // after this point, and this will avoid potential race conditions in which
- // the client immediately sends another request with the same message ID as
- // was used for this operation.
+ // Since this is the final response for this operation, we can go
+ // ahead and remove it from the "operations in progress" list. It
+ // can't be canceled after this point, and this will avoid potential
+ // race conditions in which the client immediately sends another
+ // request with the same message ID as was used for this operation.
removeOperationInProgress(operation.getMessageID());
LDAPMessage message = operationToResponseLDAPMessage(operation);
if (message != null)
{
- sendLDAPMessage(securityProvider, message);
+ sendLDAPMessage(message);
}
}
/**
- * Retrieves an LDAPMessage containing a response generated from the provided
- * operation.
+ * Retrieves an LDAPMessage containing a response generated from the
+ * provided operation.
*
- * @param operation The operation to use to generate the response
- * LDAPMessage.
- *
- * @return An LDAPMessage containing a response generated from the provided
- * operation.
+ * @param operation
+ * The operation to use to generate the response LDAPMessage.
+ * @return An LDAPMessage containing a response generated from the
+ * provided operation.
*/
private LDAPMessage operationToResponseLDAPMessage(Operation operation)
{
ResultCode resultCode = operation.getResultCode();
if (resultCode == null)
{
- // This must mean that the operation has either not yet completed or that
- // it completed without a result for some reason. In any case, log a
- // message and set the response to "operations error".
- logError(ERR_LDAP_CLIENT_SEND_RESPONSE_NO_RESULT_CODE.
- get(operation.getOperationType().toString(),
- operation.getConnectionID(), operation.getOperationID()));
+ // This must mean that the operation has either not yet completed
+ // or that it completed without a result for some reason. In any
+ // case, log a message and set the response to "operations error".
+ logError(ERR_LDAP_CLIENT_SEND_RESPONSE_NO_RESULT_CODE.get(
+ operation.getOperationType().toString(), operation
+ .getConnectionID(), operation.getOperationID()));
resultCode = DirectoryServer.getServerErrorResultCode();
}
-
MessageBuilder errorMessage = operation.getErrorMessage();
- DN matchedDN = operation.getMatchedDN();
-
+ DN matchedDN = operation.getMatchedDN();
// Referrals are not allowed for LDAPv2 clients.
List<String> referralURLs;
@@ -637,7 +559,7 @@
}
List<String> opReferrals = operation.getReferralURLs();
- if ((opReferrals != null) && (! opReferrals.isEmpty()))
+ if ((opReferrals != null) && (!opReferrals.isEmpty()))
{
StringBuilder referralsStr = new StringBuilder();
Iterator<String> iterator = opReferrals.iterator();
@@ -649,8 +571,8 @@
referralsStr.append(iterator.next());
}
- errorMessage.append(ERR_LDAPV2_REFERRALS_OMITTED.get(
- String.valueOf(referralsStr)));
+ errorMessage.append(ERR_LDAPV2_REFERRALS_OMITTED.get(String
+ .valueOf(referralsStr)));
}
}
else
@@ -661,94 +583,82 @@
ProtocolOp protocolOp;
switch (operation.getOperationType())
{
- case ADD:
- protocolOp = new AddResponseProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(),
- matchedDN, referralURLs);
- break;
- case BIND:
- ASN1OctetString serverSASLCredentials =
- ((BindOperationBasis) operation).getServerSASLCredentials();
- protocolOp = new BindResponseProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(), matchedDN,
- referralURLs, serverSASLCredentials);
- break;
- case COMPARE:
- protocolOp = new CompareResponseProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(),
- matchedDN, referralURLs);
- break;
- case DELETE:
- protocolOp = new DeleteResponseProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(),
- matchedDN, referralURLs);
- break;
- case EXTENDED:
- // If this an LDAPv2 client, then we can't send this.
- if (ldapVersion == 2)
- {
- logError(ERR_LDAPV2_SKIPPING_EXTENDED_RESPONSE.get(
- getConnectionID(), operation.getOperationID(),
- String.valueOf(operation)));
- return null;
- }
-
- ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation;
- protocolOp = new ExtendedResponseProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(), matchedDN, referralURLs,
- extOp.getResponseOID(), extOp.getResponseValue());
- break;
- case MODIFY:
- protocolOp = new ModifyResponseProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(),
- matchedDN, referralURLs);
- break;
- case MODIFY_DN:
- protocolOp = new ModifyDNResponseProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(),
- matchedDN, referralURLs);
- break;
- case SEARCH:
- protocolOp = new SearchResultDoneProtocolOp(resultCode.getIntValue(),
- errorMessage.toMessage(),
- matchedDN, referralURLs);
- break;
- default:
- // This must be a type of operation that doesn't have a response. This
- // shouldn't happen, so log a message and return.
- logError(ERR_LDAP_CLIENT_SEND_RESPONSE_INVALID_OP.get(
- String.valueOf(operation.getOperationType()),
- getConnectionID(),
- operation.getOperationID(),
- String.valueOf(operation)));
+ case ADD:
+ protocolOp =
+ new AddResponseProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs);
+ break;
+ case BIND:
+ ByteString serverSASLCredentials =
+ ((BindOperationBasis) operation).getServerSASLCredentials();
+ protocolOp =
+ new BindResponseProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs,
+ serverSASLCredentials);
+ break;
+ case COMPARE:
+ protocolOp =
+ new CompareResponseProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs);
+ break;
+ case DELETE:
+ protocolOp =
+ new DeleteResponseProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs);
+ break;
+ case EXTENDED:
+ // If this an LDAPv2 client, then we can't send this.
+ if (ldapVersion == 2)
+ {
+ logError(ERR_LDAPV2_SKIPPING_EXTENDED_RESPONSE.get(
+ getConnectionID(), operation.getOperationID(), String
+ .valueOf(operation)));
return null;
+ }
+
+ ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation;
+ protocolOp =
+ new ExtendedResponseProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs, extOp
+ .getResponseOID(), extOp.getResponseValue());
+ break;
+ case MODIFY:
+ protocolOp =
+ new ModifyResponseProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs);
+ break;
+ case MODIFY_DN:
+ protocolOp =
+ new ModifyDNResponseProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs);
+ break;
+ case SEARCH:
+ protocolOp =
+ new SearchResultDoneProtocolOp(resultCode.getIntValue(),
+ errorMessage.toMessage(), matchedDN, referralURLs);
+ break;
+ default:
+ // This must be a type of operation that doesn't have a response.
+ // This shouldn't happen, so log a message and return.
+ logError(ERR_LDAP_CLIENT_SEND_RESPONSE_INVALID_OP.get(String
+ .valueOf(operation.getOperationType()), getConnectionID(),
+ operation.getOperationID(), String.valueOf(operation)));
+ return null;
}
-
// Controls are not allowed for LDAPv2 clients.
- ArrayList<LDAPControl> controls;
+ List<Control> controls;
if (ldapVersion == 2)
{
controls = null;
}
else
{
- List<Control> responseControls = operation.getResponseControls();
- if ((responseControls == null) || responseControls.isEmpty())
- {
- controls = null;
- }
- else
- {
- controls = new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- controls.add(new LDAPControl(c));
- }
- }
+ controls = operation.getResponseControls();
}
- return new LDAPMessage(operation.getMessageID(), protocolOp, controls);
+ return new LDAPMessage(operation.getMessageID(), protocolOp,
+ controls);
}
@@ -756,34 +666,20 @@
/**
* Sends the provided search result entry to the client.
*
- * @param searchOperation The search operation with which the entry is
- * associated.
- * @param searchEntry The search result entry to be sent to the client.
+ * @param searchOperation
+ * The search operation with which the entry is associated.
+ * @param searchEntry
+ * The search result entry to be sent to the client.
*/
+ @Override
public void sendSearchEntry(SearchOperation searchOperation,
- SearchResultEntry searchEntry)
+ SearchResultEntry searchEntry)
{
SearchResultEntryProtocolOp protocolOp =
- new SearchResultEntryProtocolOp(searchEntry,ldapVersion);
+ new SearchResultEntryProtocolOp(searchEntry, ldapVersion);
- List<Control> entryControls = searchEntry.getControls();
- ArrayList<LDAPControl> controls;
- if ((entryControls == null) || entryControls.isEmpty())
- {
- controls = null;
- }
- else
- {
- controls = new ArrayList<LDAPControl>(entryControls.size());
- for (Control c : entryControls)
- {
- controls.add(new LDAPControl(c));
- }
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(searchOperation.getMessageID(), protocolOp,
- controls));
+ sendLDAPMessage(new LDAPMessage(searchOperation.getMessageID(),
+ protocolOp, searchEntry.getControls()));
}
@@ -791,92 +687,69 @@
/**
* Sends the provided search result reference to the client.
*
- * @param searchOperation The search operation with which the reference is
- * associated.
- * @param searchReference The search result reference to be sent to the
- * client.
- *
- * @return <CODE>true</CODE> if the client is able to accept referrals, or
- * <CODE>false</CODE> if the client cannot handle referrals and no
- * more attempts should be made to send them for the associated
- * search operation.
+ * @param searchOperation
+ * The search operation with which the reference is
+ * associated.
+ * @param searchReference
+ * The search result reference to be sent to the client.
+ * @return <CODE>true</CODE> if the client is able to accept
+ * referrals, or <CODE>false</CODE> if the client cannot
+ * handle referrals and no more attempts should be made to
+ * send them for the associated search operation.
*/
+ @Override
public boolean sendSearchReference(SearchOperation searchOperation,
- SearchResultReference searchReference)
+ SearchResultReference searchReference)
{
- // Make sure this is not an LDAPv2 client. If it is, then they can't see
- // referrals so we'll not send anything. Also, throw an exception so that
- // the core server will know not to try sending any more referrals to this
- // client for the rest of the operation.
+ // Make sure this is not an LDAPv2 client. If it is, then they can't
+ // see referrals so we'll not send anything. Also, throw an
+ // exception so that the core server will know not to try sending
+ // any more referrals to this client for the rest of the operation.
if (ldapVersion == 2)
{
- Message message = ERR_LDAPV2_SKIPPING_SEARCH_REFERENCE.
- get(getConnectionID(), searchOperation.getOperationID(),
- String.valueOf(searchReference));
+ Message message =
+ ERR_LDAPV2_SKIPPING_SEARCH_REFERENCE.get(getConnectionID(),
+ searchOperation.getOperationID(), String
+ .valueOf(searchReference));
logError(message);
return false;
}
SearchResultReferenceProtocolOp protocolOp =
- new SearchResultReferenceProtocolOp(searchReference);
+ new SearchResultReferenceProtocolOp(searchReference);
- List<Control> referenceControls = searchReference.getControls();
- ArrayList<LDAPControl> controls;
- if ((referenceControls == null) || referenceControls.isEmpty())
- {
- controls = null;
- }
- else
- {
- controls = new ArrayList<LDAPControl>(referenceControls.size());
- for (Control c : referenceControls)
- {
- controls.add(new LDAPControl(c));
- }
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(searchOperation.getMessageID(), protocolOp,
- controls));
+ sendLDAPMessage(new LDAPMessage(searchOperation.getMessageID(),
+ protocolOp, searchReference.getControls()));
return true;
}
-
/**
* Sends the provided intermediate response message to the client.
*
- * @param intermediateResponse The intermediate response message to be sent.
- *
- * @return <CODE>true</CODE> if processing on the associated operation should
- * continue, or <CODE>false</CODE> if not.
+ * @param intermediateResponse
+ * The intermediate response message to be sent.
+ * @return <CODE>true</CODE> if processing on the associated operation
+ * should continue, or <CODE>false</CODE> if not.
*/
+ @Override
protected boolean sendIntermediateResponseMessage(
- IntermediateResponse intermediateResponse)
+ IntermediateResponse intermediateResponse)
{
IntermediateResponseProtocolOp protocolOp =
- new IntermediateResponseProtocolOp(intermediateResponse.getOID(),
- intermediateResponse.getValue());
+ new IntermediateResponseProtocolOp(intermediateResponse
+ .getOID(), intermediateResponse.getValue());
Operation operation = intermediateResponse.getOperation();
- List<Control> controls = intermediateResponse.getControls();
- ArrayList<LDAPControl> ldapControls =
- new ArrayList<LDAPControl>(controls.size());
- for (Control c : controls)
- {
- ldapControls.add(new LDAPControl(c));
- }
+ LDAPMessage message =
+ new LDAPMessage(operation.getMessageID(), protocolOp,
+ intermediateResponse.getControls());
+ sendLDAPMessage(message);
-
- LDAPMessage message = new LDAPMessage(operation.getMessageID(), protocolOp,
- ldapControls);
- sendLDAPMessage(securityProvider, message);
-
-
- // The only reason we shouldn't continue processing is if the connection is
- // closed.
+ // The only reason we shouldn't continue processing is if the
+ // connection is closed.
return connectionValid;
}
@@ -885,95 +758,92 @@
/**
* Sends the provided LDAP message to the client.
*
- * @param secProvider The connection security provider to use to handle any
- * necessary security translation.
- * @param message The LDAP message to send to the client.
+ * @param message
+ * The LDAP message to send to the client.
*/
- public void sendLDAPMessage(ConnectionSecurityProvider secProvider,
- LDAPMessage message)
+ public void sendLDAPMessage(LDAPMessage message)
{
- ASN1Element messageElement = message.encode();
-
- ByteBuffer messageBuffer = ByteBuffer.wrap(messageElement.encode());
-
-
- // Make sure that we can only send one message at a time. This locking will
- // not have any impact on the ability to read requests from the client.
- synchronized (transmitLock)
+ // Get the buffer used by this thread.
+ WriterBuffer writerBuffer = cachedBuffers.get();
+ if (writerBuffer == null)
{
- try
+ writerBuffer = new WriterBuffer();
+ // TODO SASLPhase2 maybe don't want to cache these
+ if (isSecure())
{
- try
+ int appBufSize = activeProvider.getAppBufSize();
+ writerBuffer.writer = ASN1.getWriter(saslChannel, appBufSize);
+ }
+ else
+ writerBuffer.writer = ASN1.getWriter(saslChannel, 4096);
+ cachedBuffers.set(writerBuffer);
+ }
+ try
+ {
+ // Make sure that we can only send one message at a time. This
+ // locking will not have any impact on the ability to read
+ // requests from the client.
+ synchronized (transmitLock)
+ {
+ message.write(writerBuffer.writer);
+ writerBuffer.writer.flush();
+ if(debugEnabled())
{
- int bytesWritten = messageBuffer.limit() - messageBuffer.position();
- if (! secProvider.writeData(messageBuffer))
- {
- return;
- }
+ TRACER.debugProtocolElement(DebugLogLevel.VERBOSE,
+ message.toString());
- TRACER.debugProtocolElement(DebugLogLevel.VERBOSE, message);
- TRACER.debugProtocolElement(DebugLogLevel.VERBOSE, messageElement);
-
- messageBuffer.rewind();
- if (debugEnabled())
- {
- TRACER.debugData(DebugLogLevel.VERBOSE, messageBuffer);
- }
-
- if (keepStats)
- {
- statTracker.updateMessageWritten(message, bytesWritten);
- }
+ // TODO SASLPhase2 message buffer?
+ // TRACER.debugData(DebugLogLevel.VERBOSE, messageBuffer);
}
- catch (@Deprecated Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- // We were unable to send the message due to some other internal
- // problem. Disconnect from the client and return.
- disconnect(DisconnectReason.SERVER_ERROR, true, null);
- return;
+ if (keepStats)
+ {
+ // TODO SASLPhase2 hard-coded for now, flush probably needs to
+ // return how many bytes were flushed.
+ statTracker.updateMessageWritten(message, 4096);
}
}
- catch (Exception e)
+ // writerBuffer.buffer.clear();
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
{
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- // FIXME -- Log a message or something
- disconnect(DisconnectReason.SERVER_ERROR, true, null);
- return;
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
+
+ // FIXME -- Log a message or something
+ disconnect(DisconnectReason.SERVER_ERROR, true, null);
+ return;
}
}
/**
- * Closes the connection to the client, optionally sending it a message
- * indicating the reason for the closure. Note that the ability to send a
- * notice of disconnection may not be available for all protocols or under all
- * circumstances.
+ * Closes the connection to the client, optionally sending it a
+ * message indicating the reason for the closure. Note that the
+ * ability to send a notice of disconnection may not be available for
+ * all protocols or under all circumstances.
*
- * @param disconnectReason The disconnect reason that provides the generic
- * cause for the disconnect.
- * @param sendNotification Indicates whether to try to provide notification
- * to the client that the connection will be closed.
- * @param message The message to include in the disconnect
- * notification response. It may be
- * <CODE>null</CODE> if no message is to be sent.
+ * @param disconnectReason
+ * The disconnect reason that provides the generic cause for
+ * the disconnect.
+ * @param sendNotification
+ * Indicates whether to try to provide notification to the
+ * client that the connection will be closed.
+ * @param message
+ * The message to include in the disconnect notification
+ * response. It may be <CODE>null</CODE> if no message is to
+ * be sent.
*/
+ @Override
public void disconnect(DisconnectReason disconnectReason,
- boolean sendNotification,
- Message message)
+ boolean sendNotification, Message message)
{
- // Set a flag indicating that the connection is being terminated so that no
- // new requests will be accepted. Also cancel all operations in progress.
+ // Set a flag indicating that the connection is being terminated so
+ // that no new requests will be accepted. Also cancel all operations
+ // in progress.
synchronized (opsInProgressLock)
{
// If we are already in the middle of a disconnect, then don't
@@ -986,7 +856,6 @@
disconnectRequested = true;
}
-
if (keepStats)
{
statTracker.updateDisconnect();
@@ -997,26 +866,25 @@
DirectoryServer.connectionClosed(this);
}
-
// Indicate that this connection is no longer valid.
connectionValid = false;
- if(message != null)
+ if (message != null)
{
MessageBuilder msgBuilder = new MessageBuilder();
msgBuilder.append(disconnectReason.getClosureMessage());
msgBuilder.append(": ");
msgBuilder.append(message);
- cancelAllOperations(new CancelRequest(true, msgBuilder.toMessage()));
+ cancelAllOperations(new CancelRequest(true, msgBuilder
+ .toMessage()));
}
else
{
- cancelAllOperations(new CancelRequest(true,
- disconnectReason.getClosureMessage()));
+ cancelAllOperations(new CancelRequest(true, disconnectReason
+ .getClosureMessage()));
}
finalizeConnectionInternal();
-
// If there is a write selector for this connection, then close it.
Selector selector = writeSelector.get();
if (selector != null)
@@ -1024,13 +892,16 @@
try
{
selector.close();
- } catch (Exception e) {}
+ }
+ catch (Exception e)
+ {
+ }
}
-
- // See if we should send a notification to the client. If so, then
- // construct and send a notice of disconnection unsolicited response.
- // Note that we cannot send this notification to an LDAPv2 client.
+ // See if we should send a notification to the client. If so, then
+ // construct and send a notice of disconnection unsolicited
+ // response. Note that we cannot send this notification to an LDAPv2
+ // client.
if (sendNotification && (ldapVersion != 2))
{
try
@@ -1038,70 +909,63 @@
int resultCode;
switch (disconnectReason)
{
- case PROTOCOL_ERROR:
- resultCode = LDAPResultCode.PROTOCOL_ERROR;
- break;
- case SERVER_SHUTDOWN:
- resultCode = LDAPResultCode.UNAVAILABLE;
- break;
- case SERVER_ERROR:
- resultCode =
- DirectoryServer.getServerErrorResultCode().getIntValue();
- break;
- case ADMIN_LIMIT_EXCEEDED:
- case IDLE_TIME_LIMIT_EXCEEDED:
- case MAX_REQUEST_SIZE_EXCEEDED:
- case IO_TIMEOUT:
- resultCode = LDAPResultCode.ADMIN_LIMIT_EXCEEDED;
- break;
- case CONNECTION_REJECTED:
- resultCode = LDAPResultCode.CONSTRAINT_VIOLATION;
- break;
- default:
- resultCode = LDAPResultCode.OTHER;
- break;
+ case PROTOCOL_ERROR:
+ resultCode = LDAPResultCode.PROTOCOL_ERROR;
+ break;
+ case SERVER_SHUTDOWN:
+ resultCode = LDAPResultCode.UNAVAILABLE;
+ break;
+ case SERVER_ERROR:
+ resultCode =
+ DirectoryServer.getServerErrorResultCode().getIntValue();
+ break;
+ case ADMIN_LIMIT_EXCEEDED:
+ case IDLE_TIME_LIMIT_EXCEEDED:
+ case MAX_REQUEST_SIZE_EXCEEDED:
+ case IO_TIMEOUT:
+ resultCode = LDAPResultCode.ADMIN_LIMIT_EXCEEDED;
+ break;
+ case CONNECTION_REJECTED:
+ resultCode = LDAPResultCode.CONSTRAINT_VIOLATION;
+ break;
+ default:
+ resultCode = LDAPResultCode.OTHER;
+ break;
}
-
Message errMsg;
if (message == null)
{
- errMsg = INFO_LDAP_CLIENT_GENERIC_NOTICE_OF_DISCONNECTION.get();
+ errMsg =
+ INFO_LDAP_CLIENT_GENERIC_NOTICE_OF_DISCONNECTION.get();
}
else
{
errMsg = message;
}
-
ExtendedResponseProtocolOp notificationOp =
- new ExtendedResponseProtocolOp(resultCode, errMsg, null, null,
- OID_NOTICE_OF_DISCONNECTION, null);
- byte[] messageBytes =
- new LDAPMessage(0, notificationOp, null).encode().encode();
- ByteBuffer buffer = ByteBuffer.wrap(messageBytes);
- try
- {
- securityProvider.writeData(buffer);
- } catch (Exception e) {}
+ new ExtendedResponseProtocolOp(resultCode, errMsg, null,
+ null, OID_NOTICE_OF_DISCONNECTION, null);
+
+ sendLDAPMessage(new LDAPMessage(0, notificationOp, null));
}
catch (Exception e)
{
- // NYI -- Log a message indicating that we couldn't send the notice of
- // disconnection.
+ // NYI -- Log a message indicating that we couldn't send the
+ // notice of disconnection.
}
}
-
// Close the connection to the client.
try
{
- securityProvider.disconnect(sendNotification);
+ asn1Reader.close();
}
catch (Exception e)
{
- // In general, we don't care about any exception that might be thrown
- // here.
+ // In general, we don't care about any exception that might be
+ // thrown here.
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
@@ -1114,29 +978,29 @@
}
catch (Exception e)
{
- // In general, we don't care about any exception that might be thrown
- // here.
+ // In general, we don't care about any exception that might be
+ // thrown here.
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
}
+ // Remove the thread local buffers.
+ cachedBuffers.remove();
// NYI -- Deregister the client connection from any server components that
// might know about it.
-
// Log a disconnect message.
logDisconnect(this, disconnectReason, message);
-
try
{
PluginConfigManager pluginManager =
- DirectoryServer.getPluginConfigManager();
+ DirectoryServer.getPluginConfigManager();
pluginManager.invokePostDisconnectPlugins(this, disconnectReason,
- message);
+ message);
}
catch (Exception e)
{
@@ -1150,11 +1014,13 @@
/**
- * Retrieves the set of operations in progress for this client connection.
- * This list must not be altered by any caller.
+ * Retrieves the set of operations in progress for this client
+ * connection. This list must not be altered by any caller.
*
- * @return The set of operations in progress for this client connection.
+ * @return The set of operations in progress for this client
+ * connection.
*/
+ @Override
public Collection<Operation> getOperationsInProgress()
{
return operationsInProgress.values();
@@ -1165,11 +1031,12 @@
/**
* Retrieves the operation in progress with the specified message ID.
*
- * @param messageID The message ID for the operation to retrieve.
- *
- * @return The operation in progress with the specified message ID, or
- * <CODE>null</CODE> if no such operation could be found.
+ * @param messageID
+ * The message ID for the operation to retrieve.
+ * @return The operation in progress with the specified message ID, or
+ * <CODE>null</CODE> if no such operation could be found.
*/
+ @Override
public Operation getOperationInProgress(int messageID)
{
return operationsInProgress.get(messageID);
@@ -1178,56 +1045,59 @@
/**
- * Adds the provided operation to the set of operations in progress for this
- * client connection.
+ * Adds the provided operation to the set of operations in progress
+ * for this client connection.
*
- * @param operation The operation to add to the set of operations in
- * progress for this client connection.
- *
- * @throws DirectoryException If the operation is not added for some reason
- * (e.g., the client already has reached the
- * maximum allowed concurrent requests).
+ * @param operation
+ * The operation to add to the set of operations in progress
+ * for this client connection.
+ * @throws DirectoryException
+ * If the operation is not added for some reason (e.g., the
+ * client already has reached the maximum allowed concurrent
+ * requests).
*/
public void addOperationInProgress(AbstractOperation operation)
- throws DirectoryException
+ throws DirectoryException
{
int messageID = operation.getMessageID();
- // We need to grab a lock to ensure that no one else can add operations to
- // the queue while we are performing some preliminary checks.
+ // We need to grab a lock to ensure that no one else can add
+ // operations to the queue while we are performing some preliminary
+ // checks.
synchronized (opsInProgressLock)
{
try
{
- // If we're already in the process of disconnecting the client, then
- // reject the operation.
+ // If we're already in the process of disconnecting the client,
+ // then reject the operation.
if (disconnectRequested)
{
- Message message = WARN_LDAP_CLIENT_DISCONNECT_IN_PROGRESS.get();
+ Message message =
+ WARN_LDAP_CLIENT_DISCONNECT_IN_PROGRESS.get();
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- message);
+ message);
}
-
- // See if there is already an operation in progress with the same
- // message ID. If so, then we can't allow it.
+ // See if there is already an operation in progress with the
+ // same message ID. If so, then we can't allow it.
Operation op = operationsInProgress.get(messageID);
if (op != null)
{
Message message =
- WARN_LDAP_CLIENT_DUPLICATE_MESSAGE_ID.get(messageID);
- throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
+ WARN_LDAP_CLIENT_DUPLICATE_MESSAGE_ID.get(messageID);
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
+ message);
}
-
- // Add the operation to the list of operations in progress for this
- // connection.
+ // Add the operation to the list of operations in progress for
+ // this connection.
operationsInProgress.put(messageID, operation);
-
// Try to add the operation to the work queue,
- // or run it synchronously (typically for the administration connector)
- connectionHandler.getQueueingStrategy().enqueueRequest(operation);
+ // or run it synchronously (typically for the administration
+ // connector)
+ connectionHandler.getQueueingStrategy().enqueueRequest(
+ operation);
}
catch (DirectoryException de)
{
@@ -1250,8 +1120,8 @@
Message message =
WARN_LDAP_CLIENT_CANNOT_ENQUEUE.get(getExceptionMessage(e));
- throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
- message, e);
+ throw new DirectoryException(DirectoryServer
+ .getServerErrorResultCode(), message, e);
}
}
}
@@ -1259,16 +1129,19 @@
/**
- * Removes the provided operation from the set of operations in progress for
- * this client connection. Note that this does not make any attempt to
- * cancel any processing that may already be in progress for the operation.
+ * Removes the provided operation from the set of operations in
+ * progress for this client connection. Note that this does not make
+ * any attempt to cancel any processing that may already be in
+ * progress for the operation.
*
- * @param messageID The message ID of the operation to remove from the set
- * of operations in progress.
- *
- * @return <CODE>true</CODE> if the operation was found and removed from the
- * set of operations in progress, or <CODE>false</CODE> if not.
+ * @param messageID
+ * The message ID of the operation to remove from the set of
+ * operations in progress.
+ * @return <CODE>true</CODE> if the operation was found and removed
+ * from the set of operations in progress, or
+ * <CODE>false</CODE> if not.
*/
+ @Override
public boolean removeOperationInProgress(int messageID)
{
Operation operation = operationsInProgress.remove(messageID);
@@ -1288,15 +1161,17 @@
/**
* Attempts to cancel the specified operation.
*
- * @param messageID The message ID of the operation to cancel.
- * @param cancelRequest An object providing additional information about how
- * the cancel should be processed.
- *
- * @return A cancel result that either indicates that the cancel was
- * successful or provides a reason that it was not.
+ * @param messageID
+ * The message ID of the operation to cancel.
+ * @param cancelRequest
+ * An object providing additional information about how the
+ * cancel should be processed.
+ * @return A cancel result that either indicates that the cancel was
+ * successful or provides a reason that it was not.
*/
+ @Override
public CancelResult cancelOperation(int messageID,
- CancelRequest cancelRequest)
+ CancelRequest cancelRequest)
{
Operation op = operationsInProgress.get(messageID);
if (op == null)
@@ -1331,9 +1206,11 @@
/**
* Attempts to cancel all operations in progress on this connection.
*
- * @param cancelRequest An object providing additional information about how
- * the cancel should be processed.
+ * @param cancelRequest
+ * An object providing additional information about how the
+ * cancel should be processed.
*/
+ @Override
public void cancelAllOperations(CancelRequest cancelRequest)
{
// Make sure that no one can add any new operations.
@@ -1362,15 +1239,14 @@
}
}
- if (! (operationsInProgress.isEmpty() &&
- getPersistentSearches().isEmpty()))
+ if (!(operationsInProgress.isEmpty() && getPersistentSearches()
+ .isEmpty()))
{
lastCompletionTime.set(TimeThread.getTime());
}
operationsInProgress.clear();
-
for (PersistentSearch persistentSearch : getPersistentSearches())
{
persistentSearch.cancel();
@@ -1389,16 +1265,19 @@
/**
- * Attempts to cancel all operations in progress on this connection except the
- * operation with the specified message ID.
+ * Attempts to cancel all operations in progress on this connection
+ * except the operation with the specified message ID.
*
- * @param cancelRequest An object providing additional information about how
- * the cancel should be processed.
- * @param messageID The message ID of the operation that should not be
- * canceled.
+ * @param cancelRequest
+ * An object providing additional information about how the
+ * cancel should be processed.
+ * @param messageID
+ * The message ID of the operation that should not be
+ * canceled.
*/
+ @Override
public void cancelAllOperationsExcept(CancelRequest cancelRequest,
- int messageID)
+ int messageID)
{
// Make sure that no one can add any new operations.
synchronized (opsInProgressLock)
@@ -1438,7 +1317,6 @@
lastCompletionTime.set(TimeThread.getTime());
}
-
for (PersistentSearch persistentSearch : getPersistentSearches())
{
if (persistentSearch.getMessageID() == messageID)
@@ -1474,7 +1352,7 @@
try
{
selector = Selector.open();
- if (! writeSelector.compareAndSet(null, selector))
+ if (!writeSelector.compareAndSet(null, selector))
{
selector.close();
selector = writeSelector.get();
@@ -1506,308 +1384,109 @@
/**
- * Returns the total number of operations initiated on this connection.
+ * Returns the total number of operations initiated on this
+ * connection.
*
* @return the total number of operations on this connection
*/
- public long getNumberOfOperations() {
+ @Override
+ public long getNumberOfOperations()
+ {
long tmpNumberOfOperations;
- synchronized (operationsPerformedLock) {
+ synchronized (operationsPerformedLock)
+ {
tmpNumberOfOperations = operationsPerformed;
}
return tmpNumberOfOperations;
}
+
/**
- * Process the information contained in the provided byte buffer as an ASN.1
- * element. It may take several calls to this method in order to get all the
- * information necessary to decode a single ASN.1 element, but it may also be
- * possible that there are multiple elements (or at least fragments of
- * multiple elements) in a single buffer. This will fully process whatever
- * the client provided and set up the appropriate state information to make it
- * possible to pick up in the right place the next time around.
+ * Process data read.
*
- * @param buffer The buffer containing the data to be processed. It must be
- * ready for reading (i.e., it should have been flipped by the
- * caller), and the data provided must be unencrypted (e.g.,
- * if the client is communicating over SSL, then the
- * decryption should happen before calling this method).
- *
- * @return <CODE>true</CODE> if all the data in the provided buffer was
- * processed and the client connection can remain established, or
- * <CODE>false</CODE> if a decoding error occurred and requests from
- * this client should no longer be processed. Note that if this
- * method does return <CODE>false</CODE>, then it must have already
- * disconnected the client, and upon returning the request handler
- * should remove it from the associated selector.
+ * @return {@code true} if this connection is still valid.
*/
- public boolean processDataRead(ByteBuffer buffer)
+ public boolean processDataRead()
{
- if (debugEnabled())
+ if (this.saslPendingProvider != null)
{
- TRACER.debugData(DebugLogLevel.VERBOSE, buffer);
+ enableSASL();
}
-
-
- int bytesAvailable = buffer.limit() - buffer.position();
-
- if (keepStats)
+ while (true)
{
- statTracker.updateBytesRead(bytesAvailable);
- }
-
- while (bytesAvailable > 0)
- {
- switch (elementReadState)
+ try
{
- case ELEMENT_READ_STATE_NEED_TYPE:
- // Read just the type and then loop again to see if there is more.
- elementType = buffer.get();
- bytesAvailable--;
- elementReadState = ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
- continue;
-
-
- case ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE:
- // Get the first length byte and see if it is a single-byte or
- // multi-byte length.
- byte firstLengthByte = buffer.get();
- bytesAvailable--;
- elementLengthBytesNeeded = (firstLengthByte & 0x7F);
- if (elementLengthBytesNeeded == firstLengthByte)
- {
- elementLength = firstLengthByte;
-
- // If the length is zero, then it cannot be a valid LDAP message.
- if (elementLength == 0)
- {
- disconnect(DisconnectReason.PROTOCOL_ERROR, true,
- ERR_LDAP_CLIENT_DECODE_ZERO_BYTE_VALUE.get());
- return false;
- }
-
- // Make sure that the element is not larger than the maximum allowed
- // message size.
- if ((connectionHandler.getMaxRequestSize() > 0) &&
- (elementLength > connectionHandler.getMaxRequestSize()))
- {
- Message m = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED.get(
- elementLength, connectionHandler.getMaxRequestSize());
- disconnect(DisconnectReason.MAX_REQUEST_SIZE_EXCEEDED, true, m);
- return false;
- }
-
- elementValue = new byte[elementLength];
- elementValueBytesRead = 0;
- elementValueBytesNeeded = elementLength;
- elementReadState = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
- continue;
- }
- else
- {
- if (elementLengthBytesNeeded > 4)
- {
- // We cannot handle multi-byte lengths in which more than four
- // bytes are used to encode the length.
- Message m = ERR_LDAP_CLIENT_DECODE_INVALID_MULTIBYTE_LENGTH.get(
- elementLengthBytesNeeded);
- disconnect(DisconnectReason.PROTOCOL_ERROR, true, m);
- return false;
- }
-
- elementLength = 0x00;
- if (elementLengthBytesNeeded <= bytesAvailable)
- {
- // We can read the entire length, so do it.
- while (elementLengthBytesNeeded > 0)
- {
- elementLength = (elementLength << 8) | (buffer.get() & 0xFF);
- bytesAvailable--;
- elementLengthBytesNeeded--;
- }
-
- // If the length is zero, then it cannot be a valid LDAP message.
- if (elementLength == 0)
- {
- disconnect(DisconnectReason.PROTOCOL_ERROR, true,
- ERR_LDAP_CLIENT_DECODE_ZERO_BYTE_VALUE.get());
- return false;
- }
-
- // Make sure that the element is not larger than the maximum
- // allowed message size.
- if ((connectionHandler.getMaxRequestSize() > 0) &&
- (elementLength > connectionHandler.getMaxRequestSize()))
- {
- disconnect(DisconnectReason.MAX_REQUEST_SIZE_EXCEEDED, true,
- ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED.get(
- elementLength,
- connectionHandler.getMaxRequestSize()));
- return false;
- }
-
- elementValue = new byte[elementLength];
- elementValueBytesRead = 0;
- elementValueBytesNeeded = elementLength;
- elementReadState = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
- continue;
- }
- else
- {
- // We can't read the entire length, so just read what is
- // available.
- while (bytesAvailable > 0)
- {
- elementLength = (elementLength << 8) | (buffer.get() & 0xFF);
- bytesAvailable--;
- elementLengthBytesNeeded--;
- }
-
- return true;
- }
- }
-
-
- case ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES:
- if (bytesAvailable >= elementLengthBytesNeeded)
- {
- // We have enough data available to be able to read the entire
- // length. Do so.
- while (elementLengthBytesNeeded > 0)
- {
- elementLength = (elementLength << 8) | (buffer.get() & 0xFF);
- bytesAvailable--;
- elementLengthBytesNeeded--;
- }
-
- // If the length is zero, then it cannot be a valid LDAP message.
- if (elementLength == 0)
- {
- disconnect(DisconnectReason.PROTOCOL_ERROR, true,
- ERR_LDAP_CLIENT_DECODE_ZERO_BYTE_VALUE.get());
- return false;
- }
-
- // Make sure that the element is not larger than the maximum allowed
- // message size.
- if ((connectionHandler.getMaxRequestSize() > 0) &&
- (elementLength > connectionHandler.getMaxRequestSize()))
- {
- disconnect(DisconnectReason.MAX_REQUEST_SIZE_EXCEEDED, true,
- ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED.get(
- elementLength,
- connectionHandler.getMaxRequestSize()));
- return false;
- }
-
- elementValue = new byte[elementLength];
- elementValueBytesRead = 0;
- elementValueBytesNeeded = elementLength;
- elementReadState = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
- continue;
- }
- else
- {
- // We still don't have enough data to complete the length, so just
- // read as much as possible.
- while (bytesAvailable > 0)
- {
- elementLength = (elementLength << 8) | (buffer.get() & 0xFF);
- bytesAvailable--;
- elementLengthBytesNeeded--;
- }
-
- return true;
- }
-
-
- case ELEMENT_READ_STATE_NEED_VALUE_BYTES:
- if (bytesAvailable >= elementValueBytesNeeded)
- {
- // We have enough data available to fully read the value. Finish
- // reading the information and convert it to an ASN.1 element. Then
- // decode that as an LDAP message.
- buffer.get(elementValue, elementValueBytesRead,
- elementValueBytesNeeded);
- elementValueBytesRead += elementValueBytesNeeded;
- bytesAvailable -= elementValueBytesNeeded;
- elementReadState = ELEMENT_READ_STATE_NEED_TYPE;
-
- ASN1Sequence requestSequence;
- try
- {
- requestSequence = ASN1Sequence.decodeAsSequence(elementType,
- elementValue);
- TRACER.debugProtocolElement(DebugLogLevel.VERBOSE,
- requestSequence);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- Message m = ERR_LDAP_CLIENT_DECODE_ASN1_FAILED.get(
- String.valueOf(e));
- disconnect(DisconnectReason.PROTOCOL_ERROR, true, m);
- return false;
- }
-
- LDAPMessage requestMessage;
- try
- {
- requestMessage = LDAPMessage.decode(requestSequence);
- TRACER.debugProtocolElement(DebugLogLevel.VERBOSE,
- requestMessage);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- Message m = ERR_LDAP_CLIENT_DECODE_LDAP_MESSAGE_FAILED.get(
- String.valueOf(e));
- disconnect(DisconnectReason.PROTOCOL_ERROR, true, m);
- return false;
- }
-
- if (processLDAPMessage(requestMessage))
- {
- continue;
- }
- else
- {
- return false;
- }
- }
- else
- {
- // We can't read all the value, so just read as much as we have
- // available and pick it up again the next time around.
- buffer.get(elementValue, elementValueBytesRead, bytesAvailable);
- elementValueBytesRead += bytesAvailable;
- elementValueBytesNeeded -= bytesAvailable;
- return true;
- }
-
-
- default:
- // This should never happen. There is an invalid internal read state.
- // The only recourse that we have is to log a message and disconnect
- // the client.
- Message message =
- ERR_LDAP_CLIENT_INVALID_DECODE_STATE.get(elementReadState);
- logError(message);
- disconnect(DisconnectReason.SERVER_ERROR, true, message);
+ int result = asn1Reader.processChannelData();
+ if (result < 0)
+ {
+ // The connection has been closed by the client. Disconnect
+ // and return.
+ disconnect(DisconnectReason.CLIENT_DISCONNECT, false, null);
return false;
+ }
+ if (result == 0)
+ {
+ // We have read all the data that there is to read right now
+ // (or there wasn't any in the first place). Just return and
+ // wait for future notification.
+ return true;
+ }
+ else
+ {
+ // Decode all complete elements from the last read
+ while (asn1Reader.elementAvailable())
+ {
+ processLDAPMessage(LDAPReader.readMessage(asn1Reader));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ Message m =
+ ERR_LDAP_CLIENT_DECODE_LDAP_MESSAGE_FAILED.get(String
+ .valueOf(e));
+ disconnect(DisconnectReason.PROTOCOL_ERROR, true, m);
+ return false;
}
}
+ }
- // If we've gotten here, then all of the data must have been processed
- // properly so we can return true.
+
+ /**
+ * Process the information contained in the provided byte buffer as an
+ * ASN.1 element. It may take several calls to this method in order to
+ * get all the information necessary to decode a single ASN.1 element,
+ * but it may also be possible that there are multiple elements (or at
+ * least fragments of multiple elements) in a single buffer. This will
+ * fully process whatever the client provided and set up the
+ * appropriate state information to make it possible to pick up in the
+ * right place the next time around.
+ *
+ * @param buffer
+ * The buffer containing the data to be processed. It must be
+ * ready for reading (i.e., it should have been flipped by
+ * the caller), and the data provided must be unencrypted
+ * (e.g., if the client is communicating over SSL, then the
+ * decryption should happen before calling this method).
+ * @return <CODE>true</CODE> if all the data in the provided buffer
+ * was processed and the client connection can remain
+ * established, or <CODE>false</CODE> if a decoding error
+ * occurred and requests from this client should no longer be
+ * processed. Note that if this method does return
+ * <CODE>false</CODE>, then it must have already disconnected
+ * the client, and upon returning the request handler should
+ * remove it from the associated selector.
+ */
+ @Override
+ public boolean processDataRead(ByteBuffer buffer)
+ {
+ // this is no longer used.
return true;
}
@@ -1815,16 +1494,16 @@
/**
* Processes the provided LDAP message read from the client and takes
- * whatever action is appropriate. For most requests, this will include
- * placing the operation in the work queue. Certain requests (in particular,
- * abandons and unbinds) will be processed directly.
+ * whatever action is appropriate. For most requests, this will
+ * include placing the operation in the work queue. Certain requests
+ * (in particular, abandons and unbinds) will be processed directly.
*
- * @param message The LDAP message to process.
- *
- * @return <CODE>true</CODE> if the appropriate action was taken for the
- * request, or <CODE>false</CODE> if there was a fatal error and
- * the client has been disconnected as a result, or if the client
- * unbound from the server.
+ * @param message
+ * The LDAP message to process.
+ * @return <CODE>true</CODE> if the appropriate action was taken for
+ * the request, or <CODE>false</CODE> if there was a fatal
+ * error and the client has been disconnected as a result, or
+ * if the client unbound from the server.
*/
private boolean processLDAPMessage(LDAPMessage message)
{
@@ -1833,126 +1512,124 @@
statTracker.updateMessageRead(message);
this.getNetworkGroup().updateMessageRead(message);
}
- synchronized (operationsPerformedLock) {
+ synchronized (operationsPerformedLock)
+ {
operationsPerformed++;
}
- ArrayList<Control> opControls;
- ArrayList<LDAPControl> ldapControls = message.getControls();
- if ((ldapControls == null) || ldapControls.isEmpty())
- {
- opControls = null;
- }
- else
- {
- opControls = new ArrayList<Control>(ldapControls.size());
- for (LDAPControl c : ldapControls)
- {
- opControls.add(c.getControl());
- }
- }
+ List<Control> opControls = message.getControls();
+ // FIXME -- See if there is a bind in progress. If so, then deny
+ // most kinds of operations.
- // FIXME -- See if there is a bind in progress. If so, then deny most
- // kinds of operations.
-
-
- // Figure out what type of operation we're dealing with based on the LDAP
- // message. Abandon and unbind requests will be processed here. All other
- // types of requests will be encapsulated into operations and put into the
- // work queue to be picked up by a worker thread. Any other kinds of
- // LDAP messages (e.g., response messages) are illegal and will result in
- // the connection being terminated.
+ // Figure out what type of operation we're dealing with based on the
+ // LDAP message. Abandon and unbind requests will be processed here.
+ // All other types of requests will be encapsulated into operations
+ // and append into the work queue to be picked up by a worker
+ // thread. Any other kinds of LDAP messages (e.g., response
+ // messages) are illegal and will result in the connection being
+ // terminated.
try
{
boolean result;
switch (message.getProtocolOpType())
{
- case OP_TYPE_ABANDON_REQUEST:
- if (keepStats) this.abandonMonitor.start();
- result=processAbandonRequest(message, opControls);
- if (keepStats) {
- this.abandonMonitor.stop();
- this.abandonMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_ADD_REQUEST:
- if (keepStats) this.addMonitor.start();
- result=processAddRequest(message, opControls);
- if (keepStats) {
- this.addMonitor.stop();
- this.addMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_BIND_REQUEST:
- if (keepStats) this.bindMonitor.start();
- result=processBindRequest(message, opControls);
- if (keepStats) {
- this.bindMonitor.stop();
- this.bindMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_COMPARE_REQUEST:
- if (keepStats) this.compareMonitor.start();
- result=processCompareRequest(message, opControls);
- if (keepStats) {
- this.compareMonitor.stop();
- this.compareMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_DELETE_REQUEST:
- if (keepStats) this.delMonitor.start();
- result=processDeleteRequest(message, opControls);
- if (keepStats) {
- this.delMonitor.stop();
- this.delMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_EXTENDED_REQUEST:
- if (keepStats) this.extendedMonitor.start();
- result=processExtendedRequest(message, opControls);
- if (keepStats) {
- this.extendedMonitor.stop();
- this.extendedMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_MODIFY_REQUEST:
- if (keepStats) this.modMonitor.start();
- result=processModifyRequest(message, opControls);
- if (keepStats) {
- this.modMonitor.stop();
- this.modMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_MODIFY_DN_REQUEST:
- if (keepStats) this.moddnMonitor.start();
- result=processModifyDNRequest(message, opControls);
- if (keepStats) {
- this.moddnMonitor.stop();
- this.moddnMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_SEARCH_REQUEST:
- if (keepStats) this.searchMonitor.start();
- result=processSearchRequest(message, opControls);
- if (keepStats) {
- this.searchMonitor.stop();
- this.searchMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- case OP_TYPE_UNBIND_REQUEST:
- if (keepStats) this.unbindMonitor.start();
- result=processUnbindRequest(message, opControls);
- if (keepStats) {
- this.unbindMonitor.stop();
- this.unbindMonitor.updateMonitorProvider(statTracker);
- }
- return result;
- default:
- Message msg = ERR_LDAP_DISCONNECT_DUE_TO_INVALID_REQUEST_TYPE.get(
- message.getProtocolOpName(), message.getMessageID());
- disconnect(DisconnectReason.PROTOCOL_ERROR, true, msg);
- return false;
+ case OP_TYPE_ABANDON_REQUEST:
+ if (keepStats) this.abandonMonitor.start();
+ result = processAbandonRequest(message, opControls);
+ if (keepStats)
+ {
+ this.abandonMonitor.stop();
+ this.abandonMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_ADD_REQUEST:
+ if (keepStats) this.addMonitor.start();
+ result = processAddRequest(message, opControls);
+ if (keepStats)
+ {
+ this.addMonitor.stop();
+ this.addMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_BIND_REQUEST:
+ if (keepStats) this.bindMonitor.start();
+ result = processBindRequest(message, opControls);
+ if (keepStats)
+ {
+ this.bindMonitor.stop();
+ this.bindMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_COMPARE_REQUEST:
+ if (keepStats) this.compareMonitor.start();
+ result = processCompareRequest(message, opControls);
+ if (keepStats)
+ {
+ this.compareMonitor.stop();
+ this.compareMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_DELETE_REQUEST:
+ if (keepStats) this.delMonitor.start();
+ result = processDeleteRequest(message, opControls);
+ if (keepStats)
+ {
+ this.delMonitor.stop();
+ this.delMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_EXTENDED_REQUEST:
+ if (keepStats) this.extendedMonitor.start();
+ result = processExtendedRequest(message, opControls);
+ if (keepStats)
+ {
+ this.extendedMonitor.stop();
+ this.extendedMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_MODIFY_REQUEST:
+ if (keepStats) this.modMonitor.start();
+ result = processModifyRequest(message, opControls);
+ if (keepStats)
+ {
+ this.modMonitor.stop();
+ this.modMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_MODIFY_DN_REQUEST:
+ if (keepStats) this.moddnMonitor.start();
+ result = processModifyDNRequest(message, opControls);
+ if (keepStats)
+ {
+ this.moddnMonitor.stop();
+ this.moddnMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_SEARCH_REQUEST:
+ if (keepStats) this.searchMonitor.start();
+ result = processSearchRequest(message, opControls);
+ if (keepStats)
+ {
+ this.searchMonitor.stop();
+ this.searchMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ case OP_TYPE_UNBIND_REQUEST:
+ if (keepStats) this.unbindMonitor.start();
+ result = processUnbindRequest(message, opControls);
+ if (keepStats)
+ {
+ this.unbindMonitor.stop();
+ this.unbindMonitor.updateMonitorProvider(statTracker);
+ }
+ return result;
+ default:
+ Message msg =
+ ERR_LDAP_DISCONNECT_DUE_TO_INVALID_REQUEST_TYPE.get(message
+ .getProtocolOpName(), message.getMessageID());
+ disconnect(DisconnectReason.PROTOCOL_ERROR, true, msg);
+ return false;
}
}
catch (Exception e)
@@ -1962,9 +1639,10 @@
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
- Message msg = ERR_LDAP_DISCONNECT_DUE_TO_PROCESSING_FAILURE.get(
- message.getProtocolOpName(),
- message.getMessageID(), String.valueOf(e));
+ Message msg =
+ ERR_LDAP_DISCONNECT_DUE_TO_PROCESSING_FAILURE.get(message
+ .getProtocolOpName(), message.getMessageID(), String
+ .valueOf(e));
disconnect(DisconnectReason.SERVER_ERROR, true, msg);
return false;
}
@@ -1975,24 +1653,26 @@
/**
* Processes the provided LDAP message as an abandon request.
*
- * @param message The LDAP message containing the abandon request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the abandon request to
+ * process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processAbandonRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- AbandonRequestProtocolOp protocolOp = message.getAbandonRequestProtocolOp();
+ AbandonRequestProtocolOp protocolOp =
+ message.getAbandonRequestProtocolOp();
AbandonOperationBasis abandonOp =
- new AbandonOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- protocolOp.getIDToAbandon());
+ new AbandonOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ protocolOp.getIDToAbandon());
abandonOp.run();
if (keepStats && (abandonOp.getResultCode() == ResultCode.CANCELED))
@@ -2008,37 +1688,39 @@
/**
* Processes the provided LDAP message as an add request.
*
- * @param message The LDAP message containing the add request to process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the add request to process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processAddRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- if ((ldapVersion == 2) && (controls != null) && (! controls.isEmpty()))
+ if ((ldapVersion == 2) && (controls != null)
+ && (!controls.isEmpty()))
{
// LDAPv2 clients aren't allowed to send controls.
AddResponseProtocolOp responseOp =
- new AddResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
+ new AddResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
return false;
}
// Create the add operation and add it into the work queue.
AddRequestProtocolOp protocolOp = message.getAddRequestProtocolOp();
AddOperationBasis addOp =
- new AddOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls, protocolOp.getDN(),
- protocolOp.getAttributes());
+ new AddOperationBasis(this, nextOperationID.getAndIncrement(),
+ message.getMessageID(), controls, protocolOp.getDN(),
+ protocolOp.getAttributes());
try
{
@@ -2052,24 +1734,14 @@
}
AddResponseProtocolOp responseOp =
- new AddResponseProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(), de.getMatchedDN(),
- de.getReferralURLs());
+ new AddResponseProtocolOp(de.getResultCode().getIntValue(),
+ de.getMessageObject(), de.getMatchedDN(), de
+ .getReferralURLs());
- List<Control> responseControls = addOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, addOp.getResponseControls()));
}
-
return connectionValid;
}
@@ -2078,91 +1750,92 @@
/**
* Processes the provided LDAP message as a bind request.
*
- * @param message The LDAP message containing the bind request to process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the bind request to process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processBindRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- BindRequestProtocolOp protocolOp = message.getBindRequestProtocolOp();
+ BindRequestProtocolOp protocolOp =
+ message.getBindRequestProtocolOp();
- // See if this is an LDAPv2 bind request, and if so whether that should be
- // allowed.
+ // See if this is an LDAPv2 bind request, and if so whether that
+ // should be allowed.
String versionString;
switch (ldapVersion = protocolOp.getProtocolVersion())
{
- case 2:
- versionString = "2";
+ case 2:
+ versionString = "2";
- if (! connectionHandler.allowLDAPv2())
- {
- BindResponseProtocolOp responseOp =
- new BindResponseProtocolOp(
- LDAPResultCode.INAPPROPRIATE_AUTHENTICATION,
- ERR_LDAPV2_CLIENTS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
- disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CLIENTS_NOT_ALLOWED.get());
- return false;
- }
+ if (!connectionHandler.allowLDAPv2())
+ {
+ BindResponseProtocolOp responseOp =
+ new BindResponseProtocolOp(
+ LDAPResultCode.INAPPROPRIATE_AUTHENTICATION,
+ ERR_LDAPV2_CLIENTS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
+ disconnect(DisconnectReason.PROTOCOL_ERROR, false,
+ ERR_LDAPV2_CLIENTS_NOT_ALLOWED.get());
+ return false;
+ }
- if ((controls != null) && (! controls.isEmpty()))
- {
- // LDAPv2 clients aren't allowed to send controls.
- BindResponseProtocolOp responseOp =
- new BindResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
- disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- return false;
- }
+ if ((controls != null) && (!controls.isEmpty()))
+ {
+ // LDAPv2 clients aren't allowed to send controls.
+ BindResponseProtocolOp responseOp =
+ new BindResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
+ disconnect(DisconnectReason.PROTOCOL_ERROR, false,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ return false;
+ }
- break;
- case 3:
- versionString = "3";
- break;
- default:
- versionString = String.valueOf(ldapVersion);
- break;
+ break;
+ case 3:
+ versionString = "3";
+ break;
+ default:
+ versionString = String.valueOf(ldapVersion);
+ break;
}
-
- ASN1OctetString bindDN = protocolOp.getDN();
+ ByteString bindDN = protocolOp.getDN();
BindOperationBasis bindOp;
switch (protocolOp.getAuthenticationType())
{
- case SIMPLE:
- bindOp = new BindOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- versionString, bindDN,
- protocolOp.getSimplePassword());
- break;
- case SASL:
- bindOp = new BindOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- versionString, bindDN,
- protocolOp.getSASLMechanism(),
- protocolOp.getSASLCredentials());
- break;
- default:
- // This is an invalid authentication type, and therefore a protocol
- // error. As per RFC 2251, a protocol error in a bind request must
- // result in terminating the connection.
- Message msg =
- ERR_LDAP_INVALID_BIND_AUTH_TYPE.get(message.getMessageID(),
- String.valueOf(protocolOp.getAuthenticationType()));
- disconnect(DisconnectReason.PROTOCOL_ERROR, true, msg);
- return false;
+ case SIMPLE:
+ bindOp =
+ new BindOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ versionString, bindDN, protocolOp.getSimplePassword());
+ break;
+ case SASL:
+ bindOp =
+ new BindOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ versionString, bindDN, protocolOp.getSASLMechanism(),
+ protocolOp.getSASLCredentials());
+ break;
+ default:
+ // This is an invalid authentication type, and therefore a
+ // protocol error. As per RFC 2251, a protocol error in a bind
+ // request must result in terminating the connection.
+ Message msg =
+ ERR_LDAP_INVALID_BIND_AUTH_TYPE.get(message.getMessageID(),
+ String.valueOf(protocolOp.getAuthenticationType()));
+ disconnect(DisconnectReason.PROTOCOL_ERROR, true, msg);
+ return false;
}
// Add the operation into the work queue.
@@ -2178,32 +1851,23 @@
}
BindResponseProtocolOp responseOp =
- new BindResponseProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(), de.getMatchedDN(),
- de.getReferralURLs());
+ new BindResponseProtocolOp(de.getResultCode().getIntValue(),
+ de.getMessageObject(), de.getMatchedDN(), de
+ .getReferralURLs());
- List<Control> responseControls = bindOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, bindOp.getResponseControls()));
// If it was a protocol error, then terminate the connection.
if (de.getResultCode() == ResultCode.PROTOCOL_ERROR)
{
- Message msg = ERR_LDAP_DISCONNECT_DUE_TO_BIND_PROTOCOL_ERROR.get(
- message.getMessageID(), de.getMessageObject());
+ Message msg =
+ ERR_LDAP_DISCONNECT_DUE_TO_BIND_PROTOCOL_ERROR.get(message
+ .getMessageID(), de.getMessageObject());
disconnect(DisconnectReason.PROTOCOL_ERROR, true, msg);
}
}
-
return connectionValid;
}
@@ -2212,38 +1876,41 @@
/**
* Processes the provided LDAP message as a compare request.
*
- * @param message The LDAP message containing the compare request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the compare request to
+ * process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processCompareRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- if ((ldapVersion == 2) && (controls != null) && (! controls.isEmpty()))
+ if ((ldapVersion == 2) && (controls != null)
+ && (!controls.isEmpty()))
{
// LDAPv2 clients aren't allowed to send controls.
CompareResponseProtocolOp responseOp =
- new CompareResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
+ new CompareResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
return false;
}
- CompareRequestProtocolOp protocolOp = message.getCompareRequestProtocolOp();
+ CompareRequestProtocolOp protocolOp =
+ message.getCompareRequestProtocolOp();
CompareOperationBasis compareOp =
- new CompareOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- protocolOp.getDN(), protocolOp.getAttributeType(),
- protocolOp.getAssertionValue());
+ new CompareOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ protocolOp.getDN(), protocolOp.getAttributeType(),
+ protocolOp.getAssertionValue());
// Add the operation into the work queue.
try
@@ -2258,25 +1925,14 @@
}
CompareResponseProtocolOp responseOp =
- new CompareResponseProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(),
- de.getMatchedDN(),
- de.getReferralURLs());
+ new CompareResponseProtocolOp(de.getResultCode()
+ .getIntValue(), de.getMessageObject(), de.getMatchedDN(),
+ de.getReferralURLs());
- List<Control> responseControls = compareOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, compareOp.getResponseControls()));
}
-
return connectionValid;
}
@@ -2285,37 +1941,39 @@
/**
* Processes the provided LDAP message as a delete request.
*
- * @param message The LDAP message containing the delete request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the delete request to process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processDeleteRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- if ((ldapVersion == 2) && (controls != null) && (! controls.isEmpty()))
+ if ((ldapVersion == 2) && (controls != null)
+ && (!controls.isEmpty()))
{
// LDAPv2 clients aren't allowed to send controls.
DeleteResponseProtocolOp responseOp =
- new DeleteResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
+ new DeleteResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
return false;
}
- DeleteRequestProtocolOp protocolOp = message.getDeleteRequestProtocolOp();
+ DeleteRequestProtocolOp protocolOp =
+ message.getDeleteRequestProtocolOp();
DeleteOperationBasis deleteOp =
- new DeleteOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- protocolOp.getDN());
+ new DeleteOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ protocolOp.getDN());
// Add the operation into the work queue.
try
@@ -2330,25 +1988,14 @@
}
DeleteResponseProtocolOp responseOp =
- new DeleteResponseProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(),
- de.getMatchedDN(),
- de.getReferralURLs());
+ new DeleteResponseProtocolOp(
+ de.getResultCode().getIntValue(), de.getMessageObject(),
+ de.getMatchedDN(), de.getReferralURLs());
- List<Control> responseControls = deleteOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, deleteOp.getResponseControls()));
}
-
return connectionValid;
}
@@ -2357,43 +2004,44 @@
/**
* Processes the provided LDAP message as an extended request.
*
- * @param message The LDAP message containing the extended request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the extended request to
+ * process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processExtendedRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- // See if this is an LDAPv2 client. If it is, then they should not be
- // issuing extended requests. We can't send a response that we can be sure
- // they can understand, so we have no choice but to close the connection.
+ // See if this is an LDAPv2 client. If it is, then they should not
+ // be issuing extended requests. We can't send a response that we
+ // can be sure they can understand, so we have no choice but to
+ // close the connection.
if (ldapVersion == 2)
{
- Message msg = ERR_LDAPV2_EXTENDED_REQUEST_NOT_ALLOWED.get(
- getConnectionID(), message.getMessageID());
+ Message msg =
+ ERR_LDAPV2_EXTENDED_REQUEST_NOT_ALLOWED.get(
+ getConnectionID(), message.getMessageID());
logError(msg);
disconnect(DisconnectReason.PROTOCOL_ERROR, false, msg);
return false;
}
-
// FIXME -- Do we need to handle certain types of request here?
// -- StartTLS requests
// -- Cancel requests
-
ExtendedRequestProtocolOp protocolOp =
- message.getExtendedRequestProtocolOp();
+ message.getExtendedRequestProtocolOp();
ExtendedOperationBasis extendedOp =
- new ExtendedOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- protocolOp.getOID(), protocolOp.getValue());
+ new ExtendedOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ protocolOp.getOID(), protocolOp.getValue());
// Add the operation into the work queue.
try
@@ -2408,25 +2056,14 @@
}
ExtendedResponseProtocolOp responseOp =
- new ExtendedResponseProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(),
- de.getMatchedDN(),
- de.getReferralURLs());
+ new ExtendedResponseProtocolOp(de.getResultCode()
+ .getIntValue(), de.getMessageObject(), de.getMatchedDN(),
+ de.getReferralURLs());
- List<Control> responseControls = extendedOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, extendedOp.getResponseControls()));
}
-
return connectionValid;
}
@@ -2435,37 +2072,39 @@
/**
* Processes the provided LDAP message as a modify request.
*
- * @param message The LDAP message containing the modify request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the modify request to process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processModifyRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- if ((ldapVersion == 2) && (controls != null) && (! controls.isEmpty()))
+ if ((ldapVersion == 2) && (controls != null)
+ && (!controls.isEmpty()))
{
// LDAPv2 clients aren't allowed to send controls.
ModifyResponseProtocolOp responseOp =
- new ModifyResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
+ new ModifyResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
return false;
}
- ModifyRequestProtocolOp protocolOp = message.getModifyRequestProtocolOp();
+ ModifyRequestProtocolOp protocolOp =
+ message.getModifyRequestProtocolOp();
ModifyOperationBasis modifyOp =
- new ModifyOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- protocolOp.getDN(), protocolOp.getModifications());
+ new ModifyOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ protocolOp.getDN(), protocolOp.getModifications());
// Add the operation into the work queue.
try
@@ -2480,25 +2119,14 @@
}
ModifyResponseProtocolOp responseOp =
- new ModifyResponseProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(),
- de.getMatchedDN(),
- de.getReferralURLs());
+ new ModifyResponseProtocolOp(
+ de.getResultCode().getIntValue(), de.getMessageObject(),
+ de.getMatchedDN(), de.getReferralURLs());
- List<Control> responseControls = modifyOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, modifyOp.getResponseControls()));
}
-
return connectionValid;
}
@@ -2507,40 +2135,41 @@
/**
* Processes the provided LDAP message as a modify DN request.
*
- * @param message The LDAP message containing the modify DN request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the modify DN request to
+ * process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processModifyDNRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- if ((ldapVersion == 2) && (controls != null) && (! controls.isEmpty()))
+ if ((ldapVersion == 2) && (controls != null)
+ && (!controls.isEmpty()))
{
// LDAPv2 clients aren't allowed to send controls.
ModifyDNResponseProtocolOp responseOp =
- new ModifyDNResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
+ new ModifyDNResponseProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
return false;
}
ModifyDNRequestProtocolOp protocolOp =
- message.getModifyDNRequestProtocolOp();
+ message.getModifyDNRequestProtocolOp();
ModifyDNOperationBasis modifyDNOp =
- new ModifyDNOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- protocolOp.getEntryDN(), protocolOp.getNewRDN(),
- protocolOp.deleteOldRDN(),
- protocolOp.getNewSuperior());
+ new ModifyDNOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ protocolOp.getEntryDN(), protocolOp.getNewRDN(), protocolOp
+ .deleteOldRDN(), protocolOp.getNewSuperior());
// Add the operation into the work queue.
try
@@ -2555,25 +2184,14 @@
}
ModifyDNResponseProtocolOp responseOp =
- new ModifyDNResponseProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(),
- de.getMatchedDN(),
- de.getReferralURLs());
+ new ModifyDNResponseProtocolOp(de.getResultCode()
+ .getIntValue(), de.getMessageObject(), de.getMatchedDN(),
+ de.getReferralURLs());
- List<Control> responseControls = modifyDNOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, modifyDNOp.getResponseControls()));
}
-
return connectionValid;
}
@@ -2582,42 +2200,42 @@
/**
* Processes the provided LDAP message as a search request.
*
- * @param message The LDAP message containing the search request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the search request to process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processSearchRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
- if ((ldapVersion == 2) && (controls != null) && (! controls.isEmpty()))
+ if ((ldapVersion == 2) && (controls != null)
+ && (!controls.isEmpty()))
{
// LDAPv2 clients aren't allowed to send controls.
SearchResultDoneProtocolOp responseOp =
- new SearchResultDoneProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp));
+ new SearchResultDoneProtocolOp(LDAPResultCode.PROTOCOL_ERROR,
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp));
disconnect(DisconnectReason.PROTOCOL_ERROR, false,
- ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
+ ERR_LDAPV2_CONTROLS_NOT_ALLOWED.get());
return false;
}
- SearchRequestProtocolOp protocolOp = message.getSearchRequestProtocolOp();
+ SearchRequestProtocolOp protocolOp =
+ message.getSearchRequestProtocolOp();
SearchOperationBasis searchOp =
- new SearchOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls,
- protocolOp.getBaseDN(), protocolOp.getScope(),
- protocolOp.getDereferencePolicy(),
- protocolOp.getSizeLimit(),
- protocolOp.getTimeLimit(),
- protocolOp.getTypesOnly(), protocolOp.getFilter(),
- protocolOp.getAttributes());
+ new SearchOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls,
+ protocolOp.getBaseDN(), protocolOp.getScope(), protocolOp
+ .getDereferencePolicy(), protocolOp.getSizeLimit(),
+ protocolOp.getTimeLimit(), protocolOp.getTypesOnly(),
+ protocolOp.getFilter(), protocolOp.getAttributes());
// Add the operation into the work queue.
try
@@ -2632,25 +2250,14 @@
}
SearchResultDoneProtocolOp responseOp =
- new SearchResultDoneProtocolOp(de.getResultCode().getIntValue(),
- de.getMessageObject(),
- de.getMatchedDN(),
- de.getReferralURLs());
+ new SearchResultDoneProtocolOp(de.getResultCode()
+ .getIntValue(), de.getMessageObject(), de.getMatchedDN(),
+ de.getReferralURLs());
- List<Control> responseControls = searchOp.getResponseControls();
- ArrayList<LDAPControl> responseLDAPControls =
- new ArrayList<LDAPControl>(responseControls.size());
- for (Control c : responseControls)
- {
- responseLDAPControls.add(new LDAPControl(c));
- }
-
- sendLDAPMessage(securityProvider,
- new LDAPMessage(message.getMessageID(), responseOp,
- responseLDAPControls));
+ sendLDAPMessage(new LDAPMessage(message.getMessageID(),
+ responseOp, searchOp.getResponseControls()));
}
-
return connectionValid;
}
@@ -2659,22 +2266,22 @@
/**
* Processes the provided LDAP message as an unbind request.
*
- * @param message The LDAP message containing the unbind request to
- * process.
- * @param controls The set of pre-decoded request controls contained in the
- * message.
- *
- * @return <CODE>true</CODE> if the request was processed successfully, or
- * <CODE>false</CODE> if not and the connection has been closed as a
- * result (it is the responsibility of this method to close the
- * connection).
+ * @param message
+ * The LDAP message containing the unbind request to process.
+ * @param controls
+ * The set of pre-decoded request controls contained in the
+ * message.
+ * @return <CODE>true</CODE> if the request was processed
+ * successfully, or <CODE>false</CODE> if not and the
+ * connection has been closed as a result (it is the
+ * responsibility of this method to close the connection).
*/
private boolean processUnbindRequest(LDAPMessage message,
- ArrayList<Control> controls)
+ List<Control> controls)
{
UnbindOperationBasis unbindOp =
- new UnbindOperationBasis(this, nextOperationID.getAndIncrement(),
- message.getMessageID(), controls);
+ new UnbindOperationBasis(this, nextOperationID
+ .getAndIncrement(), message.getMessageID(), controls);
unbindOp.run();
@@ -2687,6 +2294,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public String getMonitorSummary()
{
StringBuilder buffer = new StringBuilder();
@@ -2713,9 +2321,9 @@
}
buffer.append("\" security=\"");
- if (securityProvider.isSecure())
+ if (isSecure())
{
- buffer.append(securityProvider.getSecurityMechanismName());
+ buffer.append(activeProvider.getName());
}
else
{
@@ -2732,11 +2340,13 @@
/**
- * Appends a string representation of this client connection to the provided
- * buffer.
+ * Appends a string representation of this client connection to the
+ * provided buffer.
*
- * @param buffer The buffer to which the information should be appended.
+ * @param buffer
+ * The buffer to which the information should be appended.
*/
+ @Override
public void toString(StringBuilder buffer)
{
buffer.append("LDAP client connection from ");
@@ -2752,218 +2362,90 @@
/**
- * Indicates whether TLS protection is actually available for the underlying
- * client connection. If there is any reason that TLS protection cannot be
- * enabled on this client connection, then it should be appended to the
- * provided buffer.
+ * Indicates whether TLS protection is actually available for the
+ * underlying client connection. If there is any reason that TLS
+ * protection cannot be enabled on this client connection, then it
+ * should be appended to the provided buffer.
*
- * @param unavailableReason The buffer used to hold the reason that TLS is
- * not available on the underlying client
- * connection.
- *
- * @return <CODE>true</CODE> if TLS is available on the underlying client
- * connection, or <CODE>false</CODE> if it is not.
+ * @param unavailableReason
+ * The buffer used to hold the reason that TLS is not
+ * available on the underlying client connection.
+ * @return <CODE>true</CODE> if TLS is available on the underlying
+ * client connection, or <CODE>false</CODE> if it is not.
*/
- public boolean tlsProtectionAvailable(MessageBuilder unavailableReason)
+ public boolean isTLSAvailable(MessageBuilder unavailableReason)
{
- // Make sure that this client connection does not already have some other
- // security provider enabled.
- if (! (securityProvider instanceof NullConnectionSecurityProvider))
+ if (isSecure() && activeProvider.getName().equals("TLS"))
{
-
- unavailableReason.append(ERR_LDAP_TLS_EXISTING_SECURITY_PROVIDER.get(
- securityProvider.getSecurityMechanismName()));
+ // TODO SASLPhase2 more general message
+ unavailableReason.append(ERR_LDAP_TLS_EXISTING_SECURITY_PROVIDER
+ .get(activeProvider.getName()));
return false;
}
-
-
- // Make sure that the connection handler allows the use of the StartTLS
- // operation.
- if (! connectionHandler.allowStartTLS())
+ // Make sure that the connection handler allows the use of the
+ // StartTLS operation.
+ if (!connectionHandler.allowStartTLS())
{
-
unavailableReason.append(ERR_LDAP_TLS_STARTTLS_NOT_ALLOWED.get());
return false;
}
-
-
- // Make sure that the TLS security provider is available.
- if (tlsSecurityProvider == null)
+ try
{
- try
- {
- TLSConnectionSecurityProvider tlsProvider =
- new TLSConnectionSecurityProvider();
- tlsProvider.initializeConnectionSecurityProvider(null);
- tlsProvider.setSSLClientAuthPolicy(
- connectionHandler.getSSLClientAuthPolicy());
- tlsProvider.setEnabledProtocols(
- connectionHandler.getEnabledSSLProtocols());
- tlsProvider.setEnabledCipherSuites(
- connectionHandler.getEnabledSSLCipherSuites());
-
- tlsSecurityProvider = (TLSConnectionSecurityProvider)
- tlsProvider.newInstance(this, clientChannel);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- tlsSecurityProvider = null;
-
-
- unavailableReason.append(ERR_LDAP_TLS_CANNOT_CREATE_TLS_PROVIDER.get(
- stackTraceToSingleLineString(e)));
- return false;
- }
+ TLSByteChannel tlsByteChannel =
+ connectionHandler.getTLSByteChannel(this, clientChannel);
+ setTLSPendingProvider(tlsByteChannel);
}
-
-
- // If we've gotten here, then everything looks OK.
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+ unavailableReason.append(ERR_LDAP_TLS_CANNOT_CREATE_TLS_PROVIDER
+ .get(stackTraceToSingleLineString(de)));
+ return false;
+ }
return true;
}
/**
- * Installs the TLS connection security provider on this client connection.
- * If an error occurs in the process, then the underlying client connection
- * must be terminated and an exception must be thrown to indicate the
- * underlying cause.
- *
- * @throws DirectoryException If the TLS connection security provider could
- * not be enabled and the underlying connection
- * has been closed.
- */
- public void enableTLSConnectionSecurityProvider()
- throws DirectoryException
- {
- if (tlsSecurityProvider == null)
- {
- Message message = ERR_LDAP_TLS_NO_PROVIDER.get();
-
- disconnect(DisconnectReason.OTHER, false, message);
- throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
- message);
- }
-
- clearSecurityProvider = securityProvider;
- setConnectionSecurityProvider(tlsSecurityProvider);
- }
-
-
-
- /**
- * Disables the TLS connection security provider on this client connection.
- * This must also eliminate any authentication that had been performed on the
- * client connection so that it is in an anonymous state. If a problem occurs
- * while attempting to revert the connection to a non-TLS-protected state,
- * then an exception must be thrown and the client connection must be
- * terminated.
- *
- * @throws DirectoryException If TLS protection cannot be reverted and the
- * underlying client connection has been closed.
- */
- public void disableTLSConnectionSecurityProvider()
- throws DirectoryException
- {
- Message message = ERR_LDAP_TLS_CLOSURE_NOT_ALLOWED.get();
-
- disconnect(DisconnectReason.OTHER, false, message);
- throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
- message);
- }
-
-
-
- /**
* Sends a response to the client in the clear rather than through the
- * encrypted channel. This should only be used when processing the StartTLS
- * extended operation to send the response in the clear after the TLS
- * negotiation has already been initiated.
+ * encrypted channel. This should only be used when processing the
+ * StartTLS extended operation to send the response in the clear after
+ * the TLS negotiation has already been initiated.
*
- * @param operation The operation for which to send the response in the
- * clear.
- *
- *
- * @throws DirectoryException If a problem occurs while sending the response
- * in the clear.
+ * @param operation
+ * The operation for which to send the response in the clear.
+ * @throws DirectoryException
+ * If a problem occurs while sending the response in the
+ * clear.
*/
public void sendClearResponse(Operation operation)
- throws DirectoryException
+ throws DirectoryException
{
- if (clearSecurityProvider == null)
- {
- Message message = ERR_LDAP_NO_CLEAR_SECURITY_PROVIDER.get(toString());
- throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
- message);
- }
-
- sendLDAPMessage(clearSecurityProvider,
- operationToResponseLDAPMessage(operation));
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public DN getKeyManagerProviderDN()
- {
- return connectionHandler.getKeyManagerProviderDN();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public DN getTrustManagerProviderDN()
- {
- return connectionHandler.getTrustManagerProviderDN();
- }
-
-
-
- /**
- * Retrieves the alias of the server certificate that should be used
- * for operations requiring a server certificate. The default
- * implementation returns {@code null} to indicate that any alias is
- * acceptable.
- *
- * @return The alias of the server certificate that should be used
- * for operations requring a server certificate, or
- * {@code null} if any alias is acceptable.
- */
- @Override
- public String getCertificateAlias()
- {
- return connectionHandler.getSSLServerCertNickname();
+ sendLDAPMessage(operationToResponseLDAPMessage(operation));
}
/**
* Retrieves the length of time in milliseconds that this client
- * connection has been idle.
- * <BR><BR>
+ * connection has been idle. <BR>
+ * <BR>
* Note that the default implementation will always return zero.
- * Subclasses associated with connection handlers should override
- * this method if they wish to provided idle time limit
- * functionality.
+ * Subclasses associated with connection handlers should override this
+ * method if they wish to provided idle time limit functionality.
*
- * @return The length of time in milliseconds that this client
- * connection has been idle.
+ * @return The length of time in milliseconds that this client
+ * connection has been idle.
*/
@Override
public long getIdleTime()
{
- if (operationsInProgress.isEmpty() && getPersistentSearches().isEmpty())
+ if (operationsInProgress.isEmpty()
+ && getPersistentSearches().isEmpty())
{
return (TimeThread.getTime() - lastCompletionTime.get());
}
@@ -2974,27 +2456,131 @@
}
}
- private void initializeOperationMonitors() {
- this.addMonitor = OperationMonitor.getOperationMonitor(
- ADD);
- this.searchMonitor = OperationMonitor.getOperationMonitor(
- SEARCH);
- this.abandonMonitor = OperationMonitor.getOperationMonitor(
- ABANDON);
- this.bindMonitor = OperationMonitor.getOperationMonitor(
- BIND);
- this.compareMonitor = OperationMonitor.getOperationMonitor(
- COMPARE);
- this.delMonitor = OperationMonitor.getOperationMonitor(
- DELETE);
- this.extendedMonitor = OperationMonitor.getOperationMonitor(
- EXTENDED);
- this.modMonitor = OperationMonitor.getOperationMonitor(
- MODIFY);
- this.moddnMonitor = OperationMonitor.getOperationMonitor(
- MODIFY_DN);
- this.unbindMonitor = OperationMonitor.getOperationMonitor(
- UNBIND);
+
+
+ /**
+ * Set the connection provider that is not in use yet. Used in TLS
+ * negotiation when a clear response is needed before the connection
+ * provider is active.
+ *
+ * @param provider
+ * The provider that needs to be activated.
+ */
+ public void setTLSPendingProvider(ConnectionSecurityProvider provider)
+ {
+ tlsPendingProvider = provider;
+
+ }
+
+
+
+ /**
+ * Set the connection provider that is not in use. Used in SASL
+ * negotiation when a clear response is needed before the connection
+ * provider is active.
+ *
+ * @param provider
+ * The provider that needs to be activated.
+ */
+ public void setSASLPendingProvider(ConnectionSecurityProvider provider)
+ {
+ saslPendingProvider = provider;
+
+ }
+
+
+
+ /**
+ * Enable the provider that is inactive.
+ */
+ public void enableTLS()
+ {
+ this.asn1Reader =
+ ASN1.getReader(saslChannel, tlsPendingProvider.getAppBufSize(),
+ connectionHandler.getMaxRequestSize());
+ activeProvider = tlsPendingProvider;
+ tlsChannel.redirect(tlsPendingProvider);
+ tlsPendingProvider = null;
+ }
+
+
+
+ /**
+ * Set the security provider to the specified provider.
+ *
+ * @param sslProvider
+ * The provider to set the security provider to.
+ */
+ public void enableSSL(ConnectionSecurityProvider sslProvider)
+ {
+ this.asn1Reader =
+ ASN1.getReader(saslChannel, sslProvider.getAppBufSize(),
+ connectionHandler.getMaxRequestSize());
+ activeProvider = sslProvider;
+ tlsChannel.redirect(sslProvider);
+ }
+
+
+
+ /**
+ * Enable the SASL provider that is currently inactive or pending.
+ */
+ public void enableSASL()
+ {
+ activeProvider = saslPendingProvider;
+ saslChannel.redirect(saslPendingProvider);
+ asn1Reader =
+ ASN1.getReader(saslChannel,
+ saslPendingProvider.getAppBufSize(), connectionHandler
+ .getMaxRequestSize());
+ saslPendingProvider = null;
+ }
+
+
+
+ /**
+ * Return the certificate chain array associated with a connection.
+ *
+ * @return The array of certificates associated with a connection.
+ */
+ public Certificate[] getClientCertificateChain()
+ {
+ if (activeProvider != null)
+ {
+ return activeProvider.getClientCertificateChain();
+ }
+ else
+ return new Certificate[0];
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getSSF()
+ {
+ if (activeProvider != null)
+ return activeProvider.getSSF();
+ else
+ return 0;
+ }
+
+
+
+ private void initializeOperationMonitors()
+ {
+ this.addMonitor = OperationMonitor.getOperationMonitor(ADD);
+ this.searchMonitor = OperationMonitor.getOperationMonitor(SEARCH);
+ this.abandonMonitor = OperationMonitor.getOperationMonitor(ABANDON);
+ this.bindMonitor = OperationMonitor.getOperationMonitor(BIND);
+ this.compareMonitor = OperationMonitor.getOperationMonitor(COMPARE);
+ this.delMonitor = OperationMonitor.getOperationMonitor(DELETE);
+ this.extendedMonitor =
+ OperationMonitor.getOperationMonitor(EXTENDED);
+ this.modMonitor = OperationMonitor.getOperationMonitor(MODIFY);
+ this.moddnMonitor = OperationMonitor.getOperationMonitor(MODIFY_DN);
+ this.unbindMonitor = OperationMonitor.getOperationMonitor(UNBIND);
}
}
-
--
Gitblit v1.10.0