Halve the stack depth for both the new single step tests
[mono.git] / mcs / class / referencesource / System / net / System / Net / Configuration / DefaultProxySection.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="DefaultProxySection.cs" company="Microsoft Corporation">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 namespace System.Net.Configuration
8 {
9     using System.Collections.Generic;
10     using System.Configuration;
11     using System.Globalization;
12     using System.Net;
13     using System.Reflection;
14     using System.Threading;
15     using System.Security;
16     using System.Security.Permissions;
17     using System.Security.Principal;
18     using System.ComponentModel;
19
20
21     public sealed class DefaultProxySection : ConfigurationSection
22     {
23         public DefaultProxySection()
24         {
25             this.properties.Add(this.bypasslist);
26             this.properties.Add(this.module);
27             this.properties.Add(this.proxy);
28             this.properties.Add(this.enabled);
29             this.properties.Add(this.useDefaultCredentials);
30         }
31
32         protected override void PostDeserialize()
33         {
34             // Perf optimization. If the configuration is coming from machine.config
35             // It is safe and we don't need to check for permissions.
36             if (EvaluationContext.IsMachineLevel)
37                 return;
38
39             try {
40                 ExceptionHelper.WebPermissionUnrestricted.Demand();
41             } catch (Exception exception) {
42                 throw new ConfigurationErrorsException(
43                               SR.GetString(SR.net_config_section_permission, 
44                                            ConfigurationStrings.DefaultProxySectionName),
45                               exception);
46             }
47         }
48          
49         [ConfigurationProperty(ConfigurationStrings.BypassList)]
50         public BypassElementCollection BypassList
51         {
52             get { return (BypassElementCollection)this[this.bypasslist]; }
53         }
54
55         [ConfigurationProperty(ConfigurationStrings.Module)]
56         public ModuleElement Module
57         {
58             get { return (ModuleElement)this[this.module]; }
59         }
60
61         protected override ConfigurationPropertyCollection Properties
62         {
63             get { return this.properties; }
64         }
65         
66         [ConfigurationProperty(ConfigurationStrings.Proxy)]
67         public ProxyElement Proxy
68         {
69             get { return (ProxyElement)this[this.proxy]; }
70         }
71
72         [ConfigurationProperty(ConfigurationStrings.Enabled, DefaultValue = true)]
73         public bool Enabled
74         {
75             get { return (bool) this[this.enabled]; }
76             set { this[this.enabled] = value; }
77         }
78
79         [ConfigurationProperty(ConfigurationStrings.UseDefaultCredentials, DefaultValue = false)]
80         public bool UseDefaultCredentials
81         {
82             get { return (bool) this[this.useDefaultCredentials]; }
83             set { this[this.useDefaultCredentials] = value; }
84         }
85
86         ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();
87
88         readonly ConfigurationProperty bypasslist =
89             new ConfigurationProperty(ConfigurationStrings.BypassList, 
90                                       typeof(BypassElementCollection), 
91                                       null,
92                                       ConfigurationPropertyOptions.None);
93
94         readonly ConfigurationProperty module =
95             new ConfigurationProperty(ConfigurationStrings.Module, 
96                                       typeof(ModuleElement), 
97                                       null,
98                                       ConfigurationPropertyOptions.None);
99
100         readonly ConfigurationProperty proxy =
101             new ConfigurationProperty(ConfigurationStrings.Proxy, 
102                                       typeof(ProxyElement), 
103                                       null,
104                                       ConfigurationPropertyOptions.None);
105
106         readonly ConfigurationProperty enabled =
107             new ConfigurationProperty(ConfigurationStrings.Enabled, 
108                                       typeof(bool), 
109                                       true, 
110                                       ConfigurationPropertyOptions.None);
111
112         readonly ConfigurationProperty useDefaultCredentials =
113             new ConfigurationProperty(ConfigurationStrings.UseDefaultCredentials, 
114                                       typeof(bool), 
115                                       false,
116                                       ConfigurationPropertyOptions.None);
117
118
119         // This allows us to prevent parent settings (machine.config) from propegating to higher config (app.config), unless
120         // the higher config doesn't contain the section at all.  That is, overriding defaultProxy is all-or-nothing.
121         // Template from [....].
122         protected override void Reset(ConfigurationElement parentElement)
123         {
124             // Ignore the parentElement parameter by changing it to the default settings
125             DefaultProxySection defaultElement = new DefaultProxySection();
126
127             // Initialize the parentElement to the right set of defaults (not needed now,
128             // but this will avoid errors in the future if SetDefaults is ever overridden in this class.
129             // ConfigurationElement::InitializeDefault is a no-op, so you aren\92t hurting perf by anything
130             // measurable. 
131             defaultElement.InitializeDefault();
132
133             // Finally, pass it to the base class to do the \93right things\94
134             base.Reset(defaultElement);
135         }
136     }
137
138     internal sealed class DefaultProxySectionInternal
139     {
140         [SecurityPermission(SecurityAction.Assert, Flags=SecurityPermissionFlag.ControlPrincipal)]
141         internal DefaultProxySectionInternal(DefaultProxySection section)
142         {
143             // If enabled is false, skip everything.
144             if (!section.Enabled)
145             {
146                 return;
147             }
148
149             // If nothing else is set, use the system default.
150             if (section.Proxy.AutoDetect == ProxyElement.AutoDetectValues.Unspecified &&
151                 section.Proxy.ScriptLocation == null &&
152                 String.IsNullOrEmpty(section.Module.Type) &&
153                 section.Proxy.UseSystemDefault != ProxyElement.UseSystemDefaultValues.True &&
154                 section.Proxy.ProxyAddress == null &&
155                 section.Proxy.BypassOnLocal == ProxyElement.BypassOnLocalValues.Unspecified &&
156                 section.BypassList.Count == 0)
157             {
158                 // Old-style indication to turn off the proxy.
159                 if (section.Proxy.UseSystemDefault == ProxyElement.UseSystemDefaultValues.False)
160                 {
161                     this.webProxy = new EmptyWebProxy();
162
163                     // Intentionally ignoring UseDefaultCredentials in this case.
164                     return;
165                 }
166
167                 // Suspend impersonation.
168                 try {
169                     new SecurityPermission(SecurityPermissionFlag.ControlPrincipal | SecurityPermissionFlag.UnmanagedCode).Assert();
170 #if !FEATURE_PAL
171                     using(WindowsIdentity.Impersonate(IntPtr.Zero))
172 #endif // !FEATURE_PAL
173                     {
174                         CodeAccessPermission.RevertAssert();
175                         this.webProxy = new WebRequest.WebProxyWrapper(new WebProxy(true));
176                     }
177                 } catch {
178                     throw;
179                 }
180             }
181             else
182             {
183                 // First, check out if we are using a different module type
184                 if (!String.IsNullOrEmpty(section.Module.Type))
185                 {
186                     Type theType = Type.GetType(section.Module.Type, true, true);
187                     
188                     if ((theType.Attributes & TypeAttributes.VisibilityMask) != TypeAttributes.Public)
189                         throw new ConfigurationErrorsException(SR.GetString(SR.net_config_proxy_module_not_public));
190                     
191                     // verify that its of the proper type of IWebProxy
192                     if (!typeof(IWebProxy).IsAssignableFrom(theType))
193                     {
194                         throw new InvalidCastException(SR.GetString(SR.net_invalid_cast,
195                                                                     theType.FullName,
196                                                                     "IWebProxy"));
197                     }
198                     this.webProxy = (IWebProxy)Activator.CreateInstance(
199                                     theType,
200                                     BindingFlags.CreateInstance
201                                     | BindingFlags.Instance
202                                     | BindingFlags.NonPublic
203                                     | BindingFlags.Public,
204                                     null,          // Binder
205                                     new object[0], // no arguments
206                                     CultureInfo.InvariantCulture
207                                     );
208                 }
209                 else if (section.Proxy.UseSystemDefault == ProxyElement.UseSystemDefaultValues.True &&
210                          section.Proxy.AutoDetect == ProxyElement.AutoDetectValues.Unspecified &&
211                          section.Proxy.ScriptLocation == null)
212                 {
213                     // Suspend impersonation.  This setting is deprecated but required for Everett compat.
214                     try {
215                         new SecurityPermission(SecurityPermissionFlag.ControlPrincipal | SecurityPermissionFlag.UnmanagedCode).Assert();
216 #if !FEATURE_PAL
217                         using(WindowsIdentity.Impersonate(IntPtr.Zero))
218 #endif // !FEATURE_PAL
219                         {
220                             CodeAccessPermission.RevertAssert();
221                             this.webProxy = new WebProxy(false);
222                         }
223                     } catch {
224                         throw;
225                     }
226                 }
227                 else
228                 {
229                     this.webProxy = new WebProxy();
230                 }
231
232                 WebProxy tempProxy = this.webProxy as WebProxy;
233
234                 if (tempProxy != null)
235                 {
236                     if (section.Proxy.AutoDetect != ProxyElement.AutoDetectValues.Unspecified)
237                     {
238                         tempProxy.AutoDetect = section.Proxy.AutoDetect == ProxyElement.AutoDetectValues.True;
239                     }
240                     if (section.Proxy.ScriptLocation != null)
241                     {
242                         tempProxy.ScriptLocation = section.Proxy.ScriptLocation;
243                     }
244                     if (section.Proxy.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
245                     {
246                         tempProxy.BypassProxyOnLocal = section.Proxy.BypassOnLocal == ProxyElement.BypassOnLocalValues.True;
247                     }
248                     if (section.Proxy.ProxyAddress != null)
249                     {
250                         tempProxy.Address = section.Proxy.ProxyAddress;
251                     }
252                     int bypassListSize = section.BypassList.Count;
253                     if (bypassListSize > 0)
254                     {
255                         string[] bypassList = new string[section.BypassList.Count];
256                         for (int index = 0; index < bypassListSize; ++index)
257                         {
258                             bypassList[index] = section.BypassList[index].Address;
259                         }
260                         tempProxy.BypassList = bypassList;
261                     }
262
263                     // Wrap it if type not explicitly specified in Module.
264                     if (section.Module.Type == null)
265                     {
266                         this.webProxy = new WebRequest.WebProxyWrapper(tempProxy);
267                     }
268                 }
269             }
270
271             // Now apply UseDefaultCredentials if there's a proxy.
272             if (this.webProxy != null && section.UseDefaultCredentials)
273             {
274                 this.webProxy.Credentials = SystemNetworkCredential.defaultCredential;
275             }
276         }
277
278         internal static object ClassSyncObject
279         {
280             get
281             {
282                 if (classSyncObject == null)
283                 {
284                     object o = new object();
285                     Interlocked.CompareExchange(ref classSyncObject, o, null);
286                 }
287                 return classSyncObject;
288             }
289         }
290
291         static internal DefaultProxySectionInternal GetSection()
292         {
293             lock (DefaultProxySectionInternal.ClassSyncObject)
294             {
295                 DefaultProxySection section = PrivilegedConfigurationManager.GetSection(ConfigurationStrings.DefaultProxySectionPath) as DefaultProxySection;
296                 if (section == null)
297                     return null;
298
299                 try
300                 {
301                     return new DefaultProxySectionInternal(section);
302                 }
303                 catch (Exception exception)
304                 {
305                     if (NclUtilities.IsFatal(exception)) throw;
306
307                     throw new ConfigurationErrorsException(SR.GetString(SR.net_config_proxy), exception);
308                 }
309             }
310         }
311
312         internal IWebProxy WebProxy
313         {
314             get { return this.webProxy; }
315         }
316
317         private IWebProxy webProxy;
318         private static object classSyncObject;
319     }
320 }