1 //------------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------------------------
4 
5 namespace System.ServiceModel.Configuration
6 {
7     using System;
8     using System.Collections.ObjectModel;
9     using System.ComponentModel;
10     using System.Configuration;
11     using System.IdentityModel.Tokens;
12     using System.IO;
13     using System.Runtime;
14     using System.ServiceModel;
15     using System.ServiceModel.Description;
16     using System.ServiceModel.Security.Tokens;
17     using System.Text;
18     using System.Xml;
19 
20     public sealed partial class IssuedTokenParametersElement : ServiceModelConfigurationElement
21     {
22         Collection<IssuedTokenParametersElement> optionalIssuedTokenParameters = null;
23 
IssuedTokenParametersElement()24         public IssuedTokenParametersElement()
25         {
26         }
27 
28         [ConfigurationProperty(ConfigurationStrings.DefaultMessageSecurityVersion)]
29         [TypeConverter(typeof(MessageSecurityVersionConverter))]
30         public MessageSecurityVersion DefaultMessageSecurityVersion
31         {
32             get { return (MessageSecurityVersion)base[ConfigurationStrings.DefaultMessageSecurityVersion]; }
33             set { base[ConfigurationStrings.DefaultMessageSecurityVersion] = value; }
34         }
35 
36         [ConfigurationProperty(ConfigurationStrings.AdditionalRequestParameters)]
37         public XmlElementElementCollection AdditionalRequestParameters
38         {
39             get { return (XmlElementElementCollection)base[ConfigurationStrings.AdditionalRequestParameters]; }
40         }
41 
42         [ConfigurationProperty(ConfigurationStrings.ClaimTypeRequirements)]
43         public ClaimTypeElementCollection ClaimTypeRequirements
44         {
45             get { return (ClaimTypeElementCollection)base[ConfigurationStrings.ClaimTypeRequirements]; }
46         }
47 
48         [ConfigurationProperty(ConfigurationStrings.Issuer)]
49         public IssuedTokenParametersEndpointAddressElement Issuer
50         {
51             get { return (IssuedTokenParametersEndpointAddressElement)base[ConfigurationStrings.Issuer]; }
52         }
53 
54         [ConfigurationProperty(ConfigurationStrings.IssuerMetadata)]
55         public EndpointAddressElementBase IssuerMetadata
56         {
57             get { return (EndpointAddressElementBase)base[ConfigurationStrings.IssuerMetadata]; }
58         }
59 
60         [ConfigurationProperty(ConfigurationStrings.KeySize, DefaultValue = 0)]
61         [IntegerValidator(MinValue = 0)]
62         public int KeySize
63         {
64             get { return (int)base[ConfigurationStrings.KeySize]; }
65             set { base[ConfigurationStrings.KeySize] = value; }
66         }
67 
68         [ConfigurationProperty(ConfigurationStrings.KeyType, DefaultValue = IssuedSecurityTokenParameters.defaultKeyType)]
69         [ServiceModelEnumValidator(typeof(System.IdentityModel.Tokens.SecurityKeyTypeHelper))]
70         public SecurityKeyType KeyType
71         {
72             get { return (SecurityKeyType)base[ConfigurationStrings.KeyType]; }
73             set { base[ConfigurationStrings.KeyType] = value; }
74         }
75 
76         internal Collection<IssuedTokenParametersElement> OptionalIssuedTokenParameters
77         {
78             get
79             {
80                 // OptionalIssuedTokenParameters built on assumption that configuration is writable.
81                 // This should be protected at the callers site.  If assumption is invalid, then
82                 // configuration system is in an indeterminate state.  Need to stop in a manner that
83                 // user code can not capture.
84                 if (this.IsReadOnly())
85                 {
86                     Fx.Assert("IssuedTokenParametersElement.OptionalIssuedTokenParameters should only be called by Admin APIs");
87                     DiagnosticUtility.FailFast("IssuedTokenParametersElement.OptionalIssuedTokenParameters should only be called by Admin APIs");
88                 }
89 
90                 // No need to worry about a race condition here-- this method is not meant to be called by multi-threaded
91                 // apps. It is only supposed to be called by svcutil and single threaded equivalents.
92                 if (this.optionalIssuedTokenParameters == null)
93                 {
94                     this.optionalIssuedTokenParameters = new Collection<IssuedTokenParametersElement>();
95                 }
96                 return this.optionalIssuedTokenParameters;
97             }
98         }
99 
100 
101         [ConfigurationProperty(ConfigurationStrings.TokenType, DefaultValue = "")]
102         [StringValidator(MinLength = 0)]
103         public string TokenType
104         {
105             get { return (string)base[ConfigurationStrings.TokenType]; }
106             set
107             {
108                 if (String.IsNullOrEmpty(value))
109                 {
110                     value = String.Empty;
111                 }
112 
113                 base[ConfigurationStrings.TokenType] = value;
114             }
115         }
116 
117         [ConfigurationProperty(ConfigurationStrings.UseStrTransform, DefaultValue = false)]
118         public bool UseStrTransform
119         {
120             get { return (bool)base[ConfigurationStrings.UseStrTransform]; }
121             set { base[ConfigurationStrings.UseStrTransform] = value; }
122         }
123 
ApplyConfiguration(IssuedSecurityTokenParameters parameters)124         internal void ApplyConfiguration(IssuedSecurityTokenParameters parameters)
125         {
126             if (parameters == null)
127                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("parameters"));
128 
129             if (this.AdditionalRequestParameters != null)
130             {
131                 foreach (XmlElementElement e in this.AdditionalRequestParameters)
132                 {
133                     parameters.AdditionalRequestParameters.Add(e.XmlElement);
134                 }
135             }
136 
137             if (this.ClaimTypeRequirements != null)
138             {
139                 foreach (ClaimTypeElement c in this.ClaimTypeRequirements)
140                 {
141                     parameters.ClaimTypeRequirements.Add(new ClaimTypeRequirement(c.ClaimType, c.IsOptional));
142                 }
143             }
144 
145             parameters.KeySize = this.KeySize;
146             parameters.KeyType = this.KeyType;
147             parameters.DefaultMessageSecurityVersion = this.DefaultMessageSecurityVersion;
148             parameters.UseStrTransform = this.UseStrTransform;
149 
150             if (!string.IsNullOrEmpty(this.TokenType))
151             {
152                 parameters.TokenType = this.TokenType;
153             }
154             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.Issuer].ValueOrigin)
155             {
156                 this.Issuer.Validate();
157 
158                 parameters.IssuerAddress = ConfigLoader.LoadEndpointAddress(this.Issuer);
159 
160                 if (!string.IsNullOrEmpty(this.Issuer.Binding))
161                 {
162                     parameters.IssuerBinding = ConfigLoader.LookupBinding(this.Issuer.Binding, this.Issuer.BindingConfiguration, this.EvaluationContext);
163                 }
164             }
165 
166             if (PropertyValueOrigin.Default != this.ElementInformation.Properties[ConfigurationStrings.IssuerMetadata].ValueOrigin)
167             {
168                 parameters.IssuerMetadataAddress = ConfigLoader.LoadEndpointAddress(this.IssuerMetadata);
169             }
170         }
171 
Copy(IssuedTokenParametersElement source)172         internal void Copy(IssuedTokenParametersElement source)
173         {
174             if (this.IsReadOnly())
175             {
176                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(SR.GetString(SR.ConfigReadOnly)));
177             }
178             if (null == source)
179             {
180                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("source");
181             }
182 
183             foreach (XmlElementElement xmlElement in source.AdditionalRequestParameters)
184             {
185                 XmlElementElement newElement = new XmlElementElement();
186                 newElement.Copy(xmlElement);
187                 this.AdditionalRequestParameters.Add(newElement);
188             }
189 
190             foreach (ClaimTypeElement c in source.ClaimTypeRequirements)
191             {
192                 this.ClaimTypeRequirements.Add(new ClaimTypeElement(c.ClaimType, c.IsOptional));
193             }
194 
195             this.KeySize = source.KeySize;
196             this.KeyType = source.KeyType;
197             this.TokenType = source.TokenType;
198             this.DefaultMessageSecurityVersion = source.DefaultMessageSecurityVersion;
199             this.UseStrTransform = source.UseStrTransform;
200 
201             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.Issuer].ValueOrigin)
202             {
203                 this.Issuer.Copy(source.Issuer);
204             }
205             if (PropertyValueOrigin.Default != source.ElementInformation.Properties[ConfigurationStrings.IssuerMetadata].ValueOrigin)
206             {
207                 this.IssuerMetadata.Copy(source.IssuerMetadata);
208             }
209         }
210 
Create(bool createTemplateOnly, SecurityKeyType templateKeyType)211         internal IssuedSecurityTokenParameters Create(bool createTemplateOnly, SecurityKeyType templateKeyType)
212         {
213             IssuedSecurityTokenParameters result = new IssuedSecurityTokenParameters();
214             if (!createTemplateOnly)
215             {
216                 this.ApplyConfiguration(result);
217             }
218             else
219             {
220                 result.KeyType = templateKeyType;
221             }
222             return result;
223         }
224 
InitializeFrom(IssuedSecurityTokenParameters source, bool initializeNestedBindings)225         internal void InitializeFrom(IssuedSecurityTokenParameters source, bool initializeNestedBindings)
226         {
227             if (null == source)
228                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("source");
229 
230             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.KeyType, source.KeyType);
231             if (source.KeySize > 0)
232             {
233                 SetPropertyValueIfNotDefaultValue(ConfigurationStrings.KeySize, source.KeySize);
234             }
235             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.TokenType, source.TokenType);
236             SetPropertyValueIfNotDefaultValue(ConfigurationStrings.UseStrTransform, source.UseStrTransform);
237 
238             if (source.IssuerAddress != null)
239                 this.Issuer.InitializeFrom(source.IssuerAddress);
240 
241             if (source.DefaultMessageSecurityVersion != null)
242                 SetPropertyValueIfNotDefaultValue(ConfigurationStrings.DefaultMessageSecurityVersion, source.DefaultMessageSecurityVersion);
243 
244             if (source.IssuerBinding != null && initializeNestedBindings)
245             {
246                 this.Issuer.BindingConfiguration = this.Issuer.Address.ToString();
247                 string bindingSectionName;
248                 BindingsSection.TryAdd(this.Issuer.BindingConfiguration,
249                     source.IssuerBinding,
250                     out bindingSectionName);
251                 this.Issuer.Binding = bindingSectionName;
252             }
253 
254             if (source.IssuerMetadataAddress != null)
255             {
256                 this.IssuerMetadata.InitializeFrom(source.IssuerMetadataAddress);
257             }
258 
259             foreach (XmlElement element in source.AdditionalRequestParameters)
260             {
261                 this.AdditionalRequestParameters.Add(new XmlElementElement(element));
262             }
263 
264             foreach (ClaimTypeRequirement c in source.ClaimTypeRequirements)
265             {
266                 this.ClaimTypeRequirements.Add(new ClaimTypeElement(c.ClaimType, c.IsOptional));
267             }
268 
269             foreach (IssuedSecurityTokenParameters.AlternativeIssuerEndpoint alternativeIssuer in source.AlternativeIssuerEndpoints)
270             {
271                 IssuedTokenParametersElement element = new IssuedTokenParametersElement();
272                 element.Issuer.InitializeFrom(alternativeIssuer.IssuerAddress);
273                 if (initializeNestedBindings)
274                 {
275                     element.Issuer.BindingConfiguration = element.Issuer.Address.ToString();
276                     string bindingSectionName;
277                     BindingsSection.TryAdd(element.Issuer.BindingConfiguration,
278                         alternativeIssuer.IssuerBinding,
279                         out bindingSectionName);
280                     element.Issuer.Binding = bindingSectionName;
281                 }
282                 this.OptionalIssuedTokenParameters.Add(element);
283             }
284         }
285 
SerializeToXmlElement(XmlWriter writer, String elementName)286         protected override bool SerializeToXmlElement(XmlWriter writer, String elementName)
287         {
288             bool writeMe = base.SerializeToXmlElement(writer, elementName);
289             bool writeComment = this.OptionalIssuedTokenParameters.Count > 0;
290             if (writeComment && writer != null)
291             {
292                 MemoryStream memoryStream = new MemoryStream();
293                 using (XmlTextWriter commentWriter = new XmlTextWriter(memoryStream, Encoding.UTF8))
294                 {
295                     commentWriter.Formatting = Formatting.Indented;
296                     commentWriter.WriteStartElement(ConfigurationStrings.AlternativeIssuedTokenParameters);
297                     foreach (IssuedTokenParametersElement element in this.OptionalIssuedTokenParameters)
298                     {
299                         element.SerializeToXmlElement(commentWriter, ConfigurationStrings.IssuedTokenParameters);
300                     }
301                     commentWriter.WriteEndElement();
302                     commentWriter.Flush();
303                     string commentString = new UTF8Encoding().GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
304                     writer.WriteComment(commentString.Substring(1, commentString.Length - 1));
305                     commentWriter.Close();
306                 }
307             }
308             return writeMe || writeComment;
309         }
310 
Unmerge(ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)311         protected override void Unmerge(ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
312         {
313             if (sourceElement is IssuedTokenParametersElement)
314             {
315                 IssuedTokenParametersElement source = (IssuedTokenParametersElement)sourceElement;
316                 this.optionalIssuedTokenParameters = source.optionalIssuedTokenParameters;
317             }
318 
319             base.Unmerge(sourceElement, parentElement, saveMode);
320         }
321     }
322 }
323 
324 
325 
326