001: /*
002:
003: Derby - Class org.apache.derby.iapi.sql.dictionary.StatementColumnPermission
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.iapi.sql.dictionary;
023:
024: import org.apache.derby.iapi.error.StandardException;
025: import org.apache.derby.catalog.UUID;
026: import org.apache.derby.iapi.sql.conn.Authorizer;
027: import org.apache.derby.iapi.reference.SQLState;
028: import org.apache.derby.iapi.services.io.FormatableBitSet;
029: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
030:
031: /**
032: * This class describes a column permission used (required) by a statement.
033: */
034:
035: public class StatementColumnPermission extends StatementTablePermission {
036: private FormatableBitSet columns;
037:
038: /**
039: * Constructor for StatementColumnPermission. Creates an instance of column permission requested
040: * for the given access.
041: *
042: * @param tableUUID UUID of the table
043: * @param privType Access privilege requested
044: * @param columns List of columns
045: *
046: */
047: public StatementColumnPermission(UUID tableUUID, int privType,
048: FormatableBitSet columns) {
049: super (tableUUID, privType);
050: this .columns = columns;
051: }
052:
053: /**
054: * Return list of columns that need access
055: *
056: * @return FormatableBitSet of columns
057: */
058: public FormatableBitSet getColumns() {
059: return columns;
060: }
061:
062: /**
063: * Method to check if another instance of column access descriptor matches this.
064: * Used to ensure only one access descriptor for a table/columns of given privilege is created.
065: *
066: * @param obj Another instance of StatementPermission
067: *
068: * @return true if match
069: */
070: public boolean equals(Object obj) {
071: if (obj instanceof StatementColumnPermission) {
072: StatementColumnPermission other = (StatementColumnPermission) obj;
073: if (!columns.equals(other.columns))
074: return false;
075: return super .equals(obj);
076: }
077: return false;
078: }
079:
080: /**
081: * @see StatementPermission#check
082: */
083: public void check(LanguageConnectionContext lcc,
084: String authorizationId, boolean forGrant)
085: throws StandardException {
086: DataDictionary dd = lcc.getDataDictionary();
087:
088: if (hasPermissionOnTable(dd, authorizationId, forGrant))
089: return;
090: FormatableBitSet permittedColumns = null;
091: if (!forGrant) {
092: permittedColumns = addPermittedColumns(dd,
093: false /* non-grantable permissions */,
094: Authorizer.PUBLIC_AUTHORIZATION_ID,
095: permittedColumns);
096: permittedColumns = addPermittedColumns(dd,
097: false /* non-grantable permissions */,
098: authorizationId, permittedColumns);
099: }
100: permittedColumns = addPermittedColumns(dd,
101: true /* grantable permissions */,
102: Authorizer.PUBLIC_AUTHORIZATION_ID, permittedColumns);
103: permittedColumns = addPermittedColumns(dd,
104: true /* grantable permissions */, authorizationId,
105: permittedColumns);
106:
107: for (int i = columns.anySetBit(); i >= 0; i = columns
108: .anySetBit(i)) {
109: if (permittedColumns != null && permittedColumns.get(i))
110: continue;
111:
112: // No permission on this column.
113: TableDescriptor td = getTableDescriptor(dd);
114: ColumnDescriptor cd = td.getColumnDescriptor(i + 1);
115: if (cd == null)
116: throw StandardException.newException(
117: SQLState.AUTH_INTERNAL_BAD_UUID, "column");
118: throw StandardException
119: .newException(
120: forGrant ? SQLState.AUTH_NO_COLUMN_PERMISSION_FOR_GRANT
121: : SQLState.AUTH_NO_COLUMN_PERMISSION,
122: authorizationId, getPrivName(), cd
123: .getColumnName(), td
124: .getSchemaName(), td.getName());
125: }
126: } // end of check
127:
128: /**
129: * Add one user's set of permitted columns to a list of permitted columns.
130: */
131: private FormatableBitSet addPermittedColumns(DataDictionary dd,
132: boolean forGrant, String authorizationId,
133: FormatableBitSet permittedColumns) throws StandardException {
134: if (permittedColumns != null
135: && permittedColumns.getNumBitsSet() == permittedColumns
136: .size())
137: return permittedColumns;
138: ColPermsDescriptor perms = dd.getColumnPermissions(tableUUID,
139: privType, false, authorizationId);
140: if (perms != null) {
141: if (permittedColumns == null)
142: return perms.getColumns();
143: permittedColumns.or(perms.getColumns());
144: }
145: return permittedColumns;
146: } // end of addPermittedColumns
147:
148: /**
149: * @see StatementPermission#getPermissionDescriptor
150: */
151: public PermissionsDescriptor getPermissionDescriptor(String authid,
152: DataDictionary dd) throws StandardException {
153: //If table permission found for authorizationid, then simply return that
154: if (oneAuthHasPermissionOnTable(dd, authid, false))
155: return dd.getTablePermissions(tableUUID, authid);
156: //If table permission found for PUBLIC, then simply return that
157: if (oneAuthHasPermissionOnTable(dd,
158: Authorizer.PUBLIC_AUTHORIZATION_ID, false))
159: return dd.getTablePermissions(tableUUID,
160: Authorizer.PUBLIC_AUTHORIZATION_ID);
161:
162: //If table level permission not found, then we have to find permissions
163: //at column level. Look for column level permission for the passed
164: //authorizer. If found any of the required column level permissions,
165: //return the permission descriptor for it.
166: ColPermsDescriptor colsPermsDesc = dd.getColumnPermissions(
167: tableUUID, privType, false, authid);
168: if (colsPermsDesc != null) {
169: if (colsPermsDesc.getColumns() != null) {
170: FormatableBitSet permittedColumns = colsPermsDesc
171: .getColumns();
172: for (int i = columns.anySetBit(); i >= 0; i = columns
173: .anySetBit(i)) {
174: if (permittedColumns.get(i))
175: return colsPermsDesc;
176: }
177: }
178: }
179: return null;
180: }
181:
182: /**
183: * This method gets called in execution phase after it is established that
184: * all the required privileges exist for the given sql. This method gets
185: * called by create view/trigger/constraint to record their dependency on
186: * various privileges.
187: * Special code is required to track column level privileges.
188: * It is possible that some column level privileges are available to the
189: * passed authorizer id but the rest required column level privileges
190: * are available at PUBLIC level. In this method, we check if all the
191: * required column level privileges are found for the passed authorizer.
192: * If yes, then simply return null, indicating that no dependency is
193: * required at PUBLIC level, because all the required privileges were found
194: * at the user level. But if some column level privileges are not
195: * available at user level, then they have to exist at the PUBLIC
196: * level when this method gets called.
197: */
198: public PermissionsDescriptor getPUBLIClevelColPermsDescriptor(
199: String authid, DataDictionary dd) throws StandardException {
200: ColPermsDescriptor colsPermsDesc = dd.getColumnPermissions(
201: tableUUID, privType, false, authid);
202: FormatableBitSet permittedColumns = colsPermsDesc.getColumns();
203: boolean allColumnsCoveredByUserLevelPrivilege = true;
204: for (int i = columns.anySetBit(); i >= 0
205: && allColumnsCoveredByUserLevelPrivilege; i = columns
206: .anySetBit(i)) {
207: if (permittedColumns.get(i))
208: continue;
209: else
210: allColumnsCoveredByUserLevelPrivilege = false;
211: }
212: if (allColumnsCoveredByUserLevelPrivilege)
213: return null;
214: else
215: return (dd.getColumnPermissions(tableUUID, privType, false,
216: Authorizer.PUBLIC_AUTHORIZATION_ID));
217: }
218: }
|