mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			238 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* -------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * contrib/sepgsql/schema.c
 | 
						|
 *
 | 
						|
 * Routines corresponding to schema objects
 | 
						|
 *
 | 
						|
 * Copyright (c) 2010-2015, PostgreSQL Global Development Group
 | 
						|
 *
 | 
						|
 * -------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
#include "postgres.h"
 | 
						|
 | 
						|
#include "access/genam.h"
 | 
						|
#include "access/heapam.h"
 | 
						|
#include "access/htup_details.h"
 | 
						|
#include "access/sysattr.h"
 | 
						|
#include "catalog/dependency.h"
 | 
						|
#include "catalog/indexing.h"
 | 
						|
#include "catalog/pg_database.h"
 | 
						|
#include "catalog/pg_namespace.h"
 | 
						|
#include "commands/seclabel.h"
 | 
						|
#include "lib/stringinfo.h"
 | 
						|
#include "miscadmin.h"
 | 
						|
#include "utils/builtins.h"
 | 
						|
#include "utils/fmgroids.h"
 | 
						|
#include "utils/lsyscache.h"
 | 
						|
#include "utils/tqual.h"
 | 
						|
 | 
						|
#include "sepgsql.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * sepgsql_schema_post_create
 | 
						|
 *
 | 
						|
 * This routine assigns a default security label on a newly defined
 | 
						|
 * schema.
 | 
						|
 */
 | 
						|
void
 | 
						|
sepgsql_schema_post_create(Oid namespaceId)
 | 
						|
{
 | 
						|
	Relation	rel;
 | 
						|
	ScanKeyData skey;
 | 
						|
	SysScanDesc sscan;
 | 
						|
	HeapTuple	tuple;
 | 
						|
	char	   *tcontext;
 | 
						|
	char	   *ncontext;
 | 
						|
	const char *nsp_name;
 | 
						|
	ObjectAddress object;
 | 
						|
	Form_pg_namespace nspForm;
 | 
						|
	StringInfoData audit_name;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Compute a default security label when we create a new schema object
 | 
						|
	 * under the working database.
 | 
						|
	 *
 | 
						|
	 * XXX - uncoming version of libselinux supports to take object name to
 | 
						|
	 * handle special treatment on default security label; such as special
 | 
						|
	 * label on "pg_temp" schema.
 | 
						|
	 */
 | 
						|
	rel = heap_open(NamespaceRelationId, AccessShareLock);
 | 
						|
 | 
						|
	ScanKeyInit(&skey,
 | 
						|
				ObjectIdAttributeNumber,
 | 
						|
				BTEqualStrategyNumber, F_OIDEQ,
 | 
						|
				ObjectIdGetDatum(namespaceId));
 | 
						|
 | 
						|
	sscan = systable_beginscan(rel, NamespaceOidIndexId, true,
 | 
						|
							   SnapshotSelf, 1, &skey);
 | 
						|
	tuple = systable_getnext(sscan);
 | 
						|
	if (!HeapTupleIsValid(tuple))
 | 
						|
		elog(ERROR, "catalog lookup failed for namespace %u", namespaceId);
 | 
						|
 | 
						|
	nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
 | 
						|
	nsp_name = NameStr(nspForm->nspname);
 | 
						|
	if (strncmp(nsp_name, "pg_temp_", 8) == 0)
 | 
						|
		nsp_name = "pg_temp";
 | 
						|
	else if (strncmp(nsp_name, "pg_toast_temp_", 14) == 0)
 | 
						|
		nsp_name = "pg_toast_temp";
 | 
						|
 | 
						|
	tcontext = sepgsql_get_label(DatabaseRelationId, MyDatabaseId, 0);
 | 
						|
	ncontext = sepgsql_compute_create(sepgsql_get_client_label(),
 | 
						|
									  tcontext,
 | 
						|
									  SEPG_CLASS_DB_SCHEMA,
 | 
						|
									  nsp_name);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * check db_schema:{create}
 | 
						|
	 */
 | 
						|
	initStringInfo(&audit_name);
 | 
						|
	appendStringInfo(&audit_name, "%s", quote_identifier(nsp_name));
 | 
						|
	sepgsql_avc_check_perms_label(ncontext,
 | 
						|
								  SEPG_CLASS_DB_SCHEMA,
 | 
						|
								  SEPG_DB_SCHEMA__CREATE,
 | 
						|
								  audit_name.data,
 | 
						|
								  true);
 | 
						|
	systable_endscan(sscan);
 | 
						|
	heap_close(rel, AccessShareLock);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Assign the default security label on a new procedure
 | 
						|
	 */
 | 
						|
	object.classId = NamespaceRelationId;
 | 
						|
	object.objectId = namespaceId;
 | 
						|
	object.objectSubId = 0;
 | 
						|
	SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
 | 
						|
 | 
						|
	pfree(ncontext);
 | 
						|
	pfree(tcontext);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * sepgsql_schema_drop
 | 
						|
 *
 | 
						|
 * It checks privileges to drop the supplied schema object.
 | 
						|
 */
 | 
						|
void
 | 
						|
sepgsql_schema_drop(Oid namespaceId)
 | 
						|
{
 | 
						|
	ObjectAddress object;
 | 
						|
	char	   *audit_name;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * check db_schema:{drop} permission
 | 
						|
	 */
 | 
						|
	object.classId = NamespaceRelationId;
 | 
						|
	object.objectId = namespaceId;
 | 
						|
	object.objectSubId = 0;
 | 
						|
	audit_name = getObjectIdentity(&object);
 | 
						|
 | 
						|
	sepgsql_avc_check_perms(&object,
 | 
						|
							SEPG_CLASS_DB_SCHEMA,
 | 
						|
							SEPG_DB_SCHEMA__DROP,
 | 
						|
							audit_name,
 | 
						|
							true);
 | 
						|
	pfree(audit_name);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * sepgsql_schema_relabel
 | 
						|
 *
 | 
						|
 * It checks privileges to relabel the supplied schema
 | 
						|
 * by the `seclabel'.
 | 
						|
 */
 | 
						|
void
 | 
						|
sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
 | 
						|
{
 | 
						|
	ObjectAddress object;
 | 
						|
	char	   *audit_name;
 | 
						|
 | 
						|
	object.classId = NamespaceRelationId;
 | 
						|
	object.objectId = namespaceId;
 | 
						|
	object.objectSubId = 0;
 | 
						|
	audit_name = getObjectIdentity(&object);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * check db_schema:{setattr relabelfrom} permission
 | 
						|
	 */
 | 
						|
	sepgsql_avc_check_perms(&object,
 | 
						|
							SEPG_CLASS_DB_SCHEMA,
 | 
						|
							SEPG_DB_SCHEMA__SETATTR |
 | 
						|
							SEPG_DB_SCHEMA__RELABELFROM,
 | 
						|
							audit_name,
 | 
						|
							true);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * check db_schema:{relabelto} permission
 | 
						|
	 */
 | 
						|
	sepgsql_avc_check_perms_label(seclabel,
 | 
						|
								  SEPG_CLASS_DB_SCHEMA,
 | 
						|
								  SEPG_DB_SCHEMA__RELABELTO,
 | 
						|
								  audit_name,
 | 
						|
								  true);
 | 
						|
	pfree(audit_name);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * sepgsql_schema_check_perms
 | 
						|
 *
 | 
						|
 * utility routine to check db_schema:{xxx} permissions
 | 
						|
 */
 | 
						|
static bool
 | 
						|
check_schema_perms(Oid namespaceId, uint32 required, bool abort_on_violation)
 | 
						|
{
 | 
						|
	ObjectAddress object;
 | 
						|
	char	   *audit_name;
 | 
						|
	bool		result;
 | 
						|
 | 
						|
	object.classId = NamespaceRelationId;
 | 
						|
	object.objectId = namespaceId;
 | 
						|
	object.objectSubId = 0;
 | 
						|
	audit_name = getObjectIdentity(&object);
 | 
						|
 | 
						|
	result = sepgsql_avc_check_perms(&object,
 | 
						|
									 SEPG_CLASS_DB_SCHEMA,
 | 
						|
									 required,
 | 
						|
									 audit_name,
 | 
						|
									 abort_on_violation);
 | 
						|
	pfree(audit_name);
 | 
						|
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
/* db_schema:{setattr} permission */
 | 
						|
void
 | 
						|
sepgsql_schema_setattr(Oid namespaceId)
 | 
						|
{
 | 
						|
	check_schema_perms(namespaceId, SEPG_DB_SCHEMA__SETATTR, true);
 | 
						|
}
 | 
						|
 | 
						|
/* db_schema:{search} permission */
 | 
						|
bool
 | 
						|
sepgsql_schema_search(Oid namespaceId, bool abort_on_violation)
 | 
						|
{
 | 
						|
	return check_schema_perms(namespaceId,
 | 
						|
							  SEPG_DB_SCHEMA__SEARCH,
 | 
						|
							  abort_on_violation);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
sepgsql_schema_add_name(Oid namespaceId)
 | 
						|
{
 | 
						|
	check_schema_perms(namespaceId, SEPG_DB_SCHEMA__ADD_NAME, true);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
sepgsql_schema_remove_name(Oid namespaceId)
 | 
						|
{
 | 
						|
	check_schema_perms(namespaceId, SEPG_DB_SCHEMA__REMOVE_NAME, true);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
sepgsql_schema_rename(Oid namespaceId)
 | 
						|
{
 | 
						|
	check_schema_perms(namespaceId,
 | 
						|
					   SEPG_DB_SCHEMA__ADD_NAME |
 | 
						|
					   SEPG_DB_SCHEMA__REMOVE_NAME,
 | 
						|
					   true);
 | 
						|
}
 |