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 2008/05/08 13:37:39 UTC

svn commit: r654482 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/sql/conn/ engine/org/apache/derby/impl/sql/compile/ engine/org/apache/derby/impl/sql/conn/ engine/org/apache/derby/impl/sql/execute/ testing/org/apache/derbyTesting/functi...

Author: dag
Date: Thu May  8 04:37:39 2008
New Revision: 654482

URL: http://svn.apache.org/viewvc?rev=654482&view=rev
Log:
DERBY-3667 SQL roles: Make CURRENT_ROLE check that the role is still valid

This patch, derby-3667-1, makes CURRENT_ROLE, before returning the
value, check if the current role set, if any, is still applicable for the
current user. If it is no longer applicable, the current role is set to NONE. 

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetRoleConstantAction.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java?rev=654482&r1=654481&r2=654482&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java Thu May  8 04:37:39 2008
@@ -1102,6 +1102,31 @@
 	public String getCurrentRoleId(Activation a);
 
 	/**
+	 * Get the current role authorization identifier of the dynamic
+	 * call context associated with this activation. It is checked
+	 * whether it is still valid, that is, not revoked or dropped.
+	 * @param a activation of statement needing current role
+	 * @return String	the role id
+	 *
+	 * @throws StandardException  standard exception policy
+	 */
+	public String getCurrentRoleIdChecked(Activation a)
+			throws StandardException;
+
+	/**
+	 * Checks whether the given role can be legally set for the current user.
+	 *
+	 * This method will read (potentially) the dictionary, so it needs
+	 * a transaction context.
+	 *
+	 * @param role string containing role name
+	 *
+	 * @return true if the role can be set
+	 * @throws StandardException standard exception policy
+	 */
+	public boolean roleIsSettable(String role) throws StandardException;
+
+	/**
 	 * Create a new SQL session context for the current activation
 	 * on the basis of the existing SQL session context (logical
 	 * session context analogue to call stack push, i.e. this happens

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java?rev=654482&r1=654481&r2=654482&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java Thu May  8 04:37:39 2008
@@ -158,10 +158,10 @@
 
 		case C_NodeTypes.CURRENT_ROLE_NODE:
 			sqlName = "CURRENT_ROLE";
-			methodName = "getCurrentRoleId";
+			methodName = "getCurrentRoleIdChecked";
 			methodType = "java.lang.String";
 			dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(
-				Types.VARCHAR, false, 128);
+				Types.VARCHAR, true, 128);
 			//SQL spec Section 6.4 Syntax Rule 4 says that the collation type
 			//of these functions will be the collation of character set
 			//SQL_IDENTIFIER. In Derby's case, that will mean, the collation of
@@ -232,7 +232,7 @@
 											 ClassName.LanguageConnectionContext, 0);
 		int argCount = 0;
 
-		if (methodName.equals("getCurrentRoleId") ||
+		if (methodName.equals("getCurrentRoleIdChecked") ||
 			methodName.equals("getCurrentSchemaName")) {
 
 			acb.pushThisAsActivation(mb);

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java?rev=654482&r1=654481&r2=654482&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java Thu May  8 04:37:39 2008
@@ -53,6 +53,7 @@
 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+import org.apache.derby.iapi.sql.dictionary.RoleDescriptor;
 import org.apache.derby.iapi.types.DataValueFactory;
 import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
 import org.apache.derby.iapi.sql.depend.DependencyManager;
@@ -3226,7 +3227,7 @@
 		return sb;
 	}
 
-	
+
 	/**
 	 * @see LanguageConnectionContext#setCurrentRole(Activation a, String role)
 	 */
@@ -3246,6 +3247,58 @@
 
 
 	/**
+	 * @see LanguageConnectionContext#getCurrentRoleIdChecked(Activation a)
+	 */
+	public String getCurrentRoleIdChecked(Activation a)
+			throws StandardException {
+
+		String role = getCurrentSQLSessionContext(a.getCallActivation()).
+			getRole();
+
+		if (role != null) {
+			beginNestedTransaction(true);
+
+			try {
+				if (!roleIsSettable(role)) {
+					// invalid role, so reset it.
+					setCurrentRole(a, null);
+					role = null;
+				}
+			} finally {
+				commitNestedTransaction();
+			}
+
+		}
+
+		return role;
+	}
+
+
+	/**
+	 * @see LanguageConnectionContext#roleIsSettable(String role)
+	 */
+	public boolean roleIsSettable(String role) throws StandardException {
+		DataDictionary dd = getDataDictionary();
+		String dbo = dd.getAuthorizationDatabaseOwner();
+
+		RoleDescriptor grantDesc = null;
+
+		if (getAuthorizationId().equals(dbo)) {
+			grantDesc = dd.getRoleDefinitionDescriptor(role);
+		} else {
+			grantDesc = dd.getRoleGrantDescriptor
+				(role, getAuthorizationId(), dbo);
+
+			if (grantDesc == null) {
+				// or if not, via PUBLIC?
+				grantDesc = dd.getRoleGrantDescriptor
+					(role, Authorizer.PUBLIC_AUTHORIZATION_ID,dbo);
+			}
+		}
+		return grantDesc != null;
+	}
+
+	/**
 	 * Return the current SQL session context based on caller
 	 *
 	 * @param caller the activation of the caller, if any, of the
@@ -3274,7 +3327,7 @@
 	private SQLSessionContext getCurrentSQLSessionContext() {
 		StatementContext ctx = getStatementContext();
 		SQLSessionContext curr;
-		
+
 		if (ctx == null || !ctx.inUse()) {
 			curr = getTopLevelSQLSessionContext();
 		} else {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetRoleConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetRoleConstantAction.java?rev=654482&r1=654481&r2=654482&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetRoleConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetRoleConstantAction.java Thu May  8 04:37:39 2008
@@ -130,25 +130,10 @@
                         (SQLState.ROLE_INVALID_SPECIFICATION, thisRoleName);
                 }
 
-                if (!currentAuthId.equals(dbo)) {
-                    // is it granted to us mere mortals?
-                    rd = dd.getRoleGrantDescriptor(thisRoleName,
-                                                   currentAuthId,
-                                                   dbo);
-                    if (rd == null) {
-                        // or if not, via PUBLIC?
-                        rd = dd.getRoleGrantDescriptor
-                            (thisRoleName,
-                             Authorizer.PUBLIC_AUTHORIZATION_ID,
-                             dbo);
-
-                        // Nope, we can't set this role, so throw.
-                        if (rd == null) {
-                            throw StandardException.newException
+                if (!lcc.roleIsSettable(thisRoleName)) {
+                    throw StandardException.newException
                               (SQLState. ROLE_INVALID_SPECIFICATION_NOT_GRANTED,
                                thisRoleName);
-                        }
-                    }
                 }
             } finally {
                 // reading above changes idle state, so reestablish it

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java?rev=654482&r1=654481&r2=654482&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java Thu May  8 04:37:39 2008
@@ -260,7 +260,7 @@
         // for dropper.
         _stm.execute("call test_dbo.dropper()");
 
-        String[] expected = new String[]{"OUTERMOST", "TEST_DBO"};
+        String[] expected = new String[]{null, "TEST_DBO"};
         for (int i= 0; i < 1; i++) {
             rs = ps[i].executeQuery();
             assertCurrent(variableKeywords[i], rs, expected[i]);
@@ -367,9 +367,17 @@
         assertTrue("result set empty", rs.next());
         String actualCurrent = rs.getString(1);
 
-        assertTrue(comment + "current is " + actualCurrent +
+        if (expected != null) {
+            assertTrue(comment + "current is " + actualCurrent +
                        ", expected " + expected,
-                   expected.equals(actualCurrent));
+                       expected.equals(actualCurrent));
+        } else {
+            assertTrue(comment + "current is " + actualCurrent +
+                       ", expected null",
+                       actualCurrent == null);
+        }
+
+
 
         // cardinality should be 1
         assertFalse("result set not empty", rs.next());
@@ -680,11 +688,10 @@
      * current value is correctly reset. For roles, the current role
      * is unchanged, since it is lazily checked (and potentially reset
      * to NONE if it no longer exists or it is no longer granted to
-     * session user) only when it is attempted used for anything
-     * except retrieving its current value. For schema, the current
-     * schema should revert back to the session's default schema. This
-     * holds for all frames on the session context stack (see also
-     * caller's check).
+     * session user) only when it is attempted used for anything. For
+     * schema, the current schema should revert back to the session's
+     * default schema. This holds for all frames on the session
+     * context stack (see also caller's check).
      */
     public static void dropper() throws SQLException
     {
@@ -699,7 +706,7 @@
             stm.executeUpdate("drop schema outermost restrict");
             stm.close();
 
-            String[] expected = new String[]{"OUTERMOST", "TEST_DBO"};
+            String[] expected = new String[]{null, "TEST_DBO"};
 
             // check that we revert correctly
             for (int i= 0; i < variableKeywords.length; i++) {