All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.enterprise.security.jauth.ConfigFile Maven / Gradle / Ivy

There is a newer version: 4.1.2.181
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.security.jauth;

import com.sun.enterprise.security.jmac.config.ConfigParser;
import com.sun.enterprise.security.jmac.config.GFServerConfigProvider;
import java.io.*;
import java.util.*;

import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.AppConfigurationEntry;

import com.sun.logging.LogDomains;

/**
 * This is a default file-based AuthConfig implementation.
 *
 * @version %I%, %G%
 */
class ConfigFile extends AuthConfig {

    // indicates the age of the configuration approximately in
    // terms of the number of times refresh has been called
    private int epoch;

    // parser class name
    private String parserClassName;

    // parser
    private ConfigParser parser;

    // package private for ConfigFileParser
    static final String CLIENT = "client";
    static final String SERVER = "server";

    private static final String DEFAULT_HANDLER_CLASS =
        "com.sun.enterprise.security.jmac.callback.ContainerCallbackHandler";

    private static final String DEFAULT_PARSER_CLASS =
	"com.sun.enterprise.security.jmac.config.ConfigDomainParser";

    private static final Logger logger = LogDomains.getLogger(ConfigFile.class, LogDomains.SECURITY_LOGGER);
    ConfigFile() throws IOException {
	String propertyValue = System.getProperty("config.parser");
	if (propertyValue == null) {
	    parserClassName = DEFAULT_PARSER_CLASS;
	} else {
	    parserClassName = propertyValue;
	}
	this.epoch = 1;
	parser = ConfigFile.loadParser(parserClassName);
        parser.initialize(null);
    }

    /**
     * Get a default ClientAuthContext.
     *
     * @return an instance of ConfigClient.
     */
    public ClientAuthContext getClientAuthContext(String intercept,
						String id,
						AuthPolicy requestPolicy,
						AuthPolicy responsePolicy,
						CallbackHandler handler)
		throws AuthException {

	ConfigFile.Entry[] entries = getEntries(intercept,
						id,
						requestPolicy,
						responsePolicy,
						CLIENT);
	if (entries == null || entries.length == 0) {
	    return null;
	}

	// instantiate and initialize modules up front as well

	if (handler == null) {
	    handler = ConfigFile.loadDefaultCallbackHandler();
	} else if (handler instanceof DependentCallbackHandler) { 
	    handler = new DelegatingHandler(handler);
        }

	for (int i = 0; i < entries.length; i++) {
	    entries[i].module = ConfigFile.createModule(entries[i], handler);
	}

	return new ConfigClient(entries);
    }

    /**
     * Get a default ServerAuthContext.
     *
     * @return an instance of ConfigServer.
     */
    public ServerAuthContext getServerAuthContext(String intercept,
						String id,
						AuthPolicy requestPolicy,
						AuthPolicy responsePolicy,
						CallbackHandler handler)
		throws AuthException {

	ConfigFile.Entry[] entries = getEntries(intercept,
						id,
						requestPolicy,
						responsePolicy,
						SERVER);
	if (entries == null || entries.length == 0) {
	    return null;
	}

	// instantiate and initialize modules up front as well

	if (handler == null) {
	    handler = ConfigFile.loadDefaultCallbackHandler();
	} else if (handler instanceof DependentCallbackHandler) { 
	    handler = new DelegatingHandler(handler);
        }

	for (int i = 0; i < entries.length; i++) {
	    entries[i].module = ConfigFile.createModule(entries[i], handler);
	}

	return new ConfigServer(entries);
    }

    public void refresh() throws AuthException {
	synchronized (this) {
	    ConfigParser nextParser;
	    int next = this.epoch + 1;
	    try {
		nextParser = ConfigFile.loadParser(parserClassName);
	    } catch (IOException ioe) {
		throw new AuthException(ioe.toString());
	    }
	    this.epoch = (next == 0 ? 1 : next);
	    parser = nextParser;
	}
    }

    private ConfigFile.Entry[] getEntries(String intercept,
				String id,
				AuthPolicy requestPolicy,
				AuthPolicy responsePolicy,
				String type) {

	// get the parsed module config and DD information

	Map configMap;

	synchronized (parser) {
	    configMap = parser.getConfigMap();
	}

	if (configMap == null) {
	    return null;
	}
	
	// get the module config info for this intercept

	GFServerConfigProvider.InterceptEntry intEntry = (GFServerConfigProvider.InterceptEntry)configMap.get(intercept);
	if (intEntry == null || intEntry.getIdMap() == null) {
	    if (logger != null && logger.isLoggable(Level.FINE)) {
 		logger.fine("module config has no IDs configured for [" +
				intercept +
				"]");
	    }
	    return null;
	}

	// look up the DD's provider ID in the module config

	GFServerConfigProvider.IDEntry idEntry = null;
	if (id == null || (idEntry = (GFServerConfigProvider.IDEntry)intEntry.getIdMap().get(id)) == null) {

	    // either the DD did not specify a provider ID,
	    // or the DD-specified provider ID was not found
	    // in the module config.
	    //
	    // in either case, look for a default ID in the module config

	    if (logger != null && logger.isLoggable(Level.FINE)) {
 		logger.fine("DD did not specify ID, " +
				"or DD-specified ID for [" +
				intercept +
				"] not found in config -- " +
				"attempting to look for default ID");
	    }

	    String defaultID;
	    if (CLIENT.equals(type)) {
		defaultID = intEntry.getDefaultClientID();
	    } else {
		defaultID = intEntry.getDefaultServerID();
	    }

	    idEntry = (GFServerConfigProvider.IDEntry)intEntry.getIdMap().get(defaultID);
	    if (idEntry == null) {

		// did not find a default provider ID

		if (logger != null && logger.isLoggable(Level.FINE)) {
                    logger.fine("no default config ID for [" +
					intercept +
					"]");
		}
		return null;
	    }
	}

	// we found the DD provider ID in the module config
	// or we found a default module config

	// check provider-type
	if (idEntry.getType().indexOf(type) < 0) {
	    if (logger != null && logger.isLoggable(Level.FINE)) {
 		logger.fine("request type [" +
				type +
				"] does not match config type [" +
				idEntry.getType() +
				"]");
	    }
	    return null;
	}

	// check whether a policy is set
        AuthPolicy reqP, respP;
        if(requestPolicy != null || responsePolicy != null) {
            reqP = requestPolicy;
            respP = responsePolicy;
        } else if(idEntry.getRequestPolicy() != null || idEntry.getResponsePolicy() != null) {
            //default
            reqP = new AuthPolicy(idEntry.getRequestPolicy());
            respP = new AuthPolicy(idEntry.getResponsePolicy());
        } else {
            // optimization: if policy was not set, return null
	    if (logger != null && logger.isLoggable(Level.FINE)) {
 		logger.fine("no policy applies");
	    }
	    return null;
	}

	// return the configured modules with the correct policies

//	ConfigFile.Entry[] entries = new Entry[idEntry.modules.size()];
        ConfigFile.Entry[] entries = new Entry[1];
	for (int i = 0; i < entries.length; i++) {
// Login Bridge profile?
//	    AppConfigurationEntry aEntry =
//				(AppConfigurationEntry)idEntry.modules.get(i);
	    entries[i] = new ConfigFile.Entry(reqP,
					respP,
					idEntry.getModuleClassName(),
					AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
					idEntry.getOptions());
	}
	    
	if (logger != null && logger.isLoggable(Level.FINE)) {
 		logger.fine("getEntries found " +
			entries.length +
			" entries for: " +
			intercept +
			" -- "
			+ id);


            for (int i = 0; i < entries.length; i++) {
                    logger.fine("Entry " + (i+1) + ":" +
                        "\n    module class: " + entries[i].getLoginModuleName() +
                        "\n    flag: " + entries[i].getControlFlag() +
                        "\n    options: " + entries[i].getOptions() +
                        "\n    request policy: " + entries[i].requestPolicy +
                        "\n    response policy: " + entries[i].responsePolicy);
            }

	}

	return entries;
    }

    /**
     * get a custom config file parser
     *
     * XXX custom file that can be used in place of [domain|sun-acc].xml
     */
    private static ConfigParser loadParser(String className)
		throws IOException {
	try {

	    final String finalClassName = className;
	    final ClassLoader finalLoader = AuthConfig.getClassLoader();

	    return (ConfigParser)java.security.AccessController.doPrivileged
		(new java.security.PrivilegedExceptionAction() {
		public Object run() throws Exception {
		    Class c = Class.forName(finalClassName,true,finalLoader);
		    return c.newInstance();
		}
	    });
	} catch (java.security.PrivilegedActionException pae) {
            IOException iex = new IOException(pae.getException().toString());
            iex.initCause(pae.getException());
            throw iex;
	}
    }

    /**
     * get the default callback handler
     */
    private static CallbackHandler loadDefaultCallbackHandler()
		throws AuthException {

        // get the default handler class
        try {

            final ClassLoader finalLoader = AuthConfig.getClassLoader();

            return (CallbackHandler)
                java.security.AccessController.doPrivileged
                (new java.security.PrivilegedExceptionAction() {
                public Object run() throws Exception {
 
		    String className = DEFAULT_HANDLER_CLASS;
		    Class c = Class.forName(className,
					    true,
					    finalLoader);
                    return c.newInstance();
                }
            });
        } catch (java.security.PrivilegedActionException pae) {
            AuthException aex = new AuthException(pae.getException().toString());
            aex.initCause(pae.getException());
            throw aex;
        }
    }

    /**
     * Instantiate+initialize module class
     */
    private static Object createModule(ConfigFile.Entry entry,
					CallbackHandler handler)
		throws AuthException {
	try {

	    // instantiate module using no-arg constructor

	    Object newModule = entry.newInstance();

	    // initialize module

	    Object[] initArgs = { entry.getRequestPolicy(),
				entry.getResponsePolicy(),
				handler,
				entry.getOptions() };

            try {
                Method initMethod = newModule.getClass().getMethod(AuthContext.INIT,
                        AuthPolicy.class, AuthPolicy.class, CallbackHandler.class,
                        Map.class);
                initMethod.invoke(newModule, initArgs);
		// return the new module
		return newModule;
            } catch(Exception ex) {
                throw new SecurityException("could not invoke " +
                        AuthContext.INIT +
                        " method in module: " + 
                        newModule.getClass().getName() + " " + ex, ex);
            }

	} catch (Exception e) {
	    if (e instanceof AuthException) {
		throw (AuthException)e;
	    }
	    AuthException ae = new AuthException();
	    ae.initCause(e);
	    throw ae;
	}
    }

    /**
     * Class representing a single AuthModule entry configured
     * for an ID, interception point, and stack.
     *
     * 

An instance of this class contains the same * information as its superclass, AppConfigurationEntry. * It additionally stores the request and response policy assigned * to this module. * *

This class also provides a way for a caller to obtain * an instance of the module listed in the entry by invoking * the newInstance method. */ static class Entry extends javax.security.auth.login.AppConfigurationEntry { // for loading modules private static final Class[] PARAMS = { }; private static final Object[] ARGS = { }; private AuthPolicy requestPolicy; private AuthPolicy responsePolicy; Object module = null; // convenience location to store instance - // package private for AuthContext /** * Construct a ConfigFile entry. * *

An entry encapsulates a single module and its related * information. * * @param requestPolicy the request policy assigned to the module * listed in this entry, which may be null. * * @param responsePolicy the response policy assigned to the module * listed in this entry, which may be null. * * @param moduleClass the fully qualified class name of the module. * * @param flag the module control flag. This value must either * be REQUIRED, REQUISITE, SUFFICIENT, or OPTIONAL. * * @param options the options configured for this module. */ Entry(AuthPolicy requestPolicy, AuthPolicy responsePolicy, String moduleClass, AppConfigurationEntry.LoginModuleControlFlag flag, Map options) { super(moduleClass, flag, options); this.requestPolicy = requestPolicy; this.responsePolicy = responsePolicy; } /** * Return the request policy assigned to this module. * * @return the policy, which may be null. */ AuthPolicy getRequestPolicy() { return requestPolicy; } /** * Return the response policy assigned to this module. * * @return the policy, which may be null. */ AuthPolicy getResponsePolicy() { return responsePolicy; } /** * Return a new instance of the module contained in this entry. * *

The default implementation of this method attempts * to invoke the default no-args constructor of the module class. * This method may be overridden if a different constructor * should be invoked. * * @return a new instance of the module contained in this entry. * * @exception AuthException if the instantiation failed. */ Object newInstance() throws AuthException { try { final ClassLoader finalLoader= AuthConfig.getClassLoader(); String clazz = getLoginModuleName(); Class c = Class.forName(clazz, true, finalLoader); java.lang.reflect.Constructor constructor = c.getConstructor(PARAMS); return constructor.newInstance(ARGS); } catch (Exception e) { AuthException ae = new AuthException(); ae.initCause(e); throw ae; } } } /** * parsed Intercept entry */ /* static class InterceptEntry { String defaultClientID; String defaultServerID; HashMap idMap; InterceptEntry(String defaultClientID, String defaultServerID, HashMap idMap) { this.defaultClientID = defaultClientID; this.defaultServerID = defaultServerID; this.idMap = idMap; } }*/ /** * parsed ID entry */ /*static class IDEntry { private String type; // provider type (client, server, client-server) private AuthPolicy requestPolicy; private AuthPolicy responsePolicy; private ArrayList modules; IDEntry(String type, AuthPolicy requestPolicy, AuthPolicy responsePolicy, ArrayList modules) { this.type = type; this.modules = modules; this.requestPolicy = requestPolicy; this.responsePolicy = responsePolicy; } // XXX delete this later IDEntry(String type, String requestPolicy, String responsePolicy, ArrayList modules) { this.type = type; if (requestPolicy != null) { this.requestPolicy = new AuthPolicy(AuthPolicy.SOURCE_AUTH_SENDER, true, // recipient-auth true); // beforeContent } if (responsePolicy != null) { this.responsePolicy = new AuthPolicy(AuthPolicy.SOURCE_AUTH_CONTENT, true, // recipient-auth false); // beforeContent } this.modules = modules; } } */ /** * Default implementation of ClientAuthContext. */ private static class ConfigClient implements ClientAuthContext { // class that does all the work private AuthContext context; ConfigClient(Entry[] entries) throws AuthException { context = new AuthContext(entries, logger); } public void secureRequest(AuthParam param, Subject subject, Map sharedState) throws AuthException { // invoke modules Object[] args = { param, subject, sharedState }; context.invoke(AuthContext.SECURE_REQUEST, args); } public void validateResponse(AuthParam param, Subject subject, Map sharedState) throws AuthException { // invoke modules Object[] args = { param, subject, sharedState }; context.invoke(AuthContext.VALIDATE_RESPONSE, args); } public void disposeSubject(Subject subject, Map sharedState) throws AuthException { // invoke modules Object[] args = { subject, sharedState }; context.invoke(AuthContext.DISPOSE_SUBJECT, args); } } /** * Default implementation of ServerAuthContext. */ private static class ConfigServer implements ServerAuthContext { // class that does all the work private AuthContext context; ConfigServer(Entry[] entries) throws AuthException { context = new AuthContext(entries, logger); } public void validateRequest(AuthParam param, Subject subject, Map sharedState) throws AuthException { // invoke modules Object[] args = { param, subject, sharedState }; context.invoke(AuthContext.VALIDATE_REQUEST, args); } public void secureResponse(AuthParam param, Subject subject, Map sharedState) throws AuthException { // invoke modules Object[] args = { param, subject, sharedState }; context.invoke(AuthContext.SECURE_RESPONSE, args); } public void disposeSubject(Subject subject, Map sharedState) throws AuthException { // invoke modules Object[] args = { subject, sharedState }; context.invoke(AuthContext.DISPOSE_SUBJECT, args); } public boolean managesSessions(Map sharedState) throws AuthException { // invoke modules Object[] args = { sharedState }; Object[] rValues = null; try { rValues = context.invoke(AuthContext.MANAGES_SESSIONS, args); } catch (AuthException ae) { // this new method may not be implemeneted // by old modules if (!(ae.getCause() instanceof NoSuchMethodException)) { throw ae; } } boolean rvalue = false; for (int i=0; rValues != null && i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy