You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by le...@apache.org on 2007/10/11 11:42:14 UTC

svn commit: r583755 - in /harmony/enhanced/classlib/branches/java6/modules/auth: META-INF/ make/ src/main/java/common/org/apache/harmony/auth/ src/main/java/common/org/apache/harmony/auth/module/ src/test/java/common/org/apache/harmony/auth/tests/module/

Author: leoli
Date: Thu Oct 11 02:42:13 2007
New Revision: 583755

URL: http://svn.apache.org/viewvc?rev=583755&view=rev
Log:
Apply patch for HARMONY-4918([classlib][auth][java6]Harmony lacks support for LdapLoginModule).

Added:
    harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/LdapPrincipal.java   (with props)
    harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/UserPrincipal.java   (with props)
    harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/module/LdapLoginModule.java   (with props)
    harmony/enhanced/classlib/branches/java6/modules/auth/src/test/java/common/org/apache/harmony/auth/tests/module/LdapLoginModuleTest.java   (with props)
Modified:
    harmony/enhanced/classlib/branches/java6/modules/auth/META-INF/MANIFEST.MF
    harmony/enhanced/classlib/branches/java6/modules/auth/make/exclude.common

Modified: harmony/enhanced/classlib/branches/java6/modules/auth/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/auth/META-INF/MANIFEST.MF?rev=583755&r1=583754&r2=583755&view=diff
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/auth/META-INF/MANIFEST.MF (original)
+++ harmony/enhanced/classlib/branches/java6/modules/auth/META-INF/MANIFEST.MF Thu Oct 11 02:42:13 2007
@@ -30,6 +30,7 @@
  javax.crypto.spec,
  javax.naming,
  javax.naming.directory,
+ javax.naming.ldap,
  org.apache.harmony.kernel.vm,
  org.apache.harmony.security,
  org.apache.harmony.security.asn1,

Modified: harmony/enhanced/classlib/branches/java6/modules/auth/make/exclude.common
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/auth/make/exclude.common?rev=583755&r1=583754&r2=583755&view=diff
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/auth/make/exclude.common (original)
+++ harmony/enhanced/classlib/branches/java6/modules/auth/make/exclude.common Thu Oct 11 02:42:13 2007
@@ -1,4 +1,6 @@
 # excluded to avoid random failures 
 org/apache/harmony/auth/tests/module/Krb5LoginModuleTest.java
 # jndi provider does not exist now
-org/apache/harmony/auth/tests/module/JndiLoginModuleTest.java
\ No newline at end of file
+org/apache/harmony/auth/tests/module/JndiLoginModuleTest.java
+# ldap provider does not exist now
+org/apache/harmony/auth/tests/module/LdapLoginModuleTest.java
\ No newline at end of file

Added: harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/LdapPrincipal.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/LdapPrincipal.java?rev=583755&view=auto
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/LdapPrincipal.java (added)
+++ harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/LdapPrincipal.java Thu Oct 11 02:42:13 2007
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.auth;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+import org.apache.harmony.auth.internal.nls.Messages;
+
+public class LdapPrincipal implements Serializable, Principal {
+
+    private static final long serialVersionUID = 6820120005580754861L;
+    
+    //  User name
+    private LdapName name;
+    
+    /**
+     * Sole constructor.
+     * @param name user name
+     * @throws NullPointerException if name is null
+     */
+    public LdapPrincipal(String name) throws InvalidNameException{
+        if (name == null) {
+            throw new NullPointerException(Messages.getString("auth.00")); //$NON-NLS-1$
+        }
+        this.name = new LdapName(name);
+    }
+    
+    public String getName() {
+        // TODO Auto-generated method stub
+        return name.toString();
+    }
+    
+    /**
+     * Returns string representation of this object
+     */
+    @Override
+    public String toString() {
+        return "LdapPrincipal, name=" + name; //$NON-NLS-1$
+    }
+    
+    /**
+     * Compares two UserPrincipal objects.<br>
+     * Two principal objects are considered equal if they are both of type 
+     * UnixPrincipal and their names are equal.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof LdapPrincipal) {
+            return name.equals(((LdapPrincipal) o).name);
+        }
+        return false;
+    }
+    
+    /**
+     * Return hash code of this object.
+     */
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+}

Propchange: harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/LdapPrincipal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/UserPrincipal.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/UserPrincipal.java?rev=583755&view=auto
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/UserPrincipal.java (added)
+++ harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/UserPrincipal.java Thu Oct 11 02:42:13 2007
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.auth;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+import org.apache.harmony.auth.internal.nls.Messages;
+
+public class UserPrincipal implements Serializable, Principal {
+
+    private static final long serialVersionUID = 892106070870210969L;
+    
+    //  User name
+    private String name;
+    
+    /**
+     * Sole constructor.
+     * @param name user name
+     * @throws NullPointerException if name is null
+     */
+    public UserPrincipal(String name) {
+        if (name == null) {
+            throw new NullPointerException(Messages.getString("auth.00")); //$NON-NLS-1$
+        }
+        this.name = name;
+    }
+    
+    public String getName() {
+        // TODO Auto-generated method stub
+        return name;
+    }
+    
+    /**
+     * Returns string representation of this object
+     */
+    @Override
+    public String toString() {
+        return "UserPrincipal, name=" + name; //$NON-NLS-1$
+    }
+    
+    /**
+     * Compares two UserPrincipal objects.<br>
+     * Two principal objects are considered equal if they are both of type 
+     * UnixPrincipal and their names are equal.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof UserPrincipal) {
+            return name.equals(((UserPrincipal) o).name);
+        }
+        return false;
+    }
+    
+    /**
+     * Return hash code of this object.
+     */
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+}

Propchange: harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/UserPrincipal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/module/LdapLoginModule.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/module/LdapLoginModule.java?rev=583755&view=auto
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/module/LdapLoginModule.java (added)
+++ harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/module/LdapLoginModule.java Thu Oct 11 02:42:13 2007
@@ -0,0 +1,420 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.auth.module;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.naming.AuthenticationException;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.apache.harmony.auth.LdapPrincipal;
+import org.apache.harmony.auth.UserPrincipal;
+
+public class LdapLoginModule extends SharedStateManager implements LoginModule {
+
+    private static enum LdapAuthMode{
+        search_first("search-first mode"),
+        authentication_first("authentication-first mode"),
+        authentication_only("authentication-only mode");
+        
+        private String strValue;
+        LdapAuthMode(String str){
+            strValue = str;
+        }
+        
+        public String toString(){
+            return strValue;
+        }
+    };
+    
+    //harmony lacks ldap provider
+    private final String LDAP_FACTORY = "";
+    
+    private LoginModuleUtils.LoginModuleStatus status = new LoginModuleUtils.LoginModuleStatus();
+    
+    private Subject subject;
+
+    private CallbackHandler callbackHandler;
+
+    private Map<String, ?> options;
+    
+    private String ldapUserProvider;
+    
+    private String userID;
+
+    private char[] userPassword;
+    
+    private LdapPrincipal ldapPrincipal;
+
+    private UserPrincipal userPrincipal;
+    
+    private UserPrincipal extraUserPrincipal;
+
+    private boolean useSSL = false;
+    
+    private LdapAuthMode ldapAuthMode;
+    
+    private String userFilter;
+    
+    private String authIdentity;
+    
+    private String authzIdentity;
+    
+    private String ldapPrincipalEntryName; 
+    
+    public boolean abort() throws LoginException {
+        LoginModuleUtils.ACTION action = status.checkAbout();
+        if (action.equals(LoginModuleUtils.ACTION.no_action)) {
+            if (status.isLoggined()) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+        clear();
+        debugUtil.recordDebugInfo("[LdapLoginModule] aborted authentication\n");
+        if(status.isCommitted()){
+        	debugUtil.recordDebugInfo("[LdapLoginModule]: logged out Subject\n");
+        }
+        debugUtil.printAndClearDebugInfo();
+        status.logouted();
+        return true;
+    }
+
+    public boolean commit() throws LoginException {
+        LoginModuleUtils.ACTION action = status.checkCommit();
+        switch (action) {
+        case no_action:
+            return true;
+        case logout:
+            clear();
+            throw new LoginException("Fail to login");
+        default:
+            if (subject.isReadOnly()) {
+                clear();
+                throw new LoginException("Subject is readonly.");
+            }
+            subject.getPrincipals().add(ldapPrincipal);
+            debugUtil.recordDebugInfo("[LdapLoginModule] added LadpPrincipal \""+ ldapPrincipalEntryName + "\" to Subject\n");
+            subject.getPrincipals().add(userPrincipal);
+            debugUtil.recordDebugInfo("[LdapLoginModule] added UserPrincipal \""+ userID + "\" to Subject\n");
+            if(extraUserPrincipal != null){
+                subject.getPrincipals().add(extraUserPrincipal);
+                debugUtil.recordDebugInfo("[LdapLoginModule] added UserPrincipal \""+ authzIdentity + "\" to Subject\n");
+            }
+            debugUtil.printAndClearDebugInfo();
+            status.committed();
+            clearPass();
+            return true;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public void initialize(Subject subject, CallbackHandler callbackHandler,
+            Map<String, ?> sharedState, Map<String, ?> options) {
+        this.subject = subject;
+        this.callbackHandler = callbackHandler;
+        this.sharedState = (Map<String, Object>) sharedState;
+        if (null == options) {
+            throw new NullPointerException();
+        }
+        this.options = options;
+        debugUtil = new DebugUtil(options);
+        prepareSharedState(sharedState,options);
+        processForOptions();
+        status.initialized();
+    }
+
+    public boolean login() throws LoginException {
+        LoginModuleUtils.ACTION action = status.checkLogin();
+        if (action.equals(LoginModuleUtils.ACTION.no_action)) {
+            return true;
+        }
+        getLdapParameters();
+        loginWithSharedState();
+/*        if(useFirstPass || tryFirstPass){
+            getUserIdentityFromSharedStatus();
+        }
+        else{
+            getUserIdentityFromCallbackHandler();
+        }
+        boolean passAuth = false;
+        passAuth = mainAuthenticationProcess();
+        if (!passAuth) {
+            if(tryFirstPass){
+                recordDebugInfo("[LdapLoginModule] tryFirstPass failed with:" + new FailedLoginException("Login incorrect").toString() + "\n");
+                getUserIdentityFromCallbackHandler();
+                passAuth = mainAuthenticationProcess();
+                if(!passAuth){
+                    recordDebugInfo("[LdapLoginModule] regular authentication failed\n");
+                    printAndClearDebugInfo();
+                    throw new FailedLoginException("Cannot bind to LDAP server");
+                }
+                else{
+                    recordDebugInfo("[LdapLoginModule] regular authentication succeeded\n");
+                }
+            }
+            else {
+                if (useFirstPass) {
+                    recordDebugInfo("[LdapLoginModule] useFirstPass failed with:"
+                            + new FailedLoginException("Cannot bind to LDAP server")
+                                    .toString() + "\n");                
+                } else {
+                    recordDebugInfo("[LdapLoginModule] regular authentication failed\n");
+                }
+                printAndClearDebugInfo();
+                throw new FailedLoginException("Cannot bind to LDAP server");
+            }
+        }        
+        else{
+            if(tryFirstPass){
+                recordDebugInfo("[LdapLoginModule] tryFirstPass ");
+            }
+            else if(useFirstPass){
+                recordDebugInfo("[LdapLoginModule] useFirstPass ");
+            }
+            else{
+                recordDebugInfo("[LdapLoginModule] authentication ");
+            }
+            recordDebugInfo("succeeded\n");
+        }
+        storePass();*/
+        try {
+            getPrinclpalsFromLdap();
+        } catch (InvalidNameException e) {
+            throw new LoginException("Error to get principal from ldap");
+        }
+        debugUtil.printAndClearDebugInfo();
+        status.logined();
+        return true;
+    }
+
+    public boolean logout() throws LoginException {
+        LoginModuleUtils.ACTION action = status.checkLogout();
+        if (action.equals(LoginModuleUtils.ACTION.no_action)) {
+            return true;
+        }
+        clear();
+        debugUtil.recordDebugInfo("[LdapLoginModule] logged out Subject\n");
+        debugUtil.printAndClearDebugInfo();
+        status.logouted();
+        return true;
+    }
+    
+    private void clear() throws LoginException {
+        LoginModuleUtils.clearPassword(userPassword);
+        userPassword = null;
+        if (ldapPrincipal != null) {
+            subject.getPrincipals().remove(ldapPrincipal);
+            ldapPrincipal = null;
+        }
+
+        if (userPrincipal != null) {
+            subject.getPrincipals().remove(userPrincipal);
+            userPrincipal = null;
+        }
+        
+        if (extraUserPrincipal != null) {
+            subject.getPrincipals().remove(extraUserPrincipal);
+            extraUserPrincipal = null;
+        }      
+        status.logouted();
+    }
+    
+    protected boolean mainAuthenticationProcess() throws LoginException{
+        Hashtable<String, String> env = new Hashtable<String, String>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_FACTORY);
+        env.put(Context.PROVIDER_URL, ldapUserProvider);
+        if(useSSL){
+            env.put(Context.SECURITY_PROTOCOL, "ssl");
+        }
+        DirContext ctx;
+        debugUtil.recordDebugInfo("[LdapLoginModule] attempting to authenticate user: "+ userID +"\n");
+        try{
+            if(ldapAuthMode == LdapAuthMode.search_first){
+                boolean logined = false;
+                env.put(Context.SECURITY_AUTHENTICATION, "none");
+                ctx = new InitialDirContext(env);
+                SearchControls constraints = new SearchControls();
+                constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
+                debugUtil.recordDebugInfo("[LdapLoginModule] searching for entry belonging to user: "+ userID +"\n");
+                NamingEnumeration enumer = ctx.search("", userFilter, constraints);
+                env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
+                while(enumer.hasMore()){
+                    NameClassPair item = (NameClassPair) enumer.next();
+                    try{
+                        env.put(Context.SECURITY_PRINCIPAL, "simple");
+                        env.put(Context.SECURITY_PRINCIPAL, item.getNameInNamespace());
+                        env.put(Context.SECURITY_CREDENTIALS, new String(userPassword));
+                        ctx = new InitialDirContext(env);
+                        ldapPrincipalEntryName = item.getNameInNamespace();
+                        debugUtil.recordDebugInfo("[LdapLoginModule] found entry: " + ldapPrincipalEntryName + "\n");
+                        logined = true;
+                        break;
+                    }
+                    catch(AuthenticationException e){
+                        
+                    }
+                }
+                if(!logined){
+                    return false;
+                }
+            }
+            else{
+                env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
+                env.put(Context.SECURITY_PRINCIPAL, authIdentity);
+                env.put(Context.SECURITY_CREDENTIALS, new String(userPassword));
+                try{
+                    ctx = new InitialDirContext(env);
+                }
+                catch(AuthenticationException e){
+                    return false;
+                }
+                if(ldapAuthMode == LdapAuthMode.authentication_only){
+                    ldapPrincipalEntryName = authIdentity;
+                }
+                else{
+                    SearchControls constraints = new SearchControls();
+                    constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
+                    debugUtil.recordDebugInfo("[LdapLoginModule] searching for entry belonging to user: "+ userID +"\n");
+                    NamingEnumeration enumer = ctx.search("", userFilter, constraints);
+                    if(enumer.hasMore()){
+                        NameClassPair item = (NameClassPair) enumer.next();
+                        ldapPrincipalEntryName = item.getNameInNamespace();
+                        debugUtil.recordDebugInfo("[LdapLoginModule] found entry: " + ldapPrincipalEntryName + "\n");
+                    }
+                    else{
+                        return false;
+                    }
+                }
+            }
+        }
+        catch(NamingException e){
+            return false;
+        }
+        return true;
+    }
+    
+    private void processForOptions() {
+        Object optionValue = null;
+
+        optionValue = options.get("useSSL");
+        if (optionValue != null && optionValue.equals("true")) {
+            useSSL = true;
+        }
+        
+        userFilter = (String)options.get("userFilter");
+        authIdentity = (String)options.get("authIdentity");
+        authzIdentity = (String)options.get("authzIdentity");
+        if(authIdentity==null){
+            ldapAuthMode = LdapAuthMode.search_first;
+        }
+        else if(userFilter==null){
+            ldapAuthMode = LdapAuthMode.authentication_only;
+        }
+        else{
+            ldapAuthMode = LdapAuthMode.authentication_first;
+        }
+        debugUtil.recordDebugInfo("[LdapLoginModule] "+ ldapAuthMode + "\n");
+        if(useSSL){
+        	debugUtil.recordDebugInfo("[LdapLoginModule] SSL enabled\n");
+        }
+        else{
+        	debugUtil.recordDebugInfo("[LdapLoginModule] SSL disabled\n");
+        }
+        debugUtil.printAndClearDebugInfo();
+    }
+    
+    private void getLdapParameters()throws LoginException{
+        ldapUserProvider = (String)options.get("userProvider");
+        if (ldapUserProvider == null) {
+            throw new LoginException("Unable to locate the LDAP directory service");
+        }
+        debugUtil.recordDebugInfo("[LdapLoginModule] user provider: " + ldapUserProvider + "\n");
+    }
+    
+    protected void getUserIdentityFromCallbackHandler() throws LoginException {
+        
+        if (callbackHandler == null) {
+            throw new LoginException("no CallbackHandler available");
+        }
+        ArrayList<Callback> callbacks = new ArrayList<Callback>();
+        NameCallback jndiNameCallback = new NameCallback("User ID");
+        callbacks.add(jndiNameCallback);
+        PasswordCallback jndiPasswordCallback = new PasswordCallback(
+                "User Password", false);
+        callbacks.add(jndiPasswordCallback);
+        try {
+            callbackHandler.handle(callbacks.toArray(new Callback[callbacks
+                    .size()]));
+        } catch (Exception e) {
+            throw new LoginException(e.toString());
+        }
+        userID = jndiNameCallback.getName();
+        userPassword = jndiPasswordCallback.getPassword();
+    }
+    
+    private void getPrinclpalsFromLdap() throws InvalidNameException{
+        ldapPrincipal = new LdapPrincipal(ldapPrincipalEntryName); 
+        userPrincipal = new UserPrincipal(userID);
+        if(authzIdentity != null){
+            extraUserPrincipal = new UserPrincipal(authzIdentity);
+        }
+    }
+
+	@Override
+	protected String getModuleName() {
+		return "LdapLoginModule";
+	}
+
+	@Override
+	protected String getUserName() {
+		return userID;
+	}
+
+	@Override
+	protected char[] getUserPassword() {
+		return userPassword;
+	}
+
+	@Override
+	protected void setUserName(String userName) {
+		this.userID = userName;
+	}
+
+	@Override
+	protected void setUserPassword(char[] userPassword) {
+		this.userPassword = userPassword;
+	}
+}

Propchange: harmony/enhanced/classlib/branches/java6/modules/auth/src/main/java/common/org/apache/harmony/auth/module/LdapLoginModule.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/classlib/branches/java6/modules/auth/src/test/java/common/org/apache/harmony/auth/tests/module/LdapLoginModuleTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/auth/src/test/java/common/org/apache/harmony/auth/tests/module/LdapLoginModuleTest.java?rev=583755&view=auto
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/auth/src/test/java/common/org/apache/harmony/auth/tests/module/LdapLoginModuleTest.java (added)
+++ harmony/enhanced/classlib/branches/java6/modules/auth/src/test/java/common/org/apache/harmony/auth/tests/module/LdapLoginModuleTest.java Thu Oct 11 02:42:13 2007
@@ -0,0 +1,336 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.auth.tests.module;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.auth.module.LdapLoginModule;
+import org.apache.harmony.auth.UserPrincipal;
+
+
+public class LdapLoginModuleTest extends TestCase {
+
+    //  module options
+    private HashMap<String, String> options = new HashMap<String, String>();
+
+    private final String USER_PROVIDER_URL = "ldap://9.181.106.121:389/ou=People,o=JNDITutorial,dc=my-domain,dc=com";
+    
+    protected void setUp() throws Exception {
+        options.put("userProvider", USER_PROVIDER_URL);
+        options.put("useSSL", "false");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        options.clear();
+    }
+
+    /**
+     * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#abort()}.
+     */
+    public void test_abort() throws LoginException{
+        LdapLoginModule jlm = new LdapLoginModule();
+        try {
+            assertFalse("Should return false if login failed or no login", jlm
+                    .abort());
+        } catch (LoginException e) {
+            fail("Abort failed");
+        }
+        Subject subject = new Subject();
+        subject.setReadOnly();
+        jlm.initialize(subject, null, null, options);
+        try {
+            assertFalse("Should return false if login failed or no login", jlm
+                    .abort());
+        } catch (Exception e) {
+            fail("Not any exception here");
+        }
+        subject = new Subject();
+        jlm.initialize(subject, new FaultCallbackHandler(), null, options);
+        try {
+            jlm.login();
+            fail("login should fail");
+        } catch (LoginException e) {
+            assertFalse("Should return false because of login failure", jlm
+                    .abort());
+        }
+        subject = new Subject();
+        options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
+        jlm.initialize(subject, new MockCallbackHandler(), null, options);
+        jlm.login();
+        assertTrue("Should return true if login was successful", jlm
+                .abort());
+    }
+
+    /**
+     * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#commit()}.
+     */
+    public void test_commit() {
+        LdapLoginModule module = new LdapLoginModule();
+        Subject subject = new Subject();
+        options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
+        module.initialize(subject, new MockCallbackHandler(), null, options);
+        try {
+            assertTrue("Login should be successful", module.login());
+            module.commit();
+        } catch (LoginException e) {
+            fail("Login shouldn't fail");
+        }
+        Set<Principal> principals = subject.getPrincipals();
+        assertFalse("Should get at least one principal", principals.isEmpty());
+        subject = new Subject();
+        subject.setReadOnly();
+        module.initialize(subject, new MockCallbackHandler(), null, options);
+        try {
+            assertFalse("Commit shouldn't be successful", module.commit());
+            fail("Should throw LoginException here because of trying to clear read-only subject");
+        } catch (LoginException e) {
+            // expected LoginException here
+        }
+    }
+
+    /**
+     * 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)}.
+     */
+    public void test_initialize() {
+        LdapLoginModule module = new LdapLoginModule();
+        try {
+            module.initialize(null, null, null, null);
+            fail("Should throw NullPointerException here.");
+        } catch (NullPointerException e) {
+            // expected NullPointerException
+        }
+    }
+
+    /**
+     * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#login()}.
+     */
+    public void test_login() {
+        LdapLoginModule module = new LdapLoginModule();
+        HashMap<String, String> emptyOptions = new HashMap<String, String>();
+        module.initialize(null, new MockCallbackHandler(), null, emptyOptions);
+        try {
+            module.login();
+            fail("Should throw LoginException here.");
+        } catch (LoginException e) {
+            // expected LoginException
+        }
+
+        options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
+        Subject subject = new Subject();
+        module.initialize(subject, new MockCallbackHandler(), null, options);
+        try {
+            assertTrue("Login should be successful", module.login());
+        } catch (LoginException e) {
+            fail("Login shouldn't fail");
+        }
+        module.initialize(subject, new FaultCallbackHandler(), null, options);
+        try {
+            assertFalse("Login shouldn't be successful", module.login());
+            fail("Login should fail");
+        } catch (LoginException e) {
+            // expected Loginexception here
+        }
+    }
+
+    /**
+     * Test method for {@link org.apache.harmony.auth.module.LdapLoginModule#logout()}.
+     */
+    public void test_logout() {
+        LdapLoginModule module = new LdapLoginModule();
+        Subject subject = new Subject();
+        options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
+        module.initialize(subject, new MockCallbackHandler(), null, options);
+        try {
+            assertTrue("Login should be successful", module.login());
+            module.commit();
+        } catch (LoginException e) {
+            fail("Login shouldn't fail");
+        }
+        Set<Principal> principals = subject.getPrincipals();
+        assertFalse("Should get at least one principal", principals.isEmpty());
+        try {
+            assertTrue("Should be true", module.logout());
+        } catch (LoginException e) {
+            fail("Logout failed");
+        }
+        principals = subject.getPrincipals();
+        assertTrue("Principals should be cleared", principals.isEmpty());
+    }
+    
+    public void test_optionsAndSharedStatus() throws LoginException{
+        options.put("authIdentity","cn=Manager,dc=my-domain,dc=com");
+        options.put("authzIdentity","testAuthzIdentityOption");
+        LdapLoginModule module = new LdapLoginModule();
+        Subject subject = new Subject();
+        module.initialize(subject, new MockCallbackHandler(), null, options);
+        try {
+            module.login();
+            module.commit();
+            assertTrue("Should get a principal from authzIdentity option",subject.getPrincipals().contains(new UserPrincipal("testAuthzIdentityOption")));
+        }
+        catch(LoginException e){
+            fail("Login failed");
+        }
+        finally{
+            module.logout();
+        }
+        
+        options.put("debug", "true");
+        options.put("useFirstPass", "true");
+        HashMap<String, Object> status = new HashMap<String,Object>();
+        status.put("javax.security.auth.login.name", "leo");
+        status.put("javax.security.auth.login.password", "faultPass".toCharArray());
+        subject = new Subject();
+        module.initialize(subject, new MockCallbackHandler(), status, options);
+        try {
+            module.login();
+            fail("Should be failed for using password from shared state");
+        }
+        catch(LoginException e){
+            //expected LoginException here 
+        }
+        
+        options.remove("useFirstPass");
+        options.put("tryFirstPass", "true");
+        module.initialize(subject, new MockCallbackHandler(), status, options);
+        try {
+            module.login();
+            module.commit();
+        }
+        catch(LoginException e){
+            fail("Login should be failed"); 
+        }
+        finally{
+            module.logout();
+        }
+        
+        options.remove("tryFirstPass");
+        options.put("clearPass", "true");
+        status.put("javax.security.auth.login.name", "leo");
+        status.put("javax.security.auth.login.password", "passw0rd".toCharArray());
+        module.initialize(subject, new MockCallbackHandler(), status, options);
+        try {
+            module.login();
+            module.commit();
+            assertNull("javax.security.auth.login.name in shared state should be null when clearPass switch on",status.get("javax.security.auth.login.name"));
+            assertNull("javax.security.auth.login.password in shared state should be null when clearPass switch on",status.get("javax.security.auth.login.password"));
+        } catch (LoginException e) {
+            fail("Login shouldn't fail");
+        }
+        finally{
+            module.logout();
+        }
+        
+        status = new HashMap<String,Object>();
+        options.remove("clearPass");
+        options.put("storePass", "true");
+        module.initialize(subject, new FaultCallbackHandler(), status, options);
+        try {
+            module.login();
+            module.commit();        
+        } catch (LoginException e) {
+            assertNull("javax.security.auth.login.name in shared state should be null when login failed",status.get("javax.security.auth.login.name"));
+            assertNull("javax.security.auth.login.password in shared state should be null when login failed",status.get("javax.security.auth.login.password"));
+        }
+        finally{
+            module.logout();
+        }
+        
+        module.initialize(subject, new MockCallbackHandler(), status, options);
+        try {
+            module.login();
+            module.commit();        
+        } catch (LoginException e) {
+            fail("Login failed");
+        }
+        finally{
+            module.logout();
+        }
+        assertNotNull("javax.security.auth.login.name should be stored in shared state when storePass switch on",status.get("javax.security.auth.login.name"));
+        assertNotNull("javax.security.auth.login.password should be stored in shared state when storePass switch on",status.get("javax.security.auth.login.password"));
+        
+        status.put("javax.security.auth.login.name", "tester");
+        status.put("javax.security.auth.login.password", "testerPass");
+        module.initialize(subject, new MockCallbackHandler(), status, options);
+        try {
+            module.login();
+            module.commit();        
+        } catch (LoginException e) {
+            fail("Login failed");
+        }
+        finally{
+            module.logout();
+        }
+        assertEquals("Should't override the username value in sharedState",status.get("javax.security.auth.login.name"),"tester");
+        assertEquals("Should't override the password value in sharedState",status.get("javax.security.auth.login.password"),"testerPass");     
+    }
+    
+    static private class MockCallbackHandler implements CallbackHandler{
+
+        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+            for(int i=0;i<callbacks.length;i++){
+                if(callbacks[i] instanceof NameCallback){
+                    NameCallback nc = (NameCallback)callbacks[i];
+                    nc.setName("leo");
+                }
+                else if(callbacks[i] instanceof PasswordCallback){
+                    PasswordCallback pc = (PasswordCallback)callbacks[i];
+                    pc.setPassword("secret".toCharArray());
+                }
+                else
+                {
+                    throw new Error(callbacks[i].getClass().toString());
+                }
+            }        
+        }        
+    }
+    
+    static private class FaultCallbackHandler implements CallbackHandler{
+
+        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+            for(int i=0;i<callbacks.length;i++){
+                if(callbacks[i] instanceof NameCallback){
+                    NameCallback nc = (NameCallback)callbacks[i];
+                    nc.setName("leo");
+                }
+                else if(callbacks[i] instanceof PasswordCallback){
+                    PasswordCallback pc = (PasswordCallback)callbacks[i];
+                    pc.setPassword("password".toCharArray());
+                }
+                else
+                {
+                    throw new Error(callbacks[i].getClass().toString());
+                }
+            }        
+        }        
+    }
+}

Propchange: harmony/enhanced/classlib/branches/java6/modules/auth/src/test/java/common/org/apache/harmony/auth/tests/module/LdapLoginModuleTest.java
------------------------------------------------------------------------------
    svn:eol-style = native