Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
2010-07-15 Atsushi Enomoto <atsushi@ximian.com>
* SecurityReplyChannel.cs : when the inner channel gave null
context while returning true, also output null as context.
Throw an error if the inner authenticator is invalid.
2010-07-12 Atsushi Enomoto <atsushi@ximian.com>
* SecurityReplyChannel.cs : handle WS-Trust message here.
* SecurityRequestContext.cs : so, do not pass those messages here.
2010-07-12 Atsushi Enomoto <atsushi@ximian.com>
* MessageSecurityBindingSupport.cs : and move this to here too.
2010-07-12 Atsushi Enomoto <atsushi@ximian.com>
* SecurityCapabilities.cs, SupportingTokenInfo.cs :
new internal types, split from MessageSecurityBindingSupport.cs.
2010-07-12 Atsushi Enomoto <atsushi@ximian.com>
* SecurityRequestContext.cs : revert extra and bogus changes I had
locally.
2010-07-12 Atsushi Enomoto <atsushi@ximian.com>
* SecurityChannelFactory.cs
SecurityChannelListener.cs
SecurityRequestContext.cs
SecurityOutputChannel.cs
SecurityReplyChannel.cs
SecurityRequestChannel.cs
SecureMessageGenerator.cs
SecureMessageDecryptor.cs
WSEncryptedXml.cs
WSSignedXml.cs
WSSecurityMessageHeader.cs : moved from System.ServiceModel.Channels.

View File

@@ -0,0 +1,450 @@
//
// MessageSecurityBindingSupport.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2005-2007 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Net.Security;
using System.Security.Cryptography.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels.Security
{
internal abstract class MessageSecurityBindingSupport
{
SecurityTokenManager manager;
ChannelProtectionRequirements requirements;
SecurityTokenSerializer serializer;
SecurityCapabilities element_support;
// only filled at prepared state.
SecurityTokenAuthenticator authenticator;
SecurityTokenResolver auth_token_resolver;
protected MessageSecurityBindingSupport (
SecurityCapabilities elementSupport,
SecurityTokenManager manager,
ChannelProtectionRequirements requirements)
{
element_support = elementSupport;
Initialize (manager, requirements);
}
public void Initialize (SecurityTokenManager manager,
ChannelProtectionRequirements requirements)
{
this.manager = manager;
if (requirements == null)
requirements = new ChannelProtectionRequirements ();
this.requirements = requirements;
}
public abstract IDefaultCommunicationTimeouts Timeouts { get; }
public ChannelProtectionRequirements ChannelRequirements {
get { return requirements; }
}
public SecurityTokenManager SecurityTokenManager {
get { return manager; }
}
public SecurityTokenSerializer TokenSerializer {
get {
if (serializer == null)
serializer = manager.CreateSecurityTokenSerializer (Element.MessageSecurityVersion.SecurityTokenVersion);
return serializer;
}
}
public SecurityTokenAuthenticator TokenAuthenticator {
get { return authenticator; }
}
public SecurityTokenResolver OutOfBandTokenResolver {
get { return auth_token_resolver; }
}
public abstract SecurityToken EncryptionToken { get; }
public abstract SecurityToken SigningToken { get; }
#region element_support
public SecurityBindingElement Element {
get { return element_support.Element; }
}
public bool AllowSerializedSigningTokenOnReply {
get { return element_support.AllowSerializedSigningTokenOnReply; }
}
public MessageProtectionOrder MessageProtectionOrder {
get { return element_support.MessageProtectionOrder; }
}
public SecurityTokenParameters InitiatorParameters {
get { return element_support.InitiatorParameters; }
}
public SecurityTokenParameters RecipientParameters {
get { return element_support.RecipientParameters; }
}
public bool RequireSignatureConfirmation {
get { return element_support.RequireSignatureConfirmation; }
}
public string DefaultSignatureAlgorithm {
get { return element_support.DefaultSignatureAlgorithm; }
}
public string DefaultKeyWrapAlgorithm {
get { return element_support.DefaultKeyWrapAlgorithm; }
}
#endregion
public SecurityTokenProvider CreateTokenProvider (SecurityTokenRequirement requirement)
{
return manager.CreateSecurityTokenProvider (requirement);
}
public abstract SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver);
protected void PrepareAuthenticator ()
{
authenticator = CreateTokenAuthenticator (RecipientParameters, out auth_token_resolver);
}
protected void InitializeRequirement (SecurityTokenParameters p, SecurityTokenRequirement r)
{
p.CallInitializeSecurityTokenRequirement (r);
// r.Properties [ChannelParametersCollectionProperty] =
// r.Properties [ReqType.EndpointFilterTableProperty] =
// r.Properties [ReqType.HttpAuthenticationSchemeProperty] =
// r.Properties [ReqType.IsOutOfBandTokenProperty] =
// r.Properties [ReqType.IssuerAddressProperty] =
// r.Properties [ReqType.MessageDirectionProperty] =
r.Properties [ReqType.MessageSecurityVersionProperty] = Element.MessageSecurityVersion.SecurityTokenVersion;
r.Properties [ReqType.SecurityAlgorithmSuiteProperty] = Element.DefaultAlgorithmSuite;
r.Properties [ReqType.SecurityBindingElementProperty] = Element;
// r.Properties [ReqType.SupportingTokenAttachmentModeProperty] =
// r.TransportScheme =
}
public void Release ()
{
ReleaseCore ();
authenticator = null;
}
protected abstract void ReleaseCore ();
public SupportingTokenInfoCollection CollectSupportingTokens (string action)
{
SupportingTokenInfoCollection tokens =
new SupportingTokenInfoCollection ();
SupportingTokenParameters supp;
CollectSupportingTokensCore (tokens, Element.EndpointSupportingTokenParameters, true);
if (Element.OperationSupportingTokenParameters.TryGetValue (action, out supp))
CollectSupportingTokensCore (tokens, supp, true);
CollectSupportingTokensCore (tokens, Element.OptionalEndpointSupportingTokenParameters, false);
if (Element.OptionalOperationSupportingTokenParameters.TryGetValue (action, out supp))
CollectSupportingTokensCore (tokens, supp, false);
return tokens;
}
void CollectSupportingTokensCore (
SupportingTokenInfoCollection l,
SupportingTokenParameters s,
bool required)
{
foreach (SecurityTokenParameters p in s.Signed)
l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Signed, required));
foreach (SecurityTokenParameters p in s.Endorsing)
l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.Endorsing, required));
foreach (SecurityTokenParameters p in s.SignedEndorsing)
l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEndorsing, required));
foreach (SecurityTokenParameters p in s.SignedEncrypted)
l.Add (new SupportingTokenInfo (GetSigningToken (p), SecurityTokenAttachmentMode.SignedEncrypted, required));
}
SecurityToken GetSigningToken (SecurityTokenParameters p)
{
return GetToken (CreateRequirement (), p, SecurityKeyUsage.Signature);
}
SecurityToken GetExchangeToken (SecurityTokenParameters p)
{
return GetToken (CreateRequirement (), p, SecurityKeyUsage.Exchange);
}
public SecurityToken GetToken (SecurityTokenRequirement requirement, SecurityTokenParameters targetParams, SecurityKeyUsage usage)
{
requirement.KeyUsage = usage;
requirement.Properties [ReqType.SecurityBindingElementProperty] = Element;
requirement.Properties [ReqType.MessageSecurityVersionProperty] =
Element.MessageSecurityVersion.SecurityTokenVersion;
InitializeRequirement (targetParams, requirement);
SecurityTokenProvider provider =
CreateTokenProvider (requirement);
ICommunicationObject obj = provider as ICommunicationObject;
try {
if (obj != null)
obj.Open (Timeouts.OpenTimeout);
return provider.GetToken (Timeouts.SendTimeout);
} finally {
if (obj != null && obj.State == CommunicationState.Opened)
obj.Close ();
}
}
public abstract SecurityTokenRequirement CreateRequirement ();
}
internal class InitiatorMessageSecurityBindingSupport : MessageSecurityBindingSupport
{
ChannelFactoryBase factory;
EndpointAddress message_to;
SecurityToken encryption_token;
SecurityToken signing_token;
public InitiatorMessageSecurityBindingSupport (
SecurityCapabilities elementSupport,
SecurityTokenManager manager,
ChannelProtectionRequirements requirements)
: base (elementSupport, manager, requirements)
{
}
public override IDefaultCommunicationTimeouts Timeouts {
get { return factory; }
}
public void Prepare (ChannelFactoryBase factory, EndpointAddress address)
{
this.factory = factory;
this.message_to = address;
PrepareAuthenticator ();
// This check is almost extra, though it is needed
// to check correct signing token existence.
if (EncryptionToken == null)
throw new Exception ("INTERNAL ERROR");
}
public override SecurityToken EncryptionToken {
get {
if (encryption_token == null) {
SecurityTokenRequirement r = CreateRequirement ();
r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
InitializeRequirement (RecipientParameters, r);
encryption_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Exchange);
}
return encryption_token;
}
}
public override SecurityToken SigningToken {
get {
if (signing_token == null) {
SecurityTokenRequirement r = CreateRequirement ();
r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
InitializeRequirement (InitiatorParameters, r);
signing_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Signature);
}
return signing_token;
}
}
protected override void ReleaseCore ()
{
this.factory = null;
this.message_to = null;
IDisposable disposable = signing_token as IDisposable;
if (disposable != null)
disposable.Dispose ();
signing_token = null;
disposable = encryption_token as IDisposable;
if (disposable != null)
disposable.Dispose ();
encryption_token = null;
}
public override SecurityTokenRequirement CreateRequirement ()
{
SecurityTokenRequirement r = new InitiatorServiceModelSecurityTokenRequirement ();
// r.Properties [ReqType.IssuerAddressProperty] = message_to;
r.Properties [ReqType.TargetAddressProperty] = message_to;
// FIXME: set Via
return r;
}
public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
{
resolver = null;
// This check might be almost extra, though it is
// needed to check correct signing token existence.
//
// Not sure if it is limited to this condition, but
// Ssl parameters do not support token provider and
// still do not fail. X509 parameters do fail.
if (!InitiatorParameters.InternalSupportsClientAuthentication)
return null;
SecurityTokenRequirement r = CreateRequirement ();
r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
InitializeRequirement (p, r);
return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
}
}
class RecipientMessageSecurityBindingSupport : MessageSecurityBindingSupport
{
ChannelListenerBase listener;
Uri listen_uri;
SecurityToken encryption_token;
SecurityToken signing_token;
public RecipientMessageSecurityBindingSupport (
SecurityCapabilities elementSupport,
SecurityTokenManager manager,
ChannelProtectionRequirements requirements)
: base (elementSupport, manager, requirements)
{
}
public override IDefaultCommunicationTimeouts Timeouts {
get { return listener; }
}
// FIXME: this is invoked inconsistently between SecurityReplyChannel and SecurityDuplexSessionChannel on when to do it.
public void Prepare (ChannelListenerBase listener, Uri listenUri)
{
this.listener = listener;
this.listen_uri = listenUri;
PrepareAuthenticator ();
// This check is almost extra, though it is needed
// to check correct signing token existence.
//
// Not sure if it is limited to this condition, but
// Ssl parameters do not support token provider and
// still do not fail. X509 parameters do fail.
//
// FIXME: as AsymmetricSecurityBindingElementTest
// .ServiceRecipientHasNoKeys() implies, it should be
// the recipient's parameters that is used. However
// such changes will break some of existing tests...
if (InitiatorParameters.InternalHasAsymmetricKey &&
EncryptionToken == null)
throw new Exception ("INTERNAL ERROR");
}
public override SecurityToken EncryptionToken {
get {
if (encryption_token == null) {
SecurityTokenRequirement r = CreateRequirement ();
r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Output;
encryption_token = GetToken (r, InitiatorParameters, SecurityKeyUsage.Exchange);
}
return encryption_token;
}
}
public override SecurityToken SigningToken {
get {
if (signing_token == null) {
SecurityTokenRequirement r = CreateRequirement ();
r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
InitializeRequirement (RecipientParameters, r);
signing_token = GetToken (r, RecipientParameters, SecurityKeyUsage.Signature);
}
return signing_token;
}
}
protected override void ReleaseCore ()
{
this.listener = null;
IDisposable disposable = signing_token as IDisposable;
if (disposable != null)
disposable.Dispose ();
signing_token = null;
disposable = encryption_token as IDisposable;
if (disposable != null)
disposable.Dispose ();
encryption_token = null;
}
public override SecurityTokenRequirement CreateRequirement ()
{
SecurityTokenRequirement requirement =
new RecipientServiceModelSecurityTokenRequirement ();
requirement.Properties [ReqType.ListenUriProperty] = listen_uri;
return requirement;
}
public override SecurityTokenAuthenticator CreateTokenAuthenticator (SecurityTokenParameters p, out SecurityTokenResolver resolver)
{
resolver = null;
// This check might be almost extra, though it is
// needed to check correct signing token existence.
//
// Not sure if it is limited to this condition, but
// Ssl parameters do not support token provider and
// still do not fail. X509 parameters do fail.
if (!RecipientParameters.InternalSupportsServerAuthentication)
return null;
SecurityTokenRequirement r = CreateRequirement ();
r.Properties [ReqType.MessageDirectionProperty] = MessageDirection.Input;
InitializeRequirement (p, r);
return SecurityTokenManager.CreateSecurityTokenAuthenticator (r, out resolver);
}
}
}

View File

@@ -0,0 +1,451 @@
//
// SecureMessageDecryptor.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006-2007 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels.Security
{
internal class RecipientSecureMessageDecryptor : SecureMessageDecryptor
{
RecipientMessageSecurityBindingSupport security;
public RecipientSecureMessageDecryptor (
Message source, RecipientMessageSecurityBindingSupport security)
: base (source, security)
{
this.security = security;
}
public override MessageDirection Direction {
get { return MessageDirection.Input; }
}
public override SecurityMessageProperty RequestSecurity {
get { return null; }
}
public override SecurityTokenParameters Parameters {
get { return security.RecipientParameters; }
}
public override SecurityTokenParameters CounterParameters {
get { return security.InitiatorParameters; }
}
}
internal class InitiatorSecureMessageDecryptor : SecureMessageDecryptor
{
InitiatorMessageSecurityBindingSupport security;
SecurityMessageProperty request_security;
public InitiatorSecureMessageDecryptor (
Message source, SecurityMessageProperty secprop, InitiatorMessageSecurityBindingSupport security)
: base (source, security)
{
this.security = security;
request_security = secprop;
}
public override SecurityMessageProperty RequestSecurity {
get { return request_security; }
}
public override MessageDirection Direction {
get { return MessageDirection.Output; }
}
public override SecurityTokenParameters Parameters {
get { return security.InitiatorParameters; }
}
public override SecurityTokenParameters CounterParameters {
get { return security.RecipientParameters; }
}
}
internal abstract class SecureMessageDecryptor
{
Message source_message;
MessageBuffer buf;
MessageSecurityBindingSupport security;
XmlDocument doc;
XmlNamespaceManager nsmgr; // for XPath query
SecurityMessageProperty sec_prop =
new SecurityMessageProperty ();
WSSecurityMessageHeader wss_header = null;
WSSecurityMessageHeaderReader wss_header_reader;
List<MessageHeaderInfo> headers = new List<MessageHeaderInfo> ();
SecurityTokenResolver token_resolver;
List<SecurityToken> tokens;
protected SecureMessageDecryptor (
Message source, MessageSecurityBindingSupport security)
{
source_message = source;
this.security = security;
// FIXME: use proper max buffer
buf = source.CreateBufferedCopy (int.MaxValue);
//Console.WriteLine ("####### " + buf.CreateMessage ());
doc = new XmlDocument ();
doc.PreserveWhitespace = true;
nsmgr = new XmlNamespaceManager (doc.NameTable);
nsmgr.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
nsmgr.AddNamespace ("c", Constants.WsscNamespace);
nsmgr.AddNamespace ("o", Constants.WssNamespace);
nsmgr.AddNamespace ("e", EncryptedXml.XmlEncNamespaceUrl);
nsmgr.AddNamespace ("u", Constants.WsuNamespace);
nsmgr.AddNamespace ("dsig", SignedXml.XmlDsigNamespaceUrl);
}
public abstract MessageDirection Direction { get; }
public abstract SecurityTokenParameters Parameters { get; }
public abstract SecurityTokenParameters CounterParameters { get; }
public abstract SecurityMessageProperty RequestSecurity { get; }
public SecurityTokenResolver TokenResolver {
get { return token_resolver; }
}
public Message DecryptMessage ()
{
Message srcmsg = buf.CreateMessage ();
if (srcmsg.Version.Envelope == EnvelopeVersion.None)
throw new ArgumentException ("The message to decrypt is not an expected SOAP envelope.");
XPathNavigator nav = doc.CreateNavigator ();
using (XmlWriter writer = nav.AppendChild ()) {
buf.CreateMessage ().WriteMessage (writer);
}
/*
doc.PreserveWhitespace = false;
doc.Save (Console.Out);
doc.PreserveWhitespace = true;
*/
// read and store headers, wsse:Security and setup in-band resolver.
ReadHeaders (srcmsg);
ExtractSecurity ();
Message msg = Message.CreateMessage (new XmlNodeReader (doc), srcmsg.Headers.Count, srcmsg.Version);
for (int i = 0; i < srcmsg.Headers.Count; i++) {
MessageHeaderInfo header = srcmsg.Headers [i];
if (header == wss_header) {
msg.Headers.RemoveAt (i);
msg.Headers.Add (wss_header);
}
}
// FIXME: when Local[Client|Service]SecuritySettings.DetectReplays
// is true, reject such messages which don't have <wsu:Timestamp>
msg.Properties.Add ("Security", sec_prop);
return msg;
}
void ReadHeaders (Message srcmsg)
{
SecurityTokenSerializer serializer =
security.TokenSerializer;
tokens = new List<SecurityToken> ();
token_resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver (
new ReadOnlyCollection <SecurityToken> (tokens),
true);
token_resolver = new UnionSecurityTokenResolver (token_resolver, security.OutOfBandTokenResolver);
// Add relevant protection token and supporting tokens.
tokens.Add (security.EncryptionToken);
// FIXME: this is just a workaround for symmetric binding to not require extra client certificate.
if (security.Element is AsymmetricSecurityBindingElement)
tokens.Add (security.SigningToken);
if (RequestSecurity != null && RequestSecurity.ProtectionToken != null)
tokens.Add (RequestSecurity.ProtectionToken.SecurityToken);
// FIXME: handle supporting tokens
for (int i = 0; i < srcmsg.Headers.Count; i++) {
MessageHeaderInfo header = srcmsg.Headers [i];
// FIXME: check SOAP Actor.
// MessageHeaderDescription.Actor needs to be accessible from here.
if (header.Namespace == Constants.WssNamespace &&
header.Name == "Security") {
wss_header = new WSSecurityMessageHeader (null);
wss_header_reader = new WSSecurityMessageHeaderReader (wss_header, serializer, token_resolver, doc, nsmgr, tokens);
wss_header_reader.ReadContents (srcmsg.Headers.GetReaderAtHeader (i));
headers.Add (wss_header);
}
else
headers.Add (header);
}
if (wss_header == null)
throw new InvalidOperationException ("In this service contract, a WS-Security header is required in the Message, but was not found.");
}
void ExtractSecurity ()
{
if (security.MessageProtectionOrder == MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature &&
wss_header.Find<SignedXml> () != null)
throw new MessageSecurityException ("The security binding element expects that the message signature is encrypted, while it isn't.");
WrappedKeySecurityToken wk = wss_header.Find<WrappedKeySecurityToken> ();
DerivedKeySecurityToken dk = wss_header.Find<DerivedKeySecurityToken> ();
if (wk != null) {
if (Parameters.RequireDerivedKeys && dk == null)
throw new MessageSecurityException ("DerivedKeyToken is required in this contract, but was not found in the message");
}
else
// FIXME: this is kind of hack for symmetric reply processing.
wk = RequestSecurity.ProtectionToken != null ? RequestSecurity.ProtectionToken.SecurityToken as WrappedKeySecurityToken : null;
SymmetricSecurityKey wkkey = wk != null ? wk.SecurityKeys [0] as SymmetricSecurityKey : null;
wss_header_reader.DecryptSecurity (this, wkkey, RequestSecurity != null ? RequestSecurity.EncryptionKey : null);
// signature confirmation
WSSignedXml sxml = wss_header.Find<WSSignedXml> ();
if (sxml == null)
throw new MessageSecurityException ("The the message signature is expected but not found.");
bool confirmed = false;
SecurityKeyIdentifierClause sigClause = null;
foreach (KeyInfoClause kic in sxml.KeyInfo) {
SecurityTokenReferenceKeyInfo r = kic as SecurityTokenReferenceKeyInfo;
if (r != null)
sigClause = r.Clause;
}
if (sigClause == null)
throw new MessageSecurityException ("SecurityTokenReference was not found in dsig:Signature KeyInfo.");
SecurityToken signToken;
SecurityKey signKey;
signToken = TokenResolver.ResolveToken (sigClause);
signKey = signToken.ResolveKeyIdentifierClause (sigClause);
SymmetricSecurityKey symkey = signKey as SymmetricSecurityKey;
if (symkey != null) {
confirmed = sxml.CheckSignature (new HMACSHA1 (symkey.GetSymmetricKey ()));
if (wk != null)
// FIXME: authenticate token
sec_prop.ProtectionToken = new SecurityTokenSpecification (wk, null);
} else {
AsymmetricAlgorithm alg = ((AsymmetricSecurityKey) signKey).GetAsymmetricAlgorithm (security.DefaultSignatureAlgorithm, false);
confirmed = sxml.CheckSignature (alg);
sec_prop.InitiatorToken = new SecurityTokenSpecification (
signToken,
security.TokenAuthenticator.ValidateToken (signToken));
}
if (!confirmed)
throw new MessageSecurityException ("Message signature is invalid.");
// token authentication
// FIXME: it might not be limited to recipient
if (Direction == MessageDirection.Input)
ProcessSupportingTokens (sxml);
sec_prop.EncryptionKey = ((SymmetricSecurityKey) wk.SecurityKeys [0]).GetSymmetricKey ();
sec_prop.ConfirmedSignatures.Add (Convert.ToBase64String (sxml.SignatureValue));
}
#region supporting token processing
// authenticate and map supporting tokens to proper SupportingTokenSpecification list.
void ProcessSupportingTokens (SignedXml sxml)
{
List<SupportingTokenInfo> tokens = new List<SupportingTokenInfo> ();
// First, categorize those tokens in the Security
// header:
// - Endorsing signing
// - Signed signed
// - SignedEncrypted signed encrypted
// - SignedEndorsing signing signed
foreach (object obj in wss_header.Contents) {
SecurityToken token = obj as SecurityToken;
if (token == null)
continue;
bool signed = false, endorsing = false, encrypted = false;
// signed
foreach (Reference r in sxml.SignedInfo.References)
if (r.Uri.Substring (1) == token.Id) {
signed = true;
break;
}
// FIXME: how to get 'encrypted' state?
// FIXME: endorsing
SecurityTokenAttachmentMode mode =
signed ? encrypted ? SecurityTokenAttachmentMode.SignedEncrypted :
endorsing ? SecurityTokenAttachmentMode.SignedEndorsing :
SecurityTokenAttachmentMode.Signed :
SecurityTokenAttachmentMode.Endorsing;
tokens.Add (new SupportingTokenInfo (token, mode, false));
}
// then,
// 1. validate every mandatory supporting token
// parameters (Endpoint-, Operation-). To do that,
// iterate all tokens in the header against every
// parameter in the mandatory list.
// 2. validate every token that is not validated.
// To do that, iterate all supporting token parameters
// and check if any of them can validate it.
SupportingTokenParameters supp;
string action = GetAction ();
if (action == null)
throw new ArgumentException ("SOAP action could not be retrieved from the message to decrypt.");
ValidateTokensByParameters (security.Element.EndpointSupportingTokenParameters, tokens, false);
if (security.Element.OperationSupportingTokenParameters.TryGetValue (action, out supp))
ValidateTokensByParameters (supp, tokens, false);
ValidateTokensByParameters (security.Element.OptionalEndpointSupportingTokenParameters, tokens, true);
if (security.Element.OptionalOperationSupportingTokenParameters.TryGetValue (action, out supp))
ValidateTokensByParameters (supp, tokens, true);
}
void ValidateTokensByParameters (SupportingTokenParameters supp, List<SupportingTokenInfo> tokens, bool optional)
{
ValidateTokensByParameters (supp.Endorsing, tokens, optional, SecurityTokenAttachmentMode.Endorsing);
ValidateTokensByParameters (supp.Signed, tokens, optional, SecurityTokenAttachmentMode.Signed);
ValidateTokensByParameters (supp.SignedEndorsing, tokens, optional, SecurityTokenAttachmentMode.SignedEndorsing);
ValidateTokensByParameters (supp.SignedEncrypted, tokens, optional, SecurityTokenAttachmentMode.SignedEncrypted);
}
void ValidateTokensByParameters (IEnumerable<SecurityTokenParameters> plist, List<SupportingTokenInfo> tokens, bool optional, SecurityTokenAttachmentMode attachMode)
{
foreach (SecurityTokenParameters p in plist) {
SecurityTokenResolver r;
SecurityTokenAuthenticator a =
security.CreateTokenAuthenticator (p, out r);
SupportingTokenSpecification spec = ValidateTokensByParameters (a, r, tokens);
if (spec == null) {
if (optional)
continue;
else
throw new MessageSecurityException (String.Format ("No security token could be validated for authenticator '{0}' which is indicated by the '{1}' supporting token parameters", a, attachMode));
} else {
// For endorsing tokens, verify corresponding signatures.
switch (attachMode) {
case SecurityTokenAttachmentMode.Endorsing:
case SecurityTokenAttachmentMode.SignedEndorsing:
WSSignedXml esxml = GetSignatureForToken (spec.SecurityToken);
if (esxml == null)
throw new MessageSecurityException (String.Format ("The '{1}' token '{0}' is expected to endorse the primary signature but no corresponding signature is found.", spec.SecurityToken, attachMode));
bool confirmed;
SecurityAlgorithmSuite suite = security.Element.DefaultAlgorithmSuite;
foreach (SecurityTokenReferenceKeyInfo kic in esxml.KeyInfo) {
SecurityKey signKey = spec.SecurityToken.ResolveKeyIdentifierClause (kic.Clause);
SymmetricSecurityKey symkey = signKey as SymmetricSecurityKey;
if (symkey != null) {
confirmed = esxml.CheckSignature (symkey.GetKeyedHashAlgorithm (suite.DefaultSymmetricSignatureAlgorithm));
} else {
AsymmetricAlgorithm alg = ((AsymmetricSecurityKey) signKey).GetAsymmetricAlgorithm (suite.DefaultAsymmetricSignatureAlgorithm, false);
confirmed = esxml.CheckSignature (alg);
}
if (!confirmed)
throw new MessageSecurityException (String.Format ("Signature for '{1}' token '{0}' is invalid.", spec.SecurityToken, attachMode));
break;
}
sec_prop.ConfirmedSignatures.Insert (0, Convert.ToBase64String (esxml.SignatureValue));
break;
}
}
sec_prop.IncomingSupportingTokens.Add (spec);
}
}
WSSignedXml GetSignatureForToken (SecurityToken token)
{
int count = 0;
foreach (WSSignedXml sxml in wss_header.FindAll<WSSignedXml> ()) {
if (count++ == 0)
continue; // primary signature
foreach (SecurityTokenReferenceKeyInfo r in sxml.KeyInfo)
if (token.MatchesKeyIdentifierClause (r.Clause))
return sxml;
}
return null;
}
SupportingTokenSpecification ValidateTokensByParameters (SecurityTokenAuthenticator a, SecurityTokenResolver r, List<SupportingTokenInfo> tokens)
{
foreach (SupportingTokenInfo info in tokens)
if (a.CanValidateToken (info.Token))
return new SupportingTokenSpecification (
info.Token,
a.ValidateToken (info.Token),
info.Mode);
return null;
}
#endregion
string GetAction ()
{
string ret = source_message.Headers.Action;
if (ret == null) {
HttpRequestMessageProperty reqprop =
source_message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
if (reqprop != null)
ret = reqprop.Headers ["Action"];
}
return ret;
}
}
}

View File

@@ -0,0 +1,172 @@
//
// SecurityCapabilities.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2005-2007 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Net.Security;
using System.Security.Cryptography.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels.Security
{
internal abstract class SecurityCapabilities
: ISecurityCapabilities
{
public abstract SecurityBindingElement Element { get; }
public abstract bool AllowSerializedSigningTokenOnReply { get; }
public abstract MessageProtectionOrder MessageProtectionOrder { get; }
public abstract SecurityTokenParameters InitiatorParameters { get; }
public abstract SecurityTokenParameters RecipientParameters { get; }
public abstract bool RequireSignatureConfirmation { get; }
public abstract string DefaultKeyWrapAlgorithm { get; }
public abstract string DefaultSignatureAlgorithm { get; }
// ISecurityCapabilities
// FIXME: implement correctly
public ProtectionLevel SupportedRequestProtectionLevel {
get { return ProtectionLevel.EncryptAndSign; }
}
public ProtectionLevel SupportedResponseProtectionLevel {
get { return ProtectionLevel.EncryptAndSign; }
}
public bool SupportsClientAuthentication {
get { return InitiatorParameters != null ? InitiatorParameters.InternalSupportsClientAuthentication : false; }
}
public bool SupportsClientWindowsIdentity {
get { return InitiatorParameters != null ? InitiatorParameters.InternalSupportsClientWindowsIdentity : false; }
}
public bool SupportsServerAuthentication {
get { return RecipientParameters != null ? RecipientParameters.InternalSupportsServerAuthentication : false; }
}
}
internal class SymmetricSecurityCapabilities : SecurityCapabilities
{
SymmetricSecurityBindingElement element;
public SymmetricSecurityCapabilities (
SymmetricSecurityBindingElement element)
{
this.element = element;
}
public override SecurityBindingElement Element {
get { return element; }
}
// FIXME: const true or false
public override bool AllowSerializedSigningTokenOnReply {
get { throw new NotImplementedException (); }
}
public override MessageProtectionOrder MessageProtectionOrder {
get { return element.MessageProtectionOrder; }
}
public override SecurityTokenParameters InitiatorParameters {
get { return element.ProtectionTokenParameters; }
}
public override SecurityTokenParameters RecipientParameters {
get { return element.ProtectionTokenParameters; }
}
public override bool RequireSignatureConfirmation {
get { return element.RequireSignatureConfirmation; }
}
public override string DefaultSignatureAlgorithm {
get { return element.DefaultAlgorithmSuite.DefaultSymmetricSignatureAlgorithm; }
}
public override string DefaultKeyWrapAlgorithm {
get { return element.DefaultAlgorithmSuite.DefaultSymmetricKeyWrapAlgorithm; }
}
}
internal class AsymmetricSecurityCapabilities : SecurityCapabilities
{
AsymmetricSecurityBindingElement element;
public AsymmetricSecurityCapabilities (
AsymmetricSecurityBindingElement element)
{
this.element = element;
}
public override bool AllowSerializedSigningTokenOnReply {
get { return element.AllowSerializedSigningTokenOnReply; }
}
public override SecurityBindingElement Element {
get { return element; }
}
public override MessageProtectionOrder MessageProtectionOrder {
get { return element.MessageProtectionOrder; }
}
public override SecurityTokenParameters InitiatorParameters {
get { return element.InitiatorTokenParameters; }
}
public override SecurityTokenParameters RecipientParameters {
get { return element.RecipientTokenParameters; }
}
public override bool RequireSignatureConfirmation {
get { return element.RequireSignatureConfirmation; }
}
public override string DefaultSignatureAlgorithm {
get { return element.DefaultAlgorithmSuite.DefaultAsymmetricSignatureAlgorithm; }
}
public override string DefaultKeyWrapAlgorithm {
get { return element.DefaultAlgorithmSuite.DefaultAsymmetricKeyWrapAlgorithm; }
}
}
}

View File

@@ -0,0 +1,98 @@
//
// SecurityChannelFactory.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels.Security;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Xml;
using System.Xml.XPath;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels
{
internal class SecurityChannelFactory<TChannel> : ChannelFactoryBase<TChannel>
{
IChannelFactory<TChannel> inner;
InitiatorMessageSecurityBindingSupport security;
public SecurityChannelFactory (
IChannelFactory<TChannel> innerFactory,
InitiatorMessageSecurityBindingSupport security)
{
this.inner = innerFactory;
this.security = security;
}
public InitiatorMessageSecurityBindingSupport SecuritySupport {
get { return security; }
}
protected override TChannel OnCreateChannel (
EndpointAddress remoteAddress, Uri via)
{
TChannel src = inner.CreateChannel (remoteAddress, via);
if (typeof (TChannel) == typeof (IRequestChannel))
return (TChannel) (object) new SecurityRequestChannel ((IRequestChannel) (object) src, (SecurityChannelFactory<IRequestChannel>) (object) this);
if (typeof (TChannel) == typeof (IRequestSessionChannel))
return (TChannel) (object) new SecurityRequestSessionChannel ((IRequestSessionChannel) (object) src, (SecurityChannelFactory<IRequestSessionChannel>) (object) this);
if (typeof (TChannel).IsAssignableFrom (typeof (IDuplexSessionChannel)))
return (TChannel) (object) new SecurityDuplexSessionChannel (this, (IChannel) (object) src, remoteAddress, via, security);
throw new NotSupportedException (String.Format ("Channel type '{0}' is not supported", typeof (TChannel)));
}
protected override void OnOpen (TimeSpan timeout)
{
inner.Open (timeout);
}
protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
{
return inner.BeginOpen (timeout, callback, state);
}
protected override void OnEndOpen (IAsyncResult result)
{
inner.EndOpen (result);
}
}
}

View File

@@ -0,0 +1,164 @@
//
// SecurityChannelListener.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Security;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
namespace System.ServiceModel.Channels.Security
{
internal class SecurityChannelListener<TChannel> : ChannelListenerBase<TChannel>
where TChannel : class, IChannel
{
IChannelListener<TChannel> inner;
RecipientMessageSecurityBindingSupport security;
public SecurityChannelListener (
IChannelListener<TChannel> innerListener,
RecipientMessageSecurityBindingSupport security)
{
inner = innerListener;
this.security = security;
}
public RecipientMessageSecurityBindingSupport SecuritySupport {
get { return security; }
}
public override T GetProperty<T> ()
{
if (typeof (T) == typeof (MessageSecurityBindingSupport))
return (T) (object) security;
return base.GetProperty<T> ();
}
TChannel CreateSecurityWrapper (TChannel src)
{
if (typeof (TChannel) == typeof (IReplyChannel))
return (TChannel) (object) new SecurityReplyChannel ((SecurityChannelListener<IReplyChannel>) (object) this, (IReplyChannel) (object) src);
if (typeof (TChannel).IsAssignableFrom (typeof (IDuplexSessionChannel)))
return (TChannel) (object) new SecurityDuplexSessionChannel (this, src, security);
throw new NotImplementedException ();
}
void AcquireTokens ()
{
security.Prepare (this, Uri);
}
void ReleaseTokens ()
{
security.Release ();
}
// ChannelListenerBase
protected override TChannel OnAcceptChannel (TimeSpan timeout)
{
return CreateSecurityWrapper (inner.AcceptChannel (timeout));
}
protected override IAsyncResult OnBeginAcceptChannel (TimeSpan timeout, AsyncCallback callback, object state)
{
return inner.BeginAcceptChannel (timeout, callback, state);
}
protected override TChannel OnEndAcceptChannel (IAsyncResult result)
{
return CreateSecurityWrapper (inner.EndAcceptChannel (result));
}
protected override bool OnWaitForChannel (TimeSpan timeout)
{
return inner.WaitForChannel (timeout);
}
protected override IAsyncResult OnBeginWaitForChannel (TimeSpan timeout, AsyncCallback callback, object state)
{
return inner.BeginWaitForChannel (timeout, callback, state);
}
protected override bool OnEndWaitForChannel (IAsyncResult result)
{
return inner.EndWaitForChannel (result);
}
public override Uri Uri {
get { return inner.Uri; }
}
// CommunicationObject
protected override void OnAbort ()
{
inner.Abort ();
}
protected override void OnClose (TimeSpan timeout)
{
ReleaseTokens ();
inner.Close (timeout);
}
protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
{
ReleaseTokens ();
return inner.BeginClose (timeout, callback, state);
}
protected override void OnEndClose (IAsyncResult result)
{
inner.EndClose (result);
}
protected override void OnOpen (TimeSpan timeout)
{
AcquireTokens ();
inner.Open (timeout);
}
protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
{
AcquireTokens ();
return inner.BeginOpen (timeout, callback, state);
}
protected override void OnEndOpen (IAsyncResult result)
{
inner.EndOpen (result);
}
}
}

View File

@@ -0,0 +1,185 @@
//
// SecurityRequestChannel.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Xml;
using System.Xml.XPath;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels.Security
{
class SecurityDuplexSession : DuplexSessionBase
{
SecurityDuplexSessionChannel channel;
public SecurityDuplexSession (SecurityDuplexSessionChannel channel)
{
this.channel = channel;
}
public override TimeSpan DefaultCloseTimeout {
get { return channel.DefaultCloseTimeout; }
}
public override void Close (TimeSpan timeout)
{
// valid only if the inner channel is ISessionChannel
var d = channel.Channel as IDuplexSessionChannel;
if (d != null)
d.Session.CloseOutputSession (timeout);
}
}
class SecurityDuplexSessionChannel : DuplexChannelBase, IDuplexSessionChannel
{
IChannel channel;
InitiatorMessageSecurityBindingSupport security_initiator;
RecipientMessageSecurityBindingSupport security_recipient;
SecurityDuplexSession session;
public SecurityDuplexSessionChannel (ChannelFactoryBase factory, IChannel innerChannel, EndpointAddress remoteAddress, Uri via, InitiatorMessageSecurityBindingSupport security)
: base (factory, remoteAddress, via)
{
this.channel = innerChannel;
session = new SecurityDuplexSession (this);
InitializeSecurityFunctionality (security);
}
public SecurityDuplexSessionChannel (ChannelListenerBase listener, IChannel innerChannel, RecipientMessageSecurityBindingSupport security)
: base (listener)
{
this.channel = innerChannel;
session = new SecurityDuplexSession (this);
InitializeSecurityFunctionality (security);
}
public IChannel Channel {
get { return channel; }
}
public IDuplexSession Session {
get { return session; }
}
void InitializeSecurityFunctionality (InitiatorMessageSecurityBindingSupport security)
{
security_initiator = security;
}
void InitializeSecurityFunctionality (RecipientMessageSecurityBindingSupport security)
{
security_recipient = security;
}
protected override void OnOpen (TimeSpan timeout)
{
channel.Open (timeout);
if (security_initiator != null)
security_initiator.Prepare ((ChannelFactoryBase) Manager, RemoteAddress);
else
security_recipient.Prepare ((ChannelListenerBase) Manager, LocalAddress.Uri);
}
protected override void OnClose (TimeSpan timeout)
{
if (security_initiator != null)
security_initiator.Release ();
else
security_recipient.Release ();
channel.Close (timeout);
}
protected override void OnAbort ()
{
if (security_initiator != null)
security_initiator.Release ();
else
security_recipient.Release ();
channel.Abort ();
}
public override bool TryReceive (TimeSpan timeout, out Message message)
{
ThrowIfDisposedOrNotOpen ();
var input = (IInputChannel) channel;
if (!input.TryReceive (timeout, out message))
return false;
message = DecryptMessage (message);
return true;
}
public override bool WaitForMessage (TimeSpan timeout)
{
var input = (IInputChannel) channel;
return input.WaitForMessage (timeout);
}
public override void Send (Message message)
{
Send (message, DefaultSendTimeout);
}
public override void Send (Message message, TimeSpan timeout)
{
Message secure = SecureMessage (message);
var output = (IOutputChannel) channel;
output.Send (secure, timeout);
}
Message SecureMessage (Message msg)
{
if (security_initiator != null)
return new InitiatorMessageSecurityGenerator (msg, security_initiator, RemoteAddress).SecureMessage ();
else
return new RecipientMessageSecurityGenerator (msg, null, security_recipient).SecureMessage (); // FIXME: supply SecurityMessageProperty (if any)
}
Message DecryptMessage (Message msg)
{
if (security_initiator != null)
return new InitiatorSecureMessageDecryptor (msg, null, security_initiator).DecryptMessage (); // FIXME: supply SecurityMessageProperty (if any)
else
return new RecipientSecureMessageDecryptor (msg, security_recipient).DecryptMessage ();
}
}
}

View File

@@ -0,0 +1,135 @@
//
// SecurityRequestChannel.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
/*
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Xml;
using System.Xml.XPath;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels.Security
{
class SecurityOutputChannel : SecurityOutputChannelBase
{
SecurityChannelFactory<IOutputChannel> source;
public SecurityOutputChannel (IOutputChannel innerChannel, SecurityChannelFactory<IOutputChannel> source)
: base (innerChannel)
{
this.source = source;
InitializeSecurityFunctionality (source.SecuritySupport);
}
public override ChannelFactoryBase Factory {
get { return source; }
}
}
class SecurityOutputSessionChannel : SecurityOutputChannelBase
{
SecurityChannelFactory<IOutputSessionChannel> source;
public SecurityOutputSessionChannel (IOutputSessionChannel innerChannel, SecurityChannelFactory<IOutputSessionChannel> source)
: base (innerChannel)
{
this.source = source;
InitializeSecurityFunctionality (source.SecuritySupport);
}
public override ChannelFactoryBase Factory {
get { return source; }
}
}
abstract class SecurityOutputChannelBase : LayeredOutputChannel
{
InitiatorMessageSecurityBindingSupport security;
protected SecurityOutputChannelBase (IOutputChannel innerChannel)
: base (innerChannel)
{
Opened += new EventHandler (AcquireSecurityKey);
Closing += new EventHandler (ReleaseSecurityKey);
}
protected void InitializeSecurityFunctionality (InitiatorMessageSecurityBindingSupport security)
{
this.security = security;
}
protected override IAsyncResult OnBeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
Message secure = SecureMessage (message);
return base.BeginSend (secure, timeout, callback, state);
}
protected override void OnEndSend (IAsyncResult result)
{
// FIXME: it must be also asynchronized.
base.EndSend (result);
}
protected override void OnSend (Message message, TimeSpan timeout)
{
Message secure = SecureMessage (message);
base.OnSend (secure, timeout);
}
Message SecureMessage (Message msg)
{
return new InitiatorMessageSecurityGenerator (msg, security, RemoteAddress).SecureMessage ();
}
void AcquireSecurityKey (object o, EventArgs e)
{
security.Prepare (Factory, RemoteAddress);
}
void ReleaseSecurityKey (object o, EventArgs e)
{
security.Release ();
}
}
}
*/

View File

@@ -0,0 +1,128 @@
//
// SecurityReplyChannel.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006,2010 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Security;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
namespace System.ServiceModel.Channels.Security
{
internal class SecurityReplyChannel : InternalReplyChannelBase
{
IReplyChannel inner;
public SecurityReplyChannel (
SecurityChannelListener<IReplyChannel> source,
IReplyChannel innerChannel)
: base (source)
{
this.inner = innerChannel;
}
public SecurityChannelListener<IReplyChannel> Source {
get { return (SecurityChannelListener<IReplyChannel>) Listener; }
}
// IReplyChannel
protected override void OnOpen (TimeSpan timeout)
{
inner.Open (timeout);
}
protected override void OnClose (TimeSpan timeout)
{
inner.Close (timeout);
}
public override RequestContext ReceiveRequest (TimeSpan timeout)
{
RequestContext ctx;
if (TryReceiveRequest (timeout, out ctx))
return ctx;
throw new TimeoutException ("Failed to receive request context");
}
public override bool TryReceiveRequest (TimeSpan timeout, out RequestContext context)
{
DateTime start = DateTime.Now;
if (!inner.TryReceiveRequest (timeout, out context))
return false;
if (context == null)
return true;
Message req, res;
req = context.RequestMessage;
switch (req.Headers.Action) {
case Constants.WstIssueAction:
case Constants.WstIssueReplyAction:
case Constants.WstRenewAction:
case Constants.WstCancelAction:
case Constants.WstValidateAction:
var support = Source.SecuritySupport;
var commAuth = support.TokenAuthenticator as CommunicationSecurityTokenAuthenticator;
if (commAuth != null)
res = commAuth.Communication.ProcessNegotiation (req, timeout - (DateTime.Now - start));
else
throw new MessageSecurityException ("This reply channel does not expect incoming WS-Trust requests");
context.Reply (res, timeout - (DateTime.Now - start));
context.Close (timeout - (DateTime.Now - start));
// wait for another incoming message
return TryReceiveRequest (timeout - (DateTime.Now - start), out context);
break;
}
context = new SecurityRequestContext (this, context);
return true;
}
[MonoTODO]
public override bool WaitForRequest (TimeSpan timeout)
{
throw new NotImplementedException ();
}
// IChannel
public override T GetProperty<T> ()
{
// FIXME: implement
return inner.GetProperty<T> ();
}
}
}

View File

@@ -0,0 +1,148 @@
//
// SecurityRequestChannel.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Xml;
using System.Xml.XPath;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels.Security
{
interface ISecurityChannelSource
{
MessageSecurityBindingSupport Support { get; }
}
class SecurityRequestChannel : SecurityRequestChannelBase
{
SecurityChannelFactory<IRequestChannel> source;
public SecurityRequestChannel (IRequestChannel innerChannel, SecurityChannelFactory<IRequestChannel> source)
: base (innerChannel)
{
this.source = source;
InitializeSecurityFunctionality (source.SecuritySupport);
}
public override ChannelFactoryBase Factory {
get { return source; }
}
}
class SecurityRequestSessionChannel : SecurityRequestChannelBase
{
SecurityChannelFactory<IRequestSessionChannel> source;
public SecurityRequestSessionChannel (IRequestSessionChannel innerChannel, SecurityChannelFactory<IRequestSessionChannel> source)
: base (innerChannel)
{
this.source = source;
InitializeSecurityFunctionality (source.SecuritySupport);
}
public override ChannelFactoryBase Factory {
get { return source; }
}
}
abstract class SecurityRequestChannelBase : LayeredRequestChannel
{
InitiatorMessageSecurityBindingSupport security;
protected SecurityRequestChannelBase (IRequestChannel innerChannel)
: base (innerChannel)
{
Opened += new EventHandler (AcquireSecurityKey);
Closing += new EventHandler (ReleaseSecurityKey);
}
protected void InitializeSecurityFunctionality (InitiatorMessageSecurityBindingSupport security)
{
this.security = security;
}
SecurityMessageProperty secprop;
protected override IAsyncResult OnBeginRequest (Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
// FIXME: make it really async
Message secure = SecureMessage (message);
secprop = secure.Properties.Security;
return base.BeginRequest (secure, timeout, callback, state);
}
protected override Message OnEndRequest (IAsyncResult result)
{
// FIXME: it must be also asynchronized.
Message raw = base.EndRequest (result);
return ProcessReply (raw, secprop);
}
protected override Message OnRequest (Message message, TimeSpan timeout)
{
Message secure = SecureMessage (message);
Message raw = base.OnRequest (secure, timeout);
return ProcessReply (raw, secure.Properties.Security);
}
Message SecureMessage (Message msg)
{
return new InitiatorMessageSecurityGenerator (msg, security, RemoteAddress).SecureMessage ();
}
Message ProcessReply (Message message, SecurityMessageProperty secprop)
{
// FIXME: provide correct parameters
return message.IsFault ? message : new InitiatorSecureMessageDecryptor (message, secprop, security).DecryptMessage ();
}
void AcquireSecurityKey (object o, EventArgs e)
{
security.Prepare (Factory, RemoteAddress);
}
void ReleaseSecurityKey (object o, EventArgs e)
{
security.Release ();
}
}
}

View File

@@ -0,0 +1,129 @@
//
// SecurityRequestContext.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2005-2007 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Net.Security;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Xml;
using System.Xml.XPath;
namespace System.ServiceModel.Channels.Security
{
internal class SecurityRequestContext : RequestContext
{
RecipientMessageSecurityBindingSupport security;
SecurityReplyChannel channel;
RequestContext source;
Message msg;
MessageBuffer source_request;
public SecurityRequestContext (SecurityReplyChannel channel, RequestContext source)
{
this.source = source;
this.channel = channel;
security = channel.Source.SecuritySupport;
}
public override Message RequestMessage {
get {
if (msg == null)
msg = new RecipientSecureMessageDecryptor (source.RequestMessage, security).DecryptMessage ();
return msg;
}
}
public override void Abort ()
{
source.Abort ();
}
public override IAsyncResult BeginReply (Message message, AsyncCallback callback, object state)
{
return BeginReply (message, channel.Listener.DefaultSendTimeout, callback, state);
}
public override IAsyncResult BeginReply (Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
// FIXME: implement
throw new NotImplementedException ();
}
public override void Close ()
{
Close (channel.Listener.DefaultCloseTimeout);
}
public override void Close (TimeSpan timeout)
{
source.Close (timeout);
}
public override void EndReply (IAsyncResult result)
{
// FIXME: implement
throw new NotImplementedException ();
}
public override void Reply (Message message)
{
Reply (message, channel.Listener.DefaultSendTimeout);
}
public override void Reply (Message message, TimeSpan timeout)
{
try {
if (!message.IsFault && message.Headers.Action != Constants.WstIssueReplyAction)
message = SecureMessage (message);
source.Reply (message, timeout);
} catch (Exception ex) {
FaultConverter fc = FaultConverter.GetDefaultFaultConverter (msg.Version);
Message fault;
if (fc.TryCreateFaultMessage (ex, out fault))
source.Reply (fault, timeout);
else
throw;
}
}
Message SecureMessage (Message input)
{
return new RecipientMessageSecurityGenerator (input, RequestMessage.Properties.Security, security).SecureMessage ();
}
}
}

View File

@@ -0,0 +1,70 @@
//
// SupportingTokenInfo.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2005-2007 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Net.Security;
using System.Security.Cryptography.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
namespace System.ServiceModel.Channels.Security
{
internal class SupportingTokenInfo
{
public SupportingTokenInfo (SecurityToken token,
SecurityTokenAttachmentMode mode,
bool isOptional)
{
Token = token;
Mode = mode;
IsOptional = isOptional;
}
public SecurityToken Token;
public SecurityTokenAttachmentMode Mode;
public bool IsOptional;
public EncryptedData Encrypted;
}
internal class SupportingTokenInfoCollection : Collection<SupportingTokenInfo>
{
protected override void InsertItem (int index, SupportingTokenInfo item)
{
foreach (SupportingTokenInfo i in this)
if (i.Token.GetType () == item.Token.GetType ())
throw new ArgumentException (String.Format ("Supporting tokens do not allow multiple SecurityTokens of the same type: {0}", i.Token.GetType ()));
base.InsertItem (index, item);
}
}
}

View File

@@ -0,0 +1,66 @@
//
// WSEncryptedXml.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography.Xml;
using System.Xml;
namespace System.ServiceModel.Channels.Security
{
// See http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx :)
class WSEncryptedXml : EncryptedXml
{
public WSEncryptedXml ()
{
}
public WSEncryptedXml (XmlDocument doc)
: base (doc)
{
}
public override XmlElement GetIdElement (XmlDocument doc, string id)
{
return SearchChildren (doc, id);
}
XmlElement SearchChildren (XmlNode node, string id)
{
for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling) {
XmlElement el = n as XmlElement;
if (el == null)
continue;
if (el.GetAttribute ("Id", Constants.WsuNamespace) == id || el.GetAttribute ("Id") == id)
return el;
XmlElement el2 = SearchChildren (el, id);
if (el2 != null)
return el2;
}
return null;
}
}
}

View File

@@ -0,0 +1,66 @@
//
// WSSignedXml.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography.Xml;
using System.Xml;
namespace System.ServiceModel.Channels.Security
{
// See http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx :)
class WSSignedXml : SignedXml
{
public WSSignedXml ()
{
}
public WSSignedXml (XmlDocument doc)
: base (doc)
{
}
public override XmlElement GetIdElement (XmlDocument doc, string id)
{
return SearchChildren (doc, id);
}
XmlElement SearchChildren (XmlNode node, string id)
{
for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling) {
XmlElement el = n as XmlElement;
if (el == null)
continue;
if (el.GetAttribute ("Id", Constants.WsuNamespace) == id || el.GetAttribute ("Id") == id)
return el;
XmlElement el2 = SearchChildren (el, id);
if (el2 != null)
return el2;
}
return null;
}
}
}