opendj-sdk/opends/src/server/org/opends/server/api/AccessControlHandler.java
@@ -161,8 +161,8 @@ * @return {@code true} if the operation should be allowed by the * access control configuration, or {@code false} if not. */ public abstract boolean isAllowed(CompareOperation compareOperation); public abstract boolean isAllowed(LocalBackendCompareOperation compareOperation); opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -880,7 +880,7 @@ * @param operation The compare operation to check access on. * @return True if access is allowed. */ public boolean isAllowed(CompareOperation operation) { public boolean isAllowed(LocalBackendCompareOperation operation) { AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(operation, ACI_COMPARE); String baseName; opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
@@ -58,7 +58,9 @@ * @param operation The compare operation to evaluate. * @param rights The rights of a compare operation. */ public AciLDAPOperationContainer(CompareOperation operation, int rights) { public AciLDAPOperationContainer(LocalBackendCompareOperation operation, int rights) { super(operation, rights, operation.getEntryToCompare()); } opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java
@@ -26,188 +26,27 @@ */ package org.opends.server.core; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.concurrent.locks.Lock; import org.opends.server.api.Backend; import org.opends.server.api.ClientConnection; import org.opends.server.api.plugin.PostOperationPluginResult; import org.opends.server.api.plugin.PreOperationPluginResult; import org.opends.server.api.plugin.PreParsePluginResult; import org.opends.server.controls.LDAPAssertionRequestControl; import org.opends.server.controls.ProxiedAuthV1Control; import org.opends.server.controls.ProxiedAuthV2Control; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.types.AbstractOperation; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.ByteString; import org.opends.server.types.CancelRequest; import org.opends.server.types.CancelResult; import org.opends.server.types.Control; import org.opends.server.types.DirectoryException; import org.opends.server.types.DisconnectReason; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.LDAPException; import org.opends.server.types.LockManager; import org.opends.server.types.OperationType; import org.opends.server.types.Privilege; import org.opends.server.types.ResultCode; import org.opends.server.types.SearchFilter; import org.opends.server.types.operation.PostOperationCompareOperation; import org.opends.server.types.operation.PostResponseCompareOperation; import org.opends.server.types.operation.PreOperationCompareOperation; import org.opends.server.types.operation.PreParseCompareOperation; import static org.opends.server.core.CoreConstants.*; import static org.opends.server.loggers.AccessLogger.*; import static org.opends.server.loggers.debug.DebugLogger.*; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.DebugLogLevel; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.StaticUtils.*; import org.opends.server.types.Operation; /** * This class defines an operation that may be used to determine whether a * This interface defines an operation that may be used to determine whether a * specified entry in the Directory Server contains a given attribute-value * pair. */ public class CompareOperation extends AbstractOperation implements PreParseCompareOperation, PreOperationCompareOperation, PostOperationCompareOperation, PostResponseCompareOperation public interface CompareOperation extends Operation { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = DebugLogger.getTracer(); // The attribute type for this compare operation. private AttributeType attributeType; // The assertion value for the compare operation. private ByteString assertionValue; // The raw, unprocessed entry DN as included in the client request. private ByteString rawEntryDN; // The cancel request that has been issued for this compare operation. private CancelRequest cancelRequest; // The DN of the entry for the compare operation. private DN entryDN; // The proxied authorization target DN for this operation. private DN proxiedAuthorizationDN; // The entry to be compared. private Entry entry; // The set of response controls for this compare operation. private List<Control> responseControls; // The attribute type for the compare operation. private String rawAttributeType; /** * Creates a new compare operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param rawEntryDN The raw, unprocessed entry DN as provided in the * client request. This may or may not be a valid * DN as no validation will have been performed yet. * @param rawAttributeType The raw attribute type for the compare operation. * @param assertionValue The assertion value for the compare operation. */ public CompareOperation(ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, ByteString rawEntryDN, String rawAttributeType, ByteString assertionValue) { super(clientConnection, operationID, messageID, requestControls); this.rawEntryDN = rawEntryDN; this.rawAttributeType = rawAttributeType; this.assertionValue = assertionValue; responseControls = new ArrayList<Control>(); entry = null; entryDN = null; attributeType = null; cancelRequest = null; proxiedAuthorizationDN = null; } /** * Creates a new compare operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param entryDN The entry DN for this compare operation. * @param attributeType The attribute type for this compare operation. * @param assertionValue The assertion value for the compare operation. */ public CompareOperation(ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, DN entryDN, AttributeType attributeType, ByteString assertionValue) { super(clientConnection, operationID, messageID, requestControls); this.entryDN = entryDN; this.attributeType = attributeType; this.assertionValue = assertionValue; responseControls = new ArrayList<Control>(); rawEntryDN = new ASN1OctetString(entryDN.toString()); rawAttributeType = attributeType.getNameOrOID(); cancelRequest = null; entry = null; proxiedAuthorizationDN = null; } /** * Retrieves the raw, unprocessed entry DN as included in the client request. * The DN that is returned may or may not be a valid DN, since no validation * will have been performed upon it. * * @return The raw, unprocessed entry DN as included in the client request. */ public final ByteString getRawEntryDN() { return rawEntryDN; } public ByteString getRawEntryDN(); /** @@ -217,13 +56,7 @@ * @param rawEntryDN The raw, unprocessed entry DN as included in the client * request. */ public final void setRawEntryDN(ByteString rawEntryDN) { this.rawEntryDN = rawEntryDN; entryDN = null; } public void setRawEntryDN(ByteString rawEntryDN); /** @@ -234,11 +67,7 @@ * @return The DN of the entry to compare, or <CODE>null</CODE> if the raw * entry DN has not yet been processed. */ public final DN getEntryDN() { return entryDN; } public DN getEntryDN(); /** @@ -246,11 +75,7 @@ * * @return The raw attribute type for this compare operation. */ public final String getRawAttributeType() { return rawAttributeType; } public String getRawAttributeType(); /** @@ -260,13 +85,7 @@ * @param rawAttributeType The raw attribute type for this compare * operation. */ public final void setRawAttributeType(String rawAttributeType) { this.rawAttributeType = rawAttributeType; attributeType = null; } public void setRawAttributeType(String rawAttributeType); /** @@ -276,23 +95,23 @@ * * @return The attribute type for this compare operation. */ public final AttributeType getAttributeType() { return attributeType; } public AttributeType getAttributeType(); /** * Specifies the attribute type for this compare operation. * * @param attributeType The attribute type for this compare operation. */ public void setAttributeType(AttributeType attributeType); /** * Retrieves the assertion value for this compare operation. * * @return The assertion value for this compare operation. */ public final ByteString getAssertionValue() { return assertionValue; } public ByteString getAssertionValue(); /** @@ -301,926 +120,23 @@ * * @param assertionValue The assertion value for this compare operation. */ public final void setAssertionValue(ByteString assertionValue) { this.assertionValue = assertionValue; } public void setAssertionValue(ByteString assertionValue); /** * Retrieves the entry to target with the compare operation. This should not * be called by pre-parse plugins. * Retrieves the proxied authorization target DN for this compare operation. * * @return The entry to target with the compare operation, or * <CODE>null</CODE> if the entry is not yet available. * @return The proxied authorization target DN for this compare operation */ public final Entry getEntryToCompare() { return entry; } /** * {@inheritDoc} */ @Override() public final OperationType getOperationType() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. return OperationType.COMPARE; } public DN getProxiedAuthorizationDN(); /** * {@inheritDoc} */ @Override() public final void disconnectClient(DisconnectReason disconnectReason, boolean sendNotification, String message, int messageID) { // Before calling clientConnection.disconnect, we need to mark this // operation as cancelled so that the attempt to cancel it later won't cause // an unnecessary delay. setCancelResult(CancelResult.CANCELED); clientConnection.disconnect(disconnectReason, sendNotification, message, messageID); } /** * {@inheritDoc} */ @Override() public final String[][] getRequestLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. return new String[][] { new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }, new String[] { LOG_ELEMENT_COMPARE_ATTR, rawAttributeType } }; } /** * {@inheritDoc} */ @Override() public final String[][] getResponseLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. String resultCode = String.valueOf(getResultCode().getIntValue()); String errorMessage; StringBuilder errorMessageBuffer = getErrorMessage(); if (errorMessageBuffer == null) { errorMessage = null; } else { errorMessage = errorMessageBuffer.toString(); } String matchedDNStr; DN matchedDN = getMatchedDN(); if (matchedDN == null) { matchedDNStr = null; } else { matchedDNStr = matchedDN.toString(); } String referrals; List<String> referralURLs = getReferralURLs(); if ((referralURLs == null) || referralURLs.isEmpty()) { referrals = null; } else { StringBuilder buffer = new StringBuilder(); Iterator<String> iterator = referralURLs.iterator(); buffer.append(iterator.next()); while (iterator.hasNext()) { buffer.append(", "); buffer.append(iterator.next()); } referrals = buffer.toString(); } String processingTime = String.valueOf(getProcessingTime()); return new String[][] { new String[] { LOG_ELEMENT_RESULT_CODE, resultCode }, new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage }, new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr }, new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals }, new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime } }; } /** * Retrieves the proxied authorization DN for this operation if proxied * authorization has been requested. * Specifies the proxied authorization target DN for this compare operation. * * @return The proxied authorization DN for this operation if proxied * authorization has been requested, or {@code null} if proxied * authorization has not been requested. * @param proxiedAuthorizationDN The proxied authorization target DN for * this compare operation */ public DN getProxiedAuthorizationDN() { return proxiedAuthorizationDN; } /** * {@inheritDoc} */ @Override() public final List<Control> getResponseControls() { return responseControls; } /** * {@inheritDoc} */ @Override() public final void addResponseControl(Control control) { responseControls.add(control); } /** * {@inheritDoc} */ @Override() public final void removeResponseControl(Control control) { responseControls.remove(control); } /** * Performs the work of actually processing this operation. This * should include all processing for the operation, including * invoking plugins, logging messages, performing access control, * managing synchronization, and any other work that might need to * be done in the course of processing. */ public final void run() { setResultCode(ResultCode.UNDEFINED); // Get the plugin config manager that will be used for invoking plugins. PluginConfigManager pluginConfigManager = DirectoryServer.getPluginConfigManager(); boolean skipPostOperation = false; // Start the processing timer. setProcessingStartTime(); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); return; } // Create a labeled block of code that we can break out of if a problem is // detected. compareProcessing: { // Invoke the pre-parse compare plugins. PreParsePluginResult preParseResult = pluginConfigManager.invokePreParseComparePlugins(this); if (preParseResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request and // result and return. setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logCompareRequest(this); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } else if (preParseResult.sendResponseImmediately()) { skipPostOperation = true; logCompareRequest(this); break compareProcessing; } else if (preParseResult.skipCoreProcessing()) { skipPostOperation = false; break compareProcessing; } // Log the compare request message. logCompareRequest(this); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } // Process the entry DN to convert it from the raw form to the form // required for the rest of the compare processing. try { if (entryDN == null) { entryDN = DN.decode(rawEntryDN); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); skipPostOperation = true; break compareProcessing; } // If the target entry is in the server configuration, then make sure the // requester has the CONFIG_READ privilege. if (DirectoryServer.getConfigHandler().handlesEntry(entryDN) && (! clientConnection.hasPrivilege(Privilege.CONFIG_READ, this))) { int msgID = MSGID_COMPARE_CONFIG_INSUFFICIENT_PRIVILEGES; appendErrorMessage(getMessage(msgID)); setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); skipPostOperation = true; break compareProcessing; } // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } // Grab a read lock on the entry. Lock readLock = null; for (int i=0; i < 3; i++) { readLock = LockManager.lockRead(entryDN); if (readLock != null) { break; } } if (readLock == null) { int msgID = MSGID_COMPARE_CANNOT_LOCK_ENTRY; String message = getMessage(msgID, String.valueOf(entryDN)); setResultCode(DirectoryServer.getServerErrorResultCode()); appendErrorMessage(message); skipPostOperation = true; break compareProcessing; } try { // Get the entry. If it does not exist, then fail. try { entry = DirectoryServer.getEntry(entryDN); if (entry == null) { setResultCode(ResultCode.NO_SUCH_OBJECT); appendErrorMessage(getMessage(MSGID_COMPARE_NO_SUCH_ENTRY, String.valueOf(entryDN))); // See if one of the entry's ancestors exists. DN parentDN = entryDN.getParentDNInSuffix(); while (parentDN != null) { try { if (DirectoryServer.entryExists(parentDN)) { setMatchedDN(parentDN); break; } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } break; } parentDN = parentDN.getParentDNInSuffix(); } break compareProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); break compareProcessing; } // Check to see if there are any controls in the request. If so, then // see if there is any special processing required. List<Control> requestControls = getRequestControls(); if ((requestControls != null) && (! requestControls.isEmpty())) { for (int i=0; i < requestControls.size(); i++) { Control c = requestControls.get(i); String oid = c.getOID(); if (oid.equals(OID_LDAP_ASSERTION)) { LDAPAssertionRequestControl assertControl; if (c instanceof LDAPAssertionRequestControl) { assertControl = (LDAPAssertionRequestControl) c; } else { try { assertControl = LDAPAssertionRequestControl.decodeControl(c); requestControls.set(i, assertControl); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break compareProcessing; } } try { // FIXME -- We need to determine whether the current user has // permission to make this determination. SearchFilter filter = assertControl.getSearchFilter(); if (! filter.matchesEntry(entry)) { setResultCode(ResultCode.ASSERTION_FAILED); appendErrorMessage(getMessage(MSGID_COMPARE_ASSERTION_FAILED, String.valueOf(entryDN))); break compareProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(ResultCode.PROTOCOL_ERROR); int msgID = MSGID_COMPARE_CANNOT_PROCESS_ASSERTION_FILTER; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), de.getErrorMessage())); break compareProcessing; } } else if (oid.equals(OID_PROXIED_AUTH_V1)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; appendErrorMessage(getMessage(msgID)); setResultCode(ResultCode.AUTHORIZATION_DENIED); break compareProcessing; } ProxiedAuthV1Control proxyControl; if (c instanceof ProxiedAuthV1Control) { proxyControl = (ProxiedAuthV1Control) c; } else { try { proxyControl = ProxiedAuthV1Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break compareProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); 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); if (authorizationEntry == null) { proxiedAuthorizationDN = DN.nullDN(); } else { proxiedAuthorizationDN = authorizationEntry.getDN(); } } else if (oid.equals(OID_PROXIED_AUTH_V2)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; appendErrorMessage(getMessage(msgID)); setResultCode(ResultCode.AUTHORIZATION_DENIED); break compareProcessing; } ProxiedAuthV2Control proxyControl; if (c instanceof ProxiedAuthV2Control) { proxyControl = (ProxiedAuthV2Control) c; } else { try { proxyControl = ProxiedAuthV2Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } setResultCode(ResultCode.valueOf(le.getResultCode())); appendErrorMessage(le.getMessage()); break compareProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); 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); if (authorizationEntry == null) { proxiedAuthorizationDN = DN.nullDN(); } else { proxiedAuthorizationDN = authorizationEntry.getDN(); } } // NYI -- Add support for additional controls. else if (c.isCritical()) { Backend backend = DirectoryServer.getBackend(entryDN); if ((backend == null) || (! backend.supportsControl(oid))) { setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION); int msgID = MSGID_COMPARE_UNSUPPORTED_CRITICAL_CONTROL; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN), oid)); break compareProcessing; } } } } // Check to see if the client has permission to perform the // compare. // FIXME: for now assume that this will check all permission // pertinent to the operation. This includes proxy authorization // and any other controls specified. // FIXME: earlier checks to see if the entry already exists may // have already exposed sensitive information to the client. if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isAllowed(this) == false) { setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; appendErrorMessage(getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break compareProcessing; } // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } // Invoke the pre-operation compare plugins. PreOperationPluginResult preOpResult = pluginConfigManager.invokePreOperationComparePlugins(this); if (preOpResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request and // result and return. setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } else if (preOpResult.sendResponseImmediately()) { skipPostOperation = true; break compareProcessing; } else if (preOpResult.skipCoreProcessing()) { skipPostOperation = false; break compareProcessing; } // Get the base attribute type and set of options. String baseName; HashSet<String> options; int semicolonPos = rawAttributeType.indexOf(';'); if (semicolonPos > 0) { baseName = toLowerCase(rawAttributeType.substring(0, semicolonPos)); options = new HashSet<String>(); int nextPos = rawAttributeType.indexOf(';', semicolonPos+1); while (nextPos > 0) { options.add(rawAttributeType.substring(semicolonPos+1, nextPos)); semicolonPos = nextPos; nextPos = rawAttributeType.indexOf(';', semicolonPos+1); } options.add(rawAttributeType.substring(semicolonPos+1)); } else { baseName = toLowerCase(rawAttributeType); options = null; } // Actually perform the compare operation. List<Attribute> attrList = null; if (attributeType == null) { attributeType = DirectoryServer.getAttributeType(baseName); } if (attributeType == null) { attrList = entry.getAttribute(baseName, options); attributeType = DirectoryServer.getDefaultAttributeType(baseName); } else { attrList = entry.getAttribute(attributeType, options); } if ((attrList == null) || attrList.isEmpty()) { setResultCode(ResultCode.NO_SUCH_ATTRIBUTE); if (options == null) { appendErrorMessage(getMessage(MSGID_COMPARE_OP_NO_SUCH_ATTR, String.valueOf(entryDN), baseName)); } else { appendErrorMessage(getMessage( MSGID_COMPARE_OP_NO_SUCH_ATTR_WITH_OPTIONS, String.valueOf(entryDN), baseName)); } } else { AttributeValue value = new AttributeValue(attributeType, assertionValue); boolean matchFound = false; for (Attribute a : attrList) { if (a.hasValue(value)) { matchFound = true; break; } } if (matchFound) { setResultCode(ResultCode.COMPARE_TRUE); } else { setResultCode(ResultCode.COMPARE_FALSE); } } } finally { LockManager.unlock(entryDN, readLock); } } // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } // Invoke the post-operation compare plugins. if (! skipPostOperation) { PostOperationPluginResult postOperationResult = pluginConfigManager.invokePostOperationComparePlugins(this); if (postOperationResult.connectionTerminated()) { setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } } // Indicate that it is now too late to attempt to cancel the operation. setCancelResult(CancelResult.TOO_LATE); // Stop the processing timer. setProcessingStopTime(); // Send the compare response to the client. clientConnection.sendResponse(this); // Log the compare response message. logCompareResponse(this); // Invoke the post-response compare plugins. pluginConfigManager.invokePostResponseComparePlugins(this); } /** * {@inheritDoc} */ @Override() public final CancelResult cancel(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; CancelResult cancelResult = getCancelResult(); long stopWaitingTime = System.currentTimeMillis() + 5000; while ((cancelResult == null) && (System.currentTimeMillis() < stopWaitingTime)) { try { Thread.sleep(50); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } cancelResult = getCancelResult(); } if (cancelResult == null) { // This can happen in some rare cases (e.g., if a client disconnects and // there is still a lot of data to send to that client), and in this case // we'll prevent the cancel thread from blocking for a long period of // time. cancelResult = CancelResult.CANNOT_CANCEL; } return cancelResult; } /** * {@inheritDoc} */ @Override() public final CancelRequest getCancelRequest() { return cancelRequest; } /** * {@inheritDoc} */ @Override() public boolean setCancelRequest(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; return true; } /** * {@inheritDoc} */ @Override() public final void toString(StringBuilder buffer) { buffer.append("CompareOperation(connID="); buffer.append(clientConnection.getConnectionID()); buffer.append(", opID="); buffer.append(operationID); buffer.append(", dn="); buffer.append(rawEntryDN); buffer.append(", attr="); buffer.append(rawAttributeType); buffer.append(")"); } public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN); } opendj-sdk/opends/src/server/org/opends/server/core/CompareOperationBasis.java
New file @@ -0,0 +1,720 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.core; import static org.opends.server.core.CoreConstants.*; import static org.opends.server.loggers.AccessLogger.logCompareRequest; import static org.opends.server.loggers.AccessLogger.logCompareResponse; import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.getMessage; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.opends.server.api.ClientConnection; import org.opends.server.api.plugin.PreParsePluginResult; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.types.AbstractOperation; import org.opends.server.types.AttributeType; import org.opends.server.types.ByteString; import org.opends.server.types.CancelRequest; import org.opends.server.types.CancelResult; import org.opends.server.types.Control; import org.opends.server.types.DN; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.DirectoryException; import org.opends.server.types.DisconnectReason; import org.opends.server.types.Entry; import org.opends.server.types.Operation; import org.opends.server.types.OperationType; import org.opends.server.types.ResultCode; import org.opends.server.types.operation.PostResponseCompareOperation; import org.opends.server.types.operation.PreParseCompareOperation; import org.opends.server.workflowelement.localbackend. LocalBackendCompareOperation; /** * This class defines an operation that may be used to determine whether a * specified entry in the Directory Server contains a given attribute-value * pair. */ public class CompareOperationBasis extends AbstractOperation implements PreParseCompareOperation, CompareOperation, Runnable, PostResponseCompareOperation { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = DebugLogger.getTracer(); // The attribute type for this compare operation. private AttributeType attributeType; // The assertion value for the compare operation. private ByteString assertionValue; // The raw, unprocessed entry DN as included in the client request. private ByteString rawEntryDN; // The cancel request that has been issued for this compare operation. private CancelRequest cancelRequest; // The DN of the entry for the compare operation. private DN entryDN; // The proxied authorization target DN for this operation. private DN proxiedAuthorizationDN; // The set of response controls for this compare operation. private List<Control> responseControls; // The attribute type for the compare operation. private String rawAttributeType; /** * Creates a new compare operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param rawEntryDN The raw, unprocessed entry DN as provided in the * client request. This may or may not be a valid * DN as no validation will have been performed yet. * @param rawAttributeType The raw attribute type for the compare operation. * @param assertionValue The assertion value for the compare operation. */ public CompareOperationBasis( ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, ByteString rawEntryDN, String rawAttributeType, ByteString assertionValue) { super(clientConnection, operationID, messageID, requestControls); this.rawEntryDN = rawEntryDN; this.rawAttributeType = rawAttributeType; this.assertionValue = assertionValue; responseControls = new ArrayList<Control>(); entryDN = null; attributeType = null; cancelRequest = null; proxiedAuthorizationDN = null; } /** * Creates a new compare operation with the provided information. * * @param clientConnection The client connection with which this operation * is associated. * @param operationID The operation ID for this operation. * @param messageID The message ID of the request with which this * operation is associated. * @param requestControls The set of controls included in the request. * @param entryDN The entry DN for this compare operation. * @param attributeType The attribute type for this compare operation. * @param assertionValue The assertion value for the compare operation. */ public CompareOperationBasis( ClientConnection clientConnection, long operationID, int messageID, List<Control> requestControls, DN entryDN, AttributeType attributeType, ByteString assertionValue) { super(clientConnection, operationID, messageID, requestControls); this.entryDN = entryDN; this.attributeType = attributeType; this.assertionValue = assertionValue; responseControls = new ArrayList<Control>(); rawEntryDN = new ASN1OctetString(entryDN.toString()); rawAttributeType = attributeType.getNameOrOID(); cancelRequest = null; proxiedAuthorizationDN = null; } /** * {@inheritDoc} */ public final ByteString getRawEntryDN() { return rawEntryDN; } /** * {@inheritDoc} */ public final void setRawEntryDN(ByteString rawEntryDN) { this.rawEntryDN = rawEntryDN; entryDN = null; } /** * {@inheritDoc} */ public final DN getEntryDN() { return entryDN; } /** * {@inheritDoc} */ public final String getRawAttributeType() { return rawAttributeType; } /** * {@inheritDoc} */ public final void setRawAttributeType(String rawAttributeType) { this.rawAttributeType = rawAttributeType; attributeType = null; } /** * {@inheritDoc} */ public final AttributeType getAttributeType() { return attributeType; } /** * {@inheritDoc} */ public void setAttributeType(AttributeType attributeType) { this.attributeType = attributeType; } /** * {@inheritDoc} */ public final ByteString getAssertionValue() { return assertionValue; } /** * {@inheritDoc} */ public final void setAssertionValue(ByteString assertionValue) { this.assertionValue = assertionValue; } /** * {@inheritDoc} */ @Override() public final OperationType getOperationType() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. return OperationType.COMPARE; } /** * {@inheritDoc} */ @Override() public final void disconnectClient(DisconnectReason disconnectReason, boolean sendNotification, String message, int messageID) { // Before calling clientConnection.disconnect, we need to mark this // operation as cancelled so that the attempt to cancel it later won't cause // an unnecessary delay. setCancelResult(CancelResult.CANCELED); clientConnection.disconnect(disconnectReason, sendNotification, message, messageID); } /** * {@inheritDoc} */ @Override() public final String[][] getRequestLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. return new String[][] { new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }, new String[] { LOG_ELEMENT_COMPARE_ATTR, rawAttributeType } }; } /** * {@inheritDoc} */ @Override() public final String[][] getResponseLogElements() { // Note that no debugging will be done in this method because it is a likely // candidate for being called by the logging subsystem. String resultCode = String.valueOf(getResultCode().getIntValue()); String errorMessage; StringBuilder errorMessageBuffer = getErrorMessage(); if (errorMessageBuffer == null) { errorMessage = null; } else { errorMessage = errorMessageBuffer.toString(); } String matchedDNStr; DN matchedDN = getMatchedDN(); if (matchedDN == null) { matchedDNStr = null; } else { matchedDNStr = matchedDN.toString(); } String referrals; List<String> referralURLs = getReferralURLs(); if ((referralURLs == null) || referralURLs.isEmpty()) { referrals = null; } else { StringBuilder buffer = new StringBuilder(); Iterator<String> iterator = referralURLs.iterator(); buffer.append(iterator.next()); while (iterator.hasNext()) { buffer.append(", "); buffer.append(iterator.next()); } referrals = buffer.toString(); } String processingTime = String.valueOf(getProcessingTime()); return new String[][] { new String[] { LOG_ELEMENT_RESULT_CODE, resultCode }, new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage }, new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr }, new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals }, new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime } }; } /** * Retrieves the proxied authorization DN for this operation if proxied * authorization has been requested. * * @return The proxied authorization DN for this operation if proxied * authorization has been requested, or {@code null} if proxied * authorization has not been requested. */ public DN getProxiedAuthorizationDN() { return proxiedAuthorizationDN; } /** * {@inheritDoc} */ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN) { this.proxiedAuthorizationDN = proxiedAuthorizationDN; } /** * {@inheritDoc} */ @Override() public final List<Control> getResponseControls() { return responseControls; } /** * {@inheritDoc} */ @Override() public final void addResponseControl(Control control) { responseControls.add(control); } /** * {@inheritDoc} */ @Override() public final void removeResponseControl(Control control) { responseControls.remove(control); } /** * Performs the work of actually processing this operation. This * should include all processing for the operation, including * invoking plugins, logging messages, performing access control, * managing synchronization, and any other work that might need to * be done in the course of processing. */ public final void run() { setResultCode(ResultCode.UNDEFINED); // Start the processing timer. setProcessingStartTime(); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); return; } // Get the plugin config manager that will be used for invoking plugins. PluginConfigManager pluginConfigManager = DirectoryServer.getPluginConfigManager(); // Create a labeled block of code that we can break out of if a problem is // detected. boolean workflowExecuted = false; compareProcessing: { // Invoke the pre-parse compare plugins. PreParsePluginResult preParseResult = pluginConfigManager.invokePreParseComparePlugins(this); if (preParseResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request and // result and return. setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT; appendErrorMessage(getMessage(msgID)); setProcessingStopTime(); logCompareRequest(this); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } else if (preParseResult.sendResponseImmediately()) { logCompareRequest(this); break compareProcessing; } else if (preParseResult.skipCoreProcessing()) { break compareProcessing; } // Log the compare request message. logCompareRequest(this); // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } // Process the entry DN to convert it from the raw form to the form // required for the rest of the compare processing. try { if (entryDN == null) { entryDN = DN.decode(rawEntryDN); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } setResultCode(de.getResultCode()); appendErrorMessage(de.getErrorMessage()); break compareProcessing; } // Retrieve the network group registered with the client connection // and get a workflow to process the operation. NetworkGroup ng = getClientConnection().getNetworkGroup(); Workflow workflow = ng.getWorkflowCandidate(entryDN); if (workflow == null) { // We have found no workflow for the requested base DN, just return // a no such entry result code and stop the processing. updateOperationErrMsgAndResCode(); break compareProcessing; } workflow.execute(this); workflowExecuted = true; } // Check for and handle a request to cancel this operation. if (cancelRequest != null) { indicateCancelled(cancelRequest); setProcessingStopTime(); logCompareResponse(this); pluginConfigManager.invokePostResponseComparePlugins(this); return; } // Indicate that it is now too late to attempt to cancel the operation. setCancelResult(CancelResult.TOO_LATE); // Stop the processing timer. setProcessingStopTime(); // Send the compare response to the client unless the operation result // code is CANCELED if (getResultCode() != ResultCode.CANCELED) { clientConnection.sendResponse(this); } // Log the compare response message. logCompareResponse(this); // Invoke the post-response compare plugins. if (workflowExecuted) { List localOperations = (List)getAttachment(Operation.LOCALBACKENDOPERATIONS); if (localOperations != null) { for (Object localOp : localOperations) { LocalBackendCompareOperation localOperation = (LocalBackendCompareOperation)localOp; pluginConfigManager.invokePostResponseComparePlugins(localOperation); } } } else { pluginConfigManager.invokePostResponseComparePlugins(this); } } /** * Updates the error message and the result code of the operation. * * This method is called because no workflow was found to process * the operation. */ private void updateOperationErrMsgAndResCode() { setResultCode(ResultCode.NO_SUCH_OBJECT); appendErrorMessage( getMessage(MSGID_COMPARE_NO_SUCH_ENTRY, String.valueOf(getEntryDN()))); } /** * {@inheritDoc} */ @Override() public final CancelResult cancel(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; CancelResult cancelResult = getCancelResult(); long stopWaitingTime = System.currentTimeMillis() + 5000; while ((cancelResult == null) && (System.currentTimeMillis() < stopWaitingTime)) { try { Thread.sleep(50); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } cancelResult = getCancelResult(); } if (cancelResult == null) { // This can happen in some rare cases (e.g., if a client disconnects and // there is still a lot of data to send to that client), and in this case // we'll prevent the cancel thread from blocking for a long period of // time. cancelResult = CancelResult.CANNOT_CANCEL; } return cancelResult; } /** * {@inheritDoc} */ @Override() public final CancelRequest getCancelRequest() { return cancelRequest; } /** * {@inheritDoc} */ @Override() public boolean setCancelRequest(CancelRequest cancelRequest) { this.cancelRequest = cancelRequest; return true; } /** * {@inheritDoc} */ @Override() public final void toString(StringBuilder buffer) { buffer.append("CompareOperation(connID="); buffer.append(clientConnection.getConnectionID()); buffer.append(", opID="); buffer.append(operationID); buffer.append(", dn="); buffer.append(rawEntryDN); buffer.append(", attr="); buffer.append(rawAttributeType); buffer.append(")"); } /** * {@inheritDoc} * * This method always returns null. */ public Entry getEntryToCompare() { return null; } } opendj-sdk/opends/src/server/org/opends/server/core/CompareOperationWrapper.java
New file @@ -0,0 +1,158 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.core; import org.opends.server.types.AttributeType; import org.opends.server.types.ByteString; import org.opends.server.types.DN; /** * This abstract class wraps/decorates a given compare operation. * This class will be extended by sub-classes to enhance the * functionnality of the CompareOperationBasis. */ public abstract class CompareOperationWrapper extends OperationWrapper implements CompareOperation { // The wrapped operation private CompareOperation compare; /** * Creates a new compare operation based on the provided compare operation. * * @param compare The compare operation to wrap */ public CompareOperationWrapper(CompareOperation compare) { super(compare); this.compare = compare; } /** * {@inheritDoc} */ public ByteString getRawEntryDN() { return compare.getRawEntryDN(); } /** * {@inheritDoc} */ public void setRawEntryDN(ByteString rawEntryDN) { compare.setRawEntryDN(rawEntryDN); } /** * {@inheritDoc} */ public DN getEntryDN() { return compare.getEntryDN(); } /** * {@inheritDoc} */ public String getRawAttributeType() { return compare.getRawAttributeType(); } /** * {@inheritDoc} */ public void setRawAttributeType(String rawAttributeType) { compare.setRawAttributeType(rawAttributeType); } /** * {@inheritDoc} */ public AttributeType getAttributeType() { return compare.getAttributeType(); } /** * {@inheritDoc} */ public void setAttributeType(AttributeType attributeType) { compare.setAttributeType(attributeType); } /** * {@inheritDoc} */ public ByteString getAssertionValue() { return compare.getAssertionValue(); } /** * {@inheritDoc} */ public void setAssertionValue(ByteString assertionValue) { compare.setAssertionValue(assertionValue); } /** * {@inheritDoc} */ public DN getProxiedAuthorizationDN() { return compare.getProxiedAuthorizationDN(); } /** * {@inheritDoc} */ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN) { compare.setProxiedAuthorizationDN(proxiedAuthorizationDN); } } opendj-sdk/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
@@ -116,7 +116,7 @@ * {@inheritDoc} */ @Override public boolean isAllowed(CompareOperation compareOperation) public boolean isAllowed(LocalBackendCompareOperation compareOperation) { return true; } opendj-sdk/opends/src/server/org/opends/server/core/OperationWrapper.java
New file @@ -0,0 +1,511 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.core; import java.util.List; import java.util.Map; import org.opends.server.api.ClientConnection; import org.opends.server.types.CancelRequest; import org.opends.server.types.CancelResult; import org.opends.server.types.Control; import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; import org.opends.server.types.DisconnectReason; import org.opends.server.types.Entry; import org.opends.server.types.Operation; import org.opends.server.types.OperationType; import org.opends.server.types.ResultCode; /** * This abstract class is a generic operation wrapper intended to be * subclassed by a specific operation wrapper. */ public class OperationWrapper implements Operation { // The wrapped operation. private Operation operation; /** * Creates a new generic operation wrapper. * * @param operation the generic operation to wrap */ public OperationWrapper(Operation operation) { this.operation = operation; } /** * {@inheritDoc} */ public void addRequestControl(Control control) { operation.addRequestControl(control); } /** * {@inheritDoc} */ public void addResponseControl(Control control) { operation.addResponseControl(control); } /** * {@inheritDoc} */ public void appendAdditionalLogMessage(String message) { operation.appendAdditionalLogMessage(message); } /** * {@inheritDoc} */ public void appendErrorMessage(String message) { operation.appendErrorMessage(message); } /** * {@inheritDoc} */ public CancelResult cancel(CancelRequest cancelRequest) { return operation.cancel(cancelRequest); } /** * {@inheritDoc} */ public void disconnectClient( DisconnectReason disconnectReason, boolean sendNotification, String message, int messageID) { operation.disconnectClient( disconnectReason, sendNotification, message, messageID); } /** * {@inheritDoc} */ public boolean dontSynchronize() { return operation.dontSynchronize(); } /** * {@inheritDoc} */ public StringBuilder getAdditionalLogMessage() { return operation.getAdditionalLogMessage(); } /** * {@inheritDoc} */ public Object getAttachment(String name) { return operation.getAttachment(name); } /** * {@inheritDoc} */ public Map<String, Object> getAttachments() { return operation.getAttachments(); } /** * {@inheritDoc} */ public DN getAuthorizationDN() { return operation.getAuthorizationDN(); } /** * {@inheritDoc} */ public Entry getAuthorizationEntry() { return operation.getAuthorizationEntry(); } /** * {@inheritDoc} */ public CancelRequest getCancelRequest() { return operation.getCancelRequest(); } /** * {@inheritDoc} */ public CancelResult getCancelResult() { return operation.getCancelResult(); } /** * {@inheritDoc} */ public ClientConnection getClientConnection() { return operation.getClientConnection(); } /** * {@inheritDoc} */ public String[][] getCommonLogElements() { return operation.getCommonLogElements(); } /** * {@inheritDoc} */ public long getConnectionID() { return operation.getConnectionID(); } /** * {@inheritDoc} */ public StringBuilder getErrorMessage() { return operation.getErrorMessage(); } /** * {@inheritDoc} */ public DN getMatchedDN() { return operation.getMatchedDN(); } /** * {@inheritDoc} */ public int getMessageID() { return operation.getMessageID(); } /** * {@inheritDoc} */ public long getOperationID() { return operation.getOperationID(); } /** * {@inheritDoc} */ public OperationType getOperationType() { return operation.getOperationType(); } /** * {@inheritDoc} */ public long getProcessingStartTime() { return operation.getProcessingStartTime(); } /** * {@inheritDoc} */ public long getProcessingStopTime() { return operation.getProcessingStopTime(); } /** * {@inheritDoc} */ public long getProcessingTime() { return operation.getProcessingTime(); } /** * {@inheritDoc} */ public List<String> getReferralURLs() { return operation.getReferralURLs(); } /** * {@inheritDoc} */ public List<Control> getRequestControls() { return operation.getRequestControls(); } /** * {@inheritDoc} */ public String[][] getRequestLogElements() { return operation.getRequestLogElements(); } /** * {@inheritDoc} */ public List<Control> getResponseControls() { return operation.getResponseControls(); } /** * {@inheritDoc} */ public String[][] getResponseLogElements() { return operation.getResponseLogElements(); } /** * {@inheritDoc} */ public ResultCode getResultCode() { return operation.getResultCode(); } /** * {@inheritDoc} */ public void indicateCancelled(CancelRequest cancelRequest) { operation.indicateCancelled(cancelRequest); } /** * {@inheritDoc} */ public boolean isInternalOperation() { return operation.isInternalOperation(); } /** * {@inheritDoc} */ public boolean isSynchronizationOperation() { return operation.isSynchronizationOperation(); } /** * {@inheritDoc} */ public void operationCompleted() { operation.operationCompleted(); } /** * {@inheritDoc} */ public Object removeAttachment(String name) { return operation.removeAttachment(name); } /** * {@inheritDoc} */ public void removeRequestControl(Control control) { operation.removeRequestControl(control); } /** * {@inheritDoc} */ public void removeResponseControl(Control control) { operation.removeResponseControl(control); } /** * {@inheritDoc} */ public void setAdditionalLogMessage(StringBuilder additionalLogMessage) { operation.setAdditionalLogMessage(additionalLogMessage); } /** * {@inheritDoc} */ public Object setAttachment(String name, Object value) { return operation.setAttachment(name, value); } /** * {@inheritDoc} */ public void setAttachments(Map<String, Object> attachments) { operation.setAttachments(attachments); } /** * {@inheritDoc} */ public void setAuthorizationEntry(Entry authorizationEntry) { operation.setAuthorizationEntry(authorizationEntry); } /** * {@inheritDoc} */ public boolean setCancelRequest(CancelRequest cancelRequest) { return operation.setCancelRequest(cancelRequest); } /** * {@inheritDoc} */ public void setCancelResult(CancelResult cancelResult) { operation.setCancelResult(cancelResult); } /** * {@inheritDoc} */ public void setDontSynchronize(boolean dontSynchronize) { operation.setDontSynchronize(dontSynchronize); } /** * {@inheritDoc} */ public void setErrorMessage(StringBuilder errorMessage) { operation.setErrorMessage(errorMessage); } /** * {@inheritDoc} */ public void setInternalOperation(boolean isInternalOperation) { operation.setInternalOperation(isInternalOperation); } /** * {@inheritDoc} */ public void setMatchedDN(DN matchedDN) { operation.setMatchedDN(matchedDN); } /** * {@inheritDoc} */ public void setProcessingStartTime() { operation.setProcessingStartTime(); } /** * {@inheritDoc} */ public void setProcessingStopTime() { operation.setProcessingStopTime(); } /** * {@inheritDoc} */ public void setReferralURLs(List<String> referralURLs) { operation.setReferralURLs(referralURLs); } /** * {@inheritDoc} */ public void setResponseData(DirectoryException directoryException) { operation.setResponseData(directoryException); } /** * {@inheritDoc} */ public void setResultCode(ResultCode resultCode) { operation.setResultCode(resultCode); } /** * {@inheritDoc} */ public void setSynchronizationOperation(boolean isSynchronizationOperation) { operation.setSynchronizationOperation(isSynchronizationOperation); } /** * {@inheritDoc} */ public void toString(StringBuilder buffer) { operation.toString(buffer); } } opendj-sdk/opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -82,21 +82,25 @@ import org.opends.server.types.DebugLogLevel; import org.opends.server.types.operation.PostOperationAddOperation; import org.opends.server.types.operation.PostOperationBindOperation; import org.opends.server.types.operation.PostOperationCompareOperation; import org.opends.server.types.operation.PostOperationDeleteOperation; import org.opends.server.types.operation.PostOperationModifyOperation; import org.opends.server.types.operation.PostOperationSearchOperation; import org.opends.server.types.operation.PostResponseAddOperation; import org.opends.server.types.operation.PostResponseBindOperation; import org.opends.server.types.operation.PostResponseCompareOperation; import org.opends.server.types.operation.PostResponseDeleteOperation; import org.opends.server.types.operation.PostResponseModifyOperation; import org.opends.server.types.operation.PostResponseSearchOperation; import org.opends.server.types.operation.PreOperationAddOperation; import org.opends.server.types.operation.PreOperationBindOperation; import org.opends.server.types.operation.PreOperationCompareOperation; import org.opends.server.types.operation.PreOperationDeleteOperation; import org.opends.server.types.operation.PreOperationModifyOperation; import org.opends.server.types.operation.PreOperationSearchOperation; import org.opends.server.types.operation.PreParseAddOperation; import org.opends.server.types.operation.PreParseBindOperation; import org.opends.server.types.operation.PreParseCompareOperation; import org.opends.server.types.operation.PreParseDeleteOperation; import org.opends.server.types.operation.PreParseModifyOperation; import org.opends.server.types.operation.PreParseSearchOperation; @@ -1971,7 +1975,7 @@ * @return The result of processing the pre-parse compare plugins. */ public PreParsePluginResult invokePreParseComparePlugins( CompareOperation compareOperation) PreParseCompareOperation compareOperation) { PreParsePluginResult result = null; @@ -2705,7 +2709,7 @@ * @return The result of processing the pre-operation compare plugins. */ public PreOperationPluginResult invokePreOperationComparePlugins( CompareOperation compareOperation) PreOperationCompareOperation compareOperation) { PreOperationPluginResult result = null; @@ -3439,7 +3443,7 @@ * @return The result of processing the post-operation compare plugins. */ public PostOperationPluginResult invokePostOperationComparePlugins( CompareOperation compareOperation) PostOperationCompareOperation compareOperation) { PostOperationPluginResult result = null; @@ -4161,7 +4165,7 @@ * @return The result of processing the post-response compare plugins. */ public PostResponsePluginResult invokePostResponseComparePlugins( CompareOperation compareOperation) PostResponseCompareOperation compareOperation) { PostResponsePluginResult result = null; opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -954,8 +954,8 @@ String attributeType, ByteString assertionValue) { CompareOperation compareOperation = new CompareOperation(this, nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis(this, nextOperationID(), nextMessageID(), new ArrayList<Control>(0), rawEntryDN, attributeType, assertionValue); @@ -985,8 +985,8 @@ AttributeType attributeType, ByteString assertionValue) { CompareOperation compareOperation = new CompareOperation(this, nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis(this, nextOperationID(), nextMessageID(), new ArrayList<Control>(0), entryDN, attributeType, assertionValue); opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -589,8 +589,8 @@ String attributeType, ASN1OctetString assertionValue) { CompareOperation compareOperation = new CompareOperation(this, nextOperationID(), nextMessageID(), CompareOperationBasis compareOperation = new CompareOperationBasis(this, nextOperationID(), nextMessageID(), new ArrayList<Control>(0), rawEntryDN, attributeType, assertionValue); opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -56,7 +56,7 @@ import org.opends.server.core.AbandonOperation; import org.opends.server.core.AddOperationBasis; import org.opends.server.core.BindOperationBasis; import org.opends.server.core.CompareOperation; import org.opends.server.core.CompareOperationBasis; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ExtendedOperation; @@ -2063,8 +2063,8 @@ } CompareRequestProtocolOp protocolOp = message.getCompareRequestProtocolOp(); CompareOperation compareOp = new CompareOperation(this, nextOperationID.getAndIncrement(), CompareOperationBasis compareOp = new CompareOperationBasis(this, nextOperationID.getAndIncrement(), message.getMessageID(), controls, protocolOp.getDN(), protocolOp.getAttributeType(), protocolOp.getAssertionValue()); opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java
New file @@ -0,0 +1,86 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.workflowelement.localbackend; import org.opends.server.core.CompareOperation; import org.opends.server.core.CompareOperationWrapper; import org.opends.server.types.Entry; import org.opends.server.types.operation.PostOperationCompareOperation; import org.opends.server.types.operation.PostResponseCompareOperation; import org.opends.server.types.operation.PreOperationCompareOperation; /** * This class defines an operation that may be used to determine whether a * specified entry in the Directory Server contains a given attribute-value * pair. */ public class LocalBackendCompareOperation extends CompareOperationWrapper implements PreOperationCompareOperation, PostOperationCompareOperation, PostResponseCompareOperation { // The entry to be compared. private Entry entry = null; /** * Creates a new compare operation based on the provided compare operation. * * @param compare the compare operation */ public LocalBackendCompareOperation(CompareOperation compare) { super(compare); LocalBackendWorkflowElement.attachLocalOperation (compare, this); } /** * Retrieves the entry to target with the compare operation. * * @return The entry to target with the compare operation, or * <CODE>null</CODE> if the entry is not yet available. */ public Entry getEntryToCompare() { return entry; } /** * Set the entry to target with the compare operation. * * @param entry The entry to target with the compare operation. */ public void setEntryToCompare(Entry entry) { this.entry = entry; } } opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -74,6 +74,7 @@ import org.opends.server.core.AccessControlConfigManager; 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.DirectoryServer; import org.opends.server.core.ModifyOperation; @@ -178,6 +179,9 @@ case MODIFY: processModify((ModifyOperation) operation); break; case COMPARE: processCompare((CompareOperation) operation); break; default: // jdemendi - temporary code, just make sure that we don't fell into // that incomplete code... @@ -5860,9 +5864,9 @@ /** * Perform a delete operation against a local backend. * Performs a delete operation against a local backend. * * @param operation - The operation to perform * @param operation the operation to perform */ public void processDelete(DeleteOperation operation){ LocalBackendDeleteOperation localOperation = @@ -5871,9 +5875,9 @@ } /** * Perform a local delete operation against a local backend. * Performs a local delete operation against a local backend. * * @param operation - The operation to perform * @param operation the operation to perform */ private void processLocalDelete(LocalBackendDeleteOperation localOp) { @@ -6673,6 +6677,576 @@ /** * Perform a compare operation against a local backend. * * @param operation - The operation to perform */ public void processCompare(CompareOperation operation) { LocalBackendCompareOperation localOperation = new LocalBackendCompareOperation(operation); processLocalCompare(localOperation); } /** * Perform a local compare operation against a local backend. * * @param operation - The operation to perform */ private void processLocalCompare(LocalBackendCompareOperation localOp) { // Get the plugin config manager that will be used for invoking plugins. PluginConfigManager pluginConfigManager = DirectoryServer.getPluginConfigManager(); boolean skipPostOperation = false; // Get a reference to the client connection ClientConnection clientConnection = localOp.getClientConnection(); // Check for and handle a request to cancel this operation. if (localOp.getCancelRequest() != null) { return; } // Create a labeled block of code that we can break out of if a problem is // detected. compareProcessing: { // Process the entry DN to convert it from the raw form to the form // required for the rest of the compare processing. DN entryDN = localOp.getEntryDN(); if (entryDN == null) { skipPostOperation = true; break compareProcessing; } // If the target entry is in the server configuration, then make sure the // requester has the CONFIG_READ privilege. if (DirectoryServer.getConfigHandler().handlesEntry(entryDN) && (! clientConnection.hasPrivilege(Privilege.CONFIG_READ, localOp))) { int msgID = MSGID_COMPARE_CONFIG_INSUFFICIENT_PRIVILEGES; localOp.appendErrorMessage(getMessage(msgID)); localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); skipPostOperation = true; break compareProcessing; } // Check for and handle a request to cancel this operation. if (localOp.getCancelRequest() != null) { return; } // Grab a read lock on the entry. Lock readLock = null; for (int i=0; i < 3; i++) { readLock = LockManager.lockRead(entryDN); if (readLock != null) { break; } } if (readLock == null) { int msgID = MSGID_COMPARE_CANNOT_LOCK_ENTRY; String message = getMessage(msgID, String.valueOf(entryDN)); localOp.setResultCode(DirectoryServer.getServerErrorResultCode()); localOp.appendErrorMessage(message); skipPostOperation = true; break compareProcessing; } Entry entry = null; try { // Get the entry. If it does not exist, then fail. try { entry = DirectoryServer.getEntry(entryDN); localOp.setEntryToCompare(entry); if (entry == null) { localOp.setResultCode(ResultCode.NO_SUCH_OBJECT); localOp.appendErrorMessage(getMessage(MSGID_COMPARE_NO_SUCH_ENTRY, String.valueOf(entryDN))); // See if one of the entry's ancestors exists. DN parentDN = entryDN.getParentDNInSuffix(); while (parentDN != null) { try { if (DirectoryServer.entryExists(parentDN)) { localOp.setMatchedDN(parentDN); break; } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } break; } parentDN = parentDN.getParentDNInSuffix(); } break compareProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } localOp.setResultCode(de.getResultCode()); localOp.appendErrorMessage(de.getErrorMessage()); break compareProcessing; } // Check to see if there are any controls in the request. If so, then // see if there is any special processing required. List<Control> requestControls = localOp.getRequestControls(); if ((requestControls != null) && (! requestControls.isEmpty())) { for (int i=0; i < requestControls.size(); i++) { Control c = requestControls.get(i); String oid = c.getOID(); if (oid.equals(OID_LDAP_ASSERTION)) { LDAPAssertionRequestControl assertControl; if (c instanceof LDAPAssertionRequestControl) { assertControl = (LDAPAssertionRequestControl) c; } else { try { assertControl = LDAPAssertionRequestControl.decodeControl(c); requestControls.set(i, assertControl); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } localOp.setResultCode(ResultCode.valueOf(le.getResultCode())); localOp.appendErrorMessage(le.getMessage()); break compareProcessing; } } try { // FIXME -- We need to determine whether the current user has // permission to make this determination. SearchFilter filter = assertControl.getSearchFilter(); if (! filter.matchesEntry(entry)) { localOp.setResultCode(ResultCode.ASSERTION_FAILED); localOp.appendErrorMessage( getMessage(MSGID_COMPARE_ASSERTION_FAILED, String.valueOf(entryDN))); break compareProcessing; } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } localOp.setResultCode(ResultCode.PROTOCOL_ERROR); int msgID = MSGID_COMPARE_CANNOT_PROCESS_ASSERTION_FILTER; localOp.appendErrorMessage( getMessage(msgID, String.valueOf(entryDN), de.getErrorMessage())); break compareProcessing; } } else if (oid.equals(OID_PROXIED_AUTH_V1)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege( Privilege.PROXIED_AUTH, localOp)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; localOp.appendErrorMessage(getMessage(msgID)); localOp.setResultCode(ResultCode.AUTHORIZATION_DENIED); break compareProcessing; } ProxiedAuthV1Control proxyControl; if (c instanceof ProxiedAuthV1Control) { proxyControl = (ProxiedAuthV1Control) c; } else { try { proxyControl = ProxiedAuthV1Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } localOp.setResultCode(ResultCode.valueOf(le.getResultCode())); localOp.appendErrorMessage(le.getMessage()); break compareProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } localOp.setResultCode(de.getResultCode()); localOp.appendErrorMessage(de.getErrorMessage()); break compareProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(localOp, authorizationEntry) == false) { localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; localOp.appendErrorMessage( getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break compareProcessing; } localOp.setAuthorizationEntry(authorizationEntry); if (authorizationEntry == null) { localOp.setProxiedAuthorizationDN(DN.nullDN()); } else { localOp.setProxiedAuthorizationDN(authorizationEntry.getDN()); } } else if (oid.equals(OID_PROXIED_AUTH_V2)) { // The requester must have the PROXIED_AUTH privilige in order to // be able to use this control. if (! clientConnection.hasPrivilege( Privilege.PROXIED_AUTH, localOp)) { int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES; localOp.appendErrorMessage(getMessage(msgID)); localOp.setResultCode(ResultCode.AUTHORIZATION_DENIED); break compareProcessing; } ProxiedAuthV2Control proxyControl; if (c instanceof ProxiedAuthV2Control) { proxyControl = (ProxiedAuthV2Control) c; } else { try { proxyControl = ProxiedAuthV2Control.decodeControl(c); } catch (LDAPException le) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, le); } localOp.setResultCode(ResultCode.valueOf(le.getResultCode())); localOp.appendErrorMessage(le.getMessage()); break compareProcessing; } } Entry authorizationEntry; try { authorizationEntry = proxyControl.getAuthorizationEntry(); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } localOp.setResultCode(de.getResultCode()); localOp.appendErrorMessage(de.getErrorMessage()); break compareProcessing; } if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isProxiedAuthAllowed(localOp, authorizationEntry) == false) { localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; localOp.appendErrorMessage( getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break compareProcessing; } localOp.setAuthorizationEntry(authorizationEntry); if (authorizationEntry == null) { localOp.setProxiedAuthorizationDN(DN.nullDN()); } else { localOp.setProxiedAuthorizationDN(authorizationEntry.getDN()); } } // NYI -- Add support for additional controls. else if (c.isCritical()) { Backend backend = DirectoryServer.getBackend(entryDN); if ((backend == null) || (! backend.supportsControl(oid))) { localOp.setResultCode( ResultCode.UNAVAILABLE_CRITICAL_EXTENSION); int msgID = MSGID_COMPARE_UNSUPPORTED_CRITICAL_CONTROL; localOp.appendErrorMessage( getMessage(msgID, String.valueOf(entryDN), oid)); break compareProcessing; } } } } // Check to see if the client has permission to perform the // compare. // FIXME: for now assume that this will check all permission // pertinent to the operation. This includes proxy authorization // and any other controls specified. // FIXME: earlier checks to see if the entry already exists may // have already exposed sensitive information to the client. if (AccessControlConfigManager.getInstance() .getAccessControlHandler().isAllowed(localOp) == false) { localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS; localOp.appendErrorMessage( getMessage(msgID, String.valueOf(entryDN))); skipPostOperation = true; break compareProcessing; } // Check for and handle a request to cancel this operation. if (localOp.getCancelRequest() != null) { return; } // Invoke the pre-operation compare plugins. PreOperationPluginResult preOpResult = pluginConfigManager.invokePreOperationComparePlugins(localOp); if (preOpResult.connectionTerminated()) { // There's no point in continuing with anything. Log the request and // result and return. localOp.setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT; localOp.appendErrorMessage(getMessage(msgID)); return; } else if (preOpResult.sendResponseImmediately()) { skipPostOperation = true; break compareProcessing; } else if (preOpResult.skipCoreProcessing()) { skipPostOperation = false; break compareProcessing; } // Get the base attribute type and set of options. String baseName; HashSet<String> options; String rawAttributeType = localOp.getRawAttributeType(); int semicolonPos = rawAttributeType.indexOf(';'); if (semicolonPos > 0) { baseName = toLowerCase(rawAttributeType.substring(0, semicolonPos)); options = new HashSet<String>(); int nextPos = rawAttributeType.indexOf(';', semicolonPos+1); while (nextPos > 0) { options.add(rawAttributeType.substring(semicolonPos+1, nextPos)); semicolonPos = nextPos; nextPos = rawAttributeType.indexOf(';', semicolonPos+1); } options.add(rawAttributeType.substring(semicolonPos+1)); } else { baseName = toLowerCase(rawAttributeType); options = null; } // Actually perform the compare operation. List<Attribute> attrList = null; if (localOp.getAttributeType() == null) { localOp.setAttributeType(DirectoryServer.getAttributeType(baseName)); } if (localOp.getAttributeType() == null) { attrList = entry.getAttribute(baseName, options); localOp.setAttributeType( DirectoryServer.getDefaultAttributeType(baseName)); } else { attrList = entry.getAttribute(localOp.getAttributeType(), options); } if ((attrList == null) || attrList.isEmpty()) { localOp.setResultCode(ResultCode.NO_SUCH_ATTRIBUTE); if (options == null) { localOp.appendErrorMessage(getMessage(MSGID_COMPARE_OP_NO_SUCH_ATTR, String.valueOf(entryDN), baseName)); } else { localOp.appendErrorMessage(getMessage( MSGID_COMPARE_OP_NO_SUCH_ATTR_WITH_OPTIONS, String.valueOf(entryDN), baseName)); } } else { AttributeValue value = new AttributeValue( localOp.getAttributeType(), localOp.getAssertionValue()); boolean matchFound = false; for (Attribute a : attrList) { if (a.hasValue(value)) { matchFound = true; break; } } if (matchFound) { localOp.setResultCode(ResultCode.COMPARE_TRUE); } else { localOp.setResultCode(ResultCode.COMPARE_FALSE); } } } finally { LockManager.unlock(entryDN, readLock); } } // Check for and handle a request to cancel this operation. if (localOp.getCancelRequest() != null) { return; } // Invoke the post-operation compare plugins. if (! skipPostOperation) { PostOperationPluginResult postOperationResult = pluginConfigManager.invokePostOperationComparePlugins(localOp); if (postOperationResult.connectionTerminated()) { localOp.setResultCode(ResultCode.CANCELED); int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT; localOp.appendErrorMessage(getMessage(msgID)); return; } } } /** * Attaches the current local operation to the global operation so that * operation runner can execute local operation post response later on. * opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java
@@ -48,7 +48,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import static org.testng.Assert.*; import static org.testng.Assert.assertEquals; import java.util.ArrayList; import java.util.List; @@ -138,7 +137,8 @@ return new Operation[] { new CompareOperation(conn, InternalClientConnection.nextOperationID(), new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -216,8 +216,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -240,8 +241,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -263,8 +265,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString("o=nonexistent,o=test"), @@ -285,8 +288,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString("rogasawara,o=test"), @@ -307,8 +311,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -330,8 +335,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -352,8 +358,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -371,8 +378,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -390,8 +398,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -409,8 +418,9 @@ InternalClientConnection conn = InternalClientConnection.getRootConnection(); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), new ArrayList<Control>(), new ASN1OctetString(entry.getDN().toString()), @@ -436,8 +446,9 @@ List<Control> controls = new ArrayList<Control>(); controls.add(assertControl); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, new ASN1OctetString(entry.getDN().toString()), @@ -465,8 +476,9 @@ List<Control> controls = new ArrayList<Control>(); controls.add(assertControl); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, new ASN1OctetString(entry.getDN().toString()), @@ -490,8 +502,9 @@ List<Control> controls = new ArrayList<Control>(); controls.add(authV1Control); CompareOperation compareOperation = new CompareOperation(proxyUserConn, CompareOperationBasis compareOperation = new CompareOperationBasis( proxyUserConn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, @@ -518,8 +531,9 @@ List<Control> controls = new ArrayList<Control>(); controls.add(authV1Control); CompareOperation compareOperation = new CompareOperation(proxyUserConn, CompareOperationBasis compareOperation = new CompareOperationBasis( proxyUserConn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, @@ -544,8 +558,9 @@ List<Control> controls = new ArrayList<Control>(); controls.add(authV2Control); CompareOperation compareOperation = new CompareOperation(proxyUserConn, CompareOperationBasis compareOperation = new CompareOperationBasis( proxyUserConn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, @@ -570,8 +585,9 @@ List<Control> controls = new ArrayList<Control>(); controls.add(authV2Control); CompareOperation compareOperation = new CompareOperation(proxyUserConn, CompareOperationBasis compareOperation = new CompareOperationBasis( proxyUserConn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, @@ -597,8 +613,9 @@ List<Control> controls = new ArrayList<Control>(); controls.add(authV2Control); CompareOperation compareOperation = new CompareOperation(proxyUserConn, CompareOperationBasis compareOperation = new CompareOperationBasis( proxyUserConn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, @@ -625,8 +642,9 @@ new LDAPAssertionRequestControl("1.1.1.1.1.1", true, ldapFilter); List<Control> controls = new ArrayList<Control>(); controls.add(assertControl); CompareOperation compareOperation = new CompareOperation(conn, InternalClientConnection.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis( conn, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), controls, new ASN1OctetString(entry.getDN().toString()), opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxPrivilegeTestCase.java
@@ -44,7 +44,6 @@ import java.util.UUID; import org.opends.server.TestCaseUtils; import org.opends.server.admin.ClassLoaderProvider; import org.opends.server.backends.task.Task; import org.opends.server.backends.task.TaskBackend; import org.opends.server.backends.task.TaskState; @@ -53,6 +52,7 @@ import org.opends.server.core.AddOperation; import org.opends.server.core.AddOperationBasis; import org.opends.server.core.CompareOperation; import org.opends.server.core.CompareOperationBasis; import org.opends.server.core.DeleteOperation; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; @@ -1260,8 +1260,8 @@ // Test a compare operation against the PWReset Target user. CompareOperation compareOperation = new CompareOperation(conn, conn.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, targetDN, DirectoryServer.getAttributeType("cn", true), ByteStringFactory.create("PWReset Target")); @@ -1467,8 +1467,8 @@ // Test a compare operation against the PWReset Target user. CompareOperation compareOperation = new CompareOperation(conn, conn.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, targetDN, DirectoryServer.getAttributeType("cn", true), ByteStringFactory.create("PWReset Target")); opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
@@ -48,6 +48,7 @@ import org.opends.server.core.AddOperation; import org.opends.server.core.AddOperationBasis; import org.opends.server.core.CompareOperation; import org.opends.server.core.CompareOperationBasis; import org.opends.server.core.DeleteOperation; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; @@ -1319,8 +1320,8 @@ // Test a compare operation against the PWReset Target user. CompareOperation compareOperation = new CompareOperation(conn, conn.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, targetDN, DirectoryServer.getAttributeType("cn", true), ByteStringFactory.create("PWReset Target")); @@ -1524,8 +1525,8 @@ // Test a compare operation against the PWReset Target user. CompareOperation compareOperation = new CompareOperation(conn, conn.nextOperationID(), CompareOperationBasis compareOperation = new CompareOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(), controls, targetDN, DirectoryServer.getAttributeType("cn", true), ByteStringFactory.create("PWReset Target"));