/*
|
* The contents of this file are subject to the terms of the Common Development and
|
* Distribution License (the License). You may not use this file except in compliance with the
|
* License.
|
*
|
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
|
* specific language governing permission and limitations under the License.
|
*
|
* When distributing Covered Software, include this CDDL Header Notice in each file and include
|
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
|
* Header, with the fields enclosed by brackets [] replaced by your own identifying
|
* information: "Portions Copyright [year] [name of copyright owner]".
|
*
|
* Copyright 2008-2009 Sun Microsystems, Inc.
|
* Portions Copyright 2011-2015 ForgeRock AS.
|
*/
|
package org.opends.server.authorization.dseecompat;
|
|
import java.util.Hashtable;
|
|
import javax.naming.Context;
|
|
import org.opends.server.TestCaseUtils;
|
import org.opends.server.protocols.ldap.LDAPResultCode;
|
import org.testng.annotations.*;
|
import static org.opends.server.config.ConfigConstants.*;
|
|
/**
|
* Unit test to test the ssf ACI bind rule keyword.
|
*/
|
public class SSFTestCase extends AciTestCase {
|
|
private static final String newUser="uid=new.user,ou=People,o=test";
|
private static final String descriptionStr = "description of user.1";
|
private static final String factory = "com.sun.jndi.ldap.LdapCtxFactory";
|
private static final String pwdPolicy = "Aci Temp Policy";
|
private static final String pwdPolicyDN =
|
"cn=" + pwdPolicy + ",cn=Password Policies,cn=config";
|
|
private static final String[] newEntry = new String[] {
|
"objectClass: top",
|
"objectClass: person",
|
"objectClass: organizationalPerson",
|
"objectClass: inetOrgPerson",
|
"uid: new.user",
|
"givenName: New",
|
"sn: User",
|
"cn: New User",
|
"mail: new.user@test.com",
|
"ds-pwp-password-policy-dn:" + pwdPolicyDN
|
};
|
|
private static final
|
String integrityACI = "(targetattr=\"" + "*" + "\")" +
|
"(version 3.0; acl \"integrity aci\";" +
|
"allow(all) (userdn=\"ldap:///self\" and ssf = \"1\");)";
|
|
private static final
|
String greaterIntegrityACI = "(targetattr=\"" + "*" + "\")" +
|
"(version 3.0; acl \"greater integrity aci\";" +
|
"allow(all) (userdn=\"ldap:///self\" and ssf > \"1\");)";
|
|
|
private static final
|
String medStrengthACI = "(targetattr=\"" + "*" + "\")" +
|
"(version 3.0; acl \"56 bit key aci\";" +
|
"allow(all) (userdn=\"ldap:///self\" and ssf = \"56\");)";
|
|
|
private static final
|
String medStrengthNEACI = "(targetattr=\"" + "*" + "\")" +
|
"(version 3.0; acl \"NE 56 bit key aci\";" +
|
"allow(all) (userdn=\"ldap:///self\" and ssf != \"56\");)";
|
|
|
private static final
|
String hiStrengthACI = "(targetattr=\"" + "*" + "\")" +
|
"(version 3.0; acl \"128 bit key aci\";" +
|
"allow(all) (userdn=\"ldap:///self\" and ssf = \"128\");)";
|
|
|
private static final
|
String hiPlusStrengthACI = "(targetattr=\"" + "*" + "\")" +
|
"(version 3.0; acl \"greater 128 bit aci\";" +
|
"allow(all) (userdn=\"ldap:///self\" and ssf > \"128\");)";
|
|
|
@BeforeClass
|
public void setupClass() throws Exception {
|
TestCaseUtils.initializeTestBackend(true);
|
TestCaseUtils.dsconfig(
|
"create-password-policy",
|
"--type", "password-policy",
|
"--policy-name", pwdPolicy,
|
"--set", "password-attribute:userPassword",
|
"--set", "default-password-storage-scheme: Clear"
|
);
|
TestCaseUtils.dsconfig(
|
"set-sasl-mechanism-handler-prop",
|
"--handler-name", "DIGEST-MD5",
|
"--set", "server-fqdn:localhost");
|
deleteAttrFromAdminEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
|
String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN,
|
G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL, E_EXTEND_OP);
|
LDIFAdminModify(aciLdif, DIR_MGR_DN, PWD);
|
addEntries("o=test");
|
String newUserLDIF=makeAddEntryLDIF(newUser, newEntry);
|
LDIFAdd(newUserLDIF, DIR_MGR_DN, PWD, null, LDAPResultCode.SUCCESS);
|
String pwdILDIF =
|
makeAddLDIF("userpassword", newUser, "password");
|
LDIFModify(pwdILDIF, DIR_MGR_DN, PWD);
|
}
|
|
@AfterClass(alwaysRun = true)
|
public void tearDown() throws Exception {
|
TestCaseUtils.dsconfig(
|
"delete-password-policy",
|
"--policy-name", pwdPolicy
|
);
|
TestCaseUtils.dsconfig(
|
"set-sasl-mechanism-handler-prop",
|
"--handler-name", "DIGEST-MD5",
|
"--reset", "server-fqdn",
|
"--reset", "quality-of-protection");
|
|
}
|
|
/** Valid ssf statements. Not the complete ACI. */
|
@DataProvider(name = "validStatements")
|
public Object[][] valids() {
|
return new Object[][] {
|
{"1"},
|
{"40"},
|
{"56"},
|
{"128"},
|
{"256"},
|
{"129"},
|
};
|
}
|
|
/** Invalid ssf statements. Not the complete ACI. */
|
@DataProvider(name = "invalidStatements")
|
public Object[][] invalids() {
|
return new Object[][] {
|
{"-1"},
|
{"0"},
|
{"not valid"},
|
{"1025"},
|
{"10000"},
|
};
|
}
|
|
private EnumBindRuleType bindRuleType = EnumBindRuleType.EQUAL_BINDRULE_TYPE;
|
|
/**
|
* Test valid ssf statements.
|
*
|
* @param statement The ssf statement to attempt to decode.
|
* @throws AciException If an unexpected result happens.
|
*/
|
@Test(dataProvider = "validStatements")
|
public void testValidStatements(String statement) throws AciException {
|
SSF.decode(statement, bindRuleType);
|
}
|
|
/**
|
* Test invalid ssf statements.
|
*
|
* @param statement The ssf statement to attempt to decode.
|
* @throws Exception If an unexpected result happens.
|
*/
|
@Test(expectedExceptions= AciException.class,
|
dataProvider="invalidStatements")
|
public void testInvalidStatements(String statement) throws Exception {
|
try {
|
SSF.decode(statement, bindRuleType);
|
} catch (AciException e) {
|
throw e;
|
} catch (Exception e) {
|
System.out.println(
|
"Invalid ssf <" + statement +
|
"> threw wrong exception type.");
|
throw e;
|
}
|
throw new RuntimeException(
|
"Invalid ssf <" + statement +
|
"> did not throw an exception.");
|
}
|
|
/**
|
* Test ssf bind rule using ssf value for integrity.
|
*
|
* @throws Exception If a test doesn't pass.
|
*/
|
@Test
|
public void testIntegrity() throws Exception {
|
//set QOP to integrity.
|
TestCaseUtils.dsconfig(
|
"set-sasl-mechanism-handler-prop",
|
"--handler-name", "DIGEST-MD5",
|
"--set", "quality-of-protection:" + "integrity");
|
|
//Configure JNDI props.
|
Hashtable<String, String> env = new Hashtable<>();
|
env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
|
int port = TestCaseUtils.getServerLdapPort();
|
String url = "ldap://localhost:" + Integer.valueOf(port);
|
env.put(Context.PROVIDER_URL, url);
|
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
|
String principal = "dn:" + newUser;
|
env.put(Context.SECURITY_PRINCIPAL, principal);
|
env.put(Context.SECURITY_CREDENTIALS, "password");
|
//Select integrity QOP.
|
env.put("javax.security.sasl.qop", "auth-int");
|
//Add ACI with ssf > 1, should fail.
|
String addACILDIF = makeAddLDIF("aci", newUser, greaterIntegrityACI);
|
LDIFModify(addACILDIF, DIR_MGR_DN, PWD);
|
JNDIModify(env, newUser, "description", descriptionStr,
|
LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
|
deleteAttrFromEntry(newUser, "aci");
|
//Add ACI with ssf = 1.
|
addACILDIF = makeAddLDIF("aci", newUser, integrityACI);
|
LDIFModify(addACILDIF, DIR_MGR_DN, PWD);
|
//Should succeed.
|
JNDIModify(env, newUser, "description", descriptionStr,
|
LDAPResultCode.SUCCESS);
|
deleteAttrFromEntry(newUser, "aci");
|
deleteAttrFromEntry(newUser, "description");
|
}
|
|
/**
|
* Test confidentiality settings using DIGEST-MD5.
|
* @throws Exception
|
*/
|
@Test
|
public void testConfidentiality() throws Exception {
|
//set QOP to integrity.
|
TestCaseUtils.dsconfig(
|
"set-sasl-mechanism-handler-prop",
|
"--handler-name", "DIGEST-MD5",
|
"--set", "quality-of-protection:" + "confidentiality");
|
Hashtable<String, String> env = new Hashtable<>();
|
env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
|
int port = TestCaseUtils.getServerLdapPort();
|
String url = "ldap://localhost:" + Integer.valueOf(port);
|
env.put(Context.PROVIDER_URL, url);
|
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
|
String principal = "dn:" + newUser;
|
env.put(Context.SECURITY_PRINCIPAL, principal);
|
env.put(Context.SECURITY_CREDENTIALS, "password");
|
//Select integrity QOP.
|
env.put("javax.security.sasl.qop", "auth-conf");
|
//Add ACI with ssf > 1, should succeed.
|
String addACILDIF = makeAddLDIF("aci", newUser, greaterIntegrityACI);
|
LDIFModify(addACILDIF, DIR_MGR_DN, PWD);
|
JNDIModify(env, newUser, "description", descriptionStr,
|
LDAPResultCode.SUCCESS);
|
deleteAttrFromEntry(newUser, "aci");
|
deleteAttrFromEntry(newUser, "description");
|
//Test medium strength.
|
addACILDIF = makeAddLDIF("aci", newUser, medStrengthACI);
|
LDIFModify(addACILDIF, DIR_MGR_DN, PWD);
|
env.put("javax.security.sasl.strength", "medium");
|
JNDIModify(env, newUser, "description", descriptionStr,
|
LDAPResultCode.SUCCESS);
|
deleteAttrFromEntry(newUser, "aci");
|
deleteAttrFromEntry(newUser, "description");
|
//Test medium strength "!="
|
addACILDIF = makeAddLDIF("aci", newUser, medStrengthNEACI);
|
LDIFModify(addACILDIF, DIR_MGR_DN, PWD);
|
env.put("javax.security.sasl.strength", "medium");
|
JNDIModify(env, newUser, "description", descriptionStr,
|
LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
|
deleteAttrFromEntry(newUser, "aci");
|
deleteAttrFromEntry(newUser, "description");
|
//Test high strength.
|
// TODO: this hangs sometimes during the JNDIModify (see OPENDJ-256).
|
addACILDIF = makeAddLDIF("aci", newUser, hiStrengthACI);
|
LDIFModify(addACILDIF, DIR_MGR_DN, PWD);
|
env.put("javax.security.sasl.strength", "high");
|
JNDIModify(env, newUser, "description", descriptionStr,
|
LDAPResultCode.SUCCESS);
|
deleteAttrFromEntry(newUser, "aci");
|
deleteAttrFromEntry(newUser, "description");
|
//Fail DIGEST-MD5 only goes to 128.
|
addACILDIF = makeAddLDIF("aci", newUser, hiPlusStrengthACI);
|
LDIFModify(addACILDIF, DIR_MGR_DN, PWD);
|
env.put("javax.security.sasl.strength", "high");
|
JNDIModify(env, newUser, "description", descriptionStr,
|
LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
|
deleteAttrFromEntry(newUser, "aci");
|
deleteAttrFromEntry(newUser, "description");
|
}
|
}
|