| /********************************************************************** |
| // @@@ 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 @@@ |
| **********************************************************************/ |
| |
| // ***************************************************************************** |
| // * |
| // * File: CmpSeabaseDDLauth.cpp |
| // * Description: Implements methods for user management |
| // * |
| // * Contains methods for classes: |
| // * CmpSeabaseDDLauth |
| // * CmpSeabaseDDLuser |
| // * |
| // * |
| // ***************************************************************************** |
| |
| #define SQLPARSERGLOBALS_FLAGS |
| #include "SqlParserGlobalsCmn.h" |
| |
| #include "CmpSeabaseDDLauth.h" |
| #include "CmpSeabaseDDL.h" |
| #include "StmtDDLRegisterUser.h" |
| #include "StmtDDLAlterUser.h" |
| #include "StmtDDLCreateRole.h" |
| #include "ElemDDLGrantee.h" |
| #include "CompException.h" |
| #include "Context.h" |
| #include "dbUserAuth.h" |
| #include "ComUser.h" |
| #include "CmpDDLCatErrorCodes.h" |
| #include "NAStringDef.h" |
| #include "ExpHbaseInterface.h" |
| #include "PrivMgrCommands.h" |
| #include "PrivMgrRoles.h" |
| #include "PrivMgrComponentPrivileges.h" |
| |
| |
| #define RESERVED_AUTH_NAME_PREFIX "DB__" |
| |
| inline static bool validateExternalUsername( |
| const char * externalUsername, |
| DBUserAuth::AuthenticationConfiguration configurationNumber, |
| DBUserAuth::AuthenticationConfiguration & foundConfigurationNumber); |
| |
| // **************************************************************************** |
| // Class CmpSeabaseDDLauth methods |
| // **************************************************************************** |
| |
| // ---------------------------------------------------------------------------- |
| // Constructors |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLauth::CmpSeabaseDDLauth( |
| const NAString & systemCatalog, |
| const NAString & MDSchema) |
| : authID_(NA_UserIdDefault), |
| authType_(COM_UNKNOWN_ID_CLASS), |
| authCreator_(NA_UserIdDefault), |
| authCreateTime_(0), |
| authRedefTime_(0), |
| authValid_(true), |
| systemCatalog_(systemCatalog), |
| MDSchema_(MDSchema) |
| {} |
| |
| CmpSeabaseDDLauth::CmpSeabaseDDLauth() |
| : authID_(NA_UserIdDefault), |
| authType_(COM_UNKNOWN_ID_CLASS), |
| authCreator_(NA_UserIdDefault), |
| authCreateTime_(0), |
| authRedefTime_(0), |
| authValid_(true), |
| systemCatalog_("TRAFODION"), |
| MDSchema_("TRAFODION.\"_MD_\"") |
| |
| {} |
| |
| // ---------------------------------------------------------------------------- |
| // public method: authExists |
| // |
| // Input: |
| // authName - name to look up |
| // isExternal - |
| // true - the auth name is the external name (auth_ext_name) |
| // false - the auth name is the database name (auth_db_name) |
| // |
| // Output: |
| // Returns true if authorization row exists in the metadata |
| // Returns false if authorization row does not exist in the metadata or an |
| // unexpected error occurs |
| // |
| // The diags area contains an error if any unexpected errors occurred. |
| // Callers should check the diags area when false is returned |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::authExists (const NAString &authName, bool isExternal) |
| { |
| // Read the auths table to get a count of rows for the authName |
| Int64 rowCount = 0; |
| try |
| { |
| NAString whereClause ("where "); |
| whereClause += (isExternal) ? "auth_ext_name = '" : "auth_db_name = '"; |
| whereClause += authName; |
| whereClause += "'"; |
| rowCount = selectCount(whereClause); |
| return (rowCount > 0) ? true : false; |
| } |
| |
| catch (...) |
| { |
| // If there is no error in the diags area, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("CmpSeabaseDDLauth::authExists for authName"); |
| return false; |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: describe |
| // |
| // This method is not valid for the base class |
| // |
| // Input: none |
| // |
| // Output: populates diag area, throws exception. |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::describe(const NAString &authName, NAString &authText) |
| { |
| |
| SEABASEDDL_INTERNAL_ERROR("CmpSeabaseDDLauth::describe"); |
| |
| UserException excp(NULL,0); |
| |
| throw excp; |
| |
| return 0; |
| |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // public method: getAuthDetails |
| // |
| // Populates the CmpSeabaseDDLauth class containing auth details for the |
| // requested authName |
| // |
| // Input: |
| // authName - the database or external auth name |
| // isExternal - |
| // true - the auth name is the external name (auth_ext_name) |
| // false - the auth name is the database name (auth_db_name) |
| // |
| // Output: |
| // Returned parameter (AuthStatus): |
| // STATUS_GOOD: authorization details are populated: |
| // STATUS_NOTFOUND: authorization details were not found |
| // STATUS_WARNING: (not 100) warning was returned, diags area populated |
| // STATUS_ERROR: error was returned, diags area populated |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLauth::AuthStatus |
| CmpSeabaseDDLauth::getAuthDetails(const char *pAuthName, bool isExternal) |
| { |
| // If the authname is a special PUBLIC authorization ID, set it up |
| std::string authName = pAuthName; |
| if (authName == PUBLIC_AUTH_NAME) |
| { |
| setAuthCreator(SUPER_USER); |
| setAuthCreateTime(0); |
| setAuthDbName(PUBLIC_AUTH_NAME); |
| setAuthExtName(PUBLIC_AUTH_NAME); |
| setAuthID(PUBLIC_USER); |
| setAuthRedefTime(0); |
| setAuthType(COM_ROLE_CLASS); |
| setAuthValid(false); |
| return STATUS_GOOD; |
| } |
| |
| try |
| { |
| NAString whereClause ("where "); |
| whereClause += (isExternal) ? "auth_ext_name = '" : "auth_db_name = '"; |
| whereClause += pAuthName; |
| whereClause += "'"; |
| return selectExactRow(whereClause); |
| } |
| |
| catch (...) |
| { |
| // If there is no error in the diags area, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("CmpSeabaseDDLauth::getAuthDetails for authName"); |
| return STATUS_ERROR; |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // public method: getAuthDetails |
| // |
| // Create the CmpSeabaseDDLauth class containing auth details for the |
| // request authID |
| // |
| // Input: |
| // authID - the database authorization ID to search for |
| // |
| // Output: |
| // A returned parameter: |
| // STATUS_GOOD: authorization details are populated: |
| // STATUS_NOTFOUND: authorization details were not found |
| // STATUS_WARNING: (not 100) warning was returned, diags area populated |
| // STATUS_ERROR: error was returned, diags area populated |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLauth::AuthStatus CmpSeabaseDDLauth::getAuthDetails(Int32 authID) |
| { |
| try |
| { |
| char buf[1000]; |
| str_sprintf(buf, "where auth_id = %d ", authID); |
| NAString whereClause (buf); |
| return selectExactRow(whereClause); |
| } |
| |
| catch (...) |
| { |
| // If there is no error in the diags area, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("CmpSeabaseDDLauth::getAuthDetails for authID"); |
| |
| return STATUS_ERROR; |
| } |
| } |
| |
| CmpSeabaseDDLauth::AuthStatus CmpSeabaseDDLauth::getRoleIDs( |
| const Int32 authID, |
| std::vector<int32_t> &roleIDs) |
| { |
| NAString privMgrMDLoc; |
| CONCAT_CATSCH(privMgrMDLoc,systemCatalog_.data(),SEABASE_PRIVMGR_SCHEMA); |
| |
| PrivMgrRoles role(std::string(MDSchema_.data()), |
| std::string(privMgrMDLoc.data()), |
| CmpCommon::diags()); |
| std::vector<std::string> roleNames; |
| std::vector<int32_t> roleDepths; |
| |
| if (role.fetchRolesForUser(authID,roleNames,roleIDs,roleDepths) == PrivStatus::STATUS_ERROR) |
| return STATUS_ERROR; |
| return STATUS_GOOD; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // public method: getObjectName |
| // |
| // Returns the first object name from the list of passed in objectUIDs. |
| // |
| // Input: |
| // objectUIDs - list of objectUIDs |
| // |
| // Output: |
| // returns the fully qualified object name |
| // returns NULL string if no objects were found |
| // ---------------------------------------------------------------------------- |
| NAString CmpSeabaseDDLauth::getObjectName (const std::vector <int64_t> objectUIDs) |
| { |
| char longBuf [sizeof(int64_t)*8+1]; |
| bool isFirst = true; |
| NAString objectList; |
| NAString objectName; |
| |
| if (objectUIDs.size() == 0) |
| return objectName; |
| |
| // convert objectUIDs into an "in" clause list |
| for (int i = 0; i < objectUIDs.size(); i++) |
| { |
| if (isFirst) |
| objectList = "("; |
| else |
| objectList += ", "; |
| isFirst = false; |
| sprintf (longBuf, "%ld", objectUIDs[i]); |
| objectList += longBuf; |
| } |
| objectList += ")"; |
| |
| NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); |
| char buf[1000 + objectList.length()]; |
| str_sprintf(buf, "select [first 1] trim(catalog_name) || '.' || " |
| "trim(schema_name) || '.' || trim(object_name) " |
| " from %s.\"%s\".%s where object_uid in %s", |
| sysCat.data(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS, objectList.data()); |
| |
| ExeCliInterface cliInterface(STMTHEAP); |
| Int32 cliRC = cliInterface.fetchRowsPrologue(buf, true/*no exec*/); |
| if (cliRC != 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| cliRC = cliInterface.clearExecFetchClose(NULL, 0); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| // return an empty string |
| if (cliRC == 100) |
| return objectName; |
| |
| // get the objectname |
| char * ptr = NULL; |
| Lng32 len = 0; |
| |
| // object name returned |
| cliInterface.getPtrAndLen(1,ptr,len); |
| NAString returnedName(ptr,len); |
| return returnedName; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // method: getUniqueAuthID |
| // |
| // Return an unused auth ID between the requested ranges |
| // Input: |
| // minValue - the lowest value |
| // maxValue - the highest value |
| // |
| // Output: unique ID to use |
| // exception is generated if unable to generate a unique value |
| // ---------------------------------------------------------------------------- |
| Int32 CmpSeabaseDDLauth::getUniqueAuthID( |
| const Int32 minValue, |
| const Int32 maxValue) |
| { |
| Int32 newUserID = 0; |
| char buf[300]; |
| Int32 len = snprintf(buf, 300, |
| "SELECT [FIRST 1] auth_id FROM (SELECT auth_id, " |
| "LEAD(auth_id) OVER (ORDER BY auth_id) L FROM %s.%s ) " |
| "WHERE (L - auth_id > 1 or L is null) and auth_id >= %d ", |
| MDSchema_.data(),SEABASE_AUTHS, minValue); |
| assert (len <= 300); |
| |
| len = 0; |
| Int64 metadataValue = 0; |
| bool nullTerminate = false; |
| |
| ExeCliInterface cliInterface(STMTHEAP); |
| Lng32 cliRC = cliInterface.executeImmediate(buf, (char *)&metadataValue, &len, nullTerminate); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| return 0; |
| } |
| |
| // We have lots of available ID's. Don't expect to run out of ID's for awhile |
| if (cliRC == 100 || metadataValue > maxValue) |
| { |
| SEABASEDDL_INTERNAL_ERROR("CmpSeabaseDDLauth::getUniqueAuthID failed, ran out of available IDs"); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| newUserID = (Int32)metadataValue; |
| if (newUserID == 0) |
| newUserID = ROOT_USER_ID + 1; |
| else |
| newUserID++; |
| |
| // There is a bug where grants are not being removed from component privileges |
| // when a user is dropped. So if this authID still shows up as a component |
| // privilege grantee go ahead a cleanup the inconsistency. |
| std::string privMDLoc(CmpSeabaseDDL::getSystemCatalogStatic().data()); |
| privMDLoc += std::string(".\"") + |
| std::string(SEABASE_PRIVMGR_SCHEMA) + |
| std::string("\""); |
| |
| PrivMgrComponentPrivileges componentPrivs(privMDLoc,CmpCommon::diags()); |
| if (componentPrivs.isAuthIDGrantedPrivs(newUserID)) |
| { |
| if (!componentPrivs.dropAllForGrantee(newUserID)) |
| { |
| *CmpCommon::diags() << DgSqlCode(CAT_WARN_USED_AUTHID) |
| << DgInt0(newUserID); |
| |
| Int32 newMinValue = newUserID+1; |
| newUserID = getUniqueAuthID(newUserID + 1, maxValue); |
| } |
| } |
| |
| return newUserID; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // method: isAuthNameReserved |
| // |
| // Checks to see if proposed name is reserved |
| // |
| // Input: authorization name |
| // |
| // Output: |
| // true - name is reserved |
| // false - name is not reserved |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::isAuthNameReserved (const NAString &authName) |
| { |
| bool result; |
| result = authName.length() >= strlen(RESERVED_AUTH_NAME_PREFIX) |
| && |
| authName.operator()(0,strlen(RESERVED_AUTH_NAME_PREFIX)) == |
| RESERVED_AUTH_NAME_PREFIX |
| || |
| authName == SYSTEM_AUTH_NAME |
| || |
| authName == PUBLIC_AUTH_NAME |
| || |
| authName == "NONE"; |
| |
| return result; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: isAuthNameValid |
| // |
| // checks to see if the name contains valid character |
| // |
| // Input: |
| // NAString - authName -- name string to check |
| // |
| // Returns: true if valid, false otherwise |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::isAuthNameValid(const NAString &authName) |
| { |
| string validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_@./"; |
| string strToScan = authName.data(); |
| size_t found = strToScan.find_first_not_of(validChars); |
| if (found == string::npos) |
| return true; |
| return false; |
| } |
| |
| |
| |
| // ---------------------------------------------------------------------------- |
| // method: isRoleID |
| // |
| // Determines if an authID is in the role ID range |
| // |
| // Input: |
| // Int32 - authID -- numeric ID to check |
| // |
| // Returns: true if authID is a role ID, false otherwise |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::isRoleID(Int32 authID) |
| |
| { |
| |
| return (authID >= MIN_ROLEID && authID <= MAX_ROLEID); |
| |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // method: isUserID |
| // |
| // Determines if an authID is in the user ID range |
| // |
| // Input: |
| // Int32 - authID -- numeric ID to check |
| // |
| // Returns: true if authID is a user ID, false otherwise |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::isUserID(Int32 authID) |
| |
| { |
| |
| return (authID >= MIN_USERID && authID <= MAX_USERID); |
| |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: isSystemAuth |
| // |
| // Checks the list of authorization IDs to see if the passed in authName is a |
| // system auth. This replaces checks for reserved names. |
| // |
| // isSpecialAuth indicates a system auth but it is not defined in the metadata |
| // |
| // Returns: |
| // true - is a system auth |
| // false - is not a system auth |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::isSystemAuth( |
| const ComIdClass authType, |
| const NAString &authName, |
| bool &isSpecialAuth) |
| { |
| bool isSystem = false; |
| switch (authType) |
| { |
| case COM_ROLE_CLASS: |
| { |
| int32_t numberRoles = sizeof(systemRoles)/sizeof(SystemAuthsStruct); |
| for (int32_t i = 0; i < numberRoles; i++) |
| { |
| const SystemAuthsStruct &roleDefinition = systemRoles[i]; |
| if (roleDefinition.authName == authName) |
| { |
| isSystem = true; |
| isSpecialAuth = roleDefinition.isSpecialAuth; |
| break; |
| } |
| } |
| break; |
| } |
| |
| case COM_USER_CLASS: |
| { |
| // Verify name is a standard name |
| std::string authNameStr(authName.data()); |
| size_t prefixLength = strlen(RESERVED_AUTH_NAME_PREFIX); |
| if (authNameStr.size() <= prefixLength || |
| authNameStr.compare(0,prefixLength,RESERVED_AUTH_NAME_PREFIX) == 0) |
| isSystem = true; |
| break; |
| } |
| |
| default: |
| { |
| // should never get here - assert? |
| isSystem = false; |
| } |
| } |
| return isSystem; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // protected method: createStandardAuth |
| // |
| // Inserts a standard user or role in the Trafodion metadata |
| // The authType needs to be set up before calling |
| // |
| // Input: |
| // authName |
| // authID |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::createStandardAuth( |
| const std::string authName, |
| const int32_t authID) |
| { |
| // check to see if authName is a system object |
| bool isSpecialAuth = false; |
| bool isSystem = isSystemAuth(getAuthType(), NAString(authName.c_str()), isSpecialAuth); |
| |
| // since this is being called by internal code, should not be trying to |
| // create non system object (isSystemAuth) or object that should not be |
| // registered in the metadata (isSpecialAuth), return internal error |
| if (!isSystem || isSpecialAuth) |
| { |
| NAString errorMsg ("Invalid system authorization identifier for "); |
| errorMsg += getAuthType() == COM_ROLE_CLASS ? "role " : "user "; |
| errorMsg += authName.c_str(); |
| SEABASEDDL_INTERNAL_ERROR(errorMsg.data()); |
| return false; |
| } |
| |
| setAuthDbName(authName.c_str()); |
| setAuthExtName(authName.c_str()); |
| setAuthValid(true); // assume a valid authorization ID |
| |
| Int64 createTime = NA_JulianTimestamp(); |
| setAuthCreateTime(createTime); |
| setAuthRedefTime(createTime); // make redef time the same as create time |
| |
| // Make sure authorization ID has not already been registered |
| if (authExists(getAuthDbName(),false)) |
| return false; |
| |
| try |
| { |
| Int32 minAuthID = isRole() ? MIN_ROLEID : MIN_USERID; |
| Int32 maxAuthID = isRole() ? MAX_ROLEID : MAX_USERID; |
| |
| Int32 newAuthID = (authID == NA_UserIdDefault) ? getUniqueAuthID(minAuthID, maxAuthID) : authID; |
| if (isRole()) |
| assert(isRoleID(newAuthID)); |
| else if (isUser()) |
| assert (isUserID(newAuthID)); |
| |
| setAuthID(newAuthID); |
| setAuthCreator(ComUser::getRootUserID()); |
| |
| // Add the role to AUTHS table |
| insertRow(); |
| } |
| |
| catch (...) |
| { |
| // At this time, an error should be in the diags area. |
| // If there is no error, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("Unexpected error in CmpSeabaseDDLuser::createStandardAuth"); |
| } |
| return true; |
| } |
| |
| //----------------------------------------------------------------------------- |
| // Methods that perform metadata access |
| // |
| // All methods return a UserException if an unexpected error occurs |
| //----------------------------------------------------------------------------- |
| |
| // Delete a row from the AUTHS table based on the AUTH_ID |
| void CmpSeabaseDDLauth::deleteRow(const NAString &authName) |
| { |
| NAString systemCatalog = CmpSeabaseDDL::getSystemCatalogStatic(); |
| char buf[1000]; |
| ExeCliInterface cliInterface(STMTHEAP); |
| str_sprintf(buf, "delete from %s.\"%s\".%s where auth_db_name = '%s'", |
| systemCatalog.data(), SEABASE_MD_SCHEMA, SEABASE_AUTHS, authName.data()); |
| Lng32 cliRC = cliInterface.executeImmediate(buf); |
| |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| // Existence of the row is already checked, throw an assertion the row does not exist |
| // With optimistic locking, this might occur if a concurrent session is deleting the |
| // same row and gets in first |
| CMPASSERT (cliRC == 100); |
| |
| // Not sure if it is possible to get a warning from a delete and |
| // what it means if one is returned for now, it is ignored. |
| } |
| |
| // Insert a row into the AUTHS table |
| void CmpSeabaseDDLauth::insertRow() |
| { |
| char buf[1000]; |
| ExeCliInterface cliInterface(STMTHEAP); |
| |
| NAString authType; |
| switch (getAuthType()) |
| { |
| case COM_ROLE_CLASS: |
| authType = COM_ROLE_CLASS_LIT; |
| break; |
| case COM_USER_CLASS: |
| authType = COM_USER_CLASS_LIT; |
| break; |
| default: |
| SEABASEDDL_INTERNAL_ERROR("Switch statement in CmpSeabaseDDLuser::deleteRow invalid authType"); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| NAString authValid = isAuthValid() ? "Y" : "N"; |
| |
| NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); |
| str_sprintf(buf, "insert into %s.\"%s\".%s values (%d, '%s', '%s', '%s', %d, '%s', %ld, %ld, 0)", |
| sysCat.data(), SEABASE_MD_SCHEMA, SEABASE_AUTHS, |
| getAuthID(), |
| getAuthDbName().data(), |
| getAuthExtName().data(), |
| authType.data(), |
| getAuthCreator(), |
| authValid.data(), |
| getAuthCreateTime(), |
| getAuthRedefTime()); |
| |
| Int32 cliRC = cliInterface.executeImmediate(buf); |
| |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| // Not sure if it is possible to get a warning from an insert and |
| // what it means if one is returned, for now it is ignored. |
| |
| } |
| |
| // update a row in AUTHS table based on the passed in setClause |
| void CmpSeabaseDDLauth::updateRow(NAString &setClause) |
| { |
| char buf[1000]; |
| ExeCliInterface cliInterface(STMTHEAP); |
| |
| NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); |
| str_sprintf(buf, "update %s.\"%s\".%s %s where auth_id = %d", |
| sysCat.data(), SEABASE_MD_SCHEMA, SEABASE_AUTHS, |
| setClause.data(), |
| getAuthID()); |
| |
| Int32 cliRC = cliInterface.executeImmediate(buf); |
| |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| // Existence of the row is already checked, throw an assertion the row does not exist |
| // With optimistic locking, this might occur if a concurrent session is deleting the |
| // same row and gets in first |
| CMPASSERT (cliRC == 100); |
| |
| // Not sure if it is possible to get a warning from an update and |
| // what it means if one is returned, for now it is ignored. |
| |
| } |
| |
| // select exact based on the passed in whereClause |
| CmpSeabaseDDLauth::AuthStatus |
| CmpSeabaseDDLauth::selectExactRow(const NAString & whereClause) |
| { |
| NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); |
| char buf[1000]; |
| str_sprintf(buf, "select auth_id, auth_db_name, auth_ext_name, auth_type, " |
| "auth_creator, auth_is_valid, auth_create_time, auth_redef_time" |
| " from %s.%s %s ", |
| MDSchema_.data(), SEABASE_AUTHS, whereClause.data()); |
| NAString cmd (buf); |
| |
| ExeCliInterface cliInterface(STMTHEAP); |
| |
| Int32 cliRC = cliInterface.fetchRowsPrologue(cmd.data(), true/*no exec*/); |
| if (cliRC != 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| DDLException excp (cliRC, NULL, 0); |
| throw excp; |
| } |
| |
| cliRC = cliInterface.clearExecFetchClose(NULL, 0); |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| DDLException excp (cliRC, NULL, 0); |
| throw excp; |
| } |
| |
| if (cliRC == 100) // did not find the row |
| { |
| cliInterface.clearGlobalDiags(); |
| return STATUS_NOTFOUND; |
| } |
| |
| // Set the return status |
| CmpSeabaseDDLauth::AuthStatus authStatus = |
| (cliRC == 0) ? STATUS_GOOD : STATUS_WARNING; |
| |
| // Populate the class |
| char * ptr = NULL; |
| Lng32 len = 0; |
| char type [6]; |
| |
| // value 1: auth_id (int32) |
| cliInterface.getPtrAndLen(1, ptr, len); |
| setAuthID(*(Int32*)ptr); |
| |
| // value 2: auth_db_name (NAString) |
| cliInterface.getPtrAndLen(2,ptr,len); |
| NAString dbName(ptr,len); |
| setAuthDbName(dbName); |
| |
| // value 3: auth_ext_name (NAString) |
| cliInterface.getPtrAndLen(3,ptr,len); |
| NAString extName(ptr,len); |
| setAuthExtName(extName); |
| |
| // value 4: auth_type (char) |
| // str_cpy_and_null params: *tgt, *src, len, endchar, blank, null term |
| cliInterface.getPtrAndLen(4,ptr,len); |
| str_cpy_and_null(type, ptr, len, '\0', ' ', true); |
| if ( type[0] == 'U') |
| setAuthType(COM_USER_CLASS); |
| else if (type[0] == 'R') |
| setAuthType(COM_ROLE_CLASS); |
| else |
| setAuthType(COM_UNKNOWN_ID_CLASS); |
| |
| // value 5: auth_creator (int32) |
| cliInterface.getPtrAndLen(5,ptr,len); |
| setAuthCreator(*(Int32*)ptr); |
| |
| // value 6: auth_is_valid (char) |
| cliInterface.getPtrAndLen(6,ptr,len); |
| str_cpy_and_null(type, ptr, len, '\0', ' ', true); |
| if (type[0] == 'Y') |
| setAuthValid(true); |
| else |
| setAuthValid(false); |
| |
| // value 7: auth_create_time (int64) |
| cliInterface.getPtrAndLen(7,ptr,len); |
| Int64 intValue = *(Int64*)ptr; |
| setAuthCreateTime((ComTimestamp) intValue); |
| |
| // value 8: auth_redef_time (int64) |
| cliInterface.getPtrAndLen(8,ptr,len); |
| intValue = *(Int64*)ptr; |
| setAuthRedefTime((ComTimestamp) intValue); |
| |
| cliInterface.fetchRowsEpilogue(NULL, true); |
| return authStatus; |
| } |
| |
| // selectCount - returns the number of rows based on the where clause |
| Int64 CmpSeabaseDDLauth::selectCount(const NAString & whereClause) |
| { |
| NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); |
| char buf[1000]; |
| str_sprintf(buf, "select count(*) from %s.%s %s ", |
| MDSchema_.data(), SEABASE_AUTHS, |
| whereClause.data()); |
| |
| Lng32 len = 0; |
| Int64 rowCount = 0; |
| ExeCliInterface cliInterface(STMTHEAP); |
| Lng32 cliRC = cliInterface.executeImmediate(buf, (char*)&rowCount, &len, FALSE); |
| |
| // If unexpected error occurred, return an exception |
| if (cliRC < 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| DDLException excp (cliRC, NULL, 0); |
| throw excp; |
| } |
| |
| return rowCount; |
| } |
| |
| // selectMaxAuthID - gets the last used auth ID |
| Int32 CmpSeabaseDDLauth::selectMaxAuthID(const NAString &whereClause) |
| { |
| NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); |
| char buf[400]; |
| str_sprintf(buf, "select nvl(max (auth_id),0) from %s.%s %s" , |
| MDSchema_.data(),SEABASE_AUTHS,whereClause.data()); |
| |
| Lng32 len = 0; |
| Int64 maxValue = 0; |
| bool nullTerminate = false; |
| ExeCliInterface cliInterface(STMTHEAP); |
| Lng32 cliRC = cliInterface.executeImmediate(buf, (char *)&maxValue, &len, nullTerminate); |
| if (cliRC != 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| return static_cast<Int32>(maxValue); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: verifyAuthority |
| // |
| // makes sure user has privilege to perform the operation |
| // |
| // Input: none |
| // |
| // Output: |
| // true - authority granted |
| // false - no authority or unexpected error |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLauth::verifyAuthority(const SQLOperation operation) |
| { |
| |
| // If authorization is not enabled, just return with no error |
| if (!CmpCommon::context()->isAuthorizationEnabled()) |
| return true; |
| |
| int32_t currentUser = ComUser::getCurrentUser(); |
| |
| // Root user has authority to manage users. |
| if (currentUser == ComUser::getRootUserID()) |
| return true; |
| |
| NAString systemCatalog = CmpSeabaseDDL::getSystemCatalogStatic(); |
| std::string privMDLoc(systemCatalog.data()); |
| |
| privMDLoc += std::string(".\"") + |
| std::string(SEABASE_PRIVMGR_SCHEMA) + |
| std::string("\""); |
| |
| PrivMgrComponentPrivileges componentPrivileges(privMDLoc,CmpCommon::diags()); |
| |
| // See if non-root user has authority to manage users. |
| if (componentPrivileges.hasSQLPriv(currentUser, operation, true)) |
| { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // **************************************************************************** |
| // Class CmpSeabaseDDLuser methods |
| // **************************************************************************** |
| |
| // ---------------------------------------------------------------------------- |
| // Constructor |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLuser::CmpSeabaseDDLuser( |
| const NAString & systemCatalog, |
| const NAString & MDSchema) |
| : CmpSeabaseDDLauth(systemCatalog,MDSchema) |
| |
| {} |
| |
| CmpSeabaseDDLuser::CmpSeabaseDDLuser() |
| : CmpSeabaseDDLauth() |
| |
| {} |
| |
| // ---------------------------------------------------------------------------- |
| // public method: getUserDetails |
| // |
| // Create the CmpSeabaseDDLuser class containing user details for the |
| // requested userID |
| // |
| // Input: |
| // userID - the database authorization ID to search for |
| // |
| // Output: |
| // Returned parameter: |
| // STATUS_GOOD: authorization details are populated: |
| // STATUS_NOTFOUND: authorization details were not found |
| // STATUS_WARNING: (not 100) warning was returned, diags area populated |
| // STATUS_ERROR: error was returned, diags area populated |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLauth::AuthStatus CmpSeabaseDDLuser::getUserDetails(Int32 userID) |
| { |
| CmpSeabaseDDLauth::AuthStatus retcode = getAuthDetails(userID); |
| if (retcode == STATUS_GOOD && !isUser()) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_IS_NOT_A_USER) |
| << DgString0(getAuthDbName().data()); |
| retcode = STATUS_ERROR; |
| } |
| return retcode; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // public method: getUserDetails |
| // |
| // Create the CmpSeabaseDDLuser class containing user details for the |
| // requested username |
| // |
| // Input: |
| // userName - the database username to retrieve details for |
| // isExternal - |
| // true - the username is the external name (auth_ext_name) |
| // false - the username is the database name (auth_db_name) |
| // |
| // Output: |
| // Returned parameter: |
| // STATUS_GOOD: authorization details are populated: |
| // STATUS_NOTFOUND: authorization details were not found |
| // STATUS_WARNING: (not 100) warning was returned, diags area populated |
| // STATUS_ERROR: error was returned, diags area populated |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLauth::AuthStatus |
| CmpSeabaseDDLuser::getUserDetails(const char *pUserName, bool isExternal) |
| { |
| CmpSeabaseDDLauth::AuthStatus retcode = getAuthDetails(pUserName, isExternal); |
| if (retcode == STATUS_GOOD && !isUser()) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_IS_NOT_A_USER) |
| << DgString0(getAuthDbName().data()); |
| retcode = STATUS_ERROR; |
| } |
| return retcode; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Public method: registerUser |
| // |
| // registers a user in the Trafodion metadata |
| // |
| // Input: parse tree containing a definition of the user |
| // Output: the global diags area is set up with the result |
| // ---------------------------------------------------------------------------- |
| void CmpSeabaseDDLuser::registerUser(StmtDDLRegisterUser * pNode) |
| { |
| // Set up a global try/catch loop to catch unexpected errors |
| try |
| { |
| // Verify user is authorized to perform REGISTER USER requests |
| if (!verifyAuthority(SQLOperation::MANAGE_USERS)) |
| { |
| // No authority. We're outta here. |
| *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return; |
| } |
| |
| // Verify that the specified user name is not reserved |
| setAuthDbName(pNode->getDbUserName()); |
| if (isAuthNameReserved(pNode->getDbUserName())) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_AUTH_NAME_RESERVED) |
| << DgString0(pNode->getDbUserName().data()); |
| return; |
| } |
| |
| |
| // Verify that the name does not include unsupported special characters |
| if (!isAuthNameValid(getAuthDbName())) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_INVALID_CHARS_IN_AUTH_NAME) |
| << DgString0(pNode->getDbUserName().data()); |
| return; |
| } |
| |
| setAuthExtName(pNode->getExternalUserName()); |
| if (!isAuthNameValid(getAuthExtName())) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_INVALID_CHARS_IN_AUTH_NAME) |
| << DgString0(pNode->getExternalUserName().data()); |
| return; |
| } |
| |
| // set up class members from parse node |
| setAuthType(COM_USER_CLASS); // we are a user |
| setAuthValid(true); // assume a valid user |
| |
| Int64 createTime = NA_JulianTimestamp(); |
| setAuthCreateTime(createTime); |
| setAuthRedefTime(createTime); // make redef time the same as create time |
| |
| // Make sure db user has not already been registered |
| if (authExists(getAuthDbName(), false)) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_ALREADY_EXISTS) |
| << DgString0(getAuthDbName().data()); |
| return; |
| } |
| // unexpected error occurred - ? |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) > 0) |
| return; |
| |
| // Make sure external user has not already been registered |
| if (authExists(getAuthExtName(), true)) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_USER_ALREADY_EXISTS) |
| << DgString0(getAuthExtName().data()); |
| return; |
| } |
| // unexpected error occurred - ? |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) > 0) |
| return; |
| |
| DBUserAuth::AuthenticationConfiguration configurationNumber = DBUserAuth::DefaultConfiguration; |
| DBUserAuth::AuthenticationConfiguration foundConfigurationNumber = DBUserAuth::DefaultConfiguration; |
| |
| // Verify that the external user exists in configured identity store |
| if (!validateExternalUsername(pNode->getExternalUserName().data(), |
| configurationNumber, |
| foundConfigurationNumber)) |
| return; |
| |
| // Get a unique auth ID number |
| Int32 userID = getUniqueAuthID(MIN_USERID, MAX_USERID); |
| assert(isUserID(userID)); |
| setAuthID (userID); |
| |
| // get effective user from the Context |
| Int32 *pUserID = GetCliGlobals()->currContext()->getDatabaseUserID(); |
| setAuthCreator(*pUserID); |
| |
| // Add the user to AUTHS table |
| insertRow(); |
| #if 0 |
| if (pNode->isSchemaSpecified()) |
| { |
| ExeCliInterface cliInterface(STMTHEAP); |
| char buf [1000]; |
| NAString csStmt; |
| COM_SCHEMA_CLASS_PRIVATE = 3, |
| COM_SCHEMA_CLASS_SHARED = 4, |
| COM_SCHEMA_CLASS_DEFAULT = 5}; |
| |
| csStmt = "CREATE "; |
| switch (pNode->getSchemaClass()) |
| { |
| case COM_SCHEMA_CLASS_SHARED: |
| csStmt += "SHARED "; |
| break; |
| case COM_SCHEMA_CLASS_DEFAULT: |
| case COM_SCHEMA_CLASS_PRIVATE: |
| csStmt += "PRIVATE "; |
| break; |
| default: |
| { |
| SEABASEDDL_INTERNAL_ERROR("Unknown schema class in registerUser"); |
| return; |
| } |
| } |
| |
| csStmt += pNode->getSchemaName()->getCatalogName(); |
| csStmt +- "."; |
| csStmt += pNode->getSchemaName()->getSchemaName(); |
| |
| str_sprintf(buf, "CREATE %s SCHEMA %s \"%s\".\"%s\".\"%s\" cascade", |
| (char*)catName.data(), (char*)schName.data(), objName); |
| |
| cliRC = cliInterface.executeImmediate(buf); |
| } |
| #endif |
| } |
| catch (...) |
| { |
| // At this time, an error should be in the diags area. |
| // If there is no error, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("Unexpected error in CmpSeabaseDDLuser::registerUser"); |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // public method: unregisterUser |
| // |
| // This method removes a user from the database |
| // |
| // Input: parse tree containing a definition of the user |
| // Output: the global diags area is set up with the result |
| // ---------------------------------------------------------------------------- |
| void CmpSeabaseDDLuser::unregisterUser(StmtDDLRegisterUser * pNode) |
| |
| { |
| try |
| { |
| // CASCADE option not yet supported |
| if (pNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_ONLY_SUPPORTING_RESTRICT_DROP_BEHAVIOR); |
| return; |
| } |
| |
| // Verify that the specified user name is not reserved |
| if (isAuthNameReserved(pNode->getDbUserName())) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_AUTH_NAME_RESERVED) |
| << DgString0(pNode->getDbUserName().data()); |
| return; |
| } |
| |
| // read user details from the AUTHS table |
| const NAString dbUserName(pNode->getDbUserName()); |
| CmpSeabaseDDLauth::AuthStatus retcode = getUserDetails(dbUserName); |
| if (retcode == STATUS_ERROR) |
| return; |
| if (retcode == STATUS_NOTFOUND) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_USER_NOT_EXIST) |
| << DgString0(dbUserName.data()); |
| return; |
| } |
| |
| if (ComUser::getCurrentUser() != getAuthCreator() && |
| !verifyAuthority(SQLOperation::MANAGE_USERS)) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return; |
| } |
| |
| NAString whereClause(" WHERE AUTH_TYPE = 'R' AND AUTH_CREATOR = "); |
| |
| char authIDString[20]; |
| |
| sprintf(authIDString,"%d",getAuthID()); |
| whereClause += authIDString; |
| |
| if (selectCount(whereClause) > 0) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_NO_UNREG_USER_OWNS_ROLES); |
| return; |
| } |
| |
| NAString privMgrMDLoc; |
| CONCAT_CATSCH(privMgrMDLoc,systemCatalog_.data(),SEABASE_PRIVMGR_SCHEMA); |
| |
| // User does not own any roles, but may have been granted roles. |
| if (CmpCommon::context()->isAuthorizationEnabled()) |
| { |
| |
| PrivMgrRoles role(std::string(MDSchema_.data()), |
| std::string(privMgrMDLoc.data()), |
| CmpCommon::diags()); |
| |
| if (role.isUserGrantedAnyRole(getAuthID())) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_NO_UNREG_USER_GRANTED_ROLES); |
| return; |
| } |
| } |
| |
| // Does user own any objects? |
| NAString whereClause2(" WHERE OBJECT_OWNER = "); |
| |
| NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); |
| char buf[1000]; |
| str_sprintf(buf, "SELECT COUNT(*) FROM %s.\"%s\".%s %s %d", |
| sysCat.data(), SEABASE_MD_SCHEMA, SEABASE_OBJECTS, |
| whereClause2.data(),getAuthID()); |
| |
| Int32 len = 0; |
| Int64 rowCount = 0; |
| ExeCliInterface cliInterface(STMTHEAP); |
| Lng32 cliRC = cliInterface.executeImmediate(buf, (char*)&rowCount, &len, FALSE); |
| if (cliRC != 0) |
| { |
| cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| |
| if (rowCount > 0) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_NO_UNREG_USER_OWNS_OBJECT); |
| return; |
| } |
| |
| // Is user granted any privileges? |
| if (CmpCommon::context()->isAuthorizationEnabled()) |
| { |
| PrivMgr privMgr(std::string(privMgrMDLoc),CmpCommon::diags()); |
| std::vector<PrivClass> privClasses; |
| |
| privClasses.push_back(PrivClass::ALL); |
| |
| std::vector<int64_t> objectUIDs; |
| if (privMgr.isAuthIDGrantedPrivs(getAuthID(),privClasses, objectUIDs)) |
| { |
| NAString objectName = getObjectName(objectUIDs); |
| if (objectName.length() > 0) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_NO_UNREG_USER_HAS_PRIVS) |
| << DgString0(dbUserName.data()) |
| << DgString1(objectName.data()); |
| |
| return; |
| } |
| } |
| } |
| |
| // remove any component privileges granted to this user |
| if (CmpCommon::context()->isAuthorizationEnabled()) |
| { |
| PrivMgrComponentPrivileges componentPrivileges(privMgrMDLoc.data(),CmpCommon::diags()); |
| std::string componentUIDString = "1"; |
| if (!componentPrivileges.dropAllForGrantee(getAuthID())) |
| { |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| } |
| |
| // delete the row |
| deleteRow(getAuthDbName()); |
| } |
| catch (...) |
| { |
| // At this time, an error should be in the diags area. |
| // If there is no error, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("Switch statement in CmpSeabaseDDLuser::unregisterUser"); |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // public method: alterUser |
| // |
| // This method changes a user definition |
| // |
| // Input: parse tree containing a definition of the user change |
| // Output: the global diags area is set up with the result |
| // ---------------------------------------------------------------------------- |
| void CmpSeabaseDDLuser::alterUser (StmtDDLAlterUser * pNode) |
| { |
| try |
| { |
| // read user details from the AUTHS table |
| const NAString dbUserName(pNode->getDatabaseUsername()); |
| CmpSeabaseDDLauth::AuthStatus retcode = getUserDetails(dbUserName); |
| if (retcode == STATUS_ERROR) |
| return; |
| if (retcode == STATUS_NOTFOUND) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_USER_NOT_EXIST) |
| << DgString0(dbUserName.data()); |
| return; |
| } |
| |
| if ((ComUser::getCurrentUser() != getAuthCreator()) && |
| !verifyAuthority(SQLOperation::MANAGE_USERS)) |
| { |
| // No authority. We're outta here. |
| *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return; |
| } |
| |
| // Process the requested operation |
| NAString setClause("set "); |
| switch (pNode->getAlterUserCmdSubType()) |
| { |
| case StmtDDLAlterUser::SET_EXTERNAL_NAME: |
| { |
| // If authExtName already set to specified name, we are done |
| if (getAuthExtName() == pNode->getExternalUsername()) |
| return; |
| |
| // Make sure external user has not already been registered |
| if (authExists(pNode->getExternalUsername(), true)) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_USER_ALREADY_EXISTS) |
| << DgString0(pNode->getExternalUsername().data()); |
| return; |
| } |
| // unexpected error occurred - ? |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) > 0) |
| return; |
| |
| DBUserAuth::AuthenticationConfiguration |
| configurationNumber = DBUserAuth::DefaultConfiguration; |
| DBUserAuth::AuthenticationConfiguration |
| foundConfigurationNumber = DBUserAuth::DefaultConfiguration; |
| |
| // Verify that the external user exists in configured identity store |
| if (!validateExternalUsername(pNode->getExternalUsername().data(), |
| configurationNumber, |
| foundConfigurationNumber)) |
| return; |
| |
| setAuthExtName(pNode->getExternalUsername()); |
| setClause += "auth_ext_name = '"; |
| setClause += getAuthExtName(); |
| setClause += "'"; |
| break; |
| } |
| |
| case StmtDDLAlterUser::SET_IS_VALID_USER: |
| { |
| if (isAuthNameReserved(getAuthDbName())) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_AUTH_NAME_RESERVED) |
| << DgString0(getAuthDbName().data()); |
| return; |
| } |
| |
| setAuthValid(pNode->isValidUser()); |
| setClause += (isAuthValid()) ? "auth_is_valid = 'Y'" : "auth_is_valid = 'N'"; |
| break; |
| } |
| |
| default: |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_UNSUPPORTED_COMMAND_ERROR ); |
| return; |
| } |
| } |
| updateRow(setClause); |
| } |
| catch (...) |
| { |
| // At this time, an error should be in the diags area. |
| // If there is no error, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("Switch statement in CmpSeabaseDDLuser::alterUser"); |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // method: registerStandardUser |
| // |
| // Creates a standard user ie. (DB__ROOT) in the Trafodion metadata |
| // |
| // Input: |
| // authName |
| // authID |
| // ---------------------------------------------------------------------------- |
| void CmpSeabaseDDLuser::registerStandardUser( |
| const std::string authName, |
| const int32_t authID) |
| { |
| setAuthType(COM_USER_CLASS); // we are a user |
| createStandardAuth(authName, authID); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // * * |
| // * Function: validateExternalUsername * |
| // * * |
| // * Determines if an external username is valid. * |
| // * * |
| // ----------------------------------------------------------------------------- |
| // * * |
| // * Parameters: * |
| // * * |
| // * <externalUsername> const char * In * |
| // * is the username to be validated. * |
| // * * |
| // * <configurationNumber> DBUserAuth::AuthenticationConfiguration In * |
| // * specifies which configuration to use to validate the username; a * |
| // * configuration designates one or more identity stores and their * |
| // * parameters. A value of zero indicates the "default" configuration * |
| // * should be used. * |
| // * * |
| // * <foundConfigurationNumber> DBUserAuth::AuthenticationConfiguration & In * |
| // * passes back the configuration used to validate the username. * |
| // * * |
| // ----------------------------------------------------------------------------- |
| inline static bool validateExternalUsername( |
| const char * externalUsername, |
| DBUserAuth::AuthenticationConfiguration configurationNumber, |
| DBUserAuth::AuthenticationConfiguration & foundConfigurationNumber) |
| |
| { |
| |
| // During initialization external checking needs to be disabled to setup |
| // standard database users. |
| if (Get_SqlParser_Flags(DISABLE_EXTERNAL_USERNAME_CHECK)) |
| return true; |
| |
| // Verify that the external username is defined in the identity store. |
| DBUserAuth::CheckUserResult chkUserRslt = DBUserAuth::UserDoesNotExist; |
| |
| chkUserRslt = DBUserAuth::CheckExternalUsernameDefined(externalUsername, |
| configurationNumber, |
| foundConfigurationNumber); |
| |
| // Username was found! |
| if (chkUserRslt == DBUserAuth::UserExists) |
| return true; |
| |
| // Who? |
| if (chkUserRslt == DBUserAuth::UserDoesNotExist) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_USER_NOT_FOUND) |
| << DgString0(externalUsername); |
| return false; |
| } |
| |
| // Problem looking up the username. Could be a bad configuration, a |
| // problem at the identity store, or communicating with the identity store. |
| if (chkUserRslt == DBUserAuth::ErrorDuringCheck) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_COMM_ERROR); |
| return false; |
| } |
| |
| return false; |
| |
| } |
| //---------------------- End of validateExternalUsername ----------------------- |
| |
| // ----------------------------------------------------------------------------- |
| // public method: describe |
| // |
| // This method returns the showddl text for the requested user in string format |
| // |
| // Input: |
| // authName - name of user to describe |
| // |
| // Input/Output: |
| // authText - the REGISTER USER text |
| // |
| // returns result: |
| // true - successful |
| // false - failed (ComDiags area will be set up with appropriate error) |
| //----------------------------------------------------------------------------- |
| bool CmpSeabaseDDLuser::describe (const NAString &authName, NAString &authText) |
| { |
| // If current user matches authName, allow request |
| NAString currentUserName (ComUser::getCurrentUsername()); |
| if ((currentUserName != authName) && !verifyAuthority(SQLOperation::SHOW)) |
| { |
| // No authority. We're outta here. |
| *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return false; |
| } |
| |
| CmpSeabaseDDLauth::AuthStatus retcode = getUserDetails(authName.data()); |
| // If the user was not found, set up an error |
| if (retcode == STATUS_NOTFOUND) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_USER_NOT_EXIST) |
| << DgString0(authName.data()); |
| return false; |
| } |
| |
| // If an error was detected, return |
| if (retcode == STATUS_ERROR) |
| return false; |
| |
| // Generate output text |
| authText = "REGISTER USER \""; |
| authText += getAuthExtName(); |
| if (getAuthExtName() != getAuthDbName()) |
| { |
| authText += "\" AS \""; |
| authText += getAuthDbName(); |
| } |
| authText += "\";\n"; |
| |
| if (!isAuthValid()) |
| { |
| authText += "ALTER USER \""; |
| authText += getAuthDbName(); |
| authText += "\" SET OFFLINE;\n"; |
| } |
| return true; |
| } |
| //------------------------------ End of describe ------------------------------- |
| |
| |
| // **************************************************************************** |
| // Class CmpSeabaseDDLrole methods |
| // **************************************************************************** |
| |
| // ---------------------------------------------------------------------------- |
| // Constructors |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLrole::CmpSeabaseDDLrole( |
| const NAString & systemCatalog, |
| const NAString & MDSchema) |
| : CmpSeabaseDDLauth(systemCatalog,MDSchema) |
| {} |
| |
| CmpSeabaseDDLrole::CmpSeabaseDDLrole(const NAString & systemCatalog) |
| : CmpSeabaseDDLauth() |
| { |
| |
| systemCatalog_ = systemCatalog; |
| |
| CONCAT_CATSCH(MDSchema_,systemCatalog.data(),SEABASE_MD_SCHEMA); |
| |
| } |
| |
| CmpSeabaseDDLrole::CmpSeabaseDDLrole() |
| : CmpSeabaseDDLauth() |
| {} |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Public method: createRole |
| // |
| // Creates a role in the Trafodion metadata |
| // |
| // Input: parse tree containing a definition of the role |
| // Output: the global diags area is set up with the result |
| // ---------------------------------------------------------------------------- |
| void CmpSeabaseDDLrole::createRole(StmtDDLCreateRole * pNode) |
| |
| { |
| |
| // Don't allow roles to be created unless authorization is enabled |
| if (!CmpCommon::context()->isAuthorizationEnabled()) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_AUTHORIZATION_NOT_ENABLED); |
| return; |
| } |
| |
| // Verify user is authorized to perform CREATE ROLE requests |
| if (!verifyAuthority(SQLOperation::MANAGE_ROLES)) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return; |
| } |
| |
| // Set up a global try/catch loop to catch unexpected errors |
| try |
| { |
| |
| // Verify that the specified role name is not reserved |
| setAuthDbName(pNode->getRoleName()); |
| if (isAuthNameReserved(getAuthDbName())) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_AUTH_NAME_RESERVED) |
| << DgString0(getAuthDbName().data()); |
| return; |
| } |
| |
| // Verify that the name does not include unsupported special characters |
| if (!isAuthNameValid(getAuthDbName())) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_INVALID_CHARS_IN_AUTH_NAME) |
| << DgString0(getAuthDbName().data()); |
| return; |
| } |
| |
| // set up class members from parse node |
| setAuthType(COM_ROLE_CLASS); // we are a role |
| setAuthValid(true); // assume a valid role |
| |
| Int64 createTime = NA_JulianTimestamp(); |
| setAuthCreateTime(createTime); |
| setAuthRedefTime(createTime); // make redef time the same as create time |
| |
| // Make sure role has not already been registered |
| if (authExists(getAuthDbName(),false)) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_ALREADY_EXISTS) |
| << DgString0(getAuthDbName().data()); |
| return; |
| } |
| |
| // unexpected error occurred - ? |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) > 0) |
| return; |
| |
| // Get a unique role ID number |
| Int32 roleID = getUniqueAuthID(MIN_ROLEID, MAX_ROLEID); //TODO: add role support |
| assert (isRoleID(roleID)); |
| setAuthID(roleID); |
| |
| std::string creatorUsername; |
| |
| // If the WITH ADMIN clause was specified, then create the role on behalf of the |
| // authorization ID specified in this clause. |
| // Need to translate the creator name to its authID |
| if (pNode->getOwner() == NULL) |
| { |
| // get effective user from the Context |
| Int32 userID = ComUser::getCurrentUser(); |
| setAuthCreator(userID); |
| creatorUsername = ComUser::getCurrentUsername(); |
| } |
| else |
| { |
| const NAString creatorName = |
| pNode->getOwner()->getAuthorizationIdentifier(); |
| Int32 authID = NA_UserIdDefault; |
| Int32 result = ComUser::getUserIDFromUserName(creatorName.data(),authID); |
| if (result != 0) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_USER_NOT_EXIST) |
| << DgString0(creatorName.data()); |
| return; |
| } |
| |
| // TODO: verify creator can create roles |
| setAuthCreator(authID); |
| creatorUsername = creatorName.data(); |
| } |
| // For roles, external and database names are the same. |
| setAuthExtName(getAuthDbName()); |
| // Add the role to AUTHS table |
| insertRow(); |
| |
| // Grant this role to the creator of the role if authorization is enabled. |
| NAString privMgrMDLoc; |
| |
| CONCAT_CATSCH(privMgrMDLoc,systemCatalog_.data(),SEABASE_PRIVMGR_SCHEMA); |
| |
| PrivMgrRoles roles(std::string(MDSchema_.data()),std::string(privMgrMDLoc), |
| CmpCommon::diags()); |
| |
| PrivStatus privStatus = roles.grantRoleToCreator(roleID, |
| getAuthDbName().data(), |
| getAuthCreator(), |
| creatorUsername); |
| if (privStatus != PrivStatus::STATUS_GOOD) |
| { |
| SEABASEDDL_INTERNAL_ERROR("Unable to grant role to role administrator"); |
| return; |
| } |
| } |
| catch (...) |
| { |
| // At this time, an error should be in the diags area. |
| // If there is no error, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("Switch statement in CmpSeabaseDDLrole::createRole"); |
| } |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Public method: createStandardRole |
| // |
| // Creates a standard role (ie. DB__nameROLE) in the Trafodion metadata |
| // |
| // Input: |
| // role name |
| // role ID |
| // |
| // returns: true - added role, |
| // false - did not add role |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLrole::createStandardRole( |
| const std::string roleName, |
| const int32_t roleID) |
| { |
| setAuthType(COM_ROLE_CLASS); // we are a role |
| return createStandardAuth(roleName, roleID); |
| } |
| |
| |
| // ----------------------------------------------------------------------------- |
| // public method: describe |
| // |
| // This method returns the showddl text for the requested role in string format |
| // |
| // Input: |
| // roleName - name of role to describe |
| // |
| // Input/Output: |
| // roleText - the CREATE ROLE (and GRANT ROLE) text |
| // |
| // returns result: |
| // true - successful |
| // false - failed (ComDiags area will be set up with appropriate error) |
| //----------------------------------------------------------------------------- |
| bool CmpSeabaseDDLrole::describe( |
| const NAString & roleName, |
| NAString &roleText) |
| |
| { |
| |
| try |
| { |
| // Can current user perform request |
| Int32 roleID = NA_UserIdDefault; |
| if (ComUser::getAuthIDFromAuthName(roleName.data(), roleID) != 0) |
| roleID = NA_UserIdDefault; |
| |
| if (!ComUser::currentUserHasRole(roleID) && !verifyAuthority(SQLOperation::SHOW)) |
| { |
| // No authority. We're outta here. |
| *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return false; |
| } |
| |
| CmpSeabaseDDLauth::AuthStatus retcode = getRoleDetails(roleName.data()); |
| |
| // If the role was not found, set up an error |
| if (retcode == STATUS_NOTFOUND) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_ROLE_NOT_EXIST) |
| << DgString0(roleName.data()); |
| return false; |
| } |
| |
| // If an error was detected, throw an exception so the catch handler will |
| // put a value in ComDiags area in case no message exists |
| if (retcode == STATUS_ERROR) |
| return false; |
| |
| // Generate output text |
| roleText = "CREATE ROLE \""; |
| roleText += getAuthDbName(); |
| roleText += "\""; |
| |
| // If the role owner is not DB__ROOT, list the user who administers the role. |
| if (getAuthCreator() != ComUser::getRootUserID()) |
| { |
| roleText += " WITH ADMIN \""; |
| |
| char creatorName[MAX_DBUSERNAME_LEN + 1]; |
| int32_t length = 0; |
| |
| Int16 retCode = ComUser::getAuthNameFromAuthID(getAuthCreator(),creatorName, |
| sizeof(creatorName),length); |
| if (retCode != 0) |
| { |
| SEABASEDDL_INTERNAL_ERROR("Role administrator not registered"); |
| UserException excp (NULL, 0); |
| throw excp; |
| } |
| roleText += creatorName; |
| roleText += "\""; |
| } |
| |
| roleText += ";\n"; |
| |
| // See if authorization is enabled. If so, need to list any grants of this |
| // role. Otherwise, we are outta here. |
| if (!CmpCommon::context()->isAuthorizationEnabled()) |
| return true; |
| |
| NAString privMgrMDLoc; |
| |
| CONCAT_CATSCH(privMgrMDLoc,systemCatalog_.data(),SEABASE_PRIVMGR_SCHEMA); |
| |
| PrivMgrRoles roles(std::string(MDSchema_.data()),std::string(privMgrMDLoc), |
| CmpCommon::diags()); |
| |
| |
| std::vector<std::string> granteeNames; |
| std::vector<int32_t> grantDepths; |
| std::vector<int32_t> grantorIDs; |
| |
| PrivStatus privStatus = PrivStatus::STATUS_GOOD; |
| |
| privStatus = roles.fetchUsersForRole(getAuthID(),granteeNames, |
| grantorIDs,grantDepths); |
| |
| // If no users were granted this role, nothing to do. |
| if (privStatus == PrivStatus::STATUS_NOTFOUND || granteeNames.size() == 0) |
| return true; |
| |
| if (privStatus == PrivStatus::STATUS_ERROR) |
| SEABASEDDL_INTERNAL_ERROR("Could not fetch users granted role."); |
| |
| // If CQD to display privilege grants is off, return now |
| if ((CmpCommon::getDefault(SHOWDDL_DISPLAY_PRIVILEGE_GRANTS) == DF_OFF) || |
| ((CmpCommon::getDefault(SHOWDDL_DISPLAY_PRIVILEGE_GRANTS) == DF_SYSTEM) |
| && getenv("SQLMX_REGRESS"))) |
| return true; |
| |
| // Report on each grantee. |
| for (size_t r = 0; r < granteeNames.size(); r++) |
| { |
| // If the grantor is system, we want to show the grant, but exclude |
| // it from executing in a playback script. |
| if (grantorIDs[r] == ComUser::getSystemUserID()) |
| roleText += "-- "; |
| roleText += "GRANT ROLE \""; |
| roleText += getAuthDbName(); |
| roleText += "\" TO \""; |
| roleText += granteeNames[r].c_str(); |
| roleText += "\""; |
| // Grant depth is either zero or non-zero for now. If non-zero, |
| // report WITH ADMIN OPTION. |
| if (grantDepths[r] != 0) |
| roleText += " WITH ADMIN OPTION"; |
| |
| // If the grantor is not DB__ROOT or _SYSTEM, list the grantor. |
| if (grantorIDs[r] != ComUser::getRootUserID() && |
| grantorIDs[r] != ComUser::getSystemUserID()) |
| { |
| roleText += " GRANTED BY \""; |
| char grantorName[MAX_DBUSERNAME_LEN + 1]; |
| int32_t length = 0; |
| |
| Int16 retCode = ComUser::getAuthNameFromAuthID(grantorIDs[r], |
| grantorName, |
| sizeof(grantorName), |
| length); |
| if (retCode != 0) |
| { |
| SEABASEDDL_INTERNAL_ERROR("Role grantor not registered"); |
| UserException excp(NULL,0); |
| throw excp; |
| } |
| |
| roleText += grantorName; |
| roleText += "\""; |
| } |
| roleText += ";\n"; |
| } |
| } |
| |
| catch (...) |
| { |
| // At this time, an error should be in the diags area. |
| // If there is no error, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("Switch statement in CmpSeabaseDDLrole::describe"); |
| |
| return false; |
| } |
| |
| return true; |
| } |
| //------------------------------ End of describe ------------------------------- |
| |
| // ---------------------------------------------------------------------------- |
| // Public method: dropRole |
| // |
| // Drops a role from the Trafodion metadata |
| // |
| // Input: parse tree containing a definition of the role |
| // Output: the global diags area is set up with the result |
| // ---------------------------------------------------------------------------- |
| void CmpSeabaseDDLrole::dropRole(StmtDDLCreateRole * pNode) |
| |
| { |
| |
| // Set up a global try/catch loop to catch unexpected errors |
| try |
| { |
| const NAString roleName(pNode->getRoleName()); |
| // Verify that the specified user name is not reserved |
| setAuthDbName(roleName); |
| if (isAuthNameReserved(getAuthDbName())) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_AUTH_NAME_RESERVED) |
| << DgString0(roleName.data()); |
| return; |
| } |
| |
| // read role details from the AUTHS table |
| CmpSeabaseDDLauth::AuthStatus retcode = getRoleDetails(roleName); |
| if (retcode == STATUS_ERROR) |
| return; |
| |
| if (retcode == STATUS_NOTFOUND) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_ROLE_NOT_EXIST) |
| << DgString0(roleName.data()); |
| return; |
| } |
| |
| if (ComUser::getCurrentUser() != getAuthCreator()) |
| { |
| // If the user does not have privilege, allow the drop if |
| // the user has been granted an admin role and |
| // the role being dropped is not an admin role and |
| // the authCreator of the role being dropped matches the admin role |
| if (verifyAuthority(SQLOperation::MANAGE_ROLES) == false) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); |
| return; |
| } |
| } |
| |
| NAString privMgrMDLoc; |
| |
| CONCAT_CATSCH(privMgrMDLoc,systemCatalog_.data(),SEABASE_PRIVMGR_SCHEMA); |
| |
| PrivMgrRoles role(std::string(MDSchema_.data()),std::string(privMgrMDLoc), |
| CmpCommon::diags()); |
| |
| // If authorization is not enabled and a role has been defined, skip |
| // looking for dependencies and just remove the role from auths. |
| if (CmpCommon::context()->isAuthorizationEnabled()) |
| { |
| //TODO: Could support a CASCADE option that would clean up |
| // grants and dependent objects. |
| |
| // First, see if role has been granted |
| bool roleIsGranted = role.isGranted(getAuthID(),true); |
| if (roleIsGranted) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_ROLE_IS_GRANTED_NO_DROP); |
| return; |
| } |
| |
| // Now see if the role has been granted any privileges. |
| // TODO: could allow priv grants if no dependent objects. |
| PrivMgr privMgr(std::string(privMgrMDLoc),CmpCommon::diags()); |
| std::vector<PrivClass> privClasses; |
| |
| privClasses.push_back(PrivClass::ALL); |
| std::vector<int64_t> objectUIDs; |
| |
| if (privMgr.isAuthIDGrantedPrivs(getAuthID(),privClasses, objectUIDs)) |
| { |
| NAString objectName = getObjectName(objectUIDs); |
| if (objectName.length() > 0) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_ROLE_HAS_PRIVS_NO_DROP) |
| << DgString0(roleName.data()) |
| << DgString1(objectName.data()); |
| return; |
| } |
| } |
| |
| // Role has not been granted and no privileges have been granted to |
| // the role. Remove the system grant. |
| PrivStatus privStatus = role.revokeRoleFromCreator(getAuthID(), |
| getAuthCreator()); |
| |
| if (privStatus != PrivStatus::STATUS_GOOD) |
| { |
| SEABASEDDL_INTERNAL_ERROR("Unable to remove grant to role administrator"); |
| return; |
| } |
| } |
| |
| // delete the row |
| deleteRow(roleName); |
| } |
| catch (...) |
| { |
| // At this time, an error should be in the diags area. |
| // If there is no error, set up an internal error |
| if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) |
| SEABASEDDL_INTERNAL_ERROR("Switch statement in CmpSeabaseDDLrole::dropRole"); |
| } |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Public method: dropStandardRole |
| // |
| // Drops a standard role (ie. DB__nameROLE) from the Trafodion metadata |
| // |
| // Input: role name |
| // ---------------------------------------------------------------------------- |
| void CmpSeabaseDDLrole::dropStandardRole(const std::string roleName) |
| |
| { |
| |
| // Verify name is a standard name |
| |
| size_t prefixLength = strlen(RESERVED_AUTH_NAME_PREFIX); |
| |
| if (roleName.size() <= prefixLength || |
| roleName.compare(0,prefixLength,RESERVED_AUTH_NAME_PREFIX) != 0) |
| { |
| *CmpCommon::diags() << DgSqlCode(-CAT_ROLE_NOT_EXIST) |
| << DgString0(roleName.c_str()); |
| return; |
| } |
| // delete the row |
| deleteRow(roleName.c_str()); |
| |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // public method: getRoleDetails |
| // |
| // Create the CmpSeabaseDDLuser class containing user details for the |
| // requested username |
| // |
| // Input: |
| // userName - the database username to retrieve details for |
| // isExternal - |
| // true - the username is the external name (auth_ext_name) |
| // false - the username is the database name (auth_db_name) |
| // |
| // Output: |
| // Returned parameter: |
| // STATUS_GOOD: authorization details are populated: |
| // STATUS_NOTFOUND: authorization details were not found |
| // STATUS_WARNING: (not 100) warning was returned, diags area populated |
| // STATUS_ERROR: error was returned, diags area populated |
| // ---------------------------------------------------------------------------- |
| CmpSeabaseDDLauth::AuthStatus |
| CmpSeabaseDDLrole::getRoleDetails(const char *pRoleName) |
| { |
| CmpSeabaseDDLauth::AuthStatus retcode = getAuthDetails(pRoleName,false); |
| if (retcode == STATUS_GOOD && !isRole()) |
| { |
| *CmpCommon::diags() << DgSqlCode (-CAT_IS_NOT_A_ROLE) |
| << DgString0(getAuthDbName().data()); |
| retcode = STATUS_ERROR; |
| } |
| return retcode; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Public method: getRoleIDFromRoleName |
| // |
| // Lookup a role name in the Trafodion metadata |
| // |
| // Input: Role name to lookup |
| // Output: Role ID if role was found |
| // true returned if role found |
| // false returned if role not found |
| // ---------------------------------------------------------------------------- |
| bool CmpSeabaseDDLrole::getRoleIDFromRoleName( |
| const char * roleName, |
| Int32 & roleID) |
| |
| { |
| |
| CmpSeabaseDDLauth::AuthStatus authStatus = getAuthDetails(roleName,false); |
| |
| if (authStatus != STATUS_GOOD && authStatus != STATUS_WARNING) |
| return false; |
| |
| if (getAuthType() != COM_ROLE_CLASS) |
| return false; |
| |
| roleID = getAuthID(); |
| return true; |
| |
| } |