Age Owner Branch data TLA Line data Source code
1 : : /* -------------------------------------------------------------------------
2 : : *
3 : : * contrib/sepgsql/schema.c
4 : : *
5 : : * Routines corresponding to schema objects
6 : : *
7 : : * Copyright (c) 2010-2024, PostgreSQL Global Development Group
8 : : *
9 : : * -------------------------------------------------------------------------
10 : : */
11 : : #include "postgres.h"
12 : :
13 : : #include "access/genam.h"
14 : : #include "access/htup_details.h"
15 : : #include "access/sysattr.h"
16 : : #include "access/table.h"
17 : : #include "catalog/dependency.h"
18 : : #include "catalog/pg_database.h"
19 : : #include "catalog/pg_namespace.h"
20 : : #include "commands/seclabel.h"
21 : : #include "lib/stringinfo.h"
22 : : #include "miscadmin.h"
23 : : #include "sepgsql.h"
24 : : #include "utils/builtins.h"
25 : : #include "utils/fmgroids.h"
26 : : #include "utils/lsyscache.h"
27 : : #include "utils/snapmgr.h"
28 : :
29 : : /*
30 : : * sepgsql_schema_post_create
31 : : *
32 : : * This routine assigns a default security label on a newly defined
33 : : * schema.
34 : : */
35 : : void
4830 rhaas@postgresql.org 36 :UBC 0 : sepgsql_schema_post_create(Oid namespaceId)
37 : : {
38 : : Relation rel;
39 : : ScanKeyData skey;
40 : : SysScanDesc sscan;
41 : : HeapTuple tuple;
42 : : char *tcontext;
43 : : char *ncontext;
44 : : const char *nsp_name;
45 : : ObjectAddress object;
46 : : Form_pg_namespace nspForm;
47 : : StringInfoData audit_name;
48 : :
49 : : /*
50 : : * Compute a default security label when we create a new schema object
51 : : * under the working database.
52 : : *
53 : : * XXX - upcoming version of libselinux supports to take object name to
54 : : * handle special treatment on default security label; such as special
55 : : * label on "pg_temp" schema.
56 : : */
1910 andres@anarazel.de 57 : 0 : rel = table_open(NamespaceRelationId, AccessShareLock);
58 : :
4498 rhaas@postgresql.org 59 : 0 : ScanKeyInit(&skey,
60 : : Anum_pg_namespace_oid,
61 : : BTEqualStrategyNumber, F_OIDEQ,
62 : : ObjectIdGetDatum(namespaceId));
63 : :
64 : 0 : sscan = systable_beginscan(rel, NamespaceOidIndexId, true,
65 : : SnapshotSelf, 1, &skey);
66 : 0 : tuple = systable_getnext(sscan);
67 [ # # ]: 0 : if (!HeapTupleIsValid(tuple))
2506 tgl@sss.pgh.pa.us 68 [ # # ]: 0 : elog(ERROR, "could not find tuple for namespace %u", namespaceId);
69 : :
4498 rhaas@postgresql.org 70 : 0 : nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
4035 71 : 0 : nsp_name = NameStr(nspForm->nspname);
72 [ # # ]: 0 : if (strncmp(nsp_name, "pg_temp_", 8) == 0)
73 : 0 : nsp_name = "pg_temp";
74 [ # # ]: 0 : else if (strncmp(nsp_name, "pg_toast_temp_", 14) == 0)
75 : 0 : nsp_name = "pg_toast_temp";
76 : :
4587 77 : 0 : tcontext = sepgsql_get_label(DatabaseRelationId, MyDatabaseId, 0);
4498 78 : 0 : ncontext = sepgsql_compute_create(sepgsql_get_client_label(),
79 : : tcontext,
80 : : SEPG_CLASS_DB_SCHEMA,
81 : : nsp_name);
82 : :
83 : : /*
84 : : * check db_schema:{create}
85 : : */
4020 86 : 0 : initStringInfo(&audit_name);
586 drowley@postgresql.o 87 : 0 : appendStringInfoString(&audit_name, quote_identifier(nsp_name));
4498 rhaas@postgresql.org 88 : 0 : sepgsql_avc_check_perms_label(ncontext,
89 : : SEPG_CLASS_DB_SCHEMA,
90 : : SEPG_DB_SCHEMA__CREATE,
4020 91 : 0 : audit_name.data,
92 : : true);
4498 93 : 0 : systable_endscan(sscan);
1910 andres@anarazel.de 94 : 0 : table_close(rel, AccessShareLock);
95 : :
96 : : /*
97 : : * Assign the default security label on a new procedure
98 : : */
4830 rhaas@postgresql.org 99 : 0 : object.classId = NamespaceRelationId;
100 : 0 : object.objectId = namespaceId;
101 : 0 : object.objectSubId = 0;
102 : 0 : SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
103 : :
104 : 0 : pfree(ncontext);
4587 105 : 0 : pfree(tcontext);
4830 106 : 0 : }
107 : :
108 : : /*
109 : : * sepgsql_schema_drop
110 : : *
111 : : * It checks privileges to drop the supplied schema object.
112 : : */
113 : : void
4419 114 : 0 : sepgsql_schema_drop(Oid namespaceId)
115 : : {
116 : : ObjectAddress object;
117 : : char *audit_name;
118 : :
119 : : /*
120 : : * check db_schema:{drop} permission
121 : : */
122 : 0 : object.classId = NamespaceRelationId;
123 : 0 : object.objectId = namespaceId;
124 : 0 : object.objectSubId = 0;
1369 michael@paquier.xyz 125 : 0 : audit_name = getObjectIdentity(&object, false);
126 : :
4419 rhaas@postgresql.org 127 : 0 : sepgsql_avc_check_perms(&object,
128 : : SEPG_CLASS_DB_SCHEMA,
129 : : SEPG_DB_SCHEMA__DROP,
130 : : audit_name,
131 : : true);
132 : 0 : pfree(audit_name);
133 : 0 : }
134 : :
135 : : /*
136 : : * sepgsql_schema_relabel
137 : : *
138 : : * It checks privileges to relabel the supplied schema
139 : : * by the `seclabel'.
140 : : */
141 : : void
4830 142 : 0 : sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
143 : : {
144 : : ObjectAddress object;
145 : : char *audit_name;
146 : :
4609 147 : 0 : object.classId = NamespaceRelationId;
148 : 0 : object.objectId = namespaceId;
149 : 0 : object.objectSubId = 0;
1369 michael@paquier.xyz 150 : 0 : audit_name = getObjectIdentity(&object, false);
151 : :
152 : : /*
153 : : * check db_schema:{setattr relabelfrom} permission
154 : : */
4609 rhaas@postgresql.org 155 : 0 : sepgsql_avc_check_perms(&object,
156 : : SEPG_CLASS_DB_SCHEMA,
157 : : SEPG_DB_SCHEMA__SETATTR |
158 : : SEPG_DB_SCHEMA__RELABELFROM,
159 : : audit_name,
160 : : true);
161 : :
162 : : /*
163 : : * check db_schema:{relabelto} permission
164 : : */
165 : 0 : sepgsql_avc_check_perms_label(seclabel,
166 : : SEPG_CLASS_DB_SCHEMA,
167 : : SEPG_DB_SCHEMA__RELABELTO,
168 : : audit_name,
169 : : true);
4830 170 : 0 : pfree(audit_name);
171 : 0 : }
172 : :
173 : : /*
174 : : * sepgsql_schema_check_perms
175 : : *
176 : : * utility routine to check db_schema:{xxx} permissions
177 : : */
178 : : static bool
4027 179 : 0 : check_schema_perms(Oid namespaceId, uint32 required, bool abort_on_violation)
180 : : {
181 : : ObjectAddress object;
182 : : char *audit_name;
183 : : bool result;
184 : :
4036 185 : 0 : object.classId = NamespaceRelationId;
186 : 0 : object.objectId = namespaceId;
187 : 0 : object.objectSubId = 0;
1369 michael@paquier.xyz 188 : 0 : audit_name = getObjectIdentity(&object, false);
189 : :
4027 rhaas@postgresql.org 190 : 0 : result = sepgsql_avc_check_perms(&object,
191 : : SEPG_CLASS_DB_SCHEMA,
192 : : required,
193 : : audit_name,
194 : : abort_on_violation);
4036 195 : 0 : pfree(audit_name);
196 : :
4027 197 : 0 : return result;
198 : : }
199 : :
200 : : /* db_schema:{setattr} permission */
201 : : void
4036 202 : 0 : sepgsql_schema_setattr(Oid namespaceId)
203 : : {
4027 204 : 0 : check_schema_perms(namespaceId, SEPG_DB_SCHEMA__SETATTR, true);
205 : 0 : }
206 : :
207 : : /* db_schema:{search} permission */
208 : : bool
209 : 0 : sepgsql_schema_search(Oid namespaceId, bool abort_on_violation)
210 : : {
211 : 0 : return check_schema_perms(namespaceId,
212 : : SEPG_DB_SCHEMA__SEARCH,
213 : : abort_on_violation);
214 : : }
215 : :
216 : : void
4036 217 : 0 : sepgsql_schema_add_name(Oid namespaceId)
218 : : {
4027 219 : 0 : check_schema_perms(namespaceId, SEPG_DB_SCHEMA__ADD_NAME, true);
4036 220 : 0 : }
221 : :
222 : : void
223 : 0 : sepgsql_schema_remove_name(Oid namespaceId)
224 : : {
4027 225 : 0 : check_schema_perms(namespaceId, SEPG_DB_SCHEMA__REMOVE_NAME, true);
4036 226 : 0 : }
227 : :
228 : : void
229 : 0 : sepgsql_schema_rename(Oid namespaceId)
230 : : {
231 : 0 : check_schema_perms(namespaceId,
232 : : SEPG_DB_SCHEMA__ADD_NAME |
233 : : SEPG_DB_SCHEMA__REMOVE_NAME,
234 : : true);
235 : 0 : }
|