summaryrefslogtreecommitdiff
path: root/main/utils.c
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-07-03 17:58:45 +0000
committerDavid M. Lee <dlee@digium.com>2013-07-03 17:58:45 +0000
commita75fd32212c35b41143442bd757387fad636177a (patch)
tree461033acf36f4596d8fc9800a1195e12207b3ea2 /main/utils.c
parentc4adaf91067559dd5aa90577e181693abade0602 (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.c94
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);