1 //------------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------------------------
4 namespace System.ServiceModel.Configuration
5 {
6     using System;
7     using System.Collections.Generic;
8     using System.Configuration;
9     using System.Diagnostics;
10     using System.Reflection;
11     using System.Runtime;
12     using System.Runtime.Diagnostics;
13     using System.Security;
14     using System.Security.Permissions;
15     using System.ServiceModel;
16     using System.ServiceModel.Activation;
17     using System.ServiceModel.Diagnostics;
18 
19     static class ConfigurationHelpers
20     {
21         /// Be sure to update UnsafeGetAssociatedBindingCollectionElement if you modify this method
GetAssociatedBindingCollectionElement(ContextInformation evaluationContext, string bindingCollectionName)22         internal static BindingCollectionElement GetAssociatedBindingCollectionElement(ContextInformation evaluationContext, string bindingCollectionName)
23         {
24             BindingCollectionElement retVal = null;
25             BindingsSection bindingsSection = (BindingsSection)ConfigurationHelpers.GetAssociatedSection(evaluationContext, ConfigurationStrings.BindingsSectionGroupPath);
26 
27             if (null != bindingsSection)
28             {
29                 bindingsSection.UpdateBindingSections(evaluationContext);
30                 try
31                 {
32                     retVal = bindingsSection[bindingCollectionName];
33                 }
34                 catch (KeyNotFoundException)
35                 {
36                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
37                         new ConfigurationErrorsException(SR.GetString(SR.ConfigBindingExtensionNotFound,
38                         ConfigurationHelpers.GetBindingsSectionPath(bindingCollectionName))));
39                 }
40                 catch (NullReferenceException) // System.Configuration.ConfigurationElement bug
41                 {
42                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
43                         new ConfigurationErrorsException(SR.GetString(SR.ConfigBindingExtensionNotFound,
44                         ConfigurationHelpers.GetBindingsSectionPath(bindingCollectionName))));
45                 }
46             }
47 
48             return retVal;
49         }
50 
51         // Be sure to update GetAssociatedBindingCollectionElement if you modify this method
52         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetAssociatedSection which elevates.")]
53         [SecurityCritical]
UnsafeGetAssociatedBindingCollectionElement(ContextInformation evaluationContext, string bindingCollectionName)54         internal static BindingCollectionElement UnsafeGetAssociatedBindingCollectionElement(ContextInformation evaluationContext, string bindingCollectionName)
55         {
56             BindingCollectionElement retVal = null;
57             BindingsSection bindingsSection = (BindingsSection)ConfigurationHelpers.UnsafeGetAssociatedSection(evaluationContext, ConfigurationStrings.BindingsSectionGroupPath);
58 
59             if (null != bindingsSection)
60             {
61                 bindingsSection.UpdateBindingSections(evaluationContext);
62                 try
63                 {
64                     retVal = bindingsSection[bindingCollectionName];
65                 }
66                 catch (KeyNotFoundException)
67                 {
68                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
69                         new ConfigurationErrorsException(SR.GetString(SR.ConfigBindingExtensionNotFound,
70                         ConfigurationHelpers.GetBindingsSectionPath(bindingCollectionName))));
71                 }
72                 catch (NullReferenceException) // System.Configuration.ConfigurationElement bug
73                 {
74                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
75                         new ConfigurationErrorsException(SR.GetString(SR.ConfigBindingExtensionNotFound,
76                         ConfigurationHelpers.GetBindingsSectionPath(bindingCollectionName))));
77                 }
78             }
79 
80             return retVal;
81         }
82 
83         /// Be sure to update UnsafeGetAssociatedEndpointCollectionElement if you modify this method
GetAssociatedEndpointCollectionElement(ContextInformation evaluationContext, string endpointCollectionName)84         internal static EndpointCollectionElement GetAssociatedEndpointCollectionElement(ContextInformation evaluationContext, string endpointCollectionName)
85         {
86             EndpointCollectionElement retVal = null;
87             StandardEndpointsSection endpointsSection = (StandardEndpointsSection)ConfigurationHelpers.GetAssociatedSection(evaluationContext, ConfigurationStrings.StandardEndpointsSectionPath);
88 
89             if (null != endpointsSection)
90             {
91                 endpointsSection.UpdateEndpointSections(evaluationContext);
92                 try
93                 {
94                     retVal = (EndpointCollectionElement)endpointsSection[endpointCollectionName];
95                 }
96                 catch (KeyNotFoundException)
97                 {
98                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
99                         new ConfigurationErrorsException(SR.GetString(SR.ConfigEndpointExtensionNotFound,
100                         ConfigurationHelpers.GetEndpointsSectionPath(endpointCollectionName))));
101                 }
102                 catch (NullReferenceException) // System.Configuration.ConfigurationElement bug
103                 {
104                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
105                         new ConfigurationErrorsException(SR.GetString(SR.ConfigEndpointExtensionNotFound,
106                         ConfigurationHelpers.GetEndpointsSectionPath(endpointCollectionName))));
107                 }
108             }
109 
110             return retVal;
111         }
112 
113         // Be sure to update GetAssociatedEndpointCollectionElement if you modify this method
114         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetAssociatedSection which elevates.")]
115         [SecurityCritical]
UnsafeGetAssociatedEndpointCollectionElement(ContextInformation evaluationContext, string endpointCollectionName)116         internal static EndpointCollectionElement UnsafeGetAssociatedEndpointCollectionElement(ContextInformation evaluationContext, string endpointCollectionName)
117         {
118             EndpointCollectionElement retVal = null;
119             StandardEndpointsSection endpointsSection = (StandardEndpointsSection)ConfigurationHelpers.UnsafeGetAssociatedSection(evaluationContext, ConfigurationStrings.StandardEndpointsSectionPath);
120 
121             if (null != endpointsSection)
122             {
123                 endpointsSection.UpdateEndpointSections(evaluationContext);
124                 try
125                 {
126                     retVal = (EndpointCollectionElement)endpointsSection[endpointCollectionName];
127                 }
128                 catch (KeyNotFoundException)
129                 {
130                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
131                         new ConfigurationErrorsException(SR.GetString(SR.ConfigEndpointExtensionNotFound,
132                         ConfigurationHelpers.GetEndpointsSectionPath(endpointCollectionName))));
133                 }
134                 catch (NullReferenceException) // System.Configuration.ConfigurationElement bug
135                 {
136                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
137                         new ConfigurationErrorsException(SR.GetString(SR.ConfigEndpointExtensionNotFound,
138                         ConfigurationHelpers.GetEndpointsSectionPath(endpointCollectionName))));
139                 }
140             }
141 
142             return retVal;
143         }
144 
145         /// Be sure to update UnsafeGetAssociatedSection if you modify this method
GetAssociatedSection(ContextInformation evalContext, string sectionPath)146         internal static object GetAssociatedSection(ContextInformation evalContext, string sectionPath)
147         {
148             object retval = null;
149             if (evalContext != null)
150             {
151                 retval = evalContext.GetSection(sectionPath);
152             }
153             else
154             {
155                 retval = AspNetEnvironment.Current.GetConfigurationSection(sectionPath);
156 
157                 // Trace after call to underlying configuration system to
158                 // insure that configuration system is initialized
159                 if (DiagnosticUtility.ShouldTraceVerbose)
160                 {
161                     TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.GetConfigurationSection,
162                         SR.GetString(SR.TraceCodeGetConfigurationSection),
163                         new StringTraceRecord("ConfigurationSection", sectionPath), null, null);
164                 }
165             }
166             if (retval == null)
167             {
168                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
169                     new ConfigurationErrorsException(SR.GetString(SR.ConfigSectionNotFound,
170                     sectionPath)));
171             }
172             return retval;
173         }
174 
175         // Be sure to update GetAssociatedSection if you modify this method
176         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical methods which elevate.")]
177         [SecurityCritical]
UnsafeGetAssociatedSection(ContextInformation evalContext, string sectionPath)178         internal static object UnsafeGetAssociatedSection(ContextInformation evalContext, string sectionPath)
179         {
180             object retval = null;
181             if (evalContext != null)
182             {
183                 retval = UnsafeGetSectionFromContext(evalContext, sectionPath);
184             }
185             else
186             {
187                 retval = AspNetEnvironment.Current.UnsafeGetConfigurationSection(sectionPath);
188 
189                 // Trace after call to underlying configuration system to
190                 // insure that configuration system is initialized
191                 if (DiagnosticUtility.ShouldTraceVerbose)
192                 {
193                     TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.GetConfigurationSection,
194                         SR.GetString(SR.TraceCodeGetConfigurationSection),
195                         new StringTraceRecord("ConfigurationSection", sectionPath), null, null);
196                 }
197             }
198             if (retval == null)
199             {
200                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
201                     new ConfigurationErrorsException(SR.GetString(SR.ConfigSectionNotFound,
202                     sectionPath)));
203             }
204 
205             return retval;
206         }
207 
208         /// Be sure to update UnsafeGetBindingCollectionElement if you modify this method
GetBindingCollectionElement(string bindingCollectionName)209         internal static BindingCollectionElement GetBindingCollectionElement(string bindingCollectionName)
210         {
211             return GetAssociatedBindingCollectionElement(null, bindingCollectionName);
212         }
213 
214         // Be sure to update GetBindingCollectionElement if you modify this method
215         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetAssociatedBindingCollectionElement which elevates.")]
216         [SecurityCritical]
UnsafeGetBindingCollectionElement(string bindingCollectionName)217         internal static BindingCollectionElement UnsafeGetBindingCollectionElement(string bindingCollectionName)
218         {
219             return UnsafeGetAssociatedBindingCollectionElement(null, bindingCollectionName);
220         }
221 
GetBindingsSectionPath(string sectionName)222         internal static string GetBindingsSectionPath(string sectionName)
223         {
224             return string.Concat(ConfigurationStrings.BindingsSectionGroupPath, "/", sectionName);
225         }
226 
GetEndpointsSectionPath(string sectionName)227         internal static string GetEndpointsSectionPath(string sectionName)
228         {
229             return string.Concat(ConfigurationStrings.StandardEndpointsSectionName, "/", sectionName);
230         }
231 
232         /// Be sure to update UnsafeGetEndpointCollectionElement if you modify this method
GetEndpointCollectionElement(string endpointCollectionName)233         internal static EndpointCollectionElement GetEndpointCollectionElement(string endpointCollectionName)
234         {
235             return GetAssociatedEndpointCollectionElement(null, endpointCollectionName);
236         }
237 
238         // Be sure to update GetEndpointCollectionElement if you modify this method
239         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetAssociatedEndpointCollectionElement which elevates.")]
240         [SecurityCritical]
UnsafeGetEndpointCollectionElement(string endpointCollectionName)241         internal static EndpointCollectionElement UnsafeGetEndpointCollectionElement(string endpointCollectionName)
242         {
243             return UnsafeGetAssociatedEndpointCollectionElement(null, endpointCollectionName);
244         }
245 
246         /// Be sure to update UnsafeGetSection if you modify this method
GetSection(string sectionPath)247         internal static object GetSection(string sectionPath)
248         {
249             return GetAssociatedSection(null, sectionPath);
250         }
251 
252         // Be sure to update GetSection if you modify this method
253         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetAssociatedSection which elevates.")]
254         [SecurityCritical]
UnsafeGetSection(string sectionPath)255         internal static object UnsafeGetSection(string sectionPath)
256         {
257             return UnsafeGetAssociatedSection(null, sectionPath);
258         }
259 
260         // Be sure to update UnsafeGetSection if you modify this method
261         [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetAssociatedSection which elevates.")]
262         [SecurityCritical]
UnsafeGetSectionNoTrace(string sectionPath)263         internal static object UnsafeGetSectionNoTrace(string sectionPath)
264         {
265             object retval = AspNetEnvironment.Current.UnsafeGetConfigurationSection(sectionPath);
266 
267             if (retval == null)
268             {
269                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
270                     new ConfigurationErrorsException(SR.GetString(SR.ConfigSectionNotFound,
271                     sectionPath)));
272             }
273 
274             return retval;
275         }
276 
277         [Fx.Tag.SecurityNote(Critical = "Asserts ConfigurationPermission in order to fetch config from ContextInformation,"
278             + "caller must guard return value.")]
279         [SecurityCritical]
280         [ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
UnsafeGetSectionFromContext(ContextInformation evalContext, string sectionPath)281         internal static object UnsafeGetSectionFromContext(ContextInformation evalContext, string sectionPath)
282         {
283             return evalContext.GetSection(sectionPath);
284         }
285 
GetSectionPath(string sectionName)286         internal static string GetSectionPath(string sectionName)
287         {
288             return string.Concat(ConfigurationStrings.SectionGroupName, "/", sectionName);
289         }
290 
291         [Fx.Tag.SecurityNote(Critical = "Calls SetIsPresentWithAssert which elevates in order to set a property."
292             + "Caller must guard ConfigurationElement parameter, ie only pass 'this'.")]
293         [SecurityCritical]
SetIsPresent(ConfigurationElement element)294         internal static void SetIsPresent(ConfigurationElement element)
295         {
296             // Work around for VSW 578830: ConfigurationElements that override DeserializeElement cannot set ElementInformation.IsPresent
297             PropertyInfo elementPresent = element.GetType().GetProperty("ElementPresent", BindingFlags.Instance | BindingFlags.NonPublic);
298             SetIsPresentWithAssert(elementPresent, element, true);
299         }
300 
301         [Fx.Tag.SecurityNote(Critical = "Asserts full trust in order to set a private member in the ConfigurationElement."
302             + "Caller must guard parameters.")]
303         [SecurityCritical]
304         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
SetIsPresentWithAssert(PropertyInfo elementPresent, ConfigurationElement element, bool value)305         static void SetIsPresentWithAssert(PropertyInfo elementPresent, ConfigurationElement element, bool value)
306         {
307             elementPresent.SetValue(element, value, null);
308         }
309 
GetEvaluationContext(IConfigurationContextProviderInternal provider)310         internal static ContextInformation GetEvaluationContext(IConfigurationContextProviderInternal provider)
311         {
312             if (provider != null)
313             {
314                 try
315                 {
316                     return provider.GetEvaluationContext();
317                 }
318                 catch (ConfigurationErrorsException)
319                 {
320                 }
321             }
322             return null;
323         }
324 
325         [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - The return value will be used for a security decision. if in doubt about the return value, "
326             + "it is safe to return null (caller will assume the worst case from a security perspective).")]
GetOriginalEvaluationContext(IConfigurationContextProviderInternal provider)327         internal static ContextInformation GetOriginalEvaluationContext(IConfigurationContextProviderInternal provider)
328         {
329             if (provider != null)
330             {
331                 // provider may not need this try/catch, but it doesn't hurt to do it
332                 try
333                 {
334                     return provider.GetOriginalEvaluationContext();
335                 }
336                 catch (ConfigurationErrorsException)
337                 {
338                 }
339             }
340             return null;
341         }
342 
TraceExtensionTypeNotFound(ExtensionElement extensionElement)343         internal static void TraceExtensionTypeNotFound(ExtensionElement extensionElement)
344         {
345             if (DiagnosticUtility.ShouldTraceWarning)
346             {
347                 Dictionary<string, string> values = new Dictionary<string, string>(2);
348                 values.Add("ExtensionName", extensionElement.Name);
349                 values.Add("ExtensionType", extensionElement.Type);
350 
351                 DictionaryTraceRecord traceRecord = new DictionaryTraceRecord(values);
352                 TraceUtility.TraceEvent(TraceEventType.Warning,
353                     TraceCode.ExtensionTypeNotFound,
354                     SR.GetString(SR.TraceCodeExtensionTypeNotFound),
355                     traceRecord,
356                     null,
357                     (Exception)null);
358             }
359         }
360     }
361 
362     interface IConfigurationContextProviderInternal
363     {
364         /// <summary>
365         /// return the current ContextInformation (the protected property ConfigurationElement.EvaluationContext)
366         /// this may throw ConfigurationErrorsException, caller should guard (see ConfigurationHelpers.GetEvaluationContext)
367         /// </summary>
368         /// <returns>result of ConfigurationElement.EvaluationContext</returns>
GetEvaluationContext()369         ContextInformation GetEvaluationContext();
370 
371         /// <summary>
372         /// return the ContextInformation that was present when the ConfigurationElement was first deserialized.
373         /// if Reset was called, this will be the value of parent.GetOriginalEvaluationContext()
374         /// if Reset was not called, this will be the value of this.GetEvaluationContext()
375         /// </summary>
376         /// <returns>result of parent's ConfigurationElement.EvaluationContext</returns>
377         [Fx.Tag.SecurityNote(Miscellaneous =
378             "RequiresReview - the return value will be used for a security decision. if in doubt about the return value, it "
379             + "is safe (from a security perspective)  to return null (caller will assume the worst case).")]
GetOriginalEvaluationContext()380         ContextInformation GetOriginalEvaluationContext();
381     }
382 
383     [Fx.Tag.SecurityNote(Critical = "Stores information used in a security decision.")]
384 #pragma warning disable 618 // have not moved to the v4 security model yet
385     [SecurityCritical(SecurityCriticalScope.Everything)]
386 #pragma warning restore 618
387     struct EvaluationContextHelper
388     {
389         bool reset;
390         ContextInformation inheritedContext;
391 
OnResetSystem.ServiceModel.Configuration.EvaluationContextHelper392         internal void OnReset(ConfigurationElement parent)
393         {
394             this.reset = true;
395             this.inheritedContext = ConfigurationHelpers.GetOriginalEvaluationContext(parent as IConfigurationContextProviderInternal);
396         }
397 
GetOriginalContextSystem.ServiceModel.Configuration.EvaluationContextHelper398         internal ContextInformation GetOriginalContext(IConfigurationContextProviderInternal owner)
399         {
400             if (this.reset)
401             {
402                 // if reset, inherited context is authoritative, even if null
403                 return this.inheritedContext;
404             }
405             else
406             {
407                 // otherwise use current
408                 return ConfigurationHelpers.GetEvaluationContext(owner);
409             }
410         }
411     }
412 }
413