* Convert a "text" filename argument to C string, and check it's allowable. * * Filename may be absolute or relative to the DataDir, but we only allow * absolute paths that match DataDir. */
| 68 | * absolute paths that match DataDir. |
| 69 | */ |
| 70 | static char * |
| 71 | convert_and_check_filename(text *arg) |
| 72 | { |
| 73 | char *filename = text_to_cstring(arg); |
| 74 | |
| 75 | canonicalize_path(filename); /* filename can change length here */ |
| 76 | |
| 77 | /* |
| 78 | * Members of the 'pg_write_server_files' role are allowed to access any |
| 79 | * files on the server as the PG user, so no need to do any further checks |
| 80 | * here. |
| 81 | */ |
| 82 | if (is_member_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES)) |
| 83 | return filename; |
| 84 | |
| 85 | /* |
| 86 | * User isn't a member of the pg_write_server_files role, so check if it's |
| 87 | * allowable |
| 88 | */ |
| 89 | if (is_absolute_path(filename)) |
| 90 | { |
| 91 | /* Disallow '/a/b/data/..' */ |
| 92 | if (path_contains_parent_reference(filename)) |
| 93 | ereport(ERROR, |
| 94 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 95 | errmsg("reference to parent directory (\"..\") not allowed"))); |
| 96 | |
| 97 | /* Allow absolute paths if within DataDir */ |
| 98 | if (!path_is_prefix_of_path(DataDir, filename)) |
| 99 | ereport(ERROR, |
| 100 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 101 | errmsg("absolute path not allowed"))); |
| 102 | } |
| 103 | else if (!path_is_relative_and_below_cwd(filename)) |
| 104 | ereport(ERROR, |
| 105 | (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 106 | errmsg("path must be in or below the current directory"))); |
| 107 | |
| 108 | return filename; |
| 109 | } |
| 110 | |
| 111 | |
| 112 | /* |
no test coverage detected