This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / corlib / System.Security.Permissions / PrincipalPermission.cs
1 //
2 // System.Security.Permissions.PrincipalPermission.cs
3 //
4 // Author
5 //      Sebastien Pouliot  <spouliot@motus.com>
6 //
7 // Copyright (C) 2003 Motus Technologies. http://www.motus.com
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Collections;
35 using System.Security.Principal;
36 using System.Text;
37 using System.Threading;
38
39 namespace System.Security.Permissions {
40
41         [Serializable]
42         public sealed class PrincipalPermission : IPermission, IUnrestrictedPermission, IBuiltInPermission {
43
44                 internal class PrincipalInfo {
45
46                         private string _name;
47                         private string _role;
48                         private bool _isAuthenticated;
49                         
50                         public PrincipalInfo (string name, string role, bool isAuthenticated) {
51                                 _name = name;
52                                 _role = role;
53                                 _isAuthenticated = isAuthenticated;
54                         }
55
56                         public string Name {
57                                 get { return _name; }
58                         }
59
60                         public string Role {
61                                 get { return _role; }
62                         }
63
64                         public bool IsAuthenticated {
65                                 get { return _isAuthenticated; }
66                         }
67                 }
68
69                 private ArrayList principals;
70
71                 // Constructors
72
73                 public PrincipalPermission (PermissionState state)
74                 {
75                         principals = new ArrayList ();
76                         switch (state) {
77                                 case PermissionState.None:
78                                         break;
79                                 case PermissionState.Unrestricted:
80                                         PrincipalInfo pi = new PrincipalInfo (null, null, true);
81                                         principals.Add (pi);
82                                         break;
83                                 default:
84                                         throw new ArgumentException ("unknown PermissionState");
85                         }
86                 }
87
88                 public PrincipalPermission (string name, string role) : this (name, role, true)
89                 {
90                 }
91
92                 public PrincipalPermission (string name, string role, bool isAuthenticated)
93                 {
94                         principals = new ArrayList ();
95                         PrincipalInfo pi = new PrincipalInfo (name, role, isAuthenticated);
96                         principals.Add (pi);
97                 }
98
99                 internal PrincipalPermission (ArrayList principals) 
100                 {
101                         this.principals = (ArrayList) principals.Clone ();
102                 }
103
104                 // Properties
105
106                 // Methods
107
108                 public IPermission Copy () 
109                 {
110                         return new PrincipalPermission (principals);
111                 }
112
113                 public void Demand ()
114                 {
115                         IPrincipal p = Thread.CurrentPrincipal;
116                         if (p == null)
117                                 throw new SecurityException ("no Principal");
118
119                         if (principals.Count > 0) {
120                                 // check restrictions
121                                 bool demand = false;
122                                 foreach (PrincipalInfo pi in principals) {
123                                         // if a name is present then it must be equal
124                                         // if a role is present then the identity must be a member of this role
125                                         // if authentication is required then the identity must be authenticated
126                                         if (((pi.Name == null) || (pi.Name == p.Identity.Name)) &&
127                                                 ((pi.Role == null) || (p.IsInRole (pi.Role))) &&
128                                                 ((pi.IsAuthenticated && p.Identity.IsAuthenticated) || (!pi.IsAuthenticated))) {
129                                                 demand = true;
130                                                 break;
131                                         }
132                                 }
133
134                                 if (!demand)
135                                         throw new SecurityException ("invalid Principal");
136                         }
137                 }
138
139                 public void FromXml (SecurityElement esd) 
140                 {
141                         if (esd == null)
142                                 throw new ArgumentNullException ("esd");
143                         if (esd.Tag != "IPermission")
144                                 throw new ArgumentException ("not IPermission");
145                         if (!(esd.Attributes ["class"] as string).StartsWith ("System.Security.Permissions.PrincipalPermission"))
146                                 throw new ArgumentException ("not PrincipalPermission");
147                         if ((esd.Attributes ["version"] as string) != "1")
148                                 throw new ArgumentException ("wrong version");
149
150                         principals.Clear ();
151                         // Children is null, not empty, when no child is present
152                         if (esd.Children != null) {
153                                 foreach (SecurityElement se in esd.Children) {
154                                         if (se.Tag != "Identity")
155                                                 throw new ArgumentException ("not IPermission/Identity");
156                                         string name = (se.Attributes ["Name"] as string);
157                                         string role = (se.Attributes ["Role"] as string);
158                                         bool isAuthenticated = ((se.Attributes ["Authenticated"] as string) == "true");
159                                         PrincipalInfo pi = new PrincipalInfo (name, role, isAuthenticated);
160                                         principals.Add (pi);
161                                 }
162                         }
163                 }
164
165                 public IPermission Intersect (IPermission target) 
166                 {
167                         if (target == null)
168                                 return null;
169                         if (! (target is PrincipalPermission))
170                                 throw new ArgumentException ("wrong type");
171
172                         PrincipalPermission o = (PrincipalPermission) target;
173                         if (IsUnrestricted ())
174                                 return o.Copy ();
175                         if (o.IsUnrestricted ())
176                                 return Copy ();
177
178                         PrincipalPermission intersect = new PrincipalPermission (PermissionState.None);
179                         foreach (PrincipalInfo pi in principals) {
180                                 foreach (PrincipalInfo opi in o.principals) {
181                                         if (pi.IsAuthenticated == opi.IsAuthenticated) {
182                                                 string name = null;
183                                                 if ((pi.Name == opi.Name) || (opi.Name == null))
184                                                         name = pi.Name;
185                                                 string role = null;
186                                                 if ((pi.Role == opi.Role) || (opi.Role == null))
187                                                         role = pi.Role;
188                                                 if ((name != null) || (role != null)) {
189                                                         PrincipalInfo ipi = new PrincipalInfo (name, role, pi.IsAuthenticated);
190                                                         intersect.principals.Add (ipi);
191                                                 }
192                                         }
193                                 }
194                         }
195
196                         return ((intersect.principals.Count > 0) ? intersect : null);
197                 }
198
199                 public bool IsSubsetOf (IPermission target) 
200                 {
201                         if (target == null)
202                                 return false;
203
204                         if (! (target is PrincipalPermission))
205                                 throw new ArgumentException ("wrong type");
206
207                         PrincipalPermission o = (PrincipalPermission) target;
208                         if (IsUnrestricted ())
209                                 return o.IsUnrestricted ();
210                         else if (o.IsUnrestricted ())
211                                 return true;
212
213                         // each must be a subset of the target
214                         foreach (PrincipalInfo pi in principals) {
215                                 bool thisItem = false;
216                                 foreach (PrincipalInfo opi in o.principals) {
217                                         if (((pi.Name == opi.Name) || (opi.Name == null)) && 
218                                                 ((pi.Role == opi.Role) || (opi.Role == null)) && 
219                                                 (pi.IsAuthenticated == opi.IsAuthenticated))
220                                                 thisItem = true;
221                                 }
222                                 if (!thisItem)
223                                         return false;
224                         }
225
226                         return true;
227                 }
228
229                 public bool IsUnrestricted () 
230                 {
231                         foreach (PrincipalInfo pi in principals) {
232                                 if ((pi.Name == null) && (pi.Role == null) && (pi.IsAuthenticated))
233                                         return true;
234                         }
235                         return false;
236                 }
237
238                 public override string ToString () 
239                 {
240                         return ToXml ().ToString ();
241                 }
242
243                 public SecurityElement ToXml () 
244                 {
245                         SecurityElement se = new SecurityElement ("IPermission");
246                         Type type = this.GetType ();
247                         StringBuilder asmName = new StringBuilder (type.Assembly.ToString ());
248                         asmName.Replace ('\"', '\'');
249                         se.AddAttribute ("class", type.FullName + ", " + asmName);
250                         se.AddAttribute ("version", "1");
251                         foreach (PrincipalInfo pi in principals) {
252                                 SecurityElement sec = new SecurityElement ("Identity");
253                                 if (pi.Name != null)
254                                         sec.AddAttribute ("Name", pi.Name);
255                                 if (pi.Role != null)
256                                         sec.AddAttribute ("Role", pi.Role);
257                                 if (pi.IsAuthenticated)
258                                         sec.AddAttribute ("Authenticated", "true");
259                                 se.AddChild (sec);
260                         }
261                         return se;
262                 }
263
264                 public IPermission Union (IPermission target)
265                 {
266                         if (target == null)
267                                 return Copy ();
268                         if (! (target is PrincipalPermission))
269                                 throw new ArgumentException ("wrong type");
270
271                         PrincipalPermission o = (PrincipalPermission) target;
272                         if (IsUnrestricted () || o.IsUnrestricted ())
273                                 return new PrincipalPermission (PermissionState.Unrestricted);
274
275                         PrincipalPermission union = new PrincipalPermission (principals);
276                         foreach (PrincipalInfo pi in o.principals)
277                                 union.principals.Add (pi);
278
279                         return union;
280                 }
281
282                 // IBuiltInPermission
283                 int IBuiltInPermission.GetTokenIndex ()
284                 {
285                         return 8;
286                 }
287         }
288 }