mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03:02 +01:00
Implemented CORE-4538: Access rights for CREATE DATABASE operator
This commit is contained in:
parent
45a5d66a32
commit
2a293c2691
@ -17,7 +17,7 @@ REVOKE [GRANT OPTION FOR] DROP ANY <OBJECT> FROM [USER | ROLE] <user/role name>;
|
|||||||
|
|
||||||
Where <OBJECT> could be:
|
Where <OBJECT> could be:
|
||||||
TABLE, VIEW, PROCEDURE, FUNCTION, PACKAGE, GENERATOR, SEQUENCE, DOMAIN,
|
TABLE, VIEW, PROCEDURE, FUNCTION, PACKAGE, GENERATOR, SEQUENCE, DOMAIN,
|
||||||
EXCEPTION, ROLE, DATABASE, CHARACTER SET, COLLATION, FILTER
|
EXCEPTION, ROLE, CHARACTER SET, COLLATION, FILTER
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
|
|
||||||
@ -33,3 +33,13 @@ Sample:
|
|||||||
GRANT CREATE TABLE TO Joe;
|
GRANT CREATE TABLE TO Joe;
|
||||||
GRANT ALTER ANY TABLE TO Joe;
|
GRANT ALTER ANY TABLE TO Joe;
|
||||||
REVOKE CREATE TABLE FROM Joe;
|
REVOKE CREATE TABLE FROM Joe;
|
||||||
|
|
||||||
|
For database access special form is supported:
|
||||||
|
|
||||||
|
GRANT CREATE DATABASE TO [USER | ROLE] <user/role name>;
|
||||||
|
GRANT ALTER DATABASE TO [USER | ROLE] <user/role name> [WITH GRANT OPTION];
|
||||||
|
GRANT DROP DATABASE TO [USER | ROLE] <user/role name> [WITH GRANT OPTION];
|
||||||
|
|
||||||
|
REVOKE CREATE DATABASE FROM [USER | ROLE] <user/role name>;
|
||||||
|
REVOKE [GRANT OPTION FOR] ALTER DATABASE FROM [USER | ROLE] <user/role name>;
|
||||||
|
REVOKE [GRANT OPTION FOR] DROP DATABASE FROM [USER | ROLE] <user/role name>;
|
||||||
|
@ -1604,6 +1604,12 @@ C --
|
|||||||
PARAMETER (GDS__dsql_cant_grant_option = 335545095)
|
PARAMETER (GDS__dsql_cant_grant_option = 335545095)
|
||||||
INTEGER*4 GDS__read_conflict
|
INTEGER*4 GDS__read_conflict
|
||||||
PARAMETER (GDS__read_conflict = 335545096)
|
PARAMETER (GDS__read_conflict = 335545096)
|
||||||
|
INTEGER*4 GDS__crdb_load
|
||||||
|
PARAMETER (GDS__crdb_load = 335545097)
|
||||||
|
INTEGER*4 GDS__crdb_nodb
|
||||||
|
PARAMETER (GDS__crdb_nodb = 335545098)
|
||||||
|
INTEGER*4 GDS__crdb_notable
|
||||||
|
PARAMETER (GDS__crdb_notable = 335545099)
|
||||||
INTEGER*4 GDS__gfix_db_name
|
INTEGER*4 GDS__gfix_db_name
|
||||||
PARAMETER (GDS__gfix_db_name = 335740929)
|
PARAMETER (GDS__gfix_db_name = 335740929)
|
||||||
INTEGER*4 GDS__gfix_invalid_sw
|
INTEGER*4 GDS__gfix_invalid_sw
|
||||||
|
@ -809,6 +809,9 @@ const
|
|||||||
gds_dyn_no_priv = 335545094;
|
gds_dyn_no_priv = 335545094;
|
||||||
gds_dsql_cant_grant_option = 335545095;
|
gds_dsql_cant_grant_option = 335545095;
|
||||||
gds_read_conflict = 335545096;
|
gds_read_conflict = 335545096;
|
||||||
|
gds_crdb_load = 335545097;
|
||||||
|
gds_crdb_nodb = 335545098;
|
||||||
|
gds_crdb_notable = 335545099;
|
||||||
gds_gfix_db_name = 335740929;
|
gds_gfix_db_name = 335740929;
|
||||||
gds_gfix_invalid_sw = 335740930;
|
gds_gfix_invalid_sw = 335740930;
|
||||||
gds_gfix_incmp_sw = 335740932;
|
gds_gfix_incmp_sw = 335740932;
|
||||||
|
@ -113,6 +113,60 @@ static const char* const CHECK_CONSTRAINT_EXCEPTION = "check_constraint";
|
|||||||
DATABASE DB = STATIC "ODS.RDB";
|
DATABASE DB = STATIC "ODS.RDB";
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------
|
||||||
|
|
||||||
|
void ExecInSecurityDb::executeInSecurityDb(jrd_tra* localTransaction)
|
||||||
|
{
|
||||||
|
LocalStatus st;
|
||||||
|
|
||||||
|
SecDbContext* secDbContext = localTransaction->getSecDbContext();
|
||||||
|
if (!secDbContext)
|
||||||
|
{
|
||||||
|
Attachment* lAtt = localTransaction->getAttachment();
|
||||||
|
const char* secDb = lAtt->att_database->dbb_config->getSecurityDatabase();
|
||||||
|
ClumpletWriter dpb(ClumpletWriter::WideTagged, MAX_DPB_SIZE, isc_dpb_version2);
|
||||||
|
if (lAtt->att_user)
|
||||||
|
lAtt->att_user->populateDpb(dpb);
|
||||||
|
IAttachment* att = DispatcherPtr()->attachDatabase(&st, secDb,
|
||||||
|
dpb.getBufferLength(), dpb.getBuffer());
|
||||||
|
check(&st);
|
||||||
|
|
||||||
|
ITransaction* tra = att->startTransaction(&st, 0, NULL);
|
||||||
|
check(&st);
|
||||||
|
|
||||||
|
secDbContext = localTransaction->setSecDbContext(att, tra);
|
||||||
|
}
|
||||||
|
|
||||||
|
// run all statements under savepoint control
|
||||||
|
string savePoint;
|
||||||
|
savePoint.printf("ExecInSecurityDb%d", secDbContext->savePoint++);
|
||||||
|
secDbContext->att->execute(&st, secDbContext->tra, 0, ("SAVEPOINT " + savePoint).c_str(),
|
||||||
|
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
|
||||||
|
check(&st);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
runInSecurityDb(secDbContext);
|
||||||
|
|
||||||
|
secDbContext->att->execute(&st, secDbContext->tra, 0, ("RELEASE SAVEPOINT " + savePoint).c_str(),
|
||||||
|
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
|
||||||
|
savePoint.erase();
|
||||||
|
check(&st);
|
||||||
|
}
|
||||||
|
catch (const Exception&)
|
||||||
|
{
|
||||||
|
if (savePoint.hasData())
|
||||||
|
{
|
||||||
|
LocalStatus tmp;
|
||||||
|
secDbContext->att->execute(&tmp, secDbContext->tra, 0, ("ROLLBACK TO SAVEPOINT " + savePoint).c_str(),
|
||||||
|
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------
|
//----------------------
|
||||||
|
|
||||||
|
|
||||||
@ -9662,44 +9716,11 @@ bool MappingNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's purpose is to add/drop mapping from any security name to DB security object.
|
void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
|
||||||
void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
|
|
||||||
{
|
{
|
||||||
if (!(tdbb->getAttachment() && tdbb->getAttachment()->locksmith()))
|
Firebird::LocalStatus st;
|
||||||
status_exception::raise(Arg::Gds(isc_adm_task_denied));
|
|
||||||
|
|
||||||
if (global)
|
|
||||||
{
|
|
||||||
LocalStatus st;
|
|
||||||
LocalStatus s2; // we will use it in DDL case and remember
|
|
||||||
IStatus* s = &st;
|
IStatus* s = &st;
|
||||||
|
|
||||||
SecDbContext* secDbContext = transaction->getSecDbContext();
|
|
||||||
if (!secDbContext)
|
|
||||||
{
|
|
||||||
const char* secDb = tdbb->getDatabase()->dbb_config->getSecurityDatabase();
|
|
||||||
ClumpletWriter dpb(ClumpletWriter::WideTagged, MAX_DPB_SIZE, isc_dpb_version2);
|
|
||||||
if (tdbb->getAttachment()->att_user)
|
|
||||||
tdbb->getAttachment()->att_user->populateDpb(dpb);
|
|
||||||
IAttachment* att = DispatcherPtr()->attachDatabase(s, secDb,
|
|
||||||
dpb.getBufferLength(), dpb.getBuffer());
|
|
||||||
check(s);
|
|
||||||
|
|
||||||
ITransaction* tra = att->startTransaction(s, 0, NULL);
|
|
||||||
check(s);
|
|
||||||
|
|
||||||
secDbContext = transaction->setSecDbContext(att, tra);
|
|
||||||
}
|
|
||||||
|
|
||||||
// run all statements under savepoint control
|
|
||||||
string savePoint;
|
|
||||||
savePoint.printf("GLOBALMAP%d", secDbContext->savePoint++);
|
|
||||||
secDbContext->att->execute(s, secDbContext->tra, 0, ("SAVEPOINT " + savePoint).c_str(),
|
|
||||||
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
|
|
||||||
check(s);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// first of all try to use regenerated DDL statement
|
// first of all try to use regenerated DDL statement
|
||||||
// that's the best way if security database is FB3 or higher fb version
|
// that's the best way if security database is FB3 or higher fb version
|
||||||
string ddl;
|
string ddl;
|
||||||
@ -9778,12 +9799,16 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now try to run DDL
|
// Now try to run DDL
|
||||||
secDbContext->att->execute(&s2, secDbContext->tra, 0, ddl.c_str(), SQL_DIALECT_V6,
|
secDbContext->att->execute(s, secDbContext->tra, 0, ddl.c_str(), SQL_DIALECT_V6,
|
||||||
NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (s2.getStatus() & IStatus::FB_HAS_ERRORS)
|
if (s->getStatus() & IStatus::FB_HAS_ERRORS)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// try direct access to rdb$auth_mapping table in secure db
|
// try direct access to rdb$auth_mapping table in secure db
|
||||||
|
LocalStatus s2;
|
||||||
|
s = &s2;
|
||||||
|
|
||||||
// check presence of such record in the table
|
// check presence of such record in the table
|
||||||
Message msgCheck;
|
Message msgCheck;
|
||||||
@ -9874,31 +9899,30 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
|
|||||||
secDbContext->att->execute(s, secDbContext->tra, 0, sql, SQL_DIALECT_V6,
|
secDbContext->att->execute(s, secDbContext->tra, 0, sql, SQL_DIALECT_V6,
|
||||||
msg->getMetadata(), msg->getBuffer(), NULL, NULL);
|
msg->getMetadata(), msg->getBuffer(), NULL, NULL);
|
||||||
check(s);
|
check(s);
|
||||||
|
|
||||||
secDbContext->att->execute(s, secDbContext->tra, 0, ("RELEASE SAVEPOINT " + savePoint).c_str(),
|
|
||||||
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
|
|
||||||
savePoint.erase();
|
|
||||||
check(s);
|
|
||||||
}
|
}
|
||||||
}
|
catch(const Exception& ex)
|
||||||
catch (const Exception&)
|
|
||||||
{
|
{
|
||||||
if (savePoint.hasData())
|
if (st.getStatus() & IStatus::FB_HAS_ERRORS)
|
||||||
{
|
{
|
||||||
secDbContext->att->execute(s, secDbContext->tra, 0, ("ROLLBACK TO SAVEPOINT " + savePoint).c_str(),
|
const ISC_STATUS* stat2 = st.getErrors();
|
||||||
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s2.getStatus() & IStatus::FB_HAS_ERRORS)
|
|
||||||
{
|
|
||||||
const ISC_STATUS* stat2 = s2.getErrors();
|
|
||||||
if (stat2[1] != isc_dsql_token_unk_err)
|
if (stat2[1] != isc_dsql_token_unk_err)
|
||||||
status_exception::raise(&s2);
|
status_exception::raise(&st);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's purpose is to add/drop mapping from any security name to DB security object.
|
||||||
|
void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
|
||||||
|
{
|
||||||
|
if (!(tdbb->getAttachment() && tdbb->getAttachment()->locksmith()))
|
||||||
|
status_exception::raise(Arg::Gds(isc_adm_task_denied));
|
||||||
|
|
||||||
|
if (global)
|
||||||
|
{
|
||||||
|
executeInSecurityDb(transaction);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10319,6 +10343,8 @@ void GrantRevokeNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
|||||||
// run all statements under savepoint control
|
// run all statements under savepoint control
|
||||||
AutoSavePoint savePoint(tdbb, transaction);
|
AutoSavePoint savePoint(tdbb, transaction);
|
||||||
|
|
||||||
|
createDbJobs.clear();
|
||||||
|
|
||||||
const GranteeClause* usersPtr;
|
const GranteeClause* usersPtr;
|
||||||
const GranteeClause* usersEnd;
|
const GranteeClause* usersEnd;
|
||||||
|
|
||||||
@ -10356,9 +10382,83 @@ void GrantRevokeNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (createDbJobs.hasData())
|
||||||
|
executeInSecurityDb(transaction);
|
||||||
|
|
||||||
savePoint.release(); // everything is ok
|
savePoint.release(); // everything is ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GrantRevokeNode::runInSecurityDb(SecDbContext* secDbContext)
|
||||||
|
{
|
||||||
|
for (unsigned n = 0; n < createDbJobs.getCount(); ++n)
|
||||||
|
{
|
||||||
|
CreateDbJob& j = createDbJobs[n];
|
||||||
|
LocalStatus st;
|
||||||
|
IStatus* s = &st;
|
||||||
|
|
||||||
|
Message gr;
|
||||||
|
Field<ISC_SHORT> uType(gr);
|
||||||
|
Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN);
|
||||||
|
uType = j.userType;
|
||||||
|
u = j.user.c_str();
|
||||||
|
|
||||||
|
Message result;
|
||||||
|
Field<ISC_INT64> cnt(result);
|
||||||
|
|
||||||
|
const char* checkSql = "select count(*) from RDB$DB_CREATORS where RDB$USER_TYPE = ? and RDB$USER = ?";
|
||||||
|
secDbContext->att->execute(s, secDbContext->tra, 0, checkSql, SQL_DIALECT_V6,
|
||||||
|
gr.getMetadata(), gr.getBuffer(), result.getMetadata(), result.getBuffer());
|
||||||
|
check(s);
|
||||||
|
|
||||||
|
if (isGrant)
|
||||||
|
{
|
||||||
|
if (!cnt)
|
||||||
|
{
|
||||||
|
const char* insertSql = "insert into RDB$DB_CREATORS(RDB$USER_TYPE, RDB$USER) values(?, ?)";
|
||||||
|
secDbContext->att->execute(s, secDbContext->tra, 0, insertSql, SQL_DIALECT_V6,
|
||||||
|
gr.getMetadata(), gr.getBuffer(), NULL, NULL);
|
||||||
|
check(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cnt)
|
||||||
|
{
|
||||||
|
const char* deleteSql = "delete from RDB$DB_CREATORS where RDB$USER_TYPE = ? and RDB$USER = ?";
|
||||||
|
secDbContext->att->execute(s, secDbContext->tra, 0, deleteSql, SQL_DIALECT_V6,
|
||||||
|
gr.getMetadata(), gr.getBuffer(), NULL, NULL);
|
||||||
|
|
||||||
|
j.grantErased = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!j.grantErased)
|
||||||
|
{
|
||||||
|
if (j.allOnAll)
|
||||||
|
{
|
||||||
|
const char* all = "ALL";
|
||||||
|
|
||||||
|
if (j.badGrantor)
|
||||||
|
{
|
||||||
|
// msg 246: @1 is not grantor of @2 on @3 to @4.
|
||||||
|
(Arg::PrivateDyn(246) << j.revoker.c_str() << all << all << j.user).raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
// msg 247: Warning: @1 on @2 is not granted to @3.
|
||||||
|
ERR_post_warning(
|
||||||
|
Arg::Warning(isc_dyn_miss_priv_warning) <<
|
||||||
|
all << all << j.user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// msg 247: Warning: @1 on @2 is not granted to @3.
|
||||||
|
ERR_post_warning(Arg::Warning(isc_dyn_miss_priv_warning) <<
|
||||||
|
privilegeName('C') << "DATABASE" << j.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GrantRevokeNode::modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SSHORT option,
|
void GrantRevokeNode::modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SSHORT option,
|
||||||
const GranteeClause* user)
|
const GranteeClause* user)
|
||||||
{
|
{
|
||||||
@ -10467,8 +10567,9 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
|||||||
if (!isGrant && !privs) // REVOKE ALL ON ALL
|
if (!isGrant && !privs) // REVOKE ALL ON ALL
|
||||||
{
|
{
|
||||||
AutoCacheRequest request(tdbb, drq_e_grant3, DYN_REQUESTS);
|
AutoCacheRequest request(tdbb, drq_e_grant3, DYN_REQUESTS);
|
||||||
bool grantErased = false;
|
CreateDbJob all(userType, user);
|
||||||
bool badGrantor = false;
|
all.allOnAll = true;
|
||||||
|
all.revoker = grantorRevoker;
|
||||||
|
|
||||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
PRIV IN RDB$USER_PRIVILEGES
|
PRIV IN RDB$USER_PRIVILEGES
|
||||||
@ -10478,29 +10579,14 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
|||||||
if (tdbb->getAttachment()->att_user->locksmith() || grantorRevoker == PRIV.RDB$GRANTOR)
|
if (tdbb->getAttachment()->att_user->locksmith() || grantorRevoker == PRIV.RDB$GRANTOR)
|
||||||
{
|
{
|
||||||
ERASE PRIV;
|
ERASE PRIV;
|
||||||
grantErased = true;
|
all.grantErased = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
badGrantor = true;
|
all.badGrantor = true;
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
const char* all = "ALL";
|
createDbJobs.push(all);
|
||||||
|
|
||||||
if (badGrantor && !grantErased)
|
|
||||||
{
|
|
||||||
// msg 246: @1 is not grantor of @2 on @3 to @4.
|
|
||||||
status_exception::raise(Arg::PrivateDyn(246) <<
|
|
||||||
grantorRevoker.c_str() << all << all << user.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!grantErased)
|
|
||||||
{
|
|
||||||
// msg 247: Warning: @1 on @2 is not granted to @3.
|
|
||||||
ERR_post_warning(
|
|
||||||
Arg::Warning(isc_dyn_miss_priv_warning) <<
|
|
||||||
all << all << Arg::Str(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -10527,6 +10613,30 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (objType == obj_database && strchr(privileges, 'C'))
|
||||||
|
{
|
||||||
|
if (options || grantor)
|
||||||
|
{
|
||||||
|
(Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) <<
|
||||||
|
"GRANT/ADMIN OPTION and GRANTED BY not supported for CREATE DATABASE grants").raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userType != obj_sql_role && userType != obj_user)
|
||||||
|
{
|
||||||
|
(Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) <<
|
||||||
|
"Only grants to USER or ROLE are supported for CREATE DATABASE").raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateDbJob job(userType, user);
|
||||||
|
createDbJobs.push(job);
|
||||||
|
|
||||||
|
char* cPtr = strchr(privileges, 'C');
|
||||||
|
size_t len = strlen(cPtr);
|
||||||
|
memmove(cPtr, cPtr + 1, len);
|
||||||
|
if (!privileges[0])
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char priv[2];
|
char priv[2];
|
||||||
priv[1] = '\0';
|
priv[1] = '\0';
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ namespace Jrd {
|
|||||||
class CompoundStmtNode;
|
class CompoundStmtNode;
|
||||||
class RelationSourceNode;
|
class RelationSourceNode;
|
||||||
class ValueListNode;
|
class ValueListNode;
|
||||||
|
class SecDbContext;
|
||||||
|
|
||||||
struct BoolSourceClause
|
struct BoolSourceClause
|
||||||
{
|
{
|
||||||
@ -135,6 +135,18 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ExecInSecurityDb
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~ExecInSecurityDb() { }
|
||||||
|
|
||||||
|
void executeInSecurityDb(jrd_tra* tra);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void runInSecurityDb(SecDbContext* secDbContext) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename CreateNode, typename DropNode, ISC_STATUS ERROR_CODE>
|
template <typename CreateNode, typename DropNode, ISC_STATUS ERROR_CODE>
|
||||||
class RecreateNode : public DdlNode
|
class RecreateNode : public DdlNode
|
||||||
{
|
{
|
||||||
@ -1802,7 +1814,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class MappingNode : public DdlNode
|
class MappingNode : public DdlNode, private ExecInSecurityDb
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum OP {MAP_ADD, MAP_MOD, MAP_RPL, MAP_DROP};
|
enum OP {MAP_ADD, MAP_MOD, MAP_RPL, MAP_DROP};
|
||||||
@ -1836,6 +1848,7 @@ protected:
|
|||||||
(op == MAP_ADD ? "CREATE" : op == MAP_MOD ?
|
(op == MAP_ADD ? "CREATE" : op == MAP_MOD ?
|
||||||
"ALTER" : op == MAP_RPL ? "CREATE OR ALTER" : "DROP");
|
"ALTER" : op == MAP_RPL ? "CREATE OR ALTER" : "DROP");
|
||||||
}
|
}
|
||||||
|
void runInSecurityDb(SecDbContext* secDbContext);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addItem(Firebird::string& ddl, const char* text);
|
void addItem(Firebird::string& ddl, const char* text);
|
||||||
@ -1974,11 +1987,12 @@ public:
|
|||||||
typedef Firebird::Pair<Firebird::NonPooled<char, ValueListNode*> > PrivilegeClause;
|
typedef Firebird::Pair<Firebird::NonPooled<char, ValueListNode*> > PrivilegeClause;
|
||||||
typedef Firebird::Pair<Firebird::NonPooled<SSHORT, Firebird::MetaName> > GranteeClause;
|
typedef Firebird::Pair<Firebird::NonPooled<SSHORT, Firebird::MetaName> > GranteeClause;
|
||||||
|
|
||||||
class GrantRevokeNode : public DdlNode
|
class GrantRevokeNode : public DdlNode, private ExecInSecurityDb
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GrantRevokeNode(MemoryPool& p, bool aIsGrant)
|
GrantRevokeNode(MemoryPool& p, bool aIsGrant)
|
||||||
: DdlNode(p),
|
: DdlNode(p),
|
||||||
|
createDbJobs(p),
|
||||||
isGrant(aIsGrant),
|
isGrant(aIsGrant),
|
||||||
privileges(p),
|
privileges(p),
|
||||||
roles(p),
|
roles(p),
|
||||||
@ -2001,6 +2015,7 @@ protected:
|
|||||||
statusVector <<
|
statusVector <<
|
||||||
Firebird::Arg::Gds(isGrant ? isc_dsql_grant_failed : isc_dsql_revoke_failed);
|
Firebird::Arg::Gds(isGrant ? isc_dsql_grant_failed : isc_dsql_revoke_failed);
|
||||||
}
|
}
|
||||||
|
void runInSecurityDb(SecDbContext* secDbContext);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SSHORT option, const GranteeClause* user);
|
void modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SSHORT option, const GranteeClause* user);
|
||||||
@ -2043,6 +2058,19 @@ private:
|
|||||||
return "<Unknown>";
|
return "<Unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CreateDbJob
|
||||||
|
{
|
||||||
|
CreateDbJob(SSHORT a_userType, const Firebird::MetaName& a_user)
|
||||||
|
: allOnAll(false), grantErased(false), badGrantor(false),
|
||||||
|
userType(a_userType), user(a_user)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool allOnAll, grantErased, badGrantor;
|
||||||
|
SSHORT userType;
|
||||||
|
Firebird::MetaName user, revoker;
|
||||||
|
};
|
||||||
|
Firebird::Array<CreateDbJob> createDbJobs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool isGrant;
|
bool isGrant;
|
||||||
Firebird::Array<PrivilegeClause> privileges;
|
Firebird::Array<PrivilegeClause> privileges;
|
||||||
|
@ -976,6 +976,7 @@ db_ddl_privilege_list($privilegeArray)
|
|||||||
|
|
||||||
%type db_ddl_privilege(<privilegeArray>)
|
%type db_ddl_privilege(<privilegeArray>)
|
||||||
db_ddl_privilege($privilegeArray)
|
db_ddl_privilege($privilegeArray)
|
||||||
|
| CREATE { $privilegeArray->add(PrivilegeClause('C', NULL)); }
|
||||||
| ALTER { $privilegeArray->add(PrivilegeClause('L', NULL)); }
|
| ALTER { $privilegeArray->add(PrivilegeClause('L', NULL)); }
|
||||||
| DROP { $privilegeArray->add(PrivilegeClause('O', NULL)); }
|
| DROP { $privilegeArray->add(PrivilegeClause('O', NULL)); }
|
||||||
;
|
;
|
||||||
|
@ -798,6 +798,9 @@ static const struct {
|
|||||||
{"dyn_no_priv", 335545094},
|
{"dyn_no_priv", 335545094},
|
||||||
{"dsql_cant_grant_option", 335545095},
|
{"dsql_cant_grant_option", 335545095},
|
||||||
{"read_conflict", 335545096},
|
{"read_conflict", 335545096},
|
||||||
|
{"crdb_load", 335545097},
|
||||||
|
{"crdb_nodb", 335545098},
|
||||||
|
{"crdb_notable", 335545099},
|
||||||
{"gfix_db_name", 335740929},
|
{"gfix_db_name", 335740929},
|
||||||
{"gfix_invalid_sw", 335740930},
|
{"gfix_invalid_sw", 335740930},
|
||||||
{"gfix_incmp_sw", 335740932},
|
{"gfix_incmp_sw", 335740932},
|
||||||
|
@ -832,6 +832,9 @@ const ISC_STATUS isc_dup_attribute = 335545093L;
|
|||||||
const ISC_STATUS isc_dyn_no_priv = 335545094L;
|
const ISC_STATUS isc_dyn_no_priv = 335545094L;
|
||||||
const ISC_STATUS isc_dsql_cant_grant_option = 335545095L;
|
const ISC_STATUS isc_dsql_cant_grant_option = 335545095L;
|
||||||
const ISC_STATUS isc_read_conflict = 335545096L;
|
const ISC_STATUS isc_read_conflict = 335545096L;
|
||||||
|
const ISC_STATUS isc_crdb_load = 335545097L;
|
||||||
|
const ISC_STATUS isc_crdb_nodb = 335545098L;
|
||||||
|
const ISC_STATUS isc_crdb_notable = 335545099L;
|
||||||
const ISC_STATUS isc_gfix_db_name = 335740929L;
|
const ISC_STATUS isc_gfix_db_name = 335740929L;
|
||||||
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
|
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
|
||||||
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
|
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
|
||||||
@ -1290,7 +1293,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
|
|||||||
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
||||||
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
||||||
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
||||||
const ISC_STATUS isc_err_max = 1234;
|
const ISC_STATUS isc_err_max = 1237;
|
||||||
|
|
||||||
#else /* c definitions */
|
#else /* c definitions */
|
||||||
|
|
||||||
@ -2092,6 +2095,9 @@ const ISC_STATUS isc_err_max = 1234;
|
|||||||
#define isc_dyn_no_priv 335545094L
|
#define isc_dyn_no_priv 335545094L
|
||||||
#define isc_dsql_cant_grant_option 335545095L
|
#define isc_dsql_cant_grant_option 335545095L
|
||||||
#define isc_read_conflict 335545096L
|
#define isc_read_conflict 335545096L
|
||||||
|
#define isc_crdb_load 335545097L
|
||||||
|
#define isc_crdb_nodb 335545098L
|
||||||
|
#define isc_crdb_notable 335545099L
|
||||||
#define isc_gfix_db_name 335740929L
|
#define isc_gfix_db_name 335740929L
|
||||||
#define isc_gfix_invalid_sw 335740930L
|
#define isc_gfix_invalid_sw 335740930L
|
||||||
#define isc_gfix_incmp_sw 335740932L
|
#define isc_gfix_incmp_sw 335740932L
|
||||||
@ -2550,7 +2556,7 @@ const ISC_STATUS isc_err_max = 1234;
|
|||||||
#define isc_trace_switch_param_miss 337182758L
|
#define isc_trace_switch_param_miss 337182758L
|
||||||
#define isc_trace_param_act_notcompat 337182759L
|
#define isc_trace_param_act_notcompat 337182759L
|
||||||
#define isc_trace_mandatory_switch_miss 337182760L
|
#define isc_trace_mandatory_switch_miss 337182760L
|
||||||
#define isc_err_max 1234
|
#define isc_err_max 1237
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -660,3 +660,15 @@
|
|||||||
const USHORT f_sec_map_to = 7;
|
const USHORT f_sec_map_to = 7;
|
||||||
|
|
||||||
|
|
||||||
|
// Relation 47 (RDB$DB_CREATORS)
|
||||||
|
|
||||||
|
const USHORT f_crt_user = 0;
|
||||||
|
const USHORT f_crt_u_type = 1;
|
||||||
|
|
||||||
|
|
||||||
|
// Relation 48 (SEC$DB_CREATORS)
|
||||||
|
|
||||||
|
const USHORT f_sec_crt_user = 0;
|
||||||
|
const USHORT f_sec_crt_u_type = 1;
|
||||||
|
|
||||||
|
|
||||||
|
@ -801,6 +801,9 @@ Data source : @4"}, /* eds_statement */
|
|||||||
{335545094, "There is no privilege for this operation"}, /* dyn_no_priv */
|
{335545094, "There is no privilege for this operation"}, /* dyn_no_priv */
|
||||||
{335545095, "Using GRANT OPTION on @1 not allowed"}, /* dsql_cant_grant_option */
|
{335545095, "Using GRANT OPTION on @1 not allowed"}, /* dsql_cant_grant_option */
|
||||||
{335545096, "read conflicts with concurrent update"}, /* read_conflict */
|
{335545096, "read conflicts with concurrent update"}, /* read_conflict */
|
||||||
|
{335545097, "@1 failed when working with CREATE DATABASE grants"}, /* crdb_load */
|
||||||
|
{335545098, "CREATE DATABASE grants check is not possible when database @1 is not present"}, /* crdb_nodb */
|
||||||
|
{335545099, "CREATE DATABASE grants check is not possible when table RDB$DB_CREATORS is not present in database @1"}, /* crdb_notable */
|
||||||
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
|
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
|
||||||
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
|
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
|
||||||
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
|
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
|
||||||
|
@ -797,6 +797,9 @@ static const struct {
|
|||||||
{335545094, -901}, /* 774 dyn_no_priv */
|
{335545094, -901}, /* 774 dyn_no_priv */
|
||||||
{335545095, -901}, /* 775 dsql_cant_grant_option */
|
{335545095, -901}, /* 775 dsql_cant_grant_option */
|
||||||
{335545096, -904}, /* 776 read_conflict */
|
{335545096, -904}, /* 776 read_conflict */
|
||||||
|
{335545097, -901}, /* 777 crdb_load */
|
||||||
|
{335545098, -901}, /* 778 crdb_nodb */
|
||||||
|
{335545099, -901}, /* 779 crdb_notable */
|
||||||
{335740929, -901}, /* 1 gfix_db_name */
|
{335740929, -901}, /* 1 gfix_db_name */
|
||||||
{335740930, -901}, /* 2 gfix_invalid_sw */
|
{335740930, -901}, /* 2 gfix_invalid_sw */
|
||||||
{335740932, -901}, /* 4 gfix_incmp_sw */
|
{335740932, -901}, /* 4 gfix_incmp_sw */
|
||||||
|
@ -797,6 +797,9 @@ static const struct {
|
|||||||
{335545094, "42000"}, // 774 dyn_no_priv
|
{335545094, "42000"}, // 774 dyn_no_priv
|
||||||
{335545095, "42000"}, // 775 dsql_cant_grant_option
|
{335545095, "42000"}, // 775 dsql_cant_grant_option
|
||||||
{335545096, "40001"}, // 776 read_conflict
|
{335545096, "40001"}, // 776 read_conflict
|
||||||
|
{335545097, "08004"}, // 777 crdb_load
|
||||||
|
{335545098, "0A000"}, // 778 crdb_nodb
|
||||||
|
{335545099, "0A000"}, // 779 crdb_notable
|
||||||
{335740929, "00000"}, // 1 gfix_db_name
|
{335740929, "00000"}, // 1 gfix_db_name
|
||||||
{335740930, "00000"}, // 2 gfix_invalid_sw
|
{335740930, "00000"}, // 2 gfix_invalid_sw
|
||||||
{335740932, "00000"}, // 4 gfix_incmp_sw
|
{335740932, "00000"}, // 4 gfix_incmp_sw
|
||||||
|
@ -1452,6 +1452,44 @@ processing_state SHOW_grants2 (const SCHAR* object,
|
|||||||
return ps_ERR;
|
return ps_ERR;
|
||||||
END_ERROR
|
END_ERROR
|
||||||
|
|
||||||
|
if (obj_type == obj_database || obj_type == 255)
|
||||||
|
{
|
||||||
|
FOR PRV IN SEC$DB_CREATORS
|
||||||
|
SORTED BY PRV.SEC$USER_TYPE, PRV.SEC$USER
|
||||||
|
|
||||||
|
if (first && optional_msg)
|
||||||
|
isqlGlob.prints(optional_msg);
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
fb_utils::exact_name(PRV.SEC$USER);
|
||||||
|
|
||||||
|
switch (PRV.SEC$USER_TYPE)
|
||||||
|
{
|
||||||
|
case obj_sql_role:
|
||||||
|
case obj_user:
|
||||||
|
if (mangle && isqlGlob.db_SQL_dialect > SQL_DIALECT_V6_TRANSITION)
|
||||||
|
IUTILS_copy_SQL_id(PRV.SEC$USER, SQL_identifier, DBL_QUOTE);
|
||||||
|
else
|
||||||
|
strcpy(SQL_identifier, PRV.SEC$USER);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fb_assert(false);
|
||||||
|
strcpy(SQL_identifier, PRV.SEC$USER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_grantee(PRV.SEC$USER_TYPE, SQL_identifier, user_string);
|
||||||
|
|
||||||
|
isqlGlob.printf("GRANT CREATE DATABASE TO %s%s%s",
|
||||||
|
user_string, terminator, NEWLINE);
|
||||||
|
|
||||||
|
END_FOR
|
||||||
|
ON_ERROR
|
||||||
|
ISQL_errmsg(fbStatus);
|
||||||
|
return ps_ERR;
|
||||||
|
END_ERROR
|
||||||
|
}
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
return (SKIP);
|
return (SKIP);
|
||||||
}
|
}
|
||||||
|
249
src/jrd/DbCreators.cpp
Normal file
249
src/jrd/DbCreators.cpp
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* PROGRAM: JRD access method
|
||||||
|
* MODULE: DbCreators.cpp
|
||||||
|
* DESCRIPTION: Checks CREATE DATABASE right (in security.db)
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Initial
|
||||||
|
* Developer's Public License Version 1.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed AS IS,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing rights
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code was created by Alex Peshkov
|
||||||
|
* for the Firebird Open Source RDBMS project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Alex Peshkov <peshkoff at mail.ru>
|
||||||
|
* and all contributors signed below.
|
||||||
|
*
|
||||||
|
* All Rights Reserved.
|
||||||
|
* Contributor(s): ______________________________________.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "firebird.h"
|
||||||
|
#include "firebird/Provider.h"
|
||||||
|
#include "../auth/SecureRemotePassword/Message.h"
|
||||||
|
#include "gen/iberror.h"
|
||||||
|
|
||||||
|
#include "../jrd/constants.h"
|
||||||
|
#include "../common/classes/ClumpletWriter.h"
|
||||||
|
#include "../common/classes/init.h"
|
||||||
|
#include "../common/classes/Hash.h"
|
||||||
|
#include "../common/classes/GenericMap.h"
|
||||||
|
#include "../common/classes/RefMutex.h"
|
||||||
|
#include "../common/classes/SyncObject.h"
|
||||||
|
#include "../common/classes/MetaName.h"
|
||||||
|
#include "../common/isc_s_proto.h"
|
||||||
|
#include "../common/isc_proto.h"
|
||||||
|
#include "../common/ThreadStart.h"
|
||||||
|
#include "../common/db_alias.h"
|
||||||
|
|
||||||
|
#include "../jrd/DbCreators.h"
|
||||||
|
#include "../jrd/tra.h"
|
||||||
|
#include "../jrd/ini.h"
|
||||||
|
#include "gen/ids.h"
|
||||||
|
|
||||||
|
#define DBC_DEBUG(A)
|
||||||
|
|
||||||
|
using namespace Firebird;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void check(const char* s, IStatus* st)
|
||||||
|
{
|
||||||
|
if (!(st->getStatus() & IStatus::FB_HAS_ERRORS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Arg::StatusVector newStatus(st);
|
||||||
|
newStatus << Arg::Gds(isc_crdb_load) << s;
|
||||||
|
newStatus.raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool openDb(const char* securityDb, RefPtr<IAttachment>& att, RefPtr<ITransaction>& tra)
|
||||||
|
{
|
||||||
|
DispatcherPtr prov;
|
||||||
|
|
||||||
|
ClumpletWriter embeddedSysdba(ClumpletWriter::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
|
||||||
|
embeddedSysdba.insertString(isc_dpb_user_name, SYSDBA_USER_NAME, fb_strlen(SYSDBA_USER_NAME));
|
||||||
|
embeddedSysdba.insertByte(isc_dpb_sec_attach, TRUE);
|
||||||
|
embeddedSysdba.insertByte(isc_dpb_no_db_triggers, TRUE);
|
||||||
|
|
||||||
|
LocalStatus st;
|
||||||
|
att = prov->attachDatabase(&st, securityDb,
|
||||||
|
embeddedSysdba.getBufferLength(), embeddedSysdba.getBuffer());
|
||||||
|
if (st.getStatus() & IStatus::FB_HAS_ERRORS)
|
||||||
|
{
|
||||||
|
if (!fb_utils::containsErrorCode(st.getErrors(), isc_io_error))
|
||||||
|
check("IProvider::attachDatabase", &st);
|
||||||
|
|
||||||
|
// missing security DB - checking granted rights not possible
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClumpletWriter readOnly(ClumpletWriter::Tpb, MAX_DPB_SIZE, isc_tpb_version1);
|
||||||
|
readOnly.insertTag(isc_tpb_read);
|
||||||
|
readOnly.insertTag(isc_tpb_wait);
|
||||||
|
tra = att->startTransaction(&st, readOnly.getBufferLength(), readOnly.getBuffer());
|
||||||
|
check("IAttachment::startTransaction", &st);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
|
namespace Jrd {
|
||||||
|
|
||||||
|
bool checkCreateDatabaseGrant(Firebird::string& userName, Firebird::string& trustedRole,
|
||||||
|
const char* securityDb)
|
||||||
|
{
|
||||||
|
if (userName == SYSDBA_USER_NAME || trustedRole == ADMIN_ROLE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
RefPtr<IAttachment> att;
|
||||||
|
RefPtr<ITransaction> tra;
|
||||||
|
if (!openDb(securityDb, att, tra))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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 = trustedRole.hasData() ? obj_sql_role : 255;
|
||||||
|
r = trustedRole.c_str();
|
||||||
|
|
||||||
|
Message result;
|
||||||
|
Field<ISC_INT64> cnt(result);
|
||||||
|
|
||||||
|
LocalStatus st;
|
||||||
|
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.getStatus() & IStatus::FB_HAS_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Format* DbCreatorsScan::getFormat(thread_db* tdbb, jrd_rel* relation) const
|
||||||
|
{
|
||||||
|
jrd_tra* const transaction = tdbb->getTransaction();
|
||||||
|
return transaction->getDbCreatorsList()->getList(tdbb, relation)->getFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DbCreatorsScan::retrieveRecord(thread_db* tdbb, jrd_rel* relation,
|
||||||
|
FB_UINT64 position, Record* record) const
|
||||||
|
{
|
||||||
|
jrd_tra* const transaction = tdbb->getTransaction();
|
||||||
|
return transaction->getDbCreatorsList()->getList(tdbb, relation)->fetch(position, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
DbCreatorsList::DbCreatorsList(jrd_tra* tra)
|
||||||
|
: SnapshotData(*tra->tra_pool)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
RecordBuffer* DbCreatorsList::makeBuffer(thread_db* tdbb)
|
||||||
|
{
|
||||||
|
MemoryPool* const pool = tdbb->getTransaction()->tra_pool;
|
||||||
|
allocBuffer(tdbb, *pool, rel_sec_db_creators);
|
||||||
|
return getData(rel_sec_db_creators);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordBuffer* DbCreatorsList::getList(thread_db* tdbb, jrd_rel* relation)
|
||||||
|
{
|
||||||
|
fb_assert(relation);
|
||||||
|
fb_assert(relation->rel_id == rel_sec_db_creators);
|
||||||
|
|
||||||
|
RecordBuffer* buffer = getData(relation);
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<IAttachment> att;
|
||||||
|
RefPtr<ITransaction> tra;
|
||||||
|
const char* dbName = tdbb->getDatabase()->dbb_config->getSecurityDatabase();
|
||||||
|
if (!openDb(dbName, att, tra))
|
||||||
|
{
|
||||||
|
// In embedded mode we are not raising any errors - silent return
|
||||||
|
if (MasterInterfacePtr()->serverMode(-1) < 0)
|
||||||
|
return makeBuffer(tdbb);
|
||||||
|
|
||||||
|
(Arg::Gds(isc_crdb_nodb) << dbName).raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
Message gr;
|
||||||
|
Field<ISC_SHORT> uType(gr);
|
||||||
|
Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN);
|
||||||
|
|
||||||
|
LocalStatus st;
|
||||||
|
RefPtr<IResultSet> curs(att->openCursor(&st, tra, 0,
|
||||||
|
"select RDB$USER_TYPE, RDB$USER from RDB$DB_CREATORS",
|
||||||
|
SQL_DIALECT_V6, NULL, NULL, gr.getMetadata(), NULL));
|
||||||
|
|
||||||
|
if (st.getStatus() & IStatus::FB_HAS_ERRORS)
|
||||||
|
{
|
||||||
|
if (!fb_utils::containsErrorCode(st.getErrors(), isc_dsql_relation_err))
|
||||||
|
check("IAttachment::openCursor", &st);
|
||||||
|
|
||||||
|
// isc_dsql_relation_err when opening cursor - i.e. table
|
||||||
|
// is missing due to non-FB3 security DB
|
||||||
|
|
||||||
|
// In embedded mode we are not raising any errors - silent return
|
||||||
|
if (MasterInterfacePtr()->serverMode(-1) < 0)
|
||||||
|
return makeBuffer(tdbb);
|
||||||
|
|
||||||
|
(Arg::Gds(isc_crdb_notable) << dbName).raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
buffer = makeBuffer(tdbb);
|
||||||
|
while (curs->fetchNext(&st, gr.getBuffer()) == IStatus::FB_OK)
|
||||||
|
{
|
||||||
|
int charset = CS_METADATA;
|
||||||
|
Record* record = buffer->getTempRecord();
|
||||||
|
record->nullify();
|
||||||
|
|
||||||
|
putField(tdbb, record,
|
||||||
|
DumpField(f_sec_crt_user, VALUE_STRING, u->len, u->data),
|
||||||
|
charset);
|
||||||
|
|
||||||
|
SINT64 v = uType;
|
||||||
|
putField(tdbb, record,
|
||||||
|
DumpField(f_sec_crt_u_type, VALUE_INTEGER, sizeof(v), &v),
|
||||||
|
charset);
|
||||||
|
|
||||||
|
buffer->store(record);
|
||||||
|
}
|
||||||
|
check("IResultSet::fetchNext", &st);
|
||||||
|
}
|
||||||
|
catch (const Exception&)
|
||||||
|
{
|
||||||
|
clearSnapshot();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getData(relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Jrd
|
69
src/jrd/DbCreators.h
Normal file
69
src/jrd/DbCreators.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* PROGRAM: JRD access method
|
||||||
|
* MODULE: DbCreators.h
|
||||||
|
* DESCRIPTION: GRANT CREATE DATABASE right (in security.db)
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Initial
|
||||||
|
* Developer's Public License Version 1.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed AS IS,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing rights
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code was created by Alex Peshkov
|
||||||
|
* for the Firebird Open Source RDBMS project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Alex Peshkov <peshkoff at mail.ru>
|
||||||
|
* and all contributors signed below.
|
||||||
|
*
|
||||||
|
* All Rights Reserved.
|
||||||
|
* Contributor(s): ______________________________________.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JRD_DB_CREATORS
|
||||||
|
#define JRD_DB_CREATORS
|
||||||
|
|
||||||
|
#include "../common/classes/alloc.h"
|
||||||
|
#include "../common/classes/fb_string.h"
|
||||||
|
#include "../jrd/recsrc/RecordSource.h"
|
||||||
|
#include "../jrd/Monitoring.h"
|
||||||
|
|
||||||
|
namespace Jrd {
|
||||||
|
|
||||||
|
bool checkCreateDatabaseGrant(Firebird::string& userName, Firebird::string& trustedRole,
|
||||||
|
const char* securityDb);
|
||||||
|
|
||||||
|
class DbCreatorsScan: public VirtualTableScan
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DbCreatorsScan(CompilerScratch* csb, const Firebird::string& alias,
|
||||||
|
StreamType stream, jrd_rel* relation)
|
||||||
|
: VirtualTableScan(csb, alias, stream, relation)
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const Format* getFormat(thread_db* tdbb, jrd_rel* relation) const;
|
||||||
|
bool retrieveRecord(thread_db* tdbb, jrd_rel* relation, FB_UINT64 position, Record* record) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DbCreatorsList : public SnapshotData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DbCreatorsList(jrd_tra* tra);
|
||||||
|
|
||||||
|
RecordBuffer* getList(thread_db* tdbb, jrd_rel* relation);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RecordBuffer* makeBuffer(thread_db* tdbb);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Jrd
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JRD_DB_CREATORS
|
@ -126,6 +126,7 @@
|
|||||||
#include "../jrd/DebugInterface.h"
|
#include "../jrd/DebugInterface.h"
|
||||||
#include "../jrd/EngineInterface.h"
|
#include "../jrd/EngineInterface.h"
|
||||||
#include "../jrd/CryptoManager.h"
|
#include "../jrd/CryptoManager.h"
|
||||||
|
#include "../jrd/DbCreators.h"
|
||||||
|
|
||||||
#include "../dsql/dsql.h"
|
#include "../dsql/dsql.h"
|
||||||
#include "../dsql/dsql_proto.h"
|
#include "../dsql/dsql_proto.h"
|
||||||
@ -995,7 +996,7 @@ static void release_attachment(thread_db*, Jrd::Attachment*);
|
|||||||
static void rollback(thread_db*, jrd_tra*, const bool);
|
static void rollback(thread_db*, jrd_tra*, const bool);
|
||||||
static void strip_quotes(string&);
|
static void strip_quotes(string&);
|
||||||
static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsigned flags = 0);
|
static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsigned flags = 0);
|
||||||
static void getUserInfo(UserId&, const DatabaseOptions&, const char*, const char*, const RefPtr<Config>*);
|
static void getUserInfo(UserId&, const DatabaseOptions&, const char*, const char*, const RefPtr<Config>*, bool);
|
||||||
|
|
||||||
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM);
|
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM);
|
||||||
|
|
||||||
@ -1007,7 +1008,7 @@ TraceFailedConnection::TraceFailedConnection(const char* filename, const Databas
|
|||||||
m_filename(filename),
|
m_filename(filename),
|
||||||
m_options(options)
|
m_options(options)
|
||||||
{
|
{
|
||||||
getUserInfo(m_id, *m_options, m_filename, NULL, NULL);
|
getUserInfo(m_id, *m_options, m_filename, NULL, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1397,7 +1398,7 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for correct credentials supplied
|
// Check for correct credentials supplied
|
||||||
getUserInfo(userId, options, org_filename.c_str(), expanded_name.c_str(), &config);
|
getUserInfo(userId, options, org_filename.c_str(), expanded_name.c_str(), &config, false);
|
||||||
|
|
||||||
#ifdef WIN_NT
|
#ifdef WIN_NT
|
||||||
guardDbInit.enter(); // Required to correctly expand name of just created database
|
guardDbInit.enter(); // Required to correctly expand name of just created database
|
||||||
@ -2409,7 +2410,7 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for correct credentials supplied
|
// Check for correct credentials supplied
|
||||||
getUserInfo(userId, options, org_filename.c_str(), NULL, &config);
|
getUserInfo(userId, options, org_filename.c_str(), NULL, &config, true);
|
||||||
|
|
||||||
#ifdef WIN_NT
|
#ifdef WIN_NT
|
||||||
guardDbInit.enter(); // Required to correctly expand name of just created database
|
guardDbInit.enter(); // Required to correctly expand name of just created database
|
||||||
@ -7055,9 +7056,8 @@ static VdnResult verifyDatabaseName(const PathName& name, ISC_STATUS* status, bo
|
|||||||
|
|
||||||
getUserInfo
|
getUserInfo
|
||||||
|
|
||||||
@brief Almost stub-like now.
|
@brief Fills UserId structure with resulting values.
|
||||||
Planned to take into an account mapping of users and groups.
|
Takes into an account mapping of users and groups.
|
||||||
Fills UserId structure with resulting values.
|
|
||||||
|
|
||||||
@param user
|
@param user
|
||||||
@param options
|
@param options
|
||||||
@ -7065,7 +7065,7 @@ static VdnResult verifyDatabaseName(const PathName& name, ISC_STATUS* status, bo
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
static void getUserInfo(UserId& user, const DatabaseOptions& options,
|
static void getUserInfo(UserId& user, const DatabaseOptions& options,
|
||||||
const char* aliasName, const char* dbName, const RefPtr<Config>* config)
|
const char* aliasName, const char* dbName, const RefPtr<Config>* config, bool creating)
|
||||||
{
|
{
|
||||||
bool wheel = false;
|
bool wheel = false;
|
||||||
int id = -1, group = -1; // CVC: This var contained trash
|
int id = -1, group = -1; // CVC: This var contained trash
|
||||||
@ -7092,6 +7092,12 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
|
|||||||
aliasName, dbName, (config ? (*config)->getSecurityDatabase() : NULL));
|
aliasName, dbName, (config ? (*config)->getSecurityDatabase() : NULL));
|
||||||
ISC_systemToUtf8(name);
|
ISC_systemToUtf8(name);
|
||||||
ISC_systemToUtf8(trusted_role);
|
ISC_systemToUtf8(trusted_role);
|
||||||
|
|
||||||
|
if (creating && config) // when config is NULL we are in error handler
|
||||||
|
{
|
||||||
|
if (!checkCreateDatabaseGrant(name, trusted_role, (*config)->getSecurityDatabase()))
|
||||||
|
(Arg::Gds(isc_no_priv) << "CREATE" << "DATABASE" << aliasName).raise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -394,3 +394,8 @@ NAME("SEC$MAP_FROM_TYPE", nam_sec_map_from_type)
|
|||||||
NAME("SEC$MAP_FROM", nam_sec_map_from)
|
NAME("SEC$MAP_FROM", nam_sec_map_from)
|
||||||
NAME("SEC$MAP_TO_TYPE", nam_sec_map_to_type)
|
NAME("SEC$MAP_TO_TYPE", nam_sec_map_to_type)
|
||||||
NAME("SEC$MAP_TO", nam_sec_map_to)
|
NAME("SEC$MAP_TO", nam_sec_map_to)
|
||||||
|
|
||||||
|
NAME("RDB$DB_CREATORS", nam_db_creators)
|
||||||
|
NAME("SEC$DB_CREATORS", nam_sec_db_creators)
|
||||||
|
NAME("SEC$USER", nam_sec_user)
|
||||||
|
NAME("SEC$USER_TYPE", nam_sec_user_type)
|
||||||
|
@ -85,6 +85,7 @@
|
|||||||
#include "../jrd/recsrc/RecordSource.h"
|
#include "../jrd/recsrc/RecordSource.h"
|
||||||
#include "../jrd/recsrc/Cursor.h"
|
#include "../jrd/recsrc/Cursor.h"
|
||||||
#include "../jrd/Mapping.h"
|
#include "../jrd/Mapping.h"
|
||||||
|
#include "../jrd/DbCreators.h"
|
||||||
|
|
||||||
#include "../jrd/Optimizer.h"
|
#include "../jrd/Optimizer.h"
|
||||||
#include "../dsql/BoolNodes.h"
|
#include "../dsql/BoolNodes.h"
|
||||||
@ -2264,17 +2265,24 @@ static RecordSource* gen_retrieval(thread_db* tdbb,
|
|||||||
else if (relation->isVirtual())
|
else if (relation->isVirtual())
|
||||||
{
|
{
|
||||||
// Virtual table: monitoring or security
|
// Virtual table: monitoring or security
|
||||||
if (relation->rel_id == rel_global_auth_mapping)
|
switch(relation->rel_id)
|
||||||
{
|
{
|
||||||
|
case rel_global_auth_mapping:
|
||||||
rsb = FB_NEW(*tdbb->getDefaultPool()) GlobalMappingScan(csb, alias, stream, relation);
|
rsb = FB_NEW(*tdbb->getDefaultPool()) GlobalMappingScan(csb, alias, stream, relation);
|
||||||
}
|
break;
|
||||||
else if (relation->rel_id == rel_sec_users || relation->rel_id == rel_sec_user_attributes)
|
|
||||||
{
|
case rel_sec_users:
|
||||||
|
case rel_sec_user_attributes:
|
||||||
rsb = FB_NEW(*tdbb->getDefaultPool()) UsersTableScan(csb, alias, stream, relation);
|
rsb = FB_NEW(*tdbb->getDefaultPool()) UsersTableScan(csb, alias, stream, relation);
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
{
|
case rel_sec_db_creators:
|
||||||
|
rsb = FB_NEW(*tdbb->getDefaultPool()) DbCreatorsScan(csb, alias, stream, relation);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
rsb = FB_NEW(*tdbb->getDefaultPool()) MonitoringTableScan(csb, alias, stream, relation);
|
rsb = FB_NEW(*tdbb->getDefaultPool()) MonitoringTableScan(csb, alias, stream, relation);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -649,7 +649,7 @@ END_RELATION
|
|||||||
|
|
||||||
// Relation 46 (SEC$GLOBAL_AUTH_MAPPING)
|
// Relation 46 (SEC$GLOBAL_AUTH_MAPPING)
|
||||||
RELATION(nam_sec_global_auth_mapping, rel_global_auth_mapping, ODS_12_0, rel_virtual)
|
RELATION(nam_sec_global_auth_mapping, rel_global_auth_mapping, ODS_12_0, rel_virtual)
|
||||||
FIELD(f_sec_map_name, nam_sec_map_name, fld_map_name, 1, ODS_12_0)
|
FIELD(f_sec_map_name, nam_sec_map_name, fld_map_name, 0, ODS_12_0)
|
||||||
FIELD(f_sec_map_using, nam_sec_map_using, fld_map_using, 0, ODS_12_0)
|
FIELD(f_sec_map_using, nam_sec_map_using, fld_map_using, 0, ODS_12_0)
|
||||||
FIELD(f_sec_map_plugin, nam_sec_map_plugin, fld_map_plugin, 0, ODS_12_0)
|
FIELD(f_sec_map_plugin, nam_sec_map_plugin, fld_map_plugin, 0, ODS_12_0)
|
||||||
FIELD(f_sec_map_db, nam_sec_map_db, fld_map_db, 0, ODS_12_0)
|
FIELD(f_sec_map_db, nam_sec_map_db, fld_map_db, 0, ODS_12_0)
|
||||||
@ -658,3 +658,15 @@ RELATION(nam_sec_global_auth_mapping, rel_global_auth_mapping, ODS_12_0, rel_vir
|
|||||||
FIELD(f_sec_map_to_type, nam_sec_map_to_type, fld_obj_type, 0, ODS_12_0)
|
FIELD(f_sec_map_to_type, nam_sec_map_to_type, fld_obj_type, 0, ODS_12_0)
|
||||||
FIELD(f_sec_map_to, nam_sec_map_to, fld_map_to, 0, ODS_12_0)
|
FIELD(f_sec_map_to, nam_sec_map_to, fld_map_to, 0, ODS_12_0)
|
||||||
END_RELATION
|
END_RELATION
|
||||||
|
|
||||||
|
// Relation 47 (RDB$DB_CREATORS)
|
||||||
|
RELATION(nam_db_creators, rel_db_creators, ODS_12_0, rel_persistent)
|
||||||
|
FIELD(f_crt_user, nam_user, fld_user, 1, ODS_12_0)
|
||||||
|
FIELD(f_crt_u_type, nam_user_type, fld_obj_type, 1, ODS_12_0)
|
||||||
|
END_RELATION
|
||||||
|
|
||||||
|
// Relation 48 (SEC$DB_CREATORS)
|
||||||
|
RELATION(nam_sec_db_creators, rel_sec_db_creators, ODS_12_0, rel_virtual)
|
||||||
|
FIELD(f_sec_crt_user, nam_sec_user, fld_user, 0, ODS_12_0)
|
||||||
|
FIELD(f_sec_crt_u_type, nam_sec_user_type, fld_obj_type, 0, ODS_12_0)
|
||||||
|
END_RELATION
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
#include "../jrd/Function.h"
|
#include "../jrd/Function.h"
|
||||||
#include "../jrd/Collation.h"
|
#include "../jrd/Collation.h"
|
||||||
#include "../jrd/Mapping.h"
|
#include "../jrd/Mapping.h"
|
||||||
|
#include "../jrd/DbCreators.h"
|
||||||
|
|
||||||
|
|
||||||
const int DYN_MSG_FAC = 8;
|
const int DYN_MSG_FAC = 8;
|
||||||
@ -3401,6 +3402,15 @@ MappingList* jrd_tra::getMappingList()
|
|||||||
return tra_mapping_list;
|
return tra_mapping_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DbCreatorsList* jrd_tra::getDbCreatorsList()
|
||||||
|
{
|
||||||
|
if (!tra_dbcreators_list)
|
||||||
|
{
|
||||||
|
tra_dbcreators_list = FB_NEW(*tra_pool) DbCreatorsList(this);
|
||||||
|
}
|
||||||
|
return tra_dbcreators_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
jrd_tra* jrd_tra::getOuter()
|
jrd_tra* jrd_tra::getOuter()
|
||||||
{
|
{
|
||||||
|
@ -71,6 +71,7 @@ class DeferredJob;
|
|||||||
class dsql_opn;
|
class dsql_opn;
|
||||||
class UserManagement;
|
class UserManagement;
|
||||||
class MappingList;
|
class MappingList;
|
||||||
|
class DbCreatorsList;
|
||||||
class thread_db;
|
class thread_db;
|
||||||
|
|
||||||
class SecDbContext
|
class SecDbContext
|
||||||
@ -303,6 +304,7 @@ private:
|
|||||||
UserManagement* tra_user_management;
|
UserManagement* tra_user_management;
|
||||||
SecDbContext* tra_sec_db_context;
|
SecDbContext* tra_sec_db_context;
|
||||||
MappingList* tra_mapping_list;
|
MappingList* tra_mapping_list;
|
||||||
|
DbCreatorsList* tra_dbcreators_list;
|
||||||
MemoryPool* tra_autonomous_pool;
|
MemoryPool* tra_autonomous_pool;
|
||||||
USHORT tra_autonomous_cnt;
|
USHORT tra_autonomous_cnt;
|
||||||
static const USHORT TRA_AUTONOMOUS_PER_POOL = 64;
|
static const USHORT TRA_AUTONOMOUS_PER_POOL = 64;
|
||||||
@ -359,6 +361,7 @@ public:
|
|||||||
SecDbContext* setSecDbContext(Firebird::IAttachment* att, Firebird::ITransaction* tra);
|
SecDbContext* setSecDbContext(Firebird::IAttachment* att, Firebird::ITransaction* tra);
|
||||||
void eraseSecDbContext();
|
void eraseSecDbContext();
|
||||||
MappingList* getMappingList();
|
MappingList* getMappingList();
|
||||||
|
DbCreatorsList* getDbCreatorsList();
|
||||||
|
|
||||||
GenIdCache* getGenIdCache()
|
GenIdCache* getGenIdCache()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
|
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
|
||||||
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
|
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
|
||||||
--
|
--
|
||||||
('2014-08-27 16:38:00', 'JRD', 0, 777)
|
('2014-09-02 19:54:57', 'JRD', 0, 780)
|
||||||
('2012-01-23 20:10:30', 'QLI', 1, 532)
|
('2012-01-23 20:10:30', 'QLI', 1, 532)
|
||||||
('2013-11-13 15:59:10', 'GFIX', 3, 122)
|
('2013-11-13 15:59:10', 'GFIX', 3, 122)
|
||||||
('1996-11-07 13:39:40', 'GPRE', 4, 1)
|
('1996-11-07 13:39:40', 'GPRE', 4, 1)
|
||||||
|
@ -884,6 +884,9 @@ Data source : @4', NULL, NULL)
|
|||||||
('dyn_no_priv', NULL, 'scl.epp', NULL, 0, 774, NULL, 'There is no privilege for this operation', NULL, NULL);
|
('dyn_no_priv', NULL, 'scl.epp', NULL, 0, 774, NULL, 'There is no privilege for this operation', NULL, NULL);
|
||||||
('dsql_cant_grant_option', NULL, 'DdlNodes.epp', NULL, 0, 775, NULL, 'Using GRANT OPTION on @1 not allowed', NULL, NULL);
|
('dsql_cant_grant_option', NULL, 'DdlNodes.epp', NULL, 0, 775, NULL, 'Using GRANT OPTION on @1 not allowed', NULL, NULL);
|
||||||
('read_conflict', NULL, NULL, 'vio.cpp', 0, 776, NULL, 'read conflicts with concurrent update', NULL, NULL);
|
('read_conflict', NULL, NULL, 'vio.cpp', 0, 776, NULL, 'read conflicts with concurrent update', NULL, NULL);
|
||||||
|
('crdb_load', 'check', 'DbCreators.cpp', NULL, 0, 777, NULL, '@1 failed when working with CREATE DATABASE grants', NULL, NULL);
|
||||||
|
('crdb_nodb', 'DbCreatorsList::getList', 'DbCreators.cpp', NULL, 0, 778, NULL, 'CREATE DATABASE grants check is not possible when database @1 is not present', NULL, NULL);
|
||||||
|
('crdb_notable', 'DbCreatorsList::getList', 'DbCreators.cpp', NULL, 0, 779, NULL, 'CREATE DATABASE grants check is not possible when table RDB$DB_CREATORS is not present in database @1', NULL, NULL);
|
||||||
-- QLI
|
-- QLI
|
||||||
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
|
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
|
||||||
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
|
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
|
||||||
|
@ -783,6 +783,9 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
|
|||||||
(-901, '42', '000', 0, 774, 'dyn_no_priv', NULL, NULL)
|
(-901, '42', '000', 0, 774, 'dyn_no_priv', NULL, NULL)
|
||||||
(-901, '42', '000', 0, 775, 'dsql_cant_grant_option', NULL, NULL);
|
(-901, '42', '000', 0, 775, 'dsql_cant_grant_option', NULL, NULL);
|
||||||
(-904, '40', '001', 0, 776, 'read_conflict', NULL, NULL);
|
(-904, '40', '001', 0, 776, 'read_conflict', NULL, NULL);
|
||||||
|
(-901, '08', '004', 0, 777, 'crdb_load', NULL, NULL);
|
||||||
|
(-901, '0A', '000', 0, 778, 'crdb_nodb', NULL, NULL);
|
||||||
|
(-901, '0A', '000', 0, 779, 'crdb_notable', NULL, NULL);
|
||||||
-- GFIX
|
-- GFIX
|
||||||
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
|
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
|
||||||
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
|
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user