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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
|
/* -------------------------------------------------------------------------
*
* contrib/sepgsql/relation.c
*
* Routines corresponding to relation/attribute objects
*
* Copyright (c) 2010-2011, PostgreSQL Global Development Group
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/sysattr.h"
#include "catalog/indexing.h"
#include "catalog/dependency.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_class.h"
#include "catalog/pg_namespace.h"
#include "commands/seclabel.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/tqual.h"
#include "sepgsql.h"
/*
* sepgsql_attribute_post_create
*
* This routine assigns a default security label on a newly defined
* column, using ALTER TABLE ... ADD COLUMN.
* Note that this routine is not invoked in the case of CREATE TABLE,
* although it also defines columns in addition to table.
*/
void
sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
{
char *scontext = sepgsql_get_client_label();
char *tcontext;
char *ncontext;
ObjectAddress object;
/*
* Only attributes within regular relation have individual security
* labels.
*/
if (get_rel_relkind(relOid) != RELKIND_RELATION)
return;
/*
* Compute a default security label when we create a new procedure object
* under the specified namespace.
*/
scontext = sepgsql_get_client_label();
tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
ncontext = sepgsql_compute_create(scontext, tcontext,
SEPG_CLASS_DB_COLUMN);
/*
* Assign the default security label on a new procedure
*/
object.classId = RelationRelationId;
object.objectId = relOid;
object.objectSubId = attnum;
SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
pfree(tcontext);
pfree(ncontext);
}
/*
* sepgsql_attribute_relabel
*
* It checks privileges to relabel the supplied column
* by the `seclabel'.
*/
void
sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
const char *seclabel)
{
char *scontext = sepgsql_get_client_label();
char *tcontext;
char *audit_name;
ObjectAddress object;
if (get_rel_relkind(relOid) != RELKIND_RELATION)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot set security label on non-regular columns")));
object.classId = RelationRelationId;
object.objectId = relOid;
object.objectSubId = attnum;
audit_name = getObjectDescription(&object);
/*
* check db_column:{setattr relabelfrom} permission
*/
tcontext = sepgsql_get_label(RelationRelationId, relOid, attnum);
sepgsql_check_perms(scontext,
tcontext,
SEPG_CLASS_DB_COLUMN,
SEPG_DB_COLUMN__SETATTR |
SEPG_DB_COLUMN__RELABELFROM,
audit_name,
true);
/*
* check db_column:{relabelto} permission
*/
sepgsql_check_perms(scontext,
seclabel,
SEPG_CLASS_DB_COLUMN,
SEPG_DB_PROCEDURE__RELABELTO,
audit_name,
true);
pfree(tcontext);
pfree(audit_name);
}
/*
* sepgsql_relation_post_create
*
* The post creation hook of relation/attribute
*/
void
sepgsql_relation_post_create(Oid relOid)
{
Relation rel;
ScanKeyData skey;
SysScanDesc sscan;
HeapTuple tuple;
Form_pg_class classForm;
ObjectAddress object;
uint16 tclass;
char *scontext; /* subject */
char *tcontext; /* schema */
char *rcontext; /* relation */
char *ccontext; /* column */
/*
* Fetch catalog record of the new relation. Because pg_class entry is not
* visible right now, we need to scan the catalog using SnapshotSelf.
*/
rel = heap_open(RelationRelationId, AccessShareLock);
ScanKeyInit(&skey,
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relOid));
sscan = systable_beginscan(rel, ClassOidIndexId, true,
SnapshotSelf, 1, &skey);
tuple = systable_getnext(sscan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "catalog lookup failed for relation %u", relOid);
classForm = (Form_pg_class) GETSTRUCT(tuple);
if (classForm->relkind == RELKIND_RELATION)
tclass = SEPG_CLASS_DB_TABLE;
else if (classForm->relkind == RELKIND_SEQUENCE)
tclass = SEPG_CLASS_DB_SEQUENCE;
else if (classForm->relkind == RELKIND_VIEW)
tclass = SEPG_CLASS_DB_VIEW;
else
goto out; /* No need to assign individual labels */
/*
* Compute a default security label when we create a new relation object
* under the specified namespace.
*/
scontext = sepgsql_get_client_label();
tcontext = sepgsql_get_label(NamespaceRelationId,
classForm->relnamespace, 0);
rcontext = sepgsql_compute_create(scontext, tcontext, tclass);
/*
* Assign the default security label on the new relation
*/
object.classId = RelationRelationId;
object.objectId = relOid;
object.objectSubId = 0;
SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext);
/*
* We also assigns a default security label on columns of the new regular
* tables.
*/
if (classForm->relkind == RELKIND_RELATION)
{
AttrNumber index;
ccontext = sepgsql_compute_create(scontext, rcontext,
SEPG_CLASS_DB_COLUMN);
for (index = FirstLowInvalidHeapAttributeNumber + 1;
index <= classForm->relnatts;
index++)
{
if (index == InvalidAttrNumber)
continue;
if (index == ObjectIdAttributeNumber && !classForm->relhasoids)
continue;
object.classId = RelationRelationId;
object.objectId = relOid;
object.objectSubId = index;
SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
}
pfree(ccontext);
}
pfree(rcontext);
out:
systable_endscan(sscan);
heap_close(rel, AccessShareLock);
}
/*
* sepgsql_relation_relabel
*
* It checks privileges to relabel the supplied relation by the `seclabel'.
*/
void
sepgsql_relation_relabel(Oid relOid, const char *seclabel)
{
char *scontext = sepgsql_get_client_label();
char *tcontext;
char *audit_name;
char relkind;
uint16_t tclass = 0;
relkind = get_rel_relkind(relOid);
if (relkind == RELKIND_RELATION)
tclass = SEPG_CLASS_DB_TABLE;
else if (relkind == RELKIND_SEQUENCE)
tclass = SEPG_CLASS_DB_SEQUENCE;
else if (relkind == RELKIND_VIEW)
tclass = SEPG_CLASS_DB_VIEW;
else
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot set security labels on relations except "
"for tables, sequences or views")));
audit_name = getObjectDescriptionOids(RelationRelationId, relOid);
/*
* check db_xxx:{setattr relabelfrom} permission
*/
tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
sepgsql_check_perms(scontext,
tcontext,
tclass,
SEPG_DB_TABLE__SETATTR |
SEPG_DB_TABLE__RELABELFROM,
audit_name,
true);
/*
* check db_xxx:{relabelto} permission
*/
sepgsql_check_perms(scontext,
seclabel,
tclass,
SEPG_DB_TABLE__RELABELTO,
audit_name,
true);
pfree(tcontext);
pfree(audit_name);
}
|