| //***************************************************************************** |
| // @@@ START COPYRIGHT @@@ |
| // |
| // 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. |
| // |
| // @@@ END COPYRIGHT @@@ |
| //***************************************************************************** |
| |
| #include "PrivMgrPrivileges.h" |
| |
| #include "PrivMgrMD.h" |
| #include "PrivMgrMDTable.h" |
| #include "PrivMgrDesc.h" |
| #include "PrivMgrDefs.h" |
| #include "PrivMgrRoles.h" |
| #include "PrivMgrComponentPrivileges.h" |
| #include "PrivMgrObjects.h" |
| #include "PrivMgrCommands.h" |
| |
| #include <numeric> |
| #include <cstdio> |
| #include <algorithm> |
| #include <iterator> |
| #include <vector> |
| #include "sqlcli.h" |
| #include "ComSmallDefs.h" |
| #include "ExExeUtilCli.h" |
| #include "ComDiags.h" |
| #include "ComQueue.h" |
| #include "CmpCommon.h" |
| #include "CmpContext.h" |
| #include "ComSecurityKey.h" |
| #include "NAUserId.h" |
| #include "ComUser.h" |
| #include "CmpSeabaseDDLutil.h" |
| #include "logmxevent_traf.h" |
| class ColPrivGrant; |
| class ColumnPrivsMDTable; |
| |
| // **************************************************************************** |
| // File: PrivMgrPrivileges.h |
| // |
| // This file contains: |
| // class ObjectPrivsMDRow |
| // class ObjectPrivsMDTable |
| // non inline methods for class PrivMgrPrivileges |
| // **************************************************************************** |
| |
| |
| |
| // ***************************************************************************** |
| // * Class: ObjectPrivsMDRow |
| // * Description: This class represents a row from the OBJECT_PRIVILEGES table |
| // * |
| // * An object row can be uniquely identified by its object UID, granteeID |
| // * and grantorID. |
| // ***************************************************************************** |
| class ObjectPrivsMDRow : public PrivMgrMDRow |
| { |
| public: |
| |
| // ------------------------------------------------------------------- |
| // Constructors and destructors: |
| // ------------------------------------------------------------------- |
| ObjectPrivsMDRow() |
| : PrivMgrMDRow(PRIVMGR_OBJECT_PRIVILEGES, OBJECT_PRIVILEGES_ENUM), |
| objectUID_(0), |
| grantorID_(0), |
| granteeID_(0) |
| { }; |
| |
| ObjectPrivsMDRow(const ObjectPrivsMDRow &other) |
| : PrivMgrMDRow(other) |
| { |
| objectUID_ = other.objectUID_; |
| objectName_ = other.objectName_; |
| objectType_ = other.objectType_; |
| granteeID_ = other.granteeID_; |
| granteeName_ = other.granteeName_; |
| granteeType_ = other.granteeType_; |
| grantorID_ = other.grantorID_; |
| grantorName_ = other.grantorName_; |
| grantorType_ = other.grantorType_; |
| privsBitmap_ = other.privsBitmap_; |
| grantableBitmap_ = other.grantableBitmap_; |
| current_ = other.current_; |
| visited_ = other.visited_; |
| }; |
| virtual ~ObjectPrivsMDRow() {}; |
| |
| // Methods used to determine changes after processing revoked privileges |
| PrivMgrCoreDesc& accessCurrent() { return current_; } |
| PrivMgrCoreDesc& accessVisited() { return visited_; } |
| void clearVisited() { visited_.setAllPrivAndWgo(false); }; |
| bool isChanged() |
| { return (current_ == PrivMgrCoreDesc(privsBitmap_, grantableBitmap_)); } |
| |
| void setToOriginal() { current_ = PrivMgrCoreDesc(privsBitmap_, grantableBitmap_); } |
| ; |
| |
| |
| // Return True iff some current flag is set, where visited is not. |
| NABoolean anyNotVisited() const {return current_.anyNotSet( visited_ );} |
| |
| // Clear current where current was set and visited was not. |
| // Return True iff some current flag gets cleared. |
| NABoolean cascadeLosses(); |
| |
| // Describe a row for tracing |
| void describeRow (std::string &rowDetails); |
| |
| // ------------------------------------------------------------------- |
| // Data Members: |
| // ------------------------------------------------------------------- |
| |
| int64_t objectUID_; |
| std::string objectName_; |
| ComObjectType objectType_; |
| int32_t granteeID_; |
| std::string granteeName_; |
| std::string granteeType_; |
| int32_t grantorID_; |
| std::string grantorName_; |
| std::string grantorType_; |
| PrivObjectBitmap privsBitmap_; |
| PrivObjectBitmap grantableBitmap_; |
| |
| PrivMgrCoreDesc visited_; |
| PrivMgrCoreDesc current_; |
| }; |
| |
| |
| // ***************************************************************************** |
| // * Class: ObjectPrivsMDTable |
| // * Description: This class represents the OBJECT_PRIVILEGES table |
| // * |
| // * An object privileges row can be uniquely identified by: |
| // * objectUID |
| // * granteeID |
| // * grantorID |
| // ***************************************************************************** |
| class ObjectPrivsMDTable : public PrivMgrMDTable |
| { |
| public: |
| ObjectPrivsMDTable( |
| const std::string & tableName, |
| ComDiagsArea * pDiags = NULL) |
| : PrivMgrMDTable(tableName,OBJECT_PRIVILEGES_ENUM, pDiags) |
| {}; |
| |
| virtual ~ObjectPrivsMDTable() |
| {}; |
| |
| virtual PrivStatus insert(const PrivMgrMDRow &row); |
| virtual PrivStatus selectWhereUnique( |
| const std::string & whereClause, |
| PrivMgrMDRow & row); |
| PrivStatus selectWhere( |
| const std::string & whereClause, |
| const std::string & orderByClause, |
| std::vector<PrivMgrMDRow *> &rowList); |
| PrivStatus deleteRow(const ObjectPrivsMDRow & row); |
| virtual PrivStatus deleteWhere(const std::string & whereClause); |
| PrivStatus updateRow(const ObjectPrivsMDRow & row); |
| PrivStatus updateWhere( |
| const std::string & setClause, |
| const std::string & whereClause); |
| PrivStatus insertSelect( |
| const std::string & objectsLocation, |
| const std::string & authsLocation); |
| PrivStatus insertSelectOnAuthsToPublic( |
| const std::string &objectsLocation, |
| const std::string &authsLocation); |
| |
| private: |
| ObjectPrivsMDTable(); |
| void setRow(OutputInfo *pCliRow, ObjectPrivsMDRow &rowOut); |
| |
| }; |
| |
| // ***************************************************************************** |
| // * Class: ColumnPrivsMDRow |
| // * Description: This class represents a row from the COLUMN_PRIVILEGES table |
| // * |
| // * An column row can be uniquely identified by its object UID, granteeID, |
| // * grantorID, and column ordinal. |
| // ***************************************************************************** |
| class ColumnPrivsMDRow : public PrivMgrMDRow |
| { |
| public: |
| |
| // ------------------------------------------------------------------- |
| // Constructors and destructors: |
| // ------------------------------------------------------------------- |
| ColumnPrivsMDRow() |
| : PrivMgrMDRow(PRIVMGR_COLUMN_PRIVILEGES, COLUMN_PRIVILEGES_ENUM), |
| objectUID_(0), |
| grantorID_(0), |
| granteeID_(0), |
| columnOrdinal_(0) |
| { }; |
| |
| ColumnPrivsMDRow(const ColumnPrivsMDRow &other) |
| : PrivMgrMDRow(other) |
| { |
| objectUID_ = other.objectUID_; |
| objectName_ = other.objectName_; |
| granteeID_ = other.granteeID_; |
| granteeName_ = other.granteeName_; |
| grantorID_ = other.grantorID_; |
| grantorName_ = other.grantorName_; |
| columnOrdinal_ = other.columnOrdinal_; |
| privsBitmap_ = other.privsBitmap_; |
| grantableBitmap_ = other.grantableBitmap_; |
| }; |
| virtual ~ColumnPrivsMDRow() {}; |
| |
| // Describe a row for tracing |
| void describeRow (std::string &rowDetails); |
| |
| // sets the privilege and grantable bitmaps to 0 |
| void clearVisited() |
| { |
| visited_.setColumnOrdinal(columnOrdinal_); |
| visited_.setAllPrivAndWgo(false); |
| } |
| |
| // sets the current entry to match the original privileges |
| // before they are adjusted by a revoke command |
| void setCurrentToOriginal() |
| { |
| current_.setColumnOrdinal(columnOrdinal_); |
| current_.setPrivBitmap(privsBitmap_); |
| current_.setWgoBitmap(grantableBitmap_); |
| } |
| |
| // compares the current privileges with the visited grant tree to |
| // see if there are any broken branches |
| NABoolean anyNotVisited() |
| {return current_.getPrivBitmap() != visited_.getPrivBitmap() || |
| current_.getWgoBitmap() != visited_.getWgoBitmap();} |
| |
| |
| // ------------------------------------------------------------------- |
| // Data Members: |
| // ------------------------------------------------------------------- |
| |
| int64_t objectUID_; |
| std::string objectName_; |
| int32_t granteeID_; |
| std::string granteeName_; |
| int32_t grantorID_; |
| std::string grantorName_; |
| int32_t columnOrdinal_; |
| PrivColumnBitmap privsBitmap_; |
| PrivColumnBitmap grantableBitmap_; |
| |
| PrivMgrCoreDesc visited_; |
| PrivMgrCoreDesc current_; |
| |
| }; |
| |
| |
| // ***************************************************************************** |
| // * Class: ColumnPrivsMDTable |
| // * Description: This class represents the COLUMN_PRIVILEGES table |
| // * |
| // * An column privileges row can be uniquely identified by: |
| // * objectUID |
| // * granteeID |
| // * grantorID |
| // * columnOrdinal |
| // ***************************************************************************** |
| class ColumnPrivsMDTable : public PrivMgrMDTable |
| { |
| public: |
| ColumnPrivsMDTable( |
| const std::string & tableName, |
| ComDiagsArea * pDiags = NULL) |
| : PrivMgrMDTable(tableName,COLUMN_PRIVILEGES_ENUM, pDiags) |
| {}; |
| |
| virtual ~ColumnPrivsMDTable() |
| {}; |
| |
| virtual PrivStatus insert(const PrivMgrMDRow &row); |
| virtual PrivStatus selectWhereUnique( |
| const std::string & whereClause, |
| PrivMgrMDRow & row); |
| PrivStatus selectWhere( |
| const std::string & whereClause, |
| const std::string & orderByClause, |
| std::vector<PrivMgrMDRow *> &rowList); |
| PrivStatus updateColumnRow( |
| const ColumnPrivsMDRow & row, |
| const std::string whereBase); |
| |
| private: |
| ColumnPrivsMDTable(); |
| void setRow( |
| OutputInfo *pCliRow, |
| ColumnPrivsMDRow &rowOut); |
| }; |
| |
| // ***************************************************************************** |
| // * PrivMgrPrivileges.cpp static function declarations * |
| // ***************************************************************************** |
| |
| static PrivStatus buildPrivText( |
| const std::vector<PrivMgrMDRow *> rowList, |
| const PrivMgrObjectInfo & objectInfo, |
| PrivLevel privLevel, |
| ComDiagsArea * pDiags_, |
| std::string & privilegeText); |
| |
| void static buildGrantText( |
| const std::string & privText, |
| const std::string & objectGranteeText, |
| const int32_t grantorID, |
| const std::string grantorName, |
| bool isWGO, |
| const int32_t ownerID, |
| std::string & grantText); |
| |
| void static closeColumnList(std::string & columnList); |
| |
| static void deleteRowList(std::vector<PrivMgrMDRow *> & rowList); |
| |
| static PrivMgrCoreDesc * findColumnEntry( |
| NAList<PrivMgrCoreDesc> & colPrivsToGrant, |
| const int32_t columnsOrdinal); |
| |
| static void getColRowsForGranteeGrantor( |
| const std::vector <PrivMgrMDRow *> & columnRowList, |
| const int32_t granteeID, |
| const int32_t grantorID, |
| NAList<PrivMgrCoreDesc> &colPrivGrants); |
| |
| static bool hasAllDMLPrivs( |
| ComObjectType objectType, |
| PrivObjectBitmap privBitmap); |
| |
| static bool isDelimited( const std::string &identifier); |
| |
| |
| // ***************************************************************************** |
| // PrivMgrPrivileges methods |
| // ***************************************************************************** |
| |
| // ----------------------------------------------------------------------- |
| // Default Constructor |
| // ----------------------------------------------------------------------- |
| PrivMgrPrivileges::PrivMgrPrivileges () |
| : PrivMgr(), |
| objectUID_(0), |
| grantorID_(0) |
| { |
| objectTableName_ = metadataLocation_ + "." + PRIVMGR_OBJECT_PRIVILEGES; |
| columnTableName_ = metadataLocation_ + "." + PRIVMGR_COLUMN_PRIVILEGES; |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Construct a PrivMgrPrivileges object for a new object privilege. |
| // ----------------------------------------------------------------------- |
| PrivMgrPrivileges::PrivMgrPrivileges ( |
| const int64_t objectUID, |
| const std::string &objectName, |
| const int32_t grantorID, |
| const std::string &metadataLocation, |
| ComDiagsArea * pDiags) |
| : PrivMgr(metadataLocation,pDiags), |
| objectUID_(objectUID), |
| objectName_(objectName), |
| grantorID_(grantorID) |
| { |
| objectTableName_ = metadataLocation + "." + PRIVMGR_OBJECT_PRIVILEGES; |
| columnTableName_ = metadataLocation + "." + PRIVMGR_COLUMN_PRIVILEGES; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Construct PrivMgrPrivileges object for describe statements |
| // ---------------------------------------------------------------------------- |
| PrivMgrPrivileges::PrivMgrPrivileges ( |
| const PrivMgrObjectInfo &objectInfo, |
| const std::string &metadataLocation, |
| ComDiagsArea *pDiags) |
| : PrivMgr(metadataLocation, pDiags), |
| objectUID_(((PrivMgrObjectInfo)objectInfo).getObjectUID()), |
| objectName_(((PrivMgrObjectInfo)objectInfo).getObjectName()), |
| grantorID_(0) |
| { |
| objectTableName_ = metadataLocation + "." + PRIVMGR_OBJECT_PRIVILEGES; |
| columnTableName_ = metadataLocation + "." + PRIVMGR_COLUMN_PRIVILEGES; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Construct a PrivMgrPrivileges object for an objectUID |
| // ---------------------------------------------------------------------------- |
| PrivMgrPrivileges::PrivMgrPrivileges ( |
| const int64_t objectUID, |
| const std::string &metadataLocation, |
| ComDiagsArea *pDiags) |
| : PrivMgr(metadataLocation, pDiags), |
| objectUID_(objectUID), |
| grantorID_(0) |
| { |
| objectTableName_ = metadataLocation + "." + PRIVMGR_OBJECT_PRIVILEGES; |
| columnTableName_ = metadataLocation + "." + PRIVMGR_COLUMN_PRIVILEGES; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Construct a basic PrivMgrPrivileges object |
| // ---------------------------------------------------------------------------- |
| PrivMgrPrivileges::PrivMgrPrivileges ( |
| const std::string &metadataLocation, |
| ComDiagsArea *pDiags) |
| : PrivMgr(metadataLocation, pDiags), |
| objectUID_(0), |
| grantorID_(0) |
| { |
| objectTableName_ = metadataLocation + "." + PRIVMGR_OBJECT_PRIVILEGES; |
| columnTableName_ = metadataLocation + "." + PRIVMGR_COLUMN_PRIVILEGES; |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Copy constructor |
| // ----------------------------------------------------------------------- |
| PrivMgrPrivileges::PrivMgrPrivileges(const PrivMgrPrivileges &other) |
| : PrivMgr(other) |
| { |
| objectUID_ = other.objectUID_; |
| objectName_ = other.objectName_; |
| grantorID_ = other.grantorID_; |
| objectTableName_ = other.objectTableName_; |
| columnTableName_ = other.columnTableName_; |
| objectRowList_ = other.objectRowList_; |
| columnRowList_ = other.columnRowList_; |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Destructor. |
| // ----------------------------------------------------------------------- |
| PrivMgrPrivileges::~PrivMgrPrivileges() |
| { |
| deleteRowList(objectRowList_); |
| deleteRowList(columnRowList_); |
| } |
| |
| // ***************************************************************************** |
| // * Method: buildSecurityKeys |
| // * |
| // * Builds security keys for the current object and specified user. |
| // * |
| // * Parameters: |
| // * |
| // * <granteeID> is the unique identifier for the grantee |
| // * <privs> is the list of privileges the user has on the object |
| // * <secKeySet> is the set of security keys to be passed back. Caller is |
| // * responsible for freeing keys. |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Security keys were built |
| // * *: Security keys were not built, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::buildSecurityKeys( |
| const int32_t granteeID, |
| const PrivMgrCoreDesc &privs, |
| std::vector <ComSecurityKey *> & secKeySet) |
| { |
| if (privs.isNull()) |
| return STATUS_GOOD; |
| |
| // Only need to generate keys for DML privileges |
| for ( size_t i = FIRST_DML_PRIV; i <= LAST_DML_PRIV; i++ ) |
| { |
| if ( privs.getPriv(PrivType(i))) |
| { |
| ComSecurityKey *key = NULL; |
| if (ComUser::isPublicUserID(granteeID)) |
| key = new ComSecurityKey(granteeID, |
| ComSecurityKey::OBJECT_IS_SPECIAL_ROLE); |
| else |
| key = new ComSecurityKey(granteeID, |
| objectUID_, |
| PrivType(i), |
| ComSecurityKey::OBJECT_IS_OBJECT); |
| if (key->isValid()) |
| secKeySet.push_back(key); |
| else |
| { |
| PRIVMGR_INTERNAL_ERROR("ComSecurityKey is null"); |
| return STATUS_ERROR; |
| } |
| } |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| // ***************************************************************************** |
| // * Method: getPrivsOnObject |
| // * |
| // * Creates a set of priv descriptors for all user grantees on an object |
| // * Used by Trafodion compiler to store as part of the table descriptor. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of object |
| // * <privDescs> is the list of privileges the on the object |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: privilege descriptors were built |
| // * *: unexpected error occurred, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getPrivsOnObject ( |
| const ComObjectType objectType, |
| std::vector<PrivMgrDesc> & privDescs ) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| if (objectUID_ == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for getPrivRowsForObject()"); |
| return STATUS_ERROR; |
| } |
| |
| // generate the list of privileges granted to the object and store in class |
| if (generateObjectRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // generate the list of privileges granted to the column and store in class |
| if (generateColumnRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // Gets all the user grantees (userIDs) for the object and column lists |
| // Gets all the role grantees (roleIDs) for the object and column lists |
| // The public auth ID is included in the userIDs list |
| std::vector<int32_t> userIDs; |
| std::vector<int32_t> roleIDs; |
| if (getDistinctIDs(objectRowList_, columnRowList_, userIDs, roleIDs) == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // Gather privilege descriptors for each user |
| for (size_t i = 0; i < userIDs.size(); i++) |
| { |
| int32_t userID = userIDs[i]; |
| |
| PrivMgrDesc privsOfTheUser(userID); |
| bool hasManagePrivileges = false; |
| std::vector <int32_t> emptyRoleIDs; |
| |
| // getUserPrivs returns object and column privileges summarized across all |
| // grantors. Just get direct grants to the user (role list is empty) |
| if (getUserPrivs(objectType, userID, emptyRoleIDs, privsOfTheUser, |
| hasManagePrivileges, NULL ) != STATUS_GOOD) |
| return STATUS_ERROR; |
| |
| if (!privsOfTheUser.isNull()) |
| privDescs.push_back(privsOfTheUser); |
| } |
| |
| // Attach roles to priv lists |
| for (size_t i = 0; i < roleIDs.size(); i++) |
| { |
| int32_t grantee = roleIDs[i]; |
| |
| PrivMgrDesc privsOfTheUser(grantee); |
| bool hasManagePrivileges = false; |
| std::vector <int32_t> emptyRoleIDs; |
| |
| // getUserPrivs returns object and column privileges summarized across |
| // all grantors. |
| if (getUserPrivs(objectType, grantee, emptyRoleIDs, privsOfTheUser, |
| hasManagePrivileges, NULL ) != STATUS_GOOD) |
| return STATUS_ERROR; |
| |
| if (!privsOfTheUser.isNull()) |
| privDescs.push_back(privsOfTheUser); |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ***************************************************************************** |
| // Function: getColRowsForGranteeOrdinal |
| // |
| // Returns the list of column privileges granted for the object that have |
| // been granted to the granteeID for a particular column |
| // |
| // Parameters: |
| // |
| // <granteeID> is the authID granted the privileges. |
| // <columnOrdinal> is the column number to gather privileges |
| // <columnRowList> is the list of column privs for the object |
| // <roleIDs> is the list of roles assigned the granteeID |
| // <rowList> the privileges granted to <granteeID> on <columnOrdinal>. |
| // |
| // ***************************************************************************** |
| void PrivMgrPrivileges::getColRowsForGranteeOrdinal( |
| const int32_t granteeID, |
| const int32_t columnOrdinal, |
| const std::vector <PrivMgrMDRow *> &columnRowList, |
| const std::vector<int32_t> &roleIDs, |
| std::vector<PrivMgrMDRow *> &rowList) |
| { |
| for (size_t i = 0; i < columnRowList.size(); ++i) |
| { |
| ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*columnRowList[i]); |
| PrivMgrCoreDesc colPrivGrant; |
| |
| if (row.columnOrdinal_ == columnOrdinal) |
| { |
| if (row.granteeID_ == granteeID || |
| std::find(roleIDs.begin(), roleIDs.end(), row.granteeID_) != roleIDs.end()) |
| { |
| ColumnPrivsMDRow *pRow = new ColumnPrivsMDRow(); |
| *pRow = row; |
| rowList.push_back(pRow); |
| } |
| } |
| } |
| } |
| |
| // ***************************************************************************** |
| // * Method: getDistinctIDs |
| // * |
| // * Finds all the userIDs that have been granted at least one privilege on |
| // * object. This list includes the public authorization ID |
| // * |
| // * Finds all the roleIDs that have been granted at least one privilege on |
| // * object |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getDistinctIDs( |
| const std::vector <PrivMgrMDRow *> &objectRowList, |
| const std::vector <PrivMgrMDRow *> &columnRowList, |
| std::vector<int32_t> &userIDs, |
| std::vector<int32_t> &roleIDs) |
| { |
| int32_t authID; |
| |
| // DB__ROOTROLE is a special role. If the current user has been granted |
| // this role, then they have privileges. Add it to the roleIDs list for |
| // processing. |
| roleIDs.push_back(ROOT_ROLE_ID); |
| |
| // The direct object grants are stored in memory (objectRowList) so no I/O |
| for (size_t i = 0; i < objectRowList.size(); i++) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*objectRowList[i]); |
| authID = row.granteeID_; |
| |
| // insert authID into correct list, if not already present |
| if (ComUser::isPublicUserID(authID) || CmpSeabaseDDLauth::isUserID(authID)) |
| { |
| if (std::find(userIDs.begin(), userIDs.end(), authID) == userIDs.end()) |
| userIDs.insert( std::upper_bound( userIDs.begin(), userIDs.end(), authID ), authID); |
| } |
| else |
| { |
| if (std::find(roleIDs.begin(), roleIDs.end(), authID) == roleIDs.end()) |
| roleIDs.insert( std::upper_bound( roleIDs.begin(), roleIDs.end(), authID ), authID); |
| } |
| } |
| |
| // The direct column grants are stored in memory (columnRowList) so no I/O |
| // Save grants to roles for further processing |
| for (size_t i = 0; i < columnRowList.size(); i++) |
| { |
| ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*columnRowList[i]); |
| authID = row.granteeID_; |
| |
| // insert authID into correct list, if not already present |
| if (ComUser::isPublicUserID(authID) || |
| CmpSeabaseDDLauth::isUserID(authID)) |
| { |
| if (std::find(userIDs.begin(), userIDs.end(), authID) == userIDs.end()) |
| userIDs.insert( std::upper_bound( userIDs.begin(), userIDs.end(), authID ), authID); |
| } |
| else |
| { |
| if (std::find(roleIDs.begin(), roleIDs.end(), authID) == roleIDs.end()) |
| roleIDs.insert( std::upper_bound( roleIDs.begin(), roleIDs.end(), authID ), authID); |
| } |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: getPrivRowsForObject |
| // * |
| // * returns rows describing all the privileges that have been |
| // * granted on the object |
| // * |
| // * Parameters: |
| // * |
| // * <objectPrivsRows> Zero or more rows of grants for the object. |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD : Rows were returned |
| // * STATUS_NOTFOUND: No rows were returned |
| // * *: Unable to read privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getPrivRowsForObject( |
| const int64_t objectUID, |
| std::vector<ObjectPrivsRow> & objectPrivsRows) |
| |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| if (objectUID_ == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for getPrivRowsForObject()"); |
| return STATUS_ERROR; |
| } |
| |
| // generate the list of privileges granted to the object and store in class |
| if (generateObjectRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| for (size_t i = 0; i < objectRowList_.size(); i++) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*objectRowList_[i]); |
| if (row.grantorID_ != SYSTEM_USER) |
| { |
| ObjectPrivsRow newRow; |
| |
| strcpy(newRow.objectName,row.objectName_.c_str()); |
| newRow.objectType = row.objectType_; |
| newRow.granteeID = row.granteeID_; |
| strcpy(newRow.granteeName,row.granteeName_.c_str()); |
| newRow.granteeType = CmGetComGranteeAsGranteeType(row.granteeType_.c_str()); |
| newRow.grantorID = row.grantorID_; |
| strcpy(newRow.grantorName,row.grantorName_.c_str()); |
| newRow.grantorType = CmGetComGrantorAsGrantorType(row.grantorType_.c_str()); |
| newRow.privilegesBitmap = row.privsBitmap_.to_ulong(); |
| newRow.grantableBitmap = row.grantableBitmap_.to_ulong(); |
| |
| objectPrivsRows.push_back(newRow); |
| } |
| } |
| |
| return retcode; |
| } |
| // ---------------------------------------------------------------------------- |
| // method: getTreeOfGrantors |
| // |
| // Returns the list of grantors that have granted privileges to the grantee, |
| // either directly or through another grantor in the tree. |
| // |
| // The list is determined by first looking at the direct grantors. For each |
| // returned grantor, this function is called recursively to get the previous set |
| // of grantors until there are no more grantors. |
| // |
| // The list is returned in grantor ID order. |
| // |
| // For example: |
| // user1 (owner) grants to: |
| // user6 who grants to: |
| // user3 |
| // user4 who grants to: |
| // user5 |
| // user2 |
| // user3 who grants to: |
| // user4 |
| // user5 |
| // The following grantors are returned for granteeID user4: |
| // user1, user3, user6 |
| // |
| // Params: |
| // granteeID - where to start the search |
| // listOfGrantors - returns the list of grantors |
| // ---------------------------------------------------------------------------- |
| void PrivMgrPrivileges::getTreeOfGrantors( |
| const int32_t granteeID, |
| std::set<int32_t> &listOfGrantors) |
| { |
| // search the rowList for a match |
| for (size_t i = 0; i < objectRowList_.size(); i++) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*objectRowList_[i]); |
| if (row.granteeID_ == granteeID) |
| { |
| // We found a grant to the granteeID |
| // go up to the next level using the grantorID |
| getTreeOfGrantors( row.grantorID_, listOfGrantors); |
| listOfGrantors.insert(granteeID); |
| } |
| } |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: givePrivForObjects |
| // * |
| // * Updates one or more rows in the OBJECT_PRIVILEGES table to reflect |
| // * a new owner of one or more objects. |
| // * |
| // * Parameters: |
| // * |
| // * <currentOwnerID> is the unique identifier for the current owner |
| // * <newOwnerID> is the unique identifier for the new owner |
| // * <newOwnerName> is the name of the new owner (upper cased) |
| // * <objectUIDs> is the list of objects with a new owner |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were updated to reflect new owner |
| // * *: Unable to update privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::givePrivForObjects( |
| const int32_t currentOwnerID, |
| const int32_t newOwnerID, |
| const std::string &newOwnerName, |
| const std::vector<int64_t> &objectUIDs) |
| |
| { |
| |
| PrivStatus privStatus = STATUS_GOOD; |
| |
| for (size_t i = 0; i < objectUIDs.size(); i++) |
| { |
| privStatus = givePriv(currentOwnerID,newOwnerID,newOwnerName,objectUIDs[i]); |
| if (privStatus != STATUS_GOOD) |
| return privStatus; |
| } |
| |
| return STATUS_GOOD; |
| |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: givePriv |
| // * |
| // * Updates rows in the OBJECT_PRIVILEGES table to reflect a new owner of |
| // * an objects. |
| // * |
| // * Parameters: |
| // * |
| // * <granteeID> is the unique identifier for the new owner |
| // * <granteeName> is the name of the new owner (upper cased) |
| // * <objectUIDs> is the list of objects with a new owner |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were updated to reflect new owner |
| // * *: Unable to update privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::givePriv( |
| const int32_t currentOwnerID, |
| const int32_t newOwnerID, |
| const std::string &newOwnerName, |
| const int64_t objectUID) |
| |
| { |
| |
| // ***************************************************************************** |
| // * * |
| // * The set of grants for a given object can be thought of as a tree with * |
| // * many branches and one root. At the root, is the grant from the system * |
| // * (grantor is _SYSTEM) to the owner of the object. The grant from the * |
| // * system is for all privileges, with grant option. * |
| // * * |
| // * The owner then grants privileges to one or more authIDs. Each of * |
| // * these grants can be viewed as a branch off the system grant root. With * |
| // * WITH GRANT OPTION, each of these branches can have its own set of * |
| // * branches, potentially resulting in a dense tree. See the rough * |
| // * drawing: * |
| // * * |
| // * USERG USERC USERD USERC USERB * |
| // * \ | / \ | / * |
| // * \ | / \ | / * |
| // * \ | / \ | / * |
| // * USERE USERD USERF USERB USERG * |
| // * \ | / \ | / * |
| // * \ | / \ | / * |
| // * \ | / \ | / * |
| // * USERB USERC USERD * |
| // * \ | / * |
| // * \ | / * |
| // * \ | / * |
| // * USERA * |
| // * | * |
| // * _SYSTEM * |
| // * * |
| // * * |
| // * Some of the rules are: * |
| // * 1) No grants to the owner (USERA) * |
| // * 2) A user can appear an unlimited number of times in the tree, but * |
| // * all grants from the user (for a given privilege) are from the same * |
| // * node. For example, USERB is granted 3 times, but all grants from * |
| // * USERB emanate from the same node. This is because when USERB grants * |
| // * a privilege, we start from the root and find the first node where * |
| // * USERB has WITH GRANT OPTION. * |
| // * * |
| // * When an object is given to another user, the current owner loses * |
| // * their grant from the system; instead, the new owner is granted from the * |
| // * system. All existing grants from the current owner are now from the new * |
| // * owner. Based on rule #1 above, the new owner can no longer appear in * |
| // * other nodes in the tree except the root node. So, in the case where the * |
| // * object is given to USERB, the new grant tree should be: * |
| // * * |
| // * USERD USERC * |
| // * | \ | * |
| // * | \ | * |
| // * USERC | \ | * |
| // * \ | USERF USERG * |
| // * \ | | \ / * |
| // * \ | | \ / * |
| // * \ | | \ / * |
| // * USERG ---------USERE | USERD * |
| // * \ | / * |
| // * \ | / * |
| // * \ | / * |
| // * USERB ---- USERC * |
| // * | * |
| // * _SYSTEM * |
| // * * |
| // * * |
| // * Note, previously USERA had three grants, and USERB had three grants, * |
| // * and now USERB has four grants--not six. First, the grant from USERA to * |
| // * USERB is removed. USERB is the grantee on only one node, from the system * |
| // * Second, USERA and USERB both had a grant to USERD; these grants need to * |
| // * be combined. * |
| // * * |
| // * Essentially, the subtree (or branch) of USERB has been grafted into * |
| // * the root, and all USERB leaf nodes have been removed. Any duplicate * |
| // * nodes, where USERA and USERB were grantors to the same grantee, have * |
| // * been merged. * |
| // * * |
| // * The algorithm is therefore three steps: * |
| // * * |
| // * 1) Delete any leaf nodes where the new owner is the grantee. * |
| // * 2) Get the list of nodes where the original or the new owner is the * |
| // * grantor. Merge any duplicates (update bitmaps), and update to new * |
| // * owner for old nodes. * |
| // * 3) Update grantee on system grant to new owner. * |
| // * * |
| // ***************************************************************************** |
| |
| // |
| // Delete the leaf nodes: |
| // |
| // DELETE FROM OBJECT_PRIVIELGES |
| // WHERE OBJECT_UID = objectUID and GRANTEE_ID = granteeID |
| // |
| |
| PrivStatus privStatus = STATUS_GOOD; |
| ObjectPrivsMDTable objectPrivsTable(objectTableName_,pDiags_); |
| std::vector<PrivMgrMDRow *> rowList; |
| char buf[1000]; |
| |
| sprintf(buf,"WHERE object_uid = %ld AND grantee_ID = %d", |
| objectUID,newOwnerID); |
| |
| privStatus = objectPrivsTable.deleteWhere(buf); |
| |
| if (privStatus != STATUS_GOOD) |
| return privStatus; |
| |
| sprintf(buf, "WHERE object_uid = %ld AND (grantor_ID = %d OR grantor_ID = %d) ", |
| objectUID,newOwnerID,currentOwnerID); |
| std::string orderByClause (" ORDER BY grantee_ID "); |
| |
| privStatus = objectPrivsTable.selectWhere(buf, orderByClause ,rowList); |
| if (privStatus != STATUS_GOOD) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| |
| for (size_t i = rowList.size(); i > 0; i--) |
| { |
| ObjectPrivsMDRow ¤tRow = static_cast<ObjectPrivsMDRow &>(*rowList[i - 1]); |
| if (i == 1 && currentRow.grantorID_ == currentOwnerID) |
| { |
| currentRow.grantorID_ = newOwnerID; |
| currentRow.grantorName_ = newOwnerName; |
| privStatus = objectPrivsTable.updateRow(currentRow); |
| if (privStatus != STATUS_GOOD) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| continue; |
| } |
| |
| ObjectPrivsMDRow &previousRow = static_cast<ObjectPrivsMDRow &>(*rowList[i - 1]); |
| |
| // If both granted to the same ID, merge the rows, delete one, |
| // and update the other. |
| if (currentRow.granteeID_ == previousRow.granteeID_) |
| { |
| previousRow.privsBitmap_ |= currentRow.privsBitmap_; |
| previousRow.grantableBitmap_ |= currentRow.grantableBitmap_; |
| previousRow.grantorID_ = newOwnerID; |
| previousRow.grantorName_ = newOwnerName; |
| privStatus = objectPrivsTable.deleteRow(currentRow); |
| if (privStatus != STATUS_GOOD) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| privStatus = objectPrivsTable.updateRow(previousRow); |
| if (privStatus != STATUS_GOOD) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| i--; |
| continue; |
| } |
| |
| // If this is a grant from the old owner, update to the new owner. |
| if (currentRow.grantorID_ == currentOwnerID) |
| { |
| currentRow.grantorID_ = newOwnerID; |
| currentRow.grantorName_ = newOwnerName; |
| privStatus = objectPrivsTable.updateRow(currentRow); |
| if (privStatus != STATUS_GOOD) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| continue; |
| } |
| |
| // Grant from the new owner. Will automatically be grafted into the |
| // tree in the next step. |
| } |
| |
| deleteRowList(rowList); |
| |
| // Update the root node. |
| char setClause[1000]; |
| char whereClause[1000]; |
| |
| sprintf(setClause," SET GRANTEE_ID = %d, GRANTEE_NAME = '%s' ", |
| newOwnerID,newOwnerName.c_str()); |
| sprintf(whereClause," WHERE GRANTOR_ID = %d ",SYSTEM_USER); |
| |
| privStatus = objectPrivsTable.updateWhere(setClause,whereClause); |
| if (privStatus != STATUS_GOOD) |
| return privStatus; |
| |
| return STATUS_GOOD; |
| |
| } |
| |
| |
| |
| |
| // ***************************************************************************** |
| // * Method: grantColumnPriv |
| // * |
| // * Adds or updates a row in the COLUMN_PRIVILEGES table. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> is the unique identifier for the grantee |
| // * <granteeName> is the name of the grantee (upper cased) |
| // * <grantorName> is the name of the grantor (upper cased) |
| // * <colPrivsArray> is the list of columns and privileges to grant |
| // * <isWGOSpecified> is true then also allow the grantee to grant the set |
| // * of privileges to other grantees |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were granted |
| // * *: Unable to grant privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::grantColumnPriv( |
| const ComObjectType objectType, |
| const int32_t granteeID, |
| const std::string &granteeName, |
| const std::string &grantorName, |
| const PrivMgrDesc &privsToGrant, |
| const bool isWGOSpecified) |
| { |
| |
| std::string traceMsg; |
| |
| PrivStatus privStatus = STATUS_GOOD; |
| |
| log (__FILE__, "Checking column privileges", -1); |
| |
| NAList<PrivMgrCoreDesc> colPrivsToGrant = privsToGrant.getColumnPrivs(); |
| |
| // Verify that view-col <=> referenced_col relationship exists |
| if (objectType == COM_VIEW_OBJECT) |
| { |
| ViewUsage myUsage; |
| myUsage.viewUID = objectUID_; |
| PrivMgrMDAdmin admin(trafMetadataLocation_, metadataLocation_, pDiags_); |
| if (admin.getViewColUsages(myUsage) == STATUS_ERROR) |
| return STATUS_ERROR; |
| if (myUsage.viewColUsagesStr.empty()) |
| { |
| *pDiags_ << DgSqlCode (-CAT_COLUMN_PRIVILEGE_NOT_ALLOWED) |
| << DgTableName (objectName_.c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| |
| |
| bool rowWritten = false; |
| |
| std::string whereBase(" WHERE object_uid = "); |
| |
| whereBase += UIDToString(objectUID_); |
| whereBase += " AND grantor_id = "; |
| whereBase += authIDToString(grantorID_); |
| whereBase += " AND grantee_id = "; |
| whereBase += authIDToString(granteeID); |
| whereBase += " AND column_number = "; |
| |
| ColumnPrivsMDTable columnPrivsTable(columnTableName_,pDiags_); |
| |
| // Get privileges on the object for grantor/grantee |
| ObjectPrivsMDRow objRow; |
| PrivObjectBitmap objPrivsBitmap; |
| PrivObjectBitmap objGrantableBitmap; |
| privStatus = getGrantedPrivs(granteeID, objRow); |
| |
| // getGrantedPrivs returns STATUS_GOOD or STATUS_NOTFOUND |
| // if STATUS_NOTFOUND, bitmaps are empty (as initialized above) |
| // if STATUS_GOOD, set current bitmaps |
| if (privStatus == STATUS_GOOD) |
| { |
| objPrivsBitmap = objRow.privsBitmap_; |
| objGrantableBitmap = objRow.grantableBitmap_; |
| } |
| |
| // Get existing column grants from grantor to the specified grantee. |
| NAList<PrivMgrCoreDesc> grantedColPrivs(STMTHEAP); |
| getColRowsForGranteeGrantor(columnRowList_, |
| granteeID,grantorID_, |
| grantedColPrivs); |
| |
| |
| // Walk the list of column privileges to grant, and either insert a new |
| // row in the COLUMN_PRIVILEGES table or update an existing row. |
| for (size_t i = 0; i < colPrivsToGrant.entries(); i++) |
| { |
| PrivMgrCoreDesc &colPrivToGrant = colPrivsToGrant[i]; |
| |
| // TBD - add a describe function to PrivMgrCoreDesc and PrivMgrDesc so |
| // information can ge logged. |
| |
| bool updateOperation = false; |
| bool skipOperation = false; |
| |
| PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, colPrivToGrant.getColumnOrdinal()); |
| if (grantedColPriv) |
| { |
| // An existing row with the same column has been found, it is one of four cases: |
| // |
| // 1) AuthID had WGO, now trying to take away WGO [error] |
| // 2) Adding a privilege (e.g., authID had SELECT, now granting INSERT) [update operation] |
| // 3) AuthID had privilege, now adding WGO [update operation] |
| // 4) AuthID already has privilege and/or WGO specified [skip operation] |
| |
| // case 1: see if trying to take away WGO - anyNotSet returns true iff any |
| // WGO bit set in grantedColPriv is not set in colPrivToGrant - can this |
| // really occur? |
| if (colPrivToGrant.getPrivBitmap() == grantedColPriv->getPrivBitmap() && |
| grantedColPriv->anyNotSet(colPrivToGrant)) |
| { |
| PRIVMGR_INTERNAL_ERROR("trying to remove WGO during grant"); |
| return STATUS_ERROR; |
| } |
| |
| // Case 2: If the privilege bitmaps are not the same, adding a privilege. |
| // This is an update operation |
| if (colPrivToGrant.getPrivBitmap() != grantedColPriv->getPrivBitmap()) |
| { |
| updateOperation = true; |
| colPrivToGrant.unionOfPrivs(*grantedColPriv); |
| } |
| |
| else |
| // Case 3: the privileges match, see if there are any additional WGO privs |
| // to set and mark updatable |
| // anyNotSet returns true iff any WGO bit set in colPrivToGrant is not set in |
| // grantedColPriv, this means more WGO bits need to be set. |
| if (colPrivToGrant.anyNotSet(*grantedColPriv)) |
| { |
| updateOperation = true; |
| colPrivToGrant.unionOfPrivs(*grantedColPriv); |
| } |
| // Case 4: no changes to priv or WGO bits - no updates required - skip |
| else |
| skipOperation = true; |
| } |
| |
| // Done with this entry, go to the next one |
| if (skipOperation) |
| continue; |
| |
| // Create an ObjectUsage to propagate the privilege change to dependent |
| // objects |
| ObjectUsage objectUsage; |
| objectUsage.objectUID = objectUID_; |
| objectUsage.granteeID = granteeID; |
| objectUsage.objectName = objectName_; |
| objectUsage.objectType = objectType; |
| |
| PrivMgrCoreDesc currentPrivs; // creates an empty descriptor |
| PrivMgrCoreDesc tempPrivs(objPrivsBitmap, objGrantableBitmap); |
| objectUsage.originalPrivs.setTablePrivs(tempPrivs); |
| objectUsage.updatedPrivs.setTablePrivs(tempPrivs); |
| |
| // Create list of ColumnReferences |
| objectUsage.columnReferences = new std::vector<ColumnReference *>; |
| for (size_t i = 0; i < colPrivsToGrant.entries(); i++) |
| { |
| PrivMgrCoreDesc &colPrivToGrant = colPrivsToGrant[i]; |
| PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, colPrivToGrant.getColumnOrdinal()); |
| |
| ColumnReference *adjustedCol = new ColumnReference; |
| adjustedCol->columnOrdinal = colPrivToGrant.getColumnOrdinal(); |
| |
| PrivMgrCoreDesc adjustedPrivs; |
| if (grantedColPriv) |
| adjustedPrivs = *grantedColPriv; |
| |
| adjustedCol->originalPrivs = adjustedPrivs; |
| adjustedPrivs.unionOfPrivs(colPrivToGrant); |
| adjustedCol->updatedPrivs = adjustedPrivs; |
| objectUsage.columnReferences->push_back(adjustedCol); |
| } |
| |
| // Propagate the privilege change to dependent objects |
| if (updateDependentObjects(objectUsage, PrivCommand::GRANT_COLUMN) == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // Update the COLUMN_PRIVILEGES table with new privileges |
| // Prepare for the insert or update request |
| ColumnPrivsMDRow row; |
| |
| row.objectUID_ = objectUID_; |
| row.objectName_ = objectName_; |
| row.granteeID_ = granteeID; |
| row.granteeName_ = granteeName; |
| row.grantorID_ = grantorID_; |
| row.grantorName_ = grantorName; |
| row.privsBitmap_ = colPrivToGrant.getPrivBitmap(); |
| row.grantableBitmap_ = colPrivToGrant.getWgoBitmap(); |
| row.columnOrdinal_ = colPrivToGrant.getColumnOrdinal(); |
| |
| if (updateOperation) |
| privStatus = columnPrivsTable.updateColumnRow(row,whereBase); |
| else |
| privStatus = columnPrivsTable.insert(row); |
| |
| if (privStatus == STATUS_ERROR) |
| return privStatus; |
| |
| rowWritten = true; |
| } |
| |
| return STATUS_GOOD; |
| |
| } |
| //************* End of PrivMgrPrivileges::grantColumnPriv **************** |
| |
| |
| |
| // ***************************************************************************** |
| // * Method: grantObjectPriv |
| // * |
| // * Adds or updates a row in the OBJECT_PRIVILEGES table. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> is the unique identifier for the grantee |
| // * <granteeName> is the name of the grantee (upper cased) |
| // * <grantorName> is the name of the grantor (upper cased) |
| // * <privsList> is the list of privileges to grant |
| // * <colPrivsArray> is the list of columns and privileges to grant |
| // * <isAllSpecified> if true then all privileges valid for the object |
| // * type will be granted |
| // * <isWGOSpecified> is true then also allow the grantee to grant the set |
| // * of privileges to other grantees |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were granted |
| // * *: Unable to grant privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::grantObjectPriv( |
| const ComObjectType objectType, |
| const int32_t granteeID, |
| const std::string &granteeName, |
| const std::string &grantorName, |
| const std::vector<PrivType> &privsList, |
| const std::vector<ColPrivSpec> & colPrivsArray, |
| const bool isAllSpecified, |
| const bool isWGOSpecified) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| std::string traceMsg; |
| log (__FILE__, "****** GRANT operation begins ******", -1); |
| |
| // If this grant request is called during the creation of the OBJECT_PRIVILEGES |
| // table, just return okay. Fixes a chicken and egg problem. |
| char theQuote = '"'; |
| std::string nameRequested(objectName_); |
| std::string nameToCheck(objectTableName_); |
| |
| // Delimited name issue. The passed in objectName may enclose name parts in |
| // double quotes even if the name part contains only [a-z][A-Z][0-9]_ |
| // characters. The same is true for the stored metadataLocation_. |
| // To allow equality checks to work, we strip off the double quote delimiters |
| // from both names. Fortunately, the double quote character is not allowed in |
| // any SQL identifier except as delimiters - so this works. |
| nameRequested.erase(std::remove(nameRequested.begin(), nameRequested.end(), theQuote), nameRequested.end()); |
| nameToCheck.erase(std::remove(nameToCheck.begin(), nameToCheck.end(), theQuote), nameToCheck.end()); |
| |
| if (nameRequested == nameToCheck && grantorID_ == SYSTEM_USER) |
| return STATUS_GOOD; |
| |
| // If the granting to self or DB__ROOT, return an error |
| if (grantorID_ == granteeID || granteeID == ComUser::getRootUserID()) |
| { |
| *pDiags_ << DgSqlCode(-CAT_CANT_GRANT_TO_SELF_OR_ROOT); |
| return STATUS_ERROR; |
| } |
| |
| PrivMgrDesc privsToGrant(granteeID); |
| PrivMgrDesc privsOfTheGrantor(grantorID_); |
| std::vector<int_32> roleIDs; |
| retcode = initGrantRevoke(objectType, granteeID, grantorName, |
| privsList, colPrivsArray, |
| isAllSpecified, isWGOSpecified, true, |
| privsToGrant, privsOfTheGrantor, roleIDs); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| // Make sure the grantor can grant at least one of the requested privileges |
| // SQL Ansi states that privileges that can be granted should be done so |
| // even if some requested privilege are not grantable. |
| // Remove any privsToGrant which are not held GRANTABLE by the Grantor. |
| bool warnNotAll = false; |
| PrivMgrDesc origPrivsToGrant = privsToGrant; |
| |
| // if limitToGrantable true ==> some specified privs were not grantable. |
| if ( privsToGrant.limitToGrantable( privsOfTheGrantor ) ) |
| warnNotAll = true; |
| |
| // If nothing left to grant, we are done. |
| // If one of the users roles has privilege, indicate in error message |
| if ( privsToGrant.isNull() ) |
| { |
| std::string rolesWithPrivs; |
| if (getRolesToCheck(grantorID_, roleIDs, objectType, rolesWithPrivs)== STATUS_GOOD) |
| { |
| if (rolesWithPrivs.size() > 0) |
| { |
| *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED) |
| << DgString0 (grantorName.c_str()) |
| << DgString1 (rolesWithPrivs.c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| |
| *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED) |
| << DgString0 (grantorName.c_str()); |
| return STATUS_ERROR; |
| } |
| |
| // grant any column level privileges |
| if ( !privsToGrant.isColumnLevelNull() ) |
| { |
| retcode = grantColumnPriv(objectType,granteeID,granteeName,grantorName, |
| privsToGrant,isWGOSpecified); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| } |
| |
| // If only column-level privileges were specified, no problem. |
| if (privsToGrant.getTablePrivs().isNull()) |
| { |
| // report any privs not granted |
| if (warnNotAll) |
| reportPrivWarnings(origPrivsToGrant, |
| privsToGrant, |
| CAT_NOT_ALL_PRIVILEGES_GRANTED); |
| |
| log (__FILE__, "****** GRANT operation succeeded ******", -1); |
| return STATUS_GOOD; |
| } |
| |
| // check for circular dependency. If USERX grants to USERY WGO, then USERY |
| // cannot grant back to USERX. Theoretically, USERX can grant select, update |
| // to USERY and USERY can grant delete, insert to USERX but for simplicity, |
| // we will reject the request independent on the set of privileges involved. |
| std::set<int32_t> listOfGrantors; |
| getTreeOfGrantors(grantorID_, listOfGrantors); |
| |
| // If we find the grantee in the list of grantors, return an error |
| if (listOfGrantors.find(granteeID) != listOfGrantors.end()) |
| { |
| *pDiags_ << DgSqlCode(-CAT_CIRCULAR_PRIVS) |
| << DgString0(grantorName.c_str()) |
| << DgString1(granteeName.c_str()); |
| return STATUS_ERROR; |
| } |
| |
| |
| // See if grantor has previously granted privileges to the grantee |
| bool foundRow = false; |
| |
| ObjectPrivsMDRow row; |
| retcode = getGrantedPrivs(granteeID, row); |
| if (retcode == STATUS_NOTFOUND) |
| foundRow = false; |
| else if (retcode == STATUS_GOOD) |
| foundRow = true; |
| else |
| return retcode; |
| |
| // if privileges exist, set currentPrivs to existing list |
| PrivMgrCoreDesc currentPrivs; // creates an empty descriptor |
| if (foundRow) |
| { |
| PrivMgrCoreDesc tempPrivs(row.privsBitmap_, row.grantableBitmap_); |
| currentPrivs = tempPrivs; |
| } |
| |
| PrivMgrCoreDesc savedOriginalPrivs = currentPrivs; |
| |
| // get the list of additional privileges to grant |
| // some privileges may have already been granted |
| PrivMgrDesc privsToAdd = privsToGrant; |
| PrivMgrCoreDesc::PrivResult result = privsToAdd.grantTablePrivs(currentPrivs); |
| |
| // nothing to grant - everything is already granted |
| if ( result == PrivMgrCoreDesc::NONE ) |
| { |
| if (warnNotAll) |
| reportPrivWarnings(origPrivsToGrant, |
| privsToGrant, |
| CAT_NOT_ALL_PRIVILEGES_GRANTED); |
| return STATUS_GOOD; |
| } |
| |
| // Internal consistency check. We should have granted something. |
| assert( result != PrivMgrCoreDesc::NEUTRAL ); |
| |
| // There is something to grant, update/insert metadata |
| |
| // set up row if it does not exist and add it to the objectRowList |
| if (!foundRow) |
| { |
| ObjectPrivsMDRow *pRow = new ObjectPrivsMDRow(); |
| pRow->objectUID_ = objectUID_; |
| pRow->objectName_ = objectName_; |
| pRow->objectType_ = objectType; |
| pRow->granteeID_ = granteeID; |
| pRow->granteeName_ = granteeName; |
| pRow->granteeType_ = USER_GRANTEE_LIT; |
| pRow->grantorID_ = grantorID_; |
| pRow->grantorName_ = grantorName; |
| pRow->grantorType_ = USER_GRANTOR_LIT; |
| pRow->privsBitmap_.reset(); |
| pRow->grantableBitmap_.reset(); |
| objectRowList_.push_back(pRow); |
| row = *pRow; |
| } |
| |
| // combine privsToGrant with existing privs |
| else |
| { |
| privsToGrant.unionOfPrivs(currentPrivs); |
| row.privsBitmap_ = privsToGrant.getTablePrivs().getPrivBitmap(); |
| row.grantableBitmap_ = privsToGrant.getTablePrivs().getWgoBitmap(); |
| } |
| |
| // Update dependent objects |
| ObjectUsage objectUsage; |
| objectUsage.objectUID = objectUID_; |
| objectUsage.granteeID = granteeID; |
| objectUsage.grantorIsSystem = false; |
| objectUsage.objectName = row.objectName_; |
| objectUsage.objectType = row.objectType_; |
| objectUsage.columnReferences = NULL; |
| |
| PrivMgrDesc originalPrivs (row.granteeID_); |
| originalPrivs.setTablePrivs(savedOriginalPrivs); |
| objectUsage.originalPrivs = originalPrivs; |
| objectUsage.updatedPrivs = privsToGrant; |
| |
| if (updateDependentObjects(objectUsage, PrivCommand::GRANT_OBJECT) == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| ObjectPrivsMDTable objectPrivsTable (objectTableName_, pDiags_); |
| if (foundRow) |
| { |
| row.describeRow(traceMsg); |
| traceMsg.insert(0, "updating existing privilege row "); |
| log (__FILE__, traceMsg, -1); |
| |
| // update the row |
| retcode = objectPrivsTable.updateRow(row); |
| } |
| else |
| { |
| row.privsBitmap_ = privsToGrant.getTablePrivs().getPrivBitmap(); |
| row.grantableBitmap_ = privsToGrant.getTablePrivs().getWgoBitmap(); |
| row.describeRow(traceMsg); |
| traceMsg.insert(0, "adding new privilege row "); |
| log (__FILE__, traceMsg, -1); |
| |
| // insert the row |
| retcode = objectPrivsTable.insert(row); |
| } |
| |
| if (warnNotAll) |
| reportPrivWarnings(origPrivsToGrant, |
| privsToGrant, |
| CAT_NOT_ALL_PRIVILEGES_GRANTED); |
| |
| log (__FILE__, "****** GRANT operation succeeded ******", -1); |
| |
| return retcode; |
| } |
| |
| // ***************************************************************************** |
| // * Method: grantObjectPriv |
| // * |
| // * Adds or update a row in the OBJECT_PRIVILEGES table representing the |
| // * owner privileges. The privileges and grantable bitmaps as passed in. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> is the unique identifier for the grantee |
| // * <granteeName> is the name of the grantee (upper cased) |
| // * <privBitmap> is the list of privileges to grant |
| // * <grantableBitmap> is the grantable privileges to grant |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were granted |
| // * *: Unable to grant privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::grantObjectPriv( |
| const ComObjectType objectType, |
| const int32_t granteeID, |
| const PrivObjectBitmap privsBitmap, |
| const PrivObjectBitmap grantableBitmap) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| if (objectUID_ == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for grant command"); |
| return STATUS_ERROR; |
| } |
| |
| // get the associated grantorName and granteeName |
| std::string grantorName; |
| if (!getAuthNameFromAuthID(grantorID_, grantorName)) |
| return STATUS_ERROR; |
| |
| std::string granteeName; |
| if (!getAuthNameFromAuthID(granteeID, granteeName)) |
| return STATUS_ERROR; |
| |
| // set up the values of the row to insert |
| ObjectPrivsMDRow row; |
| row.objectUID_ = objectUID_; |
| row.objectName_ = objectName_; |
| row.objectType_ = objectType; |
| row.granteeID_ = granteeID; |
| row.granteeName_ = granteeName; |
| row.granteeType_ = USER_GRANTEE_LIT; |
| row.grantorID_ = grantorID_; |
| row.grantorName_ = grantorName; |
| row.grantorType_ = (grantorID_ == SYSTEM_USER) ? SYSTEM_GRANTOR_LIT : USER_GRANTOR_LIT; |
| row.privsBitmap_ = privsBitmap; |
| row.grantableBitmap_ = grantableBitmap; |
| |
| // Insert the new row, the row should not exist since the request |
| // is coming during the creation of a new object. |
| ObjectPrivsMDTable objectPrivsTable (objectTableName_, pDiags_); |
| retcode = objectPrivsTable.insert(row); |
| |
| return retcode; |
| } |
| |
| // ***************************************************************************** |
| // * Method: grantToOwners |
| // * |
| // * Performs the initial grant from the system to the owner. For private |
| // * schemas, where the creator is not the schema/object owner, a grant from |
| // * the object owner to the creator is also performed. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> is the unique identifier for the grantee |
| // * <granteeName> is the name of the grantee (upper cased) |
| // * <ownerID> is the unique identifier for the owner of the object |
| // * <ownerName> is the name of the owner (upper cased) |
| // * <creatorID> is the unique identifier for the creator of the object |
| // * <creatorName> is the name of the creator (upper cased) |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: All DML privs were granted |
| // * *: Not all privs were granted. Error in CLI diags area. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::grantToOwners( |
| const ComObjectType objectType, |
| const Int32 granteeID, |
| const std::string & granteeName, |
| const Int32 ownerID, |
| const std::string & ownerName, |
| const Int32 creatorID, |
| const std::string & creatorName) |
| |
| { |
| |
| ObjectPrivsMDRow row; |
| PrivMgrCoreDesc corePrivs; |
| PrivObjectBitmap privsBitmap; |
| PrivObjectBitmap grantableBitmap; |
| |
| corePrivs.setAllObjectGrantPrivilege(objectType,true); |
| privsBitmap = corePrivs.getPrivBitmap(); |
| grantableBitmap = corePrivs.getWgoBitmap(); |
| |
| // Add the root grant from the system. |
| row.objectUID_ = objectUID_; |
| row.objectName_ = objectName_; |
| row.objectType_ = objectType; |
| row.granteeID_ = ownerID; |
| row.granteeName_ = ownerName; |
| row.granteeType_ = USER_GRANTEE_LIT; |
| row.grantorID_ = SYSTEM_USER; |
| row.grantorName_ = SYSTEM_AUTH_NAME; |
| row.grantorType_ = COM_SYSTEM_GRANTOR_LIT; |
| row.privsBitmap_ = privsBitmap; |
| row.grantableBitmap_ = grantableBitmap; |
| |
| ObjectPrivsMDTable objectPrivsTable(objectTableName_,pDiags_); |
| |
| PrivStatus privStatus = objectPrivsTable.insert(row); |
| |
| if (privStatus != STATUS_GOOD) |
| return privStatus; |
| |
| // If the owner and creator are the same, we are done. |
| // If not, this is an object being created in a private schema, and |
| // we need to grant privileges to the creator. If the creator is DB__ROOT, |
| // no need to grant privileges. |
| // |
| // This creator grant may be controlled by a CQD in the future. |
| if (ownerID == creatorID || creatorID == ComUser::getRootUserID() || |
| ownerID == HIVE_ROLE_ID || ownerID == HBASE_ROLE_ID) |
| return STATUS_GOOD; |
| |
| // Add a grant from the private schema owner to the creator. |
| row.grantorID_ = row.granteeID_; |
| row.grantorName_ = row.granteeName_; |
| row.grantorType_ = USER_GRANTOR_LIT; |
| row.granteeID_ = creatorID; |
| row.granteeName_ = creatorName; |
| |
| return objectPrivsTable.insert(row); |
| |
| } |
| |
| // ***************************************************************************** |
| // method: initGrantRevoke |
| // |
| // This method initializes structures needed to complete grant and revoke |
| // operations. |
| // |
| // It returns: |
| // privsToApply - the list of requested privileges to grant/revoke |
| // privsOfTheGrantor - privileges of the grantor to be used in later checks |
| // |
| // It also reads privileges for the object at table and column level from the |
| // metadata and stores the results in the class |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::initGrantRevoke( |
| const ComObjectType objectType, |
| const int32_t granteeID, |
| const std::string &grantorName, |
| const std::vector<PrivType> &privList, |
| const std::vector<ColPrivSpec> & colPrivsArray, |
| const bool isAllSpecified, |
| const bool isGOSpecified, |
| const bool isGrant, |
| PrivMgrDesc &privsToApply, |
| PrivMgrDesc &privsOfTheGrantor, |
| std::vector<int32_t> & roleIDs) |
| { |
| if (objectUID_ == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for grant or revoke command"); |
| return STATUS_ERROR; |
| } |
| |
| // Generate the list of privilege descriptors that were requested |
| PrivStatus retcode = convertPrivsToDesc(objectType, |
| isAllSpecified, |
| (isGrant) ? isGOSpecified : true, // WGO |
| (isGrant) ? false : isGOSpecified, // GOF |
| privList, |
| colPrivsArray, |
| privsToApply); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| // generate the list of privileges granted to the object and store in class |
| if (generateObjectRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // generate the list of privileges granted to object columns and store in class |
| if (generateColumnRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // get column and object privileges across all grantors |
| bool hasManagePrivileges; |
| retcode = getUserPrivs(objectType, grantorID_, roleIDs, privsOfTheGrantor, |
| hasManagePrivileges, NULL ); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| // get roleIDs for the grantor |
| retcode = getRoleIDsForUserID(grantorID_,roleIDs); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // If null, the grantor has no privileges |
| if ( privsOfTheGrantor.isNull() ) |
| { |
| std::string rolesWithPrivs; |
| if (getRolesToCheck(grantorID_, roleIDs, objectType, rolesWithPrivs)== STATUS_GOOD) |
| { |
| if (rolesWithPrivs.size() > 0) |
| { |
| *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED) |
| << DgString0 (grantorName.c_str()) |
| << DgString1 (rolesWithPrivs.c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| |
| *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED) |
| << DgString0 (grantorName.c_str()); |
| return STATUS_ERROR; |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: insertPrivRowsForObject |
| // * |
| // * writes rows that add grants of privileges for an object. |
| // * |
| // * Parameters: |
| // * |
| // * <objectPrivsRows> One or more rows of grants for the object. |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD : Rows were returned |
| // * STATUS_NOTFOUND: No rows were returned |
| // * *: Unable to read privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::insertPrivRowsForObject( |
| const int64_t objectUID, |
| const std::vector<ObjectPrivsRow> & objectPrivsRows) |
| |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| if (objectUID_ == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for insertPrivRowsForObject()"); |
| return STATUS_ERROR; |
| } |
| |
| ObjectPrivsMDTable objectPrivsTable(objectTableName_,pDiags_); |
| |
| for (int32_t i = 0; i < objectPrivsRows.size();++i) |
| { |
| ObjectPrivsMDRow row; |
| const ObjectPrivsRow &rowIn = objectPrivsRows[i]; |
| char granteeTypeString[3] = {0}; |
| char grantorTypeString[3] = {0}; |
| |
| row.objectUID_ = objectUID_; |
| row.objectName_ = rowIn.objectName; |
| row.objectType_ = rowIn.objectType; |
| row.granteeID_ = rowIn.granteeID; |
| row.granteeName_ = rowIn.granteeName; |
| CmGetComGranteeAsLit(rowIn.granteeType,granteeTypeString); |
| row.granteeType_ = granteeTypeString; |
| |
| row.grantorID_ = rowIn.grantorID; |
| row.grantorName_ = rowIn.grantorName; |
| CmGetComGrantorAsLit(rowIn.grantorType,grantorTypeString); |
| row.grantorType_ = grantorTypeString; |
| |
| row.privsBitmap_ = rowIn.privilegesBitmap; |
| row.grantableBitmap_ = rowIn.grantableBitmap; |
| |
| retcode = objectPrivsTable.insert(row); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| } |
| |
| return retcode; |
| } |
| |
| |
| // **************************************************************************** |
| // method: dealWithConstraints |
| // |
| // This method finds all the constraints associated with the table and |
| // determines if any are adversely affected by the privilege change. |
| // |
| // Params: |
| // objectUsage - the affected object |
| // listOfAffectedObjects - returns the list of affected objects |
| // |
| // Returns: PrivStatus |
| // STATUS_GOOD: No problems were encountered |
| // *: Errors were encountered, ComDiags area is set up |
| // |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::dealWithConstraints( |
| const ObjectUsage &objectUsage, |
| std::vector<ObjectUsage *> &listOfAffectedObjects) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| std::string traceMsg; |
| objectUsage.describe(traceMsg); |
| traceMsg.insert (0, "checking referencing constraints for "); |
| log (__FILE__, traceMsg, -1); |
| |
| // RI constraints can only be defined for base tables |
| if (objectUsage.objectType != COM_BASE_TABLE_OBJECT) |
| return STATUS_GOOD; |
| |
| // get the underlying tables for all RI constraints that reference the object |
| std::vector<ObjectReference *> objectList; |
| PrivMgrMDAdmin admin(trafMetadataLocation_, metadataLocation_, pDiags_); |
| retcode = admin.getReferencingTablesForConstraints(objectUsage, objectList); |
| traceMsg = "getting constraint usages: number usages found "; |
| traceMsg += to_string((long long int)objectList.size()); |
| traceMsg += ", retcode is "; |
| traceMsg += privStatusEnumToLit(retcode); |
| log (__FILE__, traceMsg, -1); |
| |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| int32_t lastObjectOwnerID = 0; |
| std::vector<int32_t> roleIDs; |
| |
| // objectList contains the list of objects referencing the referenced table, |
| // see if the requested privilege change causes an RI constraint to be invalid |
| for (size_t i = 0; i < objectList.size(); i++) |
| { |
| ObjectReference *pObjectRef = objectList[i]; |
| PrivMgrDesc originalPrivs; |
| PrivMgrDesc currentPrivs; |
| |
| pObjectRef->describe(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| // getRoleIDsForUserID does I/O to get information. The referencing |
| // list is returned by object owner to avoid rereading information for |
| // the same user |
| // At some time, we should cache user and role information |
| if (lastObjectOwnerID != pObjectRef->objectOwner) |
| { |
| roleIDs.clear(); |
| retcode = getRoleIDsForUserID(pObjectRef->objectOwner,roleIDs); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| } |
| |
| // get the summarized original and current privs for the referencing table |
| // current privs contains any adjustments due to the privilege change |
| retcode = summarizeCurrentAndOriginalPrivs(objectUsage.objectUID, |
| pObjectRef->objectOwner, |
| grantorID_, |
| roleIDs, |
| listOfAffectedObjects, |
| originalPrivs, |
| currentPrivs); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| PrivMgrCoreDesc thePrivs = currentPrivs.getTablePrivs(); |
| if (!thePrivs.getPriv(REFERENCES_PRIV)) |
| { |
| log (__FILE__, "User does not have reference privilege on the object", -1); |
| |
| // no longer have REFERENCES privilege on the table, |
| // see if privileges are granted on all required columns |
| std::vector<ColumnReference *> summarizedColRefs; |
| summarizeColPrivs(*pObjectRef, |
| pObjectRef->objectOwner, |
| grantorID_, |
| roleIDs, |
| listOfAffectedObjects, |
| summarizedColRefs); |
| |
| // check summarized privileges to see if still have priv through other privs |
| std::vector<ColumnReference *> neededColRefs = *pObjectRef->columnReferences; |
| for (size_t i = 0; i < neededColRefs.size(); i++) |
| { |
| |
| // neededColRefs contains the list of all columns referenced by this object |
| // summarizedColRefs are the current privileges with the privilege change |
| // incorporated. |
| // if user still has necessary privilege through column privileges, then |
| // revoke can proceed |
| ColumnReference *neededColRef = neededColRefs[i]; |
| for (size_t j = 0; j < summarizedColRefs.size(); j++) |
| { |
| ColumnReference *existingRef = summarizedColRefs[j]; |
| traceMsg = "Checking if have references for col: "; |
| traceMsg += to_string((long long int)existingRef->columnOrdinal); |
| log (__FILE__, traceMsg, -1); |
| if (existingRef->columnOrdinal == neededColRef->columnOrdinal) |
| { |
| PrivMgrCoreDesc colPrivs = existingRef->updatedPrivs; |
| traceMsg = "References setting: "; |
| traceMsg += (colPrivs.getPriv(REFERENCES_PRIV) ? "y" : "n"); |
| log (__FILE__, traceMsg, -1); |
| if (!colPrivs.getPriv(REFERENCES_PRIV)) |
| { |
| std::string referencingTable; |
| if (!admin.getConstraintName(objectUsage.objectUID, |
| pObjectRef->objectUID, |
| neededColRef->columnOrdinal, referencingTable)) |
| { |
| referencingTable = "UNKNOWN, Referencing table ID is "; |
| referencingTable += UIDToString(pObjectRef->objectUID ); |
| } |
| |
| *pDiags_ << DgSqlCode (-CAT_DEPENDENT_OBJECTS_EXIST) |
| << DgString0 (referencingTable.c_str()); |
| retcode = STATUS_ERROR; |
| } |
| break; |
| } |
| } |
| } |
| |
| // remove list of summarized columns |
| while (!summarizedColRefs.empty()) |
| delete summarizedColRefs.back(), summarizedColRefs.pop_back(); |
| } |
| } |
| |
| return retcode; |
| } |
| |
| |
| // **************************************************************************** |
| // method: dealWithUdrs |
| // |
| // This method finds all the udrs associated with the library and |
| // determines if any are adversely affected by the privilege change. |
| // |
| // Params: |
| // objectUsage - the affected object |
| // listOfAffectedObjects - returns the list of affected objects |
| // |
| // Returns: PrivStatus |
| // STATUS_GOOD: No problems were encountered |
| // *: Errors were encountered, ComDiags area is set up |
| // |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::dealWithUdrs( |
| const ObjectUsage &objectUsage, |
| std::vector<ObjectUsage *> &listOfAffectedObjects) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| // udrs (functions and procedures) can only be defined for in libraries |
| if (objectUsage.objectType != COM_LIBRARY_OBJECT) |
| return STATUS_GOOD; |
| |
| std::string traceMsg; |
| objectUsage.describe(traceMsg); |
| traceMsg.insert (0, "checking referencing routines for "); |
| log (__FILE__, traceMsg, -1); |
| |
| // get the udrs that reference the library for the grantee |
| std::vector<ObjectReference *> objectList; |
| PrivMgrMDAdmin admin(trafMetadataLocation_, metadataLocation_, pDiags_); |
| retcode = admin.getUdrsThatReferenceLibrary(objectUsage, objectList); |
| traceMsg = "getting routine usages: number usages found "; |
| traceMsg += to_string((long long int)objectList.size()); |
| traceMsg += ", retcode is "; |
| traceMsg += privStatusEnumToLit(retcode); |
| log (__FILE__, traceMsg, -1); |
| |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // objectList contain ObjectReferences for all udrs that reference the |
| // ObjectUsage (object losing privilege) through a library |
| PrivMgrDesc originalPrivs; |
| PrivMgrDesc currentPrivs; |
| |
| if (objectList.size() > 0) |
| { |
| std::vector<int32_t> roleIDs; |
| retcode = getRoleIDsForUserID(objectUsage.granteeID,roleIDs); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // if the grantee owns any udrs, get the summarized original and current |
| // privs for the library |
| // current privs contains any adjustments |
| retcode = summarizeCurrentAndOriginalPrivs(objectUsage.objectUID, |
| objectUsage.granteeID, |
| grantorID_, |
| roleIDs, |
| listOfAffectedObjects, |
| originalPrivs, |
| currentPrivs); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| // If the udr can no longer be created due to lack of USAGE privilege, |
| // return a dependency error. |
| PrivMgrCoreDesc thePrivs = objectUsage.updatedPrivs.getTablePrivs(); |
| if (!thePrivs.getPriv(USAGE_PRIV)) |
| { |
| // There could be multiple udrs, just pick the first one in the list |
| // for the error message. |
| ObjectReference *pObjectRef = objectList[0]; |
| *pDiags_ << DgSqlCode (-CAT_DEPENDENT_OBJECTS_EXIST) |
| << DgString0 (pObjectRef->objectName.c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // **************************************************************************** |
| // method: dealWithViews |
| // |
| // This method finds all the views that referenced the object. |
| // This method recursively calls itself to find other views referenced in the |
| // tree of referencing views |
| // |
| // Params: |
| // objectUsage - the affected object |
| // command - type of command - grant, revoke restrict, revoke cascade |
| // listOfAffectedObjects - returns the list of affected objects |
| // |
| // Returns: PrivStatus |
| // STATUS_GOOD: No problems were encountered |
| // *: Errors were encountered, ComDiags area is set up |
| // |
| // In the future, we want to cache the lists of objects instead of going to the |
| // metadata everytime. |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::dealWithViews( |
| const ObjectUsage &objectUsage, |
| const PrivCommand command, |
| const int32_t grantorID, |
| std::vector<ObjectUsage *> &listOfAffectedObjects) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| std::string traceMsg; |
| objectUsage.describe(traceMsg); |
| traceMsg.insert (0, "checking referencing views for "); |
| log (__FILE__, traceMsg, -1); |
| |
| // Get any views that referenced this object to see if the privilege changes |
| // should be propagated |
| std::vector<ViewUsage> viewUsages; |
| PrivMgrMDAdmin admin(trafMetadataLocation_, metadataLocation_, pDiags_); |
| retcode = admin.getViewsThatReferenceObject(objectUsage, viewUsages); |
| traceMsg = "getting view usages: number usages found "; |
| traceMsg += to_string((long long int)viewUsages.size()); |
| traceMsg += ", retcode is "; |
| traceMsg += privStatusEnumToLit(retcode); |
| log (__FILE__, traceMsg, -1); |
| if (retcode == STATUS_NOTFOUND) |
| return STATUS_GOOD; |
| if (retcode != STATUS_GOOD && retcode != STATUS_WARNING) |
| return retcode; |
| |
| // for each entry in the viewUsages list calculate the changed privileges |
| // if privileges change, add viewUsage to listOfAffectedObjects |
| for (size_t i = 0; i < viewUsages.size(); i++) |
| { |
| ViewUsage viewUsage = viewUsages[i]; |
| |
| viewUsage.describe(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| // gatherViewPrivileges recreates privileges for the view based on changes |
| // requested by the current grant/revoke request |
| // Updated priv descriptors are stored in the viewUsage structure. |
| retcode = gatherViewPrivileges(viewUsage, command, grantorID, listOfAffectedObjects); |
| traceMsg = "gathered view privs: retcode is "; |
| traceMsg += privStatusEnumToLit(retcode); |
| log (__FILE__, traceMsg, -1); |
| |
| if (retcode != STATUS_GOOD && retcode != STATUS_WARNING) |
| return retcode; |
| |
| // check to see if privileges changed |
| if (viewUsage.originalPrivs == viewUsage.updatedPrivs) |
| continue; |
| else |
| { |
| // This view privs have been changed by the grant/revoke request |
| // However, only INSERT, DELETE, and UPDATE privs can be propagated |
| // If the view is not updatable or insertable then, we are done with |
| // this viewUsage |
| if (viewUsage.isUpdatable || viewUsage.isInsertable) |
| { |
| // Add viewUsage to list of affected objects |
| ObjectUsage *pUsage = new (ObjectUsage); |
| pUsage->objectUID = viewUsage.viewUID; |
| pUsage->granteeID = viewUsage.viewOwner; |
| pUsage->grantorIsSystem = true; |
| pUsage->objectName = viewUsage.viewName; |
| pUsage->objectType = COM_VIEW_OBJECT; |
| pUsage->originalPrivs = viewUsage.originalPrivs; |
| pUsage->updatedPrivs = viewUsage.updatedPrivs; |
| listOfAffectedObjects.push_back(pUsage); |
| |
| traceMsg = "adding new objectUsage for "; |
| pUsage->describe(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| #if 0 |
| // When cascade is supported, the list of down stream views must be |
| // included in the list of affected objects. |
| // Also, need to understand ANSI SQL rules for propagating view privs, |
| // that is, should down stream views be updated if it parent view |
| // privs are changed and the parent has WGO specified. |
| |
| // get list of grantee ID's that have been granted privileges on the |
| // current view. |
| std::set<int32_t> granteeList; |
| if (getGranteesForViewUsage(viewUsage, granteeList) == STATUS_ERROR) |
| { |
| PRIVMGR_INTERNAL_ERROR("Error while getting grantees for down stream views"); |
| return STATUS_ERROR; |
| } |
| |
| // Call dealWithViews to see if the down stream views should be adjusted. |
| for (std::set<int32_t>::iterator it = granteeList.begin(); it!= granteeList.end(); ++it) |
| { |
| pUsage->granteeID = *it; |
| retcode = dealWithViews(*pUsage, command, viewUsage.viewOwner, listOfAffectedObjects); |
| if (retcode != STATUS_GOOD && retcode != STATUS_WARNING) |
| return retcode; |
| } |
| pUsage->granteeID = viewUsage.viewOwner; |
| #endif |
| } // updatable views |
| } // view privs changed |
| } // list of view usages |
| |
| return STATUS_GOOD; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: gatherViewColUsages |
| // |
| // This method gathers the view-col <=> referenced-col usages and creates a |
| // list of ComViewColUsage's for the referenced object. Each ComViewColUsage |
| // is identified the view column number, and the related UID and column number |
| // of the referenced object. |
| // |
| // parameters: |
| // objectRef - description of the referenced object |
| // viewUsage - description of the view |
| // viewColUsages - list of view column, referenced column usages |
| // |
| // Returns: PrivStatus |
| // |
| // STATUS_GOOD: Operation successful |
| // *: Unable to gather usages, see diags. |
| // |
| // ---------------------------------------------------------------------------- |
| PrivStatus PrivMgrPrivileges::gatherViewColUsages( |
| ObjectReference *objectRef, |
| ViewUsage &viewUsage, |
| std::vector<ComViewColUsage> &viewColUsages) |
| { |
| std::string traceMsg; |
| PrivStatus retcode; |
| |
| PrivMgrMDAdmin admin(trafMetadataLocation_, metadataLocation_, pDiags_); |
| |
| // Get columns for referenced object if they are not already present |
| if (objectRef->columnReferences == NULL) |
| { |
| retcode = admin.getColumnReferences(objectRef); |
| if (objectRef->columnReferences) |
| { |
| traceMsg += "getting column references: number references found "; |
| traceMsg += to_string((long long int)objectRef->columnReferences->size()); |
| traceMsg += ", "; |
| } |
| traceMsg += "retcode is "; |
| traceMsg += privStatusEnumToLit(retcode); |
| log (__FILE__, traceMsg, -1); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| } |
| |
| // Extract view <=> object column relationship from the TEXT table |
| // and add it to the viewUsage |
| if (viewUsage.viewColUsagesStr.empty()) |
| { |
| retcode = admin.getViewColUsages(viewUsage); |
| traceMsg = "getting view column usages"; |
| traceMsg += ", retcode is "; |
| traceMsg += privStatusEnumToLit(retcode); |
| log (__FILE__, traceMsg, -1); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| } |
| |
| // Setup the view column to referenced column relationship |
| char * beginStr = (char *)viewUsage.viewColUsagesStr.c_str(); |
| char * endStr = strchr(beginStr, ';'); |
| while (endStr != NULL) |
| { |
| ComViewColUsage colUsage; |
| std::string currentUsage(beginStr, endStr - beginStr + 1); |
| colUsage.unpackUsage (currentUsage.c_str()); |
| viewColUsages.push_back(colUsage); |
| beginStr = endStr+1; |
| endStr = strchr(beginStr, ';'); |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: gatherViewPrivileges |
| // |
| // This method gathers privileges for the view both the original and current |
| // |
| // parameters: |
| // viewUsage - description of the view |
| // listOfAffectedObjects - list of changed privileges so far |
| // |
| // Returns: PrivStatus |
| // |
| // STATUS_GOOD: Privileges were gathered |
| // *: Unable to gather privileges, see diags. |
| // |
| // ---------------------------------------------------------------------------- |
| PrivStatus PrivMgrPrivileges::gatherViewPrivileges( |
| ViewUsage &viewUsage, |
| const PrivCommand command, |
| const int32_t grantorID, |
| const std::vector<ObjectUsage *> listOfAffectedObjects) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| std::string traceMsg; |
| |
| // initialize summarized descriptors and set all applicable privileges |
| // TBD: if view is not updatable, should initialize correctly. |
| // views have same privileges as tables |
| bool setWGOtrue = true; |
| PrivMgrDesc summarizedOriginalPrivs; |
| summarizedOriginalPrivs.setAllTableGrantPrivileges(setWGOtrue); |
| PrivMgrDesc summarizedCurrentPrivs; |
| summarizedCurrentPrivs.setAllTableGrantPrivileges(setWGOtrue); |
| |
| // Get list of objects referenced by the view |
| std::vector<ObjectReference *> objectList; |
| PrivMgrMDAdmin admin(trafMetadataLocation_, metadataLocation_, pDiags_); |
| retcode = admin.getObjectsThatViewReferences(viewUsage, objectList); |
| traceMsg += "getting object references: number references found "; |
| traceMsg += to_string((long long int)objectList.size()); |
| traceMsg += ", retcode is "; |
| traceMsg += privStatusEnumToLit(retcode); |
| log (__FILE__, traceMsg, -1); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // For each referenced object, summarize the original and current |
| // privileges |
| PrivMgrDesc originalPrivs; |
| PrivMgrDesc currentPrivs; |
| int32_t lastObjectOwnerID = 0; |
| |
| std::vector<int32_t> roleIDs; |
| retcode = getRoleIDsForUserID(viewUsage.viewOwner,roleIDs); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // First gather privileges on the object |
| for (size_t i = 0; i < objectList.size(); i++) |
| { |
| ObjectReference *pObjectRef = objectList[i]; |
| pObjectRef->describe(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| // get the summarized original and current privs for the |
| // referenced object that have been granted to the view owner |
| // listOfAffectedObjects contain the privilege adjustments needed |
| // to generate the current privs |
| retcode = summarizeCurrentAndOriginalPrivs(pObjectRef->objectUID, |
| viewUsage.viewOwner, |
| grantorID, |
| roleIDs, |
| listOfAffectedObjects, |
| originalPrivs, |
| currentPrivs); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| // If the referenced object is a sequence generator, then the grantee |
| // must still have the USAGE_PRIV. The USAGE_PRIV is not a column |
| // level privilege so no column level check is necessary. |
| if (isRevokeCommand(command)) |
| { |
| if (pObjectRef->objectType == COM_SEQUENCE_GENERATOR_OBJECT) |
| { |
| PrivMgrCoreDesc thePrivs = currentPrivs.getTablePrivs(); |
| if (!thePrivs.getPriv(USAGE_PRIV)) |
| { |
| *pDiags_ << DgSqlCode (-CAT_DEPENDENT_OBJECTS_EXIST) |
| << DgString0 (viewUsage.viewName.c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| } |
| |
| // "and" the returned privilege to the summarized privileges |
| // for all objects |
| summarizedOriginalPrivs.intersectionOfPrivs(originalPrivs); |
| summarizedCurrentPrivs.intersectionOfPrivs(currentPrivs); |
| |
| // reset to prepare for next object |
| originalPrivs.resetTablePrivs(); |
| currentPrivs.resetTablePrivs(); |
| } |
| |
| // If view has all grantable col privs already, no need to check further |
| bool checkCols = false; |
| PrivMgrCoreDesc thePrivs = summarizedCurrentPrivs.getTablePrivs(); |
| for (size_t i = FIRST_DML_COL_PRIV; i <= LAST_DML_COL_PRIV; i++ ) |
| { |
| PrivType privType = PrivType(i); |
| if (thePrivs.getPriv(privType) && thePrivs.getWgo(privType)) |
| continue; |
| checkCols = true; |
| break; |
| } |
| |
| // No need to check col privs, return with summarized privs |
| if (!checkCols) |
| { |
| // Update view usage with summarized privileges |
| viewUsage.originalPrivs = summarizedOriginalPrivs; |
| viewUsage.updatedPrivs = summarizedCurrentPrivs; |
| return STATUS_GOOD; |
| } |
| |
| // Turn on bits to prepare for intersecting with object privileges |
| originalPrivs.setAllTableGrantPrivileges(setWGOtrue); |
| currentPrivs.setAllTableGrantPrivileges(setWGOtrue); |
| |
| std::vector<ColumnReference *> summarizedColRefs; |
| |
| // Gather column privileges on all objects referencing the view. |
| // for grants, a view might gain privs |
| // for revokes, a view might lose privs |
| // For example: |
| // as user1: |
| // create table sch1.t1 (c1 int, c2 int, ....); |
| // grant select on sch1.t1 to user2; |
| // grant insert (c1) on sch1.t1 to user2 |
| // as user2: |
| // create view sch2.v1 as select c1 from sch1.t1; |
| // view sch2.v1 gains the insert privilege since all columns that |
| // sch2.v1 references have granted user2 the insert privilege. |
| for (size_t i = 0; i < objectList.size(); i++) |
| { |
| ObjectReference *pObjectRef = objectList[i]; |
| |
| // gather the view-col <=> referenced-col usages |
| std::vector <ComViewColUsage> viewColUsages; |
| retcode = gatherViewColUsages(pObjectRef, viewUsage, viewColUsages); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // The view-col <=> referenced_col relationship is not found |
| // No need to proceed further. |
| // If this is a grant of a column privilege, return an error |
| // User needs to drop and recreate view |
| // The view-col <=> referenced-col usages are only being started in |
| // metadata after column privileges are officially supported. Any views |
| // create before this time, do not have this information, so column privs |
| // either do not exist (revoke) or cannot be added (grant). The view needs |
| // to be dropped and recreated (or add a fixup procedure). |
| if (retcode == STATUS_NOTFOUND) |
| { |
| if (command == GRANT_COLUMN) |
| { |
| *pDiags_ << DgSqlCode (-CAT_COLUMN_PRIVILEGE_NOT_ALLOWED) |
| << DgTableName (viewUsage.viewName.c_str()); |
| return STATUS_ERROR; |
| } |
| return STATUS_GOOD; |
| } |
| |
| |
| // gather the updated summarized column privileges on the referenced object |
| summarizeColPrivs(*pObjectRef, |
| viewUsage.viewOwner, |
| grantorID, |
| roleIDs, |
| listOfAffectedObjects, |
| summarizedColRefs); |
| |
| // For each view column, get the corresponding referenced column priv |
| for (size_t j = 0; j < viewColUsages.size(); j++) |
| { |
| ComViewColUsage colUsage = viewColUsages[j]; |
| |
| // See if the referenced object contains the associated view column |
| if (colUsage.getRefdUID() != pObjectRef->objectUID) |
| continue; |
| |
| // Get the referenced column, if NULL then something is wrong |
| ColumnReference *neededColRef = pObjectRef->find(colUsage.getRefdColNumber()); |
| if (neededColRef == NULL) |
| { |
| PRIVMGR_INTERNAL_ERROR("View column to referenced column relationship wrong"); |
| return STATUS_ERROR; |
| } |
| |
| // Find and update the current bitmaps for column |
| for (size_t k = 0; k < summarizedColRefs.size(); k++) |
| { |
| ColumnReference *existingRef = summarizedColRefs[k]; |
| if (existingRef->columnOrdinal == neededColRef->columnOrdinal) |
| { |
| originalPrivs.intersectionOfPrivs(existingRef->originalPrivs); |
| currentPrivs.intersectionOfPrivs(existingRef->updatedPrivs); |
| break; |
| } |
| } |
| } |
| } |
| |
| // Union or "or" the returned privileges to the summarized privileges |
| // for all columns. The privilege is set in currentPrivs only if all |
| // columns in the view have the privilege. |
| summarizedOriginalPrivs.unionOfPrivs(originalPrivs); |
| summarizedCurrentPrivs.unionOfPrivs(currentPrivs); |
| |
| // If user no longer has select privilege on referenced object |
| // returns an error |
| // When cascade is supported, then referenced objects will be removed |
| if (isRevokeCommand(command)) |
| { |
| if (!summarizedCurrentPrivs.getTablePrivs().getPriv(SELECT_PRIV)) |
| { |
| *pDiags_ << DgSqlCode (-CAT_DEPENDENT_OBJECTS_EXIST) |
| << DgString0 (viewUsage.viewName.c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| |
| // If view is not updatable or insertable, turn off privs in bitmaps |
| if (!viewUsage.isUpdatable) |
| { |
| summarizedCurrentPrivs.getTablePrivs().setPriv(UPDATE_PRIV,false); |
| summarizedCurrentPrivs.getTablePrivs().setPriv(UPDATE_PRIV, false); |
| summarizedCurrentPrivs.getTablePrivs().setPriv(DELETE_PRIV,false); |
| summarizedCurrentPrivs.getTablePrivs().setPriv(DELETE_PRIV, false); |
| } |
| |
| if (!viewUsage.isInsertable) |
| { |
| summarizedCurrentPrivs.getTablePrivs().setPriv(INSERT_PRIV,false); |
| summarizedCurrentPrivs.getTablePrivs().setPriv(INSERT_PRIV, false); |
| } |
| |
| // Update view usage with summarized privileges |
| viewUsage.originalPrivs = summarizedOriginalPrivs; |
| viewUsage.updatedPrivs = summarizedCurrentPrivs; |
| |
| return STATUS_GOOD; |
| } |
| |
| // **************************************************************************** |
| // method: generateColumnRowList |
| // |
| // generate the list of privileges granted to columns of the object and |
| // store in columnRowList_ class member |
| // |
| // Returns: |
| // STATUS_GOOD - list of rows was generated |
| // STATUS_NOTFOUND - no column privileges were found |
| // STATUS_ERROR - the diags area is populated with any errors |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::generateColumnRowList() |
| { |
| // If columnRowList_ already allocated, just return |
| if (columnRowList_.size() > 0) |
| return STATUS_GOOD; |
| PrivStatus privStatus = getColumnRowList(objectUID_, columnRowList_); |
| if (privStatus == STATUS_ERROR) |
| return privStatus; |
| return STATUS_GOOD; |
| } |
| |
| // **************************************************************************** |
| // method: getColumnRowList |
| // |
| // generate the list of privileges granted to the passed in objectUID and |
| // returns in the columnRowList parameter |
| // |
| // The list is ordered by grantor/grantee/column_number |
| // |
| // Returns: |
| // STATUS_GOOD - list of rows was generated |
| // STATUS_NOTFOUND - in most cases, there should be at least one row in the |
| // OBJECT_PRIVILEGES table. But there is at least one case |
| // where this is not true - trying to get privilege info |
| // for indexes when using the table (index_table) syntax. |
| // STATUS_ERROR - the diags area is populated with any errors |
| // **************************************************************************** |
| |
| PrivStatus PrivMgrPrivileges::getColumnRowList( |
| const int64_t objectUID, |
| std::vector<PrivMgrMDRow *> &columnRowList) |
| { |
| std::string whereClause ("where object_uid = "); |
| whereClause += UIDToString(objectUID); |
| std::string orderByClause (" order by grantor_id, grantee_id, column_number "); |
| |
| ColumnPrivsMDTable columnPrivsTable(columnTableName_,pDiags_); |
| PrivStatus privStatus = |
| columnPrivsTable.selectWhere(whereClause, orderByClause, columnRowList); |
| |
| std::string traceMsg ("getting column privileges, number privileges is "); |
| traceMsg += to_string((long long int)columnRowList.size()); |
| log (__FILE__, traceMsg, -1); |
| for (size_t i = 0; i < columnRowList.size(); i++) |
| { |
| ColumnPrivsMDRow privRow = static_cast<ColumnPrivsMDRow &> (*columnRowList[i]); |
| privRow.describeRow(traceMsg); |
| log (__FILE__, traceMsg, i); |
| } |
| |
| return privStatus; |
| } |
| |
| // **************************************************************************** |
| // method: generateObjectRowList |
| // |
| // generate the list of privileges granted to the object and |
| // store in objectRowList_ class member |
| // |
| // Returns: |
| // STATUS_GOOD - list of rows was generated |
| // STATUS_NOTFOUND - in most cases, there should be at least one row in the |
| // OBJECT_PRIVILEGES table. But there is at least one case |
| // where this is not true - trying to get privilege info |
| // for indexes when using the table (index_table) syntax. |
| // STATUS_ERROR - the diags area is populated with any errors |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::generateObjectRowList() |
| { |
| // If objectRowList_ already allocated, just return |
| if (objectRowList_.size() > 0) |
| return STATUS_GOOD; |
| PrivStatus privStatus = getObjectRowList(objectUID_, objectRowList_); |
| if (privStatus == STATUS_ERROR) |
| return privStatus; |
| return STATUS_GOOD; |
| } |
| |
| // **************************************************************************** |
| // method: getObjectRowList |
| // |
| // generate the list of privileges granted to the passed in objectUID and |
| // returns in the objectRowList parameter |
| // |
| // The list is ordered by grantor/grantee |
| // |
| // Returns: |
| // STATUS_GOOD - list of rows was generated |
| // STATUS_NOTFOUND - in most cases, there should be at least one row in the |
| // OBJECT_PRIVILEGES table. But there is at least one case |
| // where this is not true - trying to get privilege info |
| // for indexes when using the table (index_table) syntax. |
| // STATUS_ERROR - the diags area is populated with any errors |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::getObjectRowList( |
| const int64_t objectUID, |
| std::vector<PrivMgrMDRow *> &objectRowList) |
| { |
| std::string whereClause ("where object_uid = "); |
| whereClause += UIDToString(objectUID); |
| std::string orderByClause(" order by grantor_id, grantee_id "); |
| |
| ObjectPrivsMDTable objectPrivsTable(objectTableName_,pDiags_); |
| PrivStatus privStatus = |
| objectPrivsTable.selectWhere(whereClause, orderByClause, objectRowList); |
| if (privStatus == STATUS_ERROR) |
| return privStatus; |
| |
| std::string traceMsg ("getting object privileges, number privleges is "); |
| traceMsg += to_string((long long int)objectRowList.size()); |
| log (__FILE__, traceMsg, -1); |
| for (size_t i = 0; i < objectRowList.size(); i++) |
| { |
| ObjectPrivsMDRow privRow = static_cast<ObjectPrivsMDRow &> (*objectRowList[i]); |
| privRow.describeRow(traceMsg); |
| log (__FILE__, traceMsg, i); |
| } |
| return STATUS_GOOD; |
| } |
| |
| |
| // **************************************************************************** |
| // method: getAffectedObjects |
| // |
| // This method adds the current object to the listOfAffectedObjects and then |
| // looks for dependent objects such as constraints and views that will be |
| // affected by the privilege change. |
| // |
| // Params: |
| // objectUsage - the affected object |
| // command - GRANT or REVOKE RESTRICT or REVOKE CASCADE |
| // listOfAffectedObjects - returns the list of affected objects |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::getAffectedObjects( |
| const ObjectUsage &objectUsage, |
| const PrivCommand command, |
| std::vector<ObjectUsage *> &listOfAffectedObjects) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| std::string traceMsg; |
| |
| // found an object whose privileges need to be updated |
| ObjectUsage *pUsage = new (ObjectUsage); |
| pUsage->objectUID = objectUsage.objectUID; |
| pUsage->granteeID = objectUsage.granteeID; |
| pUsage->grantorIsSystem = objectUsage.grantorIsSystem; |
| pUsage->objectName = objectUsage.objectName; |
| pUsage->objectType = objectUsage.objectType; |
| pUsage->originalPrivs = objectUsage.originalPrivs; |
| pUsage->updatedPrivs = objectUsage.updatedPrivs; |
| pUsage->copyColumnReferences(objectUsage.columnReferences); |
| |
| listOfAffectedObjects.push_back(pUsage); |
| |
| |
| // Find list of affected constraints |
| if (isRevokeCommand(command)) |
| { |
| // TBD optimization: if no "references" privilege has been revoked, skip |
| retcode = dealWithConstraints (objectUsage, listOfAffectedObjects); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // TBD optimization: if no "execute" privilege has been revoked, skip |
| retcode = dealWithUdrs (objectUsage, listOfAffectedObjects); |
| if (retcode != STATUS_GOOD && retcode != STATUS_WARNING) |
| return retcode; |
| |
| } |
| |
| // Find list of affected views |
| retcode = dealWithViews (objectUsage, command, grantorID_, listOfAffectedObjects); |
| if (retcode != STATUS_GOOD && retcode != STATUS_WARNING) |
| return retcode; |
| |
| return STATUS_GOOD; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: getGrantedPrivs |
| // |
| // This method searches the list of object privs to get information for the |
| // object, grantor, and grantee. |
| // |
| // input: granteeID |
| // output: a row from the object_privileges table describing privilege details |
| // |
| // Returns: PrivStatus |
| // |
| // STATUS_GOOD: row was found (and returned) |
| // STATUS_NOTFOUND: no privileges have been granted |
| // ---------------------------------------------------------------------------- |
| PrivStatus PrivMgrPrivileges::getGrantedPrivs( |
| const int32_t granteeID, |
| PrivMgrMDRow &rowOut) |
| { |
| ObjectPrivsMDRow & row = static_cast<ObjectPrivsMDRow &>(rowOut); |
| |
| for (size_t i = 0; i < objectRowList_.size(); i++) |
| { |
| ObjectPrivsMDRow privRow = static_cast<ObjectPrivsMDRow &> (*objectRowList_[i]); |
| if (privRow.grantorID_ == grantorID_ && privRow.granteeID_ == granteeID) |
| { |
| row = privRow; |
| return STATUS_GOOD; |
| } |
| } |
| |
| return STATUS_NOTFOUND; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: getGranteesForViewUsage |
| // |
| // returns the list of grantees that have been granted privileges by the view |
| // owner |
| // |
| // input: viewUsage |
| // output: a unique list of grantees |
| // |
| // Returns: PrivStatus |
| // |
| // STATUS_GOOD: list was generated |
| // STATUS_ERROR: unexpected error occurred |
| // ---------------------------------------------------------------------------- |
| PrivStatus PrivMgrPrivileges::getGranteesForViewUsage ( |
| const ViewUsage &viewUsage, |
| std::set<int32_t> &granteeList) |
| { |
| PrivStatus privStatus = STATUS_GOOD; |
| |
| std::string whereClause ("where object_uid = "); |
| whereClause += UIDToString(viewUsage.viewUID); |
| whereClause += " and grantor_id <> -2 "; |
| std::string orderByClause("order by grantee_id"); |
| std::vector<PrivMgrMDRow *> rowList; |
| |
| // get list of grantees from object_privileges |
| ObjectPrivsMDTable objectPrivsTable(objectTableName_,pDiags_); |
| privStatus = objectPrivsTable.selectWhere(whereClause,orderByClause,rowList); |
| if (privStatus == STATUS_ERROR) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| |
| for (size_t i = 0; i < rowList.size(); i++) |
| { |
| ObjectPrivsMDRow ¤tRow = static_cast<ObjectPrivsMDRow &> (*rowList[i]); |
| granteeList.insert(currentRow.granteeID_); |
| } |
| deleteRowList(rowList); |
| |
| // get list of grantees for column_privileges |
| ColumnPrivsMDTable columnPrivsTable(columnTableName_,pDiags_); |
| privStatus = columnPrivsTable.selectWhere(whereClause, orderByClause, rowList); |
| if (privStatus == STATUS_ERROR) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| |
| for (size_t i = 0; i < rowList.size(); i++) |
| { |
| ColumnPrivsMDRow ¤tRow = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| granteeList.insert(currentRow.granteeID_); |
| } |
| deleteRowList(rowList); |
| return STATUS_GOOD; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: getGrantorDetailsForObject |
| // |
| // returns the effective grantor ID and grantor name for grant and revoke |
| // object statements |
| // |
| // Input: |
| // isGrantedBySpecified - true if grant request included a GRANTED BY clause |
| // grantedByName - name specified in GRANTED BY clause |
| // objectOwner - owner of object that is the subject for the grant or revoke |
| // |
| // Output: |
| // effectiveGrantorID - the ID to use for grant and revoke |
| // effectiveGrantorName - the name to use for grant and revoke |
| // |
| // returns PrivStatus with the results of the operation. The diags area |
| // contains error details. |
| // ---------------------------------------------------------------------------- |
| PrivStatus PrivMgrPrivileges::getGrantorDetailsForObject( |
| const bool isGrantedBySpecified, |
| const std::string grantedByName, |
| const int_32 objectOwner, |
| int_32 &effectiveGrantorID, |
| std::string &effectiveGrantorName) |
| |
| { |
| |
| int_32 currentUser = ComUser::getCurrentUser(); |
| short retcode = 0; |
| |
| if (!isGrantedBySpecified) |
| { |
| // If the user is DB__ROOT, a grant or revoke operation is implicitly on |
| // behalf of the object owner. Likewise, if a user has been granted the |
| // MANAGE_PRIVILEGES component-level privilege they can grant on |
| // behalf of the owner implicitly. Otherwise, the grantor is the user. |
| if (!ComUser::isRootUserID()) |
| { |
| PrivMgrComponentPrivileges componentPrivileges(metadataLocation_,pDiags_); |
| |
| if (!componentPrivileges.hasSQLPriv(currentUser,SQLOperation::MANAGE_PRIVILEGES, |
| true)) |
| { |
| effectiveGrantorName = ComUser::getCurrentUsername(); |
| effectiveGrantorID = currentUser; |
| return STATUS_GOOD; |
| } |
| } |
| // User is DB__ROOT. Get the effective grantor name. |
| char authName[MAX_USERNAME_LEN+1]; |
| Int32 actualLen = 0; |
| retcode = ComUser::getAuthNameFromAuthID(objectOwner,authName, |
| MAX_USERNAME_LEN+1,actualLen); |
| if (retcode != FEOK) |
| { |
| *pDiags_ << DgSqlCode(-20235) |
| << DgInt0(retcode) |
| << DgInt1(objectOwner); |
| return STATUS_ERROR; |
| } |
| effectiveGrantorID = objectOwner; |
| effectiveGrantorName = authName; |
| return STATUS_GOOD; |
| } |
| |
| // GRANTED BY was specified, first see if authorization name is valid. Then |
| // determine if user has authority to use the clause. |
| |
| // Get the grantor ID from the grantorName |
| retcode = ComUser::getAuthIDFromAuthName(grantedByName.c_str(),effectiveGrantorID); |
| |
| if (retcode == FENOTFOUND) |
| { |
| *pDiags_ << DgSqlCode(-CAT_AUTHID_DOES_NOT_EXIST_ERROR) |
| << DgString0(grantedByName.c_str()); |
| return STATUS_ERROR; |
| } |
| |
| if (retcode != FEOK) |
| { |
| *pDiags_ << DgSqlCode(-20235) |
| << DgInt0(retcode) |
| << DgInt1(objectOwner); |
| return STATUS_ERROR; |
| } |
| effectiveGrantorName = grantedByName; |
| |
| // Name exists, does user have authority? |
| // |
| // GRANTED BY is allowed if any of the following are true: |
| // |
| // 1) The user is DB__ROOT. |
| // 2) The user is owner of the object. |
| // 3) The user has been granted the MANAGE_PRIVILEGES component-level privilege. |
| // 4) The grantor is a role and the user has been granted the role. |
| |
| if (ComUser::isRootUserID() || currentUser == objectOwner) |
| return STATUS_GOOD; |
| |
| PrivMgrComponentPrivileges componentPrivileges(metadataLocation_,pDiags_); |
| |
| if (componentPrivileges.hasSQLPriv(currentUser,SQLOperation::MANAGE_PRIVILEGES, |
| true)) |
| return STATUS_GOOD; |
| |
| // If the grantor is not a role, user does not have authority. |
| if (!isRoleID(effectiveGrantorID)) |
| { |
| *pDiags_ << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return STATUS_ERROR; |
| } |
| |
| // Role specified in BY clause must be granted to the current user for user |
| // to have authority. |
| PrivMgrRoles roles(trafMetadataLocation_,metadataLocation_,pDiags_); |
| |
| if (roles.hasRole(currentUser,effectiveGrantorID)) |
| return STATUS_GOOD; |
| |
| *pDiags_ << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return STATUS_ERROR; |
| |
| } |
| |
| // ***************************************************************************** |
| // * Method: revokeColumnPriv |
| // * |
| // * Adds or updates a row in the COLUMN_PRIVILEGES table. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> is the unique identifier for the grantee |
| // * <granteeName> is the name of the grantee (upper cased) |
| // * <grantorName> is the name of the grantor (upper cased) |
| // * <colPrivsArray> is the list of columns and privileges to grant |
| // * <isWGOSpecified> is true then also allow the grantee to grant the set |
| // * of privileges to other grantees |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were revoked |
| // * *: Unable to revoke privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::revokeColumnPriv( |
| const ComObjectType objectType, |
| const int32_t granteeID, |
| const std::string & granteeName, |
| const std::string & grantorName, |
| const PrivMgrDesc & privsToRevoke, |
| const bool isWGOSpecified) |
| { |
| |
| PrivStatus privStatus = STATUS_GOOD; |
| |
| log (__FILE__, "checking column privileges", -1); |
| |
| NAList<PrivMgrCoreDesc> colPrivsToRevoke = privsToRevoke.getColumnPrivs(); |
| |
| // Get existing column grants from grantor to the specified grantee. |
| NAList<PrivMgrCoreDesc> grantedColPrivs(STMTHEAP); |
| getColRowsForGranteeGrantor(columnRowList_, |
| granteeID,grantorID_, |
| grantedColPrivs); |
| |
| // set up the object usage |
| ObjectUsage objectUsage; |
| objectUsage.objectUID = objectUID_; |
| objectUsage.granteeID = granteeID; |
| objectUsage.objectName = objectName_; |
| objectUsage.objectType = objectType; |
| |
| // Create list of ColumnReferences |
| objectUsage.columnReferences = new std::vector<ColumnReference *>; |
| for (size_t i = 0; i < colPrivsToRevoke.entries(); i++) |
| { |
| PrivMgrCoreDesc &colPrivToRevoke = colPrivsToRevoke[i]; |
| PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, colPrivToRevoke.getColumnOrdinal()); |
| if (grantedColPriv) |
| { |
| if (colPrivToRevoke.anyNotSet(*grantedColPriv)) |
| { |
| // sanity check -> verify that privileges to revoke actually are set |
| // in the granted list |
| for (size_t p = FIRST_DML_COL_PRIV; p <= LAST_DML_COL_PRIV; p++ ) |
| { |
| PrivType type = (PrivType)p; |
| |
| // If trying to revoke a privilege that is not granted or |
| // if trying to revoke grant option that is not granted, report it |
| //if ((colPrivToRevoke.getPriv(type) && !grantedColPriv->getPriv(type)) || |
| // (!colPrivToRevoke.getPriv(type) && colPrivToRevoke.getWgo(type) && !grantedColPriv->getWgo(type))) |
| bool printWarning = false; |
| bool printWgo = false; |
| if (colPrivToRevoke.getPriv(type)) |
| { |
| if ( !grantedColPriv->getPriv(type)) |
| printWarning = true; |
| } |
| else |
| { |
| if (colPrivToRevoke.getWgo(type) && !grantedColPriv->getWgo(type)) |
| { |
| printWarning = true; |
| printWgo = true; |
| } |
| } |
| |
| if (printWarning) |
| { |
| char buf[1000]; |
| sprintf(buf, "%s %s (columm number %d) on %s", |
| PrivMgrUserPrivs::convertPrivTypeToLiteral(type).c_str(), |
| (colPrivToRevoke.getWgo(type)) ? "WITH GRANT OPTION" : "", |
| colPrivToRevoke.getColumnOrdinal(), objectName_.c_str()); |
| *pDiags_ << DgSqlCode(CAT_GRANT_NOT_FOUND) |
| << DgString0(buf) |
| << DgString1(grantorName.c_str()) |
| << DgString2(granteeName.c_str()); |
| } |
| } |
| } |
| ColumnReference *adjustedCol = new ColumnReference; |
| adjustedCol->columnOrdinal = colPrivToRevoke.getColumnOrdinal(); |
| adjustedCol->originalPrivs = *grantedColPriv; |
| PrivMgrCoreDesc adjustedPrivs = *grantedColPriv; |
| adjustedPrivs.AndNot(colPrivToRevoke); |
| adjustedCol->updatedPrivs = adjustedPrivs; |
| objectUsage.columnReferences->push_back(adjustedCol); |
| } |
| else |
| { |
| // report errors for any missing grants |
| for (size_t p = FIRST_DML_COL_PRIV; p <= LAST_DML_COL_PRIV; p++ ) |
| { |
| // If trying to revoke a privilege that is not granted or |
| // if trying to revoke grant option that is not granted, report it |
| if (colPrivToRevoke.getPriv((PrivType)p) || colPrivToRevoke.getWgo((PrivType)p)) |
| { |
| char buf[1000]; |
| sprintf(buf, "%s %s (columm number %d) on %s", |
| PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p).c_str(), |
| (colPrivToRevoke.getWgo((PrivType)p)) ? "WITH GRANT OPTION" : "", |
| colPrivToRevoke.getColumnOrdinal(), objectName_.c_str()); |
| *pDiags_ << DgSqlCode(CAT_GRANT_NOT_FOUND) |
| << DgString0(buf) |
| << DgString1(grantorName.c_str()) |
| << DgString2(granteeName.c_str()); |
| } |
| } |
| } |
| } |
| |
| if (objectUsage.columnReferences->size() == 0) |
| return STATUS_GOOD; |
| |
| // Get privileges on the object for grantor/grantee |
| ObjectPrivsMDRow objRow; |
| privStatus = getGrantedPrivs(granteeID, objRow); |
| |
| // getGrantedPrivs returns STATUS_GOOD or STATUS_NOTFOUND |
| // if STATUS_NOTFOUND, bitmaps are empty (as initialized above) |
| // if STATUS_GOOD, set current bitmaps |
| if (privStatus == STATUS_GOOD) |
| { |
| PrivMgrCoreDesc coreDesc(objRow.privsBitmap_, objRow.grantableBitmap_); |
| objectUsage.originalPrivs.setTablePrivs(coreDesc); |
| objectUsage.updatedPrivs.setTablePrivs(coreDesc); |
| } |
| |
| // check to see if can revoke if there are referenced items when |
| // revoke cascade is supported, this returns the list of referenced |
| // items that need to change. |
| if ( updateDependentObjects(objectUsage, PrivCommand::REVOKE_COLUMN_RESTRICT) == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // At this point we have an array of privsToRevoke with column ordinal and |
| // priv bitmap. |
| // |
| // Three revoke column cases: |
| // |
| // Spec Spec Priv bitmap compare |
| // GOF Priv to granted priv bitmap Action |
| // T 1 NA Removing WGO only. Update operation. |
| // Reset privType bit in grantable bitmap, |
| // copy priv bitmap from granted privs. |
| // |
| // F 1 Equal Revoking all privs on this column, plus |
| // WGO. Delete operation. |
| // |
| // F 1 Not equal Revoking some privs on this column plus |
| // WGO for the revoked privs. Reset bits in |
| // both bitmaps. Update operation. |
| |
| |
| if (checkColumnRevokeRestrict (granteeID, colPrivsToRevoke, columnRowList_)) |
| return STATUS_ERROR; |
| |
| bool rowRevoked = false; |
| PrivColumnBitmap revokedPrivs; |
| |
| std::string whereBase(" WHERE object_uid = "); |
| |
| whereBase += UIDToString(objectUID_); |
| whereBase += " AND grantor_id = "; |
| whereBase += authIDToString(grantorID_); |
| whereBase += " AND grantee_id = "; |
| whereBase += authIDToString(granteeID); |
| whereBase += " AND column_number = "; |
| |
| ColumnPrivsMDTable columnPrivsTable(columnTableName_,pDiags_); |
| |
| for (size_t i = 0; i < colPrivsToRevoke.entries(); i++) |
| { |
| PrivMgrCoreDesc &colPrivToRevoke = colPrivsToRevoke[i]; |
| bool updateRow = false; |
| bool deleteRow = false; |
| |
| // Look for any existing granted privileges on the column for which |
| // privileges are to be granted. |
| PrivMgrCoreDesc *grantedColPriv = findColumnEntry(grantedColPrivs, colPrivToRevoke.getColumnOrdinal()); |
| if (grantedColPriv) |
| { |
| // Found row with grant for this column. |
| |
| // Verify privilege(s) being revoked was/were granted. If not, continue |
| if (!isWGOSpecified && |
| ((colPrivToRevoke.getPrivBitmap() & grantedColPriv->getPrivBitmap()) == 0)) |
| continue; |
| |
| // If all privileges are revoked, delete corresponding row |
| if (!isWGOSpecified && |
| (colPrivToRevoke.getPrivBitmap() == grantedColPriv->getPrivBitmap())) |
| deleteRow = true; |
| else |
| updateRow = true; |
| |
| // generate the final bitmaps to store in metadata |
| // removing any privileges that already have been revoked |
| PrivMgrCoreDesc adjustedPrivs = *grantedColPriv; |
| adjustedPrivs.AndNot(colPrivToRevoke); |
| |
| // If only removing WGO, then the privsBitmap does not change |
| // Not sure if this is needed ?? |
| if (isWGOSpecified) |
| adjustedPrivs.setPrivBitmap(grantedColPriv->getPrivBitmap()); |
| |
| // set adjusted privileges |
| colPrivToRevoke.setPrivBitmap(adjustedPrivs.getPrivBitmap()); |
| colPrivToRevoke.setWgoBitmap(adjustedPrivs.getWgoBitmap()); |
| |
| // Using the list of privs to revoke, change so adjustedPrivs contains |
| // Some privileges may have been requested to revoke that aren't |
| // currently granted - flip adjusted bits to final list of privs |
| revokedPrivs |= adjustedPrivs.getPrivBitmap(); |
| } |
| else |
| { |
| // The row should exist in "grantedColPrivs" |
| PRIVMGR_INTERNAL_ERROR("Column privilege not found to revoke"); |
| return STATUS_ERROR; |
| } |
| |
| |
| if (deleteRow) |
| { |
| std::string whereClause(whereBase + authIDToString(colPrivToRevoke.getColumnOrdinal())); |
| |
| privStatus = columnPrivsTable.deleteWhere(whereClause); |
| if (privStatus == STATUS_ERROR) |
| return privStatus; |
| |
| rowRevoked = true; |
| continue; |
| } |
| |
| if (!updateRow) |
| { |
| PRIVMGR_INTERNAL_ERROR("Column privilege not found to revoke"); |
| return STATUS_ERROR; |
| } |
| |
| ColumnPrivsMDRow row; |
| |
| row.objectUID_ = objectUID_; |
| row.objectName_ = objectName_; |
| row.granteeID_ = granteeID; |
| row.granteeName_ = granteeName; |
| row.grantorID_ = grantorID_; |
| row.grantorName_ = grantorName; |
| row.privsBitmap_ = colPrivToRevoke.getPrivBitmap(); |
| row.grantableBitmap_ = colPrivToRevoke.getWgoBitmap(); |
| row.columnOrdinal_ = colPrivToRevoke.getColumnOrdinal(); |
| |
| privStatus = columnPrivsTable.updateColumnRow(row,whereBase); |
| |
| if (privStatus == STATUS_ERROR) |
| return privStatus; |
| |
| rowRevoked = true; |
| } |
| |
| // if (!rowRevoked) |
| // Warning |
| |
| return STATUS_GOOD; |
| |
| } |
| //************* End of PrivMgrPrivileges::revokeColumnPriv *************** |
| |
| |
| // ***************************************************************************** |
| // * Method: revokeObjectPriv |
| // * |
| // * Deletes or updates a row in the OBJECT_PRIVILEGES table. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> is the unique identifier for the grantee |
| // * <privsList> is the list of privileges to revoke |
| // * <isAllSpecified> if true then all privileges valid for the object |
| // * type will be revoked |
| // * <isGOFSpecified> if true then remove the ability for the grantee |
| // * to revoke the set of privileges to other grantees |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were granted |
| // * *: Unable to grant privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::revokeObjectPriv (const ComObjectType objectType, |
| const int32_t granteeID, |
| const std::string & granteeName, |
| const std::string & grantorName, |
| const std::vector<PrivType> &privsList, |
| const std::vector<ColPrivSpec> & colPrivsArray, |
| const bool isAllSpecified, |
| const bool isGOFSpecified) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| std::string traceMsg; |
| log (__FILE__, "****** REVOKE operation begins ******", -1); |
| |
| PrivMgrDesc privsToRevoke(granteeID); |
| PrivMgrDesc privsOfTheGrantor(grantorID_); |
| std::vector<int_32> roleIDs; |
| retcode = initGrantRevoke(objectType, granteeID, grantorName, |
| privsList, colPrivsArray, |
| isAllSpecified, isGOFSpecified, false, |
| privsToRevoke, privsOfTheGrantor, roleIDs); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| // Remove any privsToRevoke which are not held grantable by the Grantor. |
| // If limitToGrantable returns true, some privs are not revokable. |
| bool warnNotAll = false; |
| PrivMgrDesc origPrivsToRevoke = privsToRevoke; |
| if ( privsToRevoke.limitToGrantable( privsOfTheGrantor ) ) |
| { |
| // This is ok. Can specify ALL without having all privileges set. |
| if (!isAllSpecified ) |
| warnNotAll = true; // Not all the specified privs can be revoked |
| } |
| |
| // If nothing left to revoke, we are done. |
| if ( privsToRevoke.isNull() ) |
| { |
| std::string rolesWithPrivs; |
| if (getRolesToCheck(grantorID_, roleIDs, objectType, rolesWithPrivs)== STATUS_GOOD) |
| { |
| if (rolesWithPrivs.size() > 0) |
| { |
| *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED) |
| << DgString0 (grantorName.c_str()) |
| << DgString1 (rolesWithPrivs.c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| |
| *pDiags_ << DgSqlCode (-CAT_PRIVILEGE_NOT_GRANTED) |
| << DgString0 (grantorName.c_str()); |
| return STATUS_ERROR; |
| } |
| |
| // revoke any column level privileges |
| if ( !privsToRevoke.isColumnLevelNull() ) |
| { |
| retcode = revokeColumnPriv(objectType,granteeID,granteeName, |
| grantorName,privsToRevoke,isGOFSpecified); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| } |
| |
| // If only column-level privileges were specified, no problem. |
| if (privsToRevoke.getTablePrivs().isNull()) |
| { |
| // Send a message to the Trafodion RMS process about the revoke operation. |
| // RMS will contact all master executors and ask that cached privilege |
| // information be re-calculated |
| retcode = sendSecurityKeysToRMS(granteeID, privsToRevoke); |
| |
| // report any privs not granted |
| if (warnNotAll) |
| reportPrivWarnings(origPrivsToRevoke, |
| privsToRevoke, |
| CAT_NOT_ALL_PRIVILEGES_REVOKED); |
| log (__FILE__, "****** REVOKE operation succeeded ******", -1); |
| return STATUS_GOOD; |
| } |
| |
| // See if grantor has previously granted privileges to the grantee |
| ObjectPrivsMDRow row; |
| retcode = getGrantedPrivs(granteeID, row); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| if (retcode == STATUS_NOTFOUND) |
| { |
| // Set up parameters for the error message: privileges, grantor, & grantee |
| // privilege list |
| std::string privListStr; |
| for (size_t i = 0; i < privsList.size(); i++) |
| privListStr += PrivMgrUserPrivs::convertPrivTypeToLiteral(privsList[i]) + ", "; |
| |
| privListStr.erase(privListStr.length()-2, privListStr.length()); |
| if (isGOFSpecified) |
| privListStr += " WITH GRANT OPTION"; |
| |
| *pDiags_ << DgSqlCode (CAT_GRANT_NOT_FOUND) |
| << DgString0 (privListStr.c_str()) |
| << DgString1 (grantorName.c_str()) |
| <<DgString2 (granteeName.c_str()); |
| |
| return STATUS_WARNING; |
| } |
| |
| // if privileges exist, set currentPrivs to existing list |
| // save a copy of the original privs |
| PrivMgrCoreDesc currentPrivs; // creates an empty descriptor |
| PrivMgrCoreDesc tempPrivs(row.privsBitmap_, row.grantableBitmap_); |
| currentPrivs = tempPrivs; |
| PrivMgrCoreDesc savedOriginalPrivs = currentPrivs; |
| |
| // TDB: if user privs have already been revoked, just return |
| |
| // save the privsToRevoke for query invalidation(QI) later |
| PrivMgrDesc listOfRevokedPrivileges = privsToRevoke; |
| |
| // merge requested changes with existing row |
| // First flip privsToRevoke to turn off the privilege and then union |
| // the current privs with the privsToRevoke to generate the final bitmaps |
| privsToRevoke.complement(); |
| privsToRevoke.intersectionOfPrivs(currentPrivs); |
| |
| row.privsBitmap_ = privsToRevoke.getTablePrivs().getPrivBitmap(); |
| row.grantableBitmap_ = privsToRevoke.getTablePrivs().getWgoBitmap(); |
| |
| // See if there are any dependencies that need to be removed before |
| // removing the privilege |
| ObjectUsage objectUsage; |
| objectUsage.objectUID = objectUID_; |
| objectUsage.granteeID = granteeID; |
| objectUsage.grantorIsSystem = false; |
| objectUsage.objectName = row.objectName_; |
| objectUsage.objectType = row.objectType_; |
| objectUsage.columnReferences = NULL; |
| |
| PrivMgrDesc originalPrivs (row.granteeID_); |
| originalPrivs.setTablePrivs(savedOriginalPrivs); |
| objectUsage.originalPrivs = originalPrivs; |
| objectUsage.updatedPrivs = privsToRevoke; |
| |
| if (updateDependentObjects(objectUsage, PrivCommand::REVOKE_OBJECT_RESTRICT) == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // Go rebuild the privilege tree to see if it is broken |
| // If it is broken, return an error |
| if (checkRevokeRestrict (row, objectRowList_)) |
| return STATUS_ERROR; |
| |
| ObjectPrivsMDTable objectPrivsTable (objectTableName_, pDiags_); |
| if (privsToRevoke.getTablePrivs().isNull()) |
| { |
| row.describeRow(traceMsg); |
| traceMsg.insert(0, "deleting privilege row "); |
| log (__FILE__, traceMsg, -1); |
| |
| // delete the row |
| retcode = objectPrivsTable.deleteRow(row); |
| } |
| else |
| { |
| row.describeRow(traceMsg); |
| traceMsg.insert(0, "updating existing privilege row "); |
| log (__FILE__, traceMsg, -1); |
| |
| // update the row |
| retcode = objectPrivsTable.updateRow(row); |
| } |
| |
| // Send a message to the Trafodion RMS process about the revoke operation. |
| // RMS will contact all master executors and ask that cached privilege |
| // information be re-calculated |
| retcode = sendSecurityKeysToRMS(granteeID, listOfRevokedPrivileges); |
| |
| // SQL Ansi states that privileges that can be revoked should be done so |
| // even if some requested privilege are not revokable. |
| // TDB: report which privileges were not revoked |
| if (warnNotAll) |
| reportPrivWarnings(origPrivsToRevoke, |
| privsToRevoke, |
| CAT_NOT_ALL_PRIVILEGES_REVOKED); |
| |
| log (__FILE__, "****** REVOKE operation succeeded ******", -1); |
| |
| return retcode; |
| } |
| |
| // ***************************************************************************** |
| // * Method: revokeObjectPriv |
| // * |
| // * Deletes rows in the OBJECT_PRIVILEGES table associated with the object |
| // * This code assumes that all dependent and referencing objects such as |
| // * views have been (or will be) dropped. No extra checks are performed. |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were revoked |
| // * *: Unable to revoke privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::revokeObjectPriv () |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| if (objectUID_ == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for revoke command"); |
| return STATUS_ERROR; |
| } |
| |
| char buf[100]; |
| sprintf(buf, "where object_uid = %ld", objectUID_); |
| std::string whereClause = buf; |
| |
| // delete all the rows for this object |
| ObjectPrivsMDTable objectPrivsTable (objectTableName_, pDiags_); |
| retcode = objectPrivsTable.deleteWhere(whereClause); |
| ColumnPrivsMDTable columnPrivsTable (objectTableName_, pDiags_); |
| retcode = columnPrivsTable.deleteWhere(whereClause); |
| |
| return retcode; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: checkRevokeRestrict |
| // |
| // This method starts at the beginning of the privilege tree and rebuilds |
| // it from top to bottom. If the revoke causes part of the tree to be |
| // unaccessible (a broken branch), it returns true; otherwise, revoke can |
| // proceed - returns false. |
| // |
| // Params: |
| // rowIn - the row containing proposed changes from the requested |
| // revoke statement. |
| // rowList - a list of all the rows associated with the object |
| // |
| // true - unable to perform revoke because of dependencies |
| // false - able to perform revoke.privileges |
| // |
| // The diags area is set up with where the tree was broken |
| // ---------------------------------------------------------------------------- |
| bool PrivMgrPrivileges::checkRevokeRestrict ( |
| PrivMgrMDRow &rowIn, |
| std::vector <PrivMgrMDRow *> &rowList ) |
| { |
| // Search the list of privileges associated with the object and replace |
| // the bitmaps of the current row with the bitmaps of the row sent in (rowIn). |
| // At the same time, clear visited_ and set current_ to row values |
| ObjectPrivsMDRow updatedRow = static_cast<ObjectPrivsMDRow &>(rowIn); |
| |
| std::string traceMsg; |
| log (__FILE__, "checking grant tree for broken branches", -1); |
| |
| for (int32_t i = 0; i < rowList.size(); i++) |
| { |
| // if rowIn matches this row, then update the bitmaps to use the |
| // updated bitmaps |
| ObjectPrivsMDRow ¤tRow = static_cast<ObjectPrivsMDRow &> (*rowList[i]); |
| |
| if (updatedRow.granteeID_ == currentRow.granteeID_ && |
| updatedRow.grantorID_ == currentRow.grantorID_ ) |
| { |
| currentRow.privsBitmap_ = updatedRow.privsBitmap_; |
| currentRow.grantableBitmap_ = updatedRow.grantableBitmap_; |
| } |
| // reset visited_ and current_ PrivMgrCoreDesc |
| currentRow.clearVisited(); |
| currentRow.setToOriginal(); |
| } |
| |
| // Reconstruct the privilege tree |
| // Each privilege tree starts with the root - system grantor (-2) |
| for ( size_t i = 0; i < NBR_OF_PRIVS; i++ ) |
| { |
| PrivType pType = PrivType(i); |
| |
| int32_t systemGrantor = SYSTEM_USER; |
| scanObjectBranch (pType, systemGrantor, rowList); |
| // TDB - add a scan for column privileges |
| } |
| |
| // If a branch of the tree was not visited, then we have a broken |
| // tree. Therefore, revoke restrict will leave abandoned privileges |
| // in the case, return true. |
| bool notVisited = false; |
| for (size_t i = 0; i < rowList.size(); i++) |
| { |
| ObjectPrivsMDRow ¤tRow = static_cast<ObjectPrivsMDRow &> (*rowList[i]); |
| currentRow.describeRow(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| if (currentRow.anyNotVisited()) |
| { |
| *pDiags_ << DgSqlCode(-CAT_DEPENDENT_PRIV_EXISTS) |
| << DgString0(currentRow.grantorName_.c_str()) |
| << DgString1(currentRow.granteeName_.c_str()); |
| |
| log (__FILE__, "found a branch that is not accessible", -1); |
| notVisited = true; |
| break; |
| } |
| } |
| return notVisited; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: scanObjectBranch |
| // |
| // scans the privsList entries for match on Grantor, |
| // keeping track of which priv/wgo entries have been encountered |
| // by setting "visited" flag in the entry. |
| // |
| // For each entry discovered, set visited flag to indicate that |
| // priv and wgo were seen. For wgo, if the wgo visited flag has not |
| // already been set, call scanObjectBranch recursively with this grantee |
| // as grantor. (By observing the state of the wgo visited flag |
| // we avoid redundantly exploring the sub-tree rooted in a grantor |
| // which has already been discovered as having wgo from some other |
| // ancestor grantor.) |
| // |
| // This algorithm produces a depth-first scan of all nodes of the |
| // directed graph of privilege settings which can currently be reached |
| // by an uninterrupted chain of wgo values. |
| // |
| // The implementation is dependent on the fact that PrivsList |
| // entries are ordered by Grantor, Grantee, and within each of these |
| // by Primary uid value, type. Entries for system grantor (_SYSTEM) are the |
| // first entries in the list. |
| // |
| // ----------------------------------------------------------------------------- |
| void PrivMgrPrivileges::scanObjectBranch( const PrivType pType, // in |
| const int32_t& grantor, // in |
| const std::vector<PrivMgrMDRow *> & privsList ) // in |
| { |
| |
| // The PrivMgrMDRow <list> is maintained in order by |
| // Grantee within Grantor value - through an order by clause. |
| |
| // Skip over Grantors lower than the specified one. |
| size_t i = 0; |
| while ( i < privsList.size() ) |
| { |
| ObjectPrivsMDRow ¤tRow = static_cast<ObjectPrivsMDRow &> (*privsList[i]); |
| if (currentRow.grantorID_ < grantor) |
| i++; |
| else |
| break; |
| } |
| |
| // For matching Grantor, process each Grantee. |
| while ( i < privsList.size() ) |
| { |
| ObjectPrivsMDRow &privEntry = static_cast<ObjectPrivsMDRow &> (*privsList[i]); |
| if (privEntry.grantorID_ == grantor) |
| { |
| PrivMgrCoreDesc& current = privEntry.accessCurrent(); |
| if ( current.getPriv(pType) ) |
| { |
| // This grantee has priv. Set corresponding visited flag. |
| PrivMgrCoreDesc& visited = privEntry.accessVisited(); |
| visited.setPriv(pType, true); |
| |
| if ( current.getWgo(pType)) |
| { |
| // This grantee has wgo. |
| if ( visited.getWgo(pType) ) |
| { // Already processed this subtree. |
| } |
| else |
| { |
| visited.setWgo(pType, true); |
| |
| int32_t thisGrantee( privEntry.granteeID_ ); |
| if ( ComUser::isPublicUserID(thisGrantee) ) |
| scanPublic( pType, // Deal with PUBLIC grantee wgo. |
| privsList ); |
| else |
| { |
| int32_t granteeAsGrantor; |
| if (isRoleID(thisGrantee)) |
| { |
| std::vector<int32_t> roleIDs; |
| std::vector<int32_t> userIDs; |
| roleIDs.push_back(thisGrantee); |
| if (getUserIDsForRoleIDs(roleIDs,userIDs) == STATUS_ERROR) |
| return; |
| for (size_t j = 0; j < userIDs.size(); j++) |
| { |
| granteeAsGrantor = userIDs[j]; |
| scanObjectBranch( pType, // Scan for this grantee as grantor. |
| granteeAsGrantor, |
| privsList ); |
| } |
| } |
| granteeAsGrantor = thisGrantee; |
| scanObjectBranch( pType, // Scan for this grantee as grantor. |
| granteeAsGrantor, |
| privsList ); |
| } |
| } |
| } // end this grantee has wgo |
| } // end this grantee has this priv |
| |
| i++; // on to next privsList entry |
| } |
| else |
| break; |
| |
| } // end scan privsList over Grantees for this Grantor |
| } // end scanCurrent |
| |
| |
| /* ******************************************************************* |
| scanPublic -- a grant wgo to PUBLIC has been encountered for the |
| current privilege type, so *all* users are able to grant this privilege. |
| Scan the privsList for all grantees who have this priv from any grantor, |
| marking each such entry as visited. |
| |
| ****************************************************************** */ |
| |
| void PrivMgrPrivileges::scanPublic( const PrivType pType, // in |
| const std::vector<PrivMgrMDRow *>& privsList ) // in |
| { |
| // PUBLIC has a priv wgo. So *every* grant of this priv |
| // is allowed, by any Grantor. |
| |
| for ( size_t i = 0; i < privsList.size(); i++ ) |
| { |
| ObjectPrivsMDRow &privEntry = static_cast<ObjectPrivsMDRow &> (*privsList[i]); |
| const PrivMgrCoreDesc& current = privEntry.accessCurrent(); |
| if ( current.getPriv(pType) ) |
| { |
| // This grantee has priv. Set corresponding visited flag. |
| PrivMgrCoreDesc& visited = privEntry.accessVisited(); |
| visited.setPriv(pType, true); |
| |
| if ( current.getWgo(pType) ) |
| visited.setWgo(pType, true); |
| } |
| } // end scan privsList over all Grantees/Grantors |
| } // end scanPublic |
| |
| // ---------------------------------------------------------------------------- |
| // method: checkColumnRevokeRestrict |
| // |
| // This method starts at the beginning of the privilege tree and rebuilds |
| // it from top to bottom. If the revoke causes part of the tree to be |
| // unaccessible (a broken branch), it returns true; otherwise, revoke can |
| // proceed - returns false. |
| // |
| // Params: |
| // granteeID - the target AuthID |
| // colPrivsToRevoke - the list of column entries containing proposed |
| // changes from the requested revoke statement. |
| // rowList - a list of all the rows associated with the object |
| // |
| // true - unable to perform revoke because of dependencies |
| // false - able to perform revoke.privileges |
| // |
| // The diags area is set up with where the tree was broken |
| // ---------------------------------------------------------------------------- |
| bool PrivMgrPrivileges::checkColumnRevokeRestrict ( |
| int32_t granteeID, |
| const NAList<PrivMgrCoreDesc> &colPrivsToRevoke, |
| std::vector <PrivMgrMDRow *> &rowList ) |
| { |
| std::string traceMsg; |
| log (__FILE__, "checking column grant tree for broken branches", -1); |
| |
| // Clear visited_ bitmaps and set current_ bitmaps to current priv values |
| // Search the list of privileges associated with the object and turn off |
| // the bitmaps in current_ that are no longer available when the revoke |
| // completes - based on colPrivsToRevoke. |
| for (int32_t i = 0; i < rowList.size(); i++) |
| { |
| ColumnPrivsMDRow ¤tRow = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| currentRow.setCurrentToOriginal(); |
| currentRow.clearVisited(); |
| |
| // only look at rows for the current grantor and grantee |
| if (currentRow.grantorID_ == grantorID_ && |
| currentRow.granteeID_ == granteeID) |
| { |
| // Adjust rows that have had their privileges updated |
| for (int32_t j = 0; j < colPrivsToRevoke.entries(); j++) |
| { |
| PrivMgrCoreDesc updatedEntry = (PrivMgrCoreDesc)colPrivsToRevoke[j]; |
| |
| if (updatedEntry.getColumnOrdinal() == currentRow.columnOrdinal_) |
| { |
| PrivColumnBitmap newPrivBitmap = updatedEntry.getPrivBitmap() ^= currentRow.privsBitmap_; |
| PrivColumnBitmap temp = updatedEntry.getWgoBitmap().flip(); |
| PrivColumnBitmap newGrantableBitmap = temp &= currentRow.grantableBitmap_; |
| currentRow.current_.setPrivBitmap(newPrivBitmap); |
| currentRow.current_.setWgoBitmap(newGrantableBitmap); |
| traceMsg = "Adjusted current_ to reflect revoked privileges"; |
| traceMsg += ", grantor is "; |
| traceMsg += to_string((long long int)currentRow.grantorID_); |
| traceMsg += ", grantee is "; |
| traceMsg += to_string((long long int) currentRow.granteeID_); |
| log (__FILE__, traceMsg, -1); |
| } |
| } |
| } |
| } |
| |
| // Reconstruct the privilege tree based on the adjusted privileges |
| // starting with the object owner - get the object owner. |
| PrivMgrObjects objects(trafMetadataLocation_,pDiags_); |
| int32_t objectOwner = 0; |
| PrivStatus privStatus = objects.fetchObjectOwner(objectUID_,objectOwner); |
| if (privStatus == STATUS_ERROR) |
| { |
| PRIVMGR_INTERNAL_ERROR("Could not fetch object owner"); |
| return true; |
| } |
| |
| // Create the list of columns that have been changed, during |
| // reconstruction, only look at rows that have changes. |
| // std::set does not add entries if they already exist. |
| std::set<int32_t> listOfColumnOrdinals; |
| for ( size_t i = 0; i < colPrivsToRevoke.entries(); i++) |
| { |
| PrivMgrCoreDesc colPrivToRevoke = colPrivsToRevoke[i]; |
| listOfColumnOrdinals.insert(colPrivToRevoke.getColumnOrdinal()); |
| } |
| |
| // Reconstruct tree |
| for ( size_t i = 0; i < NBR_DML_COL_PRIVS; i++ ) |
| { |
| scanColumnBranch (PrivType(i), objectOwner, listOfColumnOrdinals, rowList); |
| } |
| |
| // If a branch of the tree was not visited, then we have a broken |
| // tree. Therefore, revoke restrict will leave abandoned privileges |
| // in the case, return true. |
| bool notVisited = false; |
| for (size_t i = 0; i < rowList.size(); i++) |
| { |
| ColumnPrivsMDRow ¤tRow = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| |
| // Only look at rows that have been changed |
| for (std::set<int32_t>::iterator it = listOfColumnOrdinals.begin(); |
| it!= listOfColumnOrdinals.end(); ++it) |
| { |
| if (*it == currentRow.columnOrdinal_) |
| { |
| currentRow.describeRow(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| if (currentRow.anyNotVisited()) |
| { |
| *pDiags_ << DgSqlCode(-CAT_DEPENDENT_PRIV_EXISTS) |
| << DgString0(currentRow.grantorName_.c_str()) |
| << DgString1(currentRow.granteeName_.c_str()); |
| |
| log (__FILE__, "found a branch that is not accessible", -1); |
| notVisited = true; |
| break; |
| } |
| } |
| } |
| } |
| return notVisited; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: scanColumnBranch |
| // |
| // scans the privsList entries for match on Grantor, |
| // keeping track of which priv/wgo entries have been encountered |
| // by setting "visited" flag in the entry. |
| // |
| // For each entry discovered, set visited flag to indicate that |
| // priv and wgo were seen. For wgo, if the wgo visited flag has not |
| // already been set, call scanObjectBranch recursively with this grantee |
| // as grantor. (By observing the state of the wgo visited flag |
| // we avoid redundantly exploring the sub-tree rooted in a grantor |
| // which has already been discovered as having wgo from some other |
| // ancestor grantor.) |
| // |
| // This algorithm produces a depth-first scan of all nodes of the |
| // directed graph of privilege settings which can currently be reached |
| // by an uninterrupted chain of wgo values. |
| // |
| // The implementation is dependent on the fact that rowList |
| // entries are ordered by Grantor, Grantee, columnOrdinal |
| // ----------------------------------------------------------------------------- |
| void PrivMgrPrivileges::scanColumnBranch( const PrivType pType, |
| const int32_t& grantor, |
| const std::set<int32_t> &listOfColumnOrdinals, |
| const std::vector<PrivMgrMDRow *> & rowList ) |
| { |
| |
| // The PrivMgrMDRow <list> is maintained in order by |
| // columnOrdinal within Grantee within Grantor - through an order by clause. |
| |
| // Skip over Grantors lower than the specified one. |
| size_t i = 0; |
| while ( i < rowList.size() ) |
| { |
| ColumnPrivsMDRow ¤tRow = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| if (currentRow.grantorID_ < grantor) |
| i++; |
| else |
| break; |
| } |
| |
| // For matching Grantor, process each Grantee. |
| while ( i < rowList.size() ) |
| { |
| ColumnPrivsMDRow ¤tRow = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| if (currentRow.grantorID_ == grantor) |
| { |
| // Just look at rows that have had privileges changed |
| // The listOfColumnOrdinals has this list |
| PrivMgrCoreDesc current = currentRow.current_; |
| std::set<int32_t>::iterator it; |
| it = std::find(listOfColumnOrdinals.begin(), listOfColumnOrdinals.end(), current.getColumnOrdinal()); |
| if (it != listOfColumnOrdinals.end()) |
| { |
| if ( current.getPrivBitmap().test(pType) ) |
| { |
| // This grantee has priv. Set corresponding visited flag. |
| currentRow.visited_.setPriv(pType, true); |
| |
| if ( current.getWgoBitmap().test(pType)) |
| { |
| // This grantee has wgo. |
| if ( currentRow.visited_.getWgoBitmap().test(pType) ) |
| { // Already processed this subtree. |
| } |
| else |
| { |
| currentRow.visited_.setWgo(pType, true); |
| |
| // To check: since column level privileges do not have |
| // an anchor, we choose the object owner as the root. |
| int32_t thisGrantee( currentRow.granteeID_ ); |
| if ( ComUser::isPublicUserID(thisGrantee) ) |
| scanPublic( pType, // Deal with PUBLIC grantee wgo. |
| rowList ); |
| |
| else |
| { |
| int32_t granteeAsGrantor; |
| if (isRoleID(thisGrantee)) |
| { |
| std::vector<int32_t> roleIDs; |
| std::vector<int32_t> userIDs; |
| roleIDs.push_back(thisGrantee); |
| if (getUserIDsForRoleIDs(roleIDs,userIDs) == STATUS_ERROR) |
| return; |
| for (size_t j = 0; j < userIDs.size(); j++) |
| { |
| granteeAsGrantor = userIDs[j]; |
| scanColumnBranch( pType, // Scan for this grantee as grantor. |
| granteeAsGrantor, |
| listOfColumnOrdinals, |
| rowList ); |
| } |
| } |
| granteeAsGrantor = thisGrantee; |
| scanColumnBranch( pType, // Scan for this grantee as grantor. |
| granteeAsGrantor, |
| listOfColumnOrdinals, |
| rowList ); |
| } // end process non public auth ID |
| } // end visit row |
| } // end this grantee has wgo |
| } // end this grantee has this priv |
| } // correct column ordinal |
| i++; // on to next rowList entry |
| } |
| else |
| break; // done with the grantor |
| } // end scan rowList over Grantees for this Grantor |
| } |
| |
| /* ******************************************************************* |
| scanColumnPublic -- a grant wgo to PUBLIC has been encountered for the |
| current privilege type, so *all* users are able to grant this privilege. |
| Scan the privsList for all grantees who have this priv from any grantor, |
| marking each such entry as visited. |
| |
| ****************************************************************** */ |
| |
| void PrivMgrPrivileges::scanColumnPublic( |
| const PrivType pType, // in |
| const std::set<int32_t> &listOfColumnOrdinals, |
| const std::vector<PrivMgrMDRow *>& rowList ) // in |
| { |
| // PUBLIC has a priv wgo. So *every* grant of this priv |
| // is allowed, by any Grantor. |
| for ( size_t i = 0; i < rowList.size(); i++ ) |
| { |
| ColumnPrivsMDRow ¤tRow = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| |
| // Just look at rows that have had privileges changed |
| // The listOfColumnOrdinals has this list |
| PrivMgrCoreDesc current = currentRow.current_; |
| std::set<int32_t>::iterator it; |
| it = std::find(listOfColumnOrdinals.begin(), listOfColumnOrdinals.end(), current.getColumnOrdinal()); |
| if (it != listOfColumnOrdinals.end()) |
| { |
| if ( current.getPrivBitmap().test(pType) ) |
| { |
| // This grantee has priv. Set corresponding visited flag. |
| currentRow.visited_.setPriv(pType, true); |
| |
| // This grantee has wgo. |
| if ( currentRow.visited_.getWgoBitmap().test(pType) ) |
| currentRow.visited_.setWgo(pType, true); |
| } |
| } |
| } // end scan privsList over all Grantees/Grantors |
| } // end scanPublic |
| |
| |
| // **************************************************************************** |
| // method: sendSecurityKeysToRMS |
| // |
| // This method generates a security key for each privilege revoked for the |
| // grantee. It then makes a cli call sending the keys. |
| // SQL_EXEC_SetSecInvalidKeys will send the security keys to RMS and RMS |
| // sends then to all the master executors. The master executors check this |
| // list and recompile any queries to recheck privileges. |
| // |
| // input: |
| // granteeID - the UID of the user losing privileges |
| // the granteeID is stored in the PrivMgrDesc class - extra? |
| // revokedPrivs - the list of privileges that were revoked |
| // |
| // Returns: PrivStatus |
| // |
| // STATUS_GOOD: Privileges were granted |
| // *: Unable to send keys, see diags. |
| // **************************************************************************** |
| PrivStatus PrivMgrPrivileges::sendSecurityKeysToRMS( |
| const int32_t granteeID, |
| const PrivMgrDesc &revokedPrivs) |
| { |
| // Go through the list of table privileges and generate SQL_QIKEYs |
| std::vector<ComSecurityKey *> keyList; |
| const PrivMgrCoreDesc &privs = revokedPrivs.getTablePrivs(); |
| PrivStatus privStatus = buildSecurityKeys(granteeID, |
| revokedPrivs.getTablePrivs(), |
| keyList); |
| if (privStatus != STATUS_GOOD) |
| { |
| for(size_t k = 0; k < keyList.size(); k++) |
| delete keyList[k]; |
| keyList.clear(); |
| return privStatus; |
| } |
| |
| for (int i = 0; i < revokedPrivs.getColumnPrivs().entries(); i++) |
| { |
| const NAList<PrivMgrCoreDesc> &columnPrivs = revokedPrivs.getColumnPrivs(); |
| privStatus = buildSecurityKeys(granteeID, |
| columnPrivs[i], |
| keyList); |
| if (privStatus != STATUS_GOOD) |
| { |
| for(size_t k = 0; k < keyList.size(); k++) |
| delete keyList[k]; |
| keyList.clear(); |
| return privStatus; |
| } |
| } |
| |
| // Create an array of SQL_QIKEYs |
| int32_t numKeys = keyList.size(); |
| SQL_QIKEY siKeyList[numKeys]; |
| for (size_t j = 0; j < keyList.size(); j++) |
| { |
| ComSecurityKey *pKey = keyList[j]; |
| siKeyList[j].revokeKey.subject = pKey->getSubjectHashValue(); |
| siKeyList[j].revokeKey.object = pKey->getObjectHashValue(); |
| std::string actionString; |
| pKey->getSecurityKeyTypeAsLit(actionString); |
| strncpy(siKeyList[j].operation, actionString.c_str(), 2); |
| } |
| |
| // delete the security list |
| for(size_t k = 0; k < keyList.size(); k++) |
| delete keyList[k]; |
| keyList.clear(); |
| |
| // Call the CLI to send details to RMS |
| SQL_EXEC_SetSecInvalidKeys(numKeys, siKeyList); |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: populateObjectPriv |
| // * |
| // * Inserts rows into the OBJECT_PRIVILEGES table during initialization to |
| // * reflect object owner privileges |
| // * |
| // * Parameters: |
| // * |
| // * <objectLocation> the location of the Trafodion OBJECTS table which is |
| // * used to extract all the objects |
| // * <authsLocation> the location of the Trafodion AUTHS table which is used |
| // * to map owner IDs to grantees |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were inserted |
| // * *: Unable to insert privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::populateObjectPriv( |
| const std::string &objectsLocation, |
| const std::string &authsLocation) |
| { |
| // bug - sometimes, if don't wait, the insert command |
| // does not find rows to insert |
| //sleep(60); |
| ObjectPrivsMDTable objectPrivsTable(objectTableName_, pDiags_); |
| return objectPrivsTable.insertSelect(objectsLocation, authsLocation); |
| } |
| |
| // ***************************************************************************** |
| // * Method: getPrivBitmaps |
| // * |
| // * Reads the OBJECT_PRIVILEGES table to get the privilege bitmaps for |
| // * rows matching a where clause. |
| // * |
| // * Parameters: |
| // * |
| // * <whereClause> specifies the rows to be returned |
| // * <orderByClause> specifies the order of the rows to be returned |
| // * <privBitmaps> passes back a vector of bitmaps. |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were returned |
| // * *: Unable to read privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getPrivBitmaps( |
| const std::string & whereClause, |
| const std::string & orderByClause, |
| std::vector<PrivObjectBitmap> & privBitmaps) |
| |
| { |
| |
| std::vector<PrivMgrMDRow *> rowList; |
| |
| ObjectPrivsMDTable objectPrivsTable(objectTableName_,pDiags_); |
| |
| PrivStatus privStatus = objectPrivsTable.selectWhere(whereClause, orderByClause,rowList); |
| |
| if (privStatus != STATUS_GOOD) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| |
| for (size_t r = 0; r < rowList.size(); r++) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &>(*rowList[r]); |
| privBitmaps.push_back(row.privsBitmap_); |
| } |
| deleteRowList(rowList); |
| |
| return STATUS_GOOD; |
| |
| } |
| |
| |
| |
| // ***************************************************************************** |
| // * Method: getPrivTextForObject |
| // * |
| // * returns GRANT statements describing all the privileges that have been |
| // * granted on the object |
| // * |
| // * Parameters: |
| // * |
| // * <objectInfo> Metadata details for object. |
| // * <privilegeText> The resultant GRANT statement(s) |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD : Grants were found |
| // * STATUS_NOTFOUND: No grants were found |
| // * *: Unable to insert privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getPrivTextForObject( |
| const PrivMgrObjectInfo & objectInfo, |
| std::string & privilegeText) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| if (objectUID_ == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for describe privileges command"); |
| return STATUS_ERROR; |
| } |
| |
| // generate the list of privileges granted to the object and store in class |
| if (generateObjectRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| if (generateColumnRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // No failures possible for objects, all information in rowList. |
| buildPrivText(objectRowList_,objectInfo,PrivLevel::OBJECT,pDiags_,privilegeText); |
| |
| // build text for columns |
| retcode = buildPrivText(columnRowList_,objectInfo,PrivLevel::COLUMN, |
| pDiags_,privilegeText); |
| |
| return retcode; |
| |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: getPrivsOnObjectForUser |
| // * |
| // * returns privileges granted to the requested user for the requested |
| // * object |
| // * |
| // * Parameters: |
| // * |
| // * <objectUID> identifies the object |
| // * <userID> identifies the user |
| // * <privsOfTheUser> the list of privileges is returned |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were gathered |
| // * *: Unable to gather privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getPrivsOnObjectForUser( |
| const int64_t objectUID, |
| ComObjectType objectType, |
| const int32_t userID, |
| PrivMgrDesc &privsOfTheUser, |
| std::vector <ComSecurityKey *>* secKeySet) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| objectUID_ = objectUID; |
| if (objectUID == 0) |
| { |
| PRIVMGR_INTERNAL_ERROR("objectUID is 0 for get privileges command"); |
| return STATUS_ERROR; |
| } |
| |
| // generate the list of privileges granted to the object and store in class |
| if (generateObjectRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // generate the list of column-level privileges granted to the object and store in class |
| if (generateColumnRowList() == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // generate the list of roles for the user |
| std::vector<int32_t> roleIDs; |
| if (getRoleIDsForUserID(userID,roleIDs) == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| // generate the list of privileges for the user |
| privsOfTheUser.setGrantee(userID); |
| bool hasManagePrivileges = false; |
| |
| retcode = getUserPrivs(objectType, userID, roleIDs, privsOfTheUser, |
| hasManagePrivileges, secKeySet); |
| |
| return retcode; |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: getRoleIDsForUserID |
| // * |
| // * Returns the roleIDs for the roles granted to the user. |
| // * |
| // * Parameters: |
| // * |
| // * <userID> is the unique identifier for the user |
| // * <roleIDs> passes back the list (potentially empty) of roles granted to the user |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Role list returned |
| // * *: Unable to fetch granted roles, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getRoleIDsForUserID( |
| int32_t userID, |
| std::vector<int32_t> & roleIDs) |
| |
| { |
| |
| PrivStatus retcode = STATUS_GOOD; |
| |
| PrivMgrRoles roles(" ",metadataLocation_,pDiags_); |
| std::vector<std::string> roleNames; |
| std::vector<int32_t> roleDepths; |
| |
| retcode = roles.fetchRolesForUser(userID,roleNames,roleIDs,roleDepths); |
| return retcode; |
| } |
| //*************** End of PrivMgrPrivileges::getRoleIDsForUserID **************** |
| |
| // ***************************************************************************** |
| // * Method: getUserIDsForRoleIDs |
| // * |
| // * Returns the userIDs granted to the role passed in role list |
| // * |
| // * Parameters: |
| // * |
| // * <roleIDs> list of roles to check |
| // * <userIDs> passed back the list (potentially empty) of users granted to |
| // * the roleIDs |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Role list returned |
| // * *: Unable to fetch granted roles, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getUserIDsForRoleIDs( |
| const std::vector<int32_t> & roleIDs, |
| std::vector<int32_t> & userIDs) |
| { |
| std::vector<int32_t> userIDsForRoleIDs; |
| PrivMgrRoles roles(" ",metadataLocation_,pDiags_); |
| if (roles.fetchUsersForRoles(roleIDs, userIDsForRoleIDs) == STATUS_ERROR) |
| return STATUS_ERROR; |
| |
| for (size_t i = 0; i < userIDsForRoleIDs.size(); i++) |
| { |
| int32_t authID = userIDsForRoleIDs[i]; |
| if (std::find(userIDs.begin(), userIDs.end(), authID) == userIDs.end()) |
| userIDs.insert( std::upper_bound( userIDs.begin(), userIDs.end(), authID ), authID); |
| } |
| return STATUS_GOOD; |
| } |
| |
| // ***************************************************************************** |
| // * Method: getUserPrivs |
| // * |
| // * Accumulates privileges for a user summarized over all grantors |
| // * including PUBLIC |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> specifies the userID to accumulate |
| // * <roleIDs> specifies a list of roles granted to the grantee |
| // * <summarizedPrivs> contains the summarized privileges |
| // * <hasManagePrivileges> returns whether the grantee has MANAGE_PRIVILEGES authority |
| // * <secKeySet> if not NULL, returns a set of keys for user |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were gathered |
| // * *: Unable to gather privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getUserPrivs( |
| ComObjectType objectType, |
| const int32_t granteeID, |
| const std::vector<int32_t> & roleIDs, |
| PrivMgrDesc &summarizedPrivs, |
| bool & hasManagePrivileges, |
| std::vector<ComSecurityKey *>* secKeySet |
| ) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| PrivMgrDesc temp(granteeID); |
| |
| retcode = getPrivsFromAllGrantors( objectUID_, |
| objectType, |
| granteeID, |
| roleIDs, |
| temp, |
| hasManagePrivileges, |
| secKeySet |
| ); |
| if (retcode != STATUS_GOOD) |
| return retcode; |
| |
| summarizedPrivs = temp; |
| |
| |
| return retcode; |
| } |
| |
| // ***************************************************************************** |
| // * Method: getPrivsFromAllGrantors |
| // * |
| // * Accumulates privileges for a specified userID |
| // * Does the actual accumulation orchestrated by getUserPrivs |
| // * |
| // * Parameters: |
| // * |
| // * <objectUID> object to gather privileges for |
| // * <objectType> is the type of the subject object. |
| // * <granteeID> specifies the userID to accumulate |
| // * <roleIDs> is vector of roleIDs granted to the grantee |
| // * <hasManagePrivileges> returns whether the grantee has MANAGE_PRIVILEGES authority |
| // * <summarizedPrivs> contains the summarized privileges |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were accumulated |
| // * *: Unable to accumulate privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getPrivsFromAllGrantors( |
| const int64_t objectUID, |
| ComObjectType objectType, |
| const int32_t granteeID, |
| const std::vector<int32_t> & roleIDs, |
| PrivMgrDesc &summarizedPrivs, |
| bool & hasManagePrivileges, |
| std::vector <ComSecurityKey *>* secKeySet |
| ) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| hasManagePrivileges = false; |
| bool hasPublicGrantee = false; |
| |
| // Check to see if the granteeID is the system user |
| // if so, the system user has all privileges. Set up appropriately |
| if (ComUser::isSystemUserID(granteeID)) |
| { |
| PrivObjectBitmap bitmap; |
| bitmap.set(); |
| PrivMgrCoreDesc coreTablePrivs(bitmap, bitmap); |
| summarizedPrivs.setTablePrivs(coreTablePrivs); |
| hasManagePrivileges = true; |
| return STATUS_GOOD; |
| } |
| |
| std::vector<PrivMgrMDRow *> rowList; |
| PrivObjectBitmap systemPrivs; |
| PrivMgrComponentPrivileges componentPrivileges(metadataLocation_,pDiags_); |
| |
| componentPrivileges.getSQLDMLPrivileges(granteeID,roleIDs,systemPrivs, |
| hasManagePrivileges); |
| |
| if (hasManagePrivileges && hasAllDMLPrivs(objectType,systemPrivs)) |
| { |
| PrivMgrCoreDesc coreTablePrivs(systemPrivs,systemPrivs); |
| summarizedPrivs.setTablePrivs(coreTablePrivs); |
| } |
| |
| // Accumulate object level privileges |
| else |
| { |
| retcode = getRowsForGrantee(objectUID, granteeID, true, roleIDs, rowList, secKeySet); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| // Get the privileges for the object granted to the grantee |
| PrivMgrCoreDesc coreTablePrivs; |
| for (int32_t i = 0; i < rowList.size();++i) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*rowList[i]); |
| |
| if (ComUser::isPublicUserID(row.granteeID_)) |
| hasPublicGrantee = true; |
| |
| PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_); |
| if (secKeySet) |
| { |
| retcode = buildSecurityKeys(granteeID, |
| temp, |
| *secKeySet); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| } |
| |
| coreTablePrivs.unionOfPrivs(temp); |
| } |
| |
| PrivObjectBitmap grantableBitmap; |
| |
| if (hasManagePrivileges) |
| grantableBitmap = systemPrivs; |
| |
| PrivMgrCoreDesc temp2(systemPrivs,grantableBitmap); |
| coreTablePrivs.unionOfPrivs(temp2); |
| |
| summarizedPrivs.setTablePrivs(coreTablePrivs); |
| } |
| |
| // Add accumulated column level privileges |
| rowList.clear(); |
| retcode = getRowsForGrantee(objectUID, granteeID, false, roleIDs, rowList, secKeySet); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| |
| NAList<PrivMgrCoreDesc> coreColumnPrivs(STMTHEAP); |
| for (int32_t i = 0; i < rowList.size();++i) |
| { |
| ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| |
| if (ComUser::isPublicUserID(row.granteeID_)) |
| hasPublicGrantee = true; |
| |
| |
| // See if the ordinal has already been specified |
| PrivMgrCoreDesc temp (row.privsBitmap_, row.grantableBitmap_, row.columnOrdinal_); |
| if (secKeySet) |
| { |
| retcode = buildSecurityKeys(granteeID, |
| temp, |
| *secKeySet); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| } |
| |
| PrivMgrCoreDesc *coreColumnPriv = findColumnEntry(coreColumnPrivs, row.columnOrdinal_); |
| if (coreColumnPriv) |
| coreColumnPriv->unionOfPrivs(temp); |
| else |
| coreColumnPrivs.insert(temp); |
| } |
| |
| summarizedPrivs.setColumnPrivs(coreColumnPrivs); |
| summarizedPrivs.setHasPublicPriv(hasPublicGrantee); |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // method: getRolesToCheck |
| // |
| // This method checks all the roles granted to the user and returns a comma |
| // separated list of those roles that have privileges on the target object. |
| // ---------------------------------------------------------------------------- |
| PrivStatus PrivMgrPrivileges::getRolesToCheck( |
| const int32_t grantorID, |
| const std::vector<int32_t> & roleIDs, |
| const ComObjectType objectType, |
| std::string &rolesWithPrivs) |
| { |
| int32_t length; |
| char roleName[MAX_DBUSERNAME_LEN + 1]; |
| std::vector<int_32> emptyRoleIDs; |
| bool hasManagePrivPriv = false; |
| |
| for (size_t r = 0; r < roleIDs.size(); r++) |
| { |
| PrivMgrDesc privsOfTheRole(roleIDs[r],true); |
| if (getUserPrivs(objectType, roleIDs[r], emptyRoleIDs, privsOfTheRole, |
| hasManagePrivPriv) != STATUS_GOOD) |
| return STATUS_ERROR; |
| |
| if (!privsOfTheRole.isNull()) |
| { |
| // just return what getAuthNameFromAuthID returns |
| ComUser::getAuthNameFromAuthID(roleIDs[r],roleName, sizeof(roleName),length); |
| if (rolesWithPrivs.size() > 0) |
| rolesWithPrivs += ", "; |
| rolesWithPrivs += roleName; |
| } |
| } |
| |
| if (rolesWithPrivs.size() > 0) |
| { |
| rolesWithPrivs.insert (0,"Please retry using the BY clause for one of the following roles ("); |
| rolesWithPrivs += ")."; |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ***************************************************************************** |
| // * Method: getRowsForGrantee |
| // * |
| // * Reads OBJECT_PRIVILEGES table to obtain all privileges granted to the |
| // * specified granteeID for the object (objectUID) |
| // * |
| // * Parameters: |
| // * |
| // * <objectUID> object to gather privileges for |
| // * <granteeID> specifies the userID to gather privileges |
| // * <roleIDs> the list of roles granted to the userID |
| // * <isObjectTable> true if OBJECT_PRIVILEGES table |
| // * <rowList> returns the list of granted privileges as a vector list |
| // * consisiting of the grantor, grantee, and privileges for the object |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were retrieved |
| // * *: Unable to retrieve privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::getRowsForGrantee( |
| const int64_t objectUID, |
| const int32_t granteeID, |
| const bool isObjectTable, |
| const std::vector<int_32> &roleIDs, |
| std::vector<PrivMgrMDRow *> &rowList, |
| std::vector <ComSecurityKey *>* secKeySet) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| // create the list of row pointers |
| std::vector<int32_t> authIDs = roleIDs; |
| authIDs.push_back(granteeID); |
| authIDs.push_back(PUBLIC_USER); |
| std::vector<int32_t>::iterator it; |
| std::vector<PrivMgrMDRow *> privRowList; |
| if (isObjectTable) |
| { |
| if (objectUID == objectUID_) |
| privRowList = objectRowList_; |
| else |
| { |
| retcode = getObjectRowList(objectUID, privRowList); |
| if (retcode == STATUS_ERROR) |
| return retcode; |
| } |
| } |
| else |
| privRowList = columnRowList_; |
| |
| for (size_t i = 0; i < privRowList.size(); i++) |
| { |
| if (isObjectTable) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*privRowList[i]); |
| it = std::find(authIDs.begin(), authIDs.end(), row.granteeID_); |
| } |
| else |
| { |
| ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*privRowList[i]); |
| it = std::find(authIDs.begin(), authIDs.end(), row.granteeID_); |
| } |
| if (it != authIDs.end()) |
| rowList.push_back(privRowList[i]); |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| // **************************************************************************** |
| // method: summarizeColPrivs |
| // |
| // This method summarizes column privileges across all grantors. |
| // |
| // Params: |
| // objectReference - the affected object |
| // roleIDs - list of roles for the current object owner |
| // listOfAffectedObjects - list of affected objects |
| // summarizedColRefs - a list of ColumnReference pointers that contain the |
| // summarized privileges (the caller is responsible |
| // for deleting memory for this parameter |
| // **************************************************************************** |
| void PrivMgrPrivileges::summarizeColPrivs( |
| const ObjectReference &objReference, |
| const int32_t granteeID, |
| const int32_t grantorID, |
| const std::vector<int32_t> &roleIDs, |
| const std::vector<ObjectUsage *> &listOfAffectedObjects, |
| std::vector<ColumnReference *> &summarizedColRefs) |
| { |
| std::string traceMsg; |
| objReference.describe(traceMsg); |
| traceMsg.insert (0, "summarizing column privileges "); |
| log (__FILE__, traceMsg, -1); |
| |
| // objReference.columnReferences is the list of columns |
| // referencing the referenced table |
| std::vector<ColumnReference *> *colRefs = objReference.columnReferences; |
| for (size_t i = 0; i < colRefs->size(); i++) |
| { |
| ColumnReference *colRef = (*colRefs)[i]; |
| colRef->describe(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| // get COLUMN_PRIVILEGES rows where the grantee for the column has received |
| // privileges - the row list is in memory so this does not require I/O |
| std::vector<PrivMgrMDRow *> rowList; |
| getColRowsForGranteeOrdinal(granteeID, |
| colRef->columnOrdinal, |
| columnRowList_, |
| roleIDs, |
| rowList); |
| |
| // go through the rowList to summarize the original and current privileges |
| // We do a union operation to capture privileges from all grantors |
| ColumnReference *summarized = new ColumnReference; |
| summarized->columnOrdinal = colRef->columnOrdinal; |
| |
| if (rowList.size() > 0) |
| { |
| for (int32_t j = 0; j < rowList.size();++j) |
| { |
| ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*rowList[j]); |
| PrivMgrCoreDesc originalPrivs(row.privsBitmap_, row.grantableBitmap_); |
| PrivMgrCoreDesc updated = originalPrivs; |
| |
| // Update if privileges have been changed by request |
| for (size_t k = 0; k < listOfAffectedObjects.size(); k++) |
| { |
| ObjectUsage *currentObj = listOfAffectedObjects[k]; |
| if (currentObj->objectUID == row.objectUID_ && |
| grantorID == row.grantorID_ && |
| currentObj->granteeID == row.granteeID_ ) |
| { |
| ColumnReference *changedRef = currentObj->findColumn(row.columnOrdinal_); |
| if (changedRef) |
| updated = changedRef->updatedPrivs; |
| } |
| } |
| summarized->originalPrivs.unionOfPrivs(originalPrivs); |
| summarized->updatedPrivs.unionOfPrivs(updated); |
| } |
| } |
| else |
| { |
| // For grants, this may be the first column privs added, adjust to |
| // include new privs |
| PrivMgrCoreDesc updated; |
| for (size_t k = 0; k < listOfAffectedObjects.size(); k++) |
| { |
| ObjectUsage *currentObj = listOfAffectedObjects[k]; |
| ColumnReference *changedRef = currentObj->findColumn(colRef->columnOrdinal); |
| if (changedRef) |
| updated = changedRef->updatedPrivs; |
| } |
| // There are no originalPrivs |
| summarized->updatedPrivs.unionOfPrivs(updated); |
| } |
| |
| // Add column ref to the list |
| summarizedColRefs.push_back(summarized); |
| } |
| } |
| |
| // ***************************************************************************** |
| // * Method: summarizeCurrentAndOriginalPrivs |
| // * |
| // * Accumulates privileges for a specified object and grantee |
| // * |
| // * Parameters: |
| // * |
| // * <objectUID> object to summarize privileges for |
| // * <granteeID> specifies the userID to accumulate |
| // * <roleIDs> the list of roles granted to the userID |
| // * <summarizedOriginalPrivs> contains the original summarized privileges |
| // * <summarizedCurrentPrivs> contains the current summarized privileges |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were summarized |
| // * *: Unable to summarize privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::summarizeCurrentAndOriginalPrivs( |
| const int64_t objectUID, |
| const int32_t granteeID, |
| const int32_t grantorID, |
| const std::vector<int32_t> & roleIDs, |
| const std::vector<ObjectUsage *> listOfChangedPrivs, |
| PrivMgrDesc &summarizedOriginalPrivs, |
| PrivMgrDesc &summarizedCurrentPrivs) |
| { |
| PrivStatus retcode = STATUS_GOOD; |
| |
| // get OBJECT_PRIVILEGES rows where the grantee has received privileges |
| std::vector<PrivMgrMDRow *> rowList; |
| retcode = getRowsForGrantee(objectUID, granteeID, true, roleIDs, rowList, NULL); |
| |
| // rowList contains the original privileges, |
| // listOfChangedPrivs contains any updates to privileges |
| // go through the list and summarize the original and current privileges |
| // We do a union operation to capture privileges from all grantors |
| for (int32_t i = 0; i < rowList.size();++i) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*rowList[i]); |
| PrivMgrCoreDesc original(row.privsBitmap_, row.grantableBitmap_); |
| PrivMgrCoreDesc updated = original; |
| for (size_t j = 0; j < listOfChangedPrivs.size(); j++) |
| { |
| ObjectUsage *pObjectUsage = listOfChangedPrivs[j]; |
| if (pObjectUsage->objectUID == row.objectUID_ && |
| grantorID == row.grantorID_ && |
| pObjectUsage->granteeID == row.granteeID_ ) |
| { |
| updated = pObjectUsage->updatedPrivs.getTablePrivs(); |
| } |
| } |
| summarizedOriginalPrivs.unionOfPrivs(original); |
| summarizedCurrentPrivs.unionOfPrivs(updated); |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| // ***************************************************************************** |
| // * Method: updateDependentObjects |
| // * |
| // * This code gets the list of dependent objects that have had their privileges |
| // * changed because of the ongoing grant/revoke request. It then updates |
| // * the object privileges table to change any dependencies. |
| // * |
| // * SQL ANSI general rules state |
| // * |
| // * - When granting INSERT, UPDATE, or DELETE object or column privilege to |
| // * a table that is referenced by one or more views, then the privilege |
| // * should be propagated to any updatable views that reference the table. |
| // * The grant request to the these views should be executed as though the |
| // * current user is _SYSTEM. |
| // * |
| // * - If the table already has SELECT privilege and a new grant is |
| // * performed that adds the WITH GRANT OPTION, then the WITH GRANT OPTION |
| // * is to be propagated to referencing views. The grant request should |
| // * be executed as though the current user is _SYSTEM. |
| // * |
| // * - When revoking INSERT, UPDATE, or DELETE object or column privilege from |
| // * a table that is referenced by one or more views, then the privilege |
| // * should be revoked on any updatable views that reference the table. |
| // * The revoke request to the these views should be executed as though the |
| // * current user is _SYSTEM. |
| // * |
| // * - If the revoke is performed that removes the WITH GRANT OPTION, then |
| // * the WITH GRANT OPTION is to be removed frome referencing views. The |
| // * revoke request should be executed as though the current user is _SYSTEM. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::updateDependentObjects( |
| const ObjectUsage &objectUsage, |
| const PrivCommand command) |
| { |
| std::string traceMsg; |
| |
| // get list of any objects that need to change because of the grant/revoke |
| std::vector<ObjectUsage *> listOfObjects; |
| PrivStatus privStatus = getAffectedObjects(objectUsage, command, listOfObjects); |
| if (privStatus == STATUS_ERROR) |
| { |
| deleteListOfAffectedObjects(listOfObjects); |
| return privStatus; |
| } |
| |
| traceMsg = "list of dependent objects, number of objects is "; |
| traceMsg += to_string((long long int)listOfObjects.size()); |
| log (__FILE__, traceMsg, -1); |
| |
| char buf [1000]; |
| ObjectPrivsMDTable objectPrivsTable (objectTableName_, pDiags_); |
| |
| // update the OBJECT_PRIVILEGES row for each effected object |
| // Starting index is 1 - the first entry is the original row that is |
| // updated as part of the grant/revoke request |
| size_t i = 1; |
| for (i; i < listOfObjects.size(); i++) |
| { |
| ObjectUsage *pObjectUsage = listOfObjects[i]; |
| |
| pObjectUsage->describe(traceMsg); |
| log (__FILE__, traceMsg, i); |
| |
| // Determine row contents |
| int32_t theGrantor = (pObjectUsage->grantorIsSystem) ? SYSTEM_USER : grantorID_; |
| int32_t theGrantee = pObjectUsage->granteeID; |
| int64_t theUID = pObjectUsage->objectUID; |
| PrivMgrCoreDesc thePrivs = pObjectUsage->updatedPrivs.getTablePrivs(); |
| sprintf(buf, "where grantee_id = %d and grantor_id = %d and object_uid = %ld", |
| theGrantee, theGrantor, theUID); |
| std::string whereClause (buf); |
| |
| if (thePrivs.isNull()) |
| { |
| pObjectUsage->describe(traceMsg); |
| traceMsg.insert (0, "deleted object usage "); |
| |
| // delete the row |
| privStatus = objectPrivsTable.deleteWhere(whereClause); |
| if (privStatus == STATUS_ERROR) |
| { |
| deleteListOfAffectedObjects(listOfObjects); |
| return privStatus; |
| } |
| } |
| else |
| { |
| sprintf(buf, "set privileges_bitmap = %ld, grantable_bitmap = %ld", |
| thePrivs.getPrivBitmap().to_ulong(), |
| thePrivs.getWgoBitmap().to_ulong()); |
| std::string setClause (buf); |
| privStatus = objectPrivsTable.updateWhere(setClause, whereClause); |
| |
| if (privStatus == STATUS_ERROR) |
| { |
| deleteListOfAffectedObjects(listOfObjects); |
| return privStatus; |
| } |
| } |
| } |
| deleteListOfAffectedObjects(listOfObjects); |
| return STATUS_GOOD; |
| } |
| |
| |
| |
| // ***************************************************************************** |
| // * Method: isAuthIDGrantedPrivs |
| // * |
| // * Determines if the specified authorization ID has been granted one or |
| // * more object privileges. |
| // * |
| // * Parameters: |
| // * |
| // * <authID> identifies the user or role. |
| // * |
| // * Returns: bool |
| // * |
| // * true: Authorization ID has been granted one or more object privileges. |
| // * false: Authorization ID has not been granted any object privileges. |
| // * |
| // ***************************************************************************** |
| bool PrivMgrPrivileges::isAuthIDGrantedPrivs( |
| const int32_t authID, |
| std::vector<int64_t> &objectUIDs) |
| { |
| |
| std::string whereClause(" WHERE GRANTEE_ID = "); |
| std::string orderByClause (" ORDER BY object_name "); |
| |
| char authIDString[20]; |
| |
| sprintf(authIDString,"%d",authID); |
| |
| whereClause += authIDString; |
| |
| // set pointer in diags area |
| int32_t diagsMark = pDiags_->mark(); |
| |
| std::vector<PrivMgrMDRow *> rowList; |
| ObjectPrivsMDTable myTable(objectTableName_,pDiags_); |
| |
| PrivStatus privStatus = myTable.selectWhere(whereClause, orderByClause ,rowList); |
| if (privStatus != STATUS_GOOD) |
| { |
| deleteRowList(rowList); |
| return privStatus; |
| } |
| |
| int32_t rowCount = rowList.size(); |
| for (size_t i = 0; i < rowCount; i++) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*rowList[i]); |
| objectUIDs.push_back(row.objectUID_); |
| } |
| deleteRowList(rowList); |
| |
| if ((privStatus == STATUS_GOOD || privStatus == STATUS_WARNING) && |
| rowCount > 0) |
| return true; |
| |
| // TBD - check for granted column level privs |
| pDiags_->rewind(diagsMark); |
| return false; |
| |
| } |
| |
| // ***************************************************************************** |
| // * Method: convertPrivsToDesc |
| // * |
| // * Converts the list of requested privileges into a PrivMgrDesc |
| // * This code also checks for duplicate entries in the privilege list |
| // * and that the list of privileges is compatible with the object type. |
| // * |
| // * Parameters: |
| // * |
| // * <objectType> type of object |
| // * <isAllSpecified> if true then all privileges valid for the object |
| // * type will be revoked |
| // * <isWGOSpecified> for grants, include the with grant option |
| // * for revokes (always true), if revoke the priv, also |
| // * revoke the with grant option |
| // * <isGofSpecified> for grants - alway false (not applicable) |
| // * for revokes - only revoke the with grant option |
| // * <privsList> is the list of privileges to check |
| // * <PrivMgrCoreDesc> the core descriptor containing privileges |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Privileges were inserted |
| // * *: Unable to insert privileges, see diags. |
| // * |
| // ***************************************************************************** |
| PrivStatus PrivMgrPrivileges::convertPrivsToDesc( |
| const ComObjectType objectType, |
| const bool isAllSpecified, |
| const bool isWgoSpecified, |
| const bool isGofSpecified, |
| const std::vector<PrivType> privsList, |
| const std::vector<ColPrivSpec> & colPrivsList, |
| PrivMgrDesc &privsToProcess) |
| { |
| |
| // Categorize the objectType |
| bool isLibrary = false; |
| bool isUdr = false; |
| bool isObject = false; |
| bool isSequence = false; |
| switch (objectType) |
| { |
| case COM_BASE_TABLE_OBJECT: |
| case COM_VIEW_OBJECT: |
| isObject = true; |
| break; |
| case COM_LIBRARY_OBJECT: |
| isLibrary = true; |
| break; |
| case COM_USER_DEFINED_ROUTINE_OBJECT: |
| isUdr = true; |
| break; |
| case COM_SEQUENCE_GENERATOR_OBJECT: |
| isSequence = true; |
| break; |
| default: |
| { |
| char objectTypeLit[3] = {0}; |
| strncpy(objectTypeLit,ObjectEnumToLit(objectType),2); |
| *pDiags_ << DgSqlCode(-4219) |
| << DgString1(objectTypeLit); |
| return STATUS_ERROR; |
| } |
| } |
| |
| // If all is specified, set bits appropriate for the object type and return |
| if (isAllSpecified) |
| { |
| if (isLibrary) |
| privsToProcess.setAllLibraryGrantPrivileges(isWgoSpecified); |
| else if (isUdr) |
| privsToProcess.setAllUdrGrantPrivileges(isWgoSpecified); |
| else if (isSequence) |
| privsToProcess.setAllSequenceGrantPrivileges(isWgoSpecified); |
| else |
| privsToProcess.setAllTableGrantPrivileges(isWgoSpecified); |
| return STATUS_GOOD; |
| } |
| |
| PrivMgrCoreDesc tableCorePrivs; |
| |
| // For each privilege specified in the privsList: |
| // make sure it is not a duplicate |
| // make sure it is appropriate for the objectType |
| bool isIncompatible = false; |
| for (int32_t i = 0; i < privsList.size();++i) |
| { |
| switch (privsList[i]) |
| { |
| case EXECUTE_PRIV: |
| if (!isUdr) |
| isIncompatible = true; |
| else |
| tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified); |
| break; |
| case DELETE_PRIV: |
| case INSERT_PRIV: |
| case REFERENCES_PRIV: |
| case SELECT_PRIV: |
| if (!isObject) |
| isIncompatible = true; |
| else |
| tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified); |
| break; |
| case UPDATE_PRIV: |
| if (!isObject && !isLibrary) |
| isIncompatible = true; |
| else |
| tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified); |
| break; |
| case USAGE_PRIV: |
| if (!isLibrary && !isSequence) |
| isIncompatible = true; |
| else |
| tableCorePrivs.testAndSetBit(privsList[i],isWgoSpecified,isGofSpecified); |
| break; |
| case ALL_DML: |
| if (!isObject) |
| isIncompatible = true; |
| if (isGofSpecified) |
| tableCorePrivs.setWgo(ALL_DML,true); |
| else |
| { |
| tableCorePrivs.setPriv(ALL_DML,true); |
| tableCorePrivs.setWgo(ALL_DML,isWgoSpecified); |
| } |
| break; |
| default: |
| { |
| *pDiags_ << DgSqlCode(-CAT_INVALID_PRIVILEGE_FOR_GRANT_OR_REVOKE) |
| << DgString0(PrivMgrUserPrivs::convertPrivTypeToLiteral(privsList[i]).c_str()); |
| return STATUS_ERROR; |
| } |
| } |
| // Report error if privilege is incompatible with objectType |
| if (isIncompatible) |
| { |
| *pDiags_ << DgSqlCode(-CAT_PRIVILEGE_NOT_ALLOWED_FOR_THIS_OBJECT_TYPE) |
| << DgString0(PrivMgrUserPrivs::convertPrivTypeToLiteral(privsList[i]).c_str()); |
| return STATUS_ERROR; |
| } |
| } // end for |
| |
| privsToProcess.setTablePrivs(tableCorePrivs); |
| |
| // Merge the column-privilege-to-grant entries (colPrivArray) into one entry |
| // per column ordinal. |
| // |
| // Example: Given a commands such as |
| // |
| // GRANT SELECT(COL4),INSERT(COL2,COL4) ON TAB TO USER; |
| // |
| // three entries are generated by the parser, but only two rows are written; |
| // one for column 2 (insert) and one for column 4 (insert and select). |
| // |
| // Input may have same column ordinal in multiple entries, but the input is |
| // guaranteed not to contain same ordinal and privType more than once. |
| NAList<PrivMgrCoreDesc> columnCorePrivs(STMTHEAP); |
| for (size_t i = 0; i < colPrivsList.size(); i++) |
| { |
| const ColPrivSpec &colPrivSpec = colPrivsList[i]; |
| |
| PrivMgrCoreDesc *existingEntry = findColumnEntry(columnCorePrivs, |
| colPrivSpec.columnOrdinal); |
| if (existingEntry != NULL) |
| existingEntry->testAndSetBit(colPrivSpec.privType,isWgoSpecified,isGofSpecified); |
| else |
| { |
| PrivMgrCoreDesc colPrivToGrant; |
| colPrivToGrant.setColumnOrdinal(colPrivSpec.columnOrdinal); |
| colPrivToGrant.testAndSetBit(colPrivSpec.privType,isWgoSpecified,isGofSpecified); |
| |
| columnCorePrivs.insert(colPrivToGrant); |
| } |
| } |
| |
| privsToProcess.setColumnPrivs(columnCorePrivs); |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ***************************************************************************** |
| // PrivMgrPrivileges.cpp static functions * |
| // ***************************************************************************** |
| |
| |
| |
| // ***************************************************************************** |
| // * Function: buildPrivText * |
| // * * |
| // * Builds priv portion of SHOWDDL output. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <rowList> const std::vector<PrivMgrMDRow *> In * |
| // * is a list of rows describing the privileges granted. * |
| // * * |
| // * <objectInfo> const PrivMgrObjectInf & In * |
| // * object details needed to create appropriate text * |
| // * * |
| // * <privLevel> PrivLevel In * |
| // * is the privilege level, either OBJECT or COLUMN. * |
| // * * |
| // * <pDiags_> ComDiagsArea * In * |
| // * is where to report an internal error. * |
| // * * |
| // * <privilegeText> std::string & Out * |
| // * passes back the set of grant commands that describe the privileges on * |
| // * the object. * |
| // * * |
| // ***************************************************************************** |
| static PrivStatus buildPrivText( |
| const std::vector<PrivMgrMDRow *> rowList, |
| const PrivMgrObjectInfo & objectInfoIn, |
| PrivLevel privLevel, |
| ComDiagsArea * pDiags_, |
| std::string & privilegeText) |
| { |
| PrivMgrObjectInfo objectInfo = (PrivMgrObjectInfo) objectInfoIn; |
| |
| // Build a grant statement for each grantor/grantee row returned. |
| // TDB: If we support multiple grantees per grant statement, |
| // this code can be improved |
| std::string grantStmt; |
| std::string grantWGOStmt; |
| std::string objectText("ON "); |
| |
| // Append object type if not base table or view |
| if (objectInfo.getObjectType() != COM_BASE_TABLE_OBJECT && |
| objectInfo.getObjectType() != COM_VIEW_OBJECT) |
| objectText += comObjectTypeName(objectInfo.getObjectType()); |
| objectText += objectInfo.getObjectName() + " TO "; |
| |
| std::string lastGranteeName; |
| int32_t lastGranteeID = 0; |
| |
| std::vector<std::string> privString; |
| std::vector<std::string> WGOString; |
| std::vector<bool> hasWGO; |
| std::vector<bool> hasPriv; |
| std::vector<std::string> columnNames; |
| bool mergeStrings = false; |
| |
| // Note, this creates entries for DELETE and USAGE that are unused. |
| if (privLevel == PrivLevel::COLUMN) |
| for (size_t p = FIRST_DML_COL_PRIV; p <= LAST_DML_COL_PRIV; p++ ) |
| { |
| privString.push_back(PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p) + "("); |
| WGOString.push_back(privString[p]); |
| hasPriv.push_back(false); |
| hasWGO.push_back(false); |
| } |
| |
| for (int32_t i = 0; i < rowList.size();++i) |
| { |
| std::string objectGranteeText(objectText); |
| |
| std::string withoutWGO; |
| std::string withWGO; |
| int32_t grantorID = 0; |
| std::string grantorName; |
| if (privLevel == PrivLevel::OBJECT) |
| { |
| ObjectPrivsMDRow &row = static_cast<ObjectPrivsMDRow &> (*rowList[i]); |
| |
| grantorID = row.grantorID_; |
| grantorName = row.grantorName_; |
| PrivObjectBitmap privsBitmap = row.privsBitmap_; |
| PrivObjectBitmap wgoBitmap = row.grantableBitmap_; |
| bool delimited = isDelimited(row.granteeName_); |
| if (delimited) |
| objectGranteeText += "\""; |
| objectGranteeText += row.granteeName_; |
| if (delimited) |
| objectGranteeText += "\""; |
| for (size_t p = FIRST_DML_PRIV; p <= LAST_DML_PRIV; p++ ) |
| if (privsBitmap.test(p)) |
| { |
| std::string privTypeString = |
| PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p); |
| if (wgoBitmap.test(p)) |
| withWGO += privTypeString + ", "; |
| else |
| withoutWGO += privTypeString + ", "; |
| } |
| } |
| else |
| { |
| ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*rowList[i]); |
| // For column-level privileges we are building a piece of the |
| // output for each privilege on every loop. Privileges are stored |
| // per column, but GRANT syntax accepts via a privilege and a |
| // list of columns. For each privilege granted to a grantee, need |
| // to list all the columns. Substrings are merged when the end of the |
| // list of grants is reached or there is a new grantor or grantee. |
| if (i + 1 == rowList.size()) |
| mergeStrings = true; |
| else |
| { |
| ColumnPrivsMDRow &nextRow = static_cast<ColumnPrivsMDRow &> (*rowList[i + 1]); |
| |
| if (nextRow.grantorID_ != row.grantorID_ || |
| nextRow.granteeID_ != row.granteeID_) |
| mergeStrings = true; |
| } |
| |
| grantorID = row.grantorID_; |
| grantorName = row.grantorName_; |
| PrivColumnBitmap privsBitmap = row.privsBitmap_; |
| PrivColumnBitmap wgoBitmap = row.grantableBitmap_; |
| |
| // Get name of the grantee. If we have changed grantees, fetch the |
| // name of the grantee. |
| if (row.granteeID_ != lastGranteeID) |
| { |
| lastGranteeID = row.granteeID_; |
| lastGranteeName = row.granteeName_; |
| } |
| bool delimited = isDelimited(lastGranteeName); |
| if (delimited) |
| objectGranteeText += "\""; |
| objectGranteeText += lastGranteeName; |
| if (delimited) |
| objectGranteeText += "\""; |
| |
| // Get the column name for the row |
| const std::vector<std::string> &columnList = objectInfo.getColumnList(); |
| if (columnList.size() < row.columnOrdinal_) |
| { |
| std::string errorText("Unable to look up column name for column number "); |
| |
| errorText += PrivMgr::authIDToString(row.columnOrdinal_); |
| PRIVMGR_INTERNAL_ERROR(errorText.c_str()); |
| return STATUS_ERROR; |
| } |
| std::string columnName(columnList.at(row.columnOrdinal_)); |
| |
| // Build the list of columns granted for each privilege. WGOString |
| // and privString have been pre-populated with PRIVNAME(. |
| for (size_t p = FIRST_DML_COL_PRIV; p <= LAST_DML_COL_PRIV; p++ ) |
| if (privsBitmap.test(p)) |
| { |
| if (wgoBitmap.test(p)) |
| { |
| WGOString[p] += columnName + ", "; |
| hasWGO[p] = true; |
| } |
| else |
| { |
| privString[p] += columnName + ", "; |
| hasPriv[p] = true; |
| } |
| } |
| |
| // Check if there are column priv substrings that need to be merged. |
| if (mergeStrings) |
| { |
| for (size_t p = FIRST_DML_COL_PRIV; p <= LAST_DML_COL_PRIV; p++ ) |
| { |
| if (!isDMLPrivType(static_cast<PrivType>(p))) |
| continue; |
| |
| // See if any WGO statement exist |
| if (hasWGO[p]) |
| { |
| closeColumnList(WGOString[p]); |
| withWGO += WGOString[p]; |
| // Reset to original value |
| WGOString[p].assign(PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p) + "("); |
| hasWGO[p] = false; |
| } |
| |
| // See if any WGO statement exist |
| if (hasPriv[p]) |
| { |
| closeColumnList(privString[p]); |
| withoutWGO += privString[p]; |
| // Reset to original value |
| privString[p].assign(PrivMgrUserPrivs::convertPrivTypeToLiteral((PrivType)p) + "("); |
| hasPriv[p] = false; |
| } |
| } |
| mergeStrings = false; |
| } |
| }//End of PrivLevel::COLUMN |
| |
| if (!withoutWGO.empty()) |
| buildGrantText(withoutWGO,objectGranteeText, |
| grantorID,grantorName,false, |
| objectInfo.getObjectOwner(),grantStmt); |
| |
| if (!withWGO.empty()) |
| buildGrantText(withWGO,objectGranteeText, |
| grantorID,grantorName,true, |
| objectInfo.getObjectOwner(),grantWGOStmt); |
| privilegeText += grantStmt + grantWGOStmt; |
| grantStmt.clear(); |
| grantWGOStmt.clear(); |
| } |
| |
| return STATUS_GOOD; |
| |
| } |
| //*************************** End of buildPrivText ***************************** |
| |
| |
| // ***************************************************************************** |
| // * Function: buildGrantText * |
| // * * |
| // * Builds GRANT statement. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <privText> const std::string & In * |
| // * is the privileges granted. * |
| // * * |
| // * <objectGranteeText> const std::string & In * |
| // * is the object the privileges are granted on and to whom. * |
| // * * |
| // * <grantorID> const int32_t In * |
| // * is the ID of the authID who granted the privilege(s). If the system * |
| // * (_SYSTEM) granted the privilege, the command is prefixed with "--" to * |
| // * prevent execution in a playback script. * |
| // * * |
| // * <isWGO> bool In * |
| // * if true, add the clause WITH GRANT OPTION to the command. * |
| // * * |
| // * <grantText> std::string & Out * |
| // * passes back the grant command. * |
| // * * |
| // ***************************************************************************** |
| void static buildGrantText( |
| const std::string & privText, |
| const std::string & objectGranteeText, |
| const int32_t grantorID, |
| const std::string grantorName, |
| bool isWGO, |
| const int32_t objectOwner, |
| std::string & grantText) |
| |
| { |
| |
| if (grantorID == SYSTEM_USER) |
| grantText += "-- "; |
| |
| grantText += "GRANT "; |
| grantText += privText; |
| |
| // remove last ',' |
| size_t commaPos = grantText.find_last_of(","); |
| |
| if (commaPos != std::string::npos) |
| grantText.replace(commaPos, 1, ""); |
| |
| grantText += objectGranteeText; |
| |
| if (isWGO) |
| grantText += " WITH GRANT OPTION"; |
| else |
| |
| if (grantorID != objectOwner && |
| grantorID != SYSTEM_USER) |
| { |
| grantText += " GRANTED BY "; |
| bool delimited = isDelimited(grantorName); |
| if (delimited) |
| grantText += "\""; |
| grantText += grantorName; |
| if (delimited) |
| grantText += "\""; |
| } |
| |
| grantText += ";\n"; |
| |
| } |
| //*************************** End of buildGrantText **************************** |
| |
| |
| // ***************************************************************************** |
| // * Function: closeColumnList * |
| // * * |
| // * This function closes a list of the form "(column, column, column, ...".* |
| // * The last comma is removed and a closing parenthesis is added. * |
| // * * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <columnList> const std::string & In/Out * |
| // * is the list of columns in string. * |
| // * * |
| // ***************************************************************************** |
| void static closeColumnList(std::string & columnList) |
| |
| { |
| |
| size_t commaPos = columnList.find_last_of(","); |
| |
| // If there is no comma in the string, input not recognized, return unchanged. |
| if (commaPos == std::string::npos) |
| return; |
| |
| // Replace the trailing comma and space with a parenthesis and trailing comma. |
| // Add an additional trailing space for readability. |
| columnList.replace(commaPos,2,"),"); |
| columnList += " "; |
| |
| } |
| //************************** End of closeColumnList **************************** |
| |
| // ***************************************************************************** |
| // * * |
| // * Function: deleteRowList * |
| // * * |
| // * Deletes elements from a vector of PrivMgrMDRows. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <rowList> std::vector<PrivMgrMDRow *> & In/Out * |
| // * is the list of rows to delete. * |
| // * * |
| // * * |
| // ***************************************************************************** |
| static void deleteRowList(std::vector<PrivMgrMDRow *> & rowList) |
| |
| { |
| |
| while(!rowList.empty()) |
| delete rowList.back(), rowList.pop_back(); |
| |
| } |
| //************************** End of deleteRowList ***************************** |
| |
| |
| |
| // ***************************************************************************** |
| // * Function: findColumnEntry * |
| // * * |
| // * This function searches a vector of PrivMgrCoreDesc for a matching * |
| // * column ordinal. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * * |
| // * <colPrivEntries> NAList<PrivMgrCoreDesc> & In * |
| // * is a reference to a vector of ColPrivEntry. * |
| // * * |
| // * <columnOrdinal> const int32_t In * |
| // * is the column ordinal to search for. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Returns: PrivMgrCoreDesc * |
| // * * |
| // * NULL: No entry found with that column ordinal * |
| // * *: Entry found with matching column ordinal * |
| // * * |
| // ***************************************************************************** |
| static PrivMgrCoreDesc * findColumnEntry( |
| NAList<PrivMgrCoreDesc> & colPrivEntries, |
| const int32_t columnOrdinal) |
| |
| { |
| for (size_t i = 0; i < colPrivEntries.entries(); i++) |
| if (colPrivEntries[i].getColumnOrdinal() == columnOrdinal) |
| return & colPrivEntries[i]; |
| |
| return NULL; |
| } |
| //************************** End of findColumnEntry **************************** |
| |
| |
| // ***************************************************************************** |
| // * Function: getColRowsForGranteeGrantor * |
| // * * |
| // * Returns the list of column privileges granted for the object that have * |
| // * been granted by the grantorID to the granteeID. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <columnRowList> std::vector <PrivMgrMDRow *> & In * |
| // * is the list of column privileges granted to the object. * |
| // * * |
| // * <granteeID> const int32_t In * |
| // * is the authID granted the privileges. * |
| // * * |
| // * <grantorID> const int32_t In * |
| // * is the authID who granted the privileges. * |
| // * * |
| // * <grantedColPrivs> NAList<PrivMgrCoreDesc> & Out * |
| // * passes back a privileges granted to <granteeID> by <grantorID>. * |
| // * * |
| // ***************************************************************************** |
| static void getColRowsForGranteeGrantor( |
| const std::vector <PrivMgrMDRow *> &columnRowList, |
| const int32_t granteeID, |
| const int32_t grantorID, |
| NAList<PrivMgrCoreDesc> & grantedColPrivs) |
| |
| { |
| |
| for (size_t i = 0; i < columnRowList.size(); ++i) |
| { |
| ColumnPrivsMDRow &row = static_cast<ColumnPrivsMDRow &> (*columnRowList[i]); |
| PrivMgrCoreDesc colPrivGrant; |
| |
| if (row.grantorID_ == grantorID && row.granteeID_ == granteeID) |
| { |
| colPrivGrant.setColumnOrdinal(row.columnOrdinal_); |
| colPrivGrant.setPrivBitmap(row.privsBitmap_.to_ulong()); |
| colPrivGrant.setWgoBitmap(row.grantableBitmap_.to_ulong()); |
| |
| grantedColPrivs.insert(colPrivGrant); |
| } |
| } |
| |
| } |
| //******************* End of getColRowsForGranteeGrantor *********************** |
| |
| |
| // ***************************************************************************** |
| // * Function: hasAllDMLPrivs * |
| // * * |
| // * This function determines if a privilege bitmap has all the DML * |
| // * privileges for a specified object type. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <objectType> ComObjectType In * |
| // * is the type of the object. * |
| // * * |
| // * <privBitmap> PrivObjectBitmap In * |
| // * is the bitmap representing the privileges. * |
| // * * |
| // ***************************************************************************** |
| static bool hasAllDMLPrivs( |
| ComObjectType objectType, |
| PrivObjectBitmap privBitmap) |
| |
| { |
| |
| switch (objectType) |
| { |
| case COM_BASE_TABLE_OBJECT: |
| case COM_VIEW_OBJECT: |
| if (privBitmap.test(DELETE_PRIV) && privBitmap.test(INSERT_PRIV) && |
| privBitmap.test(REFERENCES_PRIV) && privBitmap.test(SELECT_PRIV) && |
| privBitmap.test(UPDATE_PRIV)) |
| return true; |
| break; |
| case COM_LIBRARY_OBJECT: |
| if (privBitmap.test(UPDATE_PRIV) && privBitmap.test(USAGE_PRIV)) |
| return true; |
| break; |
| case COM_STORED_PROCEDURE_OBJECT: |
| case COM_USER_DEFINED_ROUTINE_OBJECT: |
| if (privBitmap.test(EXECUTE_PRIV)) |
| return true; |
| break; |
| case COM_SEQUENCE_GENERATOR_OBJECT: |
| if (privBitmap.test(USAGE_PRIV)) |
| return true; |
| break; |
| default: |
| return false; |
| } |
| |
| return false; |
| |
| } |
| //************************** End of hasAllDMLPrivs ***************************** |
| |
| |
| // ***************************************************************************** |
| // * * |
| // * Function: isDelimited * |
| // * * |
| // * This function checks the passed in string for characters other than * |
| // * alphanumeric and underscore characters. If so, the name is delimited * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <strToScan> const std::string & In * |
| // * is the string to search for delimited characters * |
| // ***************************************************************************** |
| // * * |
| // * Returns: bool * |
| // * * |
| // * true: the passed in string contains delimited characters * |
| // * false: the passed in string contains no delimited characters * |
| // * * |
| // ***************************************************************************** |
| static bool isDelimited( const std::string &strToScan) |
| { |
| char firstChar = strToScan[0]; |
| if (isdigit(firstChar) || strToScan[0] == '_' ) |
| return true; |
| string validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; |
| size_t found = strToScan.find_first_not_of(validChars); |
| if (found == string::npos) |
| return false; |
| return true; |
| } |
| //*********************** End of isDelimited *********************************** |
| |
| |
| |
| // ***************************************************************************** |
| // method: reportPrivWarnings |
| // |
| // Ansi states that when a grant statement is executed, a set of privilege |
| // descriptors (CPD) is created based on existing privileges for the object and |
| // object’s columns. Each CPD contains the grantee, action (privileges), object, |
| // column and grantor. A similar list of privilege descriptors is created based |
| // on the grant/revoke statement (GPD). |
| // |
| // If there is an element in the GPD (what the user requested) that is not in |
| // the CPD (what was actually granted/revoked), then a warning – privilege not |
| // granted/revoked is displayed. |
| // |
| // This method compares the list of actual privileges granted/revoked |
| // (actualPrivs)to the list privileges requested (origPrivs). If a privilege |
| // was requested but not granted/revoked report a warning. |
| // ***************************************************************************** |
| void PrivMgrPrivileges::reportPrivWarnings( |
| const PrivMgrDesc &origPrivs, |
| const PrivMgrDesc &actualPrivs, |
| const CatErrorCode warningCode) |
| { |
| PrivMgrCoreDesc objPrivsNotApplied = origPrivs.getTablePrivs(); |
| objPrivsNotApplied.suppressDuplicatedPrivs(actualPrivs.getTablePrivs()); |
| if (!objPrivsNotApplied.isNull()) |
| { |
| for ( size_t i = FIRST_DML_PRIV; i <= LAST_DML_PRIV; i++ ) |
| { |
| PrivType privType = PrivType(i); |
| if (objPrivsNotApplied.getPriv(privType)) |
| { |
| *pDiags_ << DgSqlCode(warningCode) |
| << DgString0(PrivMgrUserPrivs::convertPrivTypeToLiteral(privType).c_str()); |
| } |
| } |
| } |
| |
| NAList<PrivMgrCoreDesc> colPrivs = origPrivs.getColumnPrivs(); |
| for (int i = 0; i < colPrivs.entries(); i++) |
| { |
| PrivMgrCoreDesc colPrivsNotApplied = colPrivs[i]; |
| |
| int index = actualPrivs.getColumnPriv(i); |
| if (index >= 0) |
| { |
| PrivMgrCoreDesc colPrivsActual = actualPrivs.getColumnPrivs()[index]; |
| colPrivsNotApplied.suppressDuplicatedPrivs(colPrivsActual); |
| } |
| |
| if (!colPrivsNotApplied.isNull()) |
| { |
| for ( size_t j = FIRST_DML_PRIV; j <= LAST_DML_PRIV; j++ ) |
| { |
| PrivType privType = PrivType(j); |
| if (colPrivsNotApplied.getPriv(privType)) |
| { |
| // would be better to add column name instead of number |
| // would require an I/O to read COLUMNS to get the name |
| // associated with the number |
| char privStr[100]; |
| snprintf(privStr, sizeof(privStr), "%s (column number %d) ", |
| PrivMgrUserPrivs::convertPrivTypeToLiteral(privType).c_str(), |
| colPrivsNotApplied.getColumnOrdinal()); |
| *pDiags_ << DgSqlCode(warningCode) |
| << DgString0(privStr); |
| } |
| } |
| } |
| } |
| } |
| |
| // ***************************************************************************** |
| // ObjectPrivsMDRow methods |
| // ***************************************************************************** |
| |
| void ObjectPrivsMDRow::describeRow (std::string &rowDetails) |
| { |
| rowDetails = "OBJECT_PRIVILEGES row: type is "; |
| char objectTypeLit[3] = {0}; |
| strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(objectType_),2); |
| rowDetails += objectTypeLit; |
| rowDetails += ", UID is "; |
| rowDetails += to_string((long long int) objectUID_); |
| rowDetails += ", grantor is "; |
| rowDetails += to_string((long long int)grantorID_); |
| rowDetails += ", grantee is "; |
| rowDetails += to_string((long long int) granteeID_); |
| } |
| |
| |
| // ***************************************************************************** |
| // ObjectPrivsMDTable methods |
| // ***************************************************************************** |
| |
| // ***************************************************************************** |
| // * method: ObjectPrivsMDTable::selectWhereUnique |
| // * |
| // * Select the row from the OBJECT_PRIVILEGES table based on the specified |
| // * WHERE clause - where clause should only return a single row |
| // * |
| // * Parameters: |
| // * |
| // * <whereClause> is the WHERE clause specifying a unique row. |
| // * <rowOut> passes back a set of OBJECT_PRIVILEGES rows |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Row returned. |
| // * *: Select failed. A CLI error is put into the diags area. |
| // ***************************************************************************** |
| PrivStatus ObjectPrivsMDTable::selectWhereUnique( |
| const std::string & whereClause, |
| PrivMgrMDRow & rowOut) |
| { |
| ObjectPrivsMDRow & row = static_cast<ObjectPrivsMDRow &>(rowOut); |
| |
| PrivStatus retcode = STATUS_GOOD; |
| // Should space be allocated and deleted from the heap for the rowList? |
| // -- how many rows will be returned? |
| std::vector<PrivMgrMDRow* > rowList; |
| std::string orderByClause; |
| retcode = selectWhere(whereClause, orderByClause, rowList); |
| if (retcode == STATUS_GOOD) |
| { |
| // The I/O should be performed on a primary key so only one row returned |
| // If not, return an internal error |
| if (rowList.size() != 1) |
| { |
| while(!rowList.empty()) |
| delete rowList.back(), rowList.pop_back(); |
| PRIVMGR_INTERNAL_ERROR("Select unique for object_privileges table returned more than 1 row"); |
| return STATUS_ERROR; |
| } |
| row = static_cast<ObjectPrivsMDRow &>(*rowList[0]); |
| } |
| while(!rowList.empty()) |
| delete rowList.back(), rowList.pop_back(); |
| return retcode; |
| } |
| |
| // ***************************************************************************** |
| // * method: ObjectPrivsMDTable::selectWhere |
| // * |
| // * Selects rows from the OBJECT_PRIVILEGES table based on the specified |
| // * WHERE clause. |
| // * |
| // * Parameters: |
| // * |
| // * <whereClause> is the WHERE clause |
| // * <orderByClause> is the ORDER BY clause defining returned row order. |
| // * <rowOut> passes back a set of OBJECT_PRIVILEGES rows |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Row returned. |
| // * *: Select failed. A CLI error is put into the diags area. |
| // ***************************************************************************** |
| PrivStatus ObjectPrivsMDTable::selectWhere( |
| const std::string & whereClause, |
| const std::string & orderByClause, |
| std::vector<PrivMgrMDRow *> &rowList) |
| { |
| std::string selectStmt ("SELECT OBJECT_UID, OBJECT_NAME, OBJECT_TYPE, "); |
| selectStmt += ("GRANTEE_ID, GRANTEE_NAME, GRANTEE_TYPE, "); |
| selectStmt += ("GRANTOR_ID, GRANTOR_NAME, GRANTOR_TYPE, "); |
| selectStmt += ("PRIVILEGES_BITMAP, GRANTABLE_BITMAP FROM "); |
| selectStmt += tableName_; |
| selectStmt += " "; |
| selectStmt += whereClause; |
| selectStmt += orderByClause; |
| |
| // set pointer in diags area |
| int32_t diagsMark = pDiags_->mark(); |
| |
| ExeCliInterface cliInterface(STMTHEAP, 0, NULL, |
| CmpCommon::context()->sqlSession()->getParentQid()); |
| Queue * tableQueue = NULL; |
| int32_t cliRC = cliInterface.fetchAllRows(tableQueue, (char *)selectStmt.c_str(), 0, false, false, true); |
| |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| if (cliRC == 100) // did not find the row |
| { |
| pDiags_->rewind(diagsMark); |
| return STATUS_NOTFOUND; |
| } |
| |
| tableQueue->position(); |
| for (int idx = 0; idx < tableQueue->numEntries(); idx++) |
| { |
| OutputInfo * pCliRow = (OutputInfo*)tableQueue->getNext(); |
| ObjectPrivsMDRow *pRow = new ObjectPrivsMDRow(); |
| setRow(pCliRow, *pRow); |
| rowList.push_back(pRow); |
| } |
| |
| return STATUS_GOOD; |
| } |
| |
| // ***************************************************************************** |
| // * method: ObjectPrivsMDTable::setRow |
| // * |
| // * Create an ObjectPrivsMDRow object from the information returned from the |
| // * cli. |
| // * |
| // * Parameters: |
| // * |
| // * <OutputInfo> row destails from the cli |
| // * <rowOut> passes back the ObjectPrivsMDRow row |
| // * |
| // * no errors should be generated |
| // ***************************************************************************** |
| // Row read successfully. Extract the columns. |
| void ObjectPrivsMDTable::setRow (OutputInfo *pCliRow, |
| ObjectPrivsMDRow &row) |
| { |
| char * ptr = NULL; |
| Int32 len = 0; |
| char value[500]; |
| |
| // column 1: object uid |
| pCliRow->get(0,ptr,len); |
| row.objectUID_ = *(reinterpret_cast<int64_t*>(ptr)); |
| |
| // column 2: object name |
| pCliRow->get(1,ptr,len); |
| assert (len < 257); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.objectName_ = value; |
| |
| // column 3: object type |
| pCliRow->get(2,ptr,len); |
| assert (len < 3); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.objectType_ = PrivMgr::ObjectLitToEnum(value); |
| |
| // column 4: grantee uid |
| pCliRow->get(3,ptr,len); |
| row.granteeID_ = *(reinterpret_cast<int32_t*>(ptr)); |
| |
| // column 5: grantee name |
| pCliRow->get(4,ptr,len); |
| assert (len < 257); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.granteeName_ = value; |
| |
| // column 6: grantee type |
| pCliRow->get(5,ptr,len); |
| assert (len < 3); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.granteeType_ = value; |
| |
| // column 7: grantor uid |
| pCliRow->get(6,ptr,len); |
| row.grantorID_ = *(reinterpret_cast<int32_t*>(ptr)); |
| |
| //column 8: grantor name |
| pCliRow->get(7,ptr,len); |
| assert (len < 257); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.grantorName_ = value; |
| |
| //column 9: grantor type |
| pCliRow->get(8,ptr,len); |
| assert (len < 3); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.grantorType_ = value; |
| |
| // column 10: privileges bitmap |
| pCliRow->get(9,ptr,len); |
| int64_t bitmapInt = *(reinterpret_cast<int64_t*>(ptr)); |
| row.privsBitmap_ = bitmapInt; |
| |
| // column 11: grantable bitmap |
| pCliRow->get(10,ptr,len); |
| bitmapInt = *(reinterpret_cast<int64_t*>(ptr)); |
| row.grantableBitmap_ = bitmapInt; |
| |
| // set current_ |
| PrivMgrCoreDesc tempDesc (row.privsBitmap_, row.grantableBitmap_); |
| row.current_= tempDesc; |
| row.visited_.setAllPrivAndWgo(false); |
| } |
| |
| // ***************************************************************************** |
| // * method: ObjectPrivsMDTable::insert |
| // * |
| // * Inserts a row into the OBJECT_PRIVILEGES table. |
| // * |
| // * Parameters: |
| // * |
| // * <rowIn> is a ObjectPrivsMDRow to be inserted. |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Row inserted. |
| // * *: Insert failed. A CLI error is put into the diags area. |
| // ***************************************************************************** |
| PrivStatus ObjectPrivsMDTable::insert(const PrivMgrMDRow &rowIn) |
| { |
| |
| char insertStmt[2000]; |
| const ObjectPrivsMDRow &row = static_cast<const ObjectPrivsMDRow &>(rowIn); |
| |
| int64_t privilegesBitmapLong = row.privsBitmap_.to_ulong(); |
| int64_t grantableBitmapLong = row.grantableBitmap_.to_ulong(); |
| char objectTypeLit[3] = {0}; |
| |
| strncpy(objectTypeLit,PrivMgr::ObjectEnumToLit(row.objectType_),2); |
| |
| sprintf(insertStmt, "insert into %s values (%ld, '%s', '%s', %d, '%s', '%s', %d, '%s', '%s', %ld, %ld)", |
| tableName_.c_str(), |
| row.objectUID_, |
| row.objectName_.c_str(), |
| objectTypeLit, |
| row.granteeID_, |
| row.granteeName_.c_str(), |
| row.granteeType_.c_str(), |
| row.grantorID_, |
| row.grantorName_.c_str(), |
| row.grantorType_.c_str(), |
| privilegesBitmapLong, |
| grantableBitmapLong); |
| |
| ExeCliInterface cliInterface(STMTHEAP, 0, NULL, |
| CmpCommon::context()->sqlSession()->getParentQid()); |
| int32_t cliRC = cliInterface.executeImmediate(insertStmt); |
| |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(pDiags_); |
| return STATUS_ERROR; |
| } |
| |
| // For some reason, insert sometimes returns error even though |
| // the row is inserted, so unless an errors, return STATUS_GOOD |
| return STATUS_GOOD; |
| |
| } |
| |
| // ***************************************************************************** |
| // * method: ObjectPrivsMDTable::deleteRow |
| // * |
| // * Deletes a row from the OBJECT_PRIVILEGES table based on the primary key |
| // * contents of the row. |
| // * |
| // * Parameters: |
| // * |
| // * <row> defines what row should be deleted |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Row deleted. |
| // * *: Insert failed. A CLI error is put into the diags area. |
| // ***************************************************************************** |
| PrivStatus ObjectPrivsMDTable::deleteRow(const ObjectPrivsMDRow & row) |
| |
| { |
| |
| char whereClause[1000]; |
| |
| sprintf(whereClause," WHERE object_uid = %ld AND grantor_id = %d AND grantee_id = %d ", |
| row.objectUID_,row.grantorID_,row.granteeID_); |
| |
| return deleteWhere(whereClause); |
| |
| } |
| |
| |
| // ***************************************************************************** |
| // * method: ObjectPrivsMDTable::deleteWhere |
| // * |
| // * Deletes a row from the OBJECT_PRIVILEGES table based on the where clause |
| // * |
| // * Parameters: |
| // * |
| // * <whereClause> defines what rows should be deleted |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Row(s) deleted. |
| // * *: Insert failed. A CLI error is put into the diags area. |
| // ***************************************************************************** |
| PrivStatus ObjectPrivsMDTable::deleteWhere(const std::string & whereClause) |
| { |
| std::string deleteStmt ("DELETE FROM "); |
| deleteStmt += tableName_; |
| deleteStmt += " "; |
| deleteStmt += whereClause; |
| |
| // set pointer in diags area |
| int32_t diagsMark = pDiags_->mark(); |
| |
| ExeCliInterface cliInterface(STMTHEAP, 0, NULL, |
| CmpCommon::context()->sqlSession()->getParentQid()); |
| |
| int32_t cliRC = cliInterface.executeImmediate(deleteStmt.c_str()); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| |
| |
| if (cliRC == 100) // did not find any rows |
| { |
| pDiags_->rewind(diagsMark); |
| return STATUS_NOTFOUND; |
| } |
| |
| if (cliRC > 0) |
| return STATUS_WARNING; |
| |
| return STATUS_GOOD; |
| } |
| |
| // ***************************************************************************** |
| // * method: ObjectPrivsMDTable::updateRow |
| // * |
| // * Updates grantor and bitmaps for a row in the OBJECT_PRIVILEGES table |
| // * based on the contents of the row. |
| // * |
| // * Parameters: |
| // * |
| // * <row> defines what row should be updated |
| // * |
| // * Returns: PrivStatus |
| // * |
| // * STATUS_GOOD: Row(s) deleted. |
| // * *: Insert failed. A CLI error is put into the diags area. |
| // ***************************************************************************** |
| PrivStatus ObjectPrivsMDTable::updateRow(const ObjectPrivsMDRow & row) |
| |
| { |
| |
| char setClause[1000]; |
| int64_t privilegesBitmapLong = row.privsBitmap_.to_ulong(); |
| int64_t grantableBitmapLong = row.grantableBitmap_.to_ulong(); |
| |
| sprintf(setClause," SET grantor_id = %d, grantor_name = '%s', " |
| " privileges_bitmap = %ld, grantable_bitmap = %ld ", |
| row.grantorID_,row.grantorName_.c_str(),privilegesBitmapLong,grantableBitmapLong); |
| |
| char whereClause[1000]; |
| |
| sprintf(whereClause," WHERE object_uid = %ld AND grantor_id = %d AND grantee_id = %d ", |
| row.objectUID_,row.grantorID_,row.granteeID_); |
| |
| return updateWhere(setClause,whereClause); |
| |
| } |
| |
| |
| |
| // ---------------------------------------------------------------------------- |
| // method: updateWhere |
| // |
| // This method updates one or more rows from the OBJECT_PRIVILEGES table |
| // The number of rows affected depend on the passed in set clause |
| // |
| // Input: setClause |
| // whereClause |
| // Output: status of the operation |
| // |
| // A cli error is put into the diags area if there is an error |
| // ---------------------------------------------------------------------------- |
| PrivStatus ObjectPrivsMDTable::updateWhere(const std::string & setClause, |
| const std::string & whereClause) |
| { |
| std::string updateStmt ("UPDATE "); |
| updateStmt += tableName_; |
| updateStmt += " "; |
| updateStmt += setClause; |
| updateStmt += " "; |
| updateStmt += whereClause; |
| |
| // set pointer in diags area |
| int32_t diagsMark = pDiags_->mark(); |
| |
| ExeCliInterface cliInterface(STMTHEAP, 0, NULL, |
| CmpCommon::context()->sqlSession()->getParentQid()); |
| int32_t cliRC = cliInterface.executeImmediate(updateStmt.c_str()); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| |
| if (cliRC == 100) // did not find any rows |
| { |
| pDiags_->rewind(diagsMark); |
| return STATUS_NOTFOUND; |
| } |
| |
| if (cliRC > 0) |
| return STATUS_WARNING; |
| |
| return STATUS_GOOD; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // method::insertSelect |
| // |
| // This method inserts owner rows into the OBJECT_PRIVILEGES table |
| // |
| // Input: objectsLocation - name of objects table |
| // authsLocation - name of auths table |
| // |
| // Output: PrivStatus |
| // |
| // the following is a sample insert select statement that gets processed: |
| // |
| // insert into OBJECT_PRIVILEGES |
| // select distinct |
| // object_uid, |
| // <catalogName> "<schema_name>"."<object_name>", |
| // object_type, |
| // object_owner, -- granteeID |
| // coalesce((select auth_db_name from AUTHS where auth_id = object_owner), |
| // 'DB__ROOT') --granteeName |
| // USER_GRANTEE_LIT, -- "U" |
| // SYSTEM_USER, -- system grantor ID (-2) |
| // SYSTEM_AUTH_NAME, -- grantorName (_SYSTEM) |
| // SYSTEM_GRANTOR_LIST, -- "S" |
| // case |
| // when object_type = 'BT' then 47 |
| // when object_type = 'VI' then 1 |
| // when object_type = 'LB' then 24 |
| // when object_type = 'UR' then 64 |
| // when object_type = 'SG' then 16 |
| // else 0 |
| // end as privilegesBitmap, |
| // case |
| // when object_type = 'BT' then 47 |
| // when object_type = 'VI' then 0 |
| // when object_type = 'LB' then 24 |
| // when object_type = 'UR' then 0 |
| // when object_type = 'SG' then 16 |
| // else 0 |
| // end as grantableBitmap |
| // from OBJECTS |
| // where object_type in ('VI','BT','LB','UR','SG') |
| // |
| // The "coalesce" for the granteeName above is in case the auth_id is |
| // invalid (that is, does not appear in the AUTHS table). If we don't |
| // know who the auth_id is, we'll put DB__ROOT, the super user, there. |
| // |
| // The ComDiags area is set up with unexpected errors |
| // ---------------------------------------------------------------------------- |
| PrivStatus ObjectPrivsMDTable::insertSelect( |
| const std::string &objectsLocation, |
| const std::string &authsLocation) |
| { |
| // Before inserting rows, make sure that the OBJECT_PRIVILEGES table is empty |
| char buf[2000]; |
| sprintf(buf, "select count(*) from %s", tableName_.c_str()); |
| Int64 rowsSelected = 0; |
| Lng32 theLen = 0; |
| ExeCliInterface cliInterface(STMTHEAP, 0, NULL, |
| CmpCommon::context()->sqlSession()->getParentQid()); |
| int32_t cliRC = cliInterface.executeImmediate(buf, (char*)&rowsSelected, &theLen, FALSE); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| |
| if (rowsSelected != 0) |
| { |
| std::string message ("Found "); |
| message += to_string((long long int)rowsSelected); |
| message += " rows in OBJECT_PRIVILEGES table, expecting 0 rows"; |
| PRIVMGR_INTERNAL_ERROR(message.c_str()); |
| return STATUS_ERROR; |
| } |
| |
| // Create bitmaps for all supported object types; |
| PrivMgrDesc privDesc; |
| privDesc.setAllTableGrantPrivileges(true); |
| int64_t tableBits = privDesc.getTablePrivs().getPrivBitmap().to_ulong(); |
| |
| privDesc.setAllLibraryGrantPrivileges(true); |
| int64_t libraryBits = privDesc.getTablePrivs().getPrivBitmap().to_ulong(); |
| |
| privDesc.setAllUdrGrantPrivileges(true); |
| int64_t udrBits = privDesc.getTablePrivs().getPrivBitmap().to_ulong(); |
| |
| privDesc.setAllSequenceGrantPrivileges(true); |
| int64_t sequenceBits = privDesc.getTablePrivs().getPrivBitmap().to_ulong(); |
| |
| // for views, privilegesBitmap is set to 1 (SELECT), wgo to 0 (no) |
| std::string systemGrantor(SYSTEM_AUTH_NAME); |
| |
| // Generate case stmt for grantable bitmap |
| sprintf (buf, "case when object_type = 'BT' then %ld " |
| " when object_type = 'VI' then 1 " |
| " when object_type = 'LB' then %ld " |
| " when object_type = 'UR' then %ld " |
| " when object_type = 'SG' then %ld " |
| " else 0 end", |
| tableBits, libraryBits, udrBits, sequenceBits); |
| std::string privilegesClause(buf); |
| |
| sprintf (buf, "case when object_type = 'BT' then %ld " |
| " when object_type = 'VI' then 0 " |
| " when object_type = 'LB' then %ld " |
| " when object_type = 'UR' then %ld " |
| " when object_type = 'SG' then %ld " |
| " else 0 end", |
| tableBits, libraryBits, udrBits, sequenceBits); |
| std::string grantableClause(buf); |
| |
| sprintf(buf, "insert into %s select distinct object_uid, " |
| "trim(catalog_name) || '.\"' || trim(schema_name) || '\".\"' || trim(object_name) || '\"', " |
| "object_type, object_owner, " |
| "coalesce((select auth_db_name from %s where auth_id = o.object_owner),'DB__ROOT') as auth_db_name, " |
| "'%s', %d, '%s', '%s', %s, %s from %s o " |
| "where o.object_type in ('VI','BT','LB','UR','SG')", |
| tableName_.c_str(), |
| authsLocation.c_str(), |
| USER_GRANTEE_LIT, |
| SYSTEM_USER, SYSTEM_AUTH_NAME, SYSTEM_GRANTOR_LIT, |
| privilegesClause.c_str(), grantableClause.c_str(), |
| objectsLocation.c_str()); |
| |
| // set pointer in diags area |
| int32_t diagsMark = pDiags_->mark(); |
| |
| Int64 rowsInserted = 0; |
| cliRC = cliInterface.executeImmediate(buf, NULL, NULL, FALSE, &rowsInserted); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| |
| // Bug: for some reasons, insert returns NOTFOUND even though the |
| // operations succeeded. |
| if (cliRC == 100) |
| { |
| pDiags_->rewind(diagsMark); |
| cliRC = 0; |
| } |
| |
| // Make sure rows were inserted correctly. |
| // Get the expected number of rows |
| sprintf(buf, "select count(*) from %s o where o.object_type in ('VI','BT','LB','UR', 'SG')" |
| " and object_owner > 0", |
| objectsLocation.c_str()); |
| Lng32 len = 0; |
| cliRC = cliInterface.executeImmediate(buf, (char*)&rowsSelected, &len, FALSE); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| |
| // Check to see if the number of rows selected match the rows inserted |
| if (rowsInserted != rowsSelected) |
| { |
| std::string message ("Expected to insert "); |
| message += to_string((long long int)rowsSelected); |
| message += " rows into OBJECT_PRIVILEGES table, instead "; |
| message += to_string((long long int)rowsInserted); |
| message += " were found."; |
| PRIVMGR_INTERNAL_ERROR(message.c_str()); |
| return STATUS_ERROR; |
| } |
| |
| |
| return STATUS_GOOD; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method::insertSelect |
| // |
| // This method inserts a grant of SELECT on the AUTHS table to PUBLIC |
| // into the OBJECT_PRIVILEGES table |
| // |
| // Input: objectsLocation - name of objects table |
| // authsLocation - name of auths table |
| // |
| // Output: PrivStatus |
| // |
| // The ComDiags area is set up with unexpected errors |
| // ---------------------------------------------------------------------------- |
| PrivStatus ObjectPrivsMDTable::insertSelectOnAuthsToPublic( |
| const std::string &objectsLocation, |
| const std::string &authsLocation) |
| { |
| |
| char buf[2000]; |
| |
| sprintf(buf, "insert into %s select o.object_uid,'%s','BT',-1,'PUBLIC','U'," |
| "%d,'DB__ROOT','U',1,0 FROM %s O WHERE O.OBJECT_NAME = 'AUTHS'", |
| tableName_.c_str(),authsLocation.c_str(), MIN_USERID, objectsLocation.c_str()); |
| |
| // set pointer in diags area |
| int32_t diagsMark = pDiags_->mark(); |
| |
| Int64 rowsInserted = 0; |
| ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, |
| CmpCommon::context()->sqlSession()->getParentQid()); |
| int32_t cliRC = cliInterface.executeImmediate(buf, NULL, NULL, FALSE, &rowsInserted); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| |
| // Bug: for some reasons, insert returns NOTFOUND even though the |
| // operations succeeded. |
| if (cliRC == 100) |
| { |
| pDiags_->rewind(diagsMark); |
| cliRC = 0; |
| } |
| |
| return STATUS_GOOD; |
| |
| } |
| |
| // ***************************************************************************** |
| // ColumnPrivsMDRow methods |
| // ***************************************************************************** |
| |
| void ColumnPrivsMDRow::describeRow (std::string &rowDetails) |
| { |
| rowDetails = "COLUMN_PRIVILEGES row: UID is "; |
| rowDetails += to_string((long long int) objectUID_); |
| rowDetails += ", column number is "; |
| rowDetails += to_string((long long int) columnOrdinal_); |
| rowDetails += ", grantor is "; |
| rowDetails += to_string((long long int)grantorID_); |
| rowDetails += ", grantee is "; |
| rowDetails += to_string((long long int) granteeID_); |
| } |
| |
| // ***************************************************************************** |
| // ColumnPrivsMDTable methods |
| // ***************************************************************************** |
| |
| // ***************************************************************************** |
| // * * |
| // * Function: ColumnPrivsMDTable::insert * |
| // * * |
| // * Inserts a row into the COLUMN_PRIVILEGES table. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <rowIn> const PrivMgrMDRow & In * |
| // * is a ColumnPrivsMDRow to be inserted. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Returns: PrivStatus * |
| // * * |
| // * STATUS_GOOD: Row inserted. * |
| // * *: Insert failed. A CLI error is put into the diags area. * |
| // * * |
| // ***************************************************************************** |
| PrivStatus ColumnPrivsMDTable::insert(const PrivMgrMDRow &rowIn) |
| |
| { |
| |
| char insertStmt[2000]; |
| const ColumnPrivsMDRow &row = static_cast<const ColumnPrivsMDRow &>(rowIn); |
| |
| int64_t privilegesBitmapLong = row.privsBitmap_.to_ulong(); |
| int64_t grantableBitmapLong = row.grantableBitmap_.to_ulong(); |
| |
| sprintf(insertStmt, "INSERT INTO %s VALUES (%ld, '%s', %d, '%s', %d, '%s', %d, %ld, %ld)", |
| tableName_.c_str(), |
| row.objectUID_, |
| row.objectName_.c_str(), |
| row.granteeID_, |
| row.granteeName_.c_str(), |
| row.grantorID_, |
| row.grantorName_.c_str(), |
| row.columnOrdinal_, |
| privilegesBitmapLong, |
| grantableBitmapLong); |
| |
| return CLIImmediate(insertStmt); |
| |
| } |
| //********************* End of ColumnPrivsMDTable::insert ********************** |
| |
| // ***************************************************************************** |
| // * * |
| // * Function: ColumnPrivsMDTable::selectWhere * |
| // * * |
| // * Selects rows from the COLUMN_PRIVILEGES table based on the specified * |
| // * WHERE clause. Output is sorted by grantor, grantee, column in that order.* |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <whereClause> const std::string & In * |
| // * is the WHERE clause specifying a unique row. * |
| // * * |
| // * <orderByClause> is the ORDER BY clause defining returned row order. |
| // * <rowList> std::vector<PrivMgrMDRow *> & Out * |
| // * passes back a set of ColumnPrivsMDRow rows. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Returns: PrivStatus * |
| // * * |
| // * STATUS_GOOD: Rows returned. * |
| // * *: Select failed. A CLI error is put into the diags area. * |
| // * * |
| // ***************************************************************************** |
| PrivStatus ColumnPrivsMDTable::selectWhere( |
| const std::string & whereClause, |
| const std::string & orderByClause, |
| std::vector<PrivMgrMDRow *> &rowList) |
| { |
| |
| std::string selectStmt("SELECT object_uid,object_name," |
| "grantee_id,grantee_name," |
| "grantor_id,grantor_name,column_number," |
| "privileges_bitmap,grantable_bitmap FROM "); |
| |
| selectStmt += tableName_ + " "; |
| selectStmt += whereClause + orderByClause; |
| |
| // set pointer in diags area |
| int32_t diagsMark = pDiags_->mark(); |
| |
| ExeCliInterface cliInterface(STMTHEAP); |
| Queue * tableQueue = NULL; |
| int32_t cliRC = cliInterface.fetchAllRows(tableQueue, (char *)selectStmt.c_str(), 0, false, false, true); |
| |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return STATUS_ERROR; |
| } |
| if (cliRC == 100) // did not find the row |
| { |
| pDiags_->rewind(diagsMark); |
| return STATUS_NOTFOUND; |
| } |
| |
| tableQueue->position(); |
| for (int idx = 0; idx < tableQueue->numEntries(); idx++) |
| { |
| OutputInfo * pCliRow = (OutputInfo*)tableQueue->getNext(); |
| ColumnPrivsMDRow *pRow = new ColumnPrivsMDRow(); |
| setRow(pCliRow,*pRow); |
| rowList.push_back(pRow); |
| } |
| |
| return STATUS_GOOD; |
| |
| } |
| //****************** End of ColumnPrivsMDTable::selectWhere ******************** |
| |
| // ***************************************************************************** |
| // * * |
| // * Function: ColumnPrivsMDTable::selectWhereUnique * |
| // * * |
| // * Selects a row from the COLUMN_PRIVILEGES table based on the specified * |
| // * WHERE clause. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <whereClause> const std::string & In * |
| // * is the WHERE clause specifying a unique row. * |
| // * * |
| // * <row> PrivMgrMDRow & Out * |
| // * passes back a ColumnPrivsMDRow row. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Returns: PrivStatus * |
| // * * |
| // * STATUS_GOOD: Row returned. * |
| // * *: Select failed. A CLI error is put into the diags area. * |
| // * * |
| // ***************************************************************************** |
| PrivStatus ColumnPrivsMDTable::selectWhereUnique( |
| const std::string & whereClause, |
| PrivMgrMDRow & row) |
| |
| { |
| //TODO: Currently unused. Added due to virtual declaration. Will be fleshed |
| // out when run-time column privilege checking added. |
| return STATUS_GOOD; |
| |
| } |
| //************** End of ColumnPrivsMDTable::selectWhereUnique ****************** |
| |
| // ***************************************************************************** |
| // * * |
| // * Function: MyTable::setRow * |
| // * * |
| // * Create a ColumnPrivsMDRow object from the information returned from the |
| // * CLI. |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <pCliRow> OutputInfo & In * |
| // * is a pointer to the CLI interface to the row data that was read. * |
| // * * |
| // * <row> PrivMgrMDRow & Out * |
| // * passes back a ColumnPrivsMDRow. * |
| // * * |
| // ***************************************************************************** |
| void ColumnPrivsMDTable::setRow( |
| OutputInfo *pCliRow, |
| ColumnPrivsMDRow &row) |
| |
| { |
| char * ptr = NULL; |
| Int32 len = 0; |
| char value[500]; |
| |
| // column 0: object uid |
| pCliRow->get(0,ptr,len); |
| row.objectUID_ = *(reinterpret_cast<int64_t*>(ptr)); |
| |
| // column 1: object name |
| pCliRow->get(1,ptr,len); |
| assert (len < 257); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.objectName_ = value; |
| |
| // column 2: grantee id |
| pCliRow->get(2,ptr,len); |
| row.granteeID_ = *(reinterpret_cast<int32_t*>(ptr)); |
| |
| // column 3: grantee name |
| pCliRow->get(3,ptr,len); |
| assert (len < 257); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.granteeName_ = value; |
| |
| // column 4: grantor id |
| pCliRow->get(4,ptr,len); |
| row.grantorID_ = *(reinterpret_cast<int32_t*>(ptr)); |
| |
| // column 5: grantor name |
| pCliRow->get(5,ptr,len); |
| assert (len < 257); |
| strncpy(value, ptr, len); |
| value[len] = 0; |
| row.grantorName_ = value; |
| |
| // column 6: column_number |
| pCliRow->get(6,ptr,len); |
| row.columnOrdinal_ = *(reinterpret_cast<int32_t*>(ptr)); |
| |
| // column 7: privileges bitmap |
| pCliRow->get(7,ptr,len); |
| int64_t bitmapInt = *(reinterpret_cast<int64_t*>(ptr)); |
| row.privsBitmap_ = bitmapInt; |
| |
| // column 8: grantable bitmap |
| pCliRow->get(8,ptr,len); |
| bitmapInt = *(reinterpret_cast<int64_t*>(ptr)); |
| row.grantableBitmap_ = bitmapInt; |
| |
| } |
| //******************* End of ColumnPrivsMDTable::setRow ************************ |
| |
| // ***************************************************************************** |
| // * * |
| // * Function: ColumnPrivsMDTable::updateRow * |
| // * * |
| // * Updates the bitmaps for a row in the COLUMN_PRIVILEGES table based on * |
| // * the contents of the row. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Parameters: * |
| // * * |
| // * <row> PrivMgrMDRow & In * |
| // * is the row to be updated. * |
| // * * |
| // * <whereBase> const std::string & In * |
| // * is the WHERE clause specifying the primary keys except for the * |
| // * column number, which is added within this function. * |
| // * * |
| // ***************************************************************************** |
| // * * |
| // * Returns: PrivStatus * |
| // * * |
| // * STATUS_GOOD: Row returned. * |
| // * *: Select failed. A CLI error is put into the diags area. * |
| // * * |
| // ***************************************************************************** |
| PrivStatus ColumnPrivsMDTable::updateColumnRow( |
| const ColumnPrivsMDRow & row, |
| const std::string whereBase) |
| |
| { |
| |
| char setClause[1000]; |
| int64_t privilegesBitmapLong = row.privsBitmap_.to_ulong(); |
| int64_t grantableBitmapLong = row.grantableBitmap_.to_ulong(); |
| |
| sprintf(setClause," SET privileges_bitmap = %ld, grantable_bitmap = %ld ", |
| privilegesBitmapLong,grantableBitmapLong); |
| |
| char whereClause[1000]; |
| |
| sprintf(whereClause," %s %d",whereBase.c_str(),row.columnOrdinal_); |
| |
| return updateWhere(setClause,whereClause); |
| |
| } |
| //*************** End of ColumnPrivsMDTable::updateColumnRow ******************* |
| |
| |
| |
| |
| |
| |