diff options
author | David M. Lee <dlee@digium.com> | 2013-07-03 17:58:45 +0000 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-07-03 17:58:45 +0000 |
commit | a75fd32212c35b41143442bd757387fad636177a (patch) | |
tree | 461033acf36f4596d8fc9800a1195e12207b3ea2 /main/utils.c | |
parent | c4adaf91067559dd5aa90577e181693abade0602 (diff) |
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
Diffstat (limited to 'main/utils.c')
-rw-r--r-- | main/utils.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/main/utils.c b/main/utils.c index 208a4d326..04f612703 100644 --- a/main/utils.c +++ b/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); |