mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 21:43:06 +01:00
Added/Updated bugs\core_6163_test.py. Checked on 4.0.1.2692, 3.0.8.33535.
This commit is contained in:
parent
1dbbef7b0f
commit
95f6f7934c
@ -5,20 +5,6 @@ ID: issue-6412
|
||||
ISSUE: 6412
|
||||
TITLE: Generator pages are not encrypted
|
||||
DESCRIPTION:
|
||||
Database in this test is encrypted using IBSurgeon Demo Encryption package
|
||||
( https://ib-aid.com/download-demo-firebird-encryption-plugin/ ; https://ib-aid.com/download/crypt/CryptTest.zip )
|
||||
License file plugins\\dbcrypt.conf with unlimited expiration was provided by IBSurgeon to Firebird Foundation (FF).
|
||||
This file was preliminary stored in FF Test machine.
|
||||
Test assumes that this file and all neccessary libraries already were stored into FB_HOME and %FB_HOME%\\plugins.
|
||||
|
||||
Anyone who wants to run this test on his own machine must
|
||||
1) download https://ib-aid.com/download/crypt/CryptTest.zip AND
|
||||
2) PURCHASE LICENSE and get from IBSurgeon file plugins\\dbcrypt.conf with apropriate expiration date and other info.
|
||||
|
||||
################################################ ! ! ! N O T E ! ! ! ##############################################
|
||||
FF tests storage (aka "fbt-repo") does not (and will not) contain any license file for IBSurgeon Demo Encryption package!
|
||||
#########################################################################################################################
|
||||
|
||||
Several sequences are created in this test.
|
||||
Then we obtain generator page ID and page size by querying RDB$PAGES and MON$DATABASE tables.
|
||||
After this, we check that values of sequences *PRESENT* in NON-encrypted database by opening DB file in 'rb' mode
|
||||
@ -26,451 +12,199 @@ DESCRIPTION:
|
||||
Further, we encrypt database and wait for 1 second in order to give engine complete this job.
|
||||
Finally, we read generator page again. NO any value of secuences must be found at this point.
|
||||
|
||||
Encryprion is performed by 'alter database encrypt with <plugin_name> key ...' statement,
|
||||
where <plugin_name> = dbcrypt - is the name of .dll in FB_HOME\\plugins\\ folder that implements encryption.
|
||||
|
||||
=== NOTE-1 ===
|
||||
In case of "Crypt plugin DBCRYPT failed to load/607/335544351" check that all
|
||||
needed files from IBSurgeon Demo Encryption package exist in %FB_HOME% and %FB_HOME%\\plugins
|
||||
%FB_HOME%:
|
||||
283136 fbcrypt.dll
|
||||
2905600 libcrypto-1_1-x64.dll
|
||||
481792 libssl-1_1-x64.dll
|
||||
|
||||
%FB_HOME%\\plugins:
|
||||
297984 dbcrypt.dll
|
||||
306176 keyholder.dll
|
||||
108 DbCrypt.conf
|
||||
856 keyholder.conf
|
||||
|
||||
=== NOTE-2 ===
|
||||
Version of DbCrypt.dll of october-2018 must be replaced because it has hard-coded
|
||||
date of expiration rather than reading it from DbCrypt.conf !!
|
||||
|
||||
=== NOTE-3 ===
|
||||
firebird.conf must contain following line:
|
||||
KeyHolderPlugin = KeyHolder
|
||||
|
||||
Confirmed non-encrypted content of generators page on: 4.0.0.1627; 3.0.5.33178.
|
||||
Checked on: 4.0.0.1633: OK, 2.260s; 3.0.5.33180: OK, 1.718s.
|
||||
|
||||
:::::::::::::::::::::::::::::::::::::::: NB ::::::::::::::::::::::::::::::::::::
|
||||
18.08.2020. FB 4.x has incompatible behaviour with all previous versions since build 4.0.0.2131 (06-aug-2020):
|
||||
statement 'alter sequence <seq_name> restart with 0' changes rdb$generators.rdb$initial_value to -1 thus next call
|
||||
gen_id(<seq_name>,1) will return 0 (ZERO!) rather than 1.
|
||||
See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt
|
||||
|
||||
Because of this, it was decided to make separate section for check results of FB 4.x
|
||||
Checked on 4.0.0.2164, 3.0.7.33356
|
||||
|
||||
28.02.2021
|
||||
For unknown reason 3.x and 4.x Classic hangs during run this test, both on Linux and (unexpectedly) Windows.
|
||||
Fortunately, simple solution was found.
|
||||
FB hangs only when encryption is done in ISQL but we wait for its finish within 'main' (Python) code (rather than in ISQL).
|
||||
If we force ISQL *itself* wait for several seconds than all fine.
|
||||
So, the only way to avoid hang (at least nowadays, 01-mar-2021) is to make encryption *and* waiting for its finish
|
||||
within ONE attachment to the database that is created by ISQL.
|
||||
Because of this, 'init_script' contains special table and procedure for making pauses: 'tets' and 'sp_delay'.
|
||||
Procedure 'sp_delay' must be called within Tx which was declared as SET TRANSACTION LOCK TIMEOU <N> where <N> = 1...3.
|
||||
|
||||
Checked on: 4.0.0.2372 SS/CS; 3.0.8.33420 SS/CS.
|
||||
JIRA: CORE-6163
|
||||
FBTEST: bugs.core_6163
|
||||
NOTES:
|
||||
[18.06.2022] pzotov
|
||||
::: NB :::
|
||||
Creating sequence with some starting value (say, 1000) reflects DIFFERENTLY in low-level storage in FB 4.x+ vs prev. versions.
|
||||
In FB 4.x generators page will contain value decremented by 1 (999). Rather, in FB 3.x this value will be stored 'as is' (1000).
|
||||
Because of this, we must *not* put into expected_stdout any concrete values of sequences. All we need is only to verify that
|
||||
some (known) generator value contains in the page binary content before encryption, and can not be found there when DB encrypted
|
||||
(see func 'show_gen_page_readable_outcome').
|
||||
|
||||
Above mentioned change in FB 4.x became act since build 4.0.0.2131 (06-aug-2020).
|
||||
statement 'alter sequence <seq_name> restart with 0' changes rdb$generators.rdb$initial_value to -1 thus next call
|
||||
gen_id(<seq_name>,1) will return 0 (ZERO!) rather than 1.
|
||||
See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d
|
||||
|
||||
Checked on 4.0.1.2692, 3.0.8.33535.
|
||||
"""
|
||||
|
||||
import binascii
|
||||
import datetime as py_dt
|
||||
from datetime import timedelta
|
||||
import time
|
||||
import configparser
|
||||
import pytest
|
||||
from firebird.qa import *
|
||||
|
||||
init_script = """
|
||||
recreate table test(x bigint unique);
|
||||
set term ^;
|
||||
create or alter procedure sp_delay as
|
||||
declare r bigint;
|
||||
begin
|
||||
r = rand() * 9223372036854775807;
|
||||
insert into test(x) values(:r);
|
||||
begin
|
||||
-- #########################################################
|
||||
-- ####################### D E L A Y #####################
|
||||
-- #########################################################
|
||||
in autonomous transaction do
|
||||
insert into test(x) values(:r); -- this will cause delay because of duplicate in index
|
||||
when any do
|
||||
init_ddl = """
|
||||
create sequence gen_ba0bab start with 12192683;
|
||||
create sequence gen_badf00d start with 195948557;
|
||||
create sequence gen_caca0 start with 830624;
|
||||
create sequence gen_c0ffee start with 12648430;
|
||||
create sequence gen_dec0de start with 14598366;
|
||||
create sequence gen_decade start with 14600926;
|
||||
create sequence gen_7FFFFFFF start with 2147483647;
|
||||
"""
|
||||
db = db_factory(init = init_ddl)
|
||||
act = python_act('db', substitutions=[('[ \t]+', ' ')])
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
def show_gen_page_readable_outcome(dbname, gen_page_number, pg_size, current_seq_name_val_dict):
|
||||
|
||||
db_handle = open( dbname, "rb")
|
||||
db_handle.seek( gen_page_number * pg_size )
|
||||
page_content = db_handle.read( pg_size )
|
||||
# read_binary_content( db_handle, gen_page_number * pg_size, pg_size )
|
||||
db_handle.close()
|
||||
page_as_hex=binascii.hexlify( page_content )
|
||||
|
||||
# Iterate for each sequence value:
|
||||
for k,v in sorted(current_seq_name_val_dict.items()):
|
||||
|
||||
# Get HEX representation of digital value.
|
||||
# NOTE: format( 830624, 'x') is 'caca0' contains five (odd number!) characters.
|
||||
hex_string = format(abs(v),'x')
|
||||
|
||||
# Here we 'pad' hex representation to EVEN number of digits in it,
|
||||
# otherwise binascii.hexlify fails with "Odd-length string error":
|
||||
hex_string = ''.join( ('0' * ( len(hex_string) % 2 ), hex_string ) )
|
||||
|
||||
# ::: NOTE :::
|
||||
# Generator value is stored in REVERSED bytes order.
|
||||
# dec 830624 --> hex 0x0caca0 --> 0c|ac|a0 --> stored in page as three bytes: {a0; ac; 0c}
|
||||
|
||||
# Decode string that is stored in variable 'hex_string' to HEX number,
|
||||
# REVERSE its bytes and convert it to string again for further search
|
||||
# in page content:
|
||||
#n_as_reversed_hex = binascii.hexlify( hex_string.decode('hex')[::-1] )
|
||||
n_as_reversed_hex = binascii.hexlify( bytes.fromhex(hex_string)[::-1] )
|
||||
|
||||
print(k, 'FOUND.' if n_as_reversed_hex in page_as_hex else 'NOT FOUND.' )
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
expected_stdout = """
|
||||
GEN_7FFFFFFF FOUND.
|
||||
GEN_BA0BAB FOUND.
|
||||
GEN_BADF00D FOUND.
|
||||
GEN_C0FFEE FOUND.
|
||||
GEN_CACA0 FOUND.
|
||||
GEN_DEC0DE FOUND.
|
||||
GEN_DECADE FOUND.
|
||||
|
||||
GEN_7FFFFFFF NOT FOUND.
|
||||
GEN_BA0BAB NOT FOUND.
|
||||
GEN_BADF00D NOT FOUND.
|
||||
GEN_C0FFEE NOT FOUND.
|
||||
GEN_CACA0 NOT FOUND.
|
||||
GEN_DEC0DE NOT FOUND.
|
||||
GEN_DECADE NOT FOUND.
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=3.0.5')
|
||||
def test_1(act: Action, capsys):
|
||||
|
||||
|
||||
cfp = configparser.ConfigParser()
|
||||
cfp.read( (act.files_dir / 'test_config.ini') )
|
||||
|
||||
enc_settings = cfp['encryption']
|
||||
max_encrypt_decrypt_ms = int(enc_settings['max_encrypt_decrypt_ms']) # 5000
|
||||
encryption_plugin = enc_settings['encryption_plugin'] # fbSampleDbCrypt
|
||||
encryption_holder = enc_settings['encryption_holder'] # fbSampleKeyHolder
|
||||
encryption_key = enc_settings['encryption_key'] # Red
|
||||
|
||||
encryption_started = False
|
||||
encryption_finished = False
|
||||
|
||||
with act.db.connect() as con:
|
||||
cur=con.cursor()
|
||||
get_current_seq_values='''
|
||||
execute block returns( gen_name rdb$generator_name, gen_curr bigint) as
|
||||
declare g_incr smallint;
|
||||
begin
|
||||
-- nop --
|
||||
for
|
||||
select trim(rdb$generator_name)
|
||||
from rdb$generators
|
||||
where rdb$system_flag is distinct from 1
|
||||
order by rdb$generator_id
|
||||
into gen_name
|
||||
do begin
|
||||
execute statement 'select gen_id(' || gen_name || ', 0) from rdb$database' into gen_curr;
|
||||
suspend;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
^
|
||||
set term ;^
|
||||
commit;
|
||||
"""
|
||||
'''
|
||||
|
||||
db = db_factory(sql_dialect=3, init=init_script)
|
||||
act = python_act('db', substitutions=[('^((?!(FOUND.|Database\\s+encrypted)).)*$', ''), ('[ \t]+', ' ')])
|
||||
# Obtain current values of user generators:
|
||||
cur.execute(get_current_seq_values)
|
||||
current_seq_name_val_dict={}
|
||||
for r in cur:
|
||||
current_seq_name_val_dict[ r[0] ] = r[1]
|
||||
|
||||
# version: 3.0
|
||||
|
||||
test_script_1 = """
|
||||
#---
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# import binascii
|
||||
# import time
|
||||
# #import shutil
|
||||
#
|
||||
# os.environ["ISC_USER"] = user_name
|
||||
# os.environ["ISC_PASSWORD"] = user_password
|
||||
#
|
||||
# this_fdb = db_conn.database_name
|
||||
# # ::: NB ::: DO NOT close db_conn now! We can close it only after encryption will finish!
|
||||
#
|
||||
# db_conn.execute_immediate('create sequence gen_ba0bab start with 12192683')
|
||||
# db_conn.execute_immediate('create sequence gen_badf00d start with 195948557')
|
||||
# db_conn.execute_immediate('create sequence gen_caca0 start with 830624')
|
||||
# db_conn.execute_immediate('create sequence gen_c0ffee start with 12648430')
|
||||
# db_conn.execute_immediate('create sequence gen_dec0de start with 14598366')
|
||||
# db_conn.execute_immediate('create sequence gen_decade start with 14600926')
|
||||
# db_conn.execute_immediate('create sequence gen_7FFFFFFF start with 2147483647')
|
||||
# db_conn.commit()
|
||||
#
|
||||
# ######################################################################################
|
||||
#
|
||||
# def check_page_for_readable_values(dbname, gen_page_number, pg_size, check_sequence_values):
|
||||
#
|
||||
# global binascii
|
||||
#
|
||||
# db_handle = open( dbname, "rb")
|
||||
# db_handle.seek( gen_page_number * pg_size )
|
||||
# page_content = db_handle.read( pg_size )
|
||||
# # read_binary_content( db_handle, gen_page_number * pg_size, pg_size )
|
||||
# db_handle.close()
|
||||
# page_as_hex=binascii.hexlify( page_content )
|
||||
#
|
||||
# # Iterate for each sequence value:
|
||||
# for n in check_sequence_values:
|
||||
#
|
||||
# # Get HEX representation of digital value.
|
||||
# # NOTE: format( 830624, 'x') is 'caca0' contains five (odd number!) characters.
|
||||
# hex_string = format(abs(n),'x')
|
||||
#
|
||||
# # Here we 'pad' hex representation to EVEN number of digits in it,
|
||||
# # otherwise binascii.hexlify fails with "Odd-length string error":
|
||||
# hex_string = ''.join( ('0' * ( len(hex_string)%2 ), hex_string ) )
|
||||
#
|
||||
# # ::: NOTE :::
|
||||
# # Generator value is stored in REVERSED bytes order.
|
||||
# # dec 830624 --> hex 0x0caca0 --> 0c|ac|a0 --> stored in page as three bytes: {a0; ac; 0c}
|
||||
#
|
||||
# # Decode string that is stored in variable 'hex_string' to HEX number,
|
||||
# # REVERSE its bytes and convert it to string again for further search
|
||||
# # in page content:
|
||||
# n_as_reversed_hex = binascii.hexlify( hex_string.decode('hex')[::-1] )
|
||||
#
|
||||
# print(n, n_as_reversed_hex, 'FOUND.' if n_as_reversed_hex in page_as_hex else 'NOT FOUND.' )
|
||||
# # print(n, n_as_reversed_hex, 'UNEXPECTEDLY FOUND AT POS. ' + '{:5d}'.format( page_as_hex.index(n_as_reversed_hex) ) if n_as_reversed_hex in page_as_hex else 'Not found (expected).' )
|
||||
#
|
||||
# ######################################################################################
|
||||
#
|
||||
#
|
||||
# cur=db_conn.cursor()
|
||||
# get_current_seq_values='''
|
||||
# execute block returns( gen_curr bigint) as
|
||||
# declare gen_name rdb$generator_name;
|
||||
# begin
|
||||
# for
|
||||
# select rdb$generator_name from rdb$generators where rdb$system_flag is distinct from 1 order by rdb$generator_id
|
||||
# into gen_name
|
||||
# do begin
|
||||
# execute statement 'execute block returns(g bigint) as begin g = gen_id('|| gen_name ||', 0); suspend; end' into gen_curr;
|
||||
# suspend;
|
||||
# end
|
||||
# end
|
||||
# '''
|
||||
#
|
||||
# # Obtain current values of user generators:
|
||||
# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# cur.execute(get_current_seq_values)
|
||||
# check_sequence_values=[]
|
||||
# for r in cur:
|
||||
# check_sequence_values += r[0],
|
||||
#
|
||||
#
|
||||
# # Obtain page size and number of generators page:
|
||||
# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# cur.execute('select m.mon$page_size,min(rdb$page_number) from mon$database m cross join rdb$pages p where p.rdb$page_type = 9 group by 1')
|
||||
# pg_size, gen_page_number = -1,-1
|
||||
# for r in cur:
|
||||
# pg_size=r[0]
|
||||
# gen_page_number=r[1]
|
||||
# # print(r[0],r[1])
|
||||
# cur.close()
|
||||
# db_conn.close()
|
||||
#
|
||||
# # Read gen page, convert it to hex and check whether generator values can be found there or no:
|
||||
# # Expected result: YES for all values because DB not encrypted now.
|
||||
# # ~~~~~~~~~~~~~~~
|
||||
# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values)
|
||||
#
|
||||
# # 27.02.2021.
|
||||
# # Name of encryption plugin depends on OS:
|
||||
# # * for Windows we (currently) use plugin by IBSurgeon, its name is 'dbcrypt';
|
||||
# # later it can be replaced with built-in plugin 'fbSampleDbCrypt'
|
||||
# # but currently it is included only in FB 4.x builds (not in FB 3.x).
|
||||
# # Discussed tih Dimitr, Alex, Vlad, letters since: 08-feb-2021 00:22
|
||||
# # "Windows-distributive FB 3.x: it is desired to see sub-folder 'examples\\prebuild' with files for encryption, like it is in FB 4.x
|
||||
# # *** DEFERRED ***
|
||||
# # * for Linux we use:
|
||||
# # ** 'DbCrypt_example' for FB 3.x
|
||||
# # ** 'fbSampleDbCrypt' for FB 4.x+
|
||||
# #
|
||||
# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else ( '"DbCrypt_example"' if db_conn.engine_version < 4 else '"fbSampleDbCrypt"' )
|
||||
#
|
||||
# sql_cmd='''
|
||||
# -- ################################################
|
||||
# -- ### e n c r y p t d a t a b a s e ###
|
||||
# -- ################################################
|
||||
# alter database encrypt with %(PLUGIN_NAME)s key Red;
|
||||
# commit;
|
||||
#
|
||||
#
|
||||
# -- 01.03.2021: we have to wait for several seconds
|
||||
# -- until encryption will be finished. But we must do
|
||||
# -- this delay within the same attachment as those that
|
||||
# -- launched encryption process.
|
||||
# -- The reason of that weird effect currently is unknown.
|
||||
# -- Here we make pause using 'set transaction lock timeout':
|
||||
#
|
||||
# set transaction lock timeout 2; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY
|
||||
# execute procedure sp_delay;
|
||||
# rollback;
|
||||
# show database;
|
||||
# quit;
|
||||
# ''' % locals()
|
||||
#
|
||||
# runProgram('isql', [ dsn ], sql_cmd)
|
||||
#
|
||||
# # Read again gen page, convert it to hex and check whether generator values can be found there or no.
|
||||
# # Expected result: NOT for all values because DB was encrypted.
|
||||
# # ~~~~~~~~~~~~~~~~
|
||||
# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values)
|
||||
#
|
||||
#
|
||||
#---
|
||||
"""
|
||||
expected_stdout_1 = """
|
||||
12192683 ab0bba FOUND.
|
||||
195948557 0df0ad0b FOUND.
|
||||
830624 a0ac0c FOUND.
|
||||
12648430 eeffc0 FOUND.
|
||||
14598366 dec0de FOUND.
|
||||
14600926 decade FOUND.
|
||||
2147483647 ffffff7f FOUND.
|
||||
# Obtain page size and number of generators page:
|
||||
cur.execute('select m.mon$page_size,min(rdb$page_number) from mon$database m cross join rdb$pages p where p.rdb$page_type = 9 group by 1')
|
||||
pg_size, gen_page_number = -1,-1
|
||||
for r in cur:
|
||||
pg_size=r[0]
|
||||
gen_page_number=r[1]
|
||||
|
||||
Database encrypted
|
||||
|
||||
12192683 ab0bba NOT FOUND.
|
||||
195948557 0df0ad0b NOT FOUND.
|
||||
830624 a0ac0c NOT FOUND.
|
||||
12648430 eeffc0 NOT FOUND.
|
||||
14598366 dec0de NOT FOUND.
|
||||
14600926 decade NOT FOUND.
|
||||
2147483647 ffffff7f NOT FOUND.
|
||||
"""
|
||||
# Read gen page, convert it to hex and check whether generator values can be found there or no:
|
||||
# Expected result: YES for all values because DB not encrypted now.
|
||||
# ~~~~~~~~~~~~~~~
|
||||
show_gen_page_readable_outcome(act.db.db_path, gen_page_number, pg_size, current_seq_name_val_dict)
|
||||
|
||||
#---------------------------------------
|
||||
t1=py_dt.datetime.now()
|
||||
d1 = t1-t1
|
||||
sttm = f'alter database encrypt with "{encryption_plugin}" key "{encryption_key}"'
|
||||
try:
|
||||
con.execute_immediate(sttm)
|
||||
con.commit()
|
||||
encryption_started = True
|
||||
except DatabaseError as e:
|
||||
# -ALTER DATABASE failed
|
||||
# -Crypt plugin fbSampleDbCrypt failed to load
|
||||
# ==> no sense to do anything else, encryption_started remains False.
|
||||
print( e.__str__() )
|
||||
|
||||
@pytest.mark.skip('FIXME: encryption plugin')
|
||||
@pytest.mark.version('>=3.0.5,<4')
|
||||
def test_1(act: Action):
|
||||
# Code for v3 and v4 differ, run this test with SKIP disabled to see the difference
|
||||
assert test_script_1 == test_script_2
|
||||
pytest.fail("Not IMPLEMENTED")
|
||||
while encryption_started:
|
||||
t2=py_dt.datetime.now()
|
||||
d1=t2-t1
|
||||
if d1.seconds*1000 + d1.microseconds//1000 > max_encrypt_decrypt_ms:
|
||||
print(f'TIMEOUT EXPIRATION: encryption took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {max_encrypt_decrypt_ms} ms.')
|
||||
break
|
||||
|
||||
# version: 4.0
|
||||
# Possible output:
|
||||
# Database not encrypted
|
||||
# Database encrypted, crypt thread not complete
|
||||
act.isql(switches=['-q'], input = 'show database;', combine_output = True)
|
||||
if 'Database encrypted' in act.stdout:
|
||||
if 'not complete' in act.stdout:
|
||||
pass
|
||||
else:
|
||||
encryption_finished = True
|
||||
break
|
||||
act.reset()
|
||||
|
||||
|
||||
test_script_2 = """
|
||||
#---
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# import binascii
|
||||
# import time
|
||||
#
|
||||
# os.environ["ISC_USER"] = user_name
|
||||
# os.environ["ISC_PASSWORD"] = user_password
|
||||
# this_fdb = db_conn.database_name
|
||||
#
|
||||
# db_conn.execute_immediate('create sequence gen_ba0bab start with 12192683')
|
||||
# db_conn.execute_immediate('create sequence gen_badf00d start with 195948557')
|
||||
# db_conn.execute_immediate('create sequence gen_caca0 start with 830624')
|
||||
# db_conn.execute_immediate('create sequence gen_c0ffee start with 12648430')
|
||||
# db_conn.execute_immediate('create sequence gen_dec0de start with 14598366')
|
||||
# db_conn.execute_immediate('create sequence gen_decade start with 14600926')
|
||||
# db_conn.execute_immediate('create sequence gen_7FFFFFFF start with 2147483647')
|
||||
# db_conn.commit()
|
||||
#
|
||||
# # ::: NB ::: DO NOT close db_conn now! We can close it only after encryption will finish!
|
||||
#
|
||||
# ######################################################################################
|
||||
#
|
||||
# def check_page_for_readable_values(dbname, gen_page_number, pg_size, check_sequence_values):
|
||||
#
|
||||
# global binascii
|
||||
#
|
||||
# db_handle = open( dbname, "rb")
|
||||
# db_handle.seek( gen_page_number * pg_size )
|
||||
# page_content = db_handle.read( pg_size )
|
||||
# # read_binary_content( db_handle, gen_page_number * pg_size, pg_size )
|
||||
# db_handle.close()
|
||||
# page_as_hex=binascii.hexlify( page_content )
|
||||
#
|
||||
# # Iterate for each sequence value:
|
||||
# for n in check_sequence_values:
|
||||
#
|
||||
# # Get HEX representation of digital value.
|
||||
# # NOTE: format( 830624, 'x') is 'caca0' contains five (odd number!) characters.
|
||||
# hex_string = format(abs(n),'x')
|
||||
#
|
||||
# # Here we 'pad' hex representation to EVEN number of digits in it,
|
||||
# # otherwise binascii.hexlify fails with "Odd-length string error":
|
||||
# hex_string = ''.join( ('0' * ( len(hex_string)%2 ), hex_string ) )
|
||||
#
|
||||
# # ::: NOTE :::
|
||||
# # Generator value is stored in REVERSED bytes order.
|
||||
# # dec 830624 --> hex 0x0caca0 --> 0c|ac|a0 --> stored in page as three bytes: {a0; ac; 0c}
|
||||
#
|
||||
# # Decode string that is stored in variable 'hex_string' to HEX number,
|
||||
# # REVERSE its bytes and convert it to string again for further search
|
||||
# # in page content:
|
||||
# n_as_reversed_hex = binascii.hexlify( hex_string.decode('hex')[::-1] )
|
||||
#
|
||||
# print(n, n_as_reversed_hex, 'FOUND.' if n_as_reversed_hex in page_as_hex else 'NOT FOUND.' )
|
||||
# # print(n, n_as_reversed_hex, 'UNEXPECTEDLY FOUND AT POS. ' + '{:5d}'.format( page_as_hex.index(n_as_reversed_hex) ) if n_as_reversed_hex in page_as_hex else 'Not found (expected).' )
|
||||
#
|
||||
# ######################################################################################
|
||||
#
|
||||
# cur=db_conn.cursor()
|
||||
# get_current_seq_values='''
|
||||
# execute block returns( gen_curr bigint) as
|
||||
# declare gen_name rdb$generator_name;
|
||||
# begin
|
||||
# for
|
||||
# select rdb$generator_name from rdb$generators where rdb$system_flag is distinct from 1 order by rdb$generator_id
|
||||
# into gen_name
|
||||
# do begin
|
||||
# execute statement 'execute block returns(g bigint) as begin g = gen_id('|| gen_name ||', 0); suspend; end' into gen_curr;
|
||||
# suspend;
|
||||
# end
|
||||
# end
|
||||
# '''
|
||||
#
|
||||
# # Obtain current values of user generators:
|
||||
# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# cur.execute(get_current_seq_values)
|
||||
# check_sequence_values=[]
|
||||
# for r in cur:
|
||||
# check_sequence_values += r[0],
|
||||
# #print('check_sequence_values=',check_sequence_values)
|
||||
#
|
||||
#
|
||||
#
|
||||
# # Obtain page size and number of generators page:
|
||||
# # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# cur.execute('select m.mon$page_size,min(rdb$page_number) from mon$database m cross join rdb$pages p where p.rdb$page_type = 9 group by 1')
|
||||
# pg_size, gen_page_number = -1,-1
|
||||
# for r in cur:
|
||||
# pg_size=r[0]
|
||||
# gen_page_number=r[1]
|
||||
# # print(r[0],r[1])
|
||||
#
|
||||
# # 28.02.2021, temporary:
|
||||
# srv_mode='UNKNOWN'
|
||||
# cur.execute("select rdb$config_value from rdb$config where rdb$config_name='ServerMode'")
|
||||
# for r in cur:
|
||||
# srv_mode=r[0]
|
||||
#
|
||||
# cur.close()
|
||||
# db_conn.close()
|
||||
#
|
||||
# # Read gen page, convert it to hex and check whether generator values can be found there or no:
|
||||
# # Expected result: YES for all values because DB not encrypted now.
|
||||
# # ~~~~~~~~~~~~~~~
|
||||
# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values)
|
||||
#
|
||||
#
|
||||
# # 27.02.2021.
|
||||
# # Name of encryption plugin depends on OS:
|
||||
# # * for Windows we (currently) use plugin by IBSurgeon, its name is 'dbcrypt';
|
||||
# # later it can be replaced with built-in plugin 'fbSampleDbCrypt'
|
||||
# # but currently it is included only in FB 4.x builds (not in FB 3.x).
|
||||
# # Discussed tih Dimitr, Alex, Vlad, letters since: 08-feb-2021 00:22
|
||||
# # "Windows-distributive FB 3.x: it is desired to see sub-folder 'examples\\prebuild' with files for encryption, like it is in FB 4.x
|
||||
# # *** DEFERRED ***
|
||||
# # * for Linux we use:
|
||||
# # ** 'DbCrypt_example' for FB 3.x
|
||||
# # ** 'fbSampleDbCrypt' for FB 4.x+
|
||||
# #
|
||||
# PLUGIN_NAME = 'dbcrypt' if os.name == 'nt' else ( '"DbCrypt_example"' if db_conn.engine_version < 4 else '"fbSampleDbCrypt"' )
|
||||
#
|
||||
# sql_cmd='''
|
||||
# -- ################################################
|
||||
# -- ### e n c r y p t d a t a b a s e ###
|
||||
# -- ################################################
|
||||
# alter database encrypt with %(PLUGIN_NAME)s key Red;
|
||||
# commit;
|
||||
#
|
||||
# -- 01.03.2021: we have to wait for several seconds
|
||||
# -- until encryption will be finished. But we must do
|
||||
# -- this delay within the same attachment as those that
|
||||
# -- launched encryption process.
|
||||
# -- The reason of that weird effect currently is unknown.
|
||||
# -- Here we make pause using 'set transaction lock timeout':
|
||||
#
|
||||
# -- 20.04.2021: increased delay from 2 to 3 seconds.
|
||||
# -- Otherwise can get "... crypt thread not complete":
|
||||
# set transaction lock timeout 3; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY
|
||||
# execute procedure sp_delay;
|
||||
# rollback;
|
||||
# show database;
|
||||
# quit;
|
||||
# ''' % locals()
|
||||
#
|
||||
# runProgram('isql', [ dsn ], sql_cmd)
|
||||
#
|
||||
# # Read again gen page, convert it to hex and check whether generator values can be found there or no.
|
||||
# # Expected result: NOT FOUND, for all values (because DB was encrypted).
|
||||
# # ~~~~~~~~~~~~~~~~
|
||||
# check_page_for_readable_values(this_fdb, gen_page_number, pg_size, check_sequence_values)
|
||||
#
|
||||
#
|
||||
#---
|
||||
"""
|
||||
if encryption_finished:
|
||||
# Read again gen page, convert it to hex and check whether generator values can be found there or no.
|
||||
# Expected result: NOT for all values because DB was encrypted.
|
||||
# ~~~~~~~~~~~~~~~~
|
||||
show_gen_page_readable_outcome(act.db.db_path, gen_page_number, pg_size, current_seq_name_val_dict)
|
||||
else:
|
||||
print('Nothing to be tested: DB not encrypted.')
|
||||
|
||||
expected_stdout_2 = """
|
||||
12192682 aa0bba FOUND.
|
||||
195948556 0cf0ad0b FOUND.
|
||||
830623 9fac0c FOUND.
|
||||
12648429 edffc0 FOUND.
|
||||
14598365 ddc0de FOUND.
|
||||
14600925 ddcade FOUND.
|
||||
2147483646 feffff7f FOUND.
|
||||
|
||||
Database encrypted
|
||||
|
||||
12192682 aa0bba NOT FOUND.
|
||||
195948556 0cf0ad0b NOT FOUND.
|
||||
830623 9fac0c NOT FOUND.
|
||||
12648429 edffc0 NOT FOUND.
|
||||
14598365 ddc0de NOT FOUND.
|
||||
14600925 ddcade NOT FOUND.
|
||||
2147483646 feffff7f NOT FOUND.
|
||||
"""
|
||||
|
||||
@pytest.mark.skip('FIXME: encryption plugin')
|
||||
@pytest.mark.version('>=4.0')
|
||||
def test_2(act: Action):
|
||||
# Code for v3 and v4 differ, run this test with SKIP disabled to see the difference
|
||||
assert test_script_1 == test_script_2
|
||||
pytest.fail("Not IMPLEMENTED")
|
||||
act.expected_stdout = expected_stdout
|
||||
act.stdout = capsys.readouterr().out
|
||||
assert act.clean_stdout == act.clean_expected_stdout
|
||||
act.reset()
|
||||
|
Loading…
Reference in New Issue
Block a user