Browse Source

improve DN username searching

Jason Rivard 5 years ago
parent
commit
6d3afefbe7

+ 24 - 0
server/src/main/java/password/pwm/ldap/search/SearchConfiguration.java

@@ -50,6 +50,9 @@ public class SearchConfiguration implements Serializable
     private transient ChaiProvider chaiProvider;
     private long searchTimeout;
 
+    @Builder.Default
+    private boolean ignoreOperationalErrors = false;
+
     @Builder.Default
     private boolean enableValueEscaping = true;
 
@@ -59,6 +62,27 @@ public class SearchConfiguration implements Serializable
     @Builder.Default
     private boolean enableSplitWhitespace = false;
 
+    @Builder.Default
+    private SearchScope searchScope = SearchScope.subtree;
+
+    public enum SearchScope
+    {
+        base( com.novell.ldapchai.provider.SearchScope.BASE ),
+        subtree( com.novell.ldapchai.provider.SearchScope.SUBTREE ),;
+
+        private final com.novell.ldapchai.provider.SearchScope chaiSearchScope;
+
+        SearchScope( final com.novell.ldapchai.provider.SearchScope chaiSearchScope )
+        {
+            this.chaiSearchScope = chaiSearchScope;
+        }
+
+        public com.novell.ldapchai.provider.SearchScope getChaiSearchScope()
+        {
+            return chaiSearchScope;
+        }
+    }
+
     void validate( )
     {
         if ( this.username != null && this.formValues != null )

+ 34 - 27
server/src/main/java/password/pwm/ldap/search/UserSearchEngine.java

@@ -181,7 +181,7 @@ public class UserSearchEngine implements PwmService
             //see if we need to do a contextless search.
             if ( checkIfStringIsDN( username, sessionLabel ) )
             {
-                return resolveUserDN( username );
+                return resolveUserDN( username, sessionLabel );
             }
             else
             {
@@ -207,10 +207,6 @@ public class UserSearchEngine implements PwmService
                     e.getErrorInformation().getFieldValues() )
             );
         }
-        catch ( final ChaiUnavailableException e )
-        {
-            throw PwmUnrecoverableException.fromChaiException( e );
-        }
     }
 
     public UserIdentity performSingleUserSearch(
@@ -450,6 +446,8 @@ public class UserSearchEngine implements PwmService
                     .sessionLabel( sessionLabel )
                     .searchID( searchID )
                     .jobId( jobIncrementer.next() )
+                    .searchScope( searchConfiguration.getSearchScope() )
+                    .ignoreOperationalErrors( searchConfiguration.isIgnoreOperationalErrors() )
                     .build();
             final UserSearchJob userSearchJob = new UserSearchJob( pwmApplication, this, userSearchJobParameters );
             returnMap.add( userSearchJob );
@@ -574,30 +572,38 @@ public class UserSearchEngine implements PwmService
         return false;
     }
 
-
     private UserIdentity resolveUserDN(
-            final String userDN
+            final String userDN,
+            final SessionLabel sessionLabel
     )
-            throws PwmUnrecoverableException, ChaiUnavailableException, PwmOperationalException
+            throws PwmUnrecoverableException, PwmOperationalException
     {
-        final Collection<LdapProfile> ldapProfiles = pwmApplication.getConfig().getLdapProfiles().values();
-        for ( final LdapProfile ldapProfile : ldapProfiles )
+        LOGGER.trace( sessionLabel, () -> "finding profile for userDN " + userDN );
+        final SearchConfiguration searchConfiguration = SearchConfiguration.builder()
+                .filter( "(objectClass=*)" )
+                .enableContextValidation( false )
+                .contexts( Collections.singletonList( userDN ) )
+                .searchScope( SearchConfiguration.SearchScope.base )
+                .ignoreOperationalErrors( true )
+                .build();
+        final Map<UserIdentity, Map<String, String>> results = performMultiUserSearch(
+                searchConfiguration,
+                1,
+                Collections.singleton( "objectClass" ),
+                sessionLabel );
+
+        if ( results.size() < 1 )
         {
-            final ChaiProvider provider = pwmApplication.getProxyChaiProvider( ldapProfile.getIdentifier() );
-            final ChaiUser user = provider.getEntryFactory().newChaiUser( userDN );
-            if ( user.exists() )
-            {
-                try
-                {
-                    return new UserIdentity( user.readCanonicalDN(), ldapProfile.getIdentifier() );
-                }
-                catch ( final ChaiOperationException e )
-                {
-                    LOGGER.error( () -> "unexpected error reading canonical userDN for '" + userDN + "', error: " + e.getMessage() );
-                }
-            }
+            throw new PwmOperationalException( new ErrorInformation( PwmError.ERROR_CANT_MATCH_USER ) );
         }
-        throw new PwmOperationalException( new ErrorInformation( PwmError.ERROR_CANT_MATCH_USER ) );
+        else if ( results.size() > 1 )
+        {
+            throw new PwmOperationalException( new ErrorInformation( PwmError.ERROR_CANT_MATCH_USER, "duplicate DN matches discovered" ) );
+        }
+
+        final UserIdentity userIdentity = results.keySet().iterator().next();
+        validateSpecifiedContext( userIdentity.getLdapProfile( pwmApplication.getConfig() ), userIdentity.getUserDN() );
+        return userIdentity;
     }
 
     private Map<UserIdentity, Map<String, String>> executeSearchJobs(
@@ -671,7 +677,7 @@ public class UserSearchEngine implements PwmService
     }
 
     private Map<UserIdentity, Map<String, String>> aggregateJobResults(
-          final Collection<UserSearchJob> userSearchJobs
+            final Collection<UserSearchJob> userSearchJobs
     )
             throws PwmUnrecoverableException
     {
@@ -800,11 +806,12 @@ public class UserSearchEngine implements PwmService
             final int maxThreads = Integer.parseInt( configuration.readAppProperty( AppProperty.LDAP_SEARCH_PARALLEL_THREAD_MAX ) );
             final int threads = Math.min( maxThreads, ( endPoints ) * factor );
             final ThreadFactory threadFactory = PwmScheduler.makePwmThreadFactory( PwmScheduler.makeThreadName( pwmApplication, UserSearchEngine.class ), true );
+            final int minThreads = JavaHelper.rangeCheck( 1, 10, endPoints );
 
-            LOGGER.trace( () -> "initialized with " + threads + " max threads" );
+            LOGGER.trace( () -> "initialized with threads min=" + minThreads + " max=" + threads );
 
             return new ThreadPoolExecutor(
-                    1,
+                    minThreads,
                     threads,
                     1,
                     TimeUnit.MINUTES,

+ 9 - 4
server/src/main/java/password/pwm/ldap/search/UserSearchJob.java

@@ -69,6 +69,8 @@ class UserSearchJob implements Callable<Map<UserIdentity, Map<String, String>>>
         searchHelper.setFilter( userSearchJobParameters.getSearchFilter() );
         searchHelper.setAttributes( userSearchJobParameters.getReturnAttributes() );
         searchHelper.setTimeLimit( ( int ) userSearchJobParameters.getTimeoutMs() );
+        searchHelper.setSearchScope( userSearchJobParameters.getSearchScope().getChaiSearchScope() );
+
 
         final String debugInfo;
         {
@@ -86,10 +88,10 @@ class UserSearchJob implements Callable<Map<UserIdentity, Map<String, String>>>
                         + debugInfo );
 
         final Instant startTime = Instant.now();
-        final Map<String, Map<String, String>> results;
+        final Map<String, Map<String, String>> results = new LinkedHashMap<>();
         try
         {
-            results = userSearchJobParameters.getChaiProvider().search( userSearchJobParameters.getContext(), searchHelper );
+            results.putAll( userSearchJobParameters.getChaiProvider().search( userSearchJobParameters.getContext(), searchHelper ) );
         }
         catch ( final ChaiUnavailableException e )
         {
@@ -97,8 +99,11 @@ class UserSearchJob implements Callable<Map<UserIdentity, Map<String, String>>>
         }
         catch ( final ChaiOperationException e )
         {
-            throw new PwmOperationalException( PwmError.forChaiError( e.getErrorCode() ), "ldap error during searchID="
-                    + userSearchJobParameters.getSearchID() + ", context=" + userSearchJobParameters.getContext() + ", error=" + e.getMessage() );
+            if ( !userSearchJobParameters.isIgnoreOperationalErrors() )
+            {
+                throw new PwmOperationalException( PwmError.forChaiError( e.getErrorCode() ), "ldap error during searchID="
+                        + userSearchJobParameters.getSearchID() + ", context=" + userSearchJobParameters.getContext() + ", error=" + e.getMessage() );
+            }
         }
 
         final TimeDuration searchDuration = TimeDuration.fromCurrent( startTime );

+ 2 - 0
server/src/main/java/password/pwm/ldap/search/UserSearchJobParameters.java

@@ -42,4 +42,6 @@ public class UserSearchJobParameters
     private final SessionLabel sessionLabel;
     private final int searchID;
     private final int jobId;
+    private final SearchConfiguration.SearchScope searchScope;
+    private final boolean ignoreOperationalErrors;
 }