8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:03:02 +01:00

Initial implementation for CORE-5808 (#160)

* Implemented CORE-5808
This commit is contained in:
Alexander Peshkov 2018-05-23 17:16:04 +03:00 committed by GitHub
parent 332334ab3d
commit aa6cb5d05f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1297 additions and 155 deletions

View File

@ -1820,6 +1820,8 @@ C --
PARAMETER (GDS__vld_plugins = 335545203)
INTEGER*4 GDS__db_crypt_key
PARAMETER (GDS__db_crypt_key = 335545204)
INTEGER*4 GDS__no_keyholder_plugin
PARAMETER (GDS__no_keyholder_plugin = 335545205)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw

View File

@ -1815,6 +1815,8 @@ const
gds_vld_plugins = 335545203;
isc_db_crypt_key = 335545204;
gds_db_crypt_key = 335545204;
isc_no_keyholder_plugin = 335545205;
gds_no_keyholder_plugin = 335545205;
isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930;

View File

@ -88,18 +88,12 @@ namespace // unnamed, private
inline void put(BurpGlobals* tdgbl, const UCHAR c)
{
if (--(tdgbl->io_cnt) >= 0)
*(tdgbl->io_ptr)++ = c;
else
MVOL_write(c, &tdgbl->io_cnt, &tdgbl->io_ptr);
tdgbl->put(c);
}
inline void put(BurpGlobals* tdgbl, const att_type c)
{
if (--tdgbl->io_cnt >= 0)
*(tdgbl->io_ptr)++ = UCHAR(c);
else
MVOL_write(UCHAR(c), &tdgbl->io_cnt, &tdgbl->io_ptr);
put(tdgbl, UCHAR(c));
}
inline const UCHAR* put_block(BurpGlobals* tdgbl, const UCHAR* p, ULONG n)
@ -221,11 +215,6 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
tdgbl->gbl_database_file_name = dbb_file;
tdgbl->io_ptr = NULL;
tdgbl->io_cnt = 0;
tdgbl->relations = NULL;
tdgbl->runtimeODS = 0;
gds_trans = 0;
BURP_verbose(130);
@ -280,7 +269,7 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
tdgbl->action->act_file = tdgbl->gbl_sw_files;
}
MVOL_init_write(file_name, &tdgbl->io_cnt, &tdgbl->io_ptr);
MVOL_init_write(file_name);
// Write database record
@ -416,7 +405,7 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
// Finish up
put(tdgbl, (UCHAR) rec_end);
FB_UINT64 cumul_count = MVOL_fini_write(&tdgbl->io_cnt, &tdgbl->io_ptr);
FB_UINT64 cumul_count = MVOL_fini_write();
tdgbl->action->act_action = ACT_backup_fini;
BURP_verbose(176, SafeArg() << cumul_count);
// msg 176 closing file, committing, and finishing. %ld bytes written

View File

@ -726,6 +726,41 @@ int gbak(Firebird::UtilSvc* uSvc)
}
tdgbl->gbl_sw_sql_role = argv[itr];
break;
case IN_SW_BURP_KEYHOLD:
if (++itr >= argc)
{
BURP_error(381, true);
// KeyHolder parameter missing
}
if (tdgbl->gbl_sw_keyholder)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_keyholder = argv[itr];
break;
case IN_SW_BURP_CRYPT:
if (++itr >= argc)
{
BURP_error(377, true);
// CryptPlugin parameter missing
}
if (tdgbl->gbl_sw_crypt)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_crypt = argv[itr];
break;
case IN_SW_BURP_KEYNAME:
if (++itr >= argc)
{
BURP_error(375, true);
// Key name parameter missing
}
if (tdgbl->gbl_sw_keyname)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_keyname = argv[itr];
break;
case IN_SW_BURP_ZIP:
if (tdgbl->gbl_sw_zip)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_zip = true;
break;
case IN_SW_BURP_FA:
if (tdgbl->gbl_sw_blk_factor)
BURP_error(333, true, SafeArg() << in_sw_tab->in_sw_name << tdgbl->gbl_sw_blk_factor);
@ -1202,6 +1237,8 @@ int gbak(Firebird::UtilSvc* uSvc)
}
else if (tdgbl->gbl_sw_old_descriptions)
errNum = IN_SW_BURP_OL;
else if (tdgbl->gbl_sw_zip)
errNum = IN_SW_BURP_ZIP;
if (errNum != IN_SW_BURP_0)
{
@ -1815,14 +1852,28 @@ static gbak_action open_files(const TEXT* file1,
*
**************************************/
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
FbLocalStatus temp_status;
Firebird::CheckStatusWrapper* status_vector = &temp_status;
FbLocalStatus status_vector;
// try to attach the database using the first file_name
if (sw_replace != IN_SW_BURP_C && sw_replace != IN_SW_BURP_R)
{
tdgbl->db_handle = Firebird::DispatcherPtr()->attachDatabase(status_vector, file1,
Firebird::DispatcherPtr provider;
// provide crypt key(s) for engine
if (tdgbl->gbl_sw_keyholder)
{
tdgbl->gbl_database_file_name = file1;
provider->setDbCryptCallback(&status_vector, MVOL_get_crypt(tdgbl));
if (!status_vector.isSuccess())
{
BURP_print_status(true, &status_vector);
return QUIT;
}
}
tdgbl->db_handle = provider->attachDatabase(&status_vector, file1,
dpb.getBufferLength(), dpb.getBuffer());
if (!(status_vector->getState() & Firebird::IStatus::STATE_ERRORS))
@ -1831,10 +1882,10 @@ static gbak_action open_files(const TEXT* file1,
{
// msg 13 REPLACE specified, but the first file %s is a database
BURP_error(13, true, file1);
tdgbl->db_handle->detach(status_vector);
tdgbl->db_handle->detach(&status_vector);
if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
BURP_print_status(true, status_vector);
BURP_print_status(true, &status_vector);
else
tdgbl->db_handle = NULL;
@ -1845,14 +1896,58 @@ static gbak_action open_files(const TEXT* file1,
// msg 139 Version(s) for database "%s"
BURP_print(false, 139, file1);
OutputVersion outputVersion("\t%s\n");
Firebird::UtilInterfacePtr()->getFbVersion(status_vector, tdgbl->db_handle, &outputVersion);
Firebird::UtilInterfacePtr()->getFbVersion(&status_vector, tdgbl->db_handle, &outputVersion);
}
BURP_verbose(166, file1); // msg 166: readied database %s for backup
if (tdgbl->gbl_sw_keyholder)
{
unsigned char info[] = {fb_info_crypt_key, fb_info_crypt_plugin};
unsigned char buffer[(1 + 2 + MAX_SQL_IDENTIFIER_SIZE) * 2 + 2];
unsigned int len;
tdgbl->db_handle->getInfo(&status_vector, sizeof(info), info, sizeof(buffer), buffer);
UCHAR* p = buffer;
while(p)
{
switch(*p++)
{
case fb_info_crypt_key:
len = gds__vax_integer(p, 2);
if (len < sizeof(tdgbl->gbl_hdr_keybuffer))
{
memcpy(tdgbl->gbl_hdr_keybuffer, p + 2, len);
tdgbl->gbl_hdr_keybuffer[len] = 0;
if (!tdgbl->gbl_sw_keyname)
tdgbl->gbl_sw_keyname = tdgbl->gbl_hdr_keybuffer;
}
break;
case fb_info_crypt_plugin:
len = gds__vax_integer(p, 2);
if (len < sizeof(tdgbl->gbl_hdr_cryptbuffer))
{
memcpy(tdgbl->gbl_hdr_cryptbuffer, p + 2, len);
tdgbl->gbl_hdr_cryptbuffer[len] = 0;
if (!tdgbl->gbl_sw_crypt)
tdgbl->gbl_sw_crypt = tdgbl->gbl_hdr_cryptbuffer;
}
break;
default:
p = NULL;
continue;
}
p += (2 + len);
}
}
}
else if (sw_replace == IN_SW_BURP_B ||
(status_vector->getErrors()[1] != isc_io_error && status_vector->getErrors()[1] != isc_bad_db_format))
{
BURP_print_status(true, status_vector);
BURP_print_status(true, &status_vector);
return QUIT;
}
}
@ -1928,7 +2023,7 @@ static gbak_action open_files(const TEXT* file1,
{
Firebird::string nm = tdgbl->toSystem(fil->fil_name);
#ifdef WIN_NT
if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_WRITE, CREATE_ALWAYS)) ==
if ((fil->fil_fd = NT_tape_open(nm.c_str(), MODE_WRITE, CREATE_ALWAYS)) ==
INVALID_HANDLE_VALUE)
#else
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_WRITE, open_mask)) == -1)
@ -1974,10 +2069,10 @@ static gbak_action open_files(const TEXT* file1,
}
else
{
tdgbl->db_handle->detach(status_vector);
tdgbl->db_handle->detach(&status_vector);
if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
BURP_print_status(true, status_vector);
BURP_print_status(true, &status_vector);
else
tdgbl->db_handle = NULL;
}
@ -2038,7 +2133,7 @@ static gbak_action open_files(const TEXT* file1,
// open first file
Firebird::string nm = tdgbl->toSystem(fil->fil_name);
#ifdef WIN_NT
if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) ==
if ((fil->fil_fd = NT_tape_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) ==
INVALID_HANDLE_VALUE)
#else
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE)
@ -2084,7 +2179,7 @@ static gbak_action open_files(const TEXT* file1,
tdgbl->action->act_file = fil;
Firebird::string nm = tdgbl->toSystem(fil->fil_name);
#ifdef WIN_NT
if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) ==
if ((fil->fil_fd = NT_tape_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) ==
INVALID_HANDLE_VALUE)
#else
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE)
@ -2152,17 +2247,32 @@ static gbak_action open_files(const TEXT* file1,
if (sw_replace == IN_SW_BURP_C || sw_replace == IN_SW_BURP_R)
{
tdgbl->db_handle = Firebird::DispatcherPtr()->attachDatabase(status_vector, *file2,
Firebird::DispatcherPtr provider;
// provide crypt key(s) for engine
if (tdgbl->gbl_sw_keyholder)
{
tdgbl->gbl_database_file_name = *file2;
provider->setDbCryptCallback(&status_vector, MVOL_get_crypt(tdgbl));
if (!status_vector.isSuccess())
{
BURP_print_status(true, &status_vector);
return QUIT;
}
}
tdgbl->db_handle = provider->attachDatabase(&status_vector, *file2,
dpb.getBufferLength(), dpb.getBuffer());
if (!(status_vector->getState() & Firebird::IStatus::STATE_ERRORS))
{
if (sw_replace == IN_SW_BURP_C)
{
tdgbl->db_handle->detach(status_vector);
tdgbl->db_handle->detach(&status_vector);
if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
BURP_print_status(true, status_vector);
BURP_print_status(true, &status_vector);
else
tdgbl->db_handle = NULL;
@ -2171,7 +2281,7 @@ static gbak_action open_files(const TEXT* file1,
}
else
{
tdgbl->db_handle->dropDatabase(status_vector);
tdgbl->db_handle->dropDatabase(&status_vector);
if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
{

View File

@ -35,6 +35,7 @@
#include "firebird/Message.h"
#include "../common/dsc.h"
#include "../burp/misc_proto.h"
#include "../burp/mvol_proto.h"
#include "../yvalve/gds_proto.h"
#include "../common/ThreadData.h"
#include "../common/UtilSvc.h"
@ -43,6 +44,7 @@
#include "../common/classes/MetaName.h"
#include "../../jrd/SimilarToMatcher.h"
#include "../common/status.h"
#include "../common/sha.h"
#include "../common/classes/ImplementHelper.h"
#ifdef HAVE_UNISTD_H
@ -53,6 +55,14 @@
#include <fcntl.h>
#endif
#if defined(HAVE_ZLIB_H)
#define WIRE_COMPRESS_SUPPORT 1
#endif
#ifdef WIRE_COMPRESS_SUPPORT
#include <zlib.h>
//#define COMPRESS_DEBUG 1
#endif // WIRE_COMPRESS_SUPPORT
static inline UCHAR* BURP_alloc(ULONG size)
{
@ -208,10 +218,6 @@ Version 11: FB4.0.
const int ATT_BACKUP_FORMAT = 11;
// format version number for ranges for arrays
//const int GDS_NDA_VERSION = 1; // Not used
// max array dimension
const int MAX_DIMENSION = 16;
@ -234,6 +240,10 @@ enum att_type {
att_backup_blksize, // backup block size
att_backup_file, // database file name
att_backup_volume, // backup volume number
att_backup_keyname, // name of crypt key
att_backup_zip, // zipped backup file
att_backup_hash, // hash of crypt key
att_backup_crypt, // name of crypt plugin
// Database attributes
@ -921,6 +931,8 @@ public:
// Global switches and data
struct BurpCrypt;
class BurpGlobals : public Firebird::ThreadData
{
public:
@ -973,6 +985,12 @@ public:
bool gbl_sw_mode;
bool gbl_sw_mode_val;
bool gbl_sw_overwrite;
bool gbl_sw_zip;
const SCHAR* gbl_sw_keyholder;
const SCHAR* gbl_sw_crypt;
const SCHAR* gbl_sw_keyname;
SCHAR gbl_hdr_keybuffer[MAX_SQL_IDENTIFIER_SIZE + 1];
SCHAR gbl_hdr_cryptbuffer[MAX_SQL_IDENTIFIER_SIZE + 1];
const SCHAR* gbl_sw_sql_role;
const SCHAR* gbl_sw_user;
const SCHAR* gbl_sw_password;
@ -983,11 +1001,42 @@ public:
gfld* gbl_global_fields;
unsigned gbl_network_protocol;
burp_act* action;
BurpCrypt* gbl_crypt;
ULONG io_buffer_size;
redirect_vals sw_redirect;
bool burp_throw;
UCHAR* io_ptr;
int io_cnt;
UCHAR* blk_io_ptr;
int blk_io_cnt;
void put(const UCHAR c)
{
if (gbl_io_cnt <= 0)
MVOL_write(this);
--gbl_io_cnt;
*gbl_io_ptr++ = c;
}
UCHAR get()
{
if (gbl_io_cnt <= 0)
MVOL_read(this);
--gbl_io_cnt;
return *gbl_io_ptr++;
}
#ifdef WIRE_COMPRESS_SUPPORT
z_stream gbl_stream;
#endif
UCHAR* gbl_io_ptr;
int gbl_io_cnt;
UCHAR* gbl_compress_buffer;
UCHAR* gbl_crypt_buffer;
ULONG gbl_crypt_left;
UCHAR* gbl_decompress;
burp_rel* relations;
burp_pkg* packages;
burp_prc* procedures;
@ -1010,6 +1059,11 @@ public:
SCHAR mvol_old_file [MAX_FILE_NAME_SIZE];
int mvol_volume_count;
bool mvol_empty_file;
TEXT mvol_keyname_buffer[MAX_FILE_NAME_SIZE];
const TEXT* mvol_keyname;
TEXT mvol_crypt_buffer[MAX_FILE_NAME_SIZE];
const TEXT* mvol_crypt;
TEXT gbl_key_hash[(Firebird::Sha1::HASH_SIZE + 1) * 4 / 3 + 1]; // take into an account base64
Firebird::IAttachment* db_handle;
Firebird::ITransaction* tr_handle;
Firebird::ITransaction* global_trans;

View File

@ -91,8 +91,12 @@ const int IN_SW_BURP_FETCHPASS = 45; // fetch default password from file to us
const int IN_SW_BURP_VERBINT = 46; // verbose but with specific interval
const int IN_SW_BURP_STATS = 47; // print statistics
const int IN_SW_BURP_ZIP = 48; // backup file in .zip format
const int IN_SW_BURP_KEYHOLD = 49; // name of KeyHolder plugin
const int IN_SW_BURP_KEYNAME = 50; // name of crypt key
const int IN_SW_BURP_CRYPT = 51; // name of crypt plugin
/**************************************************************************/
// used 0BCDEFGILMNOPRSTUVYZ available AHJQWX
static const char* const BURP_SW_MODE_RO = "READ_ONLY";
static const char* const BURP_SW_MODE_RW = "READ_WRITE";
@ -111,6 +115,8 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 73: @1CREATE_DATABASE create database from backup file
{IN_SW_BURP_CO, isc_spb_bkp_convert, "CONVERT", 0, 0, 0, false, true, 254, 2, NULL, boBackup},
// msg 254: @1CO(NVERT) backup external files as tables
{IN_SW_BURP_CRYPT, isc_spb_bkp_crypt, "CRYPT", 0, 0, 0, false, false, 373, 3, NULL, boGeneral},
// msg 373:@1CRY(PT) plugin name
{IN_SW_BURP_E, isc_spb_bkp_expand, "EXPAND", 0, 0, 0, false, true, 97, 1, NULL, boBackup},
// msg 97: @1EXPAND no data compression
{IN_SW_BURP_FA, isc_spb_bkp_factor, "FACTOR", 0, 0, 0, false, false, 181, 2, NULL, boBackup},
@ -125,10 +131,14 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 303: @1FIX_FSS_METADATA fix malformed UNICODE_FSS metadata
{IN_SW_BURP_G, isc_spb_bkp_no_garbage_collect, "GARBAGE_COLLECT", 0, 0, 0, false, true, 177, 1, NULL, boBackup},
// msg 177:@1GARBAGE_COLLECT inhibit garbage collection
{IN_SW_BURP_I, isc_spb_res_deactivate_idx, "INACTIVE", 0, 0, 0, false, true, 78, 1, NULL, boRestore},
{IN_SW_BURP_I, isc_spb_res_deactivate_idx, "INACTIVE", 0, 0, 0, false, true, 78, 1, NULL, boRestore},
// msg 78:@1INACTIVE deactivate indexes during restore
{IN_SW_BURP_IG, isc_spb_bkp_ignore_checksums, "IGNORE", 0, 0, 0, false, true, 178, 2, NULL, boBackup},
{IN_SW_BURP_IG, isc_spb_bkp_ignore_checksums, "IGNORE", 0, 0, 0, false, true, 178, 2, NULL, boBackup},
// msg 178:@1IGNORE ignore bad checksums
{IN_SW_BURP_KEYHOLD, isc_spb_bkp_keyholder, "KEYHOLDER", 0, 0, 0, false, false, 382, 4, NULL, boGeneral},
// msg 382:@1KEYHOLDER name of a key holder plugin
{IN_SW_BURP_KEYNAME, isc_spb_bkp_keyname, "KEYNAME", 0, 0, 0, false, false, 372, 4, NULL, boGeneral},
// msg 372:@1KEYNAME name of a key to be used for encryption
{IN_SW_BURP_K, isc_spb_res_no_shadow, "KILL", 0, 0, 0, false, true, 172, 1, NULL, boRestore},
// msg 172:@1KILL restore without creating shadows
{IN_SW_BURP_L, isc_spb_bkp_ignore_limbo, "LIMBO", 0, 0, 0, false, true, 98, 1, NULL, boBackup},
@ -167,13 +177,13 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 355: @1SKIP_DATA skip data for table
{IN_SW_BURP_STATS, isc_spb_bkp_stat, "STATISTICS", 0, 0, 0, false, false, 361, 2, NULL, boGeneral},
// msg 361: @1ST(ATISTICS) TDRW show statistics:
{-1, 0, " ", 0, 0, 0, false, false, 362, 0, NULL, boGeneral},
{-1, 0, " ", 0, 0, 0, false, false, 362, 0, NULL, boGeneral},
// msg 362: T time from start
{-1, 0, " ", 0, 0, 0, false, false, 363, 0, NULL, boGeneral},
{-1, 0, " ", 0, 0, 0, false, false, 363, 0, NULL, boGeneral},
// msg 363: D delta time
{-1, 0, " ", 0, 0, 0, false, false, 364, 0, NULL, boGeneral},
{-1, 0, " ", 0, 0, 0, false, false, 364, 0, NULL, boGeneral},
// msg 364: R page reads
{-1, 0, " ", 0, 0, 0, false, false, 365, 0, NULL, boGeneral},
{-1, 0, " ", 0, 0, 0, false, false, 365, 0, NULL, boGeneral},
// msg 365: W page writes
{IN_SW_BURP_T, 0, "TRANSPORTABLE", 0, 0, 0, false, false, 175, 1, NULL, boBackup},
// msg 175: @1TRANSPORTABLE transportable backup -- data in XDR format
@ -197,6 +207,8 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 109: @1Y redirect/suppress output (file path or OUTPUT_SUPPRESS)
{IN_SW_BURP_Z, 0, "Z", 0, 0, 0, false, false, 104, 1, NULL, boGeneral},
// msg 104: @1Z print version number
{IN_SW_BURP_ZIP, isc_spb_bkp_zip, "ZIP", 0, 0, 0, false, true, 374, 3, NULL, boBackup},
// msg 104: @1ZIP backup file is in zip compressed format
/**************************************************************************/
// The next two 'virtual' switches are hidden from user and are needed
// for services API

View File

@ -42,11 +42,11 @@
#include "../common/xdr_proto.h"
#include "../common/gdsassert.h"
#include "../common/StatusHolder.h"
#include "../common/status.h"
#include "fb_types.h"
// TMN: Currently we can't include remote/remote.h because we'd get
// conflicting blk_t definitions (we are gonna fix this, in due time).
using Firebird::FbLocalStatus;
static bool_t burp_getbytes(XDR*, SCHAR *, u_int);
static bool_t burp_putbytes(XDR*, const SCHAR*, u_int);
@ -426,8 +426,7 @@ static bool_t xdr_slice(XDR* xdrs, lstring* slice, /*USHORT sdl_length,*/ const
sdl_info info;
{
Firebird::LocalStatus ls;
Firebird::CheckStatusWrapper s(&ls);
FbLocalStatus s;
if (SDL_info(&s, sdl, &info, 0))
return FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@ -24,24 +24,27 @@
#ifndef BURP_MVOL_PROTO_H
#define BURP_MVOL_PROTO_H
#include "../burp/burp.h"
#include "firebird/Interface.h"
#include "std_desc.h"
class BurpGlobals;
FB_UINT64 MVOL_fini_read();
FB_UINT64 MVOL_fini_write(int*, UCHAR**);
FB_UINT64 MVOL_fini_write();
void MVOL_init(ULONG);
void MVOL_init_read(const char*, USHORT*, int*, UCHAR**);
void MVOL_init_write(const char*, int*, UCHAR**);
void MVOL_init_read(const char*, USHORT*);
void MVOL_init_write(const char*);
bool MVOL_split_hdr_write();
bool MVOL_split_hdr_read();
int MVOL_read(int*, UCHAR**);
void MVOL_read(BurpGlobals*);
UCHAR* MVOL_read_block(BurpGlobals*, UCHAR*, ULONG);
void MVOL_skip_block(BurpGlobals*, ULONG);
UCHAR MVOL_write(const UCHAR, int*, UCHAR**);
void MVOL_write(BurpGlobals*);
const UCHAR* MVOL_write_block(BurpGlobals*, const UCHAR*, ULONG);
Firebird::ICryptKeyCallback* MVOL_get_crypt(BurpGlobals*);
#if defined WIN_NT
DESC MVOL_open(const char*, ULONG, ULONG);
DESC NT_tape_open(const char*, ULONG, ULONG);
#endif

View File

@ -60,6 +60,7 @@
#include "../burp/OdsDetection.h"
#include "../auth/trusted/AuthSspi.h"
#include "../common/dsc_proto.h"
#include "../common/ThreadStart.h"
using MsgFormat::SafeArg;
using Firebird::FbLocalStatus;
@ -104,7 +105,7 @@ enum scan_attr_t
void add_access_dpb(BurpGlobals* tdgbl, Firebird::ClumpletWriter& dpb);
void add_files(BurpGlobals* tdgbl, const char*);
void bad_attribute(scan_attr_t, att_type, USHORT);
void create_database(BurpGlobals* tdgbl, const TEXT*);
void create_database(BurpGlobals* tdgbl, Firebird::IProvider*, const TEXT*);
void decompress(BurpGlobals* tdgbl, UCHAR*, ULONG);
void eat_blob(BurpGlobals* tdgbl);
void eat_text(BurpGlobals* tdgbl);
@ -163,7 +164,7 @@ void realign(BurpGlobals* tdgbl, UCHAR*, const burp_rel*);
#ifdef sparc
USHORT recompute_length(BurpGlobals* tdgbl, burp_rel*);
#endif
bool restore(BurpGlobals* tdgbl, const TEXT*, const TEXT*);
bool restore(BurpGlobals* tdgbl, Firebird::IProvider*, const TEXT*, const TEXT*);
void restore_security_class(BurpGlobals* tdgbl, const TEXT*, const TEXT*);
USHORT get_view_base_relation_count(BurpGlobals* tdgbl, const TEXT*, USHORT, bool* error);
void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SINT64 initial_value,
@ -184,13 +185,9 @@ const SSHORT old_sparcs[] =
{0, 0, 0, 2, 0, 0, 0, 0, 2, 4, 4, 4, 8, 8, 0, 0, 8, 8, 8};
#endif
//MVOL_read returns int
static inline int get(BurpGlobals* tdgbl)
static inline UCHAR get(BurpGlobals* tdgbl)
{
if (--(tdgbl->io_cnt) >= 0)
return *(tdgbl->io_ptr)++;
return MVOL_read(&tdgbl->io_cnt, &tdgbl->io_ptr);
return tdgbl->get();
}
static inline FB_BOOLEAN get_boolean(BurpGlobals* tdgbl)
@ -283,22 +280,11 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
Firebird::IRequest* req_handle5 = nullptr;
BASED_ON RDB$INDICES.RDB$INDEX_NAME index_name;
Firebird::DispatcherPtr provider;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
tdgbl->io_ptr = NULL;
tdgbl->io_cnt = 0;
tdgbl->relations = NULL;
tdgbl->packages = NULL;
tdgbl->procedures = NULL;
tdgbl->miss_privs = NULL;
tdgbl->RESTORE_format = 0;
tdgbl->runtimeODS = 0;
tdgbl->global_trans = 0;
tdgbl->gbl_sw_transportable = tdgbl->gbl_sw_compress = false;
if (!restore(tdgbl, file_name, database_name))
if (!restore(tdgbl, provider, file_name, database_name))
return FINI_ERROR;
BURP_verbose (76);
@ -580,7 +566,7 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
// set forced writes to the value which was in the header
dpb.insertByte(isc_dpb_force_write, tdgbl->hdr_forced_writes ? 1 : 0);
Firebird::IAttachment* db_handle = Firebird::DispatcherPtr()->attachDatabase(&tdgbl->status_vector, database_name,
Firebird::IAttachment* db_handle = provider->attachDatabase(&tdgbl->status_vector, database_name,
dpb.getBufferLength(), dpb.getBuffer());
if (tdgbl->status_vector->hasData())
general_on_error();
@ -608,7 +594,7 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
dpb.insertByte(isc_dpb_set_db_readonly, 1);
db_handle = Firebird::DispatcherPtr()->attachDatabase(&tdgbl->status_vector, database_name,
db_handle = provider->attachDatabase(&tdgbl->status_vector, database_name,
dpb.getBufferLength(), dpb.getBuffer());
if (tdgbl->status_vector->hasData())
general_on_error();
@ -807,9 +793,32 @@ private:
unsigned* version;
};
class EngineVersion :
public Firebird::AutoIface<Firebird::IVersionCallbackImpl<EngineVersion, Firebird::CheckStatusWrapper> >
{
public:
EngineVersion(char* v)
: version(v)
{
version[0] = 0;
}
// IVersionCallback implementation
void callback(Firebird::CheckStatusWrapper*, const char* text)
{
if (!version[0])
strcpy(version, text);
}
private:
char* version;
};
} // anonymous namespace
void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
void create_database(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file_name)
{
/**************************************
*
@ -836,6 +845,8 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
ULONG page_buffers = 0;
USHORT SQL_dialect = 0;
tdgbl->gbl_database_file_name = file_name;
att_type attribute;
rec_type record;
if (get_record(&record, tdgbl) == rec_physical_db)
@ -974,7 +985,9 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
// start database up shut down,
// use single-user mode to avoid conflicts during restore process
dpb.insertByte(isc_dpb_shutdown, isc_dpb_shut_attachment | isc_dpb_shut_single);
// when crypt thread to run use multi-DBO mode
dpb.insertByte(isc_dpb_shutdown, isc_dpb_shut_attachment |
(tdgbl->gbl_sw_keyholder ? isc_dpb_shut_multi : isc_dpb_shut_single));
dpb.insertInt(isc_dpb_shutdown_delay, 0);
dpb.insertInt(isc_dpb_overwrite, tdgbl->gbl_sw_overwrite);
@ -988,8 +1001,19 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
fb_strlen(tdgbl->gbl_sw_fix_fss_metadata));
}
DB = Firebird::DispatcherPtr()->createDatabase(&status_vector, file_name,
dpb.getBufferLength(), dpb.getBuffer());
// provide crypt key(s) for engine
if (tdgbl->gbl_sw_keyholder)
{
provider->setDbCryptCallback(&status_vector, MVOL_get_crypt(tdgbl));
if (!status_vector.isSuccess())
{
BURP_print_status(true, &status_vector);
BURP_exit_local(FINI_ERROR, tdgbl);
}
}
DB = provider->createDatabase(&status_vector, file_name, dpb.getBufferLength(), dpb.getBuffer());
if (status_vector->hasData())
{
BURP_error_redirect(&status_vector, 33, SafeArg() << file_name);
@ -1017,6 +1041,100 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
BURP_verbose (74, SafeArg() << file_name << page_size);
// msg 74 created database %s, page_size %ld bytes
if (tdgbl->gbl_sw_keyholder)
{
// check server version
char buf[256];
EngineVersion ev(buf);
Firebird::UtilInterfacePtr()->getFbVersion(&status_vector, DB, &ev);
const char* ptr = strstr(buf, "version \"");
int v = 0;
int c = 1;
if (ptr)
{
while(ptr && *ptr)
{
if (*ptr >='0' && *ptr <= '9')
{
v *= 100;
v += atoi(ptr);
if (c >= 3)
{
if (v < 30004)
ptr = NULL;
break;
}
++c;
ptr = strchr(ptr, '.');
}
else
++ptr;
}
}
if (!(ptr && *ptr))
{
Firebird::string x;
x.printf("Undefined or too small server version: %s, need at least 3.0.4", buf);
(Firebird::Arg::Gds(isc_random) << x).raise();
}
EXEC SQL SET TRANSACTION;
if (gds_status->hasData())
general_on_error ();
if (!tdgbl->gbl_sw_crypt)
{
BURP_error(true, 378);
// Unknown crypt plugin name - use -CRYPT switch
}
Firebird::string sql;
sql.printf("ALTER DATABASE ENCRYPT WITH \"%s\"", tdgbl->gbl_sw_crypt);
if (tdgbl->gbl_sw_keyname)
{
sql += " KEY ";
sql += tdgbl->gbl_sw_keyname;
}
tdgbl->db_handle->execute(gds_status, tdgbl->tr_handle, sql.length(), sql.c_str(), 3,
nullptr, nullptr, nullptr, nullptr);
if (gds_status->hasData())
general_on_error ();
COMMIT
ON_ERROR
general_on_error ();
END_ERROR;
UCHAR buffer[100];
UCHAR item = fb_info_crypt_state;
bool complete = false;
for (int i = 0; i < 100; ++i)
{
Thread::sleep(100);
tdgbl->db_handle->getInfo(gds_status, sizeof(item), &item, sizeof(buffer), buffer);
if (gds_status->hasData())
general_on_error ();
const UCHAR* d = buffer;
if (*d++ != fb_info_crypt_state)
BURP_error(385, true);
const int length = gds__vax_integer(d, 2);
d += 2;
const int value = gds__vax_integer(d, length);
if (value & fb_info_crypt_encrypted && !(value & fb_info_crypt_process))
{
complete = true;
break;
}
}
if (!complete)
BURP_error(386, true);
}
}
void decompress(BurpGlobals* tdgbl, UCHAR* buffer, ULONG length)
@ -10348,7 +10466,7 @@ USHORT recompute_length(BurpGlobals* tdgbl, burp_rel* relation)
}
#endif
bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_name)
bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file_name, const TEXT* database_name)
{
/**************************************
*
@ -10363,7 +10481,7 @@ bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_nam
// Read burp record first
MVOL_init_read (file_name, &tdgbl->RESTORE_format, &tdgbl->io_cnt, &tdgbl->io_ptr);
MVOL_init_read (file_name, &tdgbl->RESTORE_format);
if (tdgbl->gbl_sw_transportable)
BURP_verbose (133);
@ -10383,7 +10501,7 @@ bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_nam
BURP_verbose(349, SafeArg() << tdgbl->RESTORE_format); // backup version is @1
create_database(tdgbl, database_name);
create_database(tdgbl, provider, database_name);
EXEC SQL SET TRANSACTION NO_AUTO_UNDO;
if (gds_status->hasData())

View File

@ -145,6 +145,7 @@ public:
virtual bool finished() { return false; }
virtual void initStatus() { }
virtual bool utf8FileNames() { return false; }
virtual Firebird::ICryptKeyCallback* getCryptCallback() { return NULL; }
};

View File

@ -30,6 +30,8 @@
#ifndef FB_UTILFACE
#define FB_UTILFACE
#include "firebird/Interface.h"
#include "../common/classes/alloc.h"
#include "../common/classes/array.h"
#include "../common/classes/fb_string.h"
@ -74,6 +76,7 @@ public:
virtual bool finished() = 0;
virtual unsigned int getAuthBlock(const unsigned char** bytes) = 0;
virtual bool utf8FileNames() = 0;
virtual Firebird::ICryptKeyCallback* getCryptCallback() = 0;
void setDataMode(bool value)
{

View File

@ -334,7 +334,9 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
case isc_spb_res_fix_fss_metadata:
case isc_spb_bkp_stat:
case isc_spb_bkp_skip_data:
//case isc_spb_res_skip_data: // same value
case isc_spb_bkp_keyholder:
case isc_spb_bkp_keyname:
case isc_spb_bkp_crypt:
return StringSpb;
case isc_spb_bkp_factor:
case isc_spb_bkp_length:

View File

@ -30,6 +30,7 @@
#define FB_COMMON_CLASSES_GET_PLUGINS
#include "../common/classes/ImplementHelper.h"
#include "../common/classes/auto.h"
#include "../common/config/config.h"
#include "../common/StatusHolder.h"

View File

@ -130,6 +130,13 @@ namespace Firebird
return ptr;
}
void moveFrom(RefPtr& r)
{
assign(NULL);
ptr = r.ptr;
r.ptr = NULL;
}
T* operator=(T* p)
{
return assign(p);

View File

@ -393,6 +393,9 @@
#define isc_spb_bkp_length 7
#define isc_spb_bkp_skip_data 8
#define isc_spb_bkp_stat 15
#define isc_spb_bkp_keyholder 16
#define isc_spb_bkp_keyname 17
#define isc_spb_bkp_crypt 18
#define isc_spb_bkp_ignore_checksums 0x01
#define isc_spb_bkp_ignore_limbo 0x02
#define isc_spb_bkp_metadata_only 0x04
@ -402,6 +405,7 @@
#define isc_spb_bkp_convert 0x40
#define isc_spb_bkp_expand 0x80
#define isc_spb_bkp_no_triggers 0x8000
#define isc_spb_bkp_zip 0x010000
/********************************************
* Parameters for isc_action_svc_properties *
@ -505,6 +509,9 @@
#define isc_spb_res_access_mode 12
#define isc_spb_res_fix_fss_data 13
#define isc_spb_res_fix_fss_metadata 14
#define isc_spb_res_keyholder isc_spb_bkp_keyholder
#define isc_spb_res_keyname isc_spb_bkp_keyname
#define isc_spb_res_crypt isc_spb_bkp_crypt
#define isc_spb_res_stat isc_spb_bkp_stat
#define isc_spb_res_metadata_only isc_spb_bkp_metadata_only
#define isc_spb_res_deactivate_idx 0x0100

View File

@ -906,6 +906,7 @@ static const struct {
{"hdr_overflow", 335545202},
{"vld_plugins", 335545203},
{"db_crypt_key", 335545204},
{"no_keyholder_plugin", 335545205},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},

View File

@ -940,6 +940,7 @@ const ISC_STATUS isc_map_overflow = 335545201L;
const ISC_STATUS isc_hdr_overflow = 335545202L;
const ISC_STATUS isc_vld_plugins = 335545203L;
const ISC_STATUS isc_db_crypt_key = 335545204L;
const ISC_STATUS isc_no_keyholder_plugin = 335545205L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@ -1414,7 +1415,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
const ISC_STATUS isc_err_max = 1358;
const ISC_STATUS isc_err_max = 1359;
#else /* c definitions */
@ -2324,6 +2325,7 @@ const ISC_STATUS isc_err_max = 1358;
#define isc_hdr_overflow 335545202L
#define isc_vld_plugins 335545203L
#define isc_db_crypt_key 335545204L
#define isc_no_keyholder_plugin 335545205L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@ -2798,7 +2800,7 @@ const ISC_STATUS isc_err_max = 1358;
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1358
#define isc_err_max 1359
#endif

View File

@ -909,6 +909,7 @@ Data source : @4"}, /* eds_statement */
{335545202, "Header page overflow - too many clumplets on it"}, /* hdr_overflow */
{335545203, "No matching client/server authentication plugins configured for execute statement in embedded datasource"}, /* vld_plugins */
{335545204, "Missing database encryption key for your attachment"}, /* db_crypt_key */
{335545205, "Key holder plugin @1 failed to load"}, /* no_keyholder_plugin */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */

View File

@ -905,6 +905,7 @@ static const struct {
{335545202, -901}, /* 882 hdr_overflow */
{335545203, -901}, /* 883 vld_plugins */
{335545204, -902}, /* 884 db_crypt_key */
{335545205, -104}, /* 885 no_keyholder_plugin */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */

View File

@ -905,6 +905,7 @@ static const struct {
{335545202, "54000"}, // 882 hdr_overflow
{335545203, "28000"}, // 883 vld_plugins
{335545204, "08004"}, // 884 db_crypt_key
{335545205, "HY024"}, // 885 no_keyholder_plugin
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw

View File

@ -265,6 +265,7 @@ namespace Jrd {
: PermanentStorage(*tdbb->getDatabase()->dbb_permanent),
sync(this),
keyName(getPool()),
pluginName(getPool()),
keyProviders(getPool()),
keyConsumers(getPool()),
hash(getPool()),
@ -366,6 +367,7 @@ namespace Jrd {
keyName = "";
loadPlugin(tdbb, hdr->hdr_crypt_plugin);
pluginName = hdr->hdr_crypt_plugin;
string valid;
calcValidation(valid, cryptPlugin);
@ -395,7 +397,7 @@ namespace Jrd {
}
}
void CryptoManager::loadPlugin(thread_db* tdbb, const char* pluginName)
void CryptoManager::loadPlugin(thread_db* tdbb, const char* plugName)
{
if (cryptPlugin)
{
@ -408,10 +410,10 @@ namespace Jrd {
return;
}
AutoPtr<Factory> cryptControl(FB_NEW Factory(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, pluginName));
AutoPtr<Factory> cryptControl(FB_NEW Factory(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, plugName));
if (!cryptControl->hasData())
{
(Arg::Gds(isc_no_crypt_plugin) << pluginName).raise();
(Arg::Gds(isc_no_crypt_plugin) << plugName).raise();
}
// do not assign cryptPlugin directly before key init complete
@ -461,6 +463,7 @@ namespace Jrd {
cryptPlugin = p;
cryptPlugin->addRef();
pluginName = plugName;
// remove old factory if present
delete checkFactory;
@ -1326,6 +1329,11 @@ namespace Jrd {
return keyName.c_str();
}
const char* CryptoManager::getPluginName() const
{
return pluginName.c_str();
}
void CryptoManager::addClumplet(string& signature, ClumpletReader& block, UCHAR tag)
{
if (block.find(tag))

View File

@ -304,6 +304,7 @@ public:
ULONG getCurrentPage() const;
UCHAR getCurrentState() const;
const char* getKeyName() const;
const char* getPluginName() const;
private:
enum IoResult {SUCCESS_ALL, FAILED_CRYPT, FAILED_IO};
@ -383,7 +384,7 @@ private:
void checkDigitalSignature(thread_db* tdbb, const class Header& hdr);
BarSync sync;
Firebird::MetaName keyName;
Firebird::MetaName keyName, pluginName;
ULONG currentPage;
Firebird::Mutex pluginLoadMtx, cryptThreadMtx, holdersMutex;
AttVector keyProviders, keyConsumers;

View File

@ -62,7 +62,7 @@ SYSTEM_PRIVILEGE(USE_GRANTED_BY_CLAUSE)
SYSTEM_PRIVILEGE(GRANT_REVOKE_ON_ANY_OBJECT)
SYSTEM_PRIVILEGE(GRANT_REVOKE_ANY_DDL_RIGHT)
SYSTEM_PRIVILEGE(CREATE_PRIVILEGED_ROLES)
SYSTEM_PRIVILEGE(GET_DBCRYPT_KEY_NAME)
SYSTEM_PRIVILEGE(GET_DBCRYPT_INFO)
#ifdef FB_JRD_SYSTEM_PRIVILEGES_TMP
maxSystemPrivilege

View File

@ -770,7 +770,7 @@ void INF_database_info(thread_db* tdbb,
break;
case fb_info_crypt_key:
if (tdbb->getAttachment()->locksmith(tdbb, GET_DBCRYPT_KEY_NAME))
if (tdbb->getAttachment()->locksmith(tdbb, GET_DBCRYPT_INFO))
{
const char* key = dbb->dbb_crypto_manager->getKeyName();
if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(key)), key, info, end)))
@ -788,6 +788,25 @@ void INF_database_info(thread_db* tdbb,
length = 1 + INF_convert(isc_adm_task_denied, buffer + 1);
break;
case fb_info_crypt_plugin:
if (tdbb->getAttachment()->locksmith(tdbb, GET_DBCRYPT_INFO))
{
const char* key = dbb->dbb_crypto_manager->getPluginName();
if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(key)), key, info, end)))
{
if (transaction)
TRA_commit(tdbb, transaction, false);
return;
}
continue;
}
buffer[0] = item;
item = isc_info_error;
length = 1 + INF_convert(isc_adm_task_denied, buffer + 1);
break;
case fb_info_conn_flags:
length = INF_convert(tdbb->getAttachment()->att_remote_flags, buffer);
break;

View File

@ -148,7 +148,6 @@ enum db_info_types
fb_info_ses_idle_timeout_run = 131,
fb_info_conn_flags = 132,
fb_info_protocol_version = 133,
fb_info_crypt_key = 133,
fb_info_crypt_state = 134,
@ -156,6 +155,9 @@ enum db_info_types
fb_info_statement_timeout_db = 135,
fb_info_statement_timeout_att = 136,
fb_info_protocol_version = 137,
fb_info_crypt_plugin = 138,
isc_info_db_last_value /* Leave this LAST! */
};

View File

@ -647,6 +647,11 @@ bool Service::utf8FileNames()
return svc_utf8;
}
Firebird::ICryptKeyCallback* Service::getCryptCallback()
{
return svc_crypt_callback;
}
void Service::need_admin_privs(Arg::StatusVector& status, const char* message)
{
status << Arg::Gds(isc_insufficient_svc_privileges) << Arg::Str(message);
@ -2933,6 +2938,9 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
case isc_spb_res_fix_fss_metadata:
case isc_spb_bkp_stat:
case isc_spb_bkp_skip_data:
case isc_spb_bkp_keyholder:
case isc_spb_bkp_keyname:
case isc_spb_bkp_crypt:
if (!get_action_svc_parameter(spb.getClumpTag(), reference_burp_in_sw_table, switches))
{
return false;

View File

@ -141,6 +141,8 @@ public: // utilities interface with service
virtual void fillDpb(Firebird::ClumpletWriter& dpb);
// encoding for string parameters passed to utility
virtual bool utf8FileNames();
// get database encryption key transfer callback routine
virtual Firebird::ICryptKeyCallback* getCryptCallback();
virtual TraceManager* getTraceManager()
{
@ -196,7 +198,6 @@ public: // external interface with service
const Firebird::string& getRemoteProcess() const { return svc_remote_process; }
int getRemotePID() const { return svc_remote_pid; }
const Firebird::PathName& getExpectedDb() const { return svc_expected_db; }
Firebird::ICryptKeyCallback* getCryptCallback() { return svc_crypt_callback; }
private:
// Service must have private destructor, called from finish

View File

@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
--
('2018-02-01 17:40:00', 'JRD', 0, 885)
('2018-05-05 16:40:00', 'JRD', 0, 886)
('2015-03-17 18:33:00', 'QLI', 1, 533)
('2015-01-07 18:01:51', 'GFIX', 3, 134)
('1996-11-07 13:39:40', 'GPRE', 4, 1)
@ -9,7 +9,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
('2018-01-15 00:15:00', 'DYN', 8, 299)
('1996-11-07 13:39:40', 'INSTALL', 10, 1)
('1996-11-07 13:38:41', 'TEST', 11, 4)
('2018-02-19 19:40:00', 'GBAK', 12, 372)
('2018-04-26 20:40:00', 'GBAK', 12, 387)
('2015-08-05 12:40:00', 'SQLERR', 13, 1045)
('1996-11-07 13:38:42', 'SQLWARN', 14, 613)
('2018-02-27 14:50:31', 'JRD_BUGCHK', 15, 308)

View File

@ -992,6 +992,7 @@ Data source : @4', NULL, NULL)
('hdr_overflow', NULL, 'CryptoManager.cpp', NULL, 0, 882, NULL, 'Header page overflow - too many clumplets on it', NULL, NULL);
('vld_plugins', NULL, 'ValidatePassword.cpp', NULL, 0, 883, NULL, 'No matching client/server authentication plugins configured for execute statement in embedded datasource', NULL, NULL);
('db_crypt_key', NULL, 'CryptoManager.cpp', NULL, 0, 884, NULL, 'Missing database encryption key for your attachment', NULL, NULL);
('no_keyholder_plugin', NULL, 'mvol.cpp', NULL, 0, 885, NULL, 'Key holder plugin @1 failed to load', NULL, NULL);
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
@ -2464,6 +2465,21 @@ ERROR: Backup incomplete', NULL, NULL);
(NULL, 'api_gbak/gbak', 'burp.cpp', NULL, 12, 369, NULL, 'total statistics', NULL, NULL);
(NULL, 'get_blob', 'restore.epp', NULL, 12, 370, NULL, 'could not append BLOB data to batch', NULL, NULL);
(NULL, 'get_data', 'restore.epp', NULL, 12, 371, NULL, 'could not start batch when restoring table @1, trying old way', NULL, NULL);
(NULL, 'burp_usage', 'burp.cpp', NULL, 12, 372, NULL, ' @1KEYNAME name of a key to be used for encryption', NULL, NULL);
(NULL, 'burp_usage', 'burp.cpp', NULL, 12, 373, NULL, ' @1CRYPT crypt plugin name', NULL, NULL);
(NULL, 'burp_usage', 'burp.cpp', NULL, 12, 374, NULL, ' @1ZIP backup file is in zip compressed format', NULL, NULL);
(NULL, 'gbak', 'burp.cpp', NULL, 12, 375, NULL, 'Keyname parameter missing', NULL, NULL);
(NULL, 'gbak', 'burp.cpp', NULL, 12, 376, NULL, 'Key holder parameter missing but backup file is encrypted', NULL, NULL);
(NULL, 'gbak', 'mvol.cpp', NULL, 12, 377, NULL, 'CryptPlugin parameter missing', NULL, NULL);
(NULL, 'gbak', 'burp.cpp', NULL, 12, 378, NULL, 'Unknown crypt plugin name - use -CRYPT switch', NULL, NULL);
(NULL, NULL, 'mvol.cpp', NULL, 12, 379, NULL, 'Inflate error @1', NULL, NULL);
(NULL, NULL, 'mvol.cpp', NULL, 12, 380, NULL, 'Deflate error @1', NULL, NULL);
(NULL, 'gbak', 'burp.cpp', NULL, 12, 381, NULL, 'Key holder parameter missing', NULL, NULL);
(NULL, 'burp_usage', 'burp.cpp', NULL, 12, 382, NULL, ' @1KEYHOLDER name of a key holder plugin', NULL, NULL);
(NULL, NULL, 'mvol.cpp', NULL, 12, 383, NULL, 'Decompression stream init error @1', NULL, NULL);
(NULL, NULL, 'mvol.cpp', NULL, 12, 384, NULL, 'Compression stream init error @1', NULL, NULL);
(NULL, NULL, 'restore.epp', NULL, 12, 385, NULL, 'Invalid reply from getInfo() when waiting for DB encryption', NULL, NULL);
(NULL, NULL, 'restore.epp', NULL, 12, 386, NULL, 'Problems with just created database encryption', NULL, NULL);
-- SQLERR
(NULL, NULL, NULL, NULL, 13, 1, NULL, 'Firebird error', NULL, NULL);
(NULL, NULL, NULL, NULL, 13, 74, NULL, 'Rollback not performed', NULL, NULL);

View File

@ -891,6 +891,7 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
(-901, '54', '000', 0, 882, 'hdr_overflow', NULL, NULL)
(-901, '28', '000', 0, 883, 'vld_plugins', NULL, NULL)
(-902, '08', '004', 0, 884, 'db_crypt_key', NULL, NULL)
(-104, 'HY', '024', 0, 885, 'no_keyholder_plugin', NULL, NULL)
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)

View File

@ -41,7 +41,9 @@
#include "../common/classes/timestamp.h"
#include "../common/utils_proto.h"
#include "../common/classes/MsgPrint.h"
#include "../common/classes/GetPlugins.h"
#include "../common/StatusArg.h"
#include "../common/status.h"
#include "../common/os/os_utils.h"
#include "../jrd/license.h"
@ -108,6 +110,32 @@ bool putStringArgument(char**& av, ClumpletWriter& spb, unsigned int tag)
return true;
}
// add callback to named KeyHolderPlugin
IKeyHolderPlugin* keyHolder = NULL;
bool putCallback(char**& av, ClumpletWriter&, unsigned int)
{
if (! *av)
return false;
char* x = *av++;
GetPlugins<IKeyHolderPlugin> keyControl(IPluginManager::TYPE_KEY_HOLDER, x);
if (!keyControl.hasData())
(Firebird::Arg::Gds(isc_no_keyholder_plugin) << x).raise();
keyHolder = keyControl.plugin();
keyHolder->addRef(); // Leak memory, OK for utility
FbLocalStatus st;
ICryptKeyCallback* cb = keyHolder->chainHandle(&st);
check(&st);
ISC_STATUS_ARRAY status;
if (fb_database_crypt_callback(status, cb) != 0)
status_exception::raise(status);
return true;
}
// add string tag from file (fetch password)
bool putFileArgument(char**& av, ClumpletWriter& spb, unsigned int tag)
@ -341,6 +369,7 @@ const SvcSwitches attSwitch[] =
{"fetch_password", putFileArgument, 0, isc_spb_password, 0},
{"trusted_auth", putSingleTag, 0, isc_spb_trusted_auth, 0},
{"expected_db", putStringArgument, 0, isc_spb_expected_db, 0},
{"key_holder", putCallback, 0, 0, 0},
{0, 0, 0, 0, 0}
};
@ -376,6 +405,10 @@ const SvcSwitches backupOptions[] =
{"verbint", putIntArgument, 0, isc_spb_verbint, 0},
{"bkp_skip_data", putStringArgument, 0, isc_spb_bkp_skip_data, 0},
{"bkp_stat", putStringArgument, 0, isc_spb_bkp_stat, 0 },
{"bkp_keyholder", putStringArgument, 0, isc_spb_bkp_keyholder, 0 },
{"bkp_keyname", putStringArgument, 0, isc_spb_bkp_keyname, 0 },
{"bkp_crypt", putStringArgument, 0, isc_spb_bkp_crypt, 0 },
{"bkp_zip", putOption, 0, isc_spb_bkp_zip, 0 },
{0, 0, 0, 0, 0}
};
@ -401,6 +434,9 @@ const SvcSwitches restoreOptions[] =
{"verbint", putIntArgument, 0, isc_spb_verbint, 0},
{"res_skip_data", putStringArgument, 0, isc_spb_res_skip_data, 0},
{"res_stat", putStringArgument, 0, isc_spb_res_stat, 0 },
{"res_keyholder", putStringArgument, 0, isc_spb_res_keyholder, 0 },
{"res_keyname", putStringArgument, 0, isc_spb_res_keyname, 0 },
{"res_crypt", putStringArgument, 0, isc_spb_res_crypt, 0 },
{0, 0, 0, 0, 0}
};
@ -961,6 +997,7 @@ struct TypeText
{ putBigIntArgument, "int64 value", "456" },
{ putOption, NULL, "" },
{ putSingleTag, NULL, "" },
{ putCallback, "key holder plugin name", NULL },
{ NULL, NULL , NULL }
};
@ -1003,6 +1040,9 @@ void testSvc(isc_svc_handle* h, ClumpletWriter& spb, const SvcSwitches* sw)
{
if (sw->populate == tt->populate)
{
if (!tt->testArg)
break;
// some tricks to emulate 'char* argv[]'
char x[100];
strcpy(x, tt->testArg);