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
))