db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d..@apache.org
Subject svn commit: r632419 - in /db/derby/code/trunk/java: build/org/apache/derbyBuild/ engine/org/apache/derby/authentication/ engine/org/apache/derby/iapi/security/ engine/org/apache/derby/security/ testing/org/apache/derbyTesting/unitTests/junit/
Date Fri, 29 Feb 2008 19:34:42 GMT
Author: djd
Date: Fri Feb 29 11:34:33 2008
New Revision: 632419

URL: http://svn.apache.org/viewvc?rev=632419&view=rev
Log:
DERBY-2109 Security Principals and Permission classes to support system level permissions in Derby through standard Java security policy.

Committed a sub-set of patch 12 related to the security code without enabling any functionality.
Note that the SystemPrivilegesPermissionTest is not added into the _Suite (as the complete patch does)
as I think it will fail under J2ME. It passes with classes but fails with jars but that is to be expected
as the Derby's permissions classes are not yet added into the jars, this will occur once they are used.

Patch contributed by: Martin Zaun Email: martin dot zaun at sun dot com

Added:
    db/derby/code/trunk/java/engine/org/apache/derby/authentication/SystemPrincipal.java   (with props)
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/security/
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/security/SecurityUtil.java   (with props)
Removed:
    db/derby/code/trunk/java/engine/org/apache/derby/authentication/DatabasePrincipal.java
Modified:
    db/derby/code/trunk/java/build/org/apache/derbyBuild/classlister.java
    db/derby/code/trunk/java/engine/org/apache/derby/security/DatabasePermission.java
    db/derby/code/trunk/java/engine/org/apache/derby/security/SystemPermission.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.policy

Modified: db/derby/code/trunk/java/build/org/apache/derbyBuild/classlister.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/build/org/apache/derbyBuild/classlister.java?rev=632419&r1=632418&r2=632419&view=diff
==============================================================================
--- db/derby/code/trunk/java/build/org/apache/derbyBuild/classlister.java (original)
+++ db/derby/code/trunk/java/build/org/apache/derbyBuild/classlister.java Fri Feb 29 11:34:33 2008
@@ -494,6 +494,7 @@
 				|| className.startsWith("org.apache.derby.impl.jdbc")
 				|| className.startsWith("org.apache.derby.impl.services")
 				|| className.startsWith("org.apache.derby.iapi.")
+				|| className.startsWith("org.apache.derby.security.")
 				)
 			{
 				return;

Added: db/derby/code/trunk/java/engine/org/apache/derby/authentication/SystemPrincipal.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/authentication/SystemPrincipal.java?rev=632419&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/authentication/SystemPrincipal.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/authentication/SystemPrincipal.java Fri Feb 29 11:34:33 2008
@@ -0,0 +1,153 @@
+/*
+
+   Derby - Class org.apache.derby.authentication.SystemPrincipal
+
+   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.derby.authentication;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+
+/**
+ * This class represents Derby's notion of a principal, a concept of
+ * user identity with controlled access to Derby System Privileges.
+ * An authenticated user may have other identities which make sense in
+ * other code domains.
+ * <p>
+ * Note that principal names do NOT follow Authorization Identifier rules.
+ * For instance, although edward and edWard both match the normalized
+ * authorization identifier EDWARD, the instances
+ * <code>SystemPrincipal("edward")</code> and
+ * <code>SystemPrincipal("edWard")</code> represent different principals
+ * under the methods <code>getName()</code>, <code>equals()</code>, and
+ * <code>hashCode()</code>.
+ * <p>
+ * According to JAASRefGuide, Principal classes must implement Serializable.
+ *
+ * @see Principal#name
+ * @see <a href="http://java.sun.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html#Principals">JAASRefGuide on Principals</a> 
+ */
+final public class SystemPrincipal implements Principal, Serializable {
+
+    /**
+     * BTW, this class currently does not require special handling during
+     * serialization/deserialization, so, there's no need to define methods
+     * <code>readObject(ObjectInputStream)</code> and 
+     * <code>writeObject(ObjectOutputStream)</code>.
+     */
+    static final long serialVersionUID = 925380094921530190L;
+
+    /**
+     * The name of the principal.
+     * <p>
+     * Note that the name is not a "normalized" Authorization Identifier.
+     * This is due to peculiarities of the Java Security Runtime, which
+     * compares a <code>javax.security.auth.Subject</code>'s Principals
+     * against the literal Principal name as declared in the policy files,
+     * and not against the return value of method <code>getName()</code>.
+     * So, a normalization of names within SystemPrincipal doesn't affect
+     * permission checking by the SecurityManager.
+     * <p>
+     * In order for a <code>javax.security.auth.Subject</code> to be
+     * granted permissions on the basis Authorization Identifier rules, e.g.,
+     * for a Subject authenticated as edWard to fall under a policy clause
+     * declared for EDWARD, the Subject has to be constructed (or augmented)
+     * with both the literal name and the normalized Authorization Identifier.
+     * <p>
+     * As an alternative approach, class <code>SystemPrincipal</code> could
+     * implement the non-standard interface
+     * <code>com.sun.security.auth.PrincipalComparator</code>, which declares
+     * a method <code>implies(Subject)<code> that would allow for Principals
+     * to match Subjects on the basis of normalized Authorization Identifiers.
+     * But then we'd be relying upon non-standard Security Runtime behaviour.
+     *
+     * @see <a href="http://wiki.apache.org/db-derby/UserIdentifiers">User Names & Authorization Identifiers in Derby</a>
+     */
+    private final String name;
+
+    /**
+     * Constructs a principal for a given name.
+     *
+     * @param name the name of the principal
+     * @throws NullPointerException if name is null
+     * @throws IllegalArgumentException if name is not a legal Principal name
+     */
+    public SystemPrincipal(String name) {
+        // RuntimeException messages not localized
+        if (name == null) {
+            throw new NullPointerException("name can't be null");
+        }
+        if (name.length() == 0) {
+            throw new IllegalArgumentException("name can't be empty");
+        }
+        this.name = name;
+    }
+
+    /**
+     * Compares this principal to the specified object. Returns true if
+     * the object passed in matches the principal represented by the
+     * implementation of this interface.
+     *
+     * @param other principal to compare with
+     * @return true if the principal passed in is the same as that
+     *         encapsulated by this principal, and false otherwise
+     * @see Principal#equals
+     */
+    public boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (!(other instanceof SystemPrincipal)) {
+            return false;
+        }
+        final SystemPrincipal that = (SystemPrincipal)other;
+        return name.equals(that.name);
+    }
+
+    /**
+     * Returns the name of this principal.
+     *
+     * @return the name of this principal
+     * @see Principal#getName()
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns a hashcode for this principal.
+     *
+     * @return a hashcode for this principal
+     * @see Principal#hashCode()
+     */
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    /**
+     * Returns a string representation of this principal.
+     *
+     * @return a string representation of this principal
+     * @see Principal#toString()
+     */
+    public String toString() {
+        return getClass().getName() + "(" + name + ")";
+    }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/authentication/SystemPrincipal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/security/SecurityUtil.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/security/SecurityUtil.java?rev=632419&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/security/SecurityUtil.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/security/SecurityUtil.java Fri Feb 29 11:34:33 2008
@@ -0,0 +1,165 @@
+/*
+
+   Derby - Class org.apache.derby.security.SystemPermission
+
+   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.derby.iapi.security;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.io.IOException;
+
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.AccessControlException;
+import java.security.AccessControlContext;
+import java.security.Permission;
+import javax.security.auth.Subject;
+
+import org.apache.derby.authentication.SystemPrincipal;
+import org.apache.derby.iapi.util.IdUtil;
+import org.apache.derby.iapi.error.StandardException;
+
+
+/**
+ * This class provides helper functions for security-related features.
+ */
+public class SecurityUtil {
+
+    /**
+     * Creates a (read-only) Subject representing a given user.
+     *
+     * @param user the user name
+     * @return a Subject representing the user by its exact and normalized name
+     *
+     * @see <a href="http://wiki.apache.org/db-derby/UserIdentifiers">User Names & Authorization Identifiers in Derby</a>
+     */
+    static public Subject createSystemPrincipalSubject(String user) {
+        final Set principals = new HashSet();
+        // add the authenticated user
+        if (user != null) {
+            // The Java security runtime checks whether a Subject falls
+            // under a Principal policy by looking for a literal match
+            // of the Principal name as exactly found in a policy file
+            // clause with any of the Subject's listed Principal names.
+            //
+            // To support Authorization Identifier as Principal names
+            // we add two Principals here: one with the given name and
+            // another one with the normalized name.  This way, a
+            // permission will be granted if the authenticated user name
+            // matches a Principal clause in the policy file with either
+            // the exact same name or the normalized name.
+            //
+            // An alternative approach of normalizing all names within
+            // SystemPrincipal has issues; see comments there.
+            principals.add(new SystemPrincipal(user));
+            principals.add(new SystemPrincipal(getAuthorizationId(user)));
+        }
+        final boolean readOnly = true;
+        final Set credentials = new HashSet();
+        return new Subject(readOnly, principals, credentials, credentials);
+    }
+
+    /**
+     * Returns the Authorization Identifier for a principal name.
+     *
+     * @param name the name of the principal
+     * @return the authorization identifier for this principal
+     */
+    static private String getAuthorizationId(String name) {
+        // RuntimeException messages not localized
+        if (name == null) {
+            throw new NullPointerException("name can't be null");
+        }
+        if (name.length() == 0) {
+            throw new IllegalArgumentException("name can't be empty");
+        }
+        try {
+            return IdUtil.getUserAuthorizationId(name);
+        } catch (StandardException se) {
+            throw new IllegalArgumentException(se.getMessage());
+		}
+    }
+
+    /**
+     * Checks that a Subject has a Permission under the SecurityManager.
+     * To perform this check the following policy grant is required
+     * <ul>
+     * <li> to run the encapsulated test:
+     *      permission javax.security.auth.AuthPermission "doAsPrivileged";
+     * </ul>
+     * or an AccessControlException will be raised detailing the cause.
+     * <p>
+     *
+     * @param subject the subject representing the SystemPrincipal(s)
+     * @param perm the permission to be checked
+     * @throws AccessControlException if permissions are missing
+     */
+    static public void checkSubjectHasPermission(final Subject subject,
+                                                 final Permission perm) {
+        // the checks
+        final PrivilegedAction runCheck
+            = new PrivilegedAction() {
+                    public Object run() {
+                        AccessController.checkPermission(perm);
+                        return null;
+                    }
+                };
+        final PrivilegedAction runCheckAsPrivilegedUser
+            = new PrivilegedAction() {
+                    public Object run() {
+                        // run check as subject with new access control context
+                        final AccessControlContext acc = null;
+                        Subject.doAsPrivileged(subject, runCheck, acc);
+                        return null;
+                    }
+                };
+
+        // run check as privileged action for narrow codebase permissions
+        AccessController.doPrivileged(runCheckAsPrivilegedUser);
+    }
+
+    /**
+     * Checks that a User has a Permission under the SecurityManager.
+     * To perform this check the following policy grant is required
+     * <ul>
+     * <li> to run the encapsulated test:
+     *      permission javax.security.auth.AuthPermission "doAsPrivileged";
+     * </ul>
+     * or an AccessControlException will be raised detailing the cause.
+     * <p>
+     *
+     * @param user the user to be check for having the permission
+     * @param perm the permission to be checked
+     * @throws AccessControlException if permissions are missing
+     */
+    static public void checkUserHasPermission(String user,
+                                              Permission perm) {
+        // approve action if not running under a security manager
+        if (System.getSecurityManager() == null) {
+            return;
+        }
+
+        // check the subject for having the permission
+        final Subject subject = createSystemPrincipalSubject(user);
+        checkSubjectHasPermission(subject, perm);
+    }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/security/SecurityUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/security/DatabasePermission.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/security/DatabasePermission.java?rev=632419&r1=632418&r2=632419&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/security/DatabasePermission.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/security/DatabasePermission.java Fri Feb 29 11:34:33 2008
@@ -22,6 +22,10 @@
 package org.apache.derby.security;
 
 import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.security.AccessController;
 
 import java.util.Set;
 import java.util.HashSet;
@@ -51,7 +55,7 @@
  * @see SystemPermission
  * @see java.io.FilePermission
  */
-public class DatabasePermission extends Permission {
+final public class DatabasePermission extends Permission {
 
     /**
      * The URL protocol scheme specifying a directory location.
@@ -59,6 +63,16 @@
     static public final String URL_PROTOCOL_DIRECTORY = "directory:";
 
     /**
+     * The location text matching any database anywhere.
+     */
+    static public final String URL_PATH_INCLUSIVE_STRING = "<<ALL FILES>>";
+
+    /**
+     * The path type character matching any database anywhere.
+     */
+    static public final char URL_PATH_INCLUSIVE_CHAR = 'I';
+
+    /**
      * The URL file path separator character.
      */
     static public final char URL_PATH_SEPARATOR_CHAR = '/';
@@ -69,14 +83,13 @@
     static public final char URL_PATH_RELATIVE_CHAR = '.';
 
     /**
-     * The wildcard character specifying arbitrarily named databases
-     * under a directory path.
+     * The wildcard character matching any database in a directory.
      */
     static public final char URL_PATH_WILDCARD_CHAR = '*';
 
     /**
-     * The wildcard character specifying arbitrarily named databases
-     * anywhere under a path and its subdirectories.
+     * The wildcard character matching any database under a directory
+     * or its subdirectories.
      */
     static public final char URL_PATH_RECURSIVE_CHAR = '-';
 
@@ -120,10 +133,11 @@
      *
      * The path consists of a canonicalized form of the user-specified URL,
      * stripped off the protocol specification and any recursive/wildcard
-     * characters.  The canonical path is used when testing permissions
-     * with implies(), where real directory locations, not just notational
-     * differences, ought to be compared.  Analog to java.io.FilePermission,
-     * the canonical path is also used by equals() and hashCode() to support
+     * characters, or {@code "<<ALL FILES>>"} for the "anywhere" permission.
+     * The canonical path is used when testing permissions with implies(),
+     * where real directory locations, not just notational differences,
+     * ought to be compared.  Analog to java.io.FilePermission, the
+     * canonical path is also used by equals() and hashCode() to support
      * hashing and mapping of permissions by their real directory locations.
      *
      * Because canonical file paths are platform dependent, this field
@@ -134,7 +148,7 @@
 
     /**
      * The parent directory of this permission's canonical directory path,
-     * or null if this permission's path does not name a parent directory.
+     * or null if this permission's path does not have a parent directory.
      *
      * Because canonical file paths are platform dependent, this field
      * must not be serialized (hence transient) but be recomputed from
@@ -143,13 +157,13 @@
     private transient String parentPath;
 
     /**
-     * Indicates whether the path denotes a recursive, wildcard, or single
-     * location.
+     * Indicates whether the path denotes an inclusive, recursive, wildcard,
+     * or single location.
      *
-     * If the path denotes a recursive or wildcard location, this field's
-     * value is URL_PATH_RECURSIVE_CHAR or URL_PATH_WILDCARD_CHAR,
-     * respectively; otherwise, it's URL_PATH_SEPARATOR_CHAR denoting a
-     * single location.
+     * If the path denotes an inclusive, recursive or wildcard location,
+     * this field's value is URL_PATH_INCLUSIVE_CHAR, URL_PATH_RECURSIVE_CHAR,
+     * or URL_PATH_WILDCARD_CHAR, respectively; otherwise, it's
+     * URL_PATH_SEPARATOR_CHAR denoting a single location.
      */
     private char pathType;
 
@@ -171,17 +185,16 @@
      * <ul>
      * <li> "directory:location" - refers to a database called
      *      <i>location</i>,
-     * <li> "directory:location/*" - refers to any database in the
+     * <li> "directory:location/*" - matches any database in the
      *      directory <i>location</i>,
-     * <li> "directory:location/-" - refers to any database anywhere under
+     * <li> "directory:location/-" - matches any database under
      *      <i>location</i> or its subdirectories.
-     * <li> "directory:*" - refers to any database in the user's current
+     * <li> "directory:*" - matches any database in the user's current
      *      working directory.
-     * <li> "directory:-" - refers to any database anywhere under the
+     * <li> "directory:-" - matches any database under the
      *      user's current working directory or its subdirectories.
+     * <li> {@code "directory:<<ALL FILES>>"} matches any database anywhere.
      * </ul>
-     * Note that in contrast to FilePermission, there is no reasonable use
-     * for a special pathname "<<ALL FILES>>" matching all locations.
      *
      * @param url the database URL
      * @param actions the action string
@@ -209,18 +222,14 @@
      * @throws IllegalArgumentException if not a list of legal actions
      */
     protected void initActions(String actions) {
-        // note that exception messages on the action list aren't localized,
-        // as is the general rule with runtime exceptions indicating
-        // internal coding errors
-
         // analog to java.security.BasicPermission, we check that actions
         // is not null nor empty
-	if (actions == null) {
-	    throw new NullPointerException("actions can't be null");
+        if (actions == null) {
+            throw new NullPointerException("actions can't be null");
+        }
+        if (actions.length() == 0) {
+            throw new IllegalArgumentException("actions can't be empty");
         }
-	if (actions.length() == 0) {
-	    throw new IllegalArgumentException("actions can't be empty");
-	}
 
         // splitting the comma-separated list into the individual actions
         // may throw a java.util.regex.PatternSyntaxException, which is a
@@ -249,18 +258,14 @@
      */
     protected void initLocation(String url)
         throws IOException {
-        // note that exception messages on the URL aren't localized,
-        // as is the general rule with runtime exceptions indicating
-        // internal coding errors
-
         // analog to java.security.BasicPermission, we check that URL
         // is not null nor empty
-	if (url == null) {
-	    throw new NullPointerException("URL can't be null");
+        if (url == null) {
+            throw new NullPointerException("URL can't be null");
+        }
+        if (url.length() == 0) {
+            throw new IllegalArgumentException("URL can't be empty");
         }
-	if (url.length() == 0) {
-	    throw new IllegalArgumentException("URL can't be empty");
-	}
 
         // check URL's protocol scheme and initialize path
         if (!url.startsWith(URL_PROTOCOL_DIRECTORY)) {
@@ -270,9 +275,13 @@
         }
         String p = url.substring(URL_PROTOCOL_DIRECTORY.length());
 
-        // check path for relative/recursive/wildcard specifications,
+        // check path for inclusive/relative/recursive/wildcard specifications,
         // split path into real pathname and the path type
-        if (p.equals(URL_PATH_RECURSIVE_STRING)) {
+        if (p.equals(URL_PATH_INCLUSIVE_STRING)) {
+            // inclusive:  "<<ALL FILES>>" --> 'I', "<<ALL FILES>>"
+            pathType = URL_PATH_INCLUSIVE_CHAR;
+            // p = p;
+        } else if (p.equals(URL_PATH_RECURSIVE_STRING)) {
             // relative & recursive:  "-" --> '-', "./"
             pathType = URL_PATH_RECURSIVE_CHAR;
             p = URL_PATH_RELATIVE_PREFIX;
@@ -294,29 +303,60 @@
             // p = p;
         }
 
-        // resolve against user's working directory if relative pathname
-        if (p.startsWith(URL_PATH_RELATIVE_PREFIX)) {
-            final String cwd = System.getProperty("user.dir");
-            // concatenated path "<cwd>/./<path>" will be canonicalized
-            p = cwd + URL_PATH_SEPARATOR_STRING + p;
-        }
-
-        // store canonicalized path as required for implies(Permission);
-        // may throw IOException 
-        final File f = (new File(p)).getCanonicalFile();
-        this.path = f.getPath();
-
-        // store canonicalized path of parent file as required for
-        // implies(Permission); may throw IOException; note that
-        // the path already denotes parent directory if of wildcard type:
-        // for example, the parent of "/a/-" or "/a/*" is "/a"
-        this.parentPath = ((pathType != URL_PATH_SEPARATOR_CHAR)
-                           ? path : f.getParent());
-
-        //assert (pathType == URL_PATH_SEPARATOR_CHAR
-        //        || pathType == URL_PATH_WILDCARD_CHAR
-        //        || pathType == URL_PATH_RECURSIVE_CHAR);
-        //assert (path != null);
+        // canonicalize the path and assign parentPath
+        if (pathType == URL_PATH_INCLUSIVE_CHAR) {
+            path = URL_PATH_INCLUSIVE_STRING;
+            //assert(parentPath == null);
+        } else {
+            // resolve against user's working directory if relative pathname;
+            // the read access to the system property is encapsulated in a
+            // doPrivileged() block to allow for confined codebase permission
+            // grants
+            if (p.startsWith(URL_PATH_RELATIVE_PREFIX)) {
+                final String cwd = (String)AccessController.doPrivileged(
+                    new PrivilegedAction() {
+                        public Object run() {
+                            return System.getProperty("user.dir");
+                        }
+                    });
+                // concatenated path "<cwd>/./<path>" will be canonicalized
+                p = cwd + URL_PATH_SEPARATOR_STRING + p;
+            }
+            final String absPath = p;
+
+            // store canonicalized path as required for implies(Permission);
+            // may throw IOException; canonicalization reads the "user.dir"
+            // system property, which we encapsulate in a doPrivileged()
+            // block to allow for confined codebase permission grants
+            final File f;
+            try {
+                f = (File)AccessController.doPrivileged(
+                    new PrivilegedExceptionAction() {
+                        public Object run() throws IOException {
+                            return (new File(absPath)).getCanonicalFile();
+                        }
+                    });
+            } catch (PrivilegedActionException pae) {
+                // pae.getCause() should be an instance of IOException,
+                // as only checked exceptions will be wrapped
+                throw (IOException)pae.getCause();
+            }
+            path = f.getPath();
+
+            // store canonicalized path of parent file as required for
+            // implies(Permission); may throw IOException; note that
+            // the path already denotes parent directory if of wildcard type:
+            // for example, the parent of "/a/-" or "/a/*" is "/a"
+            parentPath = ((pathType != URL_PATH_SEPARATOR_CHAR)
+                          ? path : f.getParent());
+        }
+
+        //assert(pathType == URL_PATH_SEPARATOR_CHAR
+        //       || pathType == URL_PATH_WILDCARD_CHAR
+        //       || pathType == URL_PATH_RECURSIVE_CHAR
+        //       || pathType == URL_PATH_INCLUSIVE_CHAR);
+        //assert(path != null);
+        //assert(parentPath == null || parentPath != null);
     }
 
     /**
@@ -345,36 +385,46 @@
         }
         final DatabasePermission that = (DatabasePermission)p;
 
+        // an inclusive permission implies any other
+        if (this.pathType == URL_PATH_INCLUSIVE_CHAR) {
+            return true;
+        }
+        //assert(this.pathType != URL_PATH_INCLUSIVE_CHAR);
+
+        // a non-inclusive permission cannot imply an inclusive one
+        if (that.pathType == URL_PATH_INCLUSIVE_CHAR) {
+            return false;
+        }
+        //assert(that.pathType != URL_PATH_INCLUSIVE_CHAR);
+
         // a recursive permission implies any other if a path prefix
         if (this.pathType == URL_PATH_RECURSIVE_CHAR) {
             return (that.parentPath != null
                     && that.parentPath.startsWith(this.path));
         }
-        //assert (this.pathType != URL_PATH_RECURSIVE_CHAR);
+        //assert(this.pathType != URL_PATH_RECURSIVE_CHAR);
 
         // a non-recursive permission cannot imply a recursive one
         if (that.pathType == URL_PATH_RECURSIVE_CHAR) {
             return false;
         }
-        //assert (that.pathType != URL_PATH_RECURSIVE_CHAR);
+        //assert(that.pathType != URL_PATH_RECURSIVE_CHAR);
 
-        //System.out.println("");
-        
         // a wildcard permission implies another if a parent directory
         if (this.pathType == URL_PATH_WILDCARD_CHAR) {
             return this.path.equals(that.parentPath);
         }
-        //assert (this.pathType != URL_PATH_WILDCARD_CHAR);
+        //assert(this.pathType != URL_PATH_WILDCARD_CHAR);
 
         // a non-wildcard permission cannot imply a wildcard one
         if (that.pathType == URL_PATH_WILDCARD_CHAR) {
             return false;
         }
-        //assert (that.pathType != URL_PATH_WILDCARD_CHAR);
+        //assert(that.pathType != URL_PATH_WILDCARD_CHAR);
 
         // non-recursive, non-wildcard permissions imply when paths are equal
-        //assert (this.pathType == URL_PATH_SEPARATOR_CHAR);
-        //assert (that.pathType == URL_PATH_SEPARATOR_CHAR);
+        //assert(this.pathType == URL_PATH_SEPARATOR_CHAR);
+        //assert(that.pathType == URL_PATH_SEPARATOR_CHAR);
         return this.path.equals(that.path);
     }
 
@@ -401,7 +451,7 @@
         final DatabasePermission that = (DatabasePermission)obj;
 
         // compare canonicalized URLs
-        return (path.equals(that.path) && pathType == that.pathType);
+        return (pathType == that.pathType && path.equals(that.path));
     }
 
     /**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/security/SystemPermission.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/security/SystemPermission.java?rev=632419&r1=632418&r2=632419&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/security/SystemPermission.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/security/SystemPermission.java Fri Feb 29 11:34:33 2008
@@ -28,12 +28,12 @@
 /**
  * This class represents access to system-wide Derby privileges.
  */
-public class SystemPermission extends BasicPermission {
+final public class SystemPermission extends BasicPermission {
 
     /**
-     * The engine shutdown permission.
+     * The server and engine shutdown permission.
      */
-    static public final String SHUTDOWN = "shutdownEngine";
+    static public final String SHUTDOWN = "shutdown";
 
     /**
      * The legal system permission names.
@@ -56,10 +56,6 @@
         // (NullPointerException) or empty (IllegalArgumentException)
         //assert(name != null);
         //assert(!name.equals(""));
-
-        // note that exception messages on the name aren't localized,
-        // as is the general rule with runtime exceptions indicating
-        // internal coding errors
         if (!LEGAL_PERMISSIONS.contains(name)) {
             throw new IllegalArgumentException("Unknown permission " + name);
         }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.java?rev=632419&r1=632418&r2=632419&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.java Fri Feb 29 11:34:33 2008
@@ -33,17 +33,17 @@
 import java.io.IOException;
 
 import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
 import java.security.AccessController;
 import java.security.AccessControlException;
 import java.security.Permission;
 import javax.security.auth.Subject;
 
-import org.apache.derby.authentication.DatabasePrincipal;
+import org.apache.derby.authentication.SystemPrincipal;
 import org.apache.derby.security.SystemPermission;
 import org.apache.derby.security.DatabasePermission;
 
+import org.apache.derby.iapi.util.IdUtil;
+import org.apache.derby.iapi.error.StandardException;
 
 /**
  * This class tests the basic permission classes for system privileges.
@@ -117,7 +117,7 @@
     /**
      * The matrix defining which of the above directory paths imply each other.
      *
-     * For instance, dirPathImplications[1][2] shows the expected value for:
+     * For instance, dirPathImpls[1][2] shows the expected value for:
      * <ul>
      * <li> DP("directory:*").implies(DP(directory:level0"))
      * <li> DP("directory:./*").implies(DP(directory:./level0"))
@@ -125,7 +125,7 @@
      * <li> DP("directory:/dummy/..*").implies(DP(directory:/dummy/..level0"))
      * </ul>
      */
-    static private final boolean[][] dirPathImplications = {
+    static private final boolean[][] dirPathImpls = {
         { true, true, true, true, true, true, true, true }, 
         { false, true, true, true, false, false, false, false },
         { false, false, true, false, false, false, false, false },
@@ -141,11 +141,10 @@
      * with this test's policy file.
      */
     static private Test decorateTest(String method) {
-        final SystemPrivilegesPermissionTest undecoratedTest
-            = new SystemPrivilegesPermissionTest(method);
+        final Test undecorated = new SystemPrivilegesPermissionTest(method);
 
         // install a security manager using this test's policy file
-        return new SecurityManagerSetup(undecoratedTest, POLICY_FILE_NAME);
+        return new SecurityManagerSetup(undecorated, POLICY_FILE_NAME);
     }
     
 
@@ -175,66 +174,42 @@
      * Test case that does a check of the XXX
      */
     public void testSystemPrivileges() throws IOException {
-        //System.out.println("--> testSystemPrivileges()");
-        //System.out.println("    java.security.policy = "
-        //                   + System.getProperty("java.security.policy"));
-        //System.out.println("    System.getSecurityManager() = "
-        //                   + System.getSecurityManager());
+        println("");
+        println("testing System Privileges ...");
         assertSecurityManager();
         execute();
-        //System.out.println("<-- testSystemPrivileges()");
+        println("testing System Privileges: done.");
+        println("");
     }
 
     /**
      * Tests SystemPermissions.
      */
     public void execute() throws IOException {
-        checkDatabasePrincipal();
+        checkSystemPrincipal();
         checkSystemPermission();
         checkDatabasePermission();
     }
     
     /**
-     * Tests DatabasePrincipal.
+     * Tests SystemPrincipal.
      */
-    private void checkDatabasePrincipal() throws IOException {
-        // test DatabasePrincipal with null name argument
+    private void checkSystemPrincipal() throws IOException {
+        // test SystemPrincipal with null name argument
         try {
-            new DatabasePrincipal(null);
+            new SystemPrincipal(null);
             fail("expected NullPointerException");
         } catch (NullPointerException ex) {
             // expected exception
         }
 
-        // test DatabasePrincipal with empty name argument
+        // test SystemPrincipal with empty name argument
         try {
-            new DatabasePrincipal("");
+            new SystemPrincipal("");
             fail("expected IllegalArgumentException");
         } catch (IllegalArgumentException ex) {
             // expected exception
         }
-        
-        // test DatabasePrincipal with illegal name argument
-        try {
-            new DatabasePrincipal("disallowed: unescaped *");
-            fail("expected IllegalArgumentException");
-        } catch (IllegalArgumentException ex) {
-            // expected exception
-        }
-
-        // test DatabasePrincipal with illegal name argument
-        try {
-            new DatabasePrincipal("not yet supported: userName@databaseName");
-            fail("expected IllegalArgumentException");
-        } catch (IllegalArgumentException ex) {
-            // expected exception
-        }
-
-        // test DatabasePrincipal with legal name argument
-        new DatabasePrincipal("supported: userNameWith\\\\character");
-        new DatabasePrincipal("supported: userNameWith\\*character");
-        new DatabasePrincipal("supported: userNameWith\\@character");
-        new DatabasePrincipal("*");
     }
     
     /**
@@ -288,14 +263,14 @@
         assertTrue(sp1.implies(sp0));
 
         // test SystemPermission for authorized user against policy file
-        final DatabasePrincipal authorizedUser
-            = new DatabasePrincipal("authorizedSystemUser");
-        execute(authorizedUser, new ShutdownEngineAction(sp0), true);
+        final SystemPrincipal authorizedUser
+            = new SystemPrincipal("authorizedSystemUser");
+        execute(authorizedUser, new ShutdownAction(sp0), true);
         
         // test SystemPermission for unauthorized user against policy file
-        final DatabasePrincipal unAuthorizedUser
-            = new DatabasePrincipal("unAuthorizedSystemUser");
-        execute(unAuthorizedUser, new ShutdownEngineAction(sp0), false);
+        final SystemPrincipal unAuthorizedUser
+            = new SystemPrincipal("unAuthorizedSystemUser");
+        execute(unAuthorizedUser, new ShutdownAction(sp0), false);
     }
     
     /**
@@ -326,14 +301,18 @@
             // expected exception
         }
 
+        // this test's commented out because it's platform-dependent
+        // (no reliable way to make it pass on Unix)
         // test DatabasePermission with non-canonicalizable URL
-        try {
-            new DatabasePermission("directory:.*/\\:///../",
-                                   DatabasePermission.CREATE);
-            fail("expected IOException");
-        } catch (IOException ex) {
-            // expected exception
-        }
+        //try {
+        //    //new DatabasePermission("directory:.*/\\:///../",
+        //    //                       DatabasePermission.CREATE);
+        //    new DatabasePermission("directory:\n/../../../.*/\\:///../",
+        //                           DatabasePermission.CREATE);
+        //    fail("expected IOException");
+        //} catch (IOException ex) {
+        //    // expected exception
+        //}
 
         // test DatabasePermission with null actions
         try {
@@ -376,93 +355,106 @@
         }
 
         // test DatabasePermission on relative directory paths
-        final DatabasePermission[] relDirPathPermissions
+        final DatabasePermission[] relDirPathPerms
             = new DatabasePermission[relDirPaths.length];
         for (int i = 0; i < relDirPaths.length; i++) {
-            relDirPathPermissions[i]
+            relDirPathPerms[i]
                 = new DatabasePermission(relDirPaths[i],
                                          DatabasePermission.CREATE);
         }
-        checkNameAndActions(relDirPathPermissions,
-                            relDirPaths);
-        checkHashCodeAndEquals(relDirPathPermissions,
-                               relDirPathPermissions);
-        checkImplies(relDirPathPermissions,
-                     relDirPathPermissions);
+        checkNameAndActions(relDirPathPerms, relDirPaths);
+        checkHashCodeAndEquals(relDirPathPerms, relDirPathPerms);
+        checkImplies(relDirPathPerms, relDirPathPerms, dirPathImpls);
 
         // test DatabasePermission on relative directory path aliases
-        final DatabasePermission[] relDirPathAliasPermissions
+        final DatabasePermission[] relDirPathAliasPerms
             = new DatabasePermission[relDirPathAliases.length];
         for (int i = 0; i < relDirPathAliases.length; i++) {
-            relDirPathAliasPermissions[i]
+            relDirPathAliasPerms[i]
                 = new DatabasePermission(relDirPathAliases[i],
                                          DatabasePermission.CREATE);
         }
-        checkNameAndActions(relDirPathAliasPermissions,
-                            relDirPathAliases);
-        checkHashCodeAndEquals(relDirPathPermissions,
-                               relDirPathAliasPermissions);
-        checkImplies(relDirPathPermissions,
-                     relDirPathAliasPermissions);
+        checkNameAndActions(relDirPathAliasPerms, relDirPathAliases);
+        checkHashCodeAndEquals(relDirPathPerms, relDirPathAliasPerms);
+        checkImplies(relDirPathPerms, relDirPathAliasPerms, dirPathImpls);
+        checkImplies(relDirPathAliasPerms, relDirPathPerms, dirPathImpls);
 
         // test DatabasePermission on absolute directory paths
-        final DatabasePermission[] absDirPathPermissions
+        final DatabasePermission[] absDirPathPerms
             = new DatabasePermission[absDirPaths.length];
         for (int i = 0; i < absDirPaths.length; i++) {
-            absDirPathPermissions[i]
+            absDirPathPerms[i]
                 = new DatabasePermission(absDirPaths[i],
                                          DatabasePermission.CREATE);
         }
-        checkNameAndActions(absDirPathPermissions,
-                            absDirPaths);
-        checkHashCodeAndEquals(absDirPathPermissions,
-                               absDirPathPermissions);
-        checkImplies(absDirPathPermissions,
-                     absDirPathPermissions);
+        checkNameAndActions(absDirPathPerms, absDirPaths);
+        checkHashCodeAndEquals(absDirPathPerms, absDirPathPerms);
+        checkImplies(absDirPathPerms, absDirPathPerms, dirPathImpls);
 
         // test DatabasePermission on absolute directory path aliases
-        final DatabasePermission[] absDirPathAliasPermissions
+        final DatabasePermission[] absDirPathAliasPerms
             = new DatabasePermission[absDirPathAliases.length];
         for (int i = 0; i < absDirPathAliases.length; i++) {
-            absDirPathAliasPermissions[i]
+            absDirPathAliasPerms[i]
                 = new DatabasePermission(absDirPathAliases[i],
                                          DatabasePermission.CREATE);
         }
-        checkNameAndActions(absDirPathAliasPermissions,
-                            absDirPathAliases);
-        checkHashCodeAndEquals(absDirPathPermissions,
-                               absDirPathAliasPermissions);
-        checkImplies(absDirPathPermissions,
-                     absDirPathAliasPermissions);
+        checkNameAndActions(absDirPathAliasPerms, absDirPathAliases);
+        checkHashCodeAndEquals(absDirPathPerms, absDirPathAliasPerms);
+        checkImplies(absDirPathPerms, absDirPathAliasPerms, dirPathImpls);
+        checkImplies(absDirPathAliasPerms, absDirPathPerms, dirPathImpls);
         
-
-        // test DatabasePermission for authorized user against policy file
-        final DatabasePrincipal authorizedUser
-            = new DatabasePrincipal("authorizedSystemUser");
-        execute(authorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[2]), true);
-        execute(authorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[3]), true);
-        execute(authorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[6]), false);
-        execute(authorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[7]), true);
-
-        // test DatabasePermission for unauthorized user against policy file
-        final DatabasePrincipal unAuthorizedUser
-            = new DatabasePrincipal("unAuthorizedSystemUser");
-        execute(unAuthorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[2]), false);
-        execute(unAuthorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[3]), false);
-        execute(unAuthorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[6]), false);
-        execute(unAuthorizedUser,
-                new CreateDatabaseAction(relDirPathPermissions[7]), false);
-
-        // test DatabasePermission for authorized user against policy file
-        final DatabasePrincipal anyUser
-            = new DatabasePrincipal("anyUser");
+        // test DatabasePermission for the inclusive path specification
+        final String inclPermissionUrl = "directory:<<ALL FILES>>";
+        final DatabasePermission[] inclPerms
+            = { new DatabasePermission(inclPermissionUrl,
+                                       DatabasePermission.CREATE) };
+        checkNameAndActions(inclPerms,
+                            new String[]{ inclPermissionUrl });
+        final DatabasePermission[] inclPerms1
+            = { new DatabasePermission(inclPermissionUrl,
+                                       DatabasePermission.CREATE) };
+        checkHashCodeAndEquals(inclPerms, inclPerms1);
+        checkImplies(inclPerms, inclPerms1, new boolean[][]{ { true } });
+        final boolean[][] allTrue = new boolean[1][dirPaths.length];
+        for (int j = 0; j < dirPaths.length; j++) {
+            allTrue[0][j] = true;
+        }
+        final boolean[][] allFalse = new boolean[dirPaths.length][1];
+        for (int i = 0; i < dirPaths.length; i++) {
+            allFalse[i][0] = false;
+        }
+        checkImplies(inclPerms, relDirPathPerms, allTrue);
+        checkImplies(relDirPathPerms, inclPerms, allFalse);
+        checkImplies(inclPerms, relDirPathAliasPerms, allTrue);
+        checkImplies(relDirPathAliasPerms, inclPerms, allFalse);
+        checkImplies(inclPerms, absDirPathPerms, allTrue);
+        checkImplies(absDirPathPerms, inclPerms, allFalse);
+        checkImplies(inclPerms, absDirPathAliasPerms, allTrue);
+        checkImplies(absDirPathAliasPerms, inclPerms, allFalse);
+
+        // test DatabasePermission for unauthorized, authorized, and
+        // all-authorized users against policy file
+        final int[] singleLocPaths = { 2, 3, 6, 7 };
+        final SystemPrincipal authorizedUser
+            = new SystemPrincipal("authorizedSystemUser");
+        final SystemPrincipal unAuthorizedUser
+            = new SystemPrincipal("unAuthorizedSystemUser");
+        final SystemPrincipal superUser
+            = new SystemPrincipal("superUser");
+        for (int i = 0; i < singleLocPaths.length; i++) {
+            final int j = singleLocPaths[i];
+            execute(unAuthorizedUser,
+                    new CreateDatabaseAction(relDirPathPerms[j]), false);
+            execute(authorizedUser,
+                    new CreateDatabaseAction(relDirPathPerms[j]), (j != 6));
+            execute(superUser,
+                    new CreateDatabaseAction(relDirPathPerms[j]), true);
+        }
+
+        // test DatabasePermission for any user against policy file
+        final SystemPrincipal anyUser
+            = new SystemPrincipal("anyUser");
         final DatabasePermission dbPerm
             = new DatabasePermission("directory:dir",
                                      DatabasePermission.CREATE);
@@ -471,29 +463,28 @@
     }
 
     /**
-     * Runs a privileges user action for a given principal.
+     * Runs a privileged user action for a given principal.
      */
-    private void execute(DatabasePrincipal principal,
-                         PrivilegedExceptionAction action,
+    private void execute(SystemPrincipal principal,
+                         PrivilegedAction action,
                          boolean isGrantExpected) {
-        //System.out.println();
-        //System.out.println("    testing action " + action);
+        //println();
+        //println("    testing action " + action);
+        
         final RunAsPrivilegedUserAction runAsPrivilegedUserAction
             = new RunAsPrivilegedUserAction(principal, action);
         try {
             AccessController.doPrivileged(runAsPrivilegedUserAction);
-            //System.out.println("    Congrats! access granted " + action);
+            //println("    Congrats! access granted " + action);
             if (!isGrantExpected) {
                 fail("expected AccessControlException");
             }
-        } catch (PrivilegedActionException pae) {
-            //System.out.println("    Error: " + pae.getMessage());
-            throw new RuntimeException(pae);
         } catch (AccessControlException ace) {
+            //println("    Yikes! " + ace.getMessage());
             if (isGrantExpected) {
-                fail("caught AccessControlException");
+                //fail("caught AccessControlException");
+                throw ace;
             }
-            //System.out.println("    Yikes! " + ace.getMessage());
         }
     }
     
@@ -539,36 +530,36 @@
      * Tests DatabasePermission.implies().
      */
     private void checkImplies(DatabasePermission[] dbp0,
-                              DatabasePermission[] dbp1)
+                              DatabasePermission[] dbp1,
+                              boolean[][] impls)
         throws IOException {
-        //assert(dbp0.length == dbp1.length)
         for (int i = 0; i < dbp0.length; i++) {
             final DatabasePermission p0 = dbp0[i];
-            for (int j = 0; j < dbp0.length; j++) {
+            for (int j = 0; j < dbp1.length; j++) {
                 final DatabasePermission p1 = dbp1[j];
                 assertEquals("test: " + p0 + ".implies" + p1,
-                             dirPathImplications[i][j], p0.implies(p1));
-                assertEquals("test: " + p1 + ".implies" + p0,
-                             dirPathImplications[j][i], p1.implies(p0));
+                             impls[i][j], p0.implies(p1));
+                //assertEquals("test: " + p1 + ".implies" + p0,
+                //             impls[j][i], p1.implies(p0));
             }
         }
     }
     
     /**
-     * Represents a Shutdown Engine action.
+     * Represents a Shutdown server and engine action.
      */
-    public class ShutdownEngineAction
-        implements PrivilegedExceptionAction {
+    public class ShutdownAction
+        implements PrivilegedAction {
         protected final Permission permission;
 
-        public ShutdownEngineAction(Permission permission) {
+        public ShutdownAction(Permission permission) {
             this.permission = permission;
         }
     
-        public Object run() throws Exception {
-            //System.out.println("    checking access " + permission + "...");
+        public Object run() {
+            //println("    checking access " + permission + "...");
             AccessController.checkPermission(permission);
-            //System.out.println("    granted access " + this);
+            //println("    granted access " + this);
             return null;
         }
 
@@ -581,17 +572,17 @@
      * Represents a Create Database action.
      */
     public class CreateDatabaseAction
-        implements PrivilegedExceptionAction {
+        implements PrivilegedAction {
         protected final Permission permission;
 
-        public CreateDatabaseAction(Permission permission) throws IOException {
+        public CreateDatabaseAction(Permission permission) {
             this.permission = permission;
         }
-    
-        public Object run() throws Exception {
-            //System.out.println("    checking access " + permission + "...");
+
+        public Object run() {
+            //println("    checking access " + permission + "...");
             AccessController.checkPermission(permission);
-            //System.out.println("    granted access " + this);
+            //println("    granted access " + this);
             return null;
         }
 
@@ -601,35 +592,71 @@
     }
 
     /**
+     * Returns the Authorization Identifier for a principal name.
+     *
+     * @param name the name of the principal
+     * @return the authorization identifier for this principal
+     */
+    static private String getAuthorizationId(String name) {
+        // RuntimeException messages not localized
+        if (name == null) {
+            throw new NullPointerException("name can't be null");
+        }
+        if (name.length() == 0) {
+            throw new IllegalArgumentException("name can't be empty");
+        }
+        try {
+            return IdUtil.getUserAuthorizationId(name);
+        } catch (StandardException se) {
+            throw new IllegalArgumentException(se.getMessage());
+		}
+    }
+
+    /**
      * Represents a Privileged User action.
      */
-    public class RunAsPrivilegedUserAction
-        implements PrivilegedExceptionAction {
-        final private DatabasePrincipal principal;
-        final private PrivilegedExceptionAction action;
+    static public class RunAsPrivilegedUserAction
+        implements PrivilegedAction {
+        final private SystemPrincipal principal;
+        final private PrivilegedAction action;
 
-        public RunAsPrivilegedUserAction(DatabasePrincipal principal,
-                                         PrivilegedExceptionAction action) {
+        public RunAsPrivilegedUserAction(SystemPrincipal principal,
+                                         PrivilegedAction action) {
             this.principal = principal;
             this.action = action;
         }
         
-        public Object run() throws PrivilegedActionException {
-            final Set principalSet = new HashSet();
-            final Set noPublicCredentials = new HashSet();
-            final Set noPrivateCredentials = new HashSet();
+        public Object run() {
+            final boolean readOnly = true;
+            final Set principals = new HashSet();
+            final Set publicCredentials = new HashSet();
+            final Set privateCredentials = new HashSet();
             // add the given principal
-            principalSet.add(principal);
-            // add a principal that matches an "all user names" grant
-            principalSet.add(DatabasePrincipal.ANY_DATABASE_PRINCIPAL);
-            final Subject subject = new Subject(true, principalSet,
-                                                noPublicCredentials,
-                                                noPrivateCredentials);
-        
-            // Subject.doAs(subject, action) not strong enough
-            //System.out.println("    run doAsPrivileged() as " + principal
-            //                   + "...");
+            principals.add(principal);
+            // also add a principal with the "normalized" name for testing
+            // authorization ids
+            final String normalized = getAuthorizationId(principal.getName());
+            principals.add(new SystemPrincipal(normalized));
+            final Subject subject = new Subject(readOnly,
+                                                principals,
+                                                publicCredentials,
+                                                privateCredentials);
+
+            // check subject's permission with a fresh AccessControlContext,
+            // not the thread's current one (Subject.doAs(subject, action))
+            // println("    run doAsPrivileged() as " + principal + "...");
+            // The alternative approach to use Subject.doAs(subject, action)
+            // instead of Subject.doAsPrivileged(subject, action, null) has
+            // issues: there are subtile differences between these methods
+            // regarding the checking of the caller's protection domain.  To
+            // make doAs() work, the shutdown/createDatabase permissions must
+            // be granted to the codebase (class RunAsPrivilegedUserAction).
+            // This, however, defeats the purpose since everyone now's granted
+            // permission.  In contrast, doAsPrivileged() with a null ACC
+            // seems to effectively ignore the caller's protection domain, so
+            // the check now only depends on the principal's permissions.
             Subject.doAsPrivileged(subject, action, null);
+            //Subject.doAs(subject, action);
             return null;
         }
     }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.policy
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.policy?rev=632419&r1=632418&r2=632419&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.policy (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/SystemPrivilegesPermissionTest.policy Fri Feb 29 11:34:33 2008
@@ -21,19 +21,18 @@
 //     with the NetworkServerControl start command
 
 
-// PROVISIONAL: Universally granted permissions for testing System Privileges
-// When consolidated, these permissions should be moved/copied into the
+// Permissions required by System Privileges
+// We are liberal here and grant these permissions to all codebases
+// (it's not a goal to make the test harness or tests secure).
+// If that is of a concern, however, copy these permissions into sections
 //   ${derbyTesting.codejar}
 //   ${derbyTesting.codeclasses}
-//   ${derbyTesting.junit}
-// sections
 grant {
   // System Privileges need to run "doAsPrivileged".
   permission javax.security.auth.AuthPermission "doAsPrivileged";
 
   // System Privileges need to be allowed to resolve relative directory names,
   // which requires a property-read permission.
-  //permission java.util.PropertyPermission "*", "read,write";
   permission java.util.PropertyPermission "user.dir", "read";
 
   // System Privileges need to be allowed to canonicalize directory names,
@@ -45,48 +44,58 @@
   permission java.io.FilePermission "<<ALL FILES>>", "read";
 };
 
-// specific test authorizations for System Privileges
-grant principal org.apache.derby.authentication.DatabasePrincipal "authorizedSystemUser" {
-  permission org.apache.derby.security.SystemPermission "shutdownEngine";
+// Specific test authorizations for System Privileges
+grant principal org.apache.derby.authentication.SystemPrincipal "AUTHORIZEDSYSTEMUSER" {
+  permission org.apache.derby.security.SystemPermission "shutdown";
   permission org.apache.derby.security.DatabasePermission "directory:*", "create";
   permission org.apache.derby.security.DatabasePermission "directory:level0/level1/-", "create";
   permission org.apache.derby.security.DatabasePermission "directory:/*", "create";
   permission org.apache.derby.security.DatabasePermission "directory:/level0/level1/-", "create";
 };
 
-// specific test authorizations for System Privileges
-grant principal org.apache.derby.authentication.DatabasePrincipal "*" {
+// Specific test authorizations for System Privileges
+grant principal org.apache.derby.authentication.SystemPrincipal "SUPERUSER" {
+  permission org.apache.derby.security.SystemPermission "shutdown";
+  permission org.apache.derby.security.DatabasePermission "directory:<<ALL FILES>>", "create";
+};
+
+// Specific test authorizations for System Privileges
+grant principal org.apache.derby.authentication.SystemPrincipal * {
   permission org.apache.derby.security.DatabasePermission "directory:dir", "create";
 };
 
 //
-// Permissions for the tests (derbyTesting.jar)
-// We are liberal here, it's not a goal to make the test harness
-// or tests secure.
+// Permissions for running the test on the jars files
 //
-grant codeBase "${derbyTesting.codejar}" {
-  // Support for debugging test.
-  permission java.util.PropertyPermission "java.security.policy", "read";
-
-  // When running with useprocess=false need to install and uninstall
-  // the security manager and allow setIO to change the system err and out
-  // streams. Currently the nist suite runs with useprocess=false.
+grant codeBase "${derbyTesting.codejar}*" {
+  // Allow tests to install and uninstall the security manager and
+  // to refresh the policy
+  permission java.util.PropertyPermission "java.security.policy", "read,write";
   permission java.lang.RuntimePermission "setSecurityManager";
+  permission java.security.SecurityPermission "getPolicy";
+
+  // Allow setIO to change the system err and out streams
   permission java.lang.RuntimePermission "setIO"; 
+
+  // derbyTesting.junit.TestConfiguration... calls System.getProperties()
+  permission java.util.PropertyPermission "*", "read,write";
 };
 
 //
-// super-set of the jar permissions for running out of the classes directory
+// Permissions for running the test on the class files
 //
 grant codeBase "${derbyTesting.codeclasses}" {
-  // Support for debugging test.
-  permission java.util.PropertyPermission "java.security.policy", "read";
-
-  // When running with useprocess=false need to install and uninstall
-  // the security manager and allow setIO to change the system err and out
-  // streams. Currently the nist suite runs with useprocess=false.
+  // Allow tests to install and uninstall the security manager and
+  // to refresh the policy
+  permission java.util.PropertyPermission "java.security.policy", "read,write";
   permission java.lang.RuntimePermission "setSecurityManager";
+  permission java.security.SecurityPermission "getPolicy";
+
+  // Allow setIO to change the system err and out streams
   permission java.lang.RuntimePermission "setIO"; 
+
+  // derbyTesting.junit.TestConfiguration... calls System.getProperties()
+  permission java.util.PropertyPermission "*", "read,write";
 };
 
 // JUnit jar file tries to read junit.properties in the user's



Mime
View raw message