8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 08:40:39 +01:00

Implemented CORE-3370: Resolve additional aspects of multiple security databases from services and cross-database requests POV (mapping names)

This commit is contained in:
alexpeshkoff 2014-04-04 15:57:18 +00:00
parent b826331d55
commit 20e846369e
82 changed files with 3661 additions and 667 deletions

View File

@ -27,6 +27,7 @@ employee = $(dir_sampleDb)/employee.fdb
security.db = $(dir_secDb)/security3.fdb
{
RemoteAccess = false
DefaultDbCachePages = 50
}
#

View File

@ -0,0 +1,240 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="OpenOffice 4.0.1 (Unix)">
<META NAME="AUTHOR" CONTENT="irina ">
<META NAME="CREATED" CONTENT="20140325;10305100">
<META NAME="CHANGEDBY" CONTENT="Alex Peshkoff">
<META NAME="CHANGED" CONTENT="20140404;19502000">
<STYLE TYPE="text/css">
<!--
@page { margin: 0.79in }
P { margin-bottom: 0.08in }
A:link { so-language: zxx }
-->
</STYLE>
</HEAD>
<BODY LANG="ru-RU" DIR="LTR">
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>SQL Language
Extension: CREATE/ALTER/CREATE_OR_ALTER/DROP MAPPING</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"> <FONT SIZE=4>Implements
capability to control mapping of security objects to and between
databases.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Author:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"> <FONT SIZE=4>Alex
Peshkoff &lt;<A HREF="mailto:peshkoff@mail.ru">peshkoff@mail.ru</A>&gt;</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Preamble:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Firebird 3
supports multiple security databases. This is great feature, but it
raises some problems, missing in systems with single security
database. Clusters of databases, using same security database, are
efficiently separated and this is what we typically want to achieve
using different security databases. But in some cases we need
controlled limited interaction between such clusters. As an examples
can be provided EXECUTE STATEMENT ON EXTERNAL DATA SOURCE when some
data exchange between clusters is required and letting server-wide
SYSDBA access databases from other clusters using services. More or
less similar problems were already known in windows version of
firebird since v. 2.1 due to presence of trusted windows
authentication &ndash; we had 2 separate lists of users (in security
database and OS) and sometimes it was needed to make them be related.
For example it appears to be good idea to automatically assign to
windows users from some group appropriate firebird role.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Single
solution for all this problems is MAPPING login information, assigned
to user when it connected to firebird server, to internal security
objects in database &ndash; current_user and current_role. Mapping
rule contains 4 parts of information: </FONT>
</P>
<UL>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>mapping
scope (is mapping local for current database or affects all
databases in cluster, including security database),</FONT></P>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>mapping
name (mappings are named like all the other objects in database), </FONT>
</P>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>from
what we map </FONT>
</P>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>to what
we map.</FONT></P>
</UL>
<P STYLE="margin-bottom: 0in"><FONT SIZE=4>Here it's necessary to
mention that all versions of firebird had one hardcoded global
default rule &ndash; users authenticated in security database are
always mapped into any database one-to-one. This rule is safe - if we
have some security database it makes no use not to trust itself.
Therefore (and due to backward compatibility) this rule is kept as is
in firebird 3. What about mapping windows users to current_user
(which was enabled by default in 2.1 &amp; 2.5 when trusted
authentication enabled) in firebird 3 it must be done explicitly.
This is required for systems with multiple security databases - not
all of them need/use windows trusted authentication.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>'From' part
of mapping has 4 items:</FONT></P>
<UL>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>authentication
source (plugin name or result of mapping in other database or use of
serverwide authentication or any method),</FONT></P>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>name of
database where authentication succeeded, </FONT>
</P>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>name
from which mapping is performed,</FONT></P>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>type of
that name (username, role, OS group &ndash; this depends upon plugin
which added that name during authentication).</FONT></P>
</UL>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Each item may
be ignored (any item is accepted) except type &ndash; it's definitely
bad idea to mix different types of security objects.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>'To' part has
2 items:</FONT></P>
<UL>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>name to
which mapping is performed,</FONT></P>
<LI><P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>type of
that name (only USER/ROLE are accepted here).</FONT></P>
</UL>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Mappings are
defined using SQL (DDL) commands.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Syntax:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-left: 0.46in; margin-bottom: 0in; page-break-before: auto">
<FONT SIZE=4>{CREATE | ALTER | CREATE OR ALTER} [GLOBAL] MAPPING name
USING {PLUGIN name [IN database] | ANY PLUGIN [IN database |
SERVERWIDE] | MAPPING [IN database] | '*' [IN database]} FROM {ANY
type | type name} TO {USER | ROLE} [name]</FONT></P>
<P LANG="en-US" STYLE="margin-left: 0.46in; margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-left: 0.46in; margin-bottom: 0in"><FONT SIZE=4>DROP
[GLOBAL] MAPPING</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Description:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Each mapping
may be tagged as GLOBAL. Pay attention that global and local maps
with same name may exist and they are different objects!</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Create, alter
and create or alter commands use same set of options. Name of mapping
is used to identify it in former DDL commands. USING clause has a
most complicated set of options. One can provide explicit plugin
name, making it work only for given plugin, or make it use any plugin
(but not a result of previous mappings), or make it work only with
server-wide plugins, or make it work only with previous mapping
results, or let it use any method using asterisk. In almost all cases
(except server-wide authentication which is not related with
databases) one can also provide name of database in which name from
which mapping is performed was &ldquo;born&rdquo;. FROM clause must
set required parameter &ndash; type of name from which mapping is
done. When mapping names from plugins type is defined by plugin,
when previous mapping results - type can be only user or role. One
can provide explicit name which will be taken into an account by this
mapping or use ANY keyword to work with any name of given type. In TO
clause USER or ROLE (to what mapping is done) must be specified, name
is optional - when it is not provided original name (from what
mapping is done) is used.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Samples:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>All sample
are provided for CREATE command, use of ALTER is exactly the same,
use of DROP is obvious.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Enable use of
windows trusted authentication in all databases, using current
security database:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>CREATE GLOBAL
MAPPING TRUSTED_AUTH USING PLUGIN WIN_SSPI FROM ANY USER TO USER;</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Enable
SYSDBA-like access for windows admins:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>CREATE
MAPPING WIN_ADMINS USING PLUGIN WIN_SSPI FROM Predefined_Group
DOMAIN_ANY_RID_ADMINS TO ROLE RDB$ADMIN;</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>(there is no
group DOMAIN_ANY_RID_ADMINS in windows, but such name is added by
win_sspi plugin to provide exact backwards compatibility)</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Enable
particular user from other database access current database with
other name:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>CREATE
MAPPING FROM_RT USING PLUGIN SRP IN &quot;rt&quot; FROM USER U1 TO
USER U2;</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>(providing
database names/aliases in double quotes is important for file name
case-sensitive operating systems)</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Enable
server's SYDBA (from main security database) access current database
assuming I has non-default security database:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>CREATE
MAPPING DEF_SYSDBA USING PLUGIN SRP IN &quot;security.db&quot; FROM
USER SYSDBA TO USER;</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Force people
who logged in using legacy authentication plugin have not too much
rights:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>CREATE
MAPPING LEGACY_2_GUEST USING PLUGIN legacy_auth FROM ANY USER TO USER
GUEST;</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Notice:</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><FONT SIZE=4>Global
mapping works best if firebird 3 or higher version database is used
as security database. If you plan to use other database as security
one (using for example your own provider) please create in it table
RDB$MAP with structure repeating one in firebird 3 database and
SYSDBA-only write access.</FONT></P>
<P LANG="en-US" STYLE="margin-bottom: 0in"><BR>
</P>
</BODY>
</HTML>

View File

@ -1564,6 +1564,28 @@ C --
PARAMETER (GDS__forupdate_temptbl = 335545075)
INTEGER*4 GDS__cant_modify_sysobj
PARAMETER (GDS__cant_modify_sysobj = 335545076)
INTEGER*4 GDS__server_misconfigured
PARAMETER (GDS__server_misconfigured = 335545077)
INTEGER*4 GDS__alter_role
PARAMETER (GDS__alter_role = 335545078)
INTEGER*4 GDS__map_already_exists
PARAMETER (GDS__map_already_exists = 335545079)
INTEGER*4 GDS__map_not_exists
PARAMETER (GDS__map_not_exists = 335545080)
INTEGER*4 GDS__map_load
PARAMETER (GDS__map_load = 335545081)
INTEGER*4 GDS__map_aster
PARAMETER (GDS__map_aster = 335545082)
INTEGER*4 GDS__map_multi
PARAMETER (GDS__map_multi = 335545083)
INTEGER*4 GDS__map_undefined
PARAMETER (GDS__map_undefined = 335545084)
INTEGER*4 GDS__baddpb_damaged_mode
PARAMETER (GDS__baddpb_damaged_mode = 335545085)
INTEGER*4 GDS__baddpb_buffers_range
PARAMETER (GDS__baddpb_buffers_range = 335545086)
INTEGER*4 GDS__baddpb_temp_buffers
PARAMETER (GDS__baddpb_temp_buffers = 335545087)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw
@ -2256,6 +2278,8 @@ C --
PARAMETER (GDS__dsql_revoke_failed = 336397320)
INTEGER*4 GDS__dsql_cte_recursive_aggregate
PARAMETER (GDS__dsql_cte_recursive_aggregate = 336397321)
INTEGER*4 GDS__dsql_mapping_failed
PARAMETER (GDS__dsql_mapping_failed = 336397322)
INTEGER*4 GDS__gsec_cant_open_db
PARAMETER (GDS__gsec_cant_open_db = 336723983)
INTEGER*4 GDS__gsec_switches_error

View File

@ -789,6 +789,17 @@ const
gds_forupdate_systbl = 335545074;
gds_forupdate_temptbl = 335545075;
gds_cant_modify_sysobj = 335545076;
gds_server_misconfigured = 335545077;
gds_alter_role = 335545078;
gds_map_already_exists = 335545079;
gds_map_not_exists = 335545080;
gds_map_load = 335545081;
gds_map_aster = 335545082;
gds_map_multi = 335545083;
gds_map_undefined = 335545084;
gds_baddpb_damaged_mode = 335545085;
gds_baddpb_buffers_range = 335545086;
gds_baddpb_temp_buffers = 335545087;
gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932;
@ -1135,6 +1146,7 @@ const
gds_dsql_grant_failed = 336397319;
gds_dsql_revoke_failed = 336397320;
gds_dsql_cte_recursive_aggregate = 336397321;
gds_dsql_mapping_failed = 336397322;
gds_gsec_cant_open_db = 336723983;
gds_gsec_switches_error = 336723984;
gds_gsec_no_op_spec = 336723985;

View File

@ -200,7 +200,7 @@ int alice(Firebird::UtilSvc* uSvc)
version = true;
}
if (table->in_sw_value & sw_trusted_svc)
/* if (table->in_sw_value & sw_trusted_svc)
{
uSvc->checkService();
if (--argc <= 0) {
@ -214,7 +214,7 @@ int alice(Firebird::UtilSvc* uSvc)
uSvc->checkService();
tdgbl->ALICE_data.ua_tr_role = true;
continue;
}
} */
#ifdef TRUSTED_AUTH
if (table->in_sw_value & sw_trusted_auth)
{
@ -472,7 +472,7 @@ int alice(Firebird::UtilSvc* uSvc)
}
if (!flags || !(flags & ~(sw_user | sw_password | sw_fetch_password |
sw_trusted_auth | sw_trusted_svc | sw_trusted_role)))
sw_trusted_auth/* | sw_trusted_svc | sw_trusted_role*/)))
{
if (!help && !uSvc->isService())
{

View File

@ -60,8 +60,8 @@ const SINT64 sw_buffers = 0x0000000020000000L;
const SINT64 sw_mode = 0x0000000040000000L;
const SINT64 sw_set_db_dialect = 0x0000000080000000L;
const SINT64 sw_trusted_auth = QUADCONST(0x0000000100000000); // Byte 4, Bit 0
const SINT64 sw_trusted_svc = QUADCONST(0x0000000200000000);
const SINT64 sw_trusted_role = QUADCONST(0x0000000400000000);
//const SINT64 sw_trusted_svc = QUADCONST(0x0000000200000000);
//const SINT64 sw_trusted_role = QUADCONST(0x0000000400000000);
const SINT64 sw_fetch_password = QUADCONST(0x0000000800000000);
const SINT64 sw_nolinger = QUADCONST(0x0000001000000000);
@ -115,8 +115,8 @@ enum alice_switches
#ifdef TRUSTED_AUTH
IN_SW_ALICE_TRUSTED_AUTH = 44,
#endif
IN_SW_ALICE_TRUSTED_USER = 45,
IN_SW_ALICE_TRUSTED_ROLE = 46,
// IN_SW_ALICE_TRUSTED_USER = 45,
// IN_SW_ALICE_TRUSTED_ROLE = 46,
IN_SW_ALICE_HIDDEN_ONLINE = 47,
IN_SW_ALICE_FETCH_PASSWORD = 48,
IN_SW_ALICE_NOLINGER = 49
@ -199,7 +199,7 @@ static const Switches::in_sw_tab_t alice_in_sw_table[] =
sw_list, 0, false, 41, 2, NULL},
// msg 41: \t-prompt\t\tprompt for commit/rollback (-l)
{IN_SW_ALICE_PASSWORD, 0, "PASSWORD", sw_password,
0, (sw_trusted_auth | sw_trusted_svc | sw_trusted_role | sw_fetch_password),
0, (sw_trusted_auth /*| sw_trusted_svc | sw_trusted_role */| sw_fetch_password),
false, 42, 2, NULL},
// msg 42: \t-password\tdefault password
#ifdef DEV_BUILD
@ -233,15 +233,15 @@ static const Switches::in_sw_tab_t alice_in_sw_table[] =
0, (sw_user | sw_password), false, 115, 3, NULL},
// msg 115: -trusted use trusted authentication
#endif
{IN_SW_ALICE_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, sw_trusted_svc,
/* {IN_SW_ALICE_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, sw_trusted_svc,
0, (sw_trusted_svc | sw_user | sw_password), false, 0, TRUSTED_USER_SWITCH_LEN, NULL},
{IN_SW_ALICE_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, sw_trusted_role,
sw_trusted_svc, (sw_user | sw_password), false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL},
sw_trusted_svc, (sw_user | sw_password), false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL}, */
{IN_SW_ALICE_NO_RESERVE, 0, "USE", sw_no_reserve,
0, ~(sw_no_reserve | sw_user | sw_password | sw_nolinger), false, 49, 1, NULL},
// msg 49: \t-use\t\tuse full or reserve space for versions
{IN_SW_ALICE_USER, 0, "USER", sw_user,
0, (sw_trusted_auth | sw_trusted_svc | sw_trusted_role), false, 50, 4, NULL},
0, (sw_trusted_auth /*| sw_trusted_svc | sw_trusted_role*/), false, 50, 4, NULL},
// msg 50: \t-user\t\tdefault user name
{IN_SW_ALICE_VALIDATE, isc_spb_rpr_validate_db, "VALIDATE", sw_validate,
0, ~(sw_validate | sw_user | sw_password | sw_nolinger), false, 51, 1, NULL},

View File

@ -1,8 +1,8 @@
/*
* PROGRAM: Firebird authentication
* MODULE: Auth.cpp
* DESCRIPTION: Implementation of interfaces, passed to plugins
* Plugins loader
* MODULE: AuthDbg.cpp
* DESCRIPTION: Test module for various auth types
* NOT FOR PRODUCTION USE !
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
@ -54,8 +54,9 @@ extern "C" void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
namespace Auth {
DebugServer::DebugServer(Firebird::IPluginConfig*)
: str(getPool())
DebugServer::DebugServer(Firebird::IPluginConfig* pConf)
: str(getPool()),
config(Firebird::REF_NO_INCR, pConf->getDefaultConfig())
{ }
int FB_CARG DebugServer::authenticate(Firebird::IStatus* status, IServerBlock* sb,
@ -96,6 +97,13 @@ int FB_CARG DebugServer::authenticate(Firebird::IStatus* status, IServerBlock* s
writerInterface->add(str.c_str());
str.erase();
Firebird::RefPtr<Firebird::IConfigEntry> group(Firebird::REF_NO_INCR, config->find("GROUP"));
if (group)
{
writerInterface->add(group->getValue());
writerInterface->setType("GROUP");
}
return AUTH_SUCCESS;
}
catch (const Firebird::Exception& ex)

View File

@ -35,6 +35,7 @@
#ifdef AUTH_DEBUG
#include "firebird/Auth.h"
#include "firebird/Plugin.h"
#include "../common/classes/ImplementHelper.h"
#include "../common/classes/ClumpletWriter.h"
#include "../common/classes/init.h"
@ -57,6 +58,7 @@ public:
private:
Firebird::string str;
Firebird::RefPtr<Firebird::IConfig> config;
};
class DebugClient FB_FINAL : public Firebird::StdPlugin<IClient, FB_AUTH_CLIENT_VERSION>

View File

@ -1,42 +1,110 @@
#ifdef INCLUDE_Firebird_H // Internal build
#define INTERNAL_FIREBIRD
#endif
#include "firebird/Provider.h"
#ifdef INTERNAL_FIREBIRD
#include "../common/classes/alloc.h"
#include "../common/classes/auto.h"
#include "../common/StatusHolder.h"
#include "../common/MsgMetadata.h"
#include "../common/classes/ImplementHelper.h"
#else // INTERNAL_FIREBIRD
#include <assert.h>
#define fb_assert(x) assert(x)
#include <string.h>
#endif // INTERNAL_FIREBIRD
#ifdef INTERNAL_FIREBIRD
// This class helps to work with metadata iface
class Meta : public Firebird::RefPtr<Firebird::IMessageMetadata>
{
public:
explicit Meta(Firebird::IStatement* stmt, bool out)
Meta(Firebird::IStatement* stmt, bool out)
{
Firebird::LocalStatus s;
Firebird::IMessageMetadata* m = out ? stmt->getOutputMetadata(&s) : stmt->getInputMetadata(&s);
if (!s.isSuccess())
Firebird::LocalStatus st;
Firebird::IMessageMetadata* m = out ? stmt->getOutputMetadata(&st) : stmt->getInputMetadata(&st);
if (!st.isSuccess())
{
Firebird::status_exception::raise(s.get());
Firebird::status_exception::raise(st.get());
}
assignRefNoIncr(m);
}
};
#endif // INTERNAL_FIREBIRD
// This class helps to fill message with correct values
class Message : public Firebird::GlobalStorage
// Linked list of various fields
class FieldLink
{
public:
Message(Firebird::IMessageMetadata* aMeta)
: dataBuf(getPool()), fieldCount(0)
virtual ~FieldLink() { }
virtual void linkWithMessage(const unsigned char* buf) = 0;
FieldLink* next;
};
// This class helps to exchange values with a message
class Message
// : public AutoStorage
{
public:
Message(Firebird::IMessageMetadata* aMeta = NULL)
: metadata(NULL), buffer(NULL), builder(NULL),
fieldCount(0), fieldList(NULL)
{
Firebird::LocalStatus st;
buffer = dataBuf.getBuffer(aMeta->getMessageLength(&st));
check(&st);
metadata = aMeta;
#ifdef INTERNAL_FIREBIRD
s = &st;
#else
s = fb_get_master_interface()->getStatus();
#endif
try
{
if (aMeta)
{
createBuffer(aMeta);
metadata = aMeta;
metadata->addRef();
}
else
{
Firebird::IMetadataBuilder* bld =
#ifdef INTERNAL_FIREBIRD
Firebird::MasterInterfacePtr()->
#else
fb_get_master_interface()->
#endif
getMetadataBuilder(s, 0);
check(s);
builder = bld;
builder->addRef();
}
}
catch(...)
{
s->dispose();
throw;
}
}
~Message()
{ }
{
delete buffer;
#ifndef INTERNAL_FIREBIRD
s->dispose();
#endif
if (builder)
builder->release();
if (metadata)
metadata->release();
}
public:
template <typename T>
static bool checkType(unsigned t, unsigned /*sz*/)
{
@ -44,25 +112,58 @@ public:
}
template <typename T>
unsigned add(unsigned& t, unsigned& sz)
static unsigned getType(unsigned& sz)
{
Firebird::LocalStatus st;
return T::SQL_UnknownDataType;
}
unsigned l = metadata->getCount(&st);
check(&st);
if (fieldCount >= metadata->getMessageLength(&st))
template <typename T>
unsigned add(unsigned& t, unsigned& sz, FieldLink* lnk)
{
if (metadata)
{
(Firebird::Arg::Gds(isc_random) <<
"Attempt to add to the message more variables than possible").raise();
unsigned l = metadata->getCount(s);
check(s);
if (fieldCount >= l)
{
#ifdef INTERNAL_FIREBIRD
(Firebird::Arg::Gds(isc_random) <<
"Attempt to add to the message more variables than possible").raise();
#else
fatalErrorHandler("Attempt to add to the message more variables than possible");
#endif
}
t = metadata->getType(s, fieldCount);
check(s);
sz = metadata->getLength(s, fieldCount);
check(s);
if (!checkType<T>(t, sz))
{
#ifdef INTERNAL_FIREBIRD
(Firebird::Arg::Gds(isc_random) << "Incompatible data type").raise();
#else
fatalErrorHandler("Incompatible data type");
#endif
}
}
t = metadata->getType(&st, fieldCount);
check(&st);
sz = metadata->getLength(&st, fieldCount);
check(&st);
if (!checkType<T>(t, sz))
else
{
(Firebird::Arg::Gds(isc_random) << "Incompatible data type").raise();
fb_assert(builder);
unsigned f = builder->addField(s);
check(s);
fb_assert(f == fieldCount);
t = getType<T>(sz);
builder->setType(s, f, t);
check(s);
builder->setLength(s, f, sz);
check(s);
lnk->next = fieldList;
fieldList = lnk;
}
return fieldCount++;
@ -72,61 +173,91 @@ public:
{
if (!status->isSuccess())
{
#ifdef INTERNAL_FIREBIRD
Firebird::status_exception::raise(status->get());
#else
char s[100];
const ISC_STATUS *st = status->get();
fb_interpret(s, sizeof(s), &st);
fatalErrorHandler(s);
#endif
}
}
// makes it possible to use metadata in ?: operator
// Attention!
// No addRef/release interface here!
// Lifetime is equal at least to Message lifetime
Firebird::IMessageMetadata* getMetadata()
{
if (!metadata)
{
fb_assert(builder);
Firebird::IMessageMetadata* aMeta = builder->getMetadata(s);
check(s);
metadata = aMeta;
metadata->addRef();
builder->release();
builder = NULL;
}
return metadata;
}
public:
Firebird::RefPtr<Firebird::IMessageMetadata> metadata;
UCHAR* buffer;
bool hasMetadata()
{
return metadata ? true : false;
}
// access to message's data buffer
unsigned char* getBuffer()
{
if (!buffer)
{
getMetadata();
createBuffer(metadata);
while(fieldList)
{
fieldList->linkWithMessage(buffer);
fieldList = fieldList->next;
}
}
return buffer;
}
private:
Firebird::UCharBuffer dataBuf;
void createBuffer(Firebird::IMessageMetadata* aMeta)
{
unsigned l = aMeta->getMessageLength(s);
check(s);
buffer = new unsigned char[l];
}
public:
Firebird::IStatus* s;
private:
#ifdef INTERNAL_FIREBIRD
Firebird::LocalStatus st;
#endif
Firebird::IMessageMetadata* metadata;
unsigned char* buffer;
Firebird::IMetadataBuilder* builder;
unsigned fieldCount;
FieldLink* fieldList;
};
// With template magic, we make the fields strongly-typed.
template <>
bool Message::checkType<SLONG>(unsigned t, unsigned sz)
{
return t == SQL_LONG && sz == sizeof(SLONG);
}
template <>
bool Message::checkType<ISC_QUAD>(unsigned t, unsigned sz)
{
return (t == SQL_BLOB || t == SQL_QUAD) && sz == sizeof(ISC_QUAD);
}
template <>
bool Message::checkType<ISC_INT64>(unsigned t, unsigned sz)
{
return t == SQL_INT64 && sz == sizeof(ISC_INT64);
}
template <>
bool Message::checkType<FB_BOOLEAN>(unsigned t, unsigned sz)
{
return t == SQL_BOOLEAN && sz == sizeof(FB_BOOLEAN);
}
template <typename T>
class Field
class Field : public FieldLink
{
public:
class Null
{
public:
Null()
: ptr(NULL)
Null(Message* m)
: msg(m), ptr(NULL)
{ }
void linkMessage(short* p)
@ -137,46 +268,57 @@ public:
operator FB_BOOLEAN() const
{
msg->getBuffer();
return (*ptr) ? FB_TRUE : FB_FALSE;
}
FB_BOOLEAN operator=(FB_BOOLEAN val)
{
msg->getBuffer();
*ptr = val ? -1 : 0;
return val;
}
private:
Message* msg;
short* ptr;
};
explicit Field(Message& m)
: ptr(NULL), type(0), size(0)
explicit Field(Message& m, unsigned sz = 0)
: ptr(NULL), charBuffer(NULL), msg(&m), null(msg), ind(~0), type(0), size(sz)
{
unsigned ind = m.add<T>(type, size);
ind = msg->add<T>(type, size, this);
Firebird::LocalStatus st;
unsigned tmp = m.metadata->getOffset(&st, ind);
Message::check(&st);
ptr = (T*) (m.buffer + tmp);
if (msg->hasMetadata())
setPointers(msg->getBuffer());
}
tmp = m.metadata->getNullOffset(&st, ind);
Message::check(&st);
null.linkMessage((short*) (m.buffer + tmp));
~Field()
{
delete charBuffer;
}
operator T()
{
msg->getBuffer();
return *ptr;
}
T* operator&()
{
msg->getBuffer();
return ptr;
}
T* operator->()
{
msg->getBuffer();
return ptr;
}
T operator= (T newVal)
{
msg->getBuffer();
*ptr = newVal;
null = FB_FALSE;
return newVal;
@ -184,49 +326,71 @@ public:
operator const char*()
{
msg->getBuffer();
if (!charBuffer)
{
charBuffer.reset(FB_NEW(*getDefaultMemoryPool()) char[size + 1]);
charBuffer = new char[size + 1];
}
getStrValue(charBuffer);
return charBuffer;
}
const char* operator= (const char* newVal)
{
setStrValue(newVal, strlen(newVal));
msg->getBuffer();
setStrValue(newVal, strnlen(newVal, size));
null = FB_FALSE;
return newVal;
}
void set(unsigned length, const void* newVal)
{
msg->getBuffer();
setStrValue(newVal, length);
null = FB_FALSE;
}
private:
void linkWithMessage(const unsigned char* buf)
{
setPointers(buf);
}
void setPointers(const unsigned char* buf)
{
unsigned tmp = msg->getMetadata()->getOffset(msg->s, ind);
Message::check(msg->s);
ptr = (T*) (buf + tmp);
tmp = msg->getMetadata()->getNullOffset(msg->s, ind);
Message::check(msg->s);
null.linkMessage((short*) (buf + tmp));
}
void getStrValue(char* to)
{
T::incompatibleDataType();
//(Firebird::Arg::Gds(isc_random) << "Incompatible data type").raise();
}
void setStrValue(const void* from, unsigned len)
{
T::incompatibleDataType();
//(Firebird::Arg::Gds(isc_random) << "Incompatible data type").raise();
}
T* ptr;
Firebird::AutoPtr<char, Firebird::ArrayDelete<char> > charBuffer;
char* charBuffer;
Message* msg;
public:
Null null;
unsigned type, size;
private:
unsigned ind, type, size;
};
// ---------------------------------------------
struct Varying
{
short len;
@ -234,13 +398,22 @@ struct Varying
};
template <>
bool Message::checkType<Varying>(unsigned t, unsigned /*sz*/)
inline bool Message::checkType<Varying>(unsigned t, unsigned /*sz*/)
{
return t == SQL_VARYING;
}
template <>
inline unsigned Message::getType<Varying>(unsigned& sz)
{
if (!sz)
sz = 1;
sz += sizeof(short);
return SQL_VARYING;
}
template<>
void Field<Varying>::getStrValue(char* to)
inline void Field<Varying>::getStrValue(char* to)
{
unsigned len = ptr->len;
if (len > size)
@ -250,7 +423,7 @@ void Field<Varying>::getStrValue(char* to)
}
template<>
void Field<Varying>::setStrValue(const void* from, unsigned len)
inline void Field<Varying>::setStrValue(const void* from, unsigned len)
{
if (len > size)
len = size;
@ -264,13 +437,21 @@ struct Text
};
template <>
bool Message::checkType<Text>(unsigned t, unsigned /*sz*/)
inline bool Message::checkType<Text>(unsigned t, unsigned /*sz*/)
{
return t == SQL_TEXT;
}
template <>
inline unsigned Message::getType<Text>(unsigned& sz)
{
if (!sz)
sz = 1;
return SQL_TEXT;
}
template<>
void Field<Text>::getStrValue(char* to)
inline void Field<Text>::getStrValue(char* to)
{
memcpy(to, ptr->data, size);
to[size] = 0;
@ -285,7 +466,7 @@ void Field<Text>::getStrValue(char* to)
}
template<>
void Field<Text>::setStrValue(const void* from, unsigned len)
inline void Field<Text>::setStrValue(const void* from, unsigned len)
{
if (len > size)
len = size;
@ -293,3 +474,68 @@ void Field<Text>::setStrValue(const void* from, unsigned len)
if (len < size)
memset(&ptr->data[len], ' ', size - len);
}
template <>
inline bool Message::checkType<ISC_SHORT>(unsigned t, unsigned sz)
{
return t == SQL_SHORT && sz == sizeof(ISC_SHORT);
}
template <>
inline bool Message::checkType<ISC_LONG>(unsigned t, unsigned sz)
{
return t == SQL_LONG && sz == sizeof(ISC_LONG);
}
template <>
inline bool Message::checkType<ISC_QUAD>(unsigned t, unsigned sz)
{
return (t == SQL_BLOB || t == SQL_QUAD) && sz == sizeof(ISC_QUAD);
}
template <>
inline bool Message::checkType<ISC_INT64>(unsigned t, unsigned sz)
{
return t == SQL_INT64 && sz == sizeof(ISC_INT64);
}
template <>
inline bool Message::checkType<FB_BOOLEAN>(unsigned t, unsigned sz)
{
return t == SQL_BOOLEAN && sz == sizeof(FB_BOOLEAN);
}
template <>
inline unsigned Message::getType<ISC_SHORT>(unsigned& sz)
{
sz = sizeof(ISC_SHORT);
return SQL_SHORT;
}
template <>
inline unsigned Message::getType<ISC_LONG>(unsigned& sz)
{
sz = sizeof(ISC_LONG);
return SQL_LONG;
}
template <>
inline unsigned Message::getType<ISC_QUAD>(unsigned& sz)
{
sz = sizeof(ISC_QUAD);
return SQL_BLOB;
}
template <>
inline unsigned Message::getType<ISC_INT64>(unsigned& sz)
{
sz = sizeof(ISC_INT64);
return SQL_INT64;
}
template <>
inline unsigned Message::getType<FB_BOOLEAN>(unsigned& sz)
{
sz = sizeof(FB_BOOLEAN);
return SQL_BOOLEAN;
}

View File

@ -75,7 +75,7 @@ public:
"SELECT PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$COMMENT, "
" PLG$FIRST, PLG$MIDDLE, PLG$LAST, PLG$ATTRIBUTES, PLG$ACTIVE "
"FROM PLG$SRP WHERE CURRENT_USER = 'SYSDBA' "
" OR CURRENT_ROLE = 'RDB$ADMIN' OR CURRENT_USER = PLG$SRP.PLG$USER_NAME"
" OR CURRENT_ROLE = '" ADMIN_ROLE "' OR CURRENT_USER = PLG$SRP.PLG$USER_NAME"
,
"GRANT ALL ON PLG$SRP to VIEW PLG$SRP_VIEW"
,
@ -94,7 +94,7 @@ public:
{
for (const char** sql = script; *sql; ++sql)
{
att->execute(&s, ddlTran, 0, *sql, 3, NULL, NULL, NULL, NULL);
att->execute(&s, ddlTran, 0, *sql, SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
check(&s);
}
@ -143,19 +143,24 @@ public:
unsigned int authBlockSize = logonInfo->authBlock(&authBlock);
if (authBlockSize)
{
#if SRP_DEBUG > 0
fprintf(stderr, "SrpManagement: Using authBlock size %d\n", authBlockSize);
#endif
dpb.insertBytes(isc_dpb_auth_block, authBlock, authBlockSize);
}
else
{
const char* str = logonInfo->name();
#if SRP_DEBUG > 0
fprintf(stderr, "SrpManagement: Using name '%s'\n", str);
#endif
if (str && str[0])
dpb.insertString(isc_dpb_trusted_auth, str, strlen(str));
str = logonInfo->role();
if (str && str[0])
dpb.insertString(isc_dpb_sql_role_name, str, strlen(str));
else if (logonInfo->forceAdmin())
dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE));
}
Firebird::DispatcherPtr p;
@ -200,9 +205,9 @@ public:
case MAP_SET_OPER:
{
Firebird::string sql;
sql.printf("ALTER ROLE RDB$ADMIN %s AUTO ADMIN MAPPING",
sql.printf("ALTER ROLE " ADMIN_ROLE " %s AUTO ADMIN MAPPING",
user->operation() == MAP_SET_OPER ? "SET" : "DROP");
att->execute(status, tra, sql.length(), sql.c_str(), 3, NULL, NULL, NULL, NULL);
att->execute(status, tra, sql.length(), sql.c_str(), SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
check(status);
}
break;
@ -218,7 +223,7 @@ public:
{
for (unsigned repeat = 0; ; ++repeat)
{
stmt = att->prepare(status, tra, 0, insert, 3, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
stmt = att->prepare(status, tra, 0, insert, SQL_DIALECT_V6, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
if (status->isSuccess())
{
break;
@ -286,7 +291,7 @@ public:
dumpIt("verifier", s);
verifier.set(s.getCount(), s.begin());
stmt->execute(status, tra, add.metadata, add.buffer, NULL, NULL);
stmt->execute(status, tra, add.getMetadata(), add.getBuffer(), NULL, NULL);
check(status);
stmt->free(status);
@ -333,7 +338,7 @@ public:
Firebird::IStatement* stmt = NULL;
try
{
stmt = att->prepare(status, tra, 0, update.c_str(), 3, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
stmt = att->prepare(status, tra, 0, update.c_str(), SQL_DIALECT_V6, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
check(status);
Meta im(stmt, false);
@ -381,7 +386,7 @@ public:
assignField(active, user->active());
setField(login, user->userName());
stmt->execute(status, tra, up.metadata, up.buffer, NULL, NULL);
stmt->execute(status, tra, up.getMetadata(), up.getBuffer(), NULL, NULL);
check(status);
if (!checkCount(status, &upCount, isc_info_update_count))
@ -410,7 +415,7 @@ public:
Firebird::IStatement* stmt = NULL;
try
{
stmt = att->prepare(status, tra, 0, del, 3, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
stmt = att->prepare(status, tra, 0, del, SQL_DIALECT_V6, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
check(status);
Meta im(stmt, false);
@ -418,7 +423,7 @@ public:
Name login(dl);
setField(login, user->userName());
stmt->execute(status, tra, dl.metadata, dl.buffer, NULL, NULL);
stmt->execute(status, tra, dl.getMetadata(), dl.getBuffer(), NULL, NULL);
check(status);
if (!checkCount(status, &delCount, isc_info_delete_count))
@ -448,7 +453,7 @@ public:
" CASE WHEN RDB$RELATION_NAME IS NULL THEN 0 ELSE 1 END, PLG$ACTIVE "
"FROM PLG$SRP_VIEW LEFT JOIN RDB$USER_PRIVILEGES "
" ON PLG$SRP_VIEW.PLG$USER_NAME = RDB$USER_PRIVILEGES.RDB$USER "
" AND RDB$RELATION_NAME = 'RDB$ADMIN' "
" AND RDB$RELATION_NAME = '" ADMIN_ROLE "' "
" AND RDB$PRIVILEGE = 'M' ";
if (user->userName()->entered())
{
@ -459,7 +464,7 @@ public:
Firebird::IResultSet* rs = NULL;
try
{
stmt = att->prepare(status, tra, 0, disp.c_str(), 3,
stmt = att->prepare(status, tra, 0, disp.c_str(), SQL_DIALECT_V6,
Firebird::IStatement::PREPARE_PREFETCH_METADATA);
check(status);
@ -481,10 +486,10 @@ public:
}
rs = stmt->openCursor(status, tra, (par ? par->getMetadata() : NULL),
(par ? par->buffer : NULL), om);
(par ? par->getBuffer() : NULL), om);
check(status);
while (rs->fetchNext(status, di.buffer))
while (rs->fetchNext(status, di.getBuffer()))
{
check(status);

View File

@ -174,7 +174,8 @@ int SrpServer::authenticate(IStatus* status, IServerBlock* sb, IWriter* writerIn
Field<Varying> slt(dat);
HANDSHAKE_DEBUG(fprintf(stderr, "Srv: SRP1: Ready to run statement with login '%s'\n", account.c_str()));
stmt->execute(status, tra, par.metadata, par.buffer, dat.metadata, dat.buffer);
stmt->execute(status, tra, par.getMetadata(), par.getBuffer(),
dat.getMetadata(), dat.getBuffer());
if (!status->isSuccess())
{
status_exception::raise(status->get());
@ -266,7 +267,7 @@ int SrpServer::authenticate(IStatus* status, IServerBlock* sb, IWriter* writerIn
{
MasterInterfacePtr()->upgradeInterface(writerInterface, FB_AUTH_WRITER_VERSION, upInfo);
writerInterface->add(account.c_str());
writerInterface->setAttribute(AuthReader::AUTH_SECURE_DB, secDbName);
writerInterface->setDb(secDbName);
return AUTH_SUCCESS;
}
}

View File

@ -68,7 +68,7 @@ static bool grantRevokeAdmin(ISC_STATUS* isc_status, FB_API_HANDLE database, FB_
Firebird::string sql;
sql.printf((user->admin()->get() ? "GRANT %s TO \"%s\"" : "REVOKE %s FROM \"%s\""),
"RDB$ADMIN", userName.c_str());
ADMIN_ROLE, userName.c_str());
isc_dsql_execute_immediate(isc_status, &database, &trans, sql.length(), sql.c_str(), SQL_DIALECT_V6, NULL);
if (isc_status[1] && user->admin()->get() == 0)
@ -79,7 +79,7 @@ static bool grantRevokeAdmin(ISC_STATUS* isc_status, FB_API_HANDLE database, FB_
WITH R.RDB$USER EQ user->userName()->get()
AND R.RDB$RELATION_NAME EQ 'RDB$ADMIN'
AND R.RDB$PRIVILEGE EQ 'M'
sql.printf("REVOKE RDB$ADMIN FROM \"%s\" GRANTED BY \"%s\"",
sql.printf("REVOKE " ADMIN_ROLE " FROM \"%s\" GRANTED BY \"%s\"",
userName.c_str(), R.RDB$GRANTOR);
END_FOR
@ -162,11 +162,8 @@ void FB_CARG SecurityDatabaseManagement::start(Firebird::IStatus* st, ILogonInfo
dpb.insertString(isc_dpb_trusted_auth, str, strlen(str));
str = logonInfo->role();
if (str && str[0])
dpb.insertString(isc_dpb_sql_role_name, str, strlen(str));
else if (logonInfo->forceAdmin())
dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE));
}
ISC_STATUS_ARRAY status;
@ -350,7 +347,7 @@ int FB_CARG SecurityDatabaseManagement::execute(Firebird::IStatus* st, IUser* us
case MAP_SET_OPER:
{
Firebird::string sql;
sql.printf("ALTER ROLE RDB$ADMIN %s AUTO ADMIN MAPPING",
sql.printf("ALTER ROLE " ADMIN_ROLE " %s AUTO ADMIN MAPPING",
user->operation() == MAP_SET_OPER ? "SET" : "DROP");
isc_dsql_execute_immediate(isc_status, &database, &transaction, sql.length(), sql.c_str(), 1, NULL);
if (isc_status[1] != 0)

View File

@ -351,7 +351,7 @@ int SecurityDatabase::verify(IWriter* authBlock, IServerBlock* sBlock)
MasterInterfacePtr()->upgradeInterface(authBlock, FB_AUTH_WRITER_VERSION, upInfo);
authBlock->add(login.c_str());
authBlock->setAttribute(AuthReader::AUTH_SECURE_DB, secureDbName);
authBlock->setDb(secureDbName);
return AUTH_SUCCESS;
}

View File

@ -369,7 +369,12 @@ int WinSspiServer::authenticate(Firebird::IStatus* status,
writerInterface->add(login.c_str());
if (wheel)
writerInterface->add("RDB$ADMIN");
{
writerInterface->add(FB_DOMAIN_ANY_RID_ADMINS);
writerInterface->setType(FB_PREDEFINED_GROUP);
}
// ToDo: walk groups to which login belongs and list them using writerInterface
return AUTH_SUCCESS;
}

View File

@ -30,6 +30,10 @@
#include <firebird.h>
// This is old versions backward compatibility
#define FB_PREDEFINED_GROUP "Predefined_Group"
#define FB_DOMAIN_ANY_RID_ADMINS "DOMAIN_ANY_RID_ADMINS"
#ifdef TRUSTED_AUTH
#include <../common/classes/fb_string.h>

View File

@ -4073,16 +4073,45 @@ void write_mapping()
*
**************************************/
isc_req_handle req_handle = 0;
TEXT temp[GDS_NAME_LEN];
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
if (tdgbl->runtimeODS >= DB_VERSION_DDL11_2)
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
FOR (REQUEST_HANDLE req_handle)
M IN RDB$MAP
WITH (M.RDB$SYSTEM_FLAG EQ 0 OR M.RDB$SYSTEM_FLAG MISSING)
put(tdgbl, rec_mapping);
const SSHORT l = PUT_TEXT(att_map_name, M.RDB$MAP_NAME);
PUT_TEXT(att_map_using, M.RDB$MAP_USING);
if (!M.RDB$MAP_PLUGIN.NULL) PUT_TEXT(att_map_plugin, M.RDB$MAP_PLUGIN);
if (!M.RDB$MAP_DB.NULL) PUT_TEXT(att_map_db, M.RDB$MAP_DB);
PUT_TEXT(att_map_from_type, M.RDB$MAP_FROM_TYPE);
if (!M.RDB$MAP_FROM.NULL) PUT_TEXT(att_map_from, M.RDB$MAP_FROM);
put_int32(att_map_to_type, M.RDB$MAP_TO_TYPE);
if (!M.RDB$MAP_TO.NULL) PUT_TEXT(att_map_to, M.RDB$MAP_TO);
if (!M.RDB$DESCRIPTION.NULL)
put_source_blob(att_map_description, att_map_description, M.RDB$DESCRIPTION);
put(tdgbl, att_end);
MISC_terminate (M.RDB$MAP_NAME, temp, l, sizeof(temp));
BURP_verbose (297, temp);
// msg 297 writing mapping for %s
END_FOR;
ON_ERROR
general_on_error();
END_ERROR;
}
else if (tdgbl->runtimeODS >= DB_VERSION_DDL11_2)
{
FOR (REQUEST_HANDLE req_handle)
X IN RDB$ROLES
WITH X.RDB$ROLE_NAME EQ ADMIN_ROLE
if (X.RDB$SYSTEM_FLAG == (ROLE_FLAG_MAY_TRUST | ROLE_FLAG_DBO))
if (X.RDB$SYSTEM_FLAG == ROLE_FLAG_DBO)
{
put(tdgbl, rec_mapping);
//put_text(att_map_os, DOMAIN-ADMINS, strlen(DOMAIN-ADMINS) + 1);

View File

@ -683,7 +683,7 @@ int gbak(Firebird::UtilSvc* uSvc)
}
tdgbl->gbl_sw_user = argv[itr];
break;
case IN_SW_BURP_TRUSTED_USER:
/* case IN_SW_BURP_TRUSTED_USER:
uSvc->checkService();
if (++itr >= argc)
{
@ -692,7 +692,7 @@ int gbak(Firebird::UtilSvc* uSvc)
}
tdgbl->gbl_sw_tr_user = argv[itr];
break;
case IN_SW_BURP_ROLE:
*/ case IN_SW_BURP_ROLE:
if (++itr >= argc)
{
BURP_error(253, true);
@ -1029,7 +1029,7 @@ int gbak(Firebird::UtilSvc* uSvc)
}
break;
case IN_SW_BURP_TRUSTED_USER:
/* case IN_SW_BURP_TRUSTED_USER:
uSvc->checkService();
if (!authBlock)
{
@ -1046,7 +1046,7 @@ int gbak(Firebird::UtilSvc* uSvc)
dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE));
}
break;
*/
#ifdef TRUSTED_AUTH
case IN_SW_BURP_TRUSTED_AUTH:
if (!dpb.find(isc_dpb_trusted_auth))

View File

@ -596,10 +596,16 @@ enum att_type {
att_coll_owner_name,
// Names mapping
att_map_os = SERIES,
att_map_user,
att_map_role,
att_auto_map_role,
att_map_name = SERIES,
att_map_using,
att_map_plugin,
att_auto_map_role, // Keep it at pos.4 - ODS11.2 compatibility issue
att_map_db,
att_map_from_type,
att_map_from,
att_map_to_type,
att_map_to,
att_map_description,
// Package attributes
att_package_name = SERIES,

View File

@ -171,8 +171,8 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
{IN_SW_BURP_TRUSTED_AUTH, 0, "TRUSTED", 0, 0, 0, false, 295, 3, NULL, boGeneral},
// msg 295: @1TRU(STED) use trusted authentication
#endif
{IN_SW_BURP_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL, boGeneral},
{IN_SW_BURP_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL, boGeneral},
// {IN_SW_BURP_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL, boGeneral},
// {IN_SW_BURP_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL, boGeneral},
/*
{IN_SW_BURP_U, 0, "UNPROTECTED", 0, 0, 0, false, 0, 5, NULL, boGeneral},
*/

View File

@ -54,6 +54,7 @@
#include "../common/utils_proto.h"
#include "memory_routines.h"
#include "../burp/OdsDetection.h"
#include "../auth/trusted/AuthSspi.h"
using MsgFormat::SafeArg;
@ -7971,38 +7972,156 @@ bool get_mapping(BurpGlobals* tdgbl)
*
* Functional description
* Restore mapping to users and roles
* Restricted version - only single
* mapping is accepted
*
**************************************/
att_type attribute;
scan_attr_t scan_next_attr;
TEXT temp[GDS_NAME_LEN];
SSHORT l;
Firebird::string role, os;
Firebird::string role;
if (tdgbl->runtimeODS >= DB_VERSION_DDL11_1)
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
STORE (REQUEST_HANDLE tdgbl->handles_get_mapping_req_handle1)
M IN RDB$MAP
M.RDB$MAP_TO_TYPE.NULL = TRUE;
M.RDB$MAP_NAME.NULL = TRUE;
M.RDB$MAP_USING.NULL = TRUE;
M.RDB$MAP_PLUGIN.NULL = TRUE;
M.RDB$MAP_DB.NULL = TRUE;
M.RDB$MAP_FROM_TYPE.NULL = TRUE;
M.RDB$MAP_FROM.NULL = TRUE;
M.RDB$MAP_TO.NULL = TRUE;
M.RDB$DESCRIPTION.NULL = TRUE;
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
{
switch (attribute)
{
case att_auto_map_role:
GET_TEXT(temp);
M.RDB$MAP_NAME.NULL = FALSE;
strcpy(M.RDB$MAP_NAME, "AutoAdminImplementationMapping");
M.RDB$MAP_FROM.NULL = FALSE;
strcpy(M.RDB$MAP_FROM, FB_DOMAIN_ANY_RID_ADMINS);
M.RDB$MAP_FROM_TYPE.NULL = FALSE;
strcpy(M.RDB$MAP_FROM_TYPE, FB_PREDEFINED_GROUP);
M.RDB$MAP_USING.NULL = FALSE;
strcpy(M.RDB$MAP_USING, "P");
M.RDB$MAP_PLUGIN.NULL = FALSE;
strcpy(M.RDB$MAP_PLUGIN, "Win_Sspi");
M.RDB$MAP_TO_TYPE.NULL = FALSE;
M.RDB$MAP_TO_TYPE = 1;
M.RDB$MAP_TO.NULL = FALSE;
strcpy(M.RDB$MAP_TO, ADMIN_ROLE);
BURP_verbose(301);
// msg 301, restoring names mapping
BURP_verbose (298, M.RDB$MAP_NAME);
break;
case att_map_name:
M.RDB$MAP_NAME.NULL = FALSE;
GET_TEXT(M.RDB$MAP_NAME);
if (tdgbl->firstMap)
{
tdgbl->firstMap = false;
BURP_verbose(301);
// msg 301, restoring names mapping
}
BURP_verbose (298, M.RDB$MAP_NAME);
break;
case att_map_using:
M.RDB$MAP_USING.NULL = FALSE;
GET_TEXT(M.RDB$MAP_USING);
break;
case att_map_plugin:
M.RDB$MAP_PLUGIN.NULL = FALSE;
GET_TEXT(M.RDB$MAP_PLUGIN);
break;
case att_map_db:
M.RDB$MAP_DB.NULL = FALSE;
GET_TEXT(M.RDB$MAP_DB);
break;
case att_map_from_type:
M.RDB$MAP_FROM_TYPE.NULL = FALSE;
GET_TEXT(M.RDB$MAP_FROM_TYPE);
break;
case att_map_from:
M.RDB$MAP_FROM.NULL = FALSE;
GET_TEXT(M.RDB$MAP_FROM);
break;
case att_map_to_type:
M.RDB$MAP_TO_TYPE.NULL = FALSE;
M.RDB$MAP_TO_TYPE = (USHORT) get_int32(tdgbl);
break;
case att_map_to:
M.RDB$MAP_TO.NULL = FALSE;
GET_TEXT(M.RDB$MAP_TO);
break;
case att_map_description:
M.RDB$DESCRIPTION.NULL = FALSE;
get_source_blob (tdgbl, M.RDB$DESCRIPTION, false);
break;
default:
// msg 299 name mapping
bad_attribute(scan_next_attr, attribute, 299);
break;
}
}
if (M.RDB$MAP_NAME.NULL || M.RDB$MAP_USING.NULL ||
M.RDB$MAP_FROM_TYPE.NULL || M.RDB$MAP_TO_TYPE.NULL)
{
// msg 353 required mapping attributes are missing in backup file
BURP_error(353, true);
}
END_STORE;
ON_ERROR
general_on_error ();
END_ERROR;
}
else if (tdgbl->runtimeODS >= DB_VERSION_DDL11_1)
{
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
{
switch (attribute)
{
/* case att_map_role:
l = GET_TEXT(temp);
role.assign(temp, l);
break;
case att_map_os:
l = GET_TEXT(temp);
os.assign(temp, l);
break;
*/
case att_auto_map_role:
l = GET_TEXT(temp);
role.assign(temp, l);
break;
case att_map_to_type:
get_int32(tdgbl);
break;
case att_map_name:
case att_map_using:
case att_map_plugin:
case att_map_db:
case att_map_from_type:
case att_map_from:
case att_map_to:
GET_TEXT(temp);
break;
case att_map_description:
eat_blob(tdgbl);
default:
// msg 299 name mapping
bad_attribute(scan_next_attr, attribute, 299);
@ -8015,24 +8134,25 @@ bool get_mapping(BurpGlobals* tdgbl)
return true; // silently skip attributes on old server
}
if (role != ADMIN_ROLE)
{
BURP_error(300, false);
return true;
}
if (tdgbl->firstMap)
{
tdgbl->firstMap = false;
BURP_verbose(301);
// msg 301, restoring names mapping
}
if (role != ADMIN_ROLE)
{
BURP_error(300, false);
return true;
}
BURP_verbose(298, ADMIN_ROLE);
// msg 298, restoring map @1
Firebird::string sql;
sql.printf("%s ('%s', %d) %s",
"UPDATE OR INSERT INTO RDB$ROLES(RDB$ROLE_NAME, RDB$SYSTEM_FLAG) VALUES",
ADMIN_ROLE, ROLE_FLAG_MAY_TRUST | ROLE_FLAG_DBO,
ADMIN_ROLE, ROLE_FLAG_DBO,
"MATCHING (RDB$ROLE_NAME)");
isc_dsql_execute_immediate(tdgbl->status_vector, &tdgbl->db_handle, &tdgbl->tr_handle,
sql.length(), sql.c_str(), 1, NULL);

View File

@ -30,6 +30,7 @@
#include "../jrd/ibase.h"
#include "../common/classes/ImplementHelper.h"
#include "../common/utils_proto.h"
#include "../common/db_alias.h"
using namespace Firebird;
@ -38,7 +39,7 @@ namespace Auth {
WriterImplementation::WriterImplementation()
: current(*getDefaultMemoryPool(), ClumpletReader::WideUnTagged, MAX_DPB_SIZE),
result(*getDefaultMemoryPool(), ClumpletReader::WideUnTagged, MAX_DPB_SIZE),
method(*getDefaultMemoryPool()),
plugin(*getDefaultMemoryPool()), type(*getDefaultMemoryPool()),
sequence(0)
{ }
@ -65,16 +66,17 @@ void WriterImplementation::add(const char* name)
current.clear();
current.insertString(AuthReader::AUTH_NAME, name);
fb_assert(method.hasData());
if (method.hasData())
fb_assert(plugin.hasData());
if (plugin.hasData())
{
current.insertString(AuthReader::AUTH_METHOD, method);
current.insertString(AuthReader::AUTH_PLUGIN, plugin);
}
type = "USER";
}
void WriterImplementation::setMethod(const char* m)
void WriterImplementation::setPlugin(const char* m)
{
method = m;
plugin = m;
}
void WriterImplementation::putLevel()
@ -84,15 +86,24 @@ void WriterImplementation::putLevel()
{
return;
}
current.insertString(AuthReader::AUTH_TYPE, type);
result.insertBytes(sequence++, current.getBuffer(), current.getBufferLength());
}
void WriterImplementation::setAttribute(unsigned char tag, const char* value)
void WriterImplementation::setType(const char* value)
{
if (value)
type = value;
}
void WriterImplementation::setDb(const char* value)
{
if (value)
{
current.insertString(tag, value);
PathName target;
expandDatabaseName(value, target, NULL);
current.insertPath(AuthReader::AUTH_SECURE_DB, target);
}
}

View File

@ -45,16 +45,17 @@ public:
WriterImplementation();
void store(Firebird::ClumpletWriter* to, unsigned char tag);
void setMethod(const char* m);
void setPlugin(const char* m);
// IWriter implementation
void FB_CARG reset();
void FB_CARG add(const char* name);
void FB_CARG setAttribute(unsigned char tag, const char* value);
void FB_CARG setType(const char* value);
void FB_CARG setDb(const char* value);
private:
Firebird::ClumpletWriter current, result;
Firebird::string method;
Firebird::string plugin, type;
unsigned int sequence;
void putLevel();

View File

@ -29,234 +29,246 @@
#include "../common/StatusHolder.h"
#include "../jrd/align.h"
using namespace Firebird;
namespace Firebird {
namespace {
class MetadataBuilder FB_FINAL : public RefCntIface<IMetadataBuilder, FB_METADATA_BUILDER_VERSION>
MetadataBuilder::MetadataBuilder(const MsgMetadata* from)
: msgMetadata(new MsgMetadata)
{
public:
MetadataBuilder(const MsgMetadata* from)
: msgMetadata(new MsgMetadata)
msgMetadata->items = from->items;
}
MetadataBuilder::MetadataBuilder(unsigned fieldCount)
: msgMetadata(new MsgMetadata)
{
if (fieldCount)
msgMetadata->items.grow(fieldCount);
}
int FB_CARG MetadataBuilder::release()
{
if (--refCounter != 0)
{
msgMetadata->items = from->items;
return 1;
}
virtual int FB_CARG release()
delete this;
return 0;
}
void FB_CARG MetadataBuilder::setType(IStatus* status, unsigned index, unsigned type)
{
try
{
if (--refCounter != 0)
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setType");
msgMetadata->items[index].type = type;
if (!msgMetadata->items[index].length)
{
return 1;
unsigned dtype;
fb_utils::sqlTypeToDsc(0, type, 0, &dtype, NULL, NULL, NULL);
if (dtype < DTYPE_TYPE_MAX)
msgMetadata->items[index].length = type_lengths[dtype];
}
delete this;
return 0;
// Setting type & length is enough for an item to be ready for use
if (msgMetadata->items[index].length)
msgMetadata->items[index].finished = true;
}
// IMetadataBuilder implementation
virtual void FB_CARG setType(IStatus* status, unsigned index, unsigned type)
catch (const Exception& ex)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
ex.stuffException(status);
}
}
indexError(index, "setType");
msgMetadata->items[index].type = type;
if (!msgMetadata->items[index].length)
void FB_CARG MetadataBuilder::setSubType(IStatus* status, unsigned index, int subType)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setSubType");
msgMetadata->items[index].subType = subType;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void FB_CARG MetadataBuilder::setLength(IStatus* status, unsigned index, unsigned length)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setLength");
msgMetadata->items[index].length = length;
// Setting type & length is enough for an item to be ready for use
if (msgMetadata->items[index].type)
msgMetadata->items[index].finished = true;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void FB_CARG MetadataBuilder::setCharSet(IStatus* status, unsigned index, unsigned charSet)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setCharSet");
msgMetadata->items[index].charSet = charSet;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void FB_CARG MetadataBuilder::setScale(IStatus* status, unsigned index, unsigned scale)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setScale");
msgMetadata->items[index].scale = scale;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void FB_CARG MetadataBuilder::truncate(IStatus* status, unsigned count)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
if (count != 0)
indexError(count - 1, "truncate");
msgMetadata->items.shrink(count);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void FB_CARG MetadataBuilder::remove(IStatus* status, unsigned index)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "remove");
msgMetadata->items.remove(index);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void FB_CARG MetadataBuilder::moveNameToIndex(IStatus* status, const char* name, unsigned index)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "moveNameToIndex");
for (ObjectsArray<MsgMetadata::Item>::iterator i = msgMetadata->items.begin();
i != msgMetadata->items.end();
++i)
{
if (i->field == name)
{
unsigned dtype;
fb_utils::sqlTypeToDsc(0, type, 0, &dtype, NULL, NULL, NULL);
if (dtype < DTYPE_TYPE_MAX)
msgMetadata->items[index].length = type_lengths[dtype];
MsgMetadata::Item copy(getPool(), *i);
msgMetadata->items.remove(i);
msgMetadata->items.insert(index, copy);
return;
}
}
// Setting type & length is enough for an item to be ready for use
if (msgMetadata->items[index].length)
msgMetadata->items[index].finished = true;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
(Arg::Gds(isc_random) << (string("Name not found in IMetadataBuilder: ") + name)).raise();
}
virtual void FB_CARG setSubType(IStatus* status, unsigned index, int subType)
catch (const Exception& ex)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setSubType");
msgMetadata->items[index].subType = subType;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
ex.stuffException(status);
}
}
virtual void FB_CARG setLength(IStatus* status, unsigned index, unsigned length)
unsigned FB_CARG MetadataBuilder::addField(IStatus* status)
{
try
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setLength");
msgMetadata->items[index].length = length;
metadataError("addField");
// Setting type & length is enough for an item to be ready for use
if (msgMetadata->items[index].type)
msgMetadata->items[index].finished = true;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
msgMetadata->items.add();
return msgMetadata->items.getCount() - 1;
}
virtual void FB_CARG setCharSet(IStatus* status, unsigned index, unsigned charSet)
catch (const Exception& ex)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setCharSet");
msgMetadata->items[index].charSet = charSet;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
ex.stuffException(status);
return ~0;
}
}
virtual void FB_CARG setScale(IStatus* status, unsigned index, unsigned scale)
IMessageMetadata* FB_CARG MetadataBuilder::getMetadata(IStatus* status)
{
try
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "setScale");
msgMetadata->items[index].scale = scale;
}
catch (const Exception& ex)
metadataError("getMetadata");
unsigned i = msgMetadata->makeOffsets();
if (i != ~0u)
{
ex.stuffException(status);
(Arg::Gds(isc_item_finish) << Arg::Num(i)).raise();
}
IMessageMetadata* rc = msgMetadata;
rc->addRef();
msgMetadata = NULL;
return rc;
}
virtual void FB_CARG truncate(IStatus* status, unsigned count)
catch (const Exception& ex)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
if (count != 0)
indexError(count - 1, "truncate");
msgMetadata->items.shrink(count);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
ex.stuffException(status);
}
return NULL;
}
virtual void FB_CARG remove(IStatus* status, unsigned index)
void MetadataBuilder::metadataError(const char* functionName)
{
if (!msgMetadata)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "remove");
msgMetadata->items.remove(index);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
(Arg::Gds(isc_random) << (string("IMetadataBuilder interface is already inactive: "
"IMetadataBuilder::") + functionName)).raise();
}
}
virtual void FB_CARG moveNameToIndex(IStatus* status, const char* name, unsigned index)
void MetadataBuilder::indexError(unsigned index, const char* functionName)
{
metadataError(functionName);
if (index >= msgMetadata->items.getCount())
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
indexError(index, "moveNameToIndex");
for (ObjectsArray<MsgMetadata::Item>::iterator i = msgMetadata->items.begin();
i != msgMetadata->items.end();
++i)
{
if (i->field == name)
{
MsgMetadata::Item copy(getPool(), *i);
msgMetadata->items.remove(i);
msgMetadata->items.insert(index, copy);
return;
}
}
(Arg::Gds(isc_random) << (string("Name not found in IMetadataBuilder: ") + name)).raise();
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
(Arg::Gds(isc_invalid_index_val) << Arg::Num(index) << (string("IMetadataBuilder::") +
functionName)).raise();
}
virtual IMessageMetadata* FB_CARG getMetadata(IStatus* status)
{
try
{
MutexLockGuard g(mtx, FB_FUNCTION);
metadataError("getMetadata");
unsigned i = msgMetadata->makeOffsets();
if (i != ~0u)
{
(Arg::Gds(isc_item_finish) << Arg::Num(i)).raise();
}
IMessageMetadata* rc = msgMetadata;
rc->addRef();
msgMetadata = NULL;
return rc;
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
return NULL;
}
private:
RefPtr<MsgMetadata> msgMetadata;
Mutex mtx;
void metadataError(const char* functionName)
{
if (!msgMetadata)
{
(Arg::Gds(isc_random) << (string("IMetadataBuilder interface is already inactive: "
"IMetadataBuilder::") + functionName)).raise();
}
}
void indexError(unsigned index, const char* functionName)
{
metadataError(functionName);
if (index >= msgMetadata->items.getCount())
{
(Arg::Gds(isc_invalid_index_val) << Arg::Num(index) << (string("IMetadataBuilder::") +
functionName)).raise();
}
}
};
}
void check(IStatus* status)
{
@ -266,11 +278,6 @@ void check(IStatus* status)
}
}
} // namespace anonymous
namespace Firebird {
// Add an item based on a descriptor.
void MsgMetadata::addItem(const MetaName& name, bool nullable, const dsc& desc)

View File

@ -256,6 +256,34 @@ public:
RefPtr<IAttachment> attachment;
};
class MetadataBuilder FB_FINAL : public RefCntIface<IMetadataBuilder, FB_METADATA_BUILDER_VERSION>
{
public:
MetadataBuilder(const MsgMetadata* from);
MetadataBuilder(unsigned fieldCount);
virtual int FB_CARG release();
// IMetadataBuilder implementation
virtual void FB_CARG setType(IStatus* status, unsigned index, unsigned type);
virtual void FB_CARG setSubType(IStatus* status, unsigned index, int subType);
virtual void FB_CARG setLength(IStatus* status, unsigned index, unsigned length);
virtual void FB_CARG setCharSet(IStatus* status, unsigned index, unsigned charSet);
virtual void FB_CARG setScale(IStatus* status, unsigned index, unsigned scale);
virtual void FB_CARG truncate(IStatus* status, unsigned count);
virtual void FB_CARG remove(IStatus* status, unsigned index);
virtual void FB_CARG moveNameToIndex(IStatus* status, const char* name, unsigned index);
virtual unsigned FB_CARG addField(IStatus* status);
virtual IMessageMetadata* FB_CARG getMetadata(IStatus* status);
private:
RefPtr<MsgMetadata> msgMetadata;
Mutex mtx;
void metadataError(const char* functionName);
void indexError(unsigned index, const char* functionName);
};
} // namespace Firebird
#endif // COMMON_MSG_METADATA_H

View File

@ -273,6 +273,13 @@ OsError::OsError() throw() :
#else
Base(isc_arg_unix, errno) { }
#endif
OsError::OsError(ISC_STATUS s) throw() :
#ifdef WIN_NT
Base(isc_arg_win32, s) { }
#else
Base(isc_arg_unix, s) { }
#endif
} // namespace Arg
} // namespace Firebird

View File

@ -274,6 +274,7 @@ class OsError : public Base
{
public:
OsError() throw();
explicit OsError(ISC_STATUS s) throw();
};
} // namespace Arg

View File

@ -32,6 +32,7 @@
#include "fb_exception.h"
#include "../jrd/ibase.h"
#include "firebird/Auth.h"
#ifdef DEBUG_CLUMPLETS
#include "../yvalve/gds_proto.h"
@ -827,48 +828,44 @@ AuthReader::AuthReader(const AuthBlock& authBlock)
rewind();
}
bool AuthReader::getInfo(string* name, string* method, PathName* secureDb)
static inline void erase(NoCaseString& s)
{
s.erase();
}
static inline void set(NoCaseString& s, const ClumpletReader& rdr)
{
s.assign(rdr.getBytes(), rdr.getClumpLength());
}
bool AuthReader::getInfo(Info& info)
{
if (isEof())
{
return false;
}
if (name)
{
*name = "";
}
if (method)
{
*method = "";
}
if (secureDb)
{
*secureDb = "";
}
erase(info.type);
erase(info.name);
erase(info.plugin);
erase(info.secDb);
ClumpletReader internal(WideUnTagged, getBytes(), getClumpLength());
for (internal.rewind(); !internal.isEof(); internal.moveNext())
{
switch(internal.getClumpTag())
{
case AUTH_NAME:
if (name)
{
internal.getString(*name);
}
case AUTH_TYPE:
set(info.type, internal);
break;
case AUTH_METHOD:
if (method)
{
internal.getString(*method);
}
case AUTH_NAME:
set(info.name, internal);
break;
case AUTH_PLUGIN:
set(info.plugin, internal);
break;
case AUTH_SECURE_DB:
if (secureDb)
{
internal.getPath(*secureDb);
}
set(info.secDb, internal);
break;
default:
break;
@ -887,12 +884,12 @@ void dumpAuthBlock(const char* text, ClumpletReader* pb, unsigned char param)
Firebird::AuthReader::AuthBlock tmp;
tmp.assign(pb->getBytes(), pb->getClumpLength());
Firebird::AuthReader rdr(tmp);
string name, method;
string name, plugin;
PathName secureDb;
bool x = false;
while (rdr.getInfo(&name, &method, &secureDb))
while (rdr.getInfo(&name, &plugin, &secureDb))
{
fprintf(stderr, " %s::%s::%s", name.c_str(), method.c_str(), secureDb.c_str());
fprintf(stderr, " %s::%s::%s", name.c_str(), plugin.c_str(), secureDb.c_str());
x = true;
rdr.moveNext();
}

View File

@ -185,20 +185,29 @@ public:
class AuthReader : public ClumpletReader
{
public:
static const unsigned char AUTH_NAME = 1; // name described by it's type
static const unsigned char AUTH_PLUGIN = 2; // plugin which added a record
static const unsigned char AUTH_TYPE = 3; // it can be user/group/role/etc. - what plugin sets
static const unsigned char AUTH_SECURE_DB = 4; // sec. db in which context record was added
// missing when plugin is server-wide
typedef Array<UCHAR> AuthBlock;
// name and method are required attributes for any record
// name is set by plugin when it calls add()
static const unsigned char AUTH_NAME = 0;
// method is just a name of plugin which created this record
static const unsigned char AUTH_METHOD = 1;
struct Info
{
NoCaseString type, name, plugin, secDb;
unsigned found, current;
// additional attributes - only security database is used currently
static const unsigned char AUTH_SECURE_DB = 100;
Info()
: found(0), current(0)
{ }
};
explicit AuthReader(const AuthBlock& authBlock);
AuthReader(const ClumpletReader& rdr)
: ClumpletReader(rdr)
{ }
bool getInfo(string* name, string* method, PathName* secDb);
bool getInfo(Info& info);
};
//#define AUTH_BLOCK_DEBUG

View File

@ -73,11 +73,12 @@ namespace Firebird
return hash(&value, sizeof value, hashSize);
}
const static size_t DEFAULT_SIZE = 97; // largest prime number < 100
};
const size_t DEFAULT_HASH_SIZE = 97; // largest prime number < 100
template <typename C,
size_t HASHSIZE = DefaultHash<C>::DEFAULT_SIZE,
size_t HASHSIZE = DEFAULT_HASH_SIZE,
typename K = C, // default key
typename KeyOfValue = DefaultKeyValue<C>, // default keygen
typename F = DefaultHash<K> > // hash function definition
@ -163,12 +164,22 @@ namespace Firebird
}
~Hash()
{
// by default we let hash entries be cleaned by someone else
cleanup(NULL);
}
typedef void CleanupRoutine(C* toClean);
void cleanup(CleanupRoutine* cleanupRoutine)
{
for (size_t n = 0; n < HASHSIZE; ++n)
{
while (data[n])
{
data[n]->unLink();
Entry* entry = data[n];
entry->unLink();
if (cleanupRoutine)
cleanupRoutine(entry->get());
}
}
}

View File

@ -347,7 +347,7 @@ static bool setPath(const PathName& filename, PathName& expandedName)
// Full processing of database name
// Returns true if alias was found in databases.conf
bool expandDatabaseName(const Firebird::PathName& alias,
bool expandDatabaseName(Firebird::PathName alias,
Firebird::PathName& file,
Firebird::RefPtr<Config>* config)
{
@ -358,9 +358,12 @@ bool expandDatabaseName(const Firebird::PathName& alias,
catch (const fatal_exception& ex)
{
gds__log("File databases.conf contains bad data: %s", ex.what());
(Arg::Gds(isc_random) << "Server misconfigured - contact administrator please").raise();
Arg::Gds(isc_server_misconfigured).raise();
}
// remove whitespaces from database name
alias.trim();
ReadLockGuard guard(aliasesConf().rwLock, "expandDatabaseName");
// First of all check in databases.conf

View File

@ -28,7 +28,7 @@
class Config;
bool expandDatabaseName(const Firebird::PathName& alias,
bool expandDatabaseName(Firebird::PathName alias,
Firebird::PathName& file,
Firebird::RefPtr<Config>* config);

View File

@ -325,7 +325,8 @@ public:
SRAM_DATABASE_SNAPSHOT = 0xFE, // use downcount for shared memory types
SRAM_EVENT_MANAGER = 0xFD,
SRAM_TRACE_CONFIG = 0xFC,
SRAM_TRACE_LOG = 0xFB
SRAM_TRACE_LOG = 0xFB,
SRAM_MAPPING_RESET = 0xFA,
};
protected:

View File

@ -54,7 +54,7 @@ Get::Get(Config* firebirdConf)
void FB_CARG UserData::clear()
{
op = trustedRole = trustedAuth = 0;
op = 0;
// interface fields
user.clear();
@ -72,7 +72,6 @@ void FB_CARG UserData::clear()
dba.clear();
dbaPassword.clear();
role.clear();
trustedUser.clear();
// never clear this permanent block! authenticationBlock.clear();

View File

@ -146,7 +146,7 @@ class UserData : public IUser
{
public:
UserData()
: op(0), trustedRole(0), trustedAuth(0), authenticationBlock(*getDefaultMemoryPool())
: op(0), trustedAuth(0), authenticationBlock(*getDefaultMemoryPool())
{ }
// IUser implementation
@ -204,10 +204,10 @@ public:
typedef Firebird::Array<UCHAR> AuthenticationBlock;
int op, trustedRole, trustedAuth;
int op, trustedAuth;
CharField user, pass, first, last, middle, com, attr;
IntField adm, act;
CharField database, dba, dbaPassword, role, trustedUser;
CharField database, dba, dbaPassword, role;
AuthenticationBlock authenticationBlock;
// deprecated

View File

@ -59,6 +59,7 @@
#include "../utilities/gsec/gsec.h"
#include "../common/dsc_proto.h"
#include "../common/StatusArg.h"
#include "../auth/SecureRemotePassword/Message.h"
namespace Jrd {
@ -9147,55 +9148,426 @@ bool CreateRoleNode::isItUserName(thread_db* tdbb, jrd_tra* transaction)
//----------------------
void AlterRoleNode::print(string& text) const
void MappingNode::print(string& text) const
{
const char* null = "<Null>";
text.printf(
"AlterRoleNode\n"
" name: '%s'\n"
" map: '%d'\n",
name.c_str(), map);
"MappingNode\n"
" op: '%s'\n"
" global: '%d'\n"
" mode: '%c'\n"
" plugin: '%s'\n"
" db: '%s'\n"
" fromType: '%s'\n"
" from: '%s'\n"
" role: '%d'\n"
" to: '%s'\n",
op, global, mode,
plugin ? plugin->c_str() : null, db ? db->c_str() : null,
fromType ? fromType->c_str() : null, from ? from->getString().c_str() : null,
role, to ? to->c_str() : null);
}
// It's purpose is to add/drop mapping from OS security name to DB security object.
void AlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
void MappingNode::validateAdmin()
{
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
if (to && (*to != ADMIN_ROLE))
Arg::Gds(isc_alter_role).raise();
}
// This is FB 2.5 limited implementation!
// Later it should work with new system table, something like RDB$MAPPING.
if (name != ADMIN_ROLE)
status_exception::raise(Arg::Gds(isc_wish_list));
// add some item to DLL in "double quotes"
void MappingNode::addItem(string& ddl, const char* text)
{
ddl += '"';
char c;
while (c = *text++)
{
ddl += c;
if (c == '"')
ddl += c;
}
ddl += '"';
}
// 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));
AutoCacheRequest request(tdbb, drq_m_map, DYN_REQUESTS);
bool found = false;
if (global)
{
LocalStatus st;
LocalStatus s2; // we will use it in DDL case and remember
IStatus* s = &st;
class Check
{
public:
static void status(IStatus* s)
{
if (!s->isSuccess())
status_exception::raise(s->get());
}
};
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
ROL IN RDB$ROLES
WITH ROL.RDB$ROLE_NAME EQ name.c_str()
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::status(s);
ITransaction* tra = att->startTransaction(s, 0, NULL);
Check::status(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::status(s);
try
{
// first of all try to use regenerated DDL statement
// that's the best way if security database is FB3 or higher fb version
string ddl;
switch(op)
{
case MAP_ADD:
ddl = "CREATE MAPPING ";
break;
case MAP_MOD:
ddl = "ALTER MAPPING ";
break;
case MAP_DROP:
ddl = "DROP MAPPING ";
break;
case MAP_RPL:
ddl = "CREATE OR ALTER MAPPING ";
break;
}
addItem(ddl, name.c_str());
if (op != MAP_DROP)
{
ddl += " USING ";
switch (mode)
{
case 'P':
if (!plugin)
ddl += "ANY PLUGIN ";
else
{
ddl += "PLUGIN ";
addItem(ddl, plugin->c_str());
ddl += ' ';
}
break;
case 'S':
ddl += "ANY PLUGIN SERVERWIDE ";
break;
case '*':
ddl += "* ";
break;
case 'M':
ddl += "MAPPING ";
break;
}
if (db)
{
ddl += "IN ";
addItem(ddl, db->c_str());
ddl += ' ';
}
if (fromType)
{
ddl += "FROM ";
if (!from)
ddl += "ANY ";
addItem(ddl, fromType->c_str());
ddl += ' ';
if (from)
{
addItem(ddl, from->getString().c_str());
ddl += ' ';
}
}
ddl += "TO ";
ddl += (role ? "ROLE" : "USER");
if (to)
{
ddl += ' ';
addItem(ddl, to->c_str());
}
}
// Now try to run DDL
secDbContext->att->execute(&s2, secDbContext->tra, 0, ddl.c_str(), SQL_DIALECT_V6,
NULL, NULL, NULL, NULL);
if (!s2.isSuccess())
{
// try direct access to rdb$map table in secure db
// check presence of such record in the table
Message check;
Field<Varying> nm(check, 1);
nm = name.c_str();
Message result;
Field<ISC_INT64> cnt(result);
const char* checkSql = "select count(*) from RDB$MAP where RDB$MAP_NAME = ?";
secDbContext->att->execute(s, secDbContext->tra, 0, checkSql, SQL_DIALECT_V6,
check.getMetadata(), check.getBuffer(), result.getMetadata(), result.getBuffer());
Check::status(s);
if (cnt > 1 && op != MAP_DROP)
ERRD_bugcheck("Database mapping misconfigured");
bool hasLine = cnt > 0;
switch(op)
{
case MAP_ADD:
if (hasLine)
(Arg::Gds(isc_map_already_exists) << name).raise();
break;
case MAP_MOD:
case MAP_DROP:
if (!hasLine)
(Arg::Gds(isc_map_not_exists) << name).raise();
break;
case MAP_RPL:
op = hasLine ? MAP_MOD : MAP_DROP;
break;
}
// Get ready to modify table
Message full;
Field<ISC_SHORT> toType(full);
Field<Varying> t(full, MAX_SQL_IDENTIFIER_LEN);
Field<Varying> usng2(full, 1);
Field<Varying> plug2(full, MAX_SQL_IDENTIFIER_LEN);
Field<Varying> d2(full, MAX_SQL_IDENTIFIER_LEN);
Field<Varying> type2(full, MAX_SQL_IDENTIFIER_LEN);
Field<Varying> f2(full, 255);
Field<Varying> nm2(full, MAX_SQL_IDENTIFIER_LEN);
toType = role ? 1 : 0;
if (to)
t = to->c_str();
usng2.set(1, &mode);
if (plugin)
plug2 = plugin->c_str();
if (db)
d2 = db->c_str();
if (fromType)
type2 = fromType->c_str();
if (from)
f2 = from->getString().c_str();
nm2 = name.c_str();
Message* msg = NULL;
const char* sql = NULL;
switch(op)
{
case MAP_ADD:
sql = "insert into RDB$MAP(RDB$MAP_TO_TYPE, RDB$MAP_TO, RDB$MAP_USING, "
"RDB$MAP_PLUGIN, RDB$MAP_DB, RDB$MAP_FROM_TYPE, RDB$MAP_FROM, RDB$MAP_NAME) "
"values (?, ?, ?, ?, ?, ?, ?, ?)";
msg = &full;
break;
case MAP_MOD:
sql = "update RDB$MAP set RDB$MAP_TO_TYPE = ?, RDB$MAP_TO = ?, "
"RDB$MAP_USING = ?, RDB$MAP_PLUGIN = ?, RDB$MAP_DB = ?, "
"RDB$MAP_FROM_TYPE = ?, RDB$MAP_FROM = ? "
"where RDB$MAP_NAME = ?";
msg = &full;
break;
case MAP_DROP:
sql = "delete from RDB$MAP where RDB$MAP_NAME = ?";
msg = &check;
break;
}
// Actual modification
fb_assert(sql && msg);
secDbContext->att->execute(s, secDbContext->tra, 0, sql, SQL_DIALECT_V6,
msg->getMetadata(), msg->getBuffer(), NULL, NULL);
Check::status(s);
secDbContext->att->execute(s, secDbContext->tra, 0, ("RELEASE SAVEPOINT " + savePoint).c_str(),
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
savePoint.erase();
Check::status(s);
}
}
catch(const Exception&)
{
if (savePoint.hasData())
{
secDbContext->att->execute(s, secDbContext->tra, 0, ("ROLLBACK TO SAVEPOINT " + savePoint).c_str(),
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);
}
if (!s2.isSuccess())
{
const ISC_STATUS* stat2 = s2.get();
if (stat2[1] != isc_dsql_token_unk_err)
{
status_exception::raise(stat2);
}
}
throw;
}
return;
}
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
fb_assert(op == MAP_DROP || fromType);
short plugNull = plugin ? FALSE : TRUE;
short dbNull = db ? FALSE : TRUE;
short fromNull = from ? FALSE : TRUE;
char usingText[2];
usingText[0] = mode;
usingText[1] = '\0';
AutoCacheRequest request1(tdbb, drq_map_mod, DYN_REQUESTS);
bool found = false;
int ddlTriggerAction = 0;
FOR(REQUEST_HANDLE request1 TRANSACTION_HANDLE transaction)
M IN RDB$MAP
WITH M.RDB$MAP_NAME EQ name.c_str()
{
found = true;
switch (op)
{
case MAP_ADD:
break;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_ROLE, name);
case MAP_MOD:
case MAP_RPL:
ddlTriggerAction = DDL_TRIGGER_ALTER_MAPPING;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name);
MODIFY ROL
ROL.RDB$SYSTEM_FLAG = ROLE_FLAG_DBO | (map ? ROLE_FLAG_MAY_TRUST : 0);
END_MODIFY
MODIFY M
if (to)
{
M.RDB$MAP_TO.NULL = FALSE;
strcpy(M.RDB$MAP_TO, to->c_str());
}
else
M.RDB$MAP_TO.NULL = TRUE;
M.RDB$MAP_TO_TYPE = role ? 1 : 0;
strcpy(M.RDB$MAP_USING, usingText);
M.RDB$MAP_PLUGIN.NULL = plugNull;
if (!plugNull)
strcpy(M.RDB$MAP_PLUGIN, plugin->c_str());
M.RDB$MAP_DB.NULL = dbNull;
if (!dbNull)
strcpy(M.RDB$MAP_DB, db->c_str());
strcpy(M.RDB$MAP_FROM_TYPE, fromType->c_str());
M.RDB$MAP_FROM.NULL = fromNull;
if (!fromNull)
strcpy(M.RDB$MAP_FROM, from->getString().c_str());
END_MODIFY
break;
case MAP_DROP:
ddlTriggerAction = DDL_TRIGGER_DROP_MAPPING;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name);
ERASE M;
break;
}
}
END_FOR
if (found)
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_ROLE, name);
else
AutoCacheRequest request2(tdbb, drq_map_sto, DYN_REQUESTS);
switch (op)
{
status_exception::raise(
Arg::Gds(isc_random) << Arg::Str("Missing RDB$ADMIN role in the database"));
case MAP_ADD:
if (found)
{
(Arg::Gds(isc_map_already_exists) << name).raise();
}
// fall through ...
case MAP_RPL:
if (found)
break;
ddlTriggerAction = DDL_TRIGGER_CREATE_MAPPING;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name);
STORE(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
M IN RDB$MAP
{
strcpy(M.RDB$MAP_NAME, name.c_str());
strcpy(M.RDB$MAP_USING, usingText);
M.RDB$MAP_PLUGIN.NULL = plugNull;
if (!plugNull)
strcpy(M.RDB$MAP_PLUGIN, plugin->c_str());
M.RDB$MAP_DB.NULL = dbNull;
if (!dbNull)
strcpy(M.RDB$MAP_DB, db->c_str());
strcpy(M.RDB$MAP_FROM_TYPE, fromType->c_str());
M.RDB$MAP_FROM.NULL = fromNull;
if (!fromNull)
strcpy(M.RDB$MAP_FROM, from->getString().c_str());
M.RDB$MAP_TO_TYPE = role ? 1 : 0;
if (to)
{
M.RDB$MAP_TO.NULL = FALSE;
strcpy(M.RDB$MAP_TO, to->c_str());
}
else
M.RDB$MAP_TO.NULL = TRUE;
}
END_STORE
break;
case MAP_MOD:
case MAP_DROP:
if (!found)
{
(Arg::Gds(isc_map_not_exists) << name).raise();
}
break;
}
fb_assert(ddlTriggerAction > 0);
if (ddlTriggerAction > 0)
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name);
DFW_post_work(transaction, dfw_flash_cache, NULL, 0);
savePoint.release(); // everything is ok
}

View File

@ -1749,16 +1749,28 @@ public:
};
class AlterRoleNode : public DdlNode
class MappingNode : public DdlNode
{
public:
AlterRoleNode(MemoryPool& p, const Firebird::MetaName& aName, bool aMap)
enum OP {MAP_ADD, MAP_MOD, MAP_RPL, MAP_DROP};
MappingNode(MemoryPool& p, OP o, const Firebird::MetaName& nm)
: DdlNode(p),
name(p, aName),
map(aMap)
name(p, nm),
plugin(NULL),
db(NULL),
fromType(NULL),
from(NULL),
to(NULL),
op(o),
mode('#'),
global(false),
role(false)
{
}
void validateAdmin();
public:
virtual void print(Firebird::string& text) const;
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
@ -1766,12 +1778,25 @@ public:
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
statusVector << Firebird::Arg::Gds(isc_dsql_alter_role_failed) << name;
statusVector << Firebird::Arg::Gds(isc_dsql_mapping_failed) << name <<
(op == MAP_ADD ? "CREATE" : op == MAP_MOD ?
"ALTER" : op == MAP_RPL ? "CREATE OR ALTER" : "DROP");
}
private:
void addItem(Firebird::string& ddl, const char* text);
public:
Firebird::MetaName name;
bool map;
Firebird::MetaName* plugin;
Firebird::MetaName* db;
Firebird::MetaName* fromType;
IntlString* from;
Firebird::MetaName* to;
OP op;
char mode; // * - any source, P - plugin, M - mapping, S - any serverwide plugin
bool global;
bool role;
};

View File

@ -96,6 +96,9 @@
#include "../jrd/Attachment.h"
#include "../common/StatusArg.h"
// This is needed here to provide backward compatibility when working with SSPI plugin
#include "../auth/trusted/AuthSspi.h"
// since UNIX isn't standard, we have to define
// stuff which is in <limits.h> (which isn't available on all UNIXes...
@ -563,6 +566,8 @@ using namespace Firebird;
%token <metaNamePtr> RDB_RECORD_VERSION
%token <metaNamePtr> LINGER
%token <metaNamePtr> TAGS
%token <metaNamePtr> PLUGIN
%token <metaNamePtr> SERVERWIDE
// precedence declarations for expression evaluation
@ -687,6 +692,8 @@ using namespace Firebird;
Jrd::DeclareSubFuncNode* declareSubFuncNode;
Jrd::dsql_req* dsqlReq;
Jrd::CreateAlterUserNode* createAlterUserNode;
Jrd::MappingNode* mappingNode;
Jrd::MappingNode::OP mappingOp;
}
%include types.y
@ -1231,6 +1238,8 @@ create_clause
| USER create_user_clause { $$ = $2; }
| PACKAGE package_clause { $$ = $2; }
| PACKAGE BODY package_body_clause { $$ = $3; }
| MAPPING create_map_clause(false) { $$ = $2; }
| GLOBAL MAPPING create_map_clause(true) { $$ = $3; }
;
@ -1272,15 +1281,17 @@ create_or_alter
%type <ddlNode> replace_clause
replace_clause
: PROCEDURE replace_procedure_clause { $$ = $2; }
| FUNCTION replace_function_clause { $$ = $2; }
| TRIGGER replace_trigger_clause { $$ = $2; }
| PACKAGE replace_package_clause { $$ = $2; }
| VIEW replace_view_clause { $$ = $2; }
| EXCEPTION replace_exception_clause { $$ = $2; }
| GENERATOR replace_sequence_clause { $$ = $2; }
| SEQUENCE replace_sequence_clause { $$ = $2; }
| USER replace_user_clause { $$ = $2; }
: PROCEDURE replace_procedure_clause { $$ = $2; }
| FUNCTION replace_function_clause { $$ = $2; }
| TRIGGER replace_trigger_clause { $$ = $2; }
| PACKAGE replace_package_clause { $$ = $2; }
| VIEW replace_view_clause { $$ = $2; }
| EXCEPTION replace_exception_clause { $$ = $2; }
| GENERATOR replace_sequence_clause { $$ = $2; }
| SEQUENCE replace_sequence_clause { $$ = $2; }
| USER replace_user_clause { $$ = $2; }
| MAPPING replace_map_clause(false) { $$ = $2; }
| GLOBAL MAPPING replace_map_clause(true) { $$ = $3; }
;
@ -3330,6 +3341,9 @@ trigger_ddl_type_items
| DROP PACKAGE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_PACKAGE); }
| CREATE PACKAGE BODY { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_PACKAGE_BODY); }
| DROP PACKAGE BODY { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_PACKAGE_BODY); }
| CREATE MAPPING { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_MAPPING); }
| ALTER MAPPING { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_MAPPING); }
| DROP MAPPING { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_MAPPING); }
| trigger_ddl_type OR
trigger_ddl_type { $$ = $1 | $3; }
;
@ -3398,6 +3412,8 @@ alter_clause
| CHARACTER SET alter_charset_clause { $$ = $3; }
| GENERATOR alter_sequence_clause { $$ = $2; }
| SEQUENCE alter_sequence_clause { $$ = $2; }
| MAPPING alter_map_clause(false) { $$ = $2; }
| GLOBAL MAPPING alter_map_clause(true) { $$ = $3; }
;
%type <alterDomainNode> alter_domain
@ -3664,10 +3680,20 @@ module_op
| MODULE_NAME utf_string { $$ = $2; }
;
%type <ddlNode> alter_role_clause
%type <mappingNode> alter_role_clause
alter_role_clause
: symbol_role_name alter_role_enable AUTO ADMIN MAPPING
{ $$ = newNode<AlterRoleNode>(*$1, $2); }
{
$$ = newNode<MappingNode>(MappingNode::MAP_RPL, "AutoAdminImplementationMapping");
$$->op = $2 ? MappingNode::MAP_RPL : MappingNode::MAP_DROP;
$$->from = newNode<IntlString>(FB_DOMAIN_ANY_RID_ADMINS);
$$->fromType = newNode<MetaName>(FB_PREDEFINED_GROUP);
$$->mode = 'P';
$$->plugin = newNode<MetaName>("Win_Sspi");
$$->role = true;
$$->to = $1;
$$->validateAdmin();
}
;
%type <boolVal> alter_role_enable
@ -3804,6 +3830,10 @@ drop_clause
{ $$ = newNode<DropPackageNode>(*$2); }
| PACKAGE BODY symbol_package_name
{ $$ = newNode<DropPackageBodyNode>(*$3); }
| MAPPING drop_map_clause(false)
{ $$ = $2; }
| GLOBAL MAPPING drop_map_clause(true)
{ $$ = $3; }
;
@ -5926,6 +5956,165 @@ user_var_option($node)
}
;
// logons mapping
%type <mappingNode> create_map_clause(<boolVal>)
create_map_clause($global)
: map_clause(MappingNode::MAP_ADD)
{
$$ = $1;
$$->global = $global;
}
map_to(NOTRIAL($2))
{
$$ = $2;
}
;
%type <mappingNode> alter_map_clause(<boolVal>)
alter_map_clause($global)
: map_clause(MappingNode::MAP_MOD)
{
$$ = $1;
}
map_to(NOTRIAL($2))
{
$$ = $2;
}
;
%type <mappingNode> replace_map_clause(<boolVal>)
replace_map_clause($global)
: map_clause(MappingNode::MAP_RPL)
{
$$ = $1;
$$->global = $global;
}
map_to(NOTRIAL($2))
{
$$ = $2;
}
;
%type <mappingNode> drop_map_clause(<boolVal>)
drop_map_clause($global)
: map_name
{
MappingNode* node = newNode<MappingNode>(MappingNode::MAP_DROP, *$1);
node->global = $global;
$$ = node;
}
;
%type <mappingNode> map_clause(<mappingOp>)
map_clause($op)
: map_name
{
$$ = newNode<MappingNode>($op, *$1);
}
USING map_using(NOTRIAL($2))
FROM map_from(NOTRIAL($2))
{
$$ = $2;
}
;
%type <metaNamePtr> map_name
map_name
: valid_symbol_name
{ $$ = $1; }
;
%type map_from(<mappingNode>)
map_from($node)
: map_from_symbol_name map_logoninfo
{
$node->fromType = $1;
$node->from = $2;
}
| ANY map_from_symbol_name
{
$node->fromType = $2;
$node->from = newNode<IntlString>("*");
}
;
%type <metaNamePtr> map_from_symbol_name
map_from_symbol_name
: valid_symbol_name
| USER
{ $$ = newNode<MetaName>("USER"); }
| GROUP
{ $$ = newNode<MetaName>("GROUP"); }
;
%type <intlStringPtr> map_logoninfo
map_logoninfo
: STRING
| valid_symbol_name
{ $$ = newNode<IntlString>($1->c_str()); }
;
%type map_using(<mappingNode>)
map_using($node)
: PLUGIN valid_symbol_name map_in
{
$node->mode = 'P';
$node->plugin = $2;
$node->db = $3;
}
| ANY PLUGIN map_in
{
$node->mode = 'P';
$node->db = $3;
}
| ANY PLUGIN SERVERWIDE
{
$node->mode = 'S';
}
| MAPPING map_in
{
$node->mode = 'M';
$node->db = $2;
}
| '*' map_in
{
$node->mode = '*';
$node->db = $2;
}
;
%type <metaNamePtr> map_in
map_in
: // nothing
{ $$ = NULL; }
| KW_IN valid_symbol_name
{ $$ = $2; }
;
%type map_to(<mappingNode>)
map_to($node)
: TO map_role valid_symbol_name
{
$node->role = $2;
$node->to = $3;
}
| TO map_role
{
$node->role = $2;
}
;
%type <boolVal> map_role
map_role
: ROLE
{ $$ = true; }
| USER
{ $$ = false; }
;
// value types
%type <valueExprNode> value
@ -7163,6 +7352,8 @@ non_reserved_word
| USAGE
| LINGER
| TAGS
| PLUGIN
| SERVERWIDE
;
%%

View File

@ -47,9 +47,10 @@ class IWriter : public Firebird::IVersioned
public:
virtual void FB_CARG reset() = 0;
virtual void FB_CARG add(const char* name) = 0;
virtual void FB_CARG setAttribute(unsigned char tag, const char* value) = 0;
virtual void FB_CARG setType(const char* value) = 0;
virtual void FB_CARG setDb(const char* value) = 0;
};
#define FB_AUTH_WRITER_VERSION (FB_VERSIONED_VERSION + 3)
#define FB_AUTH_WRITER_VERSION (FB_VERSIONED_VERSION + 4)
// Representation of auth-related data, passed to/from server auth plugin
class IServerBlock : public Firebird::IVersioned
@ -149,12 +150,11 @@ class ILogonInfo : public Firebird::IVersioned
public:
virtual const char* FB_CARG name() = 0;
virtual const char* FB_CARG role() = 0;
virtual int FB_CARG forceAdmin() = 0;
virtual const char* FB_CARG networkProtocol() = 0;
virtual const char* FB_CARG remoteAddress() = 0;
virtual unsigned int FB_CARG authBlock(const unsigned char** bytes) = 0;
};
#define FB_AUTH_LOGON_INFO_VERSION (FB_VERSIONED_VERSION + 6)
#define FB_AUTH_LOGON_INFO_VERSION (FB_VERSIONED_VERSION + 5)
class IManagement : public Firebird::IPluginBase
{

View File

@ -116,10 +116,11 @@ public:
virtual void FB_CARG truncate(IStatus* status, unsigned count) = 0;
virtual void FB_CARG moveNameToIndex(IStatus* status, const char* name, unsigned index) = 0;
virtual void FB_CARG remove(IStatus* status, unsigned index) = 0;
virtual unsigned FB_CARG addField(IStatus* status) = 0;
virtual IMessageMetadata* FB_CARG getMetadata(IStatus* status) = 0;
};
#define FB_METADATA_BUILDER_VERSION (FB_REFCOUNTED_VERSION + 9)
#define FB_METADATA_BUILDER_VERSION (FB_REFCOUNTED_VERSION + 10)
class IResultSet : public IRefCounted
{

View File

@ -778,6 +778,17 @@ static const struct {
{"forupdate_systbl", 335545074},
{"forupdate_temptbl", 335545075},
{"cant_modify_sysobj", 335545076},
{"server_misconfigured", 335545077},
{"alter_role", 335545078},
{"map_already_exists", 335545079},
{"map_not_exists", 335545080},
{"map_load", 335545081},
{"map_aster", 335545082},
{"map_multi", 335545083},
{"map_undefined", 335545084},
{"baddpb_damaged_mode", 335545085},
{"baddpb_buffers_range", 335545086},
{"baddpb_temp_buffers", 335545087},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},
@ -1124,6 +1135,7 @@ static const struct {
{"dsql_grant_failed", 336397319},
{"dsql_revoke_failed", 336397320},
{"dsql_cte_recursive_aggregate", 336397321},
{"dsql_mapping_failed", 336397322},
{"gsec_cant_open_db", 336723983},
{"gsec_switches_error", 336723984},
{"gsec_no_op_spec", 336723985},

View File

@ -812,6 +812,17 @@ const ISC_STATUS isc_forupdate_virtualtbl = 335545073L;
const ISC_STATUS isc_forupdate_systbl = 335545074L;
const ISC_STATUS isc_forupdate_temptbl = 335545075L;
const ISC_STATUS isc_cant_modify_sysobj = 335545076L;
const ISC_STATUS isc_server_misconfigured = 335545077L;
const ISC_STATUS isc_alter_role = 335545078L;
const ISC_STATUS isc_map_already_exists = 335545079L;
const ISC_STATUS isc_map_not_exists = 335545080L;
const ISC_STATUS isc_map_load = 335545081L;
const ISC_STATUS isc_map_aster = 335545082L;
const ISC_STATUS isc_map_multi = 335545083L;
const ISC_STATUS isc_map_undefined = 335545084L;
const ISC_STATUS isc_baddpb_damaged_mode = 335545085L;
const ISC_STATUS isc_baddpb_buffers_range = 335545086L;
const ISC_STATUS isc_baddpb_temp_buffers = 335545087L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@ -1158,6 +1169,7 @@ const ISC_STATUS isc_dsql_alter_user_failed = 336397318L;
const ISC_STATUS isc_dsql_grant_failed = 336397319L;
const ISC_STATUS isc_dsql_revoke_failed = 336397320L;
const ISC_STATUS isc_dsql_cte_recursive_aggregate = 336397321L;
const ISC_STATUS isc_dsql_mapping_failed = 336397322L;
const ISC_STATUS isc_gsec_cant_open_db = 336723983L;
const ISC_STATUS isc_gsec_switches_error = 336723984L;
const ISC_STATUS isc_gsec_no_op_spec = 336723985L;
@ -1259,7 +1271,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
const ISC_STATUS isc_err_max = 1203;
const ISC_STATUS isc_err_max = 1215;
#else /* c definitions */
@ -2041,6 +2053,17 @@ const ISC_STATUS isc_err_max = 1203;
#define isc_forupdate_systbl 335545074L
#define isc_forupdate_temptbl 335545075L
#define isc_cant_modify_sysobj 335545076L
#define isc_server_misconfigured 335545077L
#define isc_alter_role 335545078L
#define isc_map_already_exists 335545079L
#define isc_map_not_exists 335545080L
#define isc_map_load 335545081L
#define isc_map_aster 335545082L
#define isc_map_multi 335545083L
#define isc_map_undefined 335545084L
#define isc_baddpb_damaged_mode 335545085L
#define isc_baddpb_buffers_range 335545086L
#define isc_baddpb_temp_buffers 335545087L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@ -2387,6 +2410,7 @@ const ISC_STATUS isc_err_max = 1203;
#define isc_dsql_grant_failed 336397319L
#define isc_dsql_revoke_failed 336397320L
#define isc_dsql_cte_recursive_aggregate 336397321L
#define isc_dsql_mapping_failed 336397322L
#define isc_gsec_cant_open_db 336723983L
#define isc_gsec_switches_error 336723984L
#define isc_gsec_no_op_spec 336723985L
@ -2488,7 +2512,7 @@ const ISC_STATUS isc_err_max = 1203;
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1203
#define isc_err_max 1215
#endif

View File

@ -621,3 +621,29 @@
const USHORT f_sec_attr_value = 2;
// Relation 45 (RDB$MAP)
const USHORT f_map_name = 0;
const USHORT f_map_using = 1;
const USHORT f_map_plugin = 2;
const USHORT f_map_db = 3;
const USHORT f_map_from_type = 4;
const USHORT f_map_from = 5;
const USHORT f_map_to_type = 6;
const USHORT f_map_to = 7;
const USHORT f_map_sys_flag = 8;
const USHORT f_map_desc = 9;
// Relation 46 (SEC$GLOBAL_MAP)
const USHORT f_sec_map_name = 0;
const USHORT f_sec_map_using = 1;
const USHORT f_sec_map_plugin = 2;
const USHORT f_sec_map_db = 3;
const USHORT f_sec_map_from_type = 4;
const USHORT f_sec_map_from = 5;
const USHORT f_sec_map_to_type = 6;
const USHORT f_sec_map_to = 7;

View File

@ -781,6 +781,17 @@ Data source : @4"}, /* eds_statement */
{335545074, "Cannot select system table @1 for update WITH LOCK"}, /* forupdate_systbl */
{335545075, "Cannot select temporary table @1 for update WITH LOCK"}, /* forupdate_temptbl */
{335545076, "System @1 @2 cannot be modified"}, /* cant_modify_sysobj */
{335545077, "Server misconfigured - contact administrator please"}, /* server_misconfigured */
{335545078, "Deprecated backward compatibility ALTER ROLE ... SET/DROP AUTO ADMIN mapping may be used only for RDB$ADMIN role"}, /* alter_role */
{335545079, "Mapping @1 already exists"}, /* map_already_exists */
{335545080, "Mapping @1 does not exist"}, /* map_not_exists */
{335545081, "@1 failed when loading mapping cache"}, /* map_load */
{335545082, "Invalid name <*> in authentication block"}, /* map_aster */
{335545083, "Multiple maps found for @1"}, /* map_multi */
{335545084, "Undefined mapping result - more than one different results found"}, /* map_undefined */
{335545085, "Incompatible mode of attachment to damaged database"}, /* baddpb_damaged_mode */
{335545086, "Attempt to set in database number of buffers which is out of acceptable range [@1:@2]"}, /* baddpb_buffers_range */
{335545087, "Attempt to temporarily set number of buffers less than @1"}, /* baddpb_temp_buffers */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
@ -1127,6 +1138,7 @@ Data source : @4"}, /* eds_statement */
{336397319, "GRANT failed"}, /* dsql_grant_failed */
{336397320, "REVOKE failed"}, /* dsql_revoke_failed */
{336397321, "Recursive member of CTE cannot use aggregate or window function"}, /* dsql_cte_recursive_aggregate */
{336397322, "@2 MAPPING @1 failed"}, /* dsql_mapping_failed */
{336723983, "unable to open database"}, /* gsec_cant_open_db */
{336723984, "error in switch specifications"}, /* gsec_switches_error */
{336723985, "no operation specified"}, /* gsec_no_op_spec */

View File

@ -777,6 +777,17 @@ static const struct {
{335545074, -901}, /* 754 forupdate_systbl */
{335545075, -901}, /* 755 forupdate_temptbl */
{335545076, -901}, /* 756 cant_modify_sysobj */
{335545077, -901}, /* 757 server_misconfigured */
{335545078, -901}, /* 758 alter_role */
{335545079, -901}, /* 759 map_already_exists */
{335545080, -901}, /* 760 map_not_exists */
{335545081, -901}, /* 761 map_load */
{335545082, -901}, /* 762 map_aster */
{335545083, -901}, /* 763 map_multi */
{335545084, -901}, /* 764 map_undefined */
{335545085, -924}, /* 765 baddpb_damaged_mode */
{335545086, -924}, /* 766 baddpb_buffers_range */
{335545087, -924}, /* 767 baddpb_temp_buffers */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */
@ -1123,6 +1134,7 @@ static const struct {
{336397319, -901}, /* 1031 dsql_grant_failed */
{336397320, -901}, /* 1032 dsql_revoke_failed */
{336397321, -104}, /* 1033 dsql_cte_recursive_aggregate */
{336397322, -901}, /* 1034 dsql_mapping_failed */
{336723983, -901}, /* 15 gsec_cant_open_db */
{336723984, -901}, /* 16 gsec_switches_error */
{336723985, -901}, /* 17 gsec_no_op_spec */

View File

@ -777,6 +777,17 @@ static const struct {
{335545074, "HY000"}, // 754 forupdate_systbl
{335545075, "HY000"}, // 755 forupdate_temptbl
{335545076, "42000"}, // 756 cant_modify_sysobj
{335545077, "08004"}, // 757 server_misconfigured
{335545078, "0A000"}, // 758 alter_role
{335545079, "42S01"}, // 759 map_already_exists
{335545080, "42S01"}, // 760 map_not_exists
{335545081, "08004"}, // 761 map_load
{335545082, "08004"}, // 762 map_aster
{335545083, "08004"}, // 763 map_multi
{335545084, "08004"}, // 764 map_undefined
{335545085, "HY000"}, // 765 baddpb_damaged_mode
{335545086, "HY000"}, // 766 baddpb_buffers_range
{335545087, "HY000"}, // 767 baddpb_temp_buffers
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw
@ -1123,6 +1134,7 @@ static const struct {
{336397319, "42000"}, // 1031 dsql_grant_failed
{336397320, "42000"}, // 1032 dsql_revoke_failed
{336397321, "42000"}, // 1033 dsql_cte_recursive_aggregate
{336397322, "42000"}, // 1034 dsql_mapping_failed
{336723983, "00000"}, // 15 gsec_cant_open_db
{336723984, "00000"}, // 16 gsec_switches_error
{336723985, "00000"}, // 17 gsec_no_op_spec

View File

@ -196,6 +196,7 @@ int EXTRACT_ddl(LegacyTables flag, const SCHAR* tabname)
listDomainConstraints();
list_all_triggers();
list_all_grants();
SHOW_maps(true, "");
SHOW_comments(false); // Let's make this an option later.
}

View File

@ -268,6 +268,8 @@ const int NO_GRANT_ON_FUN = 180; // There is no privilege granted on function
const int REPORT_NEW1 = 181; // Current memory = !\nDelta memory = !\nMax memory = !\nElapsed time= ~ sec\n
const int REPORT_NEW2 = 182; // Cpu = ~ sec\n (skipped on windows)
const int REPORT_NEW3 = 183; // Buffers = !\nReads = !\nWrites = !\nFetches = !\n
const int NO_MAP = 184; // There is no mapping from @1 in this database
const int NO_MAPS = 185; // There are no mappings in this database
// Initialize types

View File

@ -1458,6 +1458,8 @@ void SHOW_print_metadata_text_blob(FILE* fp, ISC_QUAD* blobid, bool escape_squot
if ((!fbStatus->isSuccess()) && fbStatus->get()[1] != isc_segstr_eof)
ISQL_errmsg(fbStatus);
blob->close(fbStatus);
}
@ -1485,7 +1487,7 @@ processing_state SHOW_metadata(const SCHAR* const* cmd, SCHAR** lcmd)
role, table, view, system, index, domain, exception,
filter, function, generator, grant, procedure, trigger,
check, database, comment, dependency, collation, security_class,
users, package, schema, wrong
users, package, schema, map, wrong
};
ShowOptions(const optionsMap* inmap, size_t insize, int wrongval)
: OptionsBase(inmap, insize, wrongval)
@ -1541,7 +1543,8 @@ processing_state SHOW_metadata(const SCHAR* const* cmd, SCHAR** lcmd)
{ShowOptions::security_class, "SECCLASSES", 6},
{ShowOptions::users, "USERS", 0},
{ShowOptions::package, "PACKAGES", 4},
{ShowOptions::schema, "SCHEMAS", 4}
{ShowOptions::schema, "SCHEMAS", 4},
{ShowOptions::map, "MAPPING", 3}
};
const ShowOptions showoptions(options, FB_NELEM(options), ShowOptions::wrong);
@ -2134,6 +2137,24 @@ processing_state SHOW_metadata(const SCHAR* const* cmd, SCHAR** lcmd)
}
break;
case ShowOptions::map:
if (*cmd[2] == '"')
{
remove_delimited_double_quotes(lcmd[2]);
ret = SHOW_maps(false, lcmd[2]);
}
else
ret = SHOW_maps(false, cmd[2]);
if (ret == OBJECT_NOT_FOUND)
{
if (*cmd[2])
key = NO_MAP;
else
key = NO_MAPS;
}
break;
case ShowOptions::schema:
return ps_ERR;
break;
@ -4275,6 +4296,149 @@ static processing_state show_packages(const SCHAR* package_name)
}
static void printIdent(bool quote, char* ident, const char* format = NULL)
{
fb_utils::exact_name(ident);
char quotedIdent[BUFFER_LENGTH128];
if (quote && isqlGlob.db_SQL_dialect > SQL_DIALECT_V6_TRANSITION)
{
IUTILS_copy_SQL_id(ident, quotedIdent, DBL_QUOTE);
ident = quotedIdent;
}
isqlGlob.printf(format ? format : "%s", ident);
}
static void printMap(bool extract, bool global, char* name, char* usng, char* plugin, char* db,
char* fromType, char* from, short toType, char* to)
{
if (extract)
{
isqlGlob.printf("CREATE ");
if (global)
isqlGlob.printf("GLOBAL ");
}
printIdent(extract, name, extract ? "MAPPING %s " : "%s ");
isqlGlob.printf("USING ");
switch (usng[0])
{
case 'P':
if (!plugin)
isqlGlob.printf("ANY PLUGIN ");
else
printIdent(extract, plugin, "PLUGIN %s ");
break;
case 'S':
isqlGlob.printf("ANY PLUGIN SERVERWIDE ");
break;
case '*':
isqlGlob.printf("* ");
break;
case 'M':
isqlGlob.printf("MAPPING ");
break;
default:
isqlGlob.printf("/*unknown = %c*/ ", usng[0]);
}
if (db)
printIdent(extract, db, "IN %s ");
fb_utils::exact_name(from);
bool anyObj = strcmp(from, "*") == 0;
isqlGlob.printf("FROM %s", anyObj ? "ANY " : "");
printIdent(extract, fromType, "%s ");
if (!anyObj)
printIdent(extract, from, "%s ");
isqlGlob.printf("TO %s ", toType ? "ROLE" : "USER");
if (to)
printIdent(extract, to);
isqlGlob.printf("%s%s", extract ? ";" : "", NEWLINE);
}
processing_state SHOW_maps(bool extract, const SCHAR* map_name)
{
/*************************************
*
* s h o w _ m a p s
*
**************************************
*
* Functional description
* Show all maps or maps to map_name
************************************/
if (isqlGlob.major_ods < ODS_VERSION12)
return OBJECT_NOT_FOUND;
bool first = true;
// List all mappings
FOR M IN RDB$MAP WITH
(M.RDB$SYSTEM_FLAG NE 1 OR M.RDB$SYSTEM_FLAG MISSING)
SORTED BY M.RDB$MAP_NAME
Firebird::NoCaseString nm = M.RDB$MAP_NAME;
nm.trim();
if ((!*map_name) || (nm == map_name))
{
if (first && extract)
isqlGlob.printf("%s/* Mapping security objects for this database */%s", NEWLINE, NEWLINE);
first = false;
printMap(extract, false, M.RDB$MAP_NAME, M.RDB$MAP_USING,
M.RDB$MAP_PLUGIN.NULL ? NULL : M.RDB$MAP_PLUGIN,
M.RDB$MAP_DB.NULL ? NULL : M.RDB$MAP_DB,
M.RDB$MAP_FROM_TYPE, M.RDB$MAP_FROM,
M.RDB$MAP_TO_TYPE, M.RDB$MAP_TO.NULL ? NULL : M.RDB$MAP_TO);
}
END_FOR
ON_ERROR
ISQL_errmsg(fbStatus);
return ps_ERR;
END_ERROR;
bool firstGlobal = true;
// List global mappings
FOR M IN SEC$GLOBAL_MAP
SORTED BY M.SEC$MAP_NAME
Firebird::NoCaseString nm = M.SEC$MAP_NAME;
nm.trim();
if ((!*map_name) || (nm == map_name))
{
if (firstGlobal)
{
const char* sep = extract ? "/" : "**";
isqlGlob.printf("%s%s* Global mapping *%s%s",
(first && (!extract)) ? "" : NEWLINE, sep, sep, NEWLINE);
firstGlobal = false;
}
first = false;
printMap(extract, true, M.SEC$MAP_NAME, M.SEC$MAP_USING,
M.SEC$MAP_PLUGIN.NULL ? NULL : M.SEC$MAP_PLUGIN,
M.SEC$MAP_DB.NULL ? NULL : M.SEC$MAP_DB,
M.SEC$MAP_FROM_TYPE, M.SEC$MAP_FROM,
M.SEC$MAP_TO_TYPE, M.SEC$MAP_TO.NULL ? NULL : M.SEC$MAP_TO);
}
END_FOR
ON_ERROR
ISQL_errmsg(fbStatus);
return ps_ERR;
END_ERROR;
return first ? OBJECT_NOT_FOUND : SKIP;
}
static processing_state show_proc(const SCHAR* procname)
{
/**************************************

View File

@ -37,5 +37,6 @@ void SHOW_print_metadata_text_blob(FILE*, ISC_QUAD*, bool escape_squote = false)
processing_state SHOW_metadata(const SCHAR* const*, SCHAR**);
void SHOW_read_owner();
const Firebird::string SHOW_trigger_action(SINT64);
processing_state SHOW_maps(bool extract, const SCHAR* map_name);
#endif // ISQL_SHOW_PROTO_H

1116
src/jrd/Mapping.cpp Normal file

File diff suppressed because it is too large Load Diff

68
src/jrd/Mapping.h Normal file
View File

@ -0,0 +1,68 @@
/*
* PROGRAM: JRD access method
* MODULE: Mapping.h
* DESCRIPTION: Maps names in authentication block
*
* 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_MAPPING
#define JRD_MAPPING
#include "../common/classes/alloc.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/ClumpletReader.h"
#include "../jrd/recsrc/RecordSource.h"
#include "../jrd/DatabaseSnapshot.h"
namespace Jrd {
void mapUser(Firebird::string& name, Firebird::string& trusted_role, Firebird::string* auth_method,
Firebird::AuthReader::AuthBlock* newAuthBlock, const Firebird::AuthReader::AuthBlock& authBlock,
const char* db, const char* securityDb);
void flashMap(const char* dbName);
class GlobalMappingScan: public VirtualTableScan
{
public:
GlobalMappingScan(CompilerScratch* csb, const Firebird::string& name, StreamType stream)
: VirtualTableScan(csb, name, stream)
{}
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 MappingList : public DataDump
{
public:
MappingList(jrd_tra* tra);
RecordBuffer* getList(thread_db* tdbb, jrd_rel* relation);
};
} // namespace Jrd
#endif // JRD_MAPPING

View File

@ -88,12 +88,6 @@ UserManagement::UserManagement(jrd_tra* tra)
return att->att_user->usr_sql_role_name.c_str();
}
int FB_CARG forceAdmin()
{
return ((att->att_user->usr_flags & USR_trole) &&
att->att_user->usr_sql_role_name == ADMIN_ROLE) ? 1 : 0;
}
const char* FB_CARG networkProtocol()
{
return att->att_network_protocol.c_str();

View File

@ -81,7 +81,7 @@ const char* const ISC_USER = "ISC_USER";
const char* const ISC_PASSWORD = "ISC_PASSWORD";
const char* const NULL_ROLE = "NONE";
const char* const ADMIN_ROLE = "RDB$ADMIN";
#define ADMIN_ROLE "RDB$ADMIN" // It's used in C-string concatenations
// User name assigned to any user granted USR_locksmith rights.
// If this name is changed, modify also the trigger in
@ -91,7 +91,6 @@ const char* const SYSDBA_USER_NAME = "SYSDBA";
// This temporary set of flags is needed to implement minimum form of
// ALTER ROLE RDB$ADMIN ADD/DROP SYSTEM_NAME "Domain Admins".
// Value 1 is skipped because rdb$system_flag = 1 is used in all other cases.
const SSHORT ROLE_FLAG_MAY_TRUST = 2;
const SSHORT ROLE_FLAG_DBO = 4;
const char* const PRIMARY_KEY = "PRIMARY KEY";
@ -359,7 +358,10 @@ static const char* const DDL_TRIGGER_ACTION_NAMES[][2] =
{"ALTER", "PACKAGE"},
{"DROP", "PACKAGE"},
{"CREATE", "PACKAGE BODY"},
{"DROP", "PACKAGE BODY"}
{"DROP", "PACKAGE BODY"},
{"CREATE", "MAPPING"},
{"ALTER", "MAPPING"},
{"DROP", "MAPPING"}
};
const int DDL_TRIGGER_BEFORE = 0;
@ -407,6 +409,9 @@ const int DDL_TRIGGER_ALTER_PACKAGE = 41;
const int DDL_TRIGGER_DROP_PACKAGE = 42;
const int DDL_TRIGGER_CREATE_PACKAGE_BODY = 43;
const int DDL_TRIGGER_DROP_PACKAGE_BODY = 44;
const int DDL_TRIGGER_CREATE_MAPPING = 45;
const int DDL_TRIGGER_ALTER_MAPPING = 46;
const int DDL_TRIGGER_DROP_MAPPING = 47;
// that's how database trigger action types are encoded
// (TRIGGER_TYPE_DB | type)
@ -418,11 +423,12 @@ const int DDL_TRIGGER_DROP_PACKAGE_BODY = 44;
// is specified by the client application
#define USERNAME_SWITCH "USER"
#define PASSWORD_SWITCH "PASSWORD"
/*
#define TRUSTED_USER_SWITCH "TRUSTED_SVC"
#define TRUSTED_USER_SWITCH_LEN (sizeof(TRUSTED_USER_SWITCH) - 1)
#define TRUSTED_ROLE_SWITCH "TRUSTED_ROLE"
#define TRUSTED_ROLE_SWITCH_LEN (sizeof(TRUSTED_ROLE_SWITCH) - 1)
*/
const TraNumber MAX_TRA_NUMBER = ~TraNumber(0);
#endif // JRD_CONSTANTS_H

View File

@ -126,6 +126,7 @@
#include "../common/utils_proto.h"
#include "../common/classes/Hash.h"
#include "../jrd/CryptoManager.h"
#include "../jrd/Mapping.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@ -153,7 +154,7 @@ namespace Jrd {
typedef Hash<
DeferredWork,
DefaultHash<DeferredWork>::DEFAULT_SIZE,
DEFAULT_HASH_SIZE,
DeferredWork,
DefaultKeyValue<DeferredWork>,
DeferredWork
@ -311,7 +312,7 @@ class DfwSavePoint;
typedef Hash<
DfwSavePoint,
DefaultHash<DfwSavePoint>::DEFAULT_SIZE,
DEFAULT_HASH_SIZE,
SLONG,
DfwSavePoint
> DfwSavePointHash;
@ -398,6 +399,7 @@ static bool drop_package_body(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool grant_privileges(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool db_crypt(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool set_linger(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
static bool flash_cache(thread_db*, SSHORT, DeferredWork*, jrd_tra*);
// ----------------------------------------------------------------
@ -969,6 +971,7 @@ static const deferred_task task_table[] =
{ dfw_store_view_context_type, store_view_context_type },
{ dfw_db_crypt, db_crypt },
{ dfw_set_linger, set_linger },
{ dfw_flash_cache, flash_cache },
{ dfw_null, NULL }
};
@ -2033,6 +2036,35 @@ static bool set_linger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tr
return false;
}
static bool flash_cache(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra*)
{
/**************************************
*
* s e t _ l i n g e r
*
**************************************
*
* Set linger interval in Database block.
*
**************************************/
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
switch (phase)
{
case 1:
case 2:
return true;
case 3:
flashMap(dbb->dbb_filename.c_str());
break;
}
return false;
}
static bool check_not_null(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
{
/**************************************

View File

@ -162,7 +162,8 @@ enum drq_type_t
drq_l_arg_src, // lookup a function argument source
drq_l_prm_coll, // lookup procedure parameter collation
drq_l_arg_coll, // lookup function argument collation
drq_m_map, // modify os=>db names mapping
drq_map_sto, // store login mapping
drq_map_mod, // modify/erase login mapping
drq_l_idx_name, // lookup index name
drq_l_collation, // DSQL/DdlNodes: lookup collation
drq_m_charset, // DSQL/DdlNodes: modify character set

View File

@ -313,15 +313,10 @@ void Connection::generateDPB(thread_db* tdbb, ClumpletWriter& dpb,
const Jrd::Attachment* attachment = tdbb->getAttachment();
dpb.insertInt(isc_dpb_ext_call_depth, attachment->att_ext_call_depth + 1);
const string& attUser = attachment->att_user->usr_user_name;
const string& attRole = attachment->att_user->usr_sql_role_name;
if ((m_provider.getFlags() & prvTrustedAuth) &&
(user.isEmpty() || user == attUser) && pwd.isEmpty() &&
(role.isEmpty() || role == attRole))
user.isEmpty() && pwd.isEmpty() && role.isEmpty())
{
dpb.insertString(isc_dpb_trusted_auth, attUser);
dpb.insertString(isc_dpb_trusted_role, attRole);
attachment->att_user->populateDpb(dpb);
}
else
{
@ -340,6 +335,8 @@ void Connection::generateDPB(thread_db* tdbb, ClumpletWriter& dpb,
if (cs) {
dpb.insertString(isc_dpb_lc_ctype, cs->getName());
}
// remote network address???
}
bool Connection::isSameDatabase(thread_db* tdbb, const string& dbName,

View File

@ -180,3 +180,11 @@
FIELD(fld_auth_method , nam_auth_method , dtype_varying , 255 , dsc_text_type_ascii , NULL , true)
FIELD(fld_linger , nam_linger , dtype_long , sizeof(SLONG) , 0 , NULL , true)
FIELD(fld_map_name , nam_map_name , dtype_text , MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , false)
FIELD(fld_map_using , nam_map_using, dtype_text, 1 , dsc_text_type_metadata , NULL , false)
FIELD(fld_map_plugin , nam_map_plugin, dtype_text, MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , true)
FIELD(fld_map_db , nam_map_db, dtype_text, MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , true)
FIELD(fld_map_from_type , nam_map_from_type , dtype_text, MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , false)
FIELD(fld_map_from , nam_map_from, dtype_text, 255 , dsc_text_type_metadata , NULL , true)
FIELD(fld_map_to , nam_map_to, dtype_text, MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , true)

View File

@ -278,6 +278,10 @@ static const struct ini_idx_t indices[] =
INDEX(51, rel_args, 0, 2)
SEGMENT(f_arg_rname, idx_metadata), // relation name
SEGMENT(f_arg_fname, idx_metadata) // field name
}},
// define index RDB$INDEX_52 for RDB$MAP RDB$MAP_NAME;
INDEX(52, rel_map, 0, 1)
SEGMENT(f_map_name, idx_metadata) // mapping name
}}
};

View File

@ -109,6 +109,7 @@
#include "../jrd/event_proto.h"
#include "../yvalve/why_proto.h"
#include "../jrd/flags.h"
#include "../jrd/Mapping.h"
#include "../jrd/Database.h"
@ -860,7 +861,7 @@ public:
string dpb_config;
public:
static const ULONG DPB_FLAGS_MASK = DBB_damaged | DBB_security_db;
static const ULONG DPB_FLAGS_MASK = DBB_damaged;
DatabaseOptions()
{
@ -1291,7 +1292,7 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
}
// Check for correct credentials supplied
getUserInfo(userId, options, org_filename.c_str(), &config);
getUserInfo(userId, options, expanded_name.c_str(), &config);
}
catch (const Exception& ex)
{
@ -1442,14 +1443,13 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
}
else
{
if ((dbb->dbb_flags & DatabaseOptions::DPB_FLAGS_MASK) != options.dpb_flags)
if ((dbb->dbb_flags & DatabaseOptions::DPB_FLAGS_MASK) !=
(options.dpb_flags & DatabaseOptions::DPB_FLAGS_MASK))
{
// looks like someone tries to attach incompatibly
Arg::Gds err(isc_bad_dpb_content);
if ((dbb->dbb_flags & DBB_damaged) != (options.dpb_flags & DBB_damaged))
err << Arg::Gds(isc_random) << "incompatible damaged database mode";
if ((dbb->dbb_flags & DBB_security_db) != (options.dpb_flags & DBB_security_db))
err << Arg::Gds(isc_random) << "incompatible security database mode";
err << Arg::Gds(isc_baddpb_damaged_mode);
err.raise();
}
@ -2387,7 +2387,7 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
}
// Check for correct credentials supplied
getUserInfo(userId, options, org_filename.c_str(), &config);
getUserInfo(userId, options, expanded_name.c_str(), &config);
}
catch (const Exception& ex)
{
@ -5471,7 +5471,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
if (dpb_page_buffers &&
(dpb_page_buffers < MIN_PAGE_BUFFERS || dpb_page_buffers > MAX_PAGE_BUFFERS))
{
ERR_post(Arg::Gds(isc_bad_dpb_content));
ERR_post(Arg::Gds(isc_bad_dpb_content) << Arg::Gds(isc_baddpb_buffers_range));
}
dpb_set_page_buffers = true;
break;
@ -5480,9 +5480,11 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
if (!Config::getSharedCache())
{
dpb_buffers = rdr.getInt();
if (dpb_buffers < 10)
int TEMP_LIMIT = 25;
if (dpb_buffers < TEMP_LIMIT)
{
ERR_post(Arg::Gds(isc_bad_dpb_content));
ERR_post(Arg::Gds(isc_bad_dpb_content) <<
Arg::Gds(isc_baddpb_temp_buffers) << Arg::Num(TEMP_LIMIT));
}
}
else
@ -5662,10 +5664,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
case isc_dpb_sec_attach:
dpb_sec_attach = rdr.getInt() != 0;
if (dpb_sec_attach)
{
dpb_buffers = 50;
dpb_flags |= DBB_security_db;
}
break;
case isc_dpb_gbak_attach:
@ -6990,6 +6989,7 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
}
else
{
auth_method = "User name in DPB";
if (options.dpb_trusted_login.hasData())
{
name = options.dpb_trusted_login;
@ -7000,32 +7000,19 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
}
else if (options.dpb_auth_block.hasData())
{
// stub instead mapUser(....);
AuthReader auth(options.dpb_auth_block);
PathName secureDb;
if (auth.getInfo(&name, &auth_method, &secureDb))
{
ISC_systemToUtf8(name);
if (secureDb.hasData())
{
if (config && (secureDb != (*config)->getSecurityDatabase()))
(Arg::Gds(isc_sec_context) << dbName).raise();
}
else
{
auth.moveNext();
if (auth.getInfo(&trusted_role, NULL, NULL))
ISC_systemToUtf8(trusted_role);
}
}
mapUser(name, trusted_role, &auth_method, &user.usr_auth_block, options.dpb_auth_block,
dbName, config ? (*config)->getSecurityDatabase() : NULL);
ISC_systemToUtf8(name);
ISC_systemToUtf8(trusted_role);
}
else
{
auth_method = "OS user name";
wheel = ISC_get_user(&name, &id, &group);
ISC_systemToUtf8(name);
if (id == 0)
{
auth_method = "OS user name / wheel";
wheel = true;
}
}
@ -7063,7 +7050,6 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
user.usr_auth_method = auth_method;
user.usr_user_id = id;
user.usr_group_id = group;
user.usr_auth_block.assign(options.dpb_auth_block);
if (wheel)
{

View File

@ -356,8 +356,30 @@ NAME("MON$TRANSACTION_ID", nam_mon_tra_id)
NAME("MON$USER", nam_mon_user)
NAME("MON$VARIABLE_NAME", nam_mon_var_name)
NAME("MON$VARIABLE_VALUE", nam_mon_var_value)
NAME("SEC$USERS", nam_sec_users)
NAME("SEC$USER_ATTRIBUTES", nam_sec_user_attributes)
NAME("RDB$BOOLEAN", nam_bool)
NAME("SEC$KEY", nam_sec_attr_key)
NAME("SEC$VALUE", nam_sec_attr_value)
NAME("RDB$MAP", nam_map)
NAME("SEC$GLOBAL_MAP", nam_sec_global_map)
NAME("RDB$MAP_NAME", nam_map_name)
NAME("RDB$MAP_USING", nam_map_using)
NAME("RDB$MAP_PLUGIN", nam_map_plugin)
NAME("RDB$MAP_DB", nam_map_db)
NAME("RDB$MAP_FROM_TYPE", nam_map_from_type)
NAME("RDB$MAP_FROM", nam_map_from)
NAME("RDB$MAP_TO_TYPE", nam_map_to_type)
NAME("RDB$MAP_TO", nam_map_to)
NAME("SEC$MAP_NAME", nam_sec_map_name)
NAME("SEC$MAP_USING", nam_sec_map_using)
NAME("SEC$MAP_PLUGIN", nam_sec_map_plugin)
NAME("SEC$MAP_DB", nam_sec_map_db)
NAME("SEC$MAP_FROM_TYPE", nam_sec_map_from_type)
NAME("SEC$MAP_FROM", nam_sec_map_from)
NAME("SEC$MAP_TO_TYPE", nam_sec_map_to_type)
NAME("SEC$MAP_TO", nam_sec_map_to)

View File

@ -84,6 +84,7 @@
#include "../common/classes/objects_array.h"
#include "../jrd/recsrc/RecordSource.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/Mapping.h"
#include "../jrd/Optimizer.h"
#include "../dsql/BoolNodes.h"
@ -2285,7 +2286,11 @@ static RecordSource* gen_retrieval(thread_db* tdbb,
else if (relation->isVirtual())
{
// Virtual table: monitoring or security
if (relation->rel_id == rel_sec_users || relation->rel_id == rel_sec_user_attributes)
if (relation->rel_id == rel_sec_global_map)
{
rsb = FB_NEW(*tdbb->getDefaultPool()) GlobalMappingScan(csb, alias, stream);
}
else if (relation->rel_id == rel_sec_users || relation->rel_id == rel_sec_user_attributes)
{
rsb = FB_NEW(*tdbb->getDefaultPool()) UsersTableScan(csb, alias, stream);
}

View File

@ -619,3 +619,29 @@ RELATION(nam_sec_user_attributes, rel_sec_user_attributes, ODS_12_0, rel_virtual
FIELD(f_sec_attr_key, nam_sec_attr_key, fld_attr_key, 0, ODS_12_0)
FIELD(f_sec_attr_value, nam_sec_attr_value, fld_attr_value, 0, ODS_12_0)
END_RELATION
// Relation 45 (RDB$MAP)
RELATION(nam_map, rel_map, ODS_12_0, rel_persistent)
FIELD(f_map_name, nam_map_name, fld_map_name, 1, ODS_12_0)
FIELD(f_map_using, nam_map_using, fld_map_using, 1, ODS_12_0)
FIELD(f_map_plugin, nam_map_plugin, fld_map_plugin, 1, ODS_12_0)
FIELD(f_map_db, nam_map_db, fld_map_db, 1, ODS_12_0)
FIELD(f_map_from_type, nam_map_from_type, fld_map_from_type, 1, ODS_12_0)
FIELD(f_map_from, nam_map_from, fld_map_from, 1, ODS_12_0)
FIELD(f_map_to_type, nam_map_to_type, fld_obj_type, 1, ODS_8_0)
FIELD(f_map_to, nam_map_to, fld_map_to, 1, ODS_12_0)
FIELD(f_map_sys_flag, nam_sys_flag, fld_flag, 1, ODS_12_0)
FIELD(f_map_desc, nam_description, fld_description, 1, ODS_12_0)
END_RELATION
// Relation 46 (SEC$GLOBAL_MAP)
RELATION(nam_sec_global_map, rel_sec_global_map, 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_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_db, nam_sec_map_db, fld_map_db, 0, ODS_12_0)
FIELD(f_sec_map_from_type, nam_sec_map_from_type, fld_map_from_type, 0, ODS_12_0)
FIELD(f_sec_map_from, nam_sec_map_from, fld_map_from, 0, ODS_12_0)
FIELD(f_sec_map_to_type, nam_sec_map_to_type, fld_obj_type, 0, ODS_8_0)
FIELD(f_sec_map_to, nam_sec_map_to, fld_map_to, 0, ODS_12_0)
END_RELATION

View File

@ -56,6 +56,7 @@
#include "../common/classes/array.h"
#include "../common/config/config.h"
#include "../common/os/os_utils.h"
#include "../common/classes/ClumpletWriter.h"
const int UIC_BASE = 10;
@ -872,20 +873,8 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
}
END_FOR
}
if (!found && (tempId.usr_flags & USR_trole))
{
request.reset(tdbb, irq_verify_trusted_role, IRQ_REQUESTS);
FOR (REQUEST_HANDLE request) FIRST 1 RR IN RDB$ROLES
WITH RR.RDB$ROLE_NAME EQ sql_role
AND RR.RDB$SYSTEM_FLAG > 0
{
if (RR.RDB$SYSTEM_FLAG & ROLE_FLAG_MAY_TRUST)
found = true;
}
END_FOR
}
else
found = true;
if (!found)
role_name = NULL_ROLE;
@ -1452,3 +1441,10 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb,
return privilege;
}
void Jrd::UserId::populateDpb(Firebird::ClumpletWriter& dpb)
{
if (usr_auth_block.hasData())
dpb.insertBytes(isc_dpb_auth_block, usr_auth_block.begin(), usr_auth_block.getCount());
else
dpb.insertString(isc_dpb_user_name, usr_user_name);
}

View File

@ -28,6 +28,10 @@
#include "../common/classes/tree.h"
#include "../common/security.h"
namespace Firebird {
class ClumpletWriter;
}
namespace Jrd {
const size_t ACL_BLOB_BUFFER_SIZE = MAX_USHORT; // used to read/write acl blob
@ -91,7 +95,7 @@ public:
Firebird::string usr_project_name; // Project name
Firebird::string usr_org_name; // Organization name
Firebird::string usr_auth_method; // Authentication method
Auth::UserData::AuthenticationBlock usr_auth_block; // Authentication block like it was passed to engine
Auth::UserData::AuthenticationBlock usr_auth_block; // Authentication block after mapping
USHORT usr_user_id; // User id
USHORT usr_group_id; // Group id
USHORT usr_flags; // Misc. crud
@ -146,6 +150,8 @@ public:
return *this;
}
void populateDpb(Firebird::ClumpletWriter& dpb);
};
// These numbers are arbitrary and only used at run-time. Can be changed if necessary at any moment.

View File

@ -56,11 +56,13 @@
#include "../common/classes/ClumpletWriter.h"
#include "../jrd/ibase.h"
#include "../common/utils_proto.h"
#include "../common/db_alias.h"
#include "../jrd/scl.h"
#include "../jrd/msg_encode.h"
#include "../jrd/trace/TraceManager.h"
#include "../jrd/trace/TraceObjects.h"
#include "../jrd/EngineInterface.h"
#include "../jrd/Mapping.h"
#include "../common/classes/DbImplementation.h"
@ -244,17 +246,9 @@ void Service::getOptions(ClumpletReader& spb)
svc_auth_block.add(spb.getBytes(), spb.getClumpLength());
break;
case isc_spb_trusted_auth:
spb.getString(svc_trusted_login);
break;
case isc_spb_trusted_role:
svc_trusted_role = true;
break;
case isc_spb_command_line:
spb.getString(svc_command_line);
{
/* {
// HACK: this does not care about the words on allowed places.
string cLine = svc_command_line;
cLine.upper();
@ -264,6 +258,10 @@ void Service::getOptions(ClumpletReader& spb)
(Arg::Gds(isc_bad_spb_form) << Arg::Gds(isc_no_trusted_spb)).raise();
}
}
*/ break;
case isc_spb_expected_db:
spb.getPath(svc_expected_db);
break;
case isc_spb_address_path:
@ -711,7 +709,7 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
svc_resp_alloc(getPool()), svc_resp_buf(0), svc_resp_ptr(0), svc_resp_buf_len(0),
svc_resp_len(0), svc_flags(0), svc_user_flag(0), svc_spb_version(0), svc_do_shutdown(false),
svc_username(getPool()), svc_auth_block(getPool()),
svc_trusted_login(getPool()), svc_trusted_role(false), svc_utf8(false),
svc_expected_db(getPool()), svc_trusted_role(false), svc_utf8(false),
svc_switches(getPool()), svc_perm_sw(getPool()), svc_address_path(getPool()),
svc_command_line(getPool()),
svc_network_protocol(getPool()), svc_remote_address(getPool()), svc_remote_process(getPool()),
@ -766,26 +764,21 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
}
else
{
if (svc_trusted_login.hasData())
{
svc_username = svc_trusted_login;
}
if (!svc_username.hasData())
{
if (svc_auth_block.hasData())
{
// stub instead mapUser(....);
AuthReader auth(svc_auth_block);
Firebird::string method;
if (auth.getInfo(&svc_username, &method, NULL) && method == "Win_Sspi")
{
auth.moveNext();
if (!auth.isEof())
{
svc_trusted_role = true;
}
}
PathName dummy;
RefPtr<Config> config;
expandDatabaseName(svc_expected_db, dummy, &config);
string trusted_role;
mapUser(svc_username, trusted_role, NULL, &svc_auth_block, svc_auth_block,
NULL, config->getSecurityDatabase());
// to be changed after refsoft special roles patch!!!
trusted_role.upper();
svc_trusted_role = trusted_role == ADMIN_ROLE;
}
else
{
@ -2045,17 +2038,9 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data)
{
if (svc_username.hasData())
{
string auth = "-";
auth += TRUSTED_USER_SWITCH;
auth += ' ';
string auth = "-user ";
auth += svc_username;
auth += ' ';
if (svc_trusted_role)
{
auth += "-";
auth += TRUSTED_ROLE_SWITCH;
auth += ' ';
}
svc_switches = auth + svc_switches;
}
}
@ -2782,14 +2767,14 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
string s;
spb.getString(s);
// HACK: this does not care about the words on allowed places.
/* // HACK: this does not care about the words on allowed places.
string cLine = s;
cLine.upper();
if (cLine.find(TRUSTED_USER_SWITCH) != string::npos ||
cLine.find(TRUSTED_ROLE_SWITCH) != string::npos)
{
(Arg::Gds(isc_bad_spb_form) << Arg::Gds(isc_no_trusted_spb)).raise();
}
} */
switches += s;
switches += ' ';

View File

@ -289,7 +289,7 @@ private:
Firebird::string svc_username;
Firebird::AuthReader::AuthBlock svc_auth_block;
Firebird::string svc_trusted_login;
Firebird::PathName svc_expected_db;
bool svc_trusted_role;
bool svc_utf8;
Firebird::string svc_switches; // Full set of switches

View File

@ -42,6 +42,7 @@
#include "../jrd/intl_classes.h"
#include "../common/ThreadStart.h"
#include "../jrd/UserManagement.h"
#include "../jrd/Mapping.h"
#include "../jrd/blb_proto.h"
#include "../jrd/cch_proto.h"
#include "../jrd/cmp_proto.h"
@ -73,6 +74,7 @@
#include "../jrd/trace/TraceJrdHelpers.h"
#include "../jrd/Function.h"
#include "../jrd/Collation.h"
#include "../jrd/Mapping.h"
const int DYN_MSG_FAC = 8;
@ -375,6 +377,23 @@ void TRA_commit(thread_db* tdbb, jrd_tra* transaction, const bool retaining_flag
if (!(transaction->tra_flags & TRA_prepared))
DFW_perform_work(tdbb, transaction);
// Commit associated transaction in security DB
SecDbContext* secContext = transaction->getSecDbContext();
if (secContext && secContext->tra)
{
LocalStatus s;
secContext->tra->commit(&s);
if (!s.isSuccess())
status_exception::raise(s.get());
secContext->tra = NULL;
flashMap(tdbb->getDatabase()->dbb_config->getSecurityDatabase());
transaction->eraseSecDbContext();
}
if (transaction->tra_flags & (TRA_prepare2 | TRA_reconnected))
MET_update_transaction(tdbb, transaction, true);
@ -958,6 +977,17 @@ void TRA_prepare(thread_db* tdbb, jrd_tra* transaction, USHORT length, const UCH
transaction->tra_flags |= TRA_prepare2;
}
// Prepare associated transaction in security DB
SecDbContext* secContext = transaction->getSecDbContext();
if (secContext && secContext->tra)
{
LocalStatus s;
secContext->tra->prepare(&s, length, msg);
if (!s.isSuccess())
status_exception::raise(s.get());
}
// Perform any meta data work deferred
DFW_perform_work(tdbb, transaction);
@ -3302,6 +3332,7 @@ jrd_tra::~jrd_tra()
delete tra_undo_record;
delete tra_undo_space;
delete tra_user_management;
delete tra_mapping_list;
delete tra_gen_ids;
if (!tra_outer)
@ -3325,6 +3356,8 @@ jrd_tra::~jrd_tra()
{
MemoryPool::deletePool(tra_autonomous_pool);
}
delete tra_sec_db_context;
}
@ -3358,6 +3391,16 @@ UserManagement* jrd_tra::getUserManagement()
}
MappingList* jrd_tra::getMappingList()
{
if (!tra_mapping_list)
{
tra_mapping_list = FB_NEW(*tra_pool) MappingList(this);
}
return tra_mapping_list;
}
jrd_tra* jrd_tra::getOuter()
{
jrd_tra* tra = this;
@ -3538,3 +3581,41 @@ void TraceSweepEvent::report(ntrace_process_state_t state)
if (state == process_state_failed || state == process_state_finished)
m_need_trace = false;
}
SecDbContext::SecDbContext(IAttachment* a, ITransaction* t)
: att(a), tra(t), savePoint(0)
{ }
SecDbContext::~SecDbContext()
{
LocalStatus s;
if (tra)
{
tra->rollback(&s);
tra = NULL;
}
if (att)
{
att->detach(&s);
att = NULL;
}
}
SecDbContext* jrd_tra::getSecDbContext()
{
return tra_sec_db_context;
}
SecDbContext* jrd_tra::setSecDbContext(IAttachment* att, ITransaction* tra)
{
fb_assert(!tra_sec_db_context);
tra_sec_db_context = FB_NEW(*getDefaultMemoryPool()) SecDbContext(att, tra);
return tra_sec_db_context;
}
void jrd_tra::eraseSecDbContext()
{
delete tra_sec_db_context;
tra_sec_db_context = NULL;
}

View File

@ -50,6 +50,11 @@ namespace EDS {
class Transaction;
}
namespace Firebird {
class IAttachment;
class ITransaction;
};
namespace Jrd {
class blb;
@ -65,8 +70,19 @@ class DeferredWork;
class DeferredJob;
class dsql_opn;
class UserManagement;
class MappingList;
class thread_db;
class SecDbContext
{
public:
SecDbContext(Firebird::IAttachment* a, Firebird::ITransaction* t);
~SecDbContext();
Firebird::IAttachment* att;
Firebird::ITransaction* tra;
int savePoint;
};
//Moved to fb_types.h
//typedef ULONG TraNumber;
@ -174,6 +190,8 @@ public:
tra_undo_space(NULL),
tra_undo_record(NULL),
tra_user_management(NULL),
tra_sec_db_context(NULL),
tra_mapping_list(NULL),
tra_autonomous_pool(NULL),
tra_autonomous_cnt(0)
{
@ -283,6 +301,8 @@ private:
Record* tra_undo_record; // temporary record used for the undo purposes
UserManagement* tra_user_management;
SecDbContext* tra_sec_db_context;
MappingList* tra_mapping_list;
MemoryPool* tra_autonomous_pool;
USHORT tra_autonomous_cnt;
static const USHORT TRA_AUTONOMOUS_PER_POOL = 64;
@ -335,6 +355,10 @@ public:
}
UserManagement* getUserManagement();
SecDbContext* getSecDbContext();
SecDbContext* setSecDbContext(Firebird::IAttachment* att, Firebird::ITransaction* tra);
void eraseSecDbContext();
MappingList* getMappingList();
GenIdCache* getGenIdCache()
{
@ -503,7 +527,8 @@ enum dfw_t {
dfw_arg_new_name, // new name
dfw_arg_field_not_null, // set domain to not nullable
dfw_db_crypt, // change database encryption status
dfw_set_linger // set database linger
dfw_set_linger, // set database linger
dfw_flash_cache // flash user mapping cache
};
// Verb actions

View File

@ -355,7 +355,7 @@ void fbtrace(UtilSvc* uSvc, TraceSvcIntf* traceSvc)
adminRole = true;
break;
/*
case IN_SW_TRACE_TRUSTED_USER:
if (!uSvc->isService())
usage(uSvc, isc_trace_switch_svc_only, sw->in_sw_name);
@ -376,7 +376,7 @@ void fbtrace(UtilSvc* uSvc, TraceSvcIntf* traceSvc)
adminRole = true;
break;
*/
case IN_SW_TRACE_SERVICE_NAME:
if (uSvc->isService())
continue;
@ -431,17 +431,17 @@ void fbtrace(UtilSvc* uSvc, TraceSvcIntf* traceSvc)
authBlock.add(bytes, authBlockSize);
AuthReader auth(authBlock);
PathName secureDb;
AuthReader::Info info;
if (auth.getInfo(&user, NULL, &secureDb))
if (auth.getInfo(info))
{
pwd = "";
user = info.name.ToString();
adminRole = false;
if (!secureDb.hasData())
if (!info.secDb.hasData())
{
auth.moveNext();
string trusted_role;
if (auth.getInfo(&trusted_role, NULL, NULL))
if (auth.getInfo(info))
{
adminRole = true;
}

View File

@ -73,8 +73,8 @@ static const struct Switches::in_sw_tab_t trace_auth_in_sw_table [] =
{IN_SW_TRACE_PASSWORD, 0, PASSWORD_SWITCH, 0, 0, 0, false, 0, 1, NULL},
{IN_SW_TRACE_SERVICE_NAME, 0, "SERVICE", 0, 0, 0, false, 0, 2, NULL},
{IN_SW_TRACE_TRUSTED_AUTH, 0, "TRUSTED", 0, 0, 0, false, 0, 1, NULL},
{IN_SW_TRACE_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL},
{IN_SW_TRACE_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL},
// {IN_SW_TRACE_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL},
// {IN_SW_TRACE_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL},
{IN_SW_TRACE_USERNAME, 0, USERNAME_SWITCH, 0, 0, 0, false, 0, 1, NULL},
{0, 0, NULL, 0, 0, 0, false, 0, 0, NULL} // End of List
};

View File

@ -1,7 +1,7 @@
/* 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 (?, ?, ?, ?);
--
('2014-03-31 20:48:34', 'JRD', 0, 757)
('2014-04-04 16:13:24', 'JRD', 0, 768)
('2012-01-23 20:10:30', 'QLI', 1, 532)
('2013-11-13 15:59:10', 'GFIX', 3, 122)
('1996-11-07 13:39:40', 'GPRE', 4, 1)
@ -9,8 +9,8 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
('2014-03-31 18:46:42', 'DYN', 8, 288)
('1996-11-07 13:39:40', 'INSTALL', 10, 1)
('1996-11-07 13:38:41', 'TEST', 11, 4)
('2014-03-03 19:17:14', 'GBAK', 12, 353)
('2014-01-26 23:00:00', 'SQLERR', 13, 1034)
('2014-04-04 16:08:08', 'GBAK', 12, 354)
('2014-04-04 16:36:53', 'SQLERR', 13, 1035)
('1996-11-07 13:38:42', 'SQLWARN', 14, 613)
('2006-09-10 03:04:31', 'JRD_BUGCHK', 15, 307)
('2014-01-13 15:41:16', 'ISQL', 17, 184)

View File

@ -864,6 +864,17 @@ Data source : @4', NULL, NULL)
('forupdate_systbl', 'PAR_rse', 'par.cpp', NULL, 0, 754, NULL, 'Cannot select system table @1 for update WITH LOCK', NULL, NULL)
('forupdate_temptbl', 'PAR_rse', 'par.cpp', NULL, 0, 755, NULL, 'Cannot select temporary table @1 for update WITH LOCK', NULL, NULL)
('cant_modify_sysobj', NULL, 'ExprNodes.cpp', NULL, 0, 756, NULL, 'System @1 @2 cannot be modified', NULL, 'Ex: System generator rdb$... cannot be modified')
('server_misconfigured', 'expandDatabaseName', 'db_alias.cpp', NULL, 0, 757, NULL, 'Server misconfigured - contact administrator please', NULL, NULL);
('alter_role', 'MappingNode::validateAdmin', 'DdlNodes.epp', NULL, 0, 758, NULL, 'Deprecated backward compatibility ALTER ROLE ... SET/DROP AUTO ADMIN mapping may be used only for RDB$ADMIN role', NULL, NULL);
('map_already_exists', 'MappingNode::execute', 'DdlNodes.epp', NULL, 0, 759, NULL, 'Mapping @1 already exists', NULL, NULL);
('map_not_exists', 'MappingNode::execute', 'DdlNodes.epp', NULL, 0, 760, NULL, 'Mapping @1 does not exist', NULL, NULL);
('map_load', 'check', 'Mapping.cpp', NULL, 0, 761, NULL, '@1 failed when loading mapping cache', NULL, NULL);
('map_aster', 'Cache::map', 'Mapping.cpp', NULL, 0, 762, NULL, 'Invalid name <*> in authentication block', NULL, NULL);
('map_multi', 'Cache::search', 'Mapping.cpp', NULL, 0, 763, NULL, 'Multiple maps found for @1', NULL, NULL);
('map_undefined', 'Found::set', 'Mapping.cpp', NULL, 0, 764, NULL, 'Undefined mapping result - more than one different results found', NULL, NULL);
('baddpb_damaged_mode', 'attachDatabase', 'jrd.cpp', NULL, 0, 765, NULL, 'Incompatible mode of attachment to damaged database', NULL, NULL);
('baddpb_buffers_range', 'DatabaseOptions::get', 'jrd.cpp', NULL, 0, 766, NULL, 'Attempt to set in database number of buffers which is out of acceptable range [@1:@2]', NULL, NULL);
('baddpb_temp_buffers', 'DatabaseOptions::get', 'jrd.cpp', NULL, 0, 767, NULL, 'Attempt to temporarily set number of buffers less than @1', NULL, NULL);
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
@ -2282,6 +2293,7 @@ ERROR: Backup incomplete', NULL, NULL);
(NULL, 'fix_system_generators', 'restore.epp', NULL, 12, 350, NULL, 'fixing system generators', NULL, NULL);
(NULL, 'BURP_abort', 'burp.cpp', NULL, 12, 351, NULL, 'Error closing database, but backup file is OK', NULL, NULL);
(NULL, NULL, 'restore.epp', NULL, 12, 352, NULL, 'database', NULL, NULL);
(NULL, 'get_mapping', 'restore.epp', NULL, 12, 353, NULL, 'required mapping attributes are missing in backup file', NULL, NULL);
-- SQLERR
(NULL, NULL, NULL, NULL, 13, 1, NULL, 'Firebird error', NULL, NULL);
(NULL, NULL, NULL, NULL, 13, 74, NULL, 'Rollback not performed', NULL, NULL);
@ -2559,6 +2571,7 @@ ERROR: Backup incomplete', NULL, NULL);
('dsql_grant_failed', 'getMainErrorCode', 'DdlNodes.h', NULL, 13, 1031, NULL, 'GRANT failed', NULL, NULL);
('dsql_revoke_failed', 'getMainErrorCode', 'DdlNodes.h', NULL, 13, 1032, NULL, 'REVOKE failed', NULL, NULL);
('dsql_cte_recursive_aggregate', 'pass1_rse_impl', 'dsql.cpp', NULL, 13, 1033, NULL, 'Recursive member of CTE cannot use aggregate or window function', NULL, NULL);
('dsql_mapping_failed', 'MappingNode::putErrorPrefix', 'DdlNodes.h', NULL, 13, 1034, NULL, '@2 MAPPING @1 failed', NULL, NULL);
-- SQLWARN
(NULL, NULL, NULL, NULL, 14, 100, NULL, 'Row not found for fetch, update or delete, or the result of a query is an empty table.', NULL, NULL);
(NULL, NULL, NULL, NULL, 14, 101, NULL, 'segment buffer length shorter than expected', NULL, NULL);

View File

@ -757,12 +757,23 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
(-902, '28', '000', 0, 748, 'secdb_name', NULL, NULL);
(-902, '28', '000', 0, 749, 'auth_data', NULL, NULL);
(-902, '28', '000', 0, 750, 'auth_datalength', NULL, NULL);
(-901, 'HY', '007', 0, 751, 'info_unprepared_stmt', NULL, NULL)
(-901, 'HY', '007', 0, 752, 'idx_key_value', NULL, NULL)
(-901, 'HY', '000', 0, 753, 'forupdate_virtualtbl', NULL, NULL)
(-901, 'HY', '000', 0, 754, 'forupdate_systbl', NULL, NULL)
(-901, 'HY', '000', 0, 755, 'forupdate_temptbl', NULL, NULL)
(-901, '42', '000', 0, 756, 'cant_modify_sysobj', NULL, NULL)
(-901, 'HY', '007', 0, 751, 'info_unprepared_stmt', NULL, NULL);
(-901, 'HY', '007', 0, 752, 'idx_key_value', NULL, NULL);
(-901, 'HY', '000', 0, 753, 'forupdate_virtualtbl', NULL, NULL);
(-901, 'HY', '000', 0, 754, 'forupdate_systbl', NULL, NULL);
(-901, 'HY', '000', 0, 755, 'forupdate_temptbl', NULL, NULL);
(-901, '42', '000', 0, 756, 'cant_modify_sysobj', NULL, NULL);
(-901, '08', '004', 0, 757, 'server_misconfigured', NULL, NULL);
(-901, '0A', '000', 0, 758, 'alter_role', NULL, NULL);
(-901, '42', 'S01', 0, 759, 'map_already_exists', NULL, NULL);
(-901, '42', 'S01', 0, 760, 'map_not_exists', NULL, NULL);
(-901, '08', '004', 0, 761, 'map_load', NULL, NULL);
(-901, '08', '004', 0, 762, 'map_aster', NULL, NULL);
(-901, '08', '004', 0, 763, 'map_multi', NULL, NULL);
(-901, '08', '004', 0, 764, 'map_undefined', NULL, NULL);
(-924, 'HY', '000', 0, 765, 'baddpb_damaged_mode', NULL, NULL);
(-924, 'HY', '000', 0, 766, 'baddpb_buffers_range', NULL, NULL);
(-924, 'HY', '000', 0, 767, 'baddpb_temp_buffers', NULL, NULL);
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
@ -1117,6 +1128,7 @@ COMMIT WORK;
(-901, '42', '000', 13, 1031, 'dsql_grant_failed', NULL, NULL);
(-901, '42', '000', 13, 1032, 'dsql_revoke_failed', NULL, NULL);
(-104, '42', '000', 13, 1033, 'dsql_cte_recursive_aggregate', NULL, NULL)
(-901, '42', '000', 13, 1034, 'dsql_mapping_failed', NULL, NULL);
-- GSEC
(-901, '00', '000', 18, 15, 'gsec_cant_open_db', NULL, NULL)
(-901, '00', '000', 18, 16, 'gsec_switches_error', NULL, NULL)

View File

@ -427,7 +427,7 @@ public:
if (!authServer)
{
authServer = authItr->plugin();
authPort->port_srv_auth_block->authBlockWriter.setMethod(authItr->name());
authPort->port_srv_auth_block->authBlockWriter.setPlugin(authItr->name());
}
// if we asked for more data but received nothing switch to next plugin
@ -1805,7 +1805,7 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
}
else
{
port->port_srv_auth_block->authBlockWriter.setMethod(plugins->name());
port->port_srv_auth_block->authBlockWriter.setPlugin(plugins->name());
switch (plugins->plugin()->authenticate(&status, port->port_srv_auth_block,
&port->port_srv_auth_block->authBlockWriter))
{

View File

@ -283,16 +283,16 @@ int gsec(Firebird::UtilSvc* uSvc)
uSvc->checkService();
fb_assert(user_data->trustedUser.entered() || user_data->authenticationBlock.hasData());
if (user_data->trustedUser.entered() || user_data->authenticationBlock.hasData())
fb_assert(user_data->dba.entered() || user_data->authenticationBlock.hasData());
if (user_data->dba.entered() || user_data->authenticationBlock.hasData())
{
class GsecInfo : public Firebird::AutoIface<ILogonInfo, FB_AUTH_LOGON_INFO_VERSION>
{
public:
GsecInfo(const char* pTrustedUser, const char* pRole, int pTrustedRole,
GsecInfo(const char* pDba, const char* pRole,
const char* pProtocol, const char* pAddress,
const UserData::AuthenticationBlock* pAuthBlock)
: trustedUser(pTrustedUser), sqlRole(pRole), trustedRole(pTrustedRole),
: dba(pDba), sqlRole(pRole),
protocol(pProtocol), address(pAddress),
authBytes(pAuthBlock->getCount() ? pAuthBlock->begin() : NULL),
authLength(pAuthBlock->getCount())
@ -301,7 +301,7 @@ int gsec(Firebird::UtilSvc* uSvc)
// ILogonInfo implementation
const char* FB_CARG name()
{
return trustedUser;
return dba;
}
const char* FB_CARG role()
@ -309,11 +309,6 @@ int gsec(Firebird::UtilSvc* uSvc)
return sqlRole;
}
int FB_CARG forceAdmin()
{
return trustedRole;
}
const char* FB_CARG networkProtocol()
{
return protocol;
@ -331,9 +326,8 @@ int gsec(Firebird::UtilSvc* uSvc)
}
private:
const char* trustedUser;
const char* dba;
const char* sqlRole;
int trustedRole;
const char* protocol;
const char* address;
const unsigned char* authBytes;
@ -351,8 +345,7 @@ int gsec(Firebird::UtilSvc* uSvc)
"Management plugin is missing or failed to load").value(), GsecMsg15);
}
GsecInfo info(user_data->trustedUser.get(), user_data->role.get(),
user_data->trustedRole && !user_data->role.entered(),
GsecInfo info(user_data->dba.get(), user_data->role.get(),
network_protocol.c_str(), remote_address.c_str(), &user_data->authenticationBlock);
manager->start(&st, &info);
}
@ -881,11 +874,6 @@ static bool get_switches(Firebird::UtilSvc::ArgvType& argv,
user_data->role.set(string);
user_data->role.setEntered(1);
break;
case IN_SW_GSEC_DBA_TRUSTED_USER:
tdsec->utilSvc->checkService();
user_data->trustedUser.set(string);
user_data->trustedUser.setEntered(1);
break;
case IN_SW_GSEC_MAPPING:
{
Firebird::string val(string);
@ -993,10 +981,6 @@ static bool get_switches(Firebird::UtilSvc::ArgvType& argv,
user_data->user.clear();
tdsec->tsec_interactive = false;
break;
case IN_SW_GSEC_DBA_TRUSTED_USER:
case IN_SW_GSEC_DBA_TRUSTED_ROLE:
tdsec->utilSvc->checkService();
// fall through ...
case IN_SW_GSEC_PASSWORD:
case IN_SW_GSEC_UID:
case IN_SW_GSEC_GID:
@ -1088,19 +1072,6 @@ static bool get_switches(Firebird::UtilSvc::ArgvType& argv,
}
user_data->dba.setSpecified(1);
break;
case IN_SW_GSEC_DBA_TRUSTED_USER:
tdsec->utilSvc->checkService();
if (user_data->trustedUser.specified())
{
err_msg_no = GsecMsg79;
break;
}
user_data->trustedUser.setSpecified(1);
break;
case IN_SW_GSEC_DBA_TRUSTED_ROLE:
tdsec->utilSvc->checkService();
user_data->trustedRole = 1;
break;
case IN_SW_GSEC_DBA_PASSWORD:
case IN_SW_GSEC_FETCH_PASSWORD:
if (user_data->dbaPassword.specified())

View File

@ -53,8 +53,8 @@ const int IN_SW_GSEC_DBA_PASSWORD = 18; // Database Admin. Password
const int IN_SW_GSEC_SQL_ROLE_NAME = 19; // SQL Role to assume
const int IN_SW_GSEC_AMBIG = 20; // ambiguous switch
//const int IN_SW_GSEC_USERNAME = 21; // placeholder for the username
const int IN_SW_GSEC_DBA_TRUSTED_USER = 22; // Database Admin. Trusted User name
const int IN_SW_GSEC_DBA_TRUSTED_ROLE = 23; // use trusted role for auth
//const int IN_SW_GSEC_DBA_TRUSTED_USER = 22; // Database Admin. Trusted User name
//const int IN_SW_GSEC_DBA_TRUSTED_ROLE = 23; // use trusted role for auth
#ifdef TRUSTED_AUTH
const int IN_SW_GSEC_TRUSTED_AUTH = 24; // Use trusted authentication
#endif
@ -86,10 +86,10 @@ static const struct Switches::in_sw_tab_t gsec_in_sw_table [] =
{IN_SW_GSEC_DBA_PASSWORD, 0, "PASSWORD", 0, 0, 0, false, 0, 2, NULL}, // Database Admin. Password
{IN_SW_GSEC_FETCH_PASSWORD, 0, "FETCH_PASSWORD", 0, 0, 0, false, 0, 2, NULL}, // Fetch Database Admin. Password
{IN_SW_GSEC_SQL_ROLE_NAME, isc_spb_sql_role_name, "ROLE", 0, 0, 0, false, 0, 2, NULL}, // SQL Role to assume
{IN_SW_GSEC_DBA_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0,
/* {IN_SW_GSEC_DBA_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0,
TRUSTED_USER_SWITCH_LEN, NULL}, // Database Admin. Trusted User name
{IN_SW_GSEC_DBA_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, false, 0,
TRUSTED_ROLE_SWITCH_LEN, NULL}, // Use trusted role for auth
TRUSTED_ROLE_SWITCH_LEN, NULL}, // Use trusted role for auth */
#ifdef TRUSTED_AUTH
{IN_SW_GSEC_TRUSTED_AUTH, 0, "TRUSTED", 0, 0, 0, false, 0, 1, NULL}, // Database Admin. Trusted User name
#endif

View File

@ -362,9 +362,9 @@ int gstat(Firebird::UtilSvc* uSvc)
MOVE_CLEAR(user_buff, sizeof(user_buff));
MOVE_CLEAR(pass_buff, sizeof(pass_buff));
TEXT tr_buff[128], *tr_user = tr_buff;
MOVE_CLEAR(tr_buff, sizeof(tr_buff));
bool trusted_role = false;
// TEXT tr_buff[128], *tr_user = tr_buff;
// MOVE_CLEAR(tr_buff, sizeof(tr_buff));
// bool trusted_role = false;
#ifdef TRUSTED_AUTH
bool trusted_auth = false;
@ -457,7 +457,7 @@ int gstat(Firebird::UtilSvc* uSvc)
}
}
break;
case IN_SW_DBA_TRUSTED_USER:
/* case IN_SW_DBA_TRUSTED_USER:
uSvc->checkService();
if (argv < end)
fb_utils::copy_terminate(tr_user, *argv++, sizeof(tr_buff));
@ -466,6 +466,7 @@ int gstat(Firebird::UtilSvc* uSvc)
uSvc->checkService();
trusted_role = true;
break;
*/
#ifdef TRUSTED_AUTH
case IN_SW_DBA_TRUSTEDAUTH:
trusted_auth = true;
@ -751,14 +752,14 @@ int gstat(Firebird::UtilSvc* uSvc)
password, strlen(password));
}
if (*tr_user)
/* if (*tr_user)
{
uSvc->checkService();
dpb.insertString(isc_dpb_trusted_auth, tr_user, strlen(tr_user));
if (trusted_role)
dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE));
}
*/
#ifdef TRUSTED_AUTH
if (trusted_auth)
dpb.insertTag(isc_dpb_trusted_auth);

View File

@ -69,8 +69,8 @@ const static struct Switches::in_sw_tab_t dba_in_sw_table[] =
{IN_SW_DBA_RELATION, isc_spb_sts_table, "TABLE", 0,0,0, false, 35, 1, NULL}, // msg 35: -t tablename
// special switch to avoid including creation date, only for tests (no message)
{IN_SW_DBA_NOCREATION, isc_spb_sts_nocreation, "NOCREATION", 0,0,0, false, 0, 1, NULL}, // msg (ignored) -n suppress creation date
{IN_SW_DBA_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0,0,0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL}, // msg 0 - ignored
{IN_SW_DBA_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0,0,0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL}, // msg 0 - ignored
// {IN_SW_DBA_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0,0,0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL}, // msg 0 - ignored
// {IN_SW_DBA_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0,0,0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL}, // msg 0 - ignored
#ifdef TRUSTED_AUTH
{IN_SW_DBA_TRUSTEDAUTH, 0, "TRUSTED", 0,0,0, false, 36, 2, NULL}, // msg 36: -tr use trusted authentication
#endif

View File

@ -265,11 +265,11 @@ class NBackup
{
public:
NBackup(UtilSvc* _uSvc, const PathName& _database, const string& _username,
const string& _password, bool _run_db_triggers, const string& _trustedUser,
bool _trustedRole, bool _direct_io)
const string& _password, bool _run_db_triggers/*, const string& _trustedUser,
bool _trustedRole*/, bool _direct_io)
: uSvc(_uSvc), newdb(0), trans(0), database(_database),
username(_username), password(_password), trustedUser(_trustedUser),
run_db_triggers(_run_db_triggers), trustedRole(_trustedRole), direct_io(_direct_io),
username(_username), password(_password), /*trustedUser(_trustedUser),*/
run_db_triggers(_run_db_triggers), /*trustedRole(_trustedRole), */direct_io(_direct_io),
dbase(0), backup(0), db_size_pages(0), m_silent(false), m_printed(false)
{
// Recognition of local prefix allows to work with
@ -318,8 +318,8 @@ private:
isc_tr_handle trans; // transaction handle
PathName database;
string username, password, trustedUser;
bool run_db_triggers, trustedRole, direct_io;
string username, password/*, trustedUser*/;
bool run_db_triggers, /*trustedRole, */direct_io;
PathName dbname; // Database file name
PathName bakname;
@ -638,7 +638,7 @@ void NBackup::attach_database()
if (password.hasData())
dpb.insertString(isc_dpb_password, password);
/*
if (trustedUser.hasData())
{
uSvc->checkService();
@ -649,7 +649,7 @@ void NBackup::attach_database()
{
uSvc->checkService();
dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE));
}
}*/
}
if (!run_db_triggers)
@ -1425,8 +1425,8 @@ void nbackup(UtilSvc* uSvc)
NBackup::BackupFiles backup_files;
int level;
bool print_size = false, version = false;
string trustedUser;
bool trustedRole = false;
// string trustedUser;
// bool trustedRole = false;
string onOff;
const Switches switches(nbackup_action_in_sw_table, FB_NELEM(nbackup_action_in_sw_table),
@ -1449,7 +1449,7 @@ void nbackup(UtilSvc* uSvc)
switch (rc->in_sw)
{
case IN_SW_NBK_TRUSTED_USER:
/* case IN_SW_NBK_TRUSTED_USER:
uSvc->checkService();
if (++itr >= argc)
missingParameterForSwitch(uSvc, argv[itr - 1]);
@ -1461,7 +1461,7 @@ void nbackup(UtilSvc* uSvc)
uSvc->checkService();
trustedRole = true;
break;
*/
case IN_SW_NBK_USER_NAME:
if (++itr >= argc)
missingParameterForSwitch(uSvc, argv[itr - 1]);
@ -1624,7 +1624,7 @@ void nbackup(UtilSvc* uSvc)
usage(uSvc, isc_nbackup_size_with_lock);
}
NBackup nbk(uSvc, database, username, password, run_db_triggers, trustedUser, trustedRole, direct_io);
NBackup nbk(uSvc, database, username, password, run_db_triggers, /*trustedUser, trustedRole, */direct_io);
try
{
switch (op)

View File

@ -75,8 +75,8 @@ static const struct Switches::in_sw_tab_t nbackup_action_in_sw_table [] =
{IN_SW_NBK_PASSWORD, 0, "PASSWORD", 0, 0, 0, false, 14, 1, NULL, nboGeneral},
{IN_SW_NBK_FETCH, 0, "FETCH_PASSWORD", 0, 0, 0, false, 15, 2, NULL, nboGeneral},
{IN_SW_NBK_VERSION, 0, "Z", 0, 0, 0, false, 18, 1, NULL, nboGeneral},
{IN_SW_NBK_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL, nboGeneral},
{IN_SW_NBK_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL, nboGeneral},
// {IN_SW_NBK_TRUSTED_USER, 0, TRUSTED_USER_SWITCH, 0, 0, 0, false, 0, TRUSTED_USER_SWITCH_LEN, NULL, nboGeneral},
// {IN_SW_NBK_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, false, 0, TRUSTED_ROLE_SWITCH_LEN, NULL, nboGeneral},
{IN_SW_NBK_HELP, 0, "?", 0, 0, 0, false, 0, 1, NULL, 0},
{IN_SW_NBK_0, 0, NULL, 0, 0, 0, false, 0, 0, NULL, 0} // End of List
};

View File

@ -250,10 +250,17 @@ int FB_CARG MasterImplementation::same(IVersioned* first, IVersioned* second)
IMetadataBuilder* MasterImplementation::getMetadataBuilder(IStatus* status, unsigned fieldCount)
{
MsgMetadata* msgMetadata = new MsgMetadata;
msgMetadata->items.grow(fieldCount);
return msgMetadata->getBuilder(status);
try
{
IMetadataBuilder* bld = new MetadataBuilder(fieldCount);
bld->addRef();
return bld;
}
catch(const Exception& ex)
{
ex.stuffException(status);
return NULL;
}
}
IDebug* FB_CARG MasterImplementation::getDebug()

View File

@ -305,6 +305,7 @@ static const TOK tokens[] =
{PI, "PI", 2, false},
{PLACING, "PLACING", 2, false},
{PLAN, "PLAN", 1, false},
{PLUGIN, "PLUGIN", 2, true},
{POSITION, "POSITION", 1, false},
{POST_EVENT, "POST_EVENT", 1, false},
{POWER, "POWER", 2, false},
@ -359,6 +360,7 @@ static const TOK tokens[] =
{SELECT, "SELECT", 1, false},
{SENSITIVE, "SENSITIVE", 2, false},
{SEQUENCE, "SEQUENCE", 2, true},
{SERVERWIDE, "SERVERWIDE", 2, true},
{SET, "SET", 1, false},
{SHADOW, "SHADOW", 1, false},
{KW_SHARED, "SHARED", 1, false},