mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 06:03:02 +01:00
Fixed CORE-1775 : Improve performance of security checking
This commit is contained in:
parent
b73c1eee66
commit
7d54298dea
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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<SCHAR, type_scl>
|
||||
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 */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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<TEXT*>(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,
|
||||
|
Loading…
Reference in New Issue
Block a user