8
0
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:
hvlad 2008-03-06 13:13:31 +00:00
parent b73c1eee66
commit 7d54298dea
7 changed files with 78 additions and 62 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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,