File: postgres_mac.sql

package info (click to toggle)
postgresql 7.2.1-2woody8
  • links: PTS
  • area: main
  • in suites: woody
  • size: 42,424 kB
  • ctags: 30,027
  • sloc: ansic: 290,568; java: 18,529; sh: 12,197; sql: 11,401; yacc: 11,189; tcl: 8,063; perl: 4,067; makefile: 3,332; xml: 2,874; lex: 2,799; python: 1,237; cpp: 845; pascal: 81; asm: 70; awk: 20; sed: 8
file content (125 lines) | stat: -rw-r--r-- 4,346 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
--Copyright 2000 mag@lme.linux.hu under the GPL
--This implements mandatory access control in a postgresql database;
--You should insert language PL/pgTCL in the database first:
--
--CREATE FUNCTION "pltcl_call_handler" ( ) RETURNS opaque AS '/usr/lib/postgresql/lib/pltcl.so' LANGUAGE 'C';
--CREATE TRUSTED PROCEDURAL LANGUAGE 'pltcl' HANDLER "pltcl_call_handler" LANCOMPILER 'PL/pgTCL';

--teszt=> select usename,usesysid from pg_user;
--usename |usesysid
----------+--------
--postgres|      31
--mag     |      32
--teszt   |      33
--thedba  |      34
--teszt3  |      35
--(5 rows)

--Everything which should be in pg_user
drop table user_labels;
create table user_labels (usesysid int4, hsl int, nhc name[],mac_read bool);
create unique index user_labels_ui on user_labels(usesysid);
insert into user_labels values (32,2,'{ilyen,olyan}','f');
insert into user_labels values (33,2,'{ilyen}','f');
insert into user_labels values (34,2,'{ilyen}','t');
insert into user_labels values (35,2,'{olyan}','f');

--The example table: the labels and one data field
drop table data;
create table data (hsl int, nhc name[], data text);
insert into data values (3,'{ilyen}', 'ez ilyen s harom');
insert into data values (3,'{olyan,amolyan}', 'ez olyan, amolyan s harom');
insert into data values (2,'{olyan}', 'ez olyan s ketto');
insert into data values (2,'{ilyen}', 'ez ilyen s ketto');
insert into data values (2,'{olyan}', 'ez olyan s ketto');
insert into data values (3,'{olyan}', 'ez olyan s harom');
insert into data values (3,'{olyan,ilyen}', 'ez ilyen,olyan s harom');
insert into data values (2,'{olyan,ilyen}', 'ez ilyen,olyan s ketto');

create table data (hsl int, nhc name[], data text);

--drop function my_in_array(_name,name);
--create function my_in_array(_name,name) returns text as '
--	set o [split $1 "}{," ]
--	set s "\\"$2\\""
--	set had [lsearch $o $s]
--	return "$s $o $had"
--' language 'pltcl';

-- Checking non-hierarchical categories: objects nhc and subjects nhc
drop function my_nhc_check(_name,_name);
create function my_nhc_check(_name,_name) returns bool as '
	set o [split $2 "}{," ]
	set s [split $1 "}{," ]
	set ss [lrange $s 1 [expr [llength $s] - 2]]
	set had 1
	foreach h $ss {
		set had "[expr ([lsearch $o $h] != -1) && $had]"
	}
	return "$had"
' language 'pltcl';
--select a.nhc as subject, b.nhc as object,my_nhc_check(a.nhc,b.nhc),b.data from user_labels a, data b;

--we have an operator for this, as well
drop operator ~ (_name,_name);
create operator ~ (LEFTARG=_name,RIGHTARG=_name,PROCEDURE=my_nhc_check);
vacuum;

--mac_check for selects. Does not look at mac-read capability yet.
create function mac_check(int,_name) returns bool as '
	select 1::bool 
	where 
		$1 <=(select hsl from user_labels u 
			where pg_get_userbyid(u.usesysid)=getpgusername()) 
		and $2 ~ (select nhc from user_labels s 
			where pg_get_userbyid(s.usesysid)=getpgusername())
' language 'SQL';

	
--In postgresql we have very little space to play with rewrite rules.
--But it is enough for our goals.
drop rule "_RETdata"; 
create rule "_RETdata" as on select to data do instead select OLD.hsl,OLD.nhc,OLD.data where mac_check(OLD.hsl,OLD.nhc);

--This is the trigger procedure for insert,update,and delete
drop function mac_trigger();
create function mac_trigger() returns opaque as '
DECLARE
	myhsl int;
	mynhc _name;
BEGIN
select hsl into myhsl from user_labels u where pg_get_userbyid(u.usesysid)=getpgusername();
select nhc into mynhc from user_labels u where pg_get_userbyid(u.usesysid)=getpgusername();
if TG_OP = ''INSERT'' then
	if NEW.nhc ~ mynhc and NEW.hsl >= myhsl then
		return NEW;
	end if;
	return NULL; 
end if;
if TG_OP = ''UPDATE'' then
	if OLD.nhc ~ mynhc and OLD.hsl <= myhsl and 
	NEW.nhc ~ mynhc and NEW.hsl >= myhsl then
		return NEW;
	end if;
	return NULL; 
end if;
if TG_OP = ''DELETE'' then
	if OLD.nhc ~ mynhc and OLD.hsl <= myhsl then
		return OLD;
	end if;
	return NULL; 
end if;
return NULL; 
END;
' language 'plpgsql';

--And here we implement it on our example data
drop trigger data_mac on data;
CREATE TRIGGER data_mac 
	BEFORE INSERT OR UPDATE OR DELETE ON data FOR EACH ROW
	EXECUTE PROCEDURE mac_trigger();

--Here should come the functional check.
insert into data values (1,'{ilyen}','Az j ilyen');
delete from data where hsl=4 and nhc='{ilyen}' and data='Az \xfaj ilyen';