1 /* -------------------------------------------------------------------------
3 * contrib/sepgsql/label.c
5 * Routines corresponding to relation/attribute objects
7 * Copyright (c) 2010-2011, PostgreSQL Global Development Group
9 * -------------------------------------------------------------------------
13 #include "access/genam.h"
14 #include "access/heapam.h"
15 #include "access/sysattr.h"
16 #include "catalog/indexing.h"
17 #include "catalog/dependency.h"
18 #include "catalog/pg_attribute.h"
19 #include "catalog/pg_class.h"
20 #include "catalog/pg_namespace.h"
21 #include "commands/seclabel.h"
22 #include "utils/fmgroids.h"
23 #include "utils/lsyscache.h"
24 #include "utils/tqual.h"
29 * sepgsql_attribute_post_create
31 * This routine assigns a default security label on a newly defined
32 * column, using ALTER TABLE ... ADD COLUMN.
33 * Note that this routine is not invoked in the case of CREATE TABLE,
34 * although it also defines columns in addition to table.
37 sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
46 char audit_name[2*NAMEDATALEN + 20];
48 Form_pg_attribute attForm;
51 * Only attributes within regular relation have individual security
54 if (get_rel_relkind(relOid) != RELKIND_RELATION)
58 * Compute a default security label of the new column underlying the
59 * specified relation, and check permission to create it.
61 rel = heap_open(AttributeRelationId, AccessShareLock);
64 Anum_pg_attribute_attrelid,
65 BTEqualStrategyNumber, F_OIDEQ,
66 ObjectIdGetDatum(relOid));
68 Anum_pg_attribute_attnum,
69 BTEqualStrategyNumber, F_INT2EQ,
70 Int16GetDatum(attnum));
72 sscan = systable_beginscan(rel, AttributeRelidNumIndexId, true,
73 SnapshotSelf, 2, &skey[0]);
75 tuple = systable_getnext(sscan);
76 if (!HeapTupleIsValid(tuple))
77 elog(ERROR, "catalog lookup failed for column %d of relation %u",
80 attForm = (Form_pg_attribute) GETSTRUCT(tuple);
82 scontext = sepgsql_get_client_label();
83 tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
84 ncontext = sepgsql_compute_create(scontext, tcontext,
85 SEPG_CLASS_DB_COLUMN);
87 * check db_column:{create} permission
89 snprintf(audit_name, sizeof(audit_name), "table %s column %s",
90 get_rel_name(relOid), NameStr(attForm->attname));
91 sepgsql_avc_check_perms_label(ncontext,
93 SEPG_DB_COLUMN__CREATE,
98 * Assign the default security label on a new procedure
100 object.classId = RelationRelationId;
101 object.objectId = relOid;
102 object.objectSubId = attnum;
103 SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
105 systable_endscan(sscan);
106 heap_close(rel, AccessShareLock);
113 * sepgsql_attribute_relabel
115 * It checks privileges to relabel the supplied column
119 sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
120 const char *seclabel)
122 ObjectAddress object;
125 if (get_rel_relkind(relOid) != RELKIND_RELATION)
127 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
128 errmsg("cannot set security label on non-regular columns")));
130 object.classId = RelationRelationId;
131 object.objectId = relOid;
132 object.objectSubId = attnum;
133 audit_name = getObjectDescription(&object);
136 * check db_column:{setattr relabelfrom} permission
138 sepgsql_avc_check_perms(&object,
139 SEPG_CLASS_DB_COLUMN,
140 SEPG_DB_COLUMN__SETATTR |
141 SEPG_DB_COLUMN__RELABELFROM,
145 * check db_column:{relabelto} permission
147 sepgsql_avc_check_perms_label(seclabel,
148 SEPG_CLASS_DB_COLUMN,
149 SEPG_DB_PROCEDURE__RELABELTO,
156 * sepgsql_relation_post_create
158 * The post creation hook of relation/attribute
161 sepgsql_relation_post_create(Oid relOid)
167 Form_pg_class classForm;
168 ObjectAddress object;
170 const char *tclass_text;
171 char *scontext; /* subject */
172 char *tcontext; /* schema */
173 char *rcontext; /* relation */
174 char *ccontext; /* column */
175 char audit_name[2*NAMEDATALEN + 20];
178 * Fetch catalog record of the new relation. Because pg_class entry is not
179 * visible right now, we need to scan the catalog using SnapshotSelf.
181 rel = heap_open(RelationRelationId, AccessShareLock);
184 ObjectIdAttributeNumber,
185 BTEqualStrategyNumber, F_OIDEQ,
186 ObjectIdGetDatum(relOid));
188 sscan = systable_beginscan(rel, ClassOidIndexId, true,
189 SnapshotSelf, 1, &skey);
191 tuple = systable_getnext(sscan);
192 if (!HeapTupleIsValid(tuple))
193 elog(ERROR, "catalog lookup failed for relation %u", relOid);
195 classForm = (Form_pg_class) GETSTRUCT(tuple);
197 switch (classForm->relkind)
199 case RELKIND_RELATION:
200 tclass = SEPG_CLASS_DB_TABLE;
201 tclass_text = "table";
203 case RELKIND_SEQUENCE:
204 tclass = SEPG_CLASS_DB_SEQUENCE;
205 tclass_text = "sequence";
208 tclass = SEPG_CLASS_DB_VIEW;
209 tclass_text = "view";
216 * check db_schema:{add_name} permission of the namespace
218 object.classId = NamespaceRelationId;
219 object.objectId = classForm->relnamespace;
220 object.objectSubId = 0;
221 sepgsql_avc_check_perms(&object,
222 SEPG_CLASS_DB_SCHEMA,
223 SEPG_DB_SCHEMA__ADD_NAME,
224 getObjectDescription(&object),
227 * Compute a default security label when we create a new relation object
228 * under the specified namespace.
230 scontext = sepgsql_get_client_label();
231 tcontext = sepgsql_get_label(NamespaceRelationId,
232 classForm->relnamespace, 0);
233 rcontext = sepgsql_compute_create(scontext, tcontext, tclass);
236 * check db_xxx:{create} permission
238 snprintf(audit_name, sizeof(audit_name), "%s %s",
239 tclass_text, NameStr(classForm->relname));
240 sepgsql_avc_check_perms_label(rcontext,
242 SEPG_DB_DATABASE__CREATE,
246 * Assign the default security label on the new relation
248 object.classId = RelationRelationId;
249 object.objectId = relOid;
250 object.objectSubId = 0;
251 SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext);
254 * We also assigns a default security label on columns of the new regular
257 if (classForm->relkind == RELKIND_RELATION)
263 Form_pg_attribute attForm;
265 arel = heap_open(AttributeRelationId, AccessShareLock);
268 Anum_pg_attribute_attrelid,
269 BTEqualStrategyNumber, F_OIDEQ,
270 ObjectIdGetDatum(relOid));
272 ascan = systable_beginscan(arel, AttributeRelidNumIndexId, true,
273 SnapshotSelf, 1, &akey);
275 while (HeapTupleIsValid(atup = systable_getnext(ascan)))
277 attForm = (Form_pg_attribute) GETSTRUCT(atup);
279 snprintf(audit_name, sizeof(audit_name), "%s %s column %s",
281 NameStr(classForm->relname),
282 NameStr(attForm->attname));
284 ccontext = sepgsql_compute_create(scontext,
286 SEPG_CLASS_DB_COLUMN);
288 * check db_column:{create} permission
290 sepgsql_avc_check_perms_label(ccontext,
291 SEPG_CLASS_DB_COLUMN,
292 SEPG_DB_COLUMN__CREATE,
296 object.classId = RelationRelationId;
297 object.objectId = relOid;
298 object.objectSubId = attForm->attnum;
299 SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
303 systable_endscan(ascan);
304 heap_close(arel, AccessShareLock);
308 systable_endscan(sscan);
309 heap_close(rel, AccessShareLock);
313 * sepgsql_relation_relabel
315 * It checks privileges to relabel the supplied relation by the `seclabel'.
318 sepgsql_relation_relabel(Oid relOid, const char *seclabel)
320 ObjectAddress object;
325 relkind = get_rel_relkind(relOid);
326 if (relkind == RELKIND_RELATION)
327 tclass = SEPG_CLASS_DB_TABLE;
328 else if (relkind == RELKIND_SEQUENCE)
329 tclass = SEPG_CLASS_DB_SEQUENCE;
330 else if (relkind == RELKIND_VIEW)
331 tclass = SEPG_CLASS_DB_VIEW;
334 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
335 errmsg("cannot set security labels on relations except "
336 "for tables, sequences or views")));
338 object.classId = RelationRelationId;
339 object.objectId = relOid;
340 object.objectSubId = 0;
341 audit_name = getObjectDescription(&object);
344 * check db_xxx:{setattr relabelfrom} permission
346 sepgsql_avc_check_perms(&object,
348 SEPG_DB_TABLE__SETATTR |
349 SEPG_DB_TABLE__RELABELFROM,
353 * check db_xxx:{relabelto} permission
355 sepgsql_avc_check_perms_label(seclabel,
357 SEPG_DB_TABLE__RELABELTO,