You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by da...@apache.org on 2012/02/22 00:52:16 UTC

svn commit: r1292084 - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting: functionTests/master/ functionTests/suites/ functionTests/tests/store/ junit/

Author: dag
Date: Tue Feb 21 23:52:15 2012
New Revision: 1292084

URL: http://svn.apache.org/viewvc?rev=1292084&view=rev
Log:
DERBY-2687 store/encryptDatabase.sql fails intermittently with ClassNotFoundException, Log Corrupted

Patch derby-2687-2 + removed an additional unused line. This converts
encryptDatabase.sql to JUnit and also makes the test ignore a hash
collision case: the stored two byte digest of the secret key can in can
1/2**16 cases match the the digest of bogus key gotten by decoding the
encrypted key using the wrong bootpassword, thus allowing boot to
proceed using a wrong encryption key, leading to a boot crash (the
"boot issue").

Another issue (less likely) can still make the test fail (the
"bootpassword change issue"), but cf. the improvement issue DERBY-5622
which would resolve that.


Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptDatabaseTest.java   (with props)
Removed:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/encryptDatabase.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionAES.properties
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionAES.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptDatabase.sql
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptDatabase_app.properties
Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryption.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionBlowfish.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionCFB.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionDES.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionECB.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionOFB.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/Decorator.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryption.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryption.runall?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryption.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryption.runall Tue Feb 21 23:52:15 2012
@@ -1,3 +1,2 @@
 unit/T_Cipher.unit
-store/encryptDatabase.sql
 store/EncryptionTest.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionBlowfish.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionBlowfish.runall?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionBlowfish.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionBlowfish.runall Tue Feb 21 23:52:15 2012
@@ -1,2 +1 @@
 unit/T_CipherBlowfish.unit
-store/encryptDatabase.sql

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionCFB.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionCFB.runall?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionCFB.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionCFB.runall Tue Feb 21 23:52:15 2012
@@ -1,2 +1 @@
 unit/T_CipherCFB.unit
-store/encryptDatabase.sql

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionDES.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionDES.runall?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionDES.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionDES.runall Tue Feb 21 23:52:15 2012
@@ -1,2 +1 @@
 unit/T_CipherDES.unit
-store/encryptDatabase.sql

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionECB.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionECB.runall?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionECB.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionECB.runall Tue Feb 21 23:52:15 2012
@@ -1,2 +1 @@
 unit/T_CipherECB.unit
-store/encryptDatabase.sql

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionOFB.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionOFB.runall?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionOFB.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionOFB.runall Tue Feb 21 23:52:15 2012
@@ -1,2 +1 @@
 unit/T_CipherOFB.unit
-store/encryptDatabase.sql

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptDatabaseTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptDatabaseTest.java?rev=1292084&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptDatabaseTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptDatabaseTest.java Tue Feb 21 23:52:15 2012
@@ -0,0 +1,325 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.store.EncryptDatabaseTest
+
+   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.store;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.List;
+import javax.sql.DataSource;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.derbyTesting.junit.*;
+
+
+/**
+ * Database encryption testing, mainly that handling of bootPassword works ok
+ * across encryption algorithms. Converted from {@code encryptDatabase.sql} in
+ * old harness, which was used in suites for the different algoritms,
+ * e.g. {@code encryptionECB}.  DERBY-2687.
+ */
+
+public class EncryptDatabaseTest  extends BaseJDBCTestCase
+{
+    // SQL states 
+    private static final String ENCRYPTION_NOCHANGE_ALGORITHM = "XBCXD";
+    private static final String ENCRYPTION_NOCHANGE_PROVIDER = "XBCXE";
+    private static final String ILLEGAL_BP_LENGTH = "XBCX2";
+    private static final String NULL_BOOT_PASSWORD = "XBCX5";
+    private static final String WRONG_BOOT_PASSWORD = "XBCXA";
+    private static final String WRONG_PASSWORD_CHANGE_FORMAT = "XBCX7";
+
+    
+    public EncryptDatabaseTest(String name) {
+        super(name);
+    }
+
+    
+    /**
+     * Construct top level suite in this JUnit test
+     *
+     * @return A suite containing embedded suites
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite("EncryptDatabase");
+        suite.addTest(wrapTest());
+        suite.addTest(wrapTest("DESede/CBC/NoPadding")); // from encryption
+        suite.addTest(wrapTest("DESede/CFB/NoPadding")); // from encryptionCFB
+        suite.addTest(wrapTest("DES/OFB/NoPadding"));    // from encryptionOFB
+        suite.addTest(wrapTest("DES/ECB/NoPadding"));    // from encryptionECB
+        suite.addTest(wrapTest("DES/CBC/NoPadding"));    // from encryptionDES
+        suite.addTest(wrapTest("Blowfish/CBC/NoPadding")); // from e..Blowfish
+        suite.addTest(wrapTest("AES/CBC/NoPadding"));    // from encryptionAES
+        suite.addTest(wrapTest("AES/OFB/NoPadding"));
+        return suite;
+    }
+
+    
+    private static Test wrapTest() {
+        return Decorator.encryptedDatabaseBpw(
+                          TestConfiguration.embeddedSuite(
+                              EncryptDatabaseTest.class),
+                          "Thursday"); // only initial bootPassword, though..
+    }
+
+
+    private static Test wrapTest(String encryptionMethod) {
+        return Decorator.encryptedDatabaseBpw(
+                          TestConfiguration.embeddedSuite(
+                              EncryptDatabaseTest.class),
+                          encryptionMethod,
+                          "Thursday"); // only initial bootPassword, though..
+    }
+
+
+    public void testEncryption() throws SQLException {
+
+        // for bug 3668 - you couldn't change the password without exiting
+        // out of db create session
+
+        Statement s = createStatement();
+        s.executeUpdate("call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+                        "'bootPassword', 'Thursday, Wednesday')");
+
+        TestConfiguration.getCurrent().shutdownEngine();
+
+        // -- test for bug 3668
+        // -- try the old password, should fail
+        assertFailedBoot("Thursday");
+
+        assertSuccessfulBoot("Wednesday");
+        s = createStatement();
+
+        // -- switch back to old password
+        s.executeUpdate("call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+                        "'bootPassword', 'Wednesday, Thursday')");
+
+        // create table t1 ( a char(20));
+        s.executeUpdate("create table t1 ( a char(20))");
+
+        // -- make sure we cannot access the secret key
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'bootPassword')"),
+            null);
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'encryptedBootPassword')"),
+            null);
+
+        s.executeUpdate("insert into t1 values ('hello world')");
+
+        // -- change the secret key
+
+        // -- these should fail
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', null)",
+            NULL_BOOT_PASSWORD);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'wrongkey, ')",
+            ILLEGAL_BP_LENGTH);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'Thursday')",
+            WRONG_PASSWORD_CHANGE_FORMAT);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'Thursday , ')",
+            ILLEGAL_BP_LENGTH);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'Thursday , short')",
+            ILLEGAL_BP_LENGTH);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'Thursdya , derbypwd')",
+            WRONG_BOOT_PASSWORD);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'Thursdayx , derbypwd')",
+            WRONG_BOOT_PASSWORD);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'xThursday , derbypwd')",
+            WRONG_BOOT_PASSWORD);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'thursday , derbypwd')",
+            WRONG_BOOT_PASSWORD);
+
+        s.executeUpdate("call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+                        "'bootPassword', ' Thursday , Saturday')");
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'bootPassword', 'Thursday , derbypwd')",
+            WRONG_BOOT_PASSWORD);
+
+
+        // -- change it again
+
+        s.executeUpdate("call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+                        "'bootPassword', 'Saturday,derbypwd')");
+
+        // -- make sure we cannot access the secret key
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'bootPassword')"),
+            null);
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'encryptedBootPassword')"),
+            null);
+
+
+        TestConfiguration.getCurrent().shutdownEngine();
+
+        assertFailedBoot(null);
+        assertFailedBoot("Thursday");
+        assertFailedBoot("Saturday");
+        assertSuccessfulBoot("derbypwd");
+
+        s = createStatement();
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'bootPassword')"),
+            null);
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'encryptedBootPassword')"),
+            null);
+
+        // -- change it again, make sure it trims white spaces
+
+        s.executeUpdate("call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+                        "'bootPassword', '   derbypwd   ,  bbderbypwdx  ')");
+        s.executeUpdate("call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+                        "'bootPassword', 'bbderbypwdx, derbypwdxx ')");
+
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'bootPassword')"),
+            null);
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("values SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" +
+                           "'encryptedBootPassword')"),
+            null);
+
+        TestConfiguration.getCurrent().shutdownEngine();
+
+        assertFailedBoot("derbypwd");
+        assertSuccessfulBoot("derbypwdxx");
+
+        s = createStatement();
+
+        JDBC.assertSingleValueResultSet(
+            s.executeQuery("select * from t1"),
+            "hello world");
+
+        // test that you cannot change the encryption provider or algorithm
+        // after database creation
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'encryptionAlgorithm', 'DES/blabla/NoPadding')",
+            ENCRYPTION_NOCHANGE_ALGORITHM);
+
+        assertFailedStatement(
+            s,
+            "call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
+            "'encryptionProvider', 'com.pom.aplomb')",
+            ENCRYPTION_NOCHANGE_PROVIDER);
+    }
+
+
+    private void assertFailedBoot(String bootPassword) throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource();
+
+        JDBCDataSource.setBeanProperty(
+                ds, "connectionAttributes",
+                (bootPassword != null ? "bootPassword=" + bootPassword
+                 : "")); // "": lest we inherit bootPassword from current config
+
+
+        try {
+            ds.getConnection();
+            fail("boot worked: unexpected");
+        } catch (SQLException e) {
+
+            String [] accepted = new String[]{
+                "XBM06",  // normal: wrong bootpassword
+                "XJ040"}; // Java error during boot: DERBY-2687
+                          // Remove when DERBY-5622 is fixed.
+            boolean found = Arrays.asList(accepted).contains(e.getSQLState()); 
+
+            if (!found) {
+                throw e;
+            }
+        }
+    }
+
+
+    private static void assertSuccessfulBoot(String bootPassword)
+            throws SQLException {
+
+        DataSource ds = JDBCDataSource.getDataSource();
+        JDBCDataSource.setBeanProperty(
+            ds, "connectionAttributes", "bootPassword=" + bootPassword);
+        ds.getConnection().close();
+    }
+
+
+    private static void assertFailedStatement(Statement s,
+                                              String sql,
+                                              String state) {
+        assertStatementError(state, s, sql);
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptDatabaseTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java Tue Feb 21 23:52:15 2012
@@ -95,6 +95,7 @@ public class _Suite extends BaseTestCase
             suite.addTest(EncryptionKeyBlowfishTest.suite());
             suite.addTest(EncryptionKeyDESTest.suite());
             suite.addTest(EncryptionAESTest.suite());
+            suite.addTest(EncryptDatabaseTest.suite());
         }
 
         return suite;

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/Decorator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/Decorator.java?rev=1292084&r1=1292083&r2=1292084&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/Decorator.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/Decorator.java Tue Feb 21 23:52:15 2012
@@ -57,16 +57,36 @@ public class Decorator {
      */
     public static Test encryptedDatabase(Test test)
     {
+        return encryptedDatabaseBpw(test, getBootPhrase(16));
+    }
+
+    /**
+     * Decorate a set of tests to use an encrypted
+     * single use database. This is to run tests
+     * using encryption as a general test and
+     * not specific tests of how encryption is handled.
+     * E.g. tests of setting various URL attributes
+     * would be handled in a specific test.
+     * <BR>
+     * The database will use the default encryption
+     * algorithm.
+     * 
+     * @param test test to decorate
+     * @param bootPassword boot passphrase to use
+     * @return decorated tests
+     */
+    public static Test encryptedDatabaseBpw(Test test, String bootPassword)
+    {
         if (JDBC.vmSupportsJSR169())
             return new TestSuite("no encryption support");
 
         Properties attributes = new Properties();
         attributes.setProperty("dataEncryption", "true");
-        attributes.setProperty("bootPassword", getBootPhrase(16));
+        attributes.setProperty("bootPassword", bootPassword);
 
         return attributesDatabase(attributes, test);
     }
-    
+
     /**
      * Decorate a set of tests to use an encrypted
      * single use database. This is to run tests
@@ -86,14 +106,37 @@ public class Decorator {
      */
     public static Test encryptedDatabase(Test test, final String algorithm)
     {
+        return encryptedDatabaseBpw(test, algorithm, getBootPhrase(16));
+    }
+
+
+    /**
+     * Decorate a set of tests to use an encrypted
+     * single use database. This is to run tests
+     * using encryption as a general test and
+     * not specific tests of how encryption is handled.
+     * E.g. tests of setting various URL attributes
+     * would be handled in a specific test.
+     * <BR>
+     * The database will use the specified encryption
+     * algorithm.
+     * 
+     * @param test test to decorate
+     * @param bootPassword boot passphrase to use
+     * @return decorated tests
+     */
+    public static Test encryptedDatabaseBpw(Test test,
+                                            final String algorithm,
+                                            String bootPassword)
+    {
         Properties attributes = new Properties();
         attributes.setProperty("dataEncryption", "true");
-        attributes.setProperty("bootPassword", getBootPhrase(64));
+        attributes.setProperty("bootPassword", bootPassword);
         attributes.setProperty("encryptionAlgorithm", algorithm);
 
         return attributesDatabase(attributes, test);
     }
-    
+
     private static String getBootPhrase(int length)
     {
         Random rand = new Random();