Browse code

gen_path now rejects filenames that match Windows device names such as CON, NUL, LPT1, etc.

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3072 e7ae566f-a301-0410-adde-c780ea21d3b5

james authored on 2008/07/18 07:41:15
Showing 3 changed files
... ...
@@ -35,6 +35,7 @@
35 35
 #include "manage.h"
36 36
 #include "crypto.h"
37 37
 #include "route.h"
38
+#include "win32.h"
38 39
 
39 40
 #include "memdbg.h"
40 41
 
... ...
@@ -1114,7 +1115,11 @@ gen_path (const char *directory, const char *filename, struct gc_arena *gc)
1114 1114
 
1115 1115
   if (safe_filename
1116 1116
       && strcmp (safe_filename, ".")
1117
-      && strcmp (safe_filename, ".."))
1117
+      && strcmp (safe_filename, "..")
1118
+#ifdef WIN32
1119
+      && win_safe_filename (safe_filename)
1120
+#endif
1121
+      )
1118 1122
     {
1119 1123
       struct buffer out = alloc_buf_gc (256, gc);
1120 1124
       char dirsep[2];
... ...
@@ -753,4 +753,67 @@ getpass (const char *prompt)
753 753
     return NULL;
754 754
 }
755 755
 
756
+/*
757
+ * Return true if filename is safe to be used on Windows,
758
+ * by avoiding the following reserved names:
759
+ *
760
+ * CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9,
761
+ * LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, and CLOCK$
762
+ *
763
+ * See: http://msdn.microsoft.com/en-us/library/aa365247.aspx
764
+ *  and http://msdn.microsoft.com/en-us/library/86k9f82k(VS.80).aspx
765
+ */
766
+
767
+static bool
768
+cmp_prefix (const char *str, const bool n, const char *pre)
769
+{
770
+  const size_t len = strlen (pre);
771
+  size_t i = 0;
772
+
773
+  if (!str)
774
+    return false;
775
+
776
+  while (true)
777
+    {
778
+      const int c1 = pre[i];
779
+      int c2 = str[i];
780
+      ++i;
781
+      if (c1 == '\0')
782
+	{
783
+	  if (n)
784
+	    {
785
+	      if (isdigit (c2))
786
+		c2 = str[i];
787
+	      else
788
+		return false;
789
+	    }
790
+	  return c2 == '\0' || c2 == '.';
791
+	}
792
+      else if (c2 == '\0')
793
+	return false;
794
+      if (c1 != tolower(c2))
795
+	return false;
796
+    }
797
+}
798
+
799
+bool
800
+win_safe_filename (const char *fn)
801
+{
802
+  if (cmp_prefix (fn, false, "con"))
803
+    return false;
804
+  if (cmp_prefix (fn, false, "prn"))
805
+    return false;
806
+  if (cmp_prefix (fn, false, "aux"))
807
+    return false;
808
+  if (cmp_prefix (fn, false, "nul"))
809
+    return false;
810
+  if (cmp_prefix (fn, true, "com"))
811
+    return false;
812
+  if (cmp_prefix (fn, true, "lpt"))
813
+    return false;
814
+  if (cmp_prefix (fn, false, "clock$"))
815
+    return false;
816
+  return true;
817
+}
818
+
756 819
 #endif
... ...
@@ -247,5 +247,8 @@ char *getpass (const char *prompt);
247 247
 /* Set Win32 security attributes structure to allow all access */
248 248
 bool init_security_attributes_allow_all (struct security_attributes *obj);
249 249
 
250
+/* return true if filename is safe to be used on Windows */
251
+bool win_safe_filename (const char *fn);
252
+
250 253
 #endif
251 254
 #endif