LDAPClientConnection.java revision ea1068c292e9b341af6d6b563cd8988a96be20a9
0N/A * The contents of this file are subject to the terms of the 0N/A * Common Development and Distribution License, Version 1.0 only 0N/A * (the "License"). You may not use this file except in compliance 0N/A * See the License for the specific language governing permissions 0N/A * and limitations under the License. 0N/A * When distributing Covered Code, include this CDDL HEADER in each 0N/A * If applicable, add the following below this CDDL HEADER, with the 0N/A * fields enclosed by brackets "[]" replaced with your own identifying 0N/A * Portions Copyright [yyyy] [name of copyright owner] 0N/A * Copyright 2006-2010 Sun Microsystems, Inc. 0N/A * Portions Copyright 2010-2015 ForgeRock AS. * 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 * A runnable whose task is to close down all IO related channels * associated with a client connection after a small delay. /** The client connection ASN1 reader. */ /** The client connection socket channel. */ /** Creates a new connection finalizer job. */ // In general, we don't care about any exception that might be // In general, we don't care about any exception that might be * Channel that writes the contents of the provided buffer to the client, * throwing an exception if the write is unsuccessful for too * long (e.g., if the client is unresponsive or there is a network * problem). If possible, it will attempt to use the selector returned * by the {@code ClientConnection.getWriteSelector} method, but it is * capable of working even if that method returns {@code null}. <BR> * Note that the original position and limit values will not be * preserved, so if that is important to the caller, then it should * record them before calling this method and restore them after it /** Synchronize concurrent writes to the same connection. */ // We won't support an infinite time limit, so fall back to using // five minutes, which is a very long timeout given that we're // blocking a worker thread. // The client connection does not provide a selector, so we'll // fall back to a more inefficient way that will work without a // The client connection has been closed. // If we've gotten here, then the write timed out. // Register with the selector for handling write operations. // We've been blocked for too long. // The client connection has been closed. /** The tracer object for the debug logger. */ * Thread local ASN1Writer and buffer. * Cached ASN1 writer: a thread can only write to one connection at a time. // Setting has changed, so recreate the holder. /** The time that the last operation was completed. */ /** The next operation ID that should be used for this connection. */ /** The selector that may be used for write operations. */ * Indicates whether the Directory Server believes this connection to be valid * and available for communication. * 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 the connection should keep statistics regarding the * operations that it is performing. /** The set of all operations currently in progress on this connection. */ * The number of operations performed on this connection. Used to compare with * the resource limits of the network group. /** The port on the client from which this connection originated. */ * The LDAP version that the client is using to communicate with the server. /** The port on the server to which this client has connected. */ /** The reference to the connection handler that accepted this connection. */ /** The statistics tracker associated with this client connection. */ /** The connection ID assigned to this connection. */ * The lock used to provide threadsafe access to the set of operations in /** The socket channel with which this client connection is associated. */ /** The byte channel used for blocking writes with time out. */ /** The string representation of the address of the client. */ * The name of the protocol that the client is using to communicate with the * The string representation of the address of the server to which the client * Creates a new LDAP client connection with the provided information. * @param connectionHandler * The connection handler that accepted this connection. * The socket channel that may be used to communicate with * @param protocol String representing the protocol (LDAP or LDAP+SSL). * @throws DirectoryException If SSL initialisation fails. * Retrieves the connection ID assigned to this connection. * @return The connection ID assigned to this connection. * Retrieves the connection handler that accepted this client * @return The connection handler that accepted this client * Retrieves the socket channel that can be used to communicate with * @return The socket channel that can be used to communicate with the * Retrieves the protocol that the client is using to communicate with * @return The protocol that the client is using to communicate with * Retrieves a string representation of the address of the client. * @return A string representation of the address of the client. * Retrieves the port number for this connection on the client system. * @return The port number for this connection on the client system. * 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. * Retrieves the port number for this connection on the server system. * @return The port number for this connection on the server system. * Retrieves the <CODE>java.net.InetAddress</CODE> associated with the * @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. * 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. * 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 * @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. * Sends a response to the client based on the information in the * The operation for which to send the response. // 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. // Avoid sending the response if one has already been sent. This may happen // if operation processing encounters a run-time exception after sending the // response: the worker thread exception handling code will attempt to send // an error result to the client indicating that a problem occurred. * Retrieves an LDAPMessage containing a response generated from the * The operation to use to generate the response LDAPMessage. * @return An LDAPMessage containing a response generated from the // 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". // Referrals are not allowed for LDAPv2 clients. // If this an LDAPv2 client, then we can't send this. // This must be a type of operation that doesn't have a response. // This shouldn't happen, so log a message and return. // Controls are not allowed for LDAPv2 clients. * Sends the provided search result entry to the client. * The search operation with which the entry is associated. * The search result entry to be sent to the client. * Sends the provided search result reference to the client. * The search operation with which the reference is * 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. // 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. * 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. // The only reason we shouldn't continue processing is if the * Sends the provided LDAP message to the client. * The LDAP message to send to the client. // Use a thread local writer. // FIXME -- Log a message or something // Clear and reset all of the internal buffers ready for the next usage. // The ASN1Writer is based on a ByteStringBuilder so closing will cause // the internal buffers to be resized if needed. * 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 * @param sendNotification * Indicates whether to try to provide notification to the * client that the connection will be closed. * The message to include in the disconnect notification * response. It may be <CODE>null</CODE> if no message is to // Set a flag indicating that the connection is being terminated so // that no new requests will be accepted. Also cancel all operations // If we are already in the middle of a disconnect, then don't // Indicate that this connection is no longer valid. // If there is a write selector for this connection, then close it. // 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 // NYI -- Log a message indicating that we couldn't send the // notice of disconnection. // Enqueue the connection channels for closing by the finalizer. // NYI -- Deregister the client connection from any server components that // Log a disconnect message. * 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 * Retrieves the operation in progress with the specified message ID. * 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. * Adds the provided operation to the set of operations in progress * for this client connection. * 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 // We need to grab a lock to ensure that no one else can add // operations to the queue while we are performing some preliminary // If we're already in the process of disconnecting the client, // then reject the operation. // Add the operation to the list of operations in progress for // See if there is already an operation in progress with the // same message ID. If so, then we can't allow it. // Try to add the operation to the work queue, // or run it synchronously (typically for the administration * 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. * 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. * Attempts to cancel the specified operation. * The message ID of the operation to cancel. * 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. // See if the operation is in the list of persistent searches. // We only need to find the first persistent search // associated with the provided message ID. The persistent // search will ensure that all other related persistent // searches are cancelled. * Attempts to cancel all operations in progress on this connection. * An object providing additional information about how the * cancel should be processed. // Make sure that no one can add any new operations. // TODO: Assume its cancelled? * Attempts to cancel all operations in progress on this connection * except the operation with the specified message ID. * An object providing additional information about how the * cancel should be processed. * The message ID of the operation that should not be // Make sure that no one can add any new operations. // TODO: Assume its cancelled? * Returns the total number of operations initiated on this * @return the total number of operations on this connection * Returns the ASN1 reader for this connection. * @return the ASN1 reader for this connection * @return number of bytes read if this connection is still valid * or negative integer to indicate an error otherwise // We should wait for the bind or startTLS to finish before // reading any more data off the socket. // The connection has been closed by the client. Disconnect // The connection failed, but there was an unread partial message so // interpret this as an IO error. // The connection failed and there was no unread data, so interpret this // as indicating that the client aborted (reset) the connection. This // happens when a client configures closes a connection which has been // configured with SO_LINGER set to 0. * 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. * 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. // 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 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 * Processes the provided LDAP message as an abandon request. * The LDAP message containing the abandon request to * The set of pre-decoded request controls contained in the * @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). // LDAPv2 clients aren't allowed to send controls. // Create the abandon operation and add it into the work queue. // Don't send an error response since abandon operations // don't have a response. * Processes the provided LDAP message as an add request. * The LDAP message containing the add request to process. * The set of pre-decoded request controls contained in the * @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). // LDAPv2 clients aren't allowed to send controls. // Create the add operation and add it into the work queue. * Processes the provided LDAP message as a bind request. * The LDAP message containing the bind request to process. * The set of pre-decoded request controls contained in the * @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). // See if this is an LDAPv2 bind request, and if so whether that // LDAPv2 clients aren't allowed to send controls. // Unsupported protocol version. RFC4511 states that we MUST send // a protocol error back to the client. // 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. // Add the operation into the work queue. // If it was a protocol error, then terminate the connection. * Processes the provided LDAP message as a compare request. * The LDAP message containing the compare request to * The set of pre-decoded request controls contained in the * @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). // LDAPv2 clients aren't allowed to send controls. // Add the operation into the work queue. * Processes the provided LDAP message as a delete request. * The LDAP message containing the delete request to process. * The set of pre-decoded request controls contained in the * @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). // LDAPv2 clients aren't allowed to send controls. // Add the operation into the work queue. * Processes the provided LDAP message as an extended request. * The LDAP message containing the extended request to * The set of pre-decoded request controls contained in the * @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). // 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 // FIXME -- Do we need to handle certain types of request here? // Add the operation into the work queue. * Processes the provided LDAP message as a modify request. * The LDAP message containing the modify request to process. * The set of pre-decoded request controls contained in the * @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). // LDAPv2 clients aren't allowed to send controls. // Add the operation into the work queue. * Processes the provided LDAP message as a modify DN request. * The LDAP message containing the modify DN request to * The set of pre-decoded request controls contained in the * @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). // LDAPv2 clients aren't allowed to send controls. // Add the operation into the work queue. * Processes the provided LDAP message as a search request. * The LDAP message containing the search request to process. * The set of pre-decoded request controls contained in the * @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). // LDAPv2 clients aren't allowed to send controls. // Add the operation into the work queue. * Processes the provided LDAP message as an unbind request. * The LDAP message containing the unbind request to process. * The set of pre-decoded request controls contained in the * @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). // The client connection will never be valid after an unbind. * Appends a string representation of this client connection to the * The buffer to which the information should be appended. // Make sure that the connection handler allows the use of the * Retrieves the length of time in milliseconds that this client * connection has been idle. <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. * @return The length of time in milliseconds that this client * connection has been idle. // There's at least one operation in progress, so it's not idle. * Set the connection provider that is not in use yet. Used in TLS * negotiation when a clear response is needed before the connection * The provider that needs to be activated. * Set the connection provider that is not in use. Used in SASL * negotiation when a clear response is needed before the connection * The provider that needs to be activated. * Enable the provider that is inactive. * Set the security provider to the specified provider. * The provider to set the security provider to. * Enable the SASL provider that is currently inactive or pending. * Return the certificate chain array associated with a connection. * @return The array of certificates associated with a connection. * Retrieves the TLS redirecting byte channel used in a LDAP client * @return The TLS redirecting byte channel.