opends/src/server/org/opends/server/api/ClientConnection.java
@@ -38,6 +38,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import org.opends.messages.Message; import org.opends.server.api.plugin.PluginResult; @@ -92,10 +93,19 @@ // The set of authentication information for this client connection. private AuthenticationInfo authenticationInfo; // Indicates whether a bind is currently in progress on this client // connection. If so, then no other operations should be allowed // until the bind completes. private boolean bindInProgress; /** * Indicates whether a multistage SASL bind is currently in progress * on this client connection. If so, then no other operations * should be allowed until the bind completes. */ protected AtomicBoolean saslBindInProgress; /** * Indicates if a bind or start TLS request is currently in progress * on this client connection. If so, then no further socket reads * will occur until the request completes. */ protected AtomicBoolean bindOrStartTLSInProgress; // Indicates whether any necessary finalization work has been done // for this client connection. @@ -148,7 +158,8 @@ connectTimeString = TimeThread.getGMTTime(); authenticationInfo = new AuthenticationInfo(); saslAuthState = null; bindInProgress = false; saslBindInProgress = new AtomicBoolean(false); bindOrStartTLSInProgress = new AtomicBoolean(false); persistentSearches = new CopyOnWriteArrayList<PersistentSearch>(); sizeLimit = DirectoryServer.getSizeLimit(); timeLimit = DirectoryServer.getTimeLimit(); @@ -695,36 +706,6 @@ /** * Indicates whether a bind operation is in progress on this client * connection. If so, then no new operations should be allowed * until the bind has completed. * * @return {@code true} if a bind operation is in progress on this * connection, or {@code false} if not. */ public boolean bindInProgress() { return bindInProgress; } /** * Specifies whether a bind operation is in progress on this client * connection. If so, then no new operations should be allowed * until the bind has completed. * * @param bindInProgress Specifies whether a bind operation is in * progress on this client connection. */ public void setBindInProgress(boolean bindInProgress) { this.bindInProgress = bindInProgress; } /** * Indicates whether the user associated with this client connection * must change their password before they will be allowed to do * anything else. @@ -1850,5 +1831,25 @@ * @return An integer representing the SSF value of a connection. */ public abstract int getSSF(); /** * Indicates a bind or start TLS request processing is finished * and the client connection may start processing data read from * the socket again. This must be called after processing each * bind request in a multistage SASL bind. */ public void finishBindOrStartTLS() { bindOrStartTLSInProgress.set(false); } /** * Indicates a multistage SASL bind operation is finished and the * client connection may accept additional LDAP messages. */ public void finishSaslBind() { saslBindInProgress.set(false); } } opends/src/server/org/opends/server/core/BindOperationBasis.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2007-2008 Sun Microsystems, Inc. * Copyright 2007-2009 Sun Microsystems, Inc. */ package org.opends.server.core; import org.opends.messages.Message; @@ -728,11 +728,6 @@ ClientConnection clientConnection = getClientConnection(); // Set a flag to indicate that a bind operation is in progress. This should // ensure that no new operations will be accepted for this client until the // bind is complete. clientConnection.setBindInProgress(true); // Wipe out any existing authentication for the client connection and create // a placeholder that will be used if the bind is successful. clientConnection.setUnauthenticated(); @@ -838,19 +833,21 @@ } finally { // If the bind processing is finished, then unset the "bind in progress" // flag to allow other operations to be processed on the connection. if (getResultCode() != ResultCode.SASL_BIND_IN_PROGRESS) { clientConnection.setBindInProgress(false); } // Stop the processing timer. setProcessingStopTime(); // Send the bind response to the client. clientConnection.sendResponse(this); // If the bind processing is finished, then unset the "bind in progress" // flag to allow other operations to be processed on the connection. if (getResultCode() != ResultCode.SASL_BIND_IN_PROGRESS) { clientConnection.finishSaslBind(); } clientConnection.finishBindOrStartTLS(); // Log the bind response. logBindResponse(this); opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -211,7 +211,6 @@ import org.opends.server.types.ObjectClass; import org.opends.server.types.ObjectClassType; import org.opends.server.types.OperatingSystem; import org.opends.server.types.OperationType; import org.opends.server.types.Privilege; import org.opends.server.types.RestoreConfig; import org.opends.server.types.ResultCode; @@ -7248,17 +7247,7 @@ public static void enqueueRequest(AbstractOperation operation) throws DirectoryException { // See if a bind is already in progress on the associated connection. If so // then reject the operation. ClientConnection clientConnection = operation.getClientConnection(); if (clientConnection.bindInProgress() && (operation.getOperationType() != OperationType.BIND)) { Message message = ERR_ENQUEUE_BIND_IN_PROGRESS.get(); throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); } //Reject or accept the unauthenticated requests based on the configuration // settings. if ((directoryServer.rejectUnauthenticatedRequests || opends/src/server/org/opends/server/core/ExtendedOperation.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.core; @@ -94,13 +94,5 @@ * the client. */ public void setResponseValue(ByteString responseValue); /** * Indicates that the response for this extended operation has been sent from * somewhere outside of this class. This should only be used by the StartTLS * extended operation for the case in which it needs to send a response in the * clear after TLS negotiation has already started on the connection. */ public void setResponseSent(); } opends/src/server/org/opends/server/core/ExtendedOperationBasis.java
@@ -76,9 +76,6 @@ // The value for the response associated with this extended operation. private ByteString responseValue; // Indicates whether a response has yet been sent for this operation. private boolean responseSent; // The set of response controls for this extended operation. private List<Control> responseControls; @@ -119,7 +116,6 @@ responseValue = null; responseControls = new ArrayList<Control>(); cancelRequest = null; responseSent = false; if (requestOID.equals(OID_CANCEL_REQUEST)) { @@ -524,17 +520,18 @@ // Stop the processing timer. setProcessingStopTime(); // Send the response to the client, if it has not already been sent. if (! responseSent) // Send the response to the client. if(cancelRequest == null || cancelResult == null || cancelResult.getResultCode() != ResultCode.CANCELED || cancelRequest.notifyOriginalRequestor() || DirectoryServer.notifyAbandonedOperations()) { responseSent = true; if(cancelRequest == null || cancelResult == null || cancelResult.getResultCode() != ResultCode.CANCELED || cancelRequest.notifyOriginalRequestor() || DirectoryServer.notifyAbandonedOperations()) { clientConnection.sendResponse(this); } clientConnection.sendResponse(this); } if(requestOID.equals(OID_START_TLS_REQUEST)) { clientConnection.finishBindOrStartTLS(); } // Log the extended response. @@ -551,37 +548,6 @@ } } /** * Sends an extended response to the client if none has already been sent. * Note that extended operation handlers are strongly discouraged from using * this method when it is not necessary because its use will prevent the * response from being sent after post-operation plugin processing, which may * impact the result that should be included. Nevertheless, it may be needed * in some special cases in which the response must be sent before the * extended operation handler completes its processing (e.g., the StartTLS * operation in which the response must be sent in the clear before actually * enabling TLS protection). */ public final void sendExtendedResponse() { if (! responseSent) { responseSent = true; clientConnection.sendResponse(this); } } /** * {@inheritDoc} */ public final void setResponseSent() { this.responseSent = true; } /** * {@inheritDoc} */ opends/src/server/org/opends/server/extensions/RedirectingByteChannel.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.extensions; @@ -38,7 +38,7 @@ */ public class RedirectingByteChannel implements ByteChannel { private final ByteChannel child; private ByteChannel redirect = null; private volatile ByteChannel redirect = null; private RedirectingByteChannel(ByteChannel child) { this.child = child; opends/src/server/org/opends/server/extensions/StartTLSExtendedOperation.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.extensions; @@ -36,8 +36,6 @@ import org.opends.server.core.DirectoryServer; import org.opends.server.core.ExtendedOperation; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.DisconnectReason; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; @@ -169,27 +167,6 @@ // TLS was successfully enabled on the client connection, but we need to // send the response in the clear. operation.setResultCode(ResultCode.SUCCESS); try { tlsCapableConnection.sendClearResponse(operation); operation.setResponseSent(); tlsCapableConnection.enableTLS(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } logError(ERR_STARTTLS_ERROR_SENDING_CLEAR_RESPONSE.get( getExceptionMessage(e))); clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM, false, ERR_STARTTLS_ERROR_SENDING_CLEAR_RESPONSE.get( getExceptionMessage(e))); } } } opends/src/server/org/opends/server/extensions/TLSCapableConnection.java
@@ -22,16 +22,12 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.extensions; import org.opends.messages.MessageBuilder; import org.opends.server.types.DirectoryException; import org.opends.server.types.Operation; /** * This interface defines a set of methods that must be implemented by a class @@ -56,36 +52,5 @@ * connection, or <CODE>false</CODE> if it is not. */ public boolean isTLSAvailable(MessageBuilder unavailableReason); /** * 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 enableTLS() throws DirectoryException; /** * 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 SSL * 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. */ public void sendClearResponse(Operation operation) throws DirectoryException; } opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.protocols.internal; @@ -2746,45 +2746,6 @@ /** * Indicates whether a bind operation is in progress on this client * connection. If so, then no new operations should be allowed * until the bind has completed. * * @return <CODE>true</CODE> if a bind operation is in progress on * this connection, or <CODE>false</CODE> if not. */ @Override() public boolean bindInProgress() { // For internal operations, we don't care if there are any binds // in progress. return false; } /** * Specifies whether a bind operation is in progress on this client * connection. If so, then no new operations should be allowed * until the bind has completed. * * @param bindInProgress Specifies whether a bind operation is in * progress on this client connection. */ @org.opends.server.types.PublicAPI( stability=org.opends.server.types.StabilityLevel.PRIVATE, mayInstantiate=false, mayExtend=false, mayInvoke=false) @Override() public void setBindInProgress(boolean bindInProgress) { // No implementation is required. } /** * Retrieves the set of operations in progress for this client * connection. This list must not be altered by any caller. * opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.protocols.jmx; import org.opends.messages.Message; @@ -1026,38 +1026,6 @@ /** * Indicates whether a bind operation is in progress on this client * connection. If so, then no new operations should be allowed until the bind * has completed. * * @return <CODE>true</CODE> if a bind operation is in progress on this * connection, or <CODE>false</CODE> if not. */ public boolean bindInProgress() { // For Jmx operations, we don't care if there are any binds in // progress. return false; } /** * Specifies whether a bind operation is in progress on this client * connection. If so, then no new operations should be allowed until the bind * has completed. * * @param bindInProgress Specifies whether a bind operation is in progress * on this client connection. */ public void setBindInProgress(boolean bindInProgress) { // No implementation is required. } /** * Retrieves the set of operations in progress for this client connection. * This list must not be altered by any caller. * opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -50,6 +50,7 @@ import org.opends.messages.Message; import org.opends.messages.MessageBuilder; import static org.opends.messages.CoreMessages.ERR_ENQUEUE_BIND_IN_PROGRESS; import org.opends.server.api.ClientConnection; import org.opends.server.api.ConnectionHandler; import org.opends.server.core.AbandonOperationBasis; @@ -76,24 +77,9 @@ 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; import org.opends.server.types.DN; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.DirectoryException; import org.opends.server.types.DisconnectReason; import org.opends.server.types.IntermediateResponse; import org.opends.server.types.Operation; import org.opends.server.types.OperationType; import org.opends.server.types.ResultCode; import org.opends.server.types.SearchResultEntry; import org.opends.server.types.SearchResultReference; import org.opends.server.types.*; import org.opends.server.util.TimeThread; import static org.opends.server.util.ServerConstants.OID_START_TLS_REQUEST; /** @@ -200,9 +186,9 @@ private final RedirectingByteChannel saslChannel; private final RedirectingByteChannel tlsChannel; private ConnectionSecurityProvider activeProvider = null; private ConnectionSecurityProvider tlsPendingProvider = null; private ConnectionSecurityProvider saslPendingProvider = null; private volatile ConnectionSecurityProvider activeProvider = null; private volatile ConnectionSecurityProvider tlsPendingProvider = null; private volatile ConnectionSecurityProvider saslPendingProvider = null; // Statistics for the processed operations private OperationMonitor addMonitor; @@ -1419,12 +1405,15 @@ */ public boolean processDataRead() { if (this.saslPendingProvider != null) { enableSASL(); } while (true) { if(bindOrStartTLSInProgress.get()) { // We should wait for the bind or startTLS to finish before // reading any more data off the socket. return true; } try { int result = asn1Reader.processChannelData(); @@ -1541,6 +1530,14 @@ // terminated. try { if(bindOrStartTLSInProgress.get() || (saslBindInProgress.get() && message.getProtocolOpType() != OP_TYPE_BIND_REQUEST)) { throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, ERR_ENQUEUE_BIND_IN_PROGRESS.get()); } boolean result; switch (message.getProtocolOpType()) { @@ -1564,7 +1561,22 @@ return result; case OP_TYPE_BIND_REQUEST: if (keepStats) this.bindMonitor.start(); bindOrStartTLSInProgress.set(true); if(message.getBindRequestProtocolOp(). getAuthenticationType() == AuthenticationType.SASL) { saslBindInProgress.set(true); } result = processBindRequest(message, opControls); if(!result) { bindOrStartTLSInProgress.set(false); if(message.getBindRequestProtocolOp(). getAuthenticationType() == AuthenticationType.SASL) { saslBindInProgress.set(false); } } if (keepStats) { this.bindMonitor.stop(); @@ -1591,7 +1603,18 @@ return result; case OP_TYPE_EXTENDED_REQUEST: if (keepStats) this.extendedMonitor.start(); if(message.getExtendedRequestProtocolOp().getOID().equals( OID_START_TLS_REQUEST)) { bindOrStartTLSInProgress.set(true); } result = processExtendedRequest(message, opControls); if(!result && message.getExtendedRequestProtocolOp().getOID().equals( OID_START_TLS_REQUEST)) { bindOrStartTLSInProgress.set(false); } if (keepStats) { this.extendedMonitor.stop(); @@ -2447,26 +2470,6 @@ /** * 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. * * @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 { sendLDAPMessage(operationToResponseLDAPMessage(operation)); } /** * Retrieves the length of time in milliseconds that this client * connection has been idle. <BR> * <BR> @@ -2649,4 +2652,23 @@ this.moddnMonitor = OperationMonitor.getOperationMonitor(MODIFY_DN); this.unbindMonitor = OperationMonitor.getOperationMonitor(UNBIND); } /** * {@inheritDoc} */ public void finishBindOrStartTLS() { if(this.tlsPendingProvider != null) { enableTLS(); } if (this.saslPendingProvider != null) { enableSASL(); } super.finishBindOrStartTLS(); } } opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.protocols.internal; @@ -1010,59 +1010,6 @@ /** * Tests the <CODE>bindInProgress</CODE> method. */ @Test() public void testBindInProgress() { InternalClientConnection conn = InternalClientConnection.getRootConnection(); assertFalse(conn.bindInProgress()); } /** * Tests the <CODE>setBindInProgress</CODE> method. */ @Test() public void testSetBindInProgress() { InternalClientConnection conn = InternalClientConnection.getRootConnection(); conn.setBindInProgress(true); assertFalse(conn.bindInProgress()); } /** * Tests the <CODE>getOperationsInProgress</CODE> method. */ @Test() public void testGetOperationsInProgress() { InternalClientConnection conn = InternalClientConnection.getRootConnection(); Collection<Operation> opList = conn.getOperationsInProgress(); assertNotNull(opList); assertTrue(opList.isEmpty()); } /** * Tests the <CODE>getOperationInProgress</CODE> method. */ @Test() public void testGetOperationInProgress() { InternalClientConnection conn = InternalClientConnection.getRootConnection(); assertNull(conn.getOperationInProgress(0)); } /**