1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server;
18  
19  
20  import org.apache.ldap.server.configuration.MutableDirectoryPartitionConfiguration;
21  import org.apache.ldap.common.util.EmptyEnumeration;
22  
23  import java.util.Hashtable;
24  import java.util.Set;
25  import java.util.HashSet;
26  import java.util.Collections;
27  
28  import javax.naming.Context;
29  import javax.naming.InitialContext;
30  import javax.naming.NoPermissionException;
31  import javax.naming.NamingEnumeration;
32  import javax.naming.directory.*;
33  
34  
35  /***
36   * A set of miscellanous tests.
37   *
38   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39   * @version $Rev: 328979 $
40   */
41  public class MiscTest extends AbstractServerTest
42  {
43      /***
44       * Cleans up old database files on creation.
45       */
46      public MiscTest()
47      {
48      }
49  
50  
51      /***
52       * Customizes setup for each test case.
53       *
54       * @throws Exception
55       */
56      public void setUp() throws Exception
57      {
58          if ( this.getName().equals( "testDisableAnonymousBinds" ) )
59          {
60              configuration.setAllowAnonymousAccess( false );
61          }
62          else if ( this.getName().equals( "testEnableAnonymousBindsOnRootDSE" ) )
63          {
64              configuration.setAllowAnonymousAccess( false );
65          }
66          else if ( this.getName().equals( "testUserAuthOnMixedCaseSuffix" ) )
67          {
68              Set partitions = new HashSet();
69              partitions.addAll( configuration.getContextPartitionConfigurations() );
70              MutableDirectoryPartitionConfiguration partition = new MutableDirectoryPartitionConfiguration();
71              partition.setSuffix( "dc=aPache,dc=org" );
72              Attributes entry = new BasicAttributes( "dc", "aPache", true );
73              Attribute oc = new BasicAttribute( "objectClass" );
74              entry.put( oc );
75              oc.add( "top" );
76              oc.add( "domain" );
77              partition.setName( "apache" );
78              partition.setContextEntry( entry );
79              partition.setIndexedAttributes( Collections.singleton( "dc" ) );
80              partitions.add( partition );
81              configuration.setContextPartitionConfigurations( partitions );
82  	}
83          else if ( this.getName().equals( "testAnonymousBindsEnabledBaseSearch" ) )
84          {
85              // allow anonymous access
86              configuration.setAllowAnonymousAccess( true );
87              
88              // create a partition to search
89              Set partitions = new HashSet();
90              partitions.addAll( configuration.getContextPartitionConfigurations() );
91              MutableDirectoryPartitionConfiguration partition = new MutableDirectoryPartitionConfiguration();
92              partition.setSuffix( "dc=apache,dc=org" );
93              Attributes entry = new BasicAttributes( "dc", "apache", true );
94              Attribute oc = new BasicAttribute( "objectClass" );
95              entry.put( oc );
96              oc.add( "top" );
97              oc.add( "domain" );
98              partition.setName( "apache" );
99              partition.setContextEntry( entry );
100             partition.setIndexedAttributes( Collections.singleton( "dc" ) );
101             partitions.add( partition );
102             configuration.setContextPartitionConfigurations( partitions );
103         }
104  
105 
106         super.setUp();
107     }
108 
109 
110     /***
111      * Test to make sure anonymous binds are disabled when going through
112      * the wire protocol.
113      *
114      * @throws Exception if anything goes wrong
115      */
116     public void testDisableAnonymousBinds() throws Exception
117     {
118         // Use the SUN JNDI provider to hit server port and bind as anonymous
119 
120         final Hashtable env = new Hashtable();
121 
122         env.put( Context.PROVIDER_URL, "ldap://localhost:" + port + "/ou=system" );
123         env.put( Context.SECURITY_AUTHENTICATION, "none" );
124         env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
125 
126         InitialDirContext ic = new InitialDirContext( env );
127         try
128         {
129             ic.search( "", "(objectClass=*)", new SearchControls() );
130             fail( "If anonymous binds are disabled we should never get here!" );
131         }
132         catch ( NoPermissionException e )
133         {
134         }
135 
136         Attributes attrs = new BasicAttributes( true );
137         Attribute oc = new BasicAttribute( "objectClass" );
138         attrs.put( oc );
139         oc.add( "top" );
140         oc.add( "organizationalUnit" );
141 
142         try
143         {
144             ic.createSubcontext( "ou=blah", attrs );
145         }
146         catch( NoPermissionException e )
147         {
148         }
149     }
150 
151 
152     /***
153      * Test to make sure anonymous binds are allowed on the RootDSE even when disabled
154      * in general when going through the wire protocol.
155      *
156      * @throws Exception if anything goes wrong
157      */
158     public void testEnableAnonymousBindsOnRootDSE() throws Exception
159     {
160         // Use the SUN JNDI provider to hit server port and bind as anonymous
161 
162         final Hashtable env = new Hashtable();
163 
164         env.put( Context.PROVIDER_URL, "ldap://localhost:" + port + "/" );
165         env.put( Context.SECURITY_AUTHENTICATION, "none" );
166         env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
167 
168         InitialDirContext ctx = new InitialDirContext( env );
169         SearchControls cons = new SearchControls();
170         cons.setSearchScope( SearchControls.OBJECT_SCOPE );
171         NamingEnumeration list = ctx.search( "", "(objectClass=*)", cons );
172         SearchResult result = null;
173         if ( list.hasMore() )
174         {
175             result = ( SearchResult ) list.next();
176         }
177         assertFalse( list.hasMore() );
178         list.close();
179 
180         assertNotNull( result );
181         assertEquals( "", result.getName().trim() );
182     }
183 
184     /***
185      * Test to make sure that if anonymous binds are allowed a user may search 
186      * within a a partition.
187      *
188      * @throws Exception if anything goes wrong
189      */
190     public void testAnonymousBindsEnabledBaseSearch() throws Exception
191     {
192         // Use the SUN JNDI provider to hit server port and bind as anonymous
193 
194         final Hashtable env = new Hashtable();
195 
196         env.put( Context.PROVIDER_URL, "ldap://localhost:" + port + "/" );
197         env.put( Context.SECURITY_AUTHENTICATION, "none" );
198         env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
199 
200         InitialDirContext ctx = new InitialDirContext( env );
201         SearchControls cons = new SearchControls();
202         cons.setSearchScope( SearchControls.OBJECT_SCOPE );
203         NamingEnumeration list = ctx.search( "dc=apache,dc=org", "(objectClass=*)", cons );
204         SearchResult result = null;
205         if ( list.hasMore() )
206         {
207             result = ( SearchResult ) list.next();
208         }
209         assertFalse( list.hasMore() );
210         list.close();
211 
212         assertNotNull( result );
213         assertNotNull( result.getAttributes().get("dc") );
214     }
215 
216     /***
217      * Reproduces the problem with
218      * <a href="http://issues.apache.org/jira/browse/DIREVE-239">DIREVE-239</a>.
219      *
220      * @throws Exception if anything goes wrong
221      */
222     public void testAdminAccessBug() throws Exception
223     {
224         // Use the SUN JNDI provider to hit server port and bind as anonymous
225 
226         final Hashtable env = new Hashtable();
227 
228         env.put( Context.PROVIDER_URL, "ldap://localhost:" + port );
229         env.put("java.naming.ldap.version", "3");
230         env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
231 
232         Attributes attributes = new BasicAttributes();
233         Attribute objectClass = new BasicAttribute( "objectClass" );
234         objectClass.add( "top" );
235         objectClass.add( "organizationalUnit" );
236         attributes.put( objectClass );
237         attributes.put( "ou", "blah" );
238         InitialDirContext ctx = new InitialDirContext( env );
239         ctx.createSubcontext( "ou=blah,ou=system", attributes );
240         SearchControls controls = new SearchControls();
241         controls.setSearchScope( SearchControls.OBJECT_SCOPE );
242         controls.setReturningAttributes( new String[] { "+" } );
243         NamingEnumeration list = ctx.search( "ou=blah,ou=system", "(objectClass=*)", controls );
244         SearchResult result = ( SearchResult ) list.next();
245         list.close();
246         Attribute creatorsName = result.getAttributes().get( "creatorsName" );
247         assertEquals( "", creatorsName.get() );
248     }
249 
250 
251     /***
252      * Test case for <a href="http://issues.apache.org/jira/browse/DIREVE-284" where users in
253      * mixed case partitions were not able to authenticate properly.  This test case creates
254      * a new partition under dc=aPache,dc=org, it then creates the example user in the JIRA
255      * issue and attempts to authenticate as that user.
256      *
257      * @throws Exception if the user cannot authenticate or test fails
258      */
259     public void testUserAuthOnMixedCaseSuffix() throws Exception
260     {
261         final Hashtable env = new Hashtable();
262 
263         env.put( Context.PROVIDER_URL, "ldap://localhost:" + port + "/dc=aPache,dc=org" );
264         env.put("java.naming.ldap.version", "3");
265         env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
266         InitialDirContext ctx = new InitialDirContext( env );
267         Attributes attrs = ctx.getAttributes( "" );
268         assertTrue( attrs.get( "dc" ).get().equals( "aPache" ) );
269 
270         Attributes user = new BasicAttributes( "cn", "Kate Bush", true );
271         Attribute oc = new BasicAttribute( "objectClass" );
272         oc.add( "top" );
273         oc.add( "person" );
274         oc.add( "organizationalPerson" );
275         oc.add( "inetOrgPerson" );
276         user.put( oc );
277         user.put( "sn", "Bush" );
278         user.put( "userPassword", "Aerial" );
279         ctx.createSubcontext( "cn=Kate Bush", user );
280 
281         env.put( Context.SECURITY_AUTHENTICATION, "simple" );
282         env.put( Context.SECURITY_CREDENTIALS, "Aerial" );
283         env.put( Context.SECURITY_PRINCIPAL, "cn=Kate Bush,dc=aPache,dc=org" );
284 
285         InitialDirContext userCtx = new InitialDirContext( env );
286         assertNotNull( userCtx );
287     }
288 
289 
290     /***
291      * Tests to make sure undefined attributes in filter assertions are pruned and do not
292      * result in exceptions.
293      */
294     public void testBogusAttributeInSearchFilter() throws Exception
295     {
296         SearchControls cons = new SearchControls();
297         NamingEnumeration e = sysRoot.search( "", "(bogusAttribute=abc123)", cons );
298         assertNotNull( e );
299         assertEquals( e.getClass(), EmptyEnumeration.class );
300         e = sysRoot.search( "", "(!(bogusAttribute=abc123))", cons );
301         assertNotNull( e );
302         assertEquals( e.getClass(), EmptyEnumeration.class );
303         e = sysRoot.search( "", "(& (bogusAttribute=abc123)(bogusAttribute=abc123) )", cons );
304         assertNotNull( e );
305         assertEquals( e.getClass(), EmptyEnumeration.class );
306         e = sysRoot.search( "", "(& (bogusAttribute=abc123)(ou=abc123) )", cons );
307         assertNotNull( e );
308         assertFalse( e.getClass().equals( EmptyEnumeration.class ) );
309 
310         e = sysRoot.search( "", "(OBJECTclass=*)", cons );
311         assertNotNull( e );
312         assertFalse( e.getClass().equals( EmptyEnumeration.class ) );
313 
314         e = sysRoot.search( "", "(objectclass=*)", cons );
315         assertNotNull( e );
316         assertFalse( e.getClass().equals( EmptyEnumeration.class ) );
317     }
318 }