static ISC_STATUS merge_setup(const UCHAR** in, UCHAR** out, const UCHAR* const end, USHORT delta_length) { /************************************** * * m e r g e _ s e t u p * ************************************** * * Functional description * Get ready to toss new stuff onto an info packet. This involves * picking up and bumping the "count" field and copying what is * already there. * **************************************/ USHORT length = (USHORT) gds__vax_integer(*in, 2); const USHORT new_length = length + delta_length; if (*out + new_length + 2 >= end) { (*out)[-1] = isc_info_truncated; return FB_FAILURE; } *in += 2; const USHORT count = 1 + *(*in)++; PUT_WORD(*out, new_length); PUT(*out, (UCHAR) count); // Copy data portion of information sans original count if (--length) { memcpy(*out, *in, length); *out += length; *in += length; } return FB_SUCCESS; }
USHORT MERGE_database_info(const UCHAR* in, UCHAR* out, USHORT out_length, USHORT impl, USHORT class_, USHORT base_level, const UCHAR* version, const UCHAR* id) //ULONG mask Was always zero { /************************************** * * M E R G E _ d a t a b a s e _ i n f o * ************************************** * * Functional description * Merge server / remote interface / Y-valve information into * database block. Return the actual length of the packet. * See also jrd/utl.cpp for decoding of this block. * **************************************/ SSHORT l; const UCHAR* p; UCHAR* start = out; const UCHAR* const end = out + out_length; UCHAR mergeLevel = 0; for (const UCHAR* getMergeLevel = in; *getMergeLevel != isc_info_end && *getMergeLevel != isc_info_truncated; getMergeLevel += (3 + gds__vax_integer(getMergeLevel + 1, 2))) { if (*getMergeLevel == isc_info_implementation) { mergeLevel = getMergeLevel[3]; break; } } for (;;) switch (*out++ = *in++) { case isc_info_end: case isc_info_truncated: return out - start; case isc_info_firebird_version: l = strlen((char *) (p = version)); if (l > MAX_UCHAR) l = MAX_UCHAR; if (merge_setup(&in, &out, end, l + 1)) return 0; for (*out++ = (UCHAR) l; l; --l) *out++ = *p++; break; case isc_info_db_id: l = strlen((SCHAR *) (p = id)); if (l > MAX_UCHAR) l = MAX_UCHAR; if (merge_setup(&in, &out, end, l + 1)) return 0; for (*out++ = (UCHAR) l; l; --l) *out++ = *p++; break; case isc_info_implementation: if (merge_setup(&in, &out, end, 2)) return 0; PUT(out, (UCHAR) impl); PUT(out, (UCHAR) class_); break; case fb_info_implementation: if (merge_setup(&in, &out, end, 6)) return 0; Firebird::DbImplementation::current.stuff(&out); PUT(out, (UCHAR) class_); PUT(out, mergeLevel); break; case isc_info_base_level: if (merge_setup(&in, &out, end, 1)) return 0; PUT(out, (UCHAR) base_level); break; default: { USHORT length = (USHORT) gds__vax_integer(in, 2); in += 2; if (out + length + 2 >= end) { out[-1] = isc_info_truncated; return 0; } PUT_WORD(out, length); while (length--) *out++ = *in++; } break; } }
static tdr* get_description(ISC_QUAD* blob_id) { TEXT buffer[1024]; TEXT* bigger_buffer = 0; AliceGlobals* tdgbl = AliceGlobals::getSpecific(); const TEXT* p = buffer; const USHORT length = snarf_blob(blob_id, (USHORT) sizeof(buffer), buffer); if (length) { p = bigger_buffer = (TEXT *) gds__alloc((SLONG) length); if (!p) { tdgbl->status[0] = isc_arg_gds; tdgbl->status[1] = isc_virmemexh; tdgbl->status[2] = isc_arg_end; ALICE_print_status(true, tdgbl->status); return NULL; } snarf_blob(blob_id, length, bigger_buffer); } tdr* trans = NULL; alice_str* host_site = NULL; alice_str* database_path = NULL; // skip version number ++p; tdr* ptr = NULL; // silence uninitialized warning SLONG id_length, id; while (*p) { switch (*p++) { case TDR_HOST_SITE: host_site = alloc_string(&p); break; case TDR_DATABASE_PATH: database_path = alloc_string(&p); break; case TDR_TRANSACTION_ID: id_length = *p++; id = gds__vax_integer(reinterpret_cast<const UCHAR*>(p), id_length); p += id_length; if (!trans) { trans = ptr = FB_NEW(*tdgbl->getDefaultPool()) tdr; } else { ptr->tdr_next = FB_NEW(*tdgbl->getDefaultPool()) tdr; ptr = ptr->tdr_next; } ptr->tdr_host_site = host_site; ptr->tdr_fullpath = database_path; parse_fullpath(ptr); ptr->tdr_id = id; database_path = NULL; break; default: ALICE_print(108); // msg 108: Transaction description item unknown. if (length) { gds__free(bigger_buffer); } return NULL; } } if (length) { gds__free(bigger_buffer); } return trans; }
bool checkCreateDatabaseGrant(const MetaName& userName, const MetaName& trustedRole, const MetaName& sqlRole, const char* securityDb) { if (userName == SYSDBA_USER_NAME) return true; RefPtr<IAttachment> att; RefPtr<ITransaction> tra; if (!openDb(securityDb, att, tra)) return false; FbLocalStatus st; MetaName role(sqlRole); if (role.hasData()) { const UCHAR info[] = { isc_info_db_sql_dialect, isc_info_end }; UCHAR buffer[BUFFER_TINY]; att->getInfo(&st, sizeof(info), info, sizeof(buffer), buffer); check("IAttachment::getInfo", &st); int dialect = SQL_DIALECT_V5; // reasonable default const UCHAR* p = buffer; while (*p != isc_info_end && *p != isc_info_truncated && p < buffer + sizeof(buffer)) { const UCHAR item = (UCHAR) *p++; const USHORT length = gds__vax_integer(p, sizeof(USHORT)); p += sizeof(USHORT); switch (item) { case isc_info_db_sql_dialect: dialect = gds__vax_integer(p, length); break; } p += length; } JRD_make_role_name(role, dialect); // We need to check is admin role granted to userName in security DB const char* sql = "select count(*) from RDB$USER_PRIVILEGES " "where RDB$USER = ? and RDB$RELATION_NAME = ? and RDB$PRIVILEGE = 'M'"; Message prm; Field<Varying> u(prm, MAX_SQL_IDENTIFIER_LEN); Field<Varying> r(prm, MAX_SQL_IDENTIFIER_LEN); u = userName.c_str(); r = role.c_str(); Message result; Field<ISC_INT64> cnt(result); att->execute(&st, tra, 0, sql, SQL_DIALECT_V6, prm.getMetadata(), prm.getBuffer(), result.getMetadata(), result.getBuffer()); if (st->getState() & IStatus::STATE_ERRORS) { // isc_dsql_relation_err when exec SQL - i.e. table RDB$USER_PRIVILEGES // is missing due to non-FB security DB if (!fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err)) check("IAttachment::execute", &st); role = ""; } else if (cnt == 0) role = ""; } else role = trustedRole; if (role == ADMIN_ROLE) return true; Message gr; Field<ISC_SHORT> uType(gr); Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN); Field<ISC_SHORT> rType(gr); Field<Varying> r(gr, MAX_SQL_IDENTIFIER_LEN); uType = obj_user; u = userName.c_str(); rType = role.hasData() ? obj_sql_role : 255; r = role.c_str(); Message result; Field<ISC_INT64> cnt(result); att->execute(&st, tra, 0, "select count(*) from RDB$DB_CREATORS" " where (RDB$USER_TYPE = ? and RDB$USER = ?) or (RDB$USER_TYPE = ? and RDB$USER = ?)", SQL_DIALECT_V6, gr.getMetadata(), gr.getBuffer(), result.getMetadata(), result.getBuffer()); if (st->getState() & IStatus::STATE_ERRORS) { if (fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err)) { // isc_dsql_relation_err when exec SQL - i.e. table RDB$DB_CREATORS // is missing due to non-FB3 security DB return false; } check("IAttachment::execute", &st); } return cnt > 0; }
bool checkCreateDatabaseGrant(const MetaName& userName, const MetaName& trustedRole, const MetaName& sqlRole, const char* securityDb) { if (userName == DBA_USER_NAME) return true; RefPtr<IAttachment> att; RefPtr<ITransaction> tra; bool hasDb = openDb(securityDb, att, tra); FbLocalStatus st; MetaName role(sqlRole); if (hasDb && role.hasData()) { const UCHAR info[] = { isc_info_db_sql_dialect, isc_info_end }; UCHAR buffer[BUFFER_TINY]; att->getInfo(&st, sizeof(info), info, sizeof(buffer), buffer); check("IAttachment::getInfo", &st); int dialect = SQL_DIALECT_V5; // reasonable default const UCHAR* p = buffer; while (*p != isc_info_end && *p != isc_info_truncated && p < buffer + sizeof(buffer)) { const UCHAR item = (UCHAR) *p++; const USHORT length = gds__vax_integer(p, sizeof(USHORT)); p += sizeof(USHORT); switch (item) { case isc_info_db_sql_dialect: dialect = gds__vax_integer(p, length); break; } p += length; } UserId::makeRoleName(role, dialect); // We need to check is role granted to userName in security DB const char* sql = "select count(*) from RDB$USER_PRIVILEGES " "where RDB$USER = ? and RDB$RELATION_NAME = ? and RDB$PRIVILEGE = 'M'"; Message prm; Field<Varying> u(prm, MAX_SQL_IDENTIFIER_LEN); Field<Varying> r(prm, MAX_SQL_IDENTIFIER_LEN); u = userName.c_str(); r = role.c_str(); Message result; Field<ISC_INT64> cnt(result); att->execute(&st, tra, 0, sql, SQL_DIALECT_V6, prm.getMetadata(), prm.getBuffer(), result.getMetadata(), result.getBuffer()); if (st->getState() & IStatus::STATE_ERRORS) { // isc_dsql_relation_err when exec SQL - i.e. table RDB$USER_PRIVILEGES // is missing due to non-FB security DB if (!fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err)) check("IAttachment::execute", &st); role = ""; } else if (cnt == 0) role = ""; } else role = trustedRole; if (role == ADMIN_ROLE) return true; if (!hasDb) return false; // check db creators table Message gr; Field<ISC_SHORT> uType(gr); Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN); Field<ISC_SHORT> rType(gr); Field<Varying> r(gr, MAX_SQL_IDENTIFIER_LEN); uType = obj_user; u = userName.c_str(); rType = role.hasData() ? obj_sql_role : 255; r = role.c_str(); Message result; Field<ISC_INT64> cnt(result); att->execute(&st, tra, 0, "select count(*) from RDB$DB_CREATORS" " where (RDB$USER_TYPE = ? and RDB$USER = ?) or (RDB$USER_TYPE = ? and RDB$USER = ?)", SQL_DIALECT_V6, gr.getMetadata(), gr.getBuffer(), result.getMetadata(), result.getBuffer()); if (st->getState() & IStatus::STATE_ERRORS) { if (fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err)) { // isc_dsql_relation_err when exec SQL - i.e. table RDB$DB_CREATORS // is missing due to non-FB3 security DB return false; } check("IAttachment::execute", &st); } if (cnt > 0) return true; if (!role.hasData()) role = "NONE"; Message par2; Field<ISC_SHORT> uType2(par2); Field<Varying> u2(par2, MAX_SQL_IDENTIFIER_LEN); Field<Varying> r2(par2, MAX_SQL_IDENTIFIER_LEN); uType2 = obj_user; u2 = userName.c_str(); r2 = role.c_str(); Message res2; Field<Text> priv(res2, 8); const char* sql = "with recursive role_tree as ( " " select rdb$relation_name as nm, 0 as ur from rdb$user_privileges " " where rdb$privilege = 'M' and rdb$field_name = 'D' and rdb$user_type = ? and rdb$user = ? " " union all " " select rdb$role_name as nm, 1 as ur from rdb$roles " " where rdb$role_name = ? " " union all " " select p.rdb$relation_name as nm, t.ur from rdb$user_privileges p " " join role_tree t on t.nm = p.rdb$user " " where p.rdb$privilege = 'M' and (p.rdb$field_name = 'D' or t.ur = 1)) " "select r.rdb$system_privileges " " from role_tree t join rdb$roles r on t.nm = r.rdb$role_name "; RefPtr<IResultSet> rs(REF_NO_INCR, att->openCursor(&st, tra, 0, sql, SQL_DIALECT_V6, par2.getMetadata(), par2.getBuffer(), res2.getMetadata(), NULL, 0)); check("IAttachment::execute", &st); UserId::Privileges privileges, wrk; while (rs->fetchNext(&st, res2.getBuffer()) == IStatus::RESULT_OK) { wrk.load(&priv); privileges |= wrk; } check("IResultSet::fetchNext", &st); return wrk.test(CREATE_DATABASE); }
SLONG API_ROUTINE isc_vax_integer(const SCHAR* input, SSHORT length) { return gds__vax_integer(reinterpret_cast<const UCHAR*>(input), length); }
bool getBlobSize( const UserBlob& b, SLONG* size, SLONG* seg_count, SLONG* max_seg) { /************************************** * * g e t B l o b S i z e * ************************************** * * Functional description * Get the size, number of segments, and max * segment length of a blob. Return true * if it happens to succeed. * This is a clone of gds__blob_size. * **************************************/ static const UCHAR blob_items[] = { isc_info_blob_max_segment, isc_info_blob_num_segments, isc_info_blob_total_length }; UCHAR buffer[64]; if (!b.getInfo(sizeof(blob_items), blob_items, sizeof(buffer), buffer)) return false; const UCHAR* p = buffer; const UCHAR* const end = buffer + sizeof(buffer); for (UCHAR item = *p++; item != isc_info_end && p < end; item = *p++) { const USHORT l = gds__vax_integer(p, 2); p += 2; const SLONG n = gds__vax_integer(p, l); p += l; switch (item) { case isc_info_blob_max_segment: if (max_seg) *max_seg = n; break; case isc_info_blob_num_segments: if (seg_count) *seg_count = n; break; case isc_info_blob_total_length: if (size) *size = n; break; default: return false; } } return true; }