00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "postgres.h"
00012
00013 #include "access/genam.h"
00014 #include "access/heapam.h"
00015 #include "access/htup_details.h"
00016 #include "catalog/catalog.h"
00017 #include "catalog/indexing.h"
00018 #include "catalog/pg_seclabel.h"
00019 #include "catalog/pg_shseclabel.h"
00020 #include "commands/seclabel.h"
00021 #include "miscadmin.h"
00022 #include "utils/builtins.h"
00023 #include "utils/fmgroids.h"
00024 #include "utils/memutils.h"
00025 #include "utils/rel.h"
00026 #include "utils/tqual.h"
00027
00028 typedef struct
00029 {
00030 const char *provider_name;
00031 check_object_relabel_type hook;
00032 } LabelProvider;
00033
00034 static List *label_provider_list = NIL;
00035
00036
00037
00038
00039
00040
00041 Oid
00042 ExecSecLabelStmt(SecLabelStmt *stmt)
00043 {
00044 LabelProvider *provider = NULL;
00045 ObjectAddress address;
00046 Relation relation;
00047 ListCell *lc;
00048
00049
00050
00051
00052
00053 if (stmt->provider == NULL)
00054 {
00055 if (label_provider_list == NIL)
00056 ereport(ERROR,
00057 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00058 errmsg("no security label providers have been loaded")));
00059 if (lnext(list_head(label_provider_list)) != NULL)
00060 ereport(ERROR,
00061 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00062 errmsg("must specify provider when multiple security label providers have been loaded")));
00063 provider = (LabelProvider *) linitial(label_provider_list);
00064 }
00065 else
00066 {
00067 foreach(lc, label_provider_list)
00068 {
00069 LabelProvider *lp = lfirst(lc);
00070
00071 if (strcmp(stmt->provider, lp->provider_name) == 0)
00072 {
00073 provider = lp;
00074 break;
00075 }
00076 }
00077 if (provider == NULL)
00078 ereport(ERROR,
00079 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00080 errmsg("security label provider \"%s\" is not loaded",
00081 stmt->provider)));
00082 }
00083
00084
00085
00086
00087
00088
00089
00090 address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
00091 &relation, ShareUpdateExclusiveLock, false);
00092
00093
00094 check_object_ownership(GetUserId(), stmt->objtype, address,
00095 stmt->objname, stmt->objargs, relation);
00096
00097
00098 switch (stmt->objtype)
00099 {
00100 case OBJECT_COLUMN:
00101
00102
00103
00104
00105
00106
00107 if (relation->rd_rel->relkind != RELKIND_RELATION &&
00108 relation->rd_rel->relkind != RELKIND_VIEW &&
00109 relation->rd_rel->relkind != RELKIND_MATVIEW &&
00110 relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
00111 relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
00112 ereport(ERROR,
00113 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00114 errmsg("\"%s\" is not a table, view, composite type, or foreign table",
00115 RelationGetRelationName(relation))));
00116 break;
00117 default:
00118 break;
00119 }
00120
00121
00122 (*provider->hook) (&address, stmt->label);
00123
00124
00125 SetSecurityLabel(&address, provider->provider_name, stmt->label);
00126
00127
00128
00129
00130
00131
00132
00133 if (relation != NULL)
00134 relation_close(relation, NoLock);
00135
00136 return address.objectId;
00137 }
00138
00139
00140
00141
00142
00143 static char *
00144 GetSharedSecurityLabel(const ObjectAddress *object, const char *provider)
00145 {
00146 Relation pg_shseclabel;
00147 ScanKeyData keys[3];
00148 SysScanDesc scan;
00149 HeapTuple tuple;
00150 Datum datum;
00151 bool isnull;
00152 char *seclabel = NULL;
00153
00154 ScanKeyInit(&keys[0],
00155 Anum_pg_shseclabel_objoid,
00156 BTEqualStrategyNumber, F_OIDEQ,
00157 ObjectIdGetDatum(object->objectId));
00158 ScanKeyInit(&keys[1],
00159 Anum_pg_shseclabel_classoid,
00160 BTEqualStrategyNumber, F_OIDEQ,
00161 ObjectIdGetDatum(object->classId));
00162 ScanKeyInit(&keys[2],
00163 Anum_pg_shseclabel_provider,
00164 BTEqualStrategyNumber, F_TEXTEQ,
00165 CStringGetTextDatum(provider));
00166
00167 pg_shseclabel = heap_open(SharedSecLabelRelationId, AccessShareLock);
00168
00169 scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
00170 SnapshotNow, 3, keys);
00171
00172 tuple = systable_getnext(scan);
00173 if (HeapTupleIsValid(tuple))
00174 {
00175 datum = heap_getattr(tuple, Anum_pg_shseclabel_label,
00176 RelationGetDescr(pg_shseclabel), &isnull);
00177 if (!isnull)
00178 seclabel = TextDatumGetCString(datum);
00179 }
00180 systable_endscan(scan);
00181
00182 heap_close(pg_shseclabel, AccessShareLock);
00183
00184 return seclabel;
00185 }
00186
00187
00188
00189
00190
00191 char *
00192 GetSecurityLabel(const ObjectAddress *object, const char *provider)
00193 {
00194 Relation pg_seclabel;
00195 ScanKeyData keys[4];
00196 SysScanDesc scan;
00197 HeapTuple tuple;
00198 Datum datum;
00199 bool isnull;
00200 char *seclabel = NULL;
00201
00202
00203 if (IsSharedRelation(object->classId))
00204 return GetSharedSecurityLabel(object, provider);
00205
00206
00207 ScanKeyInit(&keys[0],
00208 Anum_pg_seclabel_objoid,
00209 BTEqualStrategyNumber, F_OIDEQ,
00210 ObjectIdGetDatum(object->objectId));
00211 ScanKeyInit(&keys[1],
00212 Anum_pg_seclabel_classoid,
00213 BTEqualStrategyNumber, F_OIDEQ,
00214 ObjectIdGetDatum(object->classId));
00215 ScanKeyInit(&keys[2],
00216 Anum_pg_seclabel_objsubid,
00217 BTEqualStrategyNumber, F_INT4EQ,
00218 Int32GetDatum(object->objectSubId));
00219 ScanKeyInit(&keys[3],
00220 Anum_pg_seclabel_provider,
00221 BTEqualStrategyNumber, F_TEXTEQ,
00222 CStringGetTextDatum(provider));
00223
00224 pg_seclabel = heap_open(SecLabelRelationId, AccessShareLock);
00225
00226 scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
00227 SnapshotNow, 4, keys);
00228
00229 tuple = systable_getnext(scan);
00230 if (HeapTupleIsValid(tuple))
00231 {
00232 datum = heap_getattr(tuple, Anum_pg_seclabel_label,
00233 RelationGetDescr(pg_seclabel), &isnull);
00234 if (!isnull)
00235 seclabel = TextDatumGetCString(datum);
00236 }
00237 systable_endscan(scan);
00238
00239 heap_close(pg_seclabel, AccessShareLock);
00240
00241 return seclabel;
00242 }
00243
00244
00245
00246
00247
00248 static void
00249 SetSharedSecurityLabel(const ObjectAddress *object,
00250 const char *provider, const char *label)
00251 {
00252 Relation pg_shseclabel;
00253 ScanKeyData keys[4];
00254 SysScanDesc scan;
00255 HeapTuple oldtup;
00256 HeapTuple newtup = NULL;
00257 Datum values[Natts_pg_shseclabel];
00258 bool nulls[Natts_pg_shseclabel];
00259 bool replaces[Natts_pg_shseclabel];
00260
00261
00262 memset(nulls, false, sizeof(nulls));
00263 memset(replaces, false, sizeof(replaces));
00264 values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
00265 values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
00266 values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
00267 if (label != NULL)
00268 values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);
00269
00270
00271 ScanKeyInit(&keys[0],
00272 Anum_pg_shseclabel_objoid,
00273 BTEqualStrategyNumber, F_OIDEQ,
00274 ObjectIdGetDatum(object->objectId));
00275 ScanKeyInit(&keys[1],
00276 Anum_pg_shseclabel_classoid,
00277 BTEqualStrategyNumber, F_OIDEQ,
00278 ObjectIdGetDatum(object->classId));
00279 ScanKeyInit(&keys[2],
00280 Anum_pg_shseclabel_provider,
00281 BTEqualStrategyNumber, F_TEXTEQ,
00282 CStringGetTextDatum(provider));
00283
00284 pg_shseclabel = heap_open(SharedSecLabelRelationId, RowExclusiveLock);
00285
00286 scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
00287 SnapshotNow, 3, keys);
00288
00289 oldtup = systable_getnext(scan);
00290 if (HeapTupleIsValid(oldtup))
00291 {
00292 if (label == NULL)
00293 simple_heap_delete(pg_shseclabel, &oldtup->t_self);
00294 else
00295 {
00296 replaces[Anum_pg_shseclabel_label - 1] = true;
00297 newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
00298 values, nulls, replaces);
00299 simple_heap_update(pg_shseclabel, &oldtup->t_self, newtup);
00300 }
00301 }
00302 systable_endscan(scan);
00303
00304
00305 if (newtup == NULL && label != NULL)
00306 {
00307 newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
00308 values, nulls);
00309 simple_heap_insert(pg_shseclabel, newtup);
00310 }
00311
00312
00313 if (newtup != NULL)
00314 {
00315 CatalogUpdateIndexes(pg_shseclabel, newtup);
00316 heap_freetuple(newtup);
00317 }
00318
00319 heap_close(pg_shseclabel, RowExclusiveLock);
00320 }
00321
00322
00323
00324
00325
00326
00327 void
00328 SetSecurityLabel(const ObjectAddress *object,
00329 const char *provider, const char *label)
00330 {
00331 Relation pg_seclabel;
00332 ScanKeyData keys[4];
00333 SysScanDesc scan;
00334 HeapTuple oldtup;
00335 HeapTuple newtup = NULL;
00336 Datum values[Natts_pg_seclabel];
00337 bool nulls[Natts_pg_seclabel];
00338 bool replaces[Natts_pg_seclabel];
00339
00340
00341 if (IsSharedRelation(object->classId))
00342 {
00343 SetSharedSecurityLabel(object, provider, label);
00344 return;
00345 }
00346
00347
00348 memset(nulls, false, sizeof(nulls));
00349 memset(replaces, false, sizeof(replaces));
00350 values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
00351 values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
00352 values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
00353 values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
00354 if (label != NULL)
00355 values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);
00356
00357
00358 ScanKeyInit(&keys[0],
00359 Anum_pg_seclabel_objoid,
00360 BTEqualStrategyNumber, F_OIDEQ,
00361 ObjectIdGetDatum(object->objectId));
00362 ScanKeyInit(&keys[1],
00363 Anum_pg_seclabel_classoid,
00364 BTEqualStrategyNumber, F_OIDEQ,
00365 ObjectIdGetDatum(object->classId));
00366 ScanKeyInit(&keys[2],
00367 Anum_pg_seclabel_objsubid,
00368 BTEqualStrategyNumber, F_INT4EQ,
00369 Int32GetDatum(object->objectSubId));
00370 ScanKeyInit(&keys[3],
00371 Anum_pg_seclabel_provider,
00372 BTEqualStrategyNumber, F_TEXTEQ,
00373 CStringGetTextDatum(provider));
00374
00375 pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);
00376
00377 scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
00378 SnapshotNow, 4, keys);
00379
00380 oldtup = systable_getnext(scan);
00381 if (HeapTupleIsValid(oldtup))
00382 {
00383 if (label == NULL)
00384 simple_heap_delete(pg_seclabel, &oldtup->t_self);
00385 else
00386 {
00387 replaces[Anum_pg_seclabel_label - 1] = true;
00388 newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
00389 values, nulls, replaces);
00390 simple_heap_update(pg_seclabel, &oldtup->t_self, newtup);
00391 }
00392 }
00393 systable_endscan(scan);
00394
00395
00396 if (newtup == NULL && label != NULL)
00397 {
00398 newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
00399 values, nulls);
00400 simple_heap_insert(pg_seclabel, newtup);
00401 }
00402
00403
00404 if (newtup != NULL)
00405 {
00406 CatalogUpdateIndexes(pg_seclabel, newtup);
00407 heap_freetuple(newtup);
00408 }
00409
00410 heap_close(pg_seclabel, RowExclusiveLock);
00411 }
00412
00413
00414
00415
00416
00417 void
00418 DeleteSharedSecurityLabel(Oid objectId, Oid classId)
00419 {
00420 Relation pg_shseclabel;
00421 ScanKeyData skey[2];
00422 SysScanDesc scan;
00423 HeapTuple oldtup;
00424
00425 ScanKeyInit(&skey[0],
00426 Anum_pg_shseclabel_objoid,
00427 BTEqualStrategyNumber, F_OIDEQ,
00428 ObjectIdGetDatum(objectId));
00429 ScanKeyInit(&skey[1],
00430 Anum_pg_shseclabel_classoid,
00431 BTEqualStrategyNumber, F_OIDEQ,
00432 ObjectIdGetDatum(classId));
00433
00434 pg_shseclabel = heap_open(SharedSecLabelRelationId, RowExclusiveLock);
00435
00436 scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
00437 SnapshotNow, 2, skey);
00438 while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
00439 simple_heap_delete(pg_shseclabel, &oldtup->t_self);
00440 systable_endscan(scan);
00441
00442 heap_close(pg_shseclabel, RowExclusiveLock);
00443 }
00444
00445
00446
00447
00448
00449 void
00450 DeleteSecurityLabel(const ObjectAddress *object)
00451 {
00452 Relation pg_seclabel;
00453 ScanKeyData skey[3];
00454 SysScanDesc scan;
00455 HeapTuple oldtup;
00456 int nkeys;
00457
00458
00459 if (IsSharedRelation(object->classId))
00460 {
00461 Assert(object->objectSubId == 0);
00462 DeleteSharedSecurityLabel(object->objectId, object->classId);
00463 return;
00464 }
00465
00466 ScanKeyInit(&skey[0],
00467 Anum_pg_seclabel_objoid,
00468 BTEqualStrategyNumber, F_OIDEQ,
00469 ObjectIdGetDatum(object->objectId));
00470 ScanKeyInit(&skey[1],
00471 Anum_pg_seclabel_classoid,
00472 BTEqualStrategyNumber, F_OIDEQ,
00473 ObjectIdGetDatum(object->classId));
00474 if (object->objectSubId != 0)
00475 {
00476 ScanKeyInit(&skey[2],
00477 Anum_pg_seclabel_objsubid,
00478 BTEqualStrategyNumber, F_INT4EQ,
00479 Int32GetDatum(object->objectSubId));
00480 nkeys = 3;
00481 }
00482 else
00483 nkeys = 2;
00484
00485 pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);
00486
00487 scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
00488 SnapshotNow, nkeys, skey);
00489 while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
00490 simple_heap_delete(pg_seclabel, &oldtup->t_self);
00491 systable_endscan(scan);
00492
00493 heap_close(pg_seclabel, RowExclusiveLock);
00494 }
00495
00496 void
00497 register_label_provider(const char *provider_name, check_object_relabel_type hook)
00498 {
00499 LabelProvider *provider;
00500 MemoryContext oldcxt;
00501
00502 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
00503 provider = palloc(sizeof(LabelProvider));
00504 provider->provider_name = pstrdup(provider_name);
00505 provider->hook = hook;
00506 label_provider_list = lappend(label_provider_list, provider);
00507 MemoryContextSwitchTo(oldcxt);
00508 }