| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System; |
| | | 5 | | using System.Collections.ObjectModel; |
| | | 6 | | using System.IO; |
| | | 7 | | using System.Security.Cryptography; |
| | | 8 | | using System.Security.Cryptography.Xml; |
| | | 9 | | using System.Threading.Tasks; |
| | | 10 | | using System.Xml; |
| | | 11 | | using CoreWCF.Channels; |
| | | 12 | | using CoreWCF.Description; |
| | | 13 | | using CoreWCF.IdentityModel; |
| | | 14 | | using CoreWCF.IdentityModel.Policy; |
| | | 15 | | using CoreWCF.IdentityModel.Selectors; |
| | | 16 | | using CoreWCF.IdentityModel.Tokens; |
| | | 17 | | using CoreWCF.Security.Tokens; |
| | | 18 | | |
| | | 19 | | namespace CoreWCF.Security |
| | | 20 | | { |
| | | 21 | | internal class WSSecurityOneDotZeroReceiveSecurityHeader : ReceiveSecurityHeader |
| | | 22 | | { |
| | | 23 | | private KeyedHashAlgorithm _signingKey; |
| | | 24 | | private const string SIGNED_XML_HEADER = "signed_xml_header"; |
| | | 25 | | public WSSecurityOneDotZeroReceiveSecurityHeader(Message message, string actor, bool mustUnderstand, bool relay, |
| | | 26 | | SecurityStandardsManager standardsManager, |
| | | 27 | | SecurityAlgorithmSuite algorithmSuite, |
| | | 28 | | int headerIndex, |
| | | 29 | | MessageDirection transferDirection) |
| | 94 | 30 | | : base(message, actor, mustUnderstand, relay, standardsManager, algorithmSuite, headerIndex, transferDirecti |
| | | 31 | | { |
| | 94 | 32 | | } |
| | | 33 | | |
| | | 34 | | protected override bool IsReaderAtReferenceList(XmlDictionaryReader reader) |
| | | 35 | | { |
| | 188 | 36 | | return reader.IsStartElement(ReferenceList.ElementName, ReferenceList.NamespaceUri); |
| | | 37 | | } |
| | | 38 | | |
| | | 39 | | protected override bool IsReaderAtSignature(XmlDictionaryReader reader) |
| | | 40 | | { |
| | 211 | 41 | | return reader.IsStartElement(XD.XmlSignatureDictionary.Signature, XD.XmlSignatureDictionary.Namespace); |
| | | 42 | | } |
| | | 43 | | |
| | | 44 | | protected override void EnsureDecryptionComplete() |
| | | 45 | | { |
| | | 46 | | // noop |
| | 63 | 47 | | } |
| | | 48 | | |
| | | 49 | | protected override bool IsReaderAtEncryptedKey(XmlDictionaryReader reader) |
| | | 50 | | { |
| | 94 | 51 | | return reader.IsStartElement(XD.XmlEncryptionDictionary.EncryptedKey, XD.XmlEncryptionDictionary.Namespace); |
| | | 52 | | } |
| | | 53 | | |
| | | 54 | | protected override bool IsReaderAtEncryptedData(XmlDictionaryReader reader) |
| | | 55 | | { |
| | 94 | 56 | | bool encrypted = reader.IsStartElement(XD.XmlEncryptionDictionary.EncryptedData, XD.XmlEncryptionDictionary. |
| | | 57 | | |
| | 94 | 58 | | if (encrypted == true) |
| | | 59 | | { |
| | 0 | 60 | | throw new PlatformNotSupportedException(); |
| | | 61 | | } |
| | | 62 | | |
| | 94 | 63 | | return encrypted; |
| | | 64 | | } |
| | | 65 | | |
| | | 66 | | protected override bool IsReaderAtSecurityTokenReference(XmlDictionaryReader reader) |
| | | 67 | | { |
| | 94 | 68 | | return reader.IsStartElement(XD.SecurityJan2004Dictionary.SecurityTokenReference, XD.SecurityJan2004Dictiona |
| | | 69 | | } |
| | | 70 | | |
| | | 71 | | protected override EncryptedData ReadSecurityHeaderEncryptedItem(XmlDictionaryReader reader, bool readXmlreferen |
| | | 72 | | { |
| | 0 | 73 | | throw new PlatformNotSupportedException(); |
| | | 74 | | } |
| | | 75 | | |
| | | 76 | | protected override byte[] DecryptSecurityHeaderElement(EncryptedData encryptedData, WrappedKeySecurityToken wrap |
| | | 77 | | { |
| | 0 | 78 | | throw new PlatformNotSupportedException(); |
| | | 79 | | } |
| | | 80 | | |
| | | 81 | | protected override WrappedKeySecurityToken DecryptWrappedKey(XmlDictionaryReader reader) |
| | | 82 | | { |
| | 0 | 83 | | throw new PlatformNotSupportedException(); |
| | | 84 | | } |
| | | 85 | | |
| | | 86 | | protected override void OnDecryptionOfSecurityHeaderItemRequiringReferenceListEntry(string id) |
| | | 87 | | { |
| | 0 | 88 | | throw new PlatformNotSupportedException(); |
| | | 89 | | } |
| | | 90 | | |
| | | 91 | | protected override void ExecuteMessageProtectionPass(bool hasAtLeastOneSupportingTokenExpectedToBeSigned) |
| | | 92 | | { |
| | 0 | 93 | | throw new PlatformNotSupportedException(); |
| | | 94 | | } |
| | | 95 | | |
| | | 96 | | protected override ReferenceList ReadReferenceListCore(XmlDictionaryReader reader) |
| | | 97 | | { |
| | 0 | 98 | | throw new PlatformNotSupportedException(); |
| | | 99 | | } |
| | | 100 | | |
| | | 101 | | protected override void ProcessReferenceListCore(ReferenceList referenceList, WrappedKeySecurityToken wrappedKey |
| | | 102 | | { |
| | 0 | 103 | | throw new PlatformNotSupportedException(); |
| | | 104 | | } |
| | | 105 | | |
| | | 106 | | protected override void ReadSecurityTokenReference(XmlDictionaryReader reader) |
| | | 107 | | { |
| | 0 | 108 | | throw new PlatformNotSupportedException(); |
| | | 109 | | } |
| | | 110 | | |
| | | 111 | | protected override SignedXml ReadSignatureCore(XmlDictionaryReader signatureReader) |
| | | 112 | | { |
| | 23 | 113 | | XmlDocument doc = BuildSignedXmlDocument(Message.Headers, HeaderIndex); |
| | 23 | 114 | | SignedXMLInternal signedXml = new SignedXMLInternal(doc); |
| | 23 | 115 | | XmlElement signatureElement = FindSecurityHeaderSignatureElement(doc, HeaderIndex); |
| | 23 | 116 | | signedXml.LoadXml(signatureElement); |
| | 23 | 117 | | if (signedXml.SignedInfo.CanonicalizationMethodObject is XmlDsigExcC14NTransform xmlDsigExcC14NTransform) |
| | | 118 | | { |
| | 23 | 119 | | string[] inclusivePrefixes = XmlHelper.TokenizeInclusiveNamespacesPrefixList(xmlDsigExcC14NTransform.Inc |
| | 23 | 120 | | if (inclusivePrefixes != null) |
| | | 121 | | { |
| | 6 | 122 | | for (int i = 0; i < inclusivePrefixes.Length; i++) |
| | | 123 | | { |
| | 2 | 124 | | string ns = signatureReader.LookupNamespace(inclusivePrefixes[i]); |
| | 2 | 125 | | if (ns != null) |
| | | 126 | | { |
| | 2 | 127 | | XmlAttribute nsAttribute = doc.CreateAttribute("xmlns", inclusivePrefixes[i], "http://www.w3 |
| | 2 | 128 | | nsAttribute.Value = ns; |
| | 2 | 129 | | doc.DocumentElement.SetAttributeNode(nsAttribute); |
| | | 130 | | } |
| | | 131 | | } |
| | | 132 | | } |
| | | 133 | | } |
| | 23 | 134 | | using (XmlReader tempReader = signatureReader.ReadSubtree()) |
| | | 135 | | { |
| | 23 | 136 | | tempReader.Read();//move the reader to next |
| | 23 | 137 | | } |
| | 23 | 138 | | return signedXml; |
| | | 139 | | } |
| | | 140 | | |
| | | 141 | | // Builds the XmlDocument used to back signature verification. The |
| | | 142 | | // document is constructed from the SOAP message headers under a |
| | | 143 | | // synthetic root element. headerIndex is the position of the |
| | | 144 | | // wsse:Security header within the headers collection. |
| | | 145 | | internal static XmlDocument BuildSignedXmlDocument(MessageHeaders headers, int headerIndex) |
| | | 146 | | { |
| | 26 | 147 | | if (headers == null) |
| | | 148 | | { |
| | 0 | 149 | | throw new ArgumentNullException(nameof(headers)); |
| | | 150 | | } |
| | 26 | 151 | | if (headerIndex < 0 || headerIndex >= headers.Count) |
| | | 152 | | { |
| | 0 | 153 | | throw new ArgumentOutOfRangeException(nameof(headerIndex)); |
| | | 154 | | } |
| | | 155 | | |
| | | 156 | | // The verification document must be backed by the wsse:Security |
| | | 157 | | // header and only the wsse:Security header. Confirm that the |
| | | 158 | | // header at the supplied index is actually a Security header |
| | | 159 | | // belonging to a recognised WS-Security namespace before |
| | | 160 | | // continuing; otherwise the document we produce would have no |
| | | 161 | | // defensible relationship to the signature being checked. |
| | 26 | 162 | | MessageHeaderInfo headerInfo = headers[headerIndex]; |
| | 26 | 163 | | if (!string.Equals(headerInfo.Name, XD.SecurityJan2004Dictionary.Security.Value, StringComparison.Ordinal) |
| | 26 | 164 | | || !(string.Equals(headerInfo.Namespace, WSSecurity10Constants.Namespace, StringComparison.Ordinal) |
| | 26 | 165 | | || string.Equals(headerInfo.Namespace, WSSecurity11Constants.Namespace, StringComparison.Ordinal))) |
| | | 166 | | { |
| | 1 | 167 | | throw new ArgumentException(SR.Format(SR.SignatureVerificationFailed), nameof(headerIndex)); |
| | | 168 | | } |
| | | 169 | | |
| | 25 | 170 | | XmlDocument doc = new XmlDocument(); |
| | 25 | 171 | | using (XmlWriter writer = doc.CreateNavigator().AppendChild()) |
| | | 172 | | { |
| | 25 | 173 | | writer.WriteStartDocument(); |
| | 25 | 174 | | writer.WriteStartElement(SIGNED_XML_HEADER); |
| | | 175 | | // All headers are written into the synthetic verification |
| | | 176 | | // document so that signature Reference URIs targeting |
| | | 177 | | // addressing headers (wsa:To, wsa:Action, wsa:MessageID, |
| | | 178 | | // ...) and the Body continue to resolve. The Security |
| | | 179 | | // header position (headerIndex) is used by callers (see |
| | | 180 | | // ReadSignatureCore) to restrict the *Signature element |
| | | 181 | | // lookup* to inside the Security header subtree, |
| | | 182 | | // preventing attacker-planted ds:Signature elements in |
| | | 183 | | // sibling headers from being verified instead of the |
| | | 184 | | // legitimate one. |
| | 286 | 185 | | for (int i = 0; i < headers.Count; i++) |
| | | 186 | | { |
| | 118 | 187 | | headers.WriteHeader(i, writer); |
| | | 188 | | } |
| | 25 | 189 | | writer.WriteEndElement(); |
| | 25 | 190 | | writer.WriteEndDocument(); |
| | 25 | 191 | | } |
| | 25 | 192 | | return doc; |
| | | 193 | | } |
| | | 194 | | |
| | | 195 | | // Locates the ds:Signature element that ReadSignatureCore should |
| | | 196 | | // load. The lookup is constrained to the descendants of the |
| | | 197 | | // wsse:Security header at headerIndex. Sibling SOAP headers may not |
| | | 198 | | // contribute a Signature element to the verification, even if one |
| | | 199 | | // appears lexically before the Security header in the envelope. |
| | | 200 | | internal static XmlElement FindSecurityHeaderSignatureElement(XmlDocument doc, int headerIndex) |
| | | 201 | | { |
| | 25 | 202 | | if (doc == null) |
| | | 203 | | { |
| | 0 | 204 | | throw new ArgumentNullException(nameof(doc)); |
| | | 205 | | } |
| | 25 | 206 | | if (doc.DocumentElement == null || headerIndex < 0 || headerIndex >= doc.DocumentElement.ChildNodes.Count) |
| | | 207 | | { |
| | 0 | 208 | | throw new ArgumentOutOfRangeException(nameof(headerIndex)); |
| | | 209 | | } |
| | | 210 | | |
| | 25 | 211 | | XmlElement securityHeaderElement = doc.DocumentElement.ChildNodes[headerIndex] as XmlElement; |
| | 25 | 212 | | if (securityHeaderElement == null) |
| | | 213 | | { |
| | 0 | 214 | | throw new MessageSecurityException(SR.Format(SR.SignatureVerificationFailed)); |
| | | 215 | | } |
| | | 216 | | |
| | | 217 | | // Defence in depth: confirm locally that the element at |
| | | 218 | | // headerIndex really is a wsse:Security header before |
| | | 219 | | // descending into it to pick a ds:Signature. The whole |
| | | 220 | | // mitigation rests on the indexing operation above, so we |
| | | 221 | | // do not want to rely solely on the upstream check in |
| | | 222 | | // BuildSignedXmlDocument staying in lock-step with this |
| | | 223 | | // method. |
| | 25 | 224 | | if (!string.Equals(securityHeaderElement.LocalName, XD.SecurityJan2004Dictionary.Security.Value, StringCompa |
| | 25 | 225 | | || !(string.Equals(securityHeaderElement.NamespaceURI, WSSecurity10Constants.Namespace, StringComparison |
| | 25 | 226 | | || string.Equals(securityHeaderElement.NamespaceURI, WSSecurity11Constants.Namespace, StringComparis |
| | | 227 | | { |
| | 1 | 228 | | throw new MessageSecurityException(SR.Format(SR.SignatureVerificationFailed)); |
| | | 229 | | } |
| | | 230 | | |
| | 24 | 231 | | XmlNodeList nodeList = securityHeaderElement.GetElementsByTagName(XD.XmlSignatureDictionary.Signature.Value, |
| | 24 | 232 | | if (nodeList.Count == 0) |
| | | 233 | | { |
| | 0 | 234 | | throw new MessageSecurityException(SR.Format(SR.SignatureVerificationFailed)); |
| | | 235 | | } |
| | | 236 | | |
| | 24 | 237 | | return (XmlElement)nodeList[0]; |
| | | 238 | | } |
| | | 239 | | |
| | | 240 | | // Endorsing/supporting signatures must explicitly cover the element |
| | | 241 | | // identified by 'id' (the wsu:Timestamp on the transport-only path, |
| | | 242 | | // or the primary signature id on the message-protected path). If the |
| | | 243 | | // signature carries no Reference whose URI fragment matches the |
| | | 244 | | // expected id, the signature is rejected even when the cryptographic |
| | | 245 | | // CheckSignature succeeded against some other resolved element. |
| | | 246 | | private static void EnsureSignatureCoversExpectedTarget(SignedXml signedXml, string id) |
| | | 247 | | { |
| | 23 | 248 | | if (string.IsNullOrEmpty(id)) |
| | | 249 | | { |
| | 0 | 250 | | throw new MessageSecurityException(SR.Format(SR.SignatureVerificationFailed)); |
| | | 251 | | } |
| | | 252 | | |
| | 23 | 253 | | string expected = "#" + id; |
| | 70 | 254 | | foreach (Reference reference in signedXml.SignedInfo.References) |
| | | 255 | | { |
| | 23 | 256 | | if (string.Equals(reference.Uri, expected, StringComparison.Ordinal)) |
| | | 257 | | { |
| | 22 | 258 | | return; |
| | | 259 | | } |
| | | 260 | | } |
| | | 261 | | |
| | 1 | 262 | | throw new MessageSecurityException(SR.Format(SR.SignatureVerificationFailed)); |
| | 22 | 263 | | } |
| | | 264 | | |
| | | 265 | | protected override async ValueTask<SecurityToken> VerifySignatureAsync(SignedXml signedXml, bool isPrimarySignat |
| | | 266 | | { |
| | 23 | 267 | | SecurityKeyIdentifier securityKeyIdentifier = null; |
| | 23 | 268 | | string keyInfoString = signedXml.Signature.KeyInfo.GetXml().OuterXml; |
| | 23 | 269 | | using (var strReader = new StringReader(keyInfoString)) |
| | | 270 | | { |
| | 23 | 271 | | XmlReader xmlReader = XmlReader.Create(strReader); |
| | 23 | 272 | | securityKeyIdentifier = StandardsManager.SecurityTokenSerializer.ReadKeyIdentifier(xmlReader); |
| | 23 | 273 | | } |
| | 23 | 274 | | if (securityKeyIdentifier == null) |
| | | 275 | | { |
| | 0 | 276 | | throw new Exception("SecurityKeyIdentifier is missing"); |
| | | 277 | | } |
| | | 278 | | |
| | 23 | 279 | | SecurityToken token = await ResolveSignatureTokenAsync(securityKeyIdentifier, resolver, isPrimarySignature); |
| | 23 | 280 | | if (isPrimarySignature) |
| | | 281 | | { |
| | 0 | 282 | | RecordSignatureToken(token); |
| | | 283 | | } |
| | 23 | 284 | | ReadOnlyCollection<SecurityKey> keys = token.SecurityKeys; |
| | 23 | 285 | | SecurityKey securityKey = (keys != null && keys.Count > 0) ? keys[0] : null; |
| | 23 | 286 | | if (securityKey == null) |
| | | 287 | | { |
| | 0 | 288 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException( |
| | 0 | 289 | | SR.Format(SR.UnableToCreateICryptoFromTokenForSignatureVerification, token))); |
| | | 290 | | } |
| | | 291 | | // signedXml.SigningKey = securityKey; |
| | | 292 | | |
| | | 293 | | // signedXml.StartSignatureVerification(securityKey); |
| | | 294 | | // StandardSignedInfo signedInfo = (StandardSignedInfo)signedXml.Signature.SignedInfo; |
| | | 295 | | |
| | | 296 | | // ValidateDigestsOfTargetsInSecurityHeader(signedInfo, this.Timestamp, isPrimarySignature, signatureTarget, |
| | | 297 | | |
| | 23 | 298 | | if (!isPrimarySignature) |
| | | 299 | | { |
| | | 300 | | //TODO securityKey is AsymmetricSecurityKey |
| | | 301 | | //if ((!this.RequireMessageProtection) && (securityKey is AsymmetricSecurityKey) && (this.Version.Addres |
| | | 302 | | //{ |
| | | 303 | | // // For Transport Security using Asymmetric Keys verify that |
| | | 304 | | // // the 'To' header is signed. |
| | | 305 | | // int headerIndex = this.Message.Headers.FindHeader(XD.AddressingDictionary.To.Value, this.Message.V |
| | | 306 | | // if (headerIndex == -1) |
| | | 307 | | // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetS |
| | | 308 | | // XmlDictionaryReader toHeaderReader = this.Message.Headers.GetReaderAtHeader(headerIndex); |
| | | 309 | | // id = toHeaderReader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace) |
| | | 310 | | |
| | | 311 | | // // DevDiv:938534 - We added a flag that allow unsigned headers. If this is set, we do not throw an |
| | | 312 | | // if (LocalAppContextSwitches.AllowUnsignedToHeader) |
| | | 313 | | // { |
| | | 314 | | // // The lack of an id indicates that the sender did not wish to sign the header. We can safely |
| | | 315 | | // // If id is not null, then we need to validate the Digest and ensure signature is valid. The e |
| | | 316 | | // if (id != null) |
| | | 317 | | // { |
| | | 318 | | // signedXml.EnsureDigestValidityIfIdMatches(id, toHeaderReader); |
| | | 319 | | // } |
| | | 320 | | // } |
| | | 321 | | // else |
| | | 322 | | // { |
| | | 323 | | // // default behavior for all platforms |
| | | 324 | | // if (id == null) |
| | | 325 | | // { |
| | | 326 | | // // |
| | | 327 | | // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR. |
| | | 328 | | // } |
| | | 329 | | // signedXml.EnsureDigestValidity(id, toHeaderReader); |
| | | 330 | | // } |
| | | 331 | | //} |
| | | 332 | | // signedXml.CompleteSignatureVerification(); |
| | | 333 | | |
| | 23 | 334 | | SecurityAlgorithmSuite suite = AlgorithmSuite; |
| | 23 | 335 | | AlgorithmSuite.EnsureAcceptableSignatureKeySize(securityKey, token); |
| | 23 | 336 | | AlgorithmSuite.EnsureAcceptableSignatureAlgorithm(securityKey, signedXml.Signature.SignedInfo.SignatureM |
| | 23 | 337 | | EnforceReferenceDigestPolicy(signedXml, suite); |
| | 23 | 338 | | string canonicalizationAlgorithm = suite.DefaultCanonicalizationAlgorithm; |
| | 23 | 339 | | suite.GetSignatureAlgorithmAndKey(token, out string signatureAlgorithm, out SecurityKey signatureKey, ou |
| | 23 | 340 | | GetSigningAlgorithm(signatureKey, signatureAlgorithm, out _signingKey, out AsymmetricAlgorithm asymmetri |
| | 23 | 341 | | if (_signingKey != null) |
| | | 342 | | { |
| | 20 | 343 | | if (!signedXml.CheckSignature(_signingKey)) |
| | | 344 | | { |
| | 0 | 345 | | throw new Exception("Signature not valid."); |
| | | 346 | | } |
| | | 347 | | } |
| | | 348 | | else |
| | | 349 | | { |
| | 3 | 350 | | if (!signedXml.CheckSignature(asymmetricAlgorithm)) |
| | | 351 | | { |
| | 0 | 352 | | throw new Exception("Signature not valid."); |
| | | 353 | | } |
| | | 354 | | } |
| | | 355 | | |
| | 23 | 356 | | EnsureSignatureCoversExpectedTarget(signedXml, id); |
| | | 357 | | } |
| | | 358 | | // this.pendingSignature = signedXml; |
| | | 359 | | |
| | | 360 | | //if (TD.SignatureVerificationSuccessIsEnabled()) |
| | | 361 | | //{ |
| | | 362 | | // TD.SignatureVerificationSuccess(this.EventTraceActivity); |
| | | 363 | | //} |
| | | 364 | | |
| | 22 | 365 | | return token; |
| | 22 | 366 | | } |
| | | 367 | | |
| | | 368 | | private static void EnforceReferenceDigestPolicy(SignedXml signedXml, SecurityAlgorithmSuite suite) |
| | | 369 | | { |
| | 26 | 370 | | if (signedXml?.Signature?.SignedInfo == null) |
| | | 371 | | { |
| | 0 | 372 | | return; |
| | | 373 | | } |
| | | 374 | | |
| | 107 | 375 | | foreach (Reference reference in signedXml.Signature.SignedInfo.References) |
| | | 376 | | { |
| | 28 | 377 | | suite.EnsureAcceptableDigestAlgorithm(reference.DigestMethod); |
| | | 378 | | } |
| | 25 | 379 | | } |
| | | 380 | | |
| | | 381 | | private void GetSigningAlgorithm(SecurityKey signatureKey, string algorithmName, out KeyedHashAlgorithm symmetri |
| | | 382 | | { |
| | 23 | 383 | | symmetricAlgorithm = null; |
| | 23 | 384 | | asymmetricAlgorithm = null; |
| | 23 | 385 | | if (signatureKey is SymmetricSecurityKey symmetricKey) |
| | | 386 | | { |
| | 20 | 387 | | _signingKey = symmetricKey.GetKeyedHashAlgorithm(algorithmName); |
| | 20 | 388 | | if (_signingKey == null) |
| | | 389 | | { |
| | 0 | 390 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( |
| | 0 | 391 | | SR.Format(SR.UnableToCreateKeyedHashAlgorithm, symmetricKey, algorithmName))); |
| | | 392 | | } |
| | | 393 | | } |
| | | 394 | | else |
| | | 395 | | { |
| | 3 | 396 | | if (!(signatureKey is AsymmetricSecurityKey asymmetricKey)) |
| | | 397 | | { |
| | 0 | 398 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( |
| | 0 | 399 | | SR.Format(SR.UnknownICryptoType, _signingKey))); |
| | | 400 | | } |
| | | 401 | | |
| | | 402 | | //On server we validate using Public Key.... (check with Matt) |
| | 3 | 403 | | asymmetricAlgorithm = asymmetricKey.GetAsymmetricAlgorithm(algorithmName, false); |
| | 3 | 404 | | if (asymmetricAlgorithm == null) |
| | | 405 | | { |
| | 0 | 406 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( |
| | 0 | 407 | | SR.Format(SR.UnableToCreateKeyedHashAlgorithm, algorithmName, |
| | 0 | 408 | | asymmetricKey))); |
| | | 409 | | } |
| | | 410 | | } |
| | 23 | 411 | | } |
| | | 412 | | |
| | | 413 | | private async ValueTask<SecurityToken> ResolveSignatureTokenAsync(SecurityKeyIdentifier keyIdentifier, SecurityT |
| | | 414 | | { |
| | 23 | 415 | | TryResolveKeyIdentifier(keyIdentifier, resolver, true, out SecurityToken token); |
| | 23 | 416 | | if (token == null && !isPrimarySignature) |
| | | 417 | | { |
| | | 418 | | // check if there is a rsa key token authenticator |
| | 0 | 419 | | if (keyIdentifier.Count == 1) |
| | | 420 | | { |
| | 0 | 421 | | if (keyIdentifier.TryFind<RsaKeyIdentifierClause>(out RsaKeyIdentifierClause rsaClause)) |
| | | 422 | | { |
| | 0 | 423 | | RsaSecurityTokenAuthenticator rsaAuthenticator = FindAllowedAuthenticator<RsaSecurityTokenAuthen |
| | 0 | 424 | | if (rsaAuthenticator != null) |
| | | 425 | | { |
| | 0 | 426 | | token = new RsaSecurityToken(rsaClause.Rsa); |
| | 0 | 427 | | ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = await rsaAuthenticator.Vali |
| | 0 | 428 | | TokenTracker rsaTracker = GetSupportingTokenTracker(rsaAuthenticator, out SupportingTokenAut |
| | 0 | 429 | | if (rsaTracker == null) |
| | | 430 | | { |
| | 0 | 431 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException |
| | | 432 | | } |
| | 0 | 433 | | rsaTracker.RecordToken(token); |
| | 0 | 434 | | SecurityTokenAuthorizationPoliciesMapping.Add(token, authorizationPolicies); |
| | | 435 | | } |
| | 0 | 436 | | } |
| | | 437 | | } |
| | | 438 | | } |
| | 23 | 439 | | if (token == null) |
| | | 440 | | { |
| | 0 | 441 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException( |
| | 0 | 442 | | SR.Format(SR.UnableToResolveKeyInfoForVerifyingSignature, keyIdentifier, resolver))); |
| | | 443 | | } |
| | 23 | 444 | | return token; |
| | 23 | 445 | | } |
| | | 446 | | |
| | | 447 | | protected static bool TryResolveKeyIdentifier( |
| | | 448 | | SecurityKeyIdentifier keyIdentifier, SecurityTokenResolver resolver, bool isFromSignature, out SecurityToken to |
| | | 449 | | { |
| | 23 | 450 | | if (keyIdentifier == null) |
| | | 451 | | { |
| | 0 | 452 | | if (isFromSignature) |
| | | 453 | | { |
| | 0 | 454 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.Format(SR. |
| | | 455 | | } |
| | | 456 | | else |
| | | 457 | | { |
| | 0 | 458 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.Format(SR. |
| | | 459 | | } |
| | | 460 | | } |
| | 23 | 461 | | return resolver.TryResolveToken(keyIdentifier, out token); |
| | | 462 | | } |
| | | 463 | | protected override bool TryDeleteReferenceListEntry(string id) |
| | | 464 | | { |
| | 0 | 465 | | throw new NotImplementedException(); |
| | | 466 | | } |
| | | 467 | | } |
| | | 468 | | } |