internal ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver) { Saml2Subject subject = assertion.Subject; Saml2SubjectConfirmation confirmation = subject.SubjectConfirmations[0]; if (confirmation.SubjectConfirmationData != null) { this.ValidateConfirmationData(confirmation.SubjectConfirmationData); } List<SecurityKey> list = new List<SecurityKey>(); foreach (SecurityKeyIdentifier identifier in confirmation.SubjectConfirmationData.KeyIdentifiers) { SecurityKey key = null; foreach (SecurityKeyIdentifierClause clause in identifier) { if ((resolver != null) && resolver.TryResolveSecurityKey(clause, out key)) { list.Add(key); break; } } if (key == null) { if (identifier.CanCreateKey) { key = identifier.CreateKey(); list.Add(key); continue; } list.Add(new SecurityKeyElement(identifier, resolver)); } } return list.AsReadOnly(); }
internal static XmlDictionaryReader CreatePlaintextReaderFromEncryptedData( XmlDictionaryReader reader, SecurityTokenResolver serviceTokenResolver, SecurityTokenSerializer keyInfoSerializer, Collection<EncryptedKeyIdentifierClause> clauses, out EncryptingCredentials encryptingCredentials) { if (reader == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); } reader.MoveToContent(); if (reader.IsEmptyElement) { #pragma warning suppress 56504 // bogus - thinks reader.LocalName, reader.NamespaceURI need validation throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID3061, reader.LocalName, reader.NamespaceURI)); } encryptingCredentials = null; XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.EncryptedElementType, Saml2Constants.Namespace); reader.ReadStartElement(); EncryptedDataElement encryptedData = new EncryptedDataElement(keyInfoSerializer); // <xenc:EncryptedData> 1 encryptedData.ReadXml(reader); // <xenc:EncryptedKey> 0-oo reader.MoveToContent(); while (reader.IsStartElement(XmlEncryptionConstants.Elements.EncryptedKey, XmlEncryptionConstants.Namespace)) { SecurityKeyIdentifierClause skic; if (keyInfoSerializer.CanReadKeyIdentifierClause(reader)) { skic = keyInfoSerializer.ReadKeyIdentifierClause(reader); } else { EncryptedKeyElement encryptedKey = new EncryptedKeyElement(keyInfoSerializer); encryptedKey.ReadXml(reader); skic = encryptedKey.GetClause(); } EncryptedKeyIdentifierClause encryptedKeyClause = skic as EncryptedKeyIdentifierClause; if (null == encryptedKeyClause) { throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4172)); } clauses.Add(encryptedKeyClause); } reader.ReadEndElement(); // Try to resolve the decryption key from both the embedded // KeyInfo and any external clauses SecurityKey decryptionKey = null; SecurityKeyIdentifierClause matchingClause = null; foreach (SecurityKeyIdentifierClause clause in encryptedData.KeyIdentifier) { if (serviceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey)) { matchingClause = clause; break; } } if (null == decryptionKey) { foreach (SecurityKeyIdentifierClause clause in clauses) { if (serviceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey)) { matchingClause = clause; break; } } } if (null == decryptionKey) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EncryptedTokenDecryptionFailedException()); } // Need a symmetric key SymmetricSecurityKey symmetricKey = decryptionKey as SymmetricSecurityKey; if (null == symmetricKey) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException(SR.GetString(SR.ID4023))); } // Do the actual decryption SymmetricAlgorithm decryptor = symmetricKey.GetSymmetricAlgorithm(encryptedData.Algorithm); byte[] plainText = encryptedData.Decrypt(decryptor); // Save off the encrypting credentials for roundtrip encryptingCredentials = new ReceivedEncryptingCredentials(decryptionKey, new SecurityKeyIdentifier(matchingClause), encryptedData.Algorithm); return XmlDictionaryReader.CreateTextReader(plainText, reader.Quotas); }
/// <summary> /// Resolves the collection of <see cref="SecurityKey"/> referenced in a <see cref="Saml2Assertion"/>. /// </summary> /// <param name="assertion"><see cref="Saml2Assertion"/> to process.</param> /// <param name="resolver"><see cref="SecurityTokenResolver"/> to use in resolving the <see cref="SecurityKey"/>.</param> /// <returns>A read only collection of <see cref="SecurityKey"/> contained in the assertion.</returns> protected virtual ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver) { if (null == assertion) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion"); } // Must have Subject Saml2Subject subject = assertion.Subject; if (null == subject) { // No Subject throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4130))); } // Must have one SubjectConfirmation if (0 == subject.SubjectConfirmations.Count) { // No SubjectConfirmation throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4131))); } if (subject.SubjectConfirmations.Count > 1) { // More than one SubjectConfirmation throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4132))); } // Extract the keys for the given method ReadOnlyCollection<SecurityKey> securityKeys; Saml2SubjectConfirmation subjectConfirmation = subject.SubjectConfirmations[0]; // For bearer, ensure there are no keys, set the collection to empty // For HolderOfKey, ensure there is at least one key, resolve and create collection if (Saml2Constants.ConfirmationMethods.Bearer == subjectConfirmation.Method) { if (null != subjectConfirmation.SubjectConfirmationData && 0 != subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Count) { // Bearer but has keys throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4133))); } securityKeys = EmptyReadOnlyCollection<SecurityKey>.Instance; } else if (Saml2Constants.ConfirmationMethods.HolderOfKey == subjectConfirmation.Method) { if (null == subjectConfirmation.SubjectConfirmationData || 0 == subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Count) { // Holder-of-key but no keys throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4134))); } List<SecurityKey> holderKeys = new List<SecurityKey>(); SecurityKey key; foreach (SecurityKeyIdentifier keyIdentifier in subjectConfirmation.SubjectConfirmationData.KeyIdentifiers) { key = null; // Try the resolver first foreach (SecurityKeyIdentifierClause clause in keyIdentifier) { if (null != resolver && resolver.TryResolveSecurityKey(clause, out key)) { holderKeys.Add(key); break; } } // If that doesn't work, try to create the key (e.g. bare RSA or X509 raw) if (null == key) { if (keyIdentifier.CanCreateKey) { key = keyIdentifier.CreateKey(); holderKeys.Add(key); } else { holderKeys.Add(new SecurityKeyElement(keyIdentifier, resolver)); } } } securityKeys = holderKeys.AsReadOnly(); } else { // SenderVouches, as well as other random things, aren't accepted throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4136, subjectConfirmation.Method))); } return securityKeys; }
internal static SecurityKey ResolveSecurityKey(SecurityKeyIdentifier ski, SecurityTokenResolver tokenResolver) { if (ski == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ski"); if (tokenResolver != null) { for (int i = 0; i < ski.Count; ++i) { SecurityKey key = null; if (tokenResolver.TryResolveSecurityKey(ski[i], out key)) return key; } } if (ski.CanCreateKey) return ski.CreateKey(); return null; }