merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / System / System.Net / SocketPermission.cs
1 //\r
2 // System.Net.SocketPermission.cs\r
3 //\r
4 // Author:\r
5 //   Lawrence Pit (loz@cable.a2000.nl)\r
6 //\r
7 \r
8 //\r
9 // Permission is hereby granted, free of charge, to any person obtaining\r
10 // a copy of this software and associated documentation files (the\r
11 // "Software"), to deal in the Software without restriction, including\r
12 // without limitation the rights to use, copy, modify, merge, publish,\r
13 // distribute, sublicense, and/or sell copies of the Software, and to\r
14 // permit persons to whom the Software is furnished to do so, subject to\r
15 // the following conditions:\r
16 // \r
17 // The above copyright notice and this permission notice shall be\r
18 // included in all copies or substantial portions of the Software.\r
19 // \r
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
27 //\r
28 \r
29 using System.Collections;\r
30 using System.Security;\r
31 using System.Security.Permissions;\r
32 \r
33 namespace System.Net {\r
34 \r
35         [Serializable]\r
36         public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission\r
37         {\r
38                 // Fields\r
39                 ArrayList m_acceptList = new ArrayList ();\r
40                 ArrayList m_connectList = new ArrayList ();\r
41                 bool m_noRestriction;\r
42                 \r
43                 // Constructors\r
44                 public SocketPermission (PermissionState state) : base () \r
45                 {                                               \r
46                         m_noRestriction = (state == PermissionState.Unrestricted);\r
47                 }\r
48                 \r
49                 public SocketPermission (NetworkAccess access, TransportType transport, \r
50                                          string hostName, int portNumber) : base () \r
51                 {\r
52                         m_noRestriction = false;\r
53                         AddPermission (access, transport, hostName, portNumber);\r
54                 }       \r
55                 \r
56                 // Fields\r
57                 public const int AllPorts = -1;\r
58                 \r
59                 // Properties\r
60 \r
61                 public IEnumerator AcceptList {\r
62                         get { return m_acceptList.GetEnumerator (); }\r
63                 }\r
64 \r
65                 public IEnumerator ConnectList {\r
66                         get { return m_connectList.GetEnumerator (); }\r
67                 }\r
68                 \r
69                 // Methods\r
70                 \r
71                 public void AddPermission (NetworkAccess access, TransportType transport,\r
72                                            string hostName, int portNumber)\r
73                 {\r
74                         if (m_noRestriction)\r
75                                 return;\r
76                                 \r
77                         EndpointPermission permission = new EndpointPermission (hostName, portNumber, transport);\r
78 \r
79                         if (access == NetworkAccess.Accept)\r
80                                 m_acceptList.Add (permission);\r
81                         else\r
82                                 m_connectList.Add (permission);\r
83                 }               \r
84                 \r
85                 public override IPermission Copy ()\r
86                 {\r
87                         SocketPermission permission;\r
88 \r
89                         permission = new SocketPermission (m_noRestriction ? \r
90                                                 PermissionState.Unrestricted : \r
91                                                 PermissionState.None);\r
92 \r
93                         // as EndpointPermission's are immutable it's safe to do a shallow copy.                                                \r
94                         permission.m_connectList = (ArrayList) this.m_connectList.Clone ();\r
95                         permission.m_acceptList = (ArrayList) this.m_acceptList.Clone ();\r
96 \r
97                         return permission;              \r
98                 }\r
99                 \r
100                 public override IPermission Intersect (IPermission target)\r
101                 {\r
102                         if (target == null) \r
103                                 return null;\r
104                                 \r
105                         SocketPermission perm = target as SocketPermission;\r
106                         if (perm == null) \r
107                                 throw new ArgumentException ("Argument not of type SocketPermission");\r
108                         \r
109                         if (m_noRestriction) \r
110                                 return IntersectEmpty (perm) ? null : perm.Copy ();\r
111                                 \r
112                         if (perm.m_noRestriction)\r
113                                 return IntersectEmpty (this) ? null : this.Copy ();\r
114                                 \r
115                         SocketPermission newperm = new SocketPermission (PermissionState.None);\r
116                         Intersect (this.m_connectList, perm.m_connectList, newperm.m_connectList);\r
117                         Intersect (this.m_acceptList, perm.m_acceptList, newperm.m_acceptList);\r
118                         return IntersectEmpty (newperm) ? null : newperm;                       \r
119                 }\r
120                 \r
121                 private bool IntersectEmpty (SocketPermission permission)               \r
122                 {\r
123                         return !permission.m_noRestriction && \r
124                                (permission.m_connectList.Count == 0) &&\r
125                                (permission.m_acceptList.Count == 0);\r
126                 }\r
127                 \r
128                 private void Intersect (ArrayList list1, ArrayList list2, ArrayList result)\r
129                 {\r
130                         foreach (EndpointPermission perm1 in list1) {\r
131                                 foreach (EndpointPermission perm2 in list2) {\r
132                                         EndpointPermission perm = perm1.Intersect (perm2);\r
133                                         if (perm != null) {\r
134                                                 // instead of the below it's also okay to simply do:\r
135                                                 //     result.Add (perm);\r
136                                                 // below is only done to avoid double entries                                           \r
137                                                 bool replaced = false;\r
138                                                 for (int i = 0; i < result.Count; i++) {\r
139                                                         EndpointPermission res = (EndpointPermission) result [i];\r
140                                                         EndpointPermission resperm = perm.Intersect (res);\r
141                                                         if (resperm != null) {\r
142                                                                 result [i] = resperm;\r
143                                                                 replaced = true;\r
144                                                                 break;\r
145                                                         }\r
146                                                 }\r
147                                                 if (!replaced) \r
148                                                         result.Add (perm);\r
149                                         }\r
150                                 }\r
151                         }\r
152                 }\r
153                 \r
154                 public override bool IsSubsetOf (IPermission target) \r
155                 {\r
156                         if (target == null)\r
157                                 return (!m_noRestriction && m_connectList.Count == 0 && m_acceptList.Count ==    0);\r
158                         \r
159                         SocketPermission perm = target as SocketPermission;\r
160 \r
161                         if (perm == null) \r
162                                 throw new ArgumentException ("Parameter target must be of type SocketPermission");\r
163                         \r
164                         if (perm.m_noRestriction) \r
165                                 return true;\r
166 \r
167                         if (this.m_noRestriction)\r
168                                 return false;\r
169 \r
170                         if (this.m_acceptList.Count == 0 && this.m_connectList.Count == 0)\r
171                                 return true;\r
172 \r
173                         if (perm.m_acceptList.Count == 0 && perm.m_connectList.Count == 0)\r
174                                 return false;\r
175 \r
176                         return IsSubsetOf (this.m_connectList, perm.m_connectList)\r
177                             && IsSubsetOf (this.m_acceptList, perm.m_acceptList);\r
178                 }\r
179 \r
180                 private bool IsSubsetOf (ArrayList list1, ArrayList list2)\r
181                 {\r
182                         foreach (EndpointPermission perm1 in list1) {\r
183                                 bool issubset = false;\r
184                                 foreach (EndpointPermission perm2 in list2) \r
185                                         if (perm1.IsSubsetOf (perm2)) {\r
186                                                 issubset = true;\r
187                                                 break;\r
188                                         }\r
189                                 if (!issubset) \r
190                                         return false;\r
191                         }\r
192                         return true;\r
193                 }\r
194                 \r
195                 public bool IsUnrestricted () \r
196                 {\r
197                         return m_noRestriction;\r
198                 }\r
199 \r
200                 /*\r
201                 \r
202                 SocketPermission s = new SocketPermission (NetworkAccess.Connect, TransportType.Tcp, "www.google.com", 80);\r
203                 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", 8080);\r
204                 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", SocketPermission.AllPorts);\r
205                 // s = new SocketPermission (PermissionState.None);\r
206                 SecurityElement sec = s.ToXml ();       \r
207                 Console.WriteLine (sec.ToString ());\r
208 \r
209                 This is sample xml output:\r
210 \r
211                 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"\r
212                              version="1">\r
213                    <ConnectAccess>\r
214                       <ENDPOINT host="www.google.com"\r
215                                 transport="Tcp"\r
216                                 port="80"/>\r
217                    </ConnectAccess>\r
218                    <AcceptAccess>\r
219                       <ENDPOINT host="localhost"\r
220                                 transport="All"\r
221                                 port="8080"/>\r
222                       <ENDPOINT host="localhost"\r
223                                 transport="All"\r
224                                 port="All"/>\r
225                    </AcceptAccess>\r
226                 </IPermission>\r
227 \r
228 \r
229 \r
230                 This is a sample unrestricted socketpermission, no matter how many permissions you add:                 \r
231 \r
232                 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"\r
233                              version="1"\r
234                              Unrestricted="true"/>\r
235 \r
236 \r
237                 This is a sample constructed restricted socketpermission with no permissions added:\r
238 \r
239                 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"\r
240                              version="1"/>\r
241                 */\r
242                 public override SecurityElement ToXml ()\r
243                 {\r
244              \r
245                         SecurityElement root = new SecurityElement ("IPermission");\r
246 \r
247                         root.AddAttribute ("class", this.GetType ().AssemblyQualifiedName);\r
248                         root.AddAttribute ("version", "1");\r
249                         if (m_noRestriction) {\r
250                                 root.AddAttribute ("Unrestricted", "true");                             \r
251                                 return root;\r
252                         }                               \r
253                                 \r
254                         if (this.m_connectList.Count > 0)\r
255                                 ToXml (root, "ConnectAccess", m_connectList.GetEnumerator ());\r
256                         \r
257                         if (this.m_acceptList.Count > 0) \r
258                                 ToXml (root, "AcceptAccess", m_acceptList.GetEnumerator ());                    \r
259                         \r
260                         return root;\r
261                 }\r
262                 \r
263                 private void ToXml (SecurityElement root, string childName, IEnumerator enumerator)\r
264                 {\r
265                         SecurityElement child = new SecurityElement (childName);\r
266                         while (enumerator.MoveNext ()) {\r
267                                 EndpointPermission perm = enumerator.Current as EndpointPermission;\r
268                                 SecurityElement grandchild = new SecurityElement ("ENDPOINT");\r
269                                 grandchild.AddAttribute ("host", perm.Hostname);\r
270                                 grandchild.AddAttribute ("transport", perm.Transport.ToString ());\r
271                                 grandchild.AddAttribute ("port", \r
272                                                 perm.Port == AllPorts \r
273                                                 ? "All" \r
274                                                 : ((Int32) perm.Port).ToString ());\r
275                                 child.AddChild (grandchild);\r
276                         }\r
277                         root.AddChild (child);\r
278                 }\r
279                 \r
280                 public override void FromXml (SecurityElement securityElement)\r
281                 {\r
282                         if (securityElement == null)\r
283                                 throw new ArgumentNullException ("securityElement");\r
284                                 \r
285                         // LAMESPEC: it says to throw an ArgumentNullException in this case                             \r
286                         if (securityElement.Tag != "IPermission")\r
287                                 throw new ArgumentException ("securityElement");\r
288                                 \r
289                         string unrestricted = securityElement.Attribute ("Unrestricted");\r
290                         if (unrestricted != null) {\r
291                                 this.m_noRestriction = (String.Compare (unrestricted, "true", true) == 0);\r
292                                 if (this.m_noRestriction)\r
293                                         return;\r
294                         }\r
295                         \r
296                         this.m_noRestriction = false;\r
297                         this.m_connectList = new ArrayList ();\r
298                         this.m_acceptList = new ArrayList ();\r
299                         \r
300                         ArrayList children = securityElement.Children;\r
301                         foreach (SecurityElement child in children) {\r
302                                 if (child.Tag == "ConnectAccess") \r
303                                         FromXml (child.Children, NetworkAccess.Connect);\r
304                                 else if (child.Tag == "AcceptAccess")\r
305                                         FromXml (child.Children, NetworkAccess.Accept);\r
306                         }\r
307                 }               \r
308                 \r
309                 private void FromXml (ArrayList endpoints, NetworkAccess access)\r
310                 {\r
311                         foreach (SecurityElement endpoint in endpoints) {\r
312                                 if (endpoint.Tag != "ENDPOINT")\r
313                                         continue;\r
314                                 string hostname = endpoint.Attribute ("host");\r
315                                 TransportType transport = \r
316                                         (TransportType) Enum.Parse (typeof (TransportType), \r
317                                                                     endpoint.Attribute ("transport"), \r
318                                                                     true);\r
319                                 string p = endpoint.Attribute ("port");\r
320                                 int port = 0;\r
321                                 if (p == "All") \r
322                                         port = SocketPermission.AllPorts;\r
323                                 else\r
324                                         port = Int32.Parse (p);\r
325 \r
326                                 AddPermission (access, transport, hostname, port);\r
327                         }\r
328                 }\r
329                 \r
330                 public override IPermission Union (IPermission target) \r
331                 {\r
332                         // LAMESPEC: according to spec we should throw an \r
333                         // exception when target is null. We'll follow the\r
334                         // behaviour of MS.Net instead of the spec, also\r
335                         // because it matches the Intersect behaviour.\r
336                         if (target == null)\r
337                                 return null;\r
338                                 // throw new ArgumentNullException ("target");\r
339                                 \r
340                         SocketPermission perm = target as SocketPermission;\r
341                         if (perm == null)\r
342                                 throw new ArgumentException ("Argument not of type SocketPermission");\r
343                         \r
344                         if (this.m_noRestriction || perm.m_noRestriction) \r
345                                 return new SocketPermission (PermissionState.Unrestricted);\r
346                                 \r
347                         SocketPermission copy = (SocketPermission) perm.Copy ();\r
348                         copy.m_acceptList.InsertRange (copy.m_acceptList.Count, this.m_acceptList);\r
349                         copy.m_connectList.InsertRange (copy.m_connectList.Count, this.m_connectList);                          \r
350                         \r
351                         return copy;\r
352                 }\r
353         }\r
354 }\r