1 // 2 // ConfigUtil.cs 3 // 4 // Author: 5 // Atsushi Enomoto <atsushi@ximian.com> 6 // 7 // Copyright (C) 2006 Novell, Inc. http://www.novell.com 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining 10 // a copy of this software and associated documentation files (the 11 // "Software"), to deal in the Software without restriction, including 12 // without limitation the rights to use, copy, modify, merge, publish, 13 // distribute, sublicense, and/or sell copies of the Software, and to 14 // permit persons to whom the Software is furnished to do so, subject to 15 // the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 // 28 using System; 29 using System.Configuration; 30 using System.Collections.Generic; 31 using System.Linq; 32 using System.Reflection; 33 using System.Security.Cryptography.X509Certificates; 34 using System.ServiceModel.Channels; 35 using System.ServiceModel.Configuration; 36 using System.ServiceModel.Description; 37 using System.ServiceModel.Dispatcher; 38 #if !XAMMAC_4_5 39 using System.Web.Configuration; 40 #endif 41 42 using SysConfig = System.Configuration.Configuration; 43 44 namespace System.ServiceModel.Configuration 45 { 46 internal static class ConfigUtil 47 { 48 #if !XAMMAC_4_5 GetSection(string name)49 static object GetSection (string name) 50 { 51 if (ServiceHostingEnvironment.InAspNet) 52 return WebConfigurationManager.GetSection (name); 53 else 54 return ConfigurationManager.GetSection (name); 55 } 56 57 public static BindingsSection BindingsSection { 58 get { 59 return (BindingsSection) GetSection ("system.serviceModel/bindings"); 60 } 61 } 62 63 public static ClientSection ClientSection { 64 get { return (ClientSection) GetSection ("system.serviceModel/client"); } 65 } 66 67 public static ServicesSection ServicesSection { 68 get { return (ServicesSection) GetSection ("system.serviceModel/services"); } 69 } 70 71 public static BehaviorsSection BehaviorsSection { 72 get { return (BehaviorsSection) GetSection ("system.serviceModel/behaviors"); } 73 } 74 75 public static DiagnosticSection DiagnosticSection { 76 get { return (DiagnosticSection) GetSection ("system.serviceModel/diagnostics"); } 77 } 78 79 public static ExtensionsSection ExtensionsSection { 80 get { return (ExtensionsSection) GetSection ("system.serviceModel/extensions"); } 81 } 82 83 public static ProtocolMappingSection ProtocolMappingSection { 84 get { 85 return (ProtocolMappingSection) GetSection ("system.serviceModel/protocolMapping"); 86 } 87 } 88 89 public static StandardEndpointsSection StandardEndpointsSection { 90 get { 91 return (StandardEndpointsSection) GetSection ("system.serviceModel/standardEndpoints"); 92 } 93 } 94 CreateBinding(string binding, string bindingConfiguration)95 public static Binding CreateBinding (string binding, string bindingConfiguration) 96 { 97 BindingCollectionElement section = ConfigUtil.BindingsSection [binding]; 98 if (section == null) 99 throw new ArgumentException (String.Format ("binding section for {0} was not found.", binding)); 100 101 Binding b = section.GetDefault (); 102 103 foreach (IBindingConfigurationElement el in section.ConfiguredBindings) 104 if (el.Name == bindingConfiguration) 105 el.ApplyConfiguration (b); 106 107 return b; 108 } 109 110 static readonly List<Assembly> cached_assemblies = new List<Assembly> (); 111 static readonly List<NamedConfigType> cached_named_config_types = new List<NamedConfigType> (); 112 GetTypeFromConfigString(string name, NamedConfigCategory category)113 public static Type GetTypeFromConfigString (string name, NamedConfigCategory category) 114 { 115 Type type = Type.GetType (name); 116 if (type != null) 117 return type; 118 foreach (var ass in AppDomain.CurrentDomain.GetAssemblies ()) { 119 var cache = cached_named_config_types.FirstOrDefault (c => c.Name == name && c.Category == category); 120 if (cache != null) 121 return cache.Type; 122 123 if ((type = ass.GetType (name)) != null) 124 return type; 125 126 if (cached_assemblies.Contains (ass)) 127 continue; 128 if (!ass.IsDynamic) 129 cached_assemblies.Add (ass); 130 131 foreach (var t in ass.GetTypes ()) { 132 if (cached_named_config_types.Any (ct => ct.Type == t)) 133 continue; 134 135 NamedConfigType c = null; 136 var sca = t.GetCustomAttribute<ServiceContractAttribute> (false); 137 if (sca != null && !String.IsNullOrEmpty (sca.ConfigurationName)) { 138 c = new NamedConfigType () { Category = NamedConfigCategory.Contract, Name = sca.ConfigurationName, Type = t }; 139 cached_named_config_types.Add (c); 140 } 141 142 // If we need more category, add to here. 143 144 if (c != null && c.Name == name && c.Category == category) 145 cache = c; // do not break and continue caching (as the assembly is being cached) 146 } 147 if (cache != null) 148 return cache.Type; 149 } 150 return null; 151 } 152 GetBindingByProtocolMapping(Uri address)153 public static Binding GetBindingByProtocolMapping (Uri address) 154 { 155 ProtocolMappingElement el = ConfigUtil.ProtocolMappingSection.ProtocolMappingCollection [address.Scheme]; 156 if (el == null) 157 return null; 158 return ConfigUtil.CreateBinding (el.Binding, el.BindingConfiguration); 159 } 160 ConfigureStandardEndpoint(ContractDescription cd, ChannelEndpointElement element)161 public static ServiceEndpoint ConfigureStandardEndpoint (ContractDescription cd, ChannelEndpointElement element) 162 { 163 string kind = element.Kind; 164 string endpointConfiguration = element.EndpointConfiguration; 165 166 EndpointCollectionElement section = ConfigUtil.StandardEndpointsSection [kind]; 167 if (section == null) 168 throw new ArgumentException (String.Format ("standard endpoint section for '{0}' was not found.", kind)); 169 170 StandardEndpointElement e = section.GetDefaultStandardEndpointElement (); 171 172 ServiceEndpoint inst = e.CreateServiceEndpoint (cd); 173 174 foreach (StandardEndpointElement el in section.ConfiguredEndpoints) { 175 if (el.Name == endpointConfiguration) { 176 el.InitializeAndValidate (element); 177 el.ApplyConfiguration (inst, element); 178 break; 179 } 180 } 181 182 return inst; 183 } 184 ConfigureStandardEndpoint(ContractDescription cd, ServiceEndpointElement element)185 public static ServiceEndpoint ConfigureStandardEndpoint (ContractDescription cd, ServiceEndpointElement element) 186 { 187 string kind = element.Kind; 188 string endpointConfiguration = element.EndpointConfiguration; 189 190 EndpointCollectionElement section = ConfigUtil.StandardEndpointsSection [kind]; 191 if (section == null) 192 throw new ArgumentException (String.Format ("standard endpoint section for '{0}' was not found.", kind)); 193 194 StandardEndpointElement e = section.GetDefaultStandardEndpointElement (); 195 196 ServiceEndpoint inst = e.CreateServiceEndpoint (cd); 197 198 foreach (StandardEndpointElement el in section.ConfiguredEndpoints) { 199 if (el.Name == endpointConfiguration) { 200 el.InitializeAndValidate (element); 201 el.ApplyConfiguration (inst, element); 202 break; 203 } 204 } 205 206 return inst; 207 } 208 CreateEndpointBehaviors(string bindingConfiguration)209 public static KeyedByTypeCollection<IEndpointBehavior> CreateEndpointBehaviors (string bindingConfiguration) 210 { 211 var ec = BehaviorsSection.EndpointBehaviors [bindingConfiguration]; 212 if (ec == null) 213 return null; 214 var c = new KeyedByTypeCollection<IEndpointBehavior> (); 215 foreach (var bxe in ec) 216 c.Add ((IEndpointBehavior) bxe.CreateBehavior ()); 217 return c; 218 } 219 CreateInstance(this EndpointAddressElementBase el)220 public static EndpointAddress CreateInstance (this EndpointAddressElementBase el) 221 { 222 return new EndpointAddress (el.Address, el.Identity.CreateInstance (), el.Headers.Headers); 223 } 224 CopyFrom(this ChannelEndpointElement to, ChannelEndpointElement from)225 public static void CopyFrom (this ChannelEndpointElement to, ChannelEndpointElement from) 226 { 227 to.Address = from.Address; 228 to.BehaviorConfiguration = from.BehaviorConfiguration; 229 to.Binding = from.Binding; 230 to.BindingConfiguration = from.BindingConfiguration; 231 to.Contract = from.Contract; 232 if (from.Headers != null) 233 to.Headers.Headers = from.Headers.Headers; 234 if (from.Identity != null) 235 to.Identity.InitializeFrom (from.Identity.CreateInstance ()); 236 to.Name = from.Name; 237 } 238 CreateEndpointAddress(this ChannelEndpointElement el)239 public static EndpointAddress CreateEndpointAddress (this ChannelEndpointElement el) 240 { 241 return new EndpointAddress (el.Address, el.Identity != null ? el.Identity.CreateInstance () : null, el.Headers.Headers); 242 } 243 CreateEndpointAddress(this ServiceEndpointElement el)244 public static EndpointAddress CreateEndpointAddress (this ServiceEndpointElement el) 245 { 246 return new EndpointAddress (el.Address, el.Identity != null ? el.Identity.CreateInstance () : null, el.Headers.Headers); 247 } 248 #endif 249 CreateInstance(this IdentityElement el)250 public static EndpointIdentity CreateInstance (this IdentityElement el) 251 { 252 if (el.Certificate != null) 253 return new X509CertificateEndpointIdentity (el.Certificate.CreateInstance ()); 254 else if (el.CertificateReference != null) 255 return new X509CertificateEndpointIdentity (el.CertificateReference.CreateInstance ()); 256 else if (el.Dns != null) 257 return new DnsEndpointIdentity (el.Dns.Value); 258 else if (el.Rsa != null) 259 return new RsaEndpointIdentity (el.Rsa.Value); 260 else if (el.ServicePrincipalName != null) 261 return new SpnEndpointIdentity (el.ServicePrincipalName.Value); 262 else if (el.UserPrincipalName != null) 263 return new UpnEndpointIdentity (el.UserPrincipalName.Value); 264 else 265 return null; 266 } 267 CreateCertificateFrom(StoreLocation storeLocation, StoreName storeName, X509FindType findType, Object findValue)268 public static X509Certificate2 CreateCertificateFrom (StoreLocation storeLocation, StoreName storeName, X509FindType findType, Object findValue) 269 { 270 var store = new X509Store (storeName, storeLocation); 271 store.Open (OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); 272 try { 273 foreach (var c in store.Certificates.Find (findType, findValue, false)) 274 return c; 275 throw new InvalidOperationException (String.Format ("Specified X509 certificate with find type {0} and find value {1} was not found in X509 store {2} location {3}", findType, findValue, storeName, storeLocation)); 276 } finally { 277 store.Close (); 278 } 279 } 280 CreateInstance(this CertificateElement el)281 public static X509Certificate2 CreateInstance (this CertificateElement el) 282 { 283 return new X509Certificate2 (Convert.FromBase64String (el.EncodedValue)); 284 } 285 CreateInstance(this CertificateReferenceElement el)286 public static X509Certificate2 CreateInstance (this CertificateReferenceElement el) 287 { 288 return CreateCertificateFrom (el.StoreLocation, el.StoreName, el.X509FindType, el.FindValue); 289 } 290 CreateInstance(this X509ClientCertificateCredentialsElement el)291 public static X509Certificate2 CreateInstance (this X509ClientCertificateCredentialsElement el) 292 { 293 return CreateCertificateFrom (el.StoreLocation, el.StoreName, el.X509FindType, el.FindValue); 294 } 295 CreateInstance(this X509ScopedServiceCertificateElement el)296 public static X509Certificate2 CreateInstance (this X509ScopedServiceCertificateElement el) 297 { 298 return CreateCertificateFrom (el.StoreLocation, el.StoreName, el.X509FindType, el.FindValue); 299 } 300 CreateInstance(this X509DefaultServiceCertificateElement el)301 public static X509Certificate2 CreateInstance (this X509DefaultServiceCertificateElement el) 302 { 303 return CreateCertificateFrom (el.StoreLocation, el.StoreName, el.X509FindType, el.FindValue); 304 } 305 306 #if !XAMMAC_4_5 FindCollectionElement(Binding binding, SysConfig config)307 public static BindingCollectionElement FindCollectionElement (Binding binding, SysConfig config) 308 { 309 var section = (BindingsSection) config.GetSection ("system.serviceModel/bindings"); 310 foreach (var element in section.BindingCollections) { 311 if (binding.GetType ().Equals (element.BindingType)) 312 return element; 313 } 314 315 return null; 316 } 317 #endif 318 } 319 320 enum NamedConfigCategory 321 { 322 None, 323 Contract 324 } 325 326 class NamedConfigType 327 { 328 public NamedConfigCategory Category { get; set; } 329 public string Name { get; set; } 330 public Type Type { get; set; } 331 } 332 333 } 334