The attached patch provides plugin modules a hook just after object
creation time. In typical use cases, it enables to assign default
security labels on object creation by the external security providers.

As Robert suggested before, it provides a generic purpose main hook.
It takes an enum of ObjectAccessType which informs plugins what kind
of accesses are required, and identifier of the object to be referenced.
But, in this version, no additional information, such as new name in
ALTER xxx RENAME TO, are not supported.

The ObjectAccessType is defined as follows:

  typedef enum ObjectAccessType {
    OAT_POST_CREATE,    /* Post creation fixups; such as security labeling */
  } ObjectAccessType;

We will support more complete kind of access types in the future version,
however, we focus on default labeling rather than DDL permissions right
now, so only OAT_POST_CREATE is defined here.
Perhaps, we will add OAT_ALTER, OAT_DROP, OAT_COMMENT and so on.

In this patch, I put hooks on the place just after creation of database
objects that we can assign security labels. (schema, relation, attribute,
procedure, language, type, large object)

However, I didn't touch or move CommandCounterIncrement() yet, although
we had a long discussion MVCC visibility of new object.
Because I'm not clear whether it is really preferable to inject CCIs
onto random points such as TypeCreate() or ProcedureCreate() under
development of the version killed by myself.
(In other words, it was simply ugly...)

At least, we can see the new entries with SnapshotSelf, although we will
pay performance penalty. If so, it is an idea not to touch anything
related to CCIs.
The purpose of post creation hooks are assignment of default security
labels, not DDL permissions. So, it is not a bad idea not to touch
routines related to CCIs in the earlier version of external security
provider.

In this patch, we put InvokeObjectAccessHook0 on the following functions.

- heap_create_with_catalog() for relations/attributes
- ATExecAddColumn() for attributes
- NamespaceCreate() for schemas
- ProcedureCreate() for aggregates/functions
- TypeCreate() and TypeShellMake() for types
- create_proc_lang() for procedural languages
- inv_create() for large objects

Thanks,
-- 
KaiGai Kohei <kai...@ak.jp.nec.com>
*** a/src/backend/catalog/heap.c
--- b/src/backend/catalog/heap.c
***************
*** 61,66 ****
--- 61,67 ----
  #include "storage/freespace.h"
  #include "storage/smgr.h"
  #include "utils/acl.h"
+ #include "utils/esp.h"
  #include "utils/builtins.h"
  #include "utils/fmgroids.h"
  #include "utils/inval.h"
***************
*** 1189,1194 **** heap_create_with_catalog(const char *relname,
--- 1190,1202 ----
  	}
  
  	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the relation.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							RelationRelationId, relid, 0);
+ 
+ 	/*
  	 * Store any supplied constraints and defaults.
  	 *
  	 * NB: this may do a CommandCounterIncrement and rebuild the relcache
*** a/src/backend/catalog/pg_namespace.c
--- b/src/backend/catalog/pg_namespace.c
***************
*** 19,24 ****
--- 19,25 ----
  #include "catalog/indexing.h"
  #include "catalog/pg_namespace.h"
  #include "utils/builtins.h"
+ #include "utils/esp.h"
  #include "utils/rel.h"
  #include "utils/syscache.h"
  
***************
*** 75,79 **** NamespaceCreate(const char *nspName, Oid ownerId)
--- 76,87 ----
  	/* Record dependency on owner */
  	recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
  
+ 	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the new namespace.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							NamespaceRelationId, nspoid, 0);
+ 
  	return nspoid;
  }
*** a/src/backend/catalog/pg_proc.c
--- b/src/backend/catalog/pg_proc.c
***************
*** 32,37 ****
--- 32,38 ----
  #include "tcop/pquery.h"
  #include "tcop/tcopprot.h"
  #include "utils/acl.h"
+ #include "utils/esp.h"
  #include "utils/builtins.h"
  #include "utils/lsyscache.h"
  #include "utils/syscache.h"
***************
*** 614,619 **** ProcedureCreate(const char *procedureName,
--- 615,627 ----
  							  nnewmembers, newmembers);
  	}
  
+ 	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the new function.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							ProcedureRelationId, retval, 0);
+ 
  	heap_freetuple(tup);
  
  	heap_close(rel, RowExclusiveLock);
*** a/src/backend/catalog/pg_type.c
--- b/src/backend/catalog/pg_type.c
***************
*** 26,31 ****
--- 26,32 ----
  #include "miscadmin.h"
  #include "parser/scansup.h"
  #include "utils/acl.h"
+ #include "utils/esp.h"
  #include "utils/builtins.h"
  #include "utils/fmgroids.h"
  #include "utils/lsyscache.h"
***************
*** 156,161 **** TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
--- 157,169 ----
  								 false);
  
  	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the new shell type.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							TypeRelationId, typoid, 0);
+ 
+ 	/*
  	 * clean up and return the type-oid
  	 */
  	heap_freetuple(tup);
***************
*** 456,461 **** TypeCreate(Oid newTypeOid,
--- 464,476 ----
  								 rebuildDeps);
  
  	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the new type.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							TypeRelationId, typeObjectId, 0);
+ 
+ 	/*
  	 * finish up
  	 */
  	heap_close(pg_type_desc, RowExclusiveLock);
*** a/src/backend/commands/proclang.c
--- b/src/backend/commands/proclang.c
***************
*** 31,36 ****
--- 31,37 ----
  #include "parser/parser.h"
  #include "utils/acl.h"
  #include "utils/builtins.h"
+ #include "utils/esp.h"
  #include "utils/fmgroids.h"
  #include "utils/lsyscache.h"
  #include "utils/rel.h"
***************
*** 426,431 **** create_proc_lang(const char *languageName, bool replace,
--- 427,440 ----
  	}
  
  	heap_close(rel, RowExclusiveLock);
+ 
+ 	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the new procedural language.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							LanguageRelationId,
+ 							myself.objectId, 0);
  }
  
  /*
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 68,73 ****
--- 68,74 ----
  #include "storage/smgr.h"
  #include "utils/acl.h"
  #include "utils/builtins.h"
+ #include "utils/esp.h"
  #include "utils/fmgroids.h"
  #include "utils/inval.h"
  #include "utils/lsyscache.h"
***************
*** 4024,4029 **** ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
--- 4025,4037 ----
  
  	heap_close(pgclass, RowExclusiveLock);
  
+ 	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the column.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							RelationRelationId, myrelid, newattnum);
+ 
  	/* Make the attribute's catalog entry visible */
  	CommandCounterIncrement();
  
*** a/src/backend/storage/large_object/inv_api.c
--- b/src/backend/storage/large_object/inv_api.c
***************
*** 44,49 ****
--- 44,50 ----
  #include "libpq/libpq-fs.h"
  #include "miscadmin.h"
  #include "storage/large_object.h"
+ #include "utils/esp.h"
  #include "utils/fmgroids.h"
  #include "utils/rel.h"
  #include "utils/resowner.h"
***************
*** 219,224 **** inv_create(Oid lobjId)
--- 220,232 ----
  							lobjId_new, GetUserId());
  
  	/*
+ 	 * If installed, ESP can assign initial properties (such as security
+ 	 * labels) of the new procedural language.
+ 	 */
+ 	InvokeObjectAccessHook0(OAT_POST_CREATE,
+ 							LargeObjectRelationId, lobjId_new, 0);
+ 
+ 	/*
  	 * Advance command counter to make new tuple visible to later operations.
  	 */
  	CommandCounterIncrement();
*** a/src/backend/utils/adt/Makefile
--- b/src/backend/utils/adt/Makefile
***************
*** 17,23 **** endif
  
  OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \
  	cash.o char.o date.o datetime.o datum.o domains.o \
! 	enum.o float.o format_type.o \
  	geo_ops.o geo_selfuncs.o int.o int8.o like.o lockfuncs.o \
  	misc.o nabstime.o name.o numeric.o numutils.o \
  	oid.o oracle_compat.o pseudotypes.o rowtypes.o \
--- 17,23 ----
  
  OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \
  	cash.o char.o date.o datetime.o datum.o domains.o \
! 	enum.o esp.o float.o format_type.o \
  	geo_ops.o geo_selfuncs.o int.o int8.o like.o lockfuncs.o \
  	misc.o nabstime.o name.o numeric.o numutils.o \
  	oid.o oracle_compat.o pseudotypes.o rowtypes.o \
*** /dev/null
--- b/src/backend/utils/adt/esp.c
***************
*** 0 ****
--- 1,70 ----
+ /*-------------------------------------------------------------------------
+  *
+  * esp.c
+  *		External security provider hooks and related routines.
+  *
+  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * IDENTIFICATION
+  *		src/backend/utils/adt/esp.c
+  *
+  *-------------------------------------------------------------------------
+  */
+ #include "postgres.h"
+ 
+ #include "nodes/pg_list.h"
+ #include "utils/esp.h"
+ #include "utils/memutils.h"
+ 
+ typedef struct
+ {
+ 	const char				   *provider_name;
+ 	check_object_access_type	security_hook;
+ } SecurityProvider;
+ 
+ static List *security_provider_list = NIL;
+ 
+ /*
+  * invoke_object_access_hook
+  *
+  * It invokes the main security hook with the supplied argument.
+  * If and when no external security providers are installed,
+  * it shall do nothing.
+  */
+ void
+ invoke_object_access_hook(ObjectAccessType access,
+ 						  Oid classId,
+ 						  Oid objectId,
+ 						  int subId)
+ {
+ 	ListCell   *cell;
+ 
+ 	foreach (cell, security_provider_list)
+ 	{
+ 		SecurityProvider   *provider = lfirst(cell);
+ 
+ 		if (provider->security_hook)
+ 			(*provider->security_hook)(access, classId, objectId, subId);
+ 	}
+ }
+ 
+ /*
+  * register_security_provider
+  *
+  * It allows to install plugin modules of external security providers
+  */
+ void
+ register_security_provider(const char *provider_name,
+ 						   check_object_access_type security_hook)
+ {
+ 	SecurityProvider   *provider;
+ 	MemoryContext		oldcxt;
+ 
+ 	oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+ 	provider = palloc(sizeof(SecurityProvider));
+ 	provider->provider_name = pstrdup(provider_name);
+ 	provider->security_hook = security_hook;
+ 	security_provider_list = lappend(security_provider_list, provider);
+ 	MemoryContextSwitchTo(oldcxt);
+ }
*** /dev/null
--- b/src/include/utils/esp.h
***************
*** 0 ****
--- 1,42 ----
+ /*
+  * esp.h
+  *
+  * Definitions for external security providers
+  *
+  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  */
+ #ifndef	ESP_H
+ #define	ESP_H
+ 
+ typedef enum ObjectAccessType {
+ 	OAT_POST_CREATE,	/* Post creation fixups; such as security labeling */
+ } ObjectAccessType;
+ 
+ /*
+  * Definition of the main security hook type
+  */
+ typedef void (*check_object_access_type)(ObjectAccessType access,
+ 										 Oid classId,
+ 										 Oid objectId,
+ 										 int subId);
+ /*
+  * The main security hook to handle most of security events
+  */
+ extern void invoke_object_access_hook(ObjectAccessType access,
+ 									  Oid classId,
+ 									  Oid objectId,
+ 									  int subId);
+ /*
+  * Utility macros
+  */
+ #define InvokeObjectAccessHook0(access,classId,objectId,subId)			\
+ 	invoke_object_access_hook((access),(classId),(objectId),(subId))
+ 
+ /*
+  * An API to register security hooks
+  */
+ extern void register_security_provider(const char *provider,
+ 									   check_object_access_type security_hook);
+ 
+ #endif	/* ESP_H */
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to