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