001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *  http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.directory.server.integ;
020
021
022import java.util.Hashtable;
023
024import javax.naming.Context;
025import javax.naming.NamingException;
026import javax.naming.ldap.InitialLdapContext;
027import javax.naming.ldap.LdapContext;
028
029import org.apache.directory.api.ldap.model.exception.LdapException;
030import org.apache.directory.api.ldap.model.message.Control;
031import org.apache.directory.api.ldap.util.JndiUtils;
032import org.apache.directory.api.util.Network;
033import org.apache.directory.ldap.client.api.LdapConnection;
034import org.apache.directory.ldap.client.api.LdapNetworkConnection;
035import org.apache.directory.server.constants.ServerDNConstants;
036import org.apache.directory.server.core.api.DirectoryService;
037import org.apache.directory.server.core.integ.IntegrationUtils;
038import org.apache.directory.server.ldap.LdapServer;
039import org.slf4j.Logger;
040import org.slf4j.LoggerFactory;
041
042import netscape.ldap.LDAPConnection;
043import netscape.ldap.LDAPException;
044
045
046public class ServerIntegrationUtils extends IntegrationUtils
047{
048    /** The class logger */
049    private static final Logger LOG = LoggerFactory.getLogger( ServerIntegrationUtils.class );
050    private static final String CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
051
052    private static final int DEFAULT_PORT = 10389;
053    private static final String DEFAULT_ADMIN = ServerDNConstants.ADMIN_SYSTEM_DN;
054    private static final String DEFAULT_PASSWORD = "secret";
055    
056    
057    private static Hashtable<String, Object> setDefaultJNDIEnv( String factoryName, LdapServer ldapServer )
058    {
059        Hashtable<String, Object> env = new Hashtable<String, Object>();
060        
061        env.put( DirectoryService.JNDI_KEY, ldapServer.getDirectoryService() );
062        env.put( Context.PROVIDER_URL, Network.ldapLoopbackUrl( ldapServer.getPort() ) );
063        env.put( Context.SECURITY_PRINCIPAL,  ServerDNConstants.ADMIN_SYSTEM_DN );
064        env.put( Context.SECURITY_CREDENTIALS, "secret" );
065        env.put( Context.SECURITY_AUTHENTICATION, "simple" );
066        env.put( Context.INITIAL_CONTEXT_FACTORY, factoryName );
067
068        return env;
069    }
070    
071
072    /**
073     * Creates a JNDI LdapContext with a connection over the wire using the 
074     * SUN LDAP provider.  The connection is made using the administrative 
075     * user as the principalDN.  The context is to the rootDSE.
076     *
077     * @param ldapServer the LDAP server to get the connection to
078     * @return an LdapContext as the administrative user to the RootDSE
079     * @throws NamingException if there are problems creating the context
080     */
081    public static LdapContext getWiredContext( LdapServer ldapServer ) throws NamingException
082    {
083        return getWiredContext( ldapServer, null );
084    }
085
086
087    /**
088     * Creates a JNDI LdapContext with a connection over the wire using the 
089     * SUN LDAP provider.  The connection is made using the administrative 
090     * user as the principalDN.  The context is to the rootDSE.
091     *
092     * @param ldapServer the LDAP server to get the connection to
093     * @param principalDn The user to use for authentication
094     * @param password The user's password
095     * @return an LdapContext as the administrative user to the RootDSE
096     * @throws NamingException if there are problems creating the context
097     */
098    public static LdapContext getWiredContext( LdapServer ldapServer, String principalDn, String password )
099        throws NamingException
100    {
101        LOG.debug( "Creating a wired context to local LDAP server on port {}", ldapServer.getPort() );
102        Hashtable<String, Object> env = setDefaultJNDIEnv( CTX_FACTORY, ldapServer );
103        env.put( Context.SECURITY_PRINCIPAL, principalDn );
104        env.put( Context.SECURITY_CREDENTIALS, password );
105
106        return new InitialLdapContext( env, null );
107    }
108
109
110    /**
111     * Creates a JNDI LdapContext with a connection over the wire using the 
112     * SUN LDAP provider.  The connection is made using the administrative 
113     * user as the principalDN.  The context is to the rootDSE.
114     *
115     * @param ldapServer the LDAP server to get the connection to
116     * @param controls The controls to use
117     * @return an LdapContext as the administrative user to the RootDSE
118     * @throws NamingException if there are problems creating the context
119     */
120    public static LdapContext getWiredContext( LdapServer ldapServer, Control[] controls ) throws NamingException
121    {
122        LOG.debug( "Creating a wired context to local LDAP server on port {}", ldapServer.getPort() );
123        Hashtable<String, Object> env = setDefaultJNDIEnv( CTX_FACTORY, ldapServer );
124        javax.naming.ldap.Control[] jndiControls;
125        
126        try
127        {
128            jndiControls = JndiUtils.toJndiControls( ldapServer.getDirectoryService().getLdapCodecService(), controls );
129        }
130        catch ( org.apache.directory.api.asn1.EncoderException ee )
131        {
132            throw new NamingException( ee.getMessage() );
133        }
134        
135        return new InitialLdapContext( env, jndiControls );
136    }
137
138
139    /**
140     * Creates a JNDI LdapContext with a connection over the wire using the 
141     * SUN LDAP provider.  The connection is made using the administrative 
142     * user as the principalDN.  The context is to the rootDSE.
143     *
144     * @param ldapServer the LDAP server to get the connection to
145     * @return an LdapContext as the administrative user to the RootDSE
146     * @throws NamingException if there are problems creating the context
147     */
148    public static LdapContext getWiredContextThrowOnRefferal( LdapServer ldapServer ) throws NamingException
149    {
150        LOG.debug( "Creating a wired context to local LDAP server on port {}", ldapServer.getPort() );
151        Hashtable<String, Object> env = setDefaultJNDIEnv( CTX_FACTORY, ldapServer );
152        env.put( Context.REFERRAL, "throw" );
153        
154        return new InitialLdapContext( env, null );
155    }
156
157
158    /**
159     * Creates a JNDI LdapContext with a connection over the wire using the 
160     * SUN LDAP provider.  The connection is made using the administrative 
161     * user as the principalDN.  The context is to the rootDSE.
162     *
163     * @param ldapServer the LDAP server to get the connection to
164     * @return an LdapContext as the administrative user to the RootDSE
165     * @throws NamingException if there are problems creating the context
166     */
167    public static LdapContext getWiredContextRefferalIgnore( LdapServer ldapServer ) throws NamingException
168    {
169        LOG.debug( "Creating a wired context to local LDAP server on port {}", ldapServer.getPort() );
170        Hashtable<String, Object> env = setDefaultJNDIEnv( CTX_FACTORY, ldapServer );
171        env.put( Context.REFERRAL, "ignore" );
172        
173        return new InitialLdapContext( env, null );
174    }
175
176
177    /**
178     * Creates a JNDI LdapContext with a connection over the wire using the 
179     * SUN LDAP provider.  The connection is made using the administrative 
180     * user as the principalDN.  The context is to the rootDSE.
181     *
182     * @param ldapServer the LDAP server to get the connection to
183     * @return an LdapContext as the administrative user to the RootDSE
184     * @throws NamingException if there are problems creating the context
185     */
186    public static LdapContext getWiredContextFollowOnRefferal( LdapServer ldapServer ) throws NamingException
187    {
188        LOG.debug( "Creating a wired context to local LDAP server on port {}", ldapServer.getPort() );
189        Hashtable<String, Object> env = setDefaultJNDIEnv( CTX_FACTORY, ldapServer );
190        env.put( Context.REFERRAL, "follow" );
191        
192        return new InitialLdapContext( env, null );
193    }
194
195
196    public static LdapConnection getWiredConnection( LdapServer ldapServer ) throws LdapException
197    {
198        String testServer = System.getProperty( "ldap.test.server", null );
199
200        if ( testServer == null )
201        {
202            return getWiredConnection( ldapServer, ServerDNConstants.ADMIN_SYSTEM_DN, "secret" );
203        }
204
205        LOG.debug( "ldap.test.server = {}", testServer );
206
207        String admin = System.getProperty( testServer + ".admin", DEFAULT_ADMIN );
208        LOG.debug( "{}.admin = {}", testServer, admin );
209
210        String password = System.getProperty( testServer + ".password", DEFAULT_PASSWORD );
211        LOG.debug( "{}.password = {}", testServer, password );
212
213        String host = System.getProperty( testServer + ".host", Network.LOOPBACK_HOSTNAME );
214        LOG.debug( "{}.host = {}", testServer, host );
215
216        int port = Integer.parseInt( System.getProperty( testServer + ".port", Integer.toString( DEFAULT_PORT ) ) );
217        LOG.debug( "{}.port = {}", testServer, port );
218
219        LdapConnection conn = new LdapNetworkConnection( host, port );
220        conn.bind( admin, password );
221
222        return conn;
223    }
224
225
226    public static LDAPConnection getNsdkWiredConnection( LdapServer ldapServer ) throws LDAPException
227    {
228        String testServer = System.getProperty( "ldap.test.server", null );
229
230        if ( testServer == null )
231        {
232            return getNsdkWiredConnection( ldapServer, ServerDNConstants.ADMIN_SYSTEM_DN, "secret" );
233        }
234
235        LOG.debug( "ldap.test.server = {}", testServer );
236
237        String admin = System.getProperty( testServer + ".admin", DEFAULT_ADMIN );
238        LOG.debug( "{}.admin = {}", testServer, admin );
239
240        String password = System.getProperty( testServer + ".password", DEFAULT_PASSWORD );
241        LOG.debug( "{}.password = {}", testServer, password );
242
243        String host = System.getProperty( testServer + ".host", Network.LOOPBACK_HOSTNAME );
244        LOG.debug( "{}.host = {}", testServer, host );
245
246        int port = Integer.parseInt( System.getProperty( testServer + ".port", Integer.toString( DEFAULT_PORT ) ) );
247        LOG.debug( "{}.port = {}", testServer, port );
248
249        LDAPConnection conn = new LDAPConnection();
250        conn.connect( 3, host, port, admin, password );
251
252        return conn;
253    }
254
255
256    /**
257     * Gets a LDAP connection instance on a server, authenticating a user.
258     * 
259     * @param ldapServer The server we want to connect to
260     * @param principalDn The user's DN
261     * @param password The user's password
262     * @return A LdapConnection instance if we got one
263     * @throws LdapException If the connection cannot be created
264     */
265    public static LdapConnection getWiredConnection( LdapServer ldapServer, String principalDn, String password )
266        throws LdapException
267    {
268        LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() );
269        connection.bind( principalDn, password );
270
271        return connection;
272    }
273
274
275    /**
276     * Gets a LDAP connection instance on a server. We won't bind on the server.
277     * 
278     * @param ldapServer The server we want to connect to
279     * @return A LdapConnection instance if we got one
280     * @throws LdapException If the connection cannot be created
281     */
282    public static LdapConnection getLdapConnection( LdapServer ldapServer )
283    {
284        return new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() );
285    }
286
287
288    /**
289     * Gets a LDAP connection instance on a server, authenticating a user.
290     * 
291     * @param ldapServer The server we want to connect to
292     * @param principalDn The user's DN
293     * @param password The user's password
294     * @return A LdapConnection instance if we got one
295     * @throws LDAPException If the connection cannot be created
296     */
297    public static LDAPConnection getNsdkWiredConnection( LdapServer ldapServer, String principalDn, String password )
298        throws LDAPException
299    {
300        LDAPConnection connection = new LDAPConnection();
301        connection.connect( 3, Network.LOOPBACK_HOSTNAME, ldapServer.getPort(), principalDn, password );
302
303        return connection;
304    }
305
306
307    /**
308     * Gets a LDAP connection instance on a server. We will bind as Admin
309     * 
310     * @param ldapServer The server we want to connect to
311     * @return A LdapConnection instance if we got one
312     * @throws LdapException If the connection cannot be created
313     */
314    public static LdapConnection getAdminConnection( LdapServer ldapServer ) throws LdapException
315    {
316        LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() );
317        connection.bind( ServerDNConstants.ADMIN_SYSTEM_DN, "secret" );
318
319        return connection;
320    }
321}