opends/resource/config/config.ldif
@@ -47,6 +47,7 @@ ds-cfg-reject-unauthenticated-requests: false ds-cfg-default-password-policy: cn=Default Password Policy,cn=Password Policies,cn=config ds-cfg-return-bind-error-messages: false ds-cfg-idle-time-limit: 0 seconds ds-cfg-allowed-task: org.opends.server.tasks.AddSchemaFileTask ds-cfg-allowed-task: org.opends.server.tasks.BackupTask ds-cfg-allowed-task: org.opends.server.tasks.DisconnectClientTask @@ -1380,6 +1381,7 @@ ds-cfg-alternate-bind-dn: cn=Directory Manager ds-rlim-size-limit: 0 ds-rlim-time-limit: 0 ds-rlim-idle-time-limit: 0 ds-rlim-lookthrough-limit: 0 ds-pwp-password-policy-dn: cn=Root Password Policy,cn=Password Policies,cn=config opends/resource/schema/02-config.ldif
@@ -1547,6 +1547,12 @@ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' ) attributeTypes: ( 1.3.6.1.4.1.26027.1.1.462 NAME 'ds-cfg-ssl-cipher-suite' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' ) attributeTypes: ( 1.3.6.1.4.1.26027.1.1.463 NAME 'ds-cfg-idle-time-limit' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' ) attributeTypes: ( 1.3.6.1.4.1.26027.1.1.464 NAME 'ds-rlim-idle-time-limit' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE USAGE directoryOperation X-ORIGIN 'OpenDS Directory Server' ) objectClasses: ( 1.3.6.1.4.1.26027.1.2.1 NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled ) @@ -1764,7 +1770,8 @@ ds-cfg-reject-unauthenticated-requests $ ds-cfg-bind-with-dn-requires-password $ ds-cfg-lookthrough-limit $ ds-cfg-smtp-server $ ds-cfg-allowed-task $ ds-cfg-disabled-privilege $ ds-cfg-return-bind-error-messages ) X-ORIGIN 'OpenDS Directory Server' ) ds-cfg-return-bind-error-messages $ ds-cfg-idle-time-limit ) X-ORIGIN 'OpenDS Directory Server' ) objectClasses: ( 1.3.6.1.4.1.26027.1.2.41 NAME 'ds-cfg-root-dn' SUP top AUXILIARY MAY ds-cfg-alternate-bind-dn X-ORIGIN 'OpenDS Directory Server' ) objectClasses: ( 1.3.6.1.4.1.26027.1.2.42 NAME 'ds-cfg-root-dse' opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -693,5 +693,27 @@ </adm:profile> </adm:property> <adm:property name="idle-time-limit" mandatory="false" multi-valued="false"> <adm:synopsis> Specifies the maximum lenght of time that a client connection may remain established since its last completed operation. A value of "0 seconds" indicates that no idle time limit will be enforced. </adm:synopsis> <adm:default-behavior> <adm:defined> <adm:value>0 seconds</adm:value> </adm:defined> </adm:default-behavior> <adm:syntax> <adm:duration base-unit="ms" lower-limit="0"/> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:oid>1.3.6.1.4.1.26027.1.1.463</ldap:oid> <ldap:name>ds-cfg-idle-time-limit</ldap:name> </ldap:attribute> </adm:profile> </adm:property> </adm:managed-object> opends/src/server/org/opends/server/api/ClientConnection.java
@@ -108,6 +108,9 @@ // The time that this client connection was established. private long connectTime; // The idle time limit for this client connection. private long idleTimeLimit; // The opaque information used for storing intermediate state // information needed across multi-stage SASL binds. private Object saslAuthState; @@ -138,6 +141,7 @@ persistentSearches = new CopyOnWriteArrayList<PersistentSearch>(); sizeLimit = DirectoryServer.getSizeLimit(); timeLimit = DirectoryServer.getTimeLimit(); idleTimeLimit = DirectoryServer.getIdleTimeLimit(); lookthroughLimit = DirectoryServer.getLookthroughLimit(); finalized = false; privileges = new HashSet<Privilege>(); @@ -1274,6 +1278,39 @@ /** * Retrieves the maximum length of time in milliseconds that this * client connection will be allowed to remain idle before it should * be disconnected. * * @return The maximum length of time in milliseconds that this * client connection will be allowed to remain idle before * it should be disconnected. */ public final long getIdleTimeLimit() { return idleTimeLimit; } /** * Specifies the maximum length of time in milliseconds that this * client connection will be allowed to remain idle before it should * be disconnected. * * @param idleTimeLimit The maximum length of time in milliseconds * that this client connection will be * allowed to remain idle before it should be * disconnected. */ public void setIdleTimeLimit(long idleTimeLimit) { this.idleTimeLimit = idleTimeLimit; } /** * Retrieves the default maximum number of entries that should * checked for matches during a search. * @@ -1575,5 +1612,23 @@ this.networkGroup = networkGroup; } /** * Retrieves the length of time in milliseconds that this client * 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. * * @return The length of time in milliseconds that this client * connection has been idle. */ public long getIdleTime() { return 0L; } } opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -3541,6 +3541,15 @@ /** * The name of the operational attribute that may be included in user entries * to specify an idle time limit to be applied for that user. */ public static final String OP_ATTR_USER_IDLE_TIME_LIMIT = NAME_PREFIX_RLIM + "idle-time-limit"; /** * The name of the operational attribute that may be included in user * entries to specify a size limit to be applied for that user. */ opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -337,6 +337,8 @@ DirectoryServer.setReturnBindErrorMessages( globalConfig.isReturnBindErrorMessages()); DirectoryServer.setIdleTimeLimit(globalConfig.getIdleTimeLimit()); } opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -463,6 +463,9 @@ // The number of connections currently established to the server. private long currentConnections; // The idle time limit for the server. private long idleTimeLimit; // The maximum number of connections that will be allowed at any given time. private long maxAllowedConnections; @@ -731,6 +734,7 @@ directoryServer.allowedTasks = new LinkedHashSet<String>(0); directoryServer.disabledPrivileges = new LinkedHashSet<Privilege>(0); directoryServer.returnBindErrorMessages = false; directoryServer.idleTimeLimit = 0L; } @@ -1204,6 +1208,7 @@ if (startConnectionHandlers) { startConnectionHandlers(); new IdleTimeLimitThread().start(); } @@ -7526,6 +7531,35 @@ /** * Retrieves the maximum length of time in milliseconds that client * connections should be allowed to remain idle without being disconnected. * * @return The maximum length of time in milliseconds that client connections * should be allowed to remain idle without being disconnected. */ public static long getIdleTimeLimit() { return directoryServer.idleTimeLimit; } /** * Specifies the maximum length of time in milliseconds that client * connections should be allowed to remain idle without being disconnected. * * @param idleTimeLimit The maximum length of time in milliseconds that * client connections should be allowed to remain idle * without being disconnected. */ public static void setIdleTimeLimit(long idleTimeLimit) { directoryServer.idleTimeLimit = idleTimeLimit; } /** * Registers the provided backup task listener with the Directory Server. * * @param listener The backup task listener to register with the Directory opends/src/server/org/opends/server/core/IdleTimeLimitThread.java
New file @@ -0,0 +1,193 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.core; import org.opends.server.admin.std.server.ConnectionHandlerCfg; import org.opends.server.api.ClientConnection; import org.opends.server.api.ConnectionHandler; import org.opends.server.api.DirectoryThread; import org.opends.server.api.ServerShutdownListener; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.ErrorLogCategory; import org.opends.server.types.ErrorLogSeverity; import org.opends.server.types.DisconnectReason; import static org.opends.server.loggers.ErrorLogger.*; import static org.opends.server.loggers.debug.DebugLogger.*; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.util.StaticUtils.*; /** * This class defines a thread that will be used to teriminate client * connections if they have been idle for too long. */ public class IdleTimeLimitThread extends DirectoryThread implements ServerShutdownListener { /** * The debug log tracer for this object. */ private static final DebugTracer TRACER = getTracer(); // Indicates whether a shutdown request has been received. private boolean shutdownRequested; /** * Creates a new instance of this idle time limit thread. */ public IdleTimeLimitThread() { super("Idle Time Limit Thread"); setDaemon(true); shutdownRequested = false; DirectoryServer.registerShutdownListener(this); } /** * Operates in a loop, teriminating any client connections that have been idle * for too long. */ public void run() { int disconnectMessageID = MSGID_IDLETIME_LIMIT_EXCEEDED; String disconnectMessage = getMessage(disconnectMessageID); long sleepTime = 5000L; while (! shutdownRequested) { try { try { sleep(sleepTime); } catch (InterruptedException ie) {} sleepTime = 5000L; for (ConnectionHandler ch : DirectoryServer.getConnectionHandlers()) { ConnectionHandler<? extends ConnectionHandlerCfg> connHandler = (ConnectionHandler<? extends ConnectionHandlerCfg>) ch; for (ClientConnection c : connHandler.getClientConnections()) { long idleTime = c.getIdleTime(); if (idleTime > 0) { long idleTimeLimit = c.getIdleTimeLimit(); if (idleTimeLimit > 0) { if (idleTime > idleTimeLimit) { if (debugEnabled()) { TRACER.debugInfo("Terminating client connection " + c.getConnectionID() + " due to the idle time limit"); } try { c.disconnect(DisconnectReason.IDLE_TIME_LIMIT_EXCEEDED, true, disconnectMessage, disconnectMessageID); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_IDLETIME_DISCONNECT_ERROR; String message = getMessage(msgID, c.getConnectionID(), stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.MILD_ERROR, message, msgID); } } else { long shouldSleepTime = idleTimeLimit - idleTime; if (shouldSleepTime < sleepTime) { sleepTime = shouldSleepTime; } } } } } } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_IDLETIME_UNEXPECTED_ERROR; String message = getMessage(msgID, stackTraceToSingleLineString(e)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR, message, msgID); } } } /** * {@inheritDoc} */ public String getShutdownListenerName() { return "Idle Time Limit Thread"; } /** * {@inheritDoc} */ public void processServerShutdown(String reason) { shutdownRequested = true; } } opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6277,6 +6277,58 @@ /** * The message ID for the message that will be used if a user entry contains * multiple values for the user-specific idle time limit attribute. This * takes a single argument, which is the DN of the user entry. */ public static final int MSGID_BIND_MULTIPLE_USER_IDLE_TIME_LIMITS = CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_WARNING | 630; /** * The message ID for the message that will be used if an error occurs while * trying to parse a user-specific idle time limit value as an integer. This * takes two arguments, which are the provided time limit value and the DN of * the user entry. */ public static final int MSGID_BIND_CANNOT_PROCESS_USER_IDLE_TIME_LIMIT = CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_WARNING | 631; /** * The message ID for the message that will be used to indicate that the idle * time limit has been exceeded for a client connection. It does not take any * arguments. */ public static final int MSGID_IDLETIME_LIMIT_EXCEEDED = CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 632; /** * The message ID for the message that will be used if an error occurred while * trying to terminate a client connection. It takes two arguments, which are * the connection ID and a string representation of the exception that was * caught. */ public static final int MSGID_IDLETIME_DISCONNECT_ERROR = CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 632; /** * The message ID for the message that will be used if an unexpected error * occurred in the time thread. It takes a single argument, which is a string * representation of the exception that was caught. */ public static final int MSGID_IDLETIME_UNEXPECTED_ERROR = CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 632; /** * Associates a set of generic messages with the message IDs defined * in this class. */ @@ -7104,6 +7156,14 @@ "The user-specific time limit value %s contained in " + "user entry %s could not be parsed as an integer. The " + "default server time limit will be used"); registerMessage(MSGID_BIND_MULTIPLE_USER_IDLE_TIME_LIMITS, "There are multiple user-specific idle time limit values " + "contained in user entry %s. The default server idle " + "time limit will be used"); registerMessage(MSGID_BIND_CANNOT_PROCESS_USER_IDLE_TIME_LIMIT, "The user-specific idle time limit value %s contained in " + "user entry %s could not be parsed as an integer. The " + "default server idle time limit will be used"); registerMessage(MSGID_BIND_PASSWORD_EXPIRING, "The user password is about to expire (time to " + "expiration: %s)"); @@ -8549,6 +8609,17 @@ registerMessage(MSGID_ENTRYENCODECFG_INVALID_LENGTH, "Unable to decode the provided entry encode " + "configuration element because it has an invalid length"); registerMessage(MSGID_IDLETIME_LIMIT_EXCEEDED, "This connection has been teriminated because it has " + "remained idle for too long"); registerMessage(MSGID_IDLETIME_DISCONNECT_ERROR, "An error occurred while attempting to disconnect " + "client connection %d: %s"); registerMessage(MSGID_IDLETIME_UNEXPECTED_ERROR, "An unexpected error occurred in the idle time limit " + "thread: %s"); } } opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -89,6 +89,7 @@ import org.opends.server.types.ResultCode; import org.opends.server.types.SearchResultEntry; import org.opends.server.types.SearchResultReference; import org.opends.server.util.TimeThread; @@ -108,6 +109,9 @@ // The time that the last operation was completed. private AtomicLong lastCompletionTime; // The next operation ID that should be used for this connection. private AtomicLong nextOperationID; @@ -240,6 +244,7 @@ ldapVersion = 3; requestHandler = null; lastCompletionTime = new AtomicLong(TimeThread.getTime()); nextOperationID = new AtomicLong(0); connectionValid = true; disconnectRequested = false; @@ -1210,6 +1215,7 @@ } operationsInProgress.remove(messageID); lastCompletionTime.set(TimeThread.getTime()); throw de; } @@ -1247,7 +1253,15 @@ public boolean removeOperationInProgress(int messageID) { AbstractOperation operation = operationsInProgress.remove(messageID); return (operation != null); if (operation == null) { return false; } else { lastCompletionTime.set(TimeThread.getTime()); return true; } } @@ -1333,6 +1347,12 @@ } } if (! (operationsInProgress.isEmpty() && getPersistentSearches().isEmpty())) { lastCompletionTime.set(TimeThread.getTime()); } operationsInProgress.clear(); @@ -1401,12 +1421,14 @@ } operationsInProgress.remove(msgID); lastCompletionTime.set(TimeThread.getTime()); } for (PersistentSearch persistentSearch : getPersistentSearches()) { DirectoryServer.deregisterPersistentSearch(persistentSearch); lastCompletionTime.set(TimeThread.getTime()); } } catch (Exception e) @@ -2789,5 +2811,32 @@ { return connectionHandler.getSSLServerCertNickname(); } /** * Retrieves the length of time in milliseconds that this client * 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. * * @return The length of time in milliseconds that this client * connection has been idle. */ public long getIdleTime() { if (operationsInProgress.isEmpty() && getPersistentSearches().isEmpty()) { return (TimeThread.getTime() - lastCompletionTime.get()); } else { // There's at least one operation in progress, so it's not idle. return 0L; } } } opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -3091,6 +3091,7 @@ int sizeLimit = DirectoryServer.getSizeLimit(); int timeLimit = DirectoryServer.getTimeLimit(); int lookthroughLimit = DirectoryServer.getLookthroughLimit(); long idleTimeLimit = DirectoryServer.getIdleTimeLimit(); boolean skipPostOperation = false; // The password policy state information for this bind operation. @@ -3705,6 +3706,53 @@ } // See if the user's entry contains a custom idle time limit. attrType = DirectoryServer.getAttributeType( OP_ATTR_USER_IDLE_TIME_LIMIT, true); attrList = userEntry.getAttribute(attrType); if ((attrList != null) && (attrList.size() == 1)) { Attribute a = attrList.get(0); LinkedHashSet<AttributeValue> values = a.getValues(); Iterator<AttributeValue> iterator = values.iterator(); if (iterator.hasNext()) { AttributeValue v = iterator.next(); if (iterator.hasNext()) { int msgID = MSGID_BIND_MULTIPLE_USER_IDLE_TIME_LIMITS; String message = getMessage(msgID, String.valueOf(userEntry.getDN())); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_WARNING, message, msgID); } else { try { idleTimeLimit = 1000L * Long.parseLong(v.getStringValue()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_BIND_CANNOT_PROCESS_USER_IDLE_TIME_LIMIT; String message = getMessage(msgID, v.getStringValue(), String.valueOf(userEntry.getDN())); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_WARNING, message, msgID); } } } } // See if the user's entry contains a custom lookthrough limit. attrType = DirectoryServer.getAttributeType( @@ -4272,6 +4320,53 @@ } // See if the user's entry contains a custom idle time limit. attrType = DirectoryServer.getAttributeType( OP_ATTR_USER_IDLE_TIME_LIMIT, true); attrList = saslAuthUserEntry.getAttribute(attrType); if ((attrList != null) && (attrList.size() == 1)) { Attribute a = attrList.get(0); LinkedHashSet<AttributeValue> values = a.getValues(); Iterator<AttributeValue> iterator = values.iterator(); if (iterator.hasNext()) { AttributeValue v = iterator.next(); if (iterator.hasNext()) { int msgID = MSGID_BIND_MULTIPLE_USER_IDLE_TIME_LIMITS; String message = getMessage(msgID, String.valueOf(userDNString)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_WARNING, message, msgID); } else { try { idleTimeLimit = 1000L * Long.parseLong(v.getStringValue()); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } int msgID = MSGID_BIND_CANNOT_PROCESS_USER_IDLE_TIME_LIMIT; String message = getMessage(msgID, v.getStringValue(), String.valueOf(userDNString)); logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_WARNING, message, msgID); } } } } // See if the user's entry contains a custom lookthrough limit. attrType = DirectoryServer.getAttributeType( @@ -4422,6 +4517,7 @@ clientConnection.setAuthenticationInfo(authInfo); clientConnection.setSizeLimit(sizeLimit); clientConnection.setTimeLimit(timeLimit); clientConnection.setIdleTimeLimit(idleTimeLimit); clientConnection.setLookthroughLimit(lookthroughLimit); clientConnection.setMustChangePassword(mustChangePassword); opends/tests/unit-tests-testng/src/server/org/opends/server/core/IdleTimeLimitTestCase.java
New file @@ -0,0 +1,275 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.core; import java.net.Socket; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.opends.server.TestCaseUtils; import org.opends.server.protocols.asn1.*; import org.opends.server.protocols.ldap.*; import org.opends.server.tools.dsconfig.DSConfig; import static org.testng.Assert.*; /** * A set of test cases that involve disconnecting clients due to the idle time * limit. */ public class IdleTimeLimitTestCase extends CoreTestCase { /** * Ensures that the Directory Server is running. * * @throws Exception If an unexpected problem occurs. */ @BeforeClass() public void startServer() throws Exception { TestCaseUtils.startServer(); } /** * Tests the server-wide idle time limit for an anonymous connection. * * @throws Exception If an unexpected problem occurs. */ @Test(groups="slow") public void testServerWideAnonymousIdleTimeLimit() throws Exception { String[] args = { "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-D", "cn=Directory Manager", "-w", "password", "set-global-configuration-prop", "--set", "idle-time-limit:5 seconds" }; assertEquals(DSConfig.main(args, false, System.out, System.err), 0); Socket s = null; try { s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort()); ASN1Writer w = new ASN1Writer(s); ASN1Reader r = new ASN1Reader(s); r.setIOTimeout(60000); LDAPMessage m = LDAPMessage.decode(r.readElement().decodeAsSequence()); ExtendedResponseProtocolOp extendedResponse = m.getExtendedResponseProtocolOp(); assertEquals(extendedResponse.getOID(), LDAPConstants.OID_NOTICE_OF_DISCONNECTION); assertNull(r.readElement()); } finally { try { s.close(); } catch (Exception e) {} args = new String[] { "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-D", "cn=Directory Manager", "-w", "password", "set-global-configuration-prop", "--set", "idle-time-limit:0 seconds" }; assertEquals(DSConfig.main(args, false, System.out, System.err), 0); } } /** * Tests the server-wide idle time limit for an authenticated connection. * * @throws Exception If an unexpected problem occurs. */ @Test(groups="slow") public void testServerWideAuthenticatedIdleTimeLimit() throws Exception { TestCaseUtils.initializeTestBackend(true); TestCaseUtils.addEntry( "dn: uid=test.user,o=test", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "userPassword: password" ); String[] args = { "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-D", "cn=Directory Manager", "-w", "password", "set-global-configuration-prop", "--set", "idle-time-limit:5 seconds" }; assertEquals(DSConfig.main(args, false, System.out, System.err), 0); Socket s = null; try { s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort()); ASN1Writer w = new ASN1Writer(s); ASN1Reader r = new ASN1Reader(s); r.setIOTimeout(60000); BindRequestProtocolOp bindRequest = new BindRequestProtocolOp( new ASN1OctetString("uid=test.user,o=test"), 3, new ASN1OctetString("password")); LDAPMessage m = new LDAPMessage(1, bindRequest); w.writeElement(m.encode()); m = LDAPMessage.decode(r.readElement().decodeAsSequence()); BindResponseProtocolOp bindResponse = m.getBindResponseProtocolOp(); assertEquals(bindResponse.getResultCode(), 0); m = LDAPMessage.decode(r.readElement().decodeAsSequence()); ExtendedResponseProtocolOp extendedResponse = m.getExtendedResponseProtocolOp(); assertEquals(extendedResponse.getOID(), LDAPConstants.OID_NOTICE_OF_DISCONNECTION); assertNull(r.readElement()); } finally { try { s.close(); } catch (Exception e) {} args = new String[] { "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-D", "cn=Directory Manager", "-w", "password", "set-global-configuration-prop", "--set", "idle-time-limit:0 seconds" }; assertEquals(DSConfig.main(args, false, System.out, System.err), 0); } } /** * Tests a user-specific idle time limit. * * @throws Exception If an unexpected problem occurs. */ @Test(groups="slow") public void testUserSpecificIdleTimeLimit() throws Exception { TestCaseUtils.initializeTestBackend(true); TestCaseUtils.addEntry( "dn: uid=test.user,o=test", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "userPassword: password", "ds-rlim-idle-time-limit: 5" ); Socket s = null; try { s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort()); ASN1Writer w = new ASN1Writer(s); ASN1Reader r = new ASN1Reader(s); r.setIOTimeout(60000); BindRequestProtocolOp bindRequest = new BindRequestProtocolOp( new ASN1OctetString("uid=test.user,o=test"), 3, new ASN1OctetString("password")); LDAPMessage m = new LDAPMessage(1, bindRequest); w.writeElement(m.encode()); m = LDAPMessage.decode(r.readElement().decodeAsSequence()); BindResponseProtocolOp bindResponse = m.getBindResponseProtocolOp(); assertEquals(bindResponse.getResultCode(), 0); m = LDAPMessage.decode(r.readElement().decodeAsSequence()); ExtendedResponseProtocolOp extendedResponse = m.getExtendedResponseProtocolOp(); assertEquals(extendedResponse.getOID(), LDAPConstants.OID_NOTICE_OF_DISCONNECTION); assertNull(r.readElement()); } finally { try { s.close(); } catch (Exception e) {} } } }