From c95a287cc93e062e460104ee4e400351ebe8ae05 Mon Sep 17 00:00:00 2001 From: Roman Simakov Date: Tue, 25 Oct 2016 15:09:32 +0300 Subject: [PATCH] Added default sql security for database to make it possible to be more relevant to SQL Standard --- src/burp/backup.epp | 2 ++ src/burp/burp.h | 1 + src/burp/restore.epp | 32 +++++++++++++++++++++++++++++++- src/dsql/DdlNodes.epp | 9 ++++++--- src/dsql/DdlNodes.h | 1 + src/dsql/parse.y | 2 ++ src/include/gen/ids.h | 1 + src/isql/extract.epp | 9 +++++++++ src/isql/show.epp | 3 +++ src/jrd/Database.h | 1 + src/jrd/Function.epp | 9 +++++++-- src/jrd/irq.h | 1 + src/jrd/met.epp | 41 +++++++++++++++++++++++++++++++++++++++-- src/jrd/met_proto.h | 1 + src/jrd/relations.h | 1 + 15 files changed, 106 insertions(+), 8 deletions(-) diff --git a/src/burp/backup.epp b/src/burp/backup.epp index d639ea50dd..cbaa53ad29 100644 --- a/src/burp/backup.epp +++ b/src/burp/backup.epp @@ -2731,6 +2731,8 @@ void write_database( const TEXT* dbb_file) PUT_TEXT (att_database_dfl_charset, D.RDB$CHARACTER_SET_NAME); if (!D.RDB$LINGER.NULL) put_int32(att_database_linger, D.RDB$LINGER); + if (!D.RDB$SQL_SECURITY.NULL) + put_boolean(att_database_sql_security, D.RDB$SQL_SECURITY); END_FOR; ON_ERROR general_on_error(); diff --git a/src/burp/burp.h b/src/burp/burp.h index f605689c9c..1e74b60f3b 100644 --- a/src/burp/burp.h +++ b/src/burp/burp.h @@ -249,6 +249,7 @@ enum att_type { att_SQL_dialect, // SQL dialect that it speaks att_db_read_only, // Is the database ReadOnly? att_database_linger, // Disconnection timeout + att_database_sql_security,// default sql security value // Relation attributes diff --git a/src/burp/restore.epp b/src/burp/restore.epp index 6c2a13b94d..77ce97cb05 100644 --- a/src/burp/restore.epp +++ b/src/burp/restore.epp @@ -9780,7 +9780,7 @@ bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_nam // msg 129 started transaction att_type attribute; - isc_req_handle req_handle2 = 0, req_handle3 = 0, req_handle4 = 0; + isc_req_handle req_handle2 = 0, req_handle3 = 0, req_handle4 = 0, req_handle5 = 0; while (get_attribute(&attribute, tdgbl) != att_end) { @@ -9857,6 +9857,35 @@ bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_nam } break; + case att_database_sql_security: + if (tdgbl->RESTORE_format >= 11) + { + if (tdgbl->runtimeODS >= DB_VERSION_DDL12) + { + FOR (REQUEST_HANDLE req_handle5) + X IN RDB$DATABASE + MODIFY X USING + X.RDB$SQL_SECURITY = get_boolean(tdgbl); + END_MODIFY; + ON_ERROR + general_on_error(); + END_ERROR; + END_FOR; + ON_ERROR + general_on_error(); + END_ERROR; + } + else + get_boolean(tdgbl); + } + else + { + // Functions that use scan_next_attr initialize it to NO_SKIP using skip_init(). + // Here we don't use that logic, hence the first param to bad_attribute is hardcoded. + bad_attribute(NO_SKIP, attribute, 352); + } + break; + default: { SSHORT l = get(tdgbl); @@ -9870,6 +9899,7 @@ bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_nam MISC_release_request_silent(req_handle2); MISC_release_request_silent(req_handle3); MISC_release_request_silent(req_handle4); + MISC_release_request_silent(req_handle5); if (tdgbl->gbl_sw_fix_fss_data) { diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp index f9ce138926..6a8fdcc6fb 100644 --- a/src/dsql/DdlNodes.epp +++ b/src/dsql/DdlNodes.epp @@ -7585,14 +7585,11 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc case Clause::TYPE_ALTER_SQL_SECURITY: { AutoRequest request; - bool found = false; FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) REL IN RDB$RELATIONS WITH REL.RDB$RELATION_NAME EQ name.c_str() { - found = true; - MODIFY REL { const Nullable ssDefiner = @@ -11949,6 +11946,12 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc DBB.RDB$LINGER = linger; } + if (ssDefiner.specified) + { + DBB.RDB$SQL_SECURITY.NULL = FALSE; + DBB.RDB$SQL_SECURITY = ssDefiner.value ? FB_TRUE : FB_FALSE; + } + if (clauses & CLAUSE_BEGIN_BACKUP) changeBackupMode(tdbb, transaction, CLAUSE_BEGIN_BACKUP); diff --git a/src/dsql/DdlNodes.h b/src/dsql/DdlNodes.h index 7be6960714..1af1e4471f 100644 --- a/src/dsql/DdlNodes.h +++ b/src/dsql/DdlNodes.h @@ -2318,6 +2318,7 @@ public: Firebird::Array > files; Firebird::MetaName cryptPlugin; Firebird::MetaName keyName; + Nullable ssDefiner; }; diff --git a/src/dsql/parse.y b/src/dsql/parse.y index bb67ceda42..3573266a77 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -4146,6 +4146,8 @@ db_alter_clause($alterDatabaseNode) { $alterDatabaseNode->linger = $4; } | DROP LINGER { $alterDatabaseNode->linger = 0; } + | SET DEFAULT sql_security_clause + { $alterDatabaseNode->ssDefiner = $3; } ; %type crypt_key_clause() diff --git a/src/include/gen/ids.h b/src/include/gen/ids.h index e84174fc01..0de44b8932 100644 --- a/src/include/gen/ids.h +++ b/src/include/gen/ids.h @@ -40,6 +40,7 @@ const USHORT f_dat_class = 2; const USHORT f_dat_charset = 3; const USHORT f_dat_linger = 4; + const USHORT f_dat_sql_security = 5; // Relation 2 (RDB$FIELDS) diff --git a/src/isql/extract.epp b/src/isql/extract.epp index 0a1c3e37ba..87362a0d03 100644 --- a/src/isql/extract.epp +++ b/src/isql/extract.epp @@ -2076,6 +2076,15 @@ static void list_create_db() return; END_ERROR; + FOR DBPSS IN RDB$DATABASE + WITH DBPSS.RDB$SQL_SECURITY NOT MISSING + AND DBPSS.RDB$SQL_SECURITY == FB_TRUE + isqlGlob.printf("%sALTER DATABASE SET DEFAULT SQL SECURITY DEFINER%s", NEWLINE, isqlGlob.global_Term); + END_FOR + ON_ERROR + ISQL_errmsg(fbStatus); + return; + END_ERROR; if (nodb) isqlGlob.printf(" */%s", NEWLINE); diff --git a/src/isql/show.epp b/src/isql/show.epp index 11642656ad..b474fd984b 100644 --- a/src/isql/show.epp +++ b/src/isql/show.epp @@ -3544,6 +3544,9 @@ static void show_db() if (!DBB2.RDB$LINGER.NULL && DBB2.RDB$LINGER > 0) isqlGlob.printf("Linger: %d seconds%s", DBB2.RDB$LINGER, NEWLINE); + if (!DBB2.RDB$SQL_SECURITY.NULL && DBB2.RDB$SQL_SECURITY == FB_TRUE) + isqlGlob.printf("SQL SECURITY DEFINER%s", NEWLINE); + if (++pass > 1) isqlGlob.printf("RDB$DATABASE has more than one record%s", NEWLINE); diff --git a/src/jrd/Database.h b/src/jrd/Database.h index 0eab40d1da..82a31132c8 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -470,6 +470,7 @@ public: unsigned dbb_linger_seconds; time_t dbb_linger_end; Firebird::RefPtr dbb_plugin_config; + Nullable dbb_ss_definer; // default sql security value // returns true if primary file is located on raw device bool onRawDevice() const; diff --git a/src/jrd/Function.epp b/src/jrd/Function.epp index 5dbf0afbb5..3ca90daa58 100644 --- a/src/jrd/Function.epp +++ b/src/jrd/Function.epp @@ -246,8 +246,13 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT END_FOR } - if (!function->ssDefiner.specified && !X.RDB$SQL_SECURITY.NULL) - function->ssDefiner = (bool) X.RDB$SQL_SECURITY; + if (!function->ssDefiner.specified) + { + if (!X.RDB$SQL_SECURITY.NULL) + function->ssDefiner = (bool) X.RDB$SQL_SECURITY; + else + function->ssDefiner = MET_get_ss_definer(tdbb); + } size_t count = 0; ULONG length = 0; diff --git a/src/jrd/irq.h b/src/jrd/irq.h index 0e22fa485d..a02f92578b 100644 --- a/src/jrd/irq.h +++ b/src/jrd/irq.h @@ -179,6 +179,7 @@ enum irq_type_t irq_l_curr_format, // lookup table's current format irq_linger, // get database linger value + irq_dbb_ss_definer, // get database sql security value irq_MAX }; diff --git a/src/jrd/met.epp b/src/jrd/met.epp index 9b9651dcf0..9793e646a2 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -1974,6 +1974,7 @@ void MET_load_trigger(thread_db* tdbb, Nullable ssDefiner; + // If SQL SECURITY for relation was not specified it will re-use DB default so we should not care about it if (!TRG.RDB$SQL_SECURITY.NULL) ssDefiner = (bool) TRG.RDB$SQL_SECURITY; else if (relation) @@ -3343,8 +3344,13 @@ jrd_prc* MET_procedure(thread_db* tdbb, USHORT id, bool noscan, USHORT flags) END_FOR } - if (!procedure->ssDefiner.specified && !P.RDB$SQL_SECURITY.NULL) - procedure->ssDefiner = (bool) P.RDB$SQL_SECURITY; + if (!procedure->ssDefiner.specified) + { + if (!P.RDB$SQL_SECURITY.NULL) + procedure->ssDefiner = (bool) P.RDB$SQL_SECURITY; + else + procedure->ssDefiner = MET_get_ss_definer(tdbb); + } procedure->owner = P.RDB$OWNER_NAME; procedure->setImplemented(true); @@ -3801,6 +3807,8 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation) if (!REL.RDB$SQL_SECURITY.NULL) relation->rel_ss_definer = (bool) REL.RDB$SQL_SECURITY; + else + relation->rel_ss_definer = MET_get_ss_definer(tdbb); if (!REL.RDB$VIEW_BLR.isEmpty()) { @@ -5380,3 +5388,32 @@ int MET_get_linger(thread_db* tdbb) return rc; } + +Nullable MET_get_ss_definer(Jrd::thread_db* tdbb) +{ +/************************************** + * + * M E T _ s s _ d e f i n e r + * + ************************************** + * + * Functional description + * Return sql security value for current database + * + **************************************/ + SET_TDBB(tdbb); + Attachment* attachment = tdbb->getAttachment(); + Nullable r; + + AutoCacheRequest request(tdbb, irq_dbb_ss_definer, IRQ_REQUESTS); + + FOR(REQUEST_HANDLE request) + DBB IN RDB$DATABASE + { + if (!DBB.RDB$SQL_SECURITY.NULL) + r = DBB.RDB$SQL_SECURITY; + } + END_FOR + + return r; +} diff --git a/src/jrd/met_proto.h b/src/jrd/met_proto.h index df62d5a441..4c65943c4b 100644 --- a/src/jrd/met_proto.h +++ b/src/jrd/met_proto.h @@ -140,4 +140,5 @@ Firebird::MetaName MET_get_relation_field(Jrd::thread_db*, MemoryPool& csbPool, const Firebird::MetaName&, const Firebird::MetaName&, dsc*, Jrd::FieldInfo*); void MET_update_partners(Jrd::thread_db*); int MET_get_linger(Jrd::thread_db*); +Nullable MET_get_ss_definer(Jrd::thread_db*); #endif // JRD_MET_PROTO_H diff --git a/src/jrd/relations.h b/src/jrd/relations.h index 5a50cdb759..1f65369e5f 100644 --- a/src/jrd/relations.h +++ b/src/jrd/relations.h @@ -39,6 +39,7 @@ RELATION(nam_database, rel_database, ODS_8_0, rel_persistent) FIELD(f_dat_class, nam_class, fld_class, 1, ODS_8_0) FIELD(f_dat_charset, nam_charset_name, fld_charset_name, 1, ODS_8_0) FIELD(f_dat_linger, nam_linger, fld_linger, 1, ODS_12_0) + FIELD(f_dat_sql_security, nam_sql_security, fld_b_sql_security, 1, ODS_13_0) END_RELATION // Relation 2 (RDB$FIELDS)