2 // System.Security.Permissions.RegistryPermission.cs
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // Copyright (C) 2003 Motus Technologies. http://www.motus.com
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.Globalization;
34 using System.Runtime.InteropServices;
35 using System.Security.AccessControl;
37 namespace System.Security.Permissions {
41 public sealed class RegistryPermission
42 : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
44 private const int version = 1;
46 private PermissionState _state;
47 // private RegistryPermissionAccess _access;
48 private ArrayList createList;
49 private ArrayList readList;
50 private ArrayList writeList;
51 // private AccessControlActions _control;
54 public RegistryPermission (PermissionState state)
56 _state = CheckPermissionState (state, true);
57 createList = new ArrayList ();
58 readList = new ArrayList ();
59 writeList = new ArrayList ();
62 public RegistryPermission (RegistryPermissionAccess access, string pathList)
64 _state = PermissionState.None;
65 createList = new ArrayList ();
66 readList = new ArrayList ();
67 writeList = new ArrayList ();
68 AddPathList (access, pathList);
70 public RegistryPermission (RegistryPermissionAccess access, AccessControlActions control, string pathList)
72 if (!Enum.IsDefined (typeof (AccessControlActions), control)) {
73 string msg = String.Format (Locale.GetText ("Invalid enum {0}"), control);
74 throw new ArgumentException (msg, "AccessControlActions");
76 _state = PermissionState.None;
77 AddPathList (access, control, pathList);
84 public void AddPathList (RegistryPermissionAccess access, string pathList)
87 throw new ArgumentNullException ("pathList");
90 case RegistryPermissionAccess.AllAccess:
91 AddWithUnionKey (createList, pathList);
92 AddWithUnionKey (readList, pathList);
93 AddWithUnionKey (writeList, pathList);
95 case RegistryPermissionAccess.NoAccess:
96 // ??? unit tests doesn't show removal using NoAccess ???
98 case RegistryPermissionAccess.Create:
99 AddWithUnionKey (createList, pathList);
101 case RegistryPermissionAccess.Read:
102 AddWithUnionKey (readList, pathList);
104 case RegistryPermissionAccess.Write:
105 AddWithUnionKey (writeList, pathList);
108 ThrowInvalidFlag (access, false);
112 [MonoTODO ("(2.0) Access Control isn't implemented")]
113 public void AddPathList (RegistryPermissionAccess access, AccessControlActions control, string pathList)
115 throw new NotImplementedException ();
117 public string GetPathList (RegistryPermissionAccess access)
120 case RegistryPermissionAccess.AllAccess:
121 case RegistryPermissionAccess.NoAccess:
122 ThrowInvalidFlag (access, true);
124 case RegistryPermissionAccess.Create:
125 return GetPathList (createList);
126 case RegistryPermissionAccess.Read:
127 return GetPathList (readList);
128 case RegistryPermissionAccess.Write:
129 return GetPathList (writeList);
131 ThrowInvalidFlag (access, false);
134 return null; // never reached
137 public void SetPathList (RegistryPermissionAccess access, string pathList)
139 if (pathList == null)
140 throw new ArgumentNullException ("pathList");
144 case RegistryPermissionAccess.AllAccess:
148 paths = pathList.Split (';');
149 foreach (string path in paths) {
150 createList.Add (path);
152 writeList.Add (path);
155 case RegistryPermissionAccess.NoAccess:
156 // ??? unit tests doesn't show removal using NoAccess ???
158 case RegistryPermissionAccess.Create:
160 paths = pathList.Split (';');
161 foreach (string path in paths) {
162 createList.Add (path);
165 case RegistryPermissionAccess.Read:
167 paths = pathList.Split (';');
168 foreach (string path in paths) {
172 case RegistryPermissionAccess.Write:
174 paths = pathList.Split (';');
175 foreach (string path in paths) {
176 writeList.Add (path);
180 ThrowInvalidFlag (access, false);
185 public override IPermission Copy ()
187 RegistryPermission rp = new RegistryPermission (_state);
189 string path = GetPathList (RegistryPermissionAccess.Create);
191 rp.SetPathList (RegistryPermissionAccess.Create, path);
193 path = GetPathList (RegistryPermissionAccess.Read);
195 rp.SetPathList (RegistryPermissionAccess.Read, path);
197 path = GetPathList (RegistryPermissionAccess.Write);
199 rp.SetPathList (RegistryPermissionAccess.Write, path);
203 public override void FromXml (SecurityElement esd)
205 // General validation in CodeAccessPermission
206 CheckSecurityElement (esd, "esd", version, version);
207 // Note: we do not (yet) care about the return value
208 // as we only accept version 1 (min/max values)
210 // General validation in CodeAccessPermission
211 CheckSecurityElement (esd, "esd", version, version);
212 // Note: we do not (yet) care about the return value
213 // as we only accept version 1 (min/max values)
215 if (IsUnrestricted (esd))
216 _state = PermissionState.Unrestricted;
218 string create = esd.Attribute ("Create");
219 if ((create != null) && (create.Length > 0))
220 SetPathList (RegistryPermissionAccess.Create, create);
222 string read = esd.Attribute ("Read");
223 if ((read != null) && (read.Length > 0))
224 SetPathList (RegistryPermissionAccess.Read, read);
226 string write = esd.Attribute ("Write");
227 if ((write != null) && (write.Length > 0))
228 SetPathList (RegistryPermissionAccess.Write, write);
231 public override IPermission Intersect (IPermission target)
233 RegistryPermission rp = Cast (target);
237 if (IsUnrestricted ())
239 if (rp.IsUnrestricted ())
242 RegistryPermission result = new RegistryPermission (PermissionState.None);
244 IntersectKeys (createList, rp.createList, result.createList);
245 IntersectKeys (readList, rp.readList, result.readList);
246 IntersectKeys (writeList, rp.writeList, result.writeList);
248 return (result.IsEmpty () ? null : result);
251 public override bool IsSubsetOf (IPermission target)
253 RegistryPermission rp = Cast (target);
259 if (IsUnrestricted ())
260 return rp.IsUnrestricted ();
261 else if (rp.IsUnrestricted ())
264 if (!KeyIsSubsetOf (createList, rp.createList))
266 if (!KeyIsSubsetOf (readList, rp.readList))
268 if (!KeyIsSubsetOf (writeList, rp.writeList))
274 public bool IsUnrestricted ()
276 return (_state == PermissionState.Unrestricted);
279 public override SecurityElement ToXml ()
281 SecurityElement se = Element (version);
283 if (_state == PermissionState.Unrestricted) {
284 se.AddAttribute ("Unrestricted", "true");
287 string path = GetPathList (RegistryPermissionAccess.Create);
289 se.AddAttribute ("Create", path);
290 path = GetPathList (RegistryPermissionAccess.Read);
292 se.AddAttribute ("Read", path);
293 path = GetPathList (RegistryPermissionAccess.Write);
295 se.AddAttribute ("Write", path);
300 public override IPermission Union (IPermission other)
302 RegistryPermission rp = Cast (other);
306 if (IsUnrestricted () || rp.IsUnrestricted ())
307 return new RegistryPermission (PermissionState.Unrestricted);
309 if (IsEmpty () && rp.IsEmpty ())
312 RegistryPermission result = (RegistryPermission) Copy ();
313 string path = rp.GetPathList (RegistryPermissionAccess.Create);
315 result.AddPathList (RegistryPermissionAccess.Create, path);
316 path = rp.GetPathList (RegistryPermissionAccess.Read);
318 result.AddPathList (RegistryPermissionAccess.Read, path);
319 path = rp.GetPathList (RegistryPermissionAccess.Write);
321 result.AddPathList (RegistryPermissionAccess.Write, path);
325 // IBuiltInPermission
326 int IBuiltInPermission.GetTokenIndex ()
328 return (int) BuiltInToken.Registry;
333 private bool IsEmpty ()
335 return ((_state == PermissionState.None) && (createList.Count == 0) &&
336 (readList.Count == 0) && (writeList.Count == 0));
339 private RegistryPermission Cast (IPermission target)
344 RegistryPermission rp = (target as RegistryPermission);
346 ThrowInvalidPermission (target, typeof (RegistryPermission));
352 internal void ThrowInvalidFlag (RegistryPermissionAccess flag, bool context)
356 msg = Locale.GetText ("Unknown flag '{0}'.");
358 msg = Locale.GetText ("Invalid flag '{0}' in this context.");
359 throw new ArgumentException (String.Format (msg, flag), "flag");
362 private string GetPathList (ArrayList list)
364 if (IsUnrestricted ())
368 StringBuilder sb = new StringBuilder ();
369 foreach (string path in list) {
374 string result = sb.ToString ();
376 int n = result.Length;
378 return result.Substring (0, n - 1);
382 internal bool KeyIsSubsetOf (IList local, IList target)
385 foreach (string l in local) {
386 foreach (string t in target) {
387 if (l.StartsWith (t)) {
398 internal void AddWithUnionKey (IList list, string pathList)
400 string[] paths = pathList.Split (';');
401 foreach (string path in paths) {
402 int len = list.Count;
407 for (int i=0; i < len; i++) {
408 string s = (string) list [i];
409 if (s.StartsWith (path)) {
410 // replace (with reduced version)
413 else if (path.StartsWith (s)) {
424 internal void IntersectKeys (IList local, IList target, IList result)
426 foreach (string l in local) {
427 foreach (string t in target) {
428 if (t.Length > l.Length) {
429 if (t.StartsWith (l))
433 if (l.StartsWith (t))