6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 13:33:07 +01:00

Added/Updated tests\bugs\gh_6935_test.py: Checked on 6.0.0.163, 5.0.0.1284, 4.0.5.3033. RE-IMPLEMENTED. See notes about comments handling by ISQL after implementation of SET AUTOTERM, PR #7868

This commit is contained in:
pavel-zotov 2023-12-01 23:09:43 +03:00
parent 60eff4140e
commit 16d18e4201

View File

@ -62,6 +62,19 @@ NOTES:
[01.09.2021]
Added "where"-filtering for exclude statement with query to RDB$AUTH_MAPPING (4.0 Classic).
FBTEST: bugs.gh_6935
NOTES:
[01.12.2023] pzotov
New behaviour of ISQL was introduced after implementation of PR #7868: SET AUTOTERM.
Since that was implemented, ISQL handles comments (single- and multi-lined) as PART of statement that follows these comments.
In other words, ISQL in 6.x does not 'swallow' comments and sends them to engine together with statement that follows.
This means that such 'pair' (comment PLUS statement) can be 'unexpectedly' seen in MON$STATEMENTS.MON$SQL_TEXT.
Currently this is not considered as a bug, see note by Adriano: https://groups.google.com/g/firebird-devel/c/AM8vlA3YJws
Because of this, we have (in this test) to either not use comments at all or filter them out by applying substitution which
will 'know' about some special text ('comment_tag') that must be suppressed.
Checked on 6.0.0.163, 5.0.0.1284, 4.0.5.3033
"""
import pytest
@ -69,310 +82,310 @@ from firebird.qa import *
db = db_factory()
test_script = """
set list on;
set bail on;
create table log_table(id int, eff_user varchar(32), mon_user varchar(32) );
COMMENT_TAG='DONT_SHOW_IN_OUTPUT'
test_script = f"""
set list on;
set bail on;
create table log_table(id int, eff_user varchar(32), mon_user varchar(32) );
create or alter user tmp$sp_definer password '123';
create or alter user tmp$outside_caller password '123';
create or alter user tmp$almost_dba password '123';
commit;
create or alter user tmp$sp_definer password '123';
create or alter user tmp$outside_caller password '123';
create or alter user tmp$almost_dba password '123';
commit;
grant create procedure to tmp$sp_definer;
commit;
grant create procedure to tmp$sp_definer;
commit;
--###################################################
connect '$(DSN)' user tmp$sp_definer password '123';
--###################################################
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user tmp$sp_definer password '123';
-- {COMMENT_TAG} ###################################################
set term ^;
create or alter procedure sp_chk_mon_access
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,mon_user varchar(32)
,executing_sql_blob blob sub_type text
) sql security definer
as
declare c int;
begin
who_am_i = current_user;
eff_user = rdb$get_context('SYSTEM', 'EFFECTIVE_USER');
for
select
a.mon$user
,s.mon$sql_text
from rdb$database r
left join
( mon$attachments a
join mon$statements s on a.mon$attachment_id = s.mon$attachment_id and s.mon$sql_text not like '%RDB$AUTH_MAPPING%'
) on 1=1
where
a.mon$system_flag is distinct from 1
into mon_user, executing_sql_blob
do
set term ^;
create or alter procedure sp_chk_mon_access
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,mon_user varchar(32)
,executing_sql_blob blob sub_type text
) sql security definer
as
declare c int;
begin
suspend;
end
end
^
who_am_i = current_user;
create or alter procedure sp_clear_ext_pool
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,access_info varchar(255)
) sql security definer
as
begin
eff_user = rdb$get_context('SYSTEM', 'EFFECTIVE_USER');
who_am_i = current_user;
eff_user = rdb$get_context('SYSTEM', 'EFFECTIVE_USER');
begin
execute statement 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL';
access_info = 'Ext. pool clear all @@@ PASSED @@@';
when any do
begin
access_info = 'Ext. pool clear all ### FAILED ###, gdscode: ' || gdscode;
end
end
suspend;
end
^
create or alter procedure sp_chk_sql_rights
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,access_info varchar(255)
) sql security definer
as
declare c int;
begin
who_am_i = current_user;
eff_user = rdb$get_context('SYSTEM', 'EFFECTIVE_USER');
begin
-- ::: NB ::: exception raised in static PSQL can not be suppressed!
-- insert into log_table(id, eff_user, mon_user)
-- values(current_connection, :eff_user, :mon_user);
execute statement
( q'{insert /* current_user: '}'|| current_user || q'{, effective_user: '}'|| eff_user ||q'{' */ into log_table(id, eff_user, mon_user) values( ?, ?, ? )}' )
( current_connection, :eff_user, :who_am_i )
;
access_info = 'Insert into log_table @@@ PASSED @@@';
when any do
for
select
a.mon$user
,s.mon$sql_text
from rdb$database r
left join
( mon$attachments a
join mon$statements s on a.mon$attachment_id = s.mon$attachment_id and s.mon$sql_text not like '%RDB$AUTH_MAPPING%'
) on 1=1
where
a.mon$system_flag is distinct from 1
into mon_user, executing_sql_blob
do
begin
access_info = 'Insert into log_table ### FAILED ###, gdscode: ' || gdscode;
suspend;
end
end
^
suspend;
create or alter procedure sp_clear_ext_pool
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,access_info varchar(255)
) sql security definer
as
begin
end
^
set term ;^
commit;
who_am_i = current_user;
eff_user = rdb$get_context('SYSTEM', 'EFFECTIVE_USER');
begin
execute statement 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL';
access_info = 'Ext. pool clear all @@@ PASSED @@@';
when any do
begin
access_info = 'Ext. pool clear all ### FAILED ###, gdscode: ' || gdscode;
end
end
suspend;
end
^
--###################################################
connect '$(DSN)' user sysdba password 'masterkey';
--###################################################
create or alter procedure sp_chk_sql_rights
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,access_info varchar(255)
) sql security definer
as
declare c int;
begin
who_am_i = current_user;
eff_user = rdb$get_context('SYSTEM', 'EFFECTIVE_USER');
begin
-- ::: NB ::: exception raised in static PSQL can not be suppressed!
-- insert into log_table(id, eff_user, mon_user)
-- values(current_connection, :eff_user, :mon_user);
execute statement
( q'!insert /* current_user: '!'|| current_user || q'!, effective_user: '!'|| eff_user ||q'!' */ into log_table(id, eff_user, mon_user) values( ?, ?, ? )!' )
( current_connection, :eff_user, :who_am_i )
;
access_info = 'Insert into log_table @@@ PASSED @@@';
when any do
begin
access_info = 'Insert into log_table ### FAILED ###, gdscode: ' || gdscode;
end
end
set term ^;
create or alter procedure sp_chk_syspriv_main (
a_run_as_who varchar(32)
)
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,mon_user varchar(32)
,executing_sql_blob blob sub_type text
) as
begin
for
execute statement
(
'select /* Inside sp_chk_syspriv_main. Enter SP as: ' || current_user
|| ', run ES as: ' || upper(:a_run_as_who)
|| ' */ who_am_i, eff_user, mon_user, executing_sql_blob'
|| ' from sp_chk_mon_access' -- its definer is 'tmp$sp_definer'
)
as user :a_run_as_who password '123'
into
who_am_i, eff_user, mon_user, executing_sql_blob
do begin
suspend;
end
end
^
set term ;^
commit;
revoke create procedure from tmp$sp_definer;
grant execute on procedure sp_chk_syspriv_main to public;
grant execute on procedure sp_chk_mon_access to tmp$outside_caller;
grant execute on procedure sp_chk_sql_rights to tmp$outside_caller;
create role r_almost_dba set system privileges to MONITOR_ANY_ATTACHMENT, MODIFY_EXT_CONN_POOL, ACCESS_ANY_OBJECT_IN_DATABASE;
grant default r_almost_dba to user tmp$almost_dba;
grant execute on procedure sp_chk_mon_access to tmp$almost_dba;
grant execute on procedure sp_clear_ext_pool to tmp$almost_dba;
grant execute on procedure sp_chk_sql_rights to tmp$almost_dba;
grant select, insert on table log_table to tmp$almost_dba;
commit;
set bail off;
^
set term ;^
commit;
/************************
1. Usage of MON$ tables
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user sysdba password 'masterkey';
-- {COMMENT_TAG} ###################################################
... when effective user is *not* privileged and thus it should see only its own attachments,
in fact it sees only attachments established by the session user.
In other words, user 'tmp$outside_caller' calls procedure with definer 'tmp$sp_definer'
which (ooops) sees attachments by user 'tmp$outside_caller' .
************************/
set term ^;
create or alter procedure sp_chk_syspriv_main (
a_run_as_who varchar(32)
)
returns(
who_am_i varchar(32)
,eff_user varchar(32)
,mon_user varchar(32)
,executing_sql_blob blob sub_type text
) as
begin
for
execute statement
(
'select /* Inside sp_chk_syspriv_main. Enter SP as: ' || current_user
|| ', run ES as: ' || upper(:a_run_as_who)
|| ' */ who_am_i, eff_user, mon_user, executing_sql_blob'
|| ' from sp_chk_mon_access' -- its definer is 'tmp$sp_definer'
)
as user :a_run_as_who password '123'
into
who_am_i, eff_user, mon_user, executing_sql_blob
do begin
suspend;
end
end
^
set term ;^
commit;
revoke create procedure from tmp$sp_definer;
grant execute on procedure sp_chk_syspriv_main to public;
grant execute on procedure sp_chk_mon_access to tmp$outside_caller;
grant execute on procedure sp_chk_sql_rights to tmp$outside_caller;
create role r_almost_dba set system privileges to MONITOR_ANY_ATTACHMENT, MODIFY_EXT_CONN_POOL, ACCESS_ANY_OBJECT_IN_DATABASE;
grant default r_almost_dba to user tmp$almost_dba;
grant execute on procedure sp_chk_mon_access to tmp$almost_dba;
grant execute on procedure sp_clear_ext_pool to tmp$almost_dba;
grant execute on procedure sp_chk_sql_rights to tmp$almost_dba;
grant select, insert on table log_table to tmp$almost_dba;
commit;
set bail off;
--###################################################
connect '$(DSN)' user tmp$almost_dba password '123';
--###################################################
/************************
1. Usage of MON$ tables
commit;
set transaction read committed record_version;
... when effective user is *not* privileged and thus it should see only its own attachments,
in fact it sees only attachments established by the session user.
In other words, user 'tmp$outside_caller' calls procedure with definer 'tmp$sp_definer'
which (ooops) sees attachments by user 'tmp$outside_caller' .
************************/
set term ^;
execute block as
declare c varchar(32);
begin
execute statement q'{select 'tmp$sp_definer' from rdb$database}'
as user 'tmp$sp_definer' password '123'
into c
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user tmp$almost_dba password '123';
-- {COMMENT_TAG} ###################################################
commit;
set transaction read committed record_version;
set term ^;
execute block as
declare c varchar(32);
begin
execute statement q'!select 'tmp$sp_definer' from rdb$database!'
as user 'tmp$sp_definer' password '123'
into c
;
end
^
execute block as
declare c varchar(32);
begin
execute statement q'!select 'tmp$outside_caller' from rdb$database!'
as user 'tmp$outside_caller' password '123'
into c
;
end
^
set term ;^
select -- Invoke sp_chk_syspriv_main. Work as tmp$almost_dba
'CHECK-1' as msg
,p.*
from rdb$database
left join sp_chk_syspriv_main('tmp$outside_caller') p on 1=1
;
end
^
execute block as
declare c varchar(32);
begin
execute statement q'{select 'tmp$outside_caller' from rdb$database}'
as user 'tmp$outside_caller' password '123'
into c
commit;
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user sysdba password 'masterkey';
-- {COMMENT_TAG} ###################################################
ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;
commit;
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user tmp$sp_definer password '123';
-- {COMMENT_TAG} ###################################################
select /* Invoke sp_chk_syspriv_main. Work as tmp$sp_definer */
'CHECK-2' as msg
,p.*
from rdb$database
left join sp_chk_syspriv_main('tmp$outside_caller') p on 1=1
;
end
^
set term ;^
select -- Invoke sp_chk_syspriv_main. Work as tmp$almost_dba
'CHECK-1' as msg
,p.*
from rdb$database
left join sp_chk_syspriv_main('tmp$outside_caller') p on 1=1
;
commit;
--###################################################
connect '$(DSN)' user sysdba password 'masterkey';
--###################################################
ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;
commit;
--###################################################
connect '$(DSN)' user tmp$sp_definer password '123';
--###################################################
select /* Invoke sp_chk_syspriv_main. Work as tmp$sp_definer */
'CHECK-2' as msg
,p.*
from rdb$database
left join sp_chk_syspriv_main('tmp$outside_caller') p on 1=1
;
commit;
commit;
/************************
2. System privileges
/************************
2. System privileges
... if *privileged* user 'tmp$almost_dba' calls procedure with non-privileged definer 'tmp$sp_definer',
it still can perform every DBA action inside that procedure, like if it was executed under 'tmp$almost_dba's
permissions
... if *privileged* user 'tmp$almost_dba' calls procedure with non-privileged definer 'tmp$sp_definer',
it still can perform every DBA action inside that procedure, like if it was executed under 'tmp$almost_dba's
permissions
************************/
************************/
--###################################################
connect '$(DSN)' user tmp$almost_dba password '123';
--###################################################
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user tmp$almost_dba password '123';
-- {COMMENT_TAG} ###################################################
commit;
set transaction read committed record_version;
commit;
set transaction read committed record_version;
select /* Before sp_chk_syspriv_main. Work as tmp$almost_dba */
'CHECK-3' as msg
,p.*
from rdb$database
left join sp_chk_syspriv_main('tmp$outside_caller') p on 1=1
;
select /* Before sp_chk_syspriv_main. Work as tmp$almost_dba */
'CHECK-3' as msg
,p.*
from rdb$database
left join sp_chk_syspriv_main('tmp$outside_caller') p on 1=1
;
-- Verify that system privilege MODIFY_EXT_CONN_POOL not avaliable
-- for current user (despite that he is 'tmp$almost_dba') because
-- SP sp_clear_ext_pool was created with SQL SECURITY DEFINER and
-- its definer ('tmp$sp_definer') has not any system privilege:
--
select
'CHECK-4' as msg
,p.*
from rdb$database
left join sp_clear_ext_pool p on 1=1;
commit;
-- Verify that system privilege MODIFY_EXT_CONN_POOL not avaliable
-- for current user (despite that he is 'tmp$almost_dba') because
-- SP sp_clear_ext_pool was created with SQL SECURITY DEFINER and
-- its definer ('tmp$sp_definer') has not any system privilege:
--
select
'CHECK-4' as msg
,p.*
from rdb$database
left join sp_clear_ext_pool p on 1=1;
commit;
--###################################################
connect '$(DSN)' user tmp$almost_dba password '123';
--###################################################
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user tmp$almost_dba password '123';
-- {COMMENT_TAG} ###################################################
-- Verify that system privilege ACCESS_ANY_OBJECT_IN_DATABASE not avaliable
-- for current user (despite that he is 'tmp$almost_dba') because
-- SP sp_chk_sql_rights was created with SQL SECURITY DEFINER and
-- its definer ('tmp$sp_definer') has not any system privilege:
--
select
'CHECK-5' as msg
,p.who_am_i
,p.eff_user
,p.access_info
from rdb$database
left join sp_chk_sql_rights p on 1=1
;
commit;
-- Verify that system privilege ACCESS_ANY_OBJECT_IN_DATABASE not avaliable
-- for current user (despite that he is 'tmp$almost_dba') because
-- SP sp_chk_sql_rights was created with SQL SECURITY DEFINER and
-- its definer ('tmp$sp_definer') has not any system privilege:
--
select
'CHECK-5' as msg
,p.who_am_i
,p.eff_user
,p.access_info
from rdb$database
left join sp_chk_sql_rights p on 1=1
;
commit;
-- cleanup:
--###################################################
connect '$(DSN)' user sysdba password 'masterkey';
--###################################################
ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;
drop user tmp$almost_dba;
drop user tmp$sp_definer;
drop user tmp$outside_caller;
commit;
-- cleanup:
-- {COMMENT_TAG} ###################################################
connect '$(DSN)' user sysdba password 'masterkey';
-- {COMMENT_TAG} ###################################################
ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;
drop user tmp$almost_dba;
drop user tmp$sp_definer;
drop user tmp$outside_caller;
commit;
"""
act = isql_act('db', test_script, substitutions=[('EXECUTING_SQL_BLOB .* \\d.*', 'EXECUTING_SQL_BLOB')])
act = isql_act('db', test_script, substitutions=[ ('EXECUTING_SQL_BLOB .* \\d.*', 'EXECUTING_SQL_BLOB'), (f'-- {COMMENT_TAG}.*', '') ])
expected_stdout = """
MSG CHECK-1