Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8A7E591B7 for ; Wed, 26 Sep 2012 20:02:37 +0000 (UTC) Received: (qmail 62211 invoked by uid 500); 26 Sep 2012 20:02:37 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 62183 invoked by uid 500); 26 Sep 2012 20:02:37 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 62176 invoked by uid 99); 26 Sep 2012 20:02:37 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Sep 2012 20:02:37 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Sep 2012 20:02:30 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 45DB423888CD; Wed, 26 Sep 2012 20:01:45 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1390712 - in /db/derby/code/trunk/java/engine/org/apache/derby: iapi/store/raw/data/ iapi/store/raw/log/ impl/store/raw/ impl/store/raw/data/ impl/store/raw/log/ Date: Wed, 26 Sep 2012 20:01:44 -0000 To: derby-commits@db.apache.org From: kristwaa@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120926200145.45DB423888CD@eris.apache.org> Author: kristwaa Date: Wed Sep 26 20:01:43 2012 New Revision: 1390712 URL: http://svn.apache.org/viewvc?rev=1390712&view=rev Log: DERBY-5792: Make it possible to turn off encryption on an already encrypted database. A set of changes made in preparation of adding database decryption support. These modifications should not cause functional changes. Description: o DataFactory.setDatabaseEncrypted: introduced boolean flag to be able to tell the data factory that encryption has been turned off. Updated implementing method in BaseDataFileFactory o setDatabaseEncrypted: introduced second boolean flag to be able to tell the log factory that encryption has been turned off. Updated implementing methods in LogToFile and ReadOnly. o RawContainerHandle.encryptContainer: renamed to encryptOrDecryptContainer, added boolean flag to control crypto operation. Updated implementing method in BaseContainerHandle o BaseContainer.encryptContainer: renamed to encryptOrDecryptContainer, added boolean flag to control crypto operation. Updated implementing methods in RAFContainer and InputStreamContainer o EncryptData: renamed to EncryptOrDecryptData, added method decryptAllContainers, whitespace changes. o RawStore: - removed import - removed instance variable encryptDatabase - removed unused instance variable dataDirectory - renamed databaseEncrypted to isEncryptedDatabase - renamed configureDatabaseForEncryption to applyBulkCryptoOperation - made setupEncryptionEngines return a boolean: whether or not existing data must be transformed (applyBulkCryptoOperation) - simplified parts of the logic in setupEncryptionEngines - introduced isTrue/isSet for property sets - removed unused method privList(File) Patch file: derby-5792-1b-boilerplate_and_preparation.diff Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptOrDecryptData.java - copied, changed from r1390601, db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptData.java Removed: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptData.java Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/DataFactory.java db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/RawContainerHandle.java db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/log/LogFactory.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainer.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainerHandle.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseDataFileFactory.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptContainerOperation.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/InputStreamContainer.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/ReadOnly.java Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/DataFactory.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/DataFactory.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/DataFactory.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/DataFactory.java Wed Sep 26 20:01:43 2012 @@ -302,9 +302,12 @@ public interface DataFactory extends Cor throws StandardException; /** - * Set that the database is encrypted. + * Sets whether the database is encrypted. + * + * @param isEncrypted {@code true} if the database is encrypted, + * {@code false} otherwise */ - public void setDatabaseEncrypted(); + public void setDatabaseEncrypted(boolean isEncrypted); /** Return the encryption block size used by the algorithm at time of Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/RawContainerHandle.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/RawContainerHandle.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/RawContainerHandle.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/data/RawContainerHandle.java Wed Sep 26 20:01:43 2012 @@ -123,11 +123,13 @@ public interface RawContainerHandle exte /** - * Create encrypted version of the container with the - * user specified encryption properties. - * @param newFilePath file to store the new encrypted version of the container - * @exception StandardException Standard Derby error policy + * Creates an encrypted or decrypted version of the container. + * + * @param newFilePath file to store the new version of the container + * @param doEncrypt tells whether to encrypt or decrypt + * @exception StandardException Standard Derby error policy */ - public void encryptContainer(String newFilePath) throws StandardException; + public void encryptOrDecryptContainer(String newFilePath, boolean doEncrypt) + throws StandardException; } Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/log/LogFactory.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/log/LogFactory.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/log/LogFactory.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/log/LogFactory.java Wed Sep 26 20:01:43 2012 @@ -28,12 +28,10 @@ import org.apache.derby.iapi.store.raw.d import org.apache.derby.iapi.store.raw.Corruptable; import org.apache.derby.iapi.store.raw.RawStoreFactory; import org.apache.derby.iapi.store.raw.ScanHandle; -import org.apache.derby.iapi.store.raw.ScannedTransactionHandle; import org.apache.derby.iapi.store.raw.xact.TransactionFactory; import org.apache.derby.io.StorageFile; import org.apache.derby.iapi.store.access.DatabaseInstant; import org.apache.derby.iapi.reference.Property; -import org.apache.derby.catalog.UUID; import java.io.File; public interface LogFactory extends Corruptable { @@ -315,16 +313,19 @@ public interface LogFactory extends Corr **/ public void abortLogBackup(); - /* - * Set that the database is encrypted , all the transaction log has - * to be encrypted, and flush the log if requesed. Log needs to - * be flushed first, if this is being set during (re) encryption - * of an existing database. + /** + * Sets whether the database is encrypted, all the transaction log has + * to be encrypted, and flush the log if requested. + *

+ * Log needs to be flushed first if the cryptographic state of the database + * changes (for instance re-encryption with a new key). * - * @param flushLog true, if log needs to be flushed, - * otherwise false. + * @param isEncrypted {@code true} if the database is encrypted, + * {@code false} if not + * @param flushLog {@code true} if log needs to be flushed, + * {@code false} otherwise */ - public void setDatabaseEncrypted(boolean flushLog) + public void setDatabaseEncrypted(boolean isEncrypted, boolean flushLog) throws StandardException; Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java Wed Sep 26 20:01:43 2012 @@ -79,7 +79,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.security.PrivilegedExceptionAction; -import java.lang.SecurityException; import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; import org.apache.derby.iapi.sql.dictionary.DataDictionary; @@ -108,8 +107,7 @@ public final class RawStore implements R private StorageFactory storageFactory; private SecureRandom random; - private boolean databaseEncrypted; - private boolean encryptDatabase; + private boolean isEncryptedDatabase; private CipherProvider encryptionEngine; private CipherProvider decryptionEngine; private CipherProvider newEncryptionEngine; @@ -120,8 +118,6 @@ public final class RawStore implements R private int counter_decrypt; private int encryptionBlockSize = RawStoreFactory.DEFAULT_ENCRYPTION_BLOCKSIZE; - String dataDirectory; // where files are stored - // this daemon takes care of all daemon work for this raw store protected DaemonService rawStoreDaemon; @@ -171,6 +167,7 @@ public final class RawStore implements R throws StandardException { + boolean transformExistingData = false; boolean inReplicationSlaveMode = false; String slave = properties.getProperty(SlaveFactory.REPLICATION_MODE); @@ -178,7 +175,6 @@ public final class RawStore implements R inReplicationSlaveMode = true; } - dataDirectory = properties.getProperty(PersistentService.ROOT); DaemonFactory daemonFactory = (DaemonFactory)Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.DaemonFactory); rawStoreDaemon = daemonFactory.createNewDaemon("rawStoreDaemon"); @@ -206,8 +202,13 @@ public final class RawStore implements R } // setup database encryption engines. - if (create) - setupEncryptionEngines(create, properties); + if (create) { + transformExistingData = setupEncryptionEngines(create, properties); + if (SanityManager.DEBUG) { + SanityManager.ASSERT(!transformExistingData, + "no crypto data transformation for a new db"); + } + } // let everyone knows who their rawStoreFactory is and they can use it @@ -299,14 +300,14 @@ public final class RawStore implements R handleIncompleteDatabaseEncryption(properties); } - setupEncryptionEngines(create, properties); + transformExistingData = setupEncryptionEngines(create, properties); } - if (databaseEncrypted) { + if (isEncryptedDatabase) { // let log factory know if the database is encrypted . - logFactory.setDatabaseEncrypted(false); + logFactory.setDatabaseEncrypted(true, false); // let data factory know if the database is encrypted. - dataFactory.setDatabaseEncrypted(); + dataFactory.setDatabaseEncrypted(true); } // RawStoreFactory is used by LogFactory.recover() and by @@ -333,23 +334,22 @@ public final class RawStore implements R // after the factories are loaded, recover the database logFactory.recover(dataFactory, xactFactory); - // if user requested to encrpty an unecrypted database or encrypt with - // new alogorithm then do that now. - if (encryptDatabase) { - configureDatabaseForEncryption(properties, - newCipherFactory); + // If user requested to encrypt an un-encrypted database or encrypt with + // a new alogorithm then do that now. + if (transformExistingData) { + applyBulkCryptoOperation(properties, newCipherFactory); } - } public void stop() { if (SanityManager.DEBUG) { - if (databaseEncrypted) + if (isEncryptedDatabase) { SanityManager.DEBUG_PRINT("encryption statistics", "Encryption called " + counter_encrypt + " times, " + "decryption called " + counter_decrypt + " times"); + } } if (rawStoreDaemon != null) @@ -1260,18 +1260,23 @@ public final class RawStore implements R /** - * Setup Encryption Engines. + * Setup encryption engines according to the user properties and the + * current database state. + * + * @param create whether a new database is being created, or if this is + * an existing database + * @param properties database properties, including connection attributes + * @return {@code true} if the existing data in the database should be + * transformed by applying a cryptographic operation. + * @throws StandardException if the properties are conflicting, if the + * requested configuration is denied, or if something else goes wrong */ - private void setupEncryptionEngines(boolean create, Properties properties) + private boolean setupEncryptionEngines(boolean create, + Properties properties) throws StandardException { - // Check if user has requested to encrypt the database or if the - // database is encrypted already. - - String dataEncryption = - properties.getProperty(Attribute.DATA_ENCRYPTION); - databaseEncrypted = Boolean.valueOf(dataEncryption).booleanValue(); - + // Check if user has requested to encrypt the database. + boolean encryptDatabase = isTrue(properties, Attribute.DATA_ENCRYPTION); boolean reEncrypt = false; if (!create) { @@ -1289,29 +1294,15 @@ public final class RawStore implements R String canonicalName = ps.getCanonicalServiceName(name); Properties serviceprops = ps.getServiceProperties(canonicalName, (Properties)null); - dataEncryption = serviceprops.getProperty(Attribute.DATA_ENCRYPTION); - boolean encryptedDatabase = Boolean.valueOf(dataEncryption).booleanValue(); + isEncryptedDatabase = + isTrue(serviceprops, Attribute.DATA_ENCRYPTION); - if (!encryptedDatabase && databaseEncrypted) { - // It it not an encrypted database, user is asking to - // encrypt an un-encrypted database. - encryptDatabase = true; - // Set database as un-encrypted, we will set it as encrypted - // after encrypting the existing data. - databaseEncrypted = false; - } else { - // Check if the user has requested to re-necrypt an + if (isEncryptedDatabase) { + // Check if the user has requested to re-encrypt an // encrypted datbase with a new encryption password/key. - if (encryptedDatabase) { - if (properties.getProperty( - Attribute.NEW_BOOT_PASSWORD) != null) { - reEncrypt = true; - } else if (properties.getProperty( - Attribute.NEW_CRYPTO_EXTERNAL_KEY) != null){ - reEncrypt = true; - } - encryptDatabase = reEncrypt; - } + reEncrypt = isSet(properties, Attribute.NEW_BOOT_PASSWORD) || + isSet(properties, Attribute.NEW_CRYPTO_EXTERNAL_KEY); + encryptDatabase = reEncrypt; } // NOTE: if user specifies Attribute.DATA_ENCRYPTION on the @@ -1333,7 +1324,7 @@ public final class RawStore implements R } // setup encryption engines. - if (databaseEncrypted || encryptDatabase) { + if (isEncryptedDatabase || encryptDatabase) { // Check if database is or will be encrypted. We save encryption // properties as service properties, such that // user does not have to specify them on the URL everytime. @@ -1392,7 +1383,7 @@ public final class RawStore implements R String.valueOf(encryptionBlockSize)); } } else { - if (properties.getProperty(RawStoreFactory.ENCRYPTION_BLOCKSIZE) != null) { + if (isSet(properties, RawStoreFactory.ENCRYPTION_BLOCKSIZE)) { encryptionBlockSize = Integer.parseInt(properties.getProperty( RawStoreFactory.ENCRYPTION_BLOCKSIZE)); @@ -1409,7 +1400,7 @@ public final class RawStore implements R if (encryptDatabase) { if (reEncrypt) { - // Create new cipher factory with the new encrytpion + // Create new cipher factory with the new encryption // properties specified by the user. This cipher factory // is used to create the new encryption/decryption // engines to re-encrypt the database with the new @@ -1433,8 +1424,10 @@ public final class RawStore implements R // at database creation time. if(create) { currentCipherFactory.saveProperties(properties); + isEncryptedDatabase = true; } } + return (!create && encryptDatabase); } /** @@ -1449,9 +1442,7 @@ public final class RawStore implements R boolean newEngine) throws StandardException { - if ((databaseEncrypted == false && encryptDatabase == false) || - (encryptionEngine == null && newEncryptionEngine == null)) - { + if ((encryptionEngine == null && newEncryptionEngine == null)) { throw StandardException.newException( SQLState.STORE_FEATURE_NOT_IMPLEMENTED); } @@ -1478,8 +1469,7 @@ public final class RawStore implements R byte[] cleartext, int outputOffset) throws StandardException { - if (databaseEncrypted == false || decryptionEngine == null) - { + if (isEncryptedDatabase == false || decryptionEngine == null) { throw StandardException.newException( SQLState.STORE_FEATURE_NOT_IMPLEMENTED); } @@ -1501,7 +1491,7 @@ public final class RawStore implements R public int random() { // don't synchronize it, the more random the better. - return databaseEncrypted ? random.nextInt() : 0; + return isEncryptedDatabase ? random.nextInt() : 0; } public Serializable changeBootPassword(Properties properties, Serializable changePassword) @@ -1510,7 +1500,7 @@ public final class RawStore implements R if (isReadOnly()) throw StandardException.newException(SQLState.DATABASE_READ_ONLY); - if (!databaseEncrypted) + if (!isEncryptedDatabase) throw StandardException.newException(SQLState.DATABASE_NOT_ENCRYPTED); if (changePassword == null) @@ -1627,21 +1617,18 @@ public final class RawStore implements R * @param properties properties related to this database. * @exception StandardException Standard Derby Error Policy */ - public void configureDatabaseForEncryption(Properties properties, - CipherFactory newCipherFactory) + private void applyBulkCryptoOperation(Properties properties, + CipherFactory newCipherFactory) throws StandardException { - boolean reEncrypt = (databaseEncrypted && encryptDatabase); + boolean reEncrypt = isEncryptedDatabase; // check if the database can be encrypted. canEncryptDatabase(reEncrypt); - boolean externalKeyEncryption = false; - if (properties.getProperty(Attribute.CRYPTO_EXTERNAL_KEY) != null) - { - externalKeyEncryption = true; - } + boolean externalKeyEncryption = + isSet(properties, Attribute.CRYPTO_EXTERNAL_KEY); // check point the datase, so that encryption does not have // to encrypt the existing transactions logs. @@ -1679,23 +1666,20 @@ public final class RawStore implements R // to find if the re(encryption) is complete. logFactory.checkpoint(this, dataFactory, xactFactory, true); } - - - encryptDatabase = false; // let the log factory know that database is // (re) encrypted and ask it to flush the log, // before enabling encryption of the log with // the new key. - logFactory.setDatabaseEncrypted(true); + logFactory.setDatabaseEncrypted(true, true); // let the log factory and data factory know that // database is encrypted. if (!reEncrypt) { // mark in the raw store that the database is // encrypted. - databaseEncrypted = true; - dataFactory.setDatabaseEncrypted(); + isEncryptedDatabase = true; + dataFactory.setDatabaseEncrypted(true); } else { // switch the encryption/decryption engine to the new ones. decryptionEngine = newDecryptionEngine; @@ -2563,22 +2547,6 @@ public final class RawStore implements R } - private synchronized String[] privList(final File file) - { - actionCode = REGULAR_FILE_LIST_DIRECTORY_ACTION; - actionRegularFile = file; - - try - { - return (String[]) AccessController.doPrivileged( this); - } - catch( PrivilegedActionException pae) { return null;} // does not throw an exception - finally - { - actionRegularFile = null; - } - } - private synchronized String[] privList(final StorageFile file) { actionCode = STORAGE_FILE_LIST_DIRECTORY_ACTION; @@ -2741,4 +2709,14 @@ public final class RawStore implements R } return null; } // end of run + + /** Tells if the attribute/property has been specified. */ + private static boolean isSet(Properties p, String attribute) { + return p.getProperty(attribute) != null; + } + + /** Tells if the attribute/property has been set to {@code true}. */ + private static boolean isTrue(Properties p, String attribute) { + return Boolean.valueOf(p.getProperty(attribute)).booleanValue(); + } } Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainer.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainer.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainer.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainer.java Wed Sep 26 20:01:43 2012 @@ -878,16 +878,18 @@ abstract class BaseContainer implements /** - * Create encrypted version of the container with the - * user specified encryption properties. + * Creates encrypted or decrypted version of the container. * - * @param handle the container handle. - * @param newFilePath file to store the new encrypted version of the container + * @param handle the container handle + * @param newFilePath file to store the new version of the container + * @param doEncrypt tells whether to encrypt or decrypt * @exception StandardException Standard Derby error policy */ - protected abstract void encryptContainer(BaseContainerHandle handle, - String newFilePath) - throws StandardException ; + protected abstract void encryptOrDecryptContainer( + BaseContainerHandle handle, + String newFilePath, + boolean doEncrypt) + throws StandardException; /* Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainerHandle.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainerHandle.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainerHandle.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseContainerHandle.java Wed Sep 26 20:01:43 2012 @@ -1033,16 +1033,11 @@ public class BaseContainerHandle extends - /** - * Create encrypted version of the container with the - * user specified encryption properties. - * @param newFilePath file to store the new encrypted version of the container - * @exception StandardException Standard Derby error policy - */ - public void encryptContainer(String newFilePath) throws StandardException - { + /** {@inheritDoc} */ + public void encryptOrDecryptContainer(String newFilePath, boolean doEncrypt) + throws StandardException { checkOpen(); - container.encryptContainer(this, newFilePath); + container.encryptOrDecryptContainer(this, newFilePath, doEncrypt); } Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseDataFileFactory.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseDataFileFactory.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseDataFileFactory.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BaseDataFileFactory.java Wed Sep 26 20:01:43 2012 @@ -198,7 +198,7 @@ public class BaseDataFileFactory private Hashtable postRecoveryRemovedFiles; - private EncryptData containerEncrypter; + private EncryptOrDecryptData containerEncrypter; // PrivilegedAction actions @@ -2066,9 +2066,10 @@ public class BaseDataFileFactory return databaseEncrypted; } - public void setDatabaseEncrypted() + /** {@inheritDoc} */ + public void setDatabaseEncrypted(boolean isEncrypted) { - databaseEncrypted = true; + databaseEncrypted = isEncrypted; } public int encrypt( @@ -2102,7 +2103,7 @@ public class BaseDataFileFactory public void encryptAllContainers(RawTransaction t) throws StandardException { - containerEncrypter = new EncryptData(this); + containerEncrypter = new EncryptOrDecryptData(this); // encrypt all the conatiners in the databse containerEncrypter.encryptAllContainers(t); } @@ -2122,7 +2123,7 @@ public class BaseDataFileFactory // (re)encryption of the dataabase, but before the // (re)encryption cleanup was complete. if (inRecovery) { - containerEncrypter = new EncryptData(this); + containerEncrypter = new EncryptOrDecryptData(this); } containerEncrypter.removeOldVersionOfContainers(inRecovery); containerEncrypter = null; Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptContainerOperation.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptContainerOperation.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptContainerOperation.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptContainerOperation.java Wed Sep 26 20:01:43 2012 @@ -180,7 +180,7 @@ public class EncryptContainerOperation i // restore the container to the state it was before the encrytpion. BaseDataFileFactory bdff = (BaseDataFileFactory) ((RawTransaction) tran).getDataFactory(); - EncryptData ed = new EncryptData(bdff); + EncryptOrDecryptData ed = new EncryptOrDecryptData(bdff); ed.restoreContainer(containerId); releaseResource(tran); Copied: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptOrDecryptData.java (from r1390601, db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptData.java) URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptOrDecryptData.java?p2=db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptOrDecryptData.java&p1=db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptData.java&r1=1390601&r2=1390712&rev=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptData.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/EncryptOrDecryptData.java Wed Sep 26 20:01:43 2012 @@ -1,6 +1,6 @@ /* - Derby - Class org.apache.derby.impl.store.raw.data.EncryptData + Derby - Class org.apache.derby.impl.store.raw.data.EncryptOrDecryptData Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -20,15 +20,13 @@ */ package org.apache.derby.impl.store.raw.data; + import org.apache.derby.iapi.reference.SQLState; -import org.apache.derby.iapi.services.context.ContextManager; -import org.apache.derby.iapi.services.daemon.Serviceable; import org.apache.derby.iapi.services.sanity.SanityManager; import org.apache.derby.iapi.error.StandardException; import org.apache.derby.iapi.store.raw.data.RawContainerHandle; import org.apache.derby.iapi.store.raw.ContainerKey; import org.apache.derby.iapi.store.raw.LockingPolicy; -import org.apache.derby.iapi.store.raw.Transaction; import org.apache.derby.iapi.store.raw.xact.RawTransaction; import org.apache.derby.iapi.store.raw.ContainerHandle; import org.apache.derby.iapi.store.access.TransactionController; @@ -41,33 +39,32 @@ import java.security.PrivilegedAction; /** - * This class is used to encrypt all the containers in the data segment with a - * new encryption key when password/key is changed or when an existing database - * is reconfigured for encryption. - * - * Encryption of existing data in the data segments is done by doing the + * This class is used to encrypt all the containers in the data segment with a + * new encryption key when password/key is changed or when an existing database + * is reconfigured for encryption. + * + * Encryption of existing data in the data segments is done by doing the * following: * Find all the containers in data segment (seg0) and encrypt all of them * with the new encryption key, the process for each container is: - * 1.Write a log record to indicate that the container is getting encrypted. + * 1.Write a log record to indicate that the container is getting encrypted. * 2.Read all the pages of the container through the page cache and - * encrypt each page with new encryption key and then write to a + * encrypt each page with new encryption key and then write to a * temporary file(n.dat) in the data segment itself. - * 3. Rename the current container file (c.dat) to + * 3. Rename the current container file (c.dat) to * another file (o.dat) - * 4. Rename the new encrypted version of the file (n.dat). - * 5. All the old version of the container (o.dat) files are removed + * 5. All the old version of the container (o.dat) files are removed * after a successful checkpoint with a new key or on a rollback. - * */ -public class EncryptData implements PrivilegedAction { +public class EncryptOrDecryptData implements PrivilegedAction { private BaseDataFileFactory dataFactory; private StorageFactory storageFactory; private StorageFile[] oldFiles; - private int noOldFiles = 0; + private int noOldFiles = 0; /* privileged actions */ @@ -78,86 +75,110 @@ public class EncryptData implements Priv private StorageFile actionStorageFile; private StorageFile actionDestStorageFile; - public EncryptData(BaseDataFileFactory dataFactory) { - this.dataFactory = dataFactory; + public EncryptOrDecryptData(BaseDataFileFactory dataFactory) { + this.dataFactory = dataFactory; this.storageFactory = dataFactory.getStorageFactory(); - } + } + /** + * Finds all the all the containers stored in the data directory and + * decrypts them. + * + * @param t the transaction that is used for the decryption operation + * @throws StandardException Standard Derby error policy + */ + public void decryptAllContainers(RawTransaction t) + throws StandardException { + encryptOrDecryptAllContainers(t, false); + } - /* - * Find all the all the containers stored in the data directory and + /** + * Find all the all the containers stored in the data directory and * encrypt them. - * @param t the transaction that is used to configure the database - * with new encryption properties. + * + * @param t the transaction that is used for the encryption operation * @exception StandardException Standard Derby error policy - */ - public void encryptAllContainers(RawTransaction t) - throws StandardException { - - /* - * List of containers that needs to be encrypted are identified by - * simply reading the list of files in seg0. - */ + */ + public void encryptAllContainers(RawTransaction t) + throws StandardException { + encryptOrDecryptAllContainers(t, true); + } - String[] files = dataFactory.getContainerNames(); - if (files != null) { + /** + * Encrypts or decrypts all containers in the database data directory. + * + * @param t transaction used for the cryptographic operation + * @param doEncrypt tells whether to encrypt or decrypt + * @exception StandardException Standard Derby error policy + */ + private void encryptOrDecryptAllContainers(RawTransaction t, + boolean doEncrypt) + throws StandardException { + // List of containers that need to be transformed are identified by + // simply reading the list of files in seg0. + String[] files = dataFactory.getContainerNames(); + if (files != null) { oldFiles = new StorageFile[files.length]; noOldFiles = 0; - long segmentId = 0; + long segmentId = 0; - // loop through all the files in seg0 and - // encrypt all valid containers. - for (int f = files.length-1; f >= 0 ; f--) { - long containerId; - try { - containerId = - Long.parseLong(files[f].substring(1, + // Loop through all the files in seg0 and + // encrypt/decrypt all valid containers. + for (int f = files.length-1; f >= 0 ; f--) { + long containerId; + try { + containerId = + Long.parseLong(files[f].substring(1, (files[f].length() -4)), 16); - } - catch (Throwable th) - { - // ignore errors from parse, it just means - // that someone put a file in seg0 that we + } + catch (Throwable th) + { + // ignore errors from parse, it just means + // that someone put a file in seg0 that we // didn't expect. Continue with the next one. - continue; - } + continue; + } - ContainerKey ckey = new ContainerKey(segmentId, + ContainerKey ckey = new ContainerKey(segmentId, containerId); - oldFiles[noOldFiles++] = encryptContainer(t, ckey); - } + oldFiles[noOldFiles++] = + encryptOrDecryptContainer(t, ckey, doEncrypt); + } // Old versions of the container files will // be removed after the (re)encryption of database - // is completed. - } else - { - if (SanityManager.DEBUG) - SanityManager.THROWASSERT("encryption process is unable to" + + // is completed. + } else + { + if (SanityManager.DEBUG) + SanityManager.THROWASSERT("encryption process is unable to" + "read container names in seg0"); - } + } } - /** Encrypt a container. - * @param t the transaction that is used to configure the database - * with new encryption properties. - * @param ckey the key of the container that is being encrypted. - * @return file handle to the old copy of the container. + /** + * Encrypts or decrypts the specified container. + * + * @param t transaction that used to perform the cryptographic operation + * @param ckey the key of the container that is being encrypted/decrypted + * @param doEncrypt tells whether to encrypt or decrypt + * @return File handle to the old copy of the container. * @exception StandardException Standard Derby error policy */ - private StorageFile encryptContainer(RawTransaction t, - ContainerKey ckey) + private StorageFile encryptOrDecryptContainer(RawTransaction t, + ContainerKey ckey, + boolean doEncrypt) throws StandardException - { + { - LockingPolicy cl = + LockingPolicy cl = t.newLockingPolicy( LockingPolicy.MODE_CONTAINER, - TransactionController.ISOLATION_SERIALIZABLE, + TransactionController.ISOLATION_SERIALIZABLE, true); - + if (SanityManager.DEBUG ) SanityManager.ASSERT(cl != null); @@ -167,38 +188,38 @@ public class EncryptData implements Priv if (SanityManager.DEBUG ) SanityManager.ASSERT(containerHdl != null); - EncryptContainerOperation lop = + EncryptContainerOperation lop = new EncryptContainerOperation(containerHdl); t.logAndDo(lop); - + // flush the log to reduce the window between where - // the encrypted container is created & synced and the - // log record for it makes it to disk. if we fail during - // encryption of the container, log record will make sure - // container is restored to the original state and - // any temporary files are cleaned up. + // the encrypted container is created & synced and the + // log record for it makes it to disk. if we fail during + // encryption of the container, log record will make sure + // container is restored to the original state and + // any temporary files are cleaned up. dataFactory.flush(t.getLastLogInstant()); // encrypt the container. String newFilePath = getFilePath(ckey, false); StorageFile newFile = storageFactory.newStorageFile(newFilePath); - containerHdl.encryptContainer(newFilePath); + containerHdl.encryptOrDecryptContainer(newFilePath, doEncrypt); containerHdl.close(); - + /* * Replace the current container file with the new container file after - * keeping a copy of the current container file, it will be removed on - * after a checkpoint with new key or on a rollback this copy will be - * replace the container file to bring the database back to the - * state before encryption process started. + * keeping a copy of the current container file, it will be removed on + * after a checkpoint with new key or on a rollback this copy will be + * replace the container file to bring the database back to the + * state before encryption process started. */ - // discard pages in the cache related to this container. + // discard pages in the cache related to this container. if (!dataFactory.getPageCache().discard(ckey)) { if (SanityManager.DEBUG ) - SanityManager.THROWASSERT("unable to discard pages releated to " + - "container " + ckey + + SanityManager.THROWASSERT("unable to discard pages releated to " + + "container " + ckey + " from the page cache"); } @@ -206,7 +227,7 @@ public class EncryptData implements Priv // get rid of the container entry from conatainer cache if (!dataFactory.getContainerCache().discard(ckey)) { if (SanityManager.DEBUG ) - SanityManager.THROWASSERT("unable to discard a container " + + SanityManager.THROWASSERT("unable to discard a container " + ckey + " from the container cache"); } @@ -219,30 +240,30 @@ public class EncryptData implements Priv currentFile, oldFile); } - // now replace current container file with the new file. + // now replace current container file with the new file. if (!privRename(newFile, currentFile)) { throw StandardException. newException(SQLState.RAWSTORE_ERROR_RENAMING_FILE, newFile, currentFile); - + } return oldFile ; } - + /** - * Get file handle to a container file that is used to keep - * temporary versions of the container file. + * Get file handle to a container file that is used to keep + * temporary versions of the container file. */ private StorageFile getFile(ContainerKey containerId, boolean old) { - return storageFactory.newStorageFile(getFilePath(containerId, + return storageFactory.newStorageFile(getFilePath(containerId, old)); } /** * Get path to a container file that is used to keep temporary versions of - * the container file. + * the container file. */ private String getFilePath(ContainerKey containerId, boolean old) { StringBuffer sb = new StringBuffer("seg"); @@ -254,7 +275,7 @@ public class EncryptData implements Priv return sb.toString(); } - private boolean isOldContainerFile(String fileName) + private boolean isOldContainerFile(String fileName) { // all old versions of the conatainer files // start with prefix "o" and ends with ".dat" @@ -264,7 +285,7 @@ public class EncryptData implements Priv return false; } - private StorageFile getFile(String ctrFileName) + private StorageFile getFile(String ctrFileName) { long segmentId = 0; StringBuffer sb = new StringBuffer("seg"); @@ -274,35 +295,35 @@ public class EncryptData implements Priv return storageFactory.newStorageFile(sb.toString()); } - /* Restore the contaier to the state it was before - * it was encrypted with new encryption key. This function is - * called during undo of the EncryptContainerOperation log record + /* Restore the contaier to the state it was before + * it was encrypted with new encryption key. This function is + * called during undo of the EncryptContainerOperation log record * incase of a error/crash before database was successfuly configured with * new encryption properties. * @param ckey the key of the container that needs to be restored. * @exception StandardException Standard Derby error policy */ - void restoreContainer(ContainerKey containerId) - throws StandardException + void restoreContainer(ContainerKey containerId) + throws StandardException { // get rid of the container entry from conatainer cache, - // this will make sure there are no file opens on the current - // container file. - + // this will make sure there are no file opens on the current + // container file. + if (!dataFactory.getContainerCache().discard(containerId)) { if (SanityManager.DEBUG ) SanityManager.THROWASSERT( - "unable to discard container from cache:" + + "unable to discard container from cache:" + containerId); } - StorageFile currentFile = dataFactory.getContainerPath(containerId, + StorageFile currentFile = dataFactory.getContainerPath(containerId, false); StorageFile oldFile = getFile(containerId, true); StorageFile newFile = getFile(containerId, false); - - // if backup of the original container file exists, replace the + + // if backup of the original container file exists, replace the // container with the backup copy. if (privExists(oldFile)) { if (privExists(currentFile)) { @@ -326,41 +347,41 @@ public class EncryptData implements Priv if (!privDelete(newFile)) throw StandardException.newException( - SQLState.UNABLE_TO_DELETE_FILE, + SQLState.UNABLE_TO_DELETE_FILE, newFile); } } /* - * Remove all the old version (encrypted with old key or + * Remove all the old version (encrypted with old key or * un-encrypted) of the containers stored in the data directory . * - * @param inRecovery true , if cleanup is + * @param inRecovery true , if cleanup is * happening during recovery. * @exception StandardException Standard Derby Error Policy */ - public void removeOldVersionOfContainers(boolean inRecovery) + public void removeOldVersionOfContainers(boolean inRecovery) throws StandardException { - - if (inRecovery) + + if (inRecovery) { // find the old version of the container files // and delete them String[] files = dataFactory.getContainerNames(); - if (files != null) + if (files != null) { - // loop through all the files in seg0 and + // loop through all the files in seg0 and // delete all old copies of the containers. - for (int i = files.length-1; i >= 0 ; i--) + for (int i = files.length-1; i >= 0 ; i--) { // if it is a old version of the container file - // delete it. + // delete it. if (isOldContainerFile(files[i])) { StorageFile oldFile = getFile(files[i]); - if (!privDelete(oldFile)) + if (!privDelete(oldFile)) { throw StandardException.newException( SQLState.FILE_CANNOT_REMOVE_FILE, @@ -369,15 +390,15 @@ public class EncryptData implements Priv } } } - }else + }else { - // delete all the old version of the containers. - for (int i = 0 ; i < noOldFiles ; i++) + // delete all the old version of the containers. + for (int i = 0 ; i < noOldFiles ; i++) { - if (!privDelete(oldFiles[i])) + if (!privDelete(oldFiles[i])) { throw StandardException.newException( - SQLState.FILE_CANNOT_REMOVE_FILE, + SQLState.FILE_CANNOT_REMOVE_FILE, oldFiles[i]); } } @@ -385,7 +406,7 @@ public class EncryptData implements Priv } - + private synchronized boolean privExists(StorageFile file) { actionCode = STORAGE_FILE_EXISTS_ACTION; @@ -396,7 +417,7 @@ public class EncryptData implements Priv } - + private synchronized boolean privDelete(StorageFile file) { actionCode = STORAGE_FILE_DELETE_ACTION; @@ -404,10 +425,10 @@ public class EncryptData implements Priv Object ret = AccessController.doPrivileged(this); actionStorageFile = null; return ((Boolean) ret).booleanValue(); - + } - private synchronized boolean privRename(StorageFile fromFile, + private synchronized boolean privRename(StorageFile fromFile, StorageFile destFile) { actionCode = STORAGE_FILE_RENAME_ACTION; @@ -423,7 +444,7 @@ public class EncryptData implements Priv // PrivilegedAction method - public Object run() + public Object run() { switch(actionCode) { Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/InputStreamContainer.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/InputStreamContainer.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/InputStreamContainer.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/InputStreamContainer.java Wed Sep 26 20:01:43 2012 @@ -256,13 +256,15 @@ final class InputStreamContainer extends /** - * Encrypt the container. There is no support to encrypt - * this type of containers. - * - * @exception StandardException Standard Derby error policy + * Encrypts or decrypts the container. + *

+ * These operations are unsupported for this type of container. + * + * @throws StandardException STORE_FEATURE_NOT_IMPLEMENTED */ - protected void encryptContainer(BaseContainerHandle handle, - String newFilePath) + protected void encryptOrDecryptContainer(BaseContainerHandle handle, + String newFilePath, + boolean doEncrypt) throws StandardException { throw StandardException.newException( Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer.java Wed Sep 26 20:01:43 2012 @@ -1206,23 +1206,31 @@ class RAFContainer extends FileContainer /** - * Create encrypted version of the container with the - * user specified encryption properties. - * - * Read all the pages of the container from the original container - * through the page cache, encrypt each page data with new encryption - * mechanism and write to the specified container file. + * Creates encrypted or decrypted version of the container. * - * @param handle the container handle. - * @param newFilePath file to store the new encrypted version of - * the container - * @exception StandardException Derby Standard error policy + * Reads all the pages of the container from the original container + * through the page cache, then either encrypts each page data with the new + * encryption mechanism or decrypts the page data, and finally writes the + * data to the specified new container file. + *

+ * The encryption and decryption engines used to carry out the + * cryptographic operation(s) are configured through the raw store, and + * accessed via the data factory. * + * @param handle the container handle + * @param newFilePath file to store the new version of the container in + * @param doEncrypt tells whether to encrypt or decrypt + * @exception StandardException Derby Standard error policy */ - protected void encryptContainer(BaseContainerHandle handle, - String newFilePath) + protected void encryptOrDecryptContainer(BaseContainerHandle handle, + String newFilePath, + boolean doEncrypt) throws StandardException { + // TEMPORARY FOR DERBY-5792 + if (!doEncrypt) { + throw new UnsupportedOperationException("not yet implemented"); + } BasePage page = null; StorageFile newFile = dataFactory.getStorageFactory().newStorageFile(newFilePath); Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java Wed Sep 26 20:01:43 2012 @@ -4283,21 +4283,14 @@ public final class LogToFile implements } - /* - * Set that the database is encrypted , all the transaction log has - * to be encrypted, and flush the log if requesed. Log needs to - * be flushed first, if this is being set during (re) encryption - * of an existing database. - * - * @param flushLog true, if log needs to be flushed, - * otherwise false. - */ - public void setDatabaseEncrypted(boolean flushLog) + /** {@inheritDoc} */ + public void setDatabaseEncrypted(boolean isEncrypted, boolean flushLog) throws StandardException { - if (flushLog) + if (flushLog) { flushAll(); - databaseEncrypted = true; + } + databaseEncrypted = isEncrypted; } Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/ReadOnly.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/ReadOnly.java?rev=1390712&r1=1390711&r2=1390712&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/ReadOnly.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/ReadOnly.java Wed Sep 26 20:01:43 2012 @@ -369,11 +369,12 @@ public class ReadOnly implements LogFact // nothing to do for read only databases. } - /* - * Set that the database is encrypted. Read-only database can not - * be reencrypted, nothing to do in this case. + /** + * Sets whether the database is encrypted. + *

+ * Read-only database can not be re-encrypted, nothing to do in this case. */ - public void setDatabaseEncrypted(boolean flushLog) + public void setDatabaseEncrypted(boolean isEncrypted, boolean flushLog) { // nothing to do for a read-only database. }