sepostgresql/sepostgresql-pgace-8.3.0-2.patch
KaiGai Kohei fb8c5a3ba0 - BUGFIX: CREATE TABLE statement with explicit labeled columns
- BUGFIX: SELECT count(*) does not filter unallowed tuples
2008-03-02 08:10:12 +00:00

4090 lines
133 KiB
Diff

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-02-03 01:11:28.000000000 +0900
+++ pgace/src/backend/access/heap/heapam.c 2008-02-03 01:18:48.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"
@@ -1934,6 +1935,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);
}
@@ -2215,6 +2219,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,
@@ -2858,6 +2865,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-01-07 23:51:33.000000000 +0900
+++ pgace/src/backend/access/heap/tuptoaster.c 2008-01-10 12:42:25.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"
@@ -588,6 +589,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 */
@@ -837,6 +841,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,
@@ -988,6 +995,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,
@@ -1173,6 +1183,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-01-07 23:51:33.000000000 +0900
+++ pgace/src/backend/catalog/catalog.c 2008-01-08 01:39:49.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/async.c pgace/src/backend/commands/async.c
--- base/src/backend/commands/async.c 2008-01-07 23:51:33.000000000 +0900
+++ pgace/src/backend/commands/async.c 2008-01-08 01:39:49.000000000 +0900
@@ -85,6 +85,7 @@
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
+#include "security/pgace.h"
#include "storage/ipc.h"
#include "storage/sinval.h"
#include "tcop/tcopprot.h"
@@ -544,7 +545,8 @@ AtCommit_Notify(void)
rTuple = heap_modifytuple(lTuple, tdesc,
value, nulls, repl);
-
+ if (!pgaceHeapTupleUpdate(lRel, &lTuple->t_self, rTuple, true, false))
+ elog(ERROR, "could not update a tuple due to security reason");
/*
* We cannot use simple_heap_update here because the tuple
* could have been modified by an uncommitted transaction;
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-02-03 01:11:28.000000000 +0900
+++ pgace/src/backend/commands/tablecmds.c 2008-02-03 01:18:48.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-01-07 23:51:33.000000000 +0900
+++ pgace/src/backend/executor/execMain.c 2008-01-08 01:39:49.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-01-07 23:51:33.000000000 +0900
+++ pgace/src/backend/nodes/copyfuncs.c 2008-03-02 12:21:10.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;
}
@@ -3570,6 +3575,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-01-08 01:39:49.000000000 +0900
@@ -154,6 +154,7 @@ _readQuery(void)
READ_NODE_FIELD(limitCount);
READ_NODE_FIELD(rowMarks);
READ_NODE_FIELD(setOperations);
+ READ_NODE_FIELD(pgaceItem);
READ_DONE();
}
@@ -1126,8 +1127,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-01-07 23:51:33.000000000 +0900
+++ pgace/src/backend/parser/gram.y 2008-01-08 01:39:49.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 <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
%type <list> opt_check_option
+%type <defelt> OptSecurityItem SecurityItem
+
%type <target> xml_attribute_el
%type <list> xml_attribute_list xml_attributes
%type <node> xml_root_version opt_xml_root_standalone
@@ -1637,6 +1640,24 @@ alter_table_cmd:
n->def = (Node *) $3;
$$ = (Node *)n;
}
+ /* ALTER TABLE <relation> CONTEXT = '...' */
+ | SecurityItem
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_SetSecurityLabel;
+ n->name = NULL;
+ n->def = (Node *) $1;
+ $$ = (Node *) n;
+ }
+ /* ALTER TABLE <relation> ALTER [COLUMN] <colname> 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 <UDT> (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 2007-10-15 00:14:18.000000000 +0900
@@ -0,0 +1,28 @@
+#
+# src/backend/security/Makefile
+# Makefile for Security Purpose Extensions
+#
+# Copyright (c) 2006 - 2007 KaiGai Kohei <kaigai@kaigai.gr.jp>
+#
+ubdir = src/backend/security
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS := pgaceCommon.o
+
+OBJS += 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 <kaigai@kaigai.gr.jp>
+ */
+#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 <unistd.h>
+#include <sys/file.h>
+
+/*****************************************************************************
+ * 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 <tblname> [ALTER <colname>] 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-02-01 20:22:14.000000000 +0900
@@ -0,0 +1,619 @@
+/*
+ * src/backend/security/pgaceHooks.c
+ * Dummy functions of PostgreSQL Access Control Extension
+ * when no users enables the framework.
+ * Copyright 2007 KaiGai Kohei <kaigai@kaigai.gr.jp>
+ */
+#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 <parameter> string
+ * @value : given <value> 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;
+}
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-01-07 23:51:33.000000000 +0900
+++ pgace/src/backend/storage/large_object/inv_api.c 2008-02-01 20:22:14.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);
/*
@@ -632,6 +637,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);
@@ -675,6 +682,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);
@@ -754,6 +763,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-01-28 16:06:37.000000000 +0900
+++ pgace/src/backend/tcop/postgres.c 2008-01-28 16:14:33.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-01-28 16:06:37.000000000 +0900
+++ pgace/src/backend/utils/adt/ri_triggers.c 2008-01-28 16:14:33.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"
@@ -3185,6 +3186,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
@@ -3202,7 +3204,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 <kaigai@kaigai.gr.jp>
+ */
+#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-01-07 23:51:33.000000000 +0900
+++ pgace/src/include/nodes/parsenodes.h 2008-01-08 01:39:49.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 <kaigai@kaigai.gr.jp>
+ */
+#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);