opends/src/server/org/opends/server/api/AccessControlHandler.java
@@ -28,17 +28,10 @@ import org.opends.server.core.AddOperation; import org.opends.server.core.BindOperation; import org.opends.server.core.CompareOperation; import org.opends.server.core.DeleteOperation; import org.opends.server.core.ExtendedOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyOperation; import org.opends.server.core.SearchOperation; import org.opends.server.core.*; import org.opends.server.types.SearchResultEntry; import org.opends.server.types.SearchResultReference; import org.opends.server.types.Entry; /** @@ -237,5 +230,23 @@ */ public abstract boolean maySend(SearchOperation searchOperation, SearchResultReference searchReference); /** * Indicates whether a proxied authorization control is allowed * based on the current operation and the new authorization * entry. * * @param operation * The operation with which the proxied authorization * control is associated. * @param newAuthorizationEntry * The new authorization entry related to the * proxied authorization control authorization ID. * @return <CODE>true</CODE> if the operation should be allowed by * the access control configuration, or <CODE>false</CODE> * if not. */ public abstract boolean isProxiedAuthAllowed(Operation operation, Entry newAuthorizationEntry); } opends/src/server/org/opends/server/authorization/BasicAccessControlHandler.java
@@ -28,16 +28,10 @@ import org.opends.server.api.AccessControlHandler; import org.opends.server.core.AddOperation; import org.opends.server.core.BindOperation; import org.opends.server.core.CompareOperation; import org.opends.server.core.DeleteOperation; import org.opends.server.core.ExtendedOperation; import org.opends.server.core.ModifyDNOperation; import org.opends.server.core.ModifyOperation; import org.opends.server.core.SearchOperation; import org.opends.server.core.*; import org.opends.server.types.SearchResultEntry; import org.opends.server.types.SearchResultReference; import org.opends.server.types.Entry; /** * This class provides the implementation of the basic access control @@ -169,4 +163,12 @@ return true; } /** * {@inheritDoc} */ @Override public boolean isProxiedAuthAllowed(Operation operation, Entry entry) { return true; } } opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
@@ -194,7 +194,7 @@ public static final int ACI_ALL = 0x007F; /** * ACI_PROXY is used for the PROXY right. Currently not used. * ACI_PROXY is used for the PROXY right. */ public static final int ACI_PROXY = 0x0080; opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -36,6 +36,7 @@ import org.opends.server.extensions.TLSConnectionSecurityProvider; import java.net.InetAddress; import java.util.LinkedList; import static org.opends.server.authorization.dseecompat.AciHandler.*; /** * The AciContainer class contains all of the needed information to perform @@ -109,6 +110,41 @@ */ private boolean targAttrFiltersMatch=false; /* * The authorization entry currently being evaluated. If proxied * authorization is being used and the handler is doing a proxy access * check, then this entry will switched to the original authorization entry * rather than the proxy ID entry. If the check succeeds, it will be * switched back for non-proxy access checking. If proxied authentication * is not being used then this entry never changes. */ private Entry authorizationEntry; /* * Used to save the current authorization entry when the authorization * entry is switched during a proxy access check. */ private Entry saveAuthorizationEntry; /* * This entry is only used if proxied authorization is being used. It is * the original authorization entry before the proxied authorization change. */ private Entry origAuthorizationEntry=null; /* * True if proxied authorization is being used. */ private boolean proxiedAuthorization=false; /* * Used by proxied authorization processing. True if the entry has already * been processed by an access proxy check. Some operations might perform * several access checks on the same entry (modify DN), this * flag is used to bypass the proxy check after the initial evaluation. */ private boolean seenEntry=false; /** * This constructor is used by all currently supported LDAP operations. * @@ -123,9 +159,63 @@ this.clientConnection=operation.getClientConnection(); if(operation instanceof AddOperation) this.isAddOp=true; //If the proxied authorization control was processed, then the operation //will contain an attachment containing the original authorization entry. this.origAuthorizationEntry = (Entry) operation.getAttachment(ORIG_AUTH_ENTRY); if(origAuthorizationEntry != null) this.proxiedAuthorization=true; this.authorizationEntry=operation.getAuthorizationEntry(); //Reference the current authorization entry, so it can be put back //if an access proxy check was performed. this.saveAuthorizationEntry=this.authorizationEntry; this.rights = rights; } /** * Returns true if an entry has already been processed by an access proxy * check. * @return True if an entry has already been processed by an access proxy * check. */ public boolean hasSeenEntry() { return this.seenEntry; } /** * Set to true if an entry has already been processsed by an access proxy * check. * @param val The value to set the seenEntry boolean to. */ public void setSeenEntry(boolean val) { this.seenEntry=val; } /** * Returns true if proxied authorization is being used. * @return True if proxied authorization is being used. */ public boolean isProxiedAuthorization() { return this.proxiedAuthorization; } /** * If the specified value is true, then the original authorization entry, * which is the entry before the switch performed by the proxied * authorization control processing should be set to the current * authorization entry. If the specified value is false then the proxied * authorization entry is switched back using the saved copy. * @param val The value used to select the authorization entry to use. */ public void useOrigAuthorizationEntry(boolean val) { if(val) authorizationEntry=origAuthorizationEntry; else authorizationEntry=saveAuthorizationEntry; } /** * The list of deny ACIs. These are all of the applicable * ACIs that have a deny permission. Note that an ACI can @@ -226,7 +316,7 @@ * @return The client entry. */ public Entry getClientEntry() { return operation.getAuthorizationEntry(); return this.authorizationEntry; } /** @@ -275,7 +365,7 @@ * @return The client's authorization DN. */ public DN getClientDN() { return operation.getAuthorizationDN(); return this.authorizationEntry.getDN(); } /** opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -72,6 +72,12 @@ public static AttributeType globalAciType; /** * String used to save the original authorization entry in an operation * attachment if a proxied authorization control was seen. */ public static String ORIG_AUTH_ENTRY="origAuthorizationEntry"; /** * This constructor instantiates the ACI handler class that performs the * main processing for the dseecompat ACI package. It does the following * initializations: @@ -443,6 +449,32 @@ return false; } } //Check proxy authorization only if the entry has not already been //processed (working on a new entry). If working on a new entry, then //only do a proxy check if the right is not set to ACI_PROXY and the //proxied authorization control has been decoded. if(!container.hasSeenEntry()) { if(!container.hasRights(ACI_PROXY) && container.isProxiedAuthorization()) { int currentRights=container.getRights(); //Save the current rights so they can be put back if on success. container.setRights(ACI_PROXY); //Switch to the original authorization entry, not the proxied one. container.useOrigAuthorizationEntry(true); if(!accessAllowed(container)) return false; //Access is ok, put the original rights back. container.setRights(currentRights); //Put the proxied authorization entry back to the current //authorization entry. container.useOrigAuthorizationEntry(false); } //Set the seen flag so proxy processing is not performed for this //entry again. container.setSeenEntry(true); } /* * First get all allowed candidate ACIs. */ @@ -714,7 +746,6 @@ * @return True if access is allowed. */ public boolean isAllowed(CompareOperation operation) { AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(operation, ACI_COMPARE); String baseName; @@ -803,10 +834,12 @@ */ public SearchResultEntry filterEntry(SearchOperation operation, SearchResultEntry entry) { AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(operation, (ACI_READ), entry); //Proxy access check has already been done for this entry in the maySend //method, set the seen flag to true to bypass any proxy check. operationContainer.setSeenEntry(true); SearchResultEntry returnEntry; if(!skipAccessCheck(operation)) { returnEntry=accessAllowedAttrs(operationContainer); @@ -816,10 +849,10 @@ } /** * Perform all needed RDN checks for the modifyDN operation. These checks * are: * Perform all needed RDN checks for the modifyDN operation. The old RDN is * not equal to the new RDN. The access checks are: * * - Verify WRITE access to the entry. * - Verify WRITE access to the original entry. * - Verfiy WRITE_ADD access on each RDN component of the new RDN. The * WRITE_ADD access is used because this access could be restricted by * the targattrfilters keyword. @@ -829,18 +862,21 @@ * * @param operation The ModifyDN operation class containing information to * check access on. * @param oldRDN The old RDN component. * @param newRDN The new RDN component. * @return True if access is allowed. */ private boolean aciCheckRDNs(ModifyDNOperation operation) { private boolean aciCheckRDNs(ModifyDNOperation operation, RDN oldRDN, RDN newRDN) { boolean ret; AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(operation, (ACI_WRITE), operation.getOriginalEntry()); ret=accessAllowed(operationContainer); if(ret) ret=checkRDN(ACI_WRITE_ADD,operation.getNewRDN(),operationContainer); ret=checkRDN(ACI_WRITE_ADD, newRDN, operationContainer); if(ret && operation.deleteOldRDN()) { RDN oldRDN=operation.getOriginalEntry().getDN().getRDN(); ret = checkRDN(ACI_WRITE_DELETE, oldRDN, operationContainer); } @@ -923,6 +959,8 @@ public boolean isAllowed(ModifyDNOperation operation) { boolean ret=true; DN newSuperiorDN; RDN oldRDN=operation.getOriginalEntry().getDN().getRDN(); RDN newRDN=operation.getNewRDN(); if(!skipAccessCheck(operation)) { //If this is a modifyDN move to a new superior, then check if the //superior DN has import accesss. @@ -933,21 +971,41 @@ ret=false; } } //Perform the RDN access checks. if(ret) ret=aciCheckRDNs(operation); boolean rdnEquals=oldRDN.equals(newRDN); //Perform the RDN access checks only if the RDNs are not equal. if(ret && !rdnEquals) ret=aciCheckRDNs(operation, oldRDN, newRDN); //If this is a modifyDN move to a new superior, then check if the //original entry DN has export access. if(ret && (newSuperiorDN != null)) { AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(operation, (ACI_EXPORT), operation.getOriginalEntry()); operation.getOriginalEntry()); //The RDNs are not equal, skip the proxy check since it was //already performed in the aciCheckRDNs call above. if(!rdnEquals) operationContainer.setSeenEntry(true); ret=accessAllowed(operationContainer); } } return ret; } //TODO Check access to control, issue #452. /** * Called when a proxied authorization control was decoded. Currently used * to save the current authorization entry in an operation attachment, but * eventually will be used to check access to the actual control. * @param operation The operation to save the attachment to. * @param entry The new authorization entry. * @return True if the control is allowed access. */ public boolean isProxiedAuthAllowed(Operation operation, Entry entry) { operation.setAttachment(ORIG_AUTH_ENTRY, operation.getAuthorizationEntry()); return true; } //Not planned to be implemented methods. /** opends/src/server/org/opends/server/core/AddOperation.java
@@ -1767,7 +1767,17 @@ break addProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break addProcessing; } setAuthorizationEntry(authorizationEntry); } else if (oid.equals(OID_PROXIED_AUTH_V2)) @@ -1827,7 +1837,17 @@ break addProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break addProcessing; } setAuthorizationEntry(authorizationEntry); } opends/src/server/org/opends/server/core/CompareOperation.java
@@ -824,7 +824,17 @@ break compareProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break compareProcessing; } setAuthorizationEntry(authorizationEntry); } else if (oid.equals(OID_PROXIED_AUTH_V2)) @@ -884,7 +894,17 @@ break compareProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break compareProcessing; } setAuthorizationEntry(authorizationEntry); } opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java
@@ -33,6 +33,7 @@ import org.opends.server.types.InitializationException; import org.opends.server.types.SearchResultEntry; import org.opends.server.types.SearchResultReference; import org.opends.server.types.Entry; /** * This class implements a default access control provider for the @@ -197,5 +198,13 @@ return true; } /** * {@inheritDoc} */ @Override public boolean isProxiedAuthAllowed(Operation operation, Entry entry) { return true; } } } opends/src/server/org/opends/server/core/DeleteOperation.java
@@ -817,7 +817,17 @@ break deleteProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_DELETE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break deleteProcessing; } setAuthorizationEntry(authorizationEntry); } else if (oid.equals(OID_PROXIED_AUTH_V2)) @@ -876,7 +886,17 @@ break deleteProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_DELETE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break deleteProcessing; } setAuthorizationEntry(authorizationEntry); } opends/src/server/org/opends/server/core/ModifyDNOperation.java
@@ -1277,7 +1277,17 @@ break modifyDNProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } setAuthorizationEntry(authorizationEntry); } else if (oid.equals(OID_PROXIED_AUTH_V2)) @@ -1336,6 +1346,17 @@ break modifyDNProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODDN_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyDNProcessing; } setAuthorizationEntry(authorizationEntry); opends/src/server/org/opends/server/core/ModifyOperation.java
@@ -101,6 +101,7 @@ import static org.opends.server.loggers.Error.*; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.StaticUtils.*; @@ -1080,7 +1081,17 @@ break modifyProcessing; } if (AccessControlConfigManager.getInstance(). getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODIFY_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyProcessing; } setAuthorizationEntry(authorizationEntry); } @@ -1141,7 +1152,17 @@ break modifyProcessing; } if (AccessControlConfigManager.getInstance(). getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_MODIFY_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break modifyProcessing; } setAuthorizationEntry(authorizationEntry); } opends/src/server/org/opends/server/core/SearchOperation.java
@@ -1758,7 +1758,17 @@ break searchProcessing; } if (AccessControlConfigManager.getInstance(). getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_SEARCH_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(baseDN))); skipPostOperation = true; break searchProcessing; } setAuthorizationEntry(authorizationEntry); } else if (oid.equals(OID_PROXIED_AUTH_V2)) @@ -1818,6 +1828,17 @@ break searchProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(this, authorizationEntry) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_SEARCH_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(baseDN))); skipPostOperation = true; break searchProcessing; } setAuthorizationEntry(authorizationEntry); } opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
@@ -182,6 +182,8 @@ private static final String LEVEL_1_USER_DN = "cn=level1 user," + OU_BASE_DN; private static final String LEVEL_2_USER_DN = "cn=level2 user," + OU_INNER_DN; private static final String LEVEL_3_USER_DN = "cn=level3 user," + OU_LEAF_DN; //The proxy DN. private static final String PROXY_USER_DN = "cn=proxy user," + OU_BASE_DN; // We need to delete all of these between each test. This list needs to be // bottom up so that it can be handed to LDAPDelete. @@ -189,6 +191,7 @@ SALES_USER_1, SALES_USER_2, SALES_USER_3, PROXY_USER_DN, LEVEL_3_USER_DN, LEVEL_2_USER_DN, LEVEL_1_USER_DN, @@ -209,6 +212,10 @@ private static final String BIND_RULE_USERDN_ALL = "userdn=\"ldap:///all\""; private static final String BIND_RULE_USERDN_ADMIN = "userdn=\"ldap:///" + ADMIN_DN + "\""; private static final String BIND_RULE_USERDN_LEVEL_1 = "userdn=\"ldap:///" + LEVEL_1_USER_DN + "\""; //The proxy userdn bind rule. private static final String BIND_RULE_USERDN_PROXY = "userdn=\"ldap:///" + PROXY_USER_DN + "\""; private static final String BIND_RULE_USERDN_ANYONE = "userdn=\"ldap:///anyone\""; 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\""; @@ -306,6 +313,36 @@ 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); //The ACIs for the proxy tests. private static final String ALLOW_PROXY_TO_IMPORT_MGR_NEW = buildAciValue("name", "allow proxy import new mgr new tree", "target", MGR_NEW_DN_URL, "allow(import)", BIND_RULE_USERDN_PROXY); private static final String ALLOW_PROXY_TO_IMPORT_MGR= buildAciValue("name", "allow proxy import mgr tree", "target", MGR_DN_URL, "allow(import)", BIND_RULE_USERDN_PROXY); private static final String ALLOW_PROXY_TO_EXPORT_MGR_NEW = buildAciValue("name", "allow proxy export new mgr new tree", "target", MGR_NEW_DN_URL, "allow(export)", BIND_RULE_USERDN_PROXY); private static final String ALLOW_PROXY_TO_EXPORT_MGR= buildAciValue("name", "allow proxy export mgr tree", "target", MGR_DN_URL, "allow(export)", BIND_RULE_USERDN_PROXY); private static final String ALLOW_PROXY_TO_WRITE_RDN_ATTRS= buildAciValue("name", "allow proxy write to RDN attrs", "targetattr", "uid || cn || sn", "allow(write)", BIND_RULE_USERDN_PROXY); private static final String ALLOW_PROXY_TO_MOVED_ENTRY = buildAciValue("name", "allow proxy to moved entry", "targetattr", "*", "allow(search,read)", BIND_RULE_USERDN_PROXY); private static final String ALLOW_PROXY_TO_LEVEL1 = buildAciValue("name", "allow proxy to userdn level1", "targetattr", "*", "allow(proxy)", BIND_RULE_USERDN_LEVEL_1); 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); @@ -959,6 +996,8 @@ 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 SALES_USER_1__SEARCH_TESTS = @@ -1050,7 +1089,7 @@ String SELFWRITE_ACI = makeAddAciLdif(OU_GROUP_1_DN, ALLOW_ALL_TO_SELFWRITE); //ACIs used for modDN tests (export, import) //ACIs used for standard modDN tests (export, import) private static final String ACI_IMPORT_MGR_NEW = makeAddAciLdif(OU_BASE_DN, ALLOW_ALL_TO_IMPORT_MGR_NEW); @@ -1064,12 +1103,35 @@ private static final String ACI_EXPORT_MGR = makeAddAciLdif(OU_BASE_DN, ALLOW_ALL_TO_EXPORT_MGR); private static final String ACI_WRITE_RDN_ATTRS = private static final String ACI_WRITE_RDN_ATTRS = makeAddAciLdif(OU_BASE_DN, ALLOW_ALL_TO_WRITE_RDN_ATTRS); private static final String ACI_MOVED_ENTRY = private static final String ACI_MOVED_ENTRY = makeAddAciLdif(SALES_USER_1, ALLOW_ALL_TO_MOVED_ENTRY); //ACIs used for proxied auth modDN tests private static final String ACI_PROXY_IMPORT_MGR_NEW = makeAddAciLdif(OU_BASE_DN, ALLOW_PROXY_TO_IMPORT_MGR_NEW); private static final String ACI_PROXY_IMPORT_MGR = makeAddAciLdif(OU_BASE_DN, ALLOW_PROXY_TO_IMPORT_MGR); private static final String ACI_PROXY_EXPORT_MGR_NEW = makeAddAciLdif(OU_BASE_DN, ALLOW_PROXY_TO_EXPORT_MGR_NEW); private static final String ACI_PROXY_EXPORT_MGR = makeAddAciLdif(OU_BASE_DN, ALLOW_PROXY_TO_EXPORT_MGR); private static final String ACI_PROXY_WRITE_RDN_ATTRS = makeAddAciLdif(OU_BASE_DN, ALLOW_PROXY_TO_WRITE_RDN_ATTRS); private static final String ACI_PROXY_LEVEL_1= makeAddAciLdif(OU_BASE_DN, ALLOW_PROXY_TO_LEVEL1); private static final String ACI_PROXY_MOVED_ENTRY = makeAddAciLdif(SALES_USER_1, ALLOW_PROXY_TO_MOVED_ENTRY); //ACI used in testing the groupdn/roledn bind rule keywords. private static final @@ -1116,6 +1178,7 @@ GROUP_1_LDIF__SEARCH_TESTS + GROUP_2_LDIF__SEARCH_TESTS + LEVEL_1_USER_LDIF__SEARCH_TESTS + PROXY_USER_LDIF__SEARCH_TESTS + INNER_OU_FULL_LDIF__SEARCH_TESTS; private static final String NO_ACIS_LDIF = ""; @@ -1484,6 +1547,7 @@ private static class SingleSearchParams { private final String _bindDn; private final String _bindPw; private final String _proxyDN; private final String _searchBaseDn; private final String _searchFilter; private final String _searchScope; @@ -1491,9 +1555,25 @@ private final String _initialDitLdif; private final String _aciLdif; public SingleSearchParams(String bindDn, String bindPw, String proxyDN, String searchBaseDn, String searchFilter, String searchScope, String expectedResultsLdif, String initialDitLdif, String aciLdif) { _bindDn = bindDn; _bindPw = bindPw; _proxyDN=proxyDN; _searchBaseDn = searchBaseDn; _searchFilter = searchFilter; _searchScope = searchScope; _expectedResultsLdif = expectedResultsLdif; _initialDitLdif = initialDitLdif; _aciLdif = aciLdif; } public SingleSearchParams(String bindDn, String bindPw, String searchBaseDn, String searchFilter, String searchScope, String expectedResultsLdif, String initialDitLdif, String aciLdif) { _bindDn = bindDn; _bindPw = bindPw; _proxyDN = null; _searchBaseDn = searchBaseDn; _searchFilter = searchFilter; _searchScope = searchScope; @@ -1505,6 +1585,7 @@ public SingleSearchParams(SingleSearchParams that, String initialDitLdif, String aciLdif) { _bindDn = that._bindDn; _bindPw = that._bindPw; _proxyDN = null; _searchBaseDn = that._searchBaseDn; _searchFilter = that._searchFilter; _searchScope = that._searchScope; @@ -1525,6 +1606,16 @@ "-b", _searchBaseDn, "-s", _searchScope, _searchFilter}; } else if(_proxyDN != null) { return new String[]{ "-h", "127.0.0.1", "-p", getServerLdapPort(), "-D", _bindDn, "-w", _bindPw, "-b", _searchBaseDn, "-s", _searchScope, "-Y", "dn:" + _proxyDN, _searchFilter}; } else { return new String[]{ "-h", "127.0.0.1", @@ -1659,6 +1750,58 @@ } } /** * Test proxy keyword using modify DN. Exact test as testModDN, except using * proxied authorization for modifies and searches. * * Add a set of ACIs to allow exports, imports and write rights to the * proxy user PROXY_USER_DN. Also add an aci low in the DIT, with search and * read rights to the proxy user. This is ACI is to test the * ACI list after a move has been made. Add an ACI that allows LEVEL_1_USER_DN * proxy authorization rights (proxy). * * Move the subtree binding as LEVEL_1_USER_DN using proxied authorization, * search with base at new DN binding as LEVEL_1_USER_DN proxied * authorization, then move the tree back binding as LEVEL_1_USER_DN using * proxied authorization and lastly re-search with base at orig DN * binding as LEVEL_1_USER_DN using proxied authorization. * @throws Throwable */ @Test public void testProxyModDN() throws Throwable { SingleSearchParams userParamOrig = new SingleSearchParams(LEVEL_1_USER_DN, "pa$$word",PROXY_USER_DN, SALES_USER_1, OBJECTCLASS_STAR, SCOPE_BASE, null, null, null); SingleSearchParams userParamNew = new SingleSearchParams(LEVEL_1_USER_DN, "pa$$word",PROXY_USER_DN, SALES_USER_NEW_1, OBJECTCLASS_STAR, SCOPE_BASE, null, null, null); try { addEntries(BASIC_LDIF__GROUP_SEARCH_TESTS, DIR_MGR_DN, DIR_MGR_PW); modEntries(ACI_PROXY_IMPORT_MGR, DIR_MGR_DN, DIR_MGR_PW); modEntries(ACI_PROXY_IMPORT_MGR_NEW, DIR_MGR_DN, DIR_MGR_PW); modEntries(ACI_PROXY_EXPORT_MGR, DIR_MGR_DN, DIR_MGR_PW); modEntries(ACI_PROXY_EXPORT_MGR_NEW, DIR_MGR_DN, DIR_MGR_PW); modEntries(ACI_PROXY_WRITE_RDN_ATTRS, DIR_MGR_DN, DIR_MGR_PW); modEntries(ACI_PROXY_MOVED_ENTRY, DIR_MGR_DN, DIR_MGR_PW); modEntries(ACI_PROXY_LEVEL_1, DIR_MGR_DN, DIR_MGR_PW); String modrdnLdif = makeModDN(SALES_DN, "cn=sales dept", "0", MANAGER_NEW_DN); modEntries(modrdnLdif, LEVEL_1_USER_DN, "pa$$word", PROXY_USER_DN); String userNewResults = ldapSearch(userParamNew.getLdapSearchArgs()); Assert.assertFalse(userNewResults.equals("")); String modrdnLdif1 = makeModDN(SALES_NEW_DN, "cn=sales dept", "0", MANAGER_DN); modEntries(modrdnLdif1, LEVEL_1_USER_DN, "pa$$word", PROXY_USER_DN); String userOrigResults = ldapSearch(userParamOrig.getLdapSearchArgs()); Assert.assertFalse(userOrigResults.equals("")); } catch (Throwable e) { throw e; } } /** * Test modify DN. Add a set of ACIs to allow exports, imports and write * rights. Also add an aci low in the DIT to test the ACI list after a move @@ -1997,20 +2140,22 @@ Assert.assertEquals(0, retVal, "Non-zero return code because, error: " + getOutputStreamContents()); return getOutputStreamContents(); } /** * */ private void modEntries(String ldif, String bindDn, String bindPassword) throws Exception { modEntries(ldif, bindDn, bindPassword, true, false); modEntries(ldif, bindDn, bindPassword, null, true, false); } /** * */ private void modEntriesExpectFailure(String ldif, String bindDn, String bindPassword) throws Exception { modEntries(ldif, bindDn, bindPassword, false, false); private void modEntries(String ldif, String bindDn, String bindPassword, String proxyDN) throws Exception { modEntries(ldif, bindDn, bindPassword, proxyDN, true, false); } private void modEntriesExpectFailure(String ldif, String bindDn, String bindPassword) throws Exception { modEntries(ldif, bindDn, bindPassword, null, false, false); } private void _modEntries(String ldif, String bindDn, String bindPassword, @@ -2031,7 +2176,8 @@ } private void modEntries(String ldif, String bindDn, String bindPassword, boolean expectSuccess, boolean contFlag) String proxyDN, boolean expectSuccess, boolean contFlag) throws Exception { File tempFile = getTemporaryLdifFile(); TestCaseUtils.writeFile(tempFile, ldif); @@ -2048,6 +2194,10 @@ argList.add(tempFile.getAbsolutePath()); if(contFlag) argList.add("-c"); if(proxyDN != null) { argList.add("-Y"); argList.add("dn:" + proxyDN); } String[] args = new String[argList.size()]; ldapModify(argList.toArray(args), expectSuccess); } @@ -2065,7 +2215,7 @@ "changetype: modify", "delete: " + attr, attr + ":" + val)); modEntries(ldif.toString(), bindDN, pwd, errorOk, false); modEntries(ldif.toString(), bindDN, pwd, null, errorOk, false); } @@ -2090,7 +2240,7 @@ "dn: " + dn, "changetype: modify", "delete: " + attr)); modEntries(ldif.toString(), DIR_MGR_DN, DIR_MGR_PW, errorOk, false); modEntries(ldif.toString(), DIR_MGR_DN, DIR_MGR_PW, null, errorOk, false); } private void deleteEntries(String[] entries) throws Exception { @@ -2102,7 +2252,7 @@ "changetype: delete" )); } modEntries(ldif.toString(), DIR_MGR_DN, DIR_MGR_PW, true, true); modEntries(ldif.toString(), DIR_MGR_DN, DIR_MGR_PW, null, true, true); } /** @@ -2214,7 +2364,8 @@ "cn: " + cn, "sn: " + sn, "givenName: " + givenName, "userpassword: " + password); "userpassword: " + password, "ds-privilege-name: proxied-auth"); } private static String makeUserLdif(String dn, String givenName, String sn,