src.com.novell.ldapchai.provider.ChaiSetting Maven / Gradle / Ivy
Show all versions of ldapchai Show documentation
/*
* LDAP Chai API
* Copyright (c) 2006-2017 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.novell.ldapchai.provider;
import com.novell.ldapchai.cr.Answer;
import com.novell.ldapchai.exception.ChaiRuntimeException;
import java.io.Serializable;
import java.net.URI;
/**
* All settings for LDAP Chai used by {@link ChaiConfiguration}.
*
* Each setting contains:
*
* - A key value useful in external configurations
* - A default value for the setting
* - A validator to ensure that an assocated value is syntactically correct
*
*
* @author Jason D. Rivard
* @see com.novell.ldapchai.provider.ChaiConfiguration
*/
public enum ChaiSetting
{
/**
* A list of URLs to be used for ldap connections. {@link #validateValue(String)} will be used to to ensure that
* each provided value is a valid URL.
*
* Multiple ldap URLs can be specified by separating with a comma or space character.
*
* A value that does not conform to {@link URI#create(String)} requirements or has a scheme other than "ldap" or "ldaps"
* will result in an {@link IllegalArgumentException}.
*
* LDAP URL Examples
* Examples
* ldap://192.168.10.1
* ldaps://192.168.10.2
* ldaps://192.168.10.3:6322
* ldap://host1.example.com:382
* ldap://host1.example.com,ldaps://host2.example.com,ldaps://10.8.31.1:6322
* ldaps://host1.example.com ldaps://10.8.31.1:6322
*
*
* Unless {@link #FAILOVER_ENABLE} is set to true, the use of values by a {@code ChaiProvider}
* beyond the first value is unspecified.
*
* Setting Information
* Key: chai.bind.URLs
* Default: ldap://localhost
*
*
* @see #FAILOVER_ENABLE
*/
BIND_URLS( "chai.bind.URLs", "ldap://localhost", true, ( Validator ) value ->
{
if ( value == null || value.length() < 0 )
{
throw new IllegalArgumentException( "at least one valid ldap URL is required" );
}
for ( final String s : value.split( ChaiConfiguration.LDAP_URL_SEPARATOR_REGEX_PATTERN ) )
{
final URI theURI;
try
{
// test uri
theURI = URI.create( s );
if ( !"ldap".equalsIgnoreCase( theURI.getScheme() ) && !"ldaps".equalsIgnoreCase( theURI.getScheme() ) )
{
throw new IllegalArgumentException();
}
}
catch ( IllegalArgumentException e )
{
final StringBuffer sb = new StringBuffer();
sb.append( "ldap server url \"" ).append( s );
sb.append( "\" does not have proper url syntax such as \"ldap://127.0.0.1\" or \"ldaps://ldap.example.com\" " );
sb.append( "[" ).append( e.getMessage() ).append( "]" );
throw new IllegalArgumentException( sb.toString() );
}
}
} ),
/**
* Set the bind DN to be used during connection establishment. If empty, an anonymous connection
* will be attempted. Valid values should be fully qualified ldap syntax, such as:
*
* cn=administrator,ou=container,o=Organization
*
* Setting Information
* Key: chai.bind.dn
* Default: (none)
*
*/
BIND_DN( "chai.bind.dn", "", true, null ),
/**
* Password to use during chai LDAP bind. An empty password will cause an anonymous connection
* to be used.
*
* Setting Information
* Key: chai.bind.password
* Default: (none)
*
*/
BIND_PASSWORD( "chai.bind.password", "", false, null ),
/**
* Enables ldap data caching. Calls to the provider will
* be cached and subsequent calls will be returned from memory instead of being fetched
* from the ldap server.
*
* The wrapped provider is intended for "request scope" type operations, and allows routines that make
* redundant ldap calls to be more efficient.
*
* The cache is limited in size, and beyond a specific amount of cache entries, results are moved
* to a collection using {@link java.lang.ref.WeakReference}s that are subject to garbage collection. This provides some protection
* against memory leaks.
*
* Only read operations are cached. Performing any operation which may cause a modify (such as
* {@link ChaiProvider#createEntry(String, String, java.util.Map)} or
* {@link ChaiProvider#writeStringAttribute(String, String, java.util.Set, boolean)} ) will cause
* the cache to be cleared.
*
* There are many ways for this behavior to cause problems. Enabling this setting should be done
* with caution and extensive testing.
* In particular, no cache synchronization is performed between providers, which can cause unexpected
* results if not carefully guarded against.
*
* Setting Information
* Key: chai.cache.enable
* Default: false
*
*/
CACHE_ENABLE( "chai.cache.enable", "false", true, null ),
/**
* Maximum number of cached results to retain in memory.
*
* Setting Information
* Key: chai.cache.maximumSize
* Default: 128
*
*/
CACHE_MAXIMUM_SIZE( "chai.cache.maximumSize", "128", true, Validator.INTEGER_VALIDATOR ),
/**
* Maximum amount of time to cache results.
*
* Setting Information
* Key: chai.cache.maximumAge
* Default: 1000
*
*/
CACHE_MAXIMUM_AGE( "chai.cache.maximumAge", "1000", true, Validator.INTEGER_VALIDATOR ),
/**
* Enable chai statistics. If enabled, each ChaiProvider will maintain statistics and make them
* available via {@link com.novell.ldapchai.provider.ChaiProvider#getProviderStatistics()}.
*
* Setting Information
* Key: chai.statistics.enable
* Default: true
*
*
* @see ProviderStatistics
*/
STATISTICS_ENABLE( "chai.statistics.enable", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Enable watchdog idle protection. If this value is set to "true", then the {@code ChaiProvider} will automatically
* close the ldap connection after their has been no activity for some duration of time. If another
* ldap api is called after the idle connection has caused a close, the {@code ChaiProvider} will automatically
* re-open a new connection using the originally supplied connection settings and credentials.
*
* Note that if this setting is enabled, a lightweight watchdog thread will be running for each parent {@link ChaiProviderFactory}.
* So it is best to have only a single {@code ChaiProviderFactory} instance if possible.
*
* Setting Information
* Key: chai.watchdog.enable
* Default: true
*
*/
WATCHDOG_ENABLE( "chai.watchdog.enable", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Maximum time an operation can be in progress (in ms). If this time is exceeded, the connection will
* be closed. Future ldap api's called to the ChaiProvider will attempt to re-open a new
* ldap connection.
*
* Setting Information
* Key: chai.watchdog.operationTimeout
* Default: 60000
*
*/
WATCHDOG_OPERATION_TIMEOUT( "chai.watchdog.operationTimeout", "60000", true, Validator.INTEGER_VALIDATOR ),
/**
* Maximum time a ChaiProvider can remain inactive (in ms). If this time is exceeded, the connection will
* be closed. Future methods called to the ChaiProvider will attempt to re-open a new
* ldap connection.
*
* Setting Information
* Key: chai.watchdog.idleTimeout
* Default: 30000
*
*/
WATCHDOG_IDLE_TIMEOUT( "chai.watchdog.idleTimeout", "30000", true, Validator.INTEGER_VALIDATOR ),
/**
* Maximum time a ChaiProvider can remain in use(in ms). If this time is exceeded, the connection will
* be closed and re-opened.
*
* Setting Information
* Key: chai.watchdog.maxConnectionLifetime
* Default: 30000
*
*/
WATCHDOG_MAX_CONNECTION_LIFETIME( "chai.watchdog.maxConnectionLifetime", "3300000", true, Validator.INTEGER_VALIDATOR ),
/**
* Disable watchdog timeout on providers where the bind URL's principal has its password expired.
*
* Setting Information
* Key: chai.connection.watchdog.disableIfPwExpired
* Default: 5000
*
*/
WATCHDOG_DISABLE_IF_PW_EXPIRED( "chai.watchdog.disableIfPwExpired", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Sets the Chai Provider to use a promiscuous SSL socket factory when making ldaps connections. By default
* this settings is false, which means that when making an SSL connection, the remote certificate must be
* trusted by the local JVM keystore.
*
* This setting is indented for use with development environments only, and should not be enabled for
* production usage.
*
* Setting Information
* Key: chai.connection.promiscuousSSL
* Default: false
*
*/
PROMISCUOUS_SSL( "chai.connection.promiscuousSSL", "false", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Enable wire trace debugging. This will cause all data in/out of chai to be output to the
* log4j TRACE debug level. This will generate a large volume of debug messages.
*
* WARNING: Enabling this setting will cause all data values to be output to debug mode, including
* sensitive values such as passwords. Enable this setting with care!
*
* Setting Information
* Key: chai.wireDebug.enable
* Default: false
*
*/
WIRETRACE_ENABLE( "chai.wireDebug.enable", "false", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Enable fail over when multiple servers are present. Also allows retries to a single server
* in case of connection problems.
*
* Setting Information
* Key: chai.failover.enable
* Default: true
*
*/
FAILOVER_ENABLE( "chai.failover.enable", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Indicates if the failover engine will use it's "last known good" mechanism. When a new connection is made, if
* this setting is enabled, the provider will start with the last known good server instead of the first server in
* the connection url list.
*
* Setting Information
* Key: chai.failover.useLastKnownGoodHint
* Default: true
*
*/
FAILOVER_USE_LAST_KNOWN_GOOD_HINT( "chai.failover.useLastKnownGoodHint", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Minimum time Chai will wait before retrying a server marked as down. Time is in milliseconds.
*
* Setting Information
* Key: chai.failover.failBackTime
* Default: 90000
*
*/
FAILOVER_MINIMUM_FAILBACK_TIME( "chai.failover.failBackTime", "90000", true, Validator.INTEGER_VALIDATOR ),
/**
* Minimum number of attempts Chai will make to contact a server if there is a communication problem.
*
* Setting Information
* Key: chai.failover.connectRetries
* Default: 4
*
*/
FAILOVER_CONNECT_RETRIES( "chai.failover.connectRetries", "4", true, Validator.INTEGER_VALIDATOR ),
/**
* Configure alias handling. By default, alias de-referencing is set to "never", so aliases
* are effectively ignored. Valid settings are the same as those supported by JNDI:
*
* - always
- never
- finding
- searching
* See JNDI alias
* documentation
*
* Setting Information
* Key: chai.ldap.dereferenceAliases
* Default: never
*
*/
LDAP_DEREFENCE_ALIAS( "chai.ldap.dereferenceAliases", "never", true, null ),
/**
* Ldap socket timeout, if supported by the ChaiProvider implementation. Time is in milliseconds.
*
* Setting Information
* Key: chai.ldap.ldapTimeout
* Default: 5000
*
*/
LDAP_CONNECT_TIMEOUT( "chai.ldap.ldapTimeout", "5000", true, Validator.INTEGER_VALIDATOR ),
/**
* Ldap read timeout, if supported by the ChaiProvider implementation. Time is in milliseconds.
* A value of zero will leave the default value of the implementation.
*
* Setting Information
* Key: chai.ldap.ldapReadTimeout
* Default: 5000
*
*/
LDAP_READ_TIMEOUT( "chai.ldap.ldapReadTimeout", "0", true, Validator.INTEGER_VALIDATOR ),
/**
* Enable LDAP referral following. Valid settings are "true" or "false".
*
* Setting Information
* Key: chai.ldap.followReferrals
* Default: false
*
*/
LDAP_FOLLOW_REFERRALS( "chai.ldap.followReferrals", "false", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Set the fully qualified class name of the {@code ChaiProvider} class name to be used. By default this is
* the class name for the {@link JNDIProviderImpl} class.
*
* Setting Information
* Key: chai.provider.implementation
* Default: com.novell.ldapchai.provider.JNDIProviderImpl
*
*
* @see com.novell.ldapchai.provider.JNDIProviderImpl
* @see com.novell.ldapchai.provider.JLDAPProviderImpl
* @see ApacheLdapProviderImpl
*/
PROVIDER_IMPLEMENTATION( "chai.provider.implementation", JNDIProviderImpl.class.getName(), true, null ),
/**
* Enable NMAS support for Novell eDirectory. NMAS support makes some operations more efficient,
* and provides more descriptive error messages. NMAS support requires libraries from the NMAS SDK.
*
* Setting Information
* Key: chai.edirectory.enableNMAS
* Default: false
*
*/
EDIRECTORY_ENABLE_NMAS( "chai.edirectory.enableNMAS", "false", true, Validator.ENABLE_NMAS_VALIDATOR ),
/**
* Cache failed operations due to unknown extended operations. Once an unknown extended operation for a
* given {@link ChaiProvider} occurs it will not be retried.
*
* Setting Information
* Key: chai.provider.extendedOperation.failureCache
* Default: true
*
*/
EXTENDED_OPERATION_FAILURE_CACHE( "chai.provider.extendedOperation.failureCache", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Set to read-only mode. When enabled, no "write" opertions will be permitted, and will fail with an {@link com.novell.ldapchai.exception.ChaiOperationException} of
* type {@link com.novell.ldapchai.exception.ChaiError#READ_ONLY_VIOLATION}. This error will also be occurred for operations that are only potentially "write"
* operations such s {@link ChaiProvider#extendedOperation(javax.naming.ldap.ExtendedRequest)}.
*
* Setting Information
* Key: chai.provider.readonly
* Default: false
*
*/
READONLY( "chai.provider.readonly", "false", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Specify a default directory vendor. If not empty, {@link ChaiProvider} implementations should always
* return the configured value regardless of the actual directory type when {@link ChaiProvider#getDirectoryVendor()}
* is called.
*
* The value must exactly match a known value for {@link DirectoryVendor}.
*
* Setting Information
* Key: chai.vendor.default
* Default: (none)
*
*/
DEFAULT_VENDOR( "chai.vendor.default", "", true, ( Validator ) value ->
{
if ( value == null || value.length() < 1 )
{
return;
}
for ( final DirectoryVendor vendor : DirectoryVendor.values() )
{
if ( vendor.toString().equals( value ) )
{
return;
}
}
throw new IllegalArgumentException( "value must match a known directory vendor" );
}
),
JNDI_ENABLE_POOL( "chai.provider.jndi.enablePool", "false", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Case insensitive challenge/responses. If true, the case of the responses will be ignored when tested.
*
* Setting Information
* Key: chai.crsetting.caseInsensitive
* Default: true
*
*/
CR_CASE_INSENSITIVE( "chai.crsetting.caseInsensitive", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Allow duplicate response values to be used.
*
* Setting Information
* Key: chai.crsetting.allowDuplicateResponses
* Default: false
*
*/
CR_ALLOW_DUPLICATE_RESPONSES( "chai.crsetting.allowDuplicateResponses", "false", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Default Chai CR Format Type. Must be a valid string value of {@link com.novell.ldapchai.cr.Answer.FormatType}
*
* Setting Information
* Key: chai.crsetting.defaultFormatType
* Default: SHA1_SALT
*
*/
CR_DEFAULT_FORMAT_TYPE( "chai.crsetting.defaultFormatType", Answer.FormatType.SHA1_SALT.toString(), true, Validator.BOOLEAN_VALIDATOR ),
/**
* Setting key to control the ldap attribute name used when reading/writing Chai Challenge/Response formats.
*
* Setting Information
* Key: chai.cr.chai.attributeName
* Default: carLicense
*
*
* @see com.novell.ldapchai.cr.ChaiResponseSet
* @see com.novell.ldapchai.util.ConfigObjectRecord
*/
CR_CHAI_STORAGE_ATTRIBUTE( "chai.cr.chai.attributeName", "carLicense", true, null ),
/**
* Setting key to control the {@link com.novell.ldapchai.util.ConfigObjectRecord COR}
* RecordType used when reading/writing Chai Challenge/Response formats.
*
* Setting Information
* Key: chai.cr.chai.recordId
* Default: 0002
*
*
* @see com.novell.ldapchai.cr.ChaiResponseSet
* @see com.novell.ldapchai.util.ConfigObjectRecord
*/
CR_CHAI_STORAGE_RECORD_ID( "chai.cr.chai.recordId", "0002", true, null ),
/**
* Setting key to control the number of iterations to perform the CR Salt when the
* format type is set to a hash type that allows for multiple iterations such as {@link com.novell.ldapchai.cr.Answer.FormatType#SHA1_SALT}.
*
* Setting Information
* Key: chai.cr.chai.saltCount
* Default: 1000
*
*
* @see com.novell.ldapchai.cr.ChaiResponseSet
* @see com.novell.ldapchai.util.ConfigObjectRecord
*/
CR_CHAI_SALT_COUNT( "chai.cr.chai.saltCount", "1000", true, Validator.INTEGER_VALIDATOR ),
/**
* If true, then during the {@link com.novell.ldapchai.ChaiUser#setPassword(String)} operation, the control for
* OID LDAP_SERVER_POLICY_HINTS_OID - 1.2.840.113556.1.4.2066 will be sent, causing AD to enforce password policy
* rules including history rule requirements on the operation.
*
* Setting Information
* Key: chai.ad.setPolicyHintsOnPwSet
* Default: false
*
*/
AD_SET_POLICY_HINTS_ON_PW_SET( "chai.ad.setPolicyHintsOnPwSet", "false", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Enable support for search result paging. If set to "auto" then the RootDSE will be checked to see if it
* lists OID 1.2.840.113556.1.4.319. If it does then paging will be used. Otherwise setting to true or false
* will explicitly disable LDAPChai's search result paging functionality.
*
* Setting Information
* Key: chai.ldap.paging.enable
* Default: auto
*
*/
LDAP_SEARCH_PAGING_ENABLE( "chai.ldap.paging.enable", "auto", true, Validator.AUTO_OR_BOOLEAN_VALIDATOR ),
/**
* If {@link #LDAP_SEARCH_PAGING_ENABLE} is enabled, then this setting will control the page size.
*
* Setting Information
* Key: chai.ldap.paging.size
* Default: 500
*
*/
LDAP_SEARCH_PAGING_SIZE( "chai.ldap.paging.size", "500", true, Validator.INTEGER_VALIDATOR ),
/**
* Distinguished name of the default password policy in OpenLDAP.
*
* Setting Information
* Key: chai.openldap.passwordPolicyDn
* Default: (none)
*
*/
OPENLDAP_PASSWORD_POLICY_DN( "chai.openldap.passwordPolicyDn", "", true, null ),
/**
* OpenLDAP Password Policies can be read from the local file system. This setting allows specifying the local
* file URL of the password file.
*
* Setting Information
* Key: chai.openldap.passwordPolicy.url
* Default: file:/etc/openldap/check_password.conf
*
*/
OPENLDAP_LOCAL_PASSWORD_POLICY_URL( "chai.openldap.passwordPolicy.url", "file:/etc/openldap/check_password.conf", true, null ),
/**
* Use the jndi 'resolve-in-name-space' api for canonical LDAP DN's.
*
* Setting Information
* Key: chai.jndi.resolveInNamespace
* Default: true
*
*/
JNDI_RESOLVE_IN_NAMESPACE( "chai.jndi.resolveInNamespace", "true", true, Validator.BOOLEAN_VALIDATOR ),
/**
* Set the LDAP character encoding type to use during text/binary conversions.
*
* Setting Information
* Key: chai.ldap.characterEncoding
* Default: UTF8
*
*/
LDAP_CHARACTER_ENCODING( "chai.ldap.characterEncoding", "UTF8", true, null ),;
private final String key;
private final String defaultValue;
private final boolean visible;
private final Validator validator;
/**
* For a given key, find the associated setting. If no setting matches
* the supplied key, null is returned.
*
* @param key string value of the setting's key.
* @return the setting associated witht the key, or null.
* @see #getKey()
*/
public static ChaiSetting forKey( final String key )
{
for ( final ChaiSetting setting : ChaiSetting.values() )
{
if ( setting.getKey().equals( key ) )
{
return setting;
}
}
return null;
}
ChaiSetting( final String key, final String defaultValue, final boolean visible, final Validator validator )
{
this.key = key;
this.defaultValue = defaultValue;
this.validator = validator;
this.visible = visible;
}
/**
* Returns the default value for this setting. If no other value is configured, then the
* default value is used
*
* @return the default value
*/
public String getDefaultValue()
{
return defaultValue;
}
/**
* Get the key name, suitable for use in a {@link java.util.Properties} instance.
*
* @return key name
*/
public String getKey()
{
return key;
}
boolean isVisible()
{
return this.visible;
}
/**
* Validates the syntactical structure of the value. Useful for pre-testing a value to see
* if it meets requirements.
*
* @param value the value to test
* @throws IllegalArgumentException if the value is not syntactically correct
*/
public void validateValue( final String value )
{
if ( this.validator == null )
{
return;
}
this.validator.validate( value );
}
interface Validator extends Serializable
{
void validate( String value );
Validator INTEGER_VALIDATOR = ( Validator ) value ->
{
try
{
Integer.parseInt( value );
}
catch ( Exception e )
{
throw new IllegalArgumentException( e.getMessage() );
}
};
Validator BOOLEAN_VALIDATOR = ( Validator ) value ->
{
try
{
Boolean.parseBoolean( value );
}
catch ( Exception e )
{
throw new IllegalArgumentException( e.getMessage() );
}
};
Validator AUTO_OR_BOOLEAN_VALIDATOR = ( Validator ) value ->
{
if ( !"auto".equalsIgnoreCase( value ) )
{
try
{
Boolean.parseBoolean( value );
}
catch ( Exception e )
{
throw new IllegalArgumentException( e.getMessage() );
}
}
};
Validator ENABLE_NMAS_VALIDATOR = ( Validator ) value ->
{
try
{
final boolean enableNmas = Boolean.parseBoolean( value );
if ( enableNmas )
{
try
{
Class.forName( "com.novell.security.nmas.mgmt.NMASChallengeResponse" );
}
catch ( ClassNotFoundException ex )
{
final String errorMsg = "Error: Unable to enable NMAS support. One or more classes"
+ " could not be loaded from the NMAS Toolkit. Check to make sure NMASToolkit.jar"
+ " is available on the classpath.";
throw new ChaiRuntimeException( errorMsg );
}
}
}
catch ( Exception e )
{
throw new IllegalArgumentException( e.getMessage() );
}
};
}
}