|
18 | 18 | #include "access/htup_details.h"
|
19 | 19 | #include "access/reloptions.h"
|
20 | 20 | #include "access/sysattr.h"
|
| 21 | +#include "catalog/pg_authid.h" |
21 | 22 | #include "catalog/pg_foreign_table.h"
|
22 | 23 | #include "commands/copy.h"
|
23 | 24 | #include "commands/defrem.h"
|
@@ -201,24 +202,6 @@ file_fdw_validator(PG_FUNCTION_ARGS)
|
201 | 202 | List *other_options = NIL;
|
202 | 203 | ListCell *cell;
|
203 | 204 |
|
204 |
| - /* |
205 |
| - * Only superusers are allowed to set options of a file_fdw foreign table. |
206 |
| - * This is because we don't want non-superusers to be able to control |
207 |
| - * which file gets read or which program gets executed. |
208 |
| - * |
209 |
| - * Putting this sort of permissions check in a validator is a bit of a |
210 |
| - * crock, but there doesn't seem to be any other place that can enforce |
211 |
| - * the check more cleanly. |
212 |
| - * |
213 |
| - * Note that the valid_options[] array disallows setting filename and |
214 |
| - * program at any options level other than foreign table --- otherwise |
215 |
| - * there'd still be a security hole. |
216 |
| - */ |
217 |
| - if (catalog == ForeignTableRelationId && !superuser()) |
218 |
| - ereport(ERROR, |
219 |
| - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
220 |
| - errmsg("only superuser can change options of a file_fdw foreign table"))); |
221 |
| - |
222 | 205 | /*
|
223 | 206 | * Check that only options supported by file_fdw, and allowed for the
|
224 | 207 | * current object type, are given.
|
@@ -264,6 +247,38 @@ file_fdw_validator(PG_FUNCTION_ARGS)
|
264 | 247 | ereport(ERROR,
|
265 | 248 | (errcode(ERRCODE_SYNTAX_ERROR),
|
266 | 249 | errmsg("conflicting or redundant options")));
|
| 250 | + |
| 251 | + /* |
| 252 | + * Check permissions for changing which file or program is used by |
| 253 | + * the file_fdw. |
| 254 | + * |
| 255 | + * Only members of the role 'pg_read_server_files' are allowed to |
| 256 | + * set the 'filename' option of a file_fdw foreign table, while |
| 257 | + * only members of the role 'pg_execute_server_program' are |
| 258 | + * allowed to set the 'program' option. This is because we don't |
| 259 | + * want regular users to be able to control which file gets read |
| 260 | + * or which program gets executed. |
| 261 | + * |
| 262 | + * Putting this sort of permissions check in a validator is a bit |
| 263 | + * of a crock, but there doesn't seem to be any other place that |
| 264 | + * can enforce the check more cleanly. |
| 265 | + * |
| 266 | + * Note that the valid_options[] array disallows setting filename |
| 267 | + * and program at any options level other than foreign table --- |
| 268 | + * otherwise there'd still be a security hole. |
| 269 | + */ |
| 270 | + if (strcmp(def->defname, "filename") == 0 && |
| 271 | + !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_SERVER_FILES)) |
| 272 | + ereport(ERROR, |
| 273 | + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 274 | + errmsg("only superuser or a member of the pg_read_server_files role may specify the filename option of a file_fdw foreign table"))); |
| 275 | + |
| 276 | + if (strcmp(def->defname, "program") == 0 && |
| 277 | + !is_member_of_role(GetUserId(), DEFAULT_ROLE_EXECUTE_SERVER_PROGRAM)) |
| 278 | + ereport(ERROR, |
| 279 | + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 280 | + errmsg("only superuser or a member of the pg_execute_server_program role may specify the program option of a file_fdw foreign table"))); |
| 281 | + |
267 | 282 | filename = defGetString(def);
|
268 | 283 | }
|
269 | 284 |
|
|
0 commit comments