WSSecurityOneDotZeroReceiveSecurityHeader.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. //----------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.IdentityModel.Policy;
  9. using System.IdentityModel.Selectors;
  10. using System.IdentityModel.Tokens;
  11. using System.Runtime;
  12. using System.Runtime.Diagnostics;
  13. using System.Security.Cryptography;
  14. using System.ServiceModel;
  15. using System.ServiceModel.Channels;
  16. using System.ServiceModel.Description;
  17. using System.ServiceModel.Diagnostics;
  18. using System.ServiceModel.Diagnostics.Application;
  19. using System.ServiceModel.Security.Tokens;
  20. using System.Xml;
  21. using Reference = System.IdentityModel.Reference;
  22. using SignedInfo = System.IdentityModel.SignedInfo;
  23. using SignedXml = System.IdentityModel.SignedXml;
  24. using StandardSignedInfo = System.IdentityModel.StandardSignedInfo;
  25. class WSSecurityOneDotZeroReceiveSecurityHeader : ReceiveSecurityHeader
  26. {
  27. WrappedKeySecurityToken pendingDecryptionToken;
  28. ReferenceList pendingReferenceList;
  29. SignedXml pendingSignature;
  30. List<string> earlyDecryptedDataReferences;
  31. public WSSecurityOneDotZeroReceiveSecurityHeader(Message message, string actor, bool mustUnderstand, bool relay,
  32. SecurityStandardsManager standardsManager,
  33. SecurityAlgorithmSuite algorithmSuite,
  34. int headerIndex,
  35. MessageDirection transferDirection)
  36. : base(message, actor, mustUnderstand, relay, standardsManager, algorithmSuite, headerIndex, transferDirection)
  37. {
  38. }
  39. protected static SymmetricAlgorithm CreateDecryptionAlgorithm(SecurityToken token, string encryptionMethod, SecurityAlgorithmSuite suite)
  40. {
  41. if (encryptionMethod == null)
  42. {
  43. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
  44. SR.GetString(SR.EncryptionMethodMissingInEncryptedData)));
  45. }
  46. suite.EnsureAcceptableEncryptionAlgorithm(encryptionMethod);
  47. SymmetricSecurityKey symmetricSecurityKey = SecurityUtils.GetSecurityKey<SymmetricSecurityKey>(token);
  48. if (symmetricSecurityKey == null)
  49. {
  50. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
  51. SR.GetString(SR.TokenCannotCreateSymmetricCrypto, token)));
  52. }
  53. suite.EnsureAcceptableDecryptionSymmetricKeySize(symmetricSecurityKey, token);
  54. SymmetricAlgorithm algorithm = symmetricSecurityKey.GetSymmetricAlgorithm(encryptionMethod);
  55. if (algorithm == null)
  56. {
  57. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
  58. SR.GetString(SR.UnableToCreateSymmetricAlgorithmFromToken, encryptionMethod)));
  59. }
  60. return algorithm;
  61. }
  62. void DecryptBody(XmlDictionaryReader bodyContentReader, SecurityToken token)
  63. {
  64. EncryptedData bodyXml = new EncryptedData();
  65. bodyXml.ShouldReadXmlReferenceKeyInfoClause = this.MessageDirection == MessageDirection.Output;
  66. bodyXml.SecurityTokenSerializer = this.StandardsManager.SecurityTokenSerializer;
  67. bodyXml.ReadFrom(bodyContentReader, MaxReceivedMessageSize);
  68. if (!bodyContentReader.EOF && bodyContentReader.NodeType != XmlNodeType.EndElement)
  69. {
  70. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.BadEncryptedBody)));
  71. }
  72. if (token == null)
  73. {
  74. token = ResolveKeyIdentifier(bodyXml.KeyIdentifier, this.PrimaryTokenResolver, false);
  75. }
  76. RecordEncryptionToken(token);
  77. using (SymmetricAlgorithm algorithm = CreateDecryptionAlgorithm(token, bodyXml.EncryptionMethod, this.AlgorithmSuite))
  78. {
  79. bodyXml.SetUpDecryption(algorithm);
  80. this.SecurityVerifiedMessage.SetDecryptedBody(bodyXml.GetDecryptedBuffer());
  81. }
  82. }
  83. protected virtual DecryptedHeader DecryptHeader(XmlDictionaryReader reader, WrappedKeySecurityToken wrappedKeyToken)
  84. {
  85. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  86. new MessageSecurityException(SR.GetString(SR.HeaderDecryptionNotSupportedInWsSecurityJan2004)));
  87. }
  88. protected override byte[] DecryptSecurityHeaderElement(
  89. EncryptedData encryptedData, WrappedKeySecurityToken wrappedKeyToken, out SecurityToken encryptionToken)
  90. {
  91. if ((encryptedData.KeyIdentifier != null) || (wrappedKeyToken == null))
  92. {
  93. // The EncryptedData might have a KeyInfo inside it. Try resolving the SecurityKeyIdentifier.
  94. encryptionToken = ResolveKeyIdentifier(encryptedData.KeyIdentifier, this.CombinedPrimaryTokenResolver, false);
  95. if (wrappedKeyToken != null && wrappedKeyToken.ReferenceList != null && encryptedData.HasId && wrappedKeyToken.ReferenceList.ContainsReferredId(encryptedData.Id) && (wrappedKeyToken != encryptionToken))
  96. {
  97. // We have a EncryptedKey with a ReferenceList inside it. This would mean that
  98. // all the EncryptedData pointed by the ReferenceList should be encrypted only
  99. // by this key. The individual EncryptedData elements if containing a KeyInfo
  100. // clause should point back to the same EncryptedKey token.
  101. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.EncryptedKeyWasNotEncryptedWithTheRequiredEncryptingToken, wrappedKeyToken)));
  102. }
  103. }
  104. else
  105. {
  106. encryptionToken = wrappedKeyToken;
  107. }
  108. using (SymmetricAlgorithm algorithm = CreateDecryptionAlgorithm(encryptionToken, encryptedData.EncryptionMethod, this.AlgorithmSuite))
  109. {
  110. encryptedData.SetUpDecryption(algorithm);
  111. return encryptedData.GetDecryptedBuffer();
  112. }
  113. }
  114. protected override WrappedKeySecurityToken DecryptWrappedKey(XmlDictionaryReader reader)
  115. {
  116. if (TD.WrappedKeyDecryptionStartIsEnabled())
  117. {
  118. TD.WrappedKeyDecryptionStart(this.EventTraceActivity);
  119. }
  120. WrappedKeySecurityToken token = (WrappedKeySecurityToken)this.StandardsManager.SecurityTokenSerializer.ReadToken(
  121. reader, this.PrimaryTokenResolver);
  122. this.AlgorithmSuite.EnsureAcceptableKeyWrapAlgorithm(token.WrappingAlgorithm, token.WrappingSecurityKey is AsymmetricSecurityKey);
  123. if (TD.WrappedKeyDecryptionSuccessIsEnabled())
  124. {
  125. TD.WrappedKeyDecryptionSuccess(this.EventTraceActivity);
  126. }
  127. return token;
  128. }
  129. bool EnsureDigestValidityIfIdMatches(
  130. SignedInfo signedInfo,
  131. string id, XmlDictionaryReader reader, bool doSoapAttributeChecks,
  132. MessagePartSpecification signatureParts, MessageHeaderInfo info, bool checkForTokensAtHeaders)
  133. {
  134. if (signedInfo == null)
  135. {
  136. return false;
  137. }
  138. if (doSoapAttributeChecks)
  139. {
  140. VerifySoapAttributeMatchForHeader(info, signatureParts, reader);
  141. }
  142. bool signed = false;
  143. bool isRecognizedSecurityToken = checkForTokensAtHeaders && this.StandardsManager.SecurityTokenSerializer.CanReadToken(reader);
  144. try
  145. {
  146. signed = signedInfo.EnsureDigestValidityIfIdMatches(id, reader);
  147. }
  148. catch (CryptographicException exception)
  149. {
  150. //
  151. // Wrap the crypto exception here so that the perf couter can be updated correctly
  152. //
  153. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.FailedSignatureVerification), exception));
  154. }
  155. if (signed && isRecognizedSecurityToken)
  156. {
  157. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.SecurityTokenFoundOutsideSecurityHeader, info.Namespace, info.Name)));
  158. }
  159. return signed;
  160. }
  161. protected override void ExecuteMessageProtectionPass(bool hasAtLeastOneSupportingTokenExpectedToBeSigned)
  162. {
  163. SignatureTargetIdManager idManager = this.StandardsManager.IdManager;
  164. MessagePartSpecification encryptionParts = this.RequiredEncryptionParts ?? MessagePartSpecification.NoParts;
  165. MessagePartSpecification signatureParts = this.RequiredSignatureParts ?? MessagePartSpecification.NoParts;
  166. bool checkForTokensAtHeaders = hasAtLeastOneSupportingTokenExpectedToBeSigned;
  167. bool doSoapAttributeChecks = !signatureParts.IsBodyIncluded;
  168. bool encryptBeforeSign = this.EncryptBeforeSignMode;
  169. SignedInfo signedInfo = this.pendingSignature != null ? this.pendingSignature.Signature.SignedInfo : null;
  170. SignatureConfirmations signatureConfirmations = this.GetSentSignatureConfirmations();
  171. if (signatureConfirmations != null && signatureConfirmations.Count > 0 && signatureConfirmations.IsMarkedForEncryption)
  172. {
  173. // If Signature Confirmations are encrypted then the signature should
  174. // be encrypted as well.
  175. this.VerifySignatureEncryption();
  176. }
  177. MessageHeaders headers = this.SecurityVerifiedMessage.Headers;
  178. XmlDictionaryReader reader = this.SecurityVerifiedMessage.GetReaderAtFirstHeader();
  179. bool atLeastOneHeaderOrBodyEncrypted = false;
  180. for (int i = 0; i < headers.Count; i++)
  181. {
  182. if (reader.NodeType != XmlNodeType.Element)
  183. {
  184. reader.MoveToContent();
  185. }
  186. if (i == this.HeaderIndex)
  187. {
  188. reader.Skip();
  189. continue;
  190. }
  191. bool isHeaderEncrypted = false;
  192. string id = idManager.ExtractId(reader);
  193. if (id != null)
  194. {
  195. isHeaderEncrypted = TryDeleteReferenceListEntry(id);
  196. }
  197. if (!isHeaderEncrypted && reader.IsStartElement(SecurityXXX2005Strings.EncryptedHeader, SecurityXXX2005Strings.Namespace))
  198. {
  199. XmlDictionaryReader localreader = headers.GetReaderAtHeader(i);
  200. localreader.ReadStartElement(SecurityXXX2005Strings.EncryptedHeader, SecurityXXX2005Strings.Namespace);
  201. if (localreader.IsStartElement(EncryptedData.ElementName, XD.XmlEncryptionDictionary.Namespace))
  202. {
  203. string encryptedDataId = localreader.GetAttribute(XD.XmlEncryptionDictionary.Id, null);
  204. if (encryptedDataId != null && TryDeleteReferenceListEntry(encryptedDataId))
  205. {
  206. isHeaderEncrypted = true;
  207. }
  208. }
  209. }
  210. this.ElementManager.VerifyUniquenessAndSetHeaderId(id, i);
  211. MessageHeaderInfo info = headers[i];
  212. if (!isHeaderEncrypted && encryptionParts.IsHeaderIncluded(info.Name, info.Namespace))
  213. {
  214. this.SecurityVerifiedMessage.OnUnencryptedPart(info.Name, info.Namespace);
  215. }
  216. bool headerSigned;
  217. if ((!isHeaderEncrypted || encryptBeforeSign) && id != null)
  218. {
  219. headerSigned = EnsureDigestValidityIfIdMatches(signedInfo, id, reader, doSoapAttributeChecks, signatureParts, info, checkForTokensAtHeaders);
  220. }
  221. else
  222. {
  223. headerSigned = false;
  224. }
  225. if (isHeaderEncrypted)
  226. {
  227. XmlDictionaryReader decryptionReader = headerSigned ? headers.GetReaderAtHeader(i) : reader;
  228. DecryptedHeader decryptedHeader = DecryptHeader(decryptionReader, this.pendingDecryptionToken);
  229. info = decryptedHeader;
  230. id = decryptedHeader.Id;
  231. this.ElementManager.VerifyUniquenessAndSetDecryptedHeaderId(id, i);
  232. headers.ReplaceAt(i, decryptedHeader);
  233. if (!ReferenceEquals(decryptionReader, reader))
  234. {
  235. decryptionReader.Close();
  236. }
  237. if (!encryptBeforeSign && id != null)
  238. {
  239. XmlDictionaryReader decryptedHeaderReader = decryptedHeader.GetHeaderReader();
  240. headerSigned = EnsureDigestValidityIfIdMatches(signedInfo, id, decryptedHeaderReader, doSoapAttributeChecks, signatureParts, info, checkForTokensAtHeaders);
  241. decryptedHeaderReader.Close();
  242. }
  243. }
  244. if (!headerSigned && signatureParts.IsHeaderIncluded(info.Name, info.Namespace))
  245. {
  246. this.SecurityVerifiedMessage.OnUnsignedPart(info.Name, info.Namespace);
  247. }
  248. if (headerSigned && isHeaderEncrypted)
  249. {
  250. // We have a header that is signed and encrypted. So the accompanying primary signature
  251. // should be encrypted as well.
  252. this.VerifySignatureEncryption();
  253. }
  254. if (isHeaderEncrypted && !headerSigned)
  255. {
  256. // We require all encrypted headers (outside the security header) to be signed.
  257. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.EncryptedHeaderNotSigned, info.Name, info.Namespace)));
  258. }
  259. if (!headerSigned && !isHeaderEncrypted)
  260. {
  261. reader.Skip();
  262. }
  263. atLeastOneHeaderOrBodyEncrypted |= isHeaderEncrypted;
  264. }
  265. reader.ReadEndElement();
  266. if (reader.NodeType != XmlNodeType.Element)
  267. {
  268. reader.MoveToContent();
  269. }
  270. string bodyId = idManager.ExtractId(reader);
  271. this.ElementManager.VerifyUniquenessAndSetBodyId(bodyId);
  272. this.SecurityVerifiedMessage.SetBodyPrefixAndAttributes(reader);
  273. bool expectBodyEncryption = encryptionParts.IsBodyIncluded || HasPendingDecryptionItem();
  274. bool bodySigned;
  275. if ((!expectBodyEncryption || encryptBeforeSign) && bodyId != null)
  276. {
  277. bodySigned = EnsureDigestValidityIfIdMatches(signedInfo, bodyId, reader, false, null, null, false);
  278. }
  279. else
  280. {
  281. bodySigned = false;
  282. }
  283. bool bodyEncrypted;
  284. if (expectBodyEncryption)
  285. {
  286. XmlDictionaryReader bodyReader = bodySigned ? this.SecurityVerifiedMessage.CreateFullBodyReader() : reader;
  287. bodyReader.ReadStartElement();
  288. string bodyContentId = idManager.ExtractId(bodyReader);
  289. this.ElementManager.VerifyUniquenessAndSetBodyContentId(bodyContentId);
  290. bodyEncrypted = bodyContentId != null && TryDeleteReferenceListEntry(bodyContentId);
  291. if (bodyEncrypted)
  292. {
  293. DecryptBody(bodyReader, this.pendingDecryptionToken);
  294. }
  295. if (!ReferenceEquals(bodyReader, reader))
  296. {
  297. bodyReader.Close();
  298. }
  299. if (!encryptBeforeSign && signedInfo != null && signedInfo.HasUnverifiedReference(bodyId))
  300. {
  301. bodyReader = this.SecurityVerifiedMessage.CreateFullBodyReader();
  302. bodySigned = EnsureDigestValidityIfIdMatches(signedInfo, bodyId, bodyReader, false, null, null, false);
  303. bodyReader.Close();
  304. }
  305. }
  306. else
  307. {
  308. bodyEncrypted = false;
  309. }
  310. if (bodySigned && bodyEncrypted)
  311. {
  312. this.VerifySignatureEncryption();
  313. }
  314. reader.Close();
  315. if (this.pendingSignature != null)
  316. {
  317. this.pendingSignature.CompleteSignatureVerification();
  318. this.pendingSignature = null;
  319. }
  320. this.pendingDecryptionToken = null;
  321. atLeastOneHeaderOrBodyEncrypted |= bodyEncrypted;
  322. if (!bodySigned && signatureParts.IsBodyIncluded)
  323. {
  324. this.SecurityVerifiedMessage.OnUnsignedPart(XD.MessageDictionary.Body.Value, this.Version.Envelope.Namespace);
  325. }
  326. if (!bodyEncrypted && encryptionParts.IsBodyIncluded)
  327. {
  328. this.SecurityVerifiedMessage.OnUnencryptedPart(XD.MessageDictionary.Body.Value, this.Version.Envelope.Namespace);
  329. }
  330. this.SecurityVerifiedMessage.OnMessageProtectionPassComplete(atLeastOneHeaderOrBodyEncrypted);
  331. }
  332. protected override bool IsReaderAtEncryptedData(XmlDictionaryReader reader)
  333. {
  334. bool encrypted = reader.IsStartElement(EncryptedData.ElementName, XD.XmlEncryptionDictionary.Namespace);
  335. if (encrypted == true)
  336. this.HasAtLeastOneItemInsideSecurityHeaderEncrypted = true;
  337. return encrypted;
  338. }
  339. protected override bool IsReaderAtEncryptedKey(XmlDictionaryReader reader)
  340. {
  341. return reader.IsStartElement(EncryptedKey.ElementName, XD.XmlEncryptionDictionary.Namespace);
  342. }
  343. protected override bool IsReaderAtReferenceList(XmlDictionaryReader reader)
  344. {
  345. return reader.IsStartElement(ReferenceList.ElementName, ReferenceList.NamespaceUri);
  346. }
  347. protected override bool IsReaderAtSignature(XmlDictionaryReader reader)
  348. {
  349. return reader.IsStartElement(XD.XmlSignatureDictionary.Signature, XD.XmlSignatureDictionary.Namespace);
  350. }
  351. protected override bool IsReaderAtSecurityTokenReference(XmlDictionaryReader reader)
  352. {
  353. return reader.IsStartElement(XD.SecurityJan2004Dictionary.SecurityTokenReference, XD.SecurityJan2004Dictionary.Namespace);
  354. }
  355. protected override void ProcessReferenceListCore(ReferenceList referenceList, WrappedKeySecurityToken wrappedKeyToken)
  356. {
  357. this.pendingReferenceList = referenceList;
  358. this.pendingDecryptionToken = wrappedKeyToken;
  359. }
  360. protected override ReferenceList ReadReferenceListCore(XmlDictionaryReader reader)
  361. {
  362. ReferenceList referenceList = new ReferenceList();
  363. referenceList.ReadFrom(reader);
  364. return referenceList;
  365. }
  366. protected override EncryptedData ReadSecurityHeaderEncryptedItem(XmlDictionaryReader reader, bool readXmlreferenceKeyInfoClause)
  367. {
  368. EncryptedData encryptedData = new EncryptedData();
  369. encryptedData.ShouldReadXmlReferenceKeyInfoClause = readXmlreferenceKeyInfoClause;
  370. encryptedData.SecurityTokenSerializer = this.StandardsManager.SecurityTokenSerializer;
  371. encryptedData.ReadFrom(reader);
  372. return encryptedData;
  373. }
  374. protected override SignedXml ReadSignatureCore(XmlDictionaryReader signatureReader)
  375. {
  376. SignedXml signedXml = new SignedXml(ServiceModelDictionaryManager.Instance, this.StandardsManager.SecurityTokenSerializer);
  377. signedXml.Signature.SignedInfo.ResourcePool = this.ResourcePool;
  378. signedXml.ReadFrom(signatureReader);
  379. return signedXml;
  380. }
  381. protected static bool TryResolveKeyIdentifier(
  382. SecurityKeyIdentifier keyIdentifier, SecurityTokenResolver resolver, bool isFromSignature, out SecurityToken token)
  383. {
  384. if (keyIdentifier == null)
  385. {
  386. if (isFromSignature)
  387. {
  388. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoKeyInfoInSignatureToFindVerificationToken)));
  389. }
  390. else
  391. {
  392. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoKeyInfoInEncryptedItemToFindDecryptingToken)));
  393. }
  394. }
  395. return resolver.TryResolveToken(keyIdentifier, out token);
  396. }
  397. protected static SecurityToken ResolveKeyIdentifier(SecurityKeyIdentifier keyIdentifier, SecurityTokenResolver resolver, bool isFromSignature)
  398. {
  399. SecurityToken token;
  400. if (!TryResolveKeyIdentifier(keyIdentifier, resolver, isFromSignature, out token))
  401. {
  402. if (isFromSignature)
  403. {
  404. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
  405. SR.GetString(SR.UnableToResolveKeyInfoForVerifyingSignature, keyIdentifier, resolver)));
  406. }
  407. else
  408. {
  409. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
  410. SR.GetString(SR.UnableToResolveKeyInfoForDecryption, keyIdentifier, resolver)));
  411. }
  412. }
  413. return token;
  414. }
  415. SecurityToken ResolveSignatureToken(SecurityKeyIdentifier keyIdentifier, SecurityTokenResolver resolver, bool isPrimarySignature)
  416. {
  417. SecurityToken token;
  418. TryResolveKeyIdentifier(keyIdentifier, resolver, true, out token);
  419. if (token == null && !isPrimarySignature)
  420. {
  421. // check if there is a rsa key token authenticator
  422. if (keyIdentifier.Count == 1)
  423. {
  424. RsaKeyIdentifierClause rsaClause;
  425. if (keyIdentifier.TryFind<RsaKeyIdentifierClause>(out rsaClause))
  426. {
  427. RsaSecurityTokenAuthenticator rsaAuthenticator = FindAllowedAuthenticator<RsaSecurityTokenAuthenticator>(false);
  428. if (rsaAuthenticator != null)
  429. {
  430. token = new RsaSecurityToken(rsaClause.Rsa);
  431. ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies = rsaAuthenticator.ValidateToken(token);
  432. SupportingTokenAuthenticatorSpecification spec;
  433. TokenTracker rsaTracker = GetSupportingTokenTracker(rsaAuthenticator, out spec);
  434. if (rsaTracker == null)
  435. {
  436. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.UnknownTokenAuthenticatorUsedInTokenProcessing, rsaAuthenticator)));
  437. }
  438. rsaTracker.RecordToken(token);
  439. SecurityTokenAuthorizationPoliciesMapping.Add(token, authorizationPolicies);
  440. }
  441. }
  442. }
  443. }
  444. if (token == null)
  445. {
  446. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
  447. SR.GetString(SR.UnableToResolveKeyInfoForVerifyingSignature, keyIdentifier, resolver)));
  448. }
  449. return token;
  450. }
  451. protected override void ReadSecurityTokenReference(XmlDictionaryReader reader)
  452. {
  453. string strId = reader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace);
  454. SecurityKeyIdentifierClause strClause = this.StandardsManager.SecurityTokenSerializer.ReadKeyIdentifierClause(reader);
  455. if (String.IsNullOrEmpty(strClause.Id))
  456. {
  457. strClause.Id = strId;
  458. }
  459. if (!String.IsNullOrEmpty(strClause.Id))
  460. {
  461. this.ElementManager.AppendSecurityTokenReference(strClause, strClause.Id);
  462. }
  463. }
  464. bool HasPendingDecryptionItem()
  465. {
  466. return this.pendingReferenceList != null && this.pendingReferenceList.DataReferenceCount > 0;
  467. }
  468. protected override bool TryDeleteReferenceListEntry(string id)
  469. {
  470. return this.pendingReferenceList != null && this.pendingReferenceList.TryRemoveReferredId(id);
  471. }
  472. protected override void EnsureDecryptionComplete()
  473. {
  474. if (this.earlyDecryptedDataReferences != null)
  475. {
  476. for (int i = 0; i < this.earlyDecryptedDataReferences.Count; i++)
  477. {
  478. if (!TryDeleteReferenceListEntry(this.earlyDecryptedDataReferences[i]))
  479. {
  480. throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.UnexpectedEncryptedElementInSecurityHeader)), this.Message);
  481. }
  482. }
  483. }
  484. if (HasPendingDecryptionItem())
  485. {
  486. throw TraceUtility.ThrowHelperError(
  487. new MessageSecurityException(SR.GetString(SR.UnableToResolveDataReference, this.pendingReferenceList.GetReferredId(0))), this.Message);
  488. }
  489. }
  490. protected override void OnDecryptionOfSecurityHeaderItemRequiringReferenceListEntry(string id)
  491. {
  492. if (!TryDeleteReferenceListEntry(id))
  493. {
  494. if (this.earlyDecryptedDataReferences == null)
  495. {
  496. this.earlyDecryptedDataReferences = new List<string>(4);
  497. }
  498. this.earlyDecryptedDataReferences.Add(id);
  499. }
  500. }
  501. protected override SecurityToken VerifySignature(SignedXml signedXml, bool isPrimarySignature,
  502. SecurityHeaderTokenResolver resolver, object signatureTarget, string id)
  503. {
  504. if (TD.SignatureVerificationStartIsEnabled())
  505. {
  506. TD.SignatureVerificationStart(this.EventTraceActivity);
  507. }
  508. SecurityToken token = ResolveSignatureToken(signedXml.Signature.KeyIdentifier, resolver, isPrimarySignature);
  509. if (isPrimarySignature)
  510. {
  511. RecordSignatureToken(token);
  512. }
  513. ReadOnlyCollection<SecurityKey> keys = token.SecurityKeys;
  514. SecurityKey securityKey = (keys != null && keys.Count > 0) ? keys[0] : null;
  515. if (securityKey == null)
  516. {
  517. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
  518. SR.GetString(SR.UnableToCreateICryptoFromTokenForSignatureVerification, token)));
  519. }
  520. this.AlgorithmSuite.EnsureAcceptableSignatureKeySize(securityKey, token);
  521. this.AlgorithmSuite.EnsureAcceptableSignatureAlgorithm(securityKey, signedXml.Signature.SignedInfo.SignatureMethod);
  522. signedXml.StartSignatureVerification(securityKey);
  523. StandardSignedInfo signedInfo = (StandardSignedInfo)signedXml.Signature.SignedInfo;
  524. ValidateDigestsOfTargetsInSecurityHeader(signedInfo, this.Timestamp, isPrimarySignature, signatureTarget, id);
  525. if (!isPrimarySignature)
  526. {
  527. if ((!this.RequireMessageProtection) && (securityKey is AsymmetricSecurityKey) && (this.Version.Addressing != AddressingVersion.None))
  528. {
  529. // For Transport Security using Asymmetric Keys verify that
  530. // the 'To' header is signed.
  531. int headerIndex = this.Message.Headers.FindHeader(XD.AddressingDictionary.To.Value, this.Message.Version.Addressing.Namespace);
  532. if (headerIndex == -1)
  533. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TransportSecuredMessageMissingToHeader)));
  534. XmlDictionaryReader toHeaderReader = this.Message.Headers.GetReaderAtHeader(headerIndex);
  535. id = toHeaderReader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace);
  536. if (id == null)
  537. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.UnsignedToHeaderInTransportSecuredMessage)));
  538. signedXml.EnsureDigestValidity(id, toHeaderReader);
  539. }
  540. signedXml.CompleteSignatureVerification();
  541. return token;
  542. }
  543. this.pendingSignature = signedXml;
  544. if (TD.SignatureVerificationSuccessIsEnabled())
  545. {
  546. TD.SignatureVerificationSuccess(this.EventTraceActivity);
  547. }
  548. return token;
  549. }
  550. void ValidateDigestsOfTargetsInSecurityHeader(StandardSignedInfo signedInfo, SecurityTimestamp timestamp, bool isPrimarySignature, object signatureTarget, string id)
  551. {
  552. Fx.Assert(!isPrimarySignature || (isPrimarySignature && (signatureTarget == null)), "For primary signature we try to validate all the references.");
  553. for (int i = 0; i < signedInfo.ReferenceCount; i++)
  554. {
  555. Reference reference = signedInfo[i];
  556. this.AlgorithmSuite.EnsureAcceptableDigestAlgorithm(reference.DigestMethod);
  557. string referredId = reference.ExtractReferredId();
  558. if (isPrimarySignature || (id == referredId))
  559. {
  560. if (timestamp != null && timestamp.Id == referredId && !reference.TransformChain.NeedsInclusiveContext &&
  561. timestamp.DigestAlgorithm == reference.DigestMethod && timestamp.GetDigest() != null)
  562. {
  563. reference.EnsureDigestValidity(referredId, timestamp.GetDigest());
  564. this.ElementManager.SetTimestampSigned(referredId);
  565. }
  566. else
  567. {
  568. if (signatureTarget != null)
  569. reference.EnsureDigestValidity(id, signatureTarget);
  570. else
  571. {
  572. int tokenIndex = -1;
  573. XmlDictionaryReader reader = null;
  574. if (reference.IsStrTranform())
  575. {
  576. if (this.ElementManager.TryGetTokenElementIndexFromStrId(referredId, out tokenIndex))
  577. {
  578. ReceiveSecurityHeaderEntry entry;
  579. this.ElementManager.GetElementEntry(tokenIndex, out entry);
  580. bool isSignedToken = (entry.bindingMode == ReceiveSecurityHeaderBindingModes.Signed)
  581. || (entry.bindingMode == ReceiveSecurityHeaderBindingModes.SignedEndorsing);
  582. // This means it is a protected(signed)primary token.
  583. if (!this.ElementManager.IsPrimaryTokenSigned)
  584. {
  585. this.ElementManager.IsPrimaryTokenSigned = entry.bindingMode == ReceiveSecurityHeaderBindingModes.Primary &&
  586. entry.elementCategory == ReceiveSecurityHeaderElementCategory.Token;
  587. }
  588. this.ElementManager.SetSigned(tokenIndex);
  589. // We pass true if it is a signed supporting token, signed primary token or a SignedEndorsing token. We pass false if it is a SignedEncrypted Token.
  590. reader = this.ElementManager.GetReader(tokenIndex, isSignedToken);
  591. }
  592. }
  593. else
  594. reader = this.ElementManager.GetSignatureVerificationReader(referredId, this.EncryptBeforeSignMode);
  595. if (reader != null)
  596. {
  597. reference.EnsureDigestValidity(referredId, reader);
  598. reader.Close();
  599. }
  600. }
  601. }
  602. if (!isPrimarySignature)
  603. {
  604. // We were given an id to verify and we have verified it. So just break out
  605. // of the loop.
  606. break;
  607. }
  608. }
  609. }
  610. // This check makes sure that if RequireSignedPrimaryToken is true (ProtectTokens is enabled on sbe) then the incoming message
  611. // should have the primary signature over the primary(signing)token.
  612. if (isPrimarySignature && this.RequireSignedPrimaryToken && !this.ElementManager.IsPrimaryTokenSigned)
  613. {
  614. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.SupportingTokenIsNotSigned, new IssuedSecurityTokenParameters())));
  615. }
  616. // NOTE: On both client and server side, WCF quietly consumes protected tokens even if protect token is not enabled on sbe.
  617. // To change this behaviour add another check below and throw appropriate exception message.
  618. }
  619. void VerifySoapAttributeMatchForHeader(MessageHeaderInfo info, MessagePartSpecification signatureParts, XmlDictionaryReader reader)
  620. {
  621. if (!signatureParts.IsHeaderIncluded(info.Name, info.Namespace))
  622. {
  623. return;
  624. }
  625. EnvelopeVersion currentVersion = this.Version.Envelope;
  626. EnvelopeVersion otherVersion = currentVersion == EnvelopeVersion.Soap11 ? EnvelopeVersion.Soap12 : EnvelopeVersion.Soap11;
  627. bool presentInCurrentVersion;
  628. bool presentInOtherVersion;
  629. presentInCurrentVersion = null != reader.GetAttribute(XD.MessageDictionary.MustUnderstand, currentVersion.DictionaryNamespace);
  630. presentInOtherVersion = null != reader.GetAttribute(XD.MessageDictionary.MustUnderstand, otherVersion.DictionaryNamespace);
  631. if (presentInOtherVersion && !presentInCurrentVersion)
  632. {
  633. throw TraceUtility.ThrowHelperError(
  634. new MessageSecurityException(SR.GetString(
  635. SR.InvalidAttributeInSignedHeader, info.Name, info.Namespace,
  636. XD.MessageDictionary.MustUnderstand, otherVersion.DictionaryNamespace,
  637. XD.MessageDictionary.MustUnderstand, currentVersion.DictionaryNamespace)), this.SecurityVerifiedMessage);
  638. }
  639. presentInCurrentVersion = null != reader.GetAttribute(currentVersion.DictionaryActor, currentVersion.DictionaryNamespace);
  640. presentInOtherVersion = null != reader.GetAttribute(otherVersion.DictionaryActor, otherVersion.DictionaryNamespace);
  641. if (presentInOtherVersion && !presentInCurrentVersion)
  642. {
  643. throw TraceUtility.ThrowHelperError(
  644. new MessageSecurityException(SR.GetString(
  645. SR.InvalidAttributeInSignedHeader, info.Name, info.Namespace,
  646. otherVersion.DictionaryActor, otherVersion.DictionaryNamespace,
  647. currentVersion.DictionaryActor, currentVersion.DictionaryNamespace)), this.SecurityVerifiedMessage);
  648. }
  649. }
  650. }
  651. }