Subject RE: [Firebird-Architect] Create of RDB$USERS
Author Claudio Valderrama C.
> -----Original Message-----
> From: Firebird-Architect@yahoogroups.com
> [mailto:Firebird-Architect@yahoogroups.com]On Behalf Of Jim Starkey
> Sent: MiƩrcoles, 19 de Octubre de 2005 11:28
> >
> Why is it creating a security class name from the user name?

I think the explanation got lost in Alex' problems with a foreign language.

A security class name has 31 bytes.
A table name has 31 bytes.
For each table, Borland creates a sec class name that's the concatenation of
SQL$ plus the table name, truncated if necessary. Something like:

sec_name = 'SQL$' || substring(table_name from 1 for 27);

User1 creates table1, the name is 27 Aes followed by 1:
A...A1

User1 doesn't grant User2 any rights on its table.

User2 creates table2, the name is 27 Aes followed by 2:
A...A2

The two tables have the same bytes from position 1 to 27 and only differ in
the 28th position.

When User1 created table1, the security class that's stored is
SQL$A...A (no room for the "1" or whatever thing beyond the 27th byte).

When User2 created table2, the security class that's stored is
SQL$A...A (no room for the "2" or whatever thing beyond the 27th byte).

This means when User2 created table2, the GDML rights for table1 were
overwritten. Now User2 has full control over both tables although User1 is
still the owner of table1.

Thus rdb$security_classes' rdb$security_class should be char(35) instead or
the security flaw will continue living forever.


Now, let's assume we have two usernames. The first 31 positions are filled
with Ues:
U...U1
U...U2
so they have length=31. This is possible because rdb$users will allow up to
128 positions. When security classes are written, user privileges are
written, too, unless you're using an old tool that predates IB4 and that's
unaware of rdb$user_privileges. But there are some system triggers, too.
Since the limit for a user or grantor in user privileges is 31 bytes but in
rdb$user those two example user names are 32 bytes in size, you will either
get a truncation or you will have a security flaw: the two users will map to
user
U...U
in rdb$user_privileges. I didn't check if you get automatic truncation or
error message, but automatic truncation means security breach again.

Therefore rdb$user_privileges' rdb$user and rdb$grantor fields should be
enlarged to 128 positions.

It would be nice if we find a way to rename rdb$user_privileges'
rdb$relation_name to rdb$object_name without breaking the world (although I
don't have much hope) because the current field name is totally misleading:
I'm sure Borland realized quickly while in v4 development that this field
contains more than relation names, but was lazy to change it.


Before you someone shouts that I speak about bytes instead of characters:
system tables lie, when you see this definition,

SQL> show table rdb$security_classes;
RDB$SECURITY_CLASS (RDB$SECURITY_CLASS) CHAR(31) CHARACTER SET
UNICODE_FSS Nullable
RDB$ACL (RDB$ACL) BLOB segment 80, subtype ACL
Nullable
RDB$DESCRIPTION (RDB$DESCRIPTION) BLOB segment 80, subtype
TEXT CHARACTER SET UNICOD
E_FSS Nullable

You think you can store 31 unicode characters. Not so. The hardcoded
internal maximum is still 31 bytes. See this example:

SQL> insert into rdb$security_classes
values('123456789012345678901234567890123', NULL, NULL);
Statement failed, SQLCODE = -802
arithmetic exception, numeric overflow, or string truncation
SQL> insert into rdb$security_classes
values('12345678901234567890123456789012', NULL, NULL);
Statement failed, SQLCODE = -802
arithmetic exception, numeric overflow, or string truncation
SQL> insert into rdb$security_classes
values('1234567890123456789012345678901', NULL, NULL);
SQL> rollback;

Not convinced? Let's try with a user table defined with unicode:

SQL> create table uni(a char(3) character set unicode_fss);
SQL> insert into uni values('123456789');
SQL> commit;

In the first case, I can't insert more than 31 ASCII characters whereas in
the second, since the declaration and the internal layout are consistent, I
can insert up to 9 ASCII characters.

C.