1 // 2 // MessageSecurityBindingSupport.cs 3 // 4 // Author: 5 // Atsushi Enomoto <atsushi@ximian.com> 6 // 7 // Copyright (C) 2005-2007 Novell, Inc. http://www.novell.com 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining 10 // a copy of this software and associated documentation files (the 11 // "Software"), to deal in the Software without restriction, including 12 // without limitation the rights to use, copy, modify, merge, publish, 13 // distribute, sublicense, and/or sell copies of the Software, and to 14 // permit persons to whom the Software is furnished to do so, subject to 15 // the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 // 28 using System.Collections.Generic; 29 using System.Collections.ObjectModel; 30 using System.IdentityModel.Selectors; 31 using System.IdentityModel.Tokens; 32 using System.Net.Security; 33 using System.Security.Cryptography.Xml; 34 using System.ServiceModel.Channels; 35 using System.ServiceModel.Description; 36 using System.ServiceModel.Security; 37 using System.ServiceModel.Security.Tokens; 38 39 using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement; 40 41 namespace System.ServiceModel.Channels.Security 42 { 43 internal abstract class MessageSecurityBindingSupport 44 { 45 SecurityTokenManager manager; 46 ChannelProtectionRequirements requirements; 47 SecurityTokenSerializer serializer; 48 SecurityCapabilities element_support; 49 50 // only filled at prepared state. 51 SecurityTokenAuthenticator authenticator; 52 SecurityTokenResolver auth_token_resolver; 53 MessageSecurityBindingSupport( SecurityCapabilities elementSupport, SecurityTokenManager manager, ChannelProtectionRequirements requirements)54 protected MessageSecurityBindingSupport ( 55 SecurityCapabilities elementSupport, 56 SecurityTokenManager manager, 57 ChannelProtectionRequirements requirements) 58 { 59 element_support = elementSupport; 60 Initialize (manager, requirements); 61 } 62 Initialize(SecurityTokenManager manager, ChannelProtectionRequirements requirements)63 public void Initialize (SecurityTokenManager manager, 64 ChannelProtectionRequirements requirements) 65 { 66 this.manager = manager; 67 if (requirements == null) 68 requirements = new ChannelProtectionRequirements (); 69 this.requirements = requirements; 70 } 71 72 public abstract IDefaultCommunicationTimeouts Timeouts { get; } 73 74 public ChannelProtectionRequirements ChannelRequirements { 75 get { return requirements; } 76 } 77 78 public SecurityTokenManager SecurityTokenManager { 79 get { return manager; } 80 } 81 82 public SecurityTokenSerializer TokenSerializer { 83 get { 84 if (serializer == null) 85 serializer = manager.CreateSecurityTokenSerializer (Element.MessageSecurityVersion.SecurityTokenVersion); 86 return serializer; 87 } 88 } 89 90 public SecurityTokenAuthenticator TokenAuthenticator { 91 get { return authenticator; } 92 } 93 94 public SecurityTokenResolver OutOfBandTokenResolver { 95 get { return auth_token_resolver; } 96 } 97 98 public abstract SecurityToken EncryptionToken { get; } 99 100 public abstract SecurityToken SigningToken { get; } 101 102 #region element_support 103 104 public SecurityBindingElement Element { 105 get { return element_support.Element; } 106 } 107 108 public bool AllowSerializedSigningTokenOnReply { 109 get { return element_support.AllowSerializedSigningTokenOnReply; } 110 } 111 112 public MessageProtectionOrder MessageProtectionOrder { 113 get { return element_support.MessageProtectionOrder; } 114 } 115 116 public SecurityTokenParameters InitiatorParameters { 117 get { return element_support.InitiatorParameters; } 118 } 119 120 public SecurityTokenParameters RecipientParameters { 121 get { return element_support.RecipientParameters; } 122 } 123 124 public bool RequireSignatureConfirmation { 125 get { return element_support.RequireSignatureConfirmation; } 126 } 127 128 public string DefaultSignatureAlgorithm { 129 get { return element_support.DefaultSignatureAlgorithm; } 130 } 131 132 public string DefaultKeyWrapAlgorithm { 133 get { return element_support.DefaultKeyWrapAlgorithm; } 134 } 135 136 #endregion 137 CreateTokenProvider(SecurityTokenRequirement requirement)138 public SecurityTokenProvider CreateTokenProvider (SecurityTokenRequirement requirement) 139 { 140 return manager.CreateSecurityTokenProvider (requirement); 141 } 142 CreateTokenAuthenticator(SecurityTokenParameters p, out SecurityTokenResolver resolver)143 public abstract SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver); 144 PrepareAuthenticator()145 protected void PrepareAuthenticator () 146 { 147 authenticator = CreateTokenAuthenticator (RecipientParameters, out auth_token_resolver); 148 } 149 InitializeRequirement(SecurityTokenParameters p, SecurityTokenRequirement r)150 protected void InitializeRequirement (SecurityTokenParameters p, SecurityTokenRequirement r) 151 { 152 p.CallInitializeSecurityTokenRequirement (r); 153 154 // r.Properties [ChannelParametersCollectionProperty] = 155 // r.Properties [ReqType.EndpointFilterTableProperty] = 156 // r.Properties [ReqType.HttpAuthenticationSchemeProperty] = 157 // r.Properties [ReqType.IsOutOfBandTokenProperty] = 158 // r.Properties [ReqType.IssuerAddressProperty] = 159 // r.Properties [ReqType.MessageDirectionProperty] = 160 r.Properties [ReqType.MessageSecurityVersionProperty] = Element.MessageSecurityVersion.SecurityTokenVersion; 161 r.Properties [ReqType.SecurityAlgorithmSuiteProperty] = Element.DefaultAlgorithmSuite; 162 r.Properties [ReqType.SecurityBindingElementProperty] = Element; 163 // r.Properties [ReqType.SupportingTokenAttachmentModeProperty] = 164 // r.TransportScheme = 165 } 166 Release()167 public void Release () 168 { 169 ReleaseCore (); 170 171 authenticator = null; 172 } 173 ReleaseCore()174 protected abstract void ReleaseCore (); 175 CollectSupportingTokens(string action)176 public SupportingTokenInfoCollection CollectSupportingTokens (string action) 177 { 178 SupportingTokenInfoCollection tokens = 179 new SupportingTokenInfoCollection (); 180 181 SupportingTokenParameters supp; 182 183 CollectSupportingTokensCore (tokens, Element.EndpointSupportingTokenParameters, true); 184 if (Element.OperationSupportingTokenParameters.TryGetValue (action, out supp)) 185 CollectSupportingTokensCore (tokens, supp, true); 186 CollectSupportingTokensCore (tokens, Element.OptionalEndpointSupportingTokenParameters, false); 187 if (Element.OptionalOperationSupportingTokenParameters.TryGetValue (action, out supp)) 188 CollectSupportingTokensCore (tokens, supp, false); 189 190 return tokens; 191 } 192 CollectSupportingTokensCore( SupportingTokenInfoCollection l, SupportingTokenParameters s, bool required)193 void CollectSupportingTokensCore ( 194 SupportingTokenInfoCollection l, 195 SupportingTokenParameters s, 196 bool required) 197 { 198 foreach (SecurityTokenParameters p in s.Signed) 199 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Signed, required)); 200 foreach (SecurityTokenParameters p in s.Endorsing) 201 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Endorsing, required)); 202 foreach (SecurityTokenParameters p in s.SignedEndorsing) 203 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEndorsing, required)); 204 foreach (SecurityTokenParameters p in s.SignedEncrypted) 205 l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEncrypted, required)); 206 } 207 GetSigningToken(SecurityTokenParameters p)208 SecurityToken GetSigningToken (SecurityTokenParameters p) 209 { 210 return GetToken (CreateRequirement (), p, SecurityKeyUsage.Signature); 211 } 212 GetExchangeToken(SecurityTokenParameters p)213 SecurityToken GetExchangeToken (SecurityTokenParameters p) 214 { 215 return GetToken (CreateRequirement (), p, SecurityKeyUsage.Exchange); 216 } 217 GetToken(SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage)218 public SecurityToken GetToken (SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage) 219 { 220 requirement.KeyUsage = usage; 221 requirement.Properties [ReqType.SecurityBindingElementProperty] = Element; 222 requirement.Properties [ReqType.MessageSecurityVersionProperty] = 223 Element.MessageSecurityVersion.SecurityTokenVersion; 224 225 InitializeRequirement (targetParams, requirement); 226 227 SecurityTokenProvider provider = 228 CreateTokenProvider (requirement); 229 ICommunicationObject obj = provider as ICommunicationObject; 230 try { 231 if (obj != null) 232 obj.Open (Timeouts.OpenTimeout); 233 return provider.GetToken (Timeouts.SendTimeout); 234 } finally { 235 if (obj != null && obj.State == CommunicationState.Opened) 236 obj.Close (); 237 } 238 } 239 CreateRequirement()240 public abstract SecurityTokenRequirement CreateRequirement (); 241 } 242 243 internal class InitiatorMessageSecurityBindingSupport : MessageSecurityBindingSupport 244 { 245 ChannelFactoryBase factory; 246 EndpointAddress message_to; 247 SecurityToken encryption_token; 248 SecurityToken signing_token; 249 InitiatorMessageSecurityBindingSupport( SecurityCapabilities elementSupport, SecurityTokenManager manager, ChannelProtectionRequirements requirements)250 public InitiatorMessageSecurityBindingSupport ( 251 SecurityCapabilities elementSupport, 252 SecurityTokenManager manager, 253 ChannelProtectionRequirements requirements) 254 : base (elementSupport, manager, requirements) 255 { 256 } 257 258 public override IDefaultCommunicationTimeouts Timeouts { 259 get { return factory; } 260 } 261 Prepare(ChannelFactoryBase factory, EndpointAddress address)262 public void Prepare (ChannelFactoryBase factory, EndpointAddress address) 263 { 264 this.factory = factory; 265 this.message_to = address; 266 267 PrepareAuthenticator (); 268 269 // This check is almost extra, though it is needed 270 // to check correct signing token existence. 271 if (EncryptionToken == null) 272 throw new Exception ("INTERNAL ERROR"); 273 } 274 275 public override SecurityToken EncryptionToken { 276 get { 277 if (encryption_token == null) { 278 SecurityTokenRequirement r = CreateRequirement (); 279 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input; 280 InitializeRequirement (RecipientParameters, r); 281 encryption_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Exchange); 282 } 283 return encryption_token; 284 } 285 } 286 287 public override SecurityToken SigningToken { 288 get { 289 if (signing_token == null) { 290 SecurityTokenRequirement r = CreateRequirement (); 291 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input; 292 InitializeRequirement (InitiatorParameters, r); 293 signing_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Signature); 294 } 295 return signing_token; 296 } 297 } 298 ReleaseCore()299 protected override void ReleaseCore () 300 { 301 this.factory = null; 302 this.message_to = null; 303 304 IDisposable disposable = signing_token as IDisposable; 305 if (disposable != null) 306 disposable.Dispose (); 307 signing_token = null; 308 309 disposable = encryption_token as IDisposable; 310 if (disposable != null) 311 disposable.Dispose (); 312 encryption_token = null; 313 } 314 CreateRequirement()315 public override SecurityTokenRequirement CreateRequirement () 316 { 317 SecurityTokenRequirement r = new InitiatorServiceModelSecurityTokenRequirement (); 318 // r.Properties [ReqType.IssuerAddressProperty] = message_to; 319 r.Properties [ReqType.TargetAddressProperty] = message_to; 320 // FIXME: set Via 321 return r; 322 } 323 CreateTokenAuthenticator(SecurityTokenParameters p, out SecurityTokenResolver resolver)324 public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver) 325 { 326 resolver = null; 327 // This check might be almost extra, though it is 328 // needed to check correct signing token existence. 329 // 330 // Not sure if it is limited to this condition, but 331 // Ssl parameters do not support token provider and 332 // still do not fail. X509 parameters do fail. 333 if (!InitiatorParameters.InternalSupportsClientAuthentication) 334 return null; 335 336 SecurityTokenRequirement r = CreateRequirement (); 337 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output; 338 InitializeRequirement (p, r); 339 return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver); 340 } 341 } 342 343 class RecipientMessageSecurityBindingSupport : MessageSecurityBindingSupport 344 { 345 ChannelListenerBase listener; 346 Uri listen_uri; 347 SecurityToken encryption_token; 348 SecurityToken signing_token; 349 RecipientMessageSecurityBindingSupport( SecurityCapabilities elementSupport, SecurityTokenManager manager, ChannelProtectionRequirements requirements)350 public RecipientMessageSecurityBindingSupport ( 351 SecurityCapabilities elementSupport, 352 SecurityTokenManager manager, 353 ChannelProtectionRequirements requirements) 354 : base (elementSupport, manager, requirements) 355 { 356 } 357 358 public override IDefaultCommunicationTimeouts Timeouts { 359 get { return listener; } 360 } 361 362 // FIXME: this is invoked inconsistently between SecurityReplyChannel and SecurityDuplexSessionChannel on when to do it. Prepare(ChannelListenerBase listener, Uri listenUri)363 public void Prepare (ChannelListenerBase listener, Uri listenUri) 364 { 365 this.listener = listener; 366 this.listen_uri = listenUri; 367 368 PrepareAuthenticator (); 369 370 // This check is almost extra, though it is needed 371 // to check correct signing token existence. 372 // 373 // Not sure if it is limited to this condition, but 374 // Ssl parameters do not support token provider and 375 // still do not fail. X509 parameters do fail. 376 // 377 // FIXME: as AsymmetricSecurityBindingElementTest 378 // .ServiceRecipientHasNoKeys() implies, it should be 379 // the recipient's parameters that is used. However 380 // such changes will break some of existing tests... 381 if (InitiatorParameters.InternalHasAsymmetricKey && 382 EncryptionToken == null) 383 throw new Exception ("INTERNAL ERROR"); 384 } 385 386 public override SecurityToken EncryptionToken { 387 get { 388 if (encryption_token == null) { 389 SecurityTokenRequirement r = CreateRequirement (); 390 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output; 391 encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange); 392 } 393 return encryption_token; 394 } 395 } 396 397 public override SecurityToken SigningToken { 398 get { 399 if (signing_token == null) { 400 SecurityTokenRequirement r = CreateRequirement (); 401 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input; 402 InitializeRequirement (RecipientParameters, r); 403 signing_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Signature); 404 } 405 return signing_token; 406 } 407 } 408 ReleaseCore()409 protected override void ReleaseCore () 410 { 411 this.listener = null; 412 413 IDisposable disposable = signing_token as IDisposable; 414 if (disposable != null) 415 disposable.Dispose (); 416 signing_token = null; 417 418 disposable = encryption_token as IDisposable; 419 if (disposable != null) 420 disposable.Dispose (); 421 encryption_token = null; 422 } 423 CreateRequirement()424 public override SecurityTokenRequirement CreateRequirement () 425 { 426 SecurityTokenRequirement requirement = 427 new RecipientServiceModelSecurityTokenRequirement (); 428 requirement.Properties [ReqType.ListenUriProperty] = listen_uri; 429 return requirement; 430 } 431 CreateTokenAuthenticator(SecurityTokenParameters p, out SecurityTokenResolver resolver)432 public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver) 433 { 434 resolver = null; 435 // This check might be almost extra, though it is 436 // needed to check correct signing token existence. 437 // 438 // Not sure if it is limited to this condition, but 439 // Ssl parameters do not support token provider and 440 // still do not fail. X509 parameters do fail. 441 if (!RecipientParameters.InternalSupportsServerAuthentication) 442 return null; 443 444 SecurityTokenRequirement r = CreateRequirement (); 445 r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input; 446 InitializeRequirement (p, r); 447 return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver); 448 } 449 } 450 } 451