GluuFederation / oxOrm

MIT License
1 stars 1 forks source link

Custom LDAP filter does not handle NOT and Extensible search #5

Open szabix opened 3 years ago

szabix commented 3 years ago

When I want to add a custom LDAP filter to Cache Refresh on oxTrust, it results a ArrayOutOfBounds Exception. I wanted to filter out disabled accounts with the following additional filter: (!(useraccountcontrol:1.2.840.113556.1.4.803:=2))

After looking into the code of org.gluu.search.filter.Filter class, it does not handle Extensible match, unlike the com.unboundid.ldap.sdk.Filter. And the org.gluu.persist.ldap.impl.LdapFilterConverter class is not handling the NOT type correct, as it retrieves the Filter components from a field that is setting it to an empty array, than it get's the genericFilters[0], which is NULL, as the array length is 0.

Please check and fix. I've fixed as a pilot locally like this, by separating the NOT type from the AND and OR and converted the Extensive type to RAW.

`public com.unboundid.ldap.sdk.Filter convertToLdapFilter(Filter genericFilter) throws SearchException { FilterType type = genericFilter.getType();

    if ((FilterType.AND == type) || (FilterType.OR == type)) {
        Filter[] genericFilters = genericFilter.getFilters();
        com.unboundid.ldap.sdk.Filter[] ldapFilters = new com.unboundid.ldap.sdk.Filter[genericFilters.length];

        if (genericFilters != null) {
            for (int i = 0; i < genericFilters.length; i++) {
                ldapFilters[i] = convertToLdapFilter(genericFilters[i]);
            }

            if (FilterType.AND == type) {
                return com.unboundid.ldap.sdk.Filter.createANDFilter(ldapFilters);
            } else if (FilterType.OR == type) {
                return com.unboundid.ldap.sdk.Filter.createORFilter(ldapFilters);
            }
        }
    }

    if (FilterType.NOT == type) {
        return com.unboundid.ldap.sdk.Filter.createNOTFilter(convertToLdapFilter(genericFilter));
    }`

`protected Filter convertRawLdapFilterToFilterImpl(com.unboundid.ldap.sdk.Filter ldapFilter) throws SearchException { byte type = ldapFilter.getFilterType();

    if ((com.unboundid.ldap.sdk.Filter.FILTER_TYPE_AND == type) || (com.unboundid.ldap.sdk.Filter.FILTER_TYPE_OR == type)) {
        com.unboundid.ldap.sdk.Filter[] ldapFilters = ldapFilter.getComponents();
        Filter[] genericFilters = new Filter[ldapFilters.length];

        if (ldapFilters != null && ldapFilters.length > 0) {
            for (int i = 0; i < ldapFilters.length; i++) {
                genericFilters[i] = convertRawLdapFilterToFilterImpl(ldapFilters[i]);
            }

            if (com.unboundid.ldap.sdk.Filter.FILTER_TYPE_AND == type) {
                return Filter.createANDFilter(genericFilters);
            } else if (com.unboundid.ldap.sdk.Filter.FILTER_TYPE_OR == type) {
                return Filter.createORFilter(genericFilters);
            }
        }
    }

    if (com.unboundid.ldap.sdk.Filter.FILTER_TYPE_NOT == type) {
        return Filter.createNOTFilter(convertRawLdapFilterToFilterImpl(ldapFilter.getNOTComponent()));
    }

..... ..... .....

    if (com.unboundid.ldap.sdk.Filter.FILTER_TYPE_SUBSTRING == type) {
        return Filter.createSubstringFilter(ldapFilter.getAttributeName(), ldapFilter.getSubInitialString(),
                ldapFilter.getSubAnyStrings(), ldapFilter.getSubFinalString());
    }

    if (com.unboundid.ldap.sdk.Filter.FILTER_TYPE_EXTENSIBLE_MATCH == type) {
        return new Filter(FilterType.RAW, ldapFilter.toNormalizedString());
    }

    throw new SearchException(String.format("Unknown filter type '%s'", type), com.unboundid.ldap.sdk.ResultCode.PROTOCOL_ERROR_INT_VALUE);`
syserr0r commented 2 years ago

As above, in 4.4.1 CE, a custom LDAP filter of (!(userAccountControl:1.2.840.113556.1.4.803:=2)) which should work, does not, producing the following in the logs:

2022-08-30 18:51:41,411 INFO  [ForkJoinPool.commonPool-worker-5] [gluu.oxtrust.ldap.cache.service.CacheRefreshTimer] (CacheRefreshTimer.java:340) - Attempting to load entries from source server
2022-08-30 18:51:41,416 ERROR [ForkJoinPool.commonPool-worker-5] [gluu.oxtrust.ldap.cache.service.CacheRefreshTimer] (CacheRefreshTimer.java:206) - Exception happened while executing cache refresh synchronization
java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
        at org.gluu.persist.ldap.impl.LdapFilterConverter.convertRawLdapFilterToFilterImpl(LdapFilterConverter.java:116) ~[gluu-orm-ldap-4.4.1.Final.jar:?]
        at org.gluu.persist.ldap.impl.LdapFilterConverter.convertRawLdapFilterToFilter(LdapFilterConverter.java:100) ~[gluu-orm-ldap-4.4.1.Final.jar:?]
        at org.gluu.persist.ldap.impl.LdapFilterConverter$Proxy$_$$_WeldClientProxy.convertRawLdapFilterToFilter(Unknown Source) ~[gluu-orm-ldap-4.4.1.Final.jar:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshService.createFilter(CacheRefreshService.java:62) ~[classes/:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer.loadSourceServerEntriesWithoutLimits(CacheRefreshTimer.java:863) ~[classes/:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer.detectChangedEntries(CacheRefreshTimer.java:346) ~[classes/:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer.processImpl(CacheRefreshTimer.java:302) ~[classes/:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer.processInt(CacheRefreshTimer.java:201) ~[classes/:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer$Proxy$_$$_WeldSubclass.processInt(Unknown Source) ~[classes/:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer.process(CacheRefreshTimer.java:185) ~[classes/:?]
        at org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer$Proxy$_$$_WeldSubclass.process$$super(Unknown Source) ~[classes/:?]
        at jdk.internal.reflect.GeneratedMethodAccessor909.invoke(Unknown Source) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
        at org.jboss.weld.interceptor.proxy.TerminalAroundInvokeInvocationContext.proceedInternal(TerminalAroundInvokeInvocationContext.java:51) ~[weld-core-impl-3.1.9.Final.jar:3.1.9.Final]
        at org.jboss.weld.interceptor.proxy.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:78) ~[weld-core-impl-3.1.9.Final.jar:3.1.9.Final]
        at org.gluu.service.cdi.async.AsynchronousInterceptor$1.get(AsynchronousInterceptor.java:36) ~[oxcore-service-4.4.1.Final.jar:?]
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700) ~[?:?]
        at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1692) ~[?:?]
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) ~[?:?]
        at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) ~[?:?]
        at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) ~[?:?]
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) ~[?:?]
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183) ~[?:?]
nynymike commented 2 years ago

Filtering for bit fields is a pretty esoteric filter... Google turned up this article image

But I guess it should just pass throught the filter...

syserr0r commented 2 years ago

The most common use for this is with AD for filtering on account enabled/disable state, so while this might be esoteric in the unix land it is common when integrating with Windows/AD

Edit: Search for 'AD LDAP disabled filter' or similar and you'll see what I mean