FileIOPermission.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. //------------------------------------------------------------------------------
  2. //
  3. // System.Security.Permissions.FileIOPermission.cs
  4. //
  5. // Copyright (C) 2001 Nick Drochak, All Rights Reserved
  6. //
  7. // Author: Nick Drochak, [email protected]
  8. // Created: 2002-01-09
  9. //
  10. //------------------------------------------------------------------------------
  11. using System.Collections;
  12. using System.Text;
  13. using System.Security.Permissions;
  14. using System.IO;
  15. namespace System.Security.Permissions {
  16. [SerializableAttribute()]
  17. public sealed class FileIOPermission : CodeAccessPermission, IUnrestrictedPermission {
  18. private static char[] m_badCharacters = {'\"','<', '>', '|', '*', '?'};
  19. private bool m_Unrestricted = false;
  20. private Hashtable m_PathList = new Hashtable();
  21. private FileIOPermissionAccess m_AllFilesAccess = FileIOPermissionAccess.NoAccess;
  22. private FileIOPermissionAccess m_AllLocalFilesAccess = FileIOPermissionAccess.NoAccess;
  23. public FileIOPermission(PermissionState state) {
  24. if (!Enum.IsDefined(typeof(PermissionState), state)){
  25. throw new ArgumentException("Invalid permission state.", "state");
  26. }
  27. m_Unrestricted = (PermissionState.Unrestricted == state);
  28. if (m_Unrestricted) {
  29. m_AllFilesAccess = FileIOPermissionAccess.AllAccess;
  30. m_AllLocalFilesAccess = FileIOPermissionAccess.AllAccess;
  31. }
  32. }
  33. public FileIOPermission(FileIOPermissionAccess access, string path){
  34. if ((FileIOPermissionAccess.AllAccess & access) != access){
  35. throw new ArgumentException("Illegal enum value: "+access.ToString()+".");
  36. }
  37. if (path.LastIndexOfAny(m_badCharacters) >= 0){
  38. throw new ArgumentException("Illegal characters found in input. Security checks can not contain wild card characters.", "path");
  39. }
  40. AddPathList(access, path);
  41. }
  42. public FileIOPermission(FileIOPermissionAccess access, string[] pathList){
  43. if ((FileIOPermissionAccess.AllAccess & access) != access){
  44. throw new ArgumentException("Illegal enum value: "+access.ToString()+".");
  45. }
  46. AddPathList(access, pathList);
  47. }
  48. public FileIOPermissionAccess AllFiles {
  49. get {
  50. return m_AllFilesAccess;
  51. }
  52. set {
  53. // if we are already set to unrestricted, don't change this property
  54. if (!m_Unrestricted){
  55. m_AllFilesAccess = value;
  56. }
  57. }
  58. }
  59. public FileIOPermissionAccess AllLocalFiles {
  60. get {
  61. return m_AllLocalFilesAccess;
  62. }
  63. set {
  64. // if we are already set to unrestricted, don't change this property
  65. if (!m_Unrestricted){
  66. m_AllLocalFilesAccess = value;
  67. }
  68. }
  69. }
  70. public void AddPathList(FileIOPermissionAccess access, string path){
  71. if ((FileIOPermissionAccess.AllAccess & access) != access){
  72. throw new ArgumentException("Illegal enum value: {0}.",access.ToString());
  73. }
  74. if (path.LastIndexOfAny(m_badCharacters) >= 0){
  75. throw new ArgumentException("Invalid characters in path: '{0}'", path);
  76. }
  77. // LAMESPEC: docs don't say it must be a rooted path, but the MS implementation enforces it, so we will too.
  78. if(!Path.IsPathRooted(path)) {
  79. throw new ArgumentException("Absolute path information is required.");
  80. }
  81. // don't add the same path twice, instead overwrite access entry for that path
  82. if (m_PathList.ContainsKey(path)) {
  83. FileIOPermissionAccess currentPermission = (FileIOPermissionAccess)m_PathList[path];
  84. currentPermission |= access;
  85. m_PathList[path] = currentPermission;
  86. }
  87. else {
  88. m_PathList.Add(path, access);
  89. }
  90. }
  91. public void AddPathList(FileIOPermissionAccess access, string[] pathList ){
  92. foreach(string path in pathList){
  93. AddPathList(access, path);
  94. }
  95. }
  96. // private constructor used by Copy() method
  97. private FileIOPermission(Hashtable pathList, FileIOPermissionAccess allFiles,
  98. FileIOPermissionAccess allLocalFiles, bool unrestricted){
  99. m_PathList = pathList;
  100. m_AllFilesAccess = allFiles;
  101. m_AllLocalFilesAccess = allLocalFiles;
  102. m_Unrestricted = unrestricted;
  103. }
  104. public override IPermission Copy(){
  105. if (m_Unrestricted) {
  106. return new FileIOPermission(PermissionState.Unrestricted);
  107. }
  108. else{
  109. FileIOPermission retVal = new FileIOPermission(m_PathList, m_AllFilesAccess, m_AllLocalFilesAccess, m_Unrestricted);
  110. return retVal;
  111. }
  112. }
  113. /* XML Schema for FileIOPermission
  114. <IPermission class=”FileIOPermission”
  115. version=”1”
  116. (
  117. Read=”[list of files or folders]” |
  118. Write=”[list of files or folders]” |
  119. Append=”[list of files or folders]”
  120. ) v Unrestricted=”true”
  121. />
  122. */
  123. public override void FromXml(SecurityElement esd){
  124. if (null == esd) {
  125. throw new ArgumentNullException();
  126. }
  127. if (esd.Tag != "IPermission" || (string)esd.Attributes["class"] != "FileIOPermission"
  128. || (string)esd.Attributes["version"] != "1"){
  129. throw new ArgumentException("Not a valid permission element");
  130. }
  131. m_PathList.Clear();
  132. if ("true" == (string)esd.Attributes["Unrestricted"]){
  133. m_Unrestricted = true;
  134. }
  135. else{
  136. m_Unrestricted = false;
  137. string fileList;
  138. fileList = (string)esd.Attributes["Read"];
  139. string[] files;
  140. if (fileList != null){
  141. files = fileList.Split(';');
  142. AddPathList(FileIOPermissionAccess.Read, files);
  143. }
  144. fileList = (string)esd.Attributes["Write"];
  145. if (fileList != null){
  146. files = fileList.Split(';');
  147. AddPathList(FileIOPermissionAccess.Write, files);
  148. }
  149. fileList = (string)esd.Attributes["Append"];
  150. if (fileList != null){
  151. files = fileList.Split(';');
  152. AddPathList(FileIOPermissionAccess.Append, files);
  153. }
  154. }
  155. }
  156. public string[] GetPathList(FileIOPermissionAccess access){
  157. //LAMESPEC: docs says it returns (semicolon separated) list, but return
  158. //type is array. I think docs are wrong and it just returns an array
  159. if ((FileIOPermissionAccess.AllAccess & access) != access){
  160. throw new ArgumentException("Illegal enum value: "+access.ToString()+".");
  161. }
  162. ArrayList matchingPaths = new ArrayList();
  163. System.Collections.IDictionaryEnumerator pathListIterator = m_PathList.GetEnumerator();
  164. while (pathListIterator.MoveNext()) {
  165. if (((FileIOPermissionAccess)pathListIterator.Value & access) != 0) {
  166. matchingPaths.Add((string)pathListIterator.Key);
  167. }
  168. }
  169. if (matchingPaths.Count == 0) {
  170. return null;
  171. }
  172. else {
  173. return (string[])matchingPaths.ToArray(typeof(string));
  174. }
  175. }
  176. public override IPermission Intersect(IPermission target){
  177. if (null == target){
  178. return null;
  179. }
  180. else {
  181. if (target.GetType() != typeof(FileIOPermission)){
  182. throw new ArgumentException();
  183. }
  184. }
  185. FileIOPermission FIOPTarget = (FileIOPermission)target;
  186. if (FIOPTarget.IsUnrestricted() && m_Unrestricted){
  187. return new FileIOPermission(PermissionState.Unrestricted);
  188. }
  189. else if (FIOPTarget.IsUnrestricted()){
  190. return Copy();
  191. }
  192. else if (m_Unrestricted){
  193. return FIOPTarget.Copy();
  194. }
  195. else{
  196. FileIOPermission retVal = new FileIOPermission(PermissionState.None);
  197. retVal.AllFiles = m_AllFilesAccess & FIOPTarget.AllFiles;
  198. retVal.AllLocalFiles = m_AllLocalFilesAccess & FIOPTarget.AllLocalFiles;
  199. string[] paths;
  200. paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Append);
  201. if (null != paths) {
  202. foreach (string path in paths){
  203. if (m_PathList.ContainsKey(path)
  204. && ((FileIOPermissionAccess)m_PathList[path] & FileIOPermissionAccess.Append) != 0){
  205. retVal.AddPathList(FileIOPermissionAccess.Append, path);
  206. }
  207. }
  208. }
  209. paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Read);
  210. if (null != paths) {
  211. foreach (string path in paths){
  212. if (m_PathList.ContainsKey(path)
  213. && ((FileIOPermissionAccess)m_PathList[path] & FileIOPermissionAccess.Read) != 0){
  214. retVal.AddPathList(FileIOPermissionAccess.Read, path);
  215. }
  216. }
  217. }
  218. paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Write);
  219. if (null != paths) {
  220. foreach (string path in paths){
  221. if (m_PathList.ContainsKey(path)
  222. && ((FileIOPermissionAccess)m_PathList[path] & FileIOPermissionAccess.Write) != 0){
  223. retVal.AddPathList(FileIOPermissionAccess.Write, path);
  224. }
  225. }
  226. }
  227. return retVal;
  228. }
  229. }
  230. public override bool IsSubsetOf(IPermission target){
  231. // X.IsSubsetOf(Y) is true if permission Y includes everything allowed by X.
  232. if (target != null && target.GetType() != typeof(FileIOPermission)){
  233. throw new ArgumentException();
  234. }
  235. FileIOPermission FIOPTarget = (FileIOPermission)target;
  236. if (FIOPTarget.IsUnrestricted()){
  237. return true;
  238. }
  239. else if (m_Unrestricted){
  240. return false;
  241. }
  242. else if ((m_AllFilesAccess & FIOPTarget.AllFiles) != m_AllFilesAccess) {
  243. return false;
  244. }
  245. else if ((m_AllLocalFilesAccess & FIOPTarget.AllLocalFiles) != m_AllLocalFilesAccess) {
  246. return false;
  247. }
  248. else{
  249. string[] pathsNeeded;
  250. string[] pathsInTarget;
  251. pathsNeeded = GetPathList(FileIOPermissionAccess.Append);
  252. if (null != pathsNeeded) {
  253. pathsInTarget = FIOPTarget.GetPathList(FileIOPermissionAccess.Append);
  254. foreach (string path in pathsNeeded){
  255. if (Array.IndexOf(pathsInTarget, path) <0) {
  256. return false;
  257. }
  258. }
  259. }
  260. pathsNeeded = GetPathList(FileIOPermissionAccess.Read);
  261. if (null != pathsNeeded) {
  262. pathsInTarget = FIOPTarget.GetPathList(FileIOPermissionAccess.Read);
  263. foreach (string path in pathsNeeded){
  264. if (Array.IndexOf(pathsInTarget, path) <0) {
  265. return false;
  266. }
  267. }
  268. }
  269. pathsNeeded = GetPathList(FileIOPermissionAccess.Write);
  270. if (null != pathsNeeded) {
  271. pathsInTarget = FIOPTarget.GetPathList(FileIOPermissionAccess.Write);
  272. foreach (string path in pathsNeeded){
  273. if (Array.IndexOf(pathsInTarget, path) <0) {
  274. return false;
  275. }
  276. }
  277. }
  278. return true;
  279. }
  280. }
  281. public bool IsUnrestricted(){
  282. return m_Unrestricted;
  283. }
  284. public void SetPathList(FileIOPermissionAccess access, string path){
  285. if ((FileIOPermissionAccess.AllAccess & access) != access){
  286. throw new ArgumentException("Illegal enum value: "+access.ToString()+".");
  287. }
  288. if (path.LastIndexOfAny(m_badCharacters) >= 0){
  289. throw new ArgumentException("Invalid characters in path: '{0}'", path);
  290. }
  291. m_PathList.Clear();
  292. AddPathList(access, path);
  293. }
  294. public void SetPathList(FileIOPermissionAccess access, string[] pathList){
  295. if ((FileIOPermissionAccess.AllAccess & access) != access){
  296. throw new ArgumentException("Illegal enum value: "+access.ToString()+".");
  297. }
  298. foreach(string path in pathList){
  299. if (path.LastIndexOfAny(m_badCharacters) >= 0){
  300. throw new ArgumentException("Invalid characters in path entry: '{0}'", path);
  301. }
  302. }
  303. m_PathList.Clear();
  304. AddPathList(access, pathList);
  305. }
  306. public override SecurityElement ToXml(){
  307. //Encode the the current permission to XML using the
  308. //security element class.
  309. SecurityElement element = new SecurityElement("IPermission");
  310. Type type = this.GetType();
  311. StringBuilder AsmName = new StringBuilder(type.Assembly.ToString());
  312. AsmName.Replace('\"', '\'');
  313. element.AddAttribute("class", type.FullName + ", " + AsmName);
  314. element.AddAttribute("version", "1");
  315. if(m_Unrestricted){
  316. element.AddAttribute("Unrestricted", "true");
  317. }
  318. else {
  319. string[] paths;
  320. paths = GetPathList(FileIOPermissionAccess.Append);
  321. if (null != paths && paths.Length >0){
  322. element.AddAttribute("Append", String.Join(";",paths));
  323. }
  324. paths = GetPathList(FileIOPermissionAccess.Read);
  325. if (null != paths && paths.Length >0){
  326. element.AddAttribute("Read", String.Join(";",paths));
  327. }
  328. paths = GetPathList(FileIOPermissionAccess.Write);
  329. if (null != paths && paths.Length >0){
  330. element.AddAttribute("Write", String.Join(";",paths));
  331. }
  332. }
  333. return element;
  334. }
  335. public override IPermission Union(IPermission other){
  336. if (null == other){
  337. return null;
  338. }
  339. else {
  340. if (other.GetType() != typeof(FileIOPermission)){
  341. throw new ArgumentException();
  342. }
  343. }
  344. FileIOPermission FIOPTarget = (FileIOPermission)other;
  345. if (FIOPTarget.IsUnrestricted() || m_Unrestricted){
  346. return new FileIOPermission(PermissionState.Unrestricted);
  347. }
  348. else{
  349. FileIOPermission retVal = (FileIOPermission)Copy();
  350. retVal.AllFiles |= FIOPTarget.AllFiles;
  351. retVal.AllLocalFiles |= FIOPTarget.AllLocalFiles;
  352. string[] paths;
  353. paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Append);
  354. if (null != paths){
  355. retVal.AddPathList(FileIOPermissionAccess.Append, paths);
  356. }
  357. paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Read);
  358. if (null != paths){
  359. retVal.AddPathList(FileIOPermissionAccess.Read, paths);
  360. }
  361. paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Write);
  362. if (null != paths){
  363. retVal.AddPathList(FileIOPermissionAccess.Write, paths);
  364. }
  365. return retVal;
  366. }
  367. }
  368. }
  369. }