| /** |
| * Derby - Class org.apache.derbyTesting.functionTests.tests.lang.SecurityPolicyReloadingTest |
| * |
| * 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.derbyTesting.functionTests.tests.lang; |
| |
| import java.io.File; |
| import java.security.AccessControlException; |
| import java.sql.CallableStatement; |
| import java.sql.Connection; |
| import java.sql.SQLException; |
| import junit.framework.Test; |
| import org.apache.derbyTesting.junit.BaseJDBCTestCase; |
| import org.apache.derbyTesting.junit.BaseTestSuite; |
| import org.apache.derbyTesting.junit.DerbyConstants; |
| import org.apache.derbyTesting.junit.SecurityManagerSetup; |
| import org.apache.derbyTesting.junit.SupportFilesSetup; |
| import org.apache.derbyTesting.junit.TestConfiguration; |
| |
| /** |
| * Test the dynamic reloading of the security policy file while the |
| * engine is still running. |
| */ |
| public class SecurityPolicyReloadingTest extends BaseJDBCTestCase { |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // CONSTANTS |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| private static final String RELOADABLE_INITIAL_SOURCE_POLICY = "functionTests/tests/lang/SecurityPolicyReloadingTest.initial.policy"; |
| private static final String RELOADABLE_MODIFIED_SOURCE_POLICY = "functionTests/tests/lang/SecurityPolicyReloadingTest.modified.policy"; |
| private static final String UNRELOADABLE_SOURCE_POLICY = "functionTests/tests/lang/SecurityPolicyReloadingTest.unreloadable.policy"; |
| private static final String TARGET_POLICY = "server.policy"; |
| |
| private static final String NON_DBO_USER = "NON_DBO_USER"; |
| private static final String PASSWORD_TOKEN = "PASSWORD_TOKEN"; |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // INNER CLASSES |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // STATE |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // CONSTRUCTORS |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| public SecurityPolicyReloadingTest |
| ( |
| ) |
| { |
| super( "testPolicyReloading" ); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // JUnit MACHINERY |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| public static Test suite() |
| { |
| BaseTestSuite suite = |
| new BaseTestSuite("SecurityPolicyReloadingTest"); |
| |
| // The reloaded policy requires restricted property-reading permissions, |
| // which is easy to do if you can subdivide the protection domains by |
| // jar file but is not easy to do with all of the testing and server |
| // classes jumbled together in the same class tree. |
| if ( !TestConfiguration.loadingFromJars() ) { return suite; } |
| |
| suite.addTest( decorateTest() ); |
| |
| return suite; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // TEST DECORATION |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Add decorators to a test run. Context is established in the reverse order |
| * that decorators are declared here. That is, decorators compose in reverse |
| * order. The order of the setup methods is: |
| * |
| * <ul> |
| * <li>Copy security policy to visible location.</li> |
| * <li>Setup authorization-enabling properties.</li> |
| * <li>Install a security manager.</li> |
| * <li>Run the tests.</li> |
| * </ul> |
| */ |
| private static Test decorateTest() |
| { |
| Test test = new SecurityPolicyReloadingTest(); |
| |
| // |
| // Install a security manager using the initial policy file. |
| // |
| test = new SecurityManagerSetup(test, makeServerPolicyName()); |
| |
| // |
| // Set up authorization with a DBO and non-DBO user |
| // |
| test = TestConfiguration.sqlAuthorizationDecorator |
| ( |
| test, |
| new String[] { NON_DBO_USER }, |
| PASSWORD_TOKEN |
| ); |
| |
| // |
| // Copy over the initial policy file we want to use. |
| // |
| test = new SupportFilesSetup |
| ( |
| test, |
| null, |
| new String[] { getSourcePolicy() }, |
| null, |
| new String[] { makeTargetPolicyStub() } |
| ); |
| |
| // No need to run with default testing policy file because we install our |
| // own initial policy file. |
| test = SecurityManagerSetup.noSecurityManager(test); |
| return test; |
| } |
| |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // JUnit TESTS |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Verify that policy file reloading is allowed and forbidden as expected. |
| */ |
| public void testPolicyReloading() |
| throws Exception |
| { |
| //getTestConfiguration().setVerbosity( true ); |
| |
| doPolicyReloadingIsGranted(); |
| doPolicyReloadingIsNotGranted(); |
| } |
| |
| //////////////////////////////////////////////////// |
| // |
| // getPolicy() PRIVILEGE GRANTED |
| // |
| //////////////////////////////////////////////////// |
| |
| /** |
| * Verify that the DBA has the power to reload the security policy file and |
| * that a non-DBA does not have this power. |
| */ |
| private void doPolicyReloadingIsGranted() |
| throws Exception |
| { |
| dbaTest(); |
| nonDbaTest(); |
| } |
| |
| /** |
| * Verify that the DBA has the power to reload the security policy file. |
| */ |
| private void dbaTest() |
| throws Exception |
| { |
| Connection conn = openUserConnection( DerbyConstants.TEST_DBO ); |
| |
| assertTrue( "Initially, should be able to read property.", canReadProperty() ); |
| |
| // Now prove that the DBO can reload the policy file. |
| changePolicyFile( conn, RELOADABLE_MODIFIED_SOURCE_POLICY, true, null ); |
| assertFalse( "Policy file changed. Should not be able to read the property.", canReadProperty() ); |
| |
| // Return to initial policy file. |
| changePolicyFile( conn, RELOADABLE_INITIAL_SOURCE_POLICY, true, null ); |
| assertTrue( "Reverted to initial policy. Should be able to read the property again.", canReadProperty() ); |
| |
| conn.close(); |
| } |
| |
| /** |
| * Verify that the non-DBA does not have the power to reload the security policy file. |
| */ |
| private void nonDbaTest() |
| throws Exception |
| { |
| String reservedToDBO = "42504"; |
| Connection conn = openUserConnection( NON_DBO_USER ); |
| |
| assertTrue( "Initially, should be able to read property.", canReadProperty() ); |
| |
| // Now prove that the non-DBO can't reload the policy file. |
| changePolicyFile( conn, RELOADABLE_MODIFIED_SOURCE_POLICY, false, reservedToDBO ); |
| assertTrue( "Policy file not changed. Should still be able to read the property.", canReadProperty() ); |
| |
| // Return to initial policy file. |
| changePolicyFile( conn, RELOADABLE_INITIAL_SOURCE_POLICY, false, reservedToDBO ); |
| assertTrue( "Reverted to initial policy. Should still be able to read the property again.", canReadProperty() ); |
| |
| conn.close(); |
| } |
| |
| ///////////////////////////////////////////// |
| // |
| // getPolicy() IS NOT GRANTED |
| // |
| ///////////////////////////////////////////// |
| |
| /** |
| * Verify that even the DBA can't reload the policy file if getPolicy() has |
| * not been granted. |
| */ |
| private void doPolicyReloadingIsNotGranted() |
| throws Exception |
| { |
| String insufficientPrivilege = "XK000"; |
| Connection conn = openUserConnection( DerbyConstants.TEST_DBO ); |
| |
| // First change to a policy which does not permit policy reloading |
| changePolicyFile( conn, UNRELOADABLE_SOURCE_POLICY, true, null ); |
| |
| // Verify that we get an exception when we try to reload the policy file. |
| changePolicyFile( conn, RELOADABLE_INITIAL_SOURCE_POLICY, false, insufficientPrivilege ); |
| |
| conn.close(); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // Object OVERLOADS |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| public String toString() |
| { |
| StringBuffer buffer = new StringBuffer(); |
| |
| buffer.append( "SecurityPolicyReloadingTest( " ); |
| buffer.append( " )" ); |
| |
| return buffer.toString(); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // MINIONS |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Return true if we have sufficient privilege to read a special property. |
| */ |
| private boolean canReadProperty() |
| throws Exception |
| { |
| try { |
| getSystemProperty("SecurityPolicyReloadingTest.property"); |
| return true; |
| } |
| catch (AccessControlException ace) { return false; } |
| } |
| |
| /** |
| * Try to change the policy file. |
| */ |
| private void changePolicyFile( Connection conn, String newPolicyFileName, boolean shouldSucceed, String expectedSQLState ) |
| throws Exception |
| { |
| boolean reloaded = true; |
| |
| writePolicyFile( newPolicyFileName ); |
| |
| CallableStatement cs = conn.prepareCall( "call SYSCS_UTIL.SYSCS_RELOAD_SECURITY_POLICY()" ); |
| |
| try { |
| cs.execute(); |
| } |
| catch (SQLException se) |
| { |
| reloaded = false; |
| |
| assertSQLState( expectedSQLState, se ); |
| } |
| |
| assertEquals( shouldSucceed, reloaded ); |
| } |
| |
| /** |
| * Write a new policy file. |
| */ |
| private void writePolicyFile( String newPolicyFileName ) |
| throws Exception |
| { |
| SupportFilesSetup.privCopyFiles |
| ( |
| SupportFilesSetup.EXTINOUT, |
| new String[] { newPolicyFileName }, |
| new String[] { makeTargetPolicyStub() } |
| ); |
| } |
| |
| /** |
| * Construct the name of the server policy file. |
| */ |
| private static String makeServerPolicyName() |
| { |
| try { |
| String userDir = getSystemProperty( "user.dir" ); |
| String fileName = userDir + File.separator + SupportFilesSetup.EXTINOUT + File.separator + makeTargetPolicyStub(); |
| File file = new File( fileName ); |
| return file.toURI().toURL().toExternalForm(); |
| } |
| catch (Exception e) |
| { |
| System.out.println( "Unexpected exception caught by makeServerPolicyName(): " + e ); |
| |
| return null; |
| } |
| } |
| |
| /** |
| * Get the stub name (no directory spec) for the server policy file we create. |
| */ |
| private static String makeTargetPolicyStub() |
| { |
| return TARGET_POLICY; |
| } |
| |
| /** |
| * Get the source file which has the correct permissions. |
| */ |
| private static String getSourcePolicy() |
| { |
| return RELOADABLE_INITIAL_SOURCE_POLICY; |
| } |
| |
| } |