/*
* 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 2008 Sun Microsystems, Inc.
* Portions Copyright 2012 Forgerock AS
*/
package org.opends.server.protocols.ldap;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.File;
import java.net.Socket;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.tools.*;
import org.opends.server.types.*;
import org.opends.server.util.Base64;
import org.testng.annotations.*;
import static org.testng.Assert.*;
/*
* This class defines a set of testcases for testing the ;binary transfer
* option functionality across different protocol versions of LDAP.
*/
public class LDAPBinaryOptionTestCase extends LdapTestCase {
// Exported LDIF file.
File ldif = null;
//LDIFExportConfig used for exporting entries.
LDIFExportConfig exportConfig = null;
//LDIFImportConfig used for importing entries.
LDIFImportConfig importConfig = null;
//Test Backend.
Backend backend = null;
//Constant value of userCertificate attribute.
private static final String CERT=
"MIIB5TCCAU6gAwIBAgIERloIajANBgkqhkiG9" +
"w0BAQUFADA3MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRXhhbXBs" +
"ZSBDb3JwMREwDwYDVQQDEwhKb2huIERvZTAeFw0wNzA1MjcyMjM4" +
"MzRaFw0wNzA4MjUyMjM4MzRaMDcxCzAJBgNVBAYTAlVTMRUwEwYD" +
"VQQKEwxFeGFtcGxlIENvcnAxETAPBgNVBAMTCEpvaG4gRG9lMIGfMA" +
"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWNZB4qs1UvjYgvGvB" +
"9udmiUi4X4DeaSm3o0p8PSwpOFxSqgWdSwKgUugZ1EJVyYoakljDFs" +
"J0GVown+dIB24V4ozNs6wa0YotIKTV2AcySQkmzzP3e+OnE9Aa1wlB/" +
"PVnh1CFLgk1UOoruLE10bac5HA8QiAmfNMorU26AwFTcwIDAQABMA" +
"0GCSqGSIb3DQEBBQUAA4GBAGrzMKNbBRWn+LIfYTfqKYUc258XVbhFri" +
"1OV0oF82vyvciYWZzyxLc52EPDsymLmcDh+CdWxy3bVkjdMg1WEtMGr" +
"1GsxOVi/vWe+kT4tPhinnB4Fowf8zgqiUKo9/FJN26y7Fpvy1IODiBInDrKZ" +
"RvNfqemCf7o3+Cp00OmF5ey";
/**
* Ensures that the Directory Server is running before executing the
* testcases.
*
* @throws Exception If an unexpected problem occurs.
*/
@BeforeClass()
public void startServer()
throws Exception
{
TestCaseUtils.startServer();
TestCaseUtils.initializeTestBackend(true);
}
/**
* Test to verify an ADD of the binary attributes using a V3
* protocol.
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void binaryAttributeAddV3() throws Exception
{
//Add a binary attribute both with or without the binary option.
String filePath = TestCaseUtils.createTempFile(
"dn: uid=user.1,o=test",
"objectClass: inetOrgPerson",
"uid: user.1",
"sn: 1",
"cn: user 1",
"userCertificate:: "+CERT
);
String[] args = new String []
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D","cn=directory manager",
"-w","password",
"-a",
"-f", filePath
};
int err = LDAPModify.mainModify(args, false, null,null);
assertEquals(err,0);
//ADD with ;binary option.
filePath = TestCaseUtils.createTempFile(
"dn: uid=user.2,o=test",
"objectClass: inetOrgPerson",
"uid: user.2",
"sn: 2",
"cn: user 2",
"userCertificate;binary:: "+CERT
);
args = new String []
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D","cn=directory manager",
"-w","password",
"-a",
"-f", filePath
};
err = LDAPModify.mainModify(args, false, null,null);
assertEquals(err,0);
}
/**
* Test to verify an ADD of a non-binary attribute with the ;binary
* transfer option using a V3 protocol.
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void nonBinaryAttributeAddV3() throws Exception
{
String filePath = TestCaseUtils.createTempFile(
"dn: uid=user.3,o=test",
"objectClass: inetOrgPerson",
"uid: user.3",
"sn: 3",
"cn: user 3",
"cn;binary: common name"
);
String[] args = new String []
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D","cn=directory manager",
"-w","password",
"-a",
"-f", filePath,
};
int err = LDAPModify.mainModify(args, false, null,null);
assertFalse(err==0);
}
/**
* Test to verify a SEARCH using the ;binary transfer option using a V3
* protocol.
* @throws Exception If an unexpected problem occurs.
*/
@Test(dependsOnMethods = {"org.opends.server.protocols.ldap."+
"LDAPBinaryOptionTestCase.binaryAttributeAddV3"})
public void binaryAttributeSearchV3() throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
InternalSearchOperation searchOperation =
new InternalSearchOperation(
conn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf("o=test"),
SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES,
Integer.MAX_VALUE,
Integer.MAX_VALUE,
false,
LDAPFilter.decode("(uid=user.1)"),
null, null);
searchOperation.run();
assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
List<SearchResultEntry> entries = searchOperation.getSearchEntries();
SearchResultEntry e = entries.get(0);
assertNotNull(e);
List<Attribute> attrs = e.getAttribute("usercertificate");
Attribute a = attrs.get(0);
assertNotNull(a);
assertTrue(a.getOptions().contains("binary"));
}
/**
* Test to verify a SEARCH using the ;binary transfer option using a V3
* protocol for a non-binary attribute.
* @throws Exception If an unexpected problem occurs.
*/
@Test(dependsOnMethods = {"org.opends.server.protocols.ldap."+
"LDAPBinaryOptionTestCase.binaryAttributeAddV3"})
public void invalidBinaryAttributeSearchV3() throws Exception
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
LinkedHashSet<String> attrs = new LinkedHashSet<String>();
attrs.add("cn;binary");
InternalSearchOperation searchOperation =
new InternalSearchOperation(
conn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
ByteString.valueOf("o=test"),
SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES,
Integer.MAX_VALUE,
Integer.MAX_VALUE,
false,
LDAPFilter.decode("(uid=user.1)"),
attrs, null);
searchOperation.run();
assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
List<SearchResultEntry> entries = searchOperation.getSearchEntries();
SearchResultEntry e = entries.get(0);
assertNotNull(e);
List<Attribute> list = e.getAttributes();
assertEquals(list.size(), 0);
}
/**
* Test to verify an ADD and SEARCH using the ;binary transfer option using a
* V2 protocol.
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void binaryOptionUsingV2() throws Exception
{
//Construct a V2 connection.
Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());
org.opends.server.tools.LDAPReader r = new org.opends.server.tools.LDAPReader(s);
org.opends.server.tools.LDAPWriter w = new org.opends.server.tools.LDAPWriter(s);
try
{
BindRequestProtocolOp bindRequest =
new BindRequestProtocolOp(
ByteString.valueOf("cn=Directory Manager"), 2,
ByteString.valueOf("password"));
LDAPMessage message = new LDAPMessage(1, bindRequest);
w.writeMessage(message);
message = r.readMessage();
BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
assertEquals(bindResponse.getResultCode(), 0);
ArrayList<RawAttribute> addAttrs = new ArrayList<RawAttribute>();
addAttrs.add(RawAttribute.create("objectClass", "inetOrgPerson"));
addAttrs.add(RawAttribute.create("uid", "user.7"));
addAttrs.add(RawAttribute.create("cn", "user 7"));
addAttrs.add(RawAttribute.create("sn", "sn#1"));
addAttrs.add(RawAttribute.create("sn;x-foo", "sn#2"));
addAttrs.add(RawAttribute.create("sn;lang-fr", "sn#3"));
addAttrs.add(RawAttribute.create("userCertificate;binary",
ByteString.wrap(Base64.decode(CERT))));
AddRequestProtocolOp addRequest =
new AddRequestProtocolOp(ByteString.valueOf("uid=user.7,o=test"),
addAttrs);
message = new LDAPMessage(2, addRequest);
w.writeMessage(message);
message = r.readMessage();
AddResponseProtocolOp addResponse = message.getAddResponseProtocolOp();
assertEquals(addResponse.getResultCode(),0);
//Create a SEARCH request to search for this added entry.
LinkedHashSet<String> attrs = new LinkedHashSet<String>();
//Request only the interesting attributes.
attrs.add("sn");
attrs.add("userCertificate;binary");
SearchRequestProtocolOp searchRequest =
new SearchRequestProtocolOp(ByteString.valueOf("o=test"),
SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES, 0,
0, false,
LDAPFilter.decode("(uid=user.7)"),
attrs);
message = new LDAPMessage(2, searchRequest);
w.writeMessage(message);
SearchResultEntryProtocolOp searchResultEntry = null;
SearchResultDoneProtocolOp searchResultDone = null;
while (searchResultDone == null && message != null)
{
message = r.readMessage();
switch (message.getProtocolOpType())
{
case LDAPConstants.OP_TYPE_SEARCH_RESULT_ENTRY:
searchResultEntry = message.getSearchResultEntryProtocolOp();
break;
case LDAPConstants.OP_TYPE_SEARCH_RESULT_DONE:
searchResultDone = message.getSearchResultDoneProtocolOp();
assertEquals(searchResultDone.getResultCode(),
LDAPResultCode.SUCCESS);
break;
}
}
assertNotNull(searchResultEntry);
boolean certWithNoOption = false;
boolean snWithMultiVal = false;
for(LDAPAttribute a:searchResultEntry.getAttributes())
{
//Shouldn't be userCertificate;binary.
if(a.getAttributeType().equalsIgnoreCase("userCertificate"))
certWithNoOption=true;
else if(a.getAttributeType().equalsIgnoreCase("sn"))
{
List<ByteString> lVal = a.getValues();
for(ByteString v:lVal)
{
String val = v.toString();
if(val.equals("sn#1") || val.equals("sn#2")
|| val.equals("sn#3"))
{
snWithMultiVal = true;
}
else //All the values should match.
snWithMultiVal = false;
}
}
}
assertTrue(snWithMultiVal && certWithNoOption);
}
finally
{
try
{
r.close();
} catch (Exception e) {}
try
{
w.close();
} catch (Exception e) {}
try
{
s.close();
} catch (Exception e) {}
}
}
/**
* Test to verify that the DB stores the binary option by
* exporting the LDIF and searching for the binary keyword.
* @throws Exception If an unexpected problem occurs.
*/
@Test(dependsOnMethods = {"org.opends.server.protocols.ldap."+
"LDAPBinaryOptionTestCase.binaryAttributeAddV3"})
public void exportAndValidateBinaryAttribute() throws Exception
{
//Ensure that the entry exists.
String args[] = new String []
{
"--noPropertiesFile",
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-b", "o=test",
"(uid=user.1)"
};
assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
exportBackend();
assertTrue(ldif.exists());
assertTrue(containsBinary());
}
/**
* Test to verify that the server adds the binary option by
* importing an LDIF both with or without the binary option.
* @throws Exception If an unexpected problem occurs.
*/
@Test(dependsOnMethods = {"org.opends.server.protocols.ldap."+
"LDAPBinaryOptionTestCase.exportAndValidateBinaryAttribute"})
public void ImportAndValidateBinaryAttribute() throws Exception
{
//This testcase uses the exported ldif in exportAndValidBinaryAttribute
//testcase. It imports the ldif after cleaning up the database and verifies
//that the binary option is present in the binary attributes. After that, it
//modifies the binary option from the ldif and re-imports it.A re-export of
//the last import should have the binary option even though it wasn't
//there in the imported ldif.
assert(ldif.exists());
importLDIF();
assertTrue(containsBinary());
//Remove the binary option and re-import it.
FileReader reader = new FileReader(ldif);
BufferedReader buf = new BufferedReader(reader);
StringBuilder builder = new StringBuilder();
String userCert = "userCertificate;binary";
String line = null;
while((line=buf.readLine())!=null)
{
if(line.startsWith(userCert))
{
builder.append("userCertificate:");
builder.append(line.substring(userCert.length()+1, line.length()));
}
else
builder.append(line);
builder.append("\n");
}
buf.close();
ldif.delete();
ldif = new File(TestCaseUtils.createTempFile(builder.toString()));
importLDIF();
//Re-export it.
exportBackend();
assertTrue(containsBinary());
ldif.delete();
}
/**
* Test to verify a MODIFY using the ;binary transfer option using V3
* protocol.
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void binaryModifyV3() throws Exception
{
String filePath = TestCaseUtils.createTempFile(
"dn: uid=user.4,o=test",
"objectClass: inetOrgPerson",
"uid: user.4",
"sn: 4",
"cn: user 4"
);
String[] args = new String []
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D","cn=directory manager",
"-w","password",
"-a",
"-f", filePath,
};
int err = LDAPModify.mainModify(args, false, null,null);
assertEquals(err,0);
filePath = TestCaseUtils.createTempFile(
"dn: uid=user.4,o=test",
"changetype: modify",
"add: usercertificate;binary",
"userCertificate;binary:: " + CERT);
args = new String[]
{
"-h", "127.0.0.1",
"-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
"-D","cn=directory manager",
"-w","password",
"-f", filePath,
};
err = LDAPModify.mainModify(args, false, null,null);
assertEquals(err,0);
}
/**
* Utility method to verify if the LDIF file contains binary option.
* @return {@code true} if binary option is found in the LDIF
* , or {@code false} if not.
* @throws Exception If an unexpected problem occurs.
*/
private boolean containsBinary() throws Exception
{
FileReader reader = new FileReader(ldif);
BufferedReader buf = new BufferedReader(reader);
String line = null;
boolean found=false;
while((line=buf.readLine())!=null)
{
if(line.startsWith("userCertificate;binary"))
found = true;
}
buf.close();
return found;
}
/**
* Utility method to export the database into an LDIF file.
* @throws Exception If an unexpected problem occurs.
*/
private void exportBackend() throws Exception
{
//Initialize necessary instance variables.
if(ldif==null)
ldif = File.createTempFile("LDAPBinaryOptionTestCase", ".ldif");
exportConfig = new LDIFExportConfig(ldif.getAbsolutePath(),
ExistingFileBehavior.OVERWRITE);
backend = DirectoryServer.getBackend("test");
backend.exportLDIF(exportConfig);
}
/**
* Utility method to import the LDIF into the database.
* @throws Exception If an unexpected problem occurs.
*/
private void importLDIF() throws Exception
{
importConfig = new LDIFImportConfig(ldif.getAbsolutePath());
TestCaseUtils.initializeTestBackend(false);
backend = DirectoryServer.getBackend("test");
backend.importLDIF(importConfig);
}
}