Search in sources :

Example 1 with SearchResultDoneProtocolOp

use of com.unboundid.ldap.protocol.SearchResultDoneProtocolOp in project ldapsdk by pingidentity.

the class UNBOUNDIDTESTServer method run.

/**
 * Performs the processing for this server.
 */
@Override()
public void run() {
    try {
        serverSocket = new ServerSocket(0);
        listenPort = serverSocket.getLocalPort();
        while (!stopRequested.get()) {
            // Accept a connection from a client.
            clientSocket = serverSocket.accept();
            final InputStream inputStream = clientSocket.getInputStream();
            final OutputStream outputStream = clientSocket.getOutputStream();
            final ASN1StreamReader asn1Reader = new ASN1StreamReader(inputStream, 0);
            // The client must first send an UNBOUNDID-TEST bind request with no
            // credentials.
            LDAPMessage requestMessage = LDAPMessage.readFrom(asn1Reader, false);
            BindRequestProtocolOp bindRequestOp = requestMessage.getBindRequestProtocolOp();
            assertEquals(bindRequestOp.getSASLMechanism(), "UNBOUNDID-TEST");
            assertNull(bindRequestOp.getSASLCredentials());
            // Return a "SASL bind in progress" response.
            LDAPMessage responseMessage = new LDAPMessage(requestMessage.getMessageID(), new BindResponseProtocolOp(ResultCode.SASL_BIND_IN_PROGRESS_INT_VALUE, null, null, null, null));
            outputStream.write(responseMessage.encode().encode());
            outputStream.flush();
            // The next request must be an UNBOUNDID-TEST bind request with
            // credentials.  We won't do anything to validate the credentials, but
            // we will look at the third element to see what QoP the client
            // requested.
            requestMessage = LDAPMessage.readFrom(asn1Reader, false);
            bindRequestOp = requestMessage.getBindRequestProtocolOp();
            assertEquals(bindRequestOp.getSASLMechanism(), "UNBOUNDID-TEST");
            assertNotNull(bindRequestOp.getSASLCredentials());
            final ASN1Sequence credSequence = ASN1Sequence.decodeAsSequence(bindRequestOp.getSASLCredentials().getValue());
            final ASN1Element[] credElements = credSequence.elements();
            final SASLQualityOfProtection qop = SASLQualityOfProtection.forName(ASN1OctetString.decodeAsOctetString(credElements[2]).stringValue());
            assertNotNull(qop);
            final boolean qopEncode = ((qop == SASLQualityOfProtection.AUTH_INT) || (qop == SASLQualityOfProtection.AUTH_CONF));
            // Return a "success" response.  Include server SASL credentials with
            // the requested QoP.
            responseMessage = new LDAPMessage(requestMessage.getMessageID(), new BindResponseProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null, new ASN1OctetString(qop.toString())));
            outputStream.write(responseMessage.encode().encode());
            outputStream.flush();
            // request.
            if (qopEncode) {
                for (int i = 0; i < 4; i++) {
                    inputStream.read();
                }
            }
            requestMessage = LDAPMessage.readFrom(asn1Reader, false);
            final SearchRequestProtocolOp searchRequestOp = requestMessage.getSearchRequestProtocolOp();
            assertEquals(searchRequestOp.getBaseDN(), "");
            assertEquals(searchRequestOp.getScope(), SearchScope.BASE);
            assertEquals(searchRequestOp.getFilter(), Filter.createPresenceFilter("objectClass"));
            assertEquals(searchRequestOp.getAttributes(), Arrays.asList("1.1"));
            // Return a search result entry message with a DN but no attributes.
            responseMessage = new LDAPMessage(requestMessage.getMessageID(), new SearchResultEntryProtocolOp("", Collections.<Attribute>emptyList()));
            byte[] messageBytes = responseMessage.encode().encode();
            if (qopEncode) {
                // Since we know it's a tiny response, we know the length will be
                // less than 127 bytes, so we can cheat.
                outputStream.write(0);
                outputStream.write(0);
                outputStream.write(0);
                outputStream.write(messageBytes.length);
            }
            outputStream.write(messageBytes);
            outputStream.flush();
            // Return a "success" search result done message.
            responseMessage = new LDAPMessage(requestMessage.getMessageID(), new SearchResultDoneProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null));
            messageBytes = responseMessage.encode().encode();
            if (qopEncode) {
                // Since we know it's a tiny response, we know the length will be
                // less than 127 bytes, so we can cheat.
                outputStream.write(0);
                outputStream.write(0);
                outputStream.write(0);
                outputStream.write(messageBytes.length);
            }
            outputStream.write(messageBytes);
            outputStream.flush();
            // The next request should be an unbind request.
            if (qopEncode) {
                for (int i = 0; i < 4; i++) {
                    inputStream.read();
                }
            }
            requestMessage = LDAPMessage.readFrom(asn1Reader, false);
            final UnbindRequestProtocolOp unbindRequestOp = requestMessage.getUnbindRequestProtocolOp();
            // Close the connection.
            try {
                asn1Reader.close();
            } catch (final Exception e) {
            }
            try {
                outputStream.close();
            } catch (final Exception e) {
            }
            try {
                clientSocket.close();
            } catch (final Exception e) {
            }
            clientSocket = null;
        }
    } catch (final Exception e) {
        stopServer();
    }
}
Also used : ASN1OctetString(com.unboundid.asn1.ASN1OctetString) SearchRequestProtocolOp(com.unboundid.ldap.protocol.SearchRequestProtocolOp) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) SearchResultEntryProtocolOp(com.unboundid.ldap.protocol.SearchResultEntryProtocolOp) BindRequestProtocolOp(com.unboundid.ldap.protocol.BindRequestProtocolOp) ServerSocket(java.net.ServerSocket) BindResponseProtocolOp(com.unboundid.ldap.protocol.BindResponseProtocolOp) ASN1Sequence(com.unboundid.asn1.ASN1Sequence) ASN1Element(com.unboundid.asn1.ASN1Element) SearchResultDoneProtocolOp(com.unboundid.ldap.protocol.SearchResultDoneProtocolOp) ASN1StreamReader(com.unboundid.asn1.ASN1StreamReader) UnbindRequestProtocolOp(com.unboundid.ldap.protocol.UnbindRequestProtocolOp)

Example 2 with SearchResultDoneProtocolOp

use of com.unboundid.ldap.protocol.SearchResultDoneProtocolOp in project ldapsdk by pingidentity.

the class InMemoryRequestHandler method processSearchRequest.

/**
 * Attempts to process the provided search request.  The attempt will fail
 * if any of the following conditions is true:
 * <UL>
 *   <LI>There is a problem with any of the request controls.</LI>
 *   <LI>The modify DN request contains a malformed target DN, new RDN, or
 *       new superior DN.</LI>
 *   <LI>The new DN of the entry would conflict with the DN of an existing
 *       entry.</LI>
 *   <LI>The new DN of the entry would exist outside the set of defined
 *       base DNs.</LI>
 *   <LI>The new DN of the entry is not a defined base DN and does not exist
 *       immediately below an existing entry.</LI>
 * </UL>
 *
 * @param  messageID      The message ID of the LDAP message containing the
 *                        search request.
 * @param  request        The search request that was included in the LDAP
 *                        message that was received.
 * @param  controls       The set of controls included in the LDAP message.
 *                        It may be empty if there were no controls, but will
 *                        not be {@code null}.
 * @param  entryList      A list to which to add search result entries
 *                        intended for return to the client.  It must not be
 *                        {@code null}.
 * @param  referenceList  A list to which to add search result references
 *                        intended for return to the client.  It must not be
 *                        {@code null}.
 *
 * @return  The {@link LDAPMessage} containing the response to send to the
 *          client.  The protocol op in the {@code LDAPMessage} must be an
 *          {@code SearchResultDoneProtocolOp}.
 */
@NotNull()
LDAPMessage processSearchRequest(final int messageID, @NotNull final SearchRequestProtocolOp request, @NotNull final List<Control> controls, @NotNull final List<SearchResultEntry> entryList, @NotNull final List<SearchResultReference> referenceList) {
    synchronized (entryMap) {
        // Sleep before processing, if appropriate.
        final long processingStartTime = System.currentTimeMillis();
        sleepBeforeProcessing();
        // Look at the filter and see if it contains any unsupported elements.
        try {
            ensureFilterSupported(request.getFilter());
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        // Look at the time limit for the search request and see if sleeping
        // would have caused us to exceed that time limit.  It's extremely
        // unlikely that any search in the in-memory directory server would take
        // a second or more to complete, and that's the minimum time limit that
        // can be requested, so there's no need to check the time limit in most
        // cases.  However, someone may want to force a "time limit exceeded"
        // response by configuring a delay that is greater than the requested time
        // limit, so we should check now to see if that's been exceeded.
        final long timeLimitMillis = 1000L * request.getTimeLimit();
        if (timeLimitMillis > 0L) {
            final long timeLimitExpirationTime = processingStartTime + timeLimitMillis;
            if (System.currentTimeMillis() >= timeLimitExpirationTime) {
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.TIME_LIMIT_EXCEEDED_INT_VALUE, null, ERR_MEM_HANDLER_TIME_LIMIT_EXCEEDED.get(), null));
            }
        }
        // Process the provided request controls.
        final Map<String, Control> controlMap;
        try {
            controlMap = RequestControlPreProcessor.processControls(LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_REQUEST, controls);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        final ArrayList<Control> responseControls = new ArrayList<>(1);
        // If this operation type is not allowed, then reject it.
        final boolean isInternalOp = controlMap.containsKey(OID_INTERNAL_OPERATION_REQUEST_CONTROL);
        if ((!isInternalOp) && (!config.getAllowedOperationTypes().contains(OperationType.SEARCH))) {
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_NOT_ALLOWED.get(), null));
        }
        // client is authenticated.
        if ((authenticatedDN.isNullDN() && config.getAuthenticationRequiredOperationTypes().contains(OperationType.SEARCH))) {
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.INSUFFICIENT_ACCESS_RIGHTS_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_REQUIRES_AUTH.get(), null));
        }
        // Get the parsed base DN.
        final DN baseDN;
        final Schema schema = schemaRef.get();
        try {
            baseDN = new DN(request.getBaseDN(), schema);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.INVALID_DN_SYNTAX_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_MALFORMED_BASE.get(request.getBaseDN(), le.getMessage()), null));
        }
        // See if the search base or one of its superiors is a smart referral.
        final boolean hasManageDsaIT = controlMap.containsKey(ManageDsaITRequestControl.MANAGE_DSA_IT_REQUEST_OID);
        if (!hasManageDsaIT) {
            final Entry referralEntry = findNearestReferral(baseDN);
            if (referralEntry != null) {
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.REFERRAL_INT_VALUE, referralEntry.getDN(), INFO_MEM_HANDLER_REFERRAL_ENCOUNTERED.get(), getReferralURLs(baseDN, referralEntry)));
            }
        }
        // Make sure that the base entry exists.  It may be the root DSE or
        // subschema subentry.
        final Entry baseEntry;
        boolean includeChangeLog = true;
        if (baseDN.isNullDN()) {
            baseEntry = generateRootDSE();
            includeChangeLog = false;
        } else if (baseDN.equals(subschemaSubentryDN)) {
            baseEntry = subschemaSubentryRef.get();
        } else {
            baseEntry = entryMap.get(baseDN);
        }
        if (baseEntry == null) {
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.NO_SUCH_OBJECT_INT_VALUE, getMatchedDNString(baseDN), ERR_MEM_HANDLER_SEARCH_BASE_DOES_NOT_EXIST.get(request.getBaseDN()), null));
        }
        // controls.
        try {
            handleAssertionRequestControl(controlMap, baseEntry);
            handleProxiedAuthControl(controlMap);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        // Determine whether to include subentries in search results.
        final boolean includeSubEntries;
        final boolean includeNonSubEntries;
        final SearchScope scope = request.getScope();
        if (scope == SearchScope.BASE) {
            includeSubEntries = true;
            includeNonSubEntries = true;
        } else if (controlMap.containsKey(DraftLDUPSubentriesRequestControl.SUBENTRIES_REQUEST_OID)) {
            includeSubEntries = true;
            includeNonSubEntries = false;
        } else if (controlMap.containsKey(RFC3672SubentriesRequestControl.SUBENTRIES_REQUEST_OID)) {
            includeSubEntries = true;
            final RFC3672SubentriesRequestControl c = (RFC3672SubentriesRequestControl) controlMap.get(RFC3672SubentriesRequestControl.SUBENTRIES_REQUEST_OID);
            includeNonSubEntries = (!c.returnOnlySubEntries());
        } else if (baseEntry.hasObjectClass("ldapSubEntry") || baseEntry.hasObjectClass("inheritableLDAPSubEntry")) {
            includeSubEntries = true;
            includeNonSubEntries = true;
        } else if (filterIncludesLDAPSubEntry(request.getFilter())) {
            includeSubEntries = true;
            includeNonSubEntries = true;
        } else {
            includeSubEntries = false;
            includeNonSubEntries = true;
        }
        // Create a temporary list to hold all of the entries to be returned.
        // These entries will not have been pared down based on the requested
        // attributes.
        final List<Entry> fullEntryList = new ArrayList<>(entryMap.size());
        findEntriesAndRefs: {
            // Check the scope.  If it is a base-level search, then we only need to
            // examine the base entry.  Otherwise, we'll have to scan the entire
            // entry map.
            final Filter filter = request.getFilter();
            if (scope == SearchScope.BASE) {
                try {
                    if (filter.matchesEntry(baseEntry, schema)) {
                        processSearchEntry(baseEntry, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                    }
                } catch (final Exception e) {
                    Debug.debugException(e);
                }
                break findEntriesAndRefs;
            }
            // set.
            if ((scope == SearchScope.ONE) && baseDN.isNullDN()) {
                for (final DN dn : baseDNs) {
                    final Entry e = entryMap.get(dn);
                    if (e != null) {
                        try {
                            if (filter.matchesEntry(e, schema)) {
                                processSearchEntry(e, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                            }
                        } catch (final Exception ex) {
                            Debug.debugException(ex);
                        }
                    }
                }
                break findEntriesAndRefs;
            }
            // Try to use indexes to process the request.  If we can't use any
            // indexes to get a candidate list, then just iterate over all the
            // entries.  It's not necessary to consider the root DSE for non-base
            // scopes.
            final Set<DN> candidateDNs = indexSearch(filter);
            if (candidateDNs == null) {
                for (final Map.Entry<DN, ReadOnlyEntry> me : entryMap.entrySet()) {
                    final DN dn = me.getKey();
                    final Entry entry = me.getValue();
                    try {
                        if (dn.matchesBaseAndScope(baseDN, scope)) {
                            if (filter.matchesEntry(entry, schema) || (((!hasManageDsaIT) && entry.hasObjectClass("referral") && entry.hasAttribute("ref")))) {
                                processSearchEntry(entry, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                            }
                        }
                    } catch (final Exception e) {
                        Debug.debugException(e);
                    }
                }
            } else {
                for (final DN dn : candidateDNs) {
                    try {
                        if (!dn.matchesBaseAndScope(baseDN, scope)) {
                            continue;
                        }
                        final Entry entry = entryMap.get(dn);
                        if (filter.matchesEntry(entry, schema) || (((!hasManageDsaIT) && entry.hasObjectClass("referral") && entry.hasAttribute("ref")))) {
                            processSearchEntry(entry, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                        }
                    } catch (final Exception e) {
                        Debug.debugException(e);
                    }
                }
            }
        }
        // If the request included the server-side sort request control, then sort
        // the matching entries appropriately.
        final ServerSideSortRequestControl sortRequestControl = (ServerSideSortRequestControl) controlMap.get(ServerSideSortRequestControl.SERVER_SIDE_SORT_REQUEST_OID);
        if (sortRequestControl != null) {
            final EntrySorter entrySorter = new EntrySorter(false, schema, sortRequestControl.getSortKeys());
            final SortedSet<Entry> sortedEntrySet = entrySorter.sort(fullEntryList);
            fullEntryList.clear();
            fullEntryList.addAll(sortedEntrySet);
            responseControls.add(new ServerSideSortResponseControl(ResultCode.SUCCESS, null));
        }
        // If the request included the simple paged results control, then handle
        // it.
        final SimplePagedResultsControl pagedResultsControl = (SimplePagedResultsControl) controlMap.get(SimplePagedResultsControl.PAGED_RESULTS_OID);
        if (pagedResultsControl != null) {
            final int totalSize = fullEntryList.size();
            final int pageSize = pagedResultsControl.getSize();
            final ASN1OctetString cookie = pagedResultsControl.getCookie();
            final int offset;
            if ((cookie == null) || (cookie.getValueLength() == 0)) {
                // This is the first request in the series, so start at the beginning
                // of the list.
                offset = 0;
            } else {
                // offset within the result list at which to start the next batch.
                try {
                    final ASN1Integer offsetInteger = ASN1Integer.decodeAsInteger(cookie.getValue());
                    offset = offsetInteger.intValue();
                } catch (final Exception e) {
                    Debug.debugException(e);
                    return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.PROTOCOL_ERROR_INT_VALUE, null, ERR_MEM_HANDLER_MALFORMED_PAGED_RESULTS_COOKIE.get(), null), responseControls);
                }
            }
            // Create an iterator that will be used to remove entries from the
            // result set that are outside of the requested page of results.
            int pos = 0;
            final Iterator<Entry> iterator = fullEntryList.iterator();
            // offset.
            while (iterator.hasNext() && (pos < offset)) {
                iterator.next();
                iterator.remove();
                pos++;
            }
            // Next, skip over the entries that should be returned.
            int keptEntries = 0;
            while (iterator.hasNext() && (keptEntries < pageSize)) {
                iterator.next();
                pos++;
                keptEntries++;
            }
            // to include in the response.  Otherwise, use an empty cookie.
            if (iterator.hasNext()) {
                responseControls.add(new SimplePagedResultsControl(totalSize, new ASN1OctetString(new ASN1Integer(pos).encode()), false));
                while (iterator.hasNext()) {
                    iterator.next();
                    iterator.remove();
                }
            } else {
                responseControls.add(new SimplePagedResultsControl(totalSize, new ASN1OctetString(), false));
            }
        }
        // If the request includes the virtual list view request control, then
        // handle it.
        final VirtualListViewRequestControl vlvRequest = (VirtualListViewRequestControl) controlMap.get(VirtualListViewRequestControl.VIRTUAL_LIST_VIEW_REQUEST_OID);
        if (vlvRequest != null) {
            final int totalEntries = fullEntryList.size();
            final ASN1OctetString assertionValue = vlvRequest.getAssertionValue();
            // Figure out the position of the target entry in the list.
            int offset = vlvRequest.getTargetOffset();
            if (assertionValue == null) {
                // The offset is one-based, so we need to adjust it for the list's
                // zero-based offset.  Also, make sure to put it within the bounds of
                // the list.
                offset--;
                offset = Math.max(0, offset);
                offset = Math.min(fullEntryList.size(), offset);
            } else {
                final SortKey primarySortKey = sortRequestControl.getSortKeys()[0];
                final Entry testEntry = new Entry("cn=test", schema, new Attribute(primarySortKey.getAttributeName(), assertionValue));
                final EntrySorter entrySorter = new EntrySorter(false, schema, primarySortKey);
                offset = fullEntryList.size();
                for (int i = 0; i < fullEntryList.size(); i++) {
                    if (entrySorter.compare(fullEntryList.get(i), testEntry) >= 0) {
                        offset = i;
                        break;
                    }
                }
            }
            // Get the start and end positions based on the before and after counts.
            final int beforeCount = Math.max(0, vlvRequest.getBeforeCount());
            final int afterCount = Math.max(0, vlvRequest.getAfterCount());
            final int start = Math.max(0, (offset - beforeCount));
            final int end = Math.min(fullEntryList.size(), (offset + afterCount + 1));
            // Create an iterator to use to alter the list so that it only contains
            // the appropriate set of entries.
            int pos = 0;
            final Iterator<Entry> iterator = fullEntryList.iterator();
            while (iterator.hasNext()) {
                iterator.next();
                if ((pos < start) || (pos >= end)) {
                    iterator.remove();
                }
                pos++;
            }
            // Create the appropriate response control.
            responseControls.add(new VirtualListViewResponseControl((offset + 1), totalEntries, ResultCode.SUCCESS, null));
        }
        // Process the set of requested attributes so that we can pare down the
        // entries.
        final SearchEntryParer parer = new SearchEntryParer(request.getAttributes(), schema);
        final int sizeLimit;
        if (request.getSizeLimit() > 0) {
            sizeLimit = Math.min(request.getSizeLimit(), maxSizeLimit);
        } else {
            sizeLimit = maxSizeLimit;
        }
        int entryCount = 0;
        for (final Entry e : fullEntryList) {
            entryCount++;
            if (entryCount > sizeLimit) {
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.SIZE_LIMIT_EXCEEDED_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_SIZE_LIMIT_EXCEEDED.get(), null), responseControls);
            }
            final Entry trimmedEntry = parer.pareEntry(e);
            if (request.typesOnly()) {
                final Entry typesOnlyEntry = new Entry(trimmedEntry.getDN(), schema);
                for (final Attribute a : trimmedEntry.getAttributes()) {
                    typesOnlyEntry.addAttribute(new Attribute(a.getName()));
                }
                entryList.add(new SearchResultEntry(typesOnlyEntry));
            } else {
                entryList.add(new SearchResultEntry(trimmedEntry));
            }
        }
        return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null), responseControls);
    }
}
Also used : ASN1OctetString(com.unboundid.asn1.ASN1OctetString) Attribute(com.unboundid.ldap.sdk.Attribute) Schema(com.unboundid.ldap.sdk.schema.Schema) ArrayList(java.util.ArrayList) RDN(com.unboundid.ldap.sdk.RDN) DN(com.unboundid.ldap.sdk.DN) SortKey(com.unboundid.ldap.sdk.controls.SortKey) ASN1OctetString(com.unboundid.asn1.ASN1OctetString) VirtualListViewRequestControl(com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl) SubtreeDeleteRequestControl(com.unboundid.ldap.sdk.controls.SubtreeDeleteRequestControl) RFC3672SubentriesRequestControl(com.unboundid.ldap.sdk.controls.RFC3672SubentriesRequestControl) SimplePagedResultsControl(com.unboundid.ldap.sdk.controls.SimplePagedResultsControl) VirtualListViewResponseControl(com.unboundid.ldap.sdk.controls.VirtualListViewResponseControl) TransactionSpecificationRequestControl(com.unboundid.ldap.sdk.controls.TransactionSpecificationRequestControl) DraftZeilengaLDAPNoOp12RequestControl(com.unboundid.ldap.sdk.experimental.DraftZeilengaLDAPNoOp12RequestControl) PostReadRequestControl(com.unboundid.ldap.sdk.controls.PostReadRequestControl) ProxiedAuthorizationV1RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl) ServerSideSortResponseControl(com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl) PreReadResponseControl(com.unboundid.ldap.sdk.controls.PreReadResponseControl) AuthorizationIdentityResponseControl(com.unboundid.ldap.sdk.controls.AuthorizationIdentityResponseControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) AuthorizationIdentityRequestControl(com.unboundid.ldap.sdk.controls.AuthorizationIdentityRequestControl) Control(com.unboundid.ldap.sdk.Control) IgnoreNoUserModificationRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.IgnoreNoUserModificationRequestControl) ProxiedAuthorizationV2RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl) ServerSideSortRequestControl(com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl) PostReadResponseControl(com.unboundid.ldap.sdk.controls.PostReadResponseControl) DontUseCopyRequestControl(com.unboundid.ldap.sdk.controls.DontUseCopyRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) DraftLDUPSubentriesRequestControl(com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) ChangeLogEntry(com.unboundid.ldap.sdk.ChangeLogEntry) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) Entry(com.unboundid.ldap.sdk.Entry) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) SearchResultDoneProtocolOp(com.unboundid.ldap.protocol.SearchResultDoneProtocolOp) ServerSideSortResponseControl(com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl) LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) ASN1Integer(com.unboundid.asn1.ASN1Integer) LDAPException(com.unboundid.ldap.sdk.LDAPException) LDIFException(com.unboundid.ldif.LDIFException) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) ServerSideSortRequestControl(com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl) VirtualListViewResponseControl(com.unboundid.ldap.sdk.controls.VirtualListViewResponseControl) LDAPException(com.unboundid.ldap.sdk.LDAPException) RFC3672SubentriesRequestControl(com.unboundid.ldap.sdk.controls.RFC3672SubentriesRequestControl) Filter(com.unboundid.ldap.sdk.Filter) VirtualListViewRequestControl(com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl) SearchScope(com.unboundid.ldap.sdk.SearchScope) SimplePagedResultsControl(com.unboundid.ldap.sdk.controls.SimplePagedResultsControl) EntrySorter(com.unboundid.ldap.sdk.EntrySorter) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap) HashMap(java.util.HashMap) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) NotNull(com.unboundid.util.NotNull)

Example 3 with SearchResultDoneProtocolOp

use of com.unboundid.ldap.protocol.SearchResultDoneProtocolOp in project ldapsdk by pingidentity.

the class InMemoryRequestHandler method processSearchRequest.

/**
 * Attempts to process the provided search request.  The attempt will fail
 * if any of the following conditions is true:
 * <UL>
 *   <LI>There is a problem with any of the request controls.</LI>
 *   <LI>The modify DN request contains a malformed target DN, new RDN, or
 *       new superior DN.</LI>
 *   <LI>The new DN of the entry would conflict with the DN of an existing
 *       entry.</LI>
 *   <LI>The new DN of the entry would exist outside the set of defined
 *       base DNs.</LI>
 *   <LI>The new DN of the entry is not a defined base DN and does not exist
 *       immediately below an existing entry.</LI>
 * </UL>
 *
 * @param  messageID  The message ID of the LDAP message containing the search
 *                    request.
 * @param  request    The search request that was included in the LDAP message
 *                    that was received.
 * @param  controls   The set of controls included in the LDAP message.  It
 *                    may be empty if there were no controls, but will not be
 *                    {@code null}.
 *
 * @return  The {@link LDAPMessage} containing the response to send to the
 *          client.  The protocol op in the {@code LDAPMessage} must be an
 *          {@code SearchResultDoneProtocolOp}.
 */
@Override()
@NotNull()
public LDAPMessage processSearchRequest(final int messageID, @NotNull final SearchRequestProtocolOp request, @NotNull final List<Control> controls) {
    synchronized (entryMap) {
        final List<SearchResultEntry> entryList = new ArrayList<>(entryMap.size());
        final List<SearchResultReference> referenceList = new ArrayList<>(entryMap.size());
        final LDAPMessage returnMessage = processSearchRequest(messageID, request, controls, entryList, referenceList);
        for (final SearchResultEntry e : entryList) {
            try {
                connection.sendSearchResultEntry(messageID, e, e.getControls());
            } catch (final LDAPException le) {
                Debug.debugException(le);
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), le.getMatchedDN(), le.getDiagnosticMessage(), StaticUtils.toList(le.getReferralURLs())), le.getResponseControls());
            }
        }
        for (final SearchResultReference r : referenceList) {
            try {
                connection.sendSearchResultReference(messageID, new SearchResultReferenceProtocolOp(StaticUtils.toList(r.getReferralURLs())), r.getControls());
            } catch (final LDAPException le) {
                Debug.debugException(le);
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), le.getMatchedDN(), le.getDiagnosticMessage(), StaticUtils.toList(le.getReferralURLs())), le.getResponseControls());
            }
        }
        return returnMessage;
    }
}
Also used : SearchResultReferenceProtocolOp(com.unboundid.ldap.protocol.SearchResultReferenceProtocolOp) LDAPException(com.unboundid.ldap.sdk.LDAPException) ArrayList(java.util.ArrayList) LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) SearchResultDoneProtocolOp(com.unboundid.ldap.protocol.SearchResultDoneProtocolOp) SearchResultReference(com.unboundid.ldap.sdk.SearchResultReference) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) NotNull(com.unboundid.util.NotNull)

Example 4 with SearchResultDoneProtocolOp

use of com.unboundid.ldap.protocol.SearchResultDoneProtocolOp in project ldapsdk by pingidentity.

the class JSONAccessLogRequestHandler method processSearchRequest.

/**
 * {@inheritDoc}
 */
@Override()
@NotNull()
public LDAPMessage processSearchRequest(final int messageID, @NotNull final SearchRequestProtocolOp request, @NotNull final List<Control> controls) {
    final long opID = nextOperationID.getAndIncrement();
    final JSONBuffer buffer = getRequestHeader("search", opID, messageID);
    buffer.appendString("base", request.getBaseDN());
    buffer.appendNumber("scope", request.getScope().intValue());
    buffer.appendString("filter", request.getFilter().toString());
    buffer.beginArray("requested-attributes");
    for (final String requestedAttribute : request.getAttributes()) {
        buffer.appendString(requestedAttribute);
    }
    buffer.endArray();
    buffer.endObject();
    logHandler.publish(new LogRecord(Level.INFO, buffer.toString()));
    logHandler.flush();
    final AtomicLong entryCounter = new AtomicLong(0L);
    entryCounts.put(messageID, entryCounter);
    try {
        final long startTimeNanos = System.nanoTime();
        final LDAPMessage responseMessage = requestHandler.processSearchRequest(messageID, request, controls);
        final long eTimeNanos = System.nanoTime() - startTimeNanos;
        final SearchResultDoneProtocolOp protocolOp = responseMessage.getSearchResultDoneProtocolOp();
        generateResponse(buffer, "search", opID, messageID, protocolOp.getResultCode(), protocolOp.getDiagnosticMessage(), protocolOp.getMatchedDN(), protocolOp.getReferralURLs(), eTimeNanos);
        buffer.appendNumber("entries-returned", entryCounter.get());
        buffer.endObject();
        logHandler.publish(new LogRecord(Level.INFO, buffer.toString()));
        logHandler.flush();
        return responseMessage;
    } finally {
        entryCounts.remove(messageID);
    }
}
Also used : AtomicLong(java.util.concurrent.atomic.AtomicLong) LogRecord(java.util.logging.LogRecord) JSONBuffer(com.unboundid.util.json.JSONBuffer) LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) SearchResultDoneProtocolOp(com.unboundid.ldap.protocol.SearchResultDoneProtocolOp) NotNull(com.unboundid.util.NotNull)

Example 5 with SearchResultDoneProtocolOp

use of com.unboundid.ldap.protocol.SearchResultDoneProtocolOp in project ldapsdk by pingidentity.

the class LDAPListenerClientConnection method run.

/**
 * Operates in a loop, waiting for a request to arrive from the client and
 * handing it off to the request handler for processing.  This method is for
 * internal use only and must not be invoked by external callers.
 */
@InternalUseOnly()
@Override()
public void run() {
    try {
        while (true) {
            final LDAPMessage requestMessage;
            try {
                requestMessage = LDAPMessage.readFrom(asn1Reader, false);
                if (requestMessage == null) {
                    // so we won't notify the exception handler.
                    try {
                        close();
                    } catch (final IOException ioe) {
                        Debug.debugException(ioe);
                    }
                    return;
                }
            } catch (final LDAPException le) {
                // This indicates that the client sent a malformed request.
                Debug.debugException(le);
                close(le);
                return;
            }
            try {
                final int messageID = requestMessage.getMessageID();
                final List<Control> controls = requestMessage.getControls();
                LDAPMessage responseMessage;
                switch(requestMessage.getProtocolOpType()) {
                    case LDAPMessage.PROTOCOL_OP_TYPE_ABANDON_REQUEST:
                        requestHandler.processAbandonRequest(messageID, requestMessage.getAbandonRequestProtocolOp(), controls);
                        responseMessage = null;
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_ADD_REQUEST:
                        try {
                            responseMessage = requestHandler.processAddRequest(messageID, requestMessage.getAddRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new AddResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST:
                        try {
                            responseMessage = requestHandler.processBindRequest(messageID, requestMessage.getBindRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new BindResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null, null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_COMPARE_REQUEST:
                        try {
                            responseMessage = requestHandler.processCompareRequest(messageID, requestMessage.getCompareRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new CompareResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_DELETE_REQUEST:
                        try {
                            responseMessage = requestHandler.processDeleteRequest(messageID, requestMessage.getDeleteRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new DeleteResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_EXTENDED_REQUEST:
                        try {
                            responseMessage = requestHandler.processExtendedRequest(messageID, requestMessage.getExtendedRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new ExtendedResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null, null, null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST:
                        try {
                            responseMessage = requestHandler.processModifyRequest(messageID, requestMessage.getModifyRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new ModifyResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST:
                        try {
                            responseMessage = requestHandler.processModifyDNRequest(messageID, requestMessage.getModifyDNRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_REQUEST:
                        try {
                            responseMessage = requestHandler.processSearchRequest(messageID, requestMessage.getSearchRequestProtocolOp(), controls);
                        } catch (final Exception e) {
                            Debug.debugException(e);
                            responseMessage = new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.OTHER_INT_VALUE, null, ERR_CONN_REQUEST_HANDLER_FAILURE.get(StaticUtils.getExceptionMessage(e)), null));
                        }
                        break;
                    case LDAPMessage.PROTOCOL_OP_TYPE_UNBIND_REQUEST:
                        requestHandler.processUnbindRequest(messageID, requestMessage.getUnbindRequestProtocolOp(), controls);
                        close();
                        return;
                    default:
                        close(new LDAPException(ResultCode.PROTOCOL_ERROR, ERR_CONN_INVALID_PROTOCOL_OP_TYPE.get(StaticUtils.toHex(requestMessage.getProtocolOpType()))));
                        return;
                }
                if (responseMessage != null) {
                    try {
                        sendMessage(responseMessage);
                    } catch (final LDAPException le) {
                        Debug.debugException(le);
                        close(le);
                        return;
                    }
                }
            } catch (final Throwable t) {
                close(new LDAPException(ResultCode.LOCAL_ERROR, ERR_CONN_EXCEPTION_IN_REQUEST_HANDLER.get(String.valueOf(requestMessage), StaticUtils.getExceptionMessage(t))));
                StaticUtils.throwErrorOrRuntimeException(t);
            }
        }
    } finally {
        if (listener != null) {
            listener.connectionClosed(this);
        }
    }
}
Also used : ExtendedResponseProtocolOp(com.unboundid.ldap.protocol.ExtendedResponseProtocolOp) DeleteResponseProtocolOp(com.unboundid.ldap.protocol.DeleteResponseProtocolOp) LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) AddResponseProtocolOp(com.unboundid.ldap.protocol.AddResponseProtocolOp) ModifyDNResponseProtocolOp(com.unboundid.ldap.protocol.ModifyDNResponseProtocolOp) IOException(java.io.IOException) LDAPRuntimeException(com.unboundid.ldap.sdk.LDAPRuntimeException) LDAPException(com.unboundid.ldap.sdk.LDAPException) IOException(java.io.IOException) Control(com.unboundid.ldap.sdk.Control) BindResponseProtocolOp(com.unboundid.ldap.protocol.BindResponseProtocolOp) LDAPException(com.unboundid.ldap.sdk.LDAPException) SearchResultDoneProtocolOp(com.unboundid.ldap.protocol.SearchResultDoneProtocolOp) CompareResponseProtocolOp(com.unboundid.ldap.protocol.CompareResponseProtocolOp) ModifyResponseProtocolOp(com.unboundid.ldap.protocol.ModifyResponseProtocolOp) InternalUseOnly(com.unboundid.util.InternalUseOnly)

Aggregations

SearchResultDoneProtocolOp (com.unboundid.ldap.protocol.SearchResultDoneProtocolOp)13 LDAPMessage (com.unboundid.ldap.protocol.LDAPMessage)11 NotNull (com.unboundid.util.NotNull)8 ASN1OctetString (com.unboundid.asn1.ASN1OctetString)5 Control (com.unboundid.ldap.sdk.Control)5 LDAPException (com.unboundid.ldap.sdk.LDAPException)5 SearchRequestProtocolOp (com.unboundid.ldap.protocol.SearchRequestProtocolOp)4 BindResponseProtocolOp (com.unboundid.ldap.protocol.BindResponseProtocolOp)3 Attribute (com.unboundid.ldap.sdk.Attribute)3 SearchRequest (com.unboundid.ldap.sdk.SearchRequest)3 SearchResultEntry (com.unboundid.ldap.sdk.SearchResultEntry)3 ArrayList (java.util.ArrayList)3 Test (org.testng.annotations.Test)3 AddResponseProtocolOp (com.unboundid.ldap.protocol.AddResponseProtocolOp)2 BindRequestProtocolOp (com.unboundid.ldap.protocol.BindRequestProtocolOp)2 CompareResponseProtocolOp (com.unboundid.ldap.protocol.CompareResponseProtocolOp)2 DeleteResponseProtocolOp (com.unboundid.ldap.protocol.DeleteResponseProtocolOp)2 ExtendedResponseProtocolOp (com.unboundid.ldap.protocol.ExtendedResponseProtocolOp)2 ModifyDNResponseProtocolOp (com.unboundid.ldap.protocol.ModifyDNResponseProtocolOp)2 ModifyResponseProtocolOp (com.unboundid.ldap.protocol.ModifyResponseProtocolOp)2