Package org.apache.geronimo.security.jaas.client

Source Code of org.apache.geronimo.security.jaas.client.JaasLoginCoordinator

/**
*
* Copyright 2003-2005 The Apache Software Foundation
*
*  Licensed 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.geronimo.security.jaas.client;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.apache.geronimo.kernel.Kernel;
import org.apache.geronimo.kernel.KernelRegistry;
import org.apache.geronimo.kernel.GBeanNotFoundException;
import org.apache.geronimo.security.jaas.server.JaasSessionId;
import org.apache.geronimo.security.jaas.server.JaasLoginModuleConfiguration;
import org.apache.geronimo.security.jaas.LoginModuleControlFlag;
import org.apache.geronimo.security.jaas.LoginUtils;
import org.apache.geronimo.security.jaas.server.JaasLoginServiceMBean;
import org.apache.geronimo.security.remoting.jmx.JaasLoginServiceRemotingClient;


/**
* A LoginModule implementation which connects to a Geronimo server under
* the covers, and uses Geronimo realms to resolve the login.  It handles a
* mix of client-side and server-side login modules.  It treats any client
* side module as something it should manage and execute, while a server side
* login module would be managed and executed by the Geronimo server.
* <p/>
* Note that this can actually be run from within a Geronimo server, in which
* case the client/server distinction is somewhat less important, and the
* communication is optimized by avoiding network traffic.
*
* @version $Rev: 389907 $ $Date: 2006-03-30 00:16:54 +0200 (Thu, 30 Mar 2006) $
*/
public class JaasLoginCoordinator implements LoginModule {
    public final static String OPTION_HOST = "host";
    public final static String OPTION_PORT = "port";
    public final static String OPTION_KERNEL = "kernel";
    public final static String OPTION_REALM = "realm";
    public final static String OPTION_SERVICENAME = "serviceName";
    public final static String OPTION_SERVICE_INSTANCE = "serviceInstance";
    private String serverHost;
    private int serverPort;
    private String realmName;
    private String kernelName;
    private ObjectName serviceName;
    private JaasLoginServiceMBean service;
    private CallbackHandler handler;
    private Subject subject;
    private JaasSessionId sessionHandle;
    private LoginModuleProxy[] proxies;
    private final Map sharedState = new HashMap();


    public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
        serverHost = (String) options.get(OPTION_HOST);
        Object port = options.get(OPTION_PORT);
        if (port != null) {
            serverPort = Integer.parseInt((String) port);
        }
        realmName = (String) options.get(OPTION_REALM);
        kernelName = (String) options.get(OPTION_KERNEL);
        try {
            String s = (String) options.get(OPTION_SERVICENAME);
            serviceName = s != null ? new ObjectName(s) : null;
        } catch (MalformedObjectNameException e) {
            throw new IllegalArgumentException("option " + OPTION_SERVICENAME + "is not a valid ObjectName: " + options.get(OPTION_SERVICENAME));
        }
        if (port != null || kernelName != null) {
            service = connect();
        } else {
            //primarily for testing without a kernel
            service = (JaasLoginServiceMBean) options.get(OPTION_SERVICE_INSTANCE);
        }
        handler = callbackHandler;
        if (subject == null) {
            this.subject = new Subject();
        } else {
            this.subject = subject;
        }
    }

    public boolean login() throws LoginException {
        sessionHandle = service.connectToRealm(realmName);
        JaasLoginModuleConfiguration[] config = service.getLoginConfiguration(sessionHandle);
        proxies = new LoginModuleProxy[config.length];

        for (int i = 0; i < proxies.length; i++) {
            if (config[i].isServerSide()) {
                proxies[i] = new ServerLoginProxy(config[i].getFlag(), subject, i, service, sessionHandle);
            } else {
                LoginModule source = config[i].getLoginModule(JaasLoginCoordinator.class.getClassLoader());
                if (config[i].isWrapPrincipals()) {
                    proxies[i] = new WrappingClientLoginModuleProxy(config[i].getFlag(), subject, source, config[i].getLoginDomainName(), realmName);
                } else {
                    proxies[i] = new ClientLoginModuleProxy(config[i].getFlag(), subject, source);
                }
            }
            proxies[i].initialize(subject, handler, sharedState, config[i].getOptions());
            syncSharedState();
        }
        return performLogin();
    }

    public boolean commit() throws LoginException {
        for (int i = 0; i < proxies.length; i++) {
            proxies[i].commit();
            syncSharedState();
            syncPrincipals();
        }
        subject.getPrincipals().add(service.loginSucceeded(sessionHandle));
        return true;
    }

    public boolean abort() throws LoginException {
        try {
            for (int i = 0; i < proxies.length; i++) {
                proxies[i].abort();
                syncSharedState();
            }
        } finally {
            service.loginFailed(sessionHandle);
        }
        clear();
        return true;
    }

    public boolean logout() throws LoginException {
        try {
            for (int i = 0; i < proxies.length; i++) {
                proxies[i].logout();
                syncSharedState();
            }
        } finally {
            service.logout(sessionHandle);
        }
        clear();
        return true;
    }

    private void clear() {
        service = null;
        serverHost = null;
        serverPort = 0;
        realmName = null;
        kernelName = null;
        service = null;
        handler = null;
        subject = null;
        sessionHandle = null;
        proxies = null;
    }

    private JaasLoginServiceMBean connect() {
        if (serverHost != null && serverPort > 0) {
            return JaasLoginServiceRemotingClient.create(serverHost, serverPort);
        } else {
            Kernel kernel = KernelRegistry.getKernel(kernelName);
            try {
                return (JaasLoginServiceMBean) kernel.getGBean(serviceName);
            } catch (GBeanNotFoundException e) {
                IllegalStateException illegalStateException = new IllegalStateException();
                illegalStateException.initCause(e);
                throw illegalStateException;
            }
        }
    }

    /**
     * See http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html
     *
     * @return
     * @throws LoginException
     */
    private boolean performLogin() throws LoginException {
        Boolean success = null;
        Boolean backup = null;

        for (int i = 0; i < proxies.length; i++) {
            LoginModuleProxy proxy = proxies[i];
            boolean result = proxy.login();
            syncSharedState();

            if (proxy.getControlFlag() == LoginModuleControlFlag.REQUIRED) {
                if (success == null || success.booleanValue()) {
                    success = result ? Boolean.TRUE : Boolean.FALSE;
                }
            } else if (proxy.getControlFlag() == LoginModuleControlFlag.REQUISITE) {
                if (!result) {
                    return false;
                } else if (success == null) {
                    success = Boolean.TRUE;
                }
            } else if (proxy.getControlFlag() == LoginModuleControlFlag.SUFFICIENT) {
                if (result && (success == null || success.booleanValue())) {
                    return true;
                }
            } else if (proxy.getControlFlag() == LoginModuleControlFlag.OPTIONAL) {
                if (backup == null || backup.booleanValue()) {
                    backup = result ? Boolean.TRUE : Boolean.FALSE;
                }
            }
        }
        // all required and requisite modules succeeded, or at least one required module failed
        if (success != null) {
            return success.booleanValue();
        }
        // no required or requisite modules, no sufficient modules succeeded, fall back to optional modules
        if (backup != null) {
            return backup.booleanValue();
        }
        // perhaps only a sufficient module, and it failed
        return false;
    }

    private void syncSharedState() throws LoginException {
        Map map = service.syncShareState(sessionHandle, LoginUtils.getSerializableCopy(sharedState));
        sharedState.putAll(map);
    }

    private void syncPrincipals() throws LoginException {
        Set principals = service.syncPrincipals(sessionHandle, subject.getPrincipals());
        subject.getPrincipals().addAll(principals);
    }
}
TOP

Related Classes of org.apache.geronimo.security.jaas.client.JaasLoginCoordinator

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.