001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.TablePrivilegeInfo
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.impl.sql.execute;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025: import org.apache.derby.iapi.services.io.FormatableBitSet;
026: import org.apache.derby.iapi.sql.Activation;
027: import org.apache.derby.iapi.error.StandardException;
028: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
029: import org.apache.derby.iapi.store.access.TransactionController;
030: import org.apache.derby.iapi.sql.depend.DependencyManager;
031: import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
032: import org.apache.derby.iapi.sql.dictionary.PermissionsDescriptor;
033: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
034: import org.apache.derby.iapi.sql.dictionary.TablePermsDescriptor;
035: import org.apache.derby.iapi.sql.dictionary.ColPermsDescriptor;
036: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
037: import org.apache.derby.iapi.sql.dictionary.ViewDescriptor;
038: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
039: import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
040: import org.apache.derby.iapi.sql.dictionary.TupleDescriptor;
041: import org.apache.derby.iapi.reference.SQLState;
042:
043: import java.util.List;
044: import java.util.Iterator;
045:
046: public class TablePrivilegeInfo extends PrivilegeInfo {
047: // Action types
048: public static final int SELECT_ACTION = 0;
049: public static final int DELETE_ACTION = 1;
050: public static final int INSERT_ACTION = 2;
051: public static final int UPDATE_ACTION = 3;
052: public static final int REFERENCES_ACTION = 4;
053: public static final int TRIGGER_ACTION = 5;
054: public static final int ACTION_COUNT = 6;
055:
056: private static final String YES_WITH_GRANT_OPTION = "Y";
057: private static final String YES_WITHOUT_GRANT_OPTION = "y";
058: private static final String NO = "N";
059:
060: private static final String[][] actionString = { { "s", "S" },
061: { "d", "D" }, { "i", "I" }, { "u", "U" }, { "r", "R" },
062: { "t", "T" } };
063:
064: private TableDescriptor td;
065: private boolean[] actionAllowed;
066: private FormatableBitSet[] columnBitSets;
067: private List descriptorList;
068:
069: /**
070: * @param actionAllowed actionAllowed[action] is true if action is in the privilege set.
071: */
072: public TablePrivilegeInfo(TableDescriptor td,
073: boolean[] actionAllowed, FormatableBitSet[] columnBitSets,
074: List descriptorList) {
075: this .actionAllowed = actionAllowed;
076: this .columnBitSets = columnBitSets;
077: this .td = td;
078: this .descriptorList = descriptorList;
079: }
080:
081: /**
082: * Determines whether a user is the owner of an object
083: * (table, function, or procedure). Note that the database
084: * creator can access database objects without needing to be
085: * their owner.
086: *
087: * @param user authorizationId of current user
088: * @param td table descriptor being checked against
089: * @param sd SchemaDescriptor
090: * @param dd DataDictionary
091: * @param lcc LanguageConnectionContext
092: * @param grant grant if true; revoke if false
093: *
094: * @exception StandardException if user does not own the object
095: */
096: protected void checkOwnership(String user, TableDescriptor td,
097: SchemaDescriptor sd, DataDictionary dd,
098: LanguageConnectionContext lcc, boolean grant)
099: throws StandardException {
100: super .checkOwnership(user, td, sd, dd);
101:
102: // additional check specific to this subclass
103: if (grant) {
104: checkPrivileges(user, td, sd, dd, lcc);
105: }
106: }
107:
108: /**
109: * Determines if the privilege is grantable by this grantor
110: * for the given view.
111: *
112: * Note that the database owner can access database objects
113: * without needing to be their owner. This method should only
114: * be called if it is a GRANT.
115: *
116: * @param user authorizationId of current user
117: * @param td TableDescriptor to be checked against
118: * @param sd SchemaDescriptor
119: * @param dd DataDictionary
120: * @param lcc LanguageConnectionContext
121: *
122: * @exception StandardException if user does not have permission to grant
123: */
124: private void checkPrivileges(String user, TableDescriptor td,
125: SchemaDescriptor sd, DataDictionary dd,
126: LanguageConnectionContext lcc) throws StandardException {
127: if (user.equals(dd.getAuthorizationDatabaseOwner()))
128: return;
129:
130: // check view specific
131: if (td.getTableType() == TableDescriptor.VIEW_TYPE) {
132: if (descriptorList != null) {
133: TransactionController tc = lcc.getTransactionExecute();
134: int siz = descriptorList.size();
135: for (int i = 0; i < siz; i++) {
136: TupleDescriptor p;
137: SchemaDescriptor s = null;
138:
139: p = (TupleDescriptor) descriptorList.get(i);
140: if (p instanceof TableDescriptor) {
141: TableDescriptor t = (TableDescriptor) p;
142: s = t.getSchemaDescriptor();
143: } else if (p instanceof ViewDescriptor) {
144: ViewDescriptor v = (ViewDescriptor) p;
145: s = dd.getSchemaDescriptor(v.getCompSchemaId(),
146: tc);
147: } else if (p instanceof AliasDescriptor) {
148: AliasDescriptor a = (AliasDescriptor) p;
149: s = dd.getSchemaDescriptor(a.getSchemaUUID(),
150: tc);
151: }
152:
153: if (s != null
154: && !user.equals(s.getAuthorizationId())) {
155: throw StandardException.newException(
156: SQLState.AUTH_NO_OBJECT_PERMISSION,
157: user, "grant", sd.getSchemaName(), td
158: .getName());
159: }
160:
161: // FUTURE: if object is not own by grantor then check if
162: // the grantor have grant option.
163: }
164: }
165: }
166: }
167:
168: /**
169: * This is the guts of the Execution-time logic for GRANT/REVOKE of a table privilege
170: *
171: * @param activation
172: * @param grant true if grant, false if revoke
173: * @param grantees a list of authorization ids (strings)
174: *
175: * @exception StandardException Thrown on failure
176: */
177: public void executeGrantRevoke(Activation activation,
178: boolean grant, List grantees) throws StandardException {
179: LanguageConnectionContext lcc = activation
180: .getLanguageConnectionContext();
181: DataDictionary dd = lcc.getDataDictionary();
182: String currentUser = lcc.getAuthorizationId();
183: TransactionController tc = lcc.getTransactionExecute();
184: SchemaDescriptor sd = td.getSchemaDescriptor();
185:
186: // Check that the current user has permission to grant the privileges.
187: checkOwnership(currentUser, td, sd, dd, lcc, grant);
188:
189: DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
190:
191: TablePermsDescriptor tablePermsDesc = ddg
192: .newTablePermsDescriptor(td, getPermString(
193: SELECT_ACTION, false), getPermString(
194: DELETE_ACTION, false), getPermString(
195: INSERT_ACTION, false), getPermString(
196: UPDATE_ACTION, false), getPermString(
197: REFERENCES_ACTION, false), getPermString(
198: TRIGGER_ACTION, false), currentUser);
199:
200: ColPermsDescriptor[] colPermsDescs = new ColPermsDescriptor[columnBitSets.length];
201: for (int i = 0; i < columnBitSets.length; i++) {
202: if (columnBitSets[i] != null
203: ||
204: // If it is a revoke and no column list is specified then revoke all column permissions.
205: // A null column bitSet in a ColPermsDescriptor indicates that all the column permissions
206: // should be removed.
207: (!grant) && hasColumnPermissions(i)
208: && actionAllowed[i]) {
209: colPermsDescs[i] = ddg.newColPermsDescriptor(td,
210: getActionString(i, false), columnBitSets[i],
211: currentUser);
212: }
213: }
214:
215: dd.startWriting(lcc);
216: // Add or remove the privileges to/from the SYS.SYSTABLEPERMS and SYS.SYSCOLPERMS tables
217: for (Iterator itr = grantees.iterator(); itr.hasNext();) {
218: // Keep track to see if any privileges are revoked by a revoke
219: // statement. If a privilege is not revoked, we need to raise a
220: // warning. For table privileges, we do not check if privilege for
221: // a specific action has been revoked or not. Also, we do not check
222: // privileges for specific columns. If at least one privilege has
223: // been revoked, we do not raise a warning. This has to be refined
224: // further to check for specific actions/columns and raise warning
225: // if any privilege has not been revoked.
226: boolean privileges_revoked = false;
227:
228: String grantee = (String) itr.next();
229: if (tablePermsDesc != null) {
230: if (dd.addRemovePermissionsDescriptor(grant,
231: tablePermsDesc, grantee, tc)) {
232: privileges_revoked = true;
233: dd.getDependencyManager().invalidateFor(
234: tablePermsDesc,
235: DependencyManager.REVOKE_PRIVILEGE, lcc);
236: }
237: }
238: for (int i = 0; i < columnBitSets.length; i++) {
239: if (colPermsDescs[i] != null) {
240: if (dd.addRemovePermissionsDescriptor(grant,
241: colPermsDescs[i], grantee, tc)) {
242: privileges_revoked = true;
243: dd
244: .getDependencyManager()
245: .invalidateFor(
246: colPermsDescs[i],
247: DependencyManager.REVOKE_PRIVILEGE,
248: lcc);
249: }
250: }
251: }
252:
253: addWarningIfPrivilegeNotRevoked(activation, grant,
254: privileges_revoked, grantee);
255: }
256: } // end of executeConstantAction
257:
258: private String getPermString(int action, boolean forGrantOption) {
259: if (actionAllowed[action] && columnBitSets[action] == null)
260: return forGrantOption ? YES_WITH_GRANT_OPTION
261: : YES_WITHOUT_GRANT_OPTION;
262: else
263: return NO;
264: } // end of getPermString
265:
266: private String getActionString(int action, boolean forGrantOption) {
267: return actionString[action][forGrantOption ? 1 : 0];
268: }
269:
270: private boolean hasColumnPermissions(int action) {
271: return action == SELECT_ACTION || action == UPDATE_ACTION
272: || action == REFERENCES_ACTION;
273: }
274: }
|