From e956e2e6c0a14445ebc9c970baa31293fefce82a Mon Sep 17 00:00:00 2001 From: dimitr Date: Sun, 8 Jan 2012 14:05:29 +0000 Subject: [PATCH] 1) Restricted ALTER/DROP permissions to the object owners only. Now this applies to domains, charsets, collations, generators and exceptions. This fixes CORE-304: Metadata security hole - any user can alter/drop generators and exceptions. 2) Opened the gates to implement the standard USAGE privilege (CORE-2884). SQL support and validation logic are still to be developed. 3) Added the grant option to the owner permissions for packages, procedures and functions. 4) Misc cleanup and refactoring. --- src/dsql/DdlNodes.epp | 252 ++++++++++++++++++++++++++++++-------- src/dsql/PackageNodes.epp | 29 +++-- src/jrd/cvt2.cpp | 23 ---- src/jrd/cvt2_proto.h | 1 - src/jrd/drq.h | 8 ++ src/jrd/dyn.h | 4 +- src/jrd/grant.epp | 184 ++++++++++++---------------- src/jrd/ini.epp | 219 ++++++++++++++++++++++++++++----- src/jrd/ini_proto.h | 2 +- src/jrd/irq.h | 10 ++ src/jrd/met.epp | 18 +-- src/jrd/met_proto.h | 2 +- src/jrd/mov.cpp | 43 ++----- src/jrd/mov_proto.h | 3 +- src/jrd/obj.h | 2 +- src/jrd/scl.epp | 189 ++++++++++++++++++++++++++-- src/jrd/scl.h | 17 +-- src/jrd/scl_proto.h | 5 + src/jrd/types.h | 116 +++++++++--------- src/jrd/vio.cpp | 195 +++++++++++++++++------------ 20 files changed, 881 insertions(+), 441 deletions(-) diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp index c833ce8320..ba83fa563e 100644 --- a/src/dsql/DdlNodes.epp +++ b/src/dsql/DdlNodes.epp @@ -749,7 +749,7 @@ bool DdlNode::deleteSecurityClass(thread_db* tdbb, jrd_tra* transaction, void DdlNode::executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction, DdlTriggerWhen when, int action, const MetaName& objectName, const string& sqlText) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; // do nothing if user doesn't want database triggers if (attachment->att_flags & ATT_no_db_triggers) @@ -780,7 +780,8 @@ void DdlNode::executeDdlTrigger(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& name, const TypeClause& field, const string& computedSource, const BlrWriter::BlrData& computedValue) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; + const string& user_name = attachment->att_user->usr_user_name; const dsql_nod* elements = field.legacyField->fld_ranges; const USHORT dims = elements ? elements->nod_count / 2 : 0; @@ -803,6 +804,9 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& FLD.RDB$SYSTEM_FLAG = 0; strcpy(FLD.RDB$FIELD_NAME, name.c_str()); + FLD.RDB$OWNER_NAME.NULL = FALSE; + strcpy(FLD.RDB$OWNER_NAME, user_name.c_str()); + FLD.RDB$COMPUTED_SOURCE.NULL = TRUE; FLD.RDB$COMPUTED_BLR.NULL = TRUE; FLD.RDB$DIMENSIONS.NULL = TRUE; @@ -842,7 +846,7 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& if (elements) // Is the type an array? { - AutoCacheRequest request(tdbb, drq_s_fld_dym, DYN_REQUESTS); + requestHandle.reset(tdbb, drq_s_fld_dym, DYN_REQUESTS); SSHORT position = 0; const dsql_nod* const* ptr = elements->nod_arg; @@ -860,7 +864,7 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& Arg::Gds(isc_dsql_arr_range_error)); } - STORE (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) DIM IN RDB$FIELD_DIMENSIONS { strcpy(DIM.RDB$FIELD_NAME, name.c_str()); @@ -871,6 +875,21 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& END_STORE } } + + requestHandle.reset(tdbb, drq_s_gfld_prvs, DYN_REQUESTS); + + STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) + X IN RDB$USER_PRIVILEGES + { + strcpy(X.RDB$RELATION_NAME, name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); + X.RDB$USER_TYPE = obj_user; + X.RDB$OBJECT_TYPE = obj_field; + X.RDB$PRIVILEGE[0] = USAGE_PRIVILEGE; + X.RDB$PRIVILEGE[1] = 0; + X.RDB$GRANT_OPTION = 1; + } + END_STORE } @@ -1031,7 +1050,7 @@ void CommentOnNode::print(string& text, Array& /*nodes*/) const void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; const char* tableClause = NULL; const char* columnClause = NULL; @@ -1402,7 +1421,8 @@ void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsql void CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); + const string& user_name = attachment->att_user->usr_user_name; if (package.isEmpty()) { @@ -1450,7 +1470,7 @@ void CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch FUN.RDB$PRIVATE_FLAG.NULL = TRUE; FUN.RDB$OWNER_NAME.NULL = FALSE; - strcpy(FUN.RDB$OWNER_NAME, attachment->att_user->usr_user_name.c_str()); + strcpy(FUN.RDB$OWNER_NAME, user_name.c_str()); } } END_STORE @@ -1471,22 +1491,20 @@ void CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch if (package.isEmpty()) { - for (const TEXT* p = ALL_PROC_PRIVILEGES; *p; p++) - { - requestHandle.reset(tdbb, drq_s_fun_usr_prvs, DYN_REQUESTS); + requestHandle.reset(tdbb, drq_s_fun_usr_prvs, DYN_REQUESTS); - STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) - X IN RDB$USER_PRIVILEGES - { - strcpy(X.RDB$RELATION_NAME, name.c_str()); - strcpy(X.RDB$USER, attachment->att_user->usr_user_name.c_str()); - X.RDB$USER_TYPE = obj_user; - X.RDB$OBJECT_TYPE = obj_udf; - X.RDB$PRIVILEGE[0] = *p; - X.RDB$PRIVILEGE[1] = 0; - } - END_STORE + STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) + X IN RDB$USER_PRIVILEGES + { + strcpy(X.RDB$RELATION_NAME, name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); + X.RDB$USER_TYPE = obj_user; + X.RDB$OBJECT_TYPE = obj_udf; + X.RDB$PRIVILEGE[0] = EXEC_PRIVILEGE; + X.RDB$PRIVILEGE[1] = 0; + X.RDB$GRANT_OPTION = 1; } + END_STORE } executeAlter(tdbb, dsqlScratch, transaction, false, false); @@ -1495,7 +1513,7 @@ void CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction, bool secondPass, bool runTriggers) { - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); bool modified = false; @@ -1708,7 +1726,7 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch jrd_tra* transaction, unsigned pos, const ParameterClause& parameter, const bid* comment) { - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); AutoCacheRequest requestHandle(tdbb, drq_s_func_args2, DYN_REQUESTS); @@ -2353,7 +2371,8 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq void CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); + const string& user_name = attachment->att_user->usr_user_name; if (package.isEmpty()) { @@ -2399,7 +2418,7 @@ void CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc P.RDB$PACKAGE_NAME.NULL = TRUE; P.RDB$PRIVATE_FLAG.NULL = TRUE; - strcpy(P.RDB$OWNER_NAME, attachment->att_user->usr_user_name.c_str()); + strcpy(P.RDB$OWNER_NAME, user_name.c_str()); } } END_STORE @@ -2420,22 +2439,20 @@ void CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc if (package.isEmpty()) { - for (const TEXT* p = ALL_PROC_PRIVILEGES; *p; p++) - { - requestHandle.reset(tdbb, drq_s_prc_usr_prvs, DYN_REQUESTS); + requestHandle.reset(tdbb, drq_s_prc_usr_prvs, DYN_REQUESTS); - STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) - X IN RDB$USER_PRIVILEGES - { - strcpy(X.RDB$RELATION_NAME, name.c_str()); - strcpy(X.RDB$USER, attachment->att_user->usr_user_name.c_str()); - X.RDB$USER_TYPE = obj_user; - X.RDB$OBJECT_TYPE = obj_procedure; - X.RDB$PRIVILEGE[0] = *p; - X.RDB$PRIVILEGE[1] = 0; - } - END_STORE + STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) + X IN RDB$USER_PRIVILEGES + { + strcpy(X.RDB$RELATION_NAME, name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); + X.RDB$USER_TYPE = obj_user; + X.RDB$OBJECT_TYPE = obj_procedure; + X.RDB$PRIVILEGE[0] = EXEC_PRIVILEGE; + X.RDB$PRIVILEGE[1] = 0; + X.RDB$GRANT_OPTION = 1; } + END_STORE } executeAlter(tdbb, dsqlScratch, transaction, false, false); @@ -2444,7 +2461,7 @@ void CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction, bool secondPass, bool runTriggers) { - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); AutoCacheRequest requestHandle(tdbb, drq_m_prcs2, DYN_REQUESTS); bool modified = false; @@ -2604,7 +2621,7 @@ void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, DsqlCompilerScrat jrd_tra* transaction, USHORT type, unsigned pos, const ParameterClause& parameter, const bid* comment) { - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); AutoCacheRequest requestHandle(tdbb, drq_s_prms4, DYN_REQUESTS); @@ -2968,7 +2985,7 @@ void TriggerDefinition::store(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); bool modified = false; // ASF: Unregistered bug (2.0, 2.1, 2.5, 3.0): CREATE OR ALTER TRIGGER accepts different table @@ -3121,7 +3138,7 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS { fb_assert(create || alter); - Attachment* attachment = transaction->getAttachment(); + Attachment* const attachment = transaction->getAttachment(); if (relationName.isEmpty() && !attachment->locksmith()) status_exception::raise(Arg::Gds(isc_adm_task_denied)); @@ -3422,7 +3439,8 @@ void CreateCollationNode::print(string& text, Array& /*nodes*/) const void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; + const string& user_name = attachment->att_user->usr_user_name; // run all statements under savepoint control AutoSavePoint savePoint(tdbb, transaction); @@ -3439,6 +3457,9 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra strcpy(X.RDB$COLLATION_NAME, name.c_str()); X.RDB$SYSTEM_FLAG = 0; + X.RDB$OWNER_NAME.NULL = FALSE; + strcpy(X.RDB$OWNER_NAME, user_name.c_str()); + X.RDB$SPECIFIC_ATTRIBUTES.NULL = TRUE; X.RDB$BASE_COLLATION_NAME.NULL = TRUE; @@ -3572,6 +3593,21 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra } END_STORE + request.reset(tdbb, drq_s_coll_prvs, DYN_REQUESTS); + + STORE (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$USER_PRIVILEGES + { + strcpy(X.RDB$RELATION_NAME, name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); + X.RDB$USER_TYPE = obj_user; + X.RDB$OBJECT_TYPE = obj_collation; + X.RDB$PRIVILEGE[0] = USAGE_PRIVILEGE; + X.RDB$PRIVILEGE[1] = 0; + X.RDB$GRANT_OPTION = 1; + } + END_STORE + executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_COLLATION, name); @@ -3732,6 +3768,19 @@ void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc END_FOR ERASE COLL; + + if (!COLL.RDB$SECURITY_CLASS.NULL) + deleteSecurityClass(tdbb, transaction, COLL.RDB$SECURITY_CLASS); + } + END_FOR + + request.reset(tdbb, drq_e_coll_prvs, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$RELATION_NAME EQ name.c_str() + AND PRIV.RDB$OBJECT_TYPE = obj_collation + { + ERASE PRIV; } END_FOR @@ -3764,7 +3813,7 @@ void CreateDomainNode::print(string& text, Array& /*nodes*/) const void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; if (fb_utils::implicit_domain(nameType.name.c_str())) { @@ -4307,7 +4356,7 @@ void AlterDomainNode::print(string& text, Array& /*nodes*/) const void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; // run all statements under savepoint control AutoSavePoint savePoint(tdbb, transaction); @@ -4639,10 +4688,23 @@ void DropDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, ERASE X; + if (!X.RDB$SECURITY_CLASS.NULL) + deleteSecurityClass(tdbb, transaction, X.RDB$SECURITY_CLASS); + found = true; } END_FOR + request.reset(tdbb, drq_e_gfld_prvs, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$RELATION_NAME EQ name.c_str() + AND PRIV.RDB$OBJECT_TYPE = obj_field + { + ERASE PRIV; + } + END_FOR + if (found) executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_DOMAIN, name); else @@ -4755,6 +4817,9 @@ void CreateAlterExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { + Attachment* const attachment = transaction->getAttachment(); + const string& user_name = attachment->att_user->usr_user_name; + executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_EXCEPTION, name); @@ -4780,6 +4845,9 @@ void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc X.RDB$SYSTEM_FLAG = 0; strcpy(X.RDB$EXCEPTION_NAME, name.c_str()); + X.RDB$OWNER_NAME.NULL = FALSE; + strcpy(X.RDB$OWNER_NAME, user_name.c_str()); + fb_assert(message.length() < sizeof(X.RDB$MESSAGE)); strcpy(X.RDB$MESSAGE, message.c_str()); } @@ -4799,6 +4867,21 @@ void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc } } + request.reset(tdbb, drq_s_xcp_prvs, DYN_REQUESTS); + + STORE (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$USER_PRIVILEGES + { + strcpy(X.RDB$RELATION_NAME, name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); + X.RDB$USER_TYPE = obj_user; + X.RDB$OBJECT_TYPE = obj_exception; + X.RDB$PRIVILEGE[0] = USAGE_PRIVILEGE; + X.RDB$PRIVILEGE[1] = 0; + X.RDB$GRANT_OPTION = 1; + } + END_STORE + executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_EXCEPTION, name); } @@ -4858,10 +4941,24 @@ void DropExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_EXCEPTION, name); ERASE X; + + if (!X.RDB$SECURITY_CLASS.NULL) + deleteSecurityClass(tdbb, transaction, X.RDB$SECURITY_CLASS); + found = true; } END_FOR + request.reset(tdbb, drq_e_xcp_prvs, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$RELATION_NAME EQ name.c_str() + AND PRIV.RDB$OBJECT_TYPE = obj_exception + { + ERASE PRIV; + } + END_FOR + if (found) executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_EXCEPTION, name); else if (!silent) @@ -4888,14 +4985,22 @@ void CreateSequenceNode::print(string& text, Array& /*nodes*/) const void CreateSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { + // run all statements under savepoint control + AutoSavePoint savePoint(tdbb, transaction); + executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE, name); store(tdbb, transaction, name, fb_sysflag_user); executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE, name); + + savePoint.release(); // everything is ok } void CreateSequenceNode::store(thread_db* tdbb, jrd_tra* transaction, const MetaName& name, fb_sysflag sysFlag) { + Attachment* const attachment = transaction->tra_attachment; + const string& user_name = attachment->att_user->usr_user_name; + DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_generator); AutoCacheRequest request(tdbb, drq_s_gens, DYN_REQUESTS); @@ -4917,6 +5022,9 @@ void CreateSequenceNode::store(thread_db* tdbb, jrd_tra* transaction, const Meta X.RDB$GENERATOR_ID = id; X.RDB$SYSTEM_FLAG = (SSHORT) sysFlag; strcpy(X.RDB$GENERATOR_NAME, name.c_str()); + + X.RDB$OWNER_NAME.NULL = FALSE; + strcpy(X.RDB$OWNER_NAME, user_name.c_str()); } END_STORE @@ -4933,6 +5041,21 @@ void CreateSequenceNode::store(thread_db* tdbb, jrd_tra* transaction, const Meta fb_utils::init_status(tdbb->tdbb_status_vector); } } + + request.reset(tdbb, drq_s_gen_prvs, DYN_REQUESTS); + + STORE (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$USER_PRIVILEGES + { + strcpy(X.RDB$RELATION_NAME, name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); + X.RDB$USER_TYPE = obj_user; + X.RDB$OBJECT_TYPE = obj_generator; + X.RDB$PRIVILEGE[0] = USAGE_PRIVILEGE; + X.RDB$PRIVILEGE[1] = 0; + X.RDB$GRANT_OPTION = 1; + } + END_STORE } @@ -4948,6 +5071,9 @@ void DropSequenceNode::print(string& text, Array& nodes) const void DropSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { + // run all statements under savepoint control + AutoSavePoint savePoint(tdbb, transaction); + AutoCacheRequest request(tdbb, drq_e_gens, DYN_REQUESTS); bool found = false; @@ -4965,14 +5091,30 @@ void DropSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch DDL_TRIGGER_DROP_SEQUENCE, name); ERASE GEN; + + if (!GEN.RDB$SECURITY_CLASS.NULL) + deleteSecurityClass(tdbb, transaction, GEN.RDB$SECURITY_CLASS); + found = true; } END_FOR + request.reset(tdbb, drq_e_gen_prvs, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$RELATION_NAME EQ name.c_str() + AND PRIV.RDB$OBJECT_TYPE = obj_generator + { + ERASE PRIV; + } + END_FOR + if (found) executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_SEQUENCE, name); else if (!silent) status_exception::raise(Arg::Gds(isc_gennotdef) << Arg::Str(name)); + + savePoint.release(); // everything is ok } @@ -5074,7 +5216,7 @@ void RelationNode::FieldDefinition::modify(thread_db* tdbb, jrd_tra* transaction void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; AutoCacheRequest request(tdbb, drq_s_lfields, DYN_REQUESTS); @@ -5328,7 +5470,8 @@ void RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction, void RelationNode::storePrivileges(thread_db* tdbb, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; + const string& user_name = attachment->att_user->usr_user_name; AutoCacheRequest request(tdbb, drq_s_usr_prvs, DYN_REQUESTS); @@ -5338,7 +5481,7 @@ void RelationNode::storePrivileges(thread_db* tdbb, jrd_tra* transaction) X IN RDB$USER_PRIVILEGES { strcpy(X.RDB$RELATION_NAME, name.c_str()); - strcpy(X.RDB$USER, attachment->att_user->usr_user_name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); X.RDB$USER_TYPE = obj_user; X.RDB$OBJECT_TYPE = obj_relation; X.RDB$PRIVILEGE[0] = *p; @@ -6909,7 +7052,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction, const dsql_nod* element) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; dsql_fld* field = (dsql_fld*) element->nod_arg[Dsql::e_mod_fld_type_field]; @@ -7529,7 +7672,8 @@ DdlNode* CreateAlterViewNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; + const string& user_name = attachment->att_user->usr_user_name; const dsql_rel* modifyingView = NULL; @@ -7702,7 +7846,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra // so I included a call to strip trailing blanks. fb_utils::exact_name_limit(PREL.RDB$OWNER_NAME, sizeof(PREL.RDB$OWNER_NAME)); - if (attachment->att_user->usr_user_name != PREL.RDB$OWNER_NAME) + if (user_name != PREL.RDB$OWNER_NAME) { SecurityClass::flags_t priv; @@ -8861,7 +9005,7 @@ void CreateIndexNode::print(string& text, Array& /*nodes*/) const // Define an index. void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) { - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; // run all statements under savepoint control AutoSavePoint savePoint(tdbb, transaction); @@ -9556,7 +9700,7 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc // run all statements under savepoint control AutoSavePoint savePoint(tdbb, transaction); - Attachment* attachment = transaction->tra_attachment; + Attachment* const attachment = transaction->tra_attachment; SLONG dbAlloc = PageSpace::maxAlloc(tdbb->getDatabase()); SLONG start = create ? createLength + 1 : 0; AutoCacheRequest request(tdbb, drq_m_database, DYN_REQUESTS); diff --git a/src/dsql/PackageNodes.epp b/src/dsql/PackageNodes.epp index b97ade2cbc..0038aa12a6 100644 --- a/src/dsql/PackageNodes.epp +++ b/src/dsql/PackageNodes.epp @@ -497,6 +497,7 @@ void CreateAlterPackageNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* jrd_tra* transaction) { Attachment* attachment = transaction->getAttachment(); + const string& user_name = attachment->att_user->usr_user_name; executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_PACKAGE, name); @@ -513,29 +514,27 @@ void CreateAlterPackageNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* PKG.RDB$SYSTEM_FLAG = 0; PKG.RDB$OWNER_NAME.NULL = FALSE; - strcpy(PKG.RDB$OWNER_NAME, attachment->att_user->usr_user_name.c_str()); + strcpy(PKG.RDB$OWNER_NAME, user_name.c_str()); PKG.RDB$PACKAGE_HEADER_SOURCE.NULL = FALSE; attachment->storeMetaDataBlob(tdbb, transaction, &PKG.RDB$PACKAGE_HEADER_SOURCE, source); } END_STORE - for (const TEXT* p = ALL_PROC_PRIVILEGES; *p; p++) - { - requestHandle.reset(tdbb, drq_s_pkg_usr_prvs, DYN_REQUESTS); + requestHandle.reset(tdbb, drq_s_pkg_usr_prvs, DYN_REQUESTS); - STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) - X IN RDB$USER_PRIVILEGES - { - strcpy(X.RDB$RELATION_NAME, name.c_str()); - strcpy(X.RDB$USER, attachment->att_user->usr_user_name.c_str()); - X.RDB$USER_TYPE = obj_user; - X.RDB$OBJECT_TYPE = obj_package_header; - X.RDB$PRIVILEGE[0] = *p; - X.RDB$PRIVILEGE[1] = 0; - } - END_STORE; + STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction) + X IN RDB$USER_PRIVILEGES + { + strcpy(X.RDB$RELATION_NAME, name.c_str()); + strcpy(X.RDB$USER, user_name.c_str()); + X.RDB$USER_TYPE = obj_user; + X.RDB$OBJECT_TYPE = obj_package_header; + X.RDB$PRIVILEGE[0] = EXEC_PRIVILEGE; + X.RDB$PRIVILEGE[1] = 0; + X.RDB$GRANT_OPTION = 1; } + END_STORE; owner = attachment->att_user->usr_user_name; diff --git a/src/jrd/cvt2.cpp b/src/jrd/cvt2.cpp index 6f257bc4aa..4aeeae008f 100644 --- a/src/jrd/cvt2.cpp +++ b/src/jrd/cvt2.cpp @@ -634,29 +634,6 @@ SSHORT CVT2_blob_compare(const dsc* arg1, const dsc* arg2) } -void CVT2_get_name(const dsc* desc, TEXT* string) -{ -/************************************** - * - * C V T 2 _ g e t _ n a m e - * - ************************************** - * - * Functional description - * Get a name (max length 31, NULL terminated) from a descriptor. - * - **************************************/ - VaryStr temp; // 31 bytes + 1 NULL - const char* p; - - const USHORT length = CVT_make_string(desc, ttype_metadata, &p, &temp, sizeof(temp), ERR_post); - - memcpy(string, p, length); - string[length] = 0; - fb_utils::exact_name(string); -} - - USHORT CVT2_make_string2(const dsc* desc, USHORT to_interp, UCHAR** address, Jrd::MoveBuffer& temp) { /************************************** diff --git a/src/jrd/cvt2_proto.h b/src/jrd/cvt2_proto.h index 069fbfce96..fac8457391 100644 --- a/src/jrd/cvt2_proto.h +++ b/src/jrd/cvt2_proto.h @@ -28,7 +28,6 @@ SSHORT CVT2_compare(const dsc*, const dsc*); SSHORT CVT2_blob_compare(const dsc*, const dsc*); -void CVT2_get_name(const dsc*, TEXT*); USHORT CVT2_make_string2(const dsc*, USHORT, UCHAR**, Jrd::MoveBuffer&); #endif // JRD_CVT2_PROTO_H diff --git a/src/jrd/drq.h b/src/jrd/drq.h index ed78b27d97..9b3adc6cb9 100644 --- a/src/jrd/drq.h +++ b/src/jrd/drq.h @@ -231,6 +231,14 @@ enum drq_type_t drq_m_fld2, // alter domain drq_c_unq_nam2, // check for unique field names drq_s_rels2, // store relations + drq_e_coll_prvs, // erase collation privileges + drq_e_xcp_prvs, // erase exception privileges + drq_e_gen_prvs, // erase generator privileges + drq_e_gfld_prvs, // erase domain privileges + drq_s_coll_prvs, // store collation privileges + drq_s_xcp_prvs, // store exception privileges + drq_s_gen_prvs, // store generator privileges + drq_s_gfld_prvs, // store domain privileges drq_MAX }; diff --git a/src/jrd/dyn.h b/src/jrd/dyn.h index 1dc91054a7..35c3f66117 100644 --- a/src/jrd/dyn.h +++ b/src/jrd/dyn.h @@ -31,7 +31,9 @@ #include "../common/dsc.h" const char* const ALL_PRIVILEGES = "SIUDR"; // all applicable grant/revoke privileges -const char* const ALL_PROC_PRIVILEGES = "X"; // all applicable grant/revoke privileges for a procedure +const char EXEC_PRIVILEGE = 'X'; // execute privilege for procedures, functions and packages +const char USAGE_PRIVILEGE = 'S'; // usage privilege, currently equal to the select one + const int DYN_MSG_FAC = 8; diff --git a/src/jrd/grant.epp b/src/jrd/grant.epp index a5372c3c25..e7443f87be 100644 --- a/src/jrd/grant.epp +++ b/src/jrd/grant.epp @@ -60,9 +60,7 @@ using namespace Jrd; // privileges given to the owner of a relation -const SecurityClass::flags_t OWNER_PRIVS = SCL_control | SCL_read | SCL_write | SCL_delete | SCL_protect; -//const SecurityClass::flags_t VIEW_PRIVS = SCL_read | SCL_write | SCL_delete; -//const ULONG ACL_BUFFER_SIZE = 4096; +const SecurityClass::flags_t OWNER_PRIVS = SCL_control | SCL_read | SCL_write | SCL_delete | SCL_protect; inline void CHECK_AND_MOVE(Acl& to, UCHAR from) { @@ -73,11 +71,6 @@ DATABASE DB = STATIC "yachts.lnk"; static void define_default_class(thread_db*, const TEXT*, Firebird::MetaName&, const Acl&, jrd_tra*); -#ifdef NOT_USED_OR_REPLACED -static void delete_security_class(thread_db*, const TEXT*); -static void grant_views(TEXT**, SecurityClass::flags_t); -static void purge_default_class(TEXT*, SSHORT); -#endif static void finish_security_class(Acl&, SecurityClass::flags_t); static void get_object_info(thread_db*, const TEXT*, SSHORT, Firebird::MetaName&, Firebird::MetaName&, Firebird::MetaName&, bool&); @@ -112,7 +105,6 @@ void GRANT_privileges(thread_db* tdbb, const Firebird::string& name, USHORT id, bool restrct = false; - //Database* dbb = tdbb->getDatabase(); Firebird::MetaName s_class, owner, default_class; bool view; // unused after being retrieved. get_object_info(tdbb, name.c_str(), id, owner, s_class, default_class, view); @@ -137,7 +129,7 @@ void GRANT_privileges(thread_db* tdbb, const Firebird::string& name, USHORT id, grant_user(acl, owner, obj_user, priv); - // Pick up any relation-level privileges + // Pick up core privileges const SecurityClass::flags_t public_priv = get_public_privs(tdbb, name.c_str(), id); get_user_privs(tdbb, acl, name.c_str(), id, owner, public_priv); @@ -155,12 +147,6 @@ void GRANT_privileges(thread_db* tdbb, const Firebird::string& name, USHORT id, save_field_privileges(tdbb, acl, name.c_str(), owner, public_priv, transaction); - // SQL tables don't need the 'all priviliges to all views' acl anymore. - // This special acl was only generated for SQL. -#ifdef NOT_USED_OR_REPLACED - // grant_views (&acl, VIEW_PRIVS); -#endif - // finish off and store the security class for the relation finish_security_class(acl, aggregate_public); @@ -394,6 +380,81 @@ static void get_object_info(thread_db* tdbb, } END_FOR } + else if (obj_type == obj_charset) + { + AutoCacheRequest request(tdbb, irq_grant12, IRQ_REQUESTS); + + FOR(REQUEST_HANDLE request) + CS IN RDB$CHARACTER_SETS WITH + CS.RDB$CHARACTER_SET_NAME EQ object_name + { + s_class = CS.RDB$SECURITY_CLASS; + default_class = ""; + owner = CS.RDB$OWNER_NAME; + view = false; + } + END_FOR + } + else if (obj_type == obj_collation) + { + AutoCacheRequest request(tdbb, irq_grant13, IRQ_REQUESTS); + + FOR(REQUEST_HANDLE request) + COLL IN RDB$COLLATIONS WITH + COLL.RDB$COLLATION_NAME EQ object_name + { + s_class = COLL.RDB$SECURITY_CLASS; + default_class = ""; + owner = COLL.RDB$OWNER_NAME; + view = false; + } + END_FOR + } + else if (obj_type == obj_exception) + { + AutoCacheRequest request(tdbb, irq_grant14, IRQ_REQUESTS); + + FOR(REQUEST_HANDLE request) + XCP IN RDB$EXCEPTIONS WITH + XCP.RDB$EXCEPTION_NAME EQ object_name + { + s_class = XCP.RDB$SECURITY_CLASS; + default_class = ""; + owner = XCP.RDB$OWNER_NAME; + view = false; + } + END_FOR + } + else if (obj_type == obj_generator) + { + AutoCacheRequest request(tdbb, irq_grant15, IRQ_REQUESTS); + + FOR(REQUEST_HANDLE request) + GEN IN RDB$GENERATORS WITH + GEN.RDB$GENERATOR_NAME EQ object_name + { + s_class = GEN.RDB$SECURITY_CLASS; + default_class = ""; + owner = GEN.RDB$OWNER_NAME; + view = false; + } + END_FOR + } + else if (obj_type == obj_field) + { + AutoCacheRequest request(tdbb, irq_grant16, IRQ_REQUESTS); + + FOR(REQUEST_HANDLE request) + FLD IN RDB$FIELDS WITH + FLD.RDB$FIELD_NAME EQ object_name + { + s_class = FLD.RDB$SECURITY_CLASS; + default_class = ""; + owner = FLD.RDB$OWNER_NAME; + view = false; + } + END_FOR + } } @@ -524,97 +585,6 @@ static void grant_user(Acl& acl, } -#ifdef NOT_USED_OR_REPLACED -static void delete_security_class( thread_db* tdbb, const TEXT* s_class) -{ -/************************************** - * - * d e l e t e _ s e c u r i t y _ c l a s s - * - ************************************** - * - * Functional description - * Delete a security class. - * - **************************************/ - SET_TDBB(tdbb); - Database* dbb = tdbb->getDatabase(); - - AutoRequest handle; - - FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction) - CLS IN RDB$SECURITY_CLASSES - WITH CLS.RDB$SECURITY_CLASS EQ s_class - { - ERASE CLS; - } - END_FOR -} - - -static void grant_views(Acl& acl, SecurityClass::flags_t privs) -{ -/************************************** - * - * g r a n t _ v i e w s - * - ************************************** - * - * Functional description - * Grant privileges to all views. - * - **************************************/ - CHECK_AND_MOVE(acl, ACL_id_list); - CHECK_AND_MOVE(acl, id_views); - CHECK_AND_MOVE(acl, 0); - SCL_move_priv(privs, acl); -} - - -static void purge_default_class( TEXT* object_name, SSHORT obj_type) -{ -/************************************** - * - * p u r g e _ d e f a u l t _ c l a s s - * - ************************************** - * - * Functional description - * Get rid of any previously defined - * default security class for this relation. - * - **************************************/ - thread_db* tdbb = JRD_get_thread_data(); - Database* dbb = tdbb->getDatabase(); - - AutoCacheRequest request(tdbb, irq_grant8, IRQ_REQUESTS); - - FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) - REL IN RDB$RELATIONS - WITH REL.RDB$RELATION_NAME EQ object_name - AND REL.RDB$DEFAULT_CLASS NOT MISSING - { - fb_utils::exact_name_limit(REL.RDB$DEFAULT_CLASS, sizeof(REL.RDB$DEFAULT_CLASS)); - delete_security_class(tdbb, REL.RDB$DEFAULT_CLASS); - - MODIFY REL USING - REL.RDB$DEFAULT_CLASS.NULL = TRUE; - END_MODIFY - } - END_FOR - - dsc desc; - desc.dsc_dtype = dtype_text; - desc.dsc_sub_type = 0; - desc.dsc_scale = 0; - desc.dsc_ttype() = ttype_metadata; - desc.dsc_address = (UCHAR *) object_name; - desc.dsc_length = strlen(object_name); - DFW_post_work(transaction, dfw_scan_relation, &desc, 0); -} -#endif // NOT_USED_OR_REPLACED - - static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, Acl& relation_acl, const TEXT* relation_name, diff --git a/src/jrd/ini.epp b/src/jrd/ini.epp index e4ba880278..609380dcac 100644 --- a/src/jrd/ini.epp +++ b/src/jrd/ini.epp @@ -55,6 +55,7 @@ #include "../jrd/met_proto.h" #include "../jrd/obj.h" #include "../jrd/acl.h" +#include "../jrd/dyn.h" #include "../jrd/irq.h" #include "../jrd/IntlManager.h" #include "../jrd/PreparedStatement.h" @@ -70,11 +71,14 @@ const int FB_MAX_ACL_SIZE = 4096; static void add_index_set(thread_db*); -static void add_security_to_sys_rel(thread_db*, const Firebird::MetaName&, - const TEXT*, const UCHAR*, const SSHORT, const bool); -static void store_generator(thread_db*, const gen*, AutoRequest&); -static void store_global_field(thread_db*, const gfld*, AutoRequest&); -static void store_intlnames(thread_db*); +static void add_security_to_sys_obj(thread_db*, const MetaName&, + USHORT, const MetaName&, + USHORT = 0, const UCHAR* = NULL); +static void add_security_to_sys_rel(thread_db*, const MetaName&, + const TEXT*, const USHORT, const UCHAR*, const bool); +static void store_generator(thread_db*, const gen*, AutoRequest&, const MetaName&); +static void store_global_field(thread_db*, const gfld*, AutoRequest&, const MetaName&); +static void store_intlnames(thread_db*, const MetaName&); static void store_message(thread_db*, const trigger_msg*, AutoRequest&); static void store_relation_field(thread_db*, const int*, const int*, int, AutoRequest&); static void store_trigger(thread_db*, const jrd_trg*, AutoRequest&); @@ -242,7 +246,7 @@ static const trigger_msg trigger_messages[] = -void INI_format(const TEXT* owner, const TEXT* charset) +void INI_format(const MetaName& owner, const MetaName& charset) { /************************************** * @@ -259,13 +263,14 @@ void INI_format(const TEXT* owner, const TEXT* charset) thread_db* tdbb = JRD_get_thread_data(); Jrd::Attachment* attachment = tdbb->getAttachment(); + fb_assert(owner.hasData()); + // Uppercase owner name - MetaName ownerName(owner ? owner : ""); + MetaName ownerName(owner); ownerName.upper7(); // Uppercase charset name - MetaName rdbCharSetName(charset && strlen(charset) != 0 ? - charset : DEFAULT_DB_CHARACTER_SET_NAME); + MetaName rdbCharSetName(charset.hasData() ? charset.c_str() : DEFAULT_DB_CHARACTER_SET_NAME); rdbCharSetName.upper7(); const int* fld; @@ -284,7 +289,7 @@ void INI_format(const TEXT* owner, const TEXT* charset) } jrd_tra* transaction = attachment->getSysTransaction(); - + // Store RELATIONS and RELATION_FIELDS SLONG rdbRelationId; @@ -323,7 +328,7 @@ void INI_format(const TEXT* owner, const TEXT* charset) // Store global FIELDS for (const gfld* gfield = gfields; gfield->gfld_name; gfield++) - store_global_field(tdbb, gfield, handle1); + store_global_field(tdbb, gfield, handle1, ownerName); // Store DATABASE record @@ -405,14 +410,14 @@ void INI_format(const TEXT* owner, const TEXT* charset) } // Store symbols for international character sets & collations - store_intlnames(tdbb); + store_intlnames(tdbb, ownerName); // Create generators to be used by system triggers handle1.reset(); for (const gen* generator = generators; generator->gen_name; generator++) - store_generator(tdbb, generator, handle1); + store_generator(tdbb, generator, handle1, ownerName); // Adjust the value of the hidden generator RDB$GENERATORS DPM_gen_id(tdbb, 0, true, FB_NELEM(generators) - 1); @@ -433,7 +438,7 @@ void INI_format(const TEXT* owner, const TEXT* charset) DFW_perform_system_work(tdbb); - // Add security on RDB$ROLES system table + // Add security for the non-relation system metadata objects UCHAR buffer[FB_MAX_ACL_SIZE]; UCHAR* acl = buffer; @@ -442,16 +447,11 @@ void INI_format(const TEXT* owner, const TEXT* charset) *acl++ = id_person; USHORT length = ownerName.length(); - if (length > MAX_UCHAR) - length = MAX_UCHAR; + fb_assert(length <= MAX_UCHAR); + *acl++ = (UCHAR) length; + memcpy(acl, ownerName.c_str(), length); + acl += length; - *acl++ = (UCHAR)length; - if (length) - { - const TEXT* p_1 = ownerName.c_str(); - memcpy(acl, p_1, length); - acl += length; - } *acl++ = ACL_end; *acl++ = ACL_priv_list; *acl++ = priv_protect; @@ -460,6 +460,31 @@ void INI_format(const TEXT* owner, const TEXT* charset) *acl++ = priv_write; *acl++ = priv_read; *acl++ = ACL_end; + *acl++ = ACL_end; + length = acl - buffer; + + for (const gfld* gfield = gfields; gfield->gfld_name; gfield++) + add_security_to_sys_obj(tdbb, ownerName, obj_field, names[(USHORT)gfield->gfld_name], length, buffer); + + for (const gen* generator = generators; generator->gen_name; generator++) + add_security_to_sys_obj(tdbb, ownerName, obj_generator, generator->gen_name, length, buffer); + + for (const IntlManager::CharSetDefinition* charset = IntlManager::defaultCharSets; + charset->name; ++charset) + { + add_security_to_sys_obj(tdbb, ownerName, obj_charset, charset->name, length, buffer); + } + + for (const IntlManager::CollationDefinition* collation = IntlManager::defaultCollations; + collation->name; ++collation) + { + add_security_to_sys_obj(tdbb, ownerName, obj_collation, collation->name, length, buffer); + } + + // Add security on RDB$ROLES system table + + acl--; // go before the last ACL_end, it's to be overwritten + *acl++ = ACL_id_list; *acl++ = ACL_end; *acl++ = ACL_priv_list; @@ -468,10 +493,10 @@ void INI_format(const TEXT* owner, const TEXT* charset) *acl++ = ACL_end; length = acl - buffer; - add_security_to_sys_rel(tdbb, ownerName, "RDB$ROLES", buffer, length, true); - add_security_to_sys_rel(tdbb, ownerName, "RDB$PAGES", buffer, length, true); + add_security_to_sys_rel(tdbb, ownerName, "RDB$ROLES", length, buffer, true); + add_security_to_sys_rel(tdbb, ownerName, "RDB$PAGES", length, buffer, true); // DFW writes here - add_security_to_sys_rel(tdbb, ownerName, "RDB$FORMATS", buffer, length, true); + add_security_to_sys_rel(tdbb, ownerName, "RDB$FORMATS", length, buffer, true); } @@ -882,8 +907,8 @@ static void add_index_set(thread_db* tdbb) static void add_security_to_sys_rel(thread_db* tdbb, const Firebird::MetaName& user_name, const TEXT* rel_name, + const USHORT acl_length, const UCHAR* acl, - const SSHORT acl_length, const bool pub_select) { /************************************** @@ -924,7 +949,7 @@ static void add_security_to_sys_rel(thread_db* tdbb, STORE(REQUEST_HANDLE handle1) CLS IN RDB$SECURITY_CLASSES { - jrd_vtof(security_class.c_str(), CLS.RDB$SECURITY_CLASS, sizeof(CLS.RDB$SECURITY_CLASS)); + PAD(security_class.c_str(), CLS.RDB$SECURITY_CLASS); CLS.RDB$ACL = blob_id_1; } END_STORE @@ -934,7 +959,7 @@ static void add_security_to_sys_rel(thread_db* tdbb, STORE(REQUEST_HANDLE handle1) CLS IN RDB$SECURITY_CLASSES { - jrd_vtof(default_class.c_str(), CLS.RDB$SECURITY_CLASS, sizeof(CLS.RDB$SECURITY_CLASS)); + PAD(default_class.c_str(), CLS.RDB$SECURITY_CLASS); CLS.RDB$ACL = blob_id_2; } END_STORE @@ -946,10 +971,10 @@ static void add_security_to_sys_rel(thread_db* tdbb, { MODIFY REL USING REL.RDB$SECURITY_CLASS.NULL = FALSE; - jrd_vtof(security_class.c_str(), REL.RDB$SECURITY_CLASS, sizeof(REL.RDB$SECURITY_CLASS)); + PAD(security_class.c_str(), REL.RDB$SECURITY_CLASS); REL.RDB$DEFAULT_CLASS.NULL = FALSE; - jrd_vtof(default_class.c_str(), REL.RDB$DEFAULT_CLASS, sizeof(REL.RDB$DEFAULT_CLASS)); + PAD(default_class.c_str(), REL.RDB$DEFAULT_CLASS); END_MODIFY } END_FOR @@ -1003,7 +1028,124 @@ static void add_security_to_sys_rel(thread_db* tdbb, } -static void store_generator(thread_db* tdbb, const gen* generator, AutoRequest& handle) +static void add_security_to_sys_obj(thread_db* tdbb, + const MetaName& user_name, + USHORT obj_type, + const MetaName& obj_name, + USHORT acl_length, + const UCHAR* acl) +{ +/************************************** + * + * a d d _ s e c u r i t y _ t o _ s y s _ o b j + * + ************************************** + * + * Functional description + * + * Add security to system objects. + * + **************************************/ + SET_TDBB(tdbb); + Jrd::Attachment* const attachment = tdbb->getAttachment(); + + bid blob_id; + attachment->storeBinaryBlob(tdbb, attachment->getSysTransaction(), &blob_id, + ByteChunk(acl, acl_length)); + + Firebird::MetaName security_class; + security_class.printf("%s%"SQUADFORMAT, SQL_SECCLASS_PREFIX, + DPM_gen_id(tdbb, MET_lookup_generator(tdbb, SQL_SECCLASS_GENERATOR), false, 1)); + + AutoRequest handle; + + STORE(REQUEST_HANDLE handle) + CLS IN RDB$SECURITY_CLASSES + { + PAD(security_class.c_str(), CLS.RDB$SECURITY_CLASS); + CLS.RDB$ACL = blob_id; + } + END_STORE + + handle.reset(); + + if (obj_type == obj_field) + { + FOR(REQUEST_HANDLE handle) FLD IN RDB$FIELDS + WITH FLD.RDB$FIELD_NAME EQ obj_name.c_str() + { + MODIFY FLD USING + FLD.RDB$SECURITY_CLASS.NULL = FALSE; + PAD(security_class.c_str(), FLD.RDB$SECURITY_CLASS); + END_MODIFY + } + END_FOR + } + else if (obj_type == obj_charset) + { + FOR(REQUEST_HANDLE handle) CS IN RDB$CHARACTER_SETS + WITH CS.RDB$CHARACTER_SET_NAME EQ obj_name.c_str() + { + MODIFY CS USING + CS.RDB$SECURITY_CLASS.NULL = FALSE; + PAD(security_class.c_str(), CS.RDB$SECURITY_CLASS); + END_MODIFY + } + END_FOR + } + else if (obj_type == obj_collation) + { + FOR(REQUEST_HANDLE handle) COLL IN RDB$COLLATIONS + WITH COLL.RDB$COLLATION_NAME EQ obj_name.c_str() + { + MODIFY COLL USING + COLL.RDB$SECURITY_CLASS.NULL = FALSE; + PAD(security_class.c_str(), COLL.RDB$SECURITY_CLASS); + END_MODIFY + } + END_FOR + } + else if (obj_type == obj_exception) + { + FOR(REQUEST_HANDLE handle) XCP IN RDB$EXCEPTIONS + WITH XCP.RDB$EXCEPTION_NAME EQ obj_name.c_str() + { + MODIFY XCP USING + XCP.RDB$SECURITY_CLASS.NULL = FALSE; + PAD(security_class.c_str(), XCP.RDB$SECURITY_CLASS); + END_MODIFY + } + END_FOR + } + else if (obj_type == obj_generator) + { + FOR(REQUEST_HANDLE handle) GEN IN RDB$GENERATORS + WITH GEN.RDB$GENERATOR_NAME EQ obj_name.c_str() + { + MODIFY GEN USING + GEN.RDB$SECURITY_CLASS.NULL = FALSE; + PAD(security_class.c_str(), GEN.RDB$SECURITY_CLASS); + END_MODIFY + } + END_FOR + } + + handle.reset(); + + STORE(REQUEST_HANDLE handle) PRIV IN RDB$USER_PRIVILEGES + PAD(user_name.c_str(), PRIV.RDB$USER); + PAD(obj_name.c_str(), PRIV.RDB$RELATION_NAME); + PRIV.RDB$PRIVILEGE[0] = USAGE_PRIVILEGE; + PRIV.RDB$PRIVILEGE[1] = 0; + PRIV.RDB$GRANT_OPTION = 1; + PRIV.RDB$USER_TYPE = obj_user; + PRIV.RDB$OBJECT_TYPE = obj_type; + END_STORE +} + + +static void store_generator(thread_db* tdbb, const gen* generator, AutoRequest& handle, + const MetaName& owner) { /************************************** * @@ -1025,6 +1167,8 @@ static void store_generator(thread_db* tdbb, const gen* generator, AutoRequest& X.RDB$GENERATOR_ID = generator->gen_id; X.RDB$SYSTEM_FLAG = RDB_system; X.RDB$SYSTEM_FLAG.NULL = FALSE; + PAD(owner.c_str(), X.RDB$OWNER_NAME); + X.RDB$OWNER_NAME.NULL = FALSE; if (generator->gen_description) { attachment->storeMetaDataBlob(tdbb, attachment->getSysTransaction(), &X.RDB$DESCRIPTION, @@ -1038,7 +1182,8 @@ static void store_generator(thread_db* tdbb, const gen* generator, AutoRequest& } -static void store_global_field(thread_db* tdbb, const gfld* gfield, AutoRequest& handle) +static void store_global_field(thread_db* tdbb, const gfld* gfield, AutoRequest& handle, + const MetaName& owner) { /************************************** * @@ -1062,6 +1207,8 @@ static void store_global_field(thread_db* tdbb, const gfld* gfield, AutoRequest& X.RDB$FIELD_SCALE = 0; X.RDB$SYSTEM_FLAG = RDB_system; X.RDB$SYSTEM_FLAG.NULL = FALSE; + PAD(owner.c_str(), X.RDB$OWNER_NAME); + X.RDB$OWNER_NAME.NULL = FALSE; X.RDB$FIELD_SUB_TYPE.NULL = TRUE; X.RDB$CHARACTER_SET_ID.NULL = TRUE; X.RDB$COLLATION_ID.NULL = TRUE; @@ -1191,7 +1338,7 @@ static void store_global_field(thread_db* tdbb, const gfld* gfield, AutoRequest& } -static void store_intlnames(thread_db* tdbb) +static void store_intlnames(thread_db* tdbb, const MetaName& owner) { /************************************** * @@ -1220,6 +1367,8 @@ static void store_intlnames(thread_db* tdbb) X.RDB$BYTES_PER_CHARACTER = charSet->maxBytes; X.RDB$SYSTEM_FLAG = RDB_system; X.RDB$SYSTEM_FLAG.NULL = FALSE; + PAD(owner.c_str(), X.RDB$OWNER_NAME); + X.RDB$OWNER_NAME.NULL = FALSE; } END_STORE } @@ -1245,6 +1394,8 @@ static void store_intlnames(thread_db* tdbb) X.RDB$COLLATION_ID = collation->collationId; X.RDB$SYSTEM_FLAG = RDB_system; X.RDB$SYSTEM_FLAG.NULL = FALSE; + PAD(owner.c_str(), X.RDB$OWNER_NAME); + X.RDB$OWNER_NAME.NULL = FALSE; X.RDB$COLLATION_ATTRIBUTES = collation->attributes; if (collation->specificAttributes) diff --git a/src/jrd/ini_proto.h b/src/jrd/ini_proto.h index 34bd806348..769fddb170 100644 --- a/src/jrd/ini_proto.h +++ b/src/jrd/ini_proto.h @@ -29,7 +29,7 @@ namespace Jrd { class dsql_dbb; } -void INI_format(const TEXT*, const TEXT*); +void INI_format(const Firebird::MetaName&, const Firebird::MetaName&); USHORT INI_get_trig_flags(const TEXT*); void INI_init(Jrd::thread_db*); void INI_init2(Jrd::thread_db*); diff --git a/src/jrd/irq.h b/src/jrd/irq.h index 1ce04e0d6c..e855446270 100644 --- a/src/jrd/irq.h +++ b/src/jrd/irq.h @@ -155,6 +155,16 @@ enum irq_type_t irq_fun_validate, // function blr validate irq_c_fun_dpd, // get function dependencies irq_grant11, // process grant option (functions) + irq_cs_security, // verify security for character set + irq_coll_security, // verify security for collation + irq_exc_security, // verify security for exception + irq_gen_security, // verify security for generator + irq_gfld_security, // verify security for domain + irq_grant12, // process grant option (charsets) + irq_grant13, // process grant option (collations) + irq_grant14, // process grant option (exceptions) + irq_grant15, // process grant option (generators) + irq_grant16, // process grant option (domains) irq_MAX }; diff --git a/src/jrd/met.epp b/src/jrd/met.epp index dea873f88a..7b130242b8 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -3380,9 +3380,9 @@ void MET_remove_procedure(thread_db* tdbb, int id, jrd_prc* procedure) void MET_revoke(thread_db* tdbb, jrd_tra* transaction, - const TEXT* relation, - const TEXT* revokee, - const TEXT* privilege) + const MetaName& relation, + const MetaName& revokee, + const string& privilege) { /************************************** * @@ -3405,9 +3405,9 @@ void MET_revoke(thread_db* tdbb, FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) FIRST 1 P IN RDB$USER_PRIVILEGES WITH - P.RDB$RELATION_NAME EQ relation AND - P.RDB$PRIVILEGE EQ privilege AND - P.RDB$USER EQ revokee + P.RDB$RELATION_NAME EQ relation.c_str() AND + P.RDB$PRIVILEGE EQ privilege.c_str() AND + P.RDB$USER EQ revokee.c_str() { ++count; } @@ -3422,9 +3422,9 @@ void MET_revoke(thread_db* tdbb, FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) P IN RDB$USER_PRIVILEGES WITH - P.RDB$RELATION_NAME EQ relation AND - P.RDB$PRIVILEGE EQ privilege AND - P.RDB$GRANTOR EQ revokee + P.RDB$RELATION_NAME EQ relation.c_str() AND + P.RDB$PRIVILEGE EQ privilege.c_str() AND + P.RDB$GRANTOR EQ revokee.c_str() { ERASE P; } diff --git a/src/jrd/met_proto.h b/src/jrd/met_proto.h index 82444bee4a..eeb5a3b9fb 100644 --- a/src/jrd/met_proto.h +++ b/src/jrd/met_proto.h @@ -120,7 +120,7 @@ void MET_verify_cache(Jrd::thread_db*); void MET_clear_cache(Jrd::thread_db*); bool MET_procedure_in_use(Jrd::thread_db*, Jrd::jrd_prc*); void MET_remove_procedure(Jrd::thread_db*, int, Jrd::jrd_prc*); -void MET_revoke(Jrd::thread_db*, Jrd::jrd_tra*, const TEXT*, const TEXT*, const TEXT*); +void MET_revoke(Jrd::thread_db*, Jrd::jrd_tra*, const Firebird::MetaName&, const Firebird::MetaName&, const Firebird::string&); void MET_scan_partners(Jrd::thread_db*, Jrd::jrd_rel*); void MET_scan_relation(Jrd::thread_db*, Jrd::jrd_rel*); void MET_trigger_msg(Jrd::thread_db*, Firebird::string&, const Firebird::MetaName&, USHORT); diff --git a/src/jrd/mov.cpp b/src/jrd/mov.cpp index 547d26fd51..6310b98cbf 100644 --- a/src/jrd/mov.cpp +++ b/src/jrd/mov.cpp @@ -193,53 +193,30 @@ SINT64 MOV_get_int64(const dsc* desc, SSHORT scale) } -void MOV_get_metadata_str(const dsc* desc, TEXT* buffer, USHORT buffer_length) +void MOV_get_metaname(const dsc* desc, MetaName& name) { /************************************** * - * M O V _ g e t _ m e t a d a t a _ s t r + * M O V _ g e t _ m e t a n a m e * ************************************** * * Functional description * Copy string, which will afterward's * be treated as a metadata name value, - * to the user-supplied buffer. + * to the user-supplied object. * **************************************/ - USHORT dummy_type; - UCHAR *ptr; + USHORT ttype; + UCHAR* ptr = NULL; - USHORT length = CVT_get_string_ptr(desc, &dummy_type, &ptr, NULL, 0); + const USHORT length = CVT_get_string_ptr(desc, &ttype, &ptr, NULL, 0); -#ifdef DEV_BUILD - if ((dummy_type != ttype_metadata) && - (dummy_type != ttype_none) && (dummy_type != ttype_ascii)) - { - ERR_bugcheck_msg("Expected METADATA name"); - } -#endif + fb_assert(length && ptr); + fb_assert(length <= MAX_SQL_IDENTIFIER_LEN); + fb_assert(ttype == ttype_metadata); - length = ptr ? MIN(length, buffer_length - 1) : 0; - memcpy(buffer, ptr, length); - buffer[length] = 0; -} - - -void MOV_get_name(const dsc* desc, TEXT* string) -{ -/************************************** - * - * M O V _ g e t _ n a m e - * - ************************************** - * - * Functional description - * Get a name (max length 31, blank terminated) from a descriptor. - * - **************************************/ - - CVT2_get_name(desc, string); + name.assign(reinterpret_cast(ptr), length); } diff --git a/src/jrd/mov_proto.h b/src/jrd/mov_proto.h index 87d5796d6d..bb90272221 100644 --- a/src/jrd/mov_proto.h +++ b/src/jrd/mov_proto.h @@ -37,8 +37,7 @@ void MOV_double_to_date(double, SLONG[2]); bool MOV_get_boolean(const dsc*); double MOV_get_double(const dsc*); SLONG MOV_get_long(const dsc*, SSHORT); -void MOV_get_metadata_str(const dsc*, TEXT*, USHORT); -void MOV_get_name(const dsc*, TEXT*); +void MOV_get_metaname(const dsc*, Firebird::MetaName&); SQUAD MOV_get_quad(const dsc*, SSHORT); SINT64 MOV_get_int64(const dsc*, SSHORT); int MOV_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*, diff --git a/src/jrd/obj.h b/src/jrd/obj.h index 1ba557c325..ca144f3f7a 100644 --- a/src/jrd/obj.h +++ b/src/jrd/obj.h @@ -38,7 +38,7 @@ const int obj_exception = 7; const int obj_user = 8; const int obj_field = 9; const int obj_index = 10; -// const int obj_count = 11; +const int obj_charset = 11; const int obj_user_group = 12; const int obj_sql_role = 13; const int obj_generator = 14; diff --git a/src/jrd/scl.epp b/src/jrd/scl.epp index 4b3bf02039..60fd614389 100644 --- a/src/jrd/scl.epp +++ b/src/jrd/scl.epp @@ -103,12 +103,16 @@ namespace // Database is never requested through CMP_post_access. const char* const object_str_database = "DATABASE"; - const char* const object_str_schema = "SCHEMA"; const char* const object_str_table = "TABLE"; const char* const object_str_package = "PACKAGE"; const char* const object_str_procedure = "PROCEDURE"; const char* const object_str_function = "FUNCTION"; const char* const object_str_column = "COLUMN"; + const char* const object_str_charset = "CHARACTER SET"; + const char* const object_str_collation = "COLLATION"; + const char* const object_str_domain = "DOMAIN"; + const char* const object_str_exception = "EXCEPTION"; + const char* const object_str_generator = "GENERATOR"; struct SecObjectNamePriority @@ -120,12 +124,16 @@ namespace const SecObjectNamePriority priorities[] = { {object_str_database, SCL_object_database}, - {object_str_schema, SCL_object_schema}, {object_str_table, SCL_object_table}, {object_str_package, SCL_object_package}, {object_str_procedure, SCL_object_procedure}, {object_str_function, SCL_object_function}, {object_str_column, SCL_object_column}, + {object_str_charset, SCL_object_charset}, + {object_str_collation, SCL_object_collation}, + {object_str_domain, SCL_object_domain}, + {object_str_exception, SCL_object_exception}, + {object_str_generator, SCL_object_generator}, {"", 0} }; @@ -245,7 +253,7 @@ void SCL_check_access(thread_db* tdbb, else { fb_assert(type != SCL_object_database); - const char* typeAsStr = accTypeNumToStr(type); + const char* const typeAsStr = accTypeNumToStr(type); const Firebird::string fullName = r_name.hasData() ? r_name.c_str() + Firebird::string(".") + name.c_str() : name.c_str(); ERR_post(Arg::Gds(isc_no_priv) << Arg::Str(names->p_names_string) << @@ -255,6 +263,161 @@ void SCL_check_access(thread_db* tdbb, } +void SCL_check_charset(thread_db* tdbb, const MetaName& name, SecurityClass::flags_t mask) +{ +/************************************** + * + * S C L _ c h e c k _ c h a r s e t + * + ************************************** + * + * Functional description + * Given a character set name, check for a set of privileges. + * + **************************************/ + SET_TDBB(tdbb); + Jrd::Attachment* const attachment = tdbb->getAttachment(); + + const SecurityClass* s_class = NULL; + AutoCacheRequest request(tdbb, irq_cs_security, IRQ_REQUESTS); + + FOR (REQUEST_HANDLE request) + CS IN RDB$CHARACTER_SETS + WITH CS.RDB$CHARACTER_SET_NAME EQ name.c_str() + { + if (!CS.RDB$SECURITY_CLASS.NULL) + s_class = SCL_get_class(tdbb, CS.RDB$SECURITY_CLASS); + } + END_FOR + + SCL_check_access(tdbb, s_class, 0, id_charset, name, mask, SCL_object_charset, name); +} + + +void SCL_check_collation(thread_db* tdbb, const MetaName& name, SecurityClass::flags_t mask) +{ +/************************************** + * + * S C L _ c h e c k _ c o l l a t i o n + * + ************************************** + * + * Functional description + * Given a collation name, check for a set of privileges. + * + **************************************/ + SET_TDBB(tdbb); + Jrd::Attachment* const attachment = tdbb->getAttachment(); + + const SecurityClass* s_class = NULL; + AutoCacheRequest request(tdbb, irq_coll_security, IRQ_REQUESTS); + + FOR (REQUEST_HANDLE request) + COLL IN RDB$COLLATIONS + WITH COLL.RDB$COLLATION_NAME EQ name.c_str() + { + if (!COLL.RDB$SECURITY_CLASS.NULL) + s_class = SCL_get_class(tdbb, COLL.RDB$SECURITY_CLASS); + } + END_FOR + + SCL_check_access(tdbb, s_class, 0, id_collation, name, mask, SCL_object_collation, name); +} + + +void SCL_check_domain(thread_db* tdbb, const MetaName& name, SecurityClass::flags_t mask) +{ +/************************************** + * + * S C L _ c h e c k _ d o m a i n + * + ************************************** + * + * Functional description + * Given a domain name, check for a set of privileges. + * + **************************************/ + SET_TDBB(tdbb); + Jrd::Attachment* const attachment = tdbb->getAttachment(); + + const SecurityClass* s_class = NULL; + AutoCacheRequest request(tdbb, irq_gfld_security, IRQ_REQUESTS); + + FOR (REQUEST_HANDLE request) + FLD IN RDB$FIELDS + WITH FLD.RDB$FIELD_NAME EQ name.c_str() + { + if (!FLD.RDB$SECURITY_CLASS.NULL) + s_class = SCL_get_class(tdbb, FLD.RDB$SECURITY_CLASS); + } + END_FOR + + SCL_check_access(tdbb, s_class, 0, id_domain, name, mask, SCL_object_domain, name); +} + + +void SCL_check_exception(thread_db* tdbb, const MetaName& name, SecurityClass::flags_t mask) +{ +/************************************** + * + * S C L _ c h e c k _ e x c e p t i o n + * + ************************************** + * + * Functional description + * Given an exception name, check for a set of privileges. + * + **************************************/ + SET_TDBB(tdbb); + Jrd::Attachment* const attachment = tdbb->getAttachment(); + + const SecurityClass* s_class = NULL; + AutoCacheRequest request(tdbb, irq_exc_security, IRQ_REQUESTS); + + FOR (REQUEST_HANDLE request) + XCP IN RDB$EXCEPTIONS + WITH XCP.RDB$EXCEPTION_NAME EQ name.c_str() + { + if (!XCP.RDB$SECURITY_CLASS.NULL) + s_class = SCL_get_class(tdbb, XCP.RDB$SECURITY_CLASS); + } + END_FOR + + SCL_check_access(tdbb, s_class, 0, id_exception, name, mask, SCL_object_exception, name); +} + + +void SCL_check_generator(thread_db* tdbb, const MetaName& name, SecurityClass::flags_t mask) +{ +/************************************** + * + * S C L _ c h e c k _ g e n e r a t o r + * + ************************************** + * + * Functional description + * Given a generator name, check for a set of privileges. + * + **************************************/ + SET_TDBB(tdbb); + Jrd::Attachment* const attachment = tdbb->getAttachment(); + + const SecurityClass* s_class = NULL; + AutoCacheRequest request(tdbb, irq_gen_security, IRQ_REQUESTS); + + FOR (REQUEST_HANDLE request) + GEN IN RDB$GENERATORS + WITH GEN.RDB$GENERATOR_NAME EQ name.c_str() + { + if (!GEN.RDB$SECURITY_CLASS.NULL) + s_class = SCL_get_class(tdbb, GEN.RDB$SECURITY_CLASS); + } + END_FOR + + SCL_check_access(tdbb, s_class, 0, id_generator, name, mask, SCL_object_generator, name); +} + + void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHAR index_id, SecurityClass::flags_t mask) { @@ -276,7 +439,7 @@ void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHA * *******************************************************/ SET_TDBB(tdbb); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); const SecurityClass* s_class = NULL; const SecurityClass* default_s_class = NULL; @@ -384,7 +547,7 @@ void SCL_check_package(thread_db* tdbb, const dsc* dsc_name, SecurityClass::flag const Firebird::MetaName name(reinterpret_cast(dsc_name->dsc_address), dsc_name->dsc_length); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); const SecurityClass* s_class = NULL; AutoCacheRequest request(tdbb, irq_pkg_security, IRQ_REQUESTS); @@ -423,7 +586,7 @@ void SCL_check_procedure(thread_db* tdbb, const dsc* dsc_name, SecurityClass::fl const Firebird::MetaName name(reinterpret_cast(dsc_name->dsc_address), dsc_name->dsc_length); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); const SecurityClass* s_class = NULL; AutoCacheRequest request(tdbb, irq_p_security, IRQ_REQUESTS); @@ -463,7 +626,7 @@ void SCL_check_function(thread_db* tdbb, const dsc* dsc_name, SecurityClass::fla const Firebird::MetaName name(reinterpret_cast(dsc_name->dsc_address), dsc_name->dsc_length); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); const SecurityClass* s_class = NULL; AutoCacheRequest request(tdbb, irq_f_security, IRQ_REQUESTS); @@ -503,7 +666,7 @@ void SCL_check_relation(thread_db* tdbb, const dsc* dsc_name, SecurityClass::fla const Firebird::MetaName name(reinterpret_cast(dsc_name->dsc_address), dsc_name->dsc_length); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); const SecurityClass* s_class = NULL; AutoCacheRequest request(tdbb, irq_v_security, IRQ_REQUESTS); @@ -550,7 +713,7 @@ SecurityClass* SCL_get_class(thread_db* tdbb, const TEXT* par_string) return NULL; } - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); // Look for the class already known @@ -597,7 +760,7 @@ SecurityClass::flags_t SCL_get_mask(thread_db* tdbb, const TEXT* relation_name, * **************************************/ SET_TDBB(tdbb); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); // Start with database security class @@ -650,7 +813,7 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId) * **************************************/ SET_TDBB(tdbb); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); const TEXT* sql_role = tempId.usr_sql_role_name.nullStr(); Firebird::string loginName(tempId.usr_user_name); @@ -1000,7 +1163,7 @@ static SecurityClass::flags_t compute_access(thread_db* tdbb, Acl acl; SET_TDBB(tdbb); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); jrd_tra* sysTransaction = attachment->getSysTransaction(); SecurityClass::flags_t privileges = SCL_scanned; @@ -1060,7 +1223,7 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb, * **************************************/ SET_TDBB(tdbb); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); // Munch ACL. If we find a hit, eat up privileges. diff --git a/src/jrd/scl.h b/src/jrd/scl.h index 1be87c3a2a..0a0a7e9185 100644 --- a/src/jrd/scl.h +++ b/src/jrd/scl.h @@ -146,16 +146,19 @@ public: } }; -// Here, lower is more priority. // These numbers are arbitrary and only used at run-time. Can be changed if necessary at any moment. // We need to include here the new objects that accept ACLs. const SLONG SCL_object_database = 1; -const SLONG SCL_object_schema = 2; -const SLONG SCL_object_table = 3; -const SLONG SCL_object_package = 4; -const SLONG SCL_object_procedure = 5; -const SLONG SCL_object_function = 6; -const SLONG SCL_object_column = 7; +const SLONG SCL_object_table = 2; +const SLONG SCL_object_package = 3; +const SLONG SCL_object_procedure = 4; +const SLONG SCL_object_function = 5; +const SLONG SCL_object_column = 6; +const SLONG SCL_object_collation = 7; +const SLONG SCL_object_exception = 8; +const SLONG SCL_object_generator = 9; +const SLONG SCL_object_charset = 10; +const SLONG SCL_object_domain = 11; } //namespace Jrd diff --git a/src/jrd/scl_proto.h b/src/jrd/scl_proto.h index 6144864ad0..eac06d3531 100644 --- a/src/jrd/scl_proto.h +++ b/src/jrd/scl_proto.h @@ -36,6 +36,11 @@ struct dsc; void SCL_check_access(Jrd::thread_db*, const Jrd::SecurityClass*, SLONG, SLONG, const Firebird::MetaName&, Jrd::SecurityClass::flags_t, SLONG type, const Firebird::MetaName&, const Firebird::MetaName& = ""); +void SCL_check_charset(Jrd::thread_db* tdbb, const Firebird::MetaName&, Jrd::SecurityClass::flags_t); +void SCL_check_collation(Jrd::thread_db* tdbb, const Firebird::MetaName&, Jrd::SecurityClass::flags_t); +void SCL_check_domain(Jrd::thread_db* tdbb, const Firebird::MetaName&, Jrd::SecurityClass::flags_t); +void SCL_check_exception(Jrd::thread_db* tdbb, const Firebird::MetaName&, Jrd::SecurityClass::flags_t); +void SCL_check_generator(Jrd::thread_db* tdbb, const Firebird::MetaName&, Jrd::SecurityClass::flags_t); void SCL_check_index(Jrd::thread_db*, const Firebird::MetaName&, UCHAR, Jrd::SecurityClass::flags_t); void SCL_check_package(Jrd::thread_db* tdbb, const dsc*, Jrd::SecurityClass::flags_t); void SCL_check_procedure(Jrd::thread_db* tdbb, const dsc*, Jrd::SecurityClass::flags_t); diff --git a/src/jrd/types.h b/src/jrd/types.h index 24e6077551..a9d3759031 100644 --- a/src/jrd/types.h +++ b/src/jrd/types.h @@ -39,8 +39,8 @@ TYPE("CSTRING", blr_cstring, nam_f_type) TYPE("BLOB_ID", blr_blob_id, nam_f_type) TYPE("DATE", blr_sql_date, nam_f_type) TYPE("TIME", blr_sql_time, nam_f_type) -TYPE ("INT64", blr_int64, nam_f_type) -TYPE ("BOOLEAN", blr_bool, nam_f_type) +TYPE("INT64", blr_int64, nam_f_type) +TYPE("BOOLEAN", blr_bool, nam_f_type) TYPE("BINARY", 0, nam_f_sub_type) TYPE("TEXT", 1, nam_f_sub_type) @@ -75,75 +75,75 @@ TYPE("TRANSACTION_START", 8194, nam_trg_type) TYPE("TRANSACTION_COMMIT", 8195, nam_trg_type) TYPE("TRANSACTION_ROLLBACK", 8196, nam_trg_type) -TYPE ("RELATION", obj_relation, nam_obj_type) -TYPE ("VIEW", obj_view, nam_obj_type) -TYPE ("TRIGGER", obj_trigger, nam_obj_type) -TYPE ("COMPUTED_FIELD", obj_computed, nam_obj_type) -TYPE ("VALIDATION", obj_validation, nam_obj_type) -TYPE ("PROCEDURE", obj_procedure, nam_obj_type) -TYPE ("EXPRESSION_INDEX", obj_expression_index, nam_obj_type) -TYPE ("EXCEPTION", obj_exception, nam_obj_type) -TYPE ("USER", obj_user, nam_obj_type) -TYPE ("FIELD", obj_field, nam_obj_type) -TYPE ("INDEX", obj_index, nam_obj_type) -// TYPE ("DEPENDENT_COUNT", obj_count, nam_obj_type) -TYPE ("USER_GROUP", obj_user_group, nam_obj_type) -TYPE ("ROLE", obj_sql_role, nam_obj_type) -TYPE ("GENERATOR", obj_generator, nam_obj_type) -TYPE ("UDF", obj_udf, nam_obj_type) -TYPE ("BLOB_FILTER", obj_blob_filter, nam_obj_type) -TYPE ("COLLATION", obj_collation, nam_obj_type) -TYPE ("PACKAGE", obj_package_header, nam_obj_type) -TYPE ("PACKAGE BODY", obj_package_body, nam_obj_type) +TYPE("RELATION", obj_relation, nam_obj_type) +TYPE("VIEW", obj_view, nam_obj_type) +TYPE("TRIGGER", obj_trigger, nam_obj_type) +TYPE("COMPUTED_FIELD", obj_computed, nam_obj_type) +TYPE("VALIDATION", obj_validation, nam_obj_type) +TYPE("PROCEDURE", obj_procedure, nam_obj_type) +TYPE("EXPRESSION_INDEX", obj_expression_index, nam_obj_type) +TYPE("EXCEPTION", obj_exception, nam_obj_type) +TYPE("USER", obj_user, nam_obj_type) +TYPE("FIELD", obj_field, nam_obj_type) +TYPE("INDEX", obj_index, nam_obj_type) +TYPE("CHARACTER_SET", obj_charset, nam_obj_type) +TYPE("USER_GROUP", obj_user_group, nam_obj_type) +TYPE("ROLE", obj_sql_role, nam_obj_type) +TYPE("GENERATOR", obj_generator, nam_obj_type) +TYPE("UDF", obj_udf, nam_obj_type) +TYPE("BLOB_FILTER", obj_blob_filter, nam_obj_type) +TYPE("COLLATION", obj_collation, nam_obj_type) +TYPE("PACKAGE", obj_package_header, nam_obj_type) +TYPE("PACKAGE BODY", obj_package_body, nam_obj_type) TYPE("LIMBO", 1, nam_trans_state) TYPE("COMMITTED", 2, nam_trans_state) TYPE("ROLLED_BACK", 3, nam_trans_state) -TYPE ("USER", 0, nam_sys_flag) -TYPE ("SYSTEM", 1, nam_sys_flag) -TYPE ("QLI", 2, nam_sys_flag) -TYPE ("CHECK_CONSTRAINT", 3, nam_sys_flag) -TYPE ("REFERENTIAL_CONSTRAINT", 4, nam_sys_flag) -TYPE ("VIEW_CHECK", 5, nam_sys_flag) +TYPE("USER", 0, nam_sys_flag) +TYPE("SYSTEM", 1, nam_sys_flag) +TYPE("QLI", 2, nam_sys_flag) +TYPE("CHECK_CONSTRAINT", 3, nam_sys_flag) +TYPE("REFERENTIAL_CONSTRAINT", 4, nam_sys_flag) +TYPE("VIEW_CHECK", 5, nam_sys_flag) -TYPE ("PERSISTENT", rel_persistent, nam_r_type) -TYPE ("VIEW", rel_view, nam_r_type) -TYPE ("EXTERNAL", rel_external, nam_r_type) -TYPE ("VIRTUAL", rel_virtual, nam_r_type) -TYPE ("GLOBAL_TEMPORARY_PRESERVE", rel_global_temp_preserve, nam_r_type) -TYPE ("GLOBAL_TEMPORARY_DELETE", rel_global_temp_delete, nam_r_type) +TYPE("PERSISTENT", rel_persistent, nam_r_type) +TYPE("VIEW", rel_view, nam_r_type) +TYPE("EXTERNAL", rel_external, nam_r_type) +TYPE("VIRTUAL", rel_virtual, nam_r_type) +TYPE("GLOBAL_TEMPORARY_PRESERVE", rel_global_temp_preserve, nam_r_type) +TYPE("GLOBAL_TEMPORARY_DELETE", rel_global_temp_delete, nam_r_type) -TYPE ("LEGACY", prc_legacy, nam_prc_type) -TYPE ("SELECTABLE", prc_selectable, nam_prc_type) -TYPE ("EXECUTABLE", prc_executable, nam_prc_type) +TYPE("LEGACY", prc_legacy, nam_prc_type) +TYPE("SELECTABLE", prc_selectable, nam_prc_type) +TYPE("EXECUTABLE", prc_executable, nam_prc_type) TYPE("NORMAL", prm_mech_normal, nam_prm_mechanism) TYPE("TYPE OF", prm_mech_type_of, nam_prm_mechanism) -TYPE ("IDLE", mon_state_idle, nam_mon_state) -TYPE ("ACTIVE", mon_state_active, nam_mon_state) -TYPE ("STALLED", mon_state_stalled, nam_mon_state) +TYPE("IDLE", mon_state_idle, nam_mon_state) +TYPE("ACTIVE", mon_state_active, nam_mon_state) +TYPE("STALLED", mon_state_stalled, nam_mon_state) -TYPE ("ONLINE", shut_mode_online, nam_mon_shut_mode) -TYPE ("MULTI_USER_SHUTDOWN", shut_mode_multi, nam_mon_shut_mode) -TYPE ("SINGLE_USER_SHUTDOWN", shut_mode_single, nam_mon_shut_mode) -TYPE ("FULL_SHUTDOWN", shut_mode_full, nam_mon_shut_mode) +TYPE("ONLINE", shut_mode_online, nam_mon_shut_mode) +TYPE("MULTI_USER_SHUTDOWN", shut_mode_multi, nam_mon_shut_mode) +TYPE("SINGLE_USER_SHUTDOWN", shut_mode_single, nam_mon_shut_mode) +TYPE("FULL_SHUTDOWN", shut_mode_full, nam_mon_shut_mode) -TYPE ("CONSISTENCY", iso_mode_consistency, nam_mon_iso_mode) -TYPE ("CONCURRENCY", iso_mode_concurrency, nam_mon_iso_mode) -TYPE ("READ_COMMITTED_VERSION", iso_mode_rc_version, nam_mon_iso_mode) -TYPE ("READ_COMMITTED_NO_VERSION", iso_mode_rc_no_version, nam_mon_iso_mode) +TYPE("CONSISTENCY", iso_mode_consistency, nam_mon_iso_mode) +TYPE("CONCURRENCY", iso_mode_concurrency, nam_mon_iso_mode) +TYPE("READ_COMMITTED_VERSION", iso_mode_rc_version, nam_mon_iso_mode) +TYPE("READ_COMMITTED_NO_VERSION", iso_mode_rc_no_version, nam_mon_iso_mode) -TYPE ("NORMAL", backup_state_normal, nam_mon_backup_state) -TYPE ("STALLED", backup_state_stalled, nam_mon_backup_state) -TYPE ("MERGE", backup_state_merge, nam_mon_backup_state) +TYPE("NORMAL", backup_state_normal, nam_mon_backup_state) +TYPE("STALLED", backup_state_stalled, nam_mon_backup_state) +TYPE("MERGE", backup_state_merge, nam_mon_backup_state) -TYPE ("DATABASE", stat_database, nam_mon_stat_group) -TYPE ("ATTACHMENT", stat_attachment, nam_mon_stat_group) -TYPE ("TRANSACTION", stat_transaction, nam_mon_stat_group) -TYPE ("STATEMENT", stat_statement, nam_mon_stat_group) -TYPE ("CALL", stat_call, nam_mon_stat_group) +TYPE("DATABASE", stat_database, nam_mon_stat_group) +TYPE("ATTACHMENT", stat_attachment, nam_mon_stat_group) +TYPE("TRANSACTION", stat_transaction, nam_mon_stat_group) +TYPE("STATEMENT", stat_statement, nam_mon_stat_group) +TYPE("CALL", stat_call, nam_mon_stat_group) -TYPE ("ALWAYS", IDENT_TYPE_ALWAYS, nam_identity_type) -TYPE ("BY DEFAULT", IDENT_TYPE_BY_DEFAULT, nam_identity_type) +TYPE("ALWAYS", IDENT_TYPE_ALWAYS, nam_identity_type) +TYPE("BY DEFAULT", IDENT_TYPE_BY_DEFAULT, nam_identity_type) diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index e5fdbf8750..79f2688750 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -1267,9 +1267,7 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) * stub. * **************************************/ - - // Revokee is only 32 bytes. UserId would be truncated. - SqlIdentifier relation_name, revokee, privilege, procedure_name, package_name; + MetaName object_name, package_name; SET_TDBB(tdbb); jrd_req* request = tdbb->getRequest(); @@ -1359,19 +1357,23 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) if (EVL_field(0, rpb->rpb_record, f_prc_pkg_name, &desc2)) { - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); + MOV_get_metaname(&desc2, package_name); SCL_check_package(tdbb, &desc2, SCL_delete); } - else - package_name[0] = '\0'; - if (EVL_field(0, rpb->rpb_record, f_prc_name, &desc) && package_name[0] == '\0') + if (EVL_field(0, rpb->rpb_record, f_prc_name, &desc) && package_name.isEmpty()) SCL_check_procedure(tdbb, &desc, SCL_delete); DFW_post_work(transaction, dfw_delete_procedure, &desc, id, package_name); MET_lookup_procedure_id(tdbb, id, false, true, 0); break; + case rel_charsets: + EVL_field(0, rpb->rpb_record, f_cs_cs_name, &desc); + MOV_get_metaname(&desc, object_name); + SCL_check_charset(tdbb, object_name, SCL_delete); + break; + case rel_collations: EVL_field(0, rpb->rpb_record, f_coll_cs_id, &desc2); id = MOV_get_long(&desc2, 0); @@ -1380,16 +1382,22 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) id = INTL_CS_COLL_TO_TTYPE(id, MOV_get_long(&desc2, 0)); EVL_field(0, rpb->rpb_record, f_coll_name, &desc); + MOV_get_metaname(&desc, object_name); + SCL_check_collation(tdbb, object_name, SCL_delete); DFW_post_work(transaction, dfw_delete_collation, &desc, id); break; case rel_exceptions: - EVL_field(0, rpb->rpb_record, f_prc_name, &desc); + EVL_field(0, rpb->rpb_record, f_xcp_name, &desc); + MOV_get_metaname(&desc, object_name); + SCL_check_exception(tdbb, object_name, SCL_delete); DFW_post_work(transaction, dfw_delete_exception, &desc, 0); break; case rel_gens: - EVL_field (0, rpb->rpb_record, f_gen_name, &desc); + EVL_field(0, rpb->rpb_record, f_gen_name, &desc); + MOV_get_metaname(&desc, object_name); + SCL_check_generator(tdbb, object_name, SCL_delete); DFW_post_work(transaction, dfw_delete_generator, &desc, 0); break; @@ -1398,12 +1406,11 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) if (EVL_field(0, rpb->rpb_record, f_fun_pkg_name, &desc2)) { - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); + MOV_get_metaname(&desc2, package_name); SCL_check_package(tdbb, &desc2, SCL_delete); } else { - package_name[0] = '\0'; SCL_check_function(tdbb, &desc, SCL_delete); } @@ -1420,7 +1427,8 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) EVL_field(0, rpb->rpb_record, f_idx_id, &desc2); if ( (id = MOV_get_long(&desc2, 0)) ) { - MOV_get_metadata_str(&desc, relation_name, sizeof(relation_name)); + MetaName relation_name; + MOV_get_metaname(&desc, relation_name); r2 = MET_lookup_relation(tdbb, relation_name); fb_assert(r2); @@ -1446,14 +1454,14 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) DSC desc3; EVL_field(0, rpb->rpb_record, f_idx_name, &desc3); - SqlIdentifier index_name; - MOV_get_metadata_str(&desc3, index_name, sizeof(index_name)); + MetaName index_name; + MOV_get_metaname(&desc3, index_name); jrd_rel *partner; index_desc idx; if ((BTR_lookup(tdbb, r2, id - 1, &idx, r2->getPages(tdbb)) == FB_SUCCESS) && - MET_lookup_partner(tdbb, r2, &idx, index_name) && + MET_lookup_partner(tdbb, r2, &idx, index_name.nullStr()) && (partner = MET_lookup_relation_id(tdbb, idx.idx_primary_relation, false)) ) { DFW_post_work_arg(transaction, work, 0, partner->rel_id, @@ -1475,8 +1483,8 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) SCL_check_relation(tdbb, &desc, SCL_control); DFW_post_work(transaction, dfw_update_format, &desc, 0); EVL_field(0, rpb->rpb_record, f_rfr_fname, &desc2); - MOV_get_metadata_str(&desc, relation_name, sizeof(relation_name)); - if ( (r2 = MET_lookup_relation(tdbb, relation_name)) ) + MOV_get_metaname(&desc, object_name); + if ( (r2 = MET_lookup_relation(tdbb, object_name)) ) { DFW_post_work(transaction, dfw_delete_rfr, &desc2, r2->rel_id); } @@ -1487,13 +1495,12 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) case rel_args: if (EVL_field(0, rpb->rpb_record, f_arg_pkg_name, &desc2)) { - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); + MOV_get_metaname(&desc2, package_name); SCL_check_package(tdbb, &desc2, SCL_control); } else { EVL_field(0, rpb->rpb_record, f_arg_fun_name, &desc); - package_name[0] = '\0'; SCL_check_function(tdbb, &desc, SCL_control); } break; @@ -1503,20 +1510,19 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) if (EVL_field(0, rpb->rpb_record, f_prm_pkg_name, &desc2)) { - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); + MOV_get_metaname(&desc2, package_name); SCL_check_package(tdbb, &desc2, SCL_control); } else { - package_name[0] = '\0'; SCL_check_procedure(tdbb, &desc, SCL_control); } EVL_field(0, rpb->rpb_record, f_prm_name, &desc2); - MOV_get_metadata_str(&desc, procedure_name, sizeof(procedure_name)); + MOV_get_metaname(&desc, object_name); - if ((procedure = MET_lookup_procedure(tdbb, - QualifiedName(procedure_name, package_name), true))) + if ( (procedure = MET_lookup_procedure(tdbb, + QualifiedName(object_name, package_name), true)) ) { work = DFW_post_work(transaction, dfw_delete_prm, &desc2, procedure->getId(), package_name); @@ -1529,8 +1535,9 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) break; case rel_fields: - check_control(tdbb); EVL_field(0, rpb->rpb_record, f_fld_name, &desc); + MOV_get_metaname(&desc, object_name); + SCL_check_domain(tdbb, object_name, SCL_delete); DFW_post_work(transaction, dfw_delete_field, &desc, 0); MET_change_fields(tdbb, transaction, &desc); break; @@ -1666,15 +1673,16 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) if ((RIDS) relation->rel_id == rel_priv) { EVL_field(0, rpb->rpb_record, f_prv_rname, &desc); - MOV_get_metadata_str(&desc, relation_name, sizeof(relation_name)); + MOV_get_metaname(&desc, object_name); EVL_field(0, rpb->rpb_record, f_prv_grant, &desc2); if (MOV_get_long(&desc2, 0)) { EVL_field(0, rpb->rpb_record, f_prv_user, &desc2); - MOV_get_metadata_str(&desc2, revokee, sizeof(revokee)); + MetaName revokee; + MOV_get_metaname(&desc2, revokee); EVL_field(0, rpb->rpb_record, f_prv_priv, &desc2); - MOV_get_metadata_str(&desc2, privilege, sizeof(privilege)); - MET_revoke(tdbb, transaction, relation_name, revokee, privilege); + const string privilege = MOV_make_string2(tdbb, &desc2, ttype_ascii); + MET_revoke(tdbb, transaction, object_name, revokee, privilege); } } if (!(transaction->tra_flags & TRA_system) && @@ -2321,6 +2329,8 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j **************************************/ SET_TDBB(tdbb); + MetaName object_name, package_name; + #ifdef VIO_DEBUG if (debug_flag > DEBUG_WRITES) { @@ -2396,60 +2406,54 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j case rel_procedures: EVL_field(0, org_rpb->rpb_record, f_prc_name, &desc1); - { // scope - SqlIdentifier package_name; - if (EVL_field(0, org_rpb->rpb_record, f_prc_pkg_name, &desc2)) - { - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); - SCL_check_package(tdbb, &desc2, SCL_protect); - } - else - { - package_name[0] = '\0'; - SCL_check_procedure(tdbb, &desc1, SCL_protect); - } + if (EVL_field(0, org_rpb->rpb_record, f_prc_pkg_name, &desc2)) + { + MOV_get_metaname(&desc2, package_name); + SCL_check_package(tdbb, &desc2, SCL_protect); + } + else + { + SCL_check_procedure(tdbb, &desc1, SCL_protect); + } - check_class(tdbb, transaction, org_rpb, new_rpb, f_prc_class); + check_class(tdbb, transaction, org_rpb, new_rpb, f_prc_class); - if (dfw_should_know(org_rpb, new_rpb, f_prc_desc, true)) - { - EVL_field(0, org_rpb->rpb_record, f_prc_id, &desc2); - const USHORT id = MOV_get_long(&desc2, 0); - DFW_post_work(transaction, dfw_modify_procedure, &desc1, id, package_name); - } - } // scope + if (dfw_should_know(org_rpb, new_rpb, f_prc_desc, true)) + { + EVL_field(0, org_rpb->rpb_record, f_prc_id, &desc2); + const USHORT id = MOV_get_long(&desc2, 0); + DFW_post_work(transaction, dfw_modify_procedure, &desc1, id, package_name); + } break; case rel_funs: EVL_field(0, org_rpb->rpb_record, f_fun_name, &desc1); - { // scope - SqlIdentifier package_name; - if (EVL_field(0, org_rpb->rpb_record, f_fun_pkg_name, &desc2)) - { - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); - SCL_check_package(tdbb, &desc2, SCL_protect); - } - else - { - package_name[0] = '\0'; - SCL_check_function(tdbb, &desc1, SCL_protect); - } + if (EVL_field(0, org_rpb->rpb_record, f_fun_pkg_name, &desc2)) + { + MOV_get_metaname(&desc2, package_name); + SCL_check_package(tdbb, &desc2, SCL_protect); + } + else + { + SCL_check_function(tdbb, &desc1, SCL_protect); + } - check_class(tdbb, transaction, org_rpb, new_rpb, f_fun_class); + check_class(tdbb, transaction, org_rpb, new_rpb, f_fun_class); - if (dfw_should_know(org_rpb, new_rpb, f_fun_desc, true)) - { - EVL_field(0, org_rpb->rpb_record, f_fun_id, &desc2); - const USHORT id = MOV_get_long(&desc2, 0); - DFW_post_work(transaction, dfw_modify_function, &desc1, id, package_name); - } - } // scope + if (dfw_should_know(org_rpb, new_rpb, f_fun_desc, true)) + { + EVL_field(0, org_rpb->rpb_record, f_fun_id, &desc2); + const USHORT id = MOV_get_long(&desc2, 0); + DFW_post_work(transaction, dfw_modify_function, &desc1, id, package_name); + } break; case rel_gens: + EVL_field(0, org_rpb->rpb_record, f_gen_name, &desc1); + MOV_get_metaname(&desc1, object_name); + SCL_check_generator(tdbb, object_name, SCL_protect); { - EVL_field (0, org_rpb->rpb_record, f_gen_name, &desc1); // We won't accept modifying sys generators and for user gens, // only the description. // This is poor man's version of a trigger discovering changed fields. @@ -2480,11 +2484,12 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j break; case rel_fields: - check_control(tdbb); + EVL_field(0, org_rpb->rpb_record, f_fld_name, &desc1); + MOV_get_metaname(&desc1, object_name); + SCL_check_domain(tdbb, object_name, SCL_protect); if (dfw_should_know(org_rpb, new_rpb, f_fld_desc, true)) { - EVL_field(0, org_rpb->rpb_record, f_fld_name, &desc1); MET_change_fields(tdbb, transaction, &desc1); EVL_field(0, new_rpb->rpb_record, f_fld_name, &desc2); DeferredWork* dw = MET_change_fields(tdbb, transaction, &desc2); @@ -2583,6 +2588,24 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j } break; + case rel_charsets: + EVL_field(0, new_rpb->rpb_record, fld_charset_name, &desc1); + MOV_get_metaname(&desc1, object_name); + SCL_check_charset(tdbb, object_name, SCL_protect); + break; + + case rel_collations: + EVL_field(0, new_rpb->rpb_record, f_coll_name, &desc1); + MOV_get_metaname(&desc1, object_name); + SCL_check_collation(tdbb, object_name, SCL_protect); + break; + + case rel_exceptions: + EVL_field(0, new_rpb->rpb_record, f_xcp_name, &desc1); + MOV_get_metaname(&desc1, object_name); + SCL_check_exception(tdbb, object_name, SCL_protect); + break; + default: break; } @@ -2934,11 +2957,9 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) case rel_procedures: EVL_field(0, rpb->rpb_record, f_prc_name, &desc); { // scope - SqlIdentifier package_name; + MetaName package_name; if (EVL_field(0, rpb->rpb_record, f_prc_pkg_name, &desc2)) - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); - else - package_name[0] = '\0'; + MOV_get_metaname(&desc2, package_name); EVL_field(0, rpb->rpb_record, f_prc_id, &desc2); const USHORT id = MOV_get_long(&desc2, 0); @@ -2957,11 +2978,9 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) case rel_funs: EVL_field(0, rpb->rpb_record, f_fun_name, &desc); { // scope - SqlIdentifier package_name; + MetaName package_name; if (EVL_field(0, rpb->rpb_record, f_fun_pkg_name, &desc2)) - MOV_get_metadata_str(&desc2, package_name, sizeof(package_name)); - else - package_name[0] = '\0'; + MOV_get_metaname(&desc2, package_name); const USHORT id = set_metadata_id(tdbb, rpb->rpb_record, f_fun_id, drq_g_nxt_fun_id, "RDB$FUNCTIONS"); @@ -3010,6 +3029,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) EVL_field(0, rpb->rpb_record, f_fld_name, &desc); DFW_post_work(transaction, dfw_create_field, &desc, 0); set_system_flag(tdbb, rpb->rpb_record, f_fld_sys_flag, 0); + set_security_class(tdbb, rpb->rpb_record, f_fld_class); break; case rel_files: @@ -3099,6 +3119,19 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) transaction->getGenIdCache()->put(id, 0); DFW_post_work(transaction, dfw_create_generator, &desc, id); } + set_security_class(tdbb, rpb->rpb_record, f_gen_class); + break; + + case rel_charsets: + set_security_class(tdbb, rpb->rpb_record, f_cs_class); + break; + + case rel_collations: + set_security_class(tdbb, rpb->rpb_record, f_coll_class); + break; + + case rel_exceptions: + set_security_class(tdbb, rpb->rpb_record, f_xcp_class); break; default: // Shut up compiler warnings @@ -5443,7 +5476,7 @@ static void set_security_class(thread_db* tdbb, Record* record, USHORT field_id) { const SINT64 value = DYN_UTIL_gen_unique_id(tdbb, drq_g_nxt_sec_id, SQL_SECCLASS_GENERATOR); Firebird::MetaName name; - name.printf("%s%d", SQL_SECCLASS_PREFIX, value); + name.printf("%s%"SQUADFORMAT, SQL_SECCLASS_PREFIX, value); dsc desc2; desc2.makeText((USHORT) name.length(), CS_ASCII, (UCHAR*) name.c_str()); MOV_move(tdbb, &desc2, &desc1);