MessageSecurityProtocol.cs 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  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.ServiceModel;
  13. using System.ServiceModel.Channels;
  14. using System.ServiceModel.Diagnostics;
  15. using System.ServiceModel.Description;
  16. using System.ServiceModel.Security.Tokens;
  17. abstract class MessageSecurityProtocol : SecurityProtocol
  18. {
  19. readonly MessageSecurityProtocolFactory factory;
  20. SecurityToken identityVerifiedToken; // verified for the readonly target
  21. protected MessageSecurityProtocol(MessageSecurityProtocolFactory factory, EndpointAddress target, Uri via)
  22. : base(factory, target, via)
  23. {
  24. this.factory = factory;
  25. }
  26. // Protocols that have more than one active, identity checked
  27. // token at any time should override this property and return
  28. // false
  29. protected virtual bool CacheIdentityCheckResultForToken
  30. {
  31. get { return true; }
  32. }
  33. protected virtual bool DoAutomaticEncryptionMatch
  34. {
  35. get { return true; }
  36. }
  37. protected virtual bool PerformIncomingAndOutgoingMessageExpectationChecks
  38. {
  39. get { return true; }
  40. }
  41. protected bool RequiresIncomingSecurityProcessing(Message message)
  42. {
  43. // if we are receiveing a response that has no security that we should accept this AND no security header exists
  44. // then it is OK to skip the header.
  45. if (this.factory.ActAsInitiator
  46. && this.factory.SecurityBindingElement.EnableUnsecuredResponse
  47. && !this.factory.StandardsManager.SecurityVersion.DoesMessageContainSecurityHeader(message))
  48. return false;
  49. bool requiresAppSecurity = this.factory.RequireIntegrity || this.factory.RequireConfidentiality || this.factory.DetectReplays;
  50. return requiresAppSecurity || factory.ExpectSupportingTokens;
  51. }
  52. protected bool RequiresOutgoingSecurityProcessing
  53. {
  54. get
  55. {
  56. // If were are the listener, don't apply security if the flag is set
  57. if (!this.factory.ActAsInitiator && this.factory.SecurityBindingElement.EnableUnsecuredResponse)
  58. return false;
  59. bool requiresAppSecurity = this.factory.ApplyIntegrity || this.factory.ApplyConfidentiality || this.factory.AddTimestamp;
  60. return requiresAppSecurity || factory.ExpectSupportingTokens;
  61. }
  62. }
  63. protected MessageSecurityProtocolFactory MessageSecurityProtocolFactory
  64. {
  65. get { return this.factory; }
  66. }
  67. public override IAsyncResult BeginSecureOutgoingMessage(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  68. {
  69. try
  70. {
  71. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  72. ValidateOutgoingState(message);
  73. if (!this.RequiresOutgoingSecurityProcessing && message.Properties.Security == null)
  74. {
  75. return new CompletedAsyncResult<Message>(message, callback, state);
  76. }
  77. return BeginSecureOutgoingMessageCore(message, timeout, null, callback, state);
  78. }
  79. catch (Exception exception)
  80. {
  81. // Always immediately rethrow fatal exceptions.
  82. if (Fx.IsFatal(exception)) throw;
  83. base.OnSecureOutgoingMessageFailure(message);
  84. throw;
  85. }
  86. }
  87. public override IAsyncResult BeginSecureOutgoingMessage(Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState, AsyncCallback callback, object state)
  88. {
  89. try
  90. {
  91. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  92. ValidateOutgoingState(message);
  93. if (!this.RequiresOutgoingSecurityProcessing && message.Properties.Security == null)
  94. {
  95. return new CompletedAsyncResult<Message>(message, callback, state);
  96. }
  97. return BeginSecureOutgoingMessageCore(message, timeout, correlationState, callback, state);
  98. }
  99. catch (Exception exception)
  100. {
  101. // Always immediately rethrow fatal exceptions.
  102. if (Fx.IsFatal(exception)) throw;
  103. base.OnSecureOutgoingMessageFailure(message);
  104. throw;
  105. }
  106. }
  107. protected abstract IAsyncResult BeginSecureOutgoingMessageCore(Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState, AsyncCallback callback, object state);
  108. public override void EndSecureOutgoingMessage(IAsyncResult result, out Message message)
  109. {
  110. if (result == null)
  111. {
  112. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
  113. }
  114. try
  115. {
  116. SecurityProtocolCorrelationState newCorrelationState;
  117. EndSecureOutgoingMessageCore(result, out message, out newCorrelationState);
  118. base.OnOutgoingMessageSecured(message);
  119. }
  120. catch (Exception exception)
  121. {
  122. // Always immediately rethrow fatal exceptions.
  123. if (Fx.IsFatal(exception)) throw;
  124. base.OnSecureOutgoingMessageFailure(null);
  125. throw;
  126. }
  127. }
  128. public override void EndSecureOutgoingMessage(IAsyncResult result, out Message message, out SecurityProtocolCorrelationState newCorrelationState)
  129. {
  130. if (result == null)
  131. {
  132. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
  133. }
  134. try
  135. {
  136. EndSecureOutgoingMessageCore(result, out message, out newCorrelationState);
  137. base.OnOutgoingMessageSecured(message);
  138. }
  139. catch (Exception exception)
  140. {
  141. // Always immediately rethrow fatal exceptions.
  142. if (Fx.IsFatal(exception)) throw;
  143. base.OnSecureOutgoingMessageFailure(null);
  144. throw;
  145. }
  146. }
  147. protected abstract void EndSecureOutgoingMessageCore(IAsyncResult result, out Message message, out SecurityProtocolCorrelationState newCorrelationState);
  148. // helper method for attaching the client claims in a symmetric security protocol
  149. protected void AttachRecipientSecurityProperty(Message message, SecurityToken protectionToken, bool isWrappedToken, IList<SecurityToken> basicTokens, IList<SecurityToken> endorsingTokens,
  150. IList<SecurityToken> signedEndorsingTokens, IList<SecurityToken> signedTokens, Dictionary<SecurityToken, ReadOnlyCollection<IAuthorizationPolicy>> tokenPoliciesMapping)
  151. {
  152. ReadOnlyCollection<IAuthorizationPolicy> protectionTokenPolicies;
  153. if (isWrappedToken)
  154. {
  155. protectionTokenPolicies = EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
  156. }
  157. else
  158. {
  159. protectionTokenPolicies = tokenPoliciesMapping[protectionToken];
  160. }
  161. SecurityMessageProperty security = SecurityMessageProperty.GetOrCreate(message);
  162. security.ProtectionToken = new SecurityTokenSpecification(protectionToken, protectionTokenPolicies);
  163. AddSupportingTokenSpecification(security, basicTokens, endorsingTokens, signedEndorsingTokens, signedTokens, tokenPoliciesMapping);
  164. security.ServiceSecurityContext = new ServiceSecurityContext(security.GetInitiatorTokenAuthorizationPolicies());
  165. }
  166. // helper method for attaching the server claims in a symmetric security protocol
  167. protected void DoIdentityCheckAndAttachInitiatorSecurityProperty(Message message, SecurityToken protectionToken, ReadOnlyCollection<IAuthorizationPolicy> protectionTokenPolicies)
  168. {
  169. AuthorizationContext protectionAuthContext = EnsureIncomingIdentity(message, protectionToken, protectionTokenPolicies);
  170. SecurityMessageProperty security = SecurityMessageProperty.GetOrCreate(message);
  171. security.ProtectionToken = new SecurityTokenSpecification(protectionToken, protectionTokenPolicies);
  172. security.ServiceSecurityContext = new ServiceSecurityContext(protectionAuthContext, protectionTokenPolicies ?? EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance);
  173. }
  174. protected AuthorizationContext EnsureIncomingIdentity(Message message, SecurityToken token, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
  175. {
  176. if (token == null)
  177. {
  178. throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoSigningTokenAvailableToDoIncomingIdentityCheck)), message);
  179. }
  180. AuthorizationContext authContext = (authorizationPolicies != null) ? AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolicies) : null;
  181. if (this.factory.IdentityVerifier != null)
  182. {
  183. if (this.Target == null)
  184. {
  185. throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoOutgoingEndpointAddressAvailableForDoingIdentityCheckOnReply)), message);
  186. }
  187. this.factory.IdentityVerifier.EnsureIncomingIdentity(this.Target, authContext);
  188. }
  189. return authContext;
  190. }
  191. protected void EnsureOutgoingIdentity(SecurityToken token, SecurityTokenAuthenticator authenticator)
  192. {
  193. if (object.ReferenceEquals(token, this.identityVerifiedToken))
  194. {
  195. return;
  196. }
  197. if (this.factory.IdentityVerifier == null)
  198. {
  199. return;
  200. }
  201. if (this.Target == null)
  202. {
  203. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoOutgoingEndpointAddressAvailableForDoingIdentityCheck)));
  204. }
  205. ReadOnlyCollection<IAuthorizationPolicy> authzPolicies = authenticator.ValidateToken(token);
  206. this.factory.IdentityVerifier.EnsureOutgoingIdentity(this.Target, authzPolicies);
  207. if (this.CacheIdentityCheckResultForToken)
  208. {
  209. this.identityVerifiedToken = token;
  210. }
  211. }
  212. protected SecurityProtocolCorrelationState GetCorrelationState(SecurityToken correlationToken)
  213. {
  214. return new SecurityProtocolCorrelationState(correlationToken);
  215. }
  216. protected SecurityProtocolCorrelationState GetCorrelationState(SecurityToken correlationToken, ReceiveSecurityHeader securityHeader)
  217. {
  218. SecurityProtocolCorrelationState result = new SecurityProtocolCorrelationState(correlationToken);
  219. if (securityHeader.MaintainSignatureConfirmationState && !this.factory.ActAsInitiator)
  220. {
  221. result.SignatureConfirmations = securityHeader.GetSentSignatureValues();
  222. }
  223. return result;
  224. }
  225. protected SecurityToken GetCorrelationToken(SecurityProtocolCorrelationState[] correlationStates)
  226. {
  227. SecurityToken token = null;
  228. if (correlationStates != null)
  229. {
  230. for (int i = 0; i < correlationStates.Length; ++i)
  231. {
  232. if (correlationStates[i].Token == null)
  233. continue;
  234. if (token == null)
  235. {
  236. token = correlationStates[i].Token;
  237. }
  238. else if (!object.ReferenceEquals(token, correlationStates[i].Token))
  239. {
  240. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.MultipleCorrelationTokensFound)));
  241. }
  242. }
  243. }
  244. if (token == null)
  245. {
  246. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoCorrelationTokenFound)));
  247. }
  248. return token;
  249. }
  250. protected SecurityToken GetCorrelationToken(SecurityProtocolCorrelationState correlationState)
  251. {
  252. if (correlationState == null || correlationState.Token == null)
  253. {
  254. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.CannotFindCorrelationStateForApplyingSecurity)));
  255. }
  256. return correlationState.Token;
  257. }
  258. protected static void EnsureNonWrappedToken(SecurityToken token, Message message)
  259. {
  260. if (token is WrappedKeySecurityToken)
  261. {
  262. throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenNotExpectedInSecurityHeader, token)), message);
  263. }
  264. }
  265. protected SecurityToken GetTokenAndEnsureOutgoingIdentity(SecurityTokenProvider provider, bool isEncryptionOn, TimeSpan timeout, SecurityTokenAuthenticator authenticator)
  266. {
  267. SecurityToken token = GetToken(provider, this.Target, timeout);
  268. if (isEncryptionOn)
  269. {
  270. EnsureOutgoingIdentity(token, authenticator);
  271. }
  272. return token;
  273. }
  274. protected SendSecurityHeader ConfigureSendSecurityHeader(Message message, string actor, IList<SupportingTokenSpecification> supportingTokens, SecurityProtocolCorrelationState correlationState)
  275. {
  276. MessageSecurityProtocolFactory factory = this.MessageSecurityProtocolFactory;
  277. SendSecurityHeader securityHeader = CreateSendSecurityHeader(message, actor, factory);
  278. securityHeader.SignThenEncrypt = factory.MessageProtectionOrder != MessageProtectionOrder.EncryptBeforeSign;
  279. // If ProtectTokens is enabled then we make sure that both the client side and the service side sign the primary token
  280. // ( if it is an issued token, the check exists in sendsecurityheader)in the primary signature while sending a message.
  281. securityHeader.ShouldProtectTokens = factory.SecurityBindingElement.ProtectTokens;
  282. securityHeader.EncryptPrimarySignature = factory.MessageProtectionOrder == MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature;
  283. if (factory.DoRequestSignatureConfirmation && correlationState != null)
  284. {
  285. if (factory.ActAsInitiator)
  286. {
  287. securityHeader.MaintainSignatureConfirmationState = true;
  288. securityHeader.CorrelationState = correlationState;
  289. }
  290. else if (correlationState.SignatureConfirmations != null)
  291. {
  292. securityHeader.AddSignatureConfirmations(correlationState.SignatureConfirmations);
  293. }
  294. }
  295. string action = message.Headers.Action;
  296. if (this.factory.ApplyIntegrity)
  297. {
  298. securityHeader.SignatureParts = this.factory.GetOutgoingSignatureParts(action);
  299. }
  300. if (factory.ApplyConfidentiality)
  301. {
  302. securityHeader.EncryptionParts = this.factory.GetOutgoingEncryptionParts(action);
  303. }
  304. AddSupportingTokens(securityHeader, supportingTokens);
  305. return securityHeader;
  306. }
  307. protected ReceiveSecurityHeader CreateSecurityHeader(Message message, string actor, MessageDirection transferDirection, SecurityStandardsManager standardsManager)
  308. {
  309. standardsManager = standardsManager ?? this.factory.StandardsManager;
  310. ReceiveSecurityHeader securityHeader = standardsManager.CreateReceiveSecurityHeader(message, actor,
  311. this.factory.IncomingAlgorithmSuite, transferDirection);
  312. securityHeader.Layout = this.factory.SecurityHeaderLayout;
  313. securityHeader.MaxReceivedMessageSize = factory.SecurityBindingElement.MaxReceivedMessageSize;
  314. securityHeader.ReaderQuotas = factory.SecurityBindingElement.ReaderQuotas;
  315. if (this.factory.ExpectKeyDerivation)
  316. {
  317. securityHeader.DerivedTokenAuthenticator = this.factory.DerivedKeyTokenAuthenticator;
  318. }
  319. return securityHeader;
  320. }
  321. bool HasCorrelationState(SecurityProtocolCorrelationState[] correlationState)
  322. {
  323. if (correlationState == null || correlationState.Length == 0)
  324. {
  325. return false;
  326. }
  327. else if (correlationState.Length == 1 && correlationState[0] == null)
  328. {
  329. return false;
  330. }
  331. else
  332. {
  333. return true;
  334. }
  335. }
  336. protected ReceiveSecurityHeader ConfigureReceiveSecurityHeader(Message message, string actor, SecurityProtocolCorrelationState[] correlationStates, out IList<SupportingTokenAuthenticatorSpecification> supportingAuthenticators)
  337. {
  338. return ConfigureReceiveSecurityHeader(message, actor, correlationStates, null, out supportingAuthenticators);
  339. }
  340. protected ReceiveSecurityHeader ConfigureReceiveSecurityHeader(Message message, string actor, SecurityProtocolCorrelationState[] correlationStates, SecurityStandardsManager standardsManager, out IList<SupportingTokenAuthenticatorSpecification> supportingAuthenticators)
  341. {
  342. MessageSecurityProtocolFactory factory = this.MessageSecurityProtocolFactory;
  343. MessageDirection direction = factory.ActAsInitiator ? MessageDirection.Output : MessageDirection.Input;
  344. ReceiveSecurityHeader securityHeader = CreateSecurityHeader(message, actor, direction, standardsManager);
  345. string action = message.Headers.Action;
  346. supportingAuthenticators = GetSupportingTokenAuthenticatorsAndSetExpectationFlags(this.factory, message, securityHeader);
  347. if (factory.RequireIntegrity || securityHeader.ExpectSignedTokens)
  348. {
  349. securityHeader.RequiredSignatureParts = factory.GetIncomingSignatureParts(action);
  350. }
  351. if (factory.RequireConfidentiality || securityHeader.ExpectBasicTokens)
  352. {
  353. securityHeader.RequiredEncryptionParts = factory.GetIncomingEncryptionParts(action);
  354. }
  355. securityHeader.ExpectEncryption = factory.RequireConfidentiality || securityHeader.ExpectBasicTokens;
  356. securityHeader.ExpectSignature = factory.RequireIntegrity || securityHeader.ExpectSignedTokens;
  357. securityHeader.SetRequiredProtectionOrder(factory.MessageProtectionOrder);
  358. // On the receiving side if protectTokens is enabled
  359. // 1. If we are service, we make sure that the client always signs the primary token( can be any token type)else we throw.
  360. // But currently the service can sign the primary token in reply only if the primary token is an issued token
  361. // 2. If we are client, we do not care if the service signs the primary token or not. Otherwise it will be impossible to have a wcf client /service talk to each other unless we
  362. // either use a symmetric binding with issued tokens or asymmetric bindings with both the intiator and recipient parameters being issued tokens( later one is rare).
  363. securityHeader.RequireSignedPrimaryToken = !factory.ActAsInitiator && factory.SecurityBindingElement.ProtectTokens;
  364. if (factory.ActAsInitiator && factory.DoRequestSignatureConfirmation && HasCorrelationState(correlationStates))
  365. {
  366. securityHeader.MaintainSignatureConfirmationState = true;
  367. securityHeader.ExpectSignatureConfirmation = true;
  368. }
  369. else if (!factory.ActAsInitiator && factory.DoRequestSignatureConfirmation)
  370. {
  371. securityHeader.MaintainSignatureConfirmationState = true;
  372. }
  373. else
  374. {
  375. securityHeader.MaintainSignatureConfirmationState = false;
  376. }
  377. return securityHeader;
  378. }
  379. protected void ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, ref Message message,
  380. SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
  381. {
  382. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  383. securityHeader.ReplayDetectionEnabled = this.factory.DetectReplays;
  384. securityHeader.SetTimeParameters(this.factory.NonceCache, this.factory.ReplayWindow, this.factory.MaxClockSkew);
  385. securityHeader.Process(timeoutHelper.RemainingTime(), SecurityUtils.GetChannelBindingFromMessage(message), this.factory.ExtendedProtectionPolicy);
  386. if (this.factory.AddTimestamp && securityHeader.Timestamp == null)
  387. {
  388. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.RequiredTimestampMissingInSecurityHeader)));
  389. }
  390. if (requiredSigningToken != null && requiredSigningToken != securityHeader.SignatureToken)
  391. {
  392. throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.ReplyWasNotSignedWithRequiredSigningToken)), message);
  393. }
  394. if (this.DoAutomaticEncryptionMatch)
  395. {
  396. SecurityUtils.EnsureExpectedSymmetricMatch(securityHeader.SignatureToken, securityHeader.EncryptionToken, message);
  397. }
  398. if (securityHeader.MaintainSignatureConfirmationState && this.factory.ActAsInitiator)
  399. {
  400. CheckSignatureConfirmation(securityHeader, correlationStates);
  401. }
  402. message = securityHeader.ProcessedMessage;
  403. }
  404. protected void CheckSignatureConfirmation(ReceiveSecurityHeader securityHeader, SecurityProtocolCorrelationState[] correlationStates)
  405. {
  406. SignatureConfirmations receivedConfirmations = securityHeader.GetSentSignatureConfirmations();
  407. SignatureConfirmations sentSignatures = null;
  408. if (correlationStates != null)
  409. {
  410. for (int i = 0; i < correlationStates.Length; ++i)
  411. {
  412. if (correlationStates[i].SignatureConfirmations != null)
  413. {
  414. sentSignatures = correlationStates[i].SignatureConfirmations;
  415. break;
  416. }
  417. }
  418. }
  419. if (sentSignatures == null)
  420. {
  421. if (receivedConfirmations != null && receivedConfirmations.Count > 0)
  422. {
  423. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.FoundUnexpectedSignatureConfirmations)));
  424. }
  425. return;
  426. }
  427. bool allSignaturesConfirmed = false;
  428. if (receivedConfirmations != null && sentSignatures.Count == receivedConfirmations.Count)
  429. {
  430. bool[] matchingSigIndexes = new bool[sentSignatures.Count];
  431. for (int i = 0; i < sentSignatures.Count; ++i)
  432. {
  433. byte[] sentSignature;
  434. bool wasSentSigEncrypted;
  435. sentSignatures.GetConfirmation(i, out sentSignature, out wasSentSigEncrypted);
  436. for (int j = 0; j < receivedConfirmations.Count; ++j)
  437. {
  438. byte[] receivedSignature;
  439. bool wasReceivedSigEncrypted;
  440. if (matchingSigIndexes[j])
  441. {
  442. continue;
  443. }
  444. receivedConfirmations.GetConfirmation(j, out receivedSignature, out wasReceivedSigEncrypted);
  445. if ((wasReceivedSigEncrypted == wasSentSigEncrypted) && CryptoHelper.IsEqual(receivedSignature, sentSignature))
  446. {
  447. matchingSigIndexes[j] = true;
  448. break;
  449. }
  450. }
  451. }
  452. int k;
  453. for (k = 0; k < matchingSigIndexes.Length; ++k)
  454. {
  455. if (!matchingSigIndexes[k])
  456. {
  457. break;
  458. }
  459. }
  460. if (k == matchingSigIndexes.Length)
  461. {
  462. allSignaturesConfirmed = true;
  463. }
  464. }
  465. if (!allSignaturesConfirmed)
  466. {
  467. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NotAllSignaturesConfirmed)));
  468. }
  469. }
  470. public override void SecureOutgoingMessage(ref Message message, TimeSpan timeout)
  471. {
  472. try
  473. {
  474. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  475. ValidateOutgoingState(message);
  476. if (!this.RequiresOutgoingSecurityProcessing && message.Properties.Security == null)
  477. {
  478. return;
  479. }
  480. SecureOutgoingMessageCore(ref message, timeout, null);
  481. base.OnOutgoingMessageSecured(message);
  482. }
  483. catch (Exception exception)
  484. {
  485. // Always immediately rethrow fatal exceptions.
  486. if (Fx.IsFatal(exception)) throw;
  487. base.OnSecureOutgoingMessageFailure(message);
  488. throw;
  489. }
  490. }
  491. public override SecurityProtocolCorrelationState SecureOutgoingMessage(ref Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState)
  492. {
  493. try
  494. {
  495. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  496. ValidateOutgoingState(message);
  497. if (!this.RequiresOutgoingSecurityProcessing && message.Properties.Security == null)
  498. {
  499. return null;
  500. }
  501. SecurityProtocolCorrelationState newCorrelationState = SecureOutgoingMessageCore(ref message, timeout, correlationState);
  502. base.OnOutgoingMessageSecured(message);
  503. return newCorrelationState;
  504. }
  505. catch (Exception exception)
  506. {
  507. // Always immediately rethrow fatal exceptions.
  508. if (Fx.IsFatal(exception)) throw;
  509. base.OnSecureOutgoingMessageFailure(message);
  510. throw;
  511. }
  512. }
  513. protected abstract SecurityProtocolCorrelationState SecureOutgoingMessageCore(ref Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState);
  514. void ValidateOutgoingState(Message message)
  515. {
  516. if (this.PerformIncomingAndOutgoingMessageExpectationChecks && !this.factory.ExpectOutgoingMessages)
  517. {
  518. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecurityBindingNotSetUpToProcessOutgoingMessages)));
  519. }
  520. if (message == null)
  521. {
  522. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  523. }
  524. }
  525. public override void VerifyIncomingMessage(ref Message message, TimeSpan timeout)
  526. {
  527. try
  528. {
  529. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  530. if (this.PerformIncomingAndOutgoingMessageExpectationChecks && !factory.ExpectIncomingMessages)
  531. {
  532. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecurityBindingNotSetUpToProcessIncomingMessages)));
  533. }
  534. if (message == null)
  535. {
  536. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  537. }
  538. if (!this.RequiresIncomingSecurityProcessing(message))
  539. {
  540. return;
  541. }
  542. string actor = string.Empty; // message.Version.Envelope.UltimateDestinationActor;
  543. VerifyIncomingMessageCore(ref message, actor, timeout, null);
  544. base.OnIncomingMessageVerified(message);
  545. }
  546. catch (MessageSecurityException e)
  547. {
  548. base.OnVerifyIncomingMessageFailure(message, e);
  549. throw;
  550. }
  551. catch (Exception e)
  552. {
  553. // Always immediately rethrow fatal exceptions.
  554. if (Fx.IsFatal(e)) throw;
  555. base.OnVerifyIncomingMessageFailure(message, e);
  556. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.MessageSecurityVerificationFailed), e));
  557. }
  558. }
  559. public override SecurityProtocolCorrelationState VerifyIncomingMessage(ref Message message, TimeSpan timeout, params SecurityProtocolCorrelationState[] correlationStates)
  560. {
  561. try
  562. {
  563. this.CommunicationObject.ThrowIfClosedOrNotOpen();
  564. if (this.PerformIncomingAndOutgoingMessageExpectationChecks && !factory.ExpectIncomingMessages)
  565. {
  566. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecurityBindingNotSetUpToProcessIncomingMessages)));
  567. }
  568. if (message == null)
  569. {
  570. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  571. }
  572. if (!this.RequiresIncomingSecurityProcessing(message))
  573. {
  574. return null;
  575. }
  576. string actor = string.Empty; // message.Version.Envelope.UltimateDestinationActor;
  577. SecurityProtocolCorrelationState newCorrelationState = VerifyIncomingMessageCore(ref message, actor, timeout, correlationStates);
  578. base.OnIncomingMessageVerified(message);
  579. return newCorrelationState;
  580. }
  581. catch (MessageSecurityException e)
  582. {
  583. base.OnVerifyIncomingMessageFailure(message, e);
  584. throw;
  585. }
  586. catch (Exception e)
  587. {
  588. // Always immediately rethrow fatal exceptions.
  589. if (Fx.IsFatal(e)) throw;
  590. base.OnVerifyIncomingMessageFailure(message, e);
  591. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.MessageSecurityVerificationFailed), e));
  592. }
  593. }
  594. protected abstract SecurityProtocolCorrelationState VerifyIncomingMessageCore(ref Message message, string actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates);
  595. internal SecurityProtocolCorrelationState GetSignatureConfirmationCorrelationState(SecurityProtocolCorrelationState oldCorrelationState, SecurityProtocolCorrelationState newCorrelationState)
  596. {
  597. if (this.factory.ActAsInitiator)
  598. {
  599. return newCorrelationState;
  600. }
  601. else
  602. {
  603. return oldCorrelationState;
  604. }
  605. }
  606. protected abstract class GetOneTokenAndSetUpSecurityAsyncResult : GetSupportingTokensAsyncResult
  607. {
  608. readonly MessageSecurityProtocol binding;
  609. readonly SecurityTokenProvider provider;
  610. Message message;
  611. readonly bool doIdentityChecks;
  612. SecurityTokenAuthenticator identityCheckAuthenticator;
  613. static AsyncCallback getTokenCompleteCallback = Fx.ThunkCallback(new AsyncCallback(GetTokenCompleteCallback));
  614. SecurityProtocolCorrelationState newCorrelationState;
  615. SecurityProtocolCorrelationState oldCorrelationState;
  616. TimeoutHelper timeoutHelper;
  617. public GetOneTokenAndSetUpSecurityAsyncResult(Message m, MessageSecurityProtocol binding, SecurityTokenProvider provider,
  618. bool doIdentityChecks, SecurityTokenAuthenticator identityCheckAuthenticator, SecurityProtocolCorrelationState oldCorrelationState, TimeSpan timeout, AsyncCallback callback, object state)
  619. : base(m, binding, timeout, callback, state)
  620. {
  621. this.message = m;
  622. this.binding = binding;
  623. this.provider = provider;
  624. this.doIdentityChecks = doIdentityChecks;
  625. this.oldCorrelationState = oldCorrelationState;
  626. this.identityCheckAuthenticator = identityCheckAuthenticator;
  627. }
  628. protected MessageSecurityProtocol Binding
  629. {
  630. get { return this.binding; }
  631. }
  632. protected SecurityProtocolCorrelationState NewCorrelationState
  633. {
  634. get { return this.newCorrelationState; }
  635. }
  636. protected SecurityProtocolCorrelationState OldCorrelationState
  637. {
  638. get { return this.oldCorrelationState; }
  639. }
  640. internal static Message End(IAsyncResult result, out SecurityProtocolCorrelationState newCorrelationState)
  641. {
  642. GetOneTokenAndSetUpSecurityAsyncResult self = AsyncResult.End<GetOneTokenAndSetUpSecurityAsyncResult>(result);
  643. newCorrelationState = self.newCorrelationState;
  644. return self.message;
  645. }
  646. bool OnGetTokenComplete(SecurityToken token)
  647. {
  648. if (token == null)
  649. {
  650. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, this.binding.Target)));
  651. }
  652. if (this.doIdentityChecks)
  653. {
  654. this.binding.EnsureOutgoingIdentity(token, this.identityCheckAuthenticator);
  655. }
  656. OnGetTokenDone(ref this.message, token, timeoutHelper.RemainingTime());
  657. return true;
  658. }
  659. protected abstract void OnGetTokenDone(ref Message message, SecurityToken token, TimeSpan timeout);
  660. static void GetTokenCompleteCallback(IAsyncResult result)
  661. {
  662. if (result == null)
  663. {
  664. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
  665. }
  666. if (result.CompletedSynchronously)
  667. {
  668. return;
  669. }
  670. GetOneTokenAndSetUpSecurityAsyncResult self = result.AsyncState as GetOneTokenAndSetUpSecurityAsyncResult;
  671. if (self == null)
  672. {
  673. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.InvalidAsyncResult));
  674. }
  675. Exception completionException = null;
  676. bool completeSelf = false;
  677. try
  678. {
  679. SecurityToken token = self.provider.EndGetToken(result);
  680. completeSelf = self.OnGetTokenComplete(token);
  681. }
  682. #pragma warning suppress 56500 // covered by FxCOP
  683. catch (Exception e)
  684. {
  685. // Always immediately rethrow fatal exceptions.
  686. if (Fx.IsFatal(e)) throw;
  687. completeSelf = true;
  688. completionException = e;
  689. }
  690. if (completeSelf)
  691. {
  692. self.Complete(false, completionException);
  693. }
  694. }
  695. protected void SetCorrelationToken(SecurityToken token)
  696. {
  697. newCorrelationState = new SecurityProtocolCorrelationState(token);
  698. }
  699. protected override bool OnGetSupportingTokensDone(TimeSpan timeout)
  700. {
  701. this.timeoutHelper = new TimeoutHelper(timeout);
  702. IAsyncResult result = this.provider.BeginGetToken(timeoutHelper.RemainingTime(), getTokenCompleteCallback, this);
  703. if (!result.CompletedSynchronously)
  704. {
  705. return false;
  706. }
  707. SecurityToken token = this.provider.EndGetToken(result);
  708. return this.OnGetTokenComplete(token);
  709. }
  710. }
  711. // note: identity check done only on token obtained from first
  712. // token provider; either or both token providers may be null;
  713. // get token calls are skipped for null providers.
  714. protected abstract class GetTwoTokensAndSetUpSecurityAsyncResult : GetSupportingTokensAsyncResult
  715. {
  716. readonly MessageSecurityProtocol binding;
  717. readonly SecurityTokenProvider primaryProvider;
  718. readonly SecurityTokenProvider secondaryProvider;
  719. Message message;
  720. readonly bool doIdentityChecks;
  721. SecurityTokenAuthenticator identityCheckAuthenticator;
  722. SecurityToken primaryToken;
  723. static readonly AsyncCallback getPrimaryTokenCompleteCallback = Fx.ThunkCallback(new AsyncCallback(GetPrimaryTokenCompleteCallback));
  724. static readonly AsyncCallback getSecondaryTokenCompleteCallback = Fx.ThunkCallback(new AsyncCallback(GetSecondaryTokenCompleteCallback));
  725. SecurityProtocolCorrelationState newCorrelationState;
  726. SecurityProtocolCorrelationState oldCorrelationState;
  727. TimeoutHelper timeoutHelper;
  728. public GetTwoTokensAndSetUpSecurityAsyncResult(Message m, MessageSecurityProtocol binding,
  729. SecurityTokenProvider primaryProvider, SecurityTokenProvider secondaryProvider, bool doIdentityChecks, SecurityTokenAuthenticator identityCheckAuthenticator,
  730. SecurityProtocolCorrelationState oldCorrelationState,
  731. TimeSpan timeout,
  732. AsyncCallback callback, object state)
  733. : base(m, binding, timeout, callback, state)
  734. {
  735. this.message = m;
  736. this.binding = binding;
  737. this.primaryProvider = primaryProvider;
  738. this.secondaryProvider = secondaryProvider;
  739. this.doIdentityChecks = doIdentityChecks;
  740. this.identityCheckAuthenticator = identityCheckAuthenticator;
  741. this.oldCorrelationState = oldCorrelationState;
  742. }
  743. protected MessageSecurityProtocol Binding
  744. {
  745. get { return this.binding; }
  746. }
  747. protected SecurityProtocolCorrelationState NewCorrelationState
  748. {
  749. get { return this.newCorrelationState; }
  750. }
  751. protected SecurityProtocolCorrelationState OldCorrelationState
  752. {
  753. get { return this.oldCorrelationState; }
  754. }
  755. internal static Message End(IAsyncResult result, out SecurityProtocolCorrelationState newCorrelationState)
  756. {
  757. GetTwoTokensAndSetUpSecurityAsyncResult self = AsyncResult.End<GetTwoTokensAndSetUpSecurityAsyncResult>(result);
  758. newCorrelationState = self.newCorrelationState;
  759. return self.message;
  760. }
  761. bool OnGetPrimaryTokenComplete(SecurityToken token)
  762. {
  763. return OnGetPrimaryTokenComplete(token, false);
  764. }
  765. bool OnGetPrimaryTokenComplete(SecurityToken token, bool primaryCallSkipped)
  766. {
  767. if (!primaryCallSkipped)
  768. {
  769. if (token == null)
  770. {
  771. throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, this.binding.Target)), this.message);
  772. }
  773. if (this.doIdentityChecks)
  774. {
  775. this.binding.EnsureOutgoingIdentity(token, this.identityCheckAuthenticator);
  776. }
  777. }
  778. this.primaryToken = token;
  779. if (this.secondaryProvider == null)
  780. {
  781. return this.OnGetSecondaryTokenComplete(null, true);
  782. }
  783. else
  784. {
  785. IAsyncResult result = this.secondaryProvider.BeginGetToken(this.timeoutHelper.RemainingTime(), getSecondaryTokenCompleteCallback, this);
  786. if (!result.CompletedSynchronously)
  787. {
  788. return false;
  789. }
  790. SecurityToken token2 = this.secondaryProvider.EndGetToken(result);
  791. return this.OnGetSecondaryTokenComplete(token2);
  792. }
  793. }
  794. bool OnGetSecondaryTokenComplete(SecurityToken token)
  795. {
  796. return OnGetSecondaryTokenComplete(token, false);
  797. }
  798. bool OnGetSecondaryTokenComplete(SecurityToken token, bool secondaryCallSkipped)
  799. {
  800. if (!secondaryCallSkipped && token == null)
  801. {
  802. throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, this.binding.Target)), this.message);
  803. }
  804. OnBothGetTokenCallsDone(ref this.message, this.primaryToken, token, timeoutHelper.RemainingTime());
  805. return true;
  806. }
  807. protected abstract void OnBothGetTokenCallsDone(ref Message message, SecurityToken primaryToken, SecurityToken secondaryToken, TimeSpan timeout);
  808. static void GetPrimaryTokenCompleteCallback(IAsyncResult result)
  809. {
  810. if (result == null)
  811. {
  812. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
  813. }
  814. if (result.CompletedSynchronously)
  815. {
  816. return;
  817. }
  818. GetTwoTokensAndSetUpSecurityAsyncResult self = result.AsyncState as GetTwoTokensAndSetUpSecurityAsyncResult;
  819. if (self == null)
  820. {
  821. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.InvalidAsyncResult));
  822. }
  823. bool completeSelf = false;
  824. Exception completionException = null;
  825. try
  826. {
  827. SecurityToken token = self.primaryProvider.EndGetToken(result);
  828. completeSelf = self.OnGetPrimaryTokenComplete(token);
  829. }
  830. #pragma warning suppress 56500 // covered by FxCOP
  831. catch (Exception e)
  832. {
  833. // Always immediately rethrow fatal exceptions.
  834. if (Fx.IsFatal(e)) throw;
  835. completeSelf = true;
  836. completionException = e;
  837. }
  838. if (completeSelf)
  839. {
  840. self.Complete(false, completionException);
  841. }
  842. }
  843. static void GetSecondaryTokenCompleteCallback(IAsyncResult result)
  844. {
  845. if (result == null)
  846. {
  847. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
  848. }
  849. if (result.CompletedSynchronously)
  850. {
  851. return;
  852. }
  853. GetTwoTokensAndSetUpSecurityAsyncResult self = result.AsyncState as GetTwoTokensAndSetUpSecurityAsyncResult;
  854. if (self == null)
  855. {
  856. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.InvalidAsyncResult));
  857. }
  858. bool completeSelf = false;
  859. Exception completionException = null;
  860. try
  861. {
  862. SecurityToken token = self.secondaryProvider.EndGetToken(result);
  863. completeSelf = self.OnGetSecondaryTokenComplete(token);
  864. }
  865. #pragma warning suppress 56500 // covered by FxCOP
  866. catch (Exception e)
  867. {
  868. // Always immediately rethrow fatal exceptions.
  869. if (Fx.IsFatal(e)) throw;
  870. completeSelf = true;
  871. completionException = e;
  872. }
  873. if (completeSelf)
  874. {
  875. self.Complete(false, completionException);
  876. }
  877. }
  878. protected void SetCorrelationToken(SecurityToken token)
  879. {
  880. newCorrelationState = new SecurityProtocolCorrelationState(token);
  881. }
  882. protected override bool OnGetSupportingTokensDone(TimeSpan timeout)
  883. {
  884. this.timeoutHelper = new TimeoutHelper(timeout);
  885. bool completeSelf = false;
  886. if (this.primaryProvider == null)
  887. {
  888. completeSelf = this.OnGetPrimaryTokenComplete(null);
  889. }
  890. else
  891. {
  892. IAsyncResult result = this.primaryProvider.BeginGetToken(this.timeoutHelper.RemainingTime(), getPrimaryTokenCompleteCallback, this);
  893. if (result.CompletedSynchronously)
  894. {
  895. SecurityToken token = this.primaryProvider.EndGetToken(result);
  896. completeSelf = this.OnGetPrimaryTokenComplete(token);
  897. }
  898. }
  899. return completeSelf;
  900. }
  901. }
  902. }
  903. }