Package org.apache.geronimo.security

Source Code of org.apache.geronimo.security.ContextManager$Context

/**
*
* Copyright 2003-2004 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;

import java.io.Serializable;
import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.Subject;
import javax.security.jacc.EJBRoleRefPermission;

import org.apache.geronimo.security.realm.providers.GeronimoCallerPrincipal;


/**
* @version $Rev: 355877 $ $Date: 2005-12-11 03:48:27 +0100 (Sun, 11 Dec 2005) $
*/
public class ContextManager {
    private static ThreadLocal currentCallerId = new ThreadLocal();
    private static ThreadLocal currentCaller = new ThreadLocal();
    private static ThreadLocal nextCaller = new ThreadLocal();
    private static Map subjectContexts = new IdentityHashMap();
    private static Map subjectIds = new Hashtable();
    private static long nextSubjectId = System.currentTimeMillis();

    private static SecretKey key;
    private static String algorithm;
    private static String password;

    public static final GeronimoSecurityPermission GET_CONTEXT = new GeronimoSecurityPermission("getContext");
    public static final GeronimoSecurityPermission SET_CONTEXT = new GeronimoSecurityPermission("setContext");

    static {
        password = "secret";
        ContextManager.setAlgorithm("HmacSHA1");
    }

    /**
     * After a login, the client is left with a relatively empty Subject, while
     * the Subject used by the server has more important contents.  This method
     * lets a server-side component acting as an authentication client (such
     * as Tocmat/Jetty) access the fully populated server-side Subject.
     */
    public static Subject getServerSideSubject(Subject clientSideSubject) {
        Set set = clientSideSubject.getPrincipals(IdentificationPrincipal.class);
        if(set == null || set.size() == 0) {
            return null;
        }
        IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
        return getRegisteredSubject(idp.getId());
    }

    public static void setCurrentCallerId(Serializable id) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(SET_CONTEXT);

        currentCallerId.set(id);
    }

    public static Serializable getCurrentCallerId() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        return (Serializable) currentCallerId.get();
    }

    public static void setNextCaller(Subject subject) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(SET_CONTEXT);

        nextCaller.set(subject);
    }

    public static Subject getNextCaller() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        return (Subject) nextCaller.get();
    }

    public static void setCurrentCaller(Subject subject) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(SET_CONTEXT);

        currentCaller.set(subject);
    }

    public static Subject getCurrentCaller() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        return (Subject) currentCaller.get();
    }

    public static AccessControlContext getCurrentContext() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        Subject currentSubject = (Subject) currentCaller.get();
        assert currentSubject != null : "No current caller";
        Context context = (Context) subjectContexts.get(currentSubject);

        assert context != null : "No registered context";

        return context.context;
    }

    public static Principal getCurrentPrincipal(Subject callerSubject) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        if (callerSubject == null) {
            return new Principal() {
                public String getName() {
                    return "";
                }
            };
        }
        Context context = (Context) subjectContexts.get(callerSubject);

        assert context != null : "No registered context";

        return context.principal;
    }

    public static SubjectId getCurrentId() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        Context context = (Context) subjectContexts.get(currentCaller.get());

        assert context != null : "No registered context";

        return context.id;
    }

    public static SubjectId getSubjectId(Subject subject) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        Context context = (Context) subjectContexts.get(subject);

        return (context != null ? context.id : null);
    }

    public static boolean isCallerInRole(String EJBName, String role) {
        if (EJBName == null) throw new IllegalArgumentException("EJBName must not be null");
        if (role == null) throw new IllegalArgumentException("Role must not be null");

        try {
            Object caller = currentCaller.get();
            if (caller == null) return false;

            Context context = (Context) subjectContexts.get(currentCaller.get());

            assert context != null : "No registered context";

            context.context.checkPermission(new EJBRoleRefPermission(EJBName, role));
        } catch (AccessControlException e) {
            return false;
        }
        return true;
    }

    public static Subject getRegisteredSubject(SubjectId id) {
        return (Subject) subjectIds.get(id);
    }

    public static synchronized SubjectId registerSubject(Subject subject) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(SET_CONTEXT);

        if (subject == null) throw new IllegalArgumentException("Subject must not be null");

        AccessControlContext acc = (AccessControlContext) Subject.doAsPrivileged(subject, new PrivilegedAction() {
            public Object run() {
                return AccessController.getContext();
            }
        }, null);

        Context context = new Context();
        context.subject = subject;
        context.context = acc;
        Set principals = subject.getPrincipals(GeronimoCallerPrincipal.class);
        if (!principals.isEmpty()) {
            context.principal = (Principal) principals.iterator().next();
        } else if (!(principals = subject.getPrincipals(PrimaryRealmPrincipal.class)).isEmpty()) {
            context.principal = (PrimaryRealmPrincipal) principals.iterator().next();
        } else if (!(principals = subject.getPrincipals(RealmPrincipal.class)).isEmpty()) {
            context.principal = (RealmPrincipal) principals.iterator().next();
        } else if (!(principals = subject.getPrincipals()).isEmpty()) {
            context.principal = (Principal) principals.iterator().next();
        }
        Long id = new Long(nextSubjectId++);
        context.id = new SubjectId(id, hash(id));

        subjectIds.put(context.id, subject);
        subjectContexts.put(subject, context);

        return context.id;
    }

    public static synchronized void unregisterSubject(Subject subject) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(SET_CONTEXT);

        if (subject == null) throw new IllegalArgumentException("Subject must not be null");

        Context context = (Context) subjectContexts.get(subject);
        if (context == null) return;

        subjectIds.remove(context.id);
        subjectContexts.remove(subject);
    }

    /**
     * Obtain the thread's identifying principal.
     * <p/>
     * Clients should use <code>Subject.doAs*</code> to associate a Subject
     * with the thread's call stack.  It is this Subject that will be used for
     * authentication checks.
     * <p/>
     * Return a <code>IdentificationPrincipal</code>.  This kind of principal
     * is inserted into a subject if one uses one of the Geronimo LoginModules.
     * It is a secure id that identifies the Subject.
     *
     * @return the principal that identifies the Subject of this thread.
     * @see Subject#doAs(javax.security.auth.Subject, java.security.PrivilegedAction)
     * @see Subject#doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction)
     * @see Subject#doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction, java.security.AccessControlContext)
     * @see Subject#doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction, java.security.AccessControlContext)
     */
    public static IdentificationPrincipal getThreadPrincipal() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        Subject subject = Subject.getSubject(AccessController.getContext());
        if (subject != null) {
            Set set = subject.getPrincipals(IdentificationPrincipal.class);
            if (!set.isEmpty()) return (IdentificationPrincipal) set.iterator().next();
        }
        return null;
    }

    public static String getAlgorithm() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        return algorithm;
    }

    public static void setAlgorithm(String algorithm) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(SET_CONTEXT);

        ContextManager.algorithm = algorithm;

        key = new SecretKeySpec(password.getBytes(), algorithm);

        /**
         * Make sure that we can generate the  Mac.
         */
        try {
            Mac mac = Mac.getInstance(algorithm);
            mac.init(key);
        } catch (NoSuchAlgorithmException e) {
            assert false : "Should never have reached here";
        } catch (InvalidKeyException e) {
            assert false : "Should never have reached here";
        }
    }

    public static String getPassword() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(GET_CONTEXT);

        return password;
    }

    public static void setPassword(String password) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(SET_CONTEXT);

        ContextManager.password = password;

        key = new SecretKeySpec(password.getBytes(), algorithm);
    }

    private static byte[] hash(Long id) {
        long n = id.longValue();
        byte[] bytes = new byte[8];
        for (int i = 7; i >= 0; i--) {
            bytes[i] = (byte) (n);
            n >>>= 8;
        }

        try {
            Mac mac = Mac.getInstance(algorithm);
            mac.init(key);
            mac.update(bytes);

            return mac.doFinal();
        } catch (NoSuchAlgorithmException e) {
        } catch (InvalidKeyException e) {
        }
        assert false : "Should never have reached here";
        return null;
    }

    private static class Context {
        SubjectId id;
        AccessControlContext context;
        Subject subject;
        Principal principal;
    }

}
TOP

Related Classes of org.apache.geronimo.security.ContextManager$Context

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.