From dad9228494e3cc03dc477e8109f43119390b53c4 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Date: Mon, 9 Dec 2019 15:52:38 +0100
Subject: Only check for OS specific bad filenames when unpacking

When converting a SquashFS image to a tarball, it makes no sense to
refuse conversion if the filename is considered evil by the OS.

This patch adds an option to is_filename_sane to check if the OS has
a problem with the given file name. sqfs2tar sets it to false and
converts everything while rdsquashfs sets it to true when unpacking.

Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
---
 lib/common/filename_sane.c | 46 +++++++++++++++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 17 deletions(-)

(limited to 'lib/common')

diff --git a/lib/common/filename_sane.c b/lib/common/filename_sane.c
index d089ba4..56f1127 100644
--- a/lib/common/filename_sane.c
+++ b/lib/common/filename_sane.c
@@ -8,28 +8,24 @@
 
 #include <string.h>
 
+#ifdef _WIN32
 #ifdef _MSC_VER
 #define strncasecmp _strnicmp
 #define strcasecmp _stricmp
 #endif
 
 static const char *bad_names[] = {
-	".",
-	"..",
-#ifdef _WIN32
 	"CON", "PRN", "AUX", "NUL",
 	"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
 	"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
-#endif
 };
 
-bool is_filename_sane(const char *name)
+static bool is_allowed_by_os(const char *name)
 {
-	size_t i = 0;
+	size_t len, i;
 
 	for (i = 0; i < sizeof(bad_names) / sizeof(bad_names[0]); ++i) {
-#ifdef _WIN32
-		size_t len = strlen(bad_names[i]);
+		len = strlen(bad_names[i]);
 
 		if (strncasecmp(name, bad_names[i], len) != 0)
 			continue;
@@ -39,23 +35,39 @@ bool is_filename_sane(const char *name)
 
 		if (name[len] == '.' && strchr(name + len + 1, '.') == NULL)
 			return false;
+	}
+
+	return true;
+}
 #else
-		if (strcmp(name, bad_names[i]) == 0)
-			return false;
+static bool is_allowed_by_os(const char *name)
+{
+	(void)name;
+	return true;
+}
 #endif
-	}
+
+bool is_filename_sane(const char *name, bool check_os_specific)
+{
+	if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
+		return false;
+
+	if (check_os_specific && !is_allowed_by_os(name))
+		return false;
 
 	while (*name != '\0') {
 		if (*name == '/' || *name == '\\')
 			return false;
 
 #ifdef _WIN32
-		if (*name == '<' || *name == '>' || *name == ':')
-			return false;
-		if (*name == '"' || *name == '|' || *name == '?')
-			return false;
-		if (*name == '*' || *name <= 31)
-			return false;
+		if (check_os_specific) {
+			if (*name == '<' || *name == '>' || *name == ':')
+				return false;
+			if (*name == '"' || *name == '|' || *name == '?')
+				return false;
+			if (*name == '*' || *name <= 31)
+				return false;
+		}
 #endif
 
 		++name;
-- 
cgit v1.2.3