Exemple #1
0
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;
}
Exemple #2
0
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;
		}
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
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);
}
Exemple #6
0
SLONG API_ROUTINE isc_vax_integer(const SCHAR* input, SSHORT length)
{
	return gds__vax_integer(reinterpret_cast<const UCHAR*>(input), length);
}
Exemple #7
0
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;
}