diff --git a/src/jrd/cmp.cpp b/src/jrd/cmp.cpp index 87453fcc8a..519e21112c 100644 --- a/src/jrd/cmp.cpp +++ b/src/jrd/cmp.cpp @@ -348,8 +348,9 @@ static void verify_trigger_access(thread_db* tdbb, jrd_rel* owner_relation, trig continue; } } + // a direct access to an object from this trigger - const SecurityClass* sec_class = SCL_get_class(access->acc_security_name.c_str()); + const SecurityClass* sec_class = SCL_get_class(tdbb, access->acc_security_name.c_str()); SCL_check_access(sec_class, (access->acc_view_id) ? access->acc_view_id : (view ? view->rel_id : 0), @@ -386,7 +387,7 @@ void CMP_verify_access(thread_db* tdbb, jrd_req* request) access < prc->prc_request->req_access.end(); access++) { - const SecurityClass* sec_class = SCL_get_class(access->acc_security_name.c_str()); + const SecurityClass* sec_class = SCL_get_class(tdbb, access->acc_security_name.c_str()); SCL_check_access(sec_class, access->acc_view_id, NULL, prc->prc_name, access->acc_mask, access->acc_type, access->acc_name, access->acc_r_name); } @@ -422,7 +423,7 @@ void CMP_verify_access(thread_db* tdbb, jrd_req* request) for (const AccessItem* access = request->req_access.begin(); access < request->req_access.end(); access++) { - const SecurityClass* sec_class = SCL_get_class(access->acc_security_name.c_str()); + const SecurityClass* sec_class = SCL_get_class(tdbb, access->acc_security_name.c_str()); SCL_check_access(sec_class, access->acc_view_id, NULL, NULL, access->acc_mask, access->acc_type, access->acc_name, access->acc_r_name); } @@ -468,7 +469,7 @@ jrd_req* CMP_clone_request(thread_db* tdbb, jrd_req* request, USHORT level, bool const TEXT* prc_sec_name = (procedure->prc_security_name.length() > 0 ? procedure->prc_security_name.c_str() : NULL); - const SecurityClass* sec_class = SCL_get_class(prc_sec_name); + const SecurityClass* sec_class = SCL_get_class(tdbb, prc_sec_name); SCL_check_access(sec_class, 0, NULL, NULL, SCL_execute, object_procedure, procedure->prc_name); } diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 029760089d..24777de043 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -5799,10 +5799,7 @@ static void purge_attachment(thread_db* tdbb, CMP_release(tdbb, request); } - SecurityClass* sec_class; - while ( (sec_class = attachment->att_security_classes) ) { - SCL_release(sec_class); - } + SCL_release(attachment->att_security_classes); delete attachment->att_user; delete attachment; diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index 5d061e7e68..60e7356c12 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -53,6 +53,7 @@ #include "../jrd/RandomGenerator.h" #include "../jrd/os/guid.h" #include "../jrd/sbm.h" +#include "../jrd/scl.h" #ifdef DEV_BUILD #define DEBUG if (debug) DBG_supervisor(debug); @@ -143,10 +144,8 @@ class IndexLock; class ArrayField; //class PageControl; class Symbol; -class UserId; struct sort_context; class RecordSelExpr; -class SecurityClass; class vcl; class TextType; //class jrd_prc; @@ -298,7 +297,7 @@ public: SLONG att_lock_owner_handle; // Handle for the lock manager SLONG att_event_session; // Event session id, if any SecurityClass* att_security_class; // security class for database - SecurityClass* att_security_classes; // security classes + SecurityClassList* att_security_classes; // security classes vcl* att_counts[DBB_max_count]; RuntimeStatistics att_stats; ULONG att_flags; // Flags describing the state of the attachment diff --git a/src/jrd/scl.epp b/src/jrd/scl.epp index 9860a0236a..85a07185ee 100644 --- a/src/jrd/scl.epp +++ b/src/jrd/scl.epp @@ -291,9 +291,9 @@ void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHA reln_name = REL.RDB$RELATION_NAME; if (!REL.RDB$SECURITY_CLASS.NULL) - s_class = SCL_get_class(REL.RDB$SECURITY_CLASS); + s_class = SCL_get_class(tdbb, REL.RDB$SECURITY_CLASS); if (!REL.RDB$DEFAULT_CLASS.NULL) - default_s_class = SCL_get_class(REL.RDB$DEFAULT_CLASS); + default_s_class = SCL_get_class(tdbb, REL.RDB$DEFAULT_CLASS); END_FOR; CMP_release(tdbb, request); @@ -309,9 +309,9 @@ void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHA reln_name = REL.RDB$RELATION_NAME; aux_idx_name = IND.RDB$INDEX_NAME; if (!REL.RDB$SECURITY_CLASS.NULL) - s_class = SCL_get_class(REL.RDB$SECURITY_CLASS); + s_class = SCL_get_class(tdbb, REL.RDB$SECURITY_CLASS); if (!REL.RDB$DEFAULT_CLASS.NULL) - default_s_class = SCL_get_class(REL.RDB$DEFAULT_CLASS); + default_s_class = SCL_get_class(tdbb, REL.RDB$DEFAULT_CLASS); END_FOR; CMP_release (tdbb, request); @@ -352,7 +352,7 @@ void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHA fullFieldName += RF.RDB$FIELD_NAME; fullFieldName.rtrim(); if (!RF.RDB$SECURITY_CLASS.NULL) { - s_class = SCL_get_class(RF.RDB$SECURITY_CLASS); + s_class = SCL_get_class(tdbb, RF.RDB$SECURITY_CLASS); SCL_check_access(s_class, 0, NULL, NULL, mask, object_column, fullFieldName); } @@ -407,7 +407,7 @@ void SCL_check_procedure(const dsc* dsc_name, SecurityClass::flags_t mask) REQUEST(irq_p_security) = request; if (!SPROC.RDB$SECURITY_CLASS.NULL) - s_class = SCL_get_class(SPROC.RDB$SECURITY_CLASS); + s_class = SCL_get_class(tdbb, SPROC.RDB$SECURITY_CLASS); END_FOR; if (!REQUEST(irq_p_security)) @@ -451,7 +451,7 @@ void SCL_check_relation(const dsc* dsc_name, SecurityClass::flags_t mask) REQUEST(irq_v_security) = request; if (!REL.RDB$SECURITY_CLASS.NULL) - s_class = SCL_get_class(REL.RDB$SECURITY_CLASS); + s_class = SCL_get_class(tdbb, REL.RDB$SECURITY_CLASS); END_FOR; if (!REQUEST(irq_v_security)) @@ -461,7 +461,7 @@ void SCL_check_relation(const dsc* dsc_name, SecurityClass::flags_t mask) } -SecurityClass* SCL_get_class(const TEXT* _string) +SecurityClass* SCL_get_class(thread_db* tdbb, const TEXT* _string) { /************************************** * @@ -475,7 +475,7 @@ SecurityClass* SCL_get_class(const TEXT* _string) * class block. * **************************************/ - thread_db* tdbb = JRD_get_thread_data(); + SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); // Name may be absent or terminated with NULL or blank. Clean up name. @@ -484,12 +484,11 @@ SecurityClass* SCL_get_class(const TEXT* _string) return NULL; } - Firebird::string string = _string; + Firebird::MetaName string = _string; - fb_utils::exact_name(string); + //fb_utils::exact_name(string); - if (string.empty()) - { + if (string.isEmpty()) { return NULL; } @@ -498,25 +497,25 @@ SecurityClass* SCL_get_class(const TEXT* _string) // Look for the class already known SecurityClass* s_class; - for (s_class = attachment->att_security_classes; - s_class; - s_class = s_class->scl_next) - { - if (string == s_class->scl_name) { - return s_class; - } - } + SecurityClassList *list = attachment->att_security_classes; + size_t pos = 0; + if (list && list->locate(string)) + return list->current(); // Class isn't known. So make up a new security class block. - s_class = FB_NEW_RPT(*dbb->dbb_permanent, string.length()) SecurityClass(); - strcpy(s_class->scl_name, string.c_str()); + s_class = FB_NEW(*dbb->dbb_permanent) SecurityClass(*dbb->dbb_permanent); + s_class->scl_name = string; s_class->scl_flags = compute_access(tdbb, s_class, NULL, NULL, NULL); if (s_class->scl_flags & SCL_exists) { - s_class->scl_next = attachment->att_security_classes; - attachment->att_security_classes = s_class; + if (!list) { + attachment->att_security_classes = list = FB_NEW (*dbb->dbb_permanent) + SecurityClassList (*dbb->dbb_permanent); + } + + list->add(s_class); return s_class; } @@ -555,7 +554,7 @@ SecurityClass::flags_t SCL_get_mask(const TEXT* relation_name, const TEXT* field (relation = MET_lookup_relation(tdbb, relation_name))) { MET_scan_relation(tdbb, relation); - if ( (s_class = SCL_get_class(relation->rel_security_name.c_str())) ) + if ( (s_class = SCL_get_class(tdbb, relation->rel_security_name.c_str())) ) { access &= s_class->scl_flags; } @@ -565,7 +564,7 @@ SecurityClass::flags_t SCL_get_mask(const TEXT* relation_name, const TEXT* field if (field_name && (id = MET_lookup_field(tdbb, relation, field_name, 0)) >= 0 && (field = MET_get_field(relation, id)) && - (s_class = SCL_get_class(field->fld_security_name.c_str()))) + (s_class = SCL_get_class(tdbb, field->fld_security_name.c_str()))) { access &= s_class->scl_flags; } @@ -731,7 +730,7 @@ void SCL_init(bool create, if (!X.RDB$SECURITY_CLASS.NULL) tdbb->getAttachment()->att_security_class = - SCL_get_class(X.RDB$SECURITY_CLASS); + SCL_get_class(tdbb, X.RDB$SECURITY_CLASS); END_FOR; CMP_release(tdbb, handle); @@ -821,7 +820,7 @@ SecurityClass* SCL_recompute_class(thread_db* tdbb, const TEXT* string) **************************************/ SET_TDBB(tdbb); - SecurityClass* s_class = SCL_get_class(string); + SecurityClass* s_class = SCL_get_class(tdbb, string); if (!s_class) { return NULL; } @@ -834,13 +833,20 @@ SecurityClass* SCL_recompute_class(thread_db* tdbb, const TEXT* string) // Class no long exists - get rid of it! - SCL_release(s_class); + Firebird::MetaName m_string(string); + SecurityClassList *list = tdbb->getAttachment()->att_security_classes; + if (list && list->locate(m_string)) + { + list->fastRemove(); + delete s_class; + } + return NULL; } -void SCL_release(SecurityClass* s_class) +void SCL_release(SecurityClassList* list) { /************************************** * @@ -852,20 +858,15 @@ void SCL_release(SecurityClass* s_class) * Release an unneeded and unloved security class. * **************************************/ - thread_db* tdbb = JRD_get_thread_data(); - Attachment* attachment = tdbb->getAttachment(); + if (!list) + return; - for (SecurityClass** next = &attachment->att_security_classes; *next; - next = &(*next)->scl_next) - { - if (*next == s_class) - { - *next = s_class->scl_next; - break; - } - } + if (list->getFirst()) + do { + delete list->current(); + } while (list->getNext()); - delete s_class; + delete list; } @@ -1046,7 +1047,7 @@ static SecurityClass::flags_t compute_access(thread_db* tdbb, jrd_req* request = CMP_find_request(tdbb, irq_l_security, IRQ_REQUESTS); FOR(REQUEST_HANDLE request) X IN RDB$SECURITY_CLASSES - WITH X.RDB$SECURITY_CLASS EQ s_class->scl_name + WITH X.RDB$SECURITY_CLASS EQ s_class->scl_name.c_str() if (!REQUEST(irq_l_security)) REQUEST(irq_l_security) = request; diff --git a/src/jrd/scl.h b/src/jrd/scl.h index cca7ac12e5..c75dffac68 100644 --- a/src/jrd/scl.h +++ b/src/jrd/scl.h @@ -24,19 +24,37 @@ #ifndef JRD_SCL_H #define JRD_SCL_H +#include "../common/classes/MetaName.h" +#include "../common/classes/tree.h" + namespace Jrd { /* Security class definition */ -class SecurityClass : public pool_alloc_rpt +class SecurityClass { - public: +public: typedef USHORT flags_t; - SecurityClass* scl_next; /* Next security class in system */ + + SecurityClass(Firebird::MemoryPool &pool) : + scl_name(pool) {} + flags_t scl_flags; /* Access permissions */ - TEXT scl_name[2]; + Firebird::MetaName scl_name; + + static const Firebird::MetaName& generate(const void*, const SecurityClass *Item) { + return Item->scl_name; + } }; +typedef Firebird::BePlusTree< + SecurityClass*, + Firebird::MetaName, + Firebird::MemoryPool, + SecurityClass +> SecurityClassList; + + const SecurityClass::flags_t SCL_read = 1; /* Read access */ const SecurityClass::flags_t SCL_write = 2; /* Write access */ const SecurityClass::flags_t SCL_delete = 4; /* Delete access */ diff --git a/src/jrd/scl_proto.h b/src/jrd/scl_proto.h index d747d8f9d5..99088d9f8e 100644 --- a/src/jrd/scl_proto.h +++ b/src/jrd/scl_proto.h @@ -63,12 +63,12 @@ inline void SCL_check_access(const Jrd::SecurityClass* s_class, void SCL_check_index(Jrd::thread_db*, const Firebird::MetaName&, UCHAR, Jrd::SecurityClass::flags_t); void SCL_check_procedure(const dsc*, Jrd::SecurityClass::flags_t); void SCL_check_relation(const dsc*, Jrd::SecurityClass::flags_t); -Jrd::SecurityClass* SCL_get_class(const TEXT*); +Jrd::SecurityClass* SCL_get_class(Jrd::thread_db*, const TEXT*); Jrd::SecurityClass::flags_t SCL_get_mask(const TEXT*, const TEXT*); void SCL_init(bool, const Jrd::UserId& tempId, Jrd::thread_db*); void SCL_move_priv(UCHAR**, Jrd::SecurityClass::flags_t, Firebird::UCharBuffer&, ULONG*); Jrd::SecurityClass* SCL_recompute_class(Jrd::thread_db*, const TEXT*); -void SCL_release(Jrd::SecurityClass*); +void SCL_release(Jrd::SecurityClassList*); #endif // JRD_SCL_PROTO_H diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index 3c388def0d..fdaffaaa0b 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -3356,7 +3356,7 @@ static void check_rel_field_class(record_param* rpb, EVL_field(0, rpb->rpb_record, f_rfr_class, &desc); const Firebird::MetaName class_name(reinterpret_cast(desc.dsc_address), desc.dsc_length); - const SecurityClass* s_class = SCL_get_class(class_name.c_str()); + const SecurityClass* s_class = SCL_get_class(JRD_get_thread_data(), class_name.c_str()); if (s_class) { // In case when user has no access to the field,