From: Andre Noll Date: Fri, 5 Oct 2007 19:50:51 +0000 (+0200) Subject: com_add(): Only accept absolute paths. X-Git-Tag: v0.3.0~303 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=b7bfffa86a33626ebb8e8a5fcba51568492c3808;p=paraslash.git com_add(): Only accept absolute paths. --- diff --git a/aft.c b/aft.c index 8c7dd21a..ce84ef0a 100644 --- a/aft.c +++ b/aft.c @@ -16,8 +16,6 @@ #include "string.h" #include "vss.h" -#define AFS_AUDIO_FILE_DIR "/home/mp3" /* FIXME: Use cwd instead */ - static struct osl_table *audio_file_table; /** The different sorting methods of the ls command. */ @@ -243,60 +241,7 @@ static struct osl_table_description audio_file_table_desc = { .column_descriptions = aft_cols }; -static char *prefix_path(const char *prefix, int len, const char *path) -{ - int speclen; - char *n; - - for (;;) { - char c; - if (*path != '.') - break; - c = path[1]; - /* "." */ - if (!c) { - path++; - break; - } - /* "./" */ - if (c == '/') { - path += 2; - continue; - } - if (c != '.') - break; - c = path[2]; - if (!c) - path += 2; - else if (c == '/') - path += 3; - else - break; - /* ".." and "../" */ - /* Remove last component of the prefix */ - do { - if (!len) - return NULL; - len--; - } while (len && prefix[len-1] != '/'); - continue; - } - if (!len) - return para_strdup(path); - speclen = strlen(path); - n = para_malloc(speclen + len + 1); - memcpy(n, prefix, len); - memcpy(n + len, path, speclen+1); - return n; -} - -/* - * We fundamentally don't like some paths: we don't want - * dot or dot-dot anywhere. - * - * Also, we don't want double slashes or slashes at the - * end that can make pathnames ambiguous. - */ +/* We don't want * dot or dot-dot anywhere. */ static int verify_dotfile(const char *rest) { /* @@ -304,48 +249,52 @@ static int verify_dotfile(const char *rest) * now test the rest. */ switch (*rest) { - /* "." is not allowed */ - case '\0': case '/': - return 1; - - case '.': + case '\0': case '/': /* /foo/. and /foo/./bar are not ok */ + return -1; + case '.': /* path start with /foo/.. */ if (rest[1] == '\0' || rest[1] == '/') - return -1; + return -1; /* /foo/.. or /foo/../bar are not ok */ + /* /foo/..bar is ok */ } return 1; } +/* + * We fundamentally don't like some paths: We don't want double slashes or + * slashes at the end that can make pathnames ambiguous. + */ static int verify_path(const char *orig_path, char **resolved_path) { char c; - const char prefix[] = AFS_AUDIO_FILE_DIR "/"; - const char *path = orig_path; - const size_t prefix_len = strlen(prefix); + size_t len; + char *path; + if (*orig_path != '/') /* we only accept absolute paths */ + return -E_BAD_PATH; + len = strlen(orig_path); + *resolved_path = para_strdup(orig_path); + path = *resolved_path; + while (len > 1 && path[--len] == '/') + path[len] = '\0'; /* remove slash at the end */ c = *path++; - if (!c) - goto bad_path; while (c) { if (c == '/') { c = *path++; switch (c) { - default: - continue; case '/': /* double slash */ goto bad_path; case '.': if (verify_dotfile(path) < 0) goto bad_path; + default: + continue; } } c = *path++; } - if (*orig_path != '/') - *resolved_path = prefix_path(prefix, prefix_len, orig_path); - else - *resolved_path = para_strdup(orig_path); return 1; bad_path: + free(*resolved_path); return -E_BAD_PATH; } @@ -1566,7 +1515,7 @@ static int hash_sister_callback(const struct osl_object *query, return 1; } -static int add_one_audio_file(const char *arg, const void *private_data) +static int add_one_audio_file(const char *path, const void *private_data) { int ret; uint8_t format_num = -1; @@ -1574,14 +1523,10 @@ static int add_one_audio_file(const char *arg, const void *private_data) struct audio_format_info afhi, *afhi_ptr = NULL; struct osl_row *pb = NULL, *hs = NULL; /* path brother/hash sister */ struct osl_object map, obj = {.data = NULL}, query, result; - char *path = NULL; HASH_TYPE hash[HASH_SIZE]; afhi.header_offset = 0; afhi.header_len = 0; - ret = verify_path(arg, &path); - if (ret < 0) - goto out_free; ret = guess_audio_format(path); if (ret < 0 && !(pad->flags & ADD_FLAG_ALL)) { if (pad->flags & ADD_FLAG_VERBOSE) @@ -1590,7 +1535,7 @@ static int add_one_audio_file(const char *arg, const void *private_data) ret = 1; goto out_free; } - query.data = path; + query.data = (char *)path; query.size = strlen(path) + 1; ret = send_callback_request(path_brother_callback, &query, &result); if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND) @@ -1655,10 +1600,9 @@ out_unmap: munmap(map.data, map.size); out_free: if (ret < 0 && ret != -E_SEND) - send_va_buffer(pad->fd, "failed to add %s (%s)\n", path? - path : arg, PARA_STRERROR(-ret)); + send_va_buffer(pad->fd, "failed to add %s (%s)\n", path, + PARA_STRERROR(-ret)); free(obj.data); - free(path); if (afhi_ptr) free(afhi_ptr->chunk_table); /* it's not an error if not all files could be added */ @@ -1699,30 +1643,36 @@ int com_add(int fd, int argc, char * const * const argv) if (argc <= i) return -E_AFT_SYNTAX; for (; i < argc; i++) { - char *path = para_strdup(argv[i]); - size_t len = strlen(path); - while (len > 1 && path[--len] == '/') - path[len] = '\0'; + char *path; + ret = verify_path(argv[i], &path); + if (ret < 0) { + ret = send_va_buffer(fd, "%s: %s\n", argv[i], PARA_STRERROR(-ret)); + if (ret < 0) + return ret; + continue; + } ret = stat(path, &statbuf); - if (ret < 0) - PARA_NOTICE_LOG("failed to stat %s (%s)", path, + if (ret < 0) { + ret = send_va_buffer(fd, "failed to stat %s (%s)\n", path, strerror(errno)); - else { - if (S_ISDIR(statbuf.st_mode)) - ret = for_each_file_in_dir(path, add_one_audio_file, - &pad); - else - ret = add_one_audio_file(path, &pad); - if (ret < 0) { - send_va_buffer(fd, "%s: %s\n", path, PARA_STRERROR(-ret)); - free(path); + free(path); + if (ret < 0) return ret; - } + continue; + } + if (S_ISDIR(statbuf.st_mode)) + ret = for_each_file_in_dir(path, add_one_audio_file, + &pad); + else + ret = add_one_audio_file(path, &pad); + if (ret < 0) { + send_va_buffer(fd, "%s: %s\n", path, PARA_STRERROR(-ret)); + free(path); + return ret; } free(path); } - ret = 1; - return ret; + return 1; }