diff -rpNU3 base/src/backend/Makefile pgace/src/backend/Makefile --- base/src/backend/Makefile 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/Makefile 2008-01-08 01:39:49.000000000 +0900 @@ -16,7 +16,7 @@ include $(top_builddir)/src/Makefile.glo DIRS = access bootstrap catalog parser commands executor lib libpq \ main nodes optimizer port postmaster regex rewrite \ - storage tcop tsearch utils $(top_builddir)/src/timezone + security storage tcop tsearch utils $(top_builddir)/src/timezone SUBSYSOBJS = $(DIRS:%=%/SUBSYS.o) diff -rpNU3 base/src/backend/access/common/heaptuple.c pgace/src/backend/access/common/heaptuple.c --- base/src/backend/access/common/heaptuple.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/access/common/heaptuple.c 2008-01-10 12:42:25.000000000 +0900 @@ -67,6 +67,7 @@ #include "access/heapam.h" #include "access/tuptoaster.h" #include "executor/tuptable.h" +#include "security/pgace.h" /* Does att's datatype allow packing into the 1-byte-header varlena format? */ @@ -473,6 +474,9 @@ heap_attisnull(HeapTuple tup, int attnum case MinCommandIdAttributeNumber: case MaxTransactionIdAttributeNumber: case MaxCommandIdAttributeNumber: +#ifdef SECURITY_SYSATTR_NAME + case SecurityAttributeNumber: +#endif /* these are never null */ break; @@ -785,6 +789,11 @@ heap_getsysattr(HeapTuple tup, int attnu case TableOidAttributeNumber: result = ObjectIdGetDatum(tup->t_tableOid); break; +#ifdef SECURITY_SYSATTR_NAME + case SecurityAttributeNumber: + result = ObjectIdGetDatum(HeapTupleGetSecurity(tup)); + break; +#endif default: elog(ERROR, "invalid attnum: %d", attnum); result = 0; /* keep compiler quiet */ @@ -816,6 +825,7 @@ heap_copytuple(HeapTuple tuple) newTuple->t_tableOid = tuple->t_tableOid; newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE); memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len); + HeapTupleSetSecurity(newTuple, HeapTupleGetSecurity(tuple)); return newTuple; } @@ -909,6 +919,10 @@ heap_form_tuple(TupleDesc tupleDescripto if (tupleDescriptor->tdhasoid) len += sizeof(Oid); +#ifdef SECURITY_SYSATTR_NAME + len += sizeof(Oid); +#endif + hoff = len = MAXALIGN(len); /* align user data safely */ data_len = heap_compute_data_size(tupleDescriptor, values, isnull); @@ -940,6 +954,10 @@ heap_form_tuple(TupleDesc tupleDescripto if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */ td->t_infomask = HEAP_HASOID; +#ifdef SECURITY_SYSATTR_NAME + td->t_infomask |= HEAP_HASSECURITY; +#endif + heap_fill_tuple(tupleDescriptor, values, isnull, @@ -1020,6 +1038,10 @@ heap_formtuple(TupleDesc tupleDescriptor if (tupleDescriptor->tdhasoid) len += sizeof(Oid); +#ifdef SECURITY_SYSATTR_NAME + len += sizeof(Oid); +#endif + hoff = len = MAXALIGN(len); /* align user data safely */ data_len = ComputeDataSize(tupleDescriptor, values, nulls); @@ -1051,6 +1073,10 @@ heap_formtuple(TupleDesc tupleDescriptor if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */ td->t_infomask = HEAP_HASOID; +#ifdef SECURITY_SYSATTR_NAME + td->t_infomask |= HEAP_HASSECURITY; +#endif + DataFill(tupleDescriptor, values, nulls, @@ -1129,6 +1155,7 @@ heap_modify_tuple(HeapTuple tuple, newTuple->t_tableOid = tuple->t_tableOid; if (tupleDesc->tdhasoid) HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple)); + HeapTupleSetSecurity(newTuple, HeapTupleGetSecurity(tuple)); return newTuple; } @@ -1201,6 +1228,7 @@ heap_modifytuple(HeapTuple tuple, newTuple->t_tableOid = tuple->t_tableOid; if (tupleDesc->tdhasoid) HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple)); + HeapTupleSetSecurity(newTuple, HeapTupleGetSecurity(tuple)); return newTuple; } @@ -1847,6 +1875,10 @@ heap_form_minimal_tuple(TupleDesc tupleD if (tupleDescriptor->tdhasoid) len += sizeof(Oid); +#ifdef SECURITY_SYSATTR_NAME + len += sizeof(Oid); +#endif + hoff = len = MAXALIGN(len); /* align user data safely */ data_len = heap_compute_data_size(tupleDescriptor, values, isnull); @@ -1868,6 +1900,10 @@ heap_form_minimal_tuple(TupleDesc tupleD if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */ tuple->t_infomask = HEAP_HASOID; +#ifdef SECURITY_SYSATTR_NAME + tuple->t_infomask |= HEAP_HASSECURITY; +#endif + heap_fill_tuple(tupleDescriptor, values, isnull, @@ -1979,6 +2015,11 @@ heap_addheader(int natts, /* max domain hoff = offsetof(HeapTupleHeaderData, t_bits); if (withoid) hoff += sizeof(Oid); + +#ifdef SECURITY_SYSATTR_NAME + hoff += sizeof(Oid); +#endif + hoff = MAXALIGN(hoff); len = hoff + structlen; @@ -1997,6 +2038,10 @@ heap_addheader(int natts, /* max domain if (withoid) /* else leave infomask = 0 */ td->t_infomask = HEAP_HASOID; +#ifdef SECURITY_SYSATTR_NAME + td->t_infomask |= HEAP_HASSECURITY; +#endif + memcpy((char *) td + hoff, structure, structlen); return tuple; diff -rpNU3 base/src/backend/access/heap/heapam.c pgace/src/backend/access/heap/heapam.c --- base/src/backend/access/heap/heapam.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/access/heap/heapam.c 2008-03-19 10:08:35.000000000 +0900 @@ -50,6 +50,7 @@ #include "catalog/namespace.h" #include "miscadmin.h" #include "pgstat.h" +#include "security/pgace.h" #include "storage/procarray.h" #include "storage/smgr.h" #include "utils/datum.h" @@ -1946,6 +1947,9 @@ heap_insert(Relation relation, HeapTuple Oid simple_heap_insert(Relation relation, HeapTuple tup) { + if (!pgaceHeapTupleInsert(relation, tup, true, false)) + elog(ERROR, "simple_heap_insert on %s failed due to security reason", + RelationGetRelationName(relation)); return heap_insert(relation, tup, GetCurrentCommandId(true), true, true); } @@ -2227,6 +2231,9 @@ simple_heap_delete(Relation relation, It ItemPointerData update_ctid; TransactionId update_xmax; + if (!pgaceHeapTupleDelete(relation, tid, true, false)) + elog(ERROR, "simple_heap_delete on %s failed due to security reason", + RelationGetRelationName(relation)); result = heap_delete(relation, tid, &update_ctid, &update_xmax, GetCurrentCommandId(true), InvalidSnapshot, @@ -2870,6 +2877,9 @@ simple_heap_update(Relation relation, It ItemPointerData update_ctid; TransactionId update_xmax; + if (!pgaceHeapTupleUpdate(relation, otid, tup, true, false)) + elog(ERROR, "simple_heap_update on %s failed due to security reason", + RelationGetRelationName(relation)); result = heap_update(relation, otid, tup, &update_ctid, &update_xmax, GetCurrentCommandId(true), InvalidSnapshot, diff -rpNU3 base/src/backend/access/heap/tuptoaster.c pgace/src/backend/access/heap/tuptoaster.c --- base/src/backend/access/heap/tuptoaster.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/access/heap/tuptoaster.c 2008-03-19 10:08:35.000000000 +0900 @@ -35,6 +35,7 @@ #include "access/tuptoaster.h" #include "access/xact.h" #include "catalog/catalog.h" +#include "security/pgace.h" #include "utils/fmgroids.h" #include "utils/pg_lzcompress.h" #include "utils/typcache.h" @@ -589,6 +590,9 @@ toast_insert_or_update(Relation rel, Hea hoff += BITMAPLEN(numAttrs); if (newtup->t_data->t_infomask & HEAP_HASOID) hoff += sizeof(Oid); +#ifdef SECURITY_SYSATTR_NAME + hoff += sizeof(Oid); +#endif hoff = MAXALIGN(hoff); Assert(hoff == newtup->t_data->t_hoff); /* now convert to a limit on the tuple data size */ @@ -838,6 +842,9 @@ toast_insert_or_update(Relation rel, Hea new_len += BITMAPLEN(numAttrs); if (olddata->t_infomask & HEAP_HASOID) new_len += sizeof(Oid); +#ifdef SECURITY_SYSATTR_NAME + new_len += sizeof(Oid); +#endif new_len = MAXALIGN(new_len); Assert(new_len == olddata->t_hoff); new_data_len = heap_compute_data_size(tupleDesc, @@ -989,6 +996,9 @@ toast_flatten_tuple_attribute(Datum valu new_len += BITMAPLEN(numAttrs); if (olddata->t_infomask & HEAP_HASOID) new_len += sizeof(Oid); +#ifdef SECURITY_SYSATTR_NAME + new_len += sizeof(Oid); +#endif new_len = MAXALIGN(new_len); Assert(new_len == olddata->t_hoff); new_data_len = heap_compute_data_size(tupleDesc, @@ -1175,6 +1185,8 @@ toast_save_datum(Relation rel, Datum val if (!HeapTupleIsValid(toasttup)) elog(ERROR, "failed to build TOAST tuple"); + if (!pgaceHeapTupleInsert(toastrel, toasttup, true, false)) + elog(ERROR, "failed to insert TOAST tuple due to security reason"); heap_insert(toastrel, toasttup, mycid, use_wal, use_fsm); /* diff -rpNU3 base/src/backend/bootstrap/bootparse.y pgace/src/backend/bootstrap/bootparse.y --- base/src/backend/bootstrap/bootparse.y 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/bootstrap/bootparse.y 2008-01-08 01:39:49.000000000 +0900 @@ -212,7 +212,8 @@ Boot_CreateStmt: 0, ONCOMMIT_NOOP, (Datum) 0, - true); + true, + NIL); elog(DEBUG4, "relation created with oid %u", id); } do_end(); diff -rpNU3 base/src/backend/catalog/Makefile pgace/src/backend/catalog/Makefile --- base/src/backend/catalog/Makefile 2007-09-11 10:53:53.000000000 +0900 +++ pgace/src/backend/catalog/Makefile 2007-09-21 01:08:03.000000000 +0900 @@ -35,6 +35,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_sr pg_enum.h pg_namespace.h pg_conversion.h pg_depend.h \ pg_database.h pg_tablespace.h pg_pltemplate.h \ pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \ + pg_security.h \ pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \ pg_ts_parser.h pg_ts_template.h \ toasting.h indexing.h \ diff -rpNU3 base/src/backend/catalog/catalog.c pgace/src/backend/catalog/catalog.c --- base/src/backend/catalog/catalog.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/catalog/catalog.c 2008-03-19 10:08:35.000000000 +0900 @@ -30,6 +30,7 @@ #include "catalog/pg_database.h" #include "catalog/pg_namespace.h" #include "catalog/pg_pltemplate.h" +#include "catalog/pg_security.h" #include "catalog/pg_shdepend.h" #include "catalog/pg_shdescription.h" #include "catalog/pg_tablespace.h" @@ -257,6 +258,7 @@ IsSharedRelation(Oid relationId) relationId == AuthMemRelationId || relationId == DatabaseRelationId || relationId == PLTemplateRelationId || + relationId == SecurityRelationId || relationId == SharedDescriptionRelationId || relationId == SharedDependRelationId || relationId == TableSpaceRelationId) @@ -269,6 +271,8 @@ IsSharedRelation(Oid relationId) relationId == DatabaseNameIndexId || relationId == DatabaseOidIndexId || relationId == PLTemplateNameIndexId || + relationId == SecurityOidIndexId || + relationId == SecuritySeclabelIndexId || relationId == SharedDescriptionObjIndexId || relationId == SharedDependDependerIndexId || relationId == SharedDependReferenceIndexId || diff -rpNU3 base/src/backend/catalog/genbki.sh pgace/src/backend/catalog/genbki.sh --- base/src/backend/catalog/genbki.sh 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/catalog/genbki.sh 2008-01-08 01:39:49.000000000 +0900 @@ -130,6 +130,22 @@ for dir in $INCLUDE_DIRS; do fi done +# Get SECURITY_SYSATTR_NAME from security/pgace.h +for dir in $INCLUDE_DIRS; do + if [ -f "$dir/pg_config.h" ]; then + SECURITY_SYSATTR_NAME=`grep '#define[ ]*SECURITY_SYSATTR_NAME' $dir/pg_config.h | $AWK '{ print $3 }' | sed 's/\"//g'` + break + fi +done + +function SECURITY_SYSATTR_NAME_filter() { + if [ -z "$SECURITY_SYSATTR_NAME" ]; then + grep -v SECURITY_SYSATTR_NAME; + else + cat + fi +} + touch ${OUTPUT_PREFIX}.description.$$ touch ${OUTPUT_PREFIX}.shdescription.$$ @@ -143,7 +159,7 @@ touch ${OUTPUT_PREFIX}.shdescription.$$ # Substitute values of configuration constants # ---------------- # -cat $INFILES | \ +cat $INFILES | SECURITY_SYSATTR_NAME_filter | \ sed -e 's;/\*.*\*/;;g' \ -e 's;/\*;\ /*\ @@ -165,6 +181,7 @@ sed -e "s/;[ ]*$//g" \ -e "s/PGUID/$BOOTSTRAP_SUPERUSERID/g" \ -e "s/NAMEDATALEN/$NAMEDATALEN/g" \ -e "s/PGNSP/$PG_CATALOG_NAMESPACE/g" \ + -e "s/SECURITY_SYSATTR_NAME/$SECURITY_SYSATTR_NAME/g" \ | $AWK ' # ---------------- # now use awk to process remaining .h file.. diff -rpNU3 base/src/backend/catalog/heap.c pgace/src/backend/catalog/heap.c --- base/src/backend/catalog/heap.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/catalog/heap.c 2008-01-08 01:39:49.000000000 +0900 @@ -53,6 +53,7 @@ #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_relation.h" +#include "security/pgace.h" #include "storage/smgr.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -67,7 +68,8 @@ static void AddNewRelationTuple(Relation Oid new_rel_oid, Oid new_type_oid, Oid relowner, char relkind, - Datum reloptions); + Datum reloptions, + List *pgace_attr_list); static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, @@ -144,7 +146,21 @@ static FormData_pg_attribute a7 = { true, 'p', 'i', true, false, false, true, 0 }; +#ifdef SECURITY_SYSATTR_NAME +/* + * SECURITY_SYSATTR_NAME is defined at PGACE header file. + * If SELinux is enabled, it is defined as "security_context" + */ +static FormData_pg_attribute a8 = { + 0, {SECURITY_SYSATTR_NAME}, SECLABELOID, 0, sizeof(Oid), + SecurityAttributeNumber, 0, -1, -1, + true, 'p', 'i', true, false, false, true, 0 +}; + +static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8}; +#else static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7}; +#endif /* * This function returns a Form_pg_attribute pointer for a system attribute. @@ -467,7 +483,8 @@ AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind, bool oidislocal, - int oidinhcount) + int oidinhcount, + List *pgace_attr_list) { const Form_pg_attribute *dpp; int i; @@ -502,6 +519,7 @@ AddNewAttributeTuples(Oid new_rel_oid, false, ATTRIBUTE_TUPLE_SIZE, (void *) *dpp); + pgaceCreateAttributeCommon(rel, tup, pgace_attr_list); simple_heap_insert(rel, tup); @@ -592,7 +610,8 @@ void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, - Datum reloptions) + Datum reloptions, + List *pgace_attr_list) { Form_pg_class rd_rel = new_rel_desc->rd_rel; Datum values[Natts_pg_class]; @@ -642,6 +661,7 @@ InsertPgClassTuple(Relation pg_class_des * be embarrassing to do this sort of thing in polite company. */ HeapTupleSetOid(tup, new_rel_oid); + pgaceCreateRelationCommon(pg_class_desc, tup, pgace_attr_list); /* finally insert the new tuple, update the indexes, and clean up */ simple_heap_insert(pg_class_desc, tup); @@ -665,7 +685,8 @@ AddNewRelationTuple(Relation pg_class_de Oid new_type_oid, Oid relowner, char relkind, - Datum reloptions) + Datum reloptions, + List *pgace_attr_list) { Form_pg_class new_rel_reltup; @@ -725,7 +746,7 @@ AddNewRelationTuple(Relation pg_class_de new_rel_desc->rd_att->tdtypeid = new_type_oid; /* Now build and insert the tuple */ - InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid, reloptions); + InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid, reloptions, pgace_attr_list); } @@ -791,7 +812,8 @@ heap_create_with_catalog(const char *rel int oidinhcount, OnCommitAction oncommit, Datum reloptions, - bool allow_system_table_mods) + bool allow_system_table_mods, + List *pgace_attr_list) { Relation pg_class_desc; Relation new_rel_desc; @@ -963,13 +985,14 @@ heap_create_with_catalog(const char *rel new_type_oid, ownerid, relkind, - reloptions); + reloptions, + pgace_attr_list); /* * now add tuples to pg_attribute for the attributes in our new relation. */ AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind, - oidislocal, oidinhcount); + oidislocal, oidinhcount, pgace_attr_list); /* * Make a dependency link to force the relation to be deleted if its diff -rpNU3 base/src/backend/catalog/index.c pgace/src/backend/catalog/index.c --- base/src/backend/catalog/index.c 2008-02-03 01:11:28.000000000 +0900 +++ pgace/src/backend/catalog/index.c 2008-02-03 01:18:48.000000000 +0900 @@ -624,7 +624,7 @@ index_create(Oid heapRelationId, */ InsertPgClassTuple(pg_class, indexRelation, RelationGetRelid(indexRelation), - reloptions); + reloptions, NIL); /* done with pg_class */ heap_close(pg_class, RowExclusiveLock); diff -rpNU3 base/src/backend/catalog/pg_aggregate.c pgace/src/backend/catalog/pg_aggregate.c --- base/src/backend/catalog/pg_aggregate.c 2008-01-14 22:59:48.000000000 +0900 +++ pgace/src/backend/catalog/pg_aggregate.c 2008-01-14 23:08:31.000000000 +0900 @@ -213,8 +213,9 @@ AggregateCreate(const char *aggName, PointerGetDatum(NULL), /* parameterModes */ PointerGetDatum(NULL), /* parameterNames */ PointerGetDatum(NULL), /* proconfig */ - 1, /* procost */ - 0); /* prorows */ + 1, /* procost */ + 0, /* prorows */ + NULL); /* PGACE opaque */ /* * Okay to create the pg_aggregate entry. diff -rpNU3 base/src/backend/catalog/pg_largeobject.c pgace/src/backend/catalog/pg_largeobject.c --- base/src/backend/catalog/pg_largeobject.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/catalog/pg_largeobject.c 2008-01-08 01:39:49.000000000 +0900 @@ -18,6 +18,8 @@ #include "access/heapam.h" #include "catalog/indexing.h" #include "catalog/pg_largeobject.h" +#include "catalog/pg_security.h" +#include "security/pgace.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -57,6 +59,8 @@ LargeObjectCreate(Oid loid) ntup = heap_formtuple(pg_largeobject->rd_att, values, nulls); + pgaceLargeObjectCreate(pg_largeobject, ntup); + /* * Insert it */ @@ -91,6 +95,8 @@ LargeObjectDrop(Oid loid) while ((tuple = systable_getnext(sd)) != NULL) { + if (!found) + pgaceLargeObjectDrop(pg_largeobject, tuple); simple_heap_delete(pg_largeobject, &tuple->t_self); found = true; } diff -rpNU3 base/src/backend/catalog/pg_proc.c pgace/src/backend/catalog/pg_proc.c --- base/src/backend/catalog/pg_proc.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/catalog/pg_proc.c 2008-01-08 01:39:49.000000000 +0900 @@ -27,6 +27,7 @@ #include "mb/pg_wchar.h" #include "miscadmin.h" #include "parser/parse_type.h" +#include "security/pgace.h" #include "tcop/pquery.h" #include "tcop/tcopprot.h" #include "utils/acl.h" @@ -74,7 +75,8 @@ ProcedureCreate(const char *procedureNam Datum parameterNames, Datum proconfig, float4 procost, - float4 prorows) + float4 prorows, + void *pgaceItem) { Oid retval; int parameterCount; @@ -339,6 +341,7 @@ ProcedureCreate(const char *procedureNam /* Okay, do it... */ tup = heap_modifytuple(oldtup, tupDesc, values, nulls, replaces); + pgaceGramCreateFunction(rel, tup, (DefElem *)pgaceItem); simple_heap_update(rel, &tup->t_self, tup); ReleaseSysCache(oldtup); @@ -348,6 +351,7 @@ ProcedureCreate(const char *procedureNam { /* Creating a new procedure */ tup = heap_formtuple(tupDesc, values, nulls); + pgaceGramCreateFunction(rel, tup, (DefElem *)pgaceItem); simple_heap_insert(rel, tup); is_update = false; } diff -rpNU3 base/src/backend/catalog/toasting.c pgace/src/backend/catalog/toasting.c --- base/src/backend/catalog/toasting.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/catalog/toasting.c 2008-01-08 01:39:49.000000000 +0900 @@ -199,7 +199,8 @@ create_toast_table(Relation rel, Oid toa 0, ONCOMMIT_NOOP, (Datum) 0, - true); + true, + NIL); /* make the toast relation visible, else index creation will fail */ CommandCounterIncrement(); diff -rpNU3 base/src/backend/commands/cluster.c pgace/src/backend/commands/cluster.c --- base/src/backend/commands/cluster.c 2008-02-03 01:11:28.000000000 +0900 +++ pgace/src/backend/commands/cluster.c 2008-02-03 01:18:48.000000000 +0900 @@ -666,7 +666,8 @@ make_new_heap(Oid OIDOldHeap, const char 0, ONCOMMIT_NOOP, reloptions, - allowSystemTableMods); + allowSystemTableMods, + NIL); ReleaseSysCache(tuple); diff -rpNU3 base/src/backend/commands/copy.c pgace/src/backend/commands/copy.c --- base/src/backend/commands/copy.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/commands/copy.c 2008-02-01 11:24:01.000000000 +0900 @@ -22,6 +22,7 @@ #include "access/heapam.h" #include "access/xact.h" +#include "catalog/heap.h" #include "catalog/namespace.h" #include "catalog/pg_type.h" #include "commands/copy.h" @@ -34,6 +35,7 @@ #include "optimizer/planner.h" #include "parser/parse_relation.h" #include "rewrite/rewriteHandler.h" +#include "security/pgace.h" #include "storage/fd.h" #include "tcop/tcopprot.h" #include "utils/acl.h" @@ -159,6 +161,11 @@ typedef struct CopyStateData char *raw_buf; int raw_buf_index; /* next byte to process */ int raw_buf_len; /* total # of bytes stored */ + + /* dumpable/restorable system column support */ + FmgrInfo security_out_function; + bool security_force_quot; + bool security_force_notnull; } CopyStateData; typedef CopyStateData *CopyState; @@ -242,7 +249,7 @@ static const char BinarySignature[11] = /* non-export function prototypes */ static void DoCopyTo(CopyState cstate); static void CopyTo(CopyState cstate); -static void CopyOneRowTo(CopyState cstate, Oid tupleOid, +static void CopyOneRowTo(CopyState cstate, Oid tupleOid, Oid securityOid, Datum *values, bool *nulls); static void CopyFrom(CopyState cstate); static bool CopyReadLine(CopyState cstate); @@ -1073,6 +1080,8 @@ DoCopy(const CopyStmt *stmt, const char /* Generate or convert list of attributes to process */ cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, attnamelist); + pgaceCopyTable(cstate->rel, cstate->attnumlist, is_from); + num_phys_attrs = tupDesc->natts; /* Convert FORCE QUOTE name list to per-column flags, check validity */ @@ -1093,6 +1102,10 @@ DoCopy(const CopyStmt *stmt, const char (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("FORCE QUOTE column \"%s\" not referenced by COPY", NameStr(tupDesc->attrs[attnum - 1]->attname)))); + if (pgaceIsSecuritySystemColumn(attnum)) { + cstate->security_force_quot = true; + continue; + } cstate->force_quote_flags[attnum - 1] = true; } } @@ -1115,6 +1128,9 @@ DoCopy(const CopyStmt *stmt, const char (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("FORCE NOT NULL column \"%s\" not referenced by COPY", NameStr(tupDesc->attrs[attnum - 1]->attname)))); + if (pgaceIsSecuritySystemColumn(attnum)) + continue; /* ignore, if specified */ + cstate->force_notnull_flags[attnum - 1] = true; } } @@ -1305,16 +1321,27 @@ CopyTo(CopyState cstate) int attnum = lfirst_int(cur); Oid out_func_oid; bool isvarlena; + FmgrInfo *out_fmgr; + Form_pg_attribute pg_attribute; + + if (pgaceIsSecuritySystemColumn(attnum)) { + /* PGACE: dumpable system column */ + pg_attribute = SystemAttributeDefinition(attnum, false); + out_fmgr = &cstate->security_out_function; + } else { + pg_attribute = attr[attnum - 1]; + out_fmgr = &cstate->out_functions[attnum - 1]; + } if (cstate->binary) - getTypeBinaryOutputInfo(attr[attnum - 1]->atttypid, + getTypeBinaryOutputInfo(pg_attribute->atttypid, &out_func_oid, &isvarlena); else - getTypeOutputInfo(attr[attnum - 1]->atttypid, + getTypeOutputInfo(pg_attribute->atttypid, &out_func_oid, &isvarlena); - fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); + fmgr_info(out_func_oid, out_fmgr); } /* @@ -1370,6 +1397,12 @@ CopyTo(CopyState cstate) hdr_delim = true; colname = NameStr(attr[attnum - 1]->attname); + if (pgaceIsSecuritySystemColumn(attnum)) { + Form_pg_attribute sysatt = SystemAttributeDefinition(attnum, false); + colname = NameStr(sysatt->attname); + } else { + colname = NameStr(attr[attnum - 1]->attname); + } CopyAttributeOutCSV(cstate, colname, false, list_length(cstate->attnumlist) == 1); @@ -1395,11 +1428,14 @@ CopyTo(CopyState cstate) { CHECK_FOR_INTERRUPTS(); + if (!pgaceCopyToTuple(cstate->rel, cstate->attnumlist, tuple)) + continue; + /* Deconstruct the tuple ... faster than repeated heap_getattr */ heap_deform_tuple(tuple, tupDesc, values, nulls); /* Format and send the data */ - CopyOneRowTo(cstate, HeapTupleGetOid(tuple), values, nulls); + CopyOneRowTo(cstate, HeapTupleGetOid(tuple), HeapTupleGetSecurity(tuple), values, nulls); } heap_endscan(scandesc); @@ -1425,7 +1461,7 @@ CopyTo(CopyState cstate) * Emit one row during CopyTo(). */ static void -CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum *values, bool *nulls) +CopyOneRowTo(CopyState cstate, Oid tupleOid, Oid tupleSecurity, Datum *values, bool *nulls) { bool need_delim = false; FmgrInfo *out_functions = cstate->out_functions; @@ -1464,8 +1500,10 @@ CopyOneRowTo(CopyState cstate, Oid tuple foreach(cur, cstate->attnumlist) { int attnum = lfirst_int(cur); - Datum value = values[attnum - 1]; - bool isnull = nulls[attnum - 1]; + Datum value; + bool isnull; + bool force_quot; + FmgrInfo *out_fmgr; if (!cstate->binary) { @@ -1474,6 +1512,19 @@ CopyOneRowTo(CopyState cstate, Oid tuple need_delim = true; } + /* PGACE: dumpable system column support */ + if (pgaceIsSecuritySystemColumn(attnum)) { + value = tupleSecurity; + isnull = false; + force_quot = cstate->security_force_quot; + out_fmgr = &cstate->security_out_function; + } else { + value = values[attnum - 1]; + isnull = nulls[attnum - 1]; + force_quot = cstate->force_quote_flags[attnum - 1]; + out_fmgr = &out_functions[attnum - 1]; + } + if (isnull) { if (!cstate->binary) @@ -1485,11 +1536,9 @@ CopyOneRowTo(CopyState cstate, Oid tuple { if (!cstate->binary) { - string = OutputFunctionCall(&out_functions[attnum - 1], - value); + string = OutputFunctionCall(out_fmgr, value); if (cstate->csv_mode) - CopyAttributeOutCSV(cstate, string, - cstate->force_quote_flags[attnum - 1], + CopyAttributeOutCSV(cstate, string, force_quot, list_length(cstate->attnumlist) == 1); else CopyAttributeOutText(cstate, string); @@ -1498,8 +1547,7 @@ CopyOneRowTo(CopyState cstate, Oid tuple { bytea *outputbytes; - outputbytes = SendFunctionCall(&out_functions[attnum - 1], - value); + outputbytes = SendFunctionCall(out_fmgr, value); CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ); CopySendData(cstate, VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); @@ -1633,8 +1681,11 @@ CopyFrom(CopyState cstate) num_defaults; FmgrInfo *in_functions; FmgrInfo oid_in_function; + FmgrInfo security_in_function; + bool security_in_function_prepared = false; Oid *typioparams; Oid oid_typioparam; + Oid security_typioparam; int attnum; int i; Oid in_func_oid; @@ -1904,6 +1955,7 @@ CopyFrom(CopyState cstate) { bool skip_tuple; Oid loaded_oid = InvalidOid; + Oid loaded_security = InvalidOid; CHECK_FOR_INTERRUPTS(); @@ -1978,6 +2030,35 @@ CopyFrom(CopyState cstate) int attnum = lfirst_int(cur); int m = attnum - 1; + if (pgaceIsSecuritySystemColumn(attnum)) { + Form_pg_attribute sysatt = SystemAttributeDefinition(attnum, false); + if (fieldno >= fldct) + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("missing data for column \"%s\"", + NameStr(sysatt->attname)))); + string = field_strings[fieldno++]; + cstate->cur_attname = NameStr(attr[m]->attname); + cstate->cur_attval = string; + + if (!security_in_function_prepared) { + getTypeInputInfo(sysatt->atttypid, &in_func_oid, + &security_typioparam); + fmgr_info(in_func_oid, &security_in_function); + security_in_function_prepared = true; + } + if (string) { + Datum d = InputFunctionCall(&security_in_function, + string, + security_typioparam, + sysatt->atttypmod); + loaded_security = ObjectIdGetDatum(d); + } + cstate->cur_attname = NULL; + cstate->cur_attval = NULL; + continue; + } + if (fieldno >= fldct) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), @@ -2048,6 +2129,33 @@ CopyFrom(CopyState cstate) int attnum = lfirst_int(cur); int m = attnum - 1; + if (pgaceIsSecuritySystemColumn(attnum)) { + Form_pg_attribute sysatt = SystemAttributeDefinition(attnum, false); + Datum d; + + cstate->cur_attname = NameStr(sysatt->attname); + i++; + + if (!security_in_function_prepared) { + Oid security_in_func_oid; + getTypeBinaryInputInfo(sysatt->atttypid, + &security_in_func_oid, + &security_typioparam); + fmgr_info(security_in_func_oid, &security_in_function); + security_in_function_prepared = true; + } + d = CopyReadBinaryAttribute(cstate, + i, + &security_in_function, + security_typioparam, + sysatt->atttypmod, + &isnull); + if (!isnull) + loaded_security = ObjectIdGetDatum(d); + cstate->cur_attname = NULL; + continue; + } + cstate->cur_attname = NameStr(attr[m]->attname); i++; values[m] = CopyReadBinaryAttribute(cstate, @@ -2079,6 +2187,7 @@ CopyFrom(CopyState cstate) if (cstate->oids && file_has_oids) HeapTupleSetOid(tuple, loaded_oid); + HeapTupleSetSecurity(tuple, loaded_security); /* Triggers and stuff need to be invoked in query context. */ MemoryContextSwitchTo(oldcontext); @@ -2102,6 +2211,9 @@ CopyFrom(CopyState cstate) } } + if (!skip_tuple && !pgaceHeapTupleInsert(cstate->rel, tuple, false, false)) + skip_tuple = true; + if (!skip_tuple) { /* Place tuple in tuple slot */ @@ -3364,6 +3476,17 @@ CopyGetAttnums(TupleDesc tupDesc, Relati break; } } + + /* PGACE: writable system column support */ + if (attnum == InvalidAttrNumber) + { + Form_pg_attribute sysatt = SystemAttributeByName(name, true); + if (sysatt) { + if (pgaceIsSecuritySystemColumn(sysatt->attnum)) + attnum = sysatt->attnum; + } + } + if (attnum == InvalidAttrNumber) { if (rel != NULL) @@ -3413,7 +3536,7 @@ copy_dest_receive(TupleTableSlot *slot, slot_getallattrs(slot); /* And send the data */ - CopyOneRowTo(cstate, InvalidOid, slot->tts_values, slot->tts_isnull); + CopyOneRowTo(cstate, InvalidOid, InvalidOid, slot->tts_values, slot->tts_isnull); } /* diff -rpNU3 base/src/backend/commands/dbcommands.c pgace/src/backend/commands/dbcommands.c --- base/src/backend/commands/dbcommands.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/commands/dbcommands.c 2008-01-08 01:39:49.000000000 +0900 @@ -40,6 +40,7 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/bgwriter.h" +#include "security/pgace.h" #include "storage/freespace.h" #include "storage/procarray.h" #include "storage/smgr.h" @@ -92,6 +93,7 @@ createdb(const CreatedbStmt *stmt) DefElem *dtemplate = NULL; DefElem *dencoding = NULL; DefElem *dconnlimit = NULL; + DefElem *dpgace_item = NULL; char *dbname = stmt->dbname; char *dbowner = NULL; const char *dbtemplate = NULL; @@ -151,6 +153,13 @@ createdb(const CreatedbStmt *stmt) errmsg("LOCATION is not supported anymore"), errhint("Consider using tablespaces instead."))); } + else if (pgaceIsGramSecurityItem(defel)) { + if (dpgace_item) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + dpgace_item = defel; + } else elog(ERROR, "option \"%s\" not recognized", defel->defname); @@ -424,6 +433,7 @@ createdb(const CreatedbStmt *stmt) new_record, new_record_nulls); HeapTupleSetOid(tuple, dboid); + pgaceGramCreateDatabase(pg_database_rel, tuple, dpgace_item); simple_heap_insert(pg_database_rel, tuple); @@ -832,6 +842,7 @@ AlterDatabase(AlterDatabaseStmt *stmt) ListCell *option; int connlimit = -1; DefElem *dconnlimit = NULL; + DefElem *dpgace_item = NULL; Datum new_record[Natts_pg_database]; char new_record_nulls[Natts_pg_database]; char new_record_repl[Natts_pg_database]; @@ -849,6 +860,13 @@ AlterDatabase(AlterDatabaseStmt *stmt) errmsg("conflicting or redundant options"))); dconnlimit = defel; } + else if (pgaceIsGramSecurityItem(defel)) { + if (dpgace_item) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + dpgace_item = defel; + } else elog(ERROR, "option \"%s\" not recognized", defel->defname); @@ -894,6 +912,7 @@ AlterDatabase(AlterDatabaseStmt *stmt) newtuple = heap_modifytuple(tuple, RelationGetDescr(rel), new_record, new_record_nulls, new_record_repl); + pgaceGramAlterDatabase(rel, newtuple, dpgace_item); simple_heap_update(rel, &tuple->t_self, newtuple); /* Update indexes */ diff -rpNU3 base/src/backend/commands/functioncmds.c pgace/src/backend/commands/functioncmds.c --- base/src/backend/commands/functioncmds.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/commands/functioncmds.c 2008-01-08 01:39:49.000000000 +0900 @@ -47,6 +47,7 @@ #include "miscadmin.h" #include "parser/parse_func.h" #include "parser/parse_type.h" +#include "security/pgace.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -412,7 +413,8 @@ compute_attributes_sql_style(List *optio bool *security_definer, ArrayType **proconfig, float4 *procost, - float4 *prorows) + float4 *prorows, + DefElem **pgaceItem) { ListCell *option; DefElem *as_item = NULL; @@ -444,6 +446,14 @@ compute_attributes_sql_style(List *optio errmsg("conflicting or redundant options"))); language_item = defel; } + else if (pgaceIsGramSecurityItem(defel)) + { + if (*pgaceItem) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + *pgaceItem = defel; + } else if (compute_common_attribute(defel, &volatility_item, &strict_item, @@ -624,6 +634,7 @@ CreateFunction(CreateFunctionStmt *stmt) HeapTuple languageTuple; Form_pg_language languageStruct; List *as_clause; + DefElem *pgaceItem = NULL; /* Convert list of names to a name and namespace */ namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname, @@ -647,7 +658,7 @@ CreateFunction(CreateFunctionStmt *stmt) compute_attributes_sql_style(stmt->options, &as_clause, &language, &volatility, &isStrict, &security, - &proconfig, &procost, &prorows); + &proconfig, &procost, &prorows, &pgaceItem); /* Convert language name to canonical case */ languageName = case_translate_language_name(language); @@ -801,7 +812,8 @@ CreateFunction(CreateFunctionStmt *stmt) PointerGetDatum(parameterNames), PointerGetDatum(proconfig), procost, - prorows); + prorows, + pgaceItem); } @@ -1151,6 +1163,7 @@ AlterFunction(AlterFunctionStmt *stmt) List *set_items = NIL; DefElem *cost_item = NULL; DefElem *rows_item = NULL; + DefElem *pgaceItem = NULL; rel = heap_open(ProcedureRelationId, RowExclusiveLock); @@ -1182,6 +1195,15 @@ AlterFunction(AlterFunctionStmt *stmt) { DefElem *defel = (DefElem *) lfirst(l); + if (pgaceIsGramSecurityItem(defel)) { + if (pgaceItem) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + pgaceItem = defel; + continue; + } + if (compute_common_attribute(defel, &volatility_item, &strict_item, @@ -1252,6 +1274,7 @@ AlterFunction(AlterFunctionStmt *stmt) tup = heap_modifytuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl); } + pgaceGramAlterFunction(rel, tup, pgaceItem); /* Do the update */ simple_heap_update(rel, &tup->t_self, tup); diff -rpNU3 base/src/backend/commands/lockcmds.c pgace/src/backend/commands/lockcmds.c --- base/src/backend/commands/lockcmds.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/commands/lockcmds.c 2008-01-08 01:39:49.000000000 +0900 @@ -18,6 +18,7 @@ #include "catalog/namespace.h" #include "commands/lockcmds.h" #include "miscadmin.h" +#include "security/pgace.h" #include "utils/acl.h" #include "utils/lsyscache.h" @@ -59,6 +60,8 @@ LockTableCommand(LockStmt *lockstmt) aclcheck_error(aclresult, ACL_KIND_CLASS, get_rel_name(reloid)); + pgaceLockTable(reloid); + if (lockstmt->nowait) rel = relation_open_nowait(reloid, lockstmt->mode); else diff -rpNU3 base/src/backend/commands/proclang.c pgace/src/backend/commands/proclang.c --- base/src/backend/commands/proclang.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/commands/proclang.c 2008-01-08 01:39:49.000000000 +0900 @@ -144,7 +144,8 @@ CreateProceduralLanguage(CreatePLangStmt PointerGetDatum(NULL), PointerGetDatum(NULL), 1, - 0); + 0, + NULL); } /* @@ -177,7 +178,8 @@ CreateProceduralLanguage(CreatePLangStmt PointerGetDatum(NULL), PointerGetDatum(NULL), 1, - 0); + 0, + NULL); } } else diff -rpNU3 base/src/backend/commands/tablecmds.c pgace/src/backend/commands/tablecmds.c --- base/src/backend/commands/tablecmds.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/commands/tablecmds.c 2008-03-19 10:08:35.000000000 +0900 @@ -57,6 +57,7 @@ #include "parser/parser.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteHandler.h" +#include "security/pgace.h" #include "storage/smgr.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -434,7 +435,8 @@ DefineRelation(CreateStmt *stmt, char re parentOidCount, stmt->oncommit, reloptions, - allowSystemTableMods); + allowSystemTableMods, + pgaceRelationAttrList(stmt)); StoreCatalogInheritance(relationId, inheritOids); @@ -2031,6 +2033,7 @@ ATPrepCmd(List **wqueue, Relation rel, A case AT_DisableRule: case AT_AddInherit: /* INHERIT / NO INHERIT */ case AT_DropInherit: + case AT_SetSecurityLabel: ATSimplePermissions(rel, false); /* These commands never recurse */ /* No command-specific prep needed */ @@ -2253,6 +2256,9 @@ ATExecCmd(AlteredTableInfo *tab, Relatio case AT_DropInherit: ATExecDropInherit(rel, (RangeVar *) cmd->def); break; + case AT_SetSecurityLabel: + pgaceAlterRelationCommon(rel, cmd); + break; default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); diff -rpNU3 base/src/backend/commands/trigger.c pgace/src/backend/commands/trigger.c --- base/src/backend/commands/trigger.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/commands/trigger.c 2008-01-08 01:39:49.000000000 +0900 @@ -31,6 +31,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "parser/parse_func.h" +#include "security/pgace.h" #include "tcop/utility.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -1574,6 +1575,12 @@ ExecCallTriggerFunc(TriggerData *trigdat */ InitFunctionCallInfoData(fcinfo, finfo, 0, (Node *) trigdata, NULL); + /* PGACE: permission check for trigegr function */ + if (!pgaceCallFunctionTrigger(finfo, trigdata)) { + MemoryContextSwitchTo(oldContext); + return (HeapTuple) DatumGetPointer(NULL); + } + result = FunctionCallInvoke(&fcinfo); MemoryContextSwitchTo(oldContext); diff -rpNU3 base/src/backend/executor/execMain.c pgace/src/backend/executor/execMain.c --- base/src/backend/executor/execMain.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/executor/execMain.c 2008-03-19 10:08:35.000000000 +0900 @@ -48,6 +48,7 @@ #include "optimizer/clauses.h" #include "parser/parse_clause.h" #include "parser/parsetree.h" +#include "security/pgace.h" #include "storage/smgr.h" #include "utils/acl.h" #include "utils/lsyscache.h" @@ -136,6 +137,8 @@ ExecutorStart(QueryDesc *queryDesc, int Assert(queryDesc != NULL); Assert(queryDesc->estate == NULL); + pgaceExecutorStart(queryDesc, eflags); + /* * If the transaction is read-only, we need to check if any writes are * planned to non-temporary tables. EXPLAIN is considered read-only. @@ -1216,6 +1219,8 @@ ExecutePlan(EState *estate, for (;;) { + Oid __tts_security = InvalidOid; /* PGACE: explicit security labaling */ + /* Reset the per-output-tuple exprcontext */ ResetPerTupleExprContext(estate); @@ -1357,6 +1362,13 @@ lnext: ; } /* + * PGACE: security attribute system columnt support. + * If client specified a explicit security label, + * pgaceFetchSecurityLabel() fetch it via junk attribute. + */ + pgaceFetchSecurityAttribute(junkfilter, slot, &__tts_security); + + /* * Create a new "clean" tuple with all junk attributes removed. We * don't need to do this for DELETE, however (there will in fact * be no non-junk attributes in a DELETE!) @@ -1364,6 +1376,7 @@ lnext: ; if (operation != CMD_DELETE) slot = ExecFilterJunk(junkfilter, slot); } + slot->tts_security = __tts_security; /* * now that we have a tuple, do the appropriate thing with it.. either @@ -1484,6 +1497,9 @@ ExecInsert(TupleTableSlot *slot, resultRelInfo = estate->es_result_relation_info; resultRelationDesc = resultRelInfo->ri_RelationDesc; + /* PGACE: put an explicit security labeling */ + HeapTupleStoreSecurityFromSlot(tuple, slot); + /* BEFORE ROW INSERT Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) @@ -1520,6 +1536,13 @@ ExecInsert(TupleTableSlot *slot, ExecConstraints(resultRelInfo, slot, estate); /* + * PGACE: check HeapTuple Insertion permission + */ + if (!pgaceHeapTupleInsert(resultRelationDesc, tuple, + false, !!resultRelInfo->ri_projectReturning)) + return; + + /* * insert the tuple * * Note: heap_insert returns the tid (location) of the new tuple in the @@ -1586,6 +1609,10 @@ ExecDelete(ItemPointer tupleid, return; } + if (!pgaceHeapTupleDelete(resultRelationDesc, tupleid, + false, !!resultRelInfo->ri_projectReturning)) + return; + /* * delete the tuple * @@ -1722,6 +1749,9 @@ ExecUpdate(TupleTableSlot *slot, resultRelInfo = estate->es_result_relation_info; resultRelationDesc = resultRelInfo->ri_RelationDesc; + /* PGACE: put an explicit security attribute */ + HeapTupleStoreSecurityFromSlot(tuple, slot); + /* BEFORE ROW UPDATE Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0) @@ -1765,6 +1795,11 @@ lreplace:; if (resultRelationDesc->rd_att->constr) ExecConstraints(resultRelInfo, slot, estate); + /* PGACE: check HeapTuple update permission */ + if (!pgaceHeapTupleUpdate(resultRelationDesc, tupleid, tuple, + false, !!resultRelInfo->ri_projectReturning)) + return; + /* * replace the heap tuple * @@ -2629,7 +2664,8 @@ OpenIntoRel(QueryDesc *queryDesc) 0, into->onCommit, reloptions, - allowSystemTableMods); + allowSystemTableMods, + NIL); FreeTupleDesc(tupdesc); @@ -2735,6 +2771,13 @@ intorel_receive(TupleTableSlot *slot, De tuple = ExecCopySlotTuple(slot); + /* PGACE: store explicit security labeling and check HeapTuple insertion permission */ + HeapTupleStoreSecurityFromSlot(tuple, slot); + if (!pgaceHeapTupleInsert(estate->es_into_relation_descriptor, tuple, false, false)) { + heap_freetuple(tuple); + return; + } + heap_insert(estate->es_into_relation_descriptor, tuple, estate->es_output_cid, diff -rpNU3 base/src/backend/executor/execQual.c pgace/src/backend/executor/execQual.c --- base/src/backend/executor/execQual.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/executor/execQual.c 2008-01-08 01:39:49.000000000 +0900 @@ -47,6 +47,7 @@ #include "nodes/makefuncs.h" #include "optimizer/planmain.h" #include "parser/parse_expr.h" +#include "security/pgace.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -1750,6 +1751,8 @@ ExecEvalFunc(FuncExprState *fcache, /* Go directly to ExecMakeFunctionResult on subsequent uses */ fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult; + pgaceCallFunction(&fcache->func); + return ExecMakeFunctionResult(fcache, econtext, isNull, isDone); } diff -rpNU3 base/src/backend/libpq/be-fsstubs.c pgace/src/backend/libpq/be-fsstubs.c --- base/src/backend/libpq/be-fsstubs.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/libpq/be-fsstubs.c 2008-01-08 01:39:49.000000000 +0900 @@ -45,6 +45,7 @@ #include "libpq/be-fsstubs.h" #include "libpq/libpq-fs.h" #include "miscadmin.h" +#include "security/pgace.h" #include "storage/fd.h" #include "storage/large_object.h" #include "utils/memutils.h" @@ -353,6 +354,8 @@ lo_import(PG_FUNCTION_ARGS) errmsg("could not open server file \"%s\": %m", fnamebuf))); + pgaceLargeObjectImport(fd); + /* * create an inversion object */ @@ -434,6 +437,8 @@ lo_export(PG_FUNCTION_ARGS) errmsg("could not create server file \"%s\": %m", fnamebuf))); + pgaceLargeObjectExport(fd, lobjId); + /* * read in from the inversion file and write to the filesystem */ diff -rpNU3 base/src/backend/nodes/copyfuncs.c pgace/src/backend/nodes/copyfuncs.c --- base/src/backend/nodes/copyfuncs.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/nodes/copyfuncs.c 2008-03-19 10:08:35.000000000 +0900 @@ -24,6 +24,7 @@ #include "nodes/plannodes.h" #include "nodes/relation.h" +#include "security/pgace.h" #include "utils/datum.h" @@ -85,6 +86,7 @@ _copyPlannedStmt(PlannedStmt *from) COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(relationOids); COPY_SCALAR_FIELD(nParamExec); + COPY_NODE_FIELD(pgaceItem); return newnode; } @@ -1789,6 +1791,7 @@ _copyColumnDef(ColumnDef *from) COPY_NODE_FIELD(raw_default); COPY_STRING_FIELD(cooked_default); COPY_NODE_FIELD(constraints); + COPY_NODE_FIELD(pgaceItem); return newnode; } @@ -1869,6 +1872,7 @@ _copyQuery(Query *from) COPY_NODE_FIELD(limitCount); COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(setOperations); + COPY_NODE_FIELD(pgaceItem); return newnode; } @@ -2105,6 +2109,7 @@ _copyCreateStmt(CreateStmt *from) COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(oncommit); COPY_STRING_FIELD(tablespacename); + COPY_NODE_FIELD(pgaceItem); return newnode; } @@ -3602,6 +3607,10 @@ copyObject(void *from) break; default: + retval = pgaceCopyObject(from); + if (retval) + break; + elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from)); retval = from; /* keep compiler quiet */ break; diff -rpNU3 base/src/backend/nodes/outfuncs.c pgace/src/backend/nodes/outfuncs.c --- base/src/backend/nodes/outfuncs.c 2008-01-14 22:59:48.000000000 +0900 +++ pgace/src/backend/nodes/outfuncs.c 2008-01-14 23:08:31.000000000 +0900 @@ -26,6 +26,7 @@ #include "lib/stringinfo.h" #include "nodes/plannodes.h" #include "nodes/relation.h" +#include "security/pgace.h" #include "utils/datum.h" @@ -252,6 +253,7 @@ _outPlannedStmt(StringInfo str, PlannedS WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(relationOids); WRITE_INT_FIELD(nParamExec); + WRITE_NODE_FIELD(pgaceItem); } /* @@ -1748,6 +1750,7 @@ _outQuery(StringInfo str, Query *node) WRITE_NODE_FIELD(limitCount); WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(setOperations); + WRITE_NODE_FIELD(pgaceItem); } static void @@ -2440,6 +2443,8 @@ _outNode(StringInfo str, void *obj) break; default: + if (pgaceOutObject(str, obj)) + break; /* * This should be an ERROR, but it's too useful to be able to diff -rpNU3 base/src/backend/nodes/readfuncs.c pgace/src/backend/nodes/readfuncs.c --- base/src/backend/nodes/readfuncs.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/nodes/readfuncs.c 2008-03-12 20:03:44.000000000 +0900 @@ -24,6 +24,7 @@ #include "nodes/parsenodes.h" #include "nodes/readfuncs.h" +#include "security/pgace.h" /* @@ -154,6 +155,7 @@ _readQuery(void) READ_NODE_FIELD(limitCount); READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(setOperations); + READ_NODE_FIELD(pgaceItem); READ_DONE(); } @@ -1126,8 +1128,9 @@ parseNodeString(void) return_value = _readDeclareCursorStmt(); else { - elog(ERROR, "badly formatted node string \"%.32s\"...", token); - return_value = NULL; /* keep compiler quiet */ + return_value = pgaceReadObject(token); + if (!return_value) + elog(ERROR, "badly formatted node string \"%.32s\"...", token); } return (Node *) return_value; diff -rpNU3 base/src/backend/optimizer/plan/planner.c pgace/src/backend/optimizer/plan/planner.c --- base/src/backend/optimizer/plan/planner.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/optimizer/plan/planner.c 2008-01-08 01:39:49.000000000 +0900 @@ -101,6 +101,10 @@ planner(Query *parse, int cursorOptions, result = (*planner_hook) (parse, cursorOptions, boundParams); else result = standard_planner(parse, cursorOptions, boundParams); + + /* PGACE: pgaceItem is passed to PlannedStmt */ + result->pgaceItem = parse->pgaceItem; + return result; } diff -rpNU3 base/src/backend/parser/analyze.c pgace/src/backend/parser/analyze.c --- base/src/backend/parser/analyze.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/parser/analyze.c 2008-01-11 16:13:01.000000000 +0900 @@ -36,6 +36,7 @@ #include "parser/parse_relation.h" #include "parser/parse_target.h" #include "parser/parsetree.h" +#include "security/pgace.h" typedef struct @@ -404,6 +405,9 @@ transformInsertStmt(ParseState *pstate, Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable)); pstate->p_joinlist = lappend(pstate->p_joinlist, rtr); + /* security attribute system column support */ + pgaceTransformInsertStmt(&icolumns, &attrnos, selectQuery->targetList); + /*---------- * Generate an expression list for the INSERT that selects all the * non-resjunk columns from the subquery. (INSERT's tlist must be @@ -563,14 +567,15 @@ transformInsertStmt(ParseState *pstate, Expr *expr = (Expr *) lfirst(lc); ResTarget *col; TargetEntry *tle; + AttrNumber anum = (AttrNumber) lfirst_int(attnos); col = (ResTarget *) lfirst(icols); Assert(IsA(col, ResTarget)); tle = makeTargetEntry(expr, - (AttrNumber) lfirst_int(attnos), + anum, col->name, - false); + anum < 0 ? true : false); qry->targetList = lappend(qry->targetList, tle); icols = lnext(icols); @@ -733,6 +738,7 @@ transformSelectStmt(ParseState *pstate, /* handle any SELECT INTO/CREATE TABLE AS spec */ if (stmt->intoClause) { + pgaceTransformSelectStmt(qry->targetList); qry->intoClause = stmt->intoClause; if (stmt->intoClause->colNames) applyColumnNames(qry->targetList, stmt->intoClause->colNames); diff -rpNU3 base/src/backend/parser/gram.y pgace/src/backend/parser/gram.y --- base/src/backend/parser/gram.y 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/parser/gram.y 2008-03-19 10:08:35.000000000 +0900 @@ -56,6 +56,7 @@ #include "commands/defrem.h" #include "nodes/makefuncs.h" #include "parser/gramparse.h" +#include "security/pgace.h" #include "storage/lmgr.h" #include "utils/date.h" #include "utils/datetime.h" @@ -351,6 +352,8 @@ static Node *makeXmlExpr(XmlExprOp op, c %type OptTableSpace OptConsTableSpace OptTableSpaceOwner %type opt_check_option +%type OptSecurityItem SecurityItem + %type xml_attribute_el %type xml_attribute_list xml_attributes %type xml_root_version opt_xml_root_standalone @@ -1637,6 +1640,24 @@ alter_table_cmd: n->def = (Node *) $3; $$ = (Node *)n; } + /* ALTER TABLE CONTEXT = '...' */ + | SecurityItem + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetSecurityLabel; + n->name = NULL; + n->def = (Node *) $1; + $$ = (Node *) n; + } + /* ALTER TABLE ALTER [COLUMN] CONTEXT = '...' */ + | ALTER opt_column ColId SecurityItem + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetSecurityLabel; + n->name = $3; + n->def = (Node *) $4; + $$ = (Node *) n; + } | alter_rel_cmd { $$ = $1; @@ -1883,7 +1904,7 @@ opt_using: *****************************************************************************/ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' - OptInherit OptWith OnCommitOption OptTableSpace + OptInherit OptWith OnCommitOption OptTableSpace OptSecurityItem { CreateStmt *n = makeNode(CreateStmt); $4->istemp = $2; @@ -1894,10 +1915,11 @@ CreateStmt: CREATE OptTemp TABLE qualifi n->options = $9; n->oncommit = $10; n->tablespacename = $11; + n->pgaceItem = (Node *) $12; $$ = (Node *)n; } | CREATE OptTemp TABLE qualified_name OF qualified_name - '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace + '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace OptSecurityItem { /* SQL99 CREATE TABLE OF (cols) seems to be satisfied * by our inheritance capabilities. Let's try it... @@ -1911,6 +1933,7 @@ CreateStmt: CREATE OptTemp TABLE qualifi n->options = $10; n->oncommit = $11; n->tablespacename = $12; + n->pgaceItem = (Node *) $13; $$ = (Node *)n; } ; @@ -1953,13 +1976,14 @@ TableElement: | TableConstraint { $$ = $1; } ; -columnDef: ColId Typename ColQualList +columnDef: ColId Typename ColQualList OptSecurityItem { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; n->typename = $2; n->constraints = $3; n->is_local = true; + n->pgaceItem = (Node *) $4; $$ = (Node *)n; } ; @@ -4278,6 +4302,10 @@ common_func_opt_item: /* we abuse the normal content of a DefElem here */ $$ = makeDefElem("set", (Node *)$1); } + | SecurityItem + { + $$ = $1; + } ; createfunc_opt_item: @@ -5361,6 +5389,10 @@ createdb_opt_item: { $$ = makeDefElem("owner", NULL); } + | SecurityItem + { + $$ = $1; + } ; /* @@ -5409,6 +5441,10 @@ alterdb_opt_item: { $$ = makeDefElem("connectionlimit", (Node *)makeInteger($4)); } + | SecurityItem + { + $$ = $1; + } ; @@ -8736,6 +8772,26 @@ target_el: a_expr AS ColLabel } ; +/***************************************************************************** + * + * PGACE Security Items + * + *****************************************************************************/ + +OptSecurityItem: + SecurityItem { $$ = $1; } + | /* EMPTY */ { $$ = NULL; } + ; + +SecurityItem: + IDENT '=' Sconst + { + DefElem *n = pgaceGramSecurityItem($1, $3); + if (n == NULL) + yyerror("syntax error"); + $$ = n; + } + ; /***************************************************************************** * diff -rpNU3 base/src/backend/parser/parse_target.c pgace/src/backend/parser/parse_target.c --- base/src/backend/parser/parse_target.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/parser/parse_target.c 2008-01-08 01:39:49.000000000 +0900 @@ -26,6 +26,7 @@ #include "parser/parse_relation.h" #include "parser/parse_target.h" #include "parser/parse_type.h" +#include "security/pgace.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/typcache.h" @@ -335,14 +336,19 @@ transformAssignedExpr(ParseState *pstate Relation rd = pstate->p_target_relation; Assert(rd != NULL); - if (attrno <= 0) + if (attrno > 0) { + attrtype = attnumTypeId(rd, attrno); + attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod; + } else if (pgaceIsSecuritySystemColumn(attrno)) { + attrtype = SECLABELOID; + attrtypmod = -1; + } else { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot assign to system column \"%s\"", colname), parser_errposition(pstate, location))); - attrtype = attnumTypeId(rd, attrno); - attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod; + } /* * If the expression is a DEFAULT placeholder, insert the attribute's @@ -483,6 +489,9 @@ updateTargetListEntry(ParseState *pstate */ tle->resno = (AttrNumber) attrno; tle->resname = colname; + + if (pgaceIsSecuritySystemColumn(attrno)) + tle->resjunk = true; } @@ -749,6 +758,7 @@ checkInsertTargets(ParseState *pstate, L Bitmapset *wholecols = NULL; Bitmapset *partialcols = NULL; ListCell *tl; + bool security_attr = false; foreach(tl, cols) { @@ -757,14 +767,31 @@ checkInsertTargets(ParseState *pstate, L int attrno; /* Lookup column name, ereport on failure */ - attrno = attnameAttNum(pstate->p_target_relation, name, false); - if (attrno == InvalidAttrNumber) + attrno = attnameAttNum(pstate->p_target_relation, name, true); + if (attrno == InvalidAttrNumber) { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", name, RelationGetRelationName(pstate->p_target_relation)), parser_errposition(pstate, col->location))); + } else if (attrno <= 0) { + if (pgaceIsSecuritySystemColumn(attrno)) { + if (security_attr) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_COLUMN), + errmsg("column \"%s\" specified more than once", name), + parser_errposition(pstate, col->location))); + security_attr = true; + *attrnos = lappend_int(*attrnos, attrno); + continue; + } + ereport(ERROR, + (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), + errmsg("column \"%s\" of relation \"%s\" is system column", + name, RelationGetRelationName(pstate->p_target_relation)), + parser_errposition(pstate, col->location))); + } /* * Check for duplicates, but only of whole columns --- we allow diff -rpNU3 base/src/backend/postmaster/postmaster.c pgace/src/backend/postmaster/postmaster.c --- base/src/backend/postmaster/postmaster.c 2008-01-14 22:59:48.000000000 +0900 +++ pgace/src/backend/postmaster/postmaster.c 2008-01-25 19:04:56.000000000 +0900 @@ -107,6 +107,7 @@ #include "postmaster/pgarch.h" #include "postmaster/postmaster.h" #include "postmaster/syslogger.h" +#include "security/pgace.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/pg_shmem.h" @@ -1026,6 +1027,9 @@ PostmasterMain(int argc, char *argv[]) Assert(StartupPID != 0); pmState = PM_STARTUP; + if (!pgaceInitializePostmaster()) + ExitPostmaster(1); + status = ServerLoop(); /* @@ -2039,9 +2043,11 @@ pmdie(SIGNAL_ARGS) signal_child(PgArchPID, SIGQUIT); if (PgStatPID != 0) signal_child(PgStatPID, SIGQUIT); + pgaceFinalizePostmaster(); ExitPostmaster(0); break; } + pgaceFinalizePostmaster(); PG_SETMASK(&UnBlockSig); diff -rpNU3 base/src/backend/rewrite/rewriteHandler.c pgace/src/backend/rewrite/rewriteHandler.c --- base/src/backend/rewrite/rewriteHandler.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/rewrite/rewriteHandler.c 2008-01-08 01:39:49.000000000 +0900 @@ -24,6 +24,7 @@ #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteHandler.h" #include "rewrite/rewriteManip.h" +#include "security/pgace.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "commands/trigger.h" @@ -1880,5 +1881,8 @@ QueryRewrite(Query *parsetree) if (!foundOriginalQuery && lastInstead != NULL) lastInstead->canSetTag = true; + /* PGACE: general queries proxy */ + results = pgaceProxyQuery(results); + return results; } diff -rpNU3 base/src/backend/security/Makefile pgace/src/backend/security/Makefile --- base/src/backend/security/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ pgace/src/backend/security/Makefile 2008-03-13 23:25:01.000000000 +0900 @@ -0,0 +1,26 @@ +# +# src/backend/security/Makefile +# Makefile for Security Purpose Extensions +# +# Copyright (c) 2006 - 2007 KaiGai Kohei +# +ubdir = src/backend/security +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +OBJS := pgaceCommon.o pgaceHooks.o + +all: SUBSYS.o + +SUBSYS.o: $(OBJS) + $(LD) $(LDREL) $(LDOUT) $@ $^ + +depend dep: + $(CC) -MM $(CFLAGS) *.c >depend + +clean: + rm -f SUBSYS.o $(OBJS) + +ifeq (depend,$(wildcard depend)) +include depend +endif diff -rpNU3 base/src/backend/security/pgaceCommon.c pgace/src/backend/security/pgaceCommon.c --- base/src/backend/security/pgaceCommon.c 1970-01-01 09:00:00.000000000 +0900 +++ pgace/src/backend/security/pgaceCommon.c 2008-02-01 17:24:11.000000000 +0900 @@ -0,0 +1,714 @@ +/* + * src/backend/security/pgaceCommon.c + * Common part of PostgreSQL Access Control Extension + * Copyright 2007 KaiGai Kohei + */ +#include "postgres.h" + +#include "access/genam.h" +#include "access/heapam.h" +#include "access/xact.h" +#include "catalog/catalog.h" +#include "catalog/indexing.h" +#include "catalog/pg_attribute.h" +#include "catalog/pg_largeobject.h" +#include "catalog/pg_security.h" +#include "catalog/pg_type.h" +#include "executor/executor.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "nodes/parsenodes.h" +#include "parser/parse_expr.h" +#include "security/pgace.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/syscache.h" +#include +#include + +/***************************************************************************** + * Security attribute system column support + *****************************************************************************/ +#ifdef SECURITY_SYSATTR_NAME + +bool pgaceIsSecuritySystemColumn(int attrno) +{ + return ((attrno == SecurityAttributeNumber) ? true : false); +} + +void pgaceTransformSelectStmt(List *targetList) { + ListCell *l; + + foreach (l, targetList) { + TargetEntry *tle = lfirst(l); + + if (tle->resjunk) + continue; + if (!strcmp(tle->resname, SECURITY_SYSATTR_NAME)) { + if (exprType((Node *) tle->expr) != SECLABELOID) + elog(ERROR, "type mismatch in explicit labeling"); + tle->resjunk = true; + break; + } + } +} + +void pgaceTransformInsertStmt(List **p_icolumns, List **p_attrnos, List *targetList) { + AttrNumber security_attrno = 0; + ListCell *lc; + + foreach (lc, targetList) { + TargetEntry *tle = (TargetEntry *) lfirst(lc); + + security_attrno++; + if (strcmp(tle->resname, SECURITY_SYSATTR_NAME)) + continue; + + if (list_length(*p_icolumns) < list_length(targetList)) { + List *__icolumns = NIL; + List *__attrnos = NIL; + ListCell *l1, *l2; + int index = 0; + + forboth(l1, *p_icolumns, l2, *p_attrnos) { + if (++index == security_attrno) { + ResTarget *col = makeNode(ResTarget); + col->name = pstrdup(SECURITY_SYSATTR_NAME); + col->indirection = NIL; + col->val = NULL; + col->location = -1; + + __icolumns = lappend(__icolumns, col); + __attrnos = lappend_int(__attrnos, SecurityAttributeNumber); + } + if (lfirst_int(l2) == SecurityAttributeNumber) + return; + __icolumns = lappend(__icolumns, lfirst(l1)); + __attrnos = lappend_int(__attrnos, lfirst_int(l2)); + } + *p_icolumns = __icolumns; + *p_attrnos = __attrnos; + } + break; + } +} + +void pgaceFetchSecurityAttribute(JunkFilter *junkfilter, TupleTableSlot *slot, Oid *tts_security) +{ + AttrNumber attno; + Datum datum; + bool isnull; + + attno = ExecFindJunkAttribute(junkfilter, SECURITY_SYSATTR_NAME); + if (attno != InvalidAttrNumber) { + datum = ExecGetJunkAttribute(slot, attno, &isnull); + if (!isnull) + *tts_security = DatumGetObjectId(datum); + } +} +#else /* SECURITY_SYSATTR_NAME */ + +bool pgaceIsSecuritySystemColumn(int attrno) { + return false; +} + +void pgaceTransformSelectStmt(List *targetList) { + /* do nothing */ +} + +void pgaceTransformInsertStmt(List **p_icolumns, + List **p_attrnos, + List *targetList) { + /* do nothing */ +} + +void pgaceFetchSecurityAttribute(JunkFilter *junkfilter, + TupleTableSlot *slot, + Oid *tts_security) { + /* do nothing */ +} +#endif /* SECURITY_SYSATTR_NAME */ + +/***************************************************************************** + * Extended SQL statements support + *****************************************************************************/ + +/* CREATE TABLE with explicit CONTEXT */ +List *pgaceRelationAttrList(CreateStmt *stmt) +{ + List *result = NIL; + ListCell *l; + DefElem *defel, *newel; + + if (stmt->pgaceItem) { + defel = (DefElem *) stmt->pgaceItem; + + Assert(IsA(defel, DefElem)); + if (!pgaceIsGramSecurityItem(defel)) + elog(ERROR, "node is not a pgace security item"); + newel = makeDefElem(NULL, (Node *) copyObject(defel)); + result = lappend(result, newel); + } + + foreach (l, stmt->tableElts) { + ColumnDef *cdef = (ColumnDef *) lfirst(l); + defel = (DefElem *) cdef->pgaceItem; + + if (defel) { + Assert(IsA(defel, DefElem)); + if (!pgaceIsGramSecurityItem(defel)) + elog(ERROR, "node is not a pgace security item"); + newel = makeDefElem(pstrdup(cdef->colname), + (Node *) copyObject(defel)); + result = lappend(result, newel); + } + } + return result; +} + +void pgaceCreateRelationCommon(Relation rel, HeapTuple tuple, List *pgace_attr_list) { + ListCell *l; + + foreach (l, pgace_attr_list) { + DefElem *defel = (DefElem *) lfirst(l); + + if (!defel->defname) { + Assert(pgaceIsGramSecurityItem((DefElem *)defel->arg)); + pgaceGramCreateRelation(rel, tuple, (DefElem *)defel->arg); + break; + } + } +} + +void pgaceCreateAttributeCommon(Relation rel, HeapTuple tuple, List *pgace_attr_list) { + Form_pg_attribute attr = (Form_pg_attribute) GETSTRUCT(tuple); + ListCell *l; + + foreach (l, pgace_attr_list) { + DefElem *defel = lfirst(l); + + if (!defel->defname) + continue; /* for table */ + if (!strcmp(defel->defname, NameStr(attr->attname))) { + Assert(pgaceIsGramSecurityItem((DefElem *)defel->arg)); + pgaceGramCreateAttribute(rel, tuple, (DefElem *)defel->arg); + break; + } + } +} + +/* ALTER [ALTER ] CONTEXT = 'xxx' statement */ +static void alterRelationCommon(Relation rel, DefElem *defel) { + Relation pg_class; + HeapTuple tuple; + + pg_class = heap_open(RelationRelationId, RowExclusiveLock); + + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(RelationGetRelid(rel)), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for relation '%s'", RelationGetRelationName(rel)); + pgaceGramAlterRelation(rel, tuple, defel); + + simple_heap_update(pg_class, &tuple->t_self, tuple); + CatalogUpdateIndexes(pg_class, tuple); + + heap_freetuple(tuple); + heap_close(pg_class, RowExclusiveLock); +} + +static void alterAttributeCommon(Relation rel, char *colName, DefElem *defel) { + Relation pg_attr; + HeapTuple tuple; + + pg_attr = heap_open(AttributeRelationId, RowExclusiveLock); + + tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for attribute '%s' of relation '%s'", + colName, RelationGetRelationName(rel)); + pgaceGramAlterAttribute(rel, tuple, defel); + + simple_heap_update(pg_attr, &tuple->t_self, tuple); + CatalogUpdateIndexes(pg_attr, tuple); + + heap_freetuple(tuple); + heap_close(pg_attr, RowExclusiveLock); +} + +void pgaceAlterRelationCommon(Relation rel, AlterTableCmd *cmd) { + DefElem *defel = (DefElem *) cmd->def; + + Assert(IsA(defel, DefElem)); + + if (!pgaceIsGramSecurityItem(defel)) + elog(ERROR, "unsupported pgace security item"); + + if (!cmd->name) { + alterRelationCommon(rel, defel); + } else { + alterAttributeCommon(rel, cmd->name, defel); + } +} + +/***************************************************************************** + * security_label type input/output handler + *****************************************************************************/ +static Oid early_security_label_to_sid(char *seclabel); +static char *early_sid_to_security_label(Oid sid); +#define EARLY_PG_SECURITY "global/pg_security.bootstrap" + +static bool pg_security_is_available() { + /* -1 : early mode, 0: now in transfer, 1: available */ + static int pg_security_state = -1; + char fname[MAXPGPATH]; + FILE *filp; + + if (pg_security_state > 0) + return true; + if (IsBootstrapProcessingMode() || pg_security_state==0) + return false; + /* + * if initial setting up was not done, the cache file is remaining. + * so we have to insert its contains into pg_selinux. + * we can make decision of whether it already done, or not, by looking + * the existance of 'EARLY_PG_SECURITY'. + */ + snprintf(fname, sizeof(fname), "%s/%s", DataDir, EARLY_PG_SECURITY); + filp = fopen(fname, "rb"); + if (filp) { + Relation rel; + CatalogIndexState ind; + HeapTuple tuple; + char buffer[1024]; + Oid secoid, metaoid; + Datum value; + char isnull; + + pg_security_state = 0; + + PG_TRY(); + { + rel = heap_open(SecurityRelationId, RowExclusiveLock); + ind = CatalogOpenIndexes(rel); + while (fscanf(filp, "%u %s", &secoid, buffer) == 2) { + metaoid = early_security_label_to_sid(pgaceSecurityLabelOfLabel(buffer)); + + value = DirectFunctionCall1(textin, CStringGetDatum(buffer)); + isnull = ' '; + tuple = heap_formtuple(RelationGetDescr(rel), &value, &isnull); + + HeapTupleSetOid(tuple, secoid); + HeapTupleSetSecurity(tuple, metaoid); + + simple_heap_insert(rel, tuple); + CatalogIndexInsert(ind, tuple); + + heap_freetuple(tuple); + } + CatalogCloseIndexes(ind); + heap_close(rel, RowExclusiveLock); + + CommandCounterIncrement(); + } + PG_CATCH(); + { + fclose(filp); + PG_RE_THROW(); + } + PG_END_TRY(); + fclose(filp); + if (unlink(fname) != 0) + elog(ERROR, "PGACE: could not unlink '%s'", fname); + } + pg_security_state = 1; + + return true; +} + +static Oid early_security_label_to_sid(char *seclabel) +{ + char fname[MAXPGPATH], buffer[1024]; + Oid sid, minsid = SecurityRelationId; + FILE *filp; + + snprintf(fname, sizeof(fname), "%s/%s", DataDir, EARLY_PG_SECURITY); + filp = fopen(fname, "a+b"); + if (!filp) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("could not open '%s'", fname))); + flock(fileno(filp), LOCK_EX); + while (fscanf(filp, "%u %s", &sid, buffer) == 2) { + if (!strcmp(seclabel, buffer)) { + fclose(filp); + return sid; + } + if (sid < minsid) + minsid = sid; + } + sid = minsid - 1; + fprintf(filp, "%u %s\n", sid, seclabel); + fclose(filp); + + return sid; +} + +static char *early_sid_to_security_label(Oid sid) +{ + char fname[MAXPGPATH], buffer[1024], *seclabel; + FILE *filp; + Oid __sid; + + snprintf(fname, sizeof(fname), "%s/%s", DataDir, EARLY_PG_SECURITY); + filp = fopen(fname, "rb"); + if (!filp) + goto not_found; + + flock(fileno(filp), LOCK_SH); + while (fscanf(filp, "%u %s", &__sid, buffer) == 2) { + if (sid == __sid) { + fclose(filp); + return pstrdup(buffer); + } + } + fclose(filp); + +not_found: + seclabel = pgaceSecurityLabelCheckValid(NULL); + elog(seclabel ? NOTICE : ERROR, + "PGACE: No text representation for sid = %u", sid); + return seclabel; +} + +static Oid get_security_label_oid(Relation rel, CatalogIndexState ind, char *new_label) +{ + /* rel has to be opened with RowExclusiveLock */ + char *mlabel_str, *__mlabel_str; + Datum mlabel_text; + HeapTuple tuple; + Oid label_oid; + + mlabel_str = pgaceSecurityLabelOfLabel(new_label); + __mlabel_str = pgaceSecurityLabelCheckValid(mlabel_str); + if (mlabel_str != __mlabel_str) + elog(NOTICE, "PGACE: '%s' is not a valid security label," + " '%s' is applied instead.", mlabel_str, __mlabel_str); + + /* 1. lookup syscache */ + mlabel_text = DirectFunctionCall1(textin, CStringGetDatum(mlabel_str)); + tuple = SearchSysCache(SECURITYLABEL, + mlabel_text, + 0, 0, 0); + if (HeapTupleIsValid(tuple)) { + label_oid = HeapTupleGetSecurity(tuple); + ReleaseSysCache(tuple); + } else { + /* 2. lookup table on SnapshotSelf */ + SysScanDesc scan; + ScanKeyData skey; + + ScanKeyInit(&skey, + Anum_pg_security_seclabel, + BTEqualStrategyNumber, F_TEXTEQ, + PointerGetDatum(mlabel_text)); + scan = systable_beginscan(rel, SecuritySeclabelIndexId, + true, SnapshotSelf, 1, &skey); + tuple = systable_getnext(scan); + if (HeapTupleIsValid(tuple)) { + label_oid = HeapTupleGetSecurity(tuple); + } else { + /* 3. insert a new tuple into pg_security */ + Datum value = PointerGetDatum(mlabel_text); + char isnull = ' '; + Oid meta_oid; + + tuple = heap_formtuple(RelationGetDescr(rel), + &value, &isnull); + meta_oid = GetNewOid(rel); + HeapTupleSetOid(tuple, meta_oid); + HeapTupleSetSecurity(tuple, meta_oid); + + label_oid = simple_heap_insert(rel, tuple); + Assert(label_oid == meta_oid); + + CatalogIndexInsert(ind, tuple); + } + systable_endscan(scan); + } + return label_oid; +} + +static Oid security_label_to_sid(char *label_str) +{ + Datum label_text; + Oid label_oid; + HeapTuple tuple; + + if (!pg_security_is_available()) + return early_security_label_to_sid(label_str); + + /* 1. lookup system cache first */ + label_text = DirectFunctionCall1(textin, CStringGetDatum(label_str)); + tuple = SearchSysCache(SECURITYLABEL, + label_text, + 0, 0, 0); + if (HeapTupleIsValid(tuple)) { + label_oid = HeapTupleGetOid(tuple); + ReleaseSysCache(tuple); + } else { + /* 2. lookup within the current command ID */ + Relation rel; + SysScanDesc scan; + ScanKeyData skey; + Oid meta_oid; + + rel = heap_open(SecurityRelationId, RowExclusiveLock); + ScanKeyInit(&skey, + Anum_pg_security_seclabel, + BTEqualStrategyNumber, F_TEXTEQ, + PointerGetDatum(label_text)); + scan = systable_beginscan(rel, SecuritySeclabelIndexId, + true, SnapshotSelf, 1, &skey); + tuple = systable_getnext(scan); + if (HeapTupleIsValid(tuple)) { + label_oid = HeapTupleGetOid(tuple); + } else { + CatalogIndexState ind; + Datum value = PointerGetDatum(label_text); + char isnull = ' '; + + ind = CatalogOpenIndexes(rel); + + tuple = heap_formtuple(RelationGetDescr(rel), + &value, &isnull); + meta_oid = get_security_label_oid(rel, ind, label_str); + HeapTupleSetSecurity(tuple, meta_oid); + + label_oid = simple_heap_insert(rel, tuple); + + CatalogIndexInsert(ind, tuple); + CatalogCloseIndexes(ind); + } + systable_endscan(scan); + heap_close(rel, RowExclusiveLock); + } + return label_oid; +} + +static char *sid_to_security_label(Oid sid) +{ + HeapTuple tuple; + Datum tcon; + char *seclabel; + bool isnull, syscache = true; + + if (!pg_security_is_available()) + return early_sid_to_security_label(sid); + + tuple = SearchSysCache(SECURITYOID, + ObjectIdGetDatum(sid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) { + Relation rel; + SysScanDesc scan; + ScanKeyData skey; + + syscache = false; + rel = heap_open(SecurityRelationId, AccessShareLock); + ScanKeyInit(&skey, + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(sid)); + scan = systable_beginscan(rel, SecurityOidIndexId, + true, SnapshotSelf, 1, &skey); + tuple = systable_getnext(scan); + if (HeapTupleIsValid(tuple)) + tuple = heap_copytuple(tuple); + systable_endscan(scan); + heap_close(rel, AccessShareLock); + + if (!HeapTupleIsValid(tuple)) { + seclabel = pgaceSecurityLabelCheckValid(NULL); + elog(seclabel ? NOTICE : ERROR, + "PGACE: No text representation for sid = %u", sid); + return seclabel; + } + } + tcon = SysCacheGetAttr(SECURITYOID, + tuple, + Anum_pg_security_seclabel, + &isnull); + seclabel = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(tcon))); + if (syscache) + ReleaseSysCache(tuple); + + return seclabel; +} + +/* security_label_in -- security_label input function */ +Datum +security_label_in(PG_FUNCTION_ARGS) +{ + char *label = PG_GETARG_CSTRING(0); + char *__label; + + label = pgaceSecurityLabelIn(label); + __label = pgaceSecurityLabelCheckValid(label); + if (label != __label) + elog(ERROR, "PGACE: '%s' is not a valid security label", label); + + PG_RETURN_OID(security_label_to_sid(label)); +} + +/* security_label_out -- security_label output function */ +Datum +security_label_out(PG_FUNCTION_ARGS) +{ + Oid sid = PG_GETARG_OID(0); + char *label = sid_to_security_label(sid); + char *__label = pgaceSecurityLabelCheckValid(label); + if (label != __label) + elog(NOTICE, "PGACE: '%s' is not a valid security label," + " '%s' is applied instead.", label, __label); + PG_RETURN_CSTRING(pgaceSecurityLabelOut(__label)); +} + +/* security_label_raw_in -- security_label input function in raw format */ +Datum +security_label_raw_in(PG_FUNCTION_ARGS) +{ + char *label = PG_GETARG_CSTRING(0); + char *__label; + + __label = pgaceSecurityLabelCheckValid(label); + if (label != __label) + elog(ERROR, "PGACE: '%s' is not a valid security label", label); + + PG_RETURN_OID(security_label_to_sid(label)); +} + +/* security_label_raw_out -- security_label output function in raw format */ +Datum +security_label_raw_out(PG_FUNCTION_ARGS) +{ + Oid sid = PG_GETARG_OID(0); + char *label = sid_to_security_label(sid); + char *__label = pgaceSecurityLabelCheckValid(label); + + if (label != __label) + elog(NOTICE, "PGACE: '%s' is not a valid security label," + " '%s' is applied instead.", label, __label); + PG_RETURN_CSTRING(__label); +} + +/* text_to_security_label -- security_label cast function */ +Datum +text_to_security_label(PG_FUNCTION_ARGS) +{ + text *t = PG_GETARG_TEXT_P(0); + Datum seclabel; + + seclabel = DirectFunctionCall1(textout, + PointerGetDatum(t)); + return DirectFunctionCall1(security_label_in, seclabel); +} + +/* security_label_to_text -- security_label cast function */ +Datum +security_label_to_text(PG_FUNCTION_ARGS) +{ + Oid sid = PG_GETARG_OID(0); + Datum seclabel; + + seclabel = DirectFunctionCall1(security_label_out, + ObjectIdGetDatum(sid)); + return DirectFunctionCall1(textin, seclabel); +} + +/***************************************************************************** + * Set/Get security attribute of Large Object + *****************************************************************************/ +Datum +lo_get_security(PG_FUNCTION_ARGS) +{ + Oid loid = PG_GETARG_OID(0); + Oid lo_security = InvalidOid; + Relation rel; + ScanKeyData skey; + SysScanDesc sd; + HeapTuple tuple; + bool found = false; + + ScanKeyInit(&skey, + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(loid)); + + rel = heap_open(LargeObjectRelationId, AccessShareLock); + + sd = systable_beginscan(rel, LargeObjectLOidPNIndexId, true, + SnapshotNow, 1, &skey); + + while ((tuple = systable_getnext(sd)) != NULL) { + lo_security = HeapTupleGetSecurity(tuple); + pgaceLargeObjectGetSecurity(tuple); + found = true; + break; + } + systable_endscan(sd); + + heap_close(rel, AccessShareLock); + + if (!found) + elog(ERROR, "large object %u does not exist", loid); + + PG_RETURN_OID(lo_security); +} + +Datum +lo_set_security(PG_FUNCTION_ARGS) +{ + Oid loid = PG_GETARG_OID(0); + Oid lo_security = PG_GETARG_OID(1); + Relation rel; + ScanKeyData skey; + SysScanDesc sd; + HeapTuple tuple, newtup; + CatalogIndexState indstate; + bool found = false; + + ScanKeyInit(&skey, + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(loid)); + + rel = heap_open(LargeObjectRelationId, RowExclusiveLock); + + indstate = CatalogOpenIndexes(rel); + + sd = systable_beginscan(rel, LargeObjectLOidPNIndexId, true, + SnapshotNow, 1, &skey); + + while ((tuple = systable_getnext(sd)) != NULL) { + newtup = heap_copytuple(tuple); + if (!found) + pgaceLargeObjectSetSecurity(newtup, lo_security); + HeapTupleSetSecurity(newtup, lo_security); + simple_heap_update(rel, &newtup->t_self, newtup); + CatalogUpdateIndexes(rel, newtup); + found = true; + } + systable_endscan(sd); + CatalogCloseIndexes(indstate); + heap_close(rel, RowExclusiveLock); + + CommandCounterIncrement(); + + if (!found) + elog(ERROR, "large object %u does not exist.", loid); + + PG_RETURN_BOOL(true); +} diff -rpNU3 base/src/backend/security/pgaceHooks.c pgace/src/backend/security/pgaceHooks.c --- base/src/backend/security/pgaceHooks.c 1970-01-01 09:00:00.000000000 +0900 +++ pgace/src/backend/security/pgaceHooks.c 2008-03-13 23:25:01.000000000 +0900 @@ -0,0 +1,628 @@ +/* + * src/backend/security/pgaceHooks.c + * Dummy functions of PostgreSQL Access Control Extension + * when no users enables the framework. + * Copyright 2007 KaiGai Kohei + */ +#include "postgres.h" + +#include "security/pgace.h" + +/****************************************************************** + * Initialize / Finalize related hooks + ******************************************************************/ + +/* + * pgaceShmemSize() have to return the size of shared memory segment + * required by PGACE implementation. If no shared memory segment needed, + * it should return 0. + */ +Size pgaceShmemSize(void) +{ + return (Size) 0; +} + +/* + * pgaceInitialize() is called when a new PostgreSQL instance is generated. + * A PGACE implementation can initialize itself. + * + * @is_bootstrap : true, if bootstraping mode. + */ +void pgaceInitialize(bool is_bootstrap) +{ + /* do nothing */ +} + +/* + * pgaceInitializePostmaster() is called when a postmaster server process + * is started up. If it returns false, the server starting up process + * will be aborted. + */ +bool pgaceInitializePostmaster(void) +{ + return true; +} + +/* + * pgaceFinalizePostmaster() is called when a postmaster server process + * is just ending up. + */ +void pgaceFinalizePostmaster(void) +{ + /* do nothing */ +} + +/****************************************************************** + * SQL proxy hooks + ******************************************************************/ + +/* + * pgaceProxyQuery() is called just after query rewrite phase. + * PGACE implementation can modify the query trees in this hook, + * if necessary. + * + * @queryList : a list of Query typed objects. + */ +List *pgaceProxyQuery(List *queryList) +{ + return queryList; +} + +/* + * pgacePortalStart() is called on the top of PortalStart(). + * + * @portal : a Portal object currently executed. + */ +void pgacePortalStart(Portal portal) +{ + /* do nothing */ +} + +/* + * pgaceExecutorStart() is called on the top of ExecutorStart(). + * + * @queryDesc : a QueryDesc object given to ExecutorStart(). + * @eflags : eflags valus given to ExecutorStart(). + * if EXEC_FLAG_EXPLAIN_ONLY is set, no real access will run. + */ +void pgaceExecutorStart(QueryDesc *queryDesc, int eflags) +{ + /* do nothing */ +} + +/****************************************************************** + * HeapTuple modification hooks + ******************************************************************/ + +/* + * pgaceHeapTupleInsert() is called when a new tuple attempt to be inserted. + * If it returns false, this insertion of a new tuple will be cancelled. + * However, it does not generate any error. + * + * @rel : the target relation + * @tuple : the tuple attmpt to be inserted + * @is_internal : true, if this operation is invoked by system internal processes. + * @with_returning : true, if INSERT statement has RETURNING clause. + */ +bool pgaceHeapTupleInsert(Relation rel, HeapTuple tuple, + bool is_internal, bool with_returning) +{ + return true; +} + +/* + * pgaceHeapTupleUpdate() is called when a tuple attempt to be updated. + * If it returns false, this update will be cancelled. + * However, it does not generate any error. + * + * @rel : the target relation + * @otid : ItemPointer of the tuple to be updated + * @newtup : the new contains of the updated tuple + * @is_internal : true, if this operation is invoked by system internal processes. + * @with_returning : true, if INSERT statement has RETURNING clause. + */ +bool pgaceHeapTupleUpdate(Relation rel, ItemPointer otid, HeapTuple newtup, + bool is_internal, bool with_returning) +{ + return true; +} + +/* + * pgaceHeapTupleDelete() is called when a tuple attempt to be deleted. + * If it returns false, this deletion will be cancelled. + * However, it does not generate any error. + * + * @rel : the target relation + * @otid : ItemPointer of the tuple to be deleted + * @is_internal : true, if this operation is invoked by system internal processes. + * @with_returning : true, if INSERT statement has RETURNING clause. + */ +bool pgaceHeapTupleDelete(Relation rel, ItemPointer otid, + bool is_internal, bool with_returning) +{ + return true; +} + +/****************************************************************** + * Extended SQL statement hooks + ******************************************************************/ +/* + * PGACE implementation can use pgaceGramSecurityItem() hook to extend + * SQL statement for security purpose. This hook is deployed on parser/gram.y + * as a part of the SQL grammer. If no SQL extension is necessary, it has to + * return NULL to cause yyerror(). + * + * @defname : given string + * @value : given string + */ +DefElem *pgaceGramSecurityItem(char *defname, char *value) +{ + return NULL; +} + +/* + * PGACE implementation has to return true, if the given DefElem holds + * security item generated in pgaceGramSecurityItem(). false, if any other. + * + * @defel : given DefElem object + */ +bool pgaceIsGramSecurityItem(DefElem *defel) +{ + return false; +} + +/* + * pgaceGramCreateRelation() is called to modify a tuple just before inserting + * a new relation with CREATE TABLE, if extended statement is used. + * + * @rel : pg_class relation + * @tuple : a tuple of new relation + * @defel : extended statement + */ +void pgaceGramCreateRelation(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/* + * pgaceGramCreateAttribute() is called to modify a tuple just before inserting + * a new attribute with CREATE TABLE, if extended statement is used. + * + * @rel : pg_attribute relation + * @tuple : a tuple of new attribute + * @defel : extended statement + */ +void pgaceGramCreateAttribute(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/* + * pgaceGramAlterRelation() is called to modify a tuple just before updating + * a relation with ALTER TABLE, if extended statement is used. + * + * @rel : target relation + * @tuple : a tuple of new relation + * @defel : extended statement + */ +void pgaceGramAlterRelation(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/* + * pgaceGramAlterAttribute() is called to modify a tuple just before updating + * an attribute with ALTER TABLE, if extended statement is specified. + * + * @rel : target relation + * @tuple : a tuple of new attribute + * @defel : extended statement + */ +void pgaceGramAlterAttribute(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/* + * pgaceGramCreateDatabase() is called to modify a tuple just before inserting + * a new database with CREATE DATABASE, if extended statement is used. + * + * @rel : pg_database relation + * @tuple : a tuple of the new database + * @defel : extended statement + */ +void pgaceGramCreateDatabase(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/* + * pgaceGramAlterDatabase() is called to modify a tuple just before updating + * a database with ALTER DATABASE, if extended statement is used. + * + * @rel : pg_database relation + * @tuple : a tuple of the updated database + * @defel : extended statement + */ +void pgaceGramAlterDatabase(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/* + * pgaceGramCreateFunction() is called to modify a tuple just before inserting + * a new function into pg_proc, if extended statement is used. + * + * @rel : pg_proc relation + * @tuple : a tuple of the new function + * @defel : extended statement + */ +void pgaceGramCreateFunction(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/* + * pgaceGramAlterFunction() is called to modify a tuple just before updating + * a function with ALTER FUNCTION, if extended statement is used. + * + * @rel : pg_proc relation + * @tuple : a tuple of the function + * @defel : extended statement + */ +void pgaceGramAlterFunction(Relation rel, HeapTuple tuple, DefElem *defel) +{ + /* do nothing */ +} + +/****************************************************************** + * DATABASE related hooks + ******************************************************************/ + +/* + * pgaceSetDatabaseParam() is called when clients tries to set GUC variables + * + * @name : The name of GUC variable + * @argstr : The new valus of GUC variable. If argstr is NULL, it means + * clients tries to reset the variable. + */ +void pgaceSetDatabaseParam(const char *name, char *argstring) +{ + /* do nothing */ +} + +/* + * pgaceGetDatabaseParam() is called when clients tries to refer GUC variables + * + * @name : The name of GUC variable + */ +void pgaceGetDatabaseParam(const char *name) +{ + /* do nothing */ +} + +/****************************************************************** + * FUNCTION related hooks + ******************************************************************/ + +/* + * pgaceCallFunction() is called just before executing SQL function + * as a part of query. + * + * @finfo : FmgrInfo object for the target function + */ +void pgaceCallFunction(FmgrInfo *finfo) +{ + /* do nothing */ +} + +/* + * pgaceCallFunctionTrigger() is called just before executing + * trigger function. + * If it returns false, the trigger function will not be called and caller + * receives NULL tuple as a result. In the case when Before-Row triggers, + * it means the current operations on the tuple should be skipped. + * + * @finfo : FmgrInfo object for the target function + * @tgdata : TriggerData object for the current trigger invokation + */ +bool pgaceCallFunctionTrigger(FmgrInfo *finfo, TriggerData *tgdata) +{ + return true; +} + +/* + * pgaceCallFunctionFastPath() is called just before executing + * SQL function in the fast path. + * + * @finfo : FmgrInfo object for the target function + */ +void pgaceCallFunctionFastPath(FmgrInfo *finfo) +{ + /* do nothing */ +} + +/* + * pgacePreparePlanCheck() is called before foreign key/primary key constraint checks, + * at ri_PlanCheck(). PGACE implementation can return its opaque data for any purpose. + * + * @rel : the target relation in which a constraint is configured + */ +Datum pgacePreparePlanCheck(Relation rel) +{ + return (Datum) 0; +} + +/* + * pgaceRestorePlanCheck() is called after foreign key/primary key constraint checks, + * at ri_PlanCheck(). PGACE implementation can use an opaque data generated in the above + * pgacePreparePlanCheck(). + * + * @rel : the target relation in which a constraint is configured + * @pgace_saved : an opaque data returned from pgacePreparePlanCheck() + */ +void pgaceRestorePlanCheck(Relation rel, Datum pgace_saved) +{ + /* do nothing */ +} + +/****************************************************************** + * TABLE related hooks + ******************************************************************/ + +/* + * pgaceLockTable() is called when explicit LOCK statement used. + * + * @relid : the target relation id + */ +void pgaceLockTable(Oid relid) +{ + /* do nothing */ +} + +/****************************************************************** + * COPY TO/COPY FROM statement hooks + ******************************************************************/ + +/* + * pgaceCopyTable() is called when COPY TO/COPY FROM statement is processed + * + * @rel : the target relation + * @attNumList : the list of attribute numbers + * @isFrom : true, if the given statement is 'COPY FROM' + */ +void pgaceCopyTable(Relation rel, List *attNumList, bool isFrom) { + /* do nothing */ +} + +/* + * pgaceCopyToTuple() is called to check whether the given tuple should be + * filtered, or not in the process of COPY TO statement. + * If it returns false, the given tuple will be filtered from the result set + * + * @rel : the target relation + * @attNumList : the list of attribute numbers + * @tuple : the target tuple + */ +bool pgaceCopyToTuple(Relation rel, List *attNumList, HeapTuple tuple) { + return true; +} + +/****************************************************************** + * Loadable shared library module hooks + ******************************************************************/ + +/* + * pgaceLoadSharedModule() is called just before load a shared library + * module. + * + * @filename : full path name of the shared library module + */ +void pgaceLoadSharedModule(const char *filename) { + /* do nothing */ +} + +/****************************************************************** + * Binary Large Object (BLOB) hooks + ******************************************************************/ + +/* + * pgaceLargeObjectGetSecurity() is called when lo_get_security() is executed + * It returns its security attribute. + * + * @tuple : a tuple which is a part of the target largeobject. + */ +void pgaceLargeObjectGetSecurity(HeapTuple tuple) { + elog(ERROR, "PGACE: There is no guest module."); +} + +/* + * pgaceLargeObjectSetSecurity() is called when lo_set_security() is executed + * + * @tuple : a tuple which is a part of the target largeobject. + * @lo_security : new security attribute specified + */ +void pgaceLargeObjectSetSecurity(HeapTuple tuple, Oid lo_security) { + elog(ERROR, "PGACE: There is no guest module."); +} + +/* + * pgaceLargeObjectCreate() is called when a new large object is created + * + * @rel : pg_largeobject relation opened with RowExclusiveLock + * @tuple : a new tuple for the new large object + */ +void pgaceLargeObjectCreate(Relation rel, HeapTuple tuple) { + /* do nothing */ +} + +/* + * pgaceLargeObjectDrop() is called when a large object is dropped once for + * a large object + * + * @rel : pg_largeobject relation opened with RowExclusiveLock + * @tuple : one of the tuples within the target large object + */ +void pgaceLargeObjectDrop(Relation rel, HeapTuple tuple) { + /* do nothing */ +} + +/* + * pgaceLargeObjectRead is called when they read from a large object + * + * @rel : pg_largeobject relation opened with AccessShareLock + * @tuple : the head tuple within the given large object + */ +void pgaceLargeObjectRead(Relation rel, HeapTuple tuple) { + /* do nothing */ +} + +/* + * pgaceLargeObjectWrite() is called when they write to a large object + * + * @rel : pg_largeobject relation opened with RowExclusiveLock + * @newtup : the head tuple within the given large object + * @oldtup : the head tuple in older version, if exist + */ +void pgaceLargeObjectWrite(Relation rel, HeapTuple newtup, HeapTuple oldtup) { + /* do nothing */ +} + +/* + * pgaceLargeObjectTruncate() is called when they truncate a large object. + * + * @rel : pg_largeobject relation opened with RowExclusiveLock + * @loid : large object identifier + * @headtup : the head tuple to be truncated. NULL means this BLOB will be expanded. + */ +void pgaceLargeObjectTruncate(Relation rel, Oid loid, HeapTuple headtup) { + /* do nothing */ +} + +/* + * pgaceLargeObjectImport() is called when lo_import() is processed + * + * @fd : file descriptor to be inported + */ +void pgaceLargeObjectImport(int fd) { + /* do nothing */ +} + +/* + * pgaceLargeObjectExport() is called when lo_import() is processed + * + * @fd : file descriptor to be exported + * @loid : large object to be exported + */ +void pgaceLargeObjectExport(int fd, Oid loid) { + /* do nothing */ +} + +/****************************************************************** + * Security Label hooks + ******************************************************************/ + +/* + * PGACE implementation can use pgaceSecurityLabelIn() hook to translate + * a input security label from external representation into internal one. + * If no translation is necessary, it has to return @seclabel as is. + * + * @seclabel : security label being input + */ +char *pgaceSecurityLabelIn(char *seclabel) +{ + return seclabel; +} + +/* + * PGACE implementation can use pgaceSecurityLabelOut() hook to translate + * a security label in internal representation into external one. + * If no translation is necessary, it has to return @seclabel as is. + * + * @seclabel : security label being output + */ +char *pgaceSecurityLabelOut(char *seclabel) +{ + return seclabel; +} + +/* + * pgaceSecurityLabelCheckValid() checks whether the @seclabel is valid or not. + * In addition, it can returns an alternative security label, if possible. + * + * It has to return @seclabel as is, if @seclabel is a valid security label. + * It can return an alternative label, if @seclabel is NOT a valid one and + * there is an alternative. In any other case, it returns NULL. + * @seclabel may be NULL. In this case, @seclabel is always invalid. + * + * @seclabel : security label to be checked + */ +char *pgaceSecurityLabelCheckValid(char *seclabel) +{ + return seclabel; +} + +/* + * pgaceSecurityLabelOfLabel() returns the security attribute of a newly + * generated tuple within pg_security + * + * @new_label : a text representation of security context which will be newly + * inserted into pg_security. + */ +char *pgaceSecurityLabelOfLabel(char *new_label) +{ + return pstrdup("unlabeled"); +} + +/****************************************************************** + * Extended node type hooks + ******************************************************************/ + +/* + * If PGACE implementation requires new node type, a method to copy object. + * pgaceCopyObject() provides a hook to copy new node typed object. + * If a given object (@orig) has a tag extended by PGACE implementation, + * it have to copy and return it. + * If it returns NULL, @orig is not available for the PGACE implementation. + * + * @orig : a object which to copy + */ +Node *pgaceCopyObject(Node *orig) +{ + return NULL; +} + +/* + * pgaceOutObject() provides a hook to translate a object to text representation. + * If a given object (@node) has a tag extended by PGACE implementation, it have + * to put a text representation into StringInfo. + * If it returns false, @node is not available for the PGACE implementation. + * + * @str : StringInfo which to put the text representation + * @node : a object that text representation is required + */ +bool pgaceOutObject(StringInfo str, Node *node) +{ + return false; +} + +/* + * pgaceReadObject() provides a hook to read a text representation of an object. + * If a given token is a tag extended by PGACE implementation, it have to create + * an object same as original one. + * + * @token : a tag for the object + */ +void *pgaceReadObject(char *token) +{ + return NULL; +} + +/****************************************************************** + * Extended functions stub + ******************************************************************/ + +/* + * In this section, you can put function stubs when your security + * module is not activated. + */ diff -rpNU3 base/src/backend/storage/ipc/ipci.c pgace/src/backend/storage/ipc/ipci.c --- base/src/backend/storage/ipc/ipci.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/storage/ipc/ipci.c 2008-01-08 01:39:49.000000000 +0900 @@ -25,6 +25,7 @@ #include "postmaster/autovacuum.h" #include "postmaster/bgwriter.h" #include "postmaster/postmaster.h" +#include "security/pgace.h" #include "storage/freespace.h" #include "storage/ipc.h" #include "storage/pg_shmem.h" @@ -117,6 +118,7 @@ CreateSharedMemoryAndSemaphores(bool mak #ifdef EXEC_BACKEND size = add_size(size, ShmemBackendArraySize()); #endif + size = add_size(size, pgaceShmemSize()); /* freeze the addin request size and include it */ addin_request_allowed = false; diff -rpNU3 base/src/backend/storage/large_object/inv_api.c pgace/src/backend/storage/large_object/inv_api.c --- base/src/backend/storage/large_object/inv_api.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/storage/large_object/inv_api.c 2008-03-19 10:08:35.000000000 +0900 @@ -39,6 +39,7 @@ #include "catalog/pg_largeobject.h" #include "commands/comment.h" #include "libpq/libpq-fs.h" +#include "security/pgace.h" #include "storage/large_object.h" #include "utils/fmgroids.h" #include "utils/resowner.h" @@ -445,6 +446,10 @@ inv_read(LargeObjectDesc *obj_desc, char if (HeapTupleHasNulls(tuple)) /* paranoia */ elog(ERROR, "null field found in pg_largeobject"); + + if (!nread) + pgaceLargeObjectRead(lo_heap_r, tuple); + data = (Form_pg_largeobject) GETSTRUCT(tuple); /* @@ -633,6 +638,8 @@ inv_write(LargeObjectDesc *obj_desc, con replace[Anum_pg_largeobject_data - 1] = 'r'; newtup = heap_modifytuple(oldtuple, RelationGetDescr(lo_heap_r), values, nulls, replace); + if (nwritten - n == 0) + pgaceLargeObjectWrite(lo_heap_r, newtup, oldtuple); simple_heap_update(lo_heap_r, &newtup->t_self, newtup); CatalogIndexInsert(indstate, newtup); heap_freetuple(newtup); @@ -676,6 +683,8 @@ inv_write(LargeObjectDesc *obj_desc, con values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno); values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); newtup = heap_formtuple(lo_heap_r->rd_att, values, nulls); + if (nwritten - n == 0) + pgaceLargeObjectWrite(lo_heap_r, newtup, NULL); simple_heap_insert(lo_heap_r, newtup); CatalogIndexInsert(indstate, newtup); heap_freetuple(newtup); @@ -756,6 +765,7 @@ inv_truncate(LargeObjectDesc *obj_desc, olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple); Assert(olddata->pageno >= pageno); } + pgaceLargeObjectTruncate(lo_heap_r, obj_desc->id, oldtuple); /* * If we found the page of the truncation point we need to truncate the diff -rpNU3 base/src/backend/tcop/fastpath.c pgace/src/backend/tcop/fastpath.c --- base/src/backend/tcop/fastpath.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/tcop/fastpath.c 2008-01-08 01:39:49.000000000 +0900 @@ -26,6 +26,7 @@ #include "libpq/pqformat.h" #include "mb/pg_wchar.h" #include "miscadmin.h" +#include "security/pgace.h" #include "tcop/fastpath.h" #include "tcop/tcopprot.h" #include "utils/acl.h" @@ -353,6 +354,8 @@ HandleFunctionRequest(StringInfo msgBuf) */ InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, NULL, NULL); + pgaceCallFunctionFastPath(fcinfo.flinfo); + if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) rformat = parse_fcall_arguments(msgBuf, fip, &fcinfo); else diff -rpNU3 base/src/backend/tcop/postgres.c pgace/src/backend/tcop/postgres.c --- base/src/backend/tcop/postgres.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/tcop/postgres.c 2008-03-19 10:08:35.000000000 +0900 @@ -53,6 +53,7 @@ #include "parser/parser.h" #include "postmaster/autovacuum.h" #include "rewrite/rewriteHandler.h" +#include "security/pgace.h" #include "storage/freespace.h" #include "storage/ipc.h" #include "storage/proc.h" @@ -629,6 +630,9 @@ pg_rewrite_query(Query *query) { /* don't rewrite utilities, just dump 'em into result list */ querytree_list = list_make1(query); + + /* PGACE rewrite utility query, if necessary */ + querytree_list = pgaceProxyQuery(querytree_list); } else { diff -rpNU3 base/src/backend/tcop/pquery.c pgace/src/backend/tcop/pquery.c --- base/src/backend/tcop/pquery.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/tcop/pquery.c 2008-01-08 01:39:49.000000000 +0900 @@ -19,6 +19,7 @@ #include "commands/prepare.h" #include "commands/trigger.h" #include "miscadmin.h" +#include "security/pgace.h" #include "tcop/pquery.h" #include "tcop/tcopprot.h" #include "tcop/utility.h" @@ -455,6 +456,9 @@ PortalStart(Portal portal, ParamListInfo AssertArg(PortalIsValid(portal)); AssertState(portal->status == PORTAL_DEFINED); + /* PGACE: PosrtalStart hook */ + pgacePortalStart(portal); + /* * Set up global portal context pointers. */ diff -rpNU3 base/src/backend/utils/adt/ri_triggers.c pgace/src/backend/utils/adt/ri_triggers.c --- base/src/backend/utils/adt/ri_triggers.c 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/backend/utils/adt/ri_triggers.c 2008-03-19 10:08:35.000000000 +0900 @@ -37,6 +37,7 @@ #include "parser/parse_coerce.h" #include "parser/parse_relation.h" #include "miscadmin.h" +#include "security/pgace.h" #include "utils/acl.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" @@ -3202,6 +3203,7 @@ ri_PlanCheck(const char *querystr, int n Relation query_rel; Oid save_userid; bool save_secdefcxt; + Datum save_pgace; /* * The query is always run against the FK table except when this is an @@ -3219,7 +3221,18 @@ ri_PlanCheck(const char *querystr, int n SetUserIdAndContext(RelationGetForm(query_rel)->relowner, true); /* Create the plan */ - qplan = SPI_prepare(querystr, nargs, argtypes); + save_pgace = pgacePreparePlanCheck(query_rel); + PG_TRY(); + { + qplan = SPI_prepare(querystr, nargs, argtypes); + } + PG_CATCH(); + { + pgaceRestorePlanCheck(query_rel, save_pgace); + PG_RE_THROW(); + } + PG_END_TRY(); + pgaceRestorePlanCheck(query_rel, save_pgace); if (qplan == NULL) elog(ERROR, "SPI_prepare returned %d for %s", SPI_result, querystr); diff -rpNU3 base/src/backend/utils/cache/syscache.c pgace/src/backend/utils/cache/syscache.c --- base/src/backend/utils/cache/syscache.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/utils/cache/syscache.c 2008-01-08 01:39:49.000000000 +0900 @@ -39,6 +39,7 @@ #include "catalog/pg_opfamily.h" #include "catalog/pg_proc.h" #include "catalog/pg_rewrite.h" +#include "catalog/pg_security.h" #include "catalog/pg_statistic.h" #include "catalog/pg_ts_config.h" #include "catalog/pg_ts_config_map.h" @@ -676,7 +677,31 @@ static const struct cachedesc cacheinfo[ 0 }, 1024 - } + }, + {SecurityRelationId, /*SECURITYOID */ + SecurityOidIndexId, + 0, + 1, + { + ObjectIdAttributeNumber, + 0, + 0, + 0 + }, + 128 + }, + {SecurityRelationId, /* SECURITYLABEL */ + SecuritySeclabelIndexId, + 0, + 1, + { + Anum_pg_security_seclabel, + 0, + 0, + 0 + }, + 128 + }, }; static CatCache *SysCache[ diff -rpNU3 base/src/backend/utils/fmgr/dfmgr.c pgace/src/backend/utils/fmgr/dfmgr.c --- base/src/backend/utils/fmgr/dfmgr.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/utils/fmgr/dfmgr.c 2008-01-08 01:39:49.000000000 +0900 @@ -22,6 +22,7 @@ #include "port/dynloader/win32.h" #endif #include "miscadmin.h" +#include "security/pgace.h" #include "utils/dynamic_loader.h" #include "utils/hsearch.h" @@ -73,7 +74,7 @@ char *Dynamic_library_path; static void *internal_load_library(const char *libname); static void internal_unload_library(const char *libname); static bool file_exists(const char *name); -static char *expand_dynamic_library_name(const char *name); +//static char *expand_dynamic_library_name(const char *name); static void check_restricted_library_name(const char *name); static char *substitute_libpath_macro(const char *name); static char *find_in_dynamic_libpath(const char *basename); @@ -106,6 +107,9 @@ load_external_function(char *filename, c /* Expand the possibly-abbreviated filename to an exact path name */ fullname = expand_dynamic_library_name(filename); + /* PGACE: check whether the module can be loaded, or not */ + pgaceLoadSharedModule(fullname); + /* Load the shared library, unless we already did */ lib_handle = internal_load_library(fullname); @@ -146,6 +150,9 @@ load_file(const char *filename, bool res /* Expand the possibly-abbreviated filename to an exact path name */ fullname = expand_dynamic_library_name(filename); + /* PGACE: check whether the module can be loaded, or not */ + pgaceLoadSharedModule(fullname); + /* Unload the library if currently loaded */ internal_unload_library(fullname); @@ -395,7 +402,7 @@ file_exists(const char *name) * * The result will always be freshly palloc'd. */ -static char * +char * expand_dynamic_library_name(const char *name) { bool have_slash; diff -rpNU3 base/src/backend/utils/init/postinit.c pgace/src/backend/utils/init/postinit.c --- base/src/backend/utils/init/postinit.c 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/backend/utils/init/postinit.c 2008-01-08 01:39:49.000000000 +0900 @@ -31,6 +31,7 @@ #include "pgstat.h" #include "postmaster/autovacuum.h" #include "postmaster/postmaster.h" +#include "security/pgace.h" #include "storage/backendid.h" #include "storage/fd.h" #include "storage/ipc.h" @@ -601,6 +602,9 @@ InitPostgres(const char *in_dbname, Oid if (!bootstrap) pgstat_bestart(); + /* PGACE: initialize access control extension facility */ + pgaceInitialize(bootstrap); + /* close the transaction we started above */ if (!bootstrap) CommitTransactionCommand(); diff -rpNU3 base/src/backend/utils/misc/guc.c pgace/src/backend/utils/misc/guc.c --- base/src/backend/utils/misc/guc.c 2008-02-03 01:11:28.000000000 +0900 +++ pgace/src/backend/utils/misc/guc.c 2008-02-03 01:18:48.000000000 +0900 @@ -54,6 +54,7 @@ #include "postmaster/postmaster.h" #include "postmaster/syslogger.h" #include "postmaster/walwriter.h" +#include "security/pgace.h" #include "storage/fd.h" #include "storage/freespace.h" #include "tcop/tcopprot.h" @@ -268,6 +269,7 @@ static int max_index_keys; static int max_identifier_length; static int block_size; static bool integer_datetimes; +static char *security_sysattr_name; /* should be static, but commands/variable.c needs to get at these */ char *role_string; @@ -2460,6 +2462,20 @@ static struct config_string ConfigureNam }, #endif /* USE_SSL */ + { + {"security_sysattr_name", PGC_INTERNAL, PRESET_OPTIONS, + gettext_noop("Shows the name of security attribute system column"), + NULL, + GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + }, + &security_sysattr_name, +#ifdef SECURITY_SYSATTR_NAME + SECURITY_SYSATTR_NAME, NULL, NULL, +#else + "undefined", NULL, NULL, +#endif + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL @@ -3300,6 +3316,8 @@ ResetAllOptions(void) { int i; + pgaceSetDatabaseParam("all", NULL); + for (i = 0; i < num_guc_variables; i++) { struct config_generic *gconf = guc_variables[i]; @@ -4982,6 +5000,7 @@ ExecSetVariableStmt(VariableSetStmt *stm { case VAR_SET_VALUE: case VAR_SET_CURRENT: + pgaceSetDatabaseParam(stmt->name, ExtractSetVariableArgs(stmt)); set_config_option(stmt->name, ExtractSetVariableArgs(stmt), (superuser() ? PGC_SUSET : PGC_USERSET), @@ -5039,6 +5058,7 @@ ExecSetVariableStmt(VariableSetStmt *stm break; case VAR_SET_DEFAULT: case VAR_RESET: + pgaceSetDatabaseParam(stmt->name, NULL); set_config_option(stmt->name, NULL, (superuser() ? PGC_SUSET : PGC_USERSET), @@ -5367,6 +5387,9 @@ EmitWarningsOnPlaceholders(const char *c void GetPGVariable(const char *name, DestReceiver *dest) { + /* PGACE: check get param permission */ + pgaceGetDatabaseParam(name); + if (guc_name_compare(name, "all") == 0) ShowAllGUCConfig(dest); else diff -rpNU3 base/src/include/access/htup.h pgace/src/include/access/htup.h --- base/src/include/access/htup.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/access/htup.h 2008-01-10 12:42:25.000000000 +0900 @@ -161,7 +161,7 @@ typedef HeapTupleHeaderData *HeapTupleHe #define HEAP_HASVARWIDTH 0x0002 /* has variable-width attribute(s) */ #define HEAP_HASEXTERNAL 0x0004 /* has external stored attribute(s) */ #define HEAP_HASOID 0x0008 /* has an object-id field */ -/* bit 0x0010 is available */ +#define HEAP_HASSECURITY 0x0010 /* has an security attribute field */ #define HEAP_COMBOCID 0x0020 /* t_cid is a combo cid */ #define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */ #define HEAP_XMAX_SHARED_LOCK 0x0080 /* xmax is shared locker */ @@ -347,6 +347,28 @@ do { \ (tup)->t_infomask2 = ((tup)->t_infomask2 & ~HEAP_NATTS_MASK) | (natts) \ ) +#define HeapTupleHeaderGetSecurity(tup) \ + ( \ + ((tup)->t_infomask & HEAP_HASSECURITY) \ + ? (*((Oid *)((char *)(tup) + (tup)->t_hoff \ + - (((tup)->t_infomask & HEAP_HASOID) ? sizeof(Oid) : 0) \ + - sizeof(Oid)))) \ + : InvalidOid \ + ) + +#define HeapTupleHeaderSetSecurity(tup, security) \ + do { \ + Assert((tup)->t_infomask & HEAP_HASSECURITY); \ + *((Oid *)((char *)(tup) + (tup)->t_hoff \ + - (((tup)->t_infomask & HEAP_HASOID) ? sizeof(Oid) : 0) \ + - sizeof(Oid))) = (security); \ + } while(0) + +#define HeapTupleGetSecurity(tuple) \ + HeapTupleHeaderGetSecurity((tuple)->t_data) + +#define HeapTupleSetSecurity(tuple, security) \ + HeapTupleHeaderSetSecurity((tuple)->t_data, (security)) /* * BITMAPLEN(NATTS) - @@ -402,7 +424,12 @@ do { \ #define MaxTransactionIdAttributeNumber (-5) #define MaxCommandIdAttributeNumber (-6) #define TableOidAttributeNumber (-7) +#ifdef SECURITY_SYSATTR_NAME +#define SecurityAttributeNumber (-8) +#define FirstLowInvalidHeapAttributeNumber (-9) +#else #define FirstLowInvalidHeapAttributeNumber (-8) +#endif /* diff -rpNU3 base/src/include/catalog/heap.h pgace/src/include/catalog/heap.h --- base/src/include/catalog/heap.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/catalog/heap.h 2008-01-08 01:39:49.000000000 +0900 @@ -52,7 +52,8 @@ extern Oid heap_create_with_catalog(cons int oidinhcount, OnCommitAction oncommit, Datum reloptions, - bool allow_system_table_mods); + bool allow_system_table_mods, + List *pgace_attr_list); extern void heap_drop_with_catalog(Oid relid); @@ -65,7 +66,8 @@ extern List *heap_truncate_find_FKs(List extern void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, - Datum reloptions); + Datum reloptions, + List *pgace_attr_list); extern List *AddRelationRawConstraints(Relation rel, List *rawColDefaults, diff -rpNU3 base/src/include/catalog/indexing.h pgace/src/include/catalog/indexing.h --- base/src/include/catalog/indexing.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/catalog/indexing.h 2008-01-08 01:39:49.000000000 +0900 @@ -252,6 +252,11 @@ DECLARE_UNIQUE_INDEX(pg_type_oid_index, DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, on pg_type using btree(typname name_ops, typnamespace oid_ops)); #define TypeNameNspIndexId 2704 +DECLARE_UNIQUE_INDEX(pg_security_oid_index, 3401, on pg_security using btree(oid oid_ops)); +#define SecurityOidIndexId 3401 +DECLARE_UNIQUE_INDEX(pg_security_seclabel_index, 3402, on pg_security using btree(seclabel text_ops)); +#define SecuritySeclabelIndexId 3402 + /* last step of initialization script: build the indexes declared above */ BUILD_INDICES diff -rpNU3 base/src/include/catalog/pg_attribute.h pgace/src/include/catalog/pg_attribute.h --- base/src/include/catalog/pg_attribute.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/catalog/pg_attribute.h 2008-01-08 01:39:49.000000000 +0900 @@ -282,6 +282,7 @@ DATA(insert ( 1247 cmin 29 0 4 -4 0 DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 SECURITY_SYSATTR_NAME 3403 0 4 -8 0 -1 -1 t p i t f f t 0)); /* ---------------- * pg_proc @@ -338,6 +339,7 @@ DATA(insert ( 1255 cmin 29 0 4 -4 0 DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1255 SECURITY_SYSATTR_NAME 3403 0 4 -8 0 -1 -1 t p i t f f t 0)); /* ---------------- * pg_attribute @@ -386,6 +388,7 @@ DATA(insert ( 1249 cmin 29 0 4 -4 0 DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1249 SECURITY_SYSATTR_NAME 3403 0 4 -8 0 -1 -1 t p i t f f t 0)); /* ---------------- * pg_class @@ -454,6 +457,7 @@ DATA(insert ( 1259 cmin 29 0 4 -4 0 DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1259 SECURITY_SYSATTR_NAME 3403 0 4 -8 0 -1 -1 t p i t f f t 0)); /* ---------------- * pg_index diff -rpNU3 base/src/include/catalog/pg_cast.h pgace/src/include/catalog/pg_cast.h --- base/src/include/catalog/pg_cast.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/catalog/pg_cast.h 2008-01-08 01:39:49.000000000 +0900 @@ -331,4 +331,10 @@ DATA(insert ( 1560 1560 1685 i )); DATA(insert ( 1562 1562 1687 i )); DATA(insert ( 1700 1700 1703 i )); +/* + * Security Label to/from text representation + */ +DATA(insert (25 3403 3408 i)); +DATA(insert (3403 25 3409 i)); + #endif /* PG_CAST_H */ diff -rpNU3 base/src/include/catalog/pg_proc.h pgace/src/include/catalog/pg_proc.h --- base/src/include/catalog/pg_proc.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/catalog/pg_proc.h 2008-01-08 01:39:49.000000000 +0900 @@ -4113,6 +4113,16 @@ DESCR("I/O"); DATA(insert OID = 2963 ( uuid_hash PGNSP PGUID 12 1 0 f f t f i 1 23 "2950" _null_ _null_ _null_ uuid_hash - _null_ _null_ )); DESCR("hash"); +/* PostgreSQL Access Control Extension related functions */ +DATA(insert OID = 3404 ( security_label_in PGNSP PGUID 12 1 0 f f t f i 1 3403 "2275" _null_ _null_ _null_ security_label_in - _null_ _null_ )); +DATA(insert OID = 3405 ( security_label_out PGNSP PGUID 12 1 0 f f t f i 1 2275 "3403" _null_ _null_ _null_ security_label_out - _null_ _null_ )); +DATA(insert OID = 3406 ( security_label_raw_in PGNSP PGUID 12 1 0 f f t f i 1 3403 "2275" _null_ _null_ _null_ security_label_raw_in - _null_ _null_ )); +DATA(insert OID = 3407 ( security_label_raw_out PGNSP PGUID 12 1 0 f f t f i 1 2275 "3403" _null_ _null_ _null_ security_label_raw_out - _null_ _null_ )); +DATA(insert OID = 3408 ( text_to_security_label PGNSP PGUID 12 1 0 f f t f i 1 3403 "25" _null_ _null_ _null_ text_to_security_label - _null_ _null_ )); +DATA(insert OID = 3409 ( security_label_to_text PGNSP PGUID 12 1 0 f f t f i 1 25 "3403" _null_ _null_ _null_ security_label_to_text - _null_ _null_ )); +DATA(insert OID = 3410 ( lo_get_security PGNSP PGUID 12 1 0 f f t f v 1 3403 "26" _null_ _null_ _null_ lo_get_security - _null_ _null_ )); +DATA(insert OID = 3411 ( lo_set_security PGNSP PGUID 12 1 0 f f t f v 2 16 "26 3403" _null_ _null_ _null_ lo_set_security - _null_ _null_ )); + /* enum related procs */ DATA(insert OID = 3504 ( anyenum_in PGNSP PGUID 12 1 0 f f t f i 1 3500 "2275" _null_ _null_ _null_ anyenum_in - _null_ _null_ )); DESCR("I/O"); @@ -4460,7 +4470,8 @@ extern Oid ProcedureCreate(const char *p Datum parameterNames, Datum proconfig, float4 procost, - float4 prorows); + float4 prorows, + void *pgace_item); extern bool function_parse_error_transpose(const char *prosrc); diff -rpNU3 base/src/include/catalog/pg_security.h pgace/src/include/catalog/pg_security.h --- base/src/include/catalog/pg_security.h 1970-01-01 09:00:00.000000000 +0900 +++ pgace/src/include/catalog/pg_security.h 2007-09-21 01:08:03.000000000 +0900 @@ -0,0 +1,31 @@ +/* + * src/include/catalog/pg_security.h + * Definition of the security label relation (pg_security) + * + * Copyright (c) 2006 - 2007 KaiGai Kohei + */ +#ifndef PG_SECURITY_H +#define PG_SECURITY_H + +#define SecurityRelationId 3400 + +CATALOG(pg_security,3400) BKI_SHARED_RELATION +{ + text seclabel; /* text representation of security label */ +} FormData_pg_security; + +/* ---------------- + * Form_pg_security corresponds to a pointer to a tuple with + * the format of pg_security relation. + * ---------------- + */ +typedef FormData_pg_security *Form_pg_security; + +/* ---------------- + * compiler constants for pg_selinux + * ---------------- + */ +#define Natts_pg_security 1 +#define Anum_pg_security_seclabel 1 + +#endif /* PG_SELINUX_H */ diff -rpNU3 base/src/include/catalog/pg_type.h pgace/src/include/catalog/pg_type.h --- base/src/include/catalog/pg_type.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/catalog/pg_type.h 2008-01-08 01:39:49.000000000 +0900 @@ -611,6 +611,9 @@ DATA(insert OID = 2283 ( anyelement PGN #define ANYELEMENTOID 2283 DATA(insert OID = 2776 ( anynonarray PGNSP PGUID 4 t p t \054 0 0 0 anynonarray_in anynonarray_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define ANYNONARRAYOID 2776 +DATA(insert OID = 3403 ( security_label PGNSP PGUID 4 t b t \054 0 0 0 security_label_in security_label_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DESCR("Security Label Identifier for PGACE"); +#define SECLABELOID 3403 DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define ANYENUMOID 3500 diff -rpNU3 base/src/include/executor/tuptable.h pgace/src/include/executor/tuptable.h --- base/src/include/executor/tuptable.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/executor/tuptable.h 2008-01-08 01:39:49.000000000 +0900 @@ -118,6 +118,7 @@ typedef struct TupleTableSlot MinimalTuple tts_mintuple; /* set if it's a minimal tuple, else NULL */ HeapTupleData tts_minhdr; /* workspace if it's a minimal tuple */ long tts_off; /* saved state for slot_deform_tuple */ + Oid tts_security; /* pgace security system attribute */ } TupleTableSlot; /* @@ -139,6 +140,12 @@ typedef TupleTableData *TupleTable; #define TupIsNull(slot) \ ((slot) == NULL || (slot)->tts_isempty) +/* + * PGACE: HeapTupleStoreSecurityFromSlot + */ +#define HeapTupleStoreSecurityFromSlot(tuple, slot) \ + HeapTupleSetSecurity((tuple), (slot)->tts_security) + /* in executor/execTuples.c */ extern TupleTable ExecCreateTupleTable(int tableSize); extern void ExecDropTupleTable(TupleTable table, bool shouldFree); diff -rpNU3 base/src/include/fmgr.h pgace/src/include/fmgr.h --- base/src/include/fmgr.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/fmgr.h 2008-01-08 01:39:49.000000000 +0900 @@ -52,6 +52,9 @@ typedef struct FmgrInfo void *fn_extra; /* extra space for use by handler */ MemoryContext fn_mcxt; /* memory context to store fn_extra in */ fmNodePtr fn_expr; /* expression parse tree for call, or NULL */ + + PGFunction fn_pgace_addr; /* PGACE opaque addr field */ + Datum fn_pgace_data; /* PGACE opaque data field */ } FmgrInfo; /* @@ -511,6 +514,7 @@ extern Oid get_call_expr_argtype(fmNodeP */ extern char *Dynamic_library_path; +extern char *expand_dynamic_library_name(const char *name); extern PGFunction load_external_function(char *filename, char *funcname, bool signalNotFound, void **filehandle); extern PGFunction lookup_external_function(void *filehandle, char *funcname); diff -rpNU3 base/src/include/libpq/be-fsstubs.h pgace/src/include/libpq/be-fsstubs.h --- base/src/include/libpq/be-fsstubs.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/libpq/be-fsstubs.h 2008-01-08 01:39:49.000000000 +0900 @@ -36,6 +36,9 @@ extern Datum lo_tell(PG_FUNCTION_ARGS); extern Datum lo_unlink(PG_FUNCTION_ARGS); extern Datum lo_truncate(PG_FUNCTION_ARGS); +extern Datum lo_get_security(PG_FUNCTION_ARGS); +extern Datum lo_set_security(PG_FUNCTION_ARGS); + /* * These are not fmgr-callable, but are available to C code. * Probably these should have had the underscore-free names, diff -rpNU3 base/src/include/nodes/parsenodes.h pgace/src/include/nodes/parsenodes.h --- base/src/include/nodes/parsenodes.h 2008-03-19 09:48:23.000000000 +0900 +++ pgace/src/include/nodes/parsenodes.h 2008-03-19 10:08:35.000000000 +0900 @@ -131,6 +131,7 @@ typedef struct Query Node *setOperations; /* set-operation tree if this is top level of * a UNION/INTERSECT/EXCEPT query */ + Node *pgaceItem; /* PGACE: an opaque item for security purpose */ } Query; @@ -391,6 +392,7 @@ typedef struct ColumnDef Node *raw_default; /* default value (untransformed parse tree) */ char *cooked_default; /* nodeToString representation */ List *constraints; /* other constraints on column */ + Node *pgaceItem; /* PGACE: security attribute */ } ColumnDef; /* @@ -917,7 +919,8 @@ typedef enum AlterTableType AT_EnableReplicaRule, /* ENABLE REPLICA RULE name */ AT_DisableRule, /* DISABLE RULE name */ AT_AddInherit, /* INHERIT parent */ - AT_DropInherit /* NO INHERIT parent */ + AT_DropInherit, /* NO INHERIT parent */ + AT_SetSecurityLabel, /* PGACE: set security label */ } AlterTableType; typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ @@ -1108,6 +1111,7 @@ typedef struct CreateStmt List *options; /* options from WITH clause */ OnCommitAction oncommit; /* what do we do at COMMIT? */ char *tablespacename; /* table space to use, or NULL */ + Node *pgaceItem; /* PGACE: security attribute */ } CreateStmt; /* ---------- diff -rpNU3 base/src/include/nodes/plannodes.h pgace/src/include/nodes/plannodes.h --- base/src/include/nodes/plannodes.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/nodes/plannodes.h 2008-01-08 01:39:49.000000000 +0900 @@ -73,6 +73,8 @@ typedef struct PlannedStmt List *relationOids; /* OIDs of relations the plan depends on */ int nParamExec; /* number of PARAM_EXEC Params used */ + + Node *pgaceItem; /* PGACE: an opaque item for security purpose */ } PlannedStmt; /* macro for fetching the Plan associated with a SubPlan node */ diff -rpNU3 base/src/include/pg_config.h.in pgace/src/include/pg_config.h.in --- base/src/include/pg_config.h.in 2008-01-28 16:06:37.000000000 +0900 +++ pgace/src/include/pg_config.h.in 2008-01-28 16:14:33.000000000 +0900 @@ -637,6 +637,9 @@ your system. */ #undef PTHREAD_CREATE_JOINABLE +/* The name of security attribute. */ +#undef SECURITY_SYSATTR_NAME + /* The size of a `size_t', as computed by sizeof. */ #undef SIZEOF_SIZE_T diff -rpNU3 base/src/include/security/pgace.h pgace/src/include/security/pgace.h --- base/src/include/security/pgace.h 1970-01-01 09:00:00.000000000 +0900 +++ pgace/src/include/security/pgace.h 2008-02-01 20:22:14.000000000 +0900 @@ -0,0 +1,147 @@ +/* + * include/security/pgace.h + * headers for PostgreSQL Access Control Extensions (PGACE) + * Copyright 2007 KaiGai Kohei + */ +#ifndef PGACE_H +#define PGACE_H + +#include "access/htup.h" +#include "commands/trigger.h" +#include "executor/execdesc.h" +#include "nodes/parsenodes.h" +#include "utils/builtins.h" +#include "utils/rel.h" + +/* + * SECURITY_SYSATTR_NAME is the name of system column name + * for security attribute, defined in pg_config.h + * If it is not defined, security attribute support is disabled + * + * see, src/include/pg_config.h + */ + +/****************************************************************** + * Initialize / Finalize related hooks + ******************************************************************/ +extern Size pgaceShmemSize(void); +extern void pgaceInitialize(bool is_bootstrap); +extern bool pgaceInitializePostmaster(void); +extern void pgaceFinalizePostmaster(void); + +/****************************************************************** + * SQL proxy hooks + ******************************************************************/ +extern List *pgaceProxyQuery(List *queryList); +extern void pgacePortalStart(Portal portal); +extern void pgaceExecutorStart(QueryDesc *queryDesc, int eflags); + +/****************************************************************** + * HeapTuple modification hooks + ******************************************************************/ +extern bool pgaceHeapTupleInsert(Relation rel, HeapTuple tuple, + bool is_internal, bool with_returning); +extern bool pgaceHeapTupleUpdate(Relation rel, ItemPointer otid, HeapTuple newtup, + bool is_internal, bool with_returning); +extern bool pgaceHeapTupleDelete(Relation rel, ItemPointer otid, + bool is_internal, bool with_returning); + +/****************************************************************** + * Extended SQL statement hooks + ******************************************************************/ +extern DefElem *pgaceGramSecurityItem(char *defname, char *value); +extern bool pgaceIsGramSecurityItem(DefElem *defel); +extern void pgaceGramCreateRelation(Relation rel, HeapTuple tuple, DefElem *defel); +extern void pgaceGramCreateAttribute(Relation rel, HeapTuple tuple, DefElem *defel); +extern void pgaceGramAlterRelation(Relation rel, HeapTuple tuple, DefElem *defel); +extern void pgaceGramAlterAttribute(Relation rel, HeapTuple tuple, DefElem *defel); +extern void pgaceGramCreateDatabase(Relation rel, HeapTuple tuple, DefElem *defel); +extern void pgaceGramAlterDatabase(Relation rel, HeapTuple tuple, DefElem *defel); +extern void pgaceGramCreateFunction(Relation rel, HeapTuple tuple, DefElem *defel); +extern void pgaceGramAlterFunction(Relation rel, HeapTuple tuple, DefElem *defel); + +/****************************************************************** + * DATABASE related hooks + ******************************************************************/ +extern void pgaceSetDatabaseParam(const char *name, char *argstring); +extern void pgaceGetDatabaseParam(const char *name); + +/****************************************************************** + * FUNCTION related hooks + ******************************************************************/ +extern void pgaceCallFunction(FmgrInfo *finfo); +extern bool pgaceCallFunctionTrigger(FmgrInfo *finfo, TriggerData *tgdata); +extern void pgaceCallFunctionFastPath(FmgrInfo *finfo); +extern Datum pgacePreparePlanCheck(Relation rel); +extern void pgaceRestorePlanCheck(Relation rel, Datum pgace_saved); + +/****************************************************************** + * TABLE related hooks + ******************************************************************/ +extern void pgaceLockTable(Oid relid); + +/****************************************************************** + * COPY TO/COPY FROM statement hooks + ******************************************************************/ +extern void pgaceCopyTable(Relation rel, List *attNumList, bool isFrom); +extern bool pgaceCopyToTuple(Relation rel, List *attNumList, HeapTuple tuple); + +/****************************************************************** + * Loadable shared library module hooks + ******************************************************************/ +extern void pgaceLoadSharedModule(const char *filename); + +/****************************************************************** + * Binary Large Object (BLOB) hooks + ******************************************************************/ +extern void pgaceLargeObjectGetSecurity(HeapTuple tuple); +extern void pgaceLargeObjectSetSecurity(HeapTuple tuple, Oid lo_security); +extern void pgaceLargeObjectCreate(Relation rel, HeapTuple tuple); +extern void pgaceLargeObjectDrop(Relation rel, HeapTuple tuple); +extern void pgaceLargeObjectRead(Relation rel, HeapTuple tuple); +extern void pgaceLargeObjectWrite(Relation rel, HeapTuple newtup, HeapTuple oldtup); +extern void pgaceLargeObjectTruncate(Relation rel, Oid loid, HeapTuple headtup); +extern void pgaceLargeObjectImport(int fd); +extern void pgaceLargeObjectExport(int fd, Oid loid); + +/****************************************************************** + * Security Label hooks + ******************************************************************/ +extern char *pgaceSecurityLabelIn(char *seclabel); +extern char *pgaceSecurityLabelOut(char *seclabel); +extern char *pgaceSecurityLabelCheckValid(char *seclabel); +extern char *pgaceSecurityLabelOfLabel(char *new_label); + +/****************************************************************** + * Extended node type hooks + ******************************************************************/ +extern Node *pgaceCopyObject(Node *orig); +extern bool pgaceOutObject(StringInfo str, Node *node); +extern void *pgaceReadObject(char *token); + +/****************************************************************** + * PGACE common facilities (not a hooks) + ******************************************************************/ +/* Security attribute system column support */ +extern bool pgaceIsSecuritySystemColumn(int attrno); +extern void pgaceFetchSecurityAttribute(JunkFilter *junkfilter, TupleTableSlot *slot, Oid *tts_security); +extern void pgaceTransformSelectStmt(List *targetList); +extern void pgaceTransformInsertStmt(List **p_icolumns, List **p_attrnos, List *targetList); + +/* Extended SQL statements related */ +extern List *pgaceRelationAttrList(CreateStmt *stmt); +extern void pgaceCreateRelationCommon(Relation rel, HeapTuple tuple, List *pgace_attr_list); +extern void pgaceCreateAttributeCommon(Relation rel, HeapTuple tuple, List *pgace_attr_list); +extern void pgaceAlterRelationCommon(Relation rel, AlterTableCmd *cmd); + +/* SQL functions */ +extern Datum security_label_in(PG_FUNCTION_ARGS); +extern Datum security_label_out(PG_FUNCTION_ARGS); +extern Datum security_label_raw_in(PG_FUNCTION_ARGS); +extern Datum security_label_raw_out(PG_FUNCTION_ARGS); +extern Datum text_to_security_label(PG_FUNCTION_ARGS); +extern Datum security_label_to_text(PG_FUNCTION_ARGS); +extern Datum lo_get_security(PG_FUNCTION_ARGS); +extern Datum lo_set_security(PG_FUNCTION_ARGS); + +#endif // PGACE_H diff -rpNU3 base/src/include/utils/syscache.h pgace/src/include/utils/syscache.h --- base/src/include/utils/syscache.h 2008-01-07 23:51:33.000000000 +0900 +++ pgace/src/include/utils/syscache.h 2008-01-08 01:39:49.000000000 +0900 @@ -76,6 +76,8 @@ #define TSTEMPLATEOID 45 #define TYPENAMENSP 46 #define TYPEOID 47 +#define SECURITYOID 48 +#define SECURITYLABEL 49 extern void InitCatalogCache(void); extern void InitCatalogCachePhase2(void);