summaryrefslogtreecommitdiffstats
path: root/contrib/sepgsql/schema.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sepgsql/schema.c')
-rw-r--r--contrib/sepgsql/schema.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c
new file mode 100644
index 0000000..fecd02f
--- /dev/null
+++ b/contrib/sepgsql/schema.c
@@ -0,0 +1,235 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/schema.c
+ *
+ * Routines corresponding to schema objects
+ *
+ * Copyright (c) 2010-2022, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "catalog/dependency.h"
+#include "catalog/pg_database.h"
+#include "catalog/pg_namespace.h"
+#include "commands/seclabel.h"
+#include "lib/stringinfo.h"
+#include "miscadmin.h"
+#include "sepgsql.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/snapmgr.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 - upcoming 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 = table_open(NamespaceRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey,
+ Anum_pg_namespace_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(namespaceId));
+
+ sscan = systable_beginscan(rel, NamespaceOidIndexId, true,
+ SnapshotSelf, 1, &skey);
+ tuple = systable_getnext(sscan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple 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);
+ table_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, false);
+
+ 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, false);
+
+ /*
+ * 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, false);
+
+ 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);
+}