| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | * Portions Copyright 2011-2016 ForgeRock AS. |
| | | * Portions Copyright 2013 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.testng.Assert.*; |
| | | |
| | | import java.io.*; |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.io.StringReader; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Calendar; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.GregorianCalendar; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.regex.Pattern; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.protocols.ldap.LDAPResultCode; |
| | | import org.opends.server.tools.*; |
| | | import org.opends.server.tools.LDAPCompare; |
| | | import org.opends.server.tools.LDAPModify; |
| | | import org.opends.server.tools.LDAPSearch; |
| | | import org.opends.server.tools.LDIFDiff; |
| | | import org.opends.server.tools.LDIFModify; |
| | | import org.opends.server.types.LDIFExportConfig; |
| | | import org.opends.server.types.LDIFImportConfig; |
| | | import org.opends.server.util.LDIFReader; |
| | |
| | | private static final String BIND_RULE_USERDN_PARENT = "userdn=\"ldap:///parent\""; |
| | | private static final String BIND_RULE_USERDN_CN_RDN = "userdn=\"ldap:///CN=*,dc=example,dc=com\""; |
| | | private static final String BIND_RULE_USERDN_NOT_UID_RDN = "userdn!=\"ldap:///uid=*,dc=example,dc=com\""; |
| | | // @Checkstyle:off |
| | | private static final String BIND_RULE_USERDN_UID_OR_CN_RDN = "userdn=\"ldap:///uid=*,dc=example,dc=com || ldap:///cn=*,dc=example,dc=com\""; |
| | | private static final String BIND_RULE_USERDN_ALL_CN_ADMINS = "userdn=\"ldap:///dc=example,dc=com??sub?(cn=*admin*)\""; |
| | | /** TODO: this might be invalid? */ |
| | | private static final String BIND_RULE_USERDN_TOP_LEVEL_CN_ADMINS = "userdn=\"ldap:///dc=example,dc=com??one?(cn=*admin*)\""; |
| | | // @Checkstyle:on |
| | | private static final String BIND_RULE_GROUPDN_GROUP_1 = |
| | | "groupdn=\"ldap:///" + OU_GROUP_1_DN + "\""; |
| | | private static final String BIND_RULE_IP_LOCALHOST = "ip=\"127.0.0.1\""; |
| | |
| | | private static final String BIND_RULE_AUTHMETHOD_SSL = "authmethod=\"ssl\""; |
| | | private static final String BIND_RULE_AUTHMETHOD_SASL_DIGEST_MD5 = "authmethod=\"sasl DIGEST-MD5\""; |
| | | |
| | | // @Checkstyle:off |
| | | /** Admin, but not anonymous. */ |
| | | private static final String BIND_RULE_USERDN_NOT_ADMIN = and(not(BIND_RULE_USERDN_ADMIN), BIND_RULE_AUTHMETHOD_SIMPLE); |
| | | |
| | |
| | | private static final String BIND_RULE_IP_NOT_LOCALHOST_OR_USERDN_ADMIN = or(BIND_RULE_IP_NOT_LOCALHOST, BIND_RULE_USERDN_ADMIN); |
| | | |
| | | private static final String BIND_RULE_ADMIN_AND_LOCALHOST_OR_SSL = and(BIND_RULE_USERDN_ADMIN, or(BIND_RULE_AUTHMETHOD_SSL, BIND_RULE_DNS_LOCALHOST)); |
| | | // @Checkstyle:on |
| | | |
| | | |
| | | // These are made up |
| | | // @Checkstyle:off |
| | | private static final String BIND_RULE_GROUPDN_1 = "groupdn=\"ldap:///cn=SomeGroup,dc=example,dc=com\""; |
| | | private static final String BIND_RULE_GROUPDN_2 = "groupdn=\"ldap:///cn=SomeGroup,dc=example,dc=com || ldap:///cn=SomeOtherGroup,dc=example,dc=com\""; |
| | | private static final String BIND_RULE_GROUPDN_3 = "groupdn=\"ldap:///cn=SomeGroup,dc=example,dc=com || ldap:///cn=SomeOtherGroup,dc=example,dc=com || ldap:///cn=SomeThirdGroup,dc=example,dc=com\""; |
| | | private static final String BIND_RULE_USERDN_FILTER = "userdn=\"ldap:///dc=example,dc=com??one?(|(ou=eng)(ou=acct))\""; |
| | | // @Checkstyle:on |
| | | |
| | | //bind rule user attr ACIs |
| | | private static final String BIND_RULE_USERATTR_USERDN = "userattr=\"manager#USERDN\""; |
| | |
| | | private static final String BIND_RULE_NOON_AND_AFTER = "timeofday>=\"1200\""; |
| | | private static final String BIND_RULE_BEFORE_NOON = "timeofday<\"1200\""; |
| | | private static final String BIND_RULE_NOON_AND_BEFORE = "timeofday<=\"1200\""; |
| | | // @Checkstyle:off |
| | | //targattrfilters |
| | | private static final String TARG_ATTR_FILTERS = "add=cn:(!(cn=superAdmin))"; |
| | | private static final String TARG_ATTR_FILTERS_1 = "add=cn:(!(cn=superAdmin)) && telephoneNumber:(telephoneNumber=123*)"; |
| | |
| | | private static final String TARG_ATTR_FILTERS_ATTR_TYPE_NAME = "del=cn:(&(cn=foo)(cn=f*)) && 1sn_:(1sn_=joe*)"; |
| | | |
| | | private static final String SELF_MODIFY_ACI = "aci: (targetattr=\"*\")(version 3.0; acl \"self modify\";allow(all) userdn=\"userdn=\"ldap:///self\";)"; |
| | | // @Checkstyle:on |
| | | |
| | | private static final String ALLOW_ALL_TO_ALL = |
| | | buildAciValue("name", "allow all", "targetattr", "*", "allow(all)", BIND_RULE_USERDN_ALL); |
| | | |
| | | // @Checkstyle:off |
| | | private static final String ALLOW_ALL_TO_COMPARE = |
| | | buildAciValue("name", "allow compare", "targetattr", "*", "target", "ldap:///cn=*," + OU_LEAF_DN, "allow(compare)", BIND_RULE_USERDN_ALL); |
| | | // @Checkstyle:on |
| | | |
| | | private static final String DENY_READ_CN_SN_IF_PERSON = buildAciValue("name", |
| | | "deny read cn sn if person", "targetfilter", "objectClass=person", |
| | |
| | | buildAciValue("name", "allow proxy to userdn level1", "targetattr", "*", |
| | | "allow(proxy)", BIND_RULE_USERDN_LEVEL_1); |
| | | |
| | | // @Checkstyle:off |
| | | private static final String ALLOW_ALL_TO_IMPORT_MGR_NEW = |
| | | buildAciValue("name", "allow import mgr new tree", "target", MGR_NEW_DN_URL, "allow(import)", BIND_RULE_USERDN_ALL); |
| | | |
| | |
| | | |
| | | private static final String ALLOW_SEARCH_OU_AND_PERSON_TO_SIMPLE = |
| | | buildAciValue("name", "allow search ou and person to localhost", "targetattr", "*", "targetfilter", "(|(objectclass=organizationalunit)(objectclass=person))", "allow(search, read)", BIND_RULE_AUTHMETHOD_SIMPLE); |
| | | |
| | | // @Checkstyle:on |
| | | |
| | | // ----------------------------------------------------------------------------- |
| | | // ----------------------------------------------------------------------------- |
| | |
| | | // Test each feature in isolation. |
| | | // <PASSES> |
| | | // // TARGETS |
| | | // @Checkstyle:off |
| | | buildAciValue("name", "self mod", "allow (write)", BIND_RULE_USERDN_SELF), |
| | | buildAciValue("name", "parenthesis (dummy) and ( ) and () test", "allow (read)", BIND_RULE_USERDN_SELF), |
| | | buildAciValue("name", "w/ target", "target", LDAP_URL_OU_INNER, "allow (write)", BIND_RULE_USERDN_SELF), |
| | |
| | | buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_USERDN_INHERITANCE), |
| | | buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_GROUPDN_INHERITANCE), |
| | | buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_VALUE), |
| | | // @Checkstyle:on |
| | | // BUG! These work with DS 5.2p4, but not with OpenDS. |
| | | // <FAIL> |
| | | // DENY_ALL_TO_LOCALHOST_SUBNET, |
| | |
| | | buildAciValue("name", "invalid", "targetattr", "cn ||", "allow (write)", BIND_RULE_USERDN_SELF), |
| | | buildAciValue("name", "invalid", "targetattr", "not/an/attr", "allow (write)", BIND_RULE_USERDN_SELF), |
| | | buildAciValue("name", "invalid", "targetattr", "cn", "allow (write)", BIND_RULE_INVALID_DAY), |
| | | // @Checkstyle:off |
| | | /* Test cases for OPENDJ-433 */ |
| | | buildAciValue("name", "invalid", "targetattr", "cn", "garbage allow (read)", BIND_RULE_USERDN_SELF), |
| | | buildAciValue("name", "invalid", "targetattr", "cn", "allow (read)", BIND_RULE_USERDN_SELF, "garbage allow (search)", BIND_RULE_USERDN_SELF), |
| | |
| | | // OpenDJ 2.5 doesn't support acis with options |
| | | buildAciValue("name", "unsupported option in targetattr", "targetattr", "locality;lang-fr-ca", "allow (write)", BIND_RULE_USERDN_SELF), |
| | | buildAciValue("name", "complicated unsupported option in targetattr", "targetattr", "1ocal_ity;lang-fr-ca", "allow (write)", BIND_RULE_USERDN_SELF), |
| | | |
| | | // @Checkstyle:on |
| | | // </PASSES> |
| | | }; |
| | | |
| | |
| | | // "---------------\"\"-------------\"-------\"--"}, |
| | | |
| | | // TODO: this generates some failures. |
| | | // {"(version3.0;acl\"\";allow(read,write,add,delete,search,compare,selfwrite,all,proxy)userdn=\"ldap:///self\";)", |
| | | // "XXXXXXXXXXXXXXX\'\'X----------------------------------------------------------------------\"-----XX-----\"XX"}, |
| | | // {"(version3.0;acl\"\";allow(read,write,add,delete,search,compare,selfwrite,all,proxy)userdn=\"ldap:///self\";)", |
| | | // "XXXXXXXXXXXXXXX\'\'X----------------------------------------------------------------------\"-----XX-----\"XX"}, |
| | | |
| | | // TODO: this generates some failures. |
| | | // {"(version3.0;acl\"\";allow(read)userdn=\"ldap:///o=b\";)", |
| | |
| | | |
| | | @DataProvider |
| | | public Object[][] validBasisOfValidityTests() throws Exception { |
| | | TestCaseUtils.startServer(); // This appears to be necessary since the DataProviders can be called before @BeforeClass. |
| | | TestCaseUtils.startServer(); // Apparently necessary since the DataProviders can be called before @BeforeClass. |
| | | |
| | | List<String> acis = new ArrayList<>(); |
| | | for (String[] aciAndMask: INVALID_ACIS_IF_ANY_CHAR_REMOVED) { |
| | |
| | | * tests are valid acis. |
| | | */ |
| | | @Test(dataProvider = "validBasisOfValidityTests") |
| | | public void testBasisOfInvalidityTestsAreValid(String modifierDn, String modifierPw, String aciModLdif) throws Throwable { |
| | | public void testBasisOfInvalidityTestsAreValid(String modifierDn, String modifierPw, String aciModLdif) |
| | | throws Throwable { |
| | | if (TESTS_ARE_DISABLED) { // This is a hack to make sure we can disable the tests. |
| | | return; |
| | | } |
| | |
| | | |
| | | @DataProvider |
| | | public Object[][] validAcis() throws Exception { |
| | | TestCaseUtils.startServer(); // This appears to be necessary since the DataProviders can be called before @BeforeClass. |
| | | TestCaseUtils.startServer(); // Apparently necessary since the DataProviders can be called before @BeforeClass. |
| | | |
| | | return buildAciValidationParams(Arrays.asList(VALID_ACIS), false /*test once per aci*/); |
| | | } |
| | | |
| | | @DataProvider |
| | | public Object[][] invalidAcis() throws Exception { |
| | | TestCaseUtils.startServer(); // This appears to be necessary since the DataProviders can be called before @BeforeClass. |
| | | TestCaseUtils.startServer(); // Apparently necessary since the DataProviders can be called before @BeforeClass. |
| | | |
| | | List<String> invalid = newArrayList(INVALID_ACIS); |
| | | for (String[] aciAndMask: INVALID_ACIS_IF_ANY_CHAR_REMOVED) { |
| | |
| | | // Test that we can add entries with valid ACIs as well as set valid ACIs on a an entry |
| | | modEntries(aciModLdif, modifierDn, modifierPw); |
| | | } catch (Throwable e) { |
| | | System.err.println("Started with dit:\nldapmodify -a -D \"cn=Directory Manager\" -w etegrity -p 13324\n" + VALIDITY_TESTS_DIT + |
| | | "and as '" + modifierDn + "' failed to perform these modifications:\n" + |
| | | "ldapmodify -D \"" + modifierDn + "\" -w " + modifierPw + " -p 13324\n" + |
| | | aciModLdif); |
| | | System.err.println("Started with dit:\nldapmodify -a -D \"cn=Directory Manager\" -w etegrity -p 13324\n" |
| | | + VALIDITY_TESTS_DIT + "and as '" + modifierDn + "' failed to perform these modifications:\n" |
| | | + "ldapmodify -D \"" + modifierDn + "\" -w " + modifierPw + " -p 13324\n" |
| | | + aciModLdif); |
| | | throw e; |
| | | } |
| | | } |
| | |
| | | // Test that we can add entries with valid ACIs as well as set valid ACIs on a an entry |
| | | modEntriesExpectFailure(aciModLdif, modifierDn, modifierPw); |
| | | } catch (Throwable e) { |
| | | System.err.println("Started with dit:\nldapmodify -a -D \"cn=Directory Manager\" -w etegrity -p 13324\n" + VALIDITY_TESTS_DIT + |
| | | "and as '" + modifierDn + "' successfully added an invalid aci:\n" + |
| | | "ldapmodify -D \"" + modifierDn + "\" -w " + modifierPw + " -p 13324\n" + |
| | | aciModLdif); |
| | | System.err.println("Started with dit:\nldapmodify -a -D \"cn=Directory Manager\" -w etegrity -p 13324\n" |
| | | + VALIDITY_TESTS_DIT + "and as '" + modifierDn + "' successfully added an invalid aci:\n" |
| | | + "ldapmodify -D \"" + modifierDn + "\" -w " + modifierPw + " -p 13324\n" |
| | | + aciModLdif); |
| | | throw e; |
| | | } |
| | | } |
| | | |
| | | @DataProvider |
| | | public Object[][] invalidAcisMultiCombos() throws Exception { |
| | | TestCaseUtils.startServer(); // This appears to be necessary since the DataProviders can be called before @BeforeClass. |
| | | TestCaseUtils.startServer(); // Apparently necessary since the DataProviders can be called before @BeforeClass. |
| | | |
| | | List<String> invalid = new ArrayList<>(); |
| | | invalid.add(INVALID_ACIS[0]); |
| | |
| | | |
| | | private static final String ADMIN_LDIF__SEARCH_TESTS = makeUserLdif(ADMIN_DN, "aci", "admin", ADMIN_PW); |
| | | private static final String USER_LDIF__SEARCH_TESTS = makeUserLdif(USER_DN, "some", "user", USER_PW); |
| | | // @Checkstyle:off |
| | | private static final String LEVEL_1_USER_LDIF__SEARCH_TESTS = makeUserLdif(LEVEL_1_USER_DN, "level1", "user", "pa$$word"); |
| | | private static final String LEVEL_2_USER_LDIF__SEARCH_TESTS = makeUserLdif(LEVEL_2_USER_DN, "level2", "user", "pa$$word"); |
| | | private static final String LEVEL_3_USER_LDIF__SEARCH_TESTS = makeUserLdif(LEVEL_3_USER_DN, "level3", "user", "pa$$word"); |
| | | private static final String PROXY_USER_LDIF__SEARCH_TESTS = |
| | | makeUserLdif(PROXY_USER_DN, "proxy", "user", "pa$$word"); |
| | | private static final String PROXY_USER_LDIF__SEARCH_TESTS = makeUserLdif(PROXY_USER_DN, "proxy", "user", "pa$$word"); |
| | | // @Checkstyle:on |
| | | |
| | | |
| | | private static final String SALES_USER_1__SEARCH_TESTS = |
| | |
| | | _equivalentAciLdifs = Arrays.asList(equivalentAciLdifs); |
| | | } |
| | | |
| | | private void addSingleSearch(String bindDn, String searchBaseDn, String searchFilter, String searchScope, String expectedResultsLdif) { |
| | | private void addSingleSearch( |
| | | String bindDn, String searchBaseDn, String searchFilter, String searchScope, String expectedResultsLdif) { |
| | | for (String equivalentAci: _equivalentAciLdifs) { |
| | | _searchTests.add(SingleSearchParams.nonProxiedSearch(bindDn, DN_TO_PW.get(bindDn), searchBaseDn, searchFilter, searchScope, expectedResultsLdif, _initialDitLdif, equivalentAci)); |
| | | _searchTests.add(SingleSearchParams.nonProxiedSearch(bindDn, DN_TO_PW.get(bindDn), searchBaseDn, |
| | | searchFilter, searchScope, expectedResultsLdif, _initialDitLdif, equivalentAci)); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | @DataProvider |
| | | private Object[][] searchTestParams() throws Throwable { |
| | | TestCaseUtils.startServer(); // This appears to be necessary since the DataProviders can be called before @BeforeClass. |
| | | TestCaseUtils.startServer(); // Apparently necessary since the DataProviders can be called before @BeforeClass. |
| | | |
| | | try { |
| | | List<Object[]> allTestParams = new ArrayList<>(); |
| | |
| | | } |
| | | anyAttr += ")"; |
| | | |
| | | Pattern pattern = Pattern.compile("^" + anyAttr + "\\:(.*?)^", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.DOTALL); |
| | | Pattern pattern = Pattern.compile("^" + anyAttr + "\\:(.*?)^", |
| | | Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.DOTALL); |
| | | return pattern.matcher(ldif).replaceAll(""); |
| | | } |
| | | |