/*
* 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
* 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
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2012-2013 ForgeRock AS
*/
/**
* Class providing some utilities to create LDAP connections using JNDI and
* to manage entries retrieved using JNDI.
*
*/
public class ConnectionUtils
{
"org.opends.connectionutils.isstarttls";
/**
* Private constructor: this class cannot be instantiated.
*/
private ConnectionUtils()
{
}
/**
* Creates a clear LDAP connection and returns the corresponding LdapContext.
* This methods uses the specified parameters to create a JNDI environment
* hashtable and creates an InitialLdapContext instance.
*
* @param ldapURL
* the target LDAP URL
* @param dn
* passed as Context.SECURITY_PRINCIPAL if not null
* @param pwd
* passed as Context.SECURITY_CREDENTIALS if not null
* @param timeout
* passed as com.sun.jndi.ldap.connect.timeout if > 0
* @param env
* null or additional environment properties
*
* @throws NamingException
* the exception thrown when instantiating InitialLdapContext
*
* @return the created InitialLdapContext.
* @see javax.naming.Context
* @see javax.naming.ldap.InitialLdapContext
*/
throws NamingException
{
{ // We clone 'env' so that we can modify it freely
} else
{
}
"com.sun.jndi.ldap.LdapCtxFactory");
if (timeout >= 1)
{
}
{
}
{
}
/* Contains the DirContext and the Exception if any */
{
public void run()
{
try
{
} catch (NamingException ne)
{
} catch (Throwable t)
{
t.printStackTrace();
pair[1] = t;
}
}
});
t.setDaemon(true);
}
/**
* Creates an LDAPS connection and returns the corresponding LdapContext.
* This method uses the TrusteSocketFactory class so that the specified
* trust manager gets called during the SSL handshake. If trust manager is
* null, certificates are not verified during SSL handshake.
*
* @param ldapsURL the target *LDAPS* URL.
* @param dn passed as Context.SECURITY_PRINCIPAL if not null.
* @param pwd passed as Context.SECURITY_CREDENTIALS if not null.
* @param timeout passed as com.sun.jndi.ldap.connect.timeout if > 0.
* @param env null or additional environment properties.
* @param trustManager null or the trust manager to be invoked during SSL
* negotiation.
* @param keyManager null or the key manager to be invoked during SSL
* negotiation.
* @return the established connection with the given parameters.
*
* @throws NamingException the exception thrown when instantiating
* InitialLdapContext.
*
* @see javax.naming.Context
* @see javax.naming.ldap.InitialLdapContext
* @see TrustedSocketFactory
*/
{ // We clone 'env' so that we can modify it freely
} else
{
}
"com.sun.jndi.ldap.LdapCtxFactory");
{
}
{
}
if (trustManager == null)
{
trustManager = new BlindTrustManager();
}
/* Contains the DirContext and the Exception if any */
public void run() {
try {
} catch (NamingException ne) {
} catch (RuntimeException re) {
}
}
});
t.setDaemon(true);
}
/**
* Clones the provided InitialLdapContext and returns a connection using
* the same parameters.
* @param ctx the connection to be cloned.
* @param timeout the timeout to establish the connection in milliseconds.
* Use {@code 0} to express no timeout.
* @param trustManager the trust manager to be used to connect.
* @param keyManager the key manager to be used to connect.
* @return the new InitialLdapContext connected to the server.
* @throws NamingException if there was an error creating the new connection.
*/
{
{
}
/* Contains the DirContext and the Exception if any */
public void run() {
try {
{
}
} catch (NamingException ne) {
} catch (RuntimeException re) {
}
}
});
}
/**
* Creates an LDAP+StartTLS connection and returns the corresponding
* LdapContext.
* This method first creates an LdapContext with anonymous bind. Then it
* requests a StartTlsRequest extended operation. The StartTlsResponse is
* setup with the specified hostname verifier. Negotiation is done using a
* TrustSocketFactory so that the specified TrustManager gets called during
* the SSL handshake.
* If trust manager is null, certificates are not checked during SSL
* handshake.
*
* @param ldapURL the target *LDAP* URL.
* @param dn passed as Context.SECURITY_PRINCIPAL if not null.
* @param pwd passed as Context.SECURITY_CREDENTIALS if not null.
* @param timeout passed as com.sun.jndi.ldap.connect.timeout if > 0.
* @param env null or additional environment properties.
* @param trustManager null or the trust manager to be invoked during SSL
* negotiation.
* @param keyManager null or the key manager to be invoked during SSL
* negotiation.
* @param verifier null or the hostname verifier to be setup in the
* StartTlsResponse.
* @return the established connection with the given parameters.
*
* @throws NamingException the exception thrown when instantiating
* InitialLdapContext.
*
* @see javax.naming.Context
* @see javax.naming.ldap.InitialLdapContext
* @see javax.naming.ldap.StartTlsRequest
* @see javax.naming.ldap.StartTlsResponse
* @see TrustedSocketFactory
*/
throws NamingException
{
if (trustManager == null)
{
trustManager = new BlindTrustManager();
}
verifier = new BlindHostnameVerifier();
}
{ // We clone 'env' to modify it freely
}
else
{
}
"com.sun.jndi.ldap.LdapCtxFactory");
/* Contains the DirContext and the Exception if any */
public void run() {
try {
new StartTlsRequest());
try
{
}
catch(IOException x) {
xx = new CommunicationException(
"Failed to negotiate Start TLS operation");
throw xx;
}
{
{
}
}
} catch (NamingException ne)
{
} catch (RuntimeException re)
{
}
}
});
t.setDaemon(true);
}
/**
* Returns the LDAP URL used in the provided InitialLdapContext.
* @param ctx the context to analyze.
* @return the LDAP URL used in the provided InitialLdapContext.
*/
{
try
{
}
catch (NamingException ne)
{
// This is really strange. Seems like a bug somewhere.
ne);
}
return s;
}
/**
* Returns the host name used in the provided InitialLdapContext.
* @param ctx the context to analyze.
* @return the host name used in the provided InitialLdapContext.
*/
{
try
{
}
catch (Throwable t)
{
// This is really strange. Seems like a bug somewhere.
}
return s;
}
/**
* Returns the port number used in the provided InitialLdapContext.
* @param ctx the context to analyze.
* @return the port number used in the provided InitialLdapContext.
*/
{
int port = -1;
try
{
}
catch (Throwable t)
{
// This is really strange. Seems like a bug somewhere.
}
return port;
}
/**
* Returns the host port representation of the server to which this
* context is connected.
* @param ctx the context to analyze.
* @return the host port representation of the server to which this
* context is connected.
*/
{
}
/**
* Returns the bind DN used in the provided InitialLdapContext.
* @param ctx the context to analyze.
* @return the bind DN used in the provided InitialLdapContext.
*/
{
try
{
}
catch (NamingException ne)
{
// This is really strange. Seems like a bug somewhere.
ne);
}
return bindDN;
}
/**
* Returns the password used in the provided InitialLdapContext.
* @param ctx the context to analyze.
* @return the password used in the provided InitialLdapContext.
*/
{
try
{
}
catch (NamingException ne)
{
// This is really strange. Seems like a bug somewhere.
ne);
}
return bindPwd;
}
/**
* Tells whether we are using SSL in the provided InitialLdapContext.
* @param ctx the context to analyze.
* @return <CODE>true</CODE> if we are using SSL and <CODE>false</CODE>
* otherwise.
*/
{
boolean isSSL = false;
try
{
}
catch (Throwable t)
{
// This is really strange. Seems like a bug somewhere.
}
return isSSL;
}
/**
* Tells whether we are using StartTLS in the provided InitialLdapContext.
* @param ctx the context to analyze.
* @return <CODE>true</CODE> if we are using StartTLS and <CODE>false</CODE>
* otherwise.
*/
{
boolean isStartTLS = false;
try
{
}
catch (NamingException ne)
{
// This is really strange. Seems like a bug somewhere.
ne);
}
return isStartTLS;
}
/**
* Method used to know if we can connect as administrator in a server with a
* given password and dn.
* @param ldapUrl the LDAP URL of the server.
* @param dn the dn to be used.
* @param pwd the password to be used.
* @param timeout the timeout to establish the connection in milliseconds.
* Use {@code 0} to express no timeout.
* @return <CODE>true</CODE> if we can connect and read the configuration and
* <CODE>false</CODE> otherwise.
*/
{
boolean canConnectAsAdministrativeUser = false;
try
{
{
null);
}
else
{
}
} catch (NamingException ne)
{
// Nothing to do.
} catch (Throwable t)
{
throw new IllegalStateException("Unexpected throwable.", t);
}
return canConnectAsAdministrativeUser;
}
/**
* Method used to know if we are connected as administrator in a server with a
* given InitialLdapContext.
* @param ctx the context.
* @return <CODE>true</CODE> if we are connected and read the configuration
* and <CODE>false</CODE> otherwise.
*/
{
boolean connectedAsAdministrativeUser = false;
try
{
/*
* Search for the config to check that it is the directory manager.
*/
try
{
{
}
}
finally
{
try
{
}
{
"Unexpected error closing enumeration on cn=Config entry", ex);
}
}
connectedAsAdministrativeUser = true;
} catch (NamingException ne)
{
// Nothing to do.
} catch (Throwable t)
{
throw new IllegalStateException("Unexpected throwable.", t);
}
return connectedAsAdministrativeUser;
}
/**
* This is just a commodity method used to try to get an InitialLdapContext.
* @param t the Thread to be used to create the InitialLdapContext.
* @param pair an Object[] array that contains the InitialLdapContext and the
* Throwable if any occurred.
* @param timeout the timeout in milliseconds. If we do not get to create the
* connection before the timeout a CommunicationException will be thrown.
* @return the created InitialLdapContext
* @throws NamingException if something goes wrong during the creation.
*/
{
try
{
if (timeout > 0)
{
t.start();
} else
{
t.run();
}
} catch (InterruptedException x)
{
// This might happen for problems in sockets
// so it does not necessarily imply a bug
}
boolean throwException = false;
{
t.interrupt();
try
{
t.join(2000);
} catch (InterruptedException x)
{
// This might happen for problems in sockets
// so it does not necessarily imply a bug
}
throwException = true;
}
{
throwException = true;
}
if (throwException)
{
throw xx;
}
{
{
{
{
throw new IllegalStateException("Unexpected throwable occurred",
}
}
}
/**
* Returns the default LDAP timeout in milliseconds when we try to connect to
* a server.
* @return the default LDAP timeout in milliseconds when we try to connect to
* a server.
*/
public static int getDefaultLDAPTimeout()
{
return DEFAULT_LDAP_CONNECT_TIMEOUT;
}
/**
* Returns the String that can be used to represent a given host name in a
* LDAP URL.
* This method must be used when we have IPv6 addresses (the address in the
* LDAP URL must be enclosed with brackets).
* @param host the host name.
* @return the String that can be used to represent a given host name in a
* LDAP URL.
*/
{
{
// Assume an IPv6 address has been specified and adds the brackets
// for the URL.
{
}
{
}
}
return host;
}
/**
* Returns the LDAP URL for the provided parameters.
* @param host the host name.
* @param port the LDAP port.
* @param useSSL whether to use SSL or not.
* @return the LDAP URL for the provided parameters.
*/
{
if (useSSL)
{
}
else
{
}
return ldapUrl;
}
/**
* Tells whether the provided Throwable was caused because of a problem with
* a certificate while trying to establish a connection.
* @param t the Throwable to analyze.
* @return <CODE>true</CODE> if the provided Throwable was caused because of a
* problem with a certificate while trying to establish a connection and
* <CODE>false</CODE> otherwise.
*/
{
boolean returnValue = false;
while (!returnValue && (t != null))
{
returnValue = (t instanceof SSLHandshakeException) ||
(t instanceof GeneralSecurityException);
t = t.getCause();
}
return returnValue;
}
/**
* Returns the String representation of the first value of an attribute in a
* LDAP entry.
* @param entry the entry.
* @param attrName the attribute name.
* @return the String representation of the first value of an attribute in a
* LDAP entry.
* @throws NamingException if there is an error processing the entry.
*/
throws NamingException
{
{
{
if (o instanceof String)
{
v = (String)o;
}
else
{
}
}
}
return v;
}
/**
* Returns a Set with the String representation of the values of an attribute
* in a LDAP entry. The returned Set will never be null.
* @param entry the entry.
* @param attrName the attribute name.
* @return a Set with the String representation of the values of an attribute
* in a LDAP entry.
* @throws NamingException if there is an error processing the entry.
*/
throws NamingException
{
{
{
{
}
}
}
return values;
}
}