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 2007/04/13 00:54:20 UTC
svn commit: r528274 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/jdbc/ engine/org/apache/derby/loc/
shared/org/apache/derby/shared/common/reference/
testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/
Author: dag
Date: Thu Apr 12 15:54:20 2007
New Revision: 528274
URL: http://svn.apache.org/viewvc?view=rev&rev=528274
Log:
DERBY-2264 Patch DERBY-2264-7.diff, which restricts database hard upgrade to the database owner.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DboPowersTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java?view=diff&rev=528274&r1=528273&r2=528274
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java Thu Apr 12 15:54:20 2007
@@ -217,16 +217,19 @@
boolean createBoot = createBoot(info);
// DERBY-2264: keeps track of whether we do a plain boot before an
- // (re)encryption boot to (possibly) authenticate first. We can not
- // authenticate before we have booted, so in order to enforce data
- // base owner powers over encryption, we need a plain boot, then
- // authenticate, then, if all is well, boot with (re)encryption.
- // Encryption at create time is not checked.
+ // (re)encryption or hard upgrade boot to (possibly) authenticate
+ // first. We can not authenticate before we have booted, so in
+ // order to enforce data base owner powers over encryption or
+ // upgrade, we need a plain boot, then authenticate, then, if all
+ // is well, boot with (re)encryption or upgrade. Encryption at
+ // create time is not checked.
boolean isTwoPhaseEncryptionBoot = (!createBoot &&
isEncryptionBoot(info));
+ boolean isTwoPhaseUpgradeBoot = (!createBoot &&
+ isHardUpgradeBoot(info));
// Save original properties if we modified them for
- // isTwoPhaseEncryptionBoot.
+ // two phase encryption or upgrade boot.
Properties savedInfo = null;
if (database != null)
@@ -234,12 +237,13 @@
// database already booted by someone else
tr.setDatabase(database);
isTwoPhaseEncryptionBoot = false;
+ isTwoPhaseUpgradeBoot = false;
}
else if (!shutdown)
{
- if (isTwoPhaseEncryptionBoot) {
+ if (isTwoPhaseEncryptionBoot || isTwoPhaseUpgradeBoot) {
savedInfo = info;
- info = removeEncryptionProps((Properties)info.clone());
+ info = removePhaseTwoProps((Properties)info.clone());
}
// Return false iff the monitor cannot handle a service of the
@@ -298,18 +302,20 @@
// the rest.
tr.startTransaction();
- if (isTwoPhaseEncryptionBoot) {
- // DERBY-2264: shutdown and boot again with encryption
- // attributes active. This is restricted to the database owner.
+ if (isTwoPhaseEncryptionBoot || isTwoPhaseUpgradeBoot) {
+ // DERBY-2264: shutdown and boot again with encryption or
+ // upgrade attributes active. This is restricted to the
+ // database owner.
if (!usingNoneAuth) {
// a failure here leaves database booted, but no
// (re)encryption has taken place and the connection is
// rejected.
- checkIsDBOwner(OP_ENCRYPT);
+ checkIsDBOwner(isTwoPhaseEncryptionBoot? OP_ENCRYPT :
+ OP_HARD_UPGRADE);
}
// shutdown and reboot using saved properties which
- // include the (re)encyption attributes
+ // include the (re)encyption or upgrade attribute(s)
info = savedInfo;
handleException(tr.shutdownDatabaseException());
restoreContextStack();
@@ -322,7 +328,7 @@
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT(
"bootDatabase failed after initial plain boot " +
- "for (re)encryption");
+ "for (re)encryption or upgrade");
}
tr.clearContextInError();
setInactive();
@@ -442,18 +448,31 @@
(p.getProperty(Attribute.NEW_CRYPTO_EXTERNAL_KEY) != null));
}
+ /**
+ * Examine boot properties and determine if a boot with the given
+ * attributes would entail a hard upgrade.
+ *
+ * @param p the attribute set
+ * @return true if a boot will hard upgrade the database
+ */
+ private boolean isHardUpgradeBoot(Properties p)
+ {
+ return Boolean.valueOf(
+ p.getProperty(Attribute.UPGRADE_ATTR)).booleanValue();
+ }
/**
- * Remove any encryption properties from the given properties
+ * Remove any encryption or upgarde properties from the given properties
*
* @param p the attribute set
* @return clone sans encryption properties
*/
- private Properties removeEncryptionProps(Properties p)
+ private Properties removePhaseTwoProps(Properties p)
{
p.remove(Attribute.DATA_ENCRYPTION);
p.remove(Attribute.NEW_BOOT_PASSWORD);
p.remove(Attribute.NEW_CRYPTO_EXTERNAL_KEY);
+ p.remove(Attribute.UPGRADE_ATTR);
return p;
}
@@ -567,6 +586,7 @@
/* Enumerate operations controlled by database owner powers */
private static final int OP_ENCRYPT = 0;
private static final int OP_SHUTDOWN = 1;
+ private static final int OP_HARD_UPGRADE = 2;
/**
* Check if actual authenticationId is equal to the database owner's.
*
@@ -587,6 +607,9 @@
actualId, tr.getDBName());
case OP_SHUTDOWN:
throw newSQLException(SQLState.AUTH_SHUTDOWN_NOT_DB_OWNER,
+ actualId, tr.getDBName());
+ case OP_HARD_UPGRADE:
+ throw newSQLException(SQLState.AUTH_HARD_UPGRADE_NOT_DB_OWNER,
actualId, tr.getDBName());
default:
if (SanityManager.DEBUG) {
Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?view=diff&rev=528274&r1=528273&r2=528274
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Thu Apr 12 15:54:20 2007
@@ -858,6 +858,13 @@
<arg>databaseName</arg>
</msg>
+ <msg>
+ <name>2850J.C</name>
+ <text>User '{0}' cannot hard upgrade database '{1}'. Only the database owner can perform this operation.</text>
+ <arg>authorizationID</arg>
+ <arg>databaseName</arg>
+ </msg>
+
</family>
Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?view=diff&rev=528274&r1=528273&r2=528274
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Thu Apr 12 15:54:20 2007
@@ -1388,6 +1388,7 @@
String AUTH_NO_OBJECT_PERMISSION = "2850G";
String AUTH_SHUTDOWN_NOT_DB_OWNER = "2850H.C";
String AUTH_ENCRYPT_NOT_DB_OWNER = "2850I.C";
+ String AUTH_HARD_UPGRADE_NOT_DB_OWNER = "2850J.C";
/*
** Dependency manager
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DboPowersTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DboPowersTest.java?view=diff&rev=528274&r1=528273&r2=528274
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DboPowersTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DboPowersTest.java Thu Apr 12 15:54:20 2007
@@ -41,7 +41,7 @@
* {no authentication, authentication and authentication/sqlAuthorization} x
* {data base owner, other user }
*
- * One could consider removing the client/server suite to speed up
+ * One could consider removing the client/server suites to speed up
* this test as it does not add much value given the nature of the changes.
*
*/
@@ -77,7 +77,11 @@
}
/**
- * Create a new instance of DboPowersTest (for encryption tests)
+ * Create a new instance of DboPowersTest (for encryption and hard
+ * upgrade tests). The database owner credentials is needed to
+ * always be able to perform the restricted operations (when they
+ * are not under test, but used as part of a test fixture for
+ * another operation).
*
* @param name Fixture name
* @param authLevel authentication level with which test is run
@@ -125,6 +129,14 @@
dboEncryptionSuite("suite: encryption powers, client")));
}
+ /* Database hard upgrade powers */
+
+ suite.addTest(
+ dboHardUpgradeSuite("suite: hard upgrade powers, embedded"));
+ suite.addTest(
+ TestConfiguration.clientServerDecorator(
+ dboHardUpgradeSuite("suite: hard upgrade powers, client")));
+
return suite;
}
@@ -155,7 +167,7 @@
* @return A suite containing the test case for shutdown
* incarnated for the three security levels no authentication,
* authentication, and authentication plus sqlAuthorization, The
- * latter two has an instance for dbo, and one for ordinary user,
+ * latter two has an instance for dbo, and one for an ordinary user,
* so there are in all five incarnations of tests.
*/
private static Test dboShutdownSuite(String framework)
@@ -169,7 +181,7 @@
new TestSuite("suite: security level=" +
secLevelNames[NOAUTHENTICATION]);
noauthSuite.addTest(new DboPowersTest("testShutDown",
- NOAUTHENTICATION));;
+ NOAUTHENTICATION));
tests[NOAUTHENTICATION] = noauthSuite;
/* First decorate with users, then with authentication. Do this
@@ -204,7 +216,7 @@
/**
* Wraps the shutdown fixture in decorators to run with data
- * base owner and other valid user.
+ * base owner and one other valid user.
*
* @param autLev security context to use
*/
@@ -311,7 +323,7 @@
* @return A suite containing the test case for encryption
* incarnated for the three security levels no authentication,
* authentication, and authentication plus sqlAuthorization, The
- * latter two has an instance for dbo, and one for ordinary user,
+ * latter two has an instance for dbo, and one for an ordinary user,
* so there are in all five incarnations of tests.
*/
private static Test dboEncryptionSuite(String framework)
@@ -362,7 +374,7 @@
/**
* Wraps the encryption fixtures in decorators to run with data
- * base owner and other valid user.
+ * base owner and one other valid user.
*
* @param autLev security context to use
*/
@@ -566,26 +578,177 @@
*/
private void vetEncryptionAttempt (String user, SQLException e)
{
+ vetAttempt(user, e, "2850I", "(re)encryption");
+ }
+
+ /**
+ *
+ * Construct suite of tests for hard upgrade database action
+ *
+ * NOTE: there is no real upgrade going on here since the
+ * database is created with the same version, but the checking
+ * is performed nonetheless, which is what we are testing
+ * here. This saves us from having to create a database with
+ * an old version of Derby to test this power.
+ *
+ * @param framework Derby framework name
+ * @return A suite containing the test case for hard upgrade
+ * incarnated for the three security levels no authentication,
+ * authentication, and authentication plus sqlAuthorization, The
+ * latter two has an instance for dbo, and one for an ordinary user,
+ * so there are in all five incarnations of tests.
+ */
+ private static Test dboHardUpgradeSuite(String framework)
+ {
+ Test tests[] = new Test[SQLAUTHORIZATION+1]; // one per authLevel
+
+ /* Tests without any authorization active (level ==
+ * NOAUTHENTICATION).
+ */
+ TestSuite noauthSuite =
+ new TestSuite("suite: security level=" +
+ secLevelNames[NOAUTHENTICATION]);
+ noauthSuite.addTest(new DboPowersTest("testHardUpgrade",
+ NOAUTHENTICATION,
+ "foo", "bar"));
+ tests[NOAUTHENTICATION] = noauthSuite;
+
+ /* First decorate with users, then with authentication. Do this
+ * twice, once for authentication only, and once for
+ * authentication + sqlAuthorization (see extra decorator
+ * added below).
+ */
+ for (int autLev = AUTHENTICATION;
+ autLev <= SQLAUTHORIZATION ; autLev++) {
+
+ tests[autLev] = wrapHardUpgradeUserTests(autLev);
+ }
+
+ TestSuite suite = new TestSuite("dboPowers:"+framework);
+
+ /* run tests with no authentication enabled */
+ suite.addTest(tests[NOAUTHENTICATION]);
+
+ /* run test for all users with only authentication enabled */
+ suite.addTest(tests[AUTHENTICATION]);
+
+ /* run test for all users with authentication and
+ * sqlAuthorization enabled
+ */
+ suite.addTest(
+ TestConfiguration.
+ sqlAuthorizationDecorator(tests[SQLAUTHORIZATION]));
+
+ return suite;
+ }
+
+ /**
+ * Wraps the shutdown fixture in decorators to run with data
+ * base owner and one other valid user.
+ *
+ * @param autLev security context to use
+ */
+
+ private static Test wrapHardUpgradeUserTests(int autLev)
+ {
+ // add decorator for different users authenticated
+ TestSuite usersSuite =
+ new TestSuite("usersSuite: security level=" +
+ secLevelNames[autLev]);
+
+ // First decorate with users, then with
+ for (int userNo = 0; userNo < users.length; userNo++) {
+ usersSuite.addTest
+ (TestConfiguration.changeUserDecorator
+ (new DboPowersTest("testHardUpgrade",
+ autLev,
+ users[autLev-1][0], // dbo
+ users[autLev-1][0].concat(pwSuffix)),
+ users[autLev-1][userNo],
+ users[autLev-1][userNo].concat(pwSuffix)));
+ }
+
+ return DatabasePropertyTestSetup.
+ builtinAuthentication(usersSuite, users[autLev-1], pwSuffix);
+ }
+
+ /**
+ * Test database upgrade power enforcement
+ *
+ * @throws SQLException
+ */
+ public void testHardUpgrade() throws SQLException
+ {
+ println("testHardUpgrade: auth=" + this._authLevel +
+ " user="+getTestConfiguration().getUserName());
+
+ // make sure db is created
+ getConnection().close();
+ // shut it down in preparation for upgrade boot
+ bringDbDown();
+
+ String user = getTestConfiguration().getUserName();
+ String password = getTestConfiguration().getUserPassword();
+
+ DataSource ds = JDBCDataSource.getDataSource();
+ JDBCDataSource.setBeanProperty(
+ ds, "connectionAttributes", "upgrade=true");
+ JDBCDataSource.setBeanProperty(ds, "user", user);
+ JDBCDataSource.setBeanProperty(ds, "password", password);
+ try {
+ ds.getConnection();
+ vetHardUpgradeAttempt(user, null);
+ } catch (SQLException e) {
+ vetHardUpgradeAttempt(user, e);
+ }
+
+ bringDbDown();
+ }
+
+
+ /**
+ * Decide if the result of trying to hard upgrade the database is
+ * compliant with the semantics introduced by DERBY-2264.
+ *
+ * @param user The db user under which we tried to upgrade
+ * @param e Exception caught during attempt, if any
+ */
+ private void vetHardUpgradeAttempt (String user, SQLException e)
+ {
+ vetAttempt(user, e, "2850J", "hard upgrade");
+ }
+
+ /**
+ * Decide if the result of trying operation yields expected result.
+ *
+ * @param user The db user under which we tried to upgrade
+ * @param e Exception caught during attempted operation, if any
+ * @param state The expected SQL state if this operation fails due to
+ * insufficient power
+ * @param operation string describing the operation attempted
+ */
+ private void vetAttempt (String user, SQLException e,
+ String state, String operation)
+ {
switch (_authLevel) {
case NOAUTHENTICATION:
- assertEquals("encryption, no authentication", null, e);
+ assertEquals(operation + ", no authentication", null, e);
break;
case AUTHENTICATION:
if ("APP".equals(user)) {
- assertEquals("encryption, authentication, db owner", null, e);
+ assertEquals(operation + ", authentication, db owner", null, e);
} else {
- assertSQLState("database encryption restriction, " +
- "authentication, not db owner", "2850I", e);
+ assertSQLState(operation + ", authentication, not db owner",
+ state, e);
}
break;
case SQLAUTHORIZATION:
if ("TEST_DBO".equals(user)) {
- assertEquals("encryption, SQL authorization, db owner",
+ assertEquals(operation + ", SQL authorization, db owner",
null, e);
} else {
- assertSQLState("encryption restriction, " +
- "SQL authorization, not db owner",
- "2850I", e);
+ assertSQLState(operation +", SQL authorization, not db owner",
+ state, e);
}
break;
default: