1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 5 namespace System.IdentityModel.Metadata 6 { 7 using System.Collections.Generic; 8 using System.Globalization; 9 using System.IdentityModel.Configuration; 10 using System.IdentityModel.Diagnostics; 11 using System.IdentityModel.Protocols.WSFederation; 12 using System.IdentityModel.Protocols.WSTrust; 13 using System.IdentityModel.Selectors; 14 using System.IdentityModel.Tokens; 15 using System.IO; 16 using System.Security.Cryptography.X509Certificates; 17 using System.ServiceModel.Security; 18 using System.Text; 19 using System.Xml; 20 using System.Xml.Schema; 21 22 /// <summary> 23 /// Provides support for Metadata Serialization 24 /// </summary> 25 public class MetadataSerializer 26 { 27 #pragma warning disable 1591 28 public const string LanguagePrefix = "xml"; 29 public const string LanguageLocalName = "lang"; 30 public const string LanguageAttribute = LanguagePrefix + ":" + LanguageLocalName; 31 public const string LanguageNamespaceUri = "http://www.w3.org/XML/1998/namespace"; 32 #pragma warning restore 1591 33 34 const string _uriReference = "_metadata"; 35 List<string> _trustedIssuers = new List<string>(); 36 SecurityTokenSerializer _tokenSerializer; 37 38 /// <summary> 39 /// Initializes an instance of <see cref="MetadataSerializer"/> 40 /// </summary> MetadataSerializer()41 public MetadataSerializer() 42 : this(new KeyInfoSerializer(true)) 43 { 44 } 45 46 47 /// <summary> 48 /// Initializes an instance of <see cref="MetadataSerializer"/> 49 /// </summary> 50 /// <param name="tokenSerializer">Security Token Serializer</param> 51 /// <exception cref="ArgumentNullException">The parameter tokenSerializer is null.</exception> MetadataSerializer(SecurityTokenSerializer tokenSerializer)52 public MetadataSerializer(SecurityTokenSerializer tokenSerializer) 53 { 54 if (tokenSerializer == null) 55 { 56 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenSerializer"); 57 } 58 59 _tokenSerializer = tokenSerializer; 60 TrustedStoreLocation = IdentityConfiguration.DefaultTrustedStoreLocation; 61 CertificateValidationMode = IdentityConfiguration.DefaultCertificateValidationMode; 62 RevocationMode = IdentityConfiguration.DefaultRevocationMode; 63 } 64 65 /// <summary> 66 /// Creates an application service descriptor. 67 /// </summary> 68 /// <returns>An application service descriptor.</returns> CreateApplicationServiceInstance()69 protected virtual ApplicationServiceDescriptor CreateApplicationServiceInstance() 70 { 71 return new ApplicationServiceDescriptor(); 72 } 73 74 /// <summary> 75 /// Creates a contact person. 76 /// </summary> 77 /// <returns>A contact person.</returns> CreateContactPersonInstance()78 protected virtual ContactPerson CreateContactPersonInstance() 79 { 80 return new ContactPerson(); 81 } 82 83 /// <summary> 84 /// Creates an endpoint. 85 /// </summary> 86 /// <returns>An endpoint.</returns> CreateProtocolEndpointInstance()87 protected virtual ProtocolEndpoint CreateProtocolEndpointInstance() 88 { 89 return new ProtocolEndpoint(); 90 } 91 92 /// <summary> 93 /// Creates entities descriptor. 94 /// </summary> 95 /// <returns>The entities descriptor. </returns> CreateEntitiesDescriptorInstance()96 protected virtual EntitiesDescriptor CreateEntitiesDescriptorInstance() 97 { 98 return new EntitiesDescriptor(); 99 } 100 101 /// <summary> 102 /// Creates an entity descriptor. 103 /// </summary> 104 /// <returns>The entity descriptor.</returns> CreateEntityDescriptorInstance()105 protected virtual EntityDescriptor CreateEntityDescriptorInstance() 106 { 107 return new EntityDescriptor(); 108 } 109 110 /// <summary> 111 /// Creates an idpsso descriptor. 112 /// </summary> 113 /// <returns>An idpsso descriptor.</returns> CreateIdentityProviderSingleSignOnDescriptorInstance()114 protected virtual IdentityProviderSingleSignOnDescriptor CreateIdentityProviderSingleSignOnDescriptorInstance() 115 { 116 return new IdentityProviderSingleSignOnDescriptor(); 117 } 118 119 /// <summary> 120 /// Creates an indexed enpoint. 121 /// </summary> 122 /// <returns>An indexed endpoint.</returns> CreateIndexedProtocolEndpointInstance()123 protected virtual IndexedProtocolEndpoint CreateIndexedProtocolEndpointInstance() 124 { 125 return new IndexedProtocolEndpoint(); 126 } 127 128 /// <summary> 129 /// Creates a key descriptor. 130 /// </summary> 131 /// <returns>The key descriptor.</returns> CreateKeyDescriptorInstance()132 protected virtual KeyDescriptor CreateKeyDescriptorInstance() 133 { 134 return new KeyDescriptor(); 135 } 136 137 /// <summary> 138 /// Creates a localized name. 139 /// </summary> 140 /// <returns>The localized name.</returns> CreateLocalizedNameInstance()141 protected virtual LocalizedName CreateLocalizedNameInstance() 142 { 143 return new LocalizedName(); 144 } 145 146 /// <summary> 147 /// Creates a localized uri. 148 /// </summary> 149 /// <returns>A localized uri.</returns> CreateLocalizedUriInstance()150 protected virtual LocalizedUri CreateLocalizedUriInstance() 151 { 152 return new LocalizedUri(); 153 } 154 155 /// <summary> 156 /// Creates an organization. 157 /// </summary> 158 /// <returns>An organization.</returns> CreateOrganizationInstance()159 protected virtual Organization CreateOrganizationInstance() 160 { 161 return new Organization(); 162 } 163 164 /// <summary> 165 /// Creates a security token service descriptor. 166 /// </summary> 167 /// <returns>A security token service descriptor.</returns> CreateSecurityTokenServiceDescriptorInstance()168 protected virtual SecurityTokenServiceDescriptor CreateSecurityTokenServiceDescriptorInstance() 169 { 170 return new SecurityTokenServiceDescriptor(); 171 } 172 173 /// <summary> 174 /// Creates an Spsso descriptor. 175 /// </summary> 176 /// <returns>An Spsso descriptor.</returns> CreateServiceProviderSingleSignOnDescriptorInstance()177 protected virtual ServiceProviderSingleSignOnDescriptor CreateServiceProviderSingleSignOnDescriptorInstance() 178 { 179 return new ServiceProviderSingleSignOnDescriptor(); 180 } 181 182 /// <summary> 183 /// Returns the respective contact type from a string contact type. 184 /// </summary> 185 /// <param name="conactType">The string type.</param> 186 /// <param name="found">If found a match.</param> 187 /// <returns>The contact type.</returns> GetContactPersonType(string conactType, out bool found)188 private static ContactType GetContactPersonType(string conactType, out bool found) 189 { 190 if (conactType == null) 191 { 192 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("conactType"); 193 } 194 found = true; 195 if (StringComparer.Ordinal.Equals(conactType, "unspecified")) 196 { 197 return ContactType.Unspecified; 198 } 199 else if (StringComparer.Ordinal.Equals(conactType, "administrative")) 200 { 201 return ContactType.Administrative; 202 } 203 else if (StringComparer.Ordinal.Equals(conactType, "billing")) 204 { 205 return ContactType.Billing; 206 } 207 else if (StringComparer.Ordinal.Equals(conactType, "other")) 208 { 209 return ContactType.Other; 210 } 211 else if (StringComparer.Ordinal.Equals(conactType, "support")) 212 { 213 return ContactType.Support; 214 } 215 else if (StringComparer.Ordinal.Equals(conactType, "technical")) 216 { 217 return ContactType.Technical; 218 } 219 found = false; 220 return ContactType.Unspecified; 221 222 } 223 GetKeyDescriptorType(string keyType)224 private static KeyType GetKeyDescriptorType(string keyType) 225 { 226 if (keyType == null) 227 { 228 return KeyType.Unspecified; 229 } 230 else if (StringComparer.Ordinal.Equals(keyType, "encryption")) 231 { 232 return KeyType.Encryption; 233 } 234 else if (StringComparer.Ordinal.Equals(keyType, "signing")) 235 { 236 return KeyType.Signing; 237 } 238 239 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.Use, keyType))); 240 } 241 242 /// <summary> 243 /// Reads application service descriptor. 244 /// </summary> 245 /// <param name="reader">Xml reader.</param> 246 /// <returns>An application service descriptor.</returns> 247 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadApplicationServiceDescriptor(XmlReader reader)248 protected virtual ApplicationServiceDescriptor ReadApplicationServiceDescriptor(XmlReader reader) 249 { 250 if (reader == null) 251 { 252 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 253 } 254 255 ApplicationServiceDescriptor appService = CreateApplicationServiceInstance(); 256 ReadWebServiceDescriptorAttributes(reader, appService); 257 ReadCustomAttributes<ApplicationServiceDescriptor>(reader, appService); 258 259 bool isEmpty = reader.IsEmptyElement; 260 reader.ReadStartElement(); 261 if (!isEmpty) 262 { 263 while (reader.IsStartElement()) 264 { 265 if (reader.IsStartElement(FederationMetadataConstants.Elements.ApplicationServiceEndpoint, FederationMetadataConstants.Namespace)) 266 { 267 isEmpty = reader.IsEmptyElement; 268 reader.ReadStartElement(); 269 if (!isEmpty && reader.IsStartElement()) 270 { 271 EndpointReference address = EndpointReference.ReadFrom(reader); 272 appService.Endpoints.Add(address); 273 reader.ReadEndElement(); 274 } 275 } 276 else if (reader.IsStartElement(FederationMetadataConstants.Elements.PassiveRequestorEndpoint, FederationMetadataConstants.Namespace)) 277 { 278 isEmpty = reader.IsEmptyElement; 279 reader.ReadStartElement(); 280 if (!isEmpty && reader.IsStartElement()) 281 { 282 EndpointReference address = EndpointReference.ReadFrom(reader); 283 appService.PassiveRequestorEndpoints.Add(address); 284 reader.ReadEndElement(); 285 } 286 } 287 else if (ReadWebServiceDescriptorElement(reader, appService)) 288 { 289 // Do nothing 290 } 291 else if (ReadCustomElement<ApplicationServiceDescriptor>(reader, appService)) 292 { 293 // Do nothing. 294 } 295 else 296 { 297 reader.Skip(); 298 } 299 } 300 301 // SecurityTokenService 302 reader.ReadEndElement(); 303 } 304 305 return appService; 306 } 307 308 /// <summary> 309 /// Reads a contact person. 310 /// </summary> 311 /// <param name="reader">Xml reader.</param> 312 /// <returns>A contact person.</returns> 313 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadContactPerson(XmlReader reader)314 protected virtual ContactPerson ReadContactPerson(XmlReader reader) 315 { 316 if (reader == null) 317 { 318 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 319 } 320 ContactPerson person = CreateContactPersonInstance(); 321 322 string contactType = reader.GetAttribute(Saml2MetadataConstants.Attributes.ContactType, null); 323 bool foundKey = false; 324 325 person.Type = GetContactPersonType(contactType, out foundKey); 326 if (!foundKey) 327 { 328 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3201, typeof(ContactType), contactType))); 329 } 330 331 ReadCustomAttributes<ContactPerson>(reader, person); 332 333 bool isEmpty = reader.IsEmptyElement; 334 reader.ReadStartElement(); // <ContactPerson> 335 if (!isEmpty) 336 { 337 while (reader.IsStartElement()) 338 { 339 if (reader.IsStartElement(Saml2MetadataConstants.Elements.Company, Saml2MetadataConstants.Namespace)) 340 { 341 person.Company = reader.ReadElementContentAsString(Saml2MetadataConstants.Elements.Company, Saml2MetadataConstants.Namespace); 342 } 343 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.GivenName, Saml2MetadataConstants.Namespace)) 344 { 345 person.GivenName = reader.ReadElementContentAsString(Saml2MetadataConstants.Elements.GivenName, Saml2MetadataConstants.Namespace); 346 } 347 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.Surname, Saml2MetadataConstants.Namespace)) 348 { 349 person.Surname = reader.ReadElementContentAsString(Saml2MetadataConstants.Elements.Surname, Saml2MetadataConstants.Namespace); 350 } 351 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.EmailAddress, Saml2MetadataConstants.Namespace)) 352 { 353 string emailId = reader.ReadElementContentAsString(Saml2MetadataConstants.Elements.EmailAddress, Saml2MetadataConstants.Namespace); 354 if (!String.IsNullOrEmpty(emailId)) 355 { 356 person.EmailAddresses.Add(emailId); 357 } 358 } 359 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.TelephoneNumber, Saml2MetadataConstants.Namespace)) 360 { 361 string phone = reader.ReadElementContentAsString(Saml2MetadataConstants.Elements.TelephoneNumber, Saml2MetadataConstants.Namespace); 362 if (!String.IsNullOrEmpty(phone)) 363 { 364 person.TelephoneNumbers.Add(phone); 365 } 366 } 367 else if (ReadCustomElement<ContactPerson>(reader, person)) 368 { 369 // Do nothing 370 } 371 else 372 { 373 reader.Skip(); 374 } 375 376 } 377 reader.ReadEndElement(); // </ContactPerson> 378 } 379 380 // No mandatory elements to be validated. 381 return person; 382 } 383 384 /// <summary> 385 /// Extensibility point for reading custom attributes. 386 /// </summary> 387 /// <typeparam name="T">The type of element.</typeparam> 388 /// <param name="reader">Xml reader.</param> 389 /// <param name="target">An object of type T.</param> ReadCustomAttributes(XmlReader reader, T target)390 protected virtual void ReadCustomAttributes<T>(XmlReader reader, T target) 391 { 392 // Extensibility point only. Do Nothing. 393 } 394 395 /// <summary> 396 /// Extensibility point for reading custom elements. By default this returns false. 397 /// </summary> 398 /// <typeparam name="T">The type of element.</typeparam> 399 /// <param name="reader">Xml reader.</param> 400 /// <param name="target">An object of type T.</param> 401 /// <returns>True if an element of type T is read, else false.</returns> ReadCustomElement(XmlReader reader, T target)402 protected virtual bool ReadCustomElement<T>(XmlReader reader, T target) 403 { 404 // Extensibility point only. Do Nothing. 405 return false; 406 } 407 408 /// <summary> 409 /// Extensibility point for reading custom RoleDescriptors. 410 /// </summary> 411 /// <param name="xsiType">The xsi type</param> 412 /// <param name="reader">Xml reader</param> 413 /// <param name="entityDescriptor">The entity descriptor for adding the Role Descriptors</param> ReadCustomRoleDescriptor(string xsiType, XmlReader reader, EntityDescriptor entityDescriptor)414 protected virtual void ReadCustomRoleDescriptor(string xsiType, XmlReader reader, EntityDescriptor entityDescriptor) 415 { 416 // 417 // Extensibility point: Based on the xsiType, overriden implementations have the ability to read the RoleDescriptor 418 // attributes from a (##other) namespace and add the Role Descriptors to the entityDescriptor 419 // 420 if (reader == null) 421 { 422 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 423 } 424 425 TraceUtility.TraceString(System.Diagnostics.TraceEventType.Warning, SR.GetString(SR.ID3274, xsiType)); 426 reader.Skip(); 427 } 428 429 /// <summary> 430 /// Returns the <see cref="DisplayClaim"/> from the <paramref name="reader"/>. 431 /// </summary> 432 /// <param name="reader">XML reader.</param> 433 /// <returns>The display claim.</returns> 434 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> 435 /// <exception cref="MetadataSerializationException">Thrown if the XML is not well-formed.</exception> ReadDisplayClaim(XmlReader reader)436 protected virtual DisplayClaim ReadDisplayClaim(XmlReader reader) 437 { 438 if (reader == null) 439 { 440 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 441 } 442 443 // 444 // This is out of scope for extensibility. 445 // 446 string claimType = reader.GetAttribute(WSFederationMetadataConstants.Attributes.Uri, null); 447 if (!UriUtil.CanCreateValidUri(claimType, UriKind.Absolute)) 448 { 449 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, WSAuthorizationConstants.Elements.ClaimType, claimType))); 450 } 451 DisplayClaim claim = new DisplayClaim(claimType); 452 453 bool isOptional = true; 454 string optionalString = reader.GetAttribute(WSFederationMetadataConstants.Attributes.Optional); 455 if (!String.IsNullOrEmpty(optionalString)) 456 { 457 try 458 { 459 isOptional = XmlConvert.ToBoolean(optionalString.ToLowerInvariant()); 460 } 461 catch (FormatException) 462 { 463 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, WSFederationMetadataConstants.Attributes.Optional, optionalString))); 464 } 465 } 466 claim.Optional = isOptional; 467 468 bool isEmpty = reader.IsEmptyElement; 469 reader.ReadStartElement(); 470 if (!isEmpty) 471 { 472 while (reader.IsStartElement()) 473 { 474 if (reader.IsStartElement(WSAuthorizationConstants.Elements.DisplayName, WSAuthorizationConstants.Namespace)) 475 { 476 claim.DisplayTag = reader.ReadElementContentAsString(WSAuthorizationConstants.Elements.DisplayName, WSAuthorizationConstants.Namespace); 477 } 478 else if (reader.IsStartElement(WSAuthorizationConstants.Elements.Description, WSAuthorizationConstants.Namespace)) 479 { 480 claim.Description = reader.ReadElementContentAsString(WSAuthorizationConstants.Elements.Description, WSAuthorizationConstants.Namespace); 481 } 482 else 483 { 484 // Move on 485 reader.Skip(); 486 } 487 } 488 reader.ReadEndElement(); 489 } 490 return claim; 491 } 492 493 /// <summary> 494 /// Reads entities descriptor. 495 /// </summary> 496 /// <param name="reader">Xml reader.</param> 497 /// <param name="tokenResolver">The security token resolver.</param> 498 /// <returns>The entities descriptor.</returns> 499 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> 500 /// <exception cref="MetadataSerializationException">Thrown if the XML is not well-formed.</exception> ReadEntitiesDescriptor(XmlReader reader, SecurityTokenResolver tokenResolver)501 protected virtual EntitiesDescriptor ReadEntitiesDescriptor(XmlReader reader, SecurityTokenResolver tokenResolver) 502 { 503 if (reader == null) 504 { 505 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 506 } 507 508 EntitiesDescriptor resultEntityGroup = CreateEntitiesDescriptorInstance(); 509 510 // 511 // There may be embedded signed XML elements. So we need to plumb the SecurityTokenSerializer and tokenResolver 512 // 513 EnvelopedSignatureReader envelopeReader = new EnvelopedSignatureReader(reader, SecurityTokenSerializer, tokenResolver, false, false, true); 514 515 string name = envelopeReader.GetAttribute(Saml2MetadataConstants.Attributes.EntityGroupName, null); 516 if (!String.IsNullOrEmpty(name)) 517 { 518 resultEntityGroup.Name = name; 519 } 520 521 ReadCustomAttributes<EntitiesDescriptor>(envelopeReader, resultEntityGroup); 522 523 bool isEmpty = envelopeReader.IsEmptyElement; 524 envelopeReader.ReadStartElement(); // <EntitiesDescriptor> 525 if (!isEmpty) 526 { 527 while (envelopeReader.IsStartElement()) 528 { 529 if (envelopeReader.IsStartElement(Saml2MetadataConstants.Elements.EntityDescriptor, Saml2MetadataConstants.Namespace)) 530 { 531 resultEntityGroup.ChildEntities.Add(ReadEntityDescriptor(envelopeReader, tokenResolver)); 532 } 533 else if (envelopeReader.IsStartElement(Saml2MetadataConstants.Elements.EntitiesDescriptor, Saml2MetadataConstants.Namespace)) 534 { 535 resultEntityGroup.ChildEntityGroups.Add(ReadEntitiesDescriptor(envelopeReader, tokenResolver)); 536 } 537 else if (envelopeReader.TryReadSignature()) 538 { 539 // Do nothng 540 } 541 else if (ReadCustomElement<EntitiesDescriptor>(envelopeReader, resultEntityGroup)) 542 { 543 // Do nothing. 544 } 545 else 546 { 547 envelopeReader.Skip(); 548 } 549 550 } 551 envelopeReader.ReadEndElement(); // </EntitiesDescriptor> 552 } 553 554 resultEntityGroup.SigningCredentials = envelopeReader.SigningCredentials; 555 556 if (resultEntityGroup.SigningCredentials != null) 557 { 558 ValidateSigningCredential(resultEntityGroup.SigningCredentials); 559 } 560 561 if (resultEntityGroup.ChildEntityGroups.Count == 0 && resultEntityGroup.ChildEntities.Count == 0) 562 { 563 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3200, Saml2MetadataConstants.Elements.EntityDescriptor))); 564 } 565 foreach (EntityDescriptor entity in resultEntityGroup.ChildEntities) 566 { 567 if (!String.IsNullOrEmpty(entity.FederationId)) 568 { 569 if (!StringComparer.Ordinal.Equals(entity.FederationId, resultEntityGroup.Name)) 570 { 571 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, WSFederationMetadataConstants.Attributes.FederationId, entity.FederationId))); 572 } 573 } 574 } 575 return resultEntityGroup; 576 } 577 578 /// <summary> 579 /// Gets or sets the validation mode of the X509 certificate that is used to sign the metadata document. 580 /// </summary> 581 public X509CertificateValidationMode CertificateValidationMode 582 { 583 get; 584 set; 585 } 586 587 /// <summary> 588 /// Gets or sets the revocation mode of the X509 certificate that is used to sign the metadata document. 589 /// </summary> 590 public X509RevocationMode RevocationMode 591 { 592 get; 593 set; 594 } 595 596 /// <summary> 597 /// Gets or sets the trusted store location of the X509 certificate that is used to sign the metadata document. 598 /// </summary> 599 public StoreLocation TrustedStoreLocation 600 { 601 get; 602 set; 603 } 604 605 /// <summary> 606 /// Gets or sets the certificate validator of the X509 certificate that is used to sign the metadata document. 607 /// </summary> 608 public X509CertificateValidator CertificateValidator 609 { 610 get; 611 set; 612 } 613 614 /// <summary> 615 /// Gets the list of trusted issuer that this serializer instance trusts to sign the metadata docuemnt. 616 /// </summary> 617 public List<string> TrustedIssuers 618 { 619 get { return _trustedIssuers; } 620 } 621 622 /// <summary> 623 /// Validates the signing credential of the metadata document. 624 /// </summary> 625 /// <param name="signingCredentials">The signing credential used to sign the metadata document.</param> 626 /// <exception cref="ArgumentNullException">If <paramref name="signingCredentials"/> is null.</exception> ValidateSigningCredential(SigningCredentials signingCredentials)627 protected virtual void ValidateSigningCredential(SigningCredentials signingCredentials) 628 { 629 if (signingCredentials == null) 630 { 631 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("signingCredentials"); 632 } 633 634 if (CertificateValidationMode != X509CertificateValidationMode.Custom) 635 { 636 CertificateValidator = X509Util.CreateCertificateValidator(CertificateValidationMode, RevocationMode, TrustedStoreLocation); 637 } 638 else if (CertificateValidationMode == X509CertificateValidationMode.Custom && CertificateValidator == null) 639 { 640 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4280))); 641 } 642 643 X509Certificate2 certificate = GetMetadataSigningCertificate(signingCredentials.SigningKeyIdentifier); 644 645 ValidateIssuer(certificate); 646 CertificateValidator.Validate(certificate); 647 } 648 649 /// <summary> 650 /// Validates the certificate that signed the metadata document against the TrustedIssuers. This method is invoked by the ValidateSigningCredential method. 651 /// By default, this method does not perform any validation. Provide your own implementation to perform trusted issuer validation. 652 /// </summary> 653 /// <param name="signingCertificate">The signing certificate.</param> ValidateIssuer(X509Certificate2 signingCertificate)654 protected virtual void ValidateIssuer(X509Certificate2 signingCertificate) 655 { 656 // No-op by default. 657 } 658 659 /// <summary> 660 /// Gets the <see cref="X509Certificate2"/> instance created from the <paramref name="ski"/>. 661 /// By default, this method only supports <see cref="X509RawDataKeyIdentifierClause"/>. Override this method 662 /// to support other key identifier clauses. This method is invoked by the ValidateSigningCredential method. 663 /// </summary> 664 /// <param name="ski">The security key identifier instance.</param> 665 /// <returns>An <see cref="X509Certificate2"/> instance.</returns> GetMetadataSigningCertificate( SecurityKeyIdentifier ski )666 protected virtual X509Certificate2 GetMetadataSigningCertificate( SecurityKeyIdentifier ski ) 667 { 668 if (ski == null) 669 { 670 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ski"); 671 } 672 673 X509RawDataKeyIdentifierClause clause = null; 674 if (ski.TryFind<X509RawDataKeyIdentifierClause>(out clause)) 675 { 676 return new X509Certificate2(clause.GetX509RawData()); 677 } 678 else 679 { 680 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID8029))); 681 } 682 } 683 684 /// <summary> 685 /// Reads an entity descriptor. 686 /// </summary> 687 /// <param name="inputReader">The xml reader.</param> 688 /// <param name="tokenResolver">The security token resolver.</param> 689 /// <returns>An entity descriptor.</returns> 690 /// <exception cref="ArgumentNullException">The parameter inputReader is null.</exception> ReadEntityDescriptor(XmlReader inputReader, SecurityTokenResolver tokenResolver)691 protected virtual EntityDescriptor ReadEntityDescriptor(XmlReader inputReader, SecurityTokenResolver tokenResolver) 692 { 693 if (inputReader == null) 694 { 695 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("inputReader"); 696 } 697 698 EntityDescriptor resultEntity = CreateEntityDescriptorInstance(); 699 700 // 701 // There may be embedded signed XML elements. So we need to plumb the SecurityTokenSerializer and tokenResolver 702 // IDFX 703 704 EnvelopedSignatureReader reader = new EnvelopedSignatureReader(inputReader, SecurityTokenSerializer, tokenResolver, false, false, true); 705 706 // EntityID is mandatory - relaxed as per FIP 9935 707 string entityId = reader.GetAttribute(Saml2MetadataConstants.Attributes.EntityId, null); 708 if (!String.IsNullOrEmpty(entityId)) 709 { 710 resultEntity.EntityId = new EntityId(entityId); 711 } 712 713 // FederationID is optional 714 string fedId = reader.GetAttribute(WSFederationMetadataConstants.Attributes.FederationId, WSFederationMetadataConstants.Namespace); 715 if (!String.IsNullOrEmpty(fedId)) 716 { 717 resultEntity.FederationId = fedId; 718 } 719 720 ReadCustomAttributes<EntityDescriptor>(reader, resultEntity); 721 722 bool isEmpty = reader.IsEmptyElement; 723 reader.ReadStartElement(); 724 if (!isEmpty) 725 { 726 while (reader.IsStartElement()) 727 { 728 if (reader.IsStartElement(Saml2MetadataConstants.Elements.SpssoDescriptor, Saml2MetadataConstants.Namespace)) 729 { 730 resultEntity.RoleDescriptors.Add(ReadServiceProviderSingleSignOnDescriptor(reader)); 731 } 732 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.IdpssoDescriptor, Saml2MetadataConstants.Namespace)) 733 { 734 resultEntity.RoleDescriptors.Add(ReadIdentityProviderSingleSignOnDescriptor(reader)); 735 } 736 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.RoleDescriptor, Saml2MetadataConstants.Namespace)) 737 { 738 string xsiType = reader.GetAttribute("type", XmlSchema.InstanceNamespace); 739 740 if (!String.IsNullOrEmpty(xsiType)) 741 { 742 int index = xsiType.IndexOf(":", 0, StringComparison.Ordinal); 743 if (index < 0) 744 { 745 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3207, "xsi:type", Saml2MetadataConstants.Elements.RoleDescriptor, xsiType))); 746 } 747 string prefix = xsiType.Substring(0, index); 748 string ns = reader.LookupNamespace(prefix); 749 750 if (String.IsNullOrEmpty(ns)) 751 { 752 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, prefix, ns))); 753 } 754 else if (!StringComparer.Ordinal.Equals(ns, FederationMetadataConstants.Namespace)) 755 { 756 ReadCustomRoleDescriptor(xsiType, reader, resultEntity); 757 } 758 else if (StringComparer.Ordinal.Equals(xsiType, prefix + ":" + FederationMetadataConstants.Elements.ApplicationServiceType)) 759 { 760 resultEntity.RoleDescriptors.Add(ReadApplicationServiceDescriptor(reader)); 761 } 762 else if (StringComparer.Ordinal.Equals(xsiType, prefix + ":" + FederationMetadataConstants.Elements.SecurityTokenServiceType)) 763 { 764 resultEntity.RoleDescriptors.Add(ReadSecurityTokenServiceDescriptor(reader)); 765 } 766 else 767 { 768 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3207, "xsi:type", Saml2MetadataConstants.Elements.RoleDescriptor, xsiType))); 769 } 770 } 771 else 772 { 773 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID0001, "xsi:type", Saml2MetadataConstants.Elements.RoleDescriptor))); 774 } 775 } 776 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.Organization, Saml2MetadataConstants.Namespace)) 777 { 778 resultEntity.Organization = ReadOrganization(reader); 779 } 780 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.ContactPerson, Saml2MetadataConstants.Namespace)) 781 { 782 resultEntity.Contacts.Add(ReadContactPerson(reader)); 783 } 784 else if (reader.TryReadSignature()) 785 { 786 // Do nothing 787 } 788 else if (ReadCustomElement<EntityDescriptor>(reader, resultEntity)) 789 { 790 // Do nothing. 791 } 792 else 793 { 794 reader.Skip(); 795 } 796 } 797 reader.ReadEndElement(); 798 } 799 800 resultEntity.SigningCredentials = reader.SigningCredentials; 801 if (resultEntity.SigningCredentials != null) 802 { 803 ValidateSigningCredential(resultEntity.SigningCredentials); 804 } 805 806 // Elements are optional. Mandatory attributes already validated. 807 808 return resultEntity; 809 } 810 811 /// <summary> 812 /// Reads an idpsso descriptor. 813 /// </summary> 814 /// <param name="reader">The xml reader.</param> 815 /// <returns>An idpsso descriptor.</returns> 816 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadIdentityProviderSingleSignOnDescriptor(XmlReader reader)817 protected virtual IdentityProviderSingleSignOnDescriptor ReadIdentityProviderSingleSignOnDescriptor(XmlReader reader) 818 { 819 if (reader == null) 820 { 821 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 822 } 823 824 IdentityProviderSingleSignOnDescriptor idpssoDescriptor = CreateIdentityProviderSingleSignOnDescriptorInstance(); 825 ReadSingleSignOnDescriptorAttributes(reader, idpssoDescriptor); 826 ReadCustomAttributes<IdentityProviderSingleSignOnDescriptor>(reader, idpssoDescriptor); 827 828 string wantAuthnRequestSignedAttribute = reader.GetAttribute(Saml2MetadataConstants.Attributes.WantAuthenticationRequestsSigned); 829 if (!String.IsNullOrEmpty(wantAuthnRequestSignedAttribute)) 830 { 831 try 832 { 833 idpssoDescriptor.WantAuthenticationRequestsSigned = XmlConvert.ToBoolean(wantAuthnRequestSignedAttribute.ToLowerInvariant()); 834 } 835 catch (FormatException) 836 { 837 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString( 838 SR.ID3202, Saml2MetadataConstants.Attributes.WantAuthenticationRequestsSigned, wantAuthnRequestSignedAttribute))); 839 } 840 } 841 842 bool isEmpty = reader.IsEmptyElement; 843 reader.ReadStartElement(); 844 if (!isEmpty) 845 { 846 while (reader.IsStartElement()) 847 { 848 if (reader.IsStartElement(Saml2MetadataConstants.Elements.SingleSignOnService, Saml2MetadataConstants.Namespace)) 849 { 850 ProtocolEndpoint endpoint = ReadProtocolEndpoint(reader); 851 852 // Relaxed check for endpoint.ResponseLocation as per FIP 9935 853 idpssoDescriptor.SingleSignOnServices.Add(endpoint); 854 } 855 else if (reader.IsStartElement(Saml2Constants.Elements.Attribute, Saml2Constants.Namespace)) 856 { 857 idpssoDescriptor.SupportedAttributes.Add(ReadAttribute(reader)); 858 } 859 else if (ReadSingleSignOnDescriptorElement(reader, idpssoDescriptor)) 860 { 861 // Do nothing 862 } 863 else if (ReadCustomElement<IdentityProviderSingleSignOnDescriptor>(reader, idpssoDescriptor)) 864 { 865 // Do nothing. 866 } 867 else 868 { 869 reader.Skip(); 870 } 871 } 872 reader.ReadEndElement(); 873 } 874 875 // Relaxed check for( idpssoDescriptor.SingleSignOnServices.Count == 0 ) as per FIP 9935 876 return idpssoDescriptor; 877 } 878 879 /// <summary> 880 /// Reads an indexed endpoint. 881 /// </summary> 882 /// <param name="reader">The xml reader.</param> 883 /// <returns>An indexed endpoint.</returns> 884 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadIndexedProtocolEndpoint(XmlReader reader)885 protected virtual IndexedProtocolEndpoint ReadIndexedProtocolEndpoint(XmlReader reader) 886 { 887 if (reader == null) 888 { 889 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 890 } 891 892 IndexedProtocolEndpoint endpoint = CreateIndexedProtocolEndpointInstance(); 893 894 string binding = reader.GetAttribute(Saml2MetadataConstants.Attributes.Binding, null); 895 Uri bindingUri; 896 if (!UriUtil.TryCreateValidUri(binding, UriKind.RelativeOrAbsolute, out bindingUri)) 897 { 898 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.Binding, binding))); 899 } 900 endpoint.Binding = bindingUri; 901 902 string location = reader.GetAttribute(Saml2MetadataConstants.Attributes.Location, null); 903 Uri locationUri; 904 if (!UriUtil.TryCreateValidUri(location, UriKind.RelativeOrAbsolute, out locationUri)) 905 { 906 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.Location, location))); 907 } 908 endpoint.Location = locationUri; 909 910 string indexStr = reader.GetAttribute(Saml2MetadataConstants.Attributes.EndpointIndex, null); 911 int index; 912 if (!Int32.TryParse(indexStr, out index)) 913 { 914 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.EndpointIndex, indexStr))); 915 } 916 endpoint.Index = index; 917 918 // responseLocation is optional 919 string responseLocation = reader.GetAttribute(Saml2MetadataConstants.Attributes.ResponseLocation, null); 920 if (!String.IsNullOrEmpty(responseLocation)) 921 { 922 Uri responseUri; 923 if (!UriUtil.TryCreateValidUri(responseLocation, UriKind.RelativeOrAbsolute, out responseUri)) 924 { 925 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.ResponseLocation, responseLocation))); 926 } 927 endpoint.ResponseLocation = responseUri; 928 } 929 930 // isDefault is optional 931 string isDefaultString = reader.GetAttribute(Saml2MetadataConstants.Attributes.EndpointIsDefault, null); 932 if (!String.IsNullOrEmpty(isDefaultString)) 933 { 934 try 935 { 936 endpoint.IsDefault = XmlConvert.ToBoolean(isDefaultString.ToLowerInvariant()); 937 } 938 catch (FormatException) 939 { 940 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.EndpointIsDefault, isDefaultString))); 941 } 942 } 943 944 ReadCustomAttributes<IndexedProtocolEndpoint>(reader, endpoint); 945 946 bool isEmpty = reader.IsEmptyElement; 947 reader.ReadStartElement(); 948 if (!isEmpty) 949 { 950 while (reader.IsStartElement()) 951 { 952 if (ReadCustomElement<IndexedProtocolEndpoint>(reader, endpoint)) 953 { 954 // Do nothing. 955 } 956 else 957 { 958 // Move on 959 reader.Skip(); 960 } 961 } 962 reader.ReadEndElement(); 963 } 964 965 // No elements to validate. Attributes are already validated 966 return endpoint; 967 } 968 969 /// <summary> 970 /// Reads a key descriptor. 971 /// </summary> 972 /// <param name="reader">Xml reader.</param> 973 /// <returns>The key descriptor.</returns> 974 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadKeyDescriptor(XmlReader reader)975 protected virtual KeyDescriptor ReadKeyDescriptor(XmlReader reader) 976 { 977 if (reader == null) 978 { 979 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 980 } 981 KeyDescriptor resultKey = CreateKeyDescriptorInstance(); 982 983 // Use is optional 984 string use = reader.GetAttribute(Saml2MetadataConstants.Attributes.Use, null); 985 if (!String.IsNullOrEmpty(use)) 986 { 987 resultKey.Use = GetKeyDescriptorType(use); 988 } 989 990 ReadCustomAttributes<KeyDescriptor>(reader, resultKey); 991 992 bool isEmpty = reader.IsEmptyElement; 993 reader.ReadStartElement(); 994 if (!isEmpty) 995 { 996 while (reader.IsStartElement()) 997 { 998 if (reader.IsStartElement(XmlSignatureConstants.Elements.KeyInfo, XmlSignatureConstants.Namespace)) 999 { 1000 resultKey.KeyInfo = SecurityTokenSerializer.ReadKeyIdentifier(reader); 1001 } 1002 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.EncryptionMethod, Saml2MetadataConstants.Namespace)) 1003 { 1004 // Read the required algorithm attribute - relaxed as per FIP 9935 1005 string algorithm = reader.GetAttribute(Saml2MetadataConstants.Attributes.Algorithm); 1006 if (!String.IsNullOrEmpty(algorithm) && UriUtil.CanCreateValidUri(algorithm, UriKind.Absolute)) 1007 { 1008 resultKey.EncryptionMethods.Add(new EncryptionMethod(new Uri(algorithm))); 1009 } 1010 1011 isEmpty = reader.IsEmptyElement; 1012 reader.ReadStartElement(Saml2MetadataConstants.Elements.EncryptionMethod, Saml2MetadataConstants.Namespace); 1013 if (!isEmpty) 1014 { 1015 while (reader.IsStartElement()) 1016 { 1017 if (ReadCustomElement<KeyDescriptor>(reader, resultKey)) 1018 { 1019 // Do nothing for now 1020 } 1021 else 1022 { 1023 reader.Skip(); 1024 } 1025 } 1026 reader.ReadEndElement(); 1027 } 1028 } 1029 else if (ReadCustomElement<KeyDescriptor>(reader, resultKey)) 1030 { 1031 // Do nothing. 1032 } 1033 else 1034 { 1035 reader.Skip(); 1036 } 1037 } 1038 reader.ReadEndElement(); 1039 } 1040 1041 if (resultKey.KeyInfo == null) 1042 { 1043 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3200, XmlSignatureConstants.Elements.KeyInfo))); 1044 } 1045 return resultKey; 1046 } 1047 1048 /// <summary> 1049 /// Reads a localized name. 1050 /// </summary> 1051 /// <param name="reader">The xml reader.</param> 1052 /// <returns>A localized name.</returns> 1053 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadLocalizedName(XmlReader reader)1054 protected virtual LocalizedName ReadLocalizedName(XmlReader reader) 1055 { 1056 if (reader == null) 1057 { 1058 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1059 } 1060 1061 LocalizedName resultName = CreateLocalizedNameInstance(); 1062 1063 string lang = reader.GetAttribute(LanguageLocalName, LanguageNamespaceUri); 1064 try 1065 { 1066 resultName.Language = CultureInfo.GetCultureInfo(lang); 1067 } 1068 catch (ArgumentNullException) 1069 { 1070 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, LanguageLocalName, "null"))); 1071 } 1072 catch (ArgumentException) 1073 { 1074 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, LanguageLocalName, lang))); 1075 } 1076 1077 ReadCustomAttributes<LocalizedName>(reader, resultName); 1078 1079 bool isEmpty = reader.IsEmptyElement; 1080 string elementName = reader.Name; 1081 reader.ReadStartElement(); 1082 if (!isEmpty) 1083 { 1084 resultName.Name = reader.ReadContentAsString(); 1085 while (reader.IsStartElement()) 1086 { 1087 if (ReadCustomElement<LocalizedName>(reader, resultName)) 1088 { 1089 // Do nothing. 1090 } 1091 else 1092 { 1093 // Move on 1094 reader.Skip(); 1095 } 1096 } 1097 reader.ReadEndElement(); 1098 } 1099 1100 if (String.IsNullOrEmpty(resultName.Name)) 1101 { 1102 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3200, elementName))); 1103 } 1104 return resultName; 1105 } 1106 1107 /// <summary> 1108 /// Reads a localized uri. 1109 /// </summary> 1110 /// <param name="reader">The xml reader.</param> 1111 /// <returns>A localized uri.</returns> 1112 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadLocalizedUri(XmlReader reader)1113 protected virtual LocalizedUri ReadLocalizedUri(XmlReader reader) 1114 { 1115 if (reader == null) 1116 { 1117 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1118 } 1119 1120 LocalizedUri resultUri = CreateLocalizedUriInstance(); 1121 1122 string lang = reader.GetAttribute(LanguageLocalName, LanguageNamespaceUri); 1123 try 1124 { 1125 resultUri.Language = CultureInfo.GetCultureInfo(lang); 1126 } 1127 catch (ArgumentNullException) 1128 { 1129 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, LanguageLocalName, "null"))); 1130 } 1131 catch (ArgumentException) 1132 { 1133 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, LanguageLocalName, lang))); 1134 } 1135 1136 ReadCustomAttributes<LocalizedUri>(reader, resultUri); 1137 1138 bool isEmpty = reader.IsEmptyElement; 1139 string elementName = reader.Name; 1140 reader.ReadStartElement(); 1141 if (!isEmpty) 1142 { 1143 string uriContent = reader.ReadContentAsString(); 1144 Uri uri; 1145 if (!UriUtil.TryCreateValidUri(uriContent, UriKind.RelativeOrAbsolute, out uri)) 1146 { 1147 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, elementName, uriContent))); 1148 } 1149 resultUri.Uri = uri; 1150 while (reader.IsStartElement()) 1151 { 1152 if (ReadCustomElement<LocalizedUri>(reader, resultUri)) 1153 { 1154 // Do nothing. 1155 } 1156 else 1157 { 1158 reader.Skip(); 1159 } 1160 } 1161 reader.ReadEndElement(); 1162 } 1163 1164 if (resultUri.Uri == null) 1165 { 1166 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3200, elementName))); 1167 } 1168 return resultUri; 1169 } 1170 1171 /// <summary> 1172 /// Reads the given stream to deserialize a FederationMetadata instance. 1173 /// </summary> 1174 /// <param name="stream">Stream to be read.</param> 1175 /// <returns>An FederationMetadata instance.</returns> 1176 /// <exception cref="ArgumentNullException">The parameter stream is null.</exception> ReadMetadata(Stream stream)1177 public MetadataBase ReadMetadata(Stream stream) 1178 { 1179 if (stream == null) 1180 { 1181 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream"); 1182 } 1183 XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, XmlDictionaryReaderQuotas.Max); 1184 return ReadMetadata(reader); 1185 } 1186 1187 /// <summary> 1188 /// Read the given XmlReader to deserialize the FederationMetadata instance. 1189 /// </summary> 1190 /// <param name="reader">XmlReader to be read.</param> 1191 /// <returns>An FederationMetadata instance</returns> ReadMetadata(XmlReader reader)1192 public MetadataBase ReadMetadata(XmlReader reader) 1193 { 1194 return ReadMetadata(reader, EmptySecurityTokenResolver.Instance); 1195 } 1196 1197 /// <summary> 1198 /// Read the given XmlReader to deserialize the FederationMetadata instance. 1199 /// </summary> 1200 /// <param name="reader">XmlReader to be read.</param> 1201 /// <param name="tokenResolver">Token resolver to resolve the signature token.</param> 1202 /// <returns>An FederationMetadata instance.</returns> 1203 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadMetadata(XmlReader reader, SecurityTokenResolver tokenResolver)1204 public MetadataBase ReadMetadata(XmlReader reader, SecurityTokenResolver tokenResolver) 1205 { 1206 if (reader == null) 1207 { 1208 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1209 } 1210 if (tokenResolver == null) 1211 { 1212 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenResolver"); 1213 } 1214 if (false == (reader is XmlDictionaryReader)) 1215 { 1216 reader = XmlDictionaryReader.CreateDictionaryReader(reader); 1217 } 1218 1219 MetadataBase metadata = ReadMetadataCore(reader, tokenResolver); 1220 return metadata; 1221 } 1222 1223 /// <summary> 1224 /// Reads metadata. 1225 /// </summary> 1226 /// <param name="reader">The xml reader.</param> 1227 /// <param name="tokenResolver">The security token resolver.</param> 1228 /// <returns>MetadataBase</returns> 1229 /// <exception cref="ArgumentNullException">The parameter reader or tokenReolver is null.</exception> ReadMetadataCore(XmlReader reader, SecurityTokenResolver tokenResolver)1230 protected virtual MetadataBase ReadMetadataCore(XmlReader reader, SecurityTokenResolver tokenResolver) 1231 { 1232 if (reader == null) 1233 { 1234 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1235 } 1236 if (tokenResolver == null) 1237 { 1238 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenResolver"); 1239 } 1240 1241 MetadataBase metadataBase; 1242 1243 if (reader.IsStartElement(Saml2MetadataConstants.Elements.EntitiesDescriptor, Saml2MetadataConstants.Namespace)) 1244 { 1245 metadataBase = ReadEntitiesDescriptor(reader, tokenResolver); 1246 } 1247 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.EntityDescriptor, Saml2MetadataConstants.Namespace)) 1248 { 1249 metadataBase = ReadEntityDescriptor(reader, tokenResolver); 1250 } 1251 else 1252 { 1253 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3260))); 1254 } 1255 1256 return metadataBase; 1257 } 1258 1259 /// <summary> 1260 /// Reads an organization. 1261 /// </summary> 1262 /// <param name="reader">The xml reader.</param> 1263 /// <returns>An organization.</returns> 1264 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadOrganization(XmlReader reader)1265 protected virtual Organization ReadOrganization(XmlReader reader) 1266 { 1267 if (reader == null) 1268 { 1269 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1270 } 1271 Organization resultOrg = CreateOrganizationInstance(); 1272 1273 ReadCustomAttributes<Organization>(reader, resultOrg); 1274 1275 bool isEmpty = reader.IsEmptyElement; 1276 reader.ReadStartElement(); 1277 if (!isEmpty) 1278 { 1279 while (reader.IsStartElement()) 1280 { 1281 if (reader.IsStartElement(Saml2MetadataConstants.Elements.OrganizationName, Saml2MetadataConstants.Namespace)) 1282 { 1283 resultOrg.Names.Add(ReadLocalizedName(reader)); 1284 } 1285 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.OrganizationDisplayName, Saml2MetadataConstants.Namespace)) 1286 { 1287 resultOrg.DisplayNames.Add(ReadLocalizedName(reader)); 1288 } 1289 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.OrganizationUrl, Saml2MetadataConstants.Namespace)) 1290 { 1291 resultOrg.Urls.Add(ReadLocalizedUri(reader)); 1292 } 1293 else if (ReadCustomElement<Organization>(reader, resultOrg)) 1294 { 1295 // Do nothing. 1296 } 1297 else 1298 { 1299 reader.Skip(); 1300 } 1301 } 1302 reader.ReadEndElement(); 1303 } 1304 1305 // Relaxed as per FIP 9935 1306 // if ( resultOrg.DisplayNames.Count < 1 ) 1307 // if ( resultOrg.Names.Count < 1 ) 1308 // if ( resultOrg.Urls.Count < 1 ) 1309 1310 return resultOrg; 1311 } 1312 1313 /// <summary> 1314 /// Reads an endpoint. 1315 /// </summary> 1316 /// <param name="reader">Xml reader.</param> 1317 /// <returns>An endpoint.</returns> 1318 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadProtocolEndpoint(XmlReader reader)1319 protected virtual ProtocolEndpoint ReadProtocolEndpoint(XmlReader reader) 1320 { 1321 if (reader == null) 1322 { 1323 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1324 } 1325 1326 ProtocolEndpoint endpoint = CreateProtocolEndpointInstance(); 1327 1328 string binding = reader.GetAttribute(Saml2MetadataConstants.Attributes.Binding, null); 1329 Uri bindingUri; 1330 if (!UriUtil.TryCreateValidUri(binding, UriKind.RelativeOrAbsolute, out bindingUri)) 1331 { 1332 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.Binding, binding))); 1333 } 1334 endpoint.Binding = bindingUri; 1335 1336 string location = reader.GetAttribute(Saml2MetadataConstants.Attributes.Location, null); 1337 Uri locationUri; 1338 if (!UriUtil.TryCreateValidUri(location, UriKind.RelativeOrAbsolute, out locationUri)) 1339 { 1340 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.Location, location))); 1341 } 1342 endpoint.Location = locationUri; 1343 1344 string responseLocation = reader.GetAttribute(Saml2MetadataConstants.Attributes.ResponseLocation, null); 1345 if (!String.IsNullOrEmpty(responseLocation)) 1346 { 1347 Uri responseUri; 1348 if (!UriUtil.TryCreateValidUri(responseLocation, UriKind.RelativeOrAbsolute, out responseUri)) 1349 { 1350 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.ResponseLocation, responseLocation))); 1351 } 1352 endpoint.ResponseLocation = responseUri; 1353 } 1354 1355 ReadCustomAttributes<ProtocolEndpoint>(reader, endpoint); 1356 1357 bool isEmpty = reader.IsEmptyElement; 1358 reader.ReadStartElement(); // <Endpoint> 1359 if (!isEmpty) 1360 { 1361 while (reader.IsStartElement()) 1362 { 1363 if (!ReadCustomElement<ProtocolEndpoint>(reader, endpoint)) 1364 { 1365 // Move on 1366 reader.Skip(); 1367 } 1368 } 1369 reader.ReadEndElement(); // </Endpoint> 1370 } 1371 1372 return endpoint; 1373 } 1374 1375 /// <summary> 1376 /// Reads role descriptor attributes. 1377 /// </summary> 1378 /// <param name="reader">The xml reader</param> 1379 /// <param name="roleDescriptor">The role descriptor.</param> 1380 /// <exception cref="ArgumentNullException">The parameter reader/roleDescriptor/roleDescriptor.ProtocolsSupported is null.</exception> ReadRoleDescriptorAttributes(XmlReader reader, RoleDescriptor roleDescriptor)1381 protected virtual void ReadRoleDescriptorAttributes(XmlReader reader, RoleDescriptor roleDescriptor) 1382 { 1383 if (reader == null) 1384 { 1385 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1386 } 1387 if (roleDescriptor == null) 1388 { 1389 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor"); 1390 } 1391 if (roleDescriptor.ProtocolsSupported == null) 1392 { 1393 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.ProtocolsSupported"); 1394 } 1395 1396 // Optional 1397 string validUntilString = reader.GetAttribute(Saml2MetadataConstants.Attributes.ValidUntil, null); 1398 if (!String.IsNullOrEmpty(validUntilString)) 1399 { 1400 DateTime validUntil; 1401 if (!DateTime.TryParse(validUntilString, out validUntil)) 1402 { 1403 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.ValidUntil, validUntilString))); 1404 } 1405 roleDescriptor.ValidUntil = validUntil; 1406 } 1407 1408 // Optional 1409 string errorUrlString = reader.GetAttribute(Saml2MetadataConstants.Attributes.ErrorUrl, null); 1410 if (!string.IsNullOrEmpty(errorUrlString)) 1411 { 1412 Uri errorUrl; 1413 if (!UriUtil.TryCreateValidUri(errorUrlString, UriKind.RelativeOrAbsolute, out errorUrl)) 1414 { 1415 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.ErrorUrl, errorUrlString))); 1416 } 1417 roleDescriptor.ErrorUrl = errorUrl; 1418 } 1419 1420 // Mandatory 1421 string protocols = reader.GetAttribute(Saml2MetadataConstants.Attributes.ProtocolsSupported, null); 1422 if (String.IsNullOrEmpty(protocols)) 1423 { 1424 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, Saml2MetadataConstants.Attributes.ProtocolsSupported, protocols))); 1425 } 1426 foreach (string protocol in protocols.Split(' ')) 1427 { 1428 string toAdd = protocol.Trim(); 1429 if (!String.IsNullOrEmpty(toAdd)) 1430 { 1431 roleDescriptor.ProtocolsSupported.Add(new Uri(toAdd)); 1432 } 1433 } 1434 ReadCustomAttributes<RoleDescriptor>(reader, roleDescriptor); 1435 } 1436 1437 /// <summary> 1438 /// Reads role descriptor element. 1439 /// </summary> 1440 /// <param name="reader">The xml reader.</param> 1441 /// <param name="roleDescriptor">The role descriptor.</param> 1442 /// <returns>True if read.</returns> 1443 /// <exception cref="ArgumentNullException">The parameter reader/roleDescriptor/roleDescriptor.Contacts/rolDescriptor.Keys is null.</exception> ReadRoleDescriptorElement(XmlReader reader, RoleDescriptor roleDescriptor)1444 protected virtual bool ReadRoleDescriptorElement(XmlReader reader, RoleDescriptor roleDescriptor) 1445 { 1446 if (reader == null) 1447 { 1448 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1449 } 1450 if (roleDescriptor == null) 1451 { 1452 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor"); 1453 } 1454 if (roleDescriptor.Contacts == null) 1455 { 1456 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.Contacts"); 1457 } 1458 if (roleDescriptor.Keys == null) 1459 { 1460 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.Keys"); 1461 } 1462 1463 if (reader.IsStartElement(Saml2MetadataConstants.Elements.Organization, Saml2MetadataConstants.Namespace)) 1464 { 1465 roleDescriptor.Organization = ReadOrganization(reader); 1466 return true; 1467 } 1468 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.KeyDescriptor, Saml2MetadataConstants.Namespace)) 1469 { 1470 roleDescriptor.Keys.Add(ReadKeyDescriptor(reader)); 1471 return true; 1472 } 1473 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.ContactPerson, Saml2MetadataConstants.Namespace)) 1474 { 1475 roleDescriptor.Contacts.Add(ReadContactPerson(reader)); 1476 return true; 1477 } 1478 else 1479 { 1480 return ReadCustomElement<RoleDescriptor>(reader, roleDescriptor); 1481 } 1482 1483 // No mandatory elements. No validations 1484 } 1485 1486 /// <summary> 1487 /// Reads security token service descriptor. 1488 /// </summary> 1489 /// <param name="reader">The xml reader.</param> 1490 /// <returns>A security token service descriptor.</returns> 1491 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> ReadSecurityTokenServiceDescriptor(XmlReader reader)1492 protected virtual SecurityTokenServiceDescriptor ReadSecurityTokenServiceDescriptor(XmlReader reader) 1493 { 1494 if (reader == null) 1495 { 1496 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1497 } 1498 1499 SecurityTokenServiceDescriptor securityTokenServiceDescriptor = CreateSecurityTokenServiceDescriptorInstance(); 1500 ReadWebServiceDescriptorAttributes(reader, securityTokenServiceDescriptor); 1501 ReadCustomAttributes<SecurityTokenServiceDescriptor>(reader, securityTokenServiceDescriptor); 1502 1503 bool isEmpty = reader.IsEmptyElement; 1504 reader.ReadStartElement(); 1505 if (!isEmpty) 1506 { 1507 while (reader.IsStartElement()) 1508 { 1509 if (reader.IsStartElement(FederationMetadataConstants.Elements.SecurityTokenServiceEndpoint, FederationMetadataConstants.Namespace)) 1510 { 1511 isEmpty = reader.IsEmptyElement; 1512 reader.ReadStartElement(); 1513 if (!isEmpty && reader.IsStartElement()) 1514 { 1515 EndpointReference address = EndpointReference.ReadFrom(reader); 1516 securityTokenServiceDescriptor.SecurityTokenServiceEndpoints.Add(address); 1517 reader.ReadEndElement(); 1518 } 1519 } 1520 else if (reader.IsStartElement(FederationMetadataConstants.Elements.PassiveRequestorEndpoint, FederationMetadataConstants.Namespace)) 1521 { 1522 isEmpty = reader.IsEmptyElement; 1523 reader.ReadStartElement(); 1524 if (!isEmpty && reader.IsStartElement()) 1525 { 1526 EndpointReference address = EndpointReference.ReadFrom(reader); 1527 securityTokenServiceDescriptor.PassiveRequestorEndpoints.Add(address); 1528 reader.ReadEndElement(); 1529 } 1530 } 1531 else if (ReadWebServiceDescriptorElement(reader, securityTokenServiceDescriptor)) 1532 { 1533 // Do nothing 1534 } 1535 else if (ReadCustomElement<SecurityTokenServiceDescriptor>(reader, securityTokenServiceDescriptor)) 1536 { 1537 // Do nothing. 1538 } 1539 else 1540 { 1541 reader.Skip(); 1542 } 1543 } 1544 1545 reader.ReadEndElement(); // SecurityTokenService 1546 } 1547 1548 // Relaxed as per FIP 9935 1549 // if ( securityTokenServiceDescriptor.SecurityTokenServiceEndpoints.Count == 0 ) 1550 1551 return securityTokenServiceDescriptor; 1552 } 1553 1554 /// <summary> 1555 /// Reads spsso descriptor. 1556 /// </summary> 1557 /// <param name="reader">The xml reader.</param> 1558 /// <returns>An spsso descriptor.</returns> 1559 /// <exception cref="ArgumentNullException">The parameter reader is null.</exception> 1560 /// <exception cref="MetadataSerializationException">The XML was invalid.</exception> ReadServiceProviderSingleSignOnDescriptor(XmlReader reader)1561 protected virtual ServiceProviderSingleSignOnDescriptor ReadServiceProviderSingleSignOnDescriptor(XmlReader reader) 1562 { 1563 if (reader == null) 1564 { 1565 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1566 } 1567 1568 ServiceProviderSingleSignOnDescriptor spssoDescriptor = CreateServiceProviderSingleSignOnDescriptorInstance(); 1569 1570 string authnRequestsSignedAttribute = reader.GetAttribute(Saml2MetadataConstants.Attributes.AuthenticationRequestsSigned); 1571 if (!String.IsNullOrEmpty(authnRequestsSignedAttribute)) 1572 { 1573 try 1574 { 1575 spssoDescriptor.AuthenticationRequestsSigned = XmlConvert.ToBoolean(authnRequestsSignedAttribute.ToLowerInvariant()); 1576 } 1577 catch (FormatException) 1578 { 1579 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString( 1580 SR.ID3202, Saml2MetadataConstants.Attributes.AuthenticationRequestsSigned, authnRequestsSignedAttribute))); 1581 } 1582 } 1583 1584 string wantAssertionsSignedAttribute = reader.GetAttribute(Saml2MetadataConstants.Attributes.WantAssertionsSigned); 1585 if (!String.IsNullOrEmpty(wantAssertionsSignedAttribute)) 1586 { 1587 try 1588 { 1589 spssoDescriptor.WantAssertionsSigned = XmlConvert.ToBoolean(wantAssertionsSignedAttribute.ToLowerInvariant()); 1590 } 1591 catch (FormatException) 1592 { 1593 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString( 1594 SR.ID3202, Saml2MetadataConstants.Attributes.WantAssertionsSigned, wantAssertionsSignedAttribute))); 1595 } 1596 } 1597 1598 ReadSingleSignOnDescriptorAttributes(reader, spssoDescriptor); 1599 ReadCustomAttributes<ServiceProviderSingleSignOnDescriptor>(reader, spssoDescriptor); 1600 1601 bool isEmpty = reader.IsEmptyElement; 1602 reader.ReadStartElement(); 1603 if (!isEmpty) 1604 { 1605 while (reader.IsStartElement()) 1606 { 1607 if (reader.IsStartElement(Saml2MetadataConstants.Elements.AssertionConsumerService, Saml2MetadataConstants.Namespace)) 1608 { 1609 IndexedProtocolEndpoint endpoint = ReadIndexedProtocolEndpoint(reader); 1610 spssoDescriptor.AssertionConsumerServices.Add(endpoint.Index, endpoint); 1611 } 1612 else if (ReadSingleSignOnDescriptorElement(reader, spssoDescriptor)) 1613 { 1614 // Do nothing 1615 } 1616 else if (ReadCustomElement<ServiceProviderSingleSignOnDescriptor>(reader, spssoDescriptor)) 1617 { 1618 // Do nothing. 1619 } 1620 else 1621 { 1622 reader.Skip(); 1623 } 1624 } 1625 1626 reader.ReadEndElement(); // SPSSODescriptor 1627 } 1628 1629 // Relaxed as per FIP 9935 1630 // if ( spssoDescriptor.AssertionConsumerService.Count == 0 ) 1631 1632 return spssoDescriptor; 1633 } 1634 1635 /// <summary> 1636 /// Reads sso descriptor attributes. 1637 /// </summary> 1638 /// <param name="reader">The xml reader.</param> 1639 /// <param name="roleDescriptor">The sso role descriptor.</param> ReadSingleSignOnDescriptorAttributes(XmlReader reader, SingleSignOnDescriptor roleDescriptor)1640 protected virtual void ReadSingleSignOnDescriptorAttributes(XmlReader reader, SingleSignOnDescriptor roleDescriptor) 1641 { 1642 ReadRoleDescriptorAttributes(reader, roleDescriptor); 1643 ReadCustomAttributes<SingleSignOnDescriptor>(reader, roleDescriptor); 1644 } 1645 1646 /// <summary> 1647 /// Reads sso descriptor element. 1648 /// </summary> 1649 /// <param name="reader">The xml reader.</param> 1650 /// <param name="singleSignOnDescriptor">The sso descriptor.</param> 1651 /// <returns>True if read.</returns> ReadSingleSignOnDescriptorElement(XmlReader reader, SingleSignOnDescriptor singleSignOnDescriptor)1652 protected virtual bool ReadSingleSignOnDescriptorElement(XmlReader reader, SingleSignOnDescriptor singleSignOnDescriptor) 1653 { 1654 if (reader == null) 1655 { 1656 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1657 } 1658 if (singleSignOnDescriptor == null) 1659 { 1660 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ssoDescriptor"); 1661 } 1662 1663 if (ReadRoleDescriptorElement(reader, singleSignOnDescriptor)) 1664 { 1665 return true; 1666 } 1667 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.ArtifactResolutionService, Saml2MetadataConstants.Namespace)) 1668 { 1669 IndexedProtocolEndpoint endpoint = ReadIndexedProtocolEndpoint(reader); 1670 1671 // Relaxed check for endpoint.ResponseLocation != null as per FIP 9935 1672 singleSignOnDescriptor.ArtifactResolutionServices.Add(endpoint.Index, endpoint); 1673 return true; 1674 } 1675 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.SingleLogoutService, Saml2MetadataConstants.Namespace)) 1676 { 1677 singleSignOnDescriptor.SingleLogoutServices.Add(ReadProtocolEndpoint(reader)); 1678 return true; 1679 } 1680 else if (reader.IsStartElement(Saml2MetadataConstants.Elements.NameIDFormat, Saml2MetadataConstants.Namespace)) 1681 { 1682 string nameId = reader.ReadElementContentAsString(Saml2MetadataConstants.Elements.NameIDFormat, Saml2MetadataConstants.Namespace); 1683 if (!UriUtil.CanCreateValidUri(nameId, UriKind.Absolute)) 1684 { 1685 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID0014, Saml2MetadataConstants.Elements.NameIDFormat))); 1686 } 1687 singleSignOnDescriptor.NameIdentifierFormats.Add(new Uri(nameId)); 1688 return true; 1689 } 1690 else 1691 { 1692 return ReadCustomElement<SingleSignOnDescriptor>(reader, singleSignOnDescriptor); 1693 } 1694 } 1695 1696 /// <summary> 1697 /// Reads web service descriptor attributes. 1698 /// </summary> 1699 /// <param name="reader">The xml reader.</param> 1700 /// <param name="roleDescriptor">The web service descriptor.</param> 1701 /// <exception cref="ArgumentNullException">The parameter reader/roleDescriptor is null.</exception> ReadWebServiceDescriptorAttributes(XmlReader reader, WebServiceDescriptor roleDescriptor)1702 protected virtual void ReadWebServiceDescriptorAttributes(XmlReader reader, WebServiceDescriptor roleDescriptor) 1703 { 1704 if (reader == null) 1705 { 1706 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1707 } 1708 if (roleDescriptor == null) 1709 { 1710 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor"); 1711 } 1712 1713 ReadRoleDescriptorAttributes(reader, roleDescriptor); 1714 string displayName = reader.GetAttribute(Saml2MetadataConstants.Attributes.ServiceDisplayName, null); 1715 if (!String.IsNullOrEmpty(displayName)) 1716 { 1717 roleDescriptor.ServiceDisplayName = displayName; 1718 } 1719 string description = reader.GetAttribute(Saml2MetadataConstants.Attributes.ServiceDescription, null); 1720 if (!String.IsNullOrEmpty(description)) 1721 { 1722 roleDescriptor.ServiceDescription = description; 1723 } 1724 ReadCustomAttributes<WebServiceDescriptor>(reader, roleDescriptor); 1725 1726 // All optional no validations 1727 } 1728 1729 /// <summary> 1730 /// Reads web service descriptor element. 1731 /// </summary> 1732 /// <param name="reader">The xml reader.</param> 1733 /// <param name="roleDescriptor">The web service descriptor.</param> 1734 /// <returns>True if read.</returns> 1735 /// <exception cref="ArgumentNullException">The parameter reader/roleDescriptor/roleDescriptor.TargetScopes/roleDescriptor.TargetScopes/roleDescriptor.TokenTypesOffered 1736 /// is null.</exception> ReadWebServiceDescriptorElement(XmlReader reader, WebServiceDescriptor roleDescriptor)1737 public virtual bool ReadWebServiceDescriptorElement(XmlReader reader, WebServiceDescriptor roleDescriptor) 1738 { 1739 if (reader == null) 1740 { 1741 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 1742 } 1743 if (roleDescriptor == null) 1744 { 1745 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor"); 1746 } 1747 if (roleDescriptor.TargetScopes == null) 1748 { 1749 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.TargetScopes"); 1750 } 1751 if (roleDescriptor.ClaimTypesOffered == null) 1752 { 1753 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.TargetScopes"); 1754 } 1755 if (roleDescriptor.TokenTypesOffered == null) 1756 { 1757 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.TokenTypesOffered"); 1758 } 1759 1760 if (ReadRoleDescriptorElement(reader, roleDescriptor)) 1761 { 1762 return true; 1763 } 1764 else if (reader.IsStartElement(FederationMetadataConstants.Elements.TargetScopes, FederationMetadataConstants.Namespace)) 1765 { 1766 bool isEmpty = reader.IsEmptyElement; 1767 reader.ReadStartElement(); 1768 if (!isEmpty) 1769 { 1770 while (reader.IsStartElement()) 1771 { 1772 roleDescriptor.TargetScopes.Add(EndpointReference.ReadFrom(reader)); 1773 } 1774 1775 reader.ReadEndElement(); 1776 } 1777 1778 return true; 1779 } 1780 else if (reader.IsStartElement(FederationMetadataConstants.Elements.ClaimTypesOffered, FederationMetadataConstants.Namespace)) 1781 { 1782 bool isEmpty = reader.IsEmptyElement; 1783 reader.ReadStartElement(); 1784 if (!isEmpty) 1785 { 1786 while (reader.IsStartElement()) 1787 { 1788 if (reader.IsStartElement(WSAuthorizationConstants.Elements.ClaimType, WSAuthorizationConstants.Namespace)) 1789 { 1790 roleDescriptor.ClaimTypesOffered.Add(ReadDisplayClaim(reader)); 1791 } 1792 else 1793 { 1794 // Move on 1795 reader.Skip(); 1796 } 1797 } 1798 1799 reader.ReadEndElement(); 1800 } 1801 1802 return true; 1803 } 1804 else if (reader.IsStartElement(FederationMetadataConstants.Elements.ClaimTypesRequested, FederationMetadataConstants.Namespace)) 1805 { 1806 bool isEmpty = reader.IsEmptyElement; 1807 reader.ReadStartElement(); 1808 if (!isEmpty) 1809 { 1810 while (reader.IsStartElement()) 1811 { 1812 if (reader.IsStartElement(WSAuthorizationConstants.Elements.ClaimType, WSAuthorizationConstants.Namespace)) 1813 { 1814 roleDescriptor.ClaimTypesRequested.Add(ReadDisplayClaim(reader)); 1815 } 1816 else 1817 { 1818 // Move on 1819 reader.Skip(); 1820 } 1821 } 1822 1823 reader.ReadEndElement(); 1824 } 1825 1826 return true; 1827 } 1828 else if (reader.IsStartElement(FederationMetadataConstants.Elements.TokenTypesOffered, FederationMetadataConstants.Namespace)) 1829 { 1830 bool isEmpty = reader.IsEmptyElement; 1831 reader.ReadStartElement(FederationMetadataConstants.Elements.TokenTypesOffered, FederationMetadataConstants.Namespace); 1832 1833 if (!isEmpty) 1834 { 1835 while (reader.IsStartElement()) 1836 { 1837 if (reader.IsStartElement(WSFederationMetadataConstants.Elements.TokenType, WSFederationMetadataConstants.Namespace)) 1838 { 1839 string tokenType = reader.GetAttribute(WSFederationMetadataConstants.Attributes.Uri, null); 1840 Uri tokenTypeUri; 1841 if (!UriUtil.TryCreateValidUri(tokenType, UriKind.Absolute, out tokenTypeUri)) 1842 { 1843 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3202, WSFederationMetadataConstants.Elements.TokenType, tokenType))); 1844 } 1845 1846 roleDescriptor.TokenTypesOffered.Add(tokenTypeUri); 1847 1848 isEmpty = reader.IsEmptyElement; 1849 reader.ReadStartElement(); // TokenType 1850 if (!isEmpty) 1851 { 1852 reader.ReadEndElement(); // TokenType 1853 } 1854 } 1855 else 1856 { 1857 reader.Skip(); 1858 } 1859 } 1860 1861 reader.ReadEndElement(); // TokenTypeOffered 1862 } 1863 return true; 1864 } 1865 else 1866 { 1867 return ReadCustomElement<WebServiceDescriptor>(reader, roleDescriptor); 1868 } 1869 1870 // All optional. No Validations needed 1871 } 1872 1873 /// <summary> 1874 /// Gets the SecurityTokenSerializer that this instance is using to serializer 1875 /// SecurityTokens. 1876 /// </summary> 1877 public SecurityTokenSerializer SecurityTokenSerializer 1878 { 1879 get 1880 { 1881 return _tokenSerializer; 1882 } 1883 } 1884 1885 /// <summary> 1886 /// Writes an application service descriptor. 1887 /// </summary> 1888 /// <param name="writer">The xml writer.</param> 1889 /// <param name="appService">The application service descriptor.</param> 1890 /// <exception cref="ArgumentNullException">The parameter writer/appService/appService.Endpoint/aappService.PassiveRequestorEndpoints is null.</exception> WriteApplicationServiceDescriptor(XmlWriter writer, ApplicationServiceDescriptor appService)1891 protected virtual void WriteApplicationServiceDescriptor(XmlWriter writer, ApplicationServiceDescriptor appService) 1892 { 1893 if (writer == null) 1894 { 1895 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 1896 } 1897 1898 if (appService == null) 1899 { 1900 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("appService"); 1901 } 1902 1903 if (appService.Endpoints == null) 1904 { 1905 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("appService.Endpoints"); 1906 } 1907 1908 if (appService.PassiveRequestorEndpoints == null) 1909 { 1910 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("appService.PassiveRequestorEndpoints"); 1911 } 1912 1913 writer.WriteStartElement(Saml2MetadataConstants.Elements.RoleDescriptor, Saml2MetadataConstants.Namespace); 1914 writer.WriteAttributeString("xsi", "type", XmlSchema.InstanceNamespace, FederationMetadataConstants.Prefix + ":" + FederationMetadataConstants.Elements.ApplicationServiceType); 1915 1916 writer.WriteAttributeString("xmlns", FederationMetadataConstants.Prefix, null, FederationMetadataConstants.Namespace); 1917 1918 WriteWebServiceDescriptorAttributes(writer, appService); 1919 WriteCustomAttributes<ApplicationServiceDescriptor>(writer, appService); 1920 1921 WriteWebServiceDescriptorElements(writer, appService); 1922 1923 // Optional ApplicationServiceEndpoints 1924 foreach (EndpointReference epr in appService.Endpoints) 1925 { 1926 writer.WriteStartElement(FederationMetadataConstants.Elements.ApplicationServiceEndpoint, FederationMetadataConstants.Namespace); 1927 epr.WriteTo(writer); 1928 writer.WriteEndElement(); 1929 } 1930 1931 // Optional PassiveRequestorEndpoints 1932 foreach (EndpointReference epr in appService.PassiveRequestorEndpoints) 1933 { 1934 writer.WriteStartElement(FederationMetadataConstants.Elements.PassiveRequestorEndpoint, FederationMetadataConstants.Namespace); 1935 epr.WriteTo(writer); 1936 writer.WriteEndElement(); 1937 } 1938 1939 WriteCustomElements<ApplicationServiceDescriptor>(writer, appService); 1940 1941 writer.WriteEndElement(); 1942 } 1943 1944 /// <summary> 1945 /// Writes a contact person. 1946 /// </summary> 1947 /// <param name="writer">The xml writer.</param> 1948 /// <param name="contactPerson">The contact person.</param> 1949 /// <exception cref="ArgumentNullException">The parameter writer/contactPerson/contactPerson.EmaillAddresses/contactPerson.TelephoneNumbers is null.</exception> WriteContactPerson(XmlWriter writer, ContactPerson contactPerson)1950 protected virtual void WriteContactPerson(XmlWriter writer, ContactPerson contactPerson) 1951 { 1952 if (writer == null) 1953 { 1954 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 1955 } 1956 1957 if (contactPerson == null) 1958 { 1959 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contactPerson"); 1960 } 1961 1962 if (contactPerson.EmailAddresses == null) 1963 { 1964 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contactPerson.EmailAddresses"); 1965 } 1966 1967 if (contactPerson.TelephoneNumbers == null) 1968 { 1969 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contactPerson.TelephoneNumbers"); 1970 } 1971 1972 writer.WriteStartElement(Saml2MetadataConstants.Elements.ContactPerson, Saml2MetadataConstants.Namespace); 1973 if (contactPerson.Type == ContactType.Unspecified) 1974 { 1975 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.ContactType))); 1976 } 1977 1978 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ContactType, null, contactPerson.Type.ToString().ToLowerInvariant()); 1979 1980 WriteCustomAttributes<ContactPerson>(writer, contactPerson); 1981 1982 if (!String.IsNullOrEmpty(contactPerson.Company)) 1983 { 1984 writer.WriteElementString(Saml2MetadataConstants.Elements.Company, Saml2MetadataConstants.Namespace, contactPerson.Company); 1985 } 1986 1987 if (!String.IsNullOrEmpty(contactPerson.GivenName)) 1988 { 1989 writer.WriteElementString(Saml2MetadataConstants.Elements.GivenName, Saml2MetadataConstants.Namespace, contactPerson.GivenName); 1990 } 1991 1992 if (!String.IsNullOrEmpty(contactPerson.Surname)) 1993 { 1994 writer.WriteElementString(Saml2MetadataConstants.Elements.Surname, Saml2MetadataConstants.Namespace, contactPerson.Surname); 1995 } 1996 1997 foreach (string email in contactPerson.EmailAddresses) 1998 { 1999 writer.WriteElementString(Saml2MetadataConstants.Elements.EmailAddress, Saml2MetadataConstants.Namespace, email); 2000 } 2001 2002 foreach (string phone in contactPerson.TelephoneNumbers) 2003 { 2004 writer.WriteElementString(Saml2MetadataConstants.Elements.TelephoneNumber, Saml2MetadataConstants.Namespace, phone); 2005 } 2006 2007 WriteCustomElements<ContactPerson>(writer, contactPerson); 2008 2009 writer.WriteEndElement(); 2010 } 2011 2012 /// <summary> 2013 /// Extensible point to write custom attributes. 2014 /// </summary> 2015 /// <typeparam name="T">The type of the element whose attribute is being written</typeparam> 2016 /// <param name="writer">The xml writer.</param> 2017 /// <param name="source">The source element of type T.</param> WriteCustomAttributes(XmlWriter writer, T source)2018 protected virtual void WriteCustomAttributes<T>(XmlWriter writer, T source) 2019 { 2020 // Extensibility point only. Do Nothing. 2021 } 2022 2023 /// <summary> 2024 /// Extensible point to write custom elements. 2025 /// </summary> 2026 /// <typeparam name="T">The type of element being written.</typeparam> 2027 /// <param name="writer">The xml writer.</param> 2028 /// <param name="source">The source element of type T.</param> WriteCustomElements(XmlWriter writer, T source)2029 protected virtual void WriteCustomElements<T>(XmlWriter writer, T source) 2030 { 2031 // Extensibility point only. Do Nothing. 2032 } 2033 2034 /// <summary> 2035 /// Writes an endpoint. 2036 /// </summary> 2037 /// <param name="writer">The xml writer.</param> 2038 /// <param name="endpoint">The endpoint.</param> 2039 /// <param name="element">The xml qualified name element.</param> 2040 /// <exception cref="ArgumentNullException">The parameter writer/endpoint/element is null.</exception> WriteProtocolEndpoint(XmlWriter writer, ProtocolEndpoint endpoint, XmlQualifiedName element)2041 protected virtual void WriteProtocolEndpoint(XmlWriter writer, ProtocolEndpoint endpoint, XmlQualifiedName element) 2042 { 2043 if (writer == null) 2044 { 2045 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2046 } 2047 2048 if (endpoint == null) 2049 { 2050 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint"); 2051 } 2052 2053 if (element == null) 2054 { 2055 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element"); 2056 } 2057 2058 writer.WriteStartElement(element.Name, element.Namespace); 2059 if (endpoint.Binding == null) 2060 { 2061 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.Binding))); 2062 } 2063 2064 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Binding, null, (endpoint.Binding.IsAbsoluteUri ? endpoint.Binding.AbsoluteUri : endpoint.Binding.ToString())); 2065 2066 if (endpoint.Location == null) 2067 { 2068 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.Location))); 2069 } 2070 2071 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Location, null, (endpoint.Location.IsAbsoluteUri ? endpoint.Location.AbsoluteUri : endpoint.Location.ToString())); 2072 2073 if (endpoint.ResponseLocation != null) 2074 { 2075 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ResponseLocation, null, (endpoint.ResponseLocation.IsAbsoluteUri ? endpoint.ResponseLocation.AbsoluteUri : endpoint.ResponseLocation.ToString())); 2076 } 2077 2078 WriteCustomAttributes<ProtocolEndpoint>(writer, endpoint); 2079 2080 WriteCustomElements<ProtocolEndpoint>(writer, endpoint); 2081 writer.WriteEndElement(); 2082 } 2083 2084 /// <summary> 2085 /// Writes entities descriptor. 2086 /// </summary> 2087 /// <param name="writer">The <see cref="XmlWriter"/> to use.</param> 2088 /// <param name="claim">The <see cref="DisplayClaim"/> to write.</param> WriteDisplayClaim(XmlWriter writer, DisplayClaim claim)2089 protected virtual void WriteDisplayClaim(XmlWriter writer, DisplayClaim claim) 2090 { 2091 // This is not extensible since it is defined in a different spec. 2092 writer.WriteStartElement(WSAuthorizationConstants.Prefix, WSAuthorizationConstants.Elements.ClaimType, WSAuthorizationConstants.Namespace); 2093 2094 // ClaimType is mandatory 2095 if (String.IsNullOrEmpty(claim.ClaimType)) 2096 { 2097 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, WSAuthorizationConstants.Elements.ClaimType))); 2098 } 2099 2100 if (!UriUtil.CanCreateValidUri(claim.ClaimType, UriKind.Absolute)) 2101 { 2102 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID0014, claim.ClaimType))); 2103 } 2104 2105 writer.WriteAttributeString(WSFederationMetadataConstants.Attributes.Uri, claim.ClaimType); 2106 2107 if (claim.WriteOptionalAttribute) 2108 { 2109 writer.WriteAttributeString(WSFederationMetadataConstants.Attributes.Optional, XmlConvert.ToString(claim.Optional)); 2110 } 2111 2112 if (!String.IsNullOrEmpty(claim.DisplayTag)) 2113 { 2114 writer.WriteElementString(WSAuthorizationConstants.Prefix, WSAuthorizationConstants.Elements.DisplayName, WSAuthorizationConstants.Namespace, claim.DisplayTag); 2115 } 2116 2117 if (!String.IsNullOrEmpty(claim.Description)) 2118 { 2119 writer.WriteElementString(WSAuthorizationConstants.Prefix, WSAuthorizationConstants.Elements.Description, WSAuthorizationConstants.Namespace, claim.Description); 2120 } 2121 2122 writer.WriteEndElement(); // ClaimType 2123 } 2124 2125 /// <summary> 2126 /// Writes entities descriptor. 2127 /// </summary> 2128 /// <param name="inputWriter">The <see cref="XmlWriter"/> to use.</param> 2129 /// <param name="entitiesDescriptor">The entities descriptor.</param> 2130 /// <exception cref="ArgumentNullException">The parameter inputWriter/entitiesDescriptor/entitiesDescriptor.ChildEntities/entitiesDescriptor.ChildEntityGroups 2131 /// is null.</exception> WriteEntitiesDescriptor(XmlWriter inputWriter, EntitiesDescriptor entitiesDescriptor)2132 protected virtual void WriteEntitiesDescriptor(XmlWriter inputWriter, EntitiesDescriptor entitiesDescriptor) 2133 { 2134 if (inputWriter == null) 2135 { 2136 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("inputWriter"); 2137 } 2138 2139 if (entitiesDescriptor == null) 2140 { 2141 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("entitiesDescriptor"); 2142 } 2143 2144 if (entitiesDescriptor.ChildEntities == null) 2145 { 2146 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("entitiesDescriptor.ChildEntities"); 2147 } 2148 2149 if (entitiesDescriptor.ChildEntityGroups == null) 2150 { 2151 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("entitiesDescriptor.ChildEntityGroups"); 2152 } 2153 2154 string entityReference = "_" + Guid.NewGuid().ToString(); 2155 XmlWriter writer = inputWriter; 2156 EnvelopedSignatureWriter signedWriter = null; 2157 if (entitiesDescriptor.SigningCredentials != null) 2158 { 2159 signedWriter = new EnvelopedSignatureWriter(inputWriter, entitiesDescriptor.SigningCredentials, entityReference, SecurityTokenSerializer); 2160 writer = signedWriter; 2161 } 2162 2163 writer.WriteStartElement(Saml2MetadataConstants.Elements.EntitiesDescriptor, Saml2MetadataConstants.Namespace); 2164 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Id, null, entityReference); 2165 2166 if (entitiesDescriptor.ChildEntities.Count == 0 && entitiesDescriptor.ChildEntityGroups.Count == 0) 2167 { 2168 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.EntitiesDescriptor))); 2169 } 2170 2171 // Ensure FederationID in all children are valid. 2172 foreach (EntityDescriptor entity in entitiesDescriptor.ChildEntities) 2173 { 2174 if (!String.IsNullOrEmpty(entity.FederationId)) 2175 { 2176 if (!StringComparer.Ordinal.Equals(entity.FederationId, entitiesDescriptor.Name)) 2177 { 2178 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, WSFederationMetadataConstants.Attributes.FederationId))); 2179 } 2180 } 2181 } 2182 2183 if (!String.IsNullOrEmpty(entitiesDescriptor.Name)) 2184 { 2185 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.EntityGroupName, null, entitiesDescriptor.Name); 2186 } 2187 2188 WriteCustomAttributes<EntitiesDescriptor>(writer, entitiesDescriptor); 2189 2190 // WriteSamlMetadataBaseElements? 2191 2192 if (null != signedWriter) 2193 { 2194 // Write the signature at the top of the sequence 2195 signedWriter.WriteSignature(); 2196 } 2197 2198 foreach (EntityDescriptor entity in entitiesDescriptor.ChildEntities) 2199 { 2200 WriteEntityDescriptor(writer, entity); 2201 } 2202 2203 foreach (EntitiesDescriptor entityGroup in entitiesDescriptor.ChildEntityGroups) 2204 { 2205 WriteEntitiesDescriptor(writer, entityGroup); 2206 } 2207 2208 WriteCustomElements<EntitiesDescriptor>(writer, entitiesDescriptor); 2209 2210 writer.WriteEndElement(); // EntitiesDescriptor 2211 } 2212 2213 /// <summary> 2214 /// Writes an entity descriptor. 2215 /// </summary> 2216 /// <param name="inputWriter">The xml writer.</param> 2217 /// <param name="entityDescriptor">The entity descriptor.</param> 2218 /// <exception cref="ArgumentNullException">The parameter inputWriter/entityDescriptor/entityDescriptor.Contacts/entityDescriptor.RoleDescriptors is null.</exception> WriteEntityDescriptor(XmlWriter inputWriter, EntityDescriptor entityDescriptor)2219 protected virtual void WriteEntityDescriptor(XmlWriter inputWriter, EntityDescriptor entityDescriptor) 2220 { 2221 if (inputWriter == null) 2222 { 2223 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("inputWriter"); 2224 } 2225 2226 if (entityDescriptor == null) 2227 { 2228 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("entityDescriptor"); 2229 } 2230 2231 if (entityDescriptor.Contacts == null) 2232 { 2233 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("entityDescriptor.Contacts"); 2234 } 2235 2236 if (entityDescriptor.RoleDescriptors == null) 2237 { 2238 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("entityDescriptor.RoleDescriptors"); 2239 } 2240 2241 string entityReference = "_" + Guid.NewGuid().ToString(); 2242 XmlWriter writer = inputWriter; 2243 EnvelopedSignatureWriter signedWriter = null; 2244 if (entityDescriptor.SigningCredentials != null) 2245 { 2246 signedWriter = new EnvelopedSignatureWriter(inputWriter, entityDescriptor.SigningCredentials, entityReference, SecurityTokenSerializer); 2247 writer = signedWriter; 2248 } 2249 2250 writer.WriteStartElement(Saml2MetadataConstants.Elements.EntityDescriptor, Saml2MetadataConstants.Namespace); 2251 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Id, null, entityReference); 2252 2253 if (entityDescriptor.EntityId == null || entityDescriptor.EntityId.Id == null) 2254 { 2255 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.EntityId))); 2256 } 2257 2258 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.EntityId, null, entityDescriptor.EntityId.Id); 2259 2260 if (!String.IsNullOrEmpty(entityDescriptor.FederationId)) 2261 { 2262 writer.WriteAttributeString(WSFederationMetadataConstants.Attributes.FederationId, WSFederationMetadataConstants.Namespace, entityDescriptor.FederationId); 2263 } 2264 2265 WriteCustomAttributes<EntityDescriptor>(writer, entityDescriptor); 2266 2267 if (null != signedWriter) 2268 { 2269 // Write the signature at the top of the sequence 2270 signedWriter.WriteSignature(); 2271 } 2272 2273 if (entityDescriptor.RoleDescriptors.Count == 0) 2274 { 2275 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.RoleDescriptor))); 2276 } 2277 2278 foreach (RoleDescriptor roleDescriptor in entityDescriptor.RoleDescriptors) 2279 { 2280 ServiceProviderSingleSignOnDescriptor spDesc = roleDescriptor as ServiceProviderSingleSignOnDescriptor; 2281 if (spDesc != null) 2282 { 2283 WriteServiceProviderSingleSignOnDescriptor(writer, spDesc); 2284 } 2285 2286 IdentityProviderSingleSignOnDescriptor idpDesc = roleDescriptor as IdentityProviderSingleSignOnDescriptor; 2287 if (idpDesc != null) 2288 { 2289 WriteIdentityProviderSingleSignOnDescriptor(writer, idpDesc); 2290 } 2291 2292 ApplicationServiceDescriptor appService = roleDescriptor as ApplicationServiceDescriptor; 2293 if (appService != null) 2294 { 2295 WriteApplicationServiceDescriptor(writer, appService); 2296 } 2297 2298 SecurityTokenServiceDescriptor stsService = roleDescriptor as SecurityTokenServiceDescriptor; 2299 if (stsService != null) 2300 { 2301 WriteSecurityTokenServiceDescriptor(writer, stsService); 2302 } 2303 } 2304 2305 if (entityDescriptor.Organization != null) 2306 { 2307 WriteOrganization(writer, entityDescriptor.Organization); 2308 } 2309 2310 foreach (ContactPerson person in entityDescriptor.Contacts) 2311 { 2312 WriteContactPerson(writer, person); 2313 } 2314 2315 WriteCustomElements<EntityDescriptor>(writer, entityDescriptor); 2316 2317 writer.WriteEndElement(); // EntityDescriptor 2318 } 2319 2320 /// <summary> 2321 /// Writes an idpsso descriptor. 2322 /// </summary> 2323 /// <param name="writer">The xml writer.</param> 2324 /// <param name="identityProviderSingleSignOnDescriptor">The idpsso descriptor.</param> 2325 /// <exception cref="ArgumentNullException">The parameter writer/idpssoDescriptor/idpssoDescriptor.SupportedAttributes/idpssoDescriptor.SingleSignOnServices 2326 /// is null.</exception> WriteIdentityProviderSingleSignOnDescriptor(XmlWriter writer, IdentityProviderSingleSignOnDescriptor identityProviderSingleSignOnDescriptor)2327 protected virtual void WriteIdentityProviderSingleSignOnDescriptor(XmlWriter writer, IdentityProviderSingleSignOnDescriptor identityProviderSingleSignOnDescriptor) 2328 { 2329 if (writer == null) 2330 { 2331 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2332 } 2333 2334 if (identityProviderSingleSignOnDescriptor == null) 2335 { 2336 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("idpssoDescriptor"); 2337 } 2338 2339 if (identityProviderSingleSignOnDescriptor.SupportedAttributes == null) 2340 { 2341 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("idpssoDescriptor.SupportedAttributes"); 2342 } 2343 2344 if (identityProviderSingleSignOnDescriptor.SingleSignOnServices == null) 2345 { 2346 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("idpssoDescriptor.SingleSignOnServices"); 2347 } 2348 2349 writer.WriteStartElement(Saml2MetadataConstants.Elements.IdpssoDescriptor, Saml2MetadataConstants.Namespace); 2350 if (identityProviderSingleSignOnDescriptor.WantAuthenticationRequestsSigned) 2351 { 2352 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.WantAuthenticationRequestsSigned, null, 2353 XmlConvert.ToString(identityProviderSingleSignOnDescriptor.WantAuthenticationRequestsSigned)); 2354 } 2355 2356 WriteSingleSignOnDescriptorAttributes(writer, identityProviderSingleSignOnDescriptor); 2357 WriteCustomAttributes<IdentityProviderSingleSignOnDescriptor>(writer, identityProviderSingleSignOnDescriptor); 2358 2359 WriteSingleSignOnDescriptorElements(writer, identityProviderSingleSignOnDescriptor); 2360 2361 // Mandatory SingleSignonServiceEndpoint 2362 if (identityProviderSingleSignOnDescriptor.SingleSignOnServices.Count == 0) 2363 { 2364 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.SingleSignOnService))); 2365 } 2366 2367 foreach (ProtocolEndpoint endpoint in identityProviderSingleSignOnDescriptor.SingleSignOnServices) 2368 { 2369 if (endpoint.ResponseLocation != null) 2370 { 2371 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3249, Saml2MetadataConstants.Attributes.ResponseLocation))); 2372 } 2373 2374 XmlQualifiedName element = new XmlQualifiedName(Saml2MetadataConstants.Elements.SingleSignOnService, Saml2MetadataConstants.Namespace); 2375 WriteProtocolEndpoint(writer, endpoint, element); 2376 } 2377 2378 // Optional SupportedAttributes 2379 foreach (Saml2Attribute attribute in identityProviderSingleSignOnDescriptor.SupportedAttributes) 2380 { 2381 WriteAttribute(writer, attribute); 2382 } 2383 2384 WriteCustomElements<IdentityProviderSingleSignOnDescriptor>(writer, identityProviderSingleSignOnDescriptor); 2385 2386 writer.WriteEndElement(); 2387 } 2388 2389 /// <summary> 2390 /// Writes an indexed endpoint. 2391 /// </summary> 2392 /// <param name="writer">The xml writer.</param> 2393 /// <param name="indexedEP">The indexed endpoint.</param> 2394 /// <param name="element">The xml qualified element.</param> 2395 /// <exception cref="ArgumentNullException">The parameter writer/indexedEP/element is null.</exception> WriteIndexedProtocolEndpoint(XmlWriter writer, IndexedProtocolEndpoint indexedEP, XmlQualifiedName element)2396 protected virtual void WriteIndexedProtocolEndpoint(XmlWriter writer, IndexedProtocolEndpoint indexedEP, XmlQualifiedName element) 2397 { 2398 if (writer == null) 2399 { 2400 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2401 } 2402 2403 if (indexedEP == null) 2404 { 2405 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("indexedEP"); 2406 } 2407 2408 if (element == null) 2409 { 2410 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element"); 2411 } 2412 2413 writer.WriteStartElement(element.Name, element.Namespace); 2414 if (indexedEP.Binding == null) 2415 { 2416 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.Binding))); 2417 } 2418 2419 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Binding, null, (indexedEP.Binding.IsAbsoluteUri ? indexedEP.Binding.AbsoluteUri : indexedEP.Binding.ToString())); 2420 2421 if (indexedEP.Location == null) 2422 { 2423 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.Location))); 2424 } 2425 2426 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Location, null, (indexedEP.Location.IsAbsoluteUri ? indexedEP.Location.AbsoluteUri : indexedEP.Location.ToString())); 2427 2428 if (indexedEP.Index < 0) 2429 { 2430 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.EndpointIndex))); 2431 } 2432 2433 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.EndpointIndex, null, indexedEP.Index.ToString(CultureInfo.InvariantCulture)); 2434 2435 if (indexedEP.ResponseLocation != null) 2436 { 2437 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ResponseLocation, null, (indexedEP.ResponseLocation.IsAbsoluteUri ? indexedEP.ResponseLocation.AbsoluteUri : indexedEP.ResponseLocation.ToString())); 2438 } 2439 2440 if (indexedEP.IsDefault.HasValue) 2441 { 2442 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.EndpointIsDefault, null, XmlConvert.ToString(indexedEP.IsDefault.Value)); 2443 } 2444 2445 WriteCustomAttributes<IndexedProtocolEndpoint>(writer, indexedEP); 2446 WriteCustomElements<IndexedProtocolEndpoint>(writer, indexedEP); 2447 writer.WriteEndElement(); 2448 } 2449 2450 /// <summary> 2451 /// Writes a key descriptor. 2452 /// </summary> 2453 /// <param name="writer">The xml writer.</param> 2454 /// <param name="keyDescriptor">The key descriptor.</param> 2455 /// <exception cref="ArgumentNullException">The parameter writer/keyDescriptor is null.</exception> WriteKeyDescriptor(XmlWriter writer, KeyDescriptor keyDescriptor)2456 protected virtual void WriteKeyDescriptor(XmlWriter writer, KeyDescriptor keyDescriptor) 2457 { 2458 if (writer == null) 2459 { 2460 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2461 } 2462 2463 if (keyDescriptor == null) 2464 { 2465 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyDescriptor"); 2466 } 2467 2468 writer.WriteStartElement(Saml2MetadataConstants.Elements.KeyDescriptor, Saml2MetadataConstants.Namespace); 2469 if (keyDescriptor.Use == KeyType.Encryption || keyDescriptor.Use == KeyType.Signing) 2470 { 2471 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Use, null, keyDescriptor.Use.ToString().ToLowerInvariant()); 2472 } 2473 2474 WriteCustomAttributes<KeyDescriptor>(writer, keyDescriptor); 2475 2476 if (keyDescriptor.KeyInfo == null) 2477 { 2478 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, XmlSignatureConstants.Elements.KeyInfo))); 2479 } 2480 2481 SecurityTokenSerializer.WriteKeyIdentifier(writer, keyDescriptor.KeyInfo); 2482 2483 // Write the encryption method element. 2484 if (keyDescriptor.EncryptionMethods != null && keyDescriptor.EncryptionMethods.Count > 0) 2485 { 2486 foreach (EncryptionMethod encryptionMethod in keyDescriptor.EncryptionMethods) 2487 { 2488 if (encryptionMethod.Algorithm == null) 2489 { 2490 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.Algorithm))); 2491 } 2492 2493 if (!encryptionMethod.Algorithm.IsAbsoluteUri) 2494 { 2495 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID0014, Saml2MetadataConstants.Attributes.Algorithm))); 2496 } 2497 2498 writer.WriteStartElement(Saml2MetadataConstants.Elements.EncryptionMethod, Saml2MetadataConstants.Namespace); 2499 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.Algorithm, null, encryptionMethod.Algorithm.AbsoluteUri); 2500 writer.WriteEndElement(); 2501 } 2502 } 2503 2504 WriteCustomElements<KeyDescriptor>(writer, keyDescriptor); 2505 writer.WriteEndElement(); 2506 } 2507 2508 /// <summary> 2509 /// Writes a localized name. 2510 /// </summary> 2511 /// <param name="writer">The xml writer.</param> 2512 /// <param name="name">The localized name.</param> 2513 /// <param name="element">The xml qualified name.</param> 2514 /// <exception cref="ArgumentNullException">The parameter writer/name/element/name.Name is null.</exception> WriteLocalizedName(XmlWriter writer, LocalizedName name, XmlQualifiedName element)2515 protected virtual void WriteLocalizedName(XmlWriter writer, LocalizedName name, XmlQualifiedName element) 2516 { 2517 if (writer == null) 2518 { 2519 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2520 } 2521 2522 if (name == null) 2523 { 2524 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name"); 2525 } 2526 2527 if (element == null) 2528 { 2529 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element"); 2530 } 2531 2532 if (name.Name == null) 2533 { 2534 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name.Name"); 2535 } 2536 2537 writer.WriteStartElement(element.Name, element.Namespace); 2538 if (name.Language == null || String.IsNullOrEmpty(name.Name)) 2539 { 2540 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, LanguageLocalName))); 2541 } 2542 2543 writer.WriteAttributeString(LanguagePrefix, LanguageLocalName, LanguageNamespaceUri, name.Language.Name); 2544 WriteCustomAttributes<LocalizedName>(writer, name); 2545 writer.WriteString(name.Name); 2546 WriteCustomElements<LocalizedName>(writer, name); 2547 writer.WriteEndElement(); 2548 } 2549 2550 /// <summary> 2551 /// Writes localized uri 2552 /// </summary> 2553 /// <param name="writer">The xml writer.</param> 2554 /// <param name="uri">The localized uri.</param> 2555 /// <param name="element">The xml qualified name.</param> 2556 /// <exception cref="ArgumentNullException">The parameter writer/uri/element is null.</exception> WriteLocalizedUri(XmlWriter writer, LocalizedUri uri, XmlQualifiedName element)2557 protected virtual void WriteLocalizedUri(XmlWriter writer, LocalizedUri uri, XmlQualifiedName element) 2558 { 2559 if (writer == null) 2560 { 2561 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2562 } 2563 2564 if (uri == null) 2565 { 2566 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri"); 2567 } 2568 2569 if (element == null) 2570 { 2571 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element"); 2572 } 2573 2574 writer.WriteStartElement(element.Name, element.Namespace); 2575 if (uri.Language == null || uri.Uri == null) 2576 { 2577 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, LanguageLocalName))); 2578 } 2579 2580 writer.WriteAttributeString(LanguagePrefix, LanguageLocalName, LanguageNamespaceUri, uri.Language.Name); 2581 WriteCustomAttributes<LocalizedUri>(writer, uri); 2582 writer.WriteString(uri.Uri.IsAbsoluteUri ? uri.Uri.AbsoluteUri : uri.Uri.ToString()); 2583 WriteCustomElements<LocalizedUri>(writer, uri); 2584 writer.WriteEndElement(); 2585 } 2586 2587 /// <summary> 2588 /// Writes the federation metadata to the given stream. 2589 /// </summary> 2590 /// <param name="stream">Stream to write the Federation Metadata.</param> 2591 /// <param name="metadata">Metadata to write.</param> 2592 /// <exception cref="ArgumentNullException">The input argument is null.</exception> WriteMetadata(Stream stream, MetadataBase metadata)2593 public void WriteMetadata(Stream stream, MetadataBase metadata) 2594 { 2595 if (stream == null) 2596 { 2597 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream"); 2598 } 2599 2600 if (metadata == null) 2601 { 2602 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("metadata"); 2603 } 2604 2605 using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8, false)) 2606 { 2607 WriteMetadata(writer, metadata); 2608 } 2609 } 2610 2611 /// <summary> 2612 /// Writes the federation metadata to the given writer. 2613 /// </summary> 2614 /// <param name="writer">Writer to which to write the federation Metadata</param> 2615 /// <param name="metadata">Metadata to write.</param> 2616 /// <exception cref="ArgumentNullException">The input argument is null.</exception> WriteMetadata(XmlWriter writer, MetadataBase metadata)2617 public void WriteMetadata(XmlWriter writer, MetadataBase metadata) 2618 { 2619 if (writer == null) 2620 { 2621 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2622 } 2623 2624 if (metadata == null) 2625 { 2626 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("metadata"); 2627 } 2628 2629 WriteMetadataCore(writer, metadata); 2630 } 2631 2632 /// <summary> 2633 /// Writes the metadata. 2634 /// </summary> 2635 /// <param name="writer">The xml writer.</param> 2636 /// <param name="metadataBase">The saml metadat base.</param> 2637 /// <exception cref="ArgumentNullException">The parameter writer/metadataBase is null.</exception> WriteMetadataCore(XmlWriter writer, MetadataBase metadataBase)2638 protected virtual void WriteMetadataCore(XmlWriter writer, MetadataBase metadataBase) 2639 { 2640 if (writer == null) 2641 { 2642 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2643 } 2644 2645 if (metadataBase == null) 2646 { 2647 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("metadataBase"); 2648 } 2649 2650 EntitiesDescriptor entitiesDescriptor = metadataBase as EntitiesDescriptor; 2651 if (entitiesDescriptor != null) 2652 { 2653 WriteEntitiesDescriptor(writer, entitiesDescriptor); 2654 } 2655 else 2656 { 2657 EntityDescriptor entityDescriptor = metadataBase as EntityDescriptor; 2658 if (entityDescriptor == null) 2659 { 2660 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.EntitiesDescriptor))); 2661 } 2662 2663 WriteEntityDescriptor(writer, entityDescriptor); 2664 } 2665 } 2666 2667 /// <summary> 2668 /// Writes an organization. 2669 /// </summary> 2670 /// <param name="writer">The xml writer.</param> 2671 /// <param name="organization">The organization.</param> 2672 /// <exception cref="ArgumentNullException">The parameter writer/organization is null.</exception> WriteOrganization(XmlWriter writer, Organization organization)2673 protected virtual void WriteOrganization(XmlWriter writer, Organization organization) 2674 { 2675 if (writer == null) 2676 { 2677 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2678 } 2679 2680 if (organization == null) 2681 { 2682 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("organization"); 2683 } 2684 2685 if (organization.DisplayNames == null) 2686 { 2687 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("organization.DisplayNames"); 2688 } 2689 2690 if (organization.Names == null) 2691 { 2692 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("organization.Names"); 2693 } 2694 2695 if (organization.Urls == null) 2696 { 2697 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("organization.Urls"); 2698 } 2699 2700 writer.WriteStartElement(Saml2MetadataConstants.Elements.Organization, Saml2MetadataConstants.Namespace); 2701 2702 if (organization.Names.Count < 1) 2703 { 2704 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.OrganizationName))); 2705 } 2706 2707 foreach (LocalizedName name in organization.Names) 2708 { 2709 XmlQualifiedName element = new XmlQualifiedName(Saml2MetadataConstants.Elements.OrganizationName, Saml2MetadataConstants.Namespace); 2710 WriteLocalizedName(writer, name, element); 2711 } 2712 2713 if (organization.DisplayNames.Count < 1) 2714 { 2715 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.OrganizationDisplayName))); 2716 } 2717 2718 foreach (LocalizedName displayName in organization.DisplayNames) 2719 { 2720 XmlQualifiedName element = new XmlQualifiedName(Saml2MetadataConstants.Elements.OrganizationDisplayName, Saml2MetadataConstants.Namespace); 2721 WriteLocalizedName(writer, displayName, element); 2722 } 2723 2724 if (organization.Urls.Count < 1) 2725 { 2726 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.OrganizationUrl))); 2727 } 2728 2729 foreach (LocalizedUri uri in organization.Urls) 2730 { 2731 XmlQualifiedName element = new XmlQualifiedName(Saml2MetadataConstants.Elements.OrganizationUrl, Saml2MetadataConstants.Namespace); 2732 WriteLocalizedUri(writer, uri, element); 2733 } 2734 2735 WriteCustomAttributes<Organization>(writer, organization); 2736 WriteCustomElements<Organization>(writer, organization); 2737 writer.WriteEndElement(); // Organization 2738 } 2739 2740 /// <summary> 2741 /// Writes role descriptor attibutes. 2742 /// </summary> 2743 /// <param name="writer">The xml writer.</param> 2744 /// <param name="roleDescriptor">The role descriptor.</param> 2745 /// <exception cref="ArgumentNullException">The parameter writer/roleDescriptor/roleDescriptor.ProtocolsSupporeted is null.</exception> WriteRoleDescriptorAttributes(XmlWriter writer, RoleDescriptor roleDescriptor)2746 protected virtual void WriteRoleDescriptorAttributes(XmlWriter writer, RoleDescriptor roleDescriptor) 2747 { 2748 if (writer == null) 2749 { 2750 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2751 } 2752 2753 if (roleDescriptor == null) 2754 { 2755 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor"); 2756 } 2757 2758 if (roleDescriptor.ProtocolsSupported == null) 2759 { 2760 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.ProtocolsSupported"); 2761 } 2762 2763 // Optional 2764 if (roleDescriptor.ValidUntil != null && roleDescriptor.ValidUntil != DateTime.MaxValue) 2765 { 2766 // Write the date in a sortable form. 2767 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ValidUntil, null, roleDescriptor.ValidUntil.ToString("s", CultureInfo.InvariantCulture)); 2768 } 2769 2770 // Optional 2771 if (roleDescriptor.ErrorUrl != null) 2772 { 2773 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ErrorUrl, null, (roleDescriptor.ErrorUrl.IsAbsoluteUri ? roleDescriptor.ErrorUrl.AbsoluteUri : roleDescriptor.ErrorUrl.ToString())); 2774 } 2775 2776 // Mandatory 2777 if (roleDescriptor.ProtocolsSupported.Count == 0) 2778 { 2779 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Attributes.ProtocolsSupported))); 2780 } 2781 2782 StringBuilder sb = new StringBuilder(); 2783 foreach (Uri protocol in roleDescriptor.ProtocolsSupported) 2784 { 2785 sb.AppendFormat("{0} ", (protocol.IsAbsoluteUri ? protocol.AbsoluteUri : protocol.ToString())); 2786 } 2787 2788 string protocolsString = sb.ToString(); 2789 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ProtocolsSupported, null, protocolsString.Trim()); 2790 2791 WriteCustomAttributes<RoleDescriptor>(writer, roleDescriptor); 2792 } 2793 2794 /// <summary> 2795 /// Writes the role descriptor element. 2796 /// </summary> 2797 /// <param name="writer">The xml writer.</param> 2798 /// <param name="roleDescriptor">The role descriptor.</param> 2799 /// <exception cref="ArgumentNullException">The parameter writer/roleDescriptor/roleDescriptor.Contacts/roleDescriptor.Keys is null.</exception> WriteRoleDescriptorElements(XmlWriter writer, RoleDescriptor roleDescriptor)2800 protected virtual void WriteRoleDescriptorElements(XmlWriter writer, RoleDescriptor roleDescriptor) 2801 { 2802 if (writer == null) 2803 { 2804 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2805 } 2806 2807 if (roleDescriptor == null) 2808 { 2809 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor"); 2810 } 2811 2812 if (roleDescriptor.Contacts == null) 2813 { 2814 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.Contacts"); 2815 } 2816 2817 if (roleDescriptor.Keys == null) 2818 { 2819 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("roleDescriptor.Keys"); 2820 } 2821 2822 // Optional 2823 if (roleDescriptor.Organization != null) 2824 { 2825 WriteOrganization(writer, roleDescriptor.Organization); 2826 } 2827 2828 // Optional 2829 foreach (KeyDescriptor key in roleDescriptor.Keys) 2830 { 2831 WriteKeyDescriptor(writer, key); 2832 } 2833 2834 // Optional 2835 foreach (ContactPerson contact in roleDescriptor.Contacts) 2836 { 2837 WriteContactPerson(writer, contact); 2838 } 2839 2840 WriteCustomElements<RoleDescriptor>(writer, roleDescriptor); 2841 } 2842 2843 /// <summary> 2844 /// Writes a security token service descriptor. 2845 /// </summary> 2846 /// <param name="writer">The xml writer.</param> 2847 /// <param name="securityTokenServiceDescriptor">The <see cref="SecurityTokenServiceDescriptor"/>.</param> 2848 /// <exception cref="ArgumentNullException">The parameter writer/securityTokenServiceDescriptor/securityTokenServiceDescriptor.Endpoint/ 2849 /// securityTokenServiceDescriptor.PassiveRequestorEndpoints is null.</exception> WriteSecurityTokenServiceDescriptor(XmlWriter writer, SecurityTokenServiceDescriptor securityTokenServiceDescriptor)2850 protected virtual void WriteSecurityTokenServiceDescriptor(XmlWriter writer, SecurityTokenServiceDescriptor securityTokenServiceDescriptor) 2851 { 2852 if (writer == null) 2853 { 2854 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2855 } 2856 2857 if (securityTokenServiceDescriptor == null) 2858 { 2859 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityTokenServiceDescriptor"); 2860 } 2861 2862 if (securityTokenServiceDescriptor.SecurityTokenServiceEndpoints == null) 2863 { 2864 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityTokenServiceDescriptor.Endpoints"); 2865 } 2866 2867 if (securityTokenServiceDescriptor.PassiveRequestorEndpoints == null) 2868 { 2869 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityTokenServiceDescriptor.PassiveRequestorEndpoints"); 2870 } 2871 2872 writer.WriteStartElement(Saml2MetadataConstants.Elements.RoleDescriptor, Saml2MetadataConstants.Namespace); 2873 writer.WriteAttributeString("xsi", "type", XmlSchema.InstanceNamespace, FederationMetadataConstants.Prefix + ":" + FederationMetadataConstants.Elements.SecurityTokenServiceType); 2874 2875 writer.WriteAttributeString("xmlns", FederationMetadataConstants.Prefix, null, FederationMetadataConstants.Namespace); 2876 2877 WriteWebServiceDescriptorAttributes(writer, securityTokenServiceDescriptor); 2878 WriteCustomAttributes<SecurityTokenServiceDescriptor>(writer, securityTokenServiceDescriptor); 2879 2880 WriteWebServiceDescriptorElements(writer, securityTokenServiceDescriptor); 2881 2882 if (securityTokenServiceDescriptor.SecurityTokenServiceEndpoints.Count == 0) 2883 { 2884 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, FederationMetadataConstants.Elements.SecurityTokenServiceEndpoint))); 2885 } 2886 2887 foreach (EndpointReference epr in securityTokenServiceDescriptor.SecurityTokenServiceEndpoints) 2888 { 2889 writer.WriteStartElement(FederationMetadataConstants.Elements.SecurityTokenServiceEndpoint, FederationMetadataConstants.Namespace); 2890 epr.WriteTo(writer); 2891 writer.WriteEndElement(); 2892 } 2893 2894 foreach (EndpointReference epr in securityTokenServiceDescriptor.PassiveRequestorEndpoints) 2895 { 2896 writer.WriteStartElement(FederationMetadataConstants.Elements.PassiveRequestorEndpoint, FederationMetadataConstants.Namespace); 2897 epr.WriteTo(writer); 2898 writer.WriteEndElement(); 2899 } 2900 2901 WriteCustomElements<SecurityTokenServiceDescriptor>(writer, securityTokenServiceDescriptor); 2902 2903 writer.WriteEndElement(); 2904 } 2905 2906 /// <summary> 2907 /// Writes an spsso descriptor. 2908 /// </summary> 2909 /// <param name="writer">The xml writer.</param> 2910 /// <param name="serviceProviderSingleSignOnDescriptor">The spsso descriptor.</param> 2911 /// <exception cref="ArgumentNullException">The input parameter is null.</exception> WriteServiceProviderSingleSignOnDescriptor(XmlWriter writer, ServiceProviderSingleSignOnDescriptor serviceProviderSingleSignOnDescriptor)2912 protected virtual void WriteServiceProviderSingleSignOnDescriptor(XmlWriter writer, ServiceProviderSingleSignOnDescriptor serviceProviderSingleSignOnDescriptor) 2913 { 2914 if (writer == null) 2915 { 2916 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2917 } 2918 2919 if (serviceProviderSingleSignOnDescriptor == null) 2920 { 2921 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("spssoDescriptor"); 2922 } 2923 2924 if (serviceProviderSingleSignOnDescriptor.AssertionConsumerServices == null) 2925 { 2926 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("spssoDescriptor.AssertionConsumerService"); 2927 } 2928 2929 writer.WriteStartElement(Saml2MetadataConstants.Elements.SpssoDescriptor, Saml2MetadataConstants.Namespace); 2930 if (serviceProviderSingleSignOnDescriptor.AuthenticationRequestsSigned) 2931 { 2932 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.AuthenticationRequestsSigned, null, 2933 XmlConvert.ToString(serviceProviderSingleSignOnDescriptor.AuthenticationRequestsSigned)); 2934 } 2935 2936 if (serviceProviderSingleSignOnDescriptor.WantAssertionsSigned) 2937 { 2938 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.WantAssertionsSigned, null, 2939 XmlConvert.ToString(serviceProviderSingleSignOnDescriptor.WantAssertionsSigned)); 2940 } 2941 2942 WriteSingleSignOnDescriptorAttributes(writer, serviceProviderSingleSignOnDescriptor); 2943 WriteCustomAttributes<ServiceProviderSingleSignOnDescriptor>(writer, serviceProviderSingleSignOnDescriptor); 2944 2945 WriteSingleSignOnDescriptorElements(writer, serviceProviderSingleSignOnDescriptor); 2946 if (serviceProviderSingleSignOnDescriptor.AssertionConsumerServices.Count == 0) 2947 { 2948 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, Saml2MetadataConstants.Elements.AssertionConsumerService))); 2949 } 2950 2951 foreach (IndexedProtocolEndpoint ep in serviceProviderSingleSignOnDescriptor.AssertionConsumerServices.Values) 2952 { 2953 XmlQualifiedName element = new XmlQualifiedName(Saml2MetadataConstants.Elements.AssertionConsumerService, Saml2MetadataConstants.Namespace); 2954 WriteIndexedProtocolEndpoint(writer, ep, element); 2955 } 2956 2957 WriteCustomElements<ServiceProviderSingleSignOnDescriptor>(writer, serviceProviderSingleSignOnDescriptor); 2958 writer.WriteEndElement(); // SPSSODescriptor 2959 } 2960 2961 /// <summary> 2962 /// Writes the sso descriptor attributers. 2963 /// </summary> 2964 /// <param name="writer">The xml writer.</param> 2965 /// <param name="singleSignOnDescriptor">The sso descriptor.</param> WriteSingleSignOnDescriptorAttributes(XmlWriter writer, SingleSignOnDescriptor singleSignOnDescriptor)2966 protected virtual void WriteSingleSignOnDescriptorAttributes(XmlWriter writer, SingleSignOnDescriptor singleSignOnDescriptor) 2967 { 2968 WriteRoleDescriptorAttributes(writer, singleSignOnDescriptor); 2969 WriteCustomAttributes<SingleSignOnDescriptor>(writer, singleSignOnDescriptor); 2970 } 2971 2972 /// <summary> 2973 /// Writes the sso descriptor element. 2974 /// </summary> 2975 /// <param name="writer">The xml writer.</param> 2976 /// <param name="singleSignOnDescriptor">The sso descriptor.</param> WriteSingleSignOnDescriptorElements(XmlWriter writer, SingleSignOnDescriptor singleSignOnDescriptor)2977 protected virtual void WriteSingleSignOnDescriptorElements(XmlWriter writer, SingleSignOnDescriptor singleSignOnDescriptor) 2978 { 2979 if (writer == null) 2980 { 2981 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 2982 } 2983 2984 if (singleSignOnDescriptor == null) 2985 { 2986 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ssoDescriptor"); 2987 } 2988 2989 WriteRoleDescriptorElements(writer, singleSignOnDescriptor); 2990 2991 if (singleSignOnDescriptor.ArtifactResolutionServices != null && singleSignOnDescriptor.ArtifactResolutionServices.Count > 0) 2992 { 2993 // Write the artifact resolution services 2994 foreach (IndexedProtocolEndpoint ep in singleSignOnDescriptor.ArtifactResolutionServices.Values) 2995 { 2996 if (ep.ResponseLocation != null) 2997 { 2998 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3249, Saml2MetadataConstants.Attributes.ResponseLocation))); 2999 } 3000 3001 XmlQualifiedName element = new XmlQualifiedName(Saml2MetadataConstants.Elements.ArtifactResolutionService, Saml2MetadataConstants.Namespace); 3002 WriteIndexedProtocolEndpoint(writer, ep, element); 3003 } 3004 } 3005 3006 if (singleSignOnDescriptor.SingleLogoutServices != null && singleSignOnDescriptor.SingleLogoutServices.Count > 0) 3007 { 3008 // Write the single logout service endpoints. 3009 foreach (ProtocolEndpoint endpoint in singleSignOnDescriptor.SingleLogoutServices) 3010 { 3011 XmlQualifiedName element = new XmlQualifiedName(Saml2MetadataConstants.Elements.SingleLogoutService, Saml2MetadataConstants.Namespace); 3012 WriteProtocolEndpoint(writer, endpoint, element); 3013 } 3014 } 3015 3016 if (singleSignOnDescriptor.NameIdentifierFormats != null && singleSignOnDescriptor.NameIdentifierFormats.Count > 0) 3017 { 3018 // Write the name id formats 3019 foreach (Uri nameId in singleSignOnDescriptor.NameIdentifierFormats) 3020 { 3021 if (!nameId.IsAbsoluteUri) 3022 { 3023 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID0014, Saml2MetadataConstants.Elements.NameIDFormat))); 3024 } 3025 3026 writer.WriteStartElement(Saml2MetadataConstants.Elements.NameIDFormat, Saml2MetadataConstants.Namespace); 3027 writer.WriteString(nameId.AbsoluteUri); 3028 writer.WriteEndElement(); 3029 } 3030 } 3031 3032 WriteCustomElements<SingleSignOnDescriptor>(writer, singleSignOnDescriptor); 3033 } 3034 3035 /// <summary> 3036 /// Write a web service description's attributes. 3037 /// </summary> 3038 /// <param name="writer">The xml writer.</param> 3039 /// <param name="wsDescriptor">The web service desriptor.</param> 3040 /// <exception cref="ArgumentNullException">The input parameter is null.</exception> WriteWebServiceDescriptorAttributes(XmlWriter writer, WebServiceDescriptor wsDescriptor)3041 protected virtual void WriteWebServiceDescriptorAttributes(XmlWriter writer, WebServiceDescriptor wsDescriptor) 3042 { 3043 if (writer == null) 3044 { 3045 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 3046 } 3047 3048 if (wsDescriptor == null) 3049 { 3050 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsDescriptor"); 3051 } 3052 3053 WriteRoleDescriptorAttributes(writer, wsDescriptor); 3054 3055 if (!String.IsNullOrEmpty(wsDescriptor.ServiceDisplayName)) 3056 { 3057 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ServiceDisplayName, null, wsDescriptor.ServiceDisplayName); 3058 } 3059 3060 if (!String.IsNullOrEmpty(wsDescriptor.ServiceDescription)) 3061 { 3062 writer.WriteAttributeString(Saml2MetadataConstants.Attributes.ServiceDescription, null, wsDescriptor.ServiceDescription); 3063 } 3064 3065 WriteCustomAttributes<WebServiceDescriptor>(writer, wsDescriptor); 3066 } 3067 3068 /// <summary> 3069 /// Write a web service description element. 3070 /// </summary> 3071 /// <param name="writer">The xml writer.</param> 3072 /// <param name="wsDescriptor">The web service desriptor.</param> 3073 /// <exception cref="ArgumentNullException">The input parameter is null.</exception> WriteWebServiceDescriptorElements(XmlWriter writer, WebServiceDescriptor wsDescriptor)3074 protected virtual void WriteWebServiceDescriptorElements(XmlWriter writer, WebServiceDescriptor wsDescriptor) 3075 { 3076 if (writer == null) 3077 { 3078 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 3079 } 3080 3081 if (wsDescriptor == null) 3082 { 3083 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsDescriptor"); 3084 } 3085 3086 if (wsDescriptor.TargetScopes == null) 3087 { 3088 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsDescriptor.TargetScopes"); 3089 } 3090 3091 if (wsDescriptor.ClaimTypesOffered == null) 3092 { 3093 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsDescriptor.ClaimTypesOffered"); 3094 } 3095 3096 if (wsDescriptor.TokenTypesOffered == null) 3097 { 3098 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsDescriptor.TokenTypesOffered"); 3099 } 3100 3101 WriteRoleDescriptorElements(writer, wsDescriptor); 3102 3103 if (wsDescriptor.TokenTypesOffered.Count > 0) 3104 { 3105 writer.WriteStartElement(FederationMetadataConstants.Elements.TokenTypesOffered, FederationMetadataConstants.Namespace); 3106 foreach (Uri tokenType in wsDescriptor.TokenTypesOffered) 3107 { 3108 writer.WriteStartElement(WSFederationMetadataConstants.Elements.TokenType, WSFederationMetadataConstants.Namespace); 3109 if (!tokenType.IsAbsoluteUri) 3110 { 3111 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MetadataSerializationException(SR.GetString(SR.ID3203, WSAuthorizationConstants.Elements.ClaimType))); 3112 } 3113 3114 writer.WriteAttributeString(WSFederationMetadataConstants.Attributes.Uri, tokenType.AbsoluteUri); 3115 writer.WriteEndElement(); 3116 } 3117 3118 writer.WriteEndElement(); 3119 } 3120 3121 if (wsDescriptor.ClaimTypesOffered.Count > 0) 3122 { 3123 writer.WriteStartElement(FederationMetadataConstants.Elements.ClaimTypesOffered, FederationMetadataConstants.Namespace); 3124 foreach (DisplayClaim claim in wsDescriptor.ClaimTypesOffered) 3125 { 3126 WriteDisplayClaim(writer, claim); 3127 } 3128 3129 writer.WriteEndElement(); 3130 } 3131 3132 if (wsDescriptor.ClaimTypesRequested.Count > 0) 3133 { 3134 writer.WriteStartElement(FederationMetadataConstants.Elements.ClaimTypesRequested, FederationMetadataConstants.Namespace); 3135 foreach (DisplayClaim claim in wsDescriptor.ClaimTypesRequested) 3136 { 3137 WriteDisplayClaim(writer, claim); 3138 } 3139 3140 writer.WriteEndElement(); 3141 } 3142 3143 if (wsDescriptor.TargetScopes.Count > 0) 3144 { 3145 writer.WriteStartElement(FederationMetadataConstants.Elements.TargetScopes, FederationMetadataConstants.Namespace); 3146 foreach (EndpointReference address in wsDescriptor.TargetScopes) 3147 { 3148 address.WriteTo(writer); 3149 } 3150 3151 writer.WriteEndElement(); 3152 } 3153 3154 WriteCustomElements<WebServiceDescriptor>(writer, wsDescriptor); 3155 } 3156 3157 /// <summary> 3158 /// Reads the <saml:Attribute> element. 3159 /// </summary> 3160 /// <remarks> 3161 /// The default implementation requires that the content of the 3162 /// Attribute element be a simple string. To handle complex content 3163 /// or content of declared simple types other than xs:string, override 3164 /// this method. 3165 /// </remarks> 3166 /// <param name="reader">The xml reader.</param> 3167 /// <returns>A Saml2 attribute.</returns> 3168 /// <exception cref="ArgumentNullException">The input parameter is null.</exception> ReadAttribute(XmlReader reader)3169 protected virtual Saml2Attribute ReadAttribute(XmlReader reader) 3170 { 3171 if (null == reader) 3172 { 3173 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); 3174 } 3175 3176 // throw if wrong element 3177 if (!reader.IsStartElement(Saml2Constants.Elements.Attribute, Saml2Constants.Namespace)) 3178 { 3179 reader.ReadStartElement(Saml2Constants.Elements.Attribute, Saml2Constants.Namespace); 3180 } 3181 3182 try 3183 { 3184 Saml2Attribute attribute; 3185 bool isEmpty = reader.IsEmptyElement; 3186 3187 // @attributes 3188 string value; 3189 3190 // @xsi:type 3191 XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.AttributeType, Saml2Constants.Namespace); 3192 3193 // @Name - required 3194 value = reader.GetAttribute(Saml2Constants.Attributes.Name); 3195 if (String.IsNullOrEmpty(value)) 3196 { 3197 throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.Name, Saml2Constants.Elements.Attribute)); 3198 } 3199 3200 attribute = new Saml2Attribute(value); 3201 3202 // @NameFormat - optional 3203 value = reader.GetAttribute(Saml2Constants.Attributes.NameFormat); 3204 if (!String.IsNullOrEmpty(value)) 3205 { 3206 if (!UriUtil.CanCreateValidUri(value, UriKind.Absolute)) 3207 { 3208 throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID0011, Saml2Constants.Attributes.Namespace, Saml2Constants.Elements.Action)); 3209 } 3210 3211 attribute.NameFormat = new Uri(value); 3212 } 3213 3214 // @FriendlyName - optional 3215 attribute.FriendlyName = reader.GetAttribute(Saml2Constants.Attributes.FriendlyName); 3216 3217 // content 3218 reader.Read(); 3219 if (!isEmpty) 3220 { 3221 while (reader.IsStartElement(Saml2Constants.Elements.AttributeValue, Saml2Constants.Namespace)) 3222 { 3223 bool isEmptyValue = reader.IsEmptyElement; 3224 bool isNil = XmlUtil.IsNil(reader); 3225 3226 // For now, the value must be a string 3227 XmlUtil.ValidateXsiType(reader, "string", XmlSchema.Namespace); 3228 3229 if (isNil) 3230 { 3231 reader.Read(); 3232 if (!isEmptyValue) 3233 { 3234 reader.ReadEndElement(); 3235 } 3236 3237 attribute.Values.Add(null); 3238 } 3239 else if (isEmptyValue) 3240 { 3241 reader.Read(); 3242 attribute.Values.Add(""); 3243 } 3244 else 3245 { 3246 attribute.Values.Add(reader.ReadElementString()); 3247 } 3248 } 3249 3250 reader.ReadEndElement(); 3251 } 3252 3253 return attribute; 3254 } 3255 catch (Exception e) 3256 { 3257 if (System.Runtime.Fx.IsFatal(e)) 3258 throw; 3259 3260 Exception wrapped = TryWrapReadException(reader, e); 3261 if (null == wrapped) 3262 { 3263 throw; 3264 } 3265 else 3266 { 3267 throw wrapped; 3268 } 3269 } 3270 } 3271 3272 /// <summary> 3273 /// Writes the <saml:Attribute> element. 3274 /// </summary> 3275 /// <param name="writer">The xml writer.</param> 3276 /// <param name="data">The Saml2 attibute.</param> 3277 /// <exception cref="ArgumentNullException">The input parameter is null.</exception> WriteAttribute(XmlWriter writer, Saml2Attribute data)3278 protected virtual void WriteAttribute(XmlWriter writer, Saml2Attribute data) 3279 { 3280 if (null == writer) 3281 { 3282 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); 3283 } 3284 3285 if (null == data) 3286 { 3287 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data"); 3288 } 3289 3290 // <Attribute> 3291 writer.WriteStartElement(Saml2Constants.Elements.Attribute, Saml2Constants.Namespace); 3292 3293 // @Name - required 3294 writer.WriteAttributeString(Saml2Constants.Attributes.Name, data.Name); 3295 3296 // @NameFormat - optional 3297 if (null != data.NameFormat) 3298 { 3299 writer.WriteAttributeString(Saml2Constants.Attributes.NameFormat, data.NameFormat.AbsoluteUri); 3300 } 3301 3302 // @FriendlyName - optional 3303 if (null != data.FriendlyName) 3304 { 3305 writer.WriteAttributeString(Saml2Constants.Attributes.FriendlyName, data.FriendlyName); 3306 } 3307 3308 // <AttributeValue> 0-OO (nillable) 3309 foreach (string value in data.Values) 3310 { 3311 writer.WriteStartElement(Saml2Constants.Elements.AttributeValue, Saml2Constants.Namespace); 3312 3313 if (null == value) 3314 { 3315 writer.WriteAttributeString("nil", XmlSchema.InstanceNamespace, XmlConvert.ToString(true)); 3316 } 3317 else if (value.Length > 0) 3318 { 3319 writer.WriteString(value); 3320 } 3321 3322 writer.WriteEndElement(); 3323 } 3324 3325 // </Attribute> 3326 writer.WriteEndElement(); 3327 } 3328 3329 // Wraps common data validation exceptions with an XmlException 3330 // associated with the failing reader TryWrapReadException(XmlReader reader, Exception inner)3331 private static Exception TryWrapReadException(XmlReader reader, Exception inner) 3332 { 3333 if (inner is FormatException 3334 || inner is ArgumentException 3335 || inner is InvalidOperationException 3336 || inner is OverflowException) 3337 { 3338 return DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4125), inner); 3339 } 3340 3341 return null; 3342 } 3343 } 3344 } 3345