manager.c: Check for restricted file in action_createconfig.

The `CreateConfig` manager action now ensures that a config file can
only be created in the AST_CONFIG_DIR unless `live_dangerously` is set.

Resolves: #1122
22
George Joseph 2 months ago
parent c30ffc08a7
commit d4ece751c5

@ -3097,11 +3097,67 @@ static int action_createconfig(struct mansession *s, const struct message *m)
{
int fd;
const char *fn = astman_get_header(m, "Filename");
struct ast_str *filepath = ast_str_alloca(PATH_MAX);
ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
ast_str_append(&filepath, 0, "%s", fn);
char *stripped_filename;
RAII_VAR(char *, filepath, NULL, ast_free);
RAII_VAR(char *, real_dir, NULL, ast_std_free);
RAII_VAR(char *, real_path, NULL, ast_free);
char *filename;
if (ast_strlen_zero(fn)) {
astman_send_error(s, m, "Filename not specified");
return 0;
}
stripped_filename = ast_strip(ast_strdupa(fn));
/* If the file name is relative, prepend ast_config_AST_CONFIG_DIR */
if (stripped_filename[0] != '/') {
if (ast_asprintf(&filepath, "%s/%s", ast_config_AST_CONFIG_DIR, stripped_filename) == -1) {
return -1;
}
} else {
filepath = ast_strdup(stripped_filename);
}
/*
* We can't call is_restricted_file() here because it uses realpath() and...
*
* realpath() and other functions that canonicalize paths won't work with
* a filename that doesn't exist, so we need to separate the directory
* from the filename and canonicalize the directory first. We have to do
* the separation manually because dirname() and basename() aren't all
* that friendly to multi-threaded programs and there are different
* versions of basename for glibc and POSIX.
*/
filename = strrchr(filepath, '/');
if (!filename) {
astman_send_error(s, m, "Filename is invalid");
return 0;
}
*filename = '\0';
filename++;
/* filepath just has the directory now so canonicalize it. */
real_dir = realpath(filepath, NULL);
if (ast_strlen_zero(real_dir)) {
astman_send_error(s, m, strerror(errno));
return 0;
}
/* Check if the directory is restricted. */
if (!live_dangerously && !ast_begins_with(real_dir, ast_config_AST_CONFIG_DIR)) {
astman_send_error(s, m, "File requires escalated privileges");
return 0;
}
/* Create the final file path. */
if (ast_asprintf(&real_path, "%s/%s", real_dir, filename) == -1) {
astman_send_error(s, m, strerror(errno));
return -1;
}
if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
if ((fd = open(real_path, O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
close(fd);
astman_send_ack(s, m, "New configuration file created successfully");
} else {

Loading…
Cancel
Save