mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-19 11:13:09 +00:00
ARI - channel recording support
This patch is the first step in adding recording support to the Asterisk REST Interface. Recordings are stored in /var/spool/recording. Since recordings may be destructive (overwriting existing files), the API rejects attempts to escape the recording directory (avoiding issues if someone attempts to record to ../../lib/sounds/greeting, for example). (closes issue ASTERISK-21594) (closes issue ASTERISK-21581) Review: https://reviewboard.asterisk.org/r/2612/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393550 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
94
main/utils.c
94
main/utils.c
@@ -2105,6 +2105,100 @@ int ast_mkdir(const char *path, int mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int safe_mkdir(const char *base_path, char *path, int mode)
|
||||
{
|
||||
RAII_VAR(char *, absolute_path, NULL, free);
|
||||
|
||||
absolute_path = realpath(path, NULL);
|
||||
|
||||
if (absolute_path) {
|
||||
/* Path exists, but is it in the right place? */
|
||||
if (!ast_begins_with(absolute_path, base_path)) {
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
/* It is in the right place! */
|
||||
return 0;
|
||||
} else {
|
||||
/* Path doesn't exist. */
|
||||
|
||||
/* The slash terminating the subpath we're checking */
|
||||
char *path_term = strchr(path, '/');
|
||||
/* True indicates the parent path is within base_path */
|
||||
int parent_is_safe = 0;
|
||||
int res;
|
||||
|
||||
while (path_term) {
|
||||
RAII_VAR(char *, absolute_subpath, NULL, free);
|
||||
|
||||
/* Truncate the path one past the slash */
|
||||
char c = *(path_term + 1);
|
||||
*(path_term + 1) = '\0';
|
||||
absolute_subpath = realpath(path, NULL);
|
||||
|
||||
if (absolute_subpath) {
|
||||
/* Subpath exists, but is it safe? */
|
||||
parent_is_safe = ast_begins_with(
|
||||
absolute_subpath, base_path);
|
||||
} else if (parent_is_safe) {
|
||||
/* Subpath does not exist, but parent is safe
|
||||
* Create it */
|
||||
res = mkdir(path, mode);
|
||||
if (res != 0) {
|
||||
ast_assert(errno != EEXIST);
|
||||
return errno;
|
||||
}
|
||||
} else {
|
||||
/* Subpath did not exist, parent was not safe
|
||||
* Fail! */
|
||||
errno = EPERM;
|
||||
return errno;
|
||||
}
|
||||
/* Restore the path */
|
||||
*(path_term + 1) = c;
|
||||
/* Move on to the next slash */
|
||||
path_term = strchr(path_term + 1, '/');
|
||||
}
|
||||
|
||||
/* Now to build the final path, but only if it's safe */
|
||||
if (!parent_is_safe) {
|
||||
errno = EPERM;
|
||||
return errno;
|
||||
}
|
||||
|
||||
res = mkdir(path, mode);
|
||||
if (res != 0 && errno != EEXIST) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ast_safe_mkdir(const char *base_path, const char *path, int mode)
|
||||
{
|
||||
RAII_VAR(char *, absolute_base_path, NULL, free);
|
||||
RAII_VAR(char *, p, NULL, ast_free);
|
||||
|
||||
if (base_path == NULL || path == NULL) {
|
||||
errno = EFAULT;
|
||||
return errno;
|
||||
}
|
||||
|
||||
p = ast_strdup(path);
|
||||
if (p == NULL) {
|
||||
errno = ENOMEM;
|
||||
return errno;
|
||||
}
|
||||
|
||||
absolute_base_path = realpath(base_path, NULL);
|
||||
if (absolute_base_path == NULL) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
return safe_mkdir(absolute_base_path, p, mode);
|
||||
}
|
||||
|
||||
int ast_utils_init(void)
|
||||
{
|
||||
dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
|
Reference in New Issue
Block a user