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