From 1c2e0d91dc8a10ee4504043433aa924c9a713e9c Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Wed, 25 Sep 2024 09:02:38 +0000 Subject: [PATCH 01/41] support db_accessadmin Signed-off-by: Tanzeel Khan --- .../babelfishpg_tsql/sql/babelfishpg_tsql.sql | 13 +- contrib/babelfishpg_tsql/sql/ownership.sql | 6 +- .../babelfishpg_tsql--4.3.0--4.4.0.sql | 214 ++++++++++++++++++ contrib/babelfishpg_tsql/src/catalog.c | 91 +++++--- contrib/babelfishpg_tsql/src/catalog.h | 5 +- contrib/babelfishpg_tsql/src/dbcmds.c | 175 +++++++++++++- contrib/babelfishpg_tsql/src/multidb.c | 26 ++- contrib/babelfishpg_tsql/src/multidb.h | 1 + contrib/babelfishpg_tsql/src/pl_exec-2.c | 2 +- contrib/babelfishpg_tsql/src/pl_handler.c | 183 ++++++++++----- contrib/babelfishpg_tsql/src/procedures.c | 10 +- contrib/babelfishpg_tsql/src/rolecmds.c | 8 +- test/JDBC/expected/BABEL-2403.out | 12 + test/JDBC/expected/BABEL-LOGIN-USER-EXT.out | 35 ++- test/JDBC/expected/BABEL-LOGIN-vu-verify.out | 10 +- test/JDBC/expected/BABEL-USER.out | 5 + .../Test-sp_helpdbfixedrole-vu-verify.out | 3 + .../Test_alter_db_rename-vu-verify.out | 3 + .../expected/Test_rename_db_single-db.out | 8 + .../Test_sp_rename_database-vu-verify.out | 3 + .../expected/Test_sp_renamedb-vu-verify.out | 3 + .../JDBC/expected/restrict_drop_user_role.out | 36 +-- test/JDBC/expected/single_db/BABEL-2403.out | 12 + .../single_db/BABEL-LOGIN-USER-EXT.out | 33 ++- test/JDBC/expected/single_db/BABEL-USER.out | 5 + .../single_db/Test_rename_db_single-db.out | 8 + .../single_db/restrict_drop_user_role.out | 32 ++- test/JDBC/input/BABEL-LOGIN-USER-EXT.mix | 4 +- .../input/ownership/BABEL-LOGIN-vu-verify.mix | 2 +- test/JDBC/input/restrict_drop_user_role.mix | 9 + .../expected_drop.out | 1 + 31 files changed, 801 insertions(+), 157 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql index 8a0721961b..e16f957311 100644 --- a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql +++ b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql @@ -2118,7 +2118,7 @@ BEGIN LEFT OUTER JOIN pg_catalog.pg_roles AS Base4 ON Base4.rolname = Bsdb.owner WHERE Ext1.database_name = DB_NAME() AND (Ext1.type != 'R' OR Ext1.type != 'A') - AND Ext1.orig_username != 'db_owner' + AND Ext1.orig_username NOT IN ('db_owner', 'db_accessadmin') ORDER BY UserName, RoleName; END -- If the security account is the db fixed role - db_owner @@ -2150,7 +2150,7 @@ BEGIN WHERE Ext1.database_name = DB_NAME() AND Ext2.database_name = DB_NAME() AND Ext1.type = 'R' - AND Ext2.orig_username != 'db_owner' + AND Ext2.orig_username NOT IN ('db_owner', 'db_accessadmin') AND (Ext1.orig_username = @name_in_db OR pg_catalog.lower(Ext1.orig_username) = pg_catalog.lower(@name_in_db)) ORDER BY Role_name, Users_in_role; END @@ -2188,7 +2188,7 @@ BEGIN LEFT OUTER JOIN pg_catalog.pg_roles AS Base4 ON Base4.rolname = Bsdb.owner WHERE Ext1.database_name = DB_NAME() AND (Ext1.type != 'R' OR Ext1.type != 'A') - AND Ext1.orig_username != 'db_owner' + AND Ext1.orig_username NOT IN ('db_owner', 'db_accessadmin') AND (Ext1.orig_username = @name_in_db OR pg_catalog.lower(Ext1.orig_username) = pg_catalog.lower(@name_in_db)) ORDER BY UserName, RoleName; END @@ -2348,13 +2348,16 @@ CREATE OR REPLACE PROCEDURE sys.sp_helpdbfixedrole("@rolename" sys.SYSNAME = NUL $$ BEGIN -- Returns a list of the fixed database roles. - -- Only fixed role present in babelfish is db_owner. IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_owner' BEGIN SELECT CAST('db_owner' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Owners' AS sys.nvarchar(70)) AS Description; END + ELSE IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_accessadmin' + BEGIN + SELECT CAST('db_accessadmin' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Access Administrators' AS sys.nvarchar(70)) AS Description; + END ELSE IF LOWER(RTRIM(@rolename)) IN ( - 'db_accessadmin','db_securityadmin','db_ddladmin', 'db_backupoperator', + 'db_securityadmin','db_ddladmin', 'db_backupoperator', 'db_datareader', 'db_datawriter', 'db_denydatareader', 'db_denydatawriter') BEGIN -- Return an empty result set instead of raising an error diff --git a/contrib/babelfishpg_tsql/sql/ownership.sql b/contrib/babelfishpg_tsql/sql/ownership.sql index dbbda19e43..f746ea93c3 100644 --- a/contrib/babelfishpg_tsql/sql/ownership.sql +++ b/contrib/babelfishpg_tsql/sql/ownership.sql @@ -259,7 +259,9 @@ CREATE OR REPLACE PROCEDURE initialize_babelfish ( sa_name VARCHAR(128) ) LANGUAGE plpgsql AS $$ DECLARE - reserved_roles varchar[] := ARRAY['sysadmin', 'master_dbo', 'master_guest', 'master_db_owner', 'tempdb_dbo', 'tempdb_guest', 'tempdb_db_owner', 'msdb_dbo', 'msdb_guest', 'msdb_db_owner']; + reserved_roles varchar[] := ARRAY['sysadmin', 'master_dbo', 'master_guest', 'master_db_owner', 'master_db_accessadmin', + 'tempdb_dbo', 'tempdb_guest', 'tempdb_db_owner', 'tempdb_db_accessadmin', + 'msdb_dbo', 'msdb_guest', 'msdb_db_owner', 'msdb_db_accessadmin']; user_id oid := -1; db_name name := NULL; role_name varchar; @@ -450,7 +452,7 @@ ON Base.rolname = Ext.rolname LEFT OUTER JOIN pg_catalog.pg_roles Base2 ON Ext.login_name = Base2.rolname WHERE Ext.database_name = DB_NAME() - AND (Ext.orig_username IN ('dbo', 'db_owner', 'guest') -- system users should always be visible + AND (Ext.orig_username IN ('dbo', 'db_owner', 'db_accessadmin', 'guest') -- system users should always be visible OR pg_has_role(Ext.rolname, 'MEMBER')) -- Current user should be able to see users it has permission of UNION ALL SELECT diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index b9831532a8..946df73dd0 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -38,6 +38,15 @@ LANGUAGE plpgsql; * final behaviour. */ + +CREATE OR REPLACE PROCEDURE sys.babel_create_database_roles() +LANGUAGE C +AS 'babelfishpg_tsql', 'create_database_roles_for_all_dbs'; + +CALL sys.babel_create_database_roles(); + +DROP PROCEDURE sys.babel_create_database_roles(); + -- Assigning dbo role to the db_owner login DO $$ DECLARE @@ -1906,6 +1915,211 @@ CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'sp_statistics_inte CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'sp_pkeys_internal_deprecated_in_4_4_0'); +-- DATABASE_PRINCIPALS +CREATE OR REPLACE VIEW sys.database_principals AS +SELECT +CAST(Ext.orig_username AS SYS.SYSNAME) AS name, +CAST(Base.oid AS INT) AS principal_id, +CAST(Ext.type AS CHAR(1)) as type, +CAST( + CASE + WHEN Ext.type = 'S' THEN 'SQL_USER' + WHEN Ext.type = 'R' THEN 'DATABASE_ROLE' + WHEN Ext.type = 'U' THEN 'WINDOWS_USER' + ELSE NULL + END + AS SYS.NVARCHAR(60)) AS type_desc, +CAST(Ext.default_schema_name AS SYS.SYSNAME) AS default_schema_name, +CAST(Ext.create_date AS SYS.DATETIME) AS create_date, +CAST(Ext.modify_date AS SYS.DATETIME) AS modify_date, +CAST(Ext.owning_principal_id AS INT) AS owning_principal_id, +CAST(CAST(Base2.oid AS INT) AS SYS.VARBINARY(85)) AS SID, +CAST(Ext.is_fixed_role AS SYS.BIT) AS is_fixed_role, +CAST(Ext.authentication_type AS INT) AS authentication_type, +CAST(Ext.authentication_type_desc AS SYS.NVARCHAR(60)) AS authentication_type_desc, +CAST(Ext.default_language_name AS SYS.SYSNAME) AS default_language_name, +CAST(Ext.default_language_lcid AS INT) AS default_language_lcid, +CAST(Ext.allow_encrypted_value_modifications AS SYS.BIT) AS allow_encrypted_value_modifications +FROM pg_catalog.pg_roles AS Base INNER JOIN sys.babelfish_authid_user_ext AS Ext +ON Base.rolname = Ext.rolname +LEFT OUTER JOIN pg_catalog.pg_roles Base2 +ON Ext.login_name = Base2.rolname +WHERE Ext.database_name = DB_NAME() + AND (Ext.orig_username IN ('dbo', 'db_owner', 'db_accessadmin', 'guest') -- system users should always be visible + OR pg_has_role(Ext.rolname, 'MEMBER')) -- Current user should be able to see users it has permission of +UNION ALL +SELECT +CAST(name AS SYS.SYSNAME) AS name, +CAST(-1 AS INT) AS principal_id, +CAST(type AS CHAR(1)) as type, +CAST( + CASE + WHEN type = 'S' THEN 'SQL_USER' + WHEN type = 'R' THEN 'DATABASE_ROLE' + WHEN type = 'U' THEN 'WINDOWS_USER' + ELSE NULL + END + AS SYS.NVARCHAR(60)) AS type_desc, +CAST(NULL AS SYS.SYSNAME) AS default_schema_name, +CAST(NULL AS SYS.DATETIME) AS create_date, +CAST(NULL AS SYS.DATETIME) AS modify_date, +CAST(-1 AS INT) AS owning_principal_id, +CAST(CAST(0 AS INT) AS SYS.VARBINARY(85)) AS SID, +CAST(0 AS SYS.BIT) AS is_fixed_role, +CAST(-1 AS INT) AS authentication_type, +CAST(NULL AS SYS.NVARCHAR(60)) AS authentication_type_desc, +CAST(NULL AS SYS.SYSNAME) AS default_language_name, +CAST(-1 AS INT) AS default_language_lcid, +CAST(0 AS SYS.BIT) AS allow_encrypted_value_modifications +FROM (VALUES ('public', 'R'), ('sys', 'S'), ('INFORMATION_SCHEMA', 'S')) as dummy_principals(name, type); +GRANT SELECT ON sys.database_principals TO PUBLIC; + +CREATE OR REPLACE PROCEDURE sys.sp_helpdbfixedrole("@rolename" sys.SYSNAME = NULL) AS +$$ +BEGIN + -- Returns a list of the fixed database roles. + -- Only fixed role present in babelfish is db_owner. + IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_owner' + BEGIN + SELECT CAST('db_owner' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Owners' AS sys.nvarchar(70)) AS Description; + END + ELSE IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_accessadmin' + BEGIN + SELECT CAST('db_accessadmin' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Access Administrators' AS sys.nvarchar(70)) AS Description; + END + ELSE IF LOWER(RTRIM(@rolename)) IN ( + 'db_accessadmin','db_securityadmin','db_ddladmin', 'db_backupoperator', + 'db_securityadmin','db_ddladmin', 'db_backupoperator', + 'db_datareader', 'db_datawriter', 'db_denydatareader', 'db_denydatawriter') + BEGIN + -- Return an empty result set instead of raising an error + SELECT CAST(NULL AS sys.SYSNAME) AS DbFixedRole, CAST(NULL AS sys.nvarchar(70)) AS Description + WHERE 1=0; + END + ELSE + RAISERROR('''%s'' is not a known fixed role.', 16, 1, @rolename); +END +$$ +LANGUAGE 'pltsql'; +GRANT EXECUTE ON PROCEDURE sys.sp_helpdbfixedrole TO PUBLIC; + +CREATE OR REPLACE PROCEDURE sys.sp_helpuser("@name_in_db" sys.SYSNAME = NULL) AS +$$ +BEGIN + -- If security account is not specified, return info about all users + IF @name_in_db IS NULL + BEGIN + SELECT CAST(Ext1.orig_username AS SYS.SYSNAME) AS 'UserName', + CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN 'db_owner' + WHEN Ext2.orig_username IS NULL THEN 'public' + ELSE Ext2.orig_username END + AS SYS.SYSNAME) AS 'RoleName', + CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN Base4.rolname COLLATE database_default + ELSE LogExt.orig_loginname END + AS SYS.SYSNAME) AS 'LoginName', + CAST(LogExt.default_database_name AS SYS.SYSNAME) AS 'DefDBName', + CAST(Ext1.default_schema_name AS SYS.SYSNAME) AS 'DefSchemaName', + CAST(Base1.oid AS INT) AS 'UserID', + CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN CAST(Base4.oid AS INT) + WHEN Ext1.orig_username = 'guest' THEN CAST(0 AS INT) + ELSE CAST(Base3.oid AS INT) END + AS SYS.VARBINARY(85)) AS 'SID' + FROM sys.babelfish_authid_user_ext AS Ext1 + INNER JOIN pg_catalog.pg_roles AS Base1 ON Base1.rolname = Ext1.rolname + LEFT OUTER JOIN pg_catalog.pg_auth_members AS Authmbr ON Base1.oid = Authmbr.member + LEFT OUTER JOIN pg_catalog.pg_roles AS Base2 ON Base2.oid = Authmbr.roleid + LEFT OUTER JOIN sys.babelfish_authid_user_ext AS Ext2 ON Base2.rolname = Ext2.rolname + LEFT OUTER JOIN sys.babelfish_authid_login_ext As LogExt ON LogExt.rolname = Ext1.login_name + LEFT OUTER JOIN pg_catalog.pg_roles AS Base3 ON Base3.rolname = LogExt.rolname + LEFT OUTER JOIN sys.babelfish_sysdatabases AS Bsdb ON Bsdb.name = DB_NAME() + LEFT OUTER JOIN pg_catalog.pg_roles AS Base4 ON Base4.rolname = Bsdb.owner + WHERE Ext1.database_name = DB_NAME() + AND (Ext1.type != 'R' OR Ext1.type != 'A') + AND Ext1.orig_username != 'db_owner' + AND Ext1.orig_username NOT IN ('db_owner', 'db_accessadmin') + ORDER BY UserName, RoleName; + END + -- If the security account is the db fixed role - db_owner + ELSE IF @name_in_db = 'db_owner' + BEGIN + -- TODO: Need to change after we can add/drop members to/from db_owner + SELECT CAST('db_owner' AS SYS.SYSNAME) AS 'Role_name', + ROLE_ID('db_owner') AS 'Role_id', + CAST('dbo' AS SYS.SYSNAME) AS 'Users_in_role', + USER_ID('dbo') AS 'Userid'; + END + -- If the security account is a db role + ELSE IF EXISTS (SELECT 1 + FROM sys.babelfish_authid_user_ext + WHERE (orig_username = @name_in_db + OR pg_catalog.lower(orig_username) = pg_catalog.lower(@name_in_db)) + AND database_name = DB_NAME() + AND type = 'R') + BEGIN + SELECT CAST(Ext1.orig_username AS SYS.SYSNAME) AS 'Role_name', + CAST(Base1.oid AS INT) AS 'Role_id', + CAST(Ext2.orig_username AS SYS.SYSNAME) AS 'Users_in_role', + CAST(Base2.oid AS INT) AS 'Userid' + FROM sys.babelfish_authid_user_ext AS Ext2 + INNER JOIN pg_catalog.pg_roles AS Base2 ON Base2.rolname = Ext2.rolname + INNER JOIN pg_catalog.pg_auth_members AS Authmbr ON Base2.oid = Authmbr.member + LEFT OUTER JOIN pg_catalog.pg_roles AS Base1 ON Base1.oid = Authmbr.roleid + LEFT OUTER JOIN sys.babelfish_authid_user_ext AS Ext1 ON Base1.rolname = Ext1.rolname + WHERE Ext1.database_name = DB_NAME() + AND Ext2.database_name = DB_NAME() + AND Ext1.type = 'R' + AND Ext2.orig_username != 'db_owner' + AND Ext2.orig_username NOT IN ('db_owner', 'db_accessadmin') + AND (Ext1.orig_username = @name_in_db OR pg_catalog.lower(Ext1.orig_username) = pg_catalog.lower(@name_in_db)) + ORDER BY Role_name, Users_in_role; + END + -- If the security account is a user + ELSE IF EXISTS (SELECT 1 + FROM sys.babelfish_authid_user_ext + WHERE (orig_username = @name_in_db + OR pg_catalog.lower(orig_username) = pg_catalog.lower(@name_in_db)) + AND database_name = DB_NAME() + AND type != 'R') + BEGIN + SELECT DISTINCT CAST(Ext1.orig_username AS SYS.SYSNAME) AS 'UserName', + CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN 'db_owner' + WHEN Ext2.orig_username IS NULL THEN 'public' + ELSE Ext2.orig_username END + AS SYS.SYSNAME) AS 'RoleName', + CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN Base4.rolname COLLATE database_default + ELSE LogExt.orig_loginname END + AS SYS.SYSNAME) AS 'LoginName', + CAST(LogExt.default_database_name AS SYS.SYSNAME) AS 'DefDBName', + CAST(Ext1.default_schema_name AS SYS.SYSNAME) AS 'DefSchemaName', + CAST(Base1.oid AS INT) AS 'UserID', + CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN CAST(Base4.oid AS INT) + WHEN Ext1.orig_username = 'guest' THEN CAST(0 AS INT) + ELSE CAST(Base3.oid AS INT) END + AS SYS.VARBINARY(85)) AS 'SID' + FROM sys.babelfish_authid_user_ext AS Ext1 + INNER JOIN pg_catalog.pg_roles AS Base1 ON Base1.rolname = Ext1.rolname + LEFT OUTER JOIN pg_catalog.pg_auth_members AS Authmbr ON Base1.oid = Authmbr.member + LEFT OUTER JOIN pg_catalog.pg_roles AS Base2 ON Base2.oid = Authmbr.roleid + LEFT OUTER JOIN sys.babelfish_authid_user_ext AS Ext2 ON Base2.rolname = Ext2.rolname + LEFT OUTER JOIN sys.babelfish_authid_login_ext As LogExt ON LogExt.rolname = Ext1.login_name + LEFT OUTER JOIN pg_catalog.pg_roles AS Base3 ON Base3.rolname = LogExt.rolname + LEFT OUTER JOIN sys.babelfish_sysdatabases AS Bsdb ON Bsdb.name = DB_NAME() + LEFT OUTER JOIN pg_catalog.pg_roles AS Base4 ON Base4.rolname = Bsdb.owner + WHERE Ext1.database_name = DB_NAME() + AND (Ext1.type != 'R' OR Ext1.type != 'A') + AND Ext1.orig_username != 'db_owner' + AND Ext1.orig_username NOT IN ('db_owner', 'db_accessadmin') + AND (Ext1.orig_username = @name_in_db OR pg_catalog.lower(Ext1.orig_username) = pg_catalog.lower(@name_in_db)) + ORDER BY UserName, RoleName; + END + -- If the security account is not valid + ELSE + RAISERROR ( 'The name supplied (%s) is not a user, role, or aliased login.', 16, 1, @name_in_db); +END; +$$ +LANGUAGE 'pltsql'; +GRANT EXECUTE on PROCEDURE sys.sp_helpuser TO PUBLIC; + -- Drops the temporary procedure used by the upgrade script. -- Please have this be one of the last statements executed in this upgrade script. DROP PROCEDURE sys.babelfish_drop_deprecated_object(varchar, varchar, varchar); diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 1c2db7f299..30c2c28d8f 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -849,24 +849,17 @@ get_authid_login_ext_idx_oid(void) *****************************************/ bool -is_user(Oid role_oid) +is_user(Oid role_oid, bool current_db_only) { - bool is_user = true; + bool is_user = false; + bool isnull; HeapTuple tuple; - HeapTuple authtuple; - NameData rolname; + char *rolname; - authtuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(role_oid)); - if (!HeapTupleIsValid(authtuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("role with OID %u does not exist", role_oid))); - rolname = ((Form_pg_authid) GETSTRUCT(authtuple))->rolname; - tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, NameGetDatum(&rolname)); + rolname = GetUserNameFromId(role_oid, false); + tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(rolname)); - if (!HeapTupleIsValid(tuple)) - is_user = false; - else + if (HeapTupleIsValid(tuple)) { BpChar type = ((Form_authid_user_ext) GETSTRUCT(tuple))->type; char *type_str = bpchar_to_cstring(&type); @@ -875,45 +868,72 @@ is_user(Oid role_oid) * Only sysadmin can not be dropped. For the rest of the cases i.e., type * is "S" or "U" etc, we should drop the user */ - if (strcmp(type_str, "R") == 0) - is_user = false; + if (strcmp(type_str, "R") != 0) + { + if (current_db_only) + { + Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_database_name, &isnull); + char *db_name_cstring = TextDatumGetCString(db_name); + char *current_db_name = get_cur_db_name(); + + is_user = (strcmp(db_name_cstring, current_db_name) == 0); + + pfree(db_name_cstring); + pfree(current_db_name); + } + else + is_user = true; + } + ReleaseSysCache(tuple); + pfree(type_str); } - ReleaseSysCache(authtuple); + pfree(rolname); return is_user; } bool -is_role(Oid role_oid) +is_role(Oid role_oid, bool current_db_only) { - bool is_role = true; + bool is_role = false; + bool isnull; HeapTuple tuple; - HeapTuple authtuple; - NameData rolname; + char *rolname; - authtuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(role_oid)); - if (!HeapTupleIsValid(authtuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("role with OID %u does not exist", role_oid))); - rolname = ((Form_pg_authid) GETSTRUCT(authtuple))->rolname; - tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, NameGetDatum(&rolname)); + rolname = GetUserNameFromId(role_oid, false); + tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(rolname)); - if (!HeapTupleIsValid(tuple)) - is_role = false; - else + if (HeapTupleIsValid(tuple)) { BpChar type = ((Form_authid_user_ext) GETSTRUCT(tuple))->type; char *type_str = bpchar_to_cstring(&type); - if (strcmp(type_str, "R") != 0) - is_role = false; + if (strcmp(type_str, "R") == 0) + { + if (current_db_only) + { + Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_database_name, &isnull); + char *db_name_cstring = TextDatumGetCString(db_name); + char *current_db_name = get_cur_db_name(); + + is_role = (strcmp(db_name_cstring, current_db_name) == 0); + + pfree(db_name_cstring); + pfree(current_db_name); + } + else + is_role = true; + } + ReleaseSysCache(tuple); + pfree(type_str); } - ReleaseSysCache(authtuple); + pfree(rolname); return is_role; } @@ -4935,7 +4955,8 @@ rename_tsql_db(char *old_db_name, char *new_db_name) if (SINGLE_DB == get_migration_mode() && ((strlen(role) == 3 && strncmp(role, "dbo", 3) == 0) || - (strlen(role) == 8 && strncmp(role, "db_owner", 8) == 0))) + (strlen(role) == 8 && strncmp(role, "db_owner", 8) == 0) || + (strlen(role) == 14 && strncmp(role, DB_ACCESSADMIN, 14) == 0))) continue; old_role_name = get_physical_user_name(old_db_name, role, true); diff --git a/contrib/babelfishpg_tsql/src/catalog.h b/contrib/babelfishpg_tsql/src/catalog.h index 2125582eec..347b93baa9 100644 --- a/contrib/babelfishpg_tsql/src/catalog.h +++ b/contrib/babelfishpg_tsql/src/catalog.h @@ -146,8 +146,8 @@ extern Oid get_authid_login_ext_idx_oid(void); extern Oid bbf_authid_user_ext_oid; extern Oid bbf_authid_user_ext_idx_oid; -extern bool is_user(Oid role_oid); -extern bool is_role(Oid role_oid); +extern bool is_user(Oid role_oid, bool current_db_only); +extern bool is_role(Oid role_oid, bool current_db_only); extern Oid get_authid_user_ext_oid(void); extern Oid get_authid_user_ext_idx_oid(void); extern char *get_authid_user_ext_physical_name(const char *db_name, const char *login_name); @@ -312,6 +312,7 @@ typedef FormData_bbf_function_ext *Form_bbf_function_ext; #define Anum_bbf_schema_perms_grantor 8 #define PUBLIC_ROLE_NAME "public" +#define DB_ACCESSADMIN "db_accessadmin" #define PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA "ALL" #define ALL_PERMISSIONS_ON_RELATION 47 /* last 6 bits as 101111 represents ALL privileges on a relation. */ #define ALL_PERMISSIONS_ON_FUNCTION 128 /* last 8 bits as 10000000 represents ALL privileges on a procedure/function. */ diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index ac02dd079e..fcca33daf3 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -86,12 +86,14 @@ gen_createdb_subcmds(const char *dbname, const char *owner) const char *schema; const char *dbo; const char *db_owner; + const char *db_accessadmin; const char *guest; const char *guest_schema; schema = get_dbo_schema_name(dbname); dbo = get_dbo_role_name(dbname); db_owner = get_db_owner_name(dbname); + db_accessadmin = get_db_accessadmin_role_name(dbname); guest = get_guest_role_name(dbname); guest_schema = get_guest_schema_name(dbname); @@ -106,6 +108,10 @@ gen_createdb_subcmds(const char *dbname, const char *owner) appendStringInfo(&query, "GRANT CREATE, CONNECT, TEMPORARY ON DATABASE dummy TO dummy; "); appendStringInfo(&query, "GRANT dummy TO dummy; "); + /* create db_accessadmin for database */ + appendStringInfo(&query, "CREATE ROLE dummy ROLE dummy; "); + appendStringInfo(&query, "GRANT CREATE ON DATABASE dummy TO dummy; "); + if (guest) { appendStringInfo(&query, "CREATE ROLE dummy INHERIT ROLE dummy; "); @@ -125,9 +131,9 @@ gen_createdb_subcmds(const char *dbname, const char *owner) res = raw_parser(query.data, RAW_PARSE_DEFAULT); if (guest) - expected_stmt_num = list_length(logins) > 0 ? 10 : 9; + expected_stmt_num = list_length(logins) > 0 ? 12 : 11; else - expected_stmt_num = 7; + expected_stmt_num = 9; if (list_length(res) != expected_stmt_num) ereport(ERROR, @@ -147,10 +153,15 @@ gen_createdb_subcmds(const char *dbname, const char *owner) /* Grant dbo role to owner */ stmt = parsetree_nth_stmt(res, i++); - update_GrantRoleStmt(stmt, list_make1(make_accesspriv_node(dbo)), list_make1(make_rolespec_node(owner))); + stmt = parsetree_nth_stmt(res, i++); + update_CreateRoleStmt(stmt, db_accessadmin, db_owner, NULL); + + stmt = parsetree_nth_stmt(res, i++); + update_GrantStmt(stmt, get_database_name(MyDatabaseId), NULL, db_accessadmin, NULL); + if (guest) { stmt = parsetree_nth_stmt(res, i++); @@ -186,14 +197,17 @@ add_fixed_user_roles_to_bbf_authid_user_ext(const char *dbname) { const char *dbo; const char *db_owner; + const char *db_accessadmin; const char *guest; dbo = get_dbo_role_name(dbname); db_owner = get_db_owner_name(dbname); + db_accessadmin = get_db_accessadmin_role_name(dbname); guest = get_guest_role_name(dbname); add_to_bbf_authid_user_ext(dbo, "dbo", dbname, "dbo", NULL, false, true, false); add_to_bbf_authid_user_ext(db_owner, "db_owner", dbname, NULL, NULL, true, true, false); + add_to_bbf_authid_user_ext(db_accessadmin, DB_ACCESSADMIN, dbname, NULL, NULL, true, true, false); /* * For master, tempdb and msdb databases, the guest user will be @@ -215,15 +229,17 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) List *stmt_list; ListCell *elem; Node *stmt; - int expected_stmts = 6; + int expected_stmts = 8; int i = 0; const char *dbo; const char *db_owner; + const char *db_accessadmin; const char *schema; const char *guest_schema; dbo = get_dbo_role_name(dbname); db_owner = get_db_owner_name(dbname); + db_accessadmin = get_db_accessadmin_role_name(dbname); schema = get_dbo_schema_name(dbname); guest_schema = get_guest_schema_name(dbname); @@ -235,13 +251,17 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0) + if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && + strcmp(user_name, db_accessadmin) != 0) { appendStringInfo(&query, "DROP OWNED BY dummy CASCADE; "); appendStringInfo(&query, "DROP ROLE dummy; "); expected_stmts += 2; } } + /* Drop db_accessadmin*/ + appendStringInfo(&query, "REVOKE CREATE ON DATABASE dummy FROM dummy; "); + appendStringInfo(&query, "DROP ROLE dummy; "); /* Then drop db_owner and dbo in that order */ appendStringInfo(&query, "DROP OWNED BY dummy, dummy CASCADE; "); appendStringInfo(&query, "REVOKE CREATE, CONNECT, TEMPORARY ON DATABASE dummy FROM dummy; "); @@ -266,7 +286,8 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0) + if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && + strcmp(user_name, db_accessadmin) != 0) { stmt = parsetree_nth_stmt(stmt_list, i++); update_DropOwnedStmt(stmt, list_make1(user_name)); @@ -276,6 +297,11 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) } } + stmt = parsetree_nth_stmt(stmt_list, i++); + update_GrantStmt(stmt, get_database_name(MyDatabaseId), NULL, db_accessadmin, NULL); + stmt = parsetree_nth_stmt(stmt_list, i++); + update_DropRoleStmt(stmt, db_accessadmin); + stmt = parsetree_nth_stmt(stmt_list, i++); update_DropOwnedStmt(stmt, list_make2(pstrdup(db_owner), pstrdup(dbo))); @@ -579,6 +605,12 @@ create_bbf_db_internal(ParseState *pstate, const char *dbname, List *options, co save_sec_context | SECURITY_LOCAL_USERID_CHANGE); is_set_userid = true; } + else if (stmt->type == T_GrantStmt) + { + SetUserIdAndSecContext(datdba, + save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + is_set_userid = true; + } /* need to make a wrapper PlannedStmt */ wrapper = makeNode(PlannedStmt); wrapper->commandType = CMD_UTILITY; @@ -1206,3 +1238,134 @@ create_guest_schema_for_all_dbs(PG_FUNCTION_ARGS) PG_RETURN_INT32(0); } + + +/* +* This function is only being used during upgrade to v4.4.0 +* to create database roles db_accessadmin for each database +*/ +PG_FUNCTION_INFO_V1(create_database_roles_for_all_dbs); +Datum +create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) +{ + Relation sysdatabase_rel; + TableScanDesc scan; + HeapTuple tuple; + Form_sysdatabases bbf_db; + char *dbname; + int saved_nest_level = 0; + + /* We only allow this to be called from an extension's SQL script. */ + if (!creating_extension) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("%s can only be called from an SQL script executed by CREATE/ALTER EXTENSION", + "create_database_roles_for_all_dbs()"))); + + saved_nest_level = pltsql_new_guc_nest_level(); + set_config_option("babelfishpg_tsql.sql_dialect", "tsql", + GUC_CONTEXT_CONFIG, + PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); + set_config_option("babelfishpg_tsql.migration_mode", physical_schema_name_exists("dbo") ? "single-db" : "multi-db", + GUC_CONTEXT_CONFIG, + PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); + + sysdatabase_rel = table_open(sysdatabases_oid, RowExclusiveLock); + scan = table_beginscan_catalog(sysdatabase_rel, 0, NULL); + + while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + { + StringInfoData query; + List *parsetree_list; + Node *stmt; + const char *db_owner; + const char *db_accessadmin; + const char *old_createrole_self_grant = GetConfigOption("createrole_self_grant", false, true); + int i = 0; + int save_sec_context = 0; + Oid save_userid = InvalidOid; + + bbf_db = (Form_sysdatabases) GETSTRUCT(tuple); + dbname = text_to_cstring(&(bbf_db->name)); + db_owner = get_db_owner_name(dbname); + db_accessadmin = get_db_accessadmin_role_name(dbname); + + initStringInfo(&query); + + appendStringInfo(&query, "CREATE ROLE dummy ROLE dummy; "); + appendStringInfo(&query, "GRANT CREATE ON DATABASE dummy TO dummy; "); + + parsetree_list = raw_parser(query.data, RAW_PARSE_DEFAULT); + + stmt = parsetree_nth_stmt(parsetree_list, i++); + update_CreateRoleStmt(stmt, db_accessadmin, db_owner, NULL); + + stmt = parsetree_nth_stmt(parsetree_list, i++); + update_GrantStmt(stmt, get_database_name(MyDatabaseId), NULL, db_accessadmin, NULL); + + GetUserIdAndSecContext(&save_userid, &save_sec_context); + + PG_TRY(); + { + ListCell *parsetree_item; + /* + * We have performed all the permissions checks. + * Set current user to bbf_role_admin for create permissions. + * Set createrole_self_grant to "inherit" so that bbf_role_admin + * inherits the new role. + */ + SetConfigOption("createrole_self_grant", "inherit", PGC_USERSET, PGC_S_OVERRIDE); + add_to_bbf_authid_user_ext(db_accessadmin, DB_ACCESSADMIN, dbname, NULL, NULL, true, true, false); + /* Run all subcommands */ + foreach(parsetree_item, parsetree_list) + { + PlannedStmt *wrapper; + + if (stmt->type == T_GrantStmt) + { + SetUserIdAndSecContext(get_role_oid("sysadmin", false), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + } + else + { + SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + } + + /* need to make a wrapper PlannedStmt */ + wrapper = makeNode(PlannedStmt); + wrapper->commandType = CMD_UTILITY; + wrapper->canSetTag = false; + wrapper->utilityStmt = ((RawStmt *) lfirst(parsetree_item))->stmt; + wrapper->stmt_location = 0; + + /* do this step */ + ProcessUtility(wrapper, + "(CREATE LOGICAL DATABASE )", + false, + PROCESS_UTILITY_SUBCOMMAND, + NULL, + NULL, + None_Receiver, + NULL); + + CommandCounterIncrement(); + } + } + PG_FINALLY(); + { + /* Clean up. Restore previous state. */ + SetConfigOption("createrole_self_grant", old_createrole_self_grant, PGC_USERSET, PGC_S_OVERRIDE); + SetUserIdAndSecContext(save_userid, save_sec_context); + } + PG_END_TRY(); + + pfree(query.data); + pfree(dbname); + + } + pltsql_revert_guc(saved_nest_level); + table_endscan(scan); + table_close(sysdatabase_rel, RowExclusiveLock); + + PG_RETURN_INT32(0); +} + diff --git a/contrib/babelfishpg_tsql/src/multidb.c b/contrib/babelfishpg_tsql/src/multidb.c index 033f2627f4..0e99e73dc1 100644 --- a/contrib/babelfishpg_tsql/src/multidb.c +++ b/contrib/babelfishpg_tsql/src/multidb.c @@ -264,7 +264,8 @@ rewrite_object_refs(Node *stmt) /* Forbidden the use of some special principals */ if (strcmp(principal_name, "dbo") == 0 || - strcmp(principal_name, "db_owner") == 0) + strcmp(principal_name, "db_owner") == 0 || + strcmp(principal_name, DB_ACCESSADMIN) == 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot use the special principal '%s'", principal_name))); @@ -389,7 +390,8 @@ rewrite_object_refs(Node *stmt) /* TODO: allow ALTER ROLE db_owner */ if (strcmp(user_name, "dbo") == 0 || strcmp(user_name, "db_owner") == 0 || - strcmp(user_name, "guest") == 0) + strcmp(user_name, "guest") == 0 || + strcmp(user_name, DB_ACCESSADMIN) == 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot alter the user %s", user_name))); @@ -1310,7 +1312,8 @@ get_physical_user_name(char *db_name, char *user_name, bool suppress_error) (strlen(db_name) != 4 || (strncmp(db_name, "msdb", 4) != 0))) { if ((strlen(user_name) == 3 && strncmp(user_name, "dbo", 3) == 0) || - (strlen(user_name) == 8 && strncmp(user_name, "db_owner", 8) == 0)) + (strlen(user_name) == 8 && strncmp(user_name, "db_owner", 8) == 0) || + (strlen(user_name) == 14 && strncmp(user_name, DB_ACCESSADMIN, 14) == 0)) { return new_user_name; } @@ -1414,6 +1417,21 @@ get_guest_role_name(const char *dbname) } } +const char * +get_db_accessadmin_role_name(const char *dbname) +{ + char *name = palloc0(MAX_BBF_NAMEDATALEND); + + if (get_migration_mode() == SINGLE_DB && strcmp(dbname, "master") != 0 + && strcmp(dbname, "tempdb") != 0 && strcmp(dbname, "msdb") != 0) + snprintf(name, MAX_BBF_NAMEDATALEND, "%s", DB_ACCESSADMIN); + else + snprintf(name, MAX_BBF_NAMEDATALEND, "%s_%s", dbname, DB_ACCESSADMIN); + + truncate_identifier(name, strlen(name), false); + return name; +} + const char * get_guest_schema_name(const char *dbname) { @@ -1447,7 +1465,7 @@ is_builtin_database(const char *dbname) bool physical_schema_name_exists(char *phys_schema_name) { - return SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(phys_schema_name)); + return SearchSysCacheExists1(SYSNAMESPACENAME, CStringGetDatum(phys_schema_name)); } /* diff --git a/contrib/babelfishpg_tsql/src/multidb.h b/contrib/babelfishpg_tsql/src/multidb.h index 8312f9ade6..1f6d31149a 100644 --- a/contrib/babelfishpg_tsql/src/multidb.h +++ b/contrib/babelfishpg_tsql/src/multidb.h @@ -24,6 +24,7 @@ extern const char *get_dbo_schema_name(const char *dbname); extern const char *get_dbo_role_name(const char *dbname); extern const char *get_db_owner_name(const char *dbname); extern const char *get_guest_role_name(const char *dbname); +extern const char *get_db_accessadmin_role_name(const char *dbname); extern const char *get_guest_schema_name(const char *dbname); extern bool is_shared_schema(const char *name); extern void truncate_tsql_identifier(char *ident); diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index 32ff3a3139..d06b89eff0 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -3761,7 +3761,7 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) role_oid = get_role_oid(rolname, true); /* Special database roles should throw an error. */ - if (strcmp(grantee_name, "db_owner") == 0) + if (strcmp(grantee_name, "db_owner") == 0 || strcmp(grantee_name, DB_ACCESSADMIN) == 0) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Cannot grant, deny or revoke permissions to or from special roles."))); diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index cd294408cc..7f74b6bd1b 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -34,6 +34,7 @@ #include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/extension.h" +#include "commands/schemacmds.h" #include "commands/sequence.h" #include "commands/tablecmds.h" #include "commands/trigger.h" @@ -2924,13 +2925,25 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } else if (isuser || isrole) { - const char *db_owner_name; + const char *current_db_name = get_cur_db_name(); + const char *db_owner_name = get_db_owner_name(current_db_name); + const char *db_accessadmin_role = get_db_accessadmin_role_name(current_db_name); - db_owner_name = get_db_owner_name(get_cur_db_name()); - if (!has_privs_of_role(GetUserId(),get_role_oid(db_owner_name, false))) + if (has_privs_of_role(GetUserId(), get_role_oid(db_owner_name, false)) || + (isuser && has_privs_of_role(GetUserId(), get_role_oid(db_accessadmin_role, false)))) + { + /* + * members of db_owner can create roles and users + * members of db_accessadmin can only create users + */ + } + else + { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("User does not have permission to perform this action."))); + } + } /* @@ -3202,16 +3215,25 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } else if (isuser || isrole) { - const char *dbo_name; - char *db_name; - char *user_name; - char *cur_user; - Oid prev_current_user; + char *db_name = get_cur_db_name(); + bool is_member_of_db_owner = false; + bool is_member_of_db_accessadmin = false; + int save_sec_context; + Oid save_userid; + Oid db_owner = get_role_oid(get_db_owner_name(db_name), false); + Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(db_name), false); + Oid user_name = get_role_oid(stmt->role->rolename, false); + + /* db principal being altered should be a user or role in the current active logical database */ + if (!((isuser && is_user(user_name, true)) || (isrole && is_role(user_name, true)))) + ereport(ERROR, + (errcode(ERRCODE_CHECK_VIOLATION), + errmsg("Cannot alter the %s '%s', because it does not exist or you do not have permission.", isuser ? "user" : "role", stmt->role->rolename))); - db_name = get_cur_db_name(); - dbo_name = get_dbo_role_name(db_name); - user_name = stmt->role->rolename; - cur_user = GetUserNameFromId(GetUserId(), false); + is_member_of_db_owner = has_privs_of_role(GetUserId(), db_owner); + /* check membership in db_accessadmin if alter user and not already a member of db_owner */ + if (!is_member_of_db_owner && !isuser) + is_member_of_db_accessadmin = has_privs_of_role(GetUserId(), db_accessadmin); /* * Check if the current user has privileges. @@ -3222,19 +3244,37 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (strcmp(defel->defname, "default_schema") == 0) { - if (strcmp(cur_user, dbo_name) != 0 && - strcmp(cur_user, user_name) != 0) + if (is_member_of_db_owner || (isuser && is_member_of_db_accessadmin) || + user_name == GetUserId()) + { + /* + * members of db_owner can alter default schema for any role or user + * members of db_accessadmin can alter default schema for any user + */ + } + else + { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Current user does not have privileges to change schema"))); + } } else if (strcmp(defel->defname, "rename") == 0) { - if (strcmp(cur_user, dbo_name) != 0 && - strcmp(cur_user, user_name) != 0) + if (is_member_of_db_owner || (isuser && is_member_of_db_accessadmin && + !has_privs_of_role(user_name, db_owner))) + { + /* + * members of db_owner can rename any role or user + * members of db_accessadmin can rename users who are not members of db_owner + */ + } + else + { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Current user does not have privileges to change user name"))); + } } } @@ -3244,11 +3284,18 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (strcmp(defel->defname, "rolemembers") == 0) { - if (strcmp(cur_user, dbo_name) != 0 && - strcmp(cur_user, user_name) != 0) + if (is_member_of_db_owner) + { + /* + * Only members of db_owner can alter login for a user + */ + } + else + { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Current user does not have privileges to change login"))); + } } } @@ -3256,11 +3303,11 @@ bbf_ProcessUtility(PlannedStmt *pstmt, * We have performed all the permissions checks. * Set current user to bbf_role_admin for alter permissions. */ - prev_current_user = GetUserId(); - SetCurrentRoleId(get_bbf_role_admin_oid(), true); - PG_TRY(); { + GetUserIdAndSecContext(&save_userid, &save_sec_context); + SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + if (prev_ProcessUtility) prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, @@ -3276,12 +3323,11 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } PG_FINALLY(); { - SetCurrentRoleId(prev_current_user, true); + SetUserIdAndSecContext(save_userid, save_sec_context); } PG_END_TRY(); set_session_properties(db_name); - pfree(cur_user); pfree(db_name); return; @@ -3329,42 +3375,48 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (db_name != NULL && strcmp(db_name, "") != 0) { + Oid db_owner = get_role_oid(get_db_owner_name(db_name), false); + Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(db_name), false); + foreach(item, stmt->roles) { RoleSpec *rolspec = lfirst(item); - char *user_name; + char *user_name = get_physical_user_name(db_name, rolspec->rolename, false); const char *db_principal_type = drop_user ? "user" : "role"; - const char *db_owner_name; - int role_oid; - int rolename_len; - bool is_tsql_db_principal = false; - bool is_psql_db_principal = false; - Oid dbowner; - - user_name = get_physical_user_name(db_name, rolspec->rolename, false); - db_owner_name = get_db_owner_name(db_name); - dbowner = get_role_oid(db_owner_name, false); - role_oid = get_role_oid(user_name, true); - rolename_len = strlen(rolspec->rolename); - is_tsql_db_principal = OidIsValid(role_oid) && - ((drop_user && is_user(role_oid)) || - (drop_role && is_role(role_oid))); - is_psql_db_principal = OidIsValid(role_oid) && !is_tsql_db_principal; + int role_oid = get_role_oid(user_name, true); + int rolename_len = strlen(rolspec->rolename); + + if (!OidIsValid(role_oid) || /* Not found */ + (drop_user && !is_user(role_oid, true)) || /* Found but not a user in current logical db */ + (drop_role && !is_role(role_oid, true))) /* Found but not a role in current logical db */ + { + if (stmt->missing_ok) + { + stmt->roles = foreach_delete_current(stmt->roles, item); + continue; + } + else + ereport(ERROR, + (errcode(ERRCODE_CHECK_VIOLATION), + errmsg("Cannot drop the %s '%s', because it does not exist or you do not have permission.", db_principal_type, rolspec->rolename))); + } /* If user is dbo or role is db_owner, restrict dropping */ if ((drop_user && rolename_len == 3 && strncmp(rolspec->rolename, "dbo", 3) == 0) || - (drop_role && rolename_len == 8 && strncmp(rolspec->rolename, "db_owner", 8) == 0)) + (drop_role && rolename_len == 8 && strncmp(rolspec->rolename, "db_owner", 8) == 0) || + (drop_role && rolename_len == 14 && strncmp(rolspec->rolename, DB_ACCESSADMIN, 14) == 0)) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("Cannot drop the %s '%s'.", db_principal_type, rolspec->rolename))); - /* - * Check for current_user's privileges - * must be database owner to drop user/role - */ - if ((!stmt->missing_ok && !is_tsql_db_principal) || - !is_member_of_role(GetUserId(), dbowner) || - (is_tsql_db_principal && !is_member_of_role(dbowner, role_oid)) || is_psql_db_principal) + if (has_privs_of_role(GetUserId(), db_owner) || (drop_user && has_privs_of_role(GetUserId(), db_accessadmin))) + { + /* + * db_owner can drop any user or role in database + * db_accessadmin can drop users in a database + */ + } + else ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Cannot drop the %s '%s', because it does not exist or you do not have permission.", db_principal_type, rolspec->rolename))); @@ -3469,9 +3521,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (is_login(roleform->oid)) all_logins = true; - else if (is_user(roleform->oid)) + else if (is_user(roleform->oid, false)) all_users = true; - else if (is_role(roleform->oid)) + else if (is_role(roleform->oid, false)) all_roles = true; else other = true; @@ -3516,11 +3568,11 @@ bbf_ProcessUtility(PlannedStmt *pstmt, * We have performed all the permissions checks. * Set current user to bbf_role_admin for drop permissions. */ - GetUserIdAndSecContext(&save_userid, &save_sec_context); - SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); - PG_TRY(); { + GetUserIdAndSecContext(&save_userid, &save_sec_context); + SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + if (prev_ProcessUtility) prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, @@ -3551,6 +3603,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, GrantStmt *stmt; PlannedStmt *wrapper; RoleSpec *rolspec = create_schema->authrole; + Oid owner_oid = InvalidOid; + Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(get_cur_db_name()), true); + bool alter_owner = false; if (strcmp(queryString, "(CREATE LOGICAL DATABASE )") == 0 && context == PROCESS_UTILITY_SUBCOMMAND) @@ -3560,6 +3615,22 @@ bbf_ProcessUtility(PlannedStmt *pstmt, else orig_schema = "dbo"; } + else + { + owner_oid = rolspec ? get_rolespec_oid(rolspec, true) : InvalidOid; + if (OidIsValid(owner_oid) && OidIsValid(db_accessadmin) && !member_can_set_role(GetUserId(), owner_oid) && + has_privs_of_role(GetUserId(), db_accessadmin) && + (is_user(owner_oid, true) || is_role(owner_oid, true))) + { + /* + * db_accessadmin members can create schema for other users as owner + * but it does not actually have the required permission from PG + * perspective to do so, hence handle it this way. + */ + create_schema->authrole = NULL; + alter_owner = true; + } + } if (prev_ProcessUtility) prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, @@ -3599,6 +3670,12 @@ bbf_ProcessUtility(PlannedStmt *pstmt, NULL); CommandCounterIncrement(); + + if (alter_owner) + { + AlterSchemaOwner_oid(get_namespace_oid(create_schema->schemaname, false), owner_oid); + } + /* Grant ALL schema privileges to the user.*/ if (rolspec && strcmp(queryString, "(CREATE LOGICAL DATABASE )") != 0) { diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index 27f21c6790..95cd0b72de 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -2283,7 +2283,7 @@ sp_droprole(PG_FUNCTION_ARGS) role_oid = get_role_oid(physical_role_name, true); /* Check if the role does not exists */ - if (role_oid == InvalidOid || !is_role(role_oid)) + if (role_oid == InvalidOid || !is_role(role_oid, false)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot drop the role '%s', because it does not exist or you do not have permission.", rolname))); @@ -2436,7 +2436,7 @@ sp_addrolemember(PG_FUNCTION_ARGS) * Check if the user, group or role does not exists and given member * name is an role or user */ - if (member_oid == InvalidOid || (!is_role(member_oid) && !is_user(member_oid))) + if (member_oid == InvalidOid || (!is_role(member_oid, false) && !is_user(member_oid, false))) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("User or role '%s' does not exist in this database.", membername))); @@ -2446,7 +2446,7 @@ sp_addrolemember(PG_FUNCTION_ARGS) role_oid = get_role_oid(physical_role_name, true); /* Check if the role does not exists and given role name is an role */ - if (role_oid == InvalidOid || !is_role(role_oid)) + if (role_oid == InvalidOid || !is_role(role_oid, false)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", rolname))); @@ -2598,7 +2598,7 @@ sp_droprolemember(PG_FUNCTION_ARGS) role_oid = get_role_oid(physical_name, true); /* Throw an error id the given role name doesn't exist or isn't a role */ - if (role_oid == InvalidOid || !is_role(role_oid)) + if (role_oid == InvalidOid || !is_role(role_oid, false)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", rolname))); @@ -2611,7 +2611,7 @@ sp_droprolemember(PG_FUNCTION_ARGS) * Throw an error id the given member name doesn't exist or isn't a * role or user */ - if (role_oid == InvalidOid || (!is_role(role_oid) && !is_user(role_oid))) + if (role_oid == InvalidOid || (!is_role(role_oid, false) && !is_user(role_oid, false))) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot drop the principal '%s', because it does not exist or you do not have permission.", membername))); diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 9cfbd25e4d..9df544ee51 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -290,7 +290,7 @@ drop_bbf_roles(ObjectAccessType access, { if (is_login(roleid)) drop_bbf_authid_login_ext(access, classId, roleid, subId, arg); - else if (is_user(roleid) || is_role(roleid)) + else if (is_user(roleid, false) || is_role(roleid, false)) drop_bbf_authid_user_ext(access, classId, roleid, subId, arg); } @@ -1755,7 +1755,7 @@ is_alter_role_stmt(GrantRoleStmt *stmt) Oid granted = get_role_oid(spec->rolename, true); /* Check if the granted role is an existing database role */ - if (granted == InvalidOid || !is_role(granted)) + if (granted == InvalidOid || !is_role(granted, false)) return false; } @@ -1778,7 +1778,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) grantee = get_role_oid(grantee_name, false); /* Disallow ALTER ROLE if the grantee is not a db principal */ - if (!is_user(grantee) && !is_role(grantee)) + if (!is_user(grantee, false) && !is_role(grantee, false)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("%s is not a database user or a user-defined database role", @@ -1940,7 +1940,7 @@ is_rolemember(PG_FUNCTION_ARGS) * principal. Note that if given principal is current user, we'll always * have permissions. */ - if (!is_role(role_oid) || + if (!is_role(role_oid, false) || ((principal_oid != cur_user_oid) && (!has_privs_of_role(cur_user_oid, role_oid) || !has_privs_of_role(cur_user_oid, principal_oid)))) diff --git a/test/JDBC/expected/BABEL-2403.out b/test/JDBC/expected/BABEL-2403.out index c879c5bf23..2608f117b0 100644 --- a/test/JDBC/expected/BABEL-2403.out +++ b/test/JDBC/expected/BABEL-2403.out @@ -99,6 +99,12 @@ name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext m text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} name#!#pg_catalog#!#proname#!#{"Rule": " in babelfish_function_ext must also exist in pg_proc"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} @@ -188,6 +194,12 @@ name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext m text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} name#!#pg_catalog#!#proname#!#{"Rule": " in babelfish_function_ext must also exist in pg_proc"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} diff --git a/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out b/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out index 5437c600c8..96ae98cc9c 100644 --- a/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out +++ b/test/JDBC/expected/BABEL-LOGIN-USER-EXT.out @@ -130,14 +130,18 @@ master_r1#!#r1#!#r1#!#master#!#sch2 ALTER USER r1 WITH NAME = new_r1; go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current user does not have privileges to change user name)~~ + SELECT rolname, orig_username, login_name, database_name, default_schema_name FROM sys.babelfish_authid_user_ext -WHERE orig_username = 'new_r1'; +WHERE orig_username = 'new_r1' or orig_username = 'r1'; go ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar -master_new_r1#!#new_r1#!#r1#!#master#!#sch2 +master_r1#!#r1#!#r1#!#master#!#sch2 ~~END~~ @@ -217,7 +221,7 @@ r2 -- tsql -DROP USER new_r1; +DROP USER r1; go -- psql @@ -690,15 +694,19 @@ ORDER BY rolname; GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar +db1_db_accessadmin#!#db_accessadmin#!##!#db1#!# db1_db_owner#!#db_owner#!##!#db1#!# db1_dbo#!#dbo#!##!#db1#!#dbo db1_guest#!#guest#!##!#db1#!#guest +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -863,12 +871,15 @@ ORDER BY rolname; GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -914,18 +925,23 @@ ORDER BY rolname; GO ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar#!#nvarchar +db1_db_accessadmin#!##!#db_accessadmin#!#db1#!# db1_db_owner#!##!#db_owner#!#db1#!# db1_dbo#!##!#dbo#!#db1#!#dbo db1_guest#!##!#guest#!#db1#!#guest +db2_db_accessadmin#!##!#db_accessadmin#!#db2#!# db2_db_owner#!##!#db_owner#!#db2#!# db2_dbo#!##!#dbo#!#db2#!#dbo db2_guest#!##!#guest#!#db2#!#guest +master_db_accessadmin#!##!#db_accessadmin#!#master#!# master_db_owner#!##!#db_owner#!#master#!# master_dbo#!##!#dbo#!#master#!#dbo master_guest#!##!#guest#!#master#!#guest +msdb_db_accessadmin#!##!#db_accessadmin#!#msdb#!# msdb_db_owner#!##!#db_owner#!#msdb#!# msdb_dbo#!##!#dbo#!#msdb#!#dbo msdb_guest#!##!#guest#!#msdb#!#guest +tempdb_db_accessadmin#!##!#db_accessadmin#!#tempdb#!# tempdb_db_owner#!##!#db_owner#!#tempdb#!# tempdb_dbo#!##!#dbo#!#tempdb#!#dbo tempdb_guest#!##!#guest#!#tempdb#!#guest @@ -940,6 +956,7 @@ GO varchar#!#varchar guest#!#guest dbo#!#dbo +db_accessadmin#!# db_owner#!# INFORMATION_SCHEMA#!# public#!# @@ -972,6 +989,7 @@ GO varchar#!#varchar guest#!#guest dbo#!#dbo +db_accessadmin#!# db_owner#!# INFORMATION_SCHEMA#!# public#!# @@ -1106,15 +1124,19 @@ ORDER BY rolname; GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar +db2_db_accessadmin#!#db_accessadmin#!##!#db2#!# db2_db_owner#!#db_owner#!##!#db2#!# db2_dbo#!#dbo#!##!#db2#!#dbo db2_guest#!#guest#!##!#db2#!#guest +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -1130,12 +1152,15 @@ ORDER BY rolname; GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -1408,6 +1433,7 @@ GO varchar babel_4935_no_sysadmin1 babel_4935_no_sysadmin2 +db_accessadmin db_owner dbo guest @@ -1425,6 +1451,7 @@ GO varchar babel_4935_no_sysadmin1 babel_4935_no_sysadmin2 +db_accessadmin db_owner dbo guest @@ -1441,6 +1468,7 @@ GO ~~START~~ varchar babel_4935_no_sysadmin1 +db_accessadmin db_owner dbo guest @@ -1456,6 +1484,7 @@ SELECT name FROM sys.database_principals ORDER BY name GO ~~START~~ varchar +db_accessadmin db_owner dbo guest diff --git a/test/JDBC/expected/BABEL-LOGIN-vu-verify.out b/test/JDBC/expected/BABEL-LOGIN-vu-verify.out index 22aa32d6ee..604d3702db 100644 --- a/test/JDBC/expected/BABEL-LOGIN-vu-verify.out +++ b/test/JDBC/expected/BABEL-LOGIN-vu-verify.out @@ -68,6 +68,10 @@ go ALTER USER babel_login_vu_prepare_r1 WITH NAME = babel_login_vu_prepare_r1_new; go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current user does not have privileges to change user name)~~ + ALTER USER babel_login_vu_prepare_r2 WITH DEFAULT_SCHEMA = NULL; go @@ -90,7 +94,7 @@ ORDER BY rolname; go ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar -master_babel_login_vu_prepare_r1_new#!#babel_login_vu_prepare_r1_new#!#babel_login_vu_prepare_r1#!#master#!#babel_login_vu_prepare_sch +master_babel_login_vu_prepare_r1#!#babel_login_vu_prepare_r1#!#babel_login_vu_prepare_r1#!#master#!#babel_login_vu_prepare_sch master_babel_login_vu_prepare_r2#!#babel_login_vu_prepare_r2#!#babel_login_vu_prepare_r2#!#master#!#babel_login_vu_prepare_sch ~~END~~ @@ -124,7 +128,7 @@ ORDER BY rolname; go ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar -master_babel_login_vu_prepare_r1_new#!#babel_login_vu_prepare_r1_new#!#babel_login_vu_prepare_r1#!#master#!#babel_login_vu_prepare_sch +master_babel_login_vu_prepare_r1#!#babel_login_vu_prepare_r1#!#babel_login_vu_prepare_r1#!#master#!#babel_login_vu_prepare_sch master_babel_login_vu_prepare_r2#!#babel_login_vu_prepare_r2#!#babel_login_vu_prepare_r2#!#master#!#babel_login_vu_prepare_sch ~~END~~ @@ -312,7 +316,7 @@ go DROP USER babel_login_vu_prepare_err_user; go -DROP USER babel_login_vu_prepare_r1_new +DROP USER babel_login_vu_prepare_r1 go DROP USER babel_login_vu_prepare_r2 diff --git a/test/JDBC/expected/BABEL-USER.out b/test/JDBC/expected/BABEL-USER.out index 819bf7c696..6a9646102c 100644 --- a/test/JDBC/expected/BABEL-USER.out +++ b/test/JDBC/expected/BABEL-USER.out @@ -49,15 +49,19 @@ ORDER BY rolname; GO ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar#!#nvarchar +db1_db_accessadmin#!##!#db_accessadmin#!#db1#!# db1_db_owner#!##!#db_owner#!#db1#!# db1_dbo#!##!#dbo#!#db1#!#dbo db1_guest#!##!#guest#!#db1#!#guest +master_db_accessadmin#!##!#db_accessadmin#!#master#!# master_db_owner#!##!#db_owner#!#master#!# master_dbo#!##!#dbo#!#master#!#dbo master_guest#!##!#guest#!#master#!#guest +msdb_db_accessadmin#!##!#db_accessadmin#!#msdb#!# msdb_db_owner#!##!#db_owner#!#msdb#!# msdb_dbo#!##!#dbo#!#msdb#!#dbo msdb_guest#!##!#guest#!#msdb#!#guest +tempdb_db_accessadmin#!##!#db_accessadmin#!#tempdb#!# tempdb_db_owner#!##!#db_owner#!#tempdb#!# tempdb_dbo#!##!#dbo#!#tempdb#!#dbo tempdb_guest#!##!#guest#!#tempdb#!#guest @@ -72,6 +76,7 @@ GO varchar#!#varchar guest#!#guest dbo#!#dbo +db_accessadmin#!# db_owner#!# INFORMATION_SCHEMA#!# public#!# diff --git a/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out b/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out index 825df76dc1..9b79a1c785 100644 --- a/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out +++ b/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out @@ -48,6 +48,8 @@ GO INSERT INTO test_sp_helpdbfixedrole_tbl (DbFixedRole, Description) EXEC sp_helpdbfixedrole 'db_accessadmin' GO +~~ROW COUNT: 1~~ + INSERT INTO test_sp_helpdbfixedrole_tbl (DbFixedRole, Description) EXEC sp_helpdbfixedrole 'DB_securityadmin' GO INSERT INTO test_sp_helpdbfixedrole_tbl (DbFixedRole, Description) EXEC sp_helpdbfixedrole 'db_ddladmin ' @@ -67,6 +69,7 @@ SELECT DbFixedRole, Description FROM test_sp_helpdbfixedrole_tbl GO ~~START~~ varchar#!#nvarchar +db_accessadmin#!#DB Access Administrators ~~END~~ diff --git a/test/JDBC/expected/Test_alter_db_rename-vu-verify.out b/test/JDBC/expected/Test_alter_db_rename-vu-verify.out index daf6199cbc..02c5571170 100644 --- a/test/JDBC/expected/Test_alter_db_rename-vu-verify.out +++ b/test/JDBC/expected/Test_alter_db_rename-vu-verify.out @@ -19,6 +19,7 @@ rename_db_database1_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database1_db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 rename_db_database1_db_owner#!##!#db_owner#!#rename_db_database1 rename_db_database1_dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -80,6 +81,7 @@ rename_db_database2_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database2_db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 rename_db_database2_db_owner#!##!#db_owner#!#rename_db_database2 rename_db_database2_dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 @@ -190,6 +192,7 @@ thisnewdatabasenameiscasesensitc4313f9adf0e47cfa5aca25228e02f29#!#dbo varchar#!#varchar#!#nvarchar#!#nvarchar thisnewdatabasenameiscasesensit4e1f355d810759b9f1a59b04496ed2e1#!##!#guest#!#thisnewdatabasenameiscasesensit44f3247005ec268e1a10c736599cfb7e thisnewdatabasenameiscasesensit72e4dcc7ed25f5536033cf547cd7f001#!##!#db_owner#!#thisnewdatabasenameiscasesensit44f3247005ec268e1a10c736599cfb7e +thisnewdatabasenameiscasesensit944678472843354d6b3a4354630249a8#!##!#db_accessadmin#!#thisnewdatabasenameiscasesensit44f3247005ec268e1a10c736599cfb7e thisnewdatabasenameiscasesensitc4313f9adf0e47cfa5aca25228e02f29#!##!#dbo#!#thisnewdatabasenameiscasesensit44f3247005ec268e1a10c736599cfb7e ~~END~~ diff --git a/test/JDBC/expected/Test_rename_db_single-db.out b/test/JDBC/expected/Test_rename_db_single-db.out index 6c4d9dc470..f1e8d609f7 100644 --- a/test/JDBC/expected/Test_rename_db_single-db.out +++ b/test/JDBC/expected/Test_rename_db_single-db.out @@ -32,6 +32,7 @@ rename_db_database1_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database1_db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 rename_db_database1_db_owner#!##!#db_owner#!#rename_db_database1 rename_db_database1_dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -80,6 +81,7 @@ rename_db_database2_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database2_db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 rename_db_database2_db_owner#!##!#db_owner#!#rename_db_database2 rename_db_database2_dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 @@ -128,6 +130,7 @@ rename_db_database1_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database1_db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 rename_db_database1_db_owner#!##!#db_owner#!#rename_db_database1 rename_db_database1_dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -176,6 +179,7 @@ rename_db_database2_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database2_db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 rename_db_database2_db_owner#!##!#db_owner#!#rename_db_database2 rename_db_database2_dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 @@ -236,6 +240,7 @@ rename_db_database1_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database1_db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 rename_db_database1_db_owner#!##!#db_owner#!#rename_db_database1 rename_db_database1_dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -284,6 +289,7 @@ rename_db_database2_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database2_db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 rename_db_database2_db_owner#!##!#db_owner#!#rename_db_database2 rename_db_database2_dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 @@ -332,6 +338,7 @@ rename_db_database1_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database1_db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 rename_db_database1_db_owner#!##!#db_owner#!#rename_db_database1 rename_db_database1_dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -380,6 +387,7 @@ rename_db_database2_rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +rename_db_database2_db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 rename_db_database2_db_owner#!##!#db_owner#!#rename_db_database2 rename_db_database2_dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 diff --git a/test/JDBC/expected/Test_sp_rename_database-vu-verify.out b/test/JDBC/expected/Test_sp_rename_database-vu-verify.out index a59f3818fa..b2cbeb5ef1 100644 --- a/test/JDBC/expected/Test_sp_rename_database-vu-verify.out +++ b/test/JDBC/expected/Test_sp_rename_database-vu-verify.out @@ -19,6 +19,7 @@ sp_rename_database1_sp_rename_schema1#!#sp_rename_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +sp_rename_database1_db_accessadmin#!##!#db_accessadmin#!#sp_rename_database1 sp_rename_database1_db_owner#!##!#db_owner#!#sp_rename_database1 sp_rename_database1_dbo#!##!#dbo#!#sp_rename_database1 sp_rename_database1_guest#!##!#guest#!#sp_rename_database1 @@ -80,6 +81,7 @@ sp_rename_database2_sp_rename_schema1#!#sp_rename_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +sp_rename_database2_db_accessadmin#!##!#db_accessadmin#!#sp_rename_database2 sp_rename_database2_db_owner#!##!#db_owner#!#sp_rename_database2 sp_rename_database2_dbo#!##!#dbo#!#sp_rename_database2 sp_rename_database2_guest#!##!#guest#!#sp_rename_database2 @@ -197,6 +199,7 @@ sp_rename_thisnewdatabasenameisfacf8af797f428fdc401ffddc672894d#!#dbo varchar#!#varchar#!#nvarchar#!#nvarchar sp_rename_thisnewdatabasenameis1e39ca7c78a1fba2342467331fb5bd56#!##!#db_owner#!#sp_rename_thisnewdatabasenameisb8bd7c94f797959aa629fc2f9e821637 sp_rename_thisnewdatabasenameis21f79a8b66248a73068dca6edd5b0ca3#!##!#guest#!#sp_rename_thisnewdatabasenameisb8bd7c94f797959aa629fc2f9e821637 +sp_rename_thisnewdatabasenameisa0a5aa90abf2314f4773860fda5e43a2#!##!#db_accessadmin#!#sp_rename_thisnewdatabasenameisb8bd7c94f797959aa629fc2f9e821637 sp_rename_thisnewdatabasenameisfacf8af797f428fdc401ffddc672894d#!##!#dbo#!#sp_rename_thisnewdatabasenameisb8bd7c94f797959aa629fc2f9e821637 ~~END~~ diff --git a/test/JDBC/expected/Test_sp_renamedb-vu-verify.out b/test/JDBC/expected/Test_sp_renamedb-vu-verify.out index 5e9f657003..598688bd0a 100644 --- a/test/JDBC/expected/Test_sp_renamedb-vu-verify.out +++ b/test/JDBC/expected/Test_sp_renamedb-vu-verify.out @@ -19,6 +19,7 @@ sp_renamedb_database1_sp_renamedb_schema1#!#sp_renamedb_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +sp_renamedb_database1_db_accessadmin#!##!#db_accessadmin#!#sp_renamedb_database1 sp_renamedb_database1_db_owner#!##!#db_owner#!#sp_renamedb_database1 sp_renamedb_database1_dbo#!##!#dbo#!#sp_renamedb_database1 sp_renamedb_database1_guest#!##!#guest#!#sp_renamedb_database1 @@ -80,6 +81,7 @@ sp_renamedb_database2_sp_renamedb_schema1#!#sp_renamedb_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +sp_renamedb_database2_db_accessadmin#!##!#db_accessadmin#!#sp_renamedb_database2 sp_renamedb_database2_db_owner#!##!#db_owner#!#sp_renamedb_database2 sp_renamedb_database2_dbo#!##!#dbo#!#sp_renamedb_database2 sp_renamedb_database2_guest#!##!#guest#!#sp_renamedb_database2 @@ -198,6 +200,7 @@ varchar#!#varchar#!#nvarchar#!#nvarchar sp_renamedb_thisnewdatabasename115699cc11f7805d9b9b640d6455580c#!##!#dbo#!#sp_renamedb_thisnewdatabasename738bbb14cb857db43c693446c049f0bd sp_renamedb_thisnewdatabasenameb0dffbb56deab7ad4e684df689419c65#!##!#db_owner#!#sp_renamedb_thisnewdatabasename738bbb14cb857db43c693446c049f0bd sp_renamedb_thisnewdatabasenamedeb7cafbbedd23f312d90e7c10a60901#!##!#guest#!#sp_renamedb_thisnewdatabasename738bbb14cb857db43c693446c049f0bd +sp_renamedb_thisnewdatabasenameeeb9e8f522c23281503d418ce3640572#!##!#db_accessadmin#!#sp_renamedb_thisnewdatabasename738bbb14cb857db43c693446c049f0bd ~~END~~ ~~START~~ diff --git a/test/JDBC/expected/restrict_drop_user_role.out b/test/JDBC/expected/restrict_drop_user_role.out index c058d8feff..a1d76dba08 100644 --- a/test/JDBC/expected/restrict_drop_user_role.out +++ b/test/JDBC/expected/restrict_drop_user_role.out @@ -213,19 +213,35 @@ go -- both of the following statements should be executed successfully since user/role exists drop role if exists no_priv_user3; go -~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Cannot drop the role 'no_priv_user3', because it does not exist or you do not have permission.)~~ +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go +~~START~~ +int +2 +~~END~~ drop user if exists no_priv_user3; go +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go +~~START~~ +int +1 +~~END~~ + + drop user if exists no_priv_role3; go -~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Cannot drop the user 'no_priv_role3', because it does not exist or you do not have permission.)~~ +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go +~~START~~ +int +1 +~~END~~ drop role if exists no_priv_role3; @@ -263,17 +279,9 @@ go -- bbf_role_admin won't have privilege to drop non-babelfish roles drop user if exists pguser1; go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Cannot drop the user 'pguser1', because it does not exist or you do not have permission.)~~ - drop role if exists pguser1; go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Cannot drop the role 'pguser1', because it does not exist or you do not have permission.)~~ - -- psql drop role master_pguser1; @@ -344,10 +352,6 @@ go drop user if exists user1; go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Cannot drop the user 'user1', because it does not exist or you do not have permission.)~~ - use master go diff --git a/test/JDBC/expected/single_db/BABEL-2403.out b/test/JDBC/expected/single_db/BABEL-2403.out index cb9a19347f..1350ce6276 100644 --- a/test/JDBC/expected/single_db/BABEL-2403.out +++ b/test/JDBC/expected/single_db/BABEL-2403.out @@ -87,6 +87,12 @@ name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext m text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} name#!#pg_catalog#!#proname#!#{"Rule": " in babelfish_function_ext must also exist in pg_proc"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} @@ -164,6 +170,12 @@ name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext m text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} +name#!#pg_catalog#!#rolname#!#{"Rule": " in babelfish_authid_user_ext must also exist in pg_authid"} +text#!#sys#!#name#!#{"Rule": " in babelfish_authid_user_ext must also exist in babelfish_sysdatabases"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} name#!#pg_catalog#!#proname#!#{"Rule": " in babelfish_function_ext must also exist in pg_proc"} name#!#sys#!#nspname#!#{"Rule": " in babelfish_function_ext must also exist in babelfish_namespace_ext"} diff --git a/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out b/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out index 9e09597c85..94a8c2063f 100644 --- a/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out +++ b/test/JDBC/expected/single_db/BABEL-LOGIN-USER-EXT.out @@ -130,14 +130,18 @@ master_r1#!#r1#!#r1#!#master#!#sch2 ALTER USER r1 WITH NAME = new_r1; go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current user does not have privileges to change user name)~~ + SELECT rolname, orig_username, login_name, database_name, default_schema_name FROM sys.babelfish_authid_user_ext -WHERE orig_username = 'new_r1'; +WHERE orig_username = 'new_r1' or orig_username = 'r1'; go ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar -master_new_r1#!#new_r1#!#r1#!#master#!#sch2 +master_r1#!#r1#!#r1#!#master#!#sch2 ~~END~~ @@ -217,7 +221,7 @@ r2 -- tsql -DROP USER new_r1; +DROP USER r1; go -- psql @@ -691,14 +695,18 @@ GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar db1_guest#!#guest#!##!#db1#!#guest +db_accessadmin#!#db_accessadmin#!##!#db1#!# db_owner#!#db_owner#!##!#db1#!# dbo#!#dbo#!##!#db1#!#dbo +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -863,12 +871,15 @@ ORDER BY rolname; GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -919,14 +930,18 @@ GO ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar#!#nvarchar db1_guest#!##!#guest#!#db1#!#guest +db_accessadmin#!##!#db_accessadmin#!#db1#!# db_owner#!##!#db_owner#!#db1#!# dbo#!##!#dbo#!#db1#!#dbo +master_db_accessadmin#!##!#db_accessadmin#!#master#!# master_db_owner#!##!#db_owner#!#master#!# master_dbo#!##!#dbo#!#master#!#dbo master_guest#!##!#guest#!#master#!#guest +msdb_db_accessadmin#!##!#db_accessadmin#!#msdb#!# msdb_db_owner#!##!#db_owner#!#msdb#!# msdb_dbo#!##!#dbo#!#msdb#!#dbo msdb_guest#!##!#guest#!#msdb#!#guest +tempdb_db_accessadmin#!##!#db_accessadmin#!#tempdb#!# tempdb_db_owner#!##!#db_owner#!#tempdb#!# tempdb_dbo#!##!#dbo#!#tempdb#!#dbo tempdb_guest#!##!#guest#!#tempdb#!#guest @@ -941,6 +956,7 @@ GO varchar#!#varchar guest#!#guest dbo#!#dbo +db_accessadmin#!# db_owner#!# INFORMATION_SCHEMA#!# public#!# @@ -972,6 +988,7 @@ GO varchar#!#varchar guest#!#guest dbo#!#dbo +db_accessadmin#!# db_owner#!# INFORMATION_SCHEMA#!# public#!# @@ -1110,12 +1127,15 @@ ORDER BY rolname; GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -1135,12 +1155,15 @@ ORDER BY rolname; GO ~~START~~ varchar#!#nvarchar#!#varchar#!#nvarchar#!#nvarchar +master_db_accessadmin#!#db_accessadmin#!##!#master#!# master_db_owner#!#db_owner#!##!#master#!# master_dbo#!#dbo#!##!#master#!#dbo master_guest#!#guest#!##!#master#!#guest +msdb_db_accessadmin#!#db_accessadmin#!##!#msdb#!# msdb_db_owner#!#db_owner#!##!#msdb#!# msdb_dbo#!#dbo#!##!#msdb#!#dbo msdb_guest#!#guest#!##!#msdb#!#guest +tempdb_db_accessadmin#!#db_accessadmin#!##!#tempdb#!# tempdb_db_owner#!#db_owner#!##!#tempdb#!# tempdb_dbo#!#dbo#!##!#tempdb#!#dbo tempdb_guest#!#guest#!##!#tempdb#!#guest @@ -1430,6 +1453,7 @@ GO varchar babel_4935_no_sysadmin1 babel_4935_no_sysadmin2 +db_accessadmin db_owner dbo guest @@ -1447,6 +1471,7 @@ GO varchar babel_4935_no_sysadmin1 babel_4935_no_sysadmin2 +db_accessadmin db_owner dbo guest @@ -1463,6 +1488,7 @@ GO ~~START~~ varchar babel_4935_no_sysadmin1 +db_accessadmin db_owner dbo guest @@ -1478,6 +1504,7 @@ SELECT name FROM sys.database_principals ORDER BY name GO ~~START~~ varchar +db_accessadmin db_owner dbo guest diff --git a/test/JDBC/expected/single_db/BABEL-USER.out b/test/JDBC/expected/single_db/BABEL-USER.out index d22202a7e1..2917e1f1fc 100644 --- a/test/JDBC/expected/single_db/BABEL-USER.out +++ b/test/JDBC/expected/single_db/BABEL-USER.out @@ -50,14 +50,18 @@ GO ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar#!#nvarchar db1_guest#!##!#guest#!#db1#!#guest +db_accessadmin#!##!#db_accessadmin#!#db1#!# db_owner#!##!#db_owner#!#db1#!# dbo#!##!#dbo#!#db1#!#dbo +master_db_accessadmin#!##!#db_accessadmin#!#master#!# master_db_owner#!##!#db_owner#!#master#!# master_dbo#!##!#dbo#!#master#!#dbo master_guest#!##!#guest#!#master#!#guest +msdb_db_accessadmin#!##!#db_accessadmin#!#msdb#!# msdb_db_owner#!##!#db_owner#!#msdb#!# msdb_dbo#!##!#dbo#!#msdb#!#dbo msdb_guest#!##!#guest#!#msdb#!#guest +tempdb_db_accessadmin#!##!#db_accessadmin#!#tempdb#!# tempdb_db_owner#!##!#db_owner#!#tempdb#!# tempdb_dbo#!##!#dbo#!#tempdb#!#dbo tempdb_guest#!##!#guest#!#tempdb#!#guest @@ -72,6 +76,7 @@ GO varchar#!#varchar guest#!#guest dbo#!#dbo +db_accessadmin#!# db_owner#!# INFORMATION_SCHEMA#!# public#!# diff --git a/test/JDBC/expected/single_db/Test_rename_db_single-db.out b/test/JDBC/expected/single_db/Test_rename_db_single-db.out index fbb07e25cf..227059870a 100644 --- a/test/JDBC/expected/single_db/Test_rename_db_single-db.out +++ b/test/JDBC/expected/single_db/Test_rename_db_single-db.out @@ -32,6 +32,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 db_owner#!##!#db_owner#!#rename_db_database1 dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -80,6 +81,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 db_owner#!##!#db_owner#!#rename_db_database2 dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 @@ -128,6 +130,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 db_owner#!##!#db_owner#!#rename_db_database1 dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -176,6 +179,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 db_owner#!##!#db_owner#!#rename_db_database2 dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 @@ -236,6 +240,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 db_owner#!##!#db_owner#!#rename_db_database1 dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -284,6 +289,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 db_owner#!##!#db_owner#!#rename_db_database2 dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 @@ -332,6 +338,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database1 db_owner#!##!#db_owner#!#rename_db_database1 dbo#!##!#dbo#!#rename_db_database1 rename_db_database1_guest#!##!#guest#!#rename_db_database1 @@ -380,6 +387,7 @@ rename_db_schema1#!#rename_db_schema1 ~~START~~ varchar#!#varchar#!#nvarchar#!#nvarchar +db_accessadmin#!##!#db_accessadmin#!#rename_db_database2 db_owner#!##!#db_owner#!#rename_db_database2 dbo#!##!#dbo#!#rename_db_database2 rename_db_database2_guest#!##!#guest#!#rename_db_database2 diff --git a/test/JDBC/expected/single_db/restrict_drop_user_role.out b/test/JDBC/expected/single_db/restrict_drop_user_role.out index 51acb0056a..0016910d85 100644 --- a/test/JDBC/expected/single_db/restrict_drop_user_role.out +++ b/test/JDBC/expected/single_db/restrict_drop_user_role.out @@ -213,19 +213,35 @@ go -- both of the following statements should be executed successfully since user/role exists drop role if exists no_priv_user3; go -~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Cannot drop the role 'no_priv_user3', because it does not exist or you do not have permission.)~~ +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go +~~START~~ +int +2 +~~END~~ drop user if exists no_priv_user3; go +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go +~~START~~ +int +1 +~~END~~ + + drop user if exists no_priv_role3; go -~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Cannot drop the user 'no_priv_role3', because it does not exist or you do not have permission.)~~ +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go +~~START~~ +int +1 +~~END~~ drop role if exists no_priv_role3; @@ -263,17 +279,9 @@ go -- bbf_role_admin won't have privilege to drop non-babelfish roles drop user if exists pguser1; go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Cannot drop the user 'pguser1', because it does not exist or you do not have permission.)~~ - drop role if exists pguser1; go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Cannot drop the role 'pguser1', because it does not exist or you do not have permission.)~~ - -- psql drop role master_pguser1; diff --git a/test/JDBC/input/BABEL-LOGIN-USER-EXT.mix b/test/JDBC/input/BABEL-LOGIN-USER-EXT.mix index 2ccb1e5e89..a8e0ddb912 100644 --- a/test/JDBC/input/BABEL-LOGIN-USER-EXT.mix +++ b/test/JDBC/input/BABEL-LOGIN-USER-EXT.mix @@ -81,7 +81,7 @@ go SELECT rolname, orig_username, login_name, database_name, default_schema_name FROM sys.babelfish_authid_user_ext -WHERE orig_username = 'new_r1'; +WHERE orig_username = 'new_r1' or orig_username = 'r1'; go ALTER USER r2 WITH DEFAULT_SCHEMA = NULL; @@ -117,7 +117,7 @@ SELECT user_name(user_id()); go -- tsql -DROP USER new_r1; +DROP USER r1; go -- psql diff --git a/test/JDBC/input/ownership/BABEL-LOGIN-vu-verify.mix b/test/JDBC/input/ownership/BABEL-LOGIN-vu-verify.mix index 914a52ca5f..63b1532bbe 100644 --- a/test/JDBC/input/ownership/BABEL-LOGIN-vu-verify.mix +++ b/test/JDBC/input/ownership/BABEL-LOGIN-vu-verify.mix @@ -162,7 +162,7 @@ go DROP USER babel_login_vu_prepare_err_user; go -DROP USER babel_login_vu_prepare_r1_new +DROP USER babel_login_vu_prepare_r1 go DROP USER babel_login_vu_prepare_r2 diff --git a/test/JDBC/input/restrict_drop_user_role.mix b/test/JDBC/input/restrict_drop_user_role.mix index 53d5d91596..a946314493 100644 --- a/test/JDBC/input/restrict_drop_user_role.mix +++ b/test/JDBC/input/restrict_drop_user_role.mix @@ -147,12 +147,21 @@ go drop role if exists no_priv_user3; go +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go + drop user if exists no_priv_user3; go +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go + drop user if exists no_priv_role3; go +select count(*) from sys.database_principals where name like '%no_priv_%3'; +go + drop role if exists no_priv_role3; go diff --git a/test/python/expected/sql_validation_framework/expected_drop.out b/test/python/expected/sql_validation_framework/expected_drop.out index 243d664edf..ff5414284b 100644 --- a/test/python/expected/sql_validation_framework/expected_drop.out +++ b/test/python/expected/sql_validation_framework/expected_drop.out @@ -43,6 +43,7 @@ Unexpected drop found for operator sys./ in file babelfishpg_common--1.1.0--1.2. Unexpected drop found for operator sys./ in file babelfishpg_common--1.1.0--1.2.0.sql Unexpected drop found for operator sys./ in file babelfishpg_common--1.1.0--1.2.0.sql Unexpected drop found for procedure babelfish_drop_deprecated_opclass in file babelfishpg_common--1.0.0--1.1.0.sql +Unexpected drop found for procedure sys.babel_create_database_roles in file babelfishpg_tsql--4.3.0--4.4.0.sql Unexpected drop found for procedure sys.babel_create_guest_schemas in file babelfishpg_tsql--2.3.0--2.4.0.sql Unexpected drop found for procedure sys.babel_create_guest_schemas in file babelfishpg_tsql--3.0.0--3.1.0.sql Unexpected drop found for procedure sys.babelfish_drop_deprecated_function in file babelfishpg_tsql--1.2.1--2.0.0.sql From 9366d6fa8701b58dc08f2e56a9d5d508e3c997f0 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Wed, 25 Sep 2024 10:13:49 +0000 Subject: [PATCH 02/41] empty commit to rerun actions Signed-off-by: Tanzeel Khan From 1d235d6ebc91dff915dfb77838076ae285174e51 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Wed, 25 Sep 2024 15:48:03 +0000 Subject: [PATCH 03/41] add basic tests Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 14 +- contrib/babelfishpg_tsql/src/multidb.c | 13 +- contrib/babelfishpg_tsql/src/multidb.h | 2 +- contrib/babelfishpg_tsql/src/pl_handler.c | 25 ++- .../expected/db_accessadmin-vu-cleanup.out | 25 +++ .../expected/db_accessadmin-vu-prepare.out | 35 ++++ .../expected/db_accessadmin-vu-verify.out | 163 ++++++++++++++++++ .../single_db/db_accessadmin-vu-verify.out | 163 ++++++++++++++++++ test/JDBC/input/db_accessadmin-vu-cleanup.mix | 25 +++ test/JDBC/input/db_accessadmin-vu-prepare.mix | 35 ++++ test/JDBC/input/db_accessadmin-vu-verify.mix | 112 ++++++++++++ 11 files changed, 598 insertions(+), 14 deletions(-) create mode 100644 test/JDBC/expected/db_accessadmin-vu-cleanup.out create mode 100644 test/JDBC/expected/db_accessadmin-vu-prepare.out create mode 100644 test/JDBC/expected/db_accessadmin-vu-verify.out create mode 100644 test/JDBC/expected/single_db/db_accessadmin-vu-verify.out create mode 100644 test/JDBC/input/db_accessadmin-vu-cleanup.mix create mode 100644 test/JDBC/input/db_accessadmin-vu-prepare.mix create mode 100644 test/JDBC/input/db_accessadmin-vu-verify.mix diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 30c2c28d8f..cc4c0f2677 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -984,20 +984,22 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) Anum_bbf_authid_user_ext_database_name, BTEqualStrategyNumber, F_TEXTEQ, CStringGetTextDatum(db_name)); - ScanKeyInit(&key[2], - Anum_bbf_authid_user_ext_user_can_connect, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(1)); - scan = table_beginscan_catalog(bbf_authid_user_ext_rel, 3, key); + scan = table_beginscan_catalog(bbf_authid_user_ext_rel, 2, key); tuple_user_ext = heap_getnext(scan, ForwardScanDirection); if (HeapTupleIsValid(tuple_user_ext)) { Form_authid_user_ext userform; + char *db_accessadmin = get_db_accessadmin_role_name(db_name); userform = (Form_authid_user_ext) GETSTRUCT(tuple_user_ext); - user_name = pstrdup(NameStr(userform->rolname)); + if (userform->user_can_connect || + (has_privs_of_role(GetUserId(), get_role_oid(db_accessadmin, false)))) + { + user_name = pstrdup(NameStr(userform->rolname)); + } + pfree(db_accessadmin); } table_endscan(scan); diff --git a/contrib/babelfishpg_tsql/src/multidb.c b/contrib/babelfishpg_tsql/src/multidb.c index 0e99e73dc1..7ad0c379be 100644 --- a/contrib/babelfishpg_tsql/src/multidb.c +++ b/contrib/babelfishpg_tsql/src/multidb.c @@ -249,6 +249,17 @@ rewrite_object_refs(Node *stmt) errmsg("Dropping members to db_owner is not currently supported " "in Babelfish"))); } + else if (strcmp(role_name, DB_ACCESSADMIN) == 0) + { + if (has_privs_of_role(GetUserId(), get_role_oid(get_db_owner_name(db_name), false))) + { + /* only members of db_owner can alter drop members to fixed db roles */ + } + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", role_name))); + } /* * Try to get physical granted role name, see if it's an @@ -1417,7 +1428,7 @@ get_guest_role_name(const char *dbname) } } -const char * +char * get_db_accessadmin_role_name(const char *dbname) { char *name = palloc0(MAX_BBF_NAMEDATALEND); diff --git a/contrib/babelfishpg_tsql/src/multidb.h b/contrib/babelfishpg_tsql/src/multidb.h index 1f6d31149a..d74efe1a26 100644 --- a/contrib/babelfishpg_tsql/src/multidb.h +++ b/contrib/babelfishpg_tsql/src/multidb.h @@ -24,7 +24,7 @@ extern const char *get_dbo_schema_name(const char *dbname); extern const char *get_dbo_role_name(const char *dbname); extern const char *get_db_owner_name(const char *dbname); extern const char *get_guest_role_name(const char *dbname); -extern const char *get_db_accessadmin_role_name(const char *dbname); +extern char *get_db_accessadmin_role_name(const char *dbname); extern const char *get_guest_schema_name(const char *dbname); extern bool is_shared_schema(const char *name); extern void truncate_tsql_identifier(char *ident); diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 7f74b6bd1b..908fbe3c48 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3232,7 +3232,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, is_member_of_db_owner = has_privs_of_role(GetUserId(), db_owner); /* check membership in db_accessadmin if alter user and not already a member of db_owner */ - if (!is_member_of_db_owner && !isuser) + if (!is_member_of_db_owner && isuser) is_member_of_db_accessadmin = has_privs_of_role(GetUserId(), db_accessadmin); /* @@ -3299,13 +3299,13 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } } + GetUserIdAndSecContext(&save_userid, &save_sec_context); /* * We have performed all the permissions checks. * Set current user to bbf_role_admin for alter permissions. */ PG_TRY(); { - GetUserIdAndSecContext(&save_userid, &save_sec_context); SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); if (prev_ProcessUtility) @@ -3568,11 +3568,11 @@ bbf_ProcessUtility(PlannedStmt *pstmt, * We have performed all the permissions checks. * Set current user to bbf_role_admin for drop permissions. */ + GetUserIdAndSecContext(&save_userid, &save_sec_context); + SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + PG_TRY(); { - GetUserIdAndSecContext(&save_userid, &save_sec_context); - SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); - if (prev_ProcessUtility) prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, @@ -3673,7 +3673,20 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (alter_owner) { - AlterSchemaOwner_oid(get_namespace_oid(create_schema->schemaname, false), owner_oid); + Oid save_userid; + int save_sec_context; + + GetUserIdAndSecContext(&save_userid, &save_sec_context); + PG_TRY(); + { + SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + AlterSchemaOwner_oid(get_namespace_oid(create_schema->schemaname, false), owner_oid); + } + PG_FINALLY(); + { + SetUserIdAndSecContext(save_userid, save_sec_context); + } + PG_END_TRY(); } /* Grant ALL schema privileges to the user.*/ diff --git a/test/JDBC/expected/db_accessadmin-vu-cleanup.out b/test/JDBC/expected/db_accessadmin-vu-cleanup.out new file mode 100644 index 0000000000..ec399a0ba3 --- /dev/null +++ b/test/JDBC/expected/db_accessadmin-vu-cleanup.out @@ -0,0 +1,25 @@ +-- tsql +USE master +GO +DROP DATABASE babel_5136 +GO +DROP LOGIN babel_5136_l1 +GO +DROP LOGIN babel_5136_l2 +GO +DROP LOGIN babel_5136_l3 +GO +DROP LOGIN babel_5136_db_accessadmin_l1 +GO +DROP USER babel_5136_u1 +GO +DROP USER babel_5136_user_master +GO +DROP ROLE babel_5136_r1 +GO +DROP TABLE babel_5136_t1 +GO +DROP PROC babel_5136_p1 +GO +DROP FUNCTION f1 +GO diff --git a/test/JDBC/expected/db_accessadmin-vu-prepare.out b/test/JDBC/expected/db_accessadmin-vu-prepare.out new file mode 100644 index 0000000000..f88da3019a --- /dev/null +++ b/test/JDBC/expected/db_accessadmin-vu-prepare.out @@ -0,0 +1,35 @@ +-- tsql +USE master +GO +CREATE LOGIN babel_5136_l1 WITH PASSWORD = '12345678' +GO +CREATE LOGIN babel_5136_l2 WITH PASSWORD = '12345678' +GO +CREATE LOGIN babel_5136_l3 WITH PASSWORD = '12345678' +GO +CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 +GO +CREATE ROLE babel_5136_r1 +GO +CREATE TABLE babel_5136_t1 (id INT) +GO +CREATE PROC babel_5136_p1 AS SELECT 1 +GO +CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END +GO + +CREATE DATABASE babel_5136 +GO +USE babel_5136 +GO +CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 +GO +CREATE ROLE babel_5136_r1 +GO +CREATE TABLE babel_5136_t1 (id INT) +GO +CREATE PROC babel_5136_p1 AS SELECT 1 +GO +CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END +GO + diff --git a/test/JDBC/expected/db_accessadmin-vu-verify.out b/test/JDBC/expected/db_accessadmin-vu-verify.out new file mode 100644 index 0000000000..5765883a1d --- /dev/null +++ b/test/JDBC/expected/db_accessadmin-vu-verify.out @@ -0,0 +1,163 @@ + + +-- tsql +-- CREATE LOGIN AND ADD IT TO db_accessadmin + -- Only members of db_owner should be able to add/drop members to db_accessadmin +-- db_accessadmin should be able to do the following + -- CREATE USER in database + -- DROP ANY USER in database (except dbo) + -- ALTER default_schema for any user in database + -- RENAME user execpt for members of db_owner + -- CREATE SCHEMA for self or other users in database +-- CREATE A USER WITH db_accessadmin privilege in DATABASE babel_5136 +USE master +GO +CREATE LOGIN babel_5136_db_accessadmin_l1 WITH PASSWORD = '12345678' +GO +CREATE USER babel_5136_user_master FOR LOGIN babel_5136_db_accessadmin_l1 +GO +USE babel_5136 +GO +CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l1 +GO +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user +GO +-- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES +REVOKE CONNECT FROM babel_5136_db_accessadmin_user +GO +-- terminate-tsql-conn + +-- tsql user=babel_5136_l1 password=12345678 database=babel_5136 +-- Only db_owner members should be able to do this +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +-- terminate-tsql-conn + + +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 +-- Check all allowed operations +USE master +GO + +SELECT current_user +GO +~~START~~ +varchar +babel_5136_user_master +~~END~~ + + +-- should not be a member of db_accessadmin in master database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +0 +~~END~~ + + +USE babel_5136 +GO + +SELECT current_user +GO +~~START~~ +varchar +babel_5136_db_accessadmin_user +~~END~~ + + +-- should be a member of db_accessadmin in babel_5136 database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +1 +~~END~~ + + +-- db_accessadmin can not add/drop members to db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + + +-- CREATE DROP A NEW USER +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +DROP USER babel_5136_u2 +GO + +-- DROP & RECREATE EXISTING USER +DROP USER babel_5136_u1 +GO +CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 +GO + +-- ALTER USER and THEN DROP IT +ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo +GO +-- NOT SUPPORTED CURRENTLY IN BABELFISH +ALTER USER babel_5136_u1 WITH DEFAULT_LANGUAGE = English +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error at or near "DEFAULT_LANGUAGE")~~ + +ALTER USER babel_5136_u1 WITH NAME = babel_5136_u1_new_name +GO +-- NOT SUPPORTED CURRENTLY IN BABELFISH +ALTER USER babel_5136_u1_new_name WITH PASSWORD = 'shouldfail' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near '' at line 3 and character position 0)~~ + +-- db_accessadmin should not be able to ALTER LOGIN MAPPING +ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current user does not have privileges to change login)~~ + +ALTER USER babel_5136_u1_new_name WITH NAME = babel_5136_u1 +GO + +-- CREATE SCHEMA should be allowed db_accessadmin +CREATE SCHEMA s1 +GO +CREATE SCHEMA s2 AUTHORIZATION dbo +GO +CREATE SCHEMA s3 AUTHORIZATION babel_5136_u1 +GO +-- Should only be able to drop schema that it owns +DROP SCHEMA s1 +GO +DROP SCHEMA s2 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: must be owner of schema babel_5136_s2)~~ + +DROP SCHEMA s3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: must be owner of schema babel_5136_s3)~~ + + +-- Should be restricted +DROP USER dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the user 'dbo'.)~~ + +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 + diff --git a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out new file mode 100644 index 0000000000..7e7cc39530 --- /dev/null +++ b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out @@ -0,0 +1,163 @@ + + +-- tsql +-- CREATE LOGIN AND ADD IT TO db_accessadmin + -- Only members of db_owner should be able to add/drop members to db_accessadmin +-- db_accessadmin should be able to do the following + -- CREATE USER in database + -- DROP ANY USER in database (except dbo) + -- ALTER default_schema for any user in database + -- RENAME user execpt for members of db_owner + -- CREATE SCHEMA for self or other users in database +-- CREATE A USER WITH db_accessadmin privilege in DATABASE babel_5136 +USE master +GO +CREATE LOGIN babel_5136_db_accessadmin_l1 WITH PASSWORD = '12345678' +GO +CREATE USER babel_5136_user_master FOR LOGIN babel_5136_db_accessadmin_l1 +GO +USE babel_5136 +GO +CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l1 +GO +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user +GO +-- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES +REVOKE CONNECT FROM babel_5136_db_accessadmin_user +GO +-- terminate-tsql-conn + +-- tsql user=babel_5136_l1 password=12345678 database=babel_5136 +-- Only db_owner members should be able to do this +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +-- terminate-tsql-conn + + +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 +-- Check all allowed operations +USE master +GO + +SELECT current_user +GO +~~START~~ +varchar +babel_5136_user_master +~~END~~ + + +-- should not be a member of db_accessadmin in master database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +0 +~~END~~ + + +USE babel_5136 +GO + +SELECT current_user +GO +~~START~~ +varchar +babel_5136_db_accessadmin_user +~~END~~ + + +-- should be a member of db_accessadmin in babel_5136 database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +1 +~~END~~ + + +-- db_accessadmin can not add/drop members to db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + + +-- CREATE DROP A NEW USER +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +DROP USER babel_5136_u2 +GO + +-- DROP & RECREATE EXISTING USER +DROP USER babel_5136_u1 +GO +CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 +GO + +-- ALTER USER and THEN DROP IT +ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo +GO +-- NOT SUPPORTED CURRENTLY IN BABELFISH +ALTER USER babel_5136_u1 WITH DEFAULT_LANGUAGE = English +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error at or near "DEFAULT_LANGUAGE")~~ + +ALTER USER babel_5136_u1 WITH NAME = babel_5136_u1_new_name +GO +-- NOT SUPPORTED CURRENTLY IN BABELFISH +ALTER USER babel_5136_u1_new_name WITH PASSWORD = 'shouldfail' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near '' at line 3 and character position 0)~~ + +-- db_accessadmin should not be able to ALTER LOGIN MAPPING +ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current user does not have privileges to change login)~~ + +ALTER USER babel_5136_u1_new_name WITH NAME = babel_5136_u1 +GO + +-- CREATE SCHEMA should be allowed db_accessadmin +CREATE SCHEMA s1 +GO +CREATE SCHEMA s2 AUTHORIZATION dbo +GO +CREATE SCHEMA s3 AUTHORIZATION babel_5136_u1 +GO +-- Should only be able to drop schema that it owns +DROP SCHEMA s1 +GO +DROP SCHEMA s2 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: must be owner of schema s2)~~ + +DROP SCHEMA s3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: must be owner of schema s3)~~ + + +-- Should be restricted +DROP USER dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the user 'dbo'.)~~ + +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 + diff --git a/test/JDBC/input/db_accessadmin-vu-cleanup.mix b/test/JDBC/input/db_accessadmin-vu-cleanup.mix new file mode 100644 index 0000000000..b94e7ff925 --- /dev/null +++ b/test/JDBC/input/db_accessadmin-vu-cleanup.mix @@ -0,0 +1,25 @@ +-- tsql +USE master +GO +DROP DATABASE babel_5136 +GO +DROP LOGIN babel_5136_l1 +GO +DROP LOGIN babel_5136_l2 +GO +DROP LOGIN babel_5136_l3 +GO +DROP LOGIN babel_5136_db_accessadmin_l1 +GO +DROP USER babel_5136_u1 +GO +DROP USER babel_5136_user_master +GO +DROP ROLE babel_5136_r1 +GO +DROP TABLE babel_5136_t1 +GO +DROP PROC babel_5136_p1 +GO +DROP FUNCTION f1 +GO \ No newline at end of file diff --git a/test/JDBC/input/db_accessadmin-vu-prepare.mix b/test/JDBC/input/db_accessadmin-vu-prepare.mix new file mode 100644 index 0000000000..f88da3019a --- /dev/null +++ b/test/JDBC/input/db_accessadmin-vu-prepare.mix @@ -0,0 +1,35 @@ +-- tsql +USE master +GO +CREATE LOGIN babel_5136_l1 WITH PASSWORD = '12345678' +GO +CREATE LOGIN babel_5136_l2 WITH PASSWORD = '12345678' +GO +CREATE LOGIN babel_5136_l3 WITH PASSWORD = '12345678' +GO +CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 +GO +CREATE ROLE babel_5136_r1 +GO +CREATE TABLE babel_5136_t1 (id INT) +GO +CREATE PROC babel_5136_p1 AS SELECT 1 +GO +CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END +GO + +CREATE DATABASE babel_5136 +GO +USE babel_5136 +GO +CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 +GO +CREATE ROLE babel_5136_r1 +GO +CREATE TABLE babel_5136_t1 (id INT) +GO +CREATE PROC babel_5136_p1 AS SELECT 1 +GO +CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END +GO + diff --git a/test/JDBC/input/db_accessadmin-vu-verify.mix b/test/JDBC/input/db_accessadmin-vu-verify.mix new file mode 100644 index 0000000000..eb9f82c39a --- /dev/null +++ b/test/JDBC/input/db_accessadmin-vu-verify.mix @@ -0,0 +1,112 @@ +-- single_db_mode_expected +-- CREATE LOGIN AND ADD IT TO db_accessadmin + -- Only members of db_owner should be able to add/drop members to db_accessadmin + +-- db_accessadmin should be able to do the following + -- CREATE USER in database + -- DROP ANY USER in database (except dbo) + -- ALTER default_schema for any user in database + -- RENAME user execpt for members of db_owner + -- CREATE SCHEMA for self or other users in database + +-- tsql +-- CREATE A USER WITH db_accessadmin privilege in DATABASE babel_5136 +USE master +GO +CREATE LOGIN babel_5136_db_accessadmin_l1 WITH PASSWORD = '12345678' +GO +CREATE USER babel_5136_user_master FOR LOGIN babel_5136_db_accessadmin_l1 +GO +USE babel_5136 +GO +CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l1 +GO +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user +GO +-- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES +REVOKE CONNECT FROM babel_5136_db_accessadmin_user +GO +-- terminate-tsql-conn + +-- Only db_owner members should be able to do this +-- tsql user=babel_5136_l1 password=12345678 database=babel_5136 +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user +GO +-- terminate-tsql-conn + + +-- Check all allowed operations +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 +USE master +GO + +SELECT current_user +GO + +-- should not be a member of db_accessadmin in master database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO + +USE babel_5136 +GO + +SELECT current_user +GO + +-- should be a member of db_accessadmin in babel_5136 database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO + +-- db_accessadmin can not add/drop members to db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 +GO + +-- CREATE DROP A NEW USER +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +DROP USER babel_5136_u2 +GO + +-- DROP & RECREATE EXISTING USER +DROP USER babel_5136_u1 +GO +CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 +GO + +-- ALTER USER and THEN DROP IT +ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo +GO +-- NOT SUPPORTED CURRENTLY IN BABELFISH +ALTER USER babel_5136_u1 WITH DEFAULT_LANGUAGE = English +GO +ALTER USER babel_5136_u1 WITH NAME = babel_5136_u1_new_name +GO +-- NOT SUPPORTED CURRENTLY IN BABELFISH +ALTER USER babel_5136_u1_new_name WITH PASSWORD = 'shouldfail' +GO +-- db_accessadmin should not be able to ALTER LOGIN MAPPING +ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +GO +ALTER USER babel_5136_u1_new_name WITH NAME = babel_5136_u1 +GO + +-- CREATE SCHEMA should be allowed db_accessadmin +CREATE SCHEMA s1 +GO +CREATE SCHEMA s2 AUTHORIZATION dbo +GO +CREATE SCHEMA s3 AUTHORIZATION babel_5136_u1 +GO +-- Should only be able to drop schema that it owns +DROP SCHEMA s1 +GO +DROP SCHEMA s2 +GO +DROP SCHEMA s3 +GO + +-- Should be restricted +DROP USER dbo +GO +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 + From 67782424772f892b3c159a71b4b32ed927a33fcb Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Wed, 25 Sep 2024 17:19:37 +0000 Subject: [PATCH 04/41] fix get_authid_user_ext_physical_name Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index cc4c0f2677..2f714f4fa4 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -877,6 +877,8 @@ is_user(Oid role_oid, bool current_db_only) char *db_name_cstring = TextDatumGetCString(db_name); char *current_db_name = get_cur_db_name(); + Assert(!isnull); + is_user = (strcmp(db_name_cstring, current_db_name) == 0); pfree(db_name_cstring); @@ -920,6 +922,8 @@ is_role(Oid role_oid, bool current_db_only) char *db_name_cstring = TextDatumGetCString(db_name); char *current_db_name = get_cur_db_name(); + Assert(!isnull); + is_role = (strcmp(db_name_cstring, current_db_name) == 0); pfree(db_name_cstring); @@ -963,7 +967,7 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) { Relation bbf_authid_user_ext_rel; HeapTuple tuple_user_ext; - ScanKeyData key[3]; + ScanKeyData key[2]; TableScanDesc scan; char *user_name = NULL; NameData *login_name; @@ -990,14 +994,24 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) tuple_user_ext = heap_getnext(scan, ForwardScanDirection); if (HeapTupleIsValid(tuple_user_ext)) { - Form_authid_user_ext userform; + Datum datum; char *db_accessadmin = get_db_accessadmin_role_name(db_name); + bool user_can_connect; + bool isnull; + + datum = heap_getattr(tuple_user_ext, Anum_bbf_authid_user_ext_user_can_connect, + RelationGetDescr(bbf_authid_user_ext_rel), &isnull); + Assert(!isnull); + user_can_connect = DatumGetInt32(datum); - userform = (Form_authid_user_ext) GETSTRUCT(tuple_user_ext); - if (userform->user_can_connect || - (has_privs_of_role(GetUserId(), get_role_oid(db_accessadmin, false)))) + if (user_can_connect == 1 || + (has_privs_of_role(get_role_oid(login, false), get_role_oid(db_accessadmin, false)))) { - user_name = pstrdup(NameStr(userform->rolname)); + datum = heap_getattr(tuple_user_ext, Anum_bbf_authid_user_ext_rolname, + RelationGetDescr(bbf_authid_user_ext_rel), &isnull); + Assert(!isnull); + + user_name = pstrdup(DatumGetCString(datum)); } pfree(db_accessadmin); } From aa8c3a5fd856ce68fdd6e7108f650261cc750984 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Wed, 25 Sep 2024 18:14:11 +0000 Subject: [PATCH 05/41] refactor Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 12 ++++++++---- contrib/babelfishpg_tsql/src/dbcmds.c | 13 ++----------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 2f714f4fa4..58679effaa 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -874,10 +874,12 @@ is_user(Oid role_oid, bool current_db_only) { Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, Anum_bbf_authid_user_ext_database_name, &isnull); - char *db_name_cstring = TextDatumGetCString(db_name); - char *current_db_name = get_cur_db_name(); + char *db_name_cstring; + char *current_db_name; Assert(!isnull); + db_name_cstring = TextDatumGetCString(db_name); + current_db_name = get_cur_db_name(); is_user = (strcmp(db_name_cstring, current_db_name) == 0); @@ -919,10 +921,12 @@ is_role(Oid role_oid, bool current_db_only) { Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, Anum_bbf_authid_user_ext_database_name, &isnull); - char *db_name_cstring = TextDatumGetCString(db_name); - char *current_db_name = get_cur_db_name(); + char *db_name_cstring; + char *current_db_name; Assert(!isnull); + db_name_cstring = TextDatumGetCString(db_name); + current_db_name = get_cur_db_name(); is_role = (strcmp(db_name_cstring, current_db_name) == 0); diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 56e55c98bb..204c61f78f 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -1275,7 +1275,6 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) char *dbname; int saved_nest_level = 0; - /* We only allow this to be called from an extension's SQL script. */ if (!creating_extension) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -1328,15 +1327,10 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) PG_TRY(); { ListCell *parsetree_item; - /* - * We have performed all the permissions checks. - * Set current user to bbf_role_admin for create permissions. - * Set createrole_self_grant to "inherit" so that bbf_role_admin - * inherits the new role. - */ + SetConfigOption("createrole_self_grant", "inherit", PGC_USERSET, PGC_S_OVERRIDE); add_to_bbf_authid_user_ext(db_accessadmin, DB_ACCESSADMIN, dbname, NULL, NULL, true, true, false); - /* Run all subcommands */ + foreach(parsetree_item, parsetree_list) { PlannedStmt *wrapper; @@ -1350,14 +1344,12 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); } - /* need to make a wrapper PlannedStmt */ wrapper = makeNode(PlannedStmt); wrapper->commandType = CMD_UTILITY; wrapper->canSetTag = false; wrapper->utilityStmt = ((RawStmt *) lfirst(parsetree_item))->stmt; wrapper->stmt_location = 0; - /* do this step */ ProcessUtility(wrapper, "(CREATE LOGICAL DATABASE )", false, @@ -1372,7 +1364,6 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) } PG_FINALLY(); { - /* Clean up. Restore previous state. */ SetConfigOption("createrole_self_grant", old_createrole_self_grant, PGC_USERSET, PGC_S_OVERRIDE); SetUserIdAndSecContext(save_userid, save_sec_context); } From 04161b7c6f680aece296a83dc588b612950441c6 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 26 Sep 2024 13:50:38 +0000 Subject: [PATCH 06/41] refactor is_role() & is_user() to one function Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 100 ++++++---------------- contrib/babelfishpg_tsql/src/catalog.h | 5 +- contrib/babelfishpg_tsql/src/pl_handler.c | 25 +++--- contrib/babelfishpg_tsql/src/procedures.c | 10 +-- contrib/babelfishpg_tsql/src/rolecmds.c | 8 +- 5 files changed, 52 insertions(+), 96 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 58679effaa..4c7c853c70 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -848,102 +848,56 @@ get_authid_login_ext_idx_oid(void) * USER EXT *****************************************/ -bool -is_user(Oid role_oid, bool current_db_only) +/* + * Check if role is a bbf db principal. Returns BBF_ROLE if it is + * a db role, returns BBF_USER if it is db user else returns 0 + * Looks only in current bbf db when current_db_only is set to true + */ + +const int +is_database_principal(Oid role_oid, bool current_db_only) { - bool is_user = false; - bool isnull; + char result; + bool isnull; HeapTuple tuple; char *rolname; rolname = GetUserNameFromId(role_oid, false); tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(rolname)); + pfree(rolname); if (HeapTupleIsValid(tuple)) { BpChar type = ((Form_authid_user_ext) GETSTRUCT(tuple))->type; char *type_str = bpchar_to_cstring(&type); - /* - * Only sysadmin can not be dropped. For the rest of the cases i.e., type - * is "S" or "U" etc, we should drop the user - */ - if (strcmp(type_str, "R") != 0) - { - if (current_db_only) - { - Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, - Anum_bbf_authid_user_ext_database_name, &isnull); - char *db_name_cstring; - char *current_db_name; - - Assert(!isnull); - db_name_cstring = TextDatumGetCString(db_name); - current_db_name = get_cur_db_name(); - - is_user = (strcmp(db_name_cstring, current_db_name) == 0); + result = (strcmp(type_str, "R") == 0) ? BBF_ROLE : BBF_USER; - pfree(db_name_cstring); - pfree(current_db_name); - } - else - is_user = true; - } - - ReleaseSysCache(tuple); pfree(type_str); - } - pfree(rolname); - - return is_user; -} - -bool -is_role(Oid role_oid, bool current_db_only) -{ - bool is_role = false; - bool isnull; - HeapTuple tuple; - char *rolname; - - rolname = GetUserNameFromId(role_oid, false); - tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(rolname)); - - if (HeapTupleIsValid(tuple)) - { - BpChar type = ((Form_authid_user_ext) GETSTRUCT(tuple))->type; - char *type_str = bpchar_to_cstring(&type); - - if (strcmp(type_str, "R") == 0) + if (current_db_only) { - if (current_db_only) - { - Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, - Anum_bbf_authid_user_ext_database_name, &isnull); - char *db_name_cstring; - char *current_db_name; + Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_database_name, &isnull); + char *db_name_cstring; + char *current_db_name; - Assert(!isnull); - db_name_cstring = TextDatumGetCString(db_name); - current_db_name = get_cur_db_name(); + Assert(!isnull); + db_name_cstring = TextDatumGetCString(db_name); + current_db_name = get_cur_db_name(); - is_role = (strcmp(db_name_cstring, current_db_name) == 0); + /* db match failed */ + if (strcmp(db_name_cstring, current_db_name) != 0) + result = 0; - pfree(db_name_cstring); - pfree(current_db_name); - } - else - is_role = true; + pfree(db_name_cstring); + pfree(current_db_name); } - + ReleaseSysCache(tuple); - pfree(type_str); } - pfree(rolname); - - return is_role; + return result; } Oid diff --git a/contrib/babelfishpg_tsql/src/catalog.h b/contrib/babelfishpg_tsql/src/catalog.h index 347b93baa9..40d5c282d8 100644 --- a/contrib/babelfishpg_tsql/src/catalog.h +++ b/contrib/babelfishpg_tsql/src/catalog.h @@ -146,8 +146,9 @@ extern Oid get_authid_login_ext_idx_oid(void); extern Oid bbf_authid_user_ext_oid; extern Oid bbf_authid_user_ext_idx_oid; -extern bool is_user(Oid role_oid, bool current_db_only); -extern bool is_role(Oid role_oid, bool current_db_only); +#define BBF_ROLE 1 +#define BBF_USER 2 +const int is_database_principal(Oid role_oid, bool current_db_only); extern Oid get_authid_user_ext_oid(void); extern Oid get_authid_user_ext_idx_oid(void); extern char *get_authid_user_ext_physical_name(const char *db_name, const char *login_name); diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 908fbe3c48..d0c0d62a1b 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3222,10 +3222,11 @@ bbf_ProcessUtility(PlannedStmt *pstmt, Oid save_userid; Oid db_owner = get_role_oid(get_db_owner_name(db_name), false); Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(db_name), false); - Oid user_name = get_role_oid(stmt->role->rolename, false); + Oid user_oid = get_role_oid(stmt->role->rolename, false); /* db principal being altered should be a user or role in the current active logical database */ - if (!((isuser && is_user(user_name, true)) || (isrole && is_role(user_name, true)))) + if ((isuser && is_database_principal(user_oid, true) != BBF_USER) || + (isrole && is_database_principal(user_oid, true) != BBF_ROLE)) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("Cannot alter the %s '%s', because it does not exist or you do not have permission.", isuser ? "user" : "role", stmt->role->rolename))); @@ -3245,7 +3246,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (strcmp(defel->defname, "default_schema") == 0) { if (is_member_of_db_owner || (isuser && is_member_of_db_accessadmin) || - user_name == GetUserId()) + user_oid == GetUserId()) { /* * members of db_owner can alter default schema for any role or user @@ -3262,7 +3263,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, else if (strcmp(defel->defname, "rename") == 0) { if (is_member_of_db_owner || (isuser && is_member_of_db_accessadmin && - !has_privs_of_role(user_name, db_owner))) + !has_privs_of_role(user_oid, db_owner))) { /* * members of db_owner can rename any role or user @@ -3387,8 +3388,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, int rolename_len = strlen(rolspec->rolename); if (!OidIsValid(role_oid) || /* Not found */ - (drop_user && !is_user(role_oid, true)) || /* Found but not a user in current logical db */ - (drop_role && !is_role(role_oid, true))) /* Found but not a role in current logical db */ + (drop_user && is_database_principal(role_oid, true) != BBF_USER) || /* Found but not a user in current logical db */ + (drop_role && is_database_principal(role_oid, true) != BBF_ROLE)) /* Found but not a role in current logical db */ { if (stmt->missing_ok) { @@ -3521,9 +3522,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (is_login(roleform->oid)) all_logins = true; - else if (is_user(roleform->oid, false)) + else if (is_database_principal(roleform->oid, false) == BBF_USER) all_users = true; - else if (is_role(roleform->oid, false)) + else if (is_database_principal(roleform->oid, false) == BBF_ROLE) all_roles = true; else other = true; @@ -3615,12 +3616,12 @@ bbf_ProcessUtility(PlannedStmt *pstmt, else orig_schema = "dbo"; } - else + else if (rolspec) { - owner_oid = rolspec ? get_rolespec_oid(rolspec, true) : InvalidOid; - if (OidIsValid(owner_oid) && OidIsValid(db_accessadmin) && !member_can_set_role(GetUserId(), owner_oid) && + owner_oid = get_rolespec_oid(rolspec, true); + if (OidIsValid(db_accessadmin) && !member_can_set_role(GetUserId(), owner_oid) && has_privs_of_role(GetUserId(), db_accessadmin) && - (is_user(owner_oid, true) || is_role(owner_oid, true))) + (is_database_principal(owner_oid, true))) { /* * db_accessadmin members can create schema for other users as owner diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index 0ccd14a5aa..b3cc7aa69c 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -2284,7 +2284,7 @@ sp_droprole(PG_FUNCTION_ARGS) role_oid = get_role_oid(physical_role_name, true); /* Check if the role does not exists */ - if (role_oid == InvalidOid || !is_role(role_oid, false)) + if (role_oid == InvalidOid || is_database_principal(role_oid, true) != BBF_ROLE) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot drop the role '%s', because it does not exist or you do not have permission.", rolname))); @@ -2437,7 +2437,7 @@ sp_addrolemember(PG_FUNCTION_ARGS) * Check if the user, group or role does not exists and given member * name is an role or user */ - if (member_oid == InvalidOid || (!is_role(member_oid, false) && !is_user(member_oid, false))) + if (member_oid == InvalidOid || is_database_principal(member_oid, true)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("User or role '%s' does not exist in this database.", membername))); @@ -2447,7 +2447,7 @@ sp_addrolemember(PG_FUNCTION_ARGS) role_oid = get_role_oid(physical_role_name, true); /* Check if the role does not exists and given role name is an role */ - if (role_oid == InvalidOid || !is_role(role_oid, false)) + if (role_oid == InvalidOid || is_database_principal(role_oid, true) != BBF_ROLE) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", rolname))); @@ -2599,7 +2599,7 @@ sp_droprolemember(PG_FUNCTION_ARGS) role_oid = get_role_oid(physical_name, true); /* Throw an error id the given role name doesn't exist or isn't a role */ - if (role_oid == InvalidOid || !is_role(role_oid, false)) + if (role_oid == InvalidOid || is_database_principal(role_oid, true) != BBF_ROLE) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", rolname))); @@ -2612,7 +2612,7 @@ sp_droprolemember(PG_FUNCTION_ARGS) * Throw an error id the given member name doesn't exist or isn't a * role or user */ - if (role_oid == InvalidOid || (!is_role(role_oid, false) && !is_user(role_oid, false))) + if (role_oid == InvalidOid || is_database_principal(role_oid, true)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot drop the principal '%s', because it does not exist or you do not have permission.", membername))); diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index c57535a5ce..51f564a471 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -290,7 +290,7 @@ drop_bbf_roles(ObjectAccessType access, { if (is_login(roleid)) drop_bbf_authid_login_ext(access, classId, roleid, subId, arg); - else if (is_user(roleid, false) || is_role(roleid, false)) + else if (is_database_principal(roleid, false)) drop_bbf_authid_user_ext(access, classId, roleid, subId, arg); } @@ -1763,7 +1763,7 @@ is_alter_role_stmt(GrantRoleStmt *stmt) Oid granted = get_role_oid(spec->rolename, true); /* Check if the granted role is an existing database role */ - if (granted == InvalidOid || !is_role(granted, false)) + if (granted == InvalidOid || is_database_principal(granted, true) != BBF_ROLE) return false; } @@ -1786,7 +1786,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) grantee = get_role_oid(grantee_name, false); /* Disallow ALTER ROLE if the grantee is not a db principal */ - if (!is_user(grantee, false) && !is_role(grantee, false)) + if (is_database_principal(grantee, false)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("%s is not a database user or a user-defined database role", @@ -1948,7 +1948,7 @@ is_rolemember(PG_FUNCTION_ARGS) * principal. Note that if given principal is current user, we'll always * have permissions. */ - if (!is_role(role_oid, false) || + if (is_database_principal(role_oid, false) != BBF_ROLE || ((principal_oid != cur_user_oid) && (!has_privs_of_role(cur_user_oid, role_oid) || !has_privs_of_role(cur_user_oid, principal_oid)))) From c26714acd993e48d078c1d2d8fb3f56e872a2548 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 26 Sep 2024 16:25:49 +0000 Subject: [PATCH 07/41] address comments Signed-off-by: Tanzeel Khan --- .../babelfishpg_tsql/sql/babelfishpg_tsql.sql | 14 ++-- .../babelfishpg_tsql--4.3.0--4.4.0.sql | 16 ++--- contrib/babelfishpg_tsql/src/catalog.c | 64 ++++++++++++++++--- contrib/babelfishpg_tsql/src/catalog.h | 1 + contrib/babelfishpg_tsql/src/dbcmds.c | 53 +++++++-------- contrib/babelfishpg_tsql/src/hooks.c | 2 +- contrib/babelfishpg_tsql/src/multidb.c | 16 +---- contrib/babelfishpg_tsql/src/pl_handler.c | 19 +++--- contrib/babelfishpg_tsql/src/pltsql.h | 10 +++ contrib/babelfishpg_tsql/src/rolecmds.c | 15 ++++- .../Test-sp_helpdbfixedrole-vu-verify.out | 3 +- 11 files changed, 138 insertions(+), 75 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql index e16f957311..d17cff00db 100644 --- a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql +++ b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql @@ -2347,16 +2347,16 @@ GRANT EXECUTE ON PROCEDURE sys.sp_helpsrvrolemember TO PUBLIC; CREATE OR REPLACE PROCEDURE sys.sp_helpdbfixedrole("@rolename" sys.SYSNAME = NULL) AS $$ BEGIN + DECLARE @rolenamelower sys.SYSNAME = LOWER(RTRIM(@rolename)) -- Returns a list of the fixed database roles. - IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_owner' + IF @rolenamelower IS NULL OR @rolenamelower IN ('db_owner', 'db_accessadmin') BEGIN - SELECT CAST('db_owner' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Owners' AS sys.nvarchar(70)) AS Description; + SELECT CAST(DbFixedRole as sys.SYSNAME), CAST(Description AS sys.nvarchar(70)) FROM ( + VALUES ('db_owner', 'DB Owners'), + ('db_accessadmin', 'DB Access Administrators')) x(DbFixedRole, Description) + WHERE @rolenamelower IS NULL OR @rolenamelower = DbFixedRole; END - ELSE IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_accessadmin' - BEGIN - SELECT CAST('db_accessadmin' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Access Administrators' AS sys.nvarchar(70)) AS Description; - END - ELSE IF LOWER(RTRIM(@rolename)) IN ( + ELSE IF @rolenamelower IN ( 'db_securityadmin','db_ddladmin', 'db_backupoperator', 'db_datareader', 'db_datawriter', 'db_denydatareader', 'db_denydatawriter') BEGIN diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index 5caeeb1dfa..5ce3cf286e 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -1977,18 +1977,16 @@ GRANT SELECT ON sys.database_principals TO PUBLIC; CREATE OR REPLACE PROCEDURE sys.sp_helpdbfixedrole("@rolename" sys.SYSNAME = NULL) AS $$ BEGIN + DECLARE @rolenamelower sys.SYSNAME = LOWER(RTRIM(@rolename)) -- Returns a list of the fixed database roles. - -- Only fixed role present in babelfish is db_owner. - IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_owner' + IF @rolenamelower IS NULL OR @rolenamelower IN ('db_owner', 'db_accessadmin') BEGIN - SELECT CAST('db_owner' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Owners' AS sys.nvarchar(70)) AS Description; + SELECT CAST(DbFixedRole as sys.SYSNAME), CAST(Description AS sys.nvarchar(70)) FROM ( + VALUES ('db_owner', 'DB Owners'), + ('db_accessadmin', 'DB Access Administrators')) x(DbFixedRole, Description) + WHERE @rolenamelower IS NULL OR @rolenamelower = DbFixedRole; END - ELSE IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = 'db_accessadmin' - BEGIN - SELECT CAST('db_accessadmin' AS sys.SYSNAME) AS DbFixedRole, CAST('DB Access Administrators' AS sys.nvarchar(70)) AS Description; - END - ELSE IF LOWER(RTRIM(@rolename)) IN ( - 'db_accessadmin','db_securityadmin','db_ddladmin', 'db_backupoperator', + ELSE IF @rolenamelower IN ( 'db_securityadmin','db_ddladmin', 'db_backupoperator', 'db_datareader', 'db_datawriter', 'db_denydatareader', 'db_denydatawriter') BEGIN diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 4c7c853c70..5774cf668c 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -857,7 +857,7 @@ get_authid_login_ext_idx_oid(void) const int is_database_principal(Oid role_oid, bool current_db_only) { - char result; + char result = 0; bool isnull; HeapTuple tuple; char *rolname; @@ -871,10 +871,6 @@ is_database_principal(Oid role_oid, bool current_db_only) BpChar type = ((Form_authid_user_ext) GETSTRUCT(tuple))->type; char *type_str = bpchar_to_cstring(&type); - result = (strcmp(type_str, "R") == 0) ? BBF_ROLE : BBF_USER; - - pfree(type_str); - if (current_db_only) { Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, @@ -886,14 +882,16 @@ is_database_principal(Oid role_oid, bool current_db_only) db_name_cstring = TextDatumGetCString(db_name); current_db_name = get_cur_db_name(); - /* db match failed */ - if (strcmp(db_name_cstring, current_db_name) != 0) - result = 0; + if (strcmp(db_name_cstring, current_db_name) == 0) + result = (strcmp(type_str, "R") == 0) ? BBF_ROLE : BBF_USER; pfree(db_name_cstring); pfree(current_db_name); } + else + result = (strcmp(type_str, "R") == 0) ? BBF_ROLE : BBF_USER; + pfree(type_str); ReleaseSysCache(tuple); } @@ -920,6 +918,53 @@ get_authid_user_ext_idx_oid(void) return bbf_authid_user_ext_idx_oid; } +/* + * Returns palloc'd original name given the physical name of the db principal + * Looks only in current bbf db when current_db_only is set to true + */ +char * +get_authid_user_ext_original_name(const char *physical_role_name, bool current_db_only) +{ + char* orig_username = NULL; + bool isnull; + HeapTuple tuple; + + Assert(physical_role_name != NULL && strlen(physical_role_name) != 0); + + tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(physical_role_name)); + + if (HeapTupleIsValid(tuple)) + { + Datum orig_username_datum = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_orig_username, &isnull); + Assert(!isnull); + + if (current_db_only) + { + Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_database_name, &isnull); + char *db_name_cstring; + char *current_db_name; + + Assert(!isnull); + db_name_cstring = TextDatumGetCString(db_name); + current_db_name = get_cur_db_name(); + + if (strcmp(db_name_cstring, current_db_name) == 0) + orig_username = TextDatumGetCString(orig_username_datum); + + pfree(db_name_cstring); + pfree(current_db_name); + } + else + orig_username = TextDatumGetCString(orig_username_datum); + + ReleaseSysCache(tuple); + } + + return orig_username; +} + char * get_authid_user_ext_physical_name(const char *db_name, const char *login) { @@ -962,6 +1007,7 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) Assert(!isnull); user_can_connect = DatumGetInt32(datum); + /* db_accessadmin members should always have connect permissions */ if (user_can_connect == 1 || (has_privs_of_role(get_role_oid(login, false), get_role_oid(db_accessadmin, false)))) { @@ -3167,7 +3213,7 @@ create_guest_role_for_db(const char *dbname) /* do this step */ ProcessUtility(wrapper, - "(CREATE LOGICAL DATABASE )", + CREATE_LOGICAL_DATABASE, false, PROCESS_UTILITY_SUBCOMMAND, NULL, diff --git a/contrib/babelfishpg_tsql/src/catalog.h b/contrib/babelfishpg_tsql/src/catalog.h index 40d5c282d8..48e74a85cc 100644 --- a/contrib/babelfishpg_tsql/src/catalog.h +++ b/contrib/babelfishpg_tsql/src/catalog.h @@ -151,6 +151,7 @@ extern Oid bbf_authid_user_ext_idx_oid; const int is_database_principal(Oid role_oid, bool current_db_only); extern Oid get_authid_user_ext_oid(void); extern Oid get_authid_user_ext_idx_oid(void); +extern char *get_authid_user_ext_original_name(const char *physical_role_name, bool current_db_only); extern char *get_authid_user_ext_physical_name(const char *db_name, const char *login_name); extern char *get_authid_user_ext_schema_name(const char *db_name, const char *user_name); extern List *get_authid_user_ext_db_users(const char *db_name); diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 204c61f78f..e77a453bc1 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -279,11 +279,11 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) expected_stmts += 2; } } - /* Drop db_accessadmin*/ + appendStringInfo(&query, "DROP OWNED BY dummy, dummy, dummy CASCADE; "); + + /* Then drop db_accessadmin, db_owner and dbo in that order */ appendStringInfo(&query, "REVOKE CREATE ON DATABASE dummy FROM dummy; "); appendStringInfo(&query, "DROP ROLE dummy; "); - /* Then drop db_owner and dbo in that order */ - appendStringInfo(&query, "DROP OWNED BY dummy, dummy CASCADE; "); appendStringInfo(&query, "REVOKE CREATE, CONNECT, TEMPORARY ON DATABASE dummy FROM dummy; "); appendStringInfo(&query, "DROP ROLE dummy; "); appendStringInfo(&query, "DROP ROLE dummy; "); @@ -317,14 +317,14 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) } } + stmt = parsetree_nth_stmt(stmt_list, i++); + update_DropOwnedStmt(stmt, list_make3(pstrdup(db_accessadmin), pstrdup(db_owner), pstrdup(dbo))); + stmt = parsetree_nth_stmt(stmt_list, i++); update_GrantStmt(stmt, get_database_name(MyDatabaseId), NULL, db_accessadmin, NULL); stmt = parsetree_nth_stmt(stmt_list, i++); update_DropRoleStmt(stmt, db_accessadmin); - stmt = parsetree_nth_stmt(stmt_list, i++); - update_DropOwnedStmt(stmt, list_make2(pstrdup(db_owner), pstrdup(dbo))); - stmt = parsetree_nth_stmt(stmt_list, i++); update_GrantStmt(stmt, get_database_name(MyDatabaseId), NULL, dbo, NULL); @@ -645,7 +645,7 @@ create_bbf_db_internal(ParseState *pstate, const char *dbname, List *options, co /* do this step */ ProcessUtility(wrapper, - "(CREATE LOGICAL DATABASE )", + CREATE_LOGICAL_DATABASE, false, PROCESS_UTILITY_SUBCOMMAND, NULL, @@ -1272,8 +1272,11 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) TableScanDesc scan; HeapTuple tuple; Form_sysdatabases bbf_db; + StringInfoData query; + List *parsetree_list; char *dbname; - int saved_nest_level = 0; + int pltsql_save_nestlevel; + int save_nestlevel; if (!creating_extension) ereport(ERROR, @@ -1281,7 +1284,8 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) errmsg("%s can only be called from an SQL script executed by CREATE/ALTER EXTENSION", "create_database_roles_for_all_dbs()"))); - saved_nest_level = pltsql_new_guc_nest_level(); + pltsql_save_nestlevel = pltsql_new_guc_nest_level(); + save_nestlevel = NewGUCNestLevel(); set_config_option("babelfishpg_tsql.sql_dialect", "tsql", GUC_CONTEXT_CONFIG, PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); @@ -1289,33 +1293,30 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) GUC_CONTEXT_CONFIG, PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); + initStringInfo(&query); + + appendStringInfo(&query, "CREATE ROLE dummy ROLE dummy; "); + appendStringInfo(&query, "GRANT CREATE ON DATABASE dummy TO dummy; "); + + parsetree_list = raw_parser(query.data, RAW_PARSE_DEFAULT); + sysdatabase_rel = table_open(sysdatabases_oid, RowExclusiveLock); scan = table_beginscan_catalog(sysdatabase_rel, 0, NULL); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { - StringInfoData query; - List *parsetree_list; Node *stmt; + Oid save_userid; + int save_sec_context; + int i = 0; const char *db_owner; const char *db_accessadmin; - const char *old_createrole_self_grant = GetConfigOption("createrole_self_grant", false, true); - int i = 0; - int save_sec_context = 0; - Oid save_userid = InvalidOid; bbf_db = (Form_sysdatabases) GETSTRUCT(tuple); dbname = text_to_cstring(&(bbf_db->name)); db_owner = get_db_owner_name(dbname); db_accessadmin = get_db_accessadmin_role_name(dbname); - initStringInfo(&query); - - appendStringInfo(&query, "CREATE ROLE dummy ROLE dummy; "); - appendStringInfo(&query, "GRANT CREATE ON DATABASE dummy TO dummy; "); - - parsetree_list = raw_parser(query.data, RAW_PARSE_DEFAULT); - stmt = parsetree_nth_stmt(parsetree_list, i++); update_CreateRoleStmt(stmt, db_accessadmin, db_owner, NULL); @@ -1351,7 +1352,7 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) wrapper->stmt_location = 0; ProcessUtility(wrapper, - "(CREATE LOGICAL DATABASE )", + CREATE_FIXED_DB_ROLES, false, PROCESS_UTILITY_SUBCOMMAND, NULL, @@ -1364,16 +1365,16 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) } PG_FINALLY(); { - SetConfigOption("createrole_self_grant", old_createrole_self_grant, PGC_USERSET, PGC_S_OVERRIDE); SetUserIdAndSecContext(save_userid, save_sec_context); } PG_END_TRY(); - pfree(query.data); pfree(dbname); } - pltsql_revert_guc(saved_nest_level); + pfree(query.data); + AtEOXact_GUC(false, save_nestlevel); + pltsql_revert_guc(pltsql_save_nestlevel); table_endscan(scan); table_close(sysdatabase_rel, RowExclusiveLock); diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 54ad1ec59f..bb14edebdd 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -3198,7 +3198,7 @@ pltsql_store_view_definition(const char *queryString, ObjectAddress address) return; /* Skip if it is for sysdatabases while creating logical database */ - if (strcmp("(CREATE LOGICAL DATABASE )", queryString) == 0) + if (strcmp(CREATE_LOGICAL_DATABASE, queryString) == 0) return; /* Fetch the object details from Relation */ diff --git a/contrib/babelfishpg_tsql/src/multidb.c b/contrib/babelfishpg_tsql/src/multidb.c index 7ad0c379be..e211bafd9d 100644 --- a/contrib/babelfishpg_tsql/src/multidb.c +++ b/contrib/babelfishpg_tsql/src/multidb.c @@ -249,17 +249,6 @@ rewrite_object_refs(Node *stmt) errmsg("Dropping members to db_owner is not currently supported " "in Babelfish"))); } - else if (strcmp(role_name, DB_ACCESSADMIN) == 0) - { - if (has_privs_of_role(GetUserId(), get_role_oid(get_db_owner_name(db_name), false))) - { - /* only members of db_owner can alter drop members to fixed db roles */ - } - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", role_name))); - } /* * Try to get physical granted role name, see if it's an @@ -1433,8 +1422,9 @@ get_db_accessadmin_role_name(const char *dbname) { char *name = palloc0(MAX_BBF_NAMEDATALEND); - if (get_migration_mode() == SINGLE_DB && strcmp(dbname, "master") != 0 - && strcmp(dbname, "tempdb") != 0 && strcmp(dbname, "msdb") != 0) + Assert(dbname != NULL && strlen(dbname) != 0); + + if (get_migration_mode() == SINGLE_DB && !IS_BBF_BUILT_IN_DB(dbname)) snprintf(name, MAX_BBF_NAMEDATALEND, "%s", DB_ACCESSADMIN); else snprintf(name, MAX_BBF_NAMEDATALEND, "%s_%s", dbname, DB_ACCESSADMIN); diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index d0c0d62a1b..25bc0016c5 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -2616,7 +2616,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } case T_CreateRoleStmt: { - if (sql_dialect == SQL_DIALECT_TSQL && strcmp(queryString, "(CREATE LOGICAL DATABASE )") != 0) + if (sql_dialect == SQL_DIALECT_TSQL && strcmp(queryString, CREATE_LOGICAL_DATABASE) != 0 && + strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { CreateRoleStmt *stmt = (CreateRoleStmt *) parsetree; List *login_options = NIL; @@ -3604,11 +3605,10 @@ bbf_ProcessUtility(PlannedStmt *pstmt, GrantStmt *stmt; PlannedStmt *wrapper; RoleSpec *rolspec = create_schema->authrole; - Oid owner_oid = InvalidOid; - Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(get_cur_db_name()), true); + Oid owner_oid; bool alter_owner = false; - if (strcmp(queryString, "(CREATE LOGICAL DATABASE )") == 0 + if (strcmp(queryString, CREATE_LOGICAL_DATABASE) == 0 && context == PROCESS_UTILITY_SUBCOMMAND) { if (pstmt->stmt_len == 19) @@ -3616,8 +3616,10 @@ bbf_ProcessUtility(PlannedStmt *pstmt, else orig_schema = "dbo"; } - else if (rolspec) + else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { + Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(get_cur_db_name()), false); + owner_oid = get_rolespec_oid(rolspec, true); if (OidIsValid(db_accessadmin) && !member_can_set_role(GetUserId(), owner_oid) && has_privs_of_role(GetUserId(), db_accessadmin) && @@ -3691,7 +3693,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } /* Grant ALL schema privileges to the user.*/ - if (rolspec && strcmp(queryString, "(CREATE LOGICAL DATABASE )") != 0) + if (rolspec && strcmp(queryString, CREATE_LOGICAL_DATABASE) != 0) { int i; for (i = 0; i < NUMBER_OF_PERMISSIONS; i++) @@ -3773,7 +3775,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } } case T_GrantRoleStmt: - if (sql_dialect == SQL_DIALECT_TSQL && strcmp(queryString, "(CREATE LOGICAL DATABASE )") != 0) + if (sql_dialect == SQL_DIALECT_TSQL && strcmp(queryString, CREATE_LOGICAL_DATABASE) != 0 && + strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { GrantRoleStmt *grant_role = (GrantRoleStmt *) parsetree; Oid save_userid; @@ -4101,7 +4104,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, Assert(list_length(grant->objects) == 1); if (grant->objtype == OBJECT_SCHEMA) break; - else if (grant->objtype == OBJECT_TABLE && strcmp("(CREATE LOGICAL DATABASE )", queryString) != 0) + else if (grant->objtype == OBJECT_TABLE && strcmp(CREATE_LOGICAL_DATABASE, queryString) != 0) { /* * Ignore GRANT statements that are executed implicitly as a part of diff --git a/contrib/babelfishpg_tsql/src/pltsql.h b/contrib/babelfishpg_tsql/src/pltsql.h index 6efb1e8c53..a7b676e3cc 100644 --- a/contrib/babelfishpg_tsql/src/pltsql.h +++ b/contrib/babelfishpg_tsql/src/pltsql.h @@ -1979,6 +1979,16 @@ extern int insert_bulk_kilobytes_per_batch; extern bool insert_bulk_keep_nulls; extern bool insert_bulk_check_constraints; + +/* BBF SUBCOMMANDS QUERY STRING */ +#define CREATE_LOGICAL_DATABASE "(CREATE LOGICAL DATABASE )" +#define CREATE_FIXED_DB_ROLES "(CREATE FIXED DATABASE ROLES )" + +#define IS_BBF_BUILT_IN_DB(dbname) \ + (strncmp(dbname, "master", 6) == 0 || \ + strncmp(dbname, "tempdb", 6) == 0 || \ + strncmp(dbname, "msdb", 4) == 0) + /********************************************************************** * Function declarations **********************************************************************/ diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 51f564a471..577d9f5ac5 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -1777,6 +1777,9 @@ check_alter_role_stmt(GrantRoleStmt *stmt) Oid grantee; const char *granted_name; const char *grantee_name; + const char *original_user_name; + const char *db_name = get_cur_db_name(); + const char *db_owner = get_db_owner_name(db_name); RoleSpec *granted_spec; RoleSpec *grantee_spec; @@ -1786,7 +1789,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) grantee = get_role_oid(grantee_name, false); /* Disallow ALTER ROLE if the grantee is not a db principal */ - if (is_database_principal(grantee, false)) + if (!is_database_principal(grantee, true)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("%s is not a database user or a user-defined database role", @@ -1797,6 +1800,16 @@ check_alter_role_stmt(GrantRoleStmt *stmt) granted_name = granted_spec->rolename; granted = get_role_oid(granted_name, false); + original_user_name = get_authid_user_ext_original_name(granted_name, true); + Assert(original_user_name); + + /* only members of db_owner can alter drop members to fixed db roles */ + if (strcmp(original_user_name, DB_ACCESSADMIN) == 0 && + !has_privs_of_role(GetUserId(), get_role_oid(db_owner, false))) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", original_user_name))); + /* * Disallow ALTER ROLE if 1. Current login doesn't have permission on the * granted role, or 2. The current user is trying to add/drop itself from diff --git a/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out b/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out index 9b79a1c785..9c8bfa4e6b 100644 --- a/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out +++ b/test/JDBC/expected/Test-sp_helpdbfixedrole-vu-verify.out @@ -1,6 +1,6 @@ INSERT INTO test_sp_helpdbfixedrole_tbl (DbFixedRole, Description) EXEC sp_helpdbfixedrole GO -~~ROW COUNT: 1~~ +~~ROW COUNT: 2~~ SELECT DbFixedRole, Description FROM test_sp_helpdbfixedrole_tbl @@ -8,6 +8,7 @@ GO ~~START~~ varchar#!#nvarchar db_owner#!#DB Owners +db_accessadmin#!#DB Access Administrators ~~END~~ From 2f141fa008dba107229363c3856fb8b179d5af21 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 26 Sep 2024 17:07:06 +0000 Subject: [PATCH 08/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql | 11 +++++------ .../sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql | 9 ++++----- contrib/babelfishpg_tsql/src/pl_handler.c | 12 ++++++------ contrib/babelfishpg_tsql/src/procedures.c | 4 ++-- contrib/babelfishpg_tsql/src/rolecmds.c | 2 +- .../Test-sp_helpdbfixedrole-dep-vu-verify.out | 5 +++-- 6 files changed, 21 insertions(+), 22 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql index d17cff00db..535072b138 100644 --- a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql +++ b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql @@ -2347,16 +2347,15 @@ GRANT EXECUTE ON PROCEDURE sys.sp_helpsrvrolemember TO PUBLIC; CREATE OR REPLACE PROCEDURE sys.sp_helpdbfixedrole("@rolename" sys.SYSNAME = NULL) AS $$ BEGIN - DECLARE @rolenamelower sys.SYSNAME = LOWER(RTRIM(@rolename)) -- Returns a list of the fixed database roles. - IF @rolenamelower IS NULL OR @rolenamelower IN ('db_owner', 'db_accessadmin') + IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) IN ('db_owner', 'db_accessadmin') BEGIN - SELECT CAST(DbFixedRole as sys.SYSNAME), CAST(Description AS sys.nvarchar(70)) FROM ( + SELECT CAST(DbFixedRole as sys.SYSNAME) AS DbFixedRole, CAST(Description AS sys.nvarchar(70)) AS Description FROM ( VALUES ('db_owner', 'DB Owners'), ('db_accessadmin', 'DB Access Administrators')) x(DbFixedRole, Description) - WHERE @rolenamelower IS NULL OR @rolenamelower = DbFixedRole; + WHERE LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = DbFixedRole; END - ELSE IF @rolenamelower IN ( + ELSE IF LOWER(RTRIM(@rolename)) IN ( 'db_securityadmin','db_ddladmin', 'db_backupoperator', 'db_datareader', 'db_datawriter', 'db_denydatareader', 'db_denydatawriter') BEGIN @@ -2365,7 +2364,7 @@ BEGIN WHERE 1=0; END ELSE - RAISERROR('''%s'' is not a known fixed role.', 16, 1, @rolename); + RAISERROR('''%s'' is not a known fixed role.', 16, 1, LOWER(RTRIM(@rolename))); END $$ LANGUAGE 'pltsql'; diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index 5ce3cf286e..95161cec8e 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -1977,16 +1977,15 @@ GRANT SELECT ON sys.database_principals TO PUBLIC; CREATE OR REPLACE PROCEDURE sys.sp_helpdbfixedrole("@rolename" sys.SYSNAME = NULL) AS $$ BEGIN - DECLARE @rolenamelower sys.SYSNAME = LOWER(RTRIM(@rolename)) -- Returns a list of the fixed database roles. - IF @rolenamelower IS NULL OR @rolenamelower IN ('db_owner', 'db_accessadmin') + IF LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) IN ('db_owner', 'db_accessadmin') BEGIN - SELECT CAST(DbFixedRole as sys.SYSNAME), CAST(Description AS sys.nvarchar(70)) FROM ( + SELECT CAST(DbFixedRole as sys.SYSNAME) AS DbFixedRole, CAST(Description AS sys.nvarchar(70)) AS Description FROM ( VALUES ('db_owner', 'DB Owners'), ('db_accessadmin', 'DB Access Administrators')) x(DbFixedRole, Description) - WHERE @rolenamelower IS NULL OR @rolenamelower = DbFixedRole; + WHERE LOWER(RTRIM(@rolename)) IS NULL OR LOWER(RTRIM(@rolename)) = DbFixedRole; END - ELSE IF @rolenamelower IN ( + ELSE IF LOWER(RTRIM(@rolename)) IN ( 'db_securityadmin','db_ddladmin', 'db_backupoperator', 'db_datareader', 'db_datawriter', 'db_denydatareader', 'db_denydatawriter') BEGIN diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 25bc0016c5..783f81fd48 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3621,15 +3621,15 @@ bbf_ProcessUtility(PlannedStmt *pstmt, Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(get_cur_db_name()), false); owner_oid = get_rolespec_oid(rolspec, true); - if (OidIsValid(db_accessadmin) && !member_can_set_role(GetUserId(), owner_oid) && + /* + * db_accessadmin members can create schema with owner being any db principal + * If it does not have the pg permission then handle it here. We will set owner + * to current user and later alter schema owner using bbf_role_admin + */ + if (!member_can_set_role(GetUserId(), owner_oid) && has_privs_of_role(GetUserId(), db_accessadmin) && (is_database_principal(owner_oid, true))) { - /* - * db_accessadmin members can create schema for other users as owner - * but it does not actually have the required permission from PG - * perspective to do so, hence handle it this way. - */ create_schema->authrole = NULL; alter_owner = true; } diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index b3cc7aa69c..f8a6586206 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -2437,7 +2437,7 @@ sp_addrolemember(PG_FUNCTION_ARGS) * Check if the user, group or role does not exists and given member * name is an role or user */ - if (member_oid == InvalidOid || is_database_principal(member_oid, true)) + if (member_oid == InvalidOid || !is_database_principal(member_oid, true)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("User or role '%s' does not exist in this database.", membername))); @@ -2612,7 +2612,7 @@ sp_droprolemember(PG_FUNCTION_ARGS) * Throw an error id the given member name doesn't exist or isn't a * role or user */ - if (role_oid == InvalidOid || is_database_principal(role_oid, true)) + if (role_oid == InvalidOid || !is_database_principal(role_oid, true)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot drop the principal '%s', because it does not exist or you do not have permission.", membername))); diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 577d9f5ac5..c784083868 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -1803,7 +1803,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) original_user_name = get_authid_user_ext_original_name(granted_name, true); Assert(original_user_name); - /* only members of db_owner can alter drop members to fixed db roles */ + /* only members of db_owner can alter drop members of fixed db roles */ if (strcmp(original_user_name, DB_ACCESSADMIN) == 0 && !has_privs_of_role(GetUserId(), get_role_oid(db_owner, false))) ereport(ERROR, diff --git a/test/JDBC/expected/Test-sp_helpdbfixedrole-dep-vu-verify.out b/test/JDBC/expected/Test-sp_helpdbfixedrole-dep-vu-verify.out index a8ea04ef07..0d807bb979 100644 --- a/test/JDBC/expected/Test-sp_helpdbfixedrole-dep-vu-verify.out +++ b/test/JDBC/expected/Test-sp_helpdbfixedrole-dep-vu-verify.out @@ -3,6 +3,7 @@ GO ~~START~~ varchar#!#nvarchar db_owner#!#DB Owners +db_accessadmin#!#DB Access Administrators ~~END~~ @@ -18,7 +19,7 @@ SELECT dbo.test_sp_helpdbfixedrole_func() GO ~~START~~ int -1 +2 ~~END~~ @@ -26,7 +27,7 @@ SELECT * FROM test_sp_helpdbfixedrole_view GO ~~START~~ int -1 +2 ~~END~~ From ef055771fd58b0b5dd6a8a1bc70337d1974a2c88 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 26 Sep 2024 17:53:37 +0000 Subject: [PATCH 09/41] fix Signed-off-by: Tanzeel Khan --- .../babelfishpg_tsql/sql/babelfishpg_tsql.sql | 2 +- .../babelfishpg_tsql--4.3.0--4.4.0.sql | 112 ------------------ 2 files changed, 1 insertion(+), 113 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql index 535072b138..a1439f30af 100644 --- a/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql +++ b/contrib/babelfishpg_tsql/sql/babelfishpg_tsql.sql @@ -2364,7 +2364,7 @@ BEGIN WHERE 1=0; END ELSE - RAISERROR('''%s'' is not a known fixed role.', 16, 1, LOWER(RTRIM(@rolename))); + RAISERROR('''%s'' is not a known fixed role.', 16, 1, @rolename); END $$ LANGUAGE 'pltsql'; diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index 95161cec8e..cd9e23a772 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -1515,118 +1515,6 @@ BEGIN END; $$ LANGUAGE plpgsql STABLE; -CREATE OR REPLACE PROCEDURE sys.sp_helpuser("@name_in_db" sys.SYSNAME = NULL) AS -$$ -BEGIN - -- If security account is not specified, return info about all users - IF @name_in_db IS NULL - BEGIN - SELECT CAST(Ext1.orig_username AS SYS.SYSNAME) AS 'UserName', - CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN 'db_owner' - WHEN Ext2.orig_username IS NULL THEN 'public' - ELSE Ext2.orig_username END - AS SYS.SYSNAME) AS 'RoleName', - CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN Base4.rolname COLLATE database_default - ELSE LogExt.orig_loginname END - AS SYS.SYSNAME) AS 'LoginName', - CAST(LogExt.default_database_name AS SYS.SYSNAME) AS 'DefDBName', - CAST(Ext1.default_schema_name AS SYS.SYSNAME) AS 'DefSchemaName', - CAST(Base1.oid AS INT) AS 'UserID', - CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN CAST(Base4.oid AS INT) - WHEN Ext1.orig_username = 'guest' THEN CAST(0 AS INT) - ELSE CAST(Base3.oid AS INT) END - AS SYS.VARBINARY(85)) AS 'SID' - FROM sys.babelfish_authid_user_ext AS Ext1 - INNER JOIN pg_catalog.pg_roles AS Base1 ON Base1.rolname = Ext1.rolname - LEFT OUTER JOIN pg_catalog.pg_auth_members AS Authmbr ON Base1.oid = Authmbr.member - LEFT OUTER JOIN pg_catalog.pg_roles AS Base2 ON Base2.oid = Authmbr.roleid - LEFT OUTER JOIN sys.babelfish_authid_user_ext AS Ext2 ON Base2.rolname = Ext2.rolname - LEFT OUTER JOIN sys.babelfish_authid_login_ext As LogExt ON LogExt.rolname = Ext1.login_name - LEFT OUTER JOIN pg_catalog.pg_roles AS Base3 ON Base3.rolname = LogExt.rolname - LEFT OUTER JOIN sys.babelfish_sysdatabases AS Bsdb ON Bsdb.name = DB_NAME() - LEFT OUTER JOIN pg_catalog.pg_roles AS Base4 ON Base4.rolname = Bsdb.owner - WHERE Ext1.database_name = DB_NAME() - AND (Ext1.type != 'R' OR Ext1.type != 'A') - AND Ext1.orig_username != 'db_owner' - ORDER BY UserName, RoleName; - END - -- If the security account is the db fixed role - db_owner - ELSE IF @name_in_db = 'db_owner' - BEGIN - -- TODO: Need to change after we can add/drop members to/from db_owner - SELECT CAST('db_owner' AS SYS.SYSNAME) AS 'Role_name', - ROLE_ID('db_owner') AS 'Role_id', - CAST('dbo' AS SYS.SYSNAME) AS 'Users_in_role', - USER_ID('dbo') AS 'Userid'; - END - -- If the security account is a db role - ELSE IF EXISTS (SELECT 1 - FROM sys.babelfish_authid_user_ext - WHERE (orig_username = @name_in_db - OR pg_catalog.lower(orig_username) = pg_catalog.lower(@name_in_db)) - AND database_name = DB_NAME() - AND type = 'R') - BEGIN - SELECT CAST(Ext1.orig_username AS SYS.SYSNAME) AS 'Role_name', - CAST(Base1.oid AS INT) AS 'Role_id', - CAST(Ext2.orig_username AS SYS.SYSNAME) AS 'Users_in_role', - CAST(Base2.oid AS INT) AS 'Userid' - FROM sys.babelfish_authid_user_ext AS Ext2 - INNER JOIN pg_catalog.pg_roles AS Base2 ON Base2.rolname = Ext2.rolname - INNER JOIN pg_catalog.pg_auth_members AS Authmbr ON Base2.oid = Authmbr.member - LEFT OUTER JOIN pg_catalog.pg_roles AS Base1 ON Base1.oid = Authmbr.roleid - LEFT OUTER JOIN sys.babelfish_authid_user_ext AS Ext1 ON Base1.rolname = Ext1.rolname - WHERE Ext1.database_name = DB_NAME() - AND Ext2.database_name = DB_NAME() - AND Ext1.type = 'R' - AND Ext2.orig_username != 'db_owner' - AND (Ext1.orig_username = @name_in_db OR pg_catalog.lower(Ext1.orig_username) = pg_catalog.lower(@name_in_db)) - ORDER BY Role_name, Users_in_role; - END - -- If the security account is a user - ELSE IF EXISTS (SELECT 1 - FROM sys.babelfish_authid_user_ext - WHERE (orig_username = @name_in_db - OR pg_catalog.lower(orig_username) = pg_catalog.lower(@name_in_db)) - AND database_name = DB_NAME() - AND type != 'R') - BEGIN - SELECT DISTINCT CAST(Ext1.orig_username AS SYS.SYSNAME) AS 'UserName', - CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN 'db_owner' - WHEN Ext2.orig_username IS NULL THEN 'public' - ELSE Ext2.orig_username END - AS SYS.SYSNAME) AS 'RoleName', - CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN Base4.rolname COLLATE database_default - ELSE LogExt.orig_loginname END - AS SYS.SYSNAME) AS 'LoginName', - CAST(LogExt.default_database_name AS SYS.SYSNAME) AS 'DefDBName', - CAST(Ext1.default_schema_name AS SYS.SYSNAME) AS 'DefSchemaName', - CAST(Base1.oid AS INT) AS 'UserID', - CAST(CASE WHEN Ext1.orig_username = 'dbo' THEN CAST(Base4.oid AS INT) - WHEN Ext1.orig_username = 'guest' THEN CAST(0 AS INT) - ELSE CAST(Base3.oid AS INT) END - AS SYS.VARBINARY(85)) AS 'SID' - FROM sys.babelfish_authid_user_ext AS Ext1 - INNER JOIN pg_catalog.pg_roles AS Base1 ON Base1.rolname = Ext1.rolname - LEFT OUTER JOIN pg_catalog.pg_auth_members AS Authmbr ON Base1.oid = Authmbr.member - LEFT OUTER JOIN pg_catalog.pg_roles AS Base2 ON Base2.oid = Authmbr.roleid - LEFT OUTER JOIN sys.babelfish_authid_user_ext AS Ext2 ON Base2.rolname = Ext2.rolname - LEFT OUTER JOIN sys.babelfish_authid_login_ext As LogExt ON LogExt.rolname = Ext1.login_name - LEFT OUTER JOIN pg_catalog.pg_roles AS Base3 ON Base3.rolname = LogExt.rolname - LEFT OUTER JOIN sys.babelfish_sysdatabases AS Bsdb ON Bsdb.name = DB_NAME() - LEFT OUTER JOIN pg_catalog.pg_roles AS Base4 ON Base4.rolname = Bsdb.owner - WHERE Ext1.database_name = DB_NAME() - AND (Ext1.type != 'R' OR Ext1.type != 'A') - AND Ext1.orig_username != 'db_owner' - AND (Ext1.orig_username = @name_in_db OR pg_catalog.lower(Ext1.orig_username) = pg_catalog.lower(@name_in_db)) - ORDER BY UserName, RoleName; - END - -- If the security account is not valid - ELSE - RAISERROR ( 'The name supplied (%s) is not a user, role, or aliased login.', 16, 1, @name_in_db); -END; -$$ -LANGUAGE 'pltsql'; create or replace view sys.types As with RECURSIVE type_code_list as From f8263ada1fefe5ad3d962d3cef042673e6f669b5 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 26 Sep 2024 19:29:15 +0000 Subject: [PATCH 10/41] empty commit to rerun actions Signed-off-by: Tanzeel Khan From 5ccc553e1c7b020d24888c4da40cbfae4e016799 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 26 Sep 2024 20:21:52 +0000 Subject: [PATCH 11/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/dbcmds.c | 2 +- contrib/babelfishpg_tsql/src/pl_handler.c | 3 ++- contrib/babelfishpg_tsql/src/pltsql.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index e77a453bc1..12cfcbae1d 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -1163,7 +1163,7 @@ create_schema_if_not_exists(const uint16 dbid, wrapper->stmt_len = 0; ProcessUtility(wrapper, - query.data, + CREATE_GUEST_SCHEMAS_DURING_UPGRADE, false, PROCESS_UTILITY_SUBCOMMAND, NULL, diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 783f81fd48..66df5296e3 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3616,7 +3616,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, else orig_schema = "dbo"; } - else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) + else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0 && + strcmp(queryString, CREATE_GUEST_SCHEMAS_DURING_UPGRADE) != 0) { Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(get_cur_db_name()), false); diff --git a/contrib/babelfishpg_tsql/src/pltsql.h b/contrib/babelfishpg_tsql/src/pltsql.h index b9055f4591..cde0f19b73 100644 --- a/contrib/babelfishpg_tsql/src/pltsql.h +++ b/contrib/babelfishpg_tsql/src/pltsql.h @@ -1984,6 +1984,7 @@ extern bool insert_bulk_check_constraints; /* BBF SUBCOMMANDS QUERY STRING */ #define CREATE_LOGICAL_DATABASE "(CREATE LOGICAL DATABASE )" +#define CREATE_GUEST_SCHEMAS_DURING_UPGRADE "(CREATE GUEST SCHEMAS DURING UPGRADE )" #define CREATE_FIXED_DB_ROLES "(CREATE FIXED DATABASE ROLES )" #define IS_BBF_BUILT_IN_DB(dbname) \ From 2c6071d43ba65ba6c826125fb4bcf0d2b2c3ff6d Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 27 Sep 2024 05:41:15 +0000 Subject: [PATCH 12/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/pl_handler.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 66df5296e3..205e47b810 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3616,8 +3616,11 @@ bbf_ProcessUtility(PlannedStmt *pstmt, else orig_schema = "dbo"; } - else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0 && - strcmp(queryString, CREATE_GUEST_SCHEMAS_DURING_UPGRADE) != 0) + else if (strcmp(queryString, CREATE_GUEST_SCHEMAS_DURING_UPGRADE) == 0) + { + orig_schema = "guest"; + } + else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(get_cur_db_name()), false); From 8e236afdfc583a21c9f6a37a9d361b19fe40b7b8 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 27 Sep 2024 07:20:48 +0000 Subject: [PATCH 13/41] fix Signed-off-by: Tanzeel Khan From 262ab3b291390972ec3de25345e451c2f87e2bd0 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 27 Sep 2024 13:13:54 +0000 Subject: [PATCH 14/41] add test to upgrade Signed-off-by: Tanzeel Khan --- test/JDBC/upgrade/14_10/schedule | 2 +- test/JDBC/upgrade/14_11/schedule | 2 +- test/JDBC/upgrade/14_12/schedule | 2 +- test/JDBC/upgrade/14_13/schedule | 2 +- test/JDBC/upgrade/14_14/schedule | 2 +- test/JDBC/upgrade/14_3/schedule | 2 +- test/JDBC/upgrade/14_5/schedule | 2 +- test/JDBC/upgrade/14_6/schedule | 2 +- test/JDBC/upgrade/14_7/schedule | 2 +- test/JDBC/upgrade/14_8/schedule | 2 +- test/JDBC/upgrade/14_9/schedule | 2 +- test/JDBC/upgrade/15_1/schedule | 2 +- test/JDBC/upgrade/15_2/schedule | 2 +- test/JDBC/upgrade/15_3/schedule | 2 +- test/JDBC/upgrade/15_4/schedule | 2 +- test/JDBC/upgrade/15_5/schedule | 2 +- test/JDBC/upgrade/15_6/schedule | 2 +- test/JDBC/upgrade/15_7/schedule | 2 +- test/JDBC/upgrade/15_8/schedule | 2 +- test/JDBC/upgrade/15_9/schedule | 2 +- test/JDBC/upgrade/16_1/schedule | 2 +- test/JDBC/upgrade/16_2/schedule | 2 +- test/JDBC/upgrade/16_3/schedule | 2 +- test/JDBC/upgrade/16_4/schedule | 1 + test/JDBC/upgrade/latest/schedule | 2 +- test/JDBC/upgrade/singledb/schedule | 3 ++- 26 files changed, 27 insertions(+), 25 deletions(-) diff --git a/test/JDBC/upgrade/14_10/schedule b/test/JDBC/upgrade/14_10/schedule index beb43d8043..67a39cda67 100644 --- a/test/JDBC/upgrade/14_10/schedule +++ b/test/JDBC/upgrade/14_10/schedule @@ -462,4 +462,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_11/schedule b/test/JDBC/upgrade/14_11/schedule index c3e8018e36..ad14d344a3 100644 --- a/test/JDBC/upgrade/14_11/schedule +++ b/test/JDBC/upgrade/14_11/schedule @@ -460,4 +460,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_12/schedule b/test/JDBC/upgrade/14_12/schedule index 3a7f033ff2..67e735ddc8 100644 --- a/test/JDBC/upgrade/14_12/schedule +++ b/test/JDBC/upgrade/14_12/schedule @@ -461,4 +461,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_13/schedule b/test/JDBC/upgrade/14_13/schedule index b382cf58a9..1b9d7c0745 100644 --- a/test/JDBC/upgrade/14_13/schedule +++ b/test/JDBC/upgrade/14_13/schedule @@ -461,4 +461,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_14/schedule b/test/JDBC/upgrade/14_14/schedule index b382cf58a9..1b9d7c0745 100644 --- a/test/JDBC/upgrade/14_14/schedule +++ b/test/JDBC/upgrade/14_14/schedule @@ -461,4 +461,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_3/schedule b/test/JDBC/upgrade/14_3/schedule index 4022b96bac..8a1d6b3cdd 100644 --- a/test/JDBC/upgrade/14_3/schedule +++ b/test/JDBC/upgrade/14_3/schedule @@ -382,4 +382,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_5/schedule b/test/JDBC/upgrade/14_5/schedule index 7ee0776874..8e76f0e264 100644 --- a/test/JDBC/upgrade/14_5/schedule +++ b/test/JDBC/upgrade/14_5/schedule @@ -393,4 +393,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_6/schedule b/test/JDBC/upgrade/14_6/schedule index ef7e3736b2..434a96d130 100644 --- a/test/JDBC/upgrade/14_6/schedule +++ b/test/JDBC/upgrade/14_6/schedule @@ -430,4 +430,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_7/schedule b/test/JDBC/upgrade/14_7/schedule index b12f17b421..6d81b4fcaa 100644 --- a/test/JDBC/upgrade/14_7/schedule +++ b/test/JDBC/upgrade/14_7/schedule @@ -452,4 +452,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_8/schedule b/test/JDBC/upgrade/14_8/schedule index 7be63b7d01..67a671af35 100644 --- a/test/JDBC/upgrade/14_8/schedule +++ b/test/JDBC/upgrade/14_8/schedule @@ -454,4 +454,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/14_9/schedule b/test/JDBC/upgrade/14_9/schedule index 16572c3e0f..68f0e5f32b 100644 --- a/test/JDBC/upgrade/14_9/schedule +++ b/test/JDBC/upgrade/14_9/schedule @@ -457,4 +457,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_1/schedule b/test/JDBC/upgrade/15_1/schedule index 8503cbdbb7..319822ec5b 100644 --- a/test/JDBC/upgrade/15_1/schedule +++ b/test/JDBC/upgrade/15_1/schedule @@ -430,4 +430,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_2/schedule b/test/JDBC/upgrade/15_2/schedule index 9d4a234e17..80324d35ec 100644 --- a/test/JDBC/upgrade/15_2/schedule +++ b/test/JDBC/upgrade/15_2/schedule @@ -465,4 +465,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_3/schedule b/test/JDBC/upgrade/15_3/schedule index 38ab04cc37..96c61701eb 100644 --- a/test/JDBC/upgrade/15_3/schedule +++ b/test/JDBC/upgrade/15_3/schedule @@ -484,4 +484,4 @@ string_agg-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_4/schedule b/test/JDBC/upgrade/15_4/schedule index b0fd286ccd..47088b7ebb 100644 --- a/test/JDBC/upgrade/15_4/schedule +++ b/test/JDBC/upgrade/15_4/schedule @@ -497,4 +497,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_5/schedule b/test/JDBC/upgrade/15_5/schedule index 7969757b3f..a97e9c5a97 100644 --- a/test/JDBC/upgrade/15_5/schedule +++ b/test/JDBC/upgrade/15_5/schedule @@ -528,4 +528,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_6/schedule b/test/JDBC/upgrade/15_6/schedule index 92cb04ef93..5c54d33950 100644 --- a/test/JDBC/upgrade/15_6/schedule +++ b/test/JDBC/upgrade/15_6/schedule @@ -544,4 +544,4 @@ getdate-before-15_9-or-16_5 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_7/schedule b/test/JDBC/upgrade/15_7/schedule index ef41d3ad22..9db922b9d0 100644 --- a/test/JDBC/upgrade/15_7/schedule +++ b/test/JDBC/upgrade/15_7/schedule @@ -551,5 +551,5 @@ replicate-before-15_8-or-16_4 space binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_8/schedule b/test/JDBC/upgrade/15_8/schedule index 2c3a41e440..49cd875e91 100644 --- a/test/JDBC/upgrade/15_8/schedule +++ b/test/JDBC/upgrade/15_8/schedule @@ -542,4 +542,4 @@ replace alter-procedure-15_8-or-16_4 binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/15_9/schedule b/test/JDBC/upgrade/15_9/schedule index 53920cf5c5..d79753919d 100644 --- a/test/JDBC/upgrade/15_9/schedule +++ b/test/JDBC/upgrade/15_9/schedule @@ -543,4 +543,4 @@ binary-datatype-operators SELECT_INTO_TEST cast-varchar-to-time BABEL-5119 - +db_accessadmin diff --git a/test/JDBC/upgrade/16_1/schedule b/test/JDBC/upgrade/16_1/schedule index af72bac629..f7db676e87 100644 --- a/test/JDBC/upgrade/16_1/schedule +++ b/test/JDBC/upgrade/16_1/schedule @@ -537,4 +537,4 @@ space replace-before-15_8-or-16_4 binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/16_2/schedule b/test/JDBC/upgrade/16_2/schedule index 426f5e369a..e9e97405a4 100644 --- a/test/JDBC/upgrade/16_2/schedule +++ b/test/JDBC/upgrade/16_2/schedule @@ -552,4 +552,4 @@ space replace-before-15_8-or-16_4 binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/16_3/schedule b/test/JDBC/upgrade/16_3/schedule index 84c9a3d6ac..650e8ed209 100644 --- a/test/JDBC/upgrade/16_3/schedule +++ b/test/JDBC/upgrade/16_3/schedule @@ -555,4 +555,4 @@ space replace-before-15_8-or-16_4 binary-datatype-operators cast-varchar-to-time - +db_accessadmin diff --git a/test/JDBC/upgrade/16_4/schedule b/test/JDBC/upgrade/16_4/schedule index a3ea167892..e19e2dac5d 100644 --- a/test/JDBC/upgrade/16_4/schedule +++ b/test/JDBC/upgrade/16_4/schedule @@ -567,3 +567,4 @@ space binary-datatype-operators cast-varchar-to-time BABEL-5119 +db_accessadmin diff --git a/test/JDBC/upgrade/latest/schedule b/test/JDBC/upgrade/latest/schedule index 1c0825603e..fba914e823 100644 --- a/test/JDBC/upgrade/latest/schedule +++ b/test/JDBC/upgrade/latest/schedule @@ -572,4 +572,4 @@ cast-varchar-to-time test_db_collation BABEL-5119 BABEL-5129 - +db_accessadmin diff --git a/test/JDBC/upgrade/singledb/schedule b/test/JDBC/upgrade/singledb/schedule index 55ab635341..ff70ad0bf6 100644 --- a/test/JDBC/upgrade/singledb/schedule +++ b/test/JDBC/upgrade/singledb/schedule @@ -1 +1,2 @@ -TestInt \ No newline at end of file +TestInt +db_accessadmin \ No newline at end of file From 3377700424a23ec9e8393c0ac7968bee10a66203 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 27 Sep 2024 13:24:22 +0000 Subject: [PATCH 15/41] add test to upgrade Signed-off-by: Tanzeel Khan --- test/JDBC/upgrade/13_9/schedule | 1 + 1 file changed, 1 insertion(+) diff --git a/test/JDBC/upgrade/13_9/schedule b/test/JDBC/upgrade/13_9/schedule index 458e9fcd19..e7919c74c3 100644 --- a/test/JDBC/upgrade/13_9/schedule +++ b/test/JDBC/upgrade/13_9/schedule @@ -355,3 +355,4 @@ string_agg-before-14_5 space binary-datatype-operators replace-before-15_8-or-16_4 +db_accessadmin From 7b373b1215baecab0e23d6f7c594062da34c4082 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 3 Oct 2024 19:35:47 +0000 Subject: [PATCH 16/41] fix tests Signed-off-by: Tanzeel Khan --- test/JDBC/expected/BABEL-5119-vu-verify.out | 1 + .../expected/db_accessadmin-vu-cleanup.out | 6 + .../expected/db_accessadmin-vu-prepare.out | 19 ++ .../expected/db_accessadmin-vu-verify.out | 259 +++++++++++++++--- .../single_db/db_accessadmin-vu-verify.out | 259 +++++++++++++++--- test/JDBC/input/db_accessadmin-vu-cleanup.mix | 8 +- test/JDBC/input/db_accessadmin-vu-prepare.mix | 19 ++ test/JDBC/input/db_accessadmin-vu-verify.mix | 111 ++++++-- test/JDBC/upgrade/13_9/schedule | 1 - test/JDBC/upgrade/singledb/schedule | 1 - 10 files changed, 571 insertions(+), 113 deletions(-) diff --git a/test/JDBC/expected/BABEL-5119-vu-verify.out b/test/JDBC/expected/BABEL-5119-vu-verify.out index 5e2083bb83..f3d4bf2619 100644 --- a/test/JDBC/expected/BABEL-5119-vu-verify.out +++ b/test/JDBC/expected/BABEL-5119-vu-verify.out @@ -758,6 +758,7 @@ SELECT u.orig_username, SUBSTRING(a.datacl, strpos(a.datacl, '='), strpos(a.data GO ~~START~~ nvarchar#!#varchar +db_accessadmin#!#=C dbo#!#=CTc ~~END~~ diff --git a/test/JDBC/expected/db_accessadmin-vu-cleanup.out b/test/JDBC/expected/db_accessadmin-vu-cleanup.out index ec399a0ba3..942fbd4d9d 100644 --- a/test/JDBC/expected/db_accessadmin-vu-cleanup.out +++ b/test/JDBC/expected/db_accessadmin-vu-cleanup.out @@ -23,3 +23,9 @@ DROP PROC babel_5136_p1 GO DROP FUNCTION f1 GO + +-- psql +DROP ROLE r1; +GO +DROP PROCEDURE run_sql_migration_mode_safe +GO diff --git a/test/JDBC/expected/db_accessadmin-vu-prepare.out b/test/JDBC/expected/db_accessadmin-vu-prepare.out index f88da3019a..28ccd98266 100644 --- a/test/JDBC/expected/db_accessadmin-vu-prepare.out +++ b/test/JDBC/expected/db_accessadmin-vu-prepare.out @@ -33,3 +33,22 @@ GO CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END GO +-- psql + +-- CREATE HELPER PROCEDURE TO EXECUTE SQL FROM PSQL ENDPOINT INDDEPENDANT OF migration_mode +CREATE OR REPLACE PROCEDURE run_sql_migration_mode_safe(sql_string TEXT, rolname TEXT, dbname TEXT) +LANGUAGE plpgsql +AS $$ +DECLARE + new_rolname TEXT := rolname; +BEGIN + IF current_setting('babelfishpg_tsql.migration_mode') = 'multi-db' THEN + new_rolname := CONCAT(dbname, '_', rolname); + END IF; + EXECUTE format(sql_string, new_rolname); +END; +$$; +GO + +CREATE ROLE r1; +GO diff --git a/test/JDBC/expected/db_accessadmin-vu-verify.out b/test/JDBC/expected/db_accessadmin-vu-verify.out index 5765883a1d..e61f4d8900 100644 --- a/test/JDBC/expected/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/db_accessadmin-vu-verify.out @@ -22,6 +22,13 @@ CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l GO ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user GO +-- Cannot add login as member of db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_l1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: role "babel_5136_babel_5136_l1" does not exist)~~ + -- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO @@ -40,26 +47,6 @@ GO -- tsql user=babel_5136_db_accessadmin_l1 password=12345678 -- Check all allowed operations -USE master -GO - -SELECT current_user -GO -~~START~~ -varchar -babel_5136_user_master -~~END~~ - - --- should not be a member of db_accessadmin in master database -SELECT IS_ROLEMEMBER('db_accessadmin') -GO -~~START~~ -int -0 -~~END~~ - - USE babel_5136 GO @@ -80,14 +67,6 @@ int ~~END~~ --- db_accessadmin can not add/drop members to db_accessadmin -ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 -GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ - - -- CREATE DROP A NEW USER CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 GO @@ -100,16 +79,9 @@ GO CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 GO --- ALTER USER and THEN DROP IT +-- ALTER EXISTING USER and THEN DROP IT ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo GO --- NOT SUPPORTED CURRENTLY IN BABELFISH -ALTER USER babel_5136_u1 WITH DEFAULT_LANGUAGE = English -GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: syntax error at or near "DEFAULT_LANGUAGE")~~ - ALTER USER babel_5136_u1 WITH NAME = babel_5136_u1_new_name GO -- NOT SUPPORTED CURRENTLY IN BABELFISH @@ -119,14 +91,14 @@ GO ~~ERROR (Message: syntax error near '' at line 3 and character position 0)~~ --- db_accessadmin should not be able to ALTER LOGIN MAPPING -ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +DROP USER babel_5136_u1_new_name GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Current user does not have privileges to change login)~~ - -ALTER USER babel_5136_u1_new_name WITH NAME = babel_5136_u1 +CREATE USER babel_5136_u1_new_name FOR LOGIN babel_5136_l1 +GO +-- ALTER NEW USER and THEN DROP IT +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +ALTER USER babel_5136_u2 WITH NAME = babel_5136_u1 GO -- CREATE SCHEMA should be allowed db_accessadmin @@ -159,5 +131,204 @@ GO ~~ERROR (Message: Cannot drop the user 'dbo'.)~~ --- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 +DROP ROLE db_owner +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the role 'db_owner'.)~~ + +DROP ROLE db_accessadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the role 'db_accessadmin'.)~~ + +DROP USER guest +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: User 'guest' cannot be dropped, it can only be disabled. The user is already disabled in the current database.)~~ + + +-- db_accessadmin can not add/drop members to any other role +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +ALTER ROLE db_owner ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Adding members to db_owner is not currently supported in Babelfish)~~ + +ALTER ROLE babel_5136_r1 ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + + +-- should not be able to alter users login mapping or rename members of db_owner +ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current user does not have privileges to change login)~~ + +ALTER USER dbo WITH LOGIN = babel_5136_l3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the user dbo)~~ + +ALTER USER dbo WITH NAME = dbo_should_not_be_renamed +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the user dbo)~~ + +ALTER USER dbo WITH DEFAULT_SCHEMA = dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the user dbo)~~ + +GRANT CONNECT TO babel_5136_u1_new_name +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ +GRANT CONNECT TO dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ + +REVOKE CONNECT FROM babel_5136_u1_new_name +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ + +REVOKE CONNECT FROM dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ + + +-- NO OTHER DDLs SHOULD BE ALLOWED +CREATE TABLE babel_5136_t1 (id INT) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema babel_5136_dbo)~~ + +CREATE PROCEDURE babel_5136_p1 AS SELECT 1 +GO +~~ERROR (Code: 2714)~~ + +~~ERROR (Message: Function 'babel_5136_p1' already exists with the same name)~~ + +CREATE FUNCTION f1() RETURNS INT AS BEGIN RETURN 1 END +GO +~~ERROR (Code: 2714)~~ + +~~ERROR (Message: Function 'f1' already exists with the same name)~~ + +CREATE DATABASE new_database +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied to create database)~~ + + +-- In master database the current login should not have db_accessadmin privilege +-- Since db_accessadmin is database level role +USE master +GO + +SELECT current_user +GO +~~START~~ +varchar +babel_5136_user_master +~~END~~ + + +-- should not be a member of db_accessadmin in master database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +0 +~~END~~ + + +-- Should not be able to do any activity in master database +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: User does not have permission to perform this action.)~~ + +DROP USER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the user 'babel_5136_u1', because it does not exist or you do not have permission.)~~ + +DROP ROLE babel_5136_r1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the role 'babel_5136_r1', because it does not exist or you do not have permission.)~~ + +CREATE ROLE babel_5136_r2 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: User does not have permission to perform this action.)~~ + +CREATE TABLE babel_5136_t1 (id INT) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema master_dbo)~~ + +CREATE PROCEDURE babel_5136_p2 AS SELECT 1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema master_dbo)~~ + +CREATE FUNCTION babel_5136_f2() RETURNS INT AS BEGIN RETURN 1 END +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema master_dbo)~~ + +CREATE SCHEMA babel_5136_s1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for database jdbc_testdb)~~ + +CREATE SCHEMA babel_5136_s1 AUTHORIZATION babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for database jdbc_testdb)~~ + +CREATE DATABASE new_database +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied to create database)~~ + + + +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 diff --git a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out index 7e7cc39530..d36f898c8f 100644 --- a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out @@ -22,6 +22,13 @@ CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l GO ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user GO +-- Cannot add login as member of db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_l1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: role "babel_5136_babel_5136_l1" does not exist)~~ + -- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO @@ -40,26 +47,6 @@ GO -- tsql user=babel_5136_db_accessadmin_l1 password=12345678 -- Check all allowed operations -USE master -GO - -SELECT current_user -GO -~~START~~ -varchar -babel_5136_user_master -~~END~~ - - --- should not be a member of db_accessadmin in master database -SELECT IS_ROLEMEMBER('db_accessadmin') -GO -~~START~~ -int -0 -~~END~~ - - USE babel_5136 GO @@ -80,14 +67,6 @@ int ~~END~~ --- db_accessadmin can not add/drop members to db_accessadmin -ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 -GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ - - -- CREATE DROP A NEW USER CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 GO @@ -100,16 +79,9 @@ GO CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 GO --- ALTER USER and THEN DROP IT +-- ALTER EXISTING USER and THEN DROP IT ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo GO --- NOT SUPPORTED CURRENTLY IN BABELFISH -ALTER USER babel_5136_u1 WITH DEFAULT_LANGUAGE = English -GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: syntax error at or near "DEFAULT_LANGUAGE")~~ - ALTER USER babel_5136_u1 WITH NAME = babel_5136_u1_new_name GO -- NOT SUPPORTED CURRENTLY IN BABELFISH @@ -119,14 +91,14 @@ GO ~~ERROR (Message: syntax error near '' at line 3 and character position 0)~~ --- db_accessadmin should not be able to ALTER LOGIN MAPPING -ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +DROP USER babel_5136_u1_new_name GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Current user does not have privileges to change login)~~ - -ALTER USER babel_5136_u1_new_name WITH NAME = babel_5136_u1 +CREATE USER babel_5136_u1_new_name FOR LOGIN babel_5136_l1 +GO +-- ALTER NEW USER and THEN DROP IT +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +ALTER USER babel_5136_u2 WITH NAME = babel_5136_u1 GO -- CREATE SCHEMA should be allowed db_accessadmin @@ -159,5 +131,204 @@ GO ~~ERROR (Message: Cannot drop the user 'dbo'.)~~ --- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 +DROP ROLE db_owner +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the role 'db_owner'.)~~ + +DROP ROLE db_accessadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the role 'db_accessadmin'.)~~ + +DROP USER guest +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: User 'guest' cannot be dropped, it can only be disabled. The user is already disabled in the current database.)~~ + + +-- db_accessadmin can not add/drop members to any other role +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +ALTER ROLE db_owner ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Adding members to db_owner is not currently supported in Babelfish)~~ + +ALTER ROLE babel_5136_r1 ADD MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + + +-- should not be able to alter users login mapping or rename members of db_owner +ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current user does not have privileges to change login)~~ + +ALTER USER dbo WITH LOGIN = babel_5136_l3 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the user dbo)~~ + +ALTER USER dbo WITH NAME = dbo_should_not_be_renamed +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the user dbo)~~ + +ALTER USER dbo WITH DEFAULT_SCHEMA = dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the user dbo)~~ + +GRANT CONNECT TO babel_5136_u1_new_name +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ +GRANT CONNECT TO dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ + +REVOKE CONNECT FROM babel_5136_u1_new_name +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ + +REVOKE CONNECT FROM dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Grantor does not have GRANT permission.)~~ + + +-- NO OTHER DDLs SHOULD BE ALLOWED +CREATE TABLE babel_5136_t1 (id INT) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema dbo)~~ + +CREATE PROCEDURE babel_5136_p1 AS SELECT 1 +GO +~~ERROR (Code: 2714)~~ + +~~ERROR (Message: Function 'babel_5136_p1' already exists with the same name)~~ + +CREATE FUNCTION f1() RETURNS INT AS BEGIN RETURN 1 END +GO +~~ERROR (Code: 2714)~~ + +~~ERROR (Message: Function 'f1' already exists with the same name)~~ + +CREATE DATABASE new_database +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Only one user database allowed under single-db mode. User database "babel_5136" already exists)~~ + + +-- In master database the current login should not have db_accessadmin privilege +-- Since db_accessadmin is database level role +USE master +GO + +SELECT current_user +GO +~~START~~ +varchar +babel_5136_user_master +~~END~~ + + +-- should not be a member of db_accessadmin in master database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +0 +~~END~~ + + +-- Should not be able to do any activity in master database +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: User does not have permission to perform this action.)~~ + +DROP USER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the user 'babel_5136_u1', because it does not exist or you do not have permission.)~~ + +DROP ROLE babel_5136_r1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot drop the role 'babel_5136_r1', because it does not exist or you do not have permission.)~~ + +CREATE ROLE babel_5136_r2 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: User does not have permission to perform this action.)~~ + +CREATE TABLE babel_5136_t1 (id INT) +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema master_dbo)~~ + +CREATE PROCEDURE babel_5136_p2 AS SELECT 1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema master_dbo)~~ + +CREATE FUNCTION babel_5136_f2() RETURNS INT AS BEGIN RETURN 1 END +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema master_dbo)~~ + +CREATE SCHEMA babel_5136_s1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for database jdbc_testdb)~~ + +CREATE SCHEMA babel_5136_s1 AUTHORIZATION babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for database jdbc_testdb)~~ + +CREATE DATABASE new_database +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Only one user database allowed under single-db mode. User database "babel_5136" already exists)~~ + + + +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 diff --git a/test/JDBC/input/db_accessadmin-vu-cleanup.mix b/test/JDBC/input/db_accessadmin-vu-cleanup.mix index b94e7ff925..942fbd4d9d 100644 --- a/test/JDBC/input/db_accessadmin-vu-cleanup.mix +++ b/test/JDBC/input/db_accessadmin-vu-cleanup.mix @@ -22,4 +22,10 @@ GO DROP PROC babel_5136_p1 GO DROP FUNCTION f1 -GO \ No newline at end of file +GO + +-- psql +DROP ROLE r1; +GO +DROP PROCEDURE run_sql_migration_mode_safe +GO diff --git a/test/JDBC/input/db_accessadmin-vu-prepare.mix b/test/JDBC/input/db_accessadmin-vu-prepare.mix index f88da3019a..dbce921b26 100644 --- a/test/JDBC/input/db_accessadmin-vu-prepare.mix +++ b/test/JDBC/input/db_accessadmin-vu-prepare.mix @@ -33,3 +33,22 @@ GO CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END GO +-- psql +-- CREATE HELPER PROCEDURE TO EXECUTE SQL FROM PSQL ENDPOINT INDDEPENDANT OF migration_mode +CREATE OR REPLACE PROCEDURE run_sql_migration_mode_safe(sql_string TEXT, rolname TEXT, dbname TEXT) +LANGUAGE plpgsql +AS $$ +DECLARE + new_rolname TEXT := rolname; +BEGIN + IF current_setting('babelfishpg_tsql.migration_mode') = 'multi-db' THEN + new_rolname := CONCAT(dbname, '_', rolname); + END IF; + + EXECUTE format(sql_string, new_rolname); +END; +$$; +GO + +CREATE ROLE r1; +GO diff --git a/test/JDBC/input/db_accessadmin-vu-verify.mix b/test/JDBC/input/db_accessadmin-vu-verify.mix index eb9f82c39a..740440183a 100644 --- a/test/JDBC/input/db_accessadmin-vu-verify.mix +++ b/test/JDBC/input/db_accessadmin-vu-verify.mix @@ -23,6 +23,9 @@ CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l GO ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user GO +-- Cannot add login as member of db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_l1 +GO -- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO @@ -37,16 +40,6 @@ GO -- Check all allowed operations -- tsql user=babel_5136_db_accessadmin_l1 password=12345678 -USE master -GO - -SELECT current_user -GO - --- should not be a member of db_accessadmin in master database -SELECT IS_ROLEMEMBER('db_accessadmin') -GO - USE babel_5136 GO @@ -57,10 +50,6 @@ GO SELECT IS_ROLEMEMBER('db_accessadmin') GO --- db_accessadmin can not add/drop members to db_accessadmin -ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 -GO - -- CREATE DROP A NEW USER CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 GO @@ -73,21 +62,22 @@ GO CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 GO --- ALTER USER and THEN DROP IT +-- ALTER EXISTING USER and THEN DROP IT ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo GO --- NOT SUPPORTED CURRENTLY IN BABELFISH -ALTER USER babel_5136_u1 WITH DEFAULT_LANGUAGE = English -GO ALTER USER babel_5136_u1 WITH NAME = babel_5136_u1_new_name GO -- NOT SUPPORTED CURRENTLY IN BABELFISH ALTER USER babel_5136_u1_new_name WITH PASSWORD = 'shouldfail' GO --- db_accessadmin should not be able to ALTER LOGIN MAPPING -ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +DROP USER babel_5136_u1_new_name GO -ALTER USER babel_5136_u1_new_name WITH NAME = babel_5136_u1 +CREATE USER babel_5136_u1_new_name FOR LOGIN babel_5136_l1 +GO +-- ALTER NEW USER and THEN DROP IT +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +ALTER USER babel_5136_u2 WITH NAME = babel_5136_u1 GO -- CREATE SCHEMA should be allowed db_accessadmin @@ -108,5 +98,82 @@ GO -- Should be restricted DROP USER dbo GO --- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 +DROP ROLE db_owner +GO +DROP ROLE db_accessadmin +GO +DROP USER guest +GO +-- db_accessadmin can not add/drop members to any other role +ALTER ROLE db_accessadmin ADD MEMBER babel_5136_u1 +GO +ALTER ROLE db_owner ADD MEMBER babel_5136_u1 +GO +ALTER ROLE babel_5136_r1 ADD MEMBER babel_5136_u1 +GO + +-- should not be able to alter users login mapping or rename members of db_owner +ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 +GO +ALTER USER dbo WITH LOGIN = babel_5136_l3 +GO +ALTER USER dbo WITH NAME = dbo_should_not_be_renamed +GO +ALTER USER dbo WITH DEFAULT_SCHEMA = dbo +GO +GRANT CONNECT TO babel_5136_u1_new_name +GO +GRANT CONNECT TO dbo +GO +REVOKE CONNECT FROM babel_5136_u1_new_name +GO +REVOKE CONNECT FROM dbo +GO + +-- NO OTHER DDLs SHOULD BE ALLOWED +CREATE TABLE babel_5136_t1 (id INT) +GO +CREATE PROCEDURE babel_5136_p1 AS SELECT 1 +GO +CREATE FUNCTION f1() RETURNS INT AS BEGIN RETURN 1 END +GO +CREATE DATABASE new_database +GO + +-- In master database the current login should not have db_accessadmin privilege +-- Since db_accessadmin is database level role +USE master +GO + +SELECT current_user +GO + +-- should not be a member of db_accessadmin in master database +SELECT IS_ROLEMEMBER('db_accessadmin') +GO + +-- Should not be able to do any activity in master database +CREATE USER babel_5136_u2 FOR LOGIN babel_5136_l2 +GO +DROP USER babel_5136_u1 +GO +DROP ROLE babel_5136_r1 +GO +CREATE ROLE babel_5136_r2 +GO +CREATE TABLE babel_5136_t1 (id INT) +GO +CREATE PROCEDURE babel_5136_p2 AS SELECT 1 +GO +CREATE FUNCTION babel_5136_f2() RETURNS INT AS BEGIN RETURN 1 END +GO +CREATE SCHEMA babel_5136_s1 +GO +CREATE SCHEMA babel_5136_s1 AUTHORIZATION babel_5136_u1 +GO +CREATE DATABASE new_database +GO + + +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 diff --git a/test/JDBC/upgrade/13_9/schedule b/test/JDBC/upgrade/13_9/schedule index 35091c51c9..d27cbfe05b 100644 --- a/test/JDBC/upgrade/13_9/schedule +++ b/test/JDBC/upgrade/13_9/schedule @@ -357,5 +357,4 @@ concat_ws-before-15_9-or-16_5 space binary-datatype-operators replace-before-15_8-or-16_4 -db_accessadmin BABEL-CASE_EXPR-before-16_5-or-15_9 diff --git a/test/JDBC/upgrade/singledb/schedule b/test/JDBC/upgrade/singledb/schedule index ff70ad0bf6..b4bb4485a2 100644 --- a/test/JDBC/upgrade/singledb/schedule +++ b/test/JDBC/upgrade/singledb/schedule @@ -1,2 +1 @@ TestInt -db_accessadmin \ No newline at end of file From 2e2e2f2772f3bd06eb18f06698ef25869b7b4d6e Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 3 Oct 2024 20:14:00 +0000 Subject: [PATCH 17/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 9 +---- contrib/babelfishpg_tsql/src/catalog.h | 1 - contrib/babelfishpg_tsql/src/dbcmds.c | 6 +-- contrib/babelfishpg_tsql/src/multidb.c | 47 ++++++++++++++--------- contrib/babelfishpg_tsql/src/multidb.h | 2 + contrib/babelfishpg_tsql/src/pl_exec-2.c | 2 +- contrib/babelfishpg_tsql/src/pl_handler.c | 27 ++++--------- contrib/babelfishpg_tsql/src/pltsql.h | 10 +++++ contrib/babelfishpg_tsql/src/rolecmds.c | 3 +- 9 files changed, 54 insertions(+), 53 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 353019a53d..2b2e061ce9 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -998,7 +998,6 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) if (HeapTupleIsValid(tuple_user_ext)) { Datum datum; - char *db_accessadmin = get_db_accessadmin_role_name(db_name); bool user_can_connect; bool isnull; @@ -1009,7 +1008,7 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) /* db_accessadmin members should always have connect permissions */ if (user_can_connect == 1 || - (has_privs_of_role(get_role_oid(login, false), get_role_oid(db_accessadmin, false)))) + (has_privs_of_role(get_role_oid(login, false), get_db_accessadmin_oid(db_name, false)))) { datum = heap_getattr(tuple_user_ext, Anum_bbf_authid_user_ext_rolname, RelationGetDescr(bbf_authid_user_ext_rel), &isnull); @@ -1017,7 +1016,6 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) user_name = pstrdup(DatumGetCString(datum)); } - pfree(db_accessadmin); } table_endscan(scan); @@ -4977,10 +4975,7 @@ rename_tsql_db(char *old_db_name, char *new_db_name) char *old_role_name; char *new_role_name; - if (SINGLE_DB == get_migration_mode() && - ((strlen(role) == 3 && strncmp(role, "dbo", 3) == 0) || - (strlen(role) == 8 && strncmp(role, "db_owner", 8) == 0) || - (strlen(role) == 14 && strncmp(role, DB_ACCESSADMIN, 14) == 0))) + if (SINGLE_DB == get_migration_mode() && IS_FIXED_DB_PRINCIPAL(role)) continue; old_role_name = get_physical_user_name(old_db_name, role, true, true); diff --git a/contrib/babelfishpg_tsql/src/catalog.h b/contrib/babelfishpg_tsql/src/catalog.h index f84a8d6815..b71251773f 100644 --- a/contrib/babelfishpg_tsql/src/catalog.h +++ b/contrib/babelfishpg_tsql/src/catalog.h @@ -315,7 +315,6 @@ typedef FormData_bbf_function_ext *Form_bbf_function_ext; #define Anum_bbf_schema_perms_grantor 8 #define PUBLIC_ROLE_NAME "public" -#define DB_ACCESSADMIN "db_accessadmin" #define PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA "ALL" #define ALL_PERMISSIONS_ON_RELATION 47 /* last 6 bits as 101111 represents ALL privileges on a relation. */ #define ALL_PERMISSIONS_ON_FUNCTION 128 /* last 8 bits as 10000000 represents ALL privileges on a procedure/function. */ diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index cddbdd90d3..e466a28cf4 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -271,8 +271,7 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && - strcmp(user_name, db_accessadmin) != 0) + if (IS_FIXED_DB_PRINCIPAL(user_name)) { appendStringInfo(&query, "DROP OWNED BY dummy CASCADE; "); appendStringInfo(&query, "DROP ROLE dummy; "); @@ -306,8 +305,7 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && - strcmp(user_name, db_accessadmin) != 0) + if (!IS_FIXED_DB_PRINCIPAL(user_name)) { stmt = parsetree_nth_stmt(stmt_list, i++); update_DropOwnedStmt(stmt, list_make1(user_name)); diff --git a/contrib/babelfishpg_tsql/src/multidb.c b/contrib/babelfishpg_tsql/src/multidb.c index 57b0c473c2..6e3ded1de9 100644 --- a/contrib/babelfishpg_tsql/src/multidb.c +++ b/contrib/babelfishpg_tsql/src/multidb.c @@ -263,9 +263,7 @@ rewrite_object_refs(Node *stmt) principal_name = grantee->rolename; /* Forbidden the use of some special principals */ - if (strcmp(principal_name, "dbo") == 0 || - strcmp(principal_name, "db_owner") == 0 || - strcmp(principal_name, DB_ACCESSADMIN) == 0) + if (IS_FIXED_DB_PRINCIPAL(principal_name)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot use the special principal '%s'", principal_name))); @@ -388,10 +386,8 @@ rewrite_object_refs(Node *stmt) user_name = alter_role->role->rolename; /* TODO: allow ALTER ROLE db_owner */ - if (strcmp(user_name, "dbo") == 0 || - strcmp(user_name, "db_owner") == 0 || - strcmp(user_name, "guest") == 0 || - strcmp(user_name, DB_ACCESSADMIN) == 0) + if (IS_FIXED_DB_PRINCIPAL(user_name) || + strcmp(user_name, "guest") == 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot alter the user %s", user_name))); @@ -1312,13 +1308,9 @@ get_physical_user_name(char *db_name, char *user_name, bool suppress_db_error, b if (SINGLE_DB == get_migration_mode()) { /* check that db_name is not "master", "tempdb", or "msdb" */ - if ((strlen(db_name) != 6 || (strncmp(db_name, "master", 6) != 0)) && - (strlen(db_name) != 6 || (strncmp(db_name, "tempdb", 6) != 0)) && - (strlen(db_name) != 4 || (strncmp(db_name, "msdb", 4) != 0))) + if (IS_BBF_BUILT_IN_DB(db_name)) { - if (((strlen(user_name) == 3 && strncmp(user_name, "dbo", 3) == 0) || - (strlen(user_name) == 8 && strncmp(user_name, "db_owner", 8) == 0) || - (strlen(user_name) == 14 && strncmp(user_name, DB_ACCESSADMIN, 14) == 0)) + if (IS_FIXED_DB_PRINCIPAL(user_name) && (suppress_role_error || user_exists_for_db(db_name, new_user_name))) { return new_user_name; @@ -1357,8 +1349,7 @@ get_dbo_schema_name(const char *dbname) Assert(dbname != NULL); - if (SINGLE_DB == get_migration_mode() && 0 != strcmp(dbname, "master") - && 0 != strcmp(dbname, "tempdb") && 0 != strcmp(dbname, "msdb")) + if (SINGLE_DB == get_migration_mode() && !IS_BBF_BUILT_IN_DB(dbname)) { snprintf(name, MAX_BBF_NAMEDATALEND, "%s", "dbo"); } @@ -1377,8 +1368,7 @@ get_dbo_role_name_by_mode(const char *dbname, MigrationMode mode) Assert(dbname != NULL); - if (SINGLE_DB == mode && 0 != strcmp(dbname, "master") - && 0 != strcmp(dbname, "tempdb") && 0 != strcmp(dbname, "msdb")) + if (SINGLE_DB == mode && !IS_BBF_BUILT_IN_DB(dbname)) { snprintf(name, MAX_BBF_NAMEDATALEND, "%s", "dbo"); } @@ -1403,8 +1393,7 @@ get_db_owner_name_by_mode(const char *dbname, MigrationMode mode) Assert(dbname != NULL); - if (SINGLE_DB == mode && 0 != strcmp(dbname, "master") - && 0 != strcmp(dbname, "tempdb") && 0 != strcmp(dbname, "msdb")) + if (SINGLE_DB == mode && !IS_BBF_BUILT_IN_DB(dbname)) { snprintf(name, MAX_BBF_NAMEDATALEND, "%s", "db_owner"); } @@ -1422,6 +1411,16 @@ get_db_owner_name(const char *dbname) return get_db_owner_name_by_mode(dbname, get_migration_mode()); } +Oid +get_db_owner_oid(const char *dbname, bool missing_ok) +{ + char *db_owner_name = get_db_owner_name(dbname); + Oid db_owner_oid = get_role_oid(db_owner_name, missing_ok); + pfree(db_owner_name); + + return db_owner_oid; +} + char * get_guest_role_name(const char *dbname) { @@ -1454,6 +1453,16 @@ get_db_accessadmin_role_name(const char *dbname) return name; } +Oid +get_db_accessadmin_oid(const char *dbname, bool missing_ok) +{ + char *db_accessadmin_name = get_db_owner_name(dbname); + Oid db_accessadmin_oid = get_role_oid(db_accessadmin_name, missing_ok); + pfree(db_accessadmin_name); + + return db_accessadmin_oid; +} + char * get_guest_schema_name(const char *dbname) { diff --git a/contrib/babelfishpg_tsql/src/multidb.h b/contrib/babelfishpg_tsql/src/multidb.h index 16768d9e84..196ed8db76 100644 --- a/contrib/babelfishpg_tsql/src/multidb.h +++ b/contrib/babelfishpg_tsql/src/multidb.h @@ -25,7 +25,9 @@ extern char *get_dbo_role_name(const char *dbname); extern char *get_dbo_role_name_by_mode(const char *dbname, MigrationMode mode); extern char *get_db_owner_name(const char *dbname); extern char *get_db_owner_name_by_mode(const char *dbname, MigrationMode mode); +extern Oid get_db_owner_oid(const char *dbname, bool missing_ok); extern char *get_db_accessadmin_role_name(const char *dbname); +extern Oid get_db_accessadmin_oid(const char *dbname, bool missing_ok); extern char *get_guest_role_name(const char *dbname); extern char *get_guest_schema_name(const char *dbname); extern bool is_shared_schema(const char *name); diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index 2f07ad8632..b61af46e9e 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -3769,7 +3769,7 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) role_oid = get_role_oid(rolname, true); /* Special database roles should throw an error. */ - if (strcmp(grantee_name, "db_owner") == 0 || strcmp(grantee_name, DB_ACCESSADMIN) == 0) + if (IS_FIXED_DB_PRINCIPAL(grantee_name)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Cannot grant, deny or revoke permissions to or from special roles."))); diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index bb5407fe7f..c10a7d18e5 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -2927,11 +2927,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, else if (isuser || isrole) { char *current_db_name = get_cur_db_name(); - char *db_owner_name = get_db_owner_name(current_db_name); - char *db_accessadmin_role = get_db_accessadmin_role_name(current_db_name); - if (has_privs_of_role(GetUserId(), get_role_oid(db_owner_name, false)) || - (isuser && has_privs_of_role(GetUserId(), get_role_oid(db_accessadmin_role, false)))) + if (has_privs_of_role(GetUserId(), get_db_owner_oid(current_db_name, false)) || + (isuser && has_privs_of_role(GetUserId(), get_db_accessadmin_oid(current_db_name, false)))) { /* * members of db_owner can create roles and users @@ -2945,8 +2943,6 @@ bbf_ProcessUtility(PlannedStmt *pstmt, errmsg("User does not have permission to perform this action."))); } - pfree(db_owner_name); - pfree(db_accessadmin_role); pfree(current_db_name); } @@ -3224,8 +3220,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, bool is_member_of_db_accessadmin = false; int save_sec_context; Oid save_userid; - Oid db_owner = get_role_oid(get_db_owner_name(db_name), false); - Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(db_name), false); + Oid db_owner = get_db_owner_oid(db_name, false); + Oid db_accessadmin = get_db_accessadmin_oid(db_name, false); Oid user_oid = get_role_oid(stmt->role->rolename, false); /* db principal being altered should be a user or role in the current active logical database */ @@ -3380,12 +3376,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (db_name != NULL && strcmp(db_name, "") != 0) { - char *db_owner_name = get_db_owner_name(db_name); - char *db_accessadmin_name = get_db_accessadmin_role_name(db_name); - Oid db_owner = get_role_oid(db_owner_name, false); - Oid db_accessadmin = get_role_oid(db_accessadmin_name, false); - pfree(db_owner_name); - pfree(db_accessadmin_name); + Oid db_owner = get_db_owner_oid(db_name, false); + Oid db_accessadmin = get_db_accessadmin_oid(db_name, false); foreach(item, stmt->roles) { @@ -3393,7 +3385,6 @@ bbf_ProcessUtility(PlannedStmt *pstmt, char *user_name = get_physical_user_name(db_name, rolspec->rolename, false, true); const char *db_principal_type = drop_user ? "user" : "role"; int role_oid = get_role_oid(user_name, true); - int rolename_len = strlen(rolspec->rolename); if (!OidIsValid(role_oid) || /* Not found */ (drop_user && is_database_principal(role_oid, true) != BBF_USER) || /* Found but not a user in current logical db */ @@ -3411,9 +3402,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } /* If user is dbo or role is db_owner, restrict dropping */ - if ((drop_user && rolename_len == 3 && strncmp(rolspec->rolename, "dbo", 3) == 0) || - (drop_role && rolename_len == 8 && strncmp(rolspec->rolename, "db_owner", 8) == 0) || - (drop_role && rolename_len == 14 && strncmp(rolspec->rolename, DB_ACCESSADMIN, 14) == 0)) + if (IS_BBF_BUILT_IN_DB(rolspec->rolename)) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("Cannot drop the %s '%s'.", db_principal_type, rolspec->rolename))); @@ -3631,7 +3620,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { - Oid db_accessadmin = get_role_oid(get_db_accessadmin_role_name(get_cur_db_name()), false); + Oid db_accessadmin = get_db_accessadmin_oid(get_cur_db_name(), false); owner_oid = get_rolespec_oid(rolspec, true); /* diff --git a/contrib/babelfishpg_tsql/src/pltsql.h b/contrib/babelfishpg_tsql/src/pltsql.h index 5b2fe4f6fc..b16888cf22 100644 --- a/contrib/babelfishpg_tsql/src/pltsql.h +++ b/contrib/babelfishpg_tsql/src/pltsql.h @@ -1987,11 +1987,21 @@ extern bool insert_bulk_check_constraints; #define CREATE_GUEST_SCHEMAS_DURING_UPGRADE "(CREATE GUEST SCHEMAS DURING UPGRADE )" #define CREATE_FIXED_DB_ROLES "(CREATE FIXED DATABASE ROLES )" +/* FIXED DB PRINCIPALS */ +#define DBO "dbo" +#define DB_OWNER "db_owner" +#define DB_ACCESSADMIN "db_accessadmin" + #define IS_BBF_BUILT_IN_DB(dbname) \ (strncmp(dbname, "master", 6) == 0 || \ strncmp(dbname, "tempdb", 6) == 0 || \ strncmp(dbname, "msdb", 4) == 0) +#define IS_FIXED_DB_PRINCIPAL(rolname) \ + (strncmp(rolname, DBO, 3) == 0 || \ + strncmp(rolname, DB_OWNER, 8) == 0 || \ + strncmp(rolname, DB_ACCESSADMIN, 14) == 0) + /********************************************************************** * Function declarations **********************************************************************/ diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 1d5eb47d56..84ac23fc5c 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -1791,7 +1791,6 @@ check_alter_role_stmt(GrantRoleStmt *stmt) const char *grantee_name; const char *original_user_name; const char *db_name = get_cur_db_name(); - const char *db_owner = get_db_owner_name(db_name); RoleSpec *granted_spec; RoleSpec *grantee_spec; @@ -1817,7 +1816,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) /* only members of db_owner can alter drop members of fixed db roles */ if (strcmp(original_user_name, DB_ACCESSADMIN) == 0 && - !has_privs_of_role(GetUserId(), get_role_oid(db_owner, false))) + !has_privs_of_role(GetUserId(), get_db_owner_oid(db_name, false))) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", original_user_name))); From 502e58ffb528045b2809846beb68fef0ba822ae6 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 3 Oct 2024 20:35:57 +0000 Subject: [PATCH 18/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/dbcmds.c | 2 +- contrib/babelfishpg_tsql/src/multidb.c | 2 +- contrib/babelfishpg_tsql/src/pl_handler.c | 8 ++++---- contrib/babelfishpg_tsql/src/rolecmds.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index e466a28cf4..30dbadca31 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -271,7 +271,7 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (IS_FIXED_DB_PRINCIPAL(user_name)) + if (!IS_FIXED_DB_PRINCIPAL(user_name)) { appendStringInfo(&query, "DROP OWNED BY dummy CASCADE; "); appendStringInfo(&query, "DROP ROLE dummy; "); diff --git a/contrib/babelfishpg_tsql/src/multidb.c b/contrib/babelfishpg_tsql/src/multidb.c index 6e3ded1de9..d7cc205a91 100644 --- a/contrib/babelfishpg_tsql/src/multidb.c +++ b/contrib/babelfishpg_tsql/src/multidb.c @@ -1308,7 +1308,7 @@ get_physical_user_name(char *db_name, char *user_name, bool suppress_db_error, b if (SINGLE_DB == get_migration_mode()) { /* check that db_name is not "master", "tempdb", or "msdb" */ - if (IS_BBF_BUILT_IN_DB(db_name)) + if (!IS_BBF_BUILT_IN_DB(db_name)) { if (IS_FIXED_DB_PRINCIPAL(user_name) && (suppress_role_error || user_exists_for_db(db_name, new_user_name))) diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index c10a7d18e5..4397e04180 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3381,10 +3381,10 @@ bbf_ProcessUtility(PlannedStmt *pstmt, foreach(item, stmt->roles) { - RoleSpec *rolspec = lfirst(item); - char *user_name = get_physical_user_name(db_name, rolspec->rolename, false, true); - const char *db_principal_type = drop_user ? "user" : "role"; - int role_oid = get_role_oid(user_name, true); + RoleSpec *rolspec = lfirst(item); + char *user_name = get_physical_user_name(db_name, rolspec->rolename, false, true); + const char *db_principal_type = drop_user ? "user" : "role"; + int role_oid = get_role_oid(user_name, true); if (!OidIsValid(role_oid) || /* Not found */ (drop_user && is_database_principal(role_oid, true) != BBF_USER) || /* Found but not a user in current logical db */ diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 84ac23fc5c..643397bc58 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -1815,7 +1815,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) Assert(original_user_name); /* only members of db_owner can alter drop members of fixed db roles */ - if (strcmp(original_user_name, DB_ACCESSADMIN) == 0 && + if (IS_FIXED_DB_PRINCIPAL(original_user_name) && !has_privs_of_role(GetUserId(), get_db_owner_oid(db_name, false))) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), From fdb5831e779a41196f6f5907e8efef8a91bb4d9c Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 3 Oct 2024 20:55:21 +0000 Subject: [PATCH 19/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/dbcmds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 30dbadca31..c6e154ac70 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -271,7 +271,7 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (!IS_FIXED_DB_PRINCIPAL(user_name)) + if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0) { appendStringInfo(&query, "DROP OWNED BY dummy CASCADE; "); appendStringInfo(&query, "DROP ROLE dummy; "); @@ -305,7 +305,7 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (!IS_FIXED_DB_PRINCIPAL(user_name)) + if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0) { stmt = parsetree_nth_stmt(stmt_list, i++); update_DropOwnedStmt(stmt, list_make1(user_name)); From 4ef8ff2f9a1ad1f77c14a56f08931f765f6e95c3 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 3 Oct 2024 21:12:58 +0000 Subject: [PATCH 20/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/dbcmds.c | 6 ++++-- contrib/babelfishpg_tsql/src/pl_exec-2.c | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index c6e154ac70..49155f200a 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -271,7 +271,8 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0) + if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && + strcmp(user_name, db_accessadmin)) { appendStringInfo(&query, "DROP OWNED BY dummy CASCADE; "); appendStringInfo(&query, "DROP ROLE dummy; "); @@ -305,7 +306,8 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) { char *user_name = (char *) lfirst(elem); - if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0) + if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && + strcmp(user_name, db_accessadmin)) { stmt = parsetree_nth_stmt(stmt_list, i++); update_DropOwnedStmt(stmt, list_make1(user_name)); diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index b61af46e9e..9e2db15e75 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -3028,8 +3028,7 @@ exec_stmt_grantdb(PLtsql_execstate *estate, PLtsql_stmt_grantdb *stmt) { char *grantee_name = (char *) lfirst(lc); - if (strcmp(grantee_name, "dbo") == 0 || strcmp(grantee_name, "db_owner") == 0 - || strcmp(grantee_name, login) == 0) + if (IS_FIXED_DB_PRINCIPAL(grantee_name) || strcmp(grantee_name, login) == 0) ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Cannot grant or revoke permissions to dbo, db_owner or yourself."))); From 5361565560bebbb9e6032f2c7542fc86902d25cc Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 3 Oct 2024 21:53:37 +0000 Subject: [PATCH 21/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/dbcmds.c | 4 ++-- contrib/babelfishpg_tsql/src/multidb.c | 2 +- contrib/babelfishpg_tsql/src/pl_handler.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 49155f200a..85e5b3edd7 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -272,7 +272,7 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) char *user_name = (char *) lfirst(elem); if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && - strcmp(user_name, db_accessadmin)) + strcmp(user_name, db_accessadmin) != 0) { appendStringInfo(&query, "DROP OWNED BY dummy CASCADE; "); appendStringInfo(&query, "DROP ROLE dummy; "); @@ -307,7 +307,7 @@ gen_dropdb_subcmds(const char *dbname, List *db_users) char *user_name = (char *) lfirst(elem); if (strcmp(user_name, db_owner) != 0 && strcmp(user_name, dbo) != 0 && - strcmp(user_name, db_accessadmin)) + strcmp(user_name, db_accessadmin) != 0) { stmt = parsetree_nth_stmt(stmt_list, i++); update_DropOwnedStmt(stmt, list_make1(user_name)); diff --git a/contrib/babelfishpg_tsql/src/multidb.c b/contrib/babelfishpg_tsql/src/multidb.c index d7cc205a91..d3d8dab289 100644 --- a/contrib/babelfishpg_tsql/src/multidb.c +++ b/contrib/babelfishpg_tsql/src/multidb.c @@ -1456,7 +1456,7 @@ get_db_accessadmin_role_name(const char *dbname) Oid get_db_accessadmin_oid(const char *dbname, bool missing_ok) { - char *db_accessadmin_name = get_db_owner_name(dbname); + char *db_accessadmin_name = get_db_accessadmin_role_name(dbname); Oid db_accessadmin_oid = get_role_oid(db_accessadmin_name, missing_ok); pfree(db_accessadmin_name); diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 4397e04180..63146a9324 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3402,7 +3402,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } /* If user is dbo or role is db_owner, restrict dropping */ - if (IS_BBF_BUILT_IN_DB(rolspec->rolename)) + if (IS_FIXED_DB_PRINCIPAL(rolspec->rolename)) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("Cannot drop the %s '%s'.", db_principal_type, rolspec->rolename))); From e7e32fd4b2dc33247c99c7e37ed617c507197393 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 4 Oct 2024 06:05:14 +0000 Subject: [PATCH 22/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/pl_exec-2.c | 13 +++++++------ test/JDBC/expected/db_accessadmin-vu-cleanup.out | 2 -- test/JDBC/expected/db_accessadmin-vu-prepare.out | 3 --- test/JDBC/input/db_accessadmin-vu-cleanup.mix | 2 -- test/JDBC/input/db_accessadmin-vu-prepare.mix | 3 --- 5 files changed, 7 insertions(+), 16 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index 9e2db15e75..e11dadf049 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -3028,7 +3028,8 @@ exec_stmt_grantdb(PLtsql_execstate *estate, PLtsql_stmt_grantdb *stmt) { char *grantee_name = (char *) lfirst(lc); - if (IS_FIXED_DB_PRINCIPAL(grantee_name) || strcmp(grantee_name, login) == 0) + if (strcmp(grantee_name, "dbo") == 0 || strcmp(grantee_name, "db_owner") == 0 + || strcmp(grantee_name, login) == 0) ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Cannot grant or revoke permissions to dbo, db_owner or yourself."))); @@ -3767,11 +3768,6 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) rolname = pstrdup(PUBLIC_ROLE_NAME); role_oid = get_role_oid(rolname, true); - /* Special database roles should throw an error. */ - if (IS_FIXED_DB_PRINCIPAL(grantee_name)) - ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("Cannot grant, deny or revoke permissions to or from special roles."))); - if (!is_public && !OidIsValid(role_oid)) { /* sys or information_schema roles should throw an error. */ @@ -3790,6 +3786,11 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself."))); + /* Special database roles should throw an error. */ + if (IS_FIXED_DB_PRINCIPAL(grantee_name)) + ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("Cannot grant, deny or revoke permissions to or from special roles."))); + /* * If the login is not the db owner or the login is not the member of * sysadmin or login is not the schema owner, then it doesn't have the permission to GRANT/REVOKE. diff --git a/test/JDBC/expected/db_accessadmin-vu-cleanup.out b/test/JDBC/expected/db_accessadmin-vu-cleanup.out index 942fbd4d9d..d3b80891bf 100644 --- a/test/JDBC/expected/db_accessadmin-vu-cleanup.out +++ b/test/JDBC/expected/db_accessadmin-vu-cleanup.out @@ -25,7 +25,5 @@ DROP FUNCTION f1 GO -- psql -DROP ROLE r1; -GO DROP PROCEDURE run_sql_migration_mode_safe GO diff --git a/test/JDBC/expected/db_accessadmin-vu-prepare.out b/test/JDBC/expected/db_accessadmin-vu-prepare.out index 28ccd98266..d1284c931e 100644 --- a/test/JDBC/expected/db_accessadmin-vu-prepare.out +++ b/test/JDBC/expected/db_accessadmin-vu-prepare.out @@ -49,6 +49,3 @@ BEGIN END; $$; GO - -CREATE ROLE r1; -GO diff --git a/test/JDBC/input/db_accessadmin-vu-cleanup.mix b/test/JDBC/input/db_accessadmin-vu-cleanup.mix index 942fbd4d9d..d3b80891bf 100644 --- a/test/JDBC/input/db_accessadmin-vu-cleanup.mix +++ b/test/JDBC/input/db_accessadmin-vu-cleanup.mix @@ -25,7 +25,5 @@ DROP FUNCTION f1 GO -- psql -DROP ROLE r1; -GO DROP PROCEDURE run_sql_migration_mode_safe GO diff --git a/test/JDBC/input/db_accessadmin-vu-prepare.mix b/test/JDBC/input/db_accessadmin-vu-prepare.mix index dbce921b26..21ee2e68f6 100644 --- a/test/JDBC/input/db_accessadmin-vu-prepare.mix +++ b/test/JDBC/input/db_accessadmin-vu-prepare.mix @@ -49,6 +49,3 @@ BEGIN END; $$; GO - -CREATE ROLE r1; -GO From ff34749e622cfca6e66caec035c8ca3504dc8a36 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 4 Oct 2024 07:18:13 +0000 Subject: [PATCH 23/41] empty Signed-off-by: Tanzeel Khan From 64732170998c9b3e6fed4a92829a7041bb9986da Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 4 Oct 2024 11:01:52 +0000 Subject: [PATCH 24/41] see dump restore actions logs Signed-off-by: Tanzeel Khan --- .github/workflows/pg_dump-restore-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pg_dump-restore-test.yml b/.github/workflows/pg_dump-restore-test.yml index 0807cf3dc0..79526d5231 100644 --- a/.github/workflows/pg_dump-restore-test.yml +++ b/.github/workflows/pg_dump-restore-test.yml @@ -132,7 +132,7 @@ jobs: done - name: Upload Logs - if: always() && (steps.setup-base-version.outcome == 'failure' || steps.dump-restore-and-test.outcome == 'failure') + if: always() uses: actions/upload-artifact@v4 with: name: dump-restore-logs-${{ matrix.upgrade-path.dump_method }}-${{ matrix.upgrade-path.title }}-${{ matrix.upgrade-path.dump_format }}-${{ matrix.upgrade-path.type }} From c3949e0b0cfa3353baba86167b4f54f473b48e7b Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 4 Oct 2024 13:31:36 +0000 Subject: [PATCH 25/41] ssh into github actions host Signed-off-by: Tanzeel Khan --- .github/workflows/pg_dump-restore-test.yml | 7 +++++++ test/JDBC/expected/db_accessadmin-vu-cleanup.out | 4 ---- test/JDBC/expected/db_accessadmin-vu-prepare.out | 16 ---------------- test/JDBC/input/db_accessadmin-vu-cleanup.mix | 4 ---- test/JDBC/input/db_accessadmin-vu-prepare.mix | 16 ---------------- 5 files changed, 7 insertions(+), 40 deletions(-) diff --git a/.github/workflows/pg_dump-restore-test.yml b/.github/workflows/pg_dump-restore-test.yml index 79526d5231..0780211144 100644 --- a/.github/workflows/pg_dump-restore-test.yml +++ b/.github/workflows/pg_dump-restore-test.yml @@ -41,6 +41,13 @@ jobs: if: always() run: sudo snap install yq + - name: Setup upterm session + if: always() + uses: lhotari/action-upterm@v1 + timeout-minutes: 120 + with: + limit-access-to-actor: true + - name: Read Base Version and Final Version id: read-base-and-final-version if: always() && steps.install-yq.outcome == 'success' diff --git a/test/JDBC/expected/db_accessadmin-vu-cleanup.out b/test/JDBC/expected/db_accessadmin-vu-cleanup.out index d3b80891bf..ec399a0ba3 100644 --- a/test/JDBC/expected/db_accessadmin-vu-cleanup.out +++ b/test/JDBC/expected/db_accessadmin-vu-cleanup.out @@ -23,7 +23,3 @@ DROP PROC babel_5136_p1 GO DROP FUNCTION f1 GO - --- psql -DROP PROCEDURE run_sql_migration_mode_safe -GO diff --git a/test/JDBC/expected/db_accessadmin-vu-prepare.out b/test/JDBC/expected/db_accessadmin-vu-prepare.out index d1284c931e..f88da3019a 100644 --- a/test/JDBC/expected/db_accessadmin-vu-prepare.out +++ b/test/JDBC/expected/db_accessadmin-vu-prepare.out @@ -33,19 +33,3 @@ GO CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END GO --- psql - --- CREATE HELPER PROCEDURE TO EXECUTE SQL FROM PSQL ENDPOINT INDDEPENDANT OF migration_mode -CREATE OR REPLACE PROCEDURE run_sql_migration_mode_safe(sql_string TEXT, rolname TEXT, dbname TEXT) -LANGUAGE plpgsql -AS $$ -DECLARE - new_rolname TEXT := rolname; -BEGIN - IF current_setting('babelfishpg_tsql.migration_mode') = 'multi-db' THEN - new_rolname := CONCAT(dbname, '_', rolname); - END IF; - EXECUTE format(sql_string, new_rolname); -END; -$$; -GO diff --git a/test/JDBC/input/db_accessadmin-vu-cleanup.mix b/test/JDBC/input/db_accessadmin-vu-cleanup.mix index d3b80891bf..ec399a0ba3 100644 --- a/test/JDBC/input/db_accessadmin-vu-cleanup.mix +++ b/test/JDBC/input/db_accessadmin-vu-cleanup.mix @@ -23,7 +23,3 @@ DROP PROC babel_5136_p1 GO DROP FUNCTION f1 GO - --- psql -DROP PROCEDURE run_sql_migration_mode_safe -GO diff --git a/test/JDBC/input/db_accessadmin-vu-prepare.mix b/test/JDBC/input/db_accessadmin-vu-prepare.mix index 21ee2e68f6..f88da3019a 100644 --- a/test/JDBC/input/db_accessadmin-vu-prepare.mix +++ b/test/JDBC/input/db_accessadmin-vu-prepare.mix @@ -33,19 +33,3 @@ GO CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END GO --- psql --- CREATE HELPER PROCEDURE TO EXECUTE SQL FROM PSQL ENDPOINT INDDEPENDANT OF migration_mode -CREATE OR REPLACE PROCEDURE run_sql_migration_mode_safe(sql_string TEXT, rolname TEXT, dbname TEXT) -LANGUAGE plpgsql -AS $$ -DECLARE - new_rolname TEXT := rolname; -BEGIN - IF current_setting('babelfishpg_tsql.migration_mode') = 'multi-db' THEN - new_rolname := CONCAT(dbname, '_', rolname); - END IF; - - EXECUTE format(sql_string, new_rolname); -END; -$$; -GO From 55a8d9086621443d8f5415f46fdd5d959ee7c403 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 4 Oct 2024 14:08:24 +0000 Subject: [PATCH 26/41] remove temp changes and reset password for login in verify file Signed-off-by: Tanzeel Khan --- .github/workflows/pg_dump-restore-test.yml | 9 +-------- test/JDBC/expected/db_accessadmin-vu-verify.out | 3 +++ .../JDBC/expected/single_db/db_accessadmin-vu-verify.out | 3 +++ test/JDBC/input/db_accessadmin-vu-verify.mix | 3 +++ 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pg_dump-restore-test.yml b/.github/workflows/pg_dump-restore-test.yml index 0780211144..0807cf3dc0 100644 --- a/.github/workflows/pg_dump-restore-test.yml +++ b/.github/workflows/pg_dump-restore-test.yml @@ -41,13 +41,6 @@ jobs: if: always() run: sudo snap install yq - - name: Setup upterm session - if: always() - uses: lhotari/action-upterm@v1 - timeout-minutes: 120 - with: - limit-access-to-actor: true - - name: Read Base Version and Final Version id: read-base-and-final-version if: always() && steps.install-yq.outcome == 'success' @@ -139,7 +132,7 @@ jobs: done - name: Upload Logs - if: always() + if: always() && (steps.setup-base-version.outcome == 'failure' || steps.dump-restore-and-test.outcome == 'failure') uses: actions/upload-artifact@v4 with: name: dump-restore-logs-${{ matrix.upgrade-path.dump_method }}-${{ matrix.upgrade-path.title }}-${{ matrix.upgrade-path.dump_format }}-${{ matrix.upgrade-path.type }} diff --git a/test/JDBC/expected/db_accessadmin-vu-verify.out b/test/JDBC/expected/db_accessadmin-vu-verify.out index e61f4d8900..4283728a00 100644 --- a/test/JDBC/expected/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/db_accessadmin-vu-verify.out @@ -9,6 +9,9 @@ -- ALTER default_schema for any user in database -- RENAME user execpt for members of db_owner -- CREATE SCHEMA for self or other users in database +-- bbf dump does not dump password so reset the password +ALTER LOGIN babel_5136_l1 WITH PASSWORD = '12345678' +GO -- CREATE A USER WITH db_accessadmin privilege in DATABASE babel_5136 USE master GO diff --git a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out index d36f898c8f..be88745296 100644 --- a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out @@ -9,6 +9,9 @@ -- ALTER default_schema for any user in database -- RENAME user execpt for members of db_owner -- CREATE SCHEMA for self or other users in database +-- bbf dump does not dump password so reset the password +ALTER LOGIN babel_5136_l1 WITH PASSWORD = '12345678' +GO -- CREATE A USER WITH db_accessadmin privilege in DATABASE babel_5136 USE master GO diff --git a/test/JDBC/input/db_accessadmin-vu-verify.mix b/test/JDBC/input/db_accessadmin-vu-verify.mix index 740440183a..b18b07a516 100644 --- a/test/JDBC/input/db_accessadmin-vu-verify.mix +++ b/test/JDBC/input/db_accessadmin-vu-verify.mix @@ -10,6 +10,9 @@ -- CREATE SCHEMA for self or other users in database -- tsql +-- bbf dump does not dump password so reset the password +ALTER LOGIN babel_5136_l1 WITH PASSWORD = '12345678' +GO -- CREATE A USER WITH db_accessadmin privilege in DATABASE babel_5136 USE master GO From b0ad65d9d9a32e53ee6a02c727f18e0a149e413c Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 4 Oct 2024 18:42:50 +0000 Subject: [PATCH 27/41] empty Signed-off-by: Tanzeel Khan From 4bbc598ded942ece8bdd434ea070dd4c00ad9b4f Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Mon, 7 Oct 2024 14:46:14 +0000 Subject: [PATCH 28/41] refactor Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 70 +++++++++++------------ contrib/babelfishpg_tsql/src/catalog.h | 4 +- contrib/babelfishpg_tsql/src/pl_handler.c | 17 +++--- contrib/babelfishpg_tsql/src/procedures.c | 30 ++++++---- contrib/babelfishpg_tsql/src/rolecmds.c | 20 +++---- contrib/babelfishpg_tsql/src/session.c | 11 ++++ contrib/babelfishpg_tsql/src/session.h | 1 + 7 files changed, 85 insertions(+), 68 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 2b2e061ce9..d347793d03 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -851,17 +851,18 @@ get_authid_login_ext_idx_oid(void) /* * Check if role is a bbf db principal. Returns BBF_ROLE if it is * a db role, returns BBF_USER if it is db user else returns 0 - * Looks only in current bbf db when current_db_only is set to true */ const int -is_database_principal(Oid role_oid, bool current_db_only) +get_db_principal_kind(Oid role_oid, const char *db_name) { char result = 0; bool isnull; HeapTuple tuple; char *rolname; + Assert(OidIsValid(role_oid) && db_name); + rolname = GetUserNameFromId(role_oid, false); tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(rolname)); pfree(rolname); @@ -869,29 +870,22 @@ is_database_principal(Oid role_oid, bool current_db_only) if (HeapTupleIsValid(tuple)) { BpChar type = ((Form_authid_user_ext) GETSTRUCT(tuple))->type; - char *type_str = bpchar_to_cstring(&type); + Datum datum = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_database_name, + &isnull); + char *type_str; + char *db_name_cstring; - if (current_db_only) - { - Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, - Anum_bbf_authid_user_ext_database_name, &isnull); - char *db_name_cstring; - char *current_db_name; - - Assert(!isnull); - db_name_cstring = TextDatumGetCString(db_name); - current_db_name = get_cur_db_name(); + Assert(!isnull); - if (strcmp(db_name_cstring, current_db_name) == 0) - result = (strcmp(type_str, "R") == 0) ? BBF_ROLE : BBF_USER; + type_str = bpchar_to_cstring(&type); + db_name_cstring = TextDatumGetCString(datum); - pfree(db_name_cstring); - pfree(current_db_name); - } - else + if (strcmp(db_name_cstring, db_name) == 0) result = (strcmp(type_str, "R") == 0) ? BBF_ROLE : BBF_USER; pfree(type_str); + pfree(db_name_cstring); ReleaseSysCache(tuple); } @@ -923,45 +917,45 @@ get_authid_user_ext_idx_oid(void) * Looks only in current bbf db when current_db_only is set to true */ char * -get_authid_user_ext_original_name(const char *physical_role_name, bool current_db_only) +get_authid_user_ext_original_name(const char *physical_role_name, const char *db_name) { char* orig_username = NULL; bool isnull; HeapTuple tuple; - Assert(physical_role_name != NULL && strlen(physical_role_name) != 0); + Assert(physical_role_name && strlen(physical_role_name) != 0); tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(physical_role_name)); if (HeapTupleIsValid(tuple)) { - Datum orig_username_datum = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, - Anum_bbf_authid_user_ext_orig_username, &isnull); + Datum datum = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_database_name, &isnull); + char *db_name_cstring; + Assert(!isnull); - if (current_db_only) - { - Datum db_name = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, - Anum_bbf_authid_user_ext_database_name, &isnull); - char *db_name_cstring; - char *current_db_name; + db_name_cstring = TextDatumGetCString(datum); + if (strcmp(db_name_cstring, db_name) == 0) + { + datum = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, + Anum_bbf_authid_user_ext_orig_username, &isnull); Assert(!isnull); - db_name_cstring = TextDatumGetCString(db_name); - current_db_name = get_cur_db_name(); - if (strcmp(db_name_cstring, current_db_name) == 0) - orig_username = TextDatumGetCString(orig_username_datum); - - pfree(db_name_cstring); - pfree(current_db_name); + orig_username = TextDatumGetCString(datum); } - else - orig_username = TextDatumGetCString(orig_username_datum); + + pfree(db_name_cstring); ReleaseSysCache(tuple); } + if (orig_username == NULL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Could not find original name for db principal %s in database %s", physical_role_name, db_name))); + return orig_username; } diff --git a/contrib/babelfishpg_tsql/src/catalog.h b/contrib/babelfishpg_tsql/src/catalog.h index b71251773f..3eb0a8854d 100644 --- a/contrib/babelfishpg_tsql/src/catalog.h +++ b/contrib/babelfishpg_tsql/src/catalog.h @@ -148,10 +148,10 @@ extern Oid bbf_authid_user_ext_idx_oid; #define BBF_ROLE 1 #define BBF_USER 2 -const int is_database_principal(Oid role_oid, bool current_db_only); +const int get_db_principal_kind(Oid role_oid, const char *db_name); extern Oid get_authid_user_ext_oid(void); extern Oid get_authid_user_ext_idx_oid(void); -extern char *get_authid_user_ext_original_name(const char *physical_role_name, bool current_db_only); +extern char *get_authid_user_ext_original_name(const char *physical_role_name, const char *db_name); extern char *get_authid_user_ext_physical_name(const char *db_name, const char *login_name); extern char *get_authid_user_ext_schema_name(const char *db_name, const char *user_name); extern List *get_authid_user_ext_db_users(const char *db_name); diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 63146a9324..0a838becb5 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3225,8 +3225,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, Oid user_oid = get_role_oid(stmt->role->rolename, false); /* db principal being altered should be a user or role in the current active logical database */ - if ((isuser && is_database_principal(user_oid, true) != BBF_USER) || - (isrole && is_database_principal(user_oid, true) != BBF_ROLE)) + if ((isuser && get_db_principal_kind(user_oid, db_name) != BBF_USER) || + (isrole && get_db_principal_kind(user_oid, db_name) != BBF_ROLE)) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("Cannot alter the %s '%s', because it does not exist or you do not have permission.", isuser ? "user" : "role", stmt->role->rolename))); @@ -3387,8 +3387,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, int role_oid = get_role_oid(user_name, true); if (!OidIsValid(role_oid) || /* Not found */ - (drop_user && is_database_principal(role_oid, true) != BBF_USER) || /* Found but not a user in current logical db */ - (drop_role && is_database_principal(role_oid, true) != BBF_ROLE)) /* Found but not a role in current logical db */ + (drop_user && get_db_principal_kind(role_oid, db_name) != BBF_USER) || /* Found but not a user in current logical db */ + (drop_role && get_db_principal_kind(role_oid, db_name) != BBF_ROLE)) /* Found but not a role in current logical db */ { if (stmt->missing_ok) { @@ -3521,9 +3521,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (is_login(roleform->oid)) all_logins = true; - else if (is_database_principal(roleform->oid, false) == BBF_USER) + else if (get_db_principal_kind(roleform->oid, get_current_db_name()) == BBF_USER) all_users = true; - else if (is_database_principal(roleform->oid, false) == BBF_ROLE) + else if (get_db_principal_kind(roleform->oid, get_current_db_name()) == BBF_ROLE) all_roles = true; else other = true; @@ -3620,7 +3620,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { - Oid db_accessadmin = get_db_accessadmin_oid(get_cur_db_name(), false); + const char *db_name = get_current_db_name(); + Oid db_accessadmin = get_db_accessadmin_oid(db_name, false); owner_oid = get_rolespec_oid(rolspec, true); /* @@ -3630,7 +3631,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, */ if (!member_can_set_role(GetUserId(), owner_oid) && has_privs_of_role(GetUserId(), db_accessadmin) && - (is_database_principal(owner_oid, true))) + (get_db_principal_kind(owner_oid, db_name))) { create_schema->authrole = NULL; alter_owner = true; diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index e53cef8292..22a72cb0d5 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -2244,6 +2244,7 @@ sp_droprole(PG_FUNCTION_ARGS) *lowercase_rolname; size_t len; char *physical_role_name; + char *db_name = get_cur_db_name(); Oid role_oid; List *parsetree_list; ListCell *parsetree_item; @@ -2279,16 +2280,18 @@ sp_droprole(PG_FUNCTION_ARGS) errmsg("Name cannot be NULL."))); /* Map the logical role name to its physical name in the database. */ - physical_role_name = get_physical_user_name(get_cur_db_name(), lowercase_rolname, false, true); + physical_role_name = get_physical_user_name(db_name, lowercase_rolname, false, true); role_oid = get_role_oid(physical_role_name, true); pfree(physical_role_name); /* Check if the role does not exists */ - if (role_oid == InvalidOid || is_database_principal(role_oid, true) != BBF_ROLE) + if (role_oid == InvalidOid || get_db_principal_kind(role_oid, db_name) != BBF_ROLE) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot drop the role '%s', because it does not exist or you do not have permission.", rolname))); + pfree(db_name); + /* Advance cmd counter to make the delete visible */ CommandCounterIncrement(); @@ -2380,6 +2383,7 @@ sp_addrolemember(PG_FUNCTION_ARGS) size_t len; char *physical_member_name; char *physical_role_name; + char *db_name = get_cur_db_name(); Oid role_oid, member_oid; List *parsetree_list; @@ -2430,24 +2434,24 @@ sp_addrolemember(PG_FUNCTION_ARGS) errmsg("Cannot make a role a member of itself."))); /* Map the logical member name to its physical name in the database. */ - physical_member_name = get_physical_user_name(get_cur_db_name(), lowercase_membername, false, true); + physical_member_name = get_physical_user_name(db_name, lowercase_membername, false, true); member_oid = get_role_oid(physical_member_name, true); /* * Check if the user, group or role does not exists and given member * name is an role or user */ - if (member_oid == InvalidOid || !is_database_principal(member_oid, true)) + if (member_oid == InvalidOid || !get_db_principal_kind(member_oid, db_name)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("User or role '%s' does not exist in this database.", membername))); /* Map the logical role name to its physical name in the database. */ - physical_role_name = get_physical_user_name(get_cur_db_name(), lowercase_rolname, false, true); + physical_role_name = get_physical_user_name(db_name, lowercase_rolname, false, true); role_oid = get_role_oid(physical_role_name, true); /* Check if the role does not exists and given role name is an role */ - if (role_oid == InvalidOid || is_database_principal(role_oid, true) != BBF_ROLE) + if (role_oid == InvalidOid || get_db_principal_kind(role_oid, db_name) != BBF_ROLE) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", rolname))); @@ -2458,6 +2462,8 @@ sp_addrolemember(PG_FUNCTION_ARGS) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("Cannot make a role a member of itself."))); + pfree(db_name); + /* Advance cmd counter to make the delete visible */ CommandCounterIncrement(); @@ -2554,6 +2560,7 @@ sp_droprolemember(PG_FUNCTION_ARGS) *lowercase_membername; size_t len; char *physical_name; + char *db_name= get_cur_db_name(); Oid role_oid; List *parsetree_list; ListCell *parsetree_item; @@ -2597,29 +2604,32 @@ sp_droprolemember(PG_FUNCTION_ARGS) errmsg("Name cannot be NULL."))); /* Map the logical role name to its physical name in the database. */ - physical_name = get_physical_user_name(get_cur_db_name(), lowercase_rolname, false, true); + physical_name = get_physical_user_name(db_name, lowercase_rolname, false, true); role_oid = get_role_oid(physical_name, true); /* Throw an error id the given role name doesn't exist or isn't a role */ - if (role_oid == InvalidOid || is_database_principal(role_oid, true) != BBF_ROLE) + if (role_oid == InvalidOid || get_db_principal_kind(role_oid, db_name) != BBF_ROLE) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot alter the role '%s', because it does not exist or you do not have permission.", rolname))); /* Map the logical member name to its physical name in the database. */ pfree(physical_name); - physical_name = get_physical_user_name(get_cur_db_name(), lowercase_membername, false, true); + physical_name = get_physical_user_name(db_name, lowercase_membername, false, true); role_oid = get_role_oid(physical_name, true); /* * Throw an error id the given member name doesn't exist or isn't a * role or user */ - if (role_oid == InvalidOid || !is_database_principal(role_oid, true)) + if (role_oid == InvalidOid || !get_db_principal_kind(role_oid, db_name)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("Cannot drop the principal '%s', because it does not exist or you do not have permission.", membername))); + + pfree(db_name); + /* Advance cmd counter to make the delete visible */ CommandCounterIncrement(); diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 643397bc58..0793f8bb72 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -290,7 +290,7 @@ drop_bbf_roles(ObjectAccessType access, { if (is_login(roleid)) drop_bbf_authid_login_ext(access, classId, roleid, subId, arg); - else if (is_database_principal(roleid, false)) + else if (get_db_principal_kind(roleid, get_current_db_name())) drop_bbf_authid_user_ext(access, classId, roleid, subId, arg); } @@ -1775,7 +1775,7 @@ is_alter_role_stmt(GrantRoleStmt *stmt) Oid granted = get_role_oid(spec->rolename, true); /* Check if the granted role is an existing database role */ - if (granted == InvalidOid || is_database_principal(granted, true) != BBF_ROLE) + if (granted == InvalidOid || get_db_principal_kind(granted, get_current_db_name()) != BBF_ROLE) return false; } @@ -1790,7 +1790,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) const char *granted_name; const char *grantee_name; const char *original_user_name; - const char *db_name = get_cur_db_name(); + const char *db_name = get_current_db_name(); RoleSpec *granted_spec; RoleSpec *grantee_spec; @@ -1800,7 +1800,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) grantee = get_role_oid(grantee_name, false); /* Disallow ALTER ROLE if the grantee is not a db principal */ - if (!is_database_principal(grantee, true)) + if (!get_db_principal_kind(grantee, db_name)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("%s is not a database user or a user-defined database role", @@ -1811,7 +1811,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) granted_name = granted_spec->rolename; granted = get_role_oid(granted_name, false); - original_user_name = get_authid_user_ext_original_name(granted_name, true); + original_user_name = get_authid_user_ext_original_name(granted_name, db_name); Assert(original_user_name); /* only members of db_owner can alter drop members of fixed db roles */ @@ -1921,7 +1921,7 @@ is_rolemember(PG_FUNCTION_ARGS) char *dc_principal = NULL; char *physical_role_name; char *physical_principal_name; - char *cur_db_name; + char *cur_db_name = get_cur_db_name(); char *db_owner_name; char *dbo_role_name; int idx; @@ -1935,7 +1935,7 @@ is_rolemember(PG_FUNCTION_ARGS) while (idx > 0 && isspace((unsigned char) role[idx - 1])) role[--idx] = '\0'; dc_role = downcase_identifier(role, strlen(role), false, false); - physical_role_name = get_physical_user_name(get_cur_db_name(), dc_role, false, true); + physical_role_name = get_physical_user_name(cur_db_name, dc_role, false, true); role_oid = get_role_oid(physical_role_name, true); pfree(physical_role_name); @@ -1951,7 +1951,7 @@ is_rolemember(PG_FUNCTION_ARGS) while (idx > 0 && isspace((unsigned char) principal[idx - 1])) principal[--idx] = '\0'; dc_principal = downcase_identifier(principal, strlen(principal), false, false); - physical_principal_name = get_physical_user_name(get_cur_db_name(), dc_principal, false, true); + physical_principal_name = get_physical_user_name(cur_db_name, dc_principal, false, true); principal_oid = get_role_oid(physical_principal_name, true); pfree(physical_principal_name); } @@ -1975,7 +1975,7 @@ is_rolemember(PG_FUNCTION_ARGS) * principal. Note that if given principal is current user, we'll always * have permissions. */ - if (is_database_principal(role_oid, false) != BBF_ROLE || + if (get_db_principal_kind(role_oid, cur_db_name) != BBF_ROLE || ((principal_oid != cur_user_oid) && (!has_privs_of_role(cur_user_oid, role_oid) || !has_privs_of_role(cur_user_oid, principal_oid)))) @@ -1985,12 +1985,12 @@ is_rolemember(PG_FUNCTION_ARGS) * Recursively check if the given principal is a member of the role, not * considering superuserness */ - cur_db_name = get_cur_db_name(); db_owner_name = get_db_owner_name(cur_db_name); dbo_role_name = get_dbo_role_name(cur_db_name); db_owner_oid = get_role_oid(db_owner_name, false); dbo_role_oid = get_role_oid(dbo_role_name, false); + pfree(cur_db_name); pfree(db_owner_name); pfree(dbo_role_name); diff --git a/contrib/babelfishpg_tsql/src/session.c b/contrib/babelfishpg_tsql/src/session.c index 0470d0d0cd..46c2aa2486 100644 --- a/contrib/babelfishpg_tsql/src/session.c +++ b/contrib/babelfishpg_tsql/src/session.c @@ -48,12 +48,23 @@ get_cur_db_id(void) return current_db_id; } +/* same as get_current_db_name but reurn value is palloc'd */ char * get_cur_db_name(void) { return pstrdup(current_db_name); } +/* + * returns current active babelfish db name + * Callers should NOT pfree the return value + */ +const char * +get_current_db_name(void) +{ + return current_db_name; +} + void set_cur_db_name_for_parallel_worker(const char* logical_db_name) { diff --git a/contrib/babelfishpg_tsql/src/session.h b/contrib/babelfishpg_tsql/src/session.h index c5d17cb161..afac73bb21 100644 --- a/contrib/babelfishpg_tsql/src/session.h +++ b/contrib/babelfishpg_tsql/src/session.h @@ -7,6 +7,7 @@ extern int16 get_cur_db_id(void); extern void set_cur_db(int16 id, const char *name); extern char *get_cur_db_name(void); +extern const char *get_current_db_name(void); extern void bbf_set_current_user(const char *user_name); extern void set_session_properties(const char *db_name); extern void check_session_db_access(const char *dn_name); From cc6259005257f27a6123d8333e83d2e6e4d98743 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 11 Oct 2024 17:28:50 +0000 Subject: [PATCH 29/41] fix tests Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/rolecmds.c | 3 +- .../expected/db_accessadmin-vu-cleanup.out | 2 +- .../expected/db_accessadmin-vu-prepare.out | 2 +- .../expected/db_accessadmin-vu-verify.out | 234 ++++++++++++++++-- .../single_db/db_accessadmin-vu-verify.out | 234 ++++++++++++++++-- test/JDBC/input/db_accessadmin-vu-cleanup.mix | 2 +- test/JDBC/input/db_accessadmin-vu-prepare.mix | 2 +- test/JDBC/input/db_accessadmin-vu-verify.mix | 102 +++++++- 8 files changed, 541 insertions(+), 40 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 0793f8bb72..9f54b71c86 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -1994,7 +1994,8 @@ is_rolemember(PG_FUNCTION_ARGS) pfree(db_owner_name); pfree(dbo_role_name); - if ((principal_oid == db_owner_oid) || (principal_oid == dbo_role_oid)) + /* Fixed db principals cannot be member of other roles except dbo which is member of all fixed roles */ + if ((principal_oid == db_owner_oid) || (principal_oid == dbo_role_oid && !IS_FIXED_DB_PRINCIPAL(role))) PG_RETURN_INT32(0); else if (is_member_of_role_nosuper(principal_oid, role_oid)) PG_RETURN_INT32(1); diff --git a/test/JDBC/expected/db_accessadmin-vu-cleanup.out b/test/JDBC/expected/db_accessadmin-vu-cleanup.out index ec399a0ba3..234a2afc13 100644 --- a/test/JDBC/expected/db_accessadmin-vu-cleanup.out +++ b/test/JDBC/expected/db_accessadmin-vu-cleanup.out @@ -1,7 +1,7 @@ -- tsql USE master GO -DROP DATABASE babel_5136 +DROP DATABASE IF EXISTS babel_5136 GO DROP LOGIN babel_5136_l1 GO diff --git a/test/JDBC/expected/db_accessadmin-vu-prepare.out b/test/JDBC/expected/db_accessadmin-vu-prepare.out index f88da3019a..a1e3bfe041 100644 --- a/test/JDBC/expected/db_accessadmin-vu-prepare.out +++ b/test/JDBC/expected/db_accessadmin-vu-prepare.out @@ -30,6 +30,6 @@ CREATE TABLE babel_5136_t1 (id INT) GO CREATE PROC babel_5136_p1 AS SELECT 1 GO -CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END +CREATE FUNCTION babel_5136_f1() RETURNS INT AS BEGIN return 1; END GO diff --git a/test/JDBC/expected/db_accessadmin-vu-verify.out b/test/JDBC/expected/db_accessadmin-vu-verify.out index 4283728a00..778ea4ca2f 100644 --- a/test/JDBC/expected/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/db_accessadmin-vu-verify.out @@ -23,6 +23,25 @@ USE babel_5136 GO CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l1 GO +-- ADD DROP MEMBERS TO db_accessadmin USING dbo +sp_addrolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'babel_5136_db_accessadmin_user') +GO +~~START~~ +int +1 +~~END~~ + +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'babel_5136_db_accessadmin_user') +GO +~~START~~ +int +0 +~~END~~ + ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user GO -- Cannot add login as member of db_accessadmin @@ -32,9 +51,82 @@ GO ~~ERROR (Message: role "babel_5136_babel_5136_l1" does not exist)~~ +-- Cannot add fixed roles ass member of db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER syadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: role "babel_5136_syadmin" does not exist)~~ + +ALTER ROLE db_accessadmin ADD MEMBER dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'dbo')~~ + +ALTER ROLE db_accessadmin ADD MEMBER db_owner +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_owner')~~ + +ALTER ROLE db_accessadmin ADD MEMBER db_accessadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_accessadmin')~~ + +ALTER ROLE db_accessadmin DROP MEMBER syadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: role "babel_5136_syadmin" does not exist)~~ + +ALTER ROLE db_accessadmin DROP MEMBER dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'dbo')~~ + +ALTER ROLE db_accessadmin DROP MEMBER db_owner +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_owner')~~ + +ALTER ROLE db_accessadmin DROP MEMBER db_accessadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_accessadmin')~~ + + -- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO + +-- IS_ROLEMEMBER should show db_accessadmin as member of dbo but not of db_owner +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_ROLEMEMBER('db_accessadmin', 'dbo') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_ROLEMEMBER('db_accessadmin', 'db_owner') +GO +~~START~~ +int +0 +~~END~~ + -- terminate-tsql-conn -- tsql user=babel_5136_l1 password=12345678 database=babel_5136 @@ -45,7 +137,7 @@ GO ~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ --- terminate-tsql-conn +-- terminate-tsql-conn user=babel_5136_l1 password=12345678 database=babel_5136 -- tsql user=babel_5136_db_accessadmin_l1 password=12345678 @@ -81,7 +173,21 @@ DROP USER babel_5136_u1 GO CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 GO +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 + +-- tsql database=babel_5136 +SELECT current_user +GO +~~START~~ +varchar +dbo +~~END~~ + +ALTER ROLE babel_5136_r1 ADD MEMBER babel_5136_u1 +GO +-- terminate-tsql-conn database=babel_5136 +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 database=babel_5136 -- ALTER EXISTING USER and THEN DROP IT ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo GO @@ -111,6 +217,36 @@ CREATE SCHEMA s2 AUTHORIZATION dbo GO CREATE SCHEMA s3 AUTHORIZATION babel_5136_u1 GO + +-- Should be able to do GRANT/REVOKE on schema that it owns +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s1 TO babel_5136_u1 +GO +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s2 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot find the schema "s2", because it does not exist or you do not have permission.)~~ + +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s3 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.)~~ + +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s1 TO babel_5136_u1 +GO +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s2 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot find the schema "s2", because it does not exist or you do not have permission.)~~ + +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s3 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.)~~ + -- Should only be able to drop schema that it owns DROP SCHEMA s1 GO @@ -172,6 +308,48 @@ GO ~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ +ALTER ROLE babel_5136_r1 DROP MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + +ALTER ROLE db_accessadmin DROP MEMBER 'babel_5136_db_accessadmin_user' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near ''babel_5136_db_accessadmin_user'' at line 1 and character position 38)~~ + +sp_addrolemember 'db_accessadmin', 'babel_5136_u1' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +sp_addrolemember 'babel_5136_r1', 'babel_5136_u1' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + +sp_droprolemember 'babel_5136_r1', 'babel_5136_u1' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + -- should not be able to alter users login mapping or rename members of db_owner ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 @@ -223,30 +401,44 @@ GO ~~ERROR (Message: Grantor does not have GRANT permission.)~~ --- NO OTHER DDLs SHOULD BE ALLOWED -CREATE TABLE babel_5136_t1 (id INT) +-- DMLs or EXECUTING FUNCTIONS SHOULD ALSO BE NOT ALLOWED +EXEC babel_5136_p1 GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: permission denied for schema babel_5136_dbo)~~ +~~ERROR (Message: permission denied for procedure babel_5136_p1)~~ -CREATE PROCEDURE babel_5136_p1 AS SELECT 1 +SELECT * FROM babel_5136_t1 GO -~~ERROR (Code: 2714)~~ +~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Function 'babel_5136_p1' already exists with the same name)~~ +~~ERROR (Message: permission denied for table babel_5136_t1)~~ -CREATE FUNCTION f1() RETURNS INT AS BEGIN RETURN 1 END +SELECT babel_5136_f1() GO -~~ERROR (Code: 2714)~~ +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for function babel_5136_f1)~~ -~~ERROR (Message: Function 'f1' already exists with the same name)~~ -CREATE DATABASE new_database +-- NO OTHER DDLs SHOULD BE ALLOWED +CREATE TABLE babel_5136_t2 (id INT) GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: permission denied to create database)~~ +~~ERROR (Message: permission denied for schema babel_5136_dbo)~~ + +CREATE PROCEDURE babel_5136_p2 AS SELECT 1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema babel_5136_dbo)~~ + +CREATE FUNCTION babel_5136_f2() RETURNS INT AS BEGIN RETURN 1 END +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema babel_5136_dbo)~~ -- In master database the current login should not have db_accessadmin privilege @@ -326,12 +518,26 @@ GO ~~ERROR (Message: permission denied for database jdbc_testdb)~~ -CREATE DATABASE new_database +-- Should not be able to drop a database +DROP DATABASE babel_5136 GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: permission denied to create database)~~ +~~ERROR (Message: must be owner of database babel_5136)~~ + +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 database=babel_5136 + +-- tsql +DROP DATABASE babel_5136 +GO +-- terminate-tsql-conn +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 +-- Should not be able to create a database +CREATE DATABASE babel_5136 +GO +~~ERROR (Code: 33557097)~~ +~~ERROR (Message: permission denied to create database)~~ -- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 diff --git a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out index be88745296..57c4e1a1ea 100644 --- a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out @@ -23,6 +23,25 @@ USE babel_5136 GO CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l1 GO +-- ADD DROP MEMBERS TO db_accessadmin USING dbo +sp_addrolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'babel_5136_db_accessadmin_user') +GO +~~START~~ +int +1 +~~END~~ + +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'babel_5136_db_accessadmin_user') +GO +~~START~~ +int +0 +~~END~~ + ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user GO -- Cannot add login as member of db_accessadmin @@ -32,9 +51,82 @@ GO ~~ERROR (Message: role "babel_5136_babel_5136_l1" does not exist)~~ +-- Cannot add fixed roles ass member of db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER syadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: role "babel_5136_syadmin" does not exist)~~ + +ALTER ROLE db_accessadmin ADD MEMBER dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'dbo')~~ + +ALTER ROLE db_accessadmin ADD MEMBER db_owner +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_owner')~~ + +ALTER ROLE db_accessadmin ADD MEMBER db_accessadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_accessadmin')~~ + +ALTER ROLE db_accessadmin DROP MEMBER syadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: role "babel_5136_syadmin" does not exist)~~ + +ALTER ROLE db_accessadmin DROP MEMBER dbo +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'dbo')~~ + +ALTER ROLE db_accessadmin DROP MEMBER db_owner +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_owner')~~ + +ALTER ROLE db_accessadmin DROP MEMBER db_accessadmin +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot use the special principal 'db_accessadmin')~~ + + -- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO + +-- IS_ROLEMEMBER should show db_accessadmin as member of dbo but not of db_owner +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_ROLEMEMBER('db_accessadmin', 'dbo') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_ROLEMEMBER('db_accessadmin', 'db_owner') +GO +~~START~~ +int +0 +~~END~~ + -- terminate-tsql-conn -- tsql user=babel_5136_l1 password=12345678 database=babel_5136 @@ -45,7 +137,7 @@ GO ~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ --- terminate-tsql-conn +-- terminate-tsql-conn user=babel_5136_l1 password=12345678 database=babel_5136 -- tsql user=babel_5136_db_accessadmin_l1 password=12345678 @@ -81,7 +173,21 @@ DROP USER babel_5136_u1 GO CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 GO +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 + +-- tsql database=babel_5136 +SELECT current_user +GO +~~START~~ +varchar +dbo +~~END~~ + +ALTER ROLE babel_5136_r1 ADD MEMBER babel_5136_u1 +GO +-- terminate-tsql-conn database=babel_5136 +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 database=babel_5136 -- ALTER EXISTING USER and THEN DROP IT ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo GO @@ -111,6 +217,36 @@ CREATE SCHEMA s2 AUTHORIZATION dbo GO CREATE SCHEMA s3 AUTHORIZATION babel_5136_u1 GO + +-- Should be able to do GRANT/REVOKE on schema that it owns +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s1 TO babel_5136_u1 +GO +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s2 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot find the schema "s2", because it does not exist or you do not have permission.)~~ + +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s3 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.)~~ + +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s1 TO babel_5136_u1 +GO +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s2 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot find the schema "s2", because it does not exist or you do not have permission.)~~ + +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s3 TO babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.)~~ + -- Should only be able to drop schema that it owns DROP SCHEMA s1 GO @@ -172,6 +308,48 @@ GO ~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ +ALTER ROLE babel_5136_r1 DROP MEMBER babel_5136_u1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + +ALTER ROLE db_accessadmin DROP MEMBER 'babel_5136_db_accessadmin_user' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near ''babel_5136_db_accessadmin_user'' at line 1 and character position 38)~~ + +sp_addrolemember 'db_accessadmin', 'babel_5136_u1' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + +sp_addrolemember 'babel_5136_r1', 'babel_5136_u1' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + +sp_droprolemember 'babel_5136_r1', 'babel_5136_u1' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Current login babel_5136_db_accessadmin_l1 does not have permission to alter role babel_5136_babel_5136_r1)~~ + +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Cannot alter the role 'db_accessadmin', because it does not exist or you do not have permission.)~~ + -- should not be able to alter users login mapping or rename members of db_owner ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 @@ -223,30 +401,44 @@ GO ~~ERROR (Message: Grantor does not have GRANT permission.)~~ --- NO OTHER DDLs SHOULD BE ALLOWED -CREATE TABLE babel_5136_t1 (id INT) +-- DMLs or EXECUTING FUNCTIONS SHOULD ALSO BE NOT ALLOWED +EXEC babel_5136_p1 GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: permission denied for schema dbo)~~ +~~ERROR (Message: permission denied for procedure babel_5136_p1)~~ -CREATE PROCEDURE babel_5136_p1 AS SELECT 1 +SELECT * FROM babel_5136_t1 GO -~~ERROR (Code: 2714)~~ +~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Function 'babel_5136_p1' already exists with the same name)~~ +~~ERROR (Message: permission denied for table babel_5136_t1)~~ -CREATE FUNCTION f1() RETURNS INT AS BEGIN RETURN 1 END +SELECT babel_5136_f1() GO -~~ERROR (Code: 2714)~~ +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for function babel_5136_f1)~~ -~~ERROR (Message: Function 'f1' already exists with the same name)~~ -CREATE DATABASE new_database +-- NO OTHER DDLs SHOULD BE ALLOWED +CREATE TABLE babel_5136_t2 (id INT) GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Only one user database allowed under single-db mode. User database "babel_5136" already exists)~~ +~~ERROR (Message: permission denied for schema dbo)~~ + +CREATE PROCEDURE babel_5136_p2 AS SELECT 1 +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema dbo)~~ + +CREATE FUNCTION babel_5136_f2() RETURNS INT AS BEGIN RETURN 1 END +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: permission denied for schema dbo)~~ -- In master database the current login should not have db_accessadmin privilege @@ -326,12 +518,26 @@ GO ~~ERROR (Message: permission denied for database jdbc_testdb)~~ -CREATE DATABASE new_database +-- Should not be able to drop a database +DROP DATABASE babel_5136 GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Only one user database allowed under single-db mode. User database "babel_5136" already exists)~~ +~~ERROR (Message: must be owner of database babel_5136)~~ + +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 database=babel_5136 +-- tsql +DROP DATABASE babel_5136 +GO +-- terminate-tsql-conn + +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 +-- Should not be able to create a database +CREATE DATABASE babel_5136 +GO +~~ERROR (Code: 33557097)~~ +~~ERROR (Message: permission denied to create database)~~ -- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 diff --git a/test/JDBC/input/db_accessadmin-vu-cleanup.mix b/test/JDBC/input/db_accessadmin-vu-cleanup.mix index ec399a0ba3..234a2afc13 100644 --- a/test/JDBC/input/db_accessadmin-vu-cleanup.mix +++ b/test/JDBC/input/db_accessadmin-vu-cleanup.mix @@ -1,7 +1,7 @@ -- tsql USE master GO -DROP DATABASE babel_5136 +DROP DATABASE IF EXISTS babel_5136 GO DROP LOGIN babel_5136_l1 GO diff --git a/test/JDBC/input/db_accessadmin-vu-prepare.mix b/test/JDBC/input/db_accessadmin-vu-prepare.mix index f88da3019a..a1e3bfe041 100644 --- a/test/JDBC/input/db_accessadmin-vu-prepare.mix +++ b/test/JDBC/input/db_accessadmin-vu-prepare.mix @@ -30,6 +30,6 @@ CREATE TABLE babel_5136_t1 (id INT) GO CREATE PROC babel_5136_p1 AS SELECT 1 GO -CREATE FUNCTION f1() RETURNS INT AS BEGIN return 1; END +CREATE FUNCTION babel_5136_f1() RETURNS INT AS BEGIN return 1; END GO diff --git a/test/JDBC/input/db_accessadmin-vu-verify.mix b/test/JDBC/input/db_accessadmin-vu-verify.mix index b18b07a516..cca87664b6 100644 --- a/test/JDBC/input/db_accessadmin-vu-verify.mix +++ b/test/JDBC/input/db_accessadmin-vu-verify.mix @@ -24,21 +24,56 @@ USE babel_5136 GO CREATE USER babel_5136_db_accessadmin_user FOR LOGIN babel_5136_db_accessadmin_l1 GO +-- ADD DROP MEMBERS TO db_accessadmin USING dbo +sp_addrolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'babel_5136_db_accessadmin_user') +GO +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'babel_5136_db_accessadmin_user') +GO ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user GO -- Cannot add login as member of db_accessadmin ALTER ROLE db_accessadmin ADD MEMBER babel_5136_l1 GO +-- Cannot add fixed roles ass member of db_accessadmin +ALTER ROLE db_accessadmin ADD MEMBER syadmin +GO +ALTER ROLE db_accessadmin ADD MEMBER dbo +GO +ALTER ROLE db_accessadmin ADD MEMBER db_owner +GO +ALTER ROLE db_accessadmin ADD MEMBER db_accessadmin +GO +ALTER ROLE db_accessadmin DROP MEMBER syadmin +GO +ALTER ROLE db_accessadmin DROP MEMBER dbo +GO +ALTER ROLE db_accessadmin DROP MEMBER db_owner +GO +ALTER ROLE db_accessadmin DROP MEMBER db_accessadmin +GO + -- MEMBERS OF db_accessadmin WILL ALWAYS HAVE CONNECT PRIVILEGES REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO + +-- IS_ROLEMEMBER should show db_accessadmin as member of dbo but not of db_owner +SELECT IS_ROLEMEMBER('db_accessadmin') +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'dbo') +GO +SELECT IS_ROLEMEMBER('db_accessadmin', 'db_owner') +GO -- terminate-tsql-conn -- Only db_owner members should be able to do this -- tsql user=babel_5136_l1 password=12345678 database=babel_5136 ALTER ROLE db_accessadmin ADD MEMBER babel_5136_db_accessadmin_user GO --- terminate-tsql-conn +-- terminate-tsql-conn user=babel_5136_l1 password=12345678 database=babel_5136 -- Check all allowed operations @@ -64,7 +99,16 @@ DROP USER babel_5136_u1 GO CREATE USER babel_5136_u1 FOR LOGIN babel_5136_l1 GO +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 +-- tsql database=babel_5136 +SELECT current_user +GO +ALTER ROLE babel_5136_r1 ADD MEMBER babel_5136_u1 +GO +-- terminate-tsql-conn database=babel_5136 + +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 database=babel_5136 -- ALTER EXISTING USER and THEN DROP IT ALTER USER babel_5136_u1 WITH DEFAULT_SCHEMA = dbo GO @@ -90,6 +134,20 @@ CREATE SCHEMA s2 AUTHORIZATION dbo GO CREATE SCHEMA s3 AUTHORIZATION babel_5136_u1 GO + +-- Should be able to do GRANT/REVOKE on schema that it owns +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s1 TO babel_5136_u1 +GO +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s2 TO babel_5136_u1 +GO +GRANT SELECT, INSERT, EXECUTE ON SCHEMA::s3 TO babel_5136_u1 +GO +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s1 TO babel_5136_u1 +GO +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s2 TO babel_5136_u1 +GO +REVOKE SELECT, INSERT, EXECUTE ON SCHEMA::s3 TO babel_5136_u1 +GO -- Should only be able to drop schema that it owns DROP SCHEMA s1 GO @@ -115,6 +173,20 @@ ALTER ROLE db_owner ADD MEMBER babel_5136_u1 GO ALTER ROLE babel_5136_r1 ADD MEMBER babel_5136_u1 GO +ALTER ROLE babel_5136_r1 DROP MEMBER babel_5136_u1 +GO +ALTER ROLE db_accessadmin DROP MEMBER 'babel_5136_db_accessadmin_user' +GO +sp_addrolemember 'db_accessadmin', 'babel_5136_u1' +GO +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO +sp_addrolemember 'babel_5136_r1', 'babel_5136_u1' +GO +sp_droprolemember 'babel_5136_r1', 'babel_5136_u1' +GO +sp_droprolemember 'db_accessadmin', 'babel_5136_db_accessadmin_user' +GO -- should not be able to alter users login mapping or rename members of db_owner ALTER USER babel_5136_u1_new_name WITH LOGIN = babel_5136_l3 @@ -134,14 +206,20 @@ GO REVOKE CONNECT FROM dbo GO --- NO OTHER DDLs SHOULD BE ALLOWED -CREATE TABLE babel_5136_t1 (id INT) +-- DMLs or EXECUTING FUNCTIONS SHOULD ALSO BE NOT ALLOWED +EXEC babel_5136_p1 GO -CREATE PROCEDURE babel_5136_p1 AS SELECT 1 +SELECT * FROM babel_5136_t1 GO -CREATE FUNCTION f1() RETURNS INT AS BEGIN RETURN 1 END +SELECT babel_5136_f1() GO -CREATE DATABASE new_database + +-- NO OTHER DDLs SHOULD BE ALLOWED +CREATE TABLE babel_5136_t2 (id INT) +GO +CREATE PROCEDURE babel_5136_p2 AS SELECT 1 +GO +CREATE FUNCTION babel_5136_f2() RETURNS INT AS BEGIN RETURN 1 END GO -- In master database the current login should not have db_accessadmin privilege @@ -175,8 +253,18 @@ CREATE SCHEMA babel_5136_s1 GO CREATE SCHEMA babel_5136_s1 AUTHORIZATION babel_5136_u1 GO -CREATE DATABASE new_database +-- Should not be able to drop a database +DROP DATABASE babel_5136 GO +-- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 database=babel_5136 +-- tsql +DROP DATABASE babel_5136 +GO +-- terminate-tsql-conn +-- tsql user=babel_5136_db_accessadmin_l1 password=12345678 +-- Should not be able to create a database +CREATE DATABASE babel_5136 +GO -- terminate-tsql-conn user=babel_5136_db_accessadmin_l1 password=12345678 From 4ff867ae5e5a7b9088f5563614e037228031fdc4 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Mon, 14 Oct 2024 15:33:35 +0000 Subject: [PATCH 30/41] refactor Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/pl_handler.c | 6 +++--- contrib/babelfishpg_tsql/src/rolecmds.c | 6 +++--- contrib/babelfishpg_tsql/src/session.c | 4 ++-- contrib/babelfishpg_tsql/src/session.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 0a838becb5..fcb14cc106 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3521,9 +3521,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (is_login(roleform->oid)) all_logins = true; - else if (get_db_principal_kind(roleform->oid, get_current_db_name()) == BBF_USER) + else if (get_db_principal_kind(roleform->oid, get_cuurent_pltsql_db_name()) == BBF_USER) all_users = true; - else if (get_db_principal_kind(roleform->oid, get_current_db_name()) == BBF_ROLE) + else if (get_db_principal_kind(roleform->oid, get_cuurent_pltsql_db_name()) == BBF_ROLE) all_roles = true; else other = true; @@ -3620,7 +3620,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { - const char *db_name = get_current_db_name(); + const char *db_name = get_cuurent_pltsql_db_name(); Oid db_accessadmin = get_db_accessadmin_oid(db_name, false); owner_oid = get_rolespec_oid(rolspec, true); diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 9f54b71c86..304b77c586 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -290,7 +290,7 @@ drop_bbf_roles(ObjectAccessType access, { if (is_login(roleid)) drop_bbf_authid_login_ext(access, classId, roleid, subId, arg); - else if (get_db_principal_kind(roleid, get_current_db_name())) + else if (get_db_principal_kind(roleid, get_cuurent_pltsql_db_name())) drop_bbf_authid_user_ext(access, classId, roleid, subId, arg); } @@ -1775,7 +1775,7 @@ is_alter_role_stmt(GrantRoleStmt *stmt) Oid granted = get_role_oid(spec->rolename, true); /* Check if the granted role is an existing database role */ - if (granted == InvalidOid || get_db_principal_kind(granted, get_current_db_name()) != BBF_ROLE) + if (granted == InvalidOid || get_db_principal_kind(granted, get_cuurent_pltsql_db_name()) != BBF_ROLE) return false; } @@ -1790,7 +1790,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) const char *granted_name; const char *grantee_name; const char *original_user_name; - const char *db_name = get_current_db_name(); + const char *db_name = get_cuurent_pltsql_db_name(); RoleSpec *granted_spec; RoleSpec *grantee_spec; diff --git a/contrib/babelfishpg_tsql/src/session.c b/contrib/babelfishpg_tsql/src/session.c index 46c2aa2486..008320dc36 100644 --- a/contrib/babelfishpg_tsql/src/session.c +++ b/contrib/babelfishpg_tsql/src/session.c @@ -48,7 +48,7 @@ get_cur_db_id(void) return current_db_id; } -/* same as get_current_db_name but reurn value is palloc'd */ +/* same as get_cuurent_pltsql_db_name but reurn value is palloc'd */ char * get_cur_db_name(void) { @@ -60,7 +60,7 @@ get_cur_db_name(void) * Callers should NOT pfree the return value */ const char * -get_current_db_name(void) +get_cuurent_pltsql_db_name(void) { return current_db_name; } diff --git a/contrib/babelfishpg_tsql/src/session.h b/contrib/babelfishpg_tsql/src/session.h index afac73bb21..1e4f136804 100644 --- a/contrib/babelfishpg_tsql/src/session.h +++ b/contrib/babelfishpg_tsql/src/session.h @@ -7,7 +7,7 @@ extern int16 get_cur_db_id(void); extern void set_cur_db(int16 id, const char *name); extern char *get_cur_db_name(void); -extern const char *get_current_db_name(void); +extern const char *get_cuurent_pltsql_db_name(void); extern void bbf_set_current_user(const char *user_name); extern void set_session_properties(const char *db_name); extern void check_session_db_access(const char *dn_name); From 4fa94234ff14d429e0a15cd23181e08db24fab99 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Mon, 14 Oct 2024 18:42:55 +0000 Subject: [PATCH 31/41] fix is_member Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/sql/sys_functions.sql | 4 +++- .../sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/sys_functions.sql b/contrib/babelfishpg_tsql/sql/sys_functions.sql index e66e6b61f5..82ca50c108 100644 --- a/contrib/babelfishpg_tsql/sql/sys_functions.sql +++ b/contrib/babelfishpg_tsql/sql/sys_functions.sql @@ -4501,7 +4501,9 @@ BEGIN END IF; ELSIF EXISTS (SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE orig_username = role COLLATE sys.database_default) THEN - IF EXISTS (SELECT name FROM sys.user_token WHERE name = role COLLATE sys.database_default) + IF (((SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE rolname = CURRENT_USER) = 'dbo') AND role IN ('db_owner', 'db_accessadmin')) + THEN RETURN 1; + ELSIF EXISTS (SELECT name FROM sys.user_token WHERE name = role COLLATE sys.database_default) THEN RETURN 1; -- Return 1 if current session user is a member of role or windows group ELSIF (is_windows_grp) THEN RETURN NULL; -- Return NULL if session is not a windows auth session but argument is a windows group diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index 7469e7c243..8d8df301d3 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -1056,7 +1056,9 @@ BEGIN END IF; ELSIF EXISTS (SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE orig_username = role COLLATE sys.database_default) THEN - IF EXISTS (SELECT name FROM sys.user_token WHERE name = role COLLATE sys.database_default) + IF (((SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE rolname = CURRENT_USER) = 'dbo') AND role IN ('db_owner', 'db_accessadmin')) + THEN RETURN 1; + ELSIF EXISTS (SELECT name FROM sys.user_token WHERE name = role COLLATE sys.database_default) THEN RETURN 1; -- Return 1 if current session user is a member of role or windows group ELSIF (is_windows_grp) THEN RETURN NULL; -- Return NULL if session is not a windows auth session but argument is a windows group From de9321710fc8dc4b5be8d0c6445d4d4c6a0b3d25 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Mon, 14 Oct 2024 18:49:49 +0000 Subject: [PATCH 32/41] fix is_member Signed-off-by: Tanzeel Khan --- .../expected/db_accessadmin-vu-verify.out | 37 ++++++++++++++++++- .../single_db/db_accessadmin-vu-verify.out | 37 ++++++++++++++++++- test/JDBC/input/db_accessadmin-vu-verify.mix | 12 +++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/test/JDBC/expected/db_accessadmin-vu-verify.out b/test/JDBC/expected/db_accessadmin-vu-verify.out index 778ea4ca2f..8c8ca2cf09 100644 --- a/test/JDBC/expected/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/db_accessadmin-vu-verify.out @@ -105,7 +105,7 @@ GO REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO --- IS_ROLEMEMBER should show db_accessadmin as member of dbo but not of db_owner +-- IS_ROLEMEMBER & IS_MEMBER should show db_accessadmin as member of dbo but not of db_owner SELECT IS_ROLEMEMBER('db_accessadmin') GO ~~START~~ @@ -127,6 +127,41 @@ int 0 ~~END~~ +SELECT IS_ROLEMEMBER('babel_5136_r1', 'dbo') +GO +~~START~~ +int +0 +~~END~~ + +SELECT IS_MEMBER('db_accessadmin') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_MEMBER('dbo') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_MEMBER('db_owner') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_MEMBER('babel_5136_r1') +GO +~~START~~ +int +0 +~~END~~ + -- terminate-tsql-conn -- tsql user=babel_5136_l1 password=12345678 database=babel_5136 diff --git a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out index 57c4e1a1ea..d39b87cfc1 100644 --- a/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out +++ b/test/JDBC/expected/single_db/db_accessadmin-vu-verify.out @@ -105,7 +105,7 @@ GO REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO --- IS_ROLEMEMBER should show db_accessadmin as member of dbo but not of db_owner +-- IS_ROLEMEMBER & IS_MEMBER should show db_accessadmin as member of dbo but not of db_owner SELECT IS_ROLEMEMBER('db_accessadmin') GO ~~START~~ @@ -127,6 +127,41 @@ int 0 ~~END~~ +SELECT IS_ROLEMEMBER('babel_5136_r1', 'dbo') +GO +~~START~~ +int +0 +~~END~~ + +SELECT IS_MEMBER('db_accessadmin') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_MEMBER('dbo') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_MEMBER('db_owner') +GO +~~START~~ +int +1 +~~END~~ + +SELECT IS_MEMBER('babel_5136_r1') +GO +~~START~~ +int +0 +~~END~~ + -- terminate-tsql-conn -- tsql user=babel_5136_l1 password=12345678 database=babel_5136 diff --git a/test/JDBC/input/db_accessadmin-vu-verify.mix b/test/JDBC/input/db_accessadmin-vu-verify.mix index cca87664b6..7764a3e594 100644 --- a/test/JDBC/input/db_accessadmin-vu-verify.mix +++ b/test/JDBC/input/db_accessadmin-vu-verify.mix @@ -60,13 +60,23 @@ GO REVOKE CONNECT FROM babel_5136_db_accessadmin_user GO --- IS_ROLEMEMBER should show db_accessadmin as member of dbo but not of db_owner +-- IS_ROLEMEMBER & IS_MEMBER should show db_accessadmin as member of dbo but not of db_owner SELECT IS_ROLEMEMBER('db_accessadmin') GO SELECT IS_ROLEMEMBER('db_accessadmin', 'dbo') GO SELECT IS_ROLEMEMBER('db_accessadmin', 'db_owner') GO +SELECT IS_ROLEMEMBER('babel_5136_r1', 'dbo') +GO +SELECT IS_MEMBER('db_accessadmin') +GO +SELECT IS_MEMBER('dbo') +GO +SELECT IS_MEMBER('db_owner') +GO +SELECT IS_MEMBER('babel_5136_r1') +GO -- terminate-tsql-conn -- Only db_owner members should be able to do this From dc0ae6758922c797d4b2124a36674d346fcad5db Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Mon, 14 Oct 2024 19:37:01 +0000 Subject: [PATCH 33/41] fix Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/sql/sys_functions.sql | 2 +- .../sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/sys_functions.sql b/contrib/babelfishpg_tsql/sql/sys_functions.sql index 82ca50c108..90ab7a5639 100644 --- a/contrib/babelfishpg_tsql/sql/sys_functions.sql +++ b/contrib/babelfishpg_tsql/sql/sys_functions.sql @@ -4501,7 +4501,7 @@ BEGIN END IF; ELSIF EXISTS (SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE orig_username = role COLLATE sys.database_default) THEN - IF (((SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE rolname = CURRENT_USER) = 'dbo') AND role IN ('db_owner', 'db_accessadmin')) + IF (((SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE rolname = CURRENT_USER) = 'dbo' COLLATE sys.database_default) AND role COLLATE sys.database_default IN ('db_owner', 'db_accessadmin')) THEN RETURN 1; ELSIF EXISTS (SELECT name FROM sys.user_token WHERE name = role COLLATE sys.database_default) THEN RETURN 1; -- Return 1 if current session user is a member of role or windows group diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index 8d8df301d3..f004b136c2 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -1056,7 +1056,7 @@ BEGIN END IF; ELSIF EXISTS (SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE orig_username = role COLLATE sys.database_default) THEN - IF (((SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE rolname = CURRENT_USER) = 'dbo') AND role IN ('db_owner', 'db_accessadmin')) + IF (((SELECT orig_username FROM sys.babelfish_authid_user_ext WHERE rolname = CURRENT_USER) = 'dbo' COLLATE sys.database_default) AND role COLLATE sys.database_default IN ('db_owner', 'db_accessadmin')) THEN RETURN 1; ELSIF EXISTS (SELECT name FROM sys.user_token WHERE name = role COLLATE sys.database_default) THEN RETURN 1; -- Return 1 if current session user is a member of role or windows group From ce81810bfa706aac967f6b3995d16109ede133f2 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Tue, 15 Oct 2024 12:51:03 +0000 Subject: [PATCH 34/41] refactor upgrade function for creating roles Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/dbcmds.c | 191 +++++++++++++++----------- 1 file changed, 108 insertions(+), 83 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 85e5b3edd7..6a55acde1c 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -1265,6 +1265,79 @@ create_guest_schema_for_all_dbs(PG_FUNCTION_ARGS) PG_RETURN_INT32(0); } +static void +create_db_roles_if_not_exists(const char *dbname, List *parsetree_list) +{ + Node *stmt; + Oid save_userid; + int save_sec_context; + int i = 0; + char *db_owner; + char *db_accessadmin; + + db_owner = get_db_owner_name(dbname); + db_accessadmin = get_db_accessadmin_role_name(dbname); + + if (OidIsValid(get_role_oid(db_accessadmin, true))) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("role \"%s\" already exists. Please drop the role and restart upgrade.", db_accessadmin))); + + stmt = parsetree_nth_stmt(parsetree_list, i++); + update_CreateRoleStmt(stmt, db_accessadmin, db_owner, NULL); + + stmt = parsetree_nth_stmt(parsetree_list, i++); + update_GrantStmt(stmt, get_database_name(MyDatabaseId), NULL, db_accessadmin, NULL); + + GetUserIdAndSecContext(&save_userid, &save_sec_context); + + PG_TRY(); + { + ListCell *parsetree_item; + + SetConfigOption("createrole_self_grant", "inherit", PGC_USERSET, PGC_S_OVERRIDE); + add_to_bbf_authid_user_ext(db_accessadmin, DB_ACCESSADMIN, dbname, NULL, NULL, true, true, false); + + foreach(parsetree_item, parsetree_list) + { + PlannedStmt *wrapper; + + if (stmt->type == T_GrantStmt) + { + SetUserIdAndSecContext(get_role_oid("sysadmin", false), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + } + else + { + SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + } + + wrapper = makeNode(PlannedStmt); + wrapper->commandType = CMD_UTILITY; + wrapper->canSetTag = false; + wrapper->utilityStmt = ((RawStmt *) lfirst(parsetree_item))->stmt; + wrapper->stmt_location = 0; + + ProcessUtility(wrapper, + CREATE_FIXED_DB_ROLES, + false, + PROCESS_UTILITY_SUBCOMMAND, + NULL, + NULL, + None_Receiver, + NULL); + + CommandCounterIncrement(); + } + } + PG_FINALLY(); + { + SetUserIdAndSecContext(save_userid, save_sec_context); + pfree(db_owner); + pfree(db_accessadmin); + } + PG_END_TRY(); +} + /* * This function is only being used during upgrade to v4.4.0 @@ -1274,15 +1347,13 @@ PG_FUNCTION_INFO_V1(create_database_roles_for_all_dbs); Datum create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) { - Relation sysdatabase_rel; - TableScanDesc scan; - HeapTuple tuple; - Form_sysdatabases bbf_db; - StringInfoData query; - List *parsetree_list; - char *dbname; - int pltsql_save_nestlevel; - int save_nestlevel; + Relation sysdatabase_rel; + TableScanDesc scan; + HeapTuple tuple; + StringInfoData query; + List *parsetree_list; + int pltsql_save_nestlevel; + int save_nestlevel; if (!creating_extension) ereport(ERROR, @@ -1292,95 +1363,49 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) pltsql_save_nestlevel = pltsql_new_guc_nest_level(); save_nestlevel = NewGUCNestLevel(); - set_config_option("babelfishpg_tsql.sql_dialect", "tsql", - GUC_CONTEXT_CONFIG, - PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); - set_config_option("babelfishpg_tsql.migration_mode", physical_schema_name_exists("dbo") ? "single-db" : "multi-db", - GUC_CONTEXT_CONFIG, - PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); - - initStringInfo(&query); - - appendStringInfo(&query, "CREATE ROLE dummy ROLE dummy; "); - appendStringInfo(&query, "GRANT CREATE ON DATABASE dummy TO dummy; "); - parsetree_list = raw_parser(query.data, RAW_PARSE_DEFAULT); - - sysdatabase_rel = table_open(sysdatabases_oid, RowExclusiveLock); - scan = table_beginscan_catalog(sysdatabase_rel, 0, NULL); - - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + PG_TRY(); { - Node *stmt; - Oid save_userid; - int save_sec_context; - int i = 0; - const char *db_owner; - const char *db_accessadmin; + set_config_option("babelfishpg_tsql.sql_dialect", "tsql", + GUC_CONTEXT_CONFIG, + PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); + set_config_option("babelfishpg_tsql.migration_mode", physical_schema_name_exists(DBO) ? "single-db" : "multi-db", + GUC_CONTEXT_CONFIG, + PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); - bbf_db = (Form_sysdatabases) GETSTRUCT(tuple); - dbname = text_to_cstring(&(bbf_db->name)); - db_owner = get_db_owner_name(dbname); - db_accessadmin = get_db_accessadmin_role_name(dbname); + initStringInfo(&query); - stmt = parsetree_nth_stmt(parsetree_list, i++); - update_CreateRoleStmt(stmt, db_accessadmin, db_owner, NULL); + appendStringInfo(&query, "CREATE ROLE dummy ROLE dummy; "); + appendStringInfo(&query, "GRANT CREATE ON DATABASE dummy TO dummy; "); - stmt = parsetree_nth_stmt(parsetree_list, i++); - update_GrantStmt(stmt, get_database_name(MyDatabaseId), NULL, db_accessadmin, NULL); + parsetree_list = raw_parser(query.data, RAW_PARSE_DEFAULT); - GetUserIdAndSecContext(&save_userid, &save_sec_context); + sysdatabase_rel = table_open(sysdatabases_oid, RowExclusiveLock); + scan = table_beginscan_catalog(sysdatabase_rel, 0, NULL); - PG_TRY(); + while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { - ListCell *parsetree_item; + Datum datum; + bool is_null; + char *db_name; - SetConfigOption("createrole_self_grant", "inherit", PGC_USERSET, PGC_S_OVERRIDE); - add_to_bbf_authid_user_ext(db_accessadmin, DB_ACCESSADMIN, dbname, NULL, NULL, true, true, false); + datum = heap_getattr(tuple, Anum_sysdatabases_name, + sysdatabase_rel->rd_att, &is_null); + db_name = TextDatumGetCString(datum); - foreach(parsetree_item, parsetree_list) - { - PlannedStmt *wrapper; + create_db_roles_if_not_exists(db_name, parsetree_list); - if (stmt->type == T_GrantStmt) - { - SetUserIdAndSecContext(get_role_oid("sysadmin", false), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); - } - else - { - SetUserIdAndSecContext(get_bbf_role_admin_oid(), save_sec_context | SECURITY_LOCAL_USERID_CHANGE); - } - - wrapper = makeNode(PlannedStmt); - wrapper->commandType = CMD_UTILITY; - wrapper->canSetTag = false; - wrapper->utilityStmt = ((RawStmt *) lfirst(parsetree_item))->stmt; - wrapper->stmt_location = 0; - - ProcessUtility(wrapper, - CREATE_FIXED_DB_ROLES, - false, - PROCESS_UTILITY_SUBCOMMAND, - NULL, - NULL, - None_Receiver, - NULL); - - CommandCounterIncrement(); - } + pfree(db_name); } - PG_FINALLY(); - { - SetUserIdAndSecContext(save_userid, save_sec_context); - } - PG_END_TRY(); - - pfree(dbname); - } + PG_FINALLY(); + { + pltsql_revert_guc(pltsql_save_nestlevel); + } + PG_END_TRY(); + pfree(query.data); AtEOXact_GUC(false, save_nestlevel); - pltsql_revert_guc(pltsql_save_nestlevel); table_endscan(scan); table_close(sysdatabase_rel, RowExclusiveLock); From d2f5540ec1d9ec4921aa27ffd4e7459247f90b8a Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Tue, 15 Oct 2024 12:59:12 +0000 Subject: [PATCH 35/41] refactor Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 11 +++-------- contrib/babelfishpg_tsql/src/dbcmds.c | 7 +++++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index d347793d03..3705ac9657 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -912,10 +912,7 @@ get_authid_user_ext_idx_oid(void) return bbf_authid_user_ext_idx_oid; } -/* - * Returns palloc'd original name given the physical name of the db principal - * Looks only in current bbf db when current_db_only is set to true - */ +/* Returns palloc'd original name given the physical name of the db principal */ char * get_authid_user_ext_original_name(const char *physical_role_name, const char *db_name) { @@ -924,6 +921,7 @@ get_authid_user_ext_original_name(const char *physical_role_name, const char *db HeapTuple tuple; Assert(physical_role_name && strlen(physical_role_name) != 0); + Assert(db_name && strlen(db_name) != 0); tuple = SearchSysCache1(AUTHIDUSEREXTROLENAME, CStringGetDatum(physical_role_name)); @@ -942,12 +940,10 @@ get_authid_user_ext_original_name(const char *physical_role_name, const char *db datum = SysCacheGetAttr(AUTHIDUSEREXTROLENAME, tuple, Anum_bbf_authid_user_ext_orig_username, &isnull); Assert(!isnull); - orig_username = TextDatumGetCString(datum); } pfree(db_name_cstring); - ReleaseSysCache(tuple); } @@ -1005,9 +1001,8 @@ get_authid_user_ext_physical_name(const char *db_name, const char *login) (has_privs_of_role(get_role_oid(login, false), get_db_accessadmin_oid(db_name, false)))) { datum = heap_getattr(tuple_user_ext, Anum_bbf_authid_user_ext_rolname, - RelationGetDescr(bbf_authid_user_ext_rel), &isnull); + RelationGetDescr(bbf_authid_user_ext_rel), &isnull); Assert(!isnull); - user_name = pstrdup(DatumGetCString(datum)); } } diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 6a55acde1c..8f755a3c35 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -1386,11 +1386,14 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { Datum datum; - bool is_null; + bool isnull; char *db_name; datum = heap_getattr(tuple, Anum_sysdatabases_name, - sysdatabase_rel->rd_att, &is_null); + sysdatabase_rel->rd_att, &isnull); + + Assert(!isnull); + db_name = TextDatumGetCString(datum); create_db_roles_if_not_exists(db_name, parsetree_list); From 06b1d639758235687b7d77cb4e716f03887a2937 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 17 Oct 2024 13:49:19 +0000 Subject: [PATCH 36/41] fix merge issue Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/sql/ownership.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/babelfishpg_tsql/sql/ownership.sql b/contrib/babelfishpg_tsql/sql/ownership.sql index e487107643..226fc47926 100644 --- a/contrib/babelfishpg_tsql/sql/ownership.sql +++ b/contrib/babelfishpg_tsql/sql/ownership.sql @@ -262,6 +262,7 @@ DECLARE reserved_roles varchar[] := ARRAY['sysadmin', 'securityadmin', 'master_dbo', 'master_guest', 'master_db_owner', 'master_db_accessadmin', 'tempdb_dbo', 'tempdb_guest', 'tempdb_db_owner', 'tempdb_db_accessadmin', + 'msdb_dbo', 'msdb_guest', 'msdb_db_owner', 'msdb_db_accessadmin']; user_id oid := -1; db_name name := NULL; From b640fea7d92137c4bd69daad6bc9f6b03ec14ed9 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 17 Oct 2024 14:09:45 +0000 Subject: [PATCH 37/41] refactor name for upgrade function Signed-off-by: Tanzeel Khan --- .../sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql | 8 ++++---- contrib/babelfishpg_tsql/src/dbcmds.c | 6 +++--- .../expected/sql_validation_framework/expected_drop.out | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index f5023a9533..41383d7e32 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -71,13 +71,13 @@ END; $$; -CREATE OR REPLACE PROCEDURE sys.babel_create_database_roles() +CREATE OR REPLACE PROCEDURE sys.create_db_roles_during_upgrade() LANGUAGE C -AS 'babelfishpg_tsql', 'create_database_roles_for_all_dbs'; +AS 'babelfishpg_tsql', 'create_db_roles_during_upgrade'; -CALL sys.babel_create_database_roles(); +CALL sys.create_db_roles_during_upgrade(); -DROP PROCEDURE sys.babel_create_database_roles(); +DROP PROCEDURE sys.create_db_roles_during_upgrade(); DO LANGUAGE plpgsql diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 8f755a3c35..8a1cdbf130 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -1343,9 +1343,9 @@ create_db_roles_if_not_exists(const char *dbname, List *parsetree_list) * This function is only being used during upgrade to v4.4.0 * to create database roles db_accessadmin for each database */ -PG_FUNCTION_INFO_V1(create_database_roles_for_all_dbs); +PG_FUNCTION_INFO_V1(create_db_roles_during_upgrade); Datum -create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) +create_db_roles_during_upgrade(PG_FUNCTION_ARGS) { Relation sysdatabase_rel; TableScanDesc scan; @@ -1359,7 +1359,7 @@ create_database_roles_for_all_dbs(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("%s can only be called from an SQL script executed by CREATE/ALTER EXTENSION", - "create_database_roles_for_all_dbs()"))); + "create_db_roles_during_upgrade()"))); pltsql_save_nestlevel = pltsql_new_guc_nest_level(); save_nestlevel = NewGUCNestLevel(); diff --git a/test/python/expected/sql_validation_framework/expected_drop.out b/test/python/expected/sql_validation_framework/expected_drop.out index 4a62e9e4fb..ec6da0c9d8 100644 --- a/test/python/expected/sql_validation_framework/expected_drop.out +++ b/test/python/expected/sql_validation_framework/expected_drop.out @@ -43,7 +43,7 @@ Unexpected drop found for operator sys./ in file babelfishpg_common--1.1.0--1.2. Unexpected drop found for operator sys./ in file babelfishpg_common--1.1.0--1.2.0.sql Unexpected drop found for operator sys./ in file babelfishpg_common--1.1.0--1.2.0.sql Unexpected drop found for procedure babelfish_drop_deprecated_opclass in file babelfishpg_common--1.0.0--1.1.0.sql -Unexpected drop found for procedure sys.babel_create_database_roles in file babelfishpg_tsql--4.3.0--4.4.0.sql +Unexpected drop found for procedure sys.create_db_roles_during_upgrade in file babelfishpg_tsql--4.3.0--4.4.0.sql Unexpected drop found for procedure sys.babel_create_guest_schemas in file babelfishpg_tsql--2.3.0--2.4.0.sql Unexpected drop found for procedure sys.babel_create_guest_schemas in file babelfishpg_tsql--3.0.0--3.1.0.sql Unexpected drop found for procedure sys.babelfish_alter_default_privilege_on_schema in file babelfishpg_tsql--4.3.0--4.4.0.sql From e77a11ff6bad47c4d029abef5f98533bf7cd66fe Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 17 Oct 2024 14:19:08 +0000 Subject: [PATCH 38/41] use IS_BBF_BUILT_IN_DB macro in some more places Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/catalog.c | 5 ++--- contrib/babelfishpg_tsql/src/dbcmds.c | 6 ++---- contrib/babelfishpg_tsql/src/multidb.c | 4 +--- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 3705ac9657..6e09e0f02a 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -450,13 +450,12 @@ get_one_user_db_name(void) db_name = TextDatumGetCString(name); /* check that db_name is not "master", "tempdb", or "msdb" */ - if ((strlen(db_name) != 6 || (strncmp(db_name, "master", 6) != 0)) && - (strlen(db_name) != 6 || (strncmp(db_name, "tempdb", 6) != 0)) && - (strlen(db_name) != 4 || (strncmp(db_name, "msdb", 4) != 0))) + if (!IS_BBF_BUILT_IN_DB(db_name)) { user_db_name = db_name; break; } + pfree(db_name); tuple = heap_getnext(scan, ForwardScanDirection); } diff --git a/contrib/babelfishpg_tsql/src/dbcmds.c b/contrib/babelfishpg_tsql/src/dbcmds.c index 8a1cdbf130..2755a370ee 100644 --- a/contrib/babelfishpg_tsql/src/dbcmds.c +++ b/contrib/babelfishpg_tsql/src/dbcmds.c @@ -233,7 +233,7 @@ add_fixed_user_roles_to_bbf_authid_user_ext(const char *dbname) * For master, tempdb and msdb databases, the guest user will be * enabled by default */ - if (strcmp(dbname, "master") == 0 || strcmp(dbname, "tempdb") == 0 || strcmp(dbname, "msdb") == 0) + if (IS_BBF_BUILT_IN_DB(dbname)) add_to_bbf_authid_user_ext(guest, "guest", dbname, "guest", NULL, false, true, false); else add_to_bbf_authid_user_ext(guest, "guest", dbname, "guest", NULL, false, false, false); @@ -689,9 +689,7 @@ drop_bbf_db(const char *dbname, bool missing_ok, bool force_drop) bool is_set_userid = false; Oid save_userid; - if ((strlen(dbname) == 6 && (strncmp(dbname, "master", 6) == 0)) || - ((strlen(dbname) == 6 && strncmp(dbname, "tempdb", 6) == 0)) || - (strlen(dbname) == 4 && (strncmp(dbname, "msdb", 4) == 0))) + if (IS_BBF_BUILT_IN_DB(dbname)) { if (!force_drop) ereport(ERROR, diff --git a/contrib/babelfishpg_tsql/src/multidb.c b/contrib/babelfishpg_tsql/src/multidb.c index d3d8dab289..cdff39ef7c 100644 --- a/contrib/babelfishpg_tsql/src/multidb.c +++ b/contrib/babelfishpg_tsql/src/multidb.c @@ -1226,9 +1226,7 @@ get_physical_schema_name_by_mode(char *db_name, const char *schema_name, Migrati if (SINGLE_DB == mode) { - if ((strlen(db_name) == 6 && (strncmp(db_name, "master", 6) == 0)) || - (strlen(db_name) == 6 && (strncmp(db_name, "tempdb", 6) == 0)) || - (strlen(db_name) == 4 && (strncmp(db_name, "msdb", 4) == 0))) + if (IS_BBF_BUILT_IN_DB(db_name)) { result = palloc0(MAX_BBF_NAMEDATALEND); From a7c8e74698aec28ac9160a2024210c362fa64f41 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 17 Oct 2024 14:46:32 +0000 Subject: [PATCH 39/41] empty Signed-off-by: Tanzeel Khan From 0c9252880c0caac9cb70627f4eb2c9330a629b10 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Thu, 17 Oct 2024 20:35:23 +0000 Subject: [PATCH 40/41] fix upgrade file Signed-off-by: Tanzeel Khan --- .../babelfishpg_tsql--4.3.0--4.4.0.sql | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql index 41383d7e32..5c30a40c7c 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--4.3.0--4.4.0.sql @@ -1924,56 +1924,6 @@ FROM pg_catalog.pg_class t1 JOIN information_schema.table_privileges t4 ON t1.relname = t4.table_name WHERE t4.privilege_type = 'DELETE'; -CREATE OR REPLACE FUNCTION is_srvrolemember(role sys.SYSNAME, login sys.SYSNAME DEFAULT suser_name()) -RETURNS INTEGER AS -$$ -DECLARE has_role BOOLEAN; -DECLARE login_valid BOOLEAN; -BEGIN - role := TRIM(trailing from LOWER(role)); - login := TRIM(trailing from LOWER(login)); - - login_valid = (login = suser_name() COLLATE sys.database_default) OR - (EXISTS (SELECT name - FROM sys.server_principals - WHERE - LOWER(name) = login COLLATE sys.database_default - AND type = 'S')); - - IF NOT login_valid THEN - RETURN NULL; - - ELSIF role = 'public' COLLATE sys.database_default THEN - RETURN 1; - - ELSIF role = 'sysadmin' COLLATE sys.database_default THEN - has_role = pg_has_role(login::TEXT, role::TEXT, 'MEMBER'); - IF has_role THEN - RETURN 1; - ELSE - RETURN 0; - END IF; - - ELSIF role COLLATE sys.database_default IN ( - 'serveradmin', - 'securityadmin', - 'setupadmin', - 'securityadmin', - 'processadmin', - 'dbcreator', - 'diskadmin', - 'bulkadmin') THEN - RETURN 0; - - ELSE - RETURN NULL; - END IF; - - EXCEPTION WHEN OTHERS THEN - RETURN NULL; -END; -$$ LANGUAGE plpgsql STABLE; - CREATE OR REPLACE PROCEDURE sys.sp_helpuser("@name_in_db" sys.SYSNAME = NULL) AS $$ BEGIN @@ -2087,7 +2037,6 @@ END; $$ LANGUAGE 'pltsql'; - create or replace view sys.types As with RECURSIVE type_code_list as ( From 83e9771a97158e44cd6b676e1a75c910f86ba479 Mon Sep 17 00:00:00 2001 From: Tanzeel Khan Date: Fri, 18 Oct 2024 08:35:47 +0000 Subject: [PATCH 41/41] fix typo Signed-off-by: Tanzeel Khan --- contrib/babelfishpg_tsql/src/pl_handler.c | 6 +++--- contrib/babelfishpg_tsql/src/rolecmds.c | 6 +++--- contrib/babelfishpg_tsql/src/session.c | 4 ++-- contrib/babelfishpg_tsql/src/session.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index efa95ec2b1..9fd72ce252 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3612,9 +3612,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (is_login(roleform->oid)) all_logins = true; - else if (get_db_principal_kind(roleform->oid, get_cuurent_pltsql_db_name()) == BBF_USER) + else if (get_db_principal_kind(roleform->oid, get_current_pltsql_db_name()) == BBF_USER) all_users = true; - else if (get_db_principal_kind(roleform->oid, get_cuurent_pltsql_db_name()) == BBF_ROLE) + else if (get_db_principal_kind(roleform->oid, get_current_pltsql_db_name()) == BBF_ROLE) all_roles = true; else other = true; @@ -3715,7 +3715,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } else if (rolspec && strcmp(queryString, CREATE_FIXED_DB_ROLES) != 0) { - const char *db_name = get_cuurent_pltsql_db_name(); + const char *db_name = get_current_pltsql_db_name(); Oid db_accessadmin = get_db_accessadmin_oid(db_name, false); owner_oid = get_rolespec_oid(rolspec, true); diff --git a/contrib/babelfishpg_tsql/src/rolecmds.c b/contrib/babelfishpg_tsql/src/rolecmds.c index 3d11b567ab..7c14f26b16 100644 --- a/contrib/babelfishpg_tsql/src/rolecmds.c +++ b/contrib/babelfishpg_tsql/src/rolecmds.c @@ -293,7 +293,7 @@ drop_bbf_roles(ObjectAccessType access, { if (is_login(roleid)) drop_bbf_authid_login_ext(access, classId, roleid, subId, arg); - else if (get_db_principal_kind(roleid, get_cuurent_pltsql_db_name())) + else if (get_db_principal_kind(roleid, get_current_pltsql_db_name())) drop_bbf_authid_user_ext(access, classId, roleid, subId, arg); } @@ -1789,7 +1789,7 @@ is_alter_role_stmt(GrantRoleStmt *stmt) Oid granted = get_role_oid(spec->rolename, true); /* Check if the granted role is an existing database role */ - if (granted == InvalidOid || get_db_principal_kind(granted, get_cuurent_pltsql_db_name()) != BBF_ROLE) + if (granted == InvalidOid || get_db_principal_kind(granted, get_current_pltsql_db_name()) != BBF_ROLE) return false; } @@ -1804,7 +1804,7 @@ check_alter_role_stmt(GrantRoleStmt *stmt) const char *granted_name; const char *grantee_name; const char *original_user_name; - const char *db_name = get_cuurent_pltsql_db_name(); + const char *db_name = get_current_pltsql_db_name(); RoleSpec *granted_spec; RoleSpec *grantee_spec; diff --git a/contrib/babelfishpg_tsql/src/session.c b/contrib/babelfishpg_tsql/src/session.c index 008320dc36..7953611b48 100644 --- a/contrib/babelfishpg_tsql/src/session.c +++ b/contrib/babelfishpg_tsql/src/session.c @@ -48,7 +48,7 @@ get_cur_db_id(void) return current_db_id; } -/* same as get_cuurent_pltsql_db_name but reurn value is palloc'd */ +/* same as get_current_pltsql_db_name but reurn value is palloc'd */ char * get_cur_db_name(void) { @@ -60,7 +60,7 @@ get_cur_db_name(void) * Callers should NOT pfree the return value */ const char * -get_cuurent_pltsql_db_name(void) +get_current_pltsql_db_name(void) { return current_db_name; } diff --git a/contrib/babelfishpg_tsql/src/session.h b/contrib/babelfishpg_tsql/src/session.h index 1e4f136804..82f58e3bd9 100644 --- a/contrib/babelfishpg_tsql/src/session.h +++ b/contrib/babelfishpg_tsql/src/session.h @@ -7,7 +7,7 @@ extern int16 get_cur_db_id(void); extern void set_cur_db(int16 id, const char *name); extern char *get_cur_db_name(void); -extern const char *get_cuurent_pltsql_db_name(void); +extern const char *get_current_pltsql_db_name(void); extern void bbf_set_current_user(const char *user_name); extern void set_session_properties(const char *db_name); extern void check_session_db_access(const char *dn_name);