[linker] Provide better error message when an error occurs while processing xml descr...
[mono.git] / mcs / class / System / Mono.Net.Security / LegacySslStream.cs
1 //
2 // System.Net.Security.SslStream.cs
3 //
4 // Authors:
5 //      Tim Coleman (tim@timcoleman.com)
6 //      Atsushi Enomoto (atsushi@ximian.com)
7 //      Marek Safar (marek.safar@gmail.com)
8 //
9 // Copyright (C) Tim Coleman, 2004
10 // (c) 2004,2007 Novell, Inc. (http://www.novell.com)
11 // Copyright 2011 Xamarin Inc.
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 #if SECURITY_DEP
36
37 #if MONO_X509_ALIAS
38 extern alias PrebuiltSystem;
39 #endif
40 #if MONO_SECURITY_ALIAS
41 extern alias MonoSecurity;
42 #endif
43
44 #if MONO_SECURITY_ALIAS
45 using MonoCipherAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.CipherAlgorithmType;
46 using MonoHashAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.HashAlgorithmType;
47 using MonoExchangeAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.ExchangeAlgorithmType;
48 using MonoSecurityProtocolType = MonoSecurity::Mono.Security.Protocol.Tls.SecurityProtocolType;
49 using MonoSecurity::Mono.Security.Protocol.Tls;
50 using MonoSecurity::Mono.Security.Interface;
51 #else
52 using MonoCipherAlgorithmType = Mono.Security.Protocol.Tls.CipherAlgorithmType;
53 using MonoHashAlgorithmType = Mono.Security.Protocol.Tls.HashAlgorithmType;
54 using MonoExchangeAlgorithmType = Mono.Security.Protocol.Tls.ExchangeAlgorithmType;
55 using MonoSecurityProtocolType = Mono.Security.Protocol.Tls.SecurityProtocolType;
56 using Mono.Security.Protocol.Tls;
57 using Mono.Security.Interface;
58 #endif
59 #if MONO_X509_ALIAS
60 using X509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
61 #endif
62
63 using CipherAlgorithmType = System.Security.Authentication.CipherAlgorithmType;
64 using HashAlgorithmType = System.Security.Authentication.HashAlgorithmType;
65 using ExchangeAlgorithmType = System.Security.Authentication.ExchangeAlgorithmType;
66
67 using System;
68 using System.IO;
69 using System.Net;
70 using System.Net.Security;
71 using System.Security.Authentication;
72 using System.Security.Cryptography.X509Certificates;
73 using System.Security.Principal;
74 using System.Security.Cryptography;
75
76 using System.Threading.Tasks;
77
78 namespace Mono.Net.Security 
79 {
80         [MonoTODO ("Non-X509Certificate2 certificate is not supported")]
81         internal class LegacySslStream : AuthenticatedStream, IMonoSslStream
82         {
83                 #region Fields
84
85                 SslStreamBase ssl_stream;
86                 MonoTlsSettings settings;
87                 ICertificateValidator certificateValidator;
88
89                 #endregion // Fields
90
91                 #region Constructors
92
93                 public LegacySslStream (Stream innerStream)
94                         : this (innerStream, false)
95                 {
96                 }
97
98                 public LegacySslStream (Stream innerStream, bool leaveInnerStreamOpen)
99                         : this (innerStream, leaveInnerStreamOpen, null)
100                 {
101                 }
102
103                 public LegacySslStream (Stream innerStream, bool leaveInnerStreamOpen, MonoTlsSettings settings)
104                         : base (innerStream, leaveInnerStreamOpen)
105                 {
106                         this.settings = settings;
107                         this.certificateValidator = ChainValidationHelper.GetDefaultValidator (settings);
108                 }
109                 #endregion // Constructors
110
111                 #region Properties
112
113                 public override bool CanRead {
114                         get { return InnerStream.CanRead; }
115                 }
116
117                 public override bool CanSeek {
118                         get { return InnerStream.CanSeek; }
119                 }
120
121                 public override bool CanTimeout {
122                         get { return InnerStream.CanTimeout; }
123                 }
124
125                 public override bool CanWrite {
126                         get { return InnerStream.CanWrite; }
127                 }
128
129                 public override long Length {
130                         get { return InnerStream.Length; }
131                 }
132
133                 public override long Position {
134                         get { return InnerStream.Position; }
135                         set {
136                                 throw new NotSupportedException ("This stream does not support seek operations");
137                         }
138                 }
139
140                 // AuthenticatedStream overrides
141
142                 public override bool IsAuthenticated { 
143                         get { return ssl_stream != null; }
144                 }
145
146                 public override bool IsEncrypted { 
147                         get { return IsAuthenticated; }
148                 }
149
150                 public override bool IsMutuallyAuthenticated { 
151                         get { return IsAuthenticated && (IsServer ? RemoteCertificate != null : LocalCertificate != null); }
152                 }
153
154                 public override bool IsServer { 
155                         get { return ssl_stream is SslServerStream; }
156                 }
157
158                 public override bool IsSigned { 
159                         get { return IsAuthenticated; }
160                 }
161
162                 public override int ReadTimeout {
163                         get { return InnerStream.ReadTimeout; }
164                         set { InnerStream.ReadTimeout = value; }
165                 }
166
167                 public override int WriteTimeout {
168                         get { return InnerStream.WriteTimeout; }
169                         set { InnerStream.WriteTimeout = value; }
170                 }
171
172                 // SslStream
173
174                 public virtual bool CheckCertRevocationStatus {
175                         get {
176                                 if (!IsAuthenticated)
177                                         return false;
178
179                                 return ssl_stream.CheckCertRevocationStatus;
180                         }
181                 }
182
183                 public virtual CipherAlgorithmType CipherAlgorithm  {
184                         get {
185                                 CheckConnectionAuthenticated ();
186
187                                 switch (ssl_stream.CipherAlgorithm) {
188                                 case MonoCipherAlgorithmType.Des:
189                                         return CipherAlgorithmType.Des;
190                                 case MonoCipherAlgorithmType.None:
191                                         return CipherAlgorithmType.None;
192                                 case MonoCipherAlgorithmType.Rc2:
193                                         return CipherAlgorithmType.Rc2;
194                                 case MonoCipherAlgorithmType.Rc4:
195                                         return CipherAlgorithmType.Rc4;
196                                 case MonoCipherAlgorithmType.SkipJack:
197                                         break;
198                                 case MonoCipherAlgorithmType.TripleDes:
199                                         return CipherAlgorithmType.TripleDes;
200                                 case MonoCipherAlgorithmType.Rijndael:
201                                         switch (ssl_stream.CipherStrength) {
202                                         case 128:
203                                                 return CipherAlgorithmType.Aes128;
204                                         case 192:
205                                                 return CipherAlgorithmType.Aes192;
206                                         case 256:
207                                                 return CipherAlgorithmType.Aes256;
208                                         }
209                                         break;
210                                 }
211
212                                 throw new InvalidOperationException ("Not supported cipher algorithm is in use. It is likely a bug in SslStream.");
213                         }
214                 }
215
216                 public virtual int CipherStrength  {
217                         get {
218                                 CheckConnectionAuthenticated ();
219
220                                 return ssl_stream.CipherStrength;
221                         }
222                 }
223
224                 public virtual HashAlgorithmType HashAlgorithm  {
225                         get {
226                                 CheckConnectionAuthenticated ();
227
228                                 switch (ssl_stream.HashAlgorithm) {
229                                 case MonoHashAlgorithmType.Md5:
230                                         return HashAlgorithmType.Md5;
231                                 case MonoHashAlgorithmType.None:
232                                         return HashAlgorithmType.None;
233                                 case MonoHashAlgorithmType.Sha1:
234                                         return HashAlgorithmType.Sha1;
235                                 }
236
237                                 throw new InvalidOperationException ("Not supported hash algorithm is in use. It is likely a bug in SslStream.");
238                         }
239                 }
240
241                 public virtual int HashStrength  {
242                         get {
243                                 CheckConnectionAuthenticated ();
244
245                                 return ssl_stream.HashStrength;
246                         }
247                 }
248
249                 public virtual ExchangeAlgorithmType KeyExchangeAlgorithm { 
250                         get {
251                                 CheckConnectionAuthenticated ();
252
253                                 switch (ssl_stream.KeyExchangeAlgorithm) {
254                                 case MonoExchangeAlgorithmType.DiffieHellman:
255                                         return ExchangeAlgorithmType.DiffieHellman;
256                                 case MonoExchangeAlgorithmType.Fortezza:
257                                         break;
258                                 case MonoExchangeAlgorithmType.None:
259                                         return ExchangeAlgorithmType.None;
260                                 case MonoExchangeAlgorithmType.RsaKeyX:
261                                         return ExchangeAlgorithmType.RsaKeyX;
262                                 case MonoExchangeAlgorithmType.RsaSign:
263                                         return ExchangeAlgorithmType.RsaSign;
264                                 }
265
266                                 throw new InvalidOperationException ("Not supported exchange algorithm is in use. It is likely a bug in SslStream.");
267                         }
268                 }
269
270                 public virtual int KeyExchangeStrength { 
271                         get {
272                                 CheckConnectionAuthenticated ();
273
274                                 return ssl_stream.KeyExchangeStrength;
275                         }
276                 }
277
278                 X509Certificate IMonoSslStream.InternalLocalCertificate {
279                         get {
280                                 return IsServer ? ssl_stream.ServerCertificate : ((SslClientStream) ssl_stream).SelectedClientCertificate;
281                         }
282                 }
283
284                 public virtual X509Certificate LocalCertificate {
285                         get {
286                                 CheckConnectionAuthenticated ();
287
288                                 return IsServer ? ssl_stream.ServerCertificate : ((SslClientStream) ssl_stream).SelectedClientCertificate;
289                         }
290                 }
291
292                 public virtual X509Certificate RemoteCertificate {
293                         get {
294                                 CheckConnectionAuthenticated ();
295                                 return !IsServer ? ssl_stream.ServerCertificate : ((SslServerStream) ssl_stream).ClientCertificate;
296                         }
297                 }
298
299                 public virtual SslProtocols SslProtocol {
300                         get {
301                                 CheckConnectionAuthenticated ();
302
303                                 switch (ssl_stream.SecurityProtocol) {
304                                 case MonoSecurityProtocolType.Default:
305                                         return SslProtocols.Default;
306                                 case MonoSecurityProtocolType.Ssl2:
307                                         return SslProtocols.Ssl2;
308                                 case MonoSecurityProtocolType.Ssl3:
309                                         return SslProtocols.Ssl3;
310                                 case MonoSecurityProtocolType.Tls:
311                                         return SslProtocols.Tls;
312                                 }
313
314                                 throw new InvalidOperationException ("Not supported SSL/TLS protocol is in use. It is likely a bug in SslStream.");
315                         }
316                 }
317
318                 #endregion // Properties
319
320                 #region Methods
321
322 /*
323                 AsymmetricAlgorithm GetPrivateKey (X509Certificate cert, string targetHost)
324                 {
325                         // FIXME: what can I do for non-X509Certificate2 ?
326                         X509Certificate2 cert2 = cert as X509Certificate2;
327                         return cert2 != null ? cert2.PrivateKey : null;
328                 }
329 */
330                 X509Certificate OnCertificateSelection (X509CertificateCollection clientCerts, X509Certificate serverCert, string targetHost, X509CertificateCollection serverRequestedCerts)
331                 {
332                         string [] acceptableIssuers = new string [serverRequestedCerts != null ? serverRequestedCerts.Count : 0];
333                         for (int i = 0; i < acceptableIssuers.Length; i++)
334                                 acceptableIssuers [i] = serverRequestedCerts [i].GetIssuerName ();
335                         return certificateValidator.SelectClientCertificate (targetHost, clientCerts, serverCert, acceptableIssuers);
336                 }
337
338                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState)
339                 {
340                         return BeginAuthenticateAsClient (targetHost, new X509CertificateCollection (), SslProtocols.Tls, false, asyncCallback, asyncState);
341                 }
342
343                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
344                 {
345                         if (IsAuthenticated)
346                                 throw new InvalidOperationException ("This SslStream is already authenticated");
347
348                         SslClientStream s = new SslClientStream (InnerStream, targetHost, !LeaveInnerStreamOpen, GetMonoSslProtocol (enabledSslProtocols), clientCertificates);
349                         s.CheckCertRevocationStatus = checkCertificateRevocation;
350
351                         // Due to the Mono.Security internal, it cannot reuse
352                         // the delegated argument, as Mono.Security creates 
353                         // another instance of X509Certificate which lacks 
354                         // private key but is filled the private key via this
355                         // delegate.
356                         s.PrivateKeyCertSelectionDelegate = delegate (X509Certificate cert, string host) {
357                                 string hash = cert.GetCertHashString ();
358                                 // ... so, we cannot use the delegate argument.
359                                 foreach (X509Certificate cc in clientCertificates) {
360                                         if (cc.GetCertHashString () != hash)
361                                                 continue;
362                                         X509Certificate2 cert2 = cc as X509Certificate2;
363                                         cert2 = cert2 ?? new X509Certificate2 (cc);
364                                         return cert2.PrivateKey;
365                                 }
366                                 return null;
367                         };
368
369                         // Even if validation_callback is null this allows us to verify requests where the user
370                         // does not provide a verification callback but attempts to authenticate with the website
371                         // as a client (see https://bugzilla.xamarin.com/show_bug.cgi?id=18962 for an example)
372                         s.ServerCertValidation2 += (mcerts) => {
373                                 X509CertificateCollection certs = null;
374                                 if (mcerts != null) {
375                                         certs = new X509CertificateCollection ();
376                                         for (int i = 0; i < mcerts.Count; i++)
377                                                 certs.Add (new X509Certificate2 (mcerts [i].RawData));
378                                 }
379                                 return ((ChainValidationHelper)certificateValidator).ValidateChain (targetHost, certs);
380                         };
381                         s.ClientCertSelectionDelegate = OnCertificateSelection;
382
383                         ssl_stream = s;
384
385                         return BeginWrite (new byte [0], 0, 0, asyncCallback, asyncState);
386                 }
387
388                 public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
389                 {
390                         CheckConnectionAuthenticated ();
391
392                         return ssl_stream.BeginRead (buffer, offset, count, asyncCallback, asyncState);
393                 }
394
395                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState)
396                 {
397                         return BeginAuthenticateAsServer (serverCertificate, false, SslProtocols.Tls, false, asyncCallback, asyncState);
398                 }
399
400                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
401                 {
402                         if (IsAuthenticated)
403                                 throw new InvalidOperationException ("This SslStream is already authenticated");
404
405                         SslServerStream s = new SslServerStream (InnerStream, serverCertificate, false, clientCertificateRequired, !LeaveInnerStreamOpen, GetMonoSslProtocol (enabledSslProtocols));
406                         s.CheckCertRevocationStatus = checkCertificateRevocation;
407                         // Due to the Mono.Security internal, it cannot reuse
408                         // the delegated argument, as Mono.Security creates 
409                         // another instance of X509Certificate which lacks 
410                         // private key but is filled the private key via this
411                         // delegate.
412                         s.PrivateKeyCertSelectionDelegate = delegate (X509Certificate cert, string targetHost) {
413                                 // ... so, we cannot use the delegate argument.
414                                 X509Certificate2 cert2 = serverCertificate as X509Certificate2 ?? new X509Certificate2 (serverCertificate);
415                                 return cert2 != null ? cert2.PrivateKey : null;
416                         };
417
418                         s.ClientCertValidationDelegate = delegate (X509Certificate cert, int[] certErrors) {
419                                 var errors = certErrors.Length > 0 ? MonoSslPolicyErrors.RemoteCertificateChainErrors : MonoSslPolicyErrors.None;
420                                 return ((ChainValidationHelper)certificateValidator).ValidateClientCertificate (cert, errors);
421                         };
422
423                         ssl_stream = s;
424
425                         return BeginWrite (new byte[0], 0, 0, asyncCallback, asyncState);
426                 }
427
428                 MonoSecurityProtocolType GetMonoSslProtocol (SslProtocols ms)
429                 {
430                         switch (ms) {
431                         case SslProtocols.Ssl2:
432                                 return MonoSecurityProtocolType.Ssl2;
433                         case SslProtocols.Ssl3:
434                                 return MonoSecurityProtocolType.Ssl3;
435                         case SslProtocols.Tls:
436                                 return MonoSecurityProtocolType.Tls;
437                         default:
438                                 return MonoSecurityProtocolType.Default;
439                         }
440                 }
441
442                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
443                 {
444                         CheckConnectionAuthenticated ();
445
446                         return ssl_stream.BeginWrite (buffer, offset, count, asyncCallback, asyncState);
447                 }
448
449                 public virtual void AuthenticateAsClient (string targetHost)
450                 {
451                         AuthenticateAsClient (targetHost, new X509CertificateCollection (), SslProtocols.Tls, false);
452                 }
453
454                 public virtual void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
455                 {
456                         EndAuthenticateAsClient (BeginAuthenticateAsClient (
457                                 targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, null, null));
458                 }
459
460                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate)
461                 {
462                         AuthenticateAsServer (serverCertificate, false, SslProtocols.Tls, false);
463                 }
464
465                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
466                 {
467                         EndAuthenticateAsServer (BeginAuthenticateAsServer (
468                                 serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, null, null));
469                 }
470
471                 protected override void Dispose (bool disposing)
472                 {
473                         if (disposing) {
474                                 if (ssl_stream != null)
475                                         ssl_stream.Dispose ();
476                                 ssl_stream = null;
477                         }
478                         base.Dispose (disposing);
479                 }
480
481                 public virtual void EndAuthenticateAsClient (IAsyncResult asyncResult)
482                 {
483                         CheckConnectionAuthenticated ();
484
485                         if (CanRead)
486                                 ssl_stream.EndRead (asyncResult);
487                         else
488                                 ssl_stream.EndWrite (asyncResult);
489                 }
490
491                 public virtual void EndAuthenticateAsServer (IAsyncResult asyncResult)
492                 {
493                         CheckConnectionAuthenticated ();
494
495                         if (CanRead)
496                                 ssl_stream.EndRead (asyncResult);
497                         else
498                                 ssl_stream.EndWrite (asyncResult);
499                 }
500
501                 public override int EndRead (IAsyncResult asyncResult)
502                 {
503                         CheckConnectionAuthenticated ();
504
505                         return ssl_stream.EndRead (asyncResult);
506                 }
507
508                 public override void EndWrite (IAsyncResult asyncResult)
509                 {
510                         CheckConnectionAuthenticated ();
511
512                         ssl_stream.EndWrite (asyncResult);
513                 }
514
515                 public override void Flush ()
516                 {
517                         CheckConnectionAuthenticated ();
518
519                         InnerStream.Flush ();
520                 }
521
522                 public override int Read (byte[] buffer, int offset, int count)
523                 {
524                         return EndRead (BeginRead (buffer, offset, count, null, null));
525                 }
526
527                 public override long Seek (long offset, SeekOrigin origin)
528                 {
529                         throw new NotSupportedException ("This stream does not support seek operations");
530                 }
531
532                 public override void SetLength (long value)
533                 {
534                         InnerStream.SetLength (value);
535                 }
536
537                 public override void Write (byte[] buffer, int offset, int count)
538                 {
539                         EndWrite (BeginWrite (buffer, offset, count, null, null));
540                 }
541
542                 public void Write (byte[] buffer)
543                 {
544                         Write (buffer, 0, buffer.Length);
545                 }
546
547                 void CheckConnectionAuthenticated ()
548                 {
549                         if (!IsAuthenticated)
550                                 throw new InvalidOperationException ("This operation is invalid until it is successfully authenticated");
551                 }
552
553                 public virtual Task AuthenticateAsClientAsync (string targetHost)
554                 {
555                         return Task.Factory.FromAsync (BeginAuthenticateAsClient, EndAuthenticateAsClient, targetHost, null);
556                 }
557
558                 public virtual Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
559                 {
560                         var t = Tuple.Create (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, this);
561
562                         return Task.Factory.FromAsync ((callback, state) => {
563                                 var d = (Tuple<string, X509CertificateCollection, SslProtocols, bool, LegacySslStream>) state;
564                                 return d.Item5.BeginAuthenticateAsClient (d.Item1, d.Item2, d.Item3, d.Item4, callback, null);
565                         }, EndAuthenticateAsClient, t);
566                 }
567
568                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate)
569                 {
570                         return Task.Factory.FromAsync (BeginAuthenticateAsServer, EndAuthenticateAsServer, serverCertificate, null);
571                 }
572
573                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
574                 {
575                         var t = Tuple.Create (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, this);
576
577                         return Task.Factory.FromAsync ((callback, state) => {
578                                 var d = (Tuple<X509Certificate, bool, SslProtocols, bool, LegacySslStream>) state;
579                                 return d.Item5.BeginAuthenticateAsServer (d.Item1, d.Item2, d.Item3, d.Item4, callback, null);
580                         }, EndAuthenticateAsServer, t);
581                 }
582
583                 #endregion // Methods
584
585                 #region IMonoSslStream
586
587                 AuthenticatedStream IMonoSslStream.AuthenticatedStream {
588                         get { return this; }
589                 }
590
591                 TransportContext IMonoSslStream.TransportContext {
592                         get { throw new NotSupportedException (); }
593                 }
594
595                 #endregion
596         }
597 }
598
599 #endif