All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hsqldb.rights.GranteeManager Maven / Gradle / Ivy

There is a newer version: 2.7.2
Show newest version
/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb.rights;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.hsqldb.Database;
import org.hsqldb.HsqlNameManager;
import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.Routine;
import org.hsqldb.RoutineSchema;
import org.hsqldb.SchemaObject;
import org.hsqldb.Session;
import org.hsqldb.SqlInvariants;
import org.hsqldb.Tokens;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.Collection;
import org.hsqldb.lib.HashMappedList;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.lib.IntValueHashMap;
import org.hsqldb.lib.Iterator;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.lib.Set;
import org.hsqldb.lib.StringConverter;
import org.hsqldb.lib.java.JavaSystem;

/**
 * Contains a set of Grantee objects, and supports operations for creating,
 * finding, modifying and deleting Grantee objects for a Database; plus
 * Administrative privileges.
 *
 *
 * @author Campbell Burnet (campbell-burnet@users dot sourceforge.net)
 * @author Fred Toussi (fredt@users dot sourceforge.net)
 * @author Blaine Simpson (blaine dot simpson at admc dot com)
 *
 * @version 2.5.0
 * @since 1.8.0
 * @see Grantee
 */
public class GranteeManager {

    /**
     * The grantee object for the _SYSTEM role.
     */
    static User systemAuthorisation;

    static {
        HsqlName name = HsqlNameManager.newSystemObjectName(
            SqlInvariants.SYSTEM_AUTHORIZATION_NAME, SchemaObject.GRANTEE);

        systemAuthorisation          = new User(name, null);
        systemAuthorisation.isSystem = true;

        systemAuthorisation.setAdminDirect();
        systemAuthorisation.setInitialSchema(
            SqlInvariants.SYSTEM_SCHEMA_HSQLNAME);

        SqlInvariants.INFORMATION_SCHEMA_HSQLNAME.owner = systemAuthorisation;
        SqlInvariants.SYSTEM_SCHEMA_HSQLNAME.owner      = systemAuthorisation;
        SqlInvariants.LOBS_SCHEMA_HSQLNAME.owner        = systemAuthorisation;
        SqlInvariants.SQLJ_SCHEMA_HSQLNAME.owner        = systemAuthorisation;
    }

    /**
     * Map of grantee-String-to-Grantee-objects.

* Keys include all USER and ROLE names */ private HashMappedList map = new HashMappedList(); /** * Map of role-Strings-to-Grantee-object.

* Keys include all ROLES names */ private HashMappedList roleMap = new HashMappedList(); /** * Used only to pass the SchemaManager to Grantees for checking * schema authorizations. */ Database database; /** * MessageDigest instance for database */ private MessageDigest digester; /** * MessageDigest algorithm */ private String digestAlgo; /** * The PUBLIC role. */ Grantee publicRole; /** * The DBA role. */ Grantee dbaRole; /** * The role for schema creation rights. */ Grantee schemaRole; /** * The role for changing authorization rights. */ Grantee changeAuthRole; /** * Construct the GranteeManager for a Database. Construct special Grantee * objects for _SYSTEM, PUBLIC and DBA, and add them to the Grantee map. * * @param database Only needed to link to the RoleManager later on. */ public GranteeManager(Database database) { this.database = database; // map.add(systemAuthorisation.getNameString(), systemAuthorisation); // roleMap.add(systemAuthorisation.getNameString(), systemAuthorisation); addRole( this.database.nameManager.newHsqlName( SqlInvariants.PUBLIC_ROLE_NAME, false, SchemaObject.GRANTEE)); publicRole = getRole(SqlInvariants.PUBLIC_ROLE_NAME); publicRole.isPublic = true; addRole( this.database.nameManager.newHsqlName( SqlInvariants.DBA_ADMIN_ROLE_NAME, false, SchemaObject.GRANTEE)); dbaRole = getRole(SqlInvariants.DBA_ADMIN_ROLE_NAME); dbaRole.setAdminDirect(); addRole( this.database.nameManager.newHsqlName( SqlInvariants.SCHEMA_CREATE_ROLE_NAME, false, SchemaObject.GRANTEE)); schemaRole = getRole(SqlInvariants.SCHEMA_CREATE_ROLE_NAME); addRole( this.database.nameManager.newHsqlName( SqlInvariants.CHANGE_AUTH_ROLE_NAME, false, SchemaObject.GRANTEE)); changeAuthRole = getRole(SqlInvariants.CHANGE_AUTH_ROLE_NAME); } static final IntValueHashMap rightsStringLookup = new IntValueHashMap(7); static { rightsStringLookup.put(Tokens.T_ALL, GrantConstants.ALL); rightsStringLookup.put(Tokens.T_SELECT, GrantConstants.SELECT); rightsStringLookup.put(Tokens.T_UPDATE, GrantConstants.UPDATE); rightsStringLookup.put(Tokens.T_DELETE, GrantConstants.DELETE); rightsStringLookup.put(Tokens.T_INSERT, GrantConstants.INSERT); rightsStringLookup.put(Tokens.T_EXECUTE, GrantConstants.EXECUTE); rightsStringLookup.put(Tokens.T_USAGE, GrantConstants.USAGE); rightsStringLookup.put(Tokens.T_REFERENCES, GrantConstants.REFERENCES); rightsStringLookup.put(Tokens.T_TRIGGER, GrantConstants.TRIGGER); } public Grantee getDBARole() { return dbaRole; } public static Grantee getSystemRole() { return systemAuthorisation; } /** * Grants the rights represented by the rights argument on * the database object identified by the dbobject argument * to the Grantee object identified by name argument.

* * Note: For the dbobject argument, Java Class objects are identified * using a String object whose value is the fully qualified name * of the Class, while Table and other objects are * identified by an HsqlName object. A Table * object identifier must be precisely the one obtained by calling * table.getName(); if a different HsqlName * object with an identical name attribute is specified, then * rights checks and tests will fail, since the HsqlName * class implements its {@link HsqlName#hashCode hashCode} and * {@link HsqlName#equals equals} methods based on pure object * identity, rather than on attribute values.

*/ public void grant(Session session, OrderedHashSet granteeList, SchemaObject dbObject, Right right, Grantee grantor, boolean withGrantOption) { if (dbObject instanceof RoutineSchema) { SchemaObject[] routines = ((RoutineSchema) dbObject).getSpecificRoutines(); grant(session, granteeList, routines, right, grantor, withGrantOption); return; } HsqlName name = dbObject.getName(); if (dbObject instanceof Routine) { name = ((Routine) dbObject).getSpecificName(); } if (!grantor.isAccessible(dbObject)) { throw Error.error(ErrorCode.X_0L000, grantor.getName().getNameString()); } if (!grantor.isGrantable(dbObject, right)) { session.addWarning(Error.error(ErrorCode.W_01007, grantor.getName().getNameString())); return; } if (grantor.isAdmin()) { grantor = dbObject.getOwner(); } checkGranteeList(granteeList); for (int i = 0; i < granteeList.size(); i++) { Grantee grantee = get((String) granteeList.get(i)); grantee.grant(name, right, grantor, withGrantOption); if (grantee.isRole) { updateAllRights(grantee); } } } public void grant(Session session, OrderedHashSet granteeList, SchemaObject[] routines, Right right, Grantee grantor, boolean withGrantOption) { boolean granted = false; for (int i = 0; i < routines.length; i++) { if (!grantor.isGrantable(routines[i], right)) { continue; } grant(session, granteeList, routines[i], right, grantor, withGrantOption); granted = true; } if (!granted) { throw Error.error(ErrorCode.X_0L000, grantor.getName().getNameString()); } } public void checkGranteeList(OrderedHashSet granteeList) { for (int i = 0; i < granteeList.size(); i++) { String name = (String) granteeList.get(i); Grantee grantee = get(name); if (grantee == null) { throw Error.error(ErrorCode.X_28501, name); } if (isImmutable(name)) { throw Error.error(ErrorCode.X_28502, name); } if (grantee instanceof User && ((User) grantee).isExternalOnly) { throw Error.error(ErrorCode.X_28000, name); } } } /** * Grant a role to this Grantee. */ public void grant(String granteeName, String roleName, Grantee grantor) { Grantee grantee = get(granteeName); if (grantee == null) { throw Error.error(ErrorCode.X_28501, granteeName); } if (isImmutable(granteeName)) { throw Error.error(ErrorCode.X_28502, granteeName); } Grantee role = getRole(roleName); if (role == null) { throw Error.error(ErrorCode.X_0P000, roleName); } if (role == grantee) { throw Error.error(ErrorCode.X_0P501, granteeName); } // campbell-burnet@users 20050515 // SQL 2003 Foundation, 4.34.3 // No cycles of role grants are allowed. if (role.hasRole(grantee)) { // campbell-burnet@users /** @todo: Correct reporting of actual grant path */ throw Error.error(ErrorCode.X_0P501, roleName); } if (!grantor.isGrantable(role)) { throw Error.error(ErrorCode.X_0L000, grantor.getName().getNameString()); } grantee.grant(role); grantee.updateAllRights(); if (grantee.isRole) { updateAllRights(grantee); } } public void checkRoleList(String granteeName, OrderedHashSet roleList, Grantee grantor, boolean grant) { Grantee grantee = get(granteeName); for (int i = 0; i < roleList.size(); i++) { String roleName = (String) roleList.get(i); Grantee role = getRole(roleName); if (role == null) { throw Error.error(ErrorCode.X_0P000, roleName); } if (roleName.equals(SqlInvariants.SYSTEM_AUTHORIZATION_NAME) || roleName.equals(SqlInvariants.PUBLIC_ROLE_NAME)) { throw Error.error(ErrorCode.X_28502, roleName); } if (grant) { if (grantee.getDirectRoles().contains(role)) { /** @todo shouldn't throw */ throw Error.error(ErrorCode.X_0P000, granteeName); } } else { if (!grantee.getDirectRoles().contains(role)) { /** @todo shouldn't throw */ throw Error.error(ErrorCode.X_0P000, roleName); } } if (!grantor.isAdmin()) { throw Error.error(ErrorCode.X_0L000, grantor.getName().getNameString()); } } } public void grantSystemToPublic(SchemaObject object, Right right) { publicRole.grant(object.getName(), right, systemAuthorisation, true); } /** * Revoke a role from a Grantee */ public void revoke(String granteeName, String roleName, Grantee grantor) { if (!grantor.isAdmin()) { throw Error.error(ErrorCode.X_42507); } Grantee grantee = get(granteeName); if (grantee == null) { throw Error.error(ErrorCode.X_28000, granteeName); } Grantee role = (Grantee) roleMap.get(roleName); grantee.revoke(role); grantee.updateAllRights(); if (grantee.isRole) { updateAllRights(grantee); } } /** * Revokes the rights represented by the rights argument on * the database object identified by the dbobject argument * from the User object identified by the name * argument.

* @see #grant */ public void revoke(OrderedHashSet granteeList, SchemaObject dbObject, Right rights, Grantee grantor, boolean grantOption, boolean cascade) { if (dbObject instanceof RoutineSchema) { SchemaObject[] routines = ((RoutineSchema) dbObject).getSpecificRoutines(); revoke(granteeList, routines, rights, grantor, grantOption, cascade); return; } HsqlName name = dbObject.getName(); if (dbObject instanceof Routine) { name = ((Routine) dbObject).getSpecificName(); } if (!grantor.isFullyAccessibleByRole(name)) { throw Error.error(ErrorCode.X_42501, dbObject.getName().name); } if (grantor.isAdmin()) { grantor = dbObject.getOwner(); } for (int i = 0; i < granteeList.size(); i++) { String granteeName = (String) granteeList.get(i); Grantee g = get(granteeName); if (g == null) { throw Error.error(ErrorCode.X_28501, granteeName); } if (isImmutable(granteeName)) { throw Error.error(ErrorCode.X_28502, granteeName); } } for (int i = 0; i < granteeList.size(); i++) { String granteeName = (String) granteeList.get(i); Grantee g = get(granteeName); g.revoke(dbObject, rights, grantor, grantOption); g.updateAllRights(); if (g.isRole) { updateAllRights(g); } } } public void revoke(OrderedHashSet granteeList, SchemaObject[] routines, Right rights, Grantee grantor, boolean grantOption, boolean cascade) { for (int i = 0; i < routines.length; i++) { revoke(granteeList, routines[i], rights, grantor, grantOption, cascade); } } /** * Updates all the talbe level rights on a table after the addition of a * column.

*/ public void updateAddColumn(HsqlName table, HsqlName column) { // roles Iterator it = getRoles().iterator(); while (it.hasNext()) { Grantee grantee = (Grantee) it.next(); grantee.updateRightsForNewColumn(table, column); } // users it = getGrantees().iterator(); for (; it.hasNext(); ) { Grantee grantee = (Grantee) it.next(); grantee.updateRightsForNewColumn(table, column); } updateAddColumn(table); } private void updateAddColumn(HsqlName table) { // roles Iterator it = getRoles().iterator(); while (it.hasNext()) { Grantee grantee = (Grantee) it.next(); grantee.updateRightsForNewColumn(table); } // users it = getGrantees().iterator(); for (; it.hasNext(); ) { Grantee grantee = (Grantee) it.next(); grantee.updateRightsForNewColumn(table); } } /** * Removes a role without any privileges from all grantees */ void removeEmptyRole(Grantee role) { for (int i = 0; i < map.size(); i++) { Grantee grantee = (Grantee) map.get(i); grantee.roles.remove(role); } } /** * Removes all rights mappings for the database object identified by * the dbobject argument from all Grantee objects in the set. */ public void removeDbObject(HsqlName name) { for (int i = 0; i < map.size(); i++) { Grantee g = (Grantee) map.get(i); g.revokeDbObject(name); } } public void removeDbObjects(OrderedHashSet nameSet) { Iterator it = nameSet.iterator(); while (it.hasNext()) { HsqlName name = (HsqlName) it.next(); for (int i = 0; i < map.size(); i++) { Grantee g = (Grantee) map.get(i); g.revokeDbObject(name); } } } /** * First updates all ROLE Grantee objects. Then updates all USER Grantee * Objects. */ void updateAllRights(Grantee role) { for (int i = 0; i < map.size(); i++) { Grantee grantee = (Grantee) map.get(i); if (grantee.isRole) { grantee.updateNestedRoles(role); } } for (int i = 0; i < map.size(); i++) { Grantee grantee = (Grantee) map.get(i); if (!grantee.isRole) { grantee.updateAllRights(); } } } /** */ public boolean removeGrantee(String name) { /* * Explicitly can't remove PUBLIC_USER_NAME and system grantees. */ if (isReserved(name)) { return false; } Grantee g = (Grantee) map.remove(name); if (g == null) { return false; } g.clearPrivileges(); updateAllRights(g); if (g.isRole) { roleMap.remove(name); removeEmptyRole(g); } return true; } /** * Creates a new Role object under management of this object.

* * A set of constraints regarding user creation is imposed:

* *

    *
  1. Can't create a role with name same as any right. * *
  2. If this object's collection already contains an element whose * name attribute equals the name argument, then * a GRANTEE_ALREADY_EXISTS or ROLE_ALREADY_EXISTS Trace * is thrown. * (This will catch attempts to create Reserved grantee names). *
*/ public Grantee addRole(HsqlName name) { if (map.containsKey(name.name)) { throw Error.error(ErrorCode.X_28503, name.name); } if (SqlInvariants.SYSTEM_AUTHORIZATION_NAME.equals(name.name)) { throw Error.error(ErrorCode.X_28502, name.name); } if (SqlInvariants.isLobsSchemaName(name.name) || SqlInvariants.isSystemSchemaName(name.name)) { throw Error.error(ErrorCode.X_28502, name.name); } Grantee g = new Grantee(name, this); g.isRole = true; map.put(name.name, g); roleMap.add(name.name, g); return g; } public User addUser(HsqlName name) { if (map.containsKey(name.name)) { throw Error.error(ErrorCode.X_28503, name.name); } if (SqlInvariants.SYSTEM_AUTHORIZATION_NAME.equals(name.name)) { throw Error.error(ErrorCode.X_28502, name.name); } if (SqlInvariants.isLobsSchemaName(name.name) || SqlInvariants.isSystemSchemaName(name.name)) { throw Error.error(ErrorCode.X_28502, name.name); } User g = new User(name, this); map.put(name.name, g); return g; } /** * Only used for a recently added user with no dependencies */ public void removeNewUser(HsqlName name) { map.remove(name.name); } /** * Returns true if named Grantee object exists. * This will return true for reserved Grantees * SYSTEM_AUTHORIZATION_NAME, ADMIN_ROLE_NAME, PUBLIC_USER_NAME. */ boolean isGrantee(String name) { return map.containsKey(name); } public static int getCheckSingleRight(String right) { int r = getRight(right); if (r != 0) { return r; } throw Error.error(ErrorCode.X_42581, right); } /** * Translate a string representation or right(s) into its numeric form. */ public static int getRight(String right) { return rightsStringLookup.get(right, 0); } public Grantee get(String name) { return (Grantee) map.get(name); } public Collection getGrantees() { return map.values(); } public static boolean validRightString(String rightString) { return getRight(rightString) != 0; } public static boolean isImmutable(String name) { return name.equals(SqlInvariants.SYSTEM_AUTHORIZATION_NAME) || name.equals(SqlInvariants.DBA_ADMIN_ROLE_NAME) || name.equals(SqlInvariants.SCHEMA_CREATE_ROLE_NAME) || name.equals(SqlInvariants.CHANGE_AUTH_ROLE_NAME); } public static boolean isReserved(String name) { return name.equals(SqlInvariants.SYSTEM_AUTHORIZATION_NAME) || name.equals(SqlInvariants.DBA_ADMIN_ROLE_NAME) || name.equals(SqlInvariants.SCHEMA_CREATE_ROLE_NAME) || name.equals(SqlInvariants.CHANGE_AUTH_ROLE_NAME) || name.equals(SqlInvariants.PUBLIC_ROLE_NAME); } /** * Attempts to drop a Role with the specified name * from this object's set.

* * A successful drop action consists of:

* *

    * *
  • removing the Grantee object with the specified name * from the set. *

* */ public void dropRole(String name) { if (!isRole(name)) { throw Error.error(ErrorCode.X_0P000, name); } if (GranteeManager.isReserved(name)) { throw Error.error(ErrorCode.X_42507); } removeGrantee(name); } public Set getRoleNames() { return roleMap.keySet(); } public Collection getRoles() { return roleMap.values(); } /** * Returns Grantee for the named Role */ public Grantee getRole(String name) { Grantee g = (Grantee) roleMap.get(name); if (g == null) { throw Error.error(ErrorCode.X_0P000, name); } return g; } public boolean isRole(String name) { return roleMap.containsKey(name); } public String[] getSQL() { HsqlArrayList list = new HsqlArrayList(); // roles Iterator it = getRoles().iterator(); while (it.hasNext()) { Grantee grantee = (Grantee) it.next(); // built-in role names are not persisted if (!GranteeManager.isReserved( grantee.getName().getNameString())) { list.add(grantee.getSQL()); } } // users it = getGrantees().iterator(); for (; it.hasNext(); ) { Grantee grantee = (Grantee) it.next(); if (grantee instanceof User) { if (((User) grantee).isExternalOnly) { continue; } list.add(grantee.getSQL()); if (((User) grantee).isLocalOnly) { list.add(((User) grantee).getLocalUserSQL()); } } } String[] array = new String[list.size()]; list.toArray(array); return array; } public String[] getRightsSQL() { HsqlArrayList list = new HsqlArrayList(); Iterator grantees = getGrantees().iterator(); while (grantees.hasNext()) { Grantee grantee = (Grantee) grantees.next(); String name = grantee.getName().getNameString(); // _SYSTEM user, DBA Role grants not persisted if (GranteeManager.isImmutable(name)) { continue; } if (grantee instanceof User && ((User) grantee).isExternalOnly) { continue; } HsqlArrayList subList = grantee.getRightsSQL(); list.addAll(subList); } String[] array = new String[list.size()]; list.toArray(array); return array; } public void setDigestAlgo(String algo) { digestAlgo = algo; } public String getDigestAlgo() { return digestAlgo; } synchronized MessageDigest getDigester() { if (digester == null) { try { digester = MessageDigest.getInstance(digestAlgo); } catch (NoSuchAlgorithmException e) { throw Error.error(ErrorCode.GENERAL_ERROR, e); } } return digester; } String digest(String string) throws RuntimeException { byte[] data; data = string.getBytes(JavaSystem.CS_ISO_8859_1); data = getDigester().digest(data); return StringConverter.byteArrayToHexString(data); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy