Package org.apache.harmony.auth.module

Source Code of org.apache.harmony.auth.module.LdapLoginModule

/*
*  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;
  }
}
TOP

Related Classes of org.apache.harmony.auth.module.LdapLoginModule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.