-
Notifications
You must be signed in to change notification settings - Fork 0
/
SafeFile.cs
155 lines (136 loc) · 5.4 KB
/
SafeFile.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/// <summary> OWASP Enterprise Security API .NET (ESAPI.NET)
///
/// This file is part of the Open Web Application Security Project (OWASP)
/// Enterprise Security API (ESAPI) project. For details, please see
/// http://www.owasp.org/esapi.
///
/// Copyright (c) 2008 - The OWASP Foundation
///
/// The ESAPI is published by OWASP under the LGPL. You should read and accept the
/// LICENSE before you use, modify, and/or redistribute this software.
///
/// </summary>
/// <author> Alex Smolen [a href="http://www.foundstone.com"]Foundstone[/a]
/// </author>
/// <created> 2008 </created>
using System;
using System.ComponentModel;
using System.IO;
using System.Text.RegularExpressions;
using Owasp.Esapi.Errors;
using System.Runtime.InteropServices;
namespace Owasp.Esapi
{
/// <summary>
/// This class is used to safely access files. Rather than extending FileInfo, this class keeps
/// a private instance of a FileInfo class which can be accessed by callers through a public
/// property. The difference from the Java implemenation has to do with the fact the FileInfo is
/// sealed.
/// </summary>
/// <author> Alex Smolen [a href="http://www.foundstone.com"]Foundstone[/a]
/// </author>
/// <since> April 23, 2008
/// </since>
public class SafeFile:Component
{
private static readonly long serialVersionUID = 1L;
readonly String dirBlackList = "([*?<>|])";
readonly String fileBlackList = "([\\\\/:*?<>|])";
readonly String percents = "(%)([0-9a-fA-F])([0-9a-fA-F])";
private FileInfo safeFileInfo;
public SafeFile(String path)
{
safeFileInfo = new FileInfo(path);
DoDirCheck(safeFileInfo.DirectoryName);
DoFileCheck(safeFileInfo.Name);
}
public SafeFile(Uri uri)
{
safeFileInfo = new FileInfo(uri.ToString());
DoDirCheck(safeFileInfo.DirectoryName);
DoFileCheck(safeFileInfo.Name);
}
// FIXME: much stricter file validation using Validator - but won't work as drop-in replacement as well
//private void DoFileCheck( String path )
//{
// if ( !Esapi.Validator().IsValidFileName( "SafeFile constructor", path ) )
// {
// throw new ValidationException("Invalid file", "File path (" + path + ") is invalid" );
// }
//}
private void DoDirCheck(String path)
{
string matches = GetMatches(path, dirBlackList);
if (matches != null)
{
throw new ValidationException( "Invalid directory", "Directory path (" + path + ") contains illegal character: " + matches );
}
matches = GetMatches(path, percents);
if (matches != null)
{
throw new ValidationException("Invalid directory", "Directory path (" + path + ") contains encoded characters: " + matches);
}
int ch = ContainsUnprintableCharacters(path);
if (ch != -1)
{
throw new ValidationException("Invalid directory", "Directory path (" + path + ") contains unprintable character: " + ch);
}
}
private void DoFileCheck(String path)
{
string matches = GetMatches(path, fileBlackList);
if (matches != null)
{
throw new ValidationException("Invalid file", "File path (" + path + ") contains illegal character: " + matches);
}
matches = GetMatches(path, percents);
if (matches != null)
{
throw new ValidationException("Invalid file", "File path (" + path + ") contains encoded characters: " + matches);
}
int ch = ContainsUnprintableCharacters(path);
if (ch != -1)
{
throw new ValidationException("Invalid file", "File path (" + path + ") contains unprintable character: " + ch);
}
}
private int ContainsUnprintableCharacters(String s)
{
// FIXME: use Validator.isValidPrintable( s );
char[] charArray = s.ToCharArray();
for (int i = 0; i < s.Length; i++)
{
char ch = charArray[i];
if (((int)ch) < 32 || ((int)ch) > 126)
{
return (int)ch;
}
}
return -1;
}
public string GetMatches(string text, string regex)
{
MatchCollection matches = Regex.Matches(text, regex);
if (matches.Count != 0)
{
String matchesOutputString = "";
foreach (Match m in matches)
{
foreach (Group g in m.Groups)
{
matchesOutputString += ((matchesOutputString.Length == 0) ? g.ToString() : ", " + g.ToString());
}
}
return matchesOutputString;
}
return null;
}
public FileInfo SafeFileInfo
{
get
{
return safeFileInfo;
}
}
}
}