SecurityValidationBehavior.cs 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Dispatcher
  5. {
  6. using System.ServiceModel.Channels;
  7. using System.ServiceModel;
  8. using System.ServiceModel.Description;
  9. using System.ServiceModel.Security;
  10. using System.ServiceModel.Security.Tokens;
  11. using System.IdentityModel.Tokens;
  12. using System.Collections.Generic;
  13. using System.Collections.ObjectModel;
  14. using System.Runtime.CompilerServices;
  15. using System.Net.Security;
  16. using System.Security.Principal;
  17. class SecurityValidationBehavior : IEndpointBehavior, IServiceBehavior
  18. {
  19. static SecurityValidationBehavior instance;
  20. public static SecurityValidationBehavior Instance
  21. {
  22. get
  23. {
  24. if (instance == null)
  25. instance = new SecurityValidationBehavior();
  26. return instance;
  27. }
  28. }
  29. class ValidationBinding : Binding
  30. {
  31. Binding binding;
  32. BindingElementCollection elements;
  33. public ValidationBinding(Binding binding)
  34. : base(binding.Name, binding.Namespace)
  35. {
  36. this.binding = binding;
  37. }
  38. public override string Scheme
  39. {
  40. get { return this.binding.Scheme; }
  41. }
  42. public override BindingElementCollection CreateBindingElements()
  43. {
  44. if (this.elements == null)
  45. {
  46. this.elements = this.binding.CreateBindingElements();
  47. }
  48. return this.elements;
  49. }
  50. public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingParameterCollection parameters)
  51. {
  52. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  53. }
  54. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(params object[] parameters)
  55. {
  56. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  57. }
  58. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(Uri listenUriBaseAddress, params object[] parameters)
  59. {
  60. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  61. }
  62. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(Uri listenUriBaseAddress, string listenUriRelativeAddress, params object[] parameters)
  63. {
  64. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  65. }
  66. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(Uri listenUriBaseAddress, string listenUriRelativeAddress, ListenUriMode listenUriMode, params object[] parameters)
  67. {
  68. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  69. }
  70. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingParameterCollection parameters)
  71. {
  72. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  73. }
  74. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(Uri listenUriBaseAddress, BindingParameterCollection parameters)
  75. {
  76. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  77. }
  78. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(Uri listenUriBaseAddress, string listenUriRelativeAddress, BindingParameterCollection parameters)
  79. {
  80. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  81. }
  82. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(Uri listenUriBaseAddress, string listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters)
  83. {
  84. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  85. }
  86. public override bool CanBuildChannelFactory<TChannel>(BindingParameterCollection parameters)
  87. {
  88. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  89. }
  90. public override bool CanBuildChannelListener<TChannel>(BindingParameterCollection parameters)
  91. {
  92. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  93. }
  94. }
  95. void IEndpointBehavior.Validate(ServiceEndpoint serviceEndpoint)
  96. {
  97. if (serviceEndpoint == null)
  98. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceEndpoint");
  99. SecurityBindingElement sbe;
  100. Binding binding = new ValidationBinding(serviceEndpoint.Binding);
  101. ValidateBinding(binding, serviceEndpoint.Contract, out sbe);
  102. }
  103. void IEndpointBehavior.AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection parameters)
  104. {
  105. }
  106. void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
  107. {
  108. }
  109. void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
  110. {
  111. }
  112. void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
  113. {
  114. }
  115. void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
  116. {
  117. }
  118. void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
  119. {
  120. if (description == null)
  121. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description");
  122. for (int i = 0; i < description.Endpoints.Count; i++)
  123. {
  124. ServiceEndpoint endpoint = description.Endpoints[i];
  125. Binding binding = new ValidationBinding(endpoint.Binding);
  126. SecurityBindingElement sbe;
  127. ValidateBinding(binding, endpoint.Contract, out sbe);
  128. if (sbe != null)
  129. {
  130. SecurityTokenParameterInclusionModeRule.Validate(sbe, binding, endpoint.Contract, description.Behaviors);
  131. }
  132. }
  133. WindowsIdentitySupportRule.Validate(description);
  134. UsernameImpersonationRule.Validate(description);
  135. MissingClientCertificateRule.Validate(description);
  136. }
  137. void ValidateBinding(Binding binding, ContractDescription contract, out SecurityBindingElement securityBindingElement)
  138. {
  139. securityBindingElement = SecurityValidationBehavior.GetSecurityBinding(binding, contract);
  140. if (securityBindingElement != null)
  141. ValidateSecurityBinding(securityBindingElement, binding, contract);
  142. else
  143. ValidateNoSecurityBinding(binding, contract);
  144. }
  145. void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  146. {
  147. ContractProtectionRequirementsRule.ValidateSecurityBinding(sbe, binding, contract);
  148. CookieAndSessionProtectionRequirementsRule.ValidateSecurityBinding(sbe, binding, contract);
  149. SoapOverSecureTransportRequirementsRule.ValidateSecurityBinding(sbe, binding, contract);
  150. SecurityVersionSupportForEncryptedKeyBindingRule.ValidateSecurityBinding(sbe, binding, contract);
  151. SecurityVersionSupportForThumbprintKeyIdentifierClauseRule.ValidateSecurityBinding(sbe, binding, contract);
  152. SecurityBindingSupportForOneWayOnlyRule.ValidateSecurityBinding(sbe, binding, contract);
  153. IssuedKeySizeCompatibilityWithAlgorithmSuiteRule.ValidateSecurityBinding(sbe, binding, contract);
  154. MessageSecurityAndManualAddressingRule.ValidateSecurityBinding(sbe, binding, contract);
  155. NoStreamingWithSecurityRule.ValidateSecurityBinding(sbe, binding, contract);
  156. UnknownHeaderProtectionRequirementsRule.ValidateSecurityBinding(sbe, binding, contract);
  157. BearerKeyTypeIssuanceRequirementRule.ValidateSecurityBinding(sbe, binding, contract);
  158. }
  159. void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  160. {
  161. ContractProtectionRequirementsRule.ValidateNoSecurityBinding(binding, contract);
  162. CookieAndSessionProtectionRequirementsRule.ValidateNoSecurityBinding(binding, contract);
  163. SoapOverSecureTransportRequirementsRule.ValidateNoSecurityBinding(binding, contract);
  164. SecurityVersionSupportForEncryptedKeyBindingRule.ValidateNoSecurityBinding(binding, contract);
  165. SecurityVersionSupportForThumbprintKeyIdentifierClauseRule.ValidateNoSecurityBinding(binding, contract);
  166. SecurityBindingSupportForOneWayOnlyRule.ValidateNoSecurityBinding(binding, contract);
  167. IssuedKeySizeCompatibilityWithAlgorithmSuiteRule.ValidateNoSecurityBinding(binding, contract);
  168. MessageSecurityAndManualAddressingRule.ValidateNoSecurityBinding(binding, contract);
  169. UnknownHeaderProtectionRequirementsRule.ValidateNoSecurityBinding(binding, contract);
  170. BearerKeyTypeIssuanceRequirementRule.ValidateNoSecurityBinding(binding, contract);
  171. }
  172. static SecurityBindingElement GetSecurityBinding(Binding binding, ContractDescription contract)
  173. {
  174. SecurityBindingElement sbe = null;
  175. BindingElementCollection elements = binding.CreateBindingElements();
  176. for (int i = 0; i < elements.Count; i++)
  177. {
  178. BindingElement element = elements[i];
  179. if (element is SecurityBindingElement)
  180. {
  181. if (sbe != null)
  182. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  183. SR.GetString(SR.MoreThanOneSecurityBindingElementInTheBinding, binding.Name, binding.Namespace, contract.Name, contract.Namespace)));
  184. sbe = (SecurityBindingElement)element;
  185. }
  186. }
  187. return sbe;
  188. }
  189. internal void AfterBuildTimeValidation(ServiceDescription description)
  190. {
  191. S4UImpersonationRule.Validate(description);
  192. }
  193. // We do not allow streaming with message security which makes our service vulnerable
  194. // for example, GetWhitespace may be a problem if it’s called on unbounded data.
  195. static class NoStreamingWithSecurityRule
  196. {
  197. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  198. {
  199. // check to see if we are doing message security
  200. // if transport security, the sbe would be transportsecuritybindingelement
  201. if (sbe is SymmetricSecurityBindingElement || sbe is AsymmetricSecurityBindingElement)
  202. {
  203. // check to see if we are streaming
  204. // ([....] 53690): need to have a general way get the transfer Mode from the binding
  205. // TransferMode transferMode = binding.GetProperty<TransferMode>(new BindingParameterCollection());
  206. if (GetTransferMode(binding) != TransferMode.Buffered)
  207. {
  208. // throw
  209. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoStreamingWithSecurity, binding.Name, binding.Namespace)));
  210. }
  211. }
  212. }
  213. static TransferMode GetTransferMode(Binding binding)
  214. {
  215. TransferMode mode = TransferMode.Buffered;
  216. BindingElementCollection elements = binding.CreateBindingElements();
  217. TransportBindingElement element = elements.Find<TransportBindingElement>();
  218. if (element is ConnectionOrientedTransportBindingElement)
  219. {
  220. mode = ((ConnectionOrientedTransportBindingElement)element).TransferMode;
  221. }
  222. else if (element is HttpTransportBindingElement)
  223. {
  224. mode = ((HttpTransportBindingElement)element).TransferMode;
  225. }
  226. return mode;
  227. }
  228. }
  229. static class WindowsIdentitySupportRule
  230. {
  231. static public void Validate(ServiceDescription description)
  232. {
  233. bool impersonateCallerForAllServiceMethods = false;
  234. ServiceAuthorizationBehavior authorizationBehavior = description.Behaviors.Find<ServiceAuthorizationBehavior>();
  235. if (authorizationBehavior != null)
  236. {
  237. impersonateCallerForAllServiceMethods = authorizationBehavior.ImpersonateCallerForAllOperations;
  238. }
  239. else
  240. {
  241. impersonateCallerForAllServiceMethods = false;
  242. }
  243. for (int i = 0; i < description.Endpoints.Count; i++)
  244. {
  245. ServiceEndpoint endpoint = description.Endpoints[i];
  246. if (endpoint.InternalIsSystemEndpoint(description))
  247. {
  248. continue;
  249. }
  250. for (int j = 0; j < endpoint.Contract.Operations.Count; j++)
  251. {
  252. OperationDescription operation = endpoint.Contract.Operations[j];
  253. OperationBehaviorAttribute operationBehavior = operation.Behaviors.Find<OperationBehaviorAttribute>();
  254. if (impersonateCallerForAllServiceMethods &&
  255. !operation.IsServerInitiated() &&
  256. (operationBehavior == null || operationBehavior.Impersonation == ImpersonationOption.NotAllowed))
  257. {
  258. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.OperationDoesNotAllowImpersonation, operation.Name, endpoint.Contract.Name, endpoint.Contract.Namespace)));
  259. }
  260. if (impersonateCallerForAllServiceMethods || (operationBehavior != null && operationBehavior.Impersonation == ImpersonationOption.Required))
  261. {
  262. ValidateWindowsIdentityCapability(endpoint.Binding, endpoint.Contract, operation);
  263. }
  264. }
  265. }
  266. }
  267. static void ValidateWindowsIdentityCapability(Binding binding, ContractDescription contract, OperationDescription operation)
  268. {
  269. bool windowsIdentityProvided = false;
  270. ISecurityCapabilities capabilities = binding.GetProperty<ISecurityCapabilities>(new BindingParameterCollection());
  271. if (capabilities != null && capabilities.SupportsClientWindowsIdentity)
  272. {
  273. windowsIdentityProvided = true;
  274. }
  275. if (!windowsIdentityProvided)
  276. {
  277. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  278. SR.GetString(SR.BindingDoesNotSupportWindowsIdenityForImpersonation, operation.Name, binding.Name, binding.Namespace, contract.Name, contract.Namespace)));
  279. }
  280. }
  281. }
  282. static class S4UImpersonationRule
  283. {
  284. const int WindowsServerMajorNumber = 5;
  285. const int WindowsServerMinorNumber = 2;
  286. static bool IsS4URequiredForImpersonation(SecurityBindingElement sbe)
  287. {
  288. foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
  289. {
  290. if (stp is SecureConversationSecurityTokenParameters)
  291. {
  292. SecureConversationSecurityTokenParameters scstp = (SecureConversationSecurityTokenParameters)stp;
  293. if (scstp.RequireCancellation == false)
  294. return true;
  295. if (scstp.BootstrapSecurityBindingElement != null)
  296. {
  297. return IsS4URequiredForImpersonation(scstp.BootstrapSecurityBindingElement);
  298. }
  299. }
  300. if (stp is SspiSecurityTokenParameters
  301. && ((SspiSecurityTokenParameters)stp).RequireCancellation == false)
  302. return true;
  303. if (stp is X509SecurityTokenParameters)
  304. return true;
  305. }
  306. return false;
  307. }
  308. static public void Validate(ServiceDescription description)
  309. {
  310. ServiceAuthorizationBehavior behavior = description.Behaviors.Find<ServiceAuthorizationBehavior>();
  311. bool impersonateCallerForAllMethods = (behavior != null) ? behavior.ImpersonateCallerForAllOperations : false;
  312. for (int i = 0; i < description.Endpoints.Count; i++)
  313. {
  314. ServiceEndpoint endpoint = description.Endpoints[i];
  315. if (endpoint.InternalIsSystemEndpoint(description))
  316. {
  317. continue;
  318. }
  319. bool isImpersonationRequested = impersonateCallerForAllMethods;
  320. if (!isImpersonationRequested)
  321. {
  322. isImpersonationRequested = ValidatorUtils.EndpointRequiresImpersonation(endpoint);
  323. }
  324. if (isImpersonationRequested)
  325. {
  326. ICollection<BindingElement> bindingElements = endpoint.Binding.CreateBindingElements();
  327. foreach (BindingElement element in bindingElements)
  328. {
  329. SecurityBindingElement sbe = (element as SecurityBindingElement);
  330. if (sbe != null)
  331. {
  332. if (IsS4URequiredForImpersonation(sbe))
  333. {
  334. Version osVersion = Environment.OSVersion.Version;
  335. if ((osVersion.Major < WindowsServerMajorNumber)
  336. || ((osVersion.Major == WindowsServerMajorNumber) && (osVersion.Minor < WindowsServerMinorNumber)))
  337. {
  338. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  339. SR.GetString(SR.CannotPerformS4UImpersonationOnPlatform, endpoint.Binding.Name, endpoint.Binding.Namespace, endpoint.Contract.Name, endpoint.Contract.Namespace)));
  340. }
  341. }
  342. break;
  343. }
  344. }
  345. }
  346. }
  347. }
  348. }
  349. static class UnknownHeaderProtectionRequirementsRule
  350. {
  351. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  352. {
  353. if (sbe is SymmetricSecurityBindingElement || sbe is AsymmetricSecurityBindingElement)
  354. ValidateContract(binding, contract, sbe.GetIndividualProperty<ISecurityCapabilities>().SupportedRequestProtectionLevel, sbe.GetIndividualProperty<ISecurityCapabilities>().SupportedResponseProtectionLevel);
  355. else
  356. ValidateContract(binding, contract, ProtectionLevel.None, ProtectionLevel.None);
  357. }
  358. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  359. {
  360. ValidateContract(binding, contract, ProtectionLevel.None, ProtectionLevel.None);
  361. }
  362. static void ValidateContract(Binding binding, ContractDescription contract, ProtectionLevel defaultRequestProtectionLevel, ProtectionLevel defaultResponseProtectionLevel)
  363. {
  364. if (contract == null)
  365. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("contract"));
  366. ProtectionLevel contractScopeDefaultRequestProtectionLevel;
  367. ProtectionLevel contractScopeDefaultResponseProtectionLevel;
  368. if (contract.HasProtectionLevel)
  369. {
  370. contractScopeDefaultRequestProtectionLevel = contract.ProtectionLevel;
  371. contractScopeDefaultResponseProtectionLevel = contract.ProtectionLevel;
  372. }
  373. else
  374. {
  375. contractScopeDefaultRequestProtectionLevel = defaultRequestProtectionLevel;
  376. contractScopeDefaultResponseProtectionLevel = defaultResponseProtectionLevel;
  377. }
  378. foreach (OperationDescription operation in contract.Operations)
  379. {
  380. ProtectionLevel operationScopeDefaultRequestProtectionLevel;
  381. ProtectionLevel operationScopeDefaultResponseProtectionLevel;
  382. if (operation.HasProtectionLevel)
  383. {
  384. operationScopeDefaultRequestProtectionLevel = operation.ProtectionLevel;
  385. operationScopeDefaultResponseProtectionLevel = operation.ProtectionLevel;
  386. }
  387. else
  388. {
  389. operationScopeDefaultRequestProtectionLevel = contractScopeDefaultRequestProtectionLevel;
  390. operationScopeDefaultResponseProtectionLevel = contractScopeDefaultResponseProtectionLevel;
  391. }
  392. foreach (MessageDescription message in operation.Messages)
  393. {
  394. ProtectionLevel messageScopeDefaultProtectionLevel;
  395. if (message.HasProtectionLevel)
  396. {
  397. messageScopeDefaultProtectionLevel = message.ProtectionLevel;
  398. }
  399. else if (message.Direction == MessageDirection.Input)
  400. {
  401. messageScopeDefaultProtectionLevel = operationScopeDefaultRequestProtectionLevel;
  402. }
  403. else
  404. {
  405. messageScopeDefaultProtectionLevel = operationScopeDefaultResponseProtectionLevel;
  406. }
  407. foreach (MessageHeaderDescription header in message.Headers)
  408. {
  409. ProtectionLevel headerScopeDefaultProtectionLevel;
  410. if (header.HasProtectionLevel)
  411. headerScopeDefaultProtectionLevel = header.ProtectionLevel;
  412. else
  413. headerScopeDefaultProtectionLevel = messageScopeDefaultProtectionLevel;
  414. //
  415. // Finally we figured out the protection level for the individual header.
  416. // We need to throw if the header is some unknown header, i.e., user can stick any Xml frag
  417. // at the runtime, AND, its protection level is not ProtectionLevel.None
  418. //
  419. if (header.IsUnknownHeaderCollection && headerScopeDefaultProtectionLevel != ProtectionLevel.None)
  420. {
  421. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnknownHeaderCannotProtected, contract.Name, contract.Namespace, header.Name, header.Namespace)));
  422. }
  423. }
  424. }
  425. }
  426. }
  427. }
  428. static class ContractProtectionRequirementsRule
  429. {
  430. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  431. {
  432. if (sbe is SymmetricSecurityBindingElement || sbe is AsymmetricSecurityBindingElement)
  433. ValidateContract(binding, contract, sbe.GetIndividualProperty<ISecurityCapabilities>().SupportedRequestProtectionLevel, sbe.GetIndividualProperty<ISecurityCapabilities>().SupportedResponseProtectionLevel);
  434. else
  435. ValidateContract(binding, contract, ProtectionLevel.None, ProtectionLevel.None);
  436. }
  437. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  438. {
  439. ValidateContract(binding, contract, ProtectionLevel.None, ProtectionLevel.None);
  440. }
  441. static void ValidateContract(Binding binding, ContractDescription contract, ProtectionLevel defaultRequestProtectionLevel, ProtectionLevel defaultResponseProtectionLevel)
  442. {
  443. ProtectionLevel requestProtectionLevel;
  444. ProtectionLevel responseProtectionLevel;
  445. GetRequiredProtectionLevels(contract, defaultRequestProtectionLevel, defaultResponseProtectionLevel, out requestProtectionLevel, out responseProtectionLevel);
  446. ValidateBindingProtectionCapability(binding, contract, requestProtectionLevel, responseProtectionLevel);
  447. }
  448. static internal void GetRequiredProtectionLevels(ContractDescription contract, ProtectionLevel defaultRequestProtectionLevel, ProtectionLevel defaultResponseProtectionLevel, out ProtectionLevel request, out ProtectionLevel response)
  449. {
  450. ChannelProtectionRequirements requirements = ChannelProtectionRequirements.CreateFromContract(contract, defaultRequestProtectionLevel, defaultResponseProtectionLevel, false);
  451. if (requirements.IncomingSignatureParts.IsEmpty())
  452. {
  453. request = ProtectionLevel.None;
  454. }
  455. else if (requirements.IncomingEncryptionParts.IsEmpty())
  456. {
  457. request = ProtectionLevel.Sign;
  458. }
  459. else
  460. {
  461. request = ProtectionLevel.EncryptAndSign;
  462. }
  463. if (requirements.OutgoingSignatureParts.IsEmpty())
  464. {
  465. response = ProtectionLevel.None;
  466. }
  467. else if (requirements.OutgoingEncryptionParts.IsEmpty())
  468. {
  469. response = ProtectionLevel.Sign;
  470. }
  471. else
  472. {
  473. response = ProtectionLevel.EncryptAndSign;
  474. }
  475. }
  476. static void ValidateBindingProtectionCapability(Binding binding, ContractDescription contract, ProtectionLevel request, ProtectionLevel response)
  477. {
  478. bool requestValidated = request == ProtectionLevel.None;
  479. bool responseValidated = response == ProtectionLevel.None;
  480. if (!requestValidated || !responseValidated)
  481. {
  482. ISecurityCapabilities capabilities = binding.GetProperty<ISecurityCapabilities>(new BindingParameterCollection());
  483. if (capabilities != null)
  484. {
  485. if (!requestValidated)
  486. {
  487. requestValidated = ProtectionLevelHelper.IsStrongerOrEqual(capabilities.SupportedRequestProtectionLevel, request);
  488. }
  489. if (!responseValidated)
  490. {
  491. responseValidated = ProtectionLevelHelper.IsStrongerOrEqual(capabilities.SupportedResponseProtectionLevel, response);
  492. }
  493. }
  494. }
  495. if (!requestValidated)
  496. {
  497. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  498. SR.GetString(SR.AtLeastOneContractOperationRequestRequiresProtectionLevelNotSupportedByBinding, contract.Name, contract.Namespace, binding.Name, binding.Namespace)));
  499. }
  500. if (!responseValidated)
  501. {
  502. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  503. SR.GetString(SR.AtLeastOneContractOperationResponseRequiresProtectionLevelNotSupportedByBinding, contract.Name, contract.Namespace, binding.Name, binding.Namespace)));
  504. }
  505. }
  506. }
  507. static class BearerKeyTypeIssuanceRequirementRule
  508. {
  509. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  510. {
  511. foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
  512. {
  513. if (stp is IssuedSecurityTokenParameters)
  514. {
  515. IssuedSecurityTokenParameters issuedParameters = stp as IssuedSecurityTokenParameters;
  516. if (issuedParameters.KeyType == System.IdentityModel.Tokens.SecurityKeyType.BearerKey)
  517. {
  518. // The issued Bearer token cannot be used as the primary protection token and it cannot be
  519. // used as a Endorsing or Signed Endorsing token.
  520. if ((sbe is SymmetricSecurityBindingElement) && IsBearerKeyType(((SymmetricSecurityBindingElement)sbe).ProtectionTokenParameters))
  521. {
  522. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidBearerKeyUsage, binding.Name, binding.Namespace)));
  523. }
  524. if ((sbe is AsymmetricSecurityBindingElement) && (IsBearerKeyType(((AsymmetricSecurityBindingElement)sbe).InitiatorTokenParameters) || IsBearerKeyType(((AsymmetricSecurityBindingElement)sbe).RecipientTokenParameters)))
  525. {
  526. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidBearerKeyUsage, binding.Name, binding.Namespace)));
  527. }
  528. foreach (SecurityTokenParameters tokenParam in sbe.EndpointSupportingTokenParameters.Endorsing)
  529. {
  530. if (IsBearerKeyType(tokenParam))
  531. {
  532. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidBearerKeyUsage, binding.Name, binding.Namespace)));
  533. }
  534. }
  535. foreach (SecurityTokenParameters tokenParam in sbe.EndpointSupportingTokenParameters.SignedEndorsing)
  536. {
  537. if (IsBearerKeyType(tokenParam))
  538. {
  539. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidBearerKeyUsage, binding.Name, binding.Namespace)));
  540. }
  541. }
  542. }
  543. if (issuedParameters.IssuerBinding != null)
  544. {
  545. SecurityBindingElement secBindingEle = SecurityValidationBehavior.GetSecurityBinding(issuedParameters.IssuerBinding, contract);
  546. if (secBindingEle != null)
  547. ValidateSecurityBinding(secBindingEle, issuedParameters.IssuerBinding, contract);
  548. }
  549. }
  550. else if (stp is SecureConversationSecurityTokenParameters)
  551. {
  552. SecureConversationSecurityTokenParameters scParameters = stp as SecureConversationSecurityTokenParameters;
  553. ValidateSecurityBinding(scParameters.BootstrapSecurityBindingElement, binding, contract);
  554. }
  555. }
  556. }
  557. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  558. {
  559. }
  560. static bool IsBearerKeyType(SecurityTokenParameters tokenParameters)
  561. {
  562. if (!(tokenParameters is IssuedSecurityTokenParameters))
  563. return false;
  564. return ((IssuedSecurityTokenParameters)tokenParameters).KeyType == SecurityKeyType.BearerKey;
  565. }
  566. }
  567. static class CookieAndSessionProtectionRequirementsRule
  568. {
  569. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  570. {
  571. if (!(sbe is TransportSecurityBindingElement))
  572. foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
  573. {
  574. SecureConversationSecurityTokenParameters scstp = stp as SecureConversationSecurityTokenParameters;
  575. if (scstp != null)
  576. {
  577. ISecurityCapabilities bootstrapSecurityCapabilities = scstp.BootstrapSecurityBindingElement.GetIndividualProperty<ISecurityCapabilities>();
  578. if (bootstrapSecurityCapabilities != null
  579. && bootstrapSecurityCapabilities.SupportedRequestProtectionLevel == ProtectionLevel.EncryptAndSign
  580. && bootstrapSecurityCapabilities.SupportedResponseProtectionLevel == ProtectionLevel.EncryptAndSign)
  581. {
  582. continue;
  583. }
  584. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  585. SR.GetString(SR.BindingDoesNotSupportProtectionForRst, binding.Name, binding.Namespace, contract.Name, contract.Namespace)));
  586. }
  587. }
  588. }
  589. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  590. {
  591. }
  592. }
  593. static class SoapOverSecureTransportRequirementsRule
  594. {
  595. static public void ValidateSecurityBinding(SecurityBindingElement securityBindingElement, Binding binding, ContractDescription contract)
  596. {
  597. if (securityBindingElement is TransportSecurityBindingElement && !securityBindingElement.AllowInsecureTransport)
  598. {
  599. // ensure that if soap security cookie/session is configured, then the authentication mode supports encryption
  600. IEnumerable<BindingElement> elements = binding.CreateBindingElements();
  601. Collection<BindingElement> bindingElementStack = new Collection<BindingElement>();
  602. bool isBelowSecurity = false;
  603. foreach (BindingElement element in elements)
  604. {
  605. SecurityBindingElement sbe = element as SecurityBindingElement;
  606. if (sbe != null)
  607. {
  608. isBelowSecurity = true;
  609. }
  610. else if (isBelowSecurity)
  611. {
  612. bindingElementStack.Add(element);
  613. }
  614. }
  615. bool isTransportProtected = false;
  616. if (bindingElementStack.Count != 0)
  617. {
  618. BindingContext context = new BindingContext(new CustomBinding(bindingElementStack), new BindingParameterCollection());
  619. ISecurityCapabilities transportCapabilities = context.GetInnerProperty<ISecurityCapabilities>();
  620. if (transportCapabilities != null
  621. && transportCapabilities.SupportsServerAuthentication
  622. && transportCapabilities.SupportedRequestProtectionLevel == ProtectionLevel.EncryptAndSign
  623. && transportCapabilities.SupportedResponseProtectionLevel == ProtectionLevel.EncryptAndSign)
  624. {
  625. isTransportProtected = true;
  626. }
  627. }
  628. if (!isTransportProtected)
  629. {
  630. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  631. SR.GetString(SR.TransportDoesNotProtectMessage, binding.Name, binding.Namespace, contract.Name, contract.Namespace)));
  632. }
  633. }
  634. }
  635. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  636. {
  637. }
  638. }
  639. static class IssuedKeySizeCompatibilityWithAlgorithmSuiteRule
  640. {
  641. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  642. {
  643. SecurityAlgorithmSuite algorithmSuite = sbe.DefaultAlgorithmSuite;
  644. foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
  645. {
  646. if (stp is IssuedSecurityTokenParameters)
  647. {
  648. IssuedSecurityTokenParameters issuedParameters = stp as IssuedSecurityTokenParameters;
  649. if (issuedParameters.KeySize != 0)
  650. {
  651. bool isCompatible = true;
  652. if (issuedParameters.KeyType == System.IdentityModel.Tokens.SecurityKeyType.SymmetricKey &&
  653. !sbe.DefaultAlgorithmSuite.IsSymmetricKeyLengthSupported(issuedParameters.KeySize))
  654. {
  655. isCompatible = false;
  656. }
  657. else if (issuedParameters.KeyType == System.IdentityModel.Tokens.SecurityKeyType.AsymmetricKey &&
  658. !sbe.DefaultAlgorithmSuite.IsAsymmetricKeyLengthSupported(issuedParameters.KeySize))
  659. {
  660. isCompatible = false;
  661. }
  662. if (!isCompatible)
  663. {
  664. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.IssuedKeySizeNotCompatibleWithAlgorithmSuite, binding.Name, binding.Namespace, sbe.DefaultAlgorithmSuite, issuedParameters.KeySize)));
  665. }
  666. }
  667. }
  668. else if (stp is SecureConversationSecurityTokenParameters)
  669. {
  670. SecureConversationSecurityTokenParameters scParameters = stp as SecureConversationSecurityTokenParameters;
  671. ValidateSecurityBinding(scParameters.BootstrapSecurityBindingElement, binding, contract);
  672. }
  673. }
  674. }
  675. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  676. {
  677. }
  678. }
  679. static class SecurityTokenParameterInclusionModeRule
  680. {
  681. static void EnforceInclusionMode(Binding binding, SecurityTokenParameters stp, params SecurityTokenInclusionMode[] allowedInclusionModes)
  682. {
  683. bool isMatch = false;
  684. for (int i = 0; i < allowedInclusionModes.Length; ++i)
  685. {
  686. if (stp.InclusionMode == allowedInclusionModes[i])
  687. {
  688. isMatch = true;
  689. break;
  690. }
  691. }
  692. if (!isMatch)
  693. {
  694. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecurityTokenParametersHasIncompatibleInclusionMode, binding.Name, binding.Namespace, stp.GetType(), stp.InclusionMode, allowedInclusionModes[0])));
  695. }
  696. }
  697. static public void Validate(SecurityBindingElement sbe, Binding binding, ContractDescription contract, KeyedByTypeCollection<IServiceBehavior> behaviors)
  698. {
  699. if (behaviors != null)
  700. {
  701. ServiceCredentials serviceCredentials = behaviors.Find<ServiceCredentials>();
  702. if (serviceCredentials != null && serviceCredentials.GetType() != typeof(ServiceCredentials))
  703. {
  704. // A custom service credentials has been plugged in. Dont validate the binding
  705. return;
  706. }
  707. }
  708. SymmetricSecurityBindingElement ssbe = (sbe as SymmetricSecurityBindingElement);
  709. AsymmetricSecurityBindingElement asbe = (sbe as AsymmetricSecurityBindingElement);
  710. foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
  711. {
  712. if (stp is RsaSecurityTokenParameters)
  713. {
  714. // rsa keys can only be referred to using keyinfo. There's no wire format for
  715. // serializing them
  716. EnforceInclusionMode(binding, stp, SecurityTokenInclusionMode.Never);
  717. continue;
  718. }
  719. if (stp is SecureConversationSecurityTokenParameters)
  720. {
  721. Validate(((SecureConversationSecurityTokenParameters)stp).BootstrapSecurityBindingElement, binding, contract, behaviors);
  722. }
  723. if (ssbe != null)
  724. {
  725. // for the protection token, if it is asymmetric inclusion mode should be Never
  726. // all other cases inclusion mode should be AlwaysToRecipient/Once
  727. if (ssbe.ProtectionTokenParameters == stp && stp.HasAsymmetricKey)
  728. {
  729. EnforceInclusionMode(binding, stp, SecurityTokenInclusionMode.Never);
  730. }
  731. else
  732. {
  733. EnforceInclusionMode(binding, stp, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenInclusionMode.Once);
  734. }
  735. }
  736. else if (asbe != null)
  737. {
  738. if (asbe.InitiatorTokenParameters == stp && stp.HasAsymmetricKey)
  739. {
  740. // allow AlwaysToRecipient, Once and AlwaysToInitiator in this case since the duplex binding
  741. // configures AlwaysToInitiator in this case
  742. EnforceInclusionMode(binding, stp, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenInclusionMode.AlwaysToInitiator, SecurityTokenInclusionMode.Once);
  743. }
  744. else
  745. {
  746. EnforceInclusionMode(binding, stp, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenInclusionMode.Once);
  747. }
  748. }
  749. else
  750. {
  751. EnforceInclusionMode(binding, stp, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenInclusionMode.Once);
  752. }
  753. }
  754. }
  755. }
  756. static class SecurityVersionSupportForEncryptedKeyBindingRule
  757. {
  758. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  759. {
  760. SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
  761. if (sbe.MessageSecurityVersion.SecurityVersion == SecurityVersion.WSSecurity10
  762. && ssbe != null
  763. && ssbe.ProtectionTokenParameters != null
  764. && ssbe.ProtectionTokenParameters.HasAsymmetricKey)
  765. {
  766. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  767. SR.GetString(SR.SecurityVersionDoesNotSupportEncryptedKeyBinding, binding.Name, binding.Namespace, contract.Name, contract.Namespace, SecurityVersion.WSSecurity11)));
  768. }
  769. }
  770. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  771. {
  772. }
  773. }
  774. static class SecurityVersionSupportForThumbprintKeyIdentifierClauseRule
  775. {
  776. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  777. {
  778. if (sbe.MessageSecurityVersion.SecurityVersion == SecurityVersion.WSSecurity10)
  779. {
  780. foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe))
  781. {
  782. X509SecurityTokenParameters x509 = stp as X509SecurityTokenParameters;
  783. if (x509 != null && x509.X509ReferenceStyle == X509KeyIdentifierClauseType.Thumbprint)
  784. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  785. SR.GetString(SR.SecurityVersionDoesNotSupportThumbprintX509KeyIdentifierClause, binding.Name, binding.Namespace, contract.Name, contract.Namespace, SecurityVersion.WSSecurity11)));
  786. }
  787. }
  788. }
  789. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  790. {
  791. }
  792. }
  793. static class MessageSecurityAndManualAddressingRule
  794. {
  795. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  796. {
  797. TransportBindingElement transport = binding.CreateBindingElements().Find<TransportBindingElement>();
  798. if (transport != null && transport.ManualAddressing)
  799. {
  800. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  801. SR.GetString(SR.MessageSecurityDoesNotWorkWithManualAddressing, binding.Name, binding.Namespace)));
  802. }
  803. }
  804. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  805. {
  806. }
  807. }
  808. static class SecurityBindingSupportForOneWayOnlyRule
  809. {
  810. static public void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding, ContractDescription contract)
  811. {
  812. if (sbe is AsymmetricSecurityBindingElement && ((AsymmetricSecurityBindingElement)sbe).IsCertificateSignatureBinding)
  813. {
  814. for (int i = 0; i < contract.Operations.Count; i++)
  815. {
  816. OperationDescription operation = contract.Operations[i];
  817. if (!operation.IsOneWay)
  818. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  819. SR.GetString(SR.SecurityBindingSupportsOneWayOnly, binding.Name, binding.Namespace, contract.Name, contract.Namespace)));
  820. }
  821. }
  822. }
  823. static public void ValidateNoSecurityBinding(Binding binding, ContractDescription contract)
  824. {
  825. }
  826. }
  827. static class MissingClientCertificateRule
  828. {
  829. static void ValidateCore(ServiceDescription description, ServiceCredentials credentials)
  830. {
  831. for (int i = 0; i < description.Endpoints.Count; i++)
  832. {
  833. ServiceEndpoint endpoint = description.Endpoints[i];
  834. BindingElementCollection elements = endpoint.Binding.CreateBindingElements();
  835. SecurityBindingElement security = elements.Find<SecurityBindingElement>();
  836. CompositeDuplexBindingElement duplex = elements.Find<CompositeDuplexBindingElement>();
  837. if (security != null && duplex != null && SecurityBindingElement.IsMutualCertificateDuplexBinding(security))
  838. {
  839. //
  840. // We only throw when we have
  841. // 1. a MutualCertificateDuplexBindingElement,
  842. // 2. missing client certificate on the service side
  843. // 3. The server will encrypt the response, or the message going from server to client
  844. //
  845. if (credentials.ClientCertificate.Certificate == null)
  846. {
  847. ProtectionLevel requestProtectionLevel;
  848. ProtectionLevel responseProtectionLevel;
  849. ContractProtectionRequirementsRule.GetRequiredProtectionLevels(endpoint.Contract, security.GetIndividualProperty<ISecurityCapabilities>().SupportedRequestProtectionLevel, security.GetIndividualProperty<ISecurityCapabilities>().SupportedResponseProtectionLevel,
  850. out requestProtectionLevel, out responseProtectionLevel);
  851. if (responseProtectionLevel == ProtectionLevel.EncryptAndSign)
  852. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NoClientCertificate, endpoint.Binding.Name, endpoint.Binding.Namespace)));
  853. }
  854. }
  855. }
  856. }
  857. static public void Validate(ServiceDescription description)
  858. {
  859. //
  860. // Verify if the service credentials are not customized
  861. //
  862. if (!description.Behaviors.Contains(typeof(ServiceCredentials)))
  863. return;
  864. ValidateCore(description, description.Behaviors.Find<ServiceCredentials>());
  865. }
  866. }
  867. static class UsernameImpersonationRule
  868. {
  869. [MethodImpl(MethodImplOptions.NoInlining)]
  870. static void ValidateCore(ServiceDescription description, ServiceCredentials credentials)
  871. {
  872. if (credentials.UserNameAuthentication.UserNamePasswordValidationMode == UserNamePasswordValidationMode.Windows)
  873. {
  874. return;
  875. }
  876. ServiceAuthorizationBehavior behavior = description.Behaviors.Find<ServiceAuthorizationBehavior>();
  877. bool impersonateCallerForAllMethods = (behavior != null) ? behavior.ImpersonateCallerForAllOperations : false;
  878. for (int i = 0; i < description.Endpoints.Count; i++)
  879. {
  880. ServiceEndpoint endpoint = description.Endpoints[i];
  881. if (endpoint.InternalIsSystemEndpoint(description))
  882. {
  883. continue;
  884. }
  885. if (ValidatorUtils.IsStandardBinding(endpoint.Binding))
  886. {
  887. bool isImpersonationRequested = impersonateCallerForAllMethods;
  888. if (!isImpersonationRequested)
  889. {
  890. isImpersonationRequested = ValidatorUtils.EndpointRequiresImpersonation(endpoint);
  891. }
  892. if (isImpersonationRequested)
  893. {
  894. ICollection<BindingElement> bindingElements = endpoint.Binding.CreateBindingElements();
  895. foreach (BindingElement element in bindingElements)
  896. {
  897. SecurityBindingElement sbe = (element as SecurityBindingElement);
  898. if (sbe != null)
  899. {
  900. ValidateSecurityBindingElement(sbe, endpoint);
  901. break;
  902. }
  903. }
  904. }
  905. }
  906. }
  907. }
  908. static public void Validate(ServiceDescription description)
  909. {
  910. ServiceCredentials credentials = description.Behaviors.Find<ServiceCredentials>();
  911. if (credentials == null)
  912. return;
  913. ValidateCore(description, credentials);
  914. }
  915. static private void ValidateSecurityBindingElement(SecurityBindingElement sbe, ServiceEndpoint endpoint)
  916. {
  917. if (sbe == null)
  918. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sbe");
  919. if (endpoint == null)
  920. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
  921. foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true))
  922. {
  923. if (stp is UserNameSecurityTokenParameters)
  924. {
  925. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotPerformImpersonationOnUsernameToken, endpoint.Binding.Name, endpoint.Binding.Namespace, endpoint.Contract.Name, endpoint.Contract.Namespace)));
  926. }
  927. else if (stp is SecureConversationSecurityTokenParameters)
  928. {
  929. ValidateSecurityBindingElement(((SecureConversationSecurityTokenParameters)stp).BootstrapSecurityBindingElement, endpoint);
  930. }
  931. }
  932. }
  933. }
  934. static class ValidatorUtils
  935. {
  936. static public bool EndpointRequiresImpersonation(ServiceEndpoint endpoint)
  937. {
  938. if (endpoint == null)
  939. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
  940. for (int i = 0; i < endpoint.Contract.Operations.Count; ++i)
  941. {
  942. OperationDescription operation = endpoint.Contract.Operations[i];
  943. OperationBehaviorAttribute operationBehavior = operation.Behaviors.Find<OperationBehaviorAttribute>();
  944. if (operationBehavior != null && (operationBehavior.Impersonation == ImpersonationOption.Required))
  945. {
  946. return true;
  947. }
  948. }
  949. return false;
  950. }
  951. static public bool IsStandardBinding(Binding binding)
  952. {
  953. return (binding is BasicHttpBinding) ||
  954. (binding is BasicHttpsBinding) ||
  955. (binding is NetTcpBinding) ||
  956. (binding is NetMsmqBinding) ||
  957. (binding is NetNamedPipeBinding) ||
  958. #pragma warning disable 0618
  959. (binding is NetPeerTcpBinding) ||
  960. #pragma warning restore 0618
  961. (binding is WSDualHttpBinding) ||
  962. (binding is WSFederationHttpBinding) ||
  963. (binding is WSHttpBinding) ||
  964. (binding is NetHttpBinding) ||
  965. (binding is NetHttpsBinding);
  966. }
  967. }
  968. }
  969. }