Age Owner Branch data TLA Line data Source code
1 : : /* -------------------------------------------------------------------------
2 : : *
3 : : * contrib/sepgsql/database.c
4 : : *
5 : : * Routines corresponding to database objects
6 : : *
7 : : * Copyright (c) 2010-2025, 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 "commands/seclabel.h"
20 : : #include "sepgsql.h"
21 : : #include "utils/builtins.h"
22 : : #include "utils/fmgroids.h"
23 : : #include "utils/snapmgr.h"
24 : :
25 : : /*
26 : : * sepgsql_database_post_create
27 : : *
28 : : * This routine assigns a default security label on a newly defined
29 : : * database, and check permission needed for its creation.
30 : : */
31 : : void
5008 rhaas@postgresql.org 32 :UBC 0 : sepgsql_database_post_create(Oid databaseId, const char *dtemplate)
33 : : {
34 : : Relation rel;
35 : : ScanKeyData skey;
36 : : SysScanDesc sscan;
37 : : HeapTuple tuple;
38 : : char *tcontext;
39 : : char *ncontext;
40 : : ObjectAddress object;
41 : : Form_pg_database datForm;
42 : : StringInfoData audit_name;
43 : :
44 : : /*
45 : : * Oid of the source database is not saved in pg_database catalog, so we
46 : : * collect its identifier using contextual information. If NULL, its
47 : : * default is "template1" according to createdb().
48 : : */
49 [ # # ]: 0 : if (!dtemplate)
50 : 0 : dtemplate = "template1";
51 : :
52 : 0 : object.classId = DatabaseRelationId;
53 : 0 : object.objectId = get_database_oid(dtemplate, false);
54 : 0 : object.objectSubId = 0;
55 : :
56 : 0 : tcontext = sepgsql_get_label(object.classId,
57 : : object.objectId,
58 : : object.objectSubId);
59 : :
60 : : /*
61 : : * check db_database:{getattr} permission
62 : : */
4530 63 : 0 : initStringInfo(&audit_name);
2256 drowley@postgresql.o 64 : 0 : appendStringInfoString(&audit_name, quote_identifier(dtemplate));
5008 rhaas@postgresql.org 65 : 0 : sepgsql_avc_check_perms_label(tcontext,
66 : : SEPG_CLASS_DB_DATABASE,
67 : : SEPG_DB_DATABASE__GETATTR,
4530 68 : 0 : audit_name.data,
69 : : true);
70 : :
71 : : /*
72 : : * Compute a default security label of the newly created database based on
73 : : * a pair of security label of client and source database.
74 : : *
75 : : * XXX - upcoming version of libselinux supports to take object name to
76 : : * handle special treatment on default security label.
77 : : */
2420 andres@anarazel.de 78 : 0 : rel = table_open(DatabaseRelationId, AccessShareLock);
79 : :
5008 rhaas@postgresql.org 80 : 0 : ScanKeyInit(&skey,
81 : : Anum_pg_database_oid,
82 : : BTEqualStrategyNumber, F_OIDEQ,
83 : : ObjectIdGetDatum(databaseId));
84 : :
85 : 0 : sscan = systable_beginscan(rel, DatabaseOidIndexId, true,
86 : : SnapshotSelf, 1, &skey);
87 : 0 : tuple = systable_getnext(sscan);
88 [ # # ]: 0 : if (!HeapTupleIsValid(tuple))
3016 tgl@sss.pgh.pa.us 89 [ # # ]: 0 : elog(ERROR, "could not find tuple for database %u", databaseId);
90 : :
5008 rhaas@postgresql.org 91 : 0 : datForm = (Form_pg_database) GETSTRUCT(tuple);
92 : :
93 : 0 : ncontext = sepgsql_compute_create(sepgsql_get_client_label(),
94 : : tcontext,
95 : : SEPG_CLASS_DB_DATABASE,
4545 96 : 0 : NameStr(datForm->datname));
97 : :
98 : : /*
99 : : * check db_database:{create} permission
100 : : */
4530 101 : 0 : resetStringInfo(&audit_name);
2256 drowley@postgresql.o 102 : 0 : appendStringInfoString(&audit_name,
103 : 0 : quote_identifier(NameStr(datForm->datname)));
5008 rhaas@postgresql.org 104 : 0 : sepgsql_avc_check_perms_label(ncontext,
105 : : SEPG_CLASS_DB_DATABASE,
106 : : SEPG_DB_DATABASE__CREATE,
4530 107 : 0 : audit_name.data,
108 : : true);
109 : :
5008 110 : 0 : systable_endscan(sscan);
2420 andres@anarazel.de 111 : 0 : table_close(rel, AccessShareLock);
112 : :
113 : : /*
114 : : * Assign the default security label on the new database
115 : : */
5097 rhaas@postgresql.org 116 : 0 : object.classId = DatabaseRelationId;
117 : 0 : object.objectId = databaseId;
118 : 0 : object.objectSubId = 0;
119 : :
120 : 0 : SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
121 : :
122 : 0 : pfree(ncontext);
123 : 0 : pfree(tcontext);
124 : 0 : }
125 : :
126 : : /*
127 : : * sepgsql_database_drop
128 : : *
129 : : * It checks privileges to drop the supplied database
130 : : */
131 : : void
4929 132 : 0 : sepgsql_database_drop(Oid databaseId)
133 : : {
134 : : ObjectAddress object;
135 : : char *audit_name;
136 : :
137 : : /*
138 : : * check db_database:{drop} permission
139 : : */
140 : 0 : object.classId = DatabaseRelationId;
141 : 0 : object.objectId = databaseId;
142 : 0 : object.objectSubId = 0;
1879 michael@paquier.xyz 143 : 0 : audit_name = getObjectIdentity(&object, false);
144 : :
4929 rhaas@postgresql.org 145 : 0 : sepgsql_avc_check_perms(&object,
146 : : SEPG_CLASS_DB_DATABASE,
147 : : SEPG_DB_DATABASE__DROP,
148 : : audit_name,
149 : : true);
150 : 0 : pfree(audit_name);
151 : 0 : }
152 : :
153 : : /*
154 : : * sepgsql_database_post_alter
155 : : *
156 : : * It checks privileges to alter the supplied database
157 : : */
158 : : void
4546 159 : 0 : sepgsql_database_setattr(Oid databaseId)
160 : : {
161 : : ObjectAddress object;
162 : : char *audit_name;
163 : :
164 : : /*
165 : : * check db_database:{setattr} permission
166 : : */
167 : 0 : object.classId = DatabaseRelationId;
168 : 0 : object.objectId = databaseId;
169 : 0 : object.objectSubId = 0;
1879 michael@paquier.xyz 170 : 0 : audit_name = getObjectIdentity(&object, false);
171 : :
4546 rhaas@postgresql.org 172 : 0 : sepgsql_avc_check_perms(&object,
173 : : SEPG_CLASS_DB_DATABASE,
174 : : SEPG_DB_DATABASE__SETATTR,
175 : : audit_name,
176 : : true);
177 : 0 : pfree(audit_name);
178 : 0 : }
179 : :
180 : : /*
181 : : * sepgsql_database_relabel
182 : : *
183 : : * It checks privileges to relabel the supplied database with the `seclabel'
184 : : */
185 : : void
5097 186 : 0 : sepgsql_database_relabel(Oid databaseId, const char *seclabel)
187 : : {
188 : : ObjectAddress object;
189 : : char *audit_name;
190 : :
191 : 0 : object.classId = DatabaseRelationId;
192 : 0 : object.objectId = databaseId;
193 : 0 : object.objectSubId = 0;
1879 michael@paquier.xyz 194 : 0 : audit_name = getObjectIdentity(&object, false);
195 : :
196 : : /*
197 : : * check db_database:{setattr relabelfrom} permission
198 : : */
5097 rhaas@postgresql.org 199 : 0 : sepgsql_avc_check_perms(&object,
200 : : SEPG_CLASS_DB_DATABASE,
201 : : SEPG_DB_DATABASE__SETATTR |
202 : : SEPG_DB_DATABASE__RELABELFROM,
203 : : audit_name,
204 : : true);
205 : :
206 : : /*
207 : : * check db_database:{relabelto} permission
208 : : */
209 : 0 : sepgsql_avc_check_perms_label(seclabel,
210 : : SEPG_CLASS_DB_DATABASE,
211 : : SEPG_DB_DATABASE__RELABELTO,
212 : : audit_name,
213 : : true);
214 : 0 : pfree(audit_name);
215 : 0 : }
|