/*
* 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
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
* Portions copyright 2011-2013 ForgeRock AS.
*/
package org.opends.server.core;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.*;
import org.opends.server.types.*;
import org.opends.server.TestCaseUtils;
import org.opends.server.tools.LDAPWriter;
import org.opends.server.util.ServerConstants;
import org.opends.server.controls.LDAPAssertionRequestControl;
import org.opends.server.controls.ProxiedAuthV1Control;
import org.opends.server.controls.ProxiedAuthV2Control;
import org.opends.server.plugins.InvocationCounterPlugin;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.net.Socket;
public class CompareOperationTestCase extends OperationTestCase
{
private Entry entry;
private InternalClientConnection proxyUserConn;
@BeforeClass
public void setUp() throws Exception
{
TestCaseUtils.startServer();
TestCaseUtils.initializeTestBackend(true);
InternalClientConnection connection =
InternalClientConnection.getRootConnection();
// Add a test entry.
entry = TestCaseUtils.makeEntry(
"dn: uid=rogasawara,o=test",
"userpassword: password",
"objectclass: top",
"objectclass: person",
"objectclass: organizationalPerson",
"objectclass: inetOrgPerson",
"uid: rogasawara",
"mail: rogasawara@airius.co.jp",
"givenname;lang-ja:: 44Ot44OJ44OL44O8",
"sn;lang-ja:: 5bCP56yg5Y6f",
"cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==",
"title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==",
"preferredlanguage: ja",
"givenname:: 44Ot44OJ44OL44O8",
"sn:: 5bCP56yg5Y6f",
"cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==",
"title:: 5Za25qWt6YOoIOmDqOmVtw==",
"givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8",
"sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ",
"cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==",
"title;lang-ja;phonetic:: " +
"44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==",
"givenname;lang-en: Rodney",
"sn;lang-en: Ogasawara",
"cn;lang-en: Rodney Ogasawara",
"title;lang-en: Sales, Director",
"aci: (targetattr=\"*\")(version 3.0; acl \"Proxy Rights\"; " +
"allow(proxy) userdn=\"ldap:///uid=proxy.user,o=test\";)"
);
AddOperation addOperation =
connection.processAdd(entry.getDN(),
entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertNotNull(DirectoryServer.getEntry(entry.getDN()));
// Add a user capable of using the proxied authorization control.
TestCaseUtils.addEntry(
"dn: uid=proxy.user,o=test",
"objectClass: top",
"objectClass: person",
"objectClass: organizationalPerson",
"objectClass: inetOrgPerson",
"uid: proxy.user",
"givenName: Proxy",
"sn: User",
"cn: Proxy User",
"userPassword: password",
"ds-privilege-name: bypass-acl",
"ds-privilege-name: proxied-auth");
proxyUserConn =
new InternalClientConnection(DN.decode("uid=proxy.user,o=test"));
}
@Override
protected Operation[] createTestOperations() throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
return new Operation[]
{
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"))
};
}
/**
* Invokes a number of operation methods on the provided compare operation
* for which all processing has been completed.
*
* @param compareOperation The operation to be tested.
*/
private void examineCompletedOperation(CompareOperation compareOperation)
{
assertTrue(compareOperation.getProcessingStartTime() > 0);
assertTrue(compareOperation.getProcessingStopTime() > 0);
assertTrue(compareOperation.getProcessingTime() >= 0);
assertNotNull(compareOperation.getResponseLogElements());
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 1);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 1);
ensurePostReponseHasRun();
// assertEquals(InvocationCounterPlugin.getPostResponseCount(), 1);
}
/**
* Invokes a number of operation methods on the provided compare operation
* for which the pre-operation plugin was not called.
*
* @param compareOperation The operation to be tested.
*/
private void examineIncompleteOperation(CompareOperation compareOperation)
{
assertTrue(compareOperation.getProcessingStartTime() > 0);
assertTrue(compareOperation.getProcessingStopTime() > 0);
assertTrue(compareOperation.getProcessingTime() >= 0);
assertNotNull(compareOperation.getResponseLogElements());
assertTrue(compareOperation.getErrorMessage().length() > 0);
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 0);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 1);
ensurePostReponseHasRun();
// assertEquals(InvocationCounterPlugin.getPostResponseCount(), 1);
}
/**
* Invokes a number of operation methods on the provided compare operation
* for which an error was found during parsing.
*
* @param compareOperation The operation to be tested.
*/
private void examineUnparsedOperation(CompareOperation compareOperation)
{
assertTrue(compareOperation.getProcessingStartTime() > 0);
assertTrue(compareOperation.getProcessingStopTime() > 0);
assertTrue(compareOperation.getProcessingTime() >= 0);
assertNotNull(compareOperation.getResponseLogElements());
assertTrue(compareOperation.getErrorMessage().length() > 0);
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 0);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 0);
ensurePostReponseHasRun();
// assertEquals(InvocationCounterPlugin.getPostResponseCount(), 1);
}
@Test
public void testCompareTrue()
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_TRUE);
assertEquals(compareOperation.getErrorMessage().length(), 0);
examineCompletedOperation(compareOperation);
}
@Test
public void testCompareFalse()
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawala"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_FALSE);
assertEquals(compareOperation.getErrorMessage().length(), 0);
examineCompletedOperation(compareOperation);
}
@Test
public void testCompareEntryNonexistent()
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf("o=nonexistent,o=test"),
"o", ByteString.valueOf("nonexistent"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.NO_SUCH_OBJECT);
examineIncompleteOperation(compareOperation);
}
@Test
public void testCompareInvalidDn()
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf("rogasawara,o=test"),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.INVALID_DN_SYNTAX);
examineUnparsedOperation(compareOperation);
}
@Test
public void testCompareNoSuchAttribute()
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"description", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.NO_SUCH_ATTRIBUTE);
assertTrue(compareOperation.getErrorMessage().length() > 0);
examineCompletedOperation(compareOperation);
}
@Test
public void testCompareUndefinedAttribute()
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"NotAnAttribute",
ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.NO_SUCH_ATTRIBUTE);
assertTrue(compareOperation.getErrorMessage().length() > 0);
examineCompletedOperation(compareOperation);
}
@Test
public void testCompareSubtype()
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"name",
ByteString.valueOf("Ogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_TRUE);
}
@Test
public void testCompareOptions1()
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"sn",
ByteString.valueOf("Ogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_TRUE);
}
@Test
public void testCompareOptions2()
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"sn;lang-ja",
ByteString.valueOf("Ogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_FALSE);
}
@Test
public void testCompareOptions3()
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf(entry.getDN().toString()),
"givenName;lAnG-En",
ByteString.valueOf("Rodney"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_TRUE);
}
@Test
public void testCompareTrueAssertion() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
LDAPFilter ldapFilter = LDAPFilter.decode("(preferredlanguage=ja)");
LDAPAssertionRequestControl assertControl =
new LDAPAssertionRequestControl(true, ldapFilter);
List<Control> controls = new ArrayList<Control>();
controls.add(assertControl);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_TRUE);
assertEquals(compareOperation.getErrorMessage().length(), 0);
examineCompletedOperation(compareOperation);
}
@Test
public void testCompareAssertionFailed() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
LDAPFilter ldapFilter = LDAPFilter.decode("(preferredlanguage=en)");
LDAPAssertionRequestControl assertControl =
new LDAPAssertionRequestControl(true, ldapFilter);
List<Control> controls = new ArrayList<Control>();
controls.add(assertControl);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.ASSERTION_FAILED);
examineIncompleteOperation(compareOperation);
}
@Test
public void testCompareProxiedAuthV1() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
ProxiedAuthV1Control authV1Control =
new ProxiedAuthV1Control(ByteString.valueOf(
"cn=Directory Manager,cn=Root DNs,cn=config"));
List<Control> controls = new ArrayList<Control>();
controls.add(authV1Control);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_TRUE);
assertEquals(compareOperation.getErrorMessage().length(), 0);
examineCompletedOperation(compareOperation);
}
@Test
public void testCompareProxiedAuthV1Denied() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
ProxiedAuthV1Control authV1Control =
new ProxiedAuthV1Control(ByteString.valueOf("cn=nonexistent,o=test"));
List<Control> controls = new ArrayList<Control>();
controls.add(authV1Control);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.AUTHORIZATION_DENIED);
examineIncompleteOperation(compareOperation);
}
@Test
public void testCompareProxiedAuthV2() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
ProxiedAuthV2Control authV2Control =
new ProxiedAuthV2Control(ByteString.valueOf(
"dn:cn=Directory Manager,cn=Root DNs,cn=config"));
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.COMPARE_TRUE);
assertEquals(compareOperation.getErrorMessage().length(), 0);
examineCompletedOperation(compareOperation);
}
@Test
public void testCompareProxiedAuthV2Denied() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
ProxiedAuthV2Control authV2Control = new ProxiedAuthV2Control(
ByteString.valueOf("dn:cn=nonexistent,o=test"));
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.AUTHORIZATION_DENIED);
examineIncompleteOperation(compareOperation);
}
@Test
public void testCompareProxiedAuthV2Criticality() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
Control authV2Control =
new LDAPControl(ServerConstants.OID_PROXIED_AUTH_V2, false,
ByteString.empty());
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.PROTOCOL_ERROR);
examineIncompleteOperation(compareOperation);
}
@Test
public void testCompareUnsupportedControl() throws Exception
{
InvocationCounterPlugin.resetAllCounters();
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
LDAPFilter.decode("(preferredlanguage=ja)");
LDAPControl assertControl =
new LDAPControl("1.1.1.1.1.1", true);
List<Control> controls = new ArrayList<Control>();
controls.add(assertControl);
CompareOperationBasis compareOperation =
new CompareOperationBasis(
conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
compareOperation.run();
assertEquals(compareOperation.getResultCode(),
ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
examineIncompleteOperation(compareOperation);
}
@Test(groups = "slow")
public void testCompareWriteLock() throws Exception
{
// We need the operation to be run in a separate thread because we are going
// to write lock the entry in the test case thread and check that the
// compare operation does not proceed.
// Establish a connection to the server.
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
try
{
org.opends.server.tools.LDAPReader r =
new org.opends.server.tools.LDAPReader(s);
LDAPWriter w = new LDAPWriter(s);
TestCaseUtils.configureSocket(s);
BindRequestProtocolOp bindRequest =
new BindRequestProtocolOp(
ByteString.valueOf("cn=Directory Manager"),
3, ByteString.valueOf("password"));
LDAPMessage message = new LDAPMessage(1, bindRequest);
w.writeMessage(message);
message = r.readMessage();
BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
assertEquals(bindResponse.getResultCode(), LDAPResultCode.SUCCESS);
// Since we are going to be watching the post-response count, we need to
// wait for the server to become idle before kicking off the next request
// to ensure that any remaining post-response processing from the previous
// operation has completed.
TestCaseUtils.quiesceServer();
Lock writeLock = LockManager.lockWrite(entry.getDN());
assertNotNull(writeLock);
try
{
InvocationCounterPlugin.resetAllCounters();
long compareRequests = ldapStatistics.getCompareRequests();
long compareResponses = ldapStatistics.getCompareResponses();
CompareRequestProtocolOp compareRequest =
new CompareRequestProtocolOp(
ByteString.valueOf(entry.getDN().toString()),
"uid", ByteString.valueOf("rogasawara"));
message = new LDAPMessage(2, compareRequest);
w.writeMessage(message);
message = r.readMessage();
CompareResponseProtocolOp compareResponse =
message.getCompareResponseProtocolOp();
assertEquals(compareResponse.getResultCode(), LDAPResultCode.BUSY);
// assertEquals(InvocationCounterPlugin.getPreParseCount(), 1);
// assertEquals(InvocationCounterPlugin.getPreOperationCount(), 0);
// assertEquals(InvocationCounterPlugin.getPostOperationCount(), 0);
// The post response might not have been called yet.
assertEquals(InvocationCounterPlugin.waitForPostResponse(), 1);
assertEquals(ldapStatistics.getCompareRequests(), compareRequests+1);
assertEquals(ldapStatistics.getCompareResponses(), compareResponses+1);
} finally
{
LockManager.unlock(entry.getDN(), writeLock);
}
} finally
{
s.close();
}
}
}