Home | History | Annotate | Download | only in module
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.harmony.auth.tests.module;
     19 
     20 import java.io.IOException;
     21 import java.security.Principal;
     22 import java.util.HashMap;
     23 import java.util.Set;
     24 
     25 import javax.security.auth.Subject;
     26 import javax.security.auth.callback.Callback;
     27 import javax.security.auth.callback.CallbackHandler;
     28 import javax.security.auth.callback.NameCallback;
     29 import javax.security.auth.callback.PasswordCallback;
     30 import javax.security.auth.callback.UnsupportedCallbackException;
     31 import javax.security.auth.login.LoginException;
     32 
     33 import junit.framework.TestCase;
     34 
     35 import org.apache.harmony.auth.module.LdapLoginModule;
     36 import org.apache.harmony.auth.UserPrincipal;
     37 
     38 
     39 public class LdapLoginModuleTest extends TestCase {
     40 
     41     //  module options
     42     private HashMap<String, String> options = new HashMap<String, String>();
     43 
     44     private final String USER_PROVIDER_URL = "ldap://9.181.106.121:389/ou=People,o=JNDITutorial,dc=my-domain,dc=com";
     45 
     46     protected void setUp() throws Exception {
     47         options.put("userProvider", USER_PROVIDER_URL);
     48         options.put("useSSL", "false");
     49     }
     50 
     51     @Override
     52     protected void tearDown() throws Exception {
     53         options.clear();
     54     }
     55 
     56     /**
     57      * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#abort()}.
     58      */
     59     public void test_abort() throws LoginException{
     60         LdapLoginModule jlm = new LdapLoginModule();
     61         try {
     62             assertFalse("Should return false if login failed or no login", jlm
     63                     .abort());
     64         } catch (LoginException e) {
     65             fail("Abort failed");
     66         }
     67         Subject subject = new Subject();
     68         subject.setReadOnly();
     69         jlm.initialize(subject, null, null, options);
     70         try {
     71             assertFalse("Should return false if login failed or no login", jlm
     72                     .abort());
     73         } catch (Exception e) {
     74             fail("Not any exception here");
     75         }
     76         subject = new Subject();
     77         jlm.initialize(subject, new FaultCallbackHandler(), null, options);
     78         try {
     79             jlm.login();
     80             fail("login should fail");
     81         } catch (LoginException e) {
     82             assertFalse("Should return false because of login failure", jlm
     83                     .abort());
     84         }
     85         subject = new Subject();
     86         options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
     87         jlm.initialize(subject, new MockCallbackHandler(), null, options);
     88         jlm.login();
     89         assertTrue("Should return true if login was successful", jlm
     90                 .abort());
     91     }
     92 
     93     /**
     94      * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#commit()}.
     95      */
     96     public void test_commit() {
     97         LdapLoginModule module = new LdapLoginModule();
     98         Subject subject = new Subject();
     99         options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
    100         module.initialize(subject, new MockCallbackHandler(), null, options);
    101         try {
    102             assertTrue("Login should be successful", module.login());
    103             module.commit();
    104         } catch (LoginException e) {
    105             fail("Login shouldn't fail");
    106         }
    107         Set<Principal> principals = subject.getPrincipals();
    108         assertFalse("Should get at least one principal", principals.isEmpty());
    109         subject = new Subject();
    110         subject.setReadOnly();
    111         module.initialize(subject, new MockCallbackHandler(), null, options);
    112         try {
    113             assertFalse("Commit shouldn't be successful", module.commit());
    114             fail("Should throw LoginException here because of trying to clear read-only subject");
    115         } catch (LoginException e) {
    116             // expected LoginException here
    117         }
    118     }
    119 
    120     /**
    121      * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)}.
    122      */
    123     public void test_initialize() {
    124         LdapLoginModule module = new LdapLoginModule();
    125         try {
    126             module.initialize(null, null, null, null);
    127             fail("Should throw NullPointerException here.");
    128         } catch (NullPointerException e) {
    129             // expected NullPointerException
    130         }
    131     }
    132 
    133     /**
    134      * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#login()}.
    135      */
    136     public void test_login() {
    137         LdapLoginModule module = new LdapLoginModule();
    138         HashMap<String, String> emptyOptions = new HashMap<String, String>();
    139         module.initialize(null, new MockCallbackHandler(), null, emptyOptions);
    140         try {
    141             module.login();
    142             fail("Should throw LoginException here.");
    143         } catch (LoginException e) {
    144             // expected LoginException
    145         }
    146 
    147         options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
    148         Subject subject = new Subject();
    149         module.initialize(subject, new MockCallbackHandler(), null, options);
    150         try {
    151             assertTrue("Login should be successful", module.login());
    152         } catch (LoginException e) {
    153             fail("Login shouldn't fail");
    154         }
    155         module.initialize(subject, new FaultCallbackHandler(), null, options);
    156         try {
    157             assertFalse("Login shouldn't be successful", module.login());
    158             fail("Login should fail");
    159         } catch (LoginException e) {
    160             // expected Loginexception here
    161         }
    162     }
    163 
    164     /**
    165      * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#logout()}.
    166      */
    167     public void test_logout() {
    168         LdapLoginModule module = new LdapLoginModule();
    169         Subject subject = new Subject();
    170         options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
    171         module.initialize(subject, new MockCallbackHandler(), null, options);
    172         try {
    173             assertTrue("Login should be successful", module.login());
    174             module.commit();
    175         } catch (LoginException e) {
    176             fail("Login shouldn't fail");
    177         }
    178         Set<Principal> principals = subject.getPrincipals();
    179         assertFalse("Should get at least one principal", principals.isEmpty());
    180         try {
    181             assertTrue("Should be true", module.logout());
    182         } catch (LoginException e) {
    183             fail("Logout failed");
    184         }
    185         principals = subject.getPrincipals();
    186         assertTrue("Principals should be cleared", principals.isEmpty());
    187     }
    188 
    189     public void test_optionsAndSharedStatus() throws LoginException{
    190         options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
    191         options.put("authzIdentity","testAuthzIdentityOption");
    192         LdapLoginModule module = new LdapLoginModule();
    193         Subject subject = new Subject();
    194         module.initialize(subject, new MockCallbackHandler(), null, options);
    195         try {
    196             module.login();
    197             module.commit();
    198             assertTrue("Should get a principal from authzIdentity option",subject.getPrincipals().contains(new UserPrincipal("testAuthzIdentityOption")));
    199         }
    200         catch(LoginException e){
    201             fail("Login failed");
    202         }
    203         finally{
    204             module.logout();
    205         }
    206 
    207         options.put("debug", "true");
    208         options.put("useFirstPass", "true");
    209         HashMap<String, Object> status = new HashMap<String,Object>();
    210         status.put("javax.security.auth.login.name", "leo");
    211         status.put("javax.security.auth.login.password", "faultPass".toCharArray());
    212         subject = new Subject();
    213         module.initialize(subject, new MockCallbackHandler(), status, options);
    214         try {
    215             module.login();
    216             fail("Should be failed for using password from shared state");
    217         }
    218         catch(LoginException e){
    219             //expected LoginException here
    220         }
    221 
    222         options.remove("useFirstPass");
    223         options.put("tryFirstPass", "true");
    224         module.initialize(subject, new MockCallbackHandler(), status, options);
    225         try {
    226             module.login();
    227             module.commit();
    228         }
    229         catch(LoginException e){
    230             fail("Login should be failed");
    231         }
    232         finally{
    233             module.logout();
    234         }
    235 
    236         options.remove("tryFirstPass");
    237         options.put("clearPass", "true");
    238         status.put("javax.security.auth.login.name", "leo");
    239         status.put("javax.security.auth.login.password", "passw0rd".toCharArray());
    240         module.initialize(subject, new MockCallbackHandler(), status, options);
    241         try {
    242             module.login();
    243             module.commit();
    244             assertNull("javax.security.auth.login.name in shared state should be null when clearPass switch on",status.get("javax.security.auth.login.name"));
    245             assertNull("javax.security.auth.login.password in shared state should be null when clearPass switch on",status.get("javax.security.auth.login.password"));
    246         } catch (LoginException e) {
    247             fail("Login shouldn't fail");
    248         }
    249         finally{
    250             module.logout();
    251         }
    252 
    253         status = new HashMap<String,Object>();
    254         options.remove("clearPass");
    255         options.put("storePass", "true");
    256         module.initialize(subject, new FaultCallbackHandler(), status, options);
    257         try {
    258             module.login();
    259             module.commit();
    260         } catch (LoginException e) {
    261             assertNull("javax.security.auth.login.name in shared state should be null when login failed",status.get("javax.security.auth.login.name"));
    262             assertNull("javax.security.auth.login.password in shared state should be null when login failed",status.get("javax.security.auth.login.password"));
    263         }
    264         finally{
    265             module.logout();
    266         }
    267 
    268         module.initialize(subject, new MockCallbackHandler(), status, options);
    269         try {
    270             module.login();
    271             module.commit();
    272         } catch (LoginException e) {
    273             fail("Login failed");
    274         }
    275         finally{
    276             module.logout();
    277         }
    278         assertNotNull("javax.security.auth.login.name should be stored in shared state when storePass switch on",status.get("javax.security.auth.login.name"));
    279         assertNotNull("javax.security.auth.login.password should be stored in shared state when storePass switch on",status.get("javax.security.auth.login.password"));
    280 
    281         status.put("javax.security.auth.login.name", "tester");
    282         status.put("javax.security.auth.login.password", "testerPass");
    283         module.initialize(subject, new MockCallbackHandler(), status, options);
    284         try {
    285             module.login();
    286             module.commit();
    287         } catch (LoginException e) {
    288             fail("Login failed");
    289         }
    290         finally{
    291             module.logout();
    292         }
    293         assertEquals("Should't override the username value in sharedState",status.get("javax.security.auth.login.name"),"tester");
    294         assertEquals("Should't override the password value in sharedState",status.get("javax.security.auth.login.password"),"testerPass");
    295     }
    296 
    297     static private class MockCallbackHandler implements CallbackHandler{
    298 
    299         public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    300             for(int i=0;i<callbacks.length;i++){
    301                 if(callbacks[i] instanceof NameCallback){
    302                     NameCallback nc = (NameCallback)callbacks[i];
    303                     nc.setName("leo");
    304                 }
    305                 else if(callbacks[i] instanceof PasswordCallback){
    306                     PasswordCallback pc = (PasswordCallback)callbacks[i];
    307                     pc.setPassword("secret".toCharArray());
    308                 }
    309                 else
    310                 {
    311                     throw new Error(callbacks[i].getClass().toString());
    312                 }
    313             }
    314         }
    315     }
    316 
    317     static private class FaultCallbackHandler implements CallbackHandler{
    318 
    319         public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    320             for(int i=0;i<callbacks.length;i++){
    321                 if(callbacks[i] instanceof NameCallback){
    322                     NameCallback nc = (NameCallback)callbacks[i];
    323                     nc.setName("leo");
    324                 }
    325                 else if(callbacks[i] instanceof PasswordCallback){
    326                     PasswordCallback pc = (PasswordCallback)callbacks[i];
    327                     pc.setPassword("password".toCharArray());
    328                 }
    329                 else
    330                 {
    331                     throw new Error(callbacks[i].getClass().toString());
    332                 }
    333             }
    334         }
    335     }
    336 }
    337