pgsql-v9.1-security-label-2.v1.patch

application/octect-stream

Filename: pgsql-v9.1-security-label-2.v1.patch
Type: application/octect-stream
Part: 0
Message: security label support, part.2

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
Series: patch v9
File+
src/backend/commands/seclabel.c 169 0
src/backend/parser/gram.y 56 0
src/backend/tcop/utility.c 28 0
src/include/commands/seclabel.h 22 0
src/include/nodes/nodes.h 1 0
src/include/nodes/parsenodes.h 14 0
src/include/parser/kwlist.h 1 0
*** a/src/backend/commands/seclabel.c
--- b/src/backend/commands/seclabel.c
***************
*** 14,27 ****
--- 14,39 ----
  #include "access/heapam.h"
  #include "catalog/catalog.h"
  #include "catalog/indexing.h"
+ #include "catalog/namespace.h"
+ #include "catalog/pg_inherits_fn.h"
  #include "catalog/pg_seclabel.h"
  #include "commands/seclabel.h"
+ #include "miscadmin.h"
+ #include "parser/parse_clause.h"
+ #include "storage/lmgr.h"
+ #include "utils/acl.h"
  #include "utils/builtins.h"
  #include "utils/fmgroids.h"
+ #include "utils/lsyscache.h"
  #include "utils/rel.h"
  #include "utils/tqual.h"
  
  /*
+  * External security providers
+  */
+ check_relation_relabel_type check_relation_relabel_hook = NULL;
+ 
+ /*
   * GetLocalSecLabel
   *
   * It tries to look up a security label entry for the given OID of the
***************
*** 257,259 **** DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId)
--- 269,428 ----
  
  	DeleteLocalSecLabel(classOid, objOid, subId);
  }
+ 
+ /*
+  * ExecAlterRelationLabel
+  *
+  * It relabels a relation and its child tables.
+  */
+ static void
+ ExecAlterRelationLabel(RangeVar *relation, const char *attname,
+ 					   ObjectType objtype, const char *seclabel)
+ {
+ 	Oid			relOid = RangeVarGetRelid(relation, false);
+ 	bool		recurse = interpretInhOption(relation->inhOpt);
+ 	char		relkind;
+ 	List	   *child_oids;
+ 	List	   *child_numparents;
+ 	ListCell   *lo, *li;
+ 
+ 	/*
+ 	 * Sanity checks for relation types
+ 	 */
+ 	relkind = get_rel_relkind(relOid);
+ 	switch (objtype)
+ 	{
+ 		case OBJECT_TABLE:
+ 			Assert(attname == NULL);
+ 			if (relkind != RELKIND_RELATION &&
+ 				relkind != RELKIND_SEQUENCE &&
+ 				relkind != RELKIND_VIEW)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ 						 errmsg("\"%s\" is not a table, sequence or view",
+ 								relation->relname)));
+ 			break;
+ 
+ 		case OBJECT_SEQUENCE:
+ 			Assert(attname == NULL);
+ 			if (relkind != RELKIND_SEQUENCE)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ 						 errmsg("\"%s\" is not a sequence", relation->relname)));
+ 			break;
+ 
+ 		case OBJECT_VIEW:
+ 			Assert(attname == NULL);
+ 			if (relkind != RELKIND_VIEW)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ 						 errmsg("\"%s\" is not a view", relation->relname)));
+ 			break;
+ 
+ 		case OBJECT_COLUMN:
+ 			Assert(attname != NULL);
+ 			if (relkind != RELKIND_RELATION)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ 						 errmsg("\"%s.%s\" is not a column of tables",
+ 								relation->relname, attname)));
+ 			break;
+ 
+ 		default:
+ 			elog(ERROR, "unexpected object type %d", (int)objtype);
+ 			break;
+ 	}
+ 
+ 	/*
+ 	 * Build a list of relations to be altered.
+ 	 * Even if relation->inhOpt is not true, we make a dummy list
+ 	 * and lock the relation to simplify the logic.
+ 	 */
+ 	if (recurse)
+ 	{
+ 		child_oids = find_all_inheritors(relOid,
+ 										 AccessExclusiveLock,
+ 										 &child_numparents);
+ 	}
+ 	else
+ 	{
+ 		child_oids = list_make1_oid(relOid);
+ 		child_numparents = list_make1_int(0);
+ 		/* make sure the relation being already locked */
+ 		LockRelationOid(relOid, AccessExclusiveLock);
+ 	}
+ 
+ 	/*
+ 	 * Relabel each tables being listed
+ 	 */
+ 	forboth (lo, child_oids, li, child_numparents)
+ 	{
+ 		Oid			tableOid = lfirst_oid(lo);
+ 		Oid			numParents = lfirst_int(li);
+ 		Oid			namespaceOid = get_rel_namespace(tableOid);
+ 		AttrNumber	attnum = InvalidAttrNumber;
+ 
+ 		/*
+ 		 * Verify existence of attribute
+ 		 */
+ 		if (attname != NULL)
+ 		{
+ 			attnum = get_attnum(tableOid, attname);
+ 			if (attnum == InvalidAttrNumber)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_UNDEFINED_COLUMN),
+ 						 errmsg("column \"%s\" of relation \"%s\" does not exist",
+ 								attname, get_rel_name(tableOid))));
+ 		}
+ 		/*
+ 		 * Prevent to relabel system catalogs
+ 		 */
+ 		if (!allowSystemTableMods &&
+ 			(IsSystemNamespace(namespaceOid) || IsToastNamespace(namespaceOid)))
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 					 errmsg("permission denied: \"%s\" is a system catalog",
+ 							get_rel_name(tableOid))));
+ 		/*
+ 		 * Permission checks
+ 		 */
+ 		if (!pg_class_ownercheck(tableOid, GetUserId()))
+ 			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+ 						   get_rel_name(tableOid));
+ 
+ 		if (check_relation_relabel_hook)
+ 			(*check_relation_relabel_hook)(tableOid, attnum, seclabel,
+ 										   recurse, numParents);
+ 		/*
+ 		 * Do the actual relabeling
+ 		 */
+ 		SetSecurityLabel(RelationRelationId, tableOid, attnum, seclabel);
+ 	}
+ }
+ 
+ /*
+  * ExecAlterLabelStmt
+  *
+  * ALTER <thing> <name> SECURITY LABEL TO <seclabel> statement.
+  */
+ void
+ ExecAlterLabelStmt(AlterLabelStmt *stmt)
+ {
+ 	const char *seclabel = strVal(stmt->seclabel);
+ 
+ 	switch (stmt->objectType)
+ 	{
+ 		case OBJECT_TABLE:
+ 		case OBJECT_COLUMN:
+ 		case OBJECT_SEQUENCE:
+ 		case OBJECT_VIEW:
+ 			ExecAlterRelationLabel(stmt->relation, stmt->addname,
+ 								   stmt->objectType, seclabel);
+ 			break;
+ 
+ 		default:
+ 			elog(ERROR, "unrecognized object type: %d", (int)stmt->objectType);
+ 			break;
+ 	}
+ }
+ 
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 182,188 **** static TypeName *TableFuncTypeName(List *columns);
  
  %type <node>	stmt schema_stmt
  		AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
! 		AlterForeignServerStmt AlterGroupStmt
  		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
  		AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
  		AlterRoleStmt AlterRoleSetStmt
--- 182,188 ----
  
  %type <node>	stmt schema_stmt
  		AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
! 		AlterForeignServerStmt AlterGroupStmt AlterLabelStmt
  		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
  		AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
  		AlterRoleStmt AlterRoleSetStmt
***************
*** 422,427 **** static TypeName *TableFuncTypeName(List *columns);
--- 422,429 ----
  %type <str>		OptTableSpace OptConsTableSpace OptTableSpaceOwner
  %type <list>	opt_check_option
  
+ %type <value>	label_item
+ 
  %type <target>	xml_attribute_el
  %type <list>	xml_attribute_list xml_attributes
  %type <node>	xml_root_version opt_xml_root_standalone
***************
*** 498,504 **** static TypeName *TableFuncTypeName(List *columns);
  
  	KEY
  
! 	LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
  	LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
  	LOCATION LOCK_P LOGIN_P
  
--- 500,506 ----
  
  	KEY
  
! 	LABEL LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
  	LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
  	LOCATION LOCK_P LOGIN_P
  
***************
*** 652,657 **** stmt :
--- 654,660 ----
  			| AlterForeignServerStmt
  			| AlterFunctionStmt
  			| AlterGroupStmt
+ 			| AlterLabelStmt
  			| AlterObjectSchemaStmt
  			| AlterOwnerStmt
  			| AlterSeqStmt
***************
*** 6026,6031 **** AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
--- 6029,6084 ----
  				}
  		;
  
+ /*****************************************************************************
+  *
+  * ALTER THING name SECURITY LABEL TO label
+  *
+  *****************************************************************************/
+ 
+ AlterLabelStmt:	ALTER TABLE relation_expr label_item
+ 				{
+ 					AlterLabelStmt *n = makeNode(AlterLabelStmt);
+ 
+ 					n->objectType = OBJECT_TABLE;
+ 					n->relation = $3;
+ 					n->seclabel = $4;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER TABLE relation_expr ALTER opt_column ColId label_item
+ 				{
+ 					AlterLabelStmt *n = makeNode(AlterLabelStmt);
+ 
+ 					n->objectType = OBJECT_COLUMN;
+ 					n->relation = $3;
+ 					n->addname = $6;
+ 					n->seclabel = $7;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER SEQUENCE qualified_name label_item
+ 				{
+ 					AlterLabelStmt *n = makeNode(AlterLabelStmt);
+ 
+ 					n->objectType = OBJECT_SEQUENCE;
+ 					n->relation = $3;
+ 					n->seclabel = $4;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER VIEW qualified_name label_item
+ 				{
+ 					AlterLabelStmt *n = makeNode(AlterLabelStmt);
+ 
+ 					n->objectType = OBJECT_VIEW;
+ 					n->relation = $3;
+ 					n->seclabel = $4;
+ 					$$ = (Node *)n;
+ 				}
+ 			;
+ 
+ label_item:	SECURITY LABEL TO Sconst
+ 				{
+ 					$$ = makeString($4);
+ 				}
+ 			;
  
  /*****************************************************************************
   *
***************
*** 10921,10926 **** unreserved_keyword:
--- 10974,10980 ----
  			| INVOKER
  			| ISOLATION
  			| KEY
+ 			| LABEL
  			| LANGUAGE
  			| LARGE_P
  			| LAST_P
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 161,166 **** check_xact_readonly(Node *parsetree)
--- 161,167 ----
  		case T_AlterDatabaseSetStmt:
  		case T_AlterDomainStmt:
  		case T_AlterFunctionStmt:
+ 		case T_AlterLabelStmt:
  		case T_AlterRoleStmt:
  		case T_AlterRoleSetStmt:
  		case T_AlterObjectSchemaStmt:
***************
*** 696,701 **** standard_ProcessUtility(Node *parsetree,
--- 697,706 ----
  			ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
  			break;
  
+ 		case T_AlterLabelStmt:
+ 			ExecAlterLabelStmt((AlterLabelStmt *) parsetree);
+ 			break;
+ 
  		case T_AlterTableStmt:
  			{
  				List	   *stmts;
***************
*** 1760,1765 **** CreateCommandTag(Node *parsetree)
--- 1765,1789 ----
  			}
  			break;
  
+ 		case T_AlterLabelStmt:
+ 			switch (((AlterLabelStmt *) parsetree)->objectType)
+ 			{
+ 				case OBJECT_TABLE:
+ 				case OBJECT_COLUMN:
+ 					tag = "ALTER TABLE";
+ 					break;
+ 				case OBJECT_SEQUENCE:
+ 					tag = "ALTER SEQUENCE";
+ 					break;
+ 				case OBJECT_VIEW:
+ 					tag = "ALTER VIEW";
+ 					break;
+ 				default:
+ 					tag = "???";
+ 					break;
+ 			}
+ 			break;
+ 
  		case T_AlterTableStmt:
  			switch (((AlterTableStmt *) parsetree)->relkind)
  			{
***************
*** 2352,2357 **** GetCommandLogLevel(Node *parsetree)
--- 2376,2385 ----
  			lev = LOGSTMT_DDL;
  			break;
  
+ 		case T_AlterLabelStmt:
+ 			lev = LOGSTMT_DDL;
+ 			break;
+ 
  		case T_AlterTableStmt:
  			lev = LOGSTMT_DDL;
  			break;
*** a/src/include/commands/seclabel.h
--- b/src/include/commands/seclabel.h
***************
*** 9,14 ****
--- 9,31 ----
  #ifndef SECLABEL_H
  #define SECLABEL_H
  
+ #include "nodes/primnodes.h"
+ #include "nodes/parsenodes.h"
+ 
+ /*
+  * External security provider hooks
+  */
+ 
+ /*
+  * check_relation_relabel_hook
+  *
+  * It enables ESP module to make its access control decision on relabeling
+  * the relation/attribute. If violated, it can raise an error to prevent.
+  */
+ typedef void (*check_relation_relabel_type)(Oid, AttrNumber, const char *, bool, int);
+ 
+ extern check_relation_relabel_type check_relation_relabel_hook;
+ 
  /*
   * Internal APIs
   */
***************
*** 17,21 **** extern void  SetSecurityLabel(Oid classOid, Oid objOid, int4 subId,
  							  const char *seclabel);
  extern void  DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId);
  
! #endif	/* SECLABEL_H */
  
--- 34,42 ----
  							  const char *seclabel);
  extern void  DeleteSecurityLabel(Oid classOid, Oid objOid, int4 subId);
  
! /*
!  * Statement support
!  */
! extern void ExecAlterLabelStmt(AlterLabelStmt *stmt);
  
+ #endif	/* SECLABEL_H */
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
***************
*** 347,352 **** typedef enum NodeTag
--- 347,353 ----
  	T_AlterUserMappingStmt,
  	T_DropUserMappingStmt,
  	T_AlterTableSpaceOptionsStmt,
+ 	T_AlterLabelStmt,
  
  	/*
  	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 2073,2078 **** typedef struct AlterOwnerStmt
--- 2073,2092 ----
  	char	   *newowner;		/* the new owner */
  } AlterOwnerStmt;
  
+ /* ----------------------
+  *		ALTER object SECURITY LABEL TO Statement
+  * ----------------------
+  */
+ typedef struct AlterLabelStmt
+ {
+ 	NodeTag		type;
+ 	ObjectType	objectType;		/* OBJECT_TABLE, OBJECT_TYPE, etc */
+ 	RangeVar   *relation;		/* in case it's a table */
+ 	List	   *object;			/* in case it's some other object */
+ 	List	   *objarg;			/* argument types, if applicable */
+ 	char	   *addname;		/* additional name if needed */
+ 	Value	   *seclabel;		/* the new security label */
+ } AlterLabelStmt;
  
  /* ----------------------
   *		Create Rule Statement
*** a/src/include/parser/kwlist.h
--- b/src/include/parser/kwlist.h
***************
*** 208,213 **** PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD)
--- 208,214 ----
  PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD)
  PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD)
  PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)
+ PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD)
  PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)
  PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD)
  PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD)