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.authn;
18  
19  
20  import org.apache.ldap.common.exception.LdapConfigurationException;
21  import org.apache.ldap.common.exception.LdapNoPermissionException;
22  import org.apache.ldap.common.util.ArrayUtils;
23  import org.apache.ldap.server.AbstractCoreTest;
24  import org.apache.ldap.server.jndi.EnvKeys;
25  import org.apache.mina.util.AvailablePortFinder;
26  
27  import javax.naming.*;
28  import javax.naming.directory.Attribute;
29  import javax.naming.directory.Attributes;
30  import javax.naming.directory.DirContext;
31  import javax.naming.directory.InitialDirContext;
32  import javax.naming.ldap.InitialLdapContext;
33  import java.io.File;
34  import java.io.IOException;
35  import java.util.Hashtable;
36  
37  
38  /***
39   * A set of simple tests to make sure simple authentication is working as it
40   * should.
41   *
42   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
43   * @version $Rev: 165254 $
44   */
45  public class SimpleAuthenticationTest extends AbstractCoreTest
46  {
47      /***
48       * Cleans up old database files on creation.
49       * @throws IOException 
50       */
51      public SimpleAuthenticationTest() throws IOException
52      {
53          doDelete( new File( "target" + File.separator + "eve" ) );
54      }
55  
56  
57      /***
58       * Customizes setup for each test case.
59       *
60       * <ul>
61       *   <li>sets doDelete to false for test1AdminAccountCreation</li>
62       *   <li>sets doDelete to false for test2AccountExistsOnRestart</li>
63       *   <li>sets doDelete to true for all other cases</li>
64       *   <li>bypasses normal setup for test5BuildDbNoPassWithPrincAuthNone</li>
65       *   <li>bypasses normal setup for test4BuildDbNoPassNoPrincAuthNone</li>
66       *   <li>bypasses normal setup for test6BuildDbNoPassNotAdminPrinc</li>
67       * </ul>
68       *
69       * @throws Exception
70       */
71      protected void setUp() throws Exception
72      {
73          if ( getName().equals( "test1AdminAccountCreation" ) ||
74               getName().equals( "test2AccountExistsOnRestart" ) )
75          {
76              super.doDelete = false;
77          }
78          else
79          {
80              super.doDelete = true;
81          }
82  
83          if ( getName().equals( "test5BuildDbNoPassWithPrincAuthNone" ) ||
84                  getName().equals( "test6BuildDbNoPassNotAdminPrinc" ) ||
85               getName().equals( "test4BuildDbNoPassNoPrincAuthNone" ) )
86          {
87              return;
88          }
89  
90          super.setUp();
91      }
92  
93  
94      /***
95       * Checks all attributes of the admin account entry minus the userPassword
96       * attribute.
97       *
98       * @param attrs the entries attributes
99       */
100     protected void performAdminAccountChecks( Attributes attrs )
101     {
102         assertTrue( attrs.get( "objectClass" ).contains( "top" ) );
103         assertTrue( attrs.get( "objectClass" ).contains( "person" ) );
104         assertTrue( attrs.get( "objectClass" ).contains( "organizationalPerson" ) );
105         assertTrue( attrs.get( "objectClass" ).contains( "inetOrgPerson" ) );
106         assertTrue( attrs.get( "displayName" ).contains( "Directory Superuser" ) );
107     }
108 
109 
110     /***
111      * Check the creation of the admin account.
112      *
113      * @throws NamingException if there are failures
114      */
115     public void test1AdminAccountCreation() throws NamingException
116     {
117         DirContext ctx = ( DirContext ) sysRoot.lookup( "uid=admin" );
118         Attributes attrs = ctx.getAttributes( "" );
119         performAdminAccountChecks( attrs );
120         assertTrue( ArrayUtils.isEquals( attrs.get( "userPassword" ).get(), "secret".getBytes() ));
121     }
122 
123 
124     /***
125      * Check the creation of the admin account even after a restart.
126      *
127      * @throws NamingException if there are failures
128      */
129     public void test2AccountExistsOnRestart() throws NamingException
130     {
131         DirContext ctx = ( DirContext ) sysRoot.lookup( "uid=admin" );
132         Attributes attrs = ctx.getAttributes( "" );
133 
134         performAdminAccountChecks( attrs );
135         assertTrue( ArrayUtils.isEquals( attrs.get( "userPassword" ).get(), "secret".getBytes() ));
136     }
137 
138 
139     public void test3UseAkarasulu() throws NamingException
140     {
141         Hashtable env = new Hashtable();
142         env.put( Context.PROVIDER_URL, "ou=system" );
143         env.put( Context.SECURITY_PRINCIPAL, "uid=akarasulu,ou=users,ou=system" );
144         env.put( Context.SECURITY_CREDENTIALS, "test" );
145         env.put( Context.SECURITY_AUTHENTICATION, "simple" );
146         env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.CoreContextFactory" );
147         InitialDirContext ic = new InitialDirContext( env );
148         Attributes attrs = ic.getAttributes( "uid=akarasulu,ou=users" );
149         Attribute ou = attrs.get( "ou" );
150         assertTrue( ou.contains( "Engineering" ) );
151         assertTrue( ou.contains( "People" ) );
152 
153         Attribute objectClass = attrs.get( "objectClass" );
154         assertTrue( objectClass.contains( "top" ) );
155         assertTrue( objectClass.contains( "person" ) );
156         assertTrue( objectClass.contains( "organizationalPerson" ) );
157         assertTrue( objectClass.contains( "inetOrgPerson" ) );
158 
159         assertTrue( attrs.get( "telephonenumber" ).contains( "+1 408 555 4798" ) );
160         assertTrue( attrs.get( "uid" ).contains( "akarasulu" ) );
161         assertTrue( attrs.get( "givenname" ).contains( "Alex" ) );
162         assertTrue( attrs.get( "mail" ).contains( "akarasulu@apache.org" ) );
163         assertTrue( attrs.get( "l" ).contains( "Bogusville" ) );
164         assertTrue( attrs.get( "sn" ).contains( "Karasulu" ) );
165         assertTrue( attrs.get( "cn" ).contains( "Alex Karasulu" ) );
166         assertTrue( attrs.get( "facsimiletelephonenumber" ).contains( "+1 408 555 9751" ) );
167         assertTrue( attrs.get( "roomnumber" ).contains( "4612" ) );
168     }
169 
170 
171     /***
172      * Tests to make sure we throw an error when Context.SECURITY_AUTHENTICATION
173      * is set to "none" when trying to bootstrap the system.  Only the admin
174      * user is allowed to bootstrap.
175      *
176      * @throws Exception if anything goes wrong
177      */
178     public void test4BuildDbNoPassNoPrincAuthNone() throws Exception
179     {
180         // clean out the database
181         tearDown();
182         doDelete( new File( "target" + File.separator + "eve" ) );
183         Hashtable env = new Hashtable();
184         env.put( Context.SECURITY_AUTHENTICATION, "none" );
185         env.put( EnvKeys.DISABLE_ANONYMOUS, "true" );
186 
187         int port = AvailablePortFinder.getNextAvailable( 1024 );
188 
189         env.put( EnvKeys.LDAP_PORT, String.valueOf( port ) );
190 
191         try
192         {
193             setSysRoot( env );
194             fail( "should not get here due to exception" );
195         }
196         catch( LdapNoPermissionException e )
197         {
198         }
199 
200         // ok this should start up the system now as admin
201         Hashtable anonymous = new Hashtable();
202 
203         anonymous.put( EnvKeys.LDAP_PORT, String.valueOf( port ) );
204 
205         InitialLdapContext ctx = ( InitialLdapContext ) setSysRoot( anonymous );
206         assertNotNull( ctx );
207 
208         // now go in as anonymous user and we should be wh
209         env.put( Context.PROVIDER_URL, "ou=system" );
210         env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.CoreContextFactory" );
211 
212         InitialLdapContext initial = new InitialLdapContext( env, null );
213 
214         try
215         {
216             ctx = ( InitialLdapContext ) initial.lookup( "uid=admin" );
217             fail( "should not get here due to exception cuz anonymous user is "
218                     + "not allowed read access to the admin account entry" );
219         }
220         catch( LdapConfigurationException e )
221         {
222         }
223         catch( LdapNoPermissionException e )
224         {
225         }
226     }
227 
228 
229     /***
230      * Tests to make sure we throw an error when Context.SECURITY_AUTHENTICATION
231      * is set to "none" when trying to bootstrap the system even when the
232      * principal is set to the admin user.  Only the admin user is allowed to
233      * bootstrap.  This is a configuration issue or a nonsense set of property
234      * values.
235      *
236      * @throws Exception if anything goes wrong
237      */
238     public void test5BuildDbNoPassWithPrincAuthNone() throws Exception
239     {
240         // clean out the database
241         tearDown();
242         doDelete( new File( "target" + File.separator + "eve" ) );
243         Hashtable env = new Hashtable();
244         env.put( Context.SECURITY_AUTHENTICATION, "none" );
245         env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
246 
247         try
248         {
249             setSysRoot( env );
250             fail( "should not get here due to exception" );
251         }
252         catch( ConfigurationException e )
253         {
254         }
255     }
256 
257 
258     /***
259      * Tests to make sure we throw an error when Context.SECURITY_AUTHENTICATION
260      * is set to "simple" when trying to bootstrap the system but the admin is
261      * not the principal.  Only the admin user is allowed to bootstrap.
262      * Subsequent calls can 'bind' (authenticate in our case since there is no
263      * network connection) anonymously though.
264      *
265      * @throws Exception if anything goes wrong
266      */
267     public void test6BuildDbNoPassNotAdminPrinc() throws Exception
268     {
269         // clean out the database
270         tearDown();
271         doDelete( new File( "target" + File.separator + "eve" ) );
272         Hashtable env = new Hashtable();
273         env.put( Context.SECURITY_AUTHENTICATION, "simple" );
274         env.put( Context.SECURITY_PRINCIPAL, "uid=akarasulu,ou=users,ou=system" );
275 
276         try
277         {
278             setSysRoot( env );
279             fail( "should not get here due to exception" );
280         }
281         catch( ConfigurationException e )
282         {
283         }
284     }
285 
286 
287     /***
288      * Tests to make sure we can authenticate after the database has already
289      * been started by the admin user when simple authentication is in effect.
290      *
291      * @throws Exception if anything goes wrong
292      */
293     public void test8PassPrincAuthTypeSimple() throws Exception
294     {
295         Hashtable env = new Hashtable();
296         env.put( Context.PROVIDER_URL, "ou=system" );
297         env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
298         env.put( Context.SECURITY_CREDENTIALS, "secret" );
299         env.put( Context.SECURITY_AUTHENTICATION, "simple" );
300         env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.CoreContextFactory" );
301         assertNotNull( new InitialContext( env ) );
302     }
303 
304 
305     /***
306      * Checks to see if we can authenticate as a test user after the admin fires
307      * up and builds the the system database.
308      *
309      * @throws Exception if anything goes wrong
310      */
311     public void test10TestNonAdminUser() throws Exception
312     {
313         Hashtable env = new Hashtable();
314         env.put( Context.PROVIDER_URL, "ou=system" );
315         env.put( Context.SECURITY_PRINCIPAL, "uid=akarasulu,ou=users,ou=system" );
316         env.put( Context.SECURITY_CREDENTIALS, "test" );
317         env.put( Context.SECURITY_AUTHENTICATION, "simple" );
318         env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.CoreContextFactory" );
319         assertNotNull( new InitialContext( env ) );
320     }
321 }