Skip to content

Commit

Permalink
SQL SECURITY Feature (#42)
Browse files Browse the repository at this point in the history
* Added SQL SECURITY clause to various DDL statements
  • Loading branch information
romansimakov authored and AlexPeshkoff committed Sep 28, 2016
1 parent d3a0723 commit 9aab6ed
Show file tree
Hide file tree
Showing 44 changed files with 820 additions and 153 deletions.
162 changes: 162 additions & 0 deletions doc/sql.extensions/README.sql_security.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
SQL SECURITY.

Implements capability to run executable objects regarding SQL SECURITY clause.
SQL Standard (2003, 2011) Feature.

Author:
Red Soft, roman.simakov(at)red-soft.ru

Syntax is:

CREATE TABLE <TABLENAME> (...) [SQL SECURITY {DEFINER | INVOKER}]
ALTER TABLE <TABLENAME> ... [{ALTER SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY}]
CREATE [OR ALTER] FUNCTION <FUNCTIONNAME> ... [SQL SECURITY {DEFINER | INVOKER}] AS ...
CREATE [OR ALTER] PROCEDURE <PROCEDURENAME> ... [SQL SECURITY {DEFINER | INVOKER}] AS ...
CREATE [OR ALTER] TRIGGER <TRIGGERNAME> ... [SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY] [AS ...]
CREATE [OR ALTER] PACKAGE <PACKAGENAME> [SQL SECURITY {DEFINER | INVOKER}] AS ...

Description:

Makes it possible to execute some objects with permissions of either definer or invoker.
By default INVOKER is used to keep backword compatibility.

If INVOKER is specified a current set of privileges of the current user will be used.
If DEFINER - a set of privileges of object owner will be used to check an access to database objects used by this object.

Trigger inherits SQL SECURITY option from TABLE but can overwrite it by explicit specifying. If SQL SECURITY option
will be changed for table, existing triggers without explicitly specified option will not use new value immediately
it will take effect next time trigger will be loaded into metadata cache.

For procedures and functions defined in package explicit SQL SECURITY clause is prohibit.


Example 1. It's enought to grant only SELECT privilege to user US for table T.
In case of INVOKER it will require also EXECUTE for function F.

set term ^;
create function f() returns int
as
begin
return 3;
end^
set term ;^
create table t (i integer, c computed by (i + f())) sql security definer;
insert into t values (2);
grant select on table t to user us;

commit;

connect 'localhost:/tmp/7.fdb' user us password 'pas';
select * from t;


Example 2. It's enough to grant EXECUTE privilege to user US for function F.
In case of INVOKER it will require also INSERT for table T.

set term ^;
create function f (i integer) returns int sql security definer
as
begin
insert into t values (:i);
return i + 1;
end^
set term ;^
grant execute on function f to user us;

commit;

connect 'localhost:/tmp/59.fdb' user us password 'pas';
select f(3) from rdb$database;


Example 3. It's enought to grant only EXECUTE privilege to user US for procedure P.
In case of INVOKER it will require also INSERT for table T to either user US or procedure P.

set term ^;
create procedure p (i integer) sql security definer
as
begin
insert into t values (:i);
end^
set term ;^

grant execute on procedure p to user us;
commit;

connect 'localhost:/tmp/17.fdb' user us password 'pas';
execute procedure p(1);


Example 4. It's enought to grant only INSERT privilege to user US for table TR.
In case of INVOKER it will require also INSERT for table T to user US.

create table tr (i integer);
create table t (i integer);
set term ^;
create trigger tr_ins for tr after insert sql security definer
as
begin
insert into t values (NEW.i);
end^
set term ;^
grant insert on table tr to user us;

commit;

connect 'localhost:/tmp/29.fdb' user us password 'pas';
insert into tr values(2);

the same result if specify SQL SECURITY DEFINER for table TR.

create table tr (i integer) sql security definer;
create table t (i integer);
set term ^;
create trigger tr_ins for tr after insert
as
begin
insert into t values (NEW.i);
end^
set term ;^
grant insert on table tr to user us;

commit;

connect 'localhost:/tmp/29.fdb' user us password 'pas';
insert into tr values(2);


Example 5. It's enought to grant only EXECUTE privilege to user US for package PK.
In case of INVOKER it will require also INSERT for table T to user US.

create table t (i integer);
set term ^;
create package pk sql security definer
as
begin
function f(i integer) returns int;
end^

create package body pk
as
begin
function f(i integer) returns int
as
begin
insert into t values (:i);
return i + 1;
end
end^
set term ;^
grant execute on package pk to user us;

commit;

connect 'localhost:/tmp/69.fdb' user us password 'pas';
select pk.f(3) from rdb$database;

Example 6. Altering explicit option SQL SECURITY for triggers.
To remove explicit SQL SECURITY OPTION from trigger you can execute:
alter trigger tr_ins drop sql security;

To set it again to SQL SECURITY INVOKER you can:
alter trigger tr_ins sql security invoker;
2 changes: 1 addition & 1 deletion extern/btyacc/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#define MAXCHAR 255
#define MAXSHORT ((int)0x7FFFFFFF)
#define MINSHORT ((int)0x80000000)
#define MAXTABLE 120000
#define MAXTABLE 200000

#ifdef __MSDOS__
#define BITS_PER_WORD 16
Expand Down
2 changes: 2 additions & 0 deletions lang_helpers/gds_codes.ftn
Original file line number Diff line number Diff line change
Expand Up @@ -1792,6 +1792,8 @@ C --
PARAMETER (GDS__dsql_no_output_sqlda = 336003110)
INTEGER*4 GDS__dsql_wrong_param_num
PARAMETER (GDS__dsql_wrong_param_num = 336003111)
INTEGER*4 GDS__dsql_invalid_drop_ss_clause
PARAMETER (GDS__dsql_invalid_drop_ss_clause = 336003112)
INTEGER*4 GDS__dyn_filter_not_found
PARAMETER (GDS__dyn_filter_not_found = 336068645)
INTEGER*4 GDS__dyn_func_not_found
Expand Down
2 changes: 2 additions & 0 deletions lang_helpers/gds_codes.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,8 @@
gds_dsql_no_output_sqlda = 336003110;
isc_dsql_wrong_param_num = 336003111;
gds_dsql_wrong_param_num = 336003111;
isc_dsql_invalid_drop_ss_clause = 336003112;
gds_dsql_invalid_drop_ss_clause = 336003112;
isc_dyn_filter_not_found = 336068645;
gds_dyn_filter_not_found = 336068645;
isc_dyn_func_not_found = 336068649;
Expand Down
37 changes: 35 additions & 2 deletions src/burp/backup.epp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ void put_data(burp_rel*);
void put_index(burp_rel*);
int put_message(att_type, att_type, const TEXT*, const ULONG);
void put_int32(att_type, SLONG);
void put_int64( att_type attribute, SINT64 value);
void put_int64(att_type attribute, SINT64 value);
void put_boolean(att_type, FB_BOOLEAN value);
void put_relation(burp_rel*);
bool put_source_blob(att_type, att_type, ISC_QUAD&);
int put_text(att_type, const TEXT*, SSHORT);
Expand Down Expand Up @@ -1984,7 +1985,7 @@ void put_int32( att_type attribute, SLONG value)
}


void put_int64( att_type attribute, SINT64 value)
void put_int64(att_type attribute, SINT64 value)
{
/**************************************
*
Expand All @@ -2009,6 +2010,24 @@ void put_int64( att_type attribute, SINT64 value)
}


void put_boolean(att_type attribute, const FB_BOOLEAN value)
{
/**************************************
*
* p u t _ b o o l e a n
*
**************************************
*
* Functional description
* Write a FB_BOOLEAN value as an attribute.
**************************************/
BurpGlobals* tdgbl = BurpGlobals::getSpecific();

put(tdgbl, attribute);
put(tdgbl, value ? 1u : 0u);
}


void put_relation( burp_rel* relation)
{
/**************************************
Expand Down Expand Up @@ -2946,6 +2965,8 @@ void write_functions()
put_int32(att_function_legacy_flag, X.RDB$LEGACY_FLAG);
if (!X.RDB$DETERMINISTIC_FLAG.NULL)
put_int32(att_function_deterministic_flag, X.RDB$DETERMINISTIC_FLAG);
if (!X.RDB$SQL_SECURITY.NULL)
put_boolean(att_function_sql_security, X.RDB$SQL_SECURITY);

put(tdgbl, att_end);

Expand Down Expand Up @@ -3523,6 +3544,9 @@ void write_packages()
if (!X.RDB$DESCRIPTION.NULL)
put_source_blob(att_package_description, att_package_description, X.RDB$DESCRIPTION);

if (!X.RDB$SQL_SECURITY.NULL)
put_boolean(att_package_sql_security, X.RDB$SQL_SECURITY);

put(tdgbl, att_end);
}
END_FOR
Expand Down Expand Up @@ -3602,6 +3626,9 @@ void write_procedures()
if (!X.RDB$PRIVATE_FLAG.NULL)
put_int32(att_procedure_private_flag, X.RDB$PRIVATE_FLAG);

if (!X.RDB$SQL_SECURITY.NULL)
put_boolean(att_procedure_sql_security, X.RDB$SQL_SECURITY);

put(tdgbl, att_end);
COPY(X.RDB$PROCEDURE_NAME, proc);
write_procedure_prms ((X.RDB$PACKAGE_NAME.NULL ? "" : X.RDB$PACKAGE_NAME), proc);
Expand Down Expand Up @@ -3872,6 +3899,9 @@ void write_relations()
if (!X.RDB$RELATION_TYPE.NULL)
put_int32 (att_relation_type, X.RDB$RELATION_TYPE);

if (!X.RDB$SQL_SECURITY.NULL)
put_boolean(att_relation_sql_security, X.RDB$SQL_SECURITY);

put(tdgbl, att_end);
burp_rel* relation = (burp_rel*) BURP_alloc_zero (sizeof(burp_rel));
relation->rel_next = tdgbl->relations;
Expand Down Expand Up @@ -4226,6 +4256,9 @@ void write_triggers()
if (!X.RDB$ENTRYPOINT.NULL)
PUT_TEXT(att_trig_entrypoint, X.RDB$ENTRYPOINT);

if (!X.RDB$SQL_SECURITY.NULL)
put_boolean(att_trig_sql_security, X.RDB$SQL_SECURITY);

put(tdgbl, att_end);

END_FOR;
Expand Down
11 changes: 9 additions & 2 deletions src/burp/burp.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,11 @@ Version 9: FB2.5.
Version 10: FB3.0.
See backup_capabilities in OdsDetection.h.
Version 11: FB 4.0
*/

const int ATT_BACKUP_FORMAT = 10;
const int ATT_BACKUP_FORMAT = 11;

// format version number for ranges for arrays

Expand Down Expand Up @@ -267,6 +269,7 @@ enum att_type {
att_relation_flags,
att_relation_ext_file_name, // name of file for external tables
att_relation_type,
att_relation_sql_security,

// Field attributes (used for both global and local fields)

Expand Down Expand Up @@ -400,6 +403,7 @@ enum att_type {
att_trig_engine_name,
att_trig_entrypoint,
att_trig_type2,
att_trig_sql_security,

// Function attributes

Expand All @@ -423,6 +427,7 @@ enum att_type {
att_function_owner_name,
att_function_legacy_flag,
att_function_deterministic_flag,
att_function_sql_security,

// Function argument attributes

Expand Down Expand Up @@ -518,6 +523,7 @@ enum att_type {
att_procedure_entrypoint,
att_procedure_package_name,
att_procedure_private_flag,
att_procedure_sql_security,

// Stored procedure parameter attributes

Expand Down Expand Up @@ -617,7 +623,8 @@ enum att_type {
att_package_valid_body_flag,
att_package_security_class,
att_package_owner_name,
att_package_description
att_package_description,
att_package_sql_security
};


Expand Down
Loading

0 comments on commit 9aab6ed

Please sign in to comment.