Package com.sun.jini.test.spec.security.security

Source Code of com.sun.jini.test.spec.security.security.VerifyCodebaseIntegrityTest

/*
* 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 com.sun.jini.test.spec.security.security;

import java.util.logging.Level;

// jav
import java.util.ArrayList;
import java.io.File;
import java.net.URL;
import java.net.MalformedURLException;

// net.jini
import net.jini.security.Security;

// com.sun.jini
import com.sun.jini.qa.harness.TestException;
import com.sun.jini.qa.harness.QATest;
import com.sun.jini.test.spec.security.util.Util;
import com.sun.jini.test.spec.security.util.BaseIntegrityVerifier;
import com.sun.jini.test.spec.security.util.TrueIntegrityVerifier;
import com.sun.jini.test.spec.security.util.FalseIntegrityVerifier;
import com.sun.jini.test.spec.security.util.FakeClassLoader;


/**
* <pre>
* Purpose
*   This test verifies the following:
*     'verifyCodebaseIntegrity' static method of Security class verifies that
*     the URLs in the specified codebase all provide content integrity, using
*     verifiers from the specified class loader. If a null class loader is
*     specified, the context class loader of the current thread is used
*     instead. An ordered list of integrity verifiers is obtained as specified
*     below. For each URL (if any) in the specified codebase,
*     IntegrityVerifier.providesIntegrity method of each verifier is called (in
*     order) with the URL. If any verifier call returns true, the URL is
*     verified (and no further verifiers are called with that URL). If all of
*     the verifier calls return false for a URL, this method throws a
*     SecurityException. If all of the URLs are verified, this method returns
*     normally. The list of integrity verifiers is obtained as follows. For
*     each resource named META-INF/services/net.jini.security.IntegrityVerifier
*     that is visible to the specified class loader, the contents of the
*     resource are parsed as UTF-8 text to produce a list of class names.
*     The resource must contain a list of fully qualified class names, one per
*     line. Space and tab characters surrounding each name, as well as blank
*     lines, are ignored.  The comment character is '#'; all characters on each
*     line starting with the first comment character are ignored. Each class
*     name (that is not a duplicate of any previous class name) is loaded
*     through the specified class loader, and the resulting class must be
*     assignable to IntegrityVerifier and have a public no-argument
*     constructor. The constructor is invoked to create an integrity verifier
*     instance. This method throws MalformedURLException if the specified
*     codebase contains an invalid URL.
*
* Test Cases
*   Case 1: actions described below
*   Case 2: Set ClassLoader for current thread to FakeClassLoader1 with empty
*           array of URLs. During the test construct each time
*           FakeClassLoader2, do not set it as ClassLoader for current thread,
*           and invoke 'verifyCodebaseIntegrity' with constructed
*           FakeClassLoader2. In this case checks will be made that tested
*           integrity verifiers where loaded through FakeClassLoader2 and not
*           FakeClassLoader1.
*   Case 3: Case1 for MultiURL
*   Case 4: Case2 for MultiURL
*
* Infrastructure
*   This test requires the following infrastructure:
*     Resource1 - META-INF/services/net.jini.security.IntegrityVerifier
*             resource containing TrueIntegrityVerifier and
*             FalseIntegrityVerifier in this order
*     Resource2 - META-INF/services/net.jini.security.IntegrityVerifier
*             resource containing FalseIntegrityVerifier
*     Resource3 - META-INF/services/net.jini.security.IntegrityVerifier
*             resource containing FalseIntegrityVerifier and
*             TrueIntegrityVerifier in this order
*     TestURL - URL string for which 'providesIntegrity' method of any
*             integrity verifier containing in jsk-resources.jar will return
*             false
*     MultiURL - String containing several URL strings
*     WrongURL - wrong URL string
*     TrueIntegrityVerifier - TrustVerifier whose 'providesIntegrity' method
*             always returns true
*     FalseIntegrityVerifier - TrustVerifier whose 'providesIntegrity' method
*             always returns false
*     FakeClassLoader - test class loader, which is actually a URLClassLoader
*
* Action
*   For each test case the test performs the following steps:
*     1) invoke 'Security.verifyCodebaseIntegrity' method with WrongURL string
*     2) assert that MalformedURLException will be thrown
*     3) construct FakeClassLoader with Resource1 as a parameter and set it
*        as ClassLoader for the current thread
*     4) invoke 'Security.verifyCodebaseIntegrity(TestURL, null)'
*     5) assert that TrueIntegrityVerifier will be loaded through
*        FakeClassLoader
*     6) assert that FalseIntegrityVerifier will be loaded through
*        FakeClassLoader
*     7) assert that 'providesIntegrity' method of TrueIntegrityVerifier will
*        be invoked
*     8) assert that 'providesIntegrity' method of FalseIntegrityVerifier will
*        not be invoked
*     9) assert that method will return normally
*     10) construct FakeClassLoader with Resource2 as a parameter and set it
*         as ClassLoader for the current thread
*     11) invoke 'Security.verifyCodebaseIntegrity(TestURL, null)'
*     12) assert that FalseIntegrityVerifier will be loaded through
*         FakeClassLoader
*     13) assert that 'providesIntegrity' method of FalseIntegrityVerifier will
*         be invoked
*     14) assert that method will throw SecurityException
*     15) construct FakeClassLoader with Resource3 as a parameter and set it
*         as ClassLoader for the current thread
*     16) invoke 'Security.verifyCodebaseIntegrity(TestURL, null)'
*     17) assert that FalseIntegrityVerifier will be loaded through
*         FakeClassLoader
*     18) assert that TrueIntegrityVerifier will be loaded through
*         FakeClassLoader
*     19) assert that 'providesIntegrity' method of FalseIntegrityVerifier
*         will be invoked
*     20) assert that 'providesIntegrity' method of TrueIntegrityVerifier
*         will be invoked
*     21) assert that method will return normally
* </pre>
*/
public class VerifyCodebaseIntegrityTest extends QATest {

    /** Resource name method */
    protected static String resName =
            "META-INF/services/net.jini.security.IntegrityVerifier";

    /**
     * Array of classes whose 'providesIntegrity' methods are expected to be
     * called.
     */
    protected Class[] expCls = new Class[0];

    /**
     * Array of urls which are expected to be parameters for 'providesIntegrity'
     * methods.
     */
    protected URL[] expUrls = new URL[0];

    /** Expected result of iteration. */
    protected Class expRes;

    /**
     * This method performs all actions mentioned in class description.
     *
     */
    public void run() throws Exception {
        File jarFile = null;
        String[] wrongUrls = new String[] {
            "?:", "file:/fake.jar ?: file:/fake1.java" };
        String[] testUrls = new String[] {
            "http://fakehost:8080/bla-bla.java",
            "http://fh/bla1.java http://fh/bla2.java http://fh/bla3.java" };
        boolean[] useNullLoader = new boolean[] { true, false };
        Class[][] clNames = new Class[][] {
            new Class[] {
                TrueIntegrityVerifier.class,
                FalseIntegrityVerifier.class },
            new Class[] { FalseIntegrityVerifier.class },
            new Class[] {
                FalseIntegrityVerifier.class,
                TrueIntegrityVerifier.class } };
        ClassLoader testCl;

        for (int i = 0; i < useNullLoader.length; ++i) {
            logger.fine("=========== Check wrong URLs ===========");

            for (int j = 0; j < wrongUrls.length; ++j) {
                jarFile = Util.createResourceJar(resName,
                        new Class[] { Class.class });

                if (useNullLoader[i]) {
                    testCl = null;
                } else {
                    testCl = new FakeClassLoader(jarFile.toURI().toURL());
                }

                try {
                    callVerifyCodebaseIntegrity(wrongUrls[j], testCl);

                    // FAIL
                    throw new TestException(
                            "Method did not throw any exception while "
                            + "MalformedURLException was expected.");
                } catch (MalformedURLException mue) {
                    // PASS
                    logger.fine("MalformedURLException was thrown "
                            + "as expected.");
                } finally {
                    jarFile.delete();
                }
            }
            logger.fine("=========== Check correct URLs ===========");

            for (int j = 0; j < clNames.length; ++j) {
                logger.fine("========== Iteration #" + (j + 1)
                        + " ==========");
                logger.fine("Test integrity verifiers are: "
                        + Util.arrayToString(clNames[j]));

                for (int k = 0; k < testUrls.length; ++k) {
                    BaseIntegrityVerifier.initLists();
                    jarFile = Util.createResourceJar(resName, clNames[j]);
                    expRes = getExpRes(clNames[j], testUrls[k]);

                    if (useNullLoader[i]) {
                        testCl = null;
                    } else {
                        testCl = new FakeClassLoader(jarFile.toURI().toURL());
                    }
                    Thread.currentThread().setContextClassLoader(
                            new FakeClassLoader(jarFile.toURI().toURL()));

                    try {
                        callVerifyCodebaseIntegrity(testUrls[k], testCl);

                        if (expRes != null) {
                            // FAIL
                            throw new TestException(
                                    "Method returned normally while "
                                    + "SecurityException was expected "
                                    + "to be thrown.");
                        }

                        // PASS
                        logger.fine("Method returned normally "
                                + "as expected.");
                    } catch (SecurityException se) {
                        if (expRes == null) {
                            // FAIL
                            throw new TestException(
                                    "Method throws " + se
                                    + " exception while "
                                    + "normal return was expected.");
                        }

                        // PASS
                        logger.fine("Method threw " + se + " as expected.");
                    } finally {
                        jarFile.delete();
                    }

                    /*
                     * check that classes where loaded through the right
                     * classloader
                     */
                    Class[] loadedCls = null;

                    if (testCl == null) {
                        loadedCls = ((FakeClassLoader)
                                Thread.currentThread()
                                    .getContextClassLoader()).getClasses();
                    } else {
                        loadedCls = ((FakeClassLoader) testCl).getClasses();
                    }
                    Class[] notLoadedCls = Util.containsClasses(
                            loadedCls, clNames[j]);

                    if (notLoadedCls != null) {
                        // FAIL
                        throw new TestException(
                                "The following classes was not loaded "
                                + " through expected class loader: "
                                + Util.arrayToString(notLoadedCls));
                    }

                    // PASS
                    logger.fine("All requested classes were loaded through "
                                + "expected class loader.");

                    // check that passed parameters where correct
                    Class[] classes = BaseIntegrityVerifier.getClasses();
                    URL[] actUrls = BaseIntegrityVerifier.getUrls();
                    String resStr = checkURLs(actUrls, classes);

                    if (resStr != null) {
                        // FAIL
                        throw new TestException(resStr);
                    }

                    // PASS
                    logger.fine("All classes got expected urls.");
                }
            }
        }
    }

    /**
     * Invokes 'Security.verifyCodebaseIntegrity' method with given argument.
     * Rethrows any exception thrown by 'verifyCodebaseIntegrity' method.
     *
     * @param codebase space-separated list of URLs for
     *        'verifyCodebaseIntegrity' method
     * @param loader ClassLoader for 'verifyCodebaseIntegrity' method
     */
    protected void callVerifyCodebaseIntegrity(String codebase,
            ClassLoader loader) throws MalformedURLException {
        logger.fine("Call 'Security.verifyCodebaseIntegrity([" + codebase
                + "], " + loader + ")'.");
        Security.verifyCodebaseIntegrity(codebase, loader);
    }

    /**
     * Return Class representing expected result - if non-null, that means
     * that SecurityException must be thrown. Fills array of
     * classes whose 'providesIntegrity' methods are expected to be called.
     *
     * @param clNames array of classes for which evaluate the result
     * @param str URLs string for which get expected results
     * @throws MalformedURLException if any of the URLs are invalid
     */
    protected Class getExpRes(Class[] clNames, String str)
            throws MalformedURLException {
        ArrayList clList = new ArrayList();
        expUrls = Util.strToUrls(str);

        for (int i = 0; i < clNames.length; ++i) {
            clList.add(clNames[i]);

            if (clNames[i] == TrueIntegrityVerifier.class) {
                expCls = (Class []) clList.toArray(new Class[clList.size()]);
                return null;
            }
        }
        expCls = (Class []) clList.toArray(new Class[clList.size()]);
        return SecurityException.class;
    }

    /**
     * Checks expected set of URLs with actual one.
     * We need to check that all expected classes got all expected URLs.
     *
     * @param actUrls actual set of URLs
     * @param actCls actual set of classes
     * @return null if sets are equal or non-null string indicating error
     */
    protected String checkURLs(URL[] actUrls, Class[] actCls) {
        if ((actUrls.length == 0 && expUrls.length != 0)
                && (actUrls.length != 0 && expUrls.length == 0)) {
            // FAIL
            return "Actual set of URLs is: [" + Util.arrayToString(actUrls)
                    + "] while [" + Util.arrayToString(expUrls)
                    + "] was expected.";
        }

        if (expRes != null) {
            /*
             * We just need to check that at least one of expected urls was
             * passed as a parameter.
             */
            for (int i = 0; i < expUrls.length; ++i) {
                if (expUrls[i].equals(actUrls[0])) {
                    Class[] cls = Util.containsClasses(actCls, expCls);

                    if (cls != null) {
                        // FAIL
                        return "'providesIntegrity' methods of the following "
                                + "classes were not called with " + expUrls[i]
                                + " as a parameter: " + Util.arrayToString(cls);
                    }

                    // PASS
                    return null;
                }
            }

            // FAIL
            return "No 'providesIntegrity' methods where called with one of "
                    + Util.arrayToString(expUrls) + " URLs.";
        }

        for (int i = 0; i < expUrls.length; ++i) {
            ArrayList clList = new ArrayList();

            // get list of classes which got expUrls[i] as a parameter
            for (int j = 0; j < actUrls.length; ++j) {
                if (expUrls[i].equals(actUrls[j])) {
                    clList.add(actCls[j]);
                }
            }

            // check what classes did not get expected url
            Class[] cls = Util.containsClasses((Class []) clList.toArray(
                    new Class[clList.size()]), expCls);

            if (cls != null) {
                // FAIL
                return "'providesIntegrity' methods of the following "
                        + "classes were not called with " + expUrls[i]
                        + " as a parameter: " + Util.arrayToString(cls);
            }
        }

        // PASS
        return null;
    }
}
TOP

Related Classes of com.sun.jini.test.spec.security.security.VerifyCodebaseIntegrityTest

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.