diff --git a/src/common/classes/array.h b/src/common/classes/array.h index d587f1ca0d..297b2c9ff0 100644 --- a/src/common/classes/array.h +++ b/src/common/classes/array.h @@ -212,6 +212,10 @@ public: memmove(data + index, data + index + 1, sizeof(T) * (--count - index)); return &data[index]; } + T* remove(T* itrFrom, T* itrTo) + { + return removeRange(itrFrom - begin(), itrTo - begin()); + } void shrink(size_t newCount) { fb_assert(newCount <= count); @@ -254,6 +258,12 @@ public: memcpy(data + count, L.data, sizeof(T) * L.count); count += L.count; } + void assign(const Array& L) + { + ensureCapacity(L.count); + memcpy(data, L.data, sizeof(T) * L.count); + count = L.count; + } // NOTE: getCount method must be signal safe // Used as such in GlobalRWLock::blockingAstHandler size_t getCount() const { return count; } diff --git a/src/jrd/grant.epp b/src/jrd/grant.epp index 95e02fdd92..1900c8a1c0 100644 --- a/src/jrd/grant.epp +++ b/src/jrd/grant.epp @@ -64,69 +64,37 @@ const SecurityClass::flags_t VIEW_PRIVS = SCL_read | SCL_write | SCL_delete; const ULONG ACL_BUFFER_SIZE = 4096; static const char* DEFAULT_CLASS = "SQL$DEFAULT"; -#define CHECK_ACL_BOUND(to, start, length_ptr, move_length)\ - {\ - if (((start).begin() + *length_ptr) < (to + move_length)) {\ - GRANT_realloc_acl(start, &to, length_ptr);\ - }\ - } -#define CHECK_AND_MOVE(to, from, start, length_ptr) {CHECK_ACL_BOUND (to, start, length_ptr, 1); *(to)++ = from;} -#define CHECK_MOVE_INCR(to, from, start, length_ptr) {CHECK_ACL_BOUND (to, start, length_ptr, 1); *(to)++ = (from)++;} +inline void CHECK_AND_MOVE(Acl& to, UCHAR from) +{ + to.add(from); +} DATABASE DB = STATIC "yachts.lnk"; -static void define_default_class(thread_db*, const TEXT*, Firebird::MetaName&, const UCHAR*, USHORT); +static void define_default_class(thread_db*, const TEXT*, Firebird::MetaName&, const Acl&); #ifdef NOT_USED_OR_REPLACED static void delete_security_class(thread_db*, const TEXT*); #endif -static void finish_security_class(UCHAR**, SecurityClass::flags_t, Firebird::UCharBuffer&, ULONG*); +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&); static SecurityClass::flags_t get_public_privs(thread_db*, const TEXT*, SSHORT); -static void get_user_privs(thread_db*, UCHAR**, const TEXT*, SSHORT, const Firebird::MetaName&, - SecurityClass::flags_t, Firebird::UCharBuffer&, ULONG*); -static void grant_user(UCHAR**, const Firebird::MetaName&, SSHORT, SecurityClass::flags_t, - Firebird::UCharBuffer&, ULONG*); +static void get_user_privs(thread_db*, Acl&, const TEXT*, SSHORT, const Firebird::MetaName&, + SecurityClass::flags_t); +static void grant_user(Acl&, const Firebird::MetaName&, SSHORT, SecurityClass::flags_t); #ifdef NOT_USED_OR_REPLACED -static void grant_views(TEXT**, SecurityClass::flags_t, Firebird::UCharBuffer&, ULONG*); +static void grant_views(TEXT**, SecurityClass::flags_t); static void purge_default_class(TEXT*, SSHORT); #endif -static SecurityClass::flags_t save_field_privileges(thread_db*, Firebird::UCharBuffer&, UCHAR**, +static SecurityClass::flags_t save_field_privileges(thread_db*, Acl&, const TEXT*, const Firebird::MetaName&, - SecurityClass::flags_t, ULONG*); -static void save_security_class(thread_db*, const Firebird::MetaName&, const UCHAR*, USHORT); + SecurityClass::flags_t); +static void save_security_class(thread_db*, const Firebird::MetaName&, const Acl&); static SecurityClass::flags_t trans_sql_priv(const TEXT*); -static SecurityClass::flags_t squeeze_acl(UCHAR*, UCHAR**, const Firebird::MetaName&, SSHORT); +static SecurityClass::flags_t squeeze_acl(Acl&, const Firebird::MetaName&, SSHORT); static bool check_string(const UCHAR*, const Firebird::MetaName&); -void GRANT_realloc_acl(Firebird::UCharBuffer& start_ptr, - UCHAR** write_ptr, - ULONG* buffer_length) -{ -/************************************** - * - * G R A N T _ r e a l l o c _ a c l - * - ************************************** - * - * Functional description - * The ACl list is greater than the current length, Increase it by - * MAX_AXL_SIZE. Do a ERR_punt in case of no memory! - * - **************************************/ - - const ULONG old_offset = *write_ptr - start_ptr.begin(); - const ULONG realloc_length = *buffer_length + ACL_BUFFER_SIZE; - -// realloc the new length, ERR_punt incase of no memory -// the write_ptr is set back to the same offset in the new buffer - *write_ptr = start_ptr.getBuffer(realloc_length) + old_offset; - - *buffer_length = realloc_length; -} - - bool GRANT_privileges( thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra*) // unused param, makes dfw.epp happy { @@ -150,7 +118,8 @@ bool GRANT_privileges( thread_db* tdbb, SSHORT phase, DeferredWork* work, case 3: { - ULONG length = ACL_BUFFER_SIZE, *length_ptr = &length; + ULONG length = ACL_BUFFER_SIZE; + ULONG* length_ptr = &length; ULONG default_length = ACL_BUFFER_SIZE; ULONG* default_length_ptr = &default_length; @@ -169,52 +138,29 @@ bool GRANT_privileges( thread_db* tdbb, SSHORT phase, DeferredWork* work, } /* start the acl off by giving the owner all privileges */ - Firebird::UCharBuffer str_buffer; - Firebird::UCharBuffer str_default_buffer; + Acl acl, default_acl; - UCHAR* acl = str_buffer.getBuffer(ACL_BUFFER_SIZE); - str_default_buffer.getBuffer(ACL_BUFFER_SIZE); - - CHECK_AND_MOVE(acl, ACL_version, str_buffer, length_ptr); - grant_user(&acl, - owner, - obj_user, - ((work->dfw_id == obj_procedure) ? - (SCL_execute | OWNER_PRIVS) : OWNER_PRIVS), - str_buffer, - length_ptr); + CHECK_AND_MOVE(acl, ACL_version); + grant_user(acl, owner, obj_user, + ((work->dfw_id == obj_procedure) ? (SCL_execute | OWNER_PRIVS) : OWNER_PRIVS)); /* Pick up any relation-level privileges */ const SecurityClass::flags_t public_priv = get_public_privs(tdbb, work->dfw_name.c_str(), work->dfw_id); - get_user_privs(tdbb, &acl, work->dfw_name.c_str(), work->dfw_id, - owner, public_priv, str_buffer, length_ptr); + get_user_privs(tdbb, acl, work->dfw_name.c_str(), work->dfw_id, owner, public_priv); if (work->dfw_id == obj_relation) { - /* If we have the space to copy the acl list - no need to realloc */ - if (length > default_length) { - str_default_buffer.getBuffer(length); - default_length = length; - } /* Now handle field-level privileges. This might require adding UPDATE privilege to the relation-level acl, Therefore, save off the relation acl because we need to add a default field acl in that case. */ - memcpy(str_default_buffer.begin(), str_buffer.begin(), - (int) (acl - str_buffer.begin())); - UCHAR* default_acl = - str_default_buffer.begin() + (acl - str_buffer.begin()); - const UCHAR* const temp_acl = acl; + default_acl.assign(acl); const SecurityClass::flags_t aggregate_public = - save_field_privileges(tdbb, str_buffer, - &acl, work->dfw_name.c_str(), - owner, public_priv, - length_ptr); + save_field_privileges(tdbb, acl, work->dfw_name.c_str(), owner, public_priv); /* SQL tables don't need the 'all priviliges to all views' acl anymore. This special acl was only generated for SQL. */ @@ -224,15 +170,11 @@ bool GRANT_privileges( thread_db* tdbb, SSHORT phase, DeferredWork* work, /* finish off and store the security class for the relation */ - finish_security_class(&acl, aggregate_public, str_buffer, - length_ptr); + finish_security_class(acl, aggregate_public); - save_security_class(tdbb, - s_class, - str_buffer.begin(), - (USHORT)(acl - str_buffer.begin())); + save_security_class(tdbb, s_class, acl); - if (temp_acl != acl) /* relation privs were added? */ + if (acl.getCount() != default_acl.getCount()) /* relation privs were added? */ restrct = true; /* if there have been privileges added at the relation level which @@ -241,21 +183,13 @@ bool GRANT_privileges( thread_db* tdbb, SSHORT phase, DeferredWork* work, if (restrct) { - finish_security_class(&default_acl, public_priv, - str_default_buffer, - default_length_ptr); - define_default_class( - tdbb, - work->dfw_name.c_str(), - default_class, - str_default_buffer.begin(), - (USHORT)(default_acl - str_default_buffer.begin())); + finish_security_class(default_acl, public_priv); + define_default_class(tdbb, work->dfw_name.c_str(), default_class, default_acl); } } else { - finish_security_class(&acl, public_priv, str_buffer, length_ptr); - save_security_class(tdbb, s_class, str_buffer.begin(), - (USHORT)(acl - str_buffer.begin())); + finish_security_class(acl, public_priv); + save_security_class(tdbb, s_class, acl); } break; @@ -276,7 +210,7 @@ static void define_default_class( thread_db* tdbb, const TEXT* relation_name, Firebird::MetaName& default_class, - const UCHAR* buffer, USHORT length) + const Acl& acl) { /************************************** * @@ -323,7 +257,7 @@ static void define_default_class( REQUEST(irq_grant7) = request; } - save_security_class(tdbb, default_class, buffer, length); + save_security_class(tdbb, default_class, acl); dsc desc; desc.dsc_dtype = dtype_text; @@ -365,10 +299,7 @@ static void delete_security_class( thread_db* tdbb, const TEXT* s_class) #endif // NOT_USED_OR_REPLACED -static void finish_security_class(UCHAR** acl_ptr, - SecurityClass::flags_t public_priv, - Firebird::UCharBuffer& start_ptr, - ULONG* length_ptr) +static void finish_security_class(Acl& acl, SecurityClass::flags_t public_priv) { /************************************** * @@ -381,16 +312,12 @@ static void finish_security_class(UCHAR** acl_ptr, * in a wildcard for any public privileges. * **************************************/ - UCHAR* acl = *acl_ptr; - if (public_priv) { - CHECK_AND_MOVE(acl, ACL_id_list, start_ptr, length_ptr); - SCL_move_priv(&acl, public_priv, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, ACL_id_list); + SCL_move_priv(public_priv, acl); } - CHECK_AND_MOVE(acl, ACL_end, start_ptr, length_ptr); - - *acl_ptr = acl; + CHECK_AND_MOVE(acl, ACL_end); } @@ -503,13 +430,11 @@ static void get_object_info(thread_db* tdbb, static void get_user_privs(thread_db* tdbb, - UCHAR** acl_ptr, + Acl& acl, const TEXT* object_name, SSHORT obj_type, const Firebird::MetaName& owner, - SecurityClass::flags_t public_priv, - Firebird::UCharBuffer& start_ptr, - ULONG* length_ptr) + SecurityClass::flags_t public_priv) { /************************************** * @@ -524,7 +449,6 @@ static void get_user_privs(thread_db* tdbb, SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); - UCHAR* acl = *acl_ptr; Firebird::MetaName user; SSHORT user_type = -2; SecurityClass::flags_t priv = 0; @@ -548,7 +472,7 @@ static void get_user_privs(thread_db* tdbb, { if (user.length()) { - grant_user(&acl, user, user_type, priv, start_ptr, length_ptr); + grant_user(acl, user, user_type, priv); } user_type = PRV.RDB$USER_TYPE; if (user_type == obj_user) @@ -568,18 +492,14 @@ static void get_user_privs(thread_db* tdbb, REQUEST(irq_grant2) = request; if (user.length()) - grant_user(&acl, user, user_type, priv, start_ptr, length_ptr); - - *acl_ptr = acl; + grant_user(acl, user, user_type, priv); } -static void grant_user(UCHAR** acl_ptr, +static void grant_user(Acl& acl, const Firebird::MetaName& user, SSHORT user_type, - SecurityClass::flags_t privs, - Firebird::UCharBuffer& start_ptr, - ULONG* length_ptr) + SecurityClass::flags_t privs) { /************************************** * @@ -591,32 +511,30 @@ static void grant_user(UCHAR** acl_ptr, * Grant privileges to a particular user. * **************************************/ - UCHAR* acl = *acl_ptr; - - CHECK_AND_MOVE(acl, ACL_id_list, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, ACL_id_list); switch (user_type) { case obj_user_group: - CHECK_AND_MOVE(acl, id_group, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, id_group); break; case obj_sql_role: - CHECK_AND_MOVE(acl, id_sql_role, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, id_sql_role); break; case obj_user: - CHECK_AND_MOVE(acl, id_person, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, id_person); break; case obj_procedure: - CHECK_AND_MOVE(acl, id_procedure, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, id_procedure); break; case obj_trigger: - CHECK_AND_MOVE(acl, id_trigger, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, id_trigger); break; case obj_view: - CHECK_AND_MOVE(acl, id_view, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, id_view); break; default: @@ -625,23 +543,18 @@ static void grant_user(UCHAR** acl_ptr, } const UCHAR length = user.length(); - CHECK_AND_MOVE(acl, length, start_ptr, length_ptr); + CHECK_AND_MOVE(acl, length); if (length) { - CHECK_ACL_BOUND(acl, start_ptr, length_ptr, length); - memcpy(acl, user.c_str(), length); - acl += length; + acl.add(reinterpret_cast(user.c_str()), length); } - SCL_move_priv(&acl, privs, start_ptr, length_ptr); - - *acl_ptr = acl; + SCL_move_priv(privs, acl); } #ifdef NOT_USED_OR_REPLACED static void grant_views( - UCHAR** acl_ptr, - SecurityClass::flags_t privs, Firebird::UCharBuffer& start_ptr, - ULONG* length_ptr) + Acl& acl, + SecurityClass::flags_t privs) { /************************************** * @@ -653,14 +566,10 @@ static void grant_views( * Grant privileges to all views. * **************************************/ - UCHAR* acl = *acl_ptr; - - CHECK_AND_MOVE(acl, ACL_id_list, start_ptr, length_ptr); - CHECK_AND_MOVE(acl, id_views, start_ptr, length_ptr); - CHECK_AND_MOVE(acl, 0, start_ptr, length_ptr); - SCL_move_priv(&acl, privs, start_ptr, length_ptr); - - *acl_ptr = acl; + CHECK_AND_MOVE(acl, ACL_id_list); + CHECK_AND_MOVE(acl, id_views); + CHECK_AND_MOVE(acl, 0); + SCL_move_priv(privs, acl); } @@ -715,12 +624,10 @@ static void purge_default_class( TEXT* object_name, SSHORT obj_type) static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, - Firebird::UCharBuffer& str_relation_buffer, - UCHAR** acl_ptr, + Acl& relation_acl, const TEXT* relation_name, const Firebird::MetaName& owner, - SecurityClass::flags_t public_priv, - ULONG* length_ptr) + SecurityClass::flags_t public_priv) { /************************************** * @@ -735,30 +642,13 @@ static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, * security class to be effective. * **************************************/ - Firebird::UCharBuffer str_field_buffer; - Firebird::UCharBuffer str_field_buffer_start; + Acl field_acl, acl_start; SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); - // initialize the field-level acl buffer to include all relation-level privs - str_field_buffer_start.getBuffer(*length_ptr - 1); - str_field_buffer.getBuffer(*length_ptr - 1); - - ULONG field_length, start_length; - field_length = start_length = *length_ptr; - ULONG* field_length_ptr = &field_length; - - memcpy(str_field_buffer.begin(), str_relation_buffer.begin(), - (int) (*acl_ptr - str_relation_buffer.begin())); - const int field_buffer_start_index = (int) (*acl_ptr - str_relation_buffer.begin()); - UCHAR* field_acl = str_field_buffer.begin() + field_buffer_start_index; - UCHAR* relation_acl = str_relation_buffer.begin() + field_buffer_start_index; - - int i; -/* remember this starting point for subsequent fields. */ - for (i = 0; field_buffer_start_index > i; - i++, str_field_buffer_start[i] = str_field_buffer[i]); + field_acl.assign(relation_acl); + acl_start.assign(field_acl); Firebird::MetaName field_name, user, s_class; SecurityClass::flags_t aggregate_public = public_priv; @@ -796,31 +686,11 @@ static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, if (user != "PUBLIC") { const SecurityClass::flags_t field_priv = - public_priv | - priv | - squeeze_acl(str_field_buffer.begin(), - &field_acl, - user, - user_type); - grant_user(&field_acl, - user, - user_type, - field_priv, - str_field_buffer, - field_length_ptr); + public_priv | priv | squeeze_acl(field_acl, user, user_type); + grant_user(field_acl, user, user_type, field_priv); const SecurityClass::flags_t relation_priv = - public_priv | - priv | - squeeze_acl(str_relation_buffer.begin(), - &relation_acl, - user, - user_type); - grant_user(&relation_acl, - user, - user_type, - relation_priv, - str_relation_buffer, - length_ptr); + public_priv | priv | squeeze_acl(relation_acl, user, user_type); + grant_user(relation_acl, user, user_type, relation_priv); } else { @@ -844,15 +714,8 @@ static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, if (field_name.length()) { aggregate_public |= field_public; - finish_security_class(&field_acl, - (field_public | public_priv), - str_field_buffer, - field_length_ptr); - save_security_class( - tdbb, - s_class, - str_field_buffer.begin(), - (USHORT)(field_acl - str_field_buffer.begin())); + finish_security_class(field_acl, (field_public | public_priv)); + save_security_class(tdbb, s_class, field_acl); } /* initialize for new field */ @@ -891,15 +754,7 @@ static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, field_public = 0; /* restart a security class at the end of the relation-level privs */ - - i = 0; - while (field_buffer_start_index > i) - { - ++i; - str_field_buffer[i] = str_field_buffer_start[i]; - } - - field_acl = str_field_buffer.begin() + field_buffer_start_index; + field_acl.assign(acl_start); } priv |= trans_sql_priv(PRV.RDB$PRIVILEGE); @@ -921,31 +776,11 @@ static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, if (user != "PUBLIC") { const SecurityClass::flags_t field_priv = - public_priv | - priv | - squeeze_acl(str_field_buffer.begin(), - &field_acl, - user, - user_type); - grant_user(&field_acl, - user, - user_type, - field_priv, - str_field_buffer, - field_length_ptr); + public_priv | priv | squeeze_acl(field_acl, user, user_type); + grant_user(field_acl, user, user_type, field_priv); const SecurityClass::flags_t relation_priv = - public_priv | - priv | - squeeze_acl(str_relation_buffer.begin(), - &relation_acl, - user, - user_type); - grant_user(&relation_acl, - user, - user_type, - relation_priv, - str_relation_buffer, - length_ptr); + public_priv | priv | squeeze_acl(relation_acl, user, user_type); + grant_user(relation_acl, user, user_type, relation_priv); } else { @@ -958,14 +793,8 @@ static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, if (field_name.length()) { aggregate_public |= field_public; - finish_security_class(&field_acl, - (field_public | public_priv), - str_field_buffer, - field_length_ptr); - save_security_class(tdbb, - s_class, - str_field_buffer.begin(), - (USHORT)(field_acl - str_field_buffer.begin())); + finish_security_class(field_acl, (field_public | public_priv)); + save_security_class(tdbb, s_class, field_acl); dsc desc; desc.dsc_dtype = dtype_text; @@ -977,16 +806,13 @@ static SecurityClass::flags_t save_field_privileges(thread_db* tdbb, DFW_post_system_work(tdbb, dfw_update_format, &desc, 0); } - *acl_ptr = relation_acl; - return aggregate_public; } static void save_security_class(thread_db* tdbb, const Firebird::MetaName& s_class, - const UCHAR* buffer, - USHORT length) + const Acl& acl) { /************************************** * @@ -1003,7 +829,15 @@ static void save_security_class(thread_db* tdbb, bid blob_id; blb* blob = BLB_create(tdbb, dbb->dbb_sys_trans, &blob_id); - BLB_put_segment(tdbb, blob, buffer, length); + size_t length = acl.getCount(); + const UCHAR *buffer = acl.begin(); + while (length) + { + size_t step = length > ACL_BLOB_BUFFER_SIZE ? ACL_BLOB_BUFFER_SIZE : length; + BLB_put_segment(tdbb, blob, buffer, static_cast(step)); + length -= step; + buffer += step; + } BLB_close(tdbb, blob); jrd_req* request = CMP_find_request(tdbb, irq_grant3, IRQ_REQUESTS); @@ -1078,8 +912,7 @@ static SecurityClass::flags_t trans_sql_priv(const TEXT* privileges) } -static SecurityClass::flags_t squeeze_acl(UCHAR* acl_base, - UCHAR** acl_ptr, +static SecurityClass::flags_t squeeze_acl(Acl& acl, const Firebird::MetaName& user, SSHORT user_type) { @@ -1101,53 +934,54 @@ static SecurityClass::flags_t squeeze_acl(UCHAR* acl_base, UCHAR c; /* Make sure that this half-finished acl looks good enough to process. */ - **acl_ptr = 0; - UCHAR* acl = acl_base; + acl.push(0); - if (*acl++ != ACL_version) + UCHAR* a = acl.begin(); + + if (*a++ != ACL_version) BUGCHECK(160); /* msg 160 wrong ACL version */ bool hit = false; - while ( (c = *acl++) ) + while ( (c = *a++) ) switch (c) { case ACL_id_list: - dup_acl = acl - 1; + dup_acl = a - 1; hit = true; - while ( (c = *acl++) ) { + while ( (c = *a++) ) { switch (c) { case id_person: if (user_type != obj_user) hit = false; - if (check_string(acl, user)) + if (check_string(a, user)) hit = false; break; case id_sql_role: if (user_type != obj_sql_role) hit = false; - if (check_string(acl, user)) + if (check_string(a, user)) hit = false; break; case id_view: if (user_type != obj_view) hit = false; - if (check_string(acl, user)) + if (check_string(a, user)) hit = false; break; case id_procedure: if (user_type != obj_procedure) hit = false; - if (check_string(acl, user)) + if (check_string(a, user)) hit = false; break; case id_trigger: if (user_type != obj_trigger) hit = false; - if (check_string(acl, user)) + if (check_string(a, user)) hit = false; break; @@ -1156,7 +990,7 @@ static SecurityClass::flags_t squeeze_acl(UCHAR* acl_base, hit = false; // CVC: What's the idea of calling a function whose only // result is boolean without checking it? - check_string(acl, user); + check_string(a, user); break; case id_views: @@ -1168,27 +1002,27 @@ static SecurityClass::flags_t squeeze_acl(UCHAR* acl_base, { hit = false; // Seems strange with the same increment just after the switch. - acl += *acl + 1; + a += *a + 1; } break; case id_group: if (user_type != obj_user_group) hit = false; - if (check_string(acl, user)) + if (check_string(a, user)) hit = false; break; default: BUGCHECK(293); /* bad ACL */ } - acl += *acl + 1; + a += *a + 1; } break; case ACL_priv_list: if (hit) { - while ( (c = *acl++) ) + while ( (c = *a++) ) switch (c) { case priv_control: privilege |= SCL_control; @@ -1238,21 +1072,20 @@ static SecurityClass::flags_t squeeze_acl(UCHAR* acl_base, BUGCHECK(293); /* bad ACL */ } /* Squeeze out duplicate acl element. */ - UCHAR* dest = dup_acl; - const UCHAR* source = acl; - int length = *acl_ptr - source + 1; // ptrdiff_t - *acl_ptr = *acl_ptr - (source - dest); - acl = dup_acl; - for (; length; *dest++ = *source++, length--); + acl.remove(dup_acl, a); + a = dup_acl; } else - while (*acl++); + while (*a++); break; default: BUGCHECK(293); /* bad ACL */ } + // remove added extra '\0' byte + acl.pop(); + return privilege; } diff --git a/src/jrd/grant_proto.h b/src/jrd/grant_proto.h index 9d6ed2b17f..77cae95897 100644 --- a/src/jrd/grant_proto.h +++ b/src/jrd/grant_proto.h @@ -29,7 +29,6 @@ class Jrd::DeferredWork; bool GRANT_privileges(Jrd::thread_db*, SSHORT, Jrd::DeferredWork*, Jrd::jrd_tra*); -void GRANT_realloc_acl(Firebird::UCharBuffer&, UCHAR**, ULONG *); #endif // JRD_GRANT_PROTO_H diff --git a/src/jrd/scl.epp b/src/jrd/scl.epp index 540fec6183..b0a36d9e8d 100644 --- a/src/jrd/scl.epp +++ b/src/jrd/scl.epp @@ -67,28 +67,22 @@ const int UIC_BASE = 10; -const SLONG BLOB_BUFFER_SIZE = 4096; /* used to read in acl blob */ - using namespace Jrd; DATABASE DB = FILENAME "ODS.RDB"; static bool check_hex(const UCHAR*, USHORT); static bool check_number(const UCHAR*, USHORT); -static bool check_user_group(const UCHAR*, USHORT, const ULONG); +static bool check_user_group(const UCHAR*, USHORT); static bool check_string(const UCHAR*, const Firebird::MetaName&); static SecurityClass::flags_t compute_access(thread_db*, const SecurityClass*, const jrd_rel*, const Firebird::MetaName&, const Firebird::MetaName&); -static SecurityClass::flags_t walk_acl(thread_db*, const UCHAR*, const jrd_rel*, - const Firebird::MetaName&, const Firebird::MetaName&, const ULONG); +static SecurityClass::flags_t walk_acl(thread_db*, const Acl&, const jrd_rel*, + const Firebird::MetaName&, const Firebird::MetaName&); -static inline void check_and_move(UCHAR*& to, UCHAR from, Firebird::UCharBuffer& start, ULONG* length_ptr) +static inline void check_and_move(UCHAR from, Acl& to) { - if ((start.begin() + *length_ptr) < (to + 1)) - { - GRANT_realloc_acl(start, &to, length_ptr); - } - *to++ = from; + to.push(from); } struct P_NAMES { @@ -768,8 +762,7 @@ void SCL_init(bool create, } -void SCL_move_priv(UCHAR** acl_ptr, SecurityClass::flags_t mask, - Firebird::UCharBuffer& start_ptr, ULONG* length_ptr) +void SCL_move_priv(SecurityClass::flags_t mask, Acl& acl) { /************************************** * @@ -781,25 +774,21 @@ void SCL_move_priv(UCHAR** acl_ptr, SecurityClass::flags_t mask, * Given a mask of privileges, move privileges types to acl. * **************************************/ - UCHAR* p = *acl_ptr; - // Terminate identification criteria, and move privileges - check_and_move(p, ACL_end, start_ptr, length_ptr); - check_and_move(p, ACL_priv_list, start_ptr, length_ptr); + check_and_move(ACL_end, acl); + check_and_move(ACL_priv_list, acl); for (const P_NAMES* priv = p_names; priv->p_names_priv; priv++) { if (mask & priv->p_names_priv) { fb_assert(priv->p_names_acl <= MAX_UCHAR); - check_and_move(p, priv->p_names_acl, start_ptr, length_ptr); + check_and_move(priv->p_names_acl, acl); } } - check_and_move(p, 0, start_ptr, length_ptr); - - *acl_ptr = p; + check_and_move(0, acl); } @@ -934,8 +923,7 @@ static bool check_number(const UCHAR* acl, USHORT number) static bool check_user_group(const UCHAR* acl, - USHORT number, - const ULONG length) + USHORT number) { /************************************** * @@ -975,19 +963,14 @@ static bool check_user_group(const UCHAR* acl, } else // processing group name { - Firebird::UCharBuffer buffer; - fb_assert(l < length); // Not sure how we can guarantee this. - UCHAR* user_group_name = buffer.getBuffer(length); + Firebird::string user_group_name; do { const TEXT one_char = *acl++; - *user_group_name++ = LOWWER(one_char); + user_group_name += LOWWER(one_char); } while (--l); - *user_group_name = '\0'; - user_group_name = buffer.begin(); // convert unix group name to unix group id - - n = ISC_get_user_group_id(reinterpret_cast(user_group_name)); + n = ISC_get_user_group_id(user_group_name.c_str()); } } @@ -1035,10 +1018,7 @@ static SecurityClass::flags_t compute_access(thread_db* tdbb, * access permissions. Return a flag word of recognized privileges. * **************************************/ - Firebird::UCharBuffer str_buffer; - UCHAR* buffer = str_buffer.getBuffer(BLOB_BUFFER_SIZE); - - SLONG length = BLOB_BUFFER_SIZE; + Acl acl; SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); @@ -1055,13 +1035,11 @@ static SecurityClass::flags_t compute_access(thread_db* tdbb, privileges |= SCL_exists; blb* blob = BLB_open(tdbb, dbb->dbb_sys_trans, &X.RDB$ACL); - UCHAR* acl = buffer; + UCHAR* buffer = acl.getBuffer(ACL_BLOB_BUFFER_SIZE); + UCHAR* end = buffer; while (true) { - acl += BLB_get_segment(tdbb, blob, acl, - (USHORT) (length - - ((acl - buffer) * - (sizeof(buffer[0]))))); + end += BLB_get_segment(tdbb, blob, end, (USHORT) (acl.getCount() - (end - buffer)) ); if (blob->blb_flags & BLB_eof) break; @@ -1069,22 +1047,21 @@ static SecurityClass::flags_t compute_access(thread_db* tdbb, if (blob->blb_fragment_size) { - const ULONG old_offset = (ULONG) (acl - buffer); - length += BLOB_BUFFER_SIZE; - buffer = str_buffer.getBuffer(length); - acl = buffer + old_offset; + const ptrdiff_t old_offset = end - buffer; + buffer = acl.getBuffer(acl.getCount() + ACL_BLOB_BUFFER_SIZE); + end = buffer + old_offset; } } BLB_close(tdbb, blob); blob = NULL; - if (acl != buffer) + acl.shrink(end - buffer); + if (acl.getCount() > 0) { privileges |= walk_acl( tdbb, - buffer, + acl, view, trg_name, - prc_name, - length); + prc_name); } END_FOR; @@ -1096,11 +1073,10 @@ static SecurityClass::flags_t compute_access(thread_db* tdbb, static SecurityClass::flags_t walk_acl(thread_db* tdbb, - const UCHAR* acl, + const Acl& acl, const jrd_rel* view, const Firebird::MetaName& trg_name, - const Firebird::MetaName& prc_name, - const ULONG length) + const Firebird::MetaName& prc_name) { /************************************** * @@ -1131,9 +1107,11 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb, user.usr_user_name = view->rel_owner_name.c_str(); } - SecurityClass::flags_t privilege = 0; - if (*acl++ != ACL_version) + SecurityClass::flags_t privilege = 0; + const UCHAR* a = acl.begin(); + + if (*a++ != ACL_version) { BUGCHECK(160); // msg 160 wrong ACL version } @@ -1147,42 +1125,40 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb, bool hit = false; UCHAR c; - while ( (c = *acl++) ) + while ( (c = *a++) ) { switch (c) { case ACL_id_list: hit = true; - while ( (c = *acl++) ) + while ( (c = *a++) ) { switch (c) { case id_person: - if (!(p = user.usr_user_name.nullStr()) || check_string(acl, p)) + if (!(p = user.usr_user_name.nullStr()) || check_string(a, p)) hit = false; break; case id_project: - if (!(p = user.usr_project_name.nullStr()) || check_string(acl, p)) + if (!(p = user.usr_project_name.nullStr()) || check_string(a, p)) hit = false; break; case id_organization: - if (!(p = user.usr_org_name.nullStr()) || check_string(acl, p)) + if (!(p = user.usr_org_name.nullStr()) || check_string(a, p)) hit = false; break; case id_group: - if (check_user_group(acl, - user.usr_group_id, - length)) + if (check_user_group(a, user.usr_group_id)) { hit = false; } break; case id_sql_role: - if (!role_name || check_string(acl, role_name)) + if (!role_name || check_string(a, role_name)) hit = false; else { @@ -1218,17 +1194,17 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb, break; case id_view: - if (!view || check_string(acl, view->rel_name)) + if (!view || check_string(a, view->rel_name)) hit = false; break; case id_procedure: - if (check_string(acl, prc_name)) + if (check_string(a, prc_name)) hit = false; break; case id_trigger: - if (check_string(acl, trg_name)) + if (check_string(a, trg_name)) { hit = false; } @@ -1247,13 +1223,13 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb, break; case id_user: - if (check_number(acl, user.usr_user_id)) { + if (check_number(a, user.usr_user_id)) { hit = false; } break; case id_node: - if (check_hex(acl, user.usr_node_id)) { + if (check_hex(a, user.usr_node_id)) { hit = false; } break; @@ -1261,13 +1237,13 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb, default: return SCL_corrupt; } - acl += *acl + 1; + a += *a + 1; } break; case ACL_priv_list: if (hit) { - while ( (c = *acl++) ) + while ( (c = *a++) ) switch (c) { case priv_control: privilege |= SCL_control; @@ -1330,7 +1306,7 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb, // -- Madhukar Thakur (May 1, 1995) } else - while (*acl++); + while (*a++); break; default: diff --git a/src/jrd/scl.h b/src/jrd/scl.h index 7c3ac9ba14..82d85ce1c3 100644 --- a/src/jrd/scl.h +++ b/src/jrd/scl.h @@ -29,6 +29,8 @@ namespace Jrd { +const size_t ACL_BLOB_BUFFER_SIZE = 4096; /* used to read/write acl blob */ + // Security class definition class SecurityClass diff --git a/src/jrd/scl_proto.h b/src/jrd/scl_proto.h index 335944f1f6..0ce1091dcc 100644 --- a/src/jrd/scl_proto.h +++ b/src/jrd/scl_proto.h @@ -66,9 +66,14 @@ void SCL_check_relation(const dsc*, Jrd::SecurityClass::flags_t); 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_all(Jrd::SecurityClassList*&); +namespace Jrd { +typedef Firebird::Array Acl; +} +void SCL_move_priv(Jrd::SecurityClass::flags_t, Jrd::Acl&); + + #endif // JRD_SCL_PROTO_H