Author: atsushi
Date: 2007-01-11 02:20:53 -0500 (Thu, 11 Jan 2007)
New Revision: 70835
Added:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityUtility.cs
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityOutputChannel.cs
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestChannel.cs
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestContext.cs
trunk/olive/class/System.ServiceModel/System.ServiceModel.dll.sources
Log:
2007-01-11 Atsushi Enomoto <[EMAIL PROTECTED]>
* MessageSecurityUtility.cs, SecureMessageGenerator.cs :
split encryptor part in the former file into latter file, and
make it nonstatic.
* SecurityRequestChannel.cs, SecurityOutputChannel.cs,
SecurityRequestContext.cs : apply the change above.
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
2007-01-11 07:17:21 UTC (rev 70834)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
2007-01-11 07:20:53 UTC (rev 70835)
@@ -1,5 +1,13 @@
2007-01-11 Atsushi Enomoto <[EMAIL PROTECTED]>
+ * MessageSecurityUtility.cs, SecureMessageGenerator.cs :
+ split encryptor part in the former file into latter file, and
+ make it nonstatic.
+ * SecurityRequestChannel.cs, SecurityOutputChannel.cs,
+ SecurityRequestContext.cs : apply the change above.
+
+2007-01-11 Atsushi Enomoto <[EMAIL PROTECTED]>
+
* MessageSecurityBindingSupport.cs :
Fixed incorrect TrgGetValue() use.
Added CollectRecipientSupportingTokens().
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityUtility.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityUtility.cs
2007-01-11 07:17:21 UTC (rev 70834)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityUtility.cs
2007-01-11 07:20:53 UTC (rev 70835)
@@ -58,315 +58,6 @@
return token.ResolveKeyIdentifierClause (clause);
}
- public static Message SecureMessage (
- Message msg,
- ISecurityChannelSource security,
- EndpointAddress remoteAddress)
- {
- // FIXME: I believe it should be done at channel
- // creation phase, but WinFX does not.
- if
(!security.Support.InitiatorParameters.InternalHasAsymmetricKey)
- throw new InvalidOperationException ("Wrong
security token parameters: it must have an asymmetric key (HasAsymmetricKey).
There is likely a misconfiguration in the custom security binding element.");
-
- return SecureMessage (
- msg,
- remoteAddress,
- security.Support,
- MessageDirection.Input);
- }
-
- public static Message SecureMessage (
- Message msg,
- EndpointAddress messageTo,
- MessageSecurityBindingSupport security,
- MessageDirection direction)
- {
- SecurityTokenParameters initiatorParams =
- security.InitiatorParameters;
- SecurityTokenParameters recipientParams =
- security.RecipientParameters;
- SecurityToken encToken =
- security.EncryptionToken;
- SecurityToken signToken =
- security.SigningToken;
- MessageProtectionOrder protectionOrder =
- security.MessageProtectionOrder;
- SecurityTokenSerializer serializer =
- security.TokenSerializer;
- SecurityBindingElement element =
- security.Element;
- ScopedMessagePartSpecification spec =
- direction == MessageDirection.Input ?
-
security.ChannelRequirements.IncomingSignatureParts :
-
security.ChannelRequirements.OutgoingSignatureParts;
- SecurityTokenParameters securingParams =
- direction == MessageDirection.Input ?
- initiatorParams : recipientParams;
-
- SupportingTokenInfoCollection tokens =
- security.CollectInitiatorSupportingTokens
(msg.Headers.Action, messageTo);
-
-
- // SecurityTokenInclusionMode
- // - Initiator or Recipient
- // - done or notyet. FIXME: not implemented yet
- // It also affects on key reference output
-
- SecurityTokenInclusionMode appliedMode =
- securingParams.InclusionMode;
- bool msgIncludesToken = ShouldIncludeToken
(appliedMode, direction, false);
-
- SecurityKeyIdentifierClause encClause =
- initiatorParams.CallCreateKeyIdentifierClause
(encToken, msgIncludesToken ? initiatorParams.ReferenceStyle :
SecurityTokenReferenceStyle.External);
- SecurityKeyIdentifierClause signClause =
- recipientParams.CallCreateKeyIdentifierClause
(signToken, msgIncludesToken ? recipientParams.ReferenceStyle :
SecurityTokenReferenceStyle.External);
-
- AsymmetricSecurityKey encKey = (AsymmetricSecurityKey)
- encToken.ResolveKeyIdentifierClause (encClause);
- AsymmetricSecurityKey signKey = (AsymmetricSecurityKey)
- signToken.ResolveKeyIdentifierClause
(signClause);
- string messageId = "uuid:" + Guid.NewGuid ();
- int identForMessageId = 1;
-
- msg.Headers.Add (MessageHeader.CreateHeader
("MessageID", msg.Version.Addressing.Namespace, messageId));
-
- // FIXME: get correct ReplyTo value
- msg.Headers.Add (MessageHeader.CreateHeader ("ReplyTo",
msg.Version.Addressing.Namespace, EndpointAddress10.FromEndpointAddress (new
EndpointAddress (Constants.WsaAnonymousUri))));
-
- if (messageTo != null)
- msg.Headers.Add (MessageHeader.CreateHeader
("To", msg.Version.Addressing.Namespace, messageTo.Uri.AbsoluteUri, true));
-
- // addition except for wsse:Security is done. Start
securing...
-
- XmlDocument doc = new XmlDocument ();
- doc.PreserveWhitespace = true;
- XPathNavigator nav = doc.CreateNavigator ();
- using (XmlWriter w = nav.AppendChild ()) {
- msg.WriteMessage (w);
- }
- XmlNamespaceManager nsmgr = new XmlNamespaceManager
(doc.NameTable);
- nsmgr.AddNamespace ("s",
msg.Version.Envelope.Namespace);
-
- WrappedKeySecurityToken ekey = null;
- ReferenceList encRefList = null;
- Signature sig = null;
- EncryptedData sigenc = null;
-
- SecurityAlgorithmSuite suite =
element.DefaultAlgorithmSuite;
-
- // wss:Security
- WSSecurityMessageHeader header =
- new WSSecurityMessageHeader (serializer);
- // wss:Security/wsu:Timestamp
- if (element.IncludeTimestamp) {
- WsuTimestamp timestamp = new WsuTimestamp ();
- timestamp.Id = messageId + "-" +
identForMessageId++;
- timestamp.Created = DateTime.Now;
- // FIXME: on service side, use
element.LocalServiceSettings.TimestampValidityDuration
- timestamp.Expires = timestamp.Created.Add
(element.LocalClientSettings.TimestampValidityDuration);
- header.Contents.Add (timestamp);
- }
- msg.Headers.Add (header);
-
- // FIXME: it needs to choose message parts by
- // ChannelProtectionRequirements.
- XmlElement body = doc.SelectSingleNode
("/s:Envelope/s:Body/*", nsmgr) as XmlElement;
-
- switch (protectionOrder) {
- case MessageProtectionOrder.EncryptBeforeSign:
- // FIXME: implement
- throw new NotImplementedException ();
- case MessageProtectionOrder.SignBeforeEncrypt:
- case
MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature:
-
- MessagePartSpecification sigSpec;
- if (!spec.TryGetParts (GetAction (msg), false,
out sigSpec))
- sigSpec = spec.ChannelParts;
-
- // encryption key (possibly also used for
signing)
- // FIXME: get correct SymmetricAlgorithm
according to the algorithm suite
- RijndaelManaged aes = new RijndaelManaged ();
- aes.KeySize = 256;
- aes.Mode = CipherMode.CBC;
- aes.Padding = PaddingMode.ISO10126;
-
- // sign
- SignedXml sxml = new SignedXml (body);
-
- HMACSHA1 sigHash = null;
- if (security.DefaultSignatureAlgorithm ==
SignedXml.XmlDsigHMACSHA1Url)
- sigHash = new HMACSHA1 (aes.Key);
- else
- sxml.SigningKey =
signKey.GetAsymmetricAlgorithm (security.DefaultSignatureAlgorithm, true);
-
- sig = sxml.Signature;
- sig.SignedInfo.CanonicalizationMethod =
- suite.DefaultCanonicalizationAlgorithm;
- foreach (XmlNode n in doc.SelectNodes
("/s:Envelope/s:Header", nsmgr)) {
- XmlElement el = n as XmlElement;
- if (el == null)
- continue;
- // FIXME: check sigSpec.HeaderTypes and
skip it if not included.
- sig.SignedInfo.AddReference
(CreateReference (el, suite));
- }
- foreach (XmlNode n in body.ChildNodes) {
- XmlElement el = n as XmlElement;
- if (el == null)
- continue;
- sig.SignedInfo.AddReference
(CreateReference (el, suite));
- }
- if (sigHash != null)
- sxml.ComputeSignature (sigHash);
- else
- sxml.ComputeSignature ();
- sxml.KeyInfo = new KeyInfo ();
- SecurityTokenReferenceKeyInfo sigKeyInfo = new
SecurityTokenReferenceKeyInfo (signClause, serializer, doc);
- sxml.KeyInfo.AddClause (sigKeyInfo);
-
- // encrypt
- string ekeyId = messageId + "-" +
identForMessageId++;
-
- EncryptedXml exml = new EncryptedXml ();
- ekey = new WrappedKeySecurityToken (ekeyId,
- aes.Key,
- suite.DefaultAsymmetricKeyWrapAlgorithm,
- encToken,
- new SecurityKeyIdentifier (encClause));
- encRefList = new ReferenceList ();
- if (!initiatorParams.RequireDerivedKeys)
- ekey.ReferenceList = encRefList;
-
- EncryptedData edata = Encrypt (body, aes,
suite, ekeyId, encRefList, encClause, serializer, exml, doc);
- edata.KeyInfo = null;
- EncryptedXml.ReplaceElement (body, edata,
false);
-
- // encrypt signature
- if (protectionOrder ==
MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature) {
- XmlElement sigxml = sig.GetXml ();
- sigenc = Encrypt (sigxml, aes, suite,
ekeyId, encRefList, encClause, serializer, exml, doc);
- }
- break;
- }
-
- Message ret = Message.CreateMessage (msg.Version,
msg.Headers.Action, new XmlNodeReader (doc.SelectSingleNode
("/s:Envelope/s:Body/*", nsmgr) as XmlElement));
-
- ret.Headers.Clear ();
- ret.Headers.CopyHeadersFrom (msg);
-
- if (sig != null && msgIncludesToken)
- header.Contents.Add (signToken);
- if (signToken != encToken && msgIncludesToken)
- header.Contents.Add (encToken);
-
- if (ekey != null)
- header.Contents.Add (ekey);
-
- // generate derived key if needed
- if (initiatorParams.RequireDerivedKeys) {
- RijndaelManaged deriv = new RijndaelManaged ();
- deriv.KeySize = 128;
- deriv.Mode = CipherMode.CBC;
- deriv.Padding = PaddingMode.ISO10126;
- deriv.GenerateKey ();
- WsscDerivedKeyToken derivedKey =
- new WsscDerivedKeyToken ();
- derivedKey.Id = GenerateId (doc);
- derivedKey.Offset = 0;
- derivedKey.Nonce = deriv.Key;
- derivedKey.Length = derivedKey.Nonce.Length;
- if (ekey != null)
- derivedKey.SecurityTokenReference =
- new LocalIdKeyIdentifierClause
(ekey.Id);
- header.Contents.Add (derivedKey);
- if (encRefList != null)
- header.Contents.Add (encRefList);
- }
-
- if (sigenc != null)
- header.Contents.Add (sigenc);
- else if (sig != null)
- header.Contents.Add (sig);
-
- return ret;
- }
-
- static bool ShouldIncludeToken (SecurityTokenInclusionMode mode,
- MessageDirection direction, bool isInitialized)
- {
- switch (mode) {
- case SecurityTokenInclusionMode.Never:
- return false;
- case SecurityTokenInclusionMode.AlwaysToInitiator:
- return direction == MessageDirection.Output;
- case SecurityTokenInclusionMode.AlwaysToRecipient:
- return direction == MessageDirection.Input;
- case SecurityTokenInclusionMode.Once:
- return !isInitialized;
- }
- throw new Exception ("Internal Error: should not
happen.");
- }
-
- static Reference CreateReference (XmlElement el,
SecurityAlgorithmSuite suite)
- {
- if (el.GetAttribute ("Id") == String.Empty)
- el.SetAttribute ("Id", GenerateId
(el.OwnerDocument));
- Reference r = new Reference ("#" + el.GetAttribute
("Id"));
- r.AddTransform (CreateTransform
(suite.DefaultCanonicalizationAlgorithm));
- r.DigestMethod = suite.DefaultDigestAlgorithm;
- return r;
- }
-
- static Transform CreateTransform (string url)
- {
- switch (url) {
- case SignedXml.XmlDsigC14NTransformUrl:
- return new XmlDsigC14NTransform ();
- case SignedXml.XmlDsigC14NWithCommentsTransformUrl:
- return new XmlDsigC14NWithCommentsTransform ();
- case SignedXml.XmlDsigExcC14NTransformUrl:
- return new XmlDsigExcC14NTransform ();
- case SignedXml.XmlDsigExcC14NWithCommentsTransformUrl:
- return new XmlDsigExcC14NWithCommentsTransform
();
- }
- throw new Exception (String.Format ("INTERNAL ERROR:
Invalid canonicalization URL: {0}", url));
- }
-
- static EncryptedData Encrypt (XmlElement target,
SymmetricAlgorithm aes, SecurityAlgorithmSuite suite, string ekeyId,
ReferenceList refList, SecurityKeyIdentifierClause encClause,
SecurityTokenSerializer serializer, EncryptedXml exml, XmlDocument doc)
- {
- byte [] encrypted = exml.EncryptData (target, aes,
false);
- EncryptedData edata = new EncryptedData ();
- edata.Id = GenerateId (doc);
- edata.Type = EncryptedXml.XmlEncElementUrl;
- edata.EncryptionMethod = new EncryptionMethod
(suite.DefaultEncryptionAlgorithm);
- // FIXME: here wsse:DigestMethod should be embedded
- // inside EncryptionMethod. Since it is not possible
- // with S.S.C.Xml.EncryptionMethod, we will have to
- // build our own XML encryption classes.
-
- edata.KeyInfo = new KeyInfo ();
- LocalIdKeyIdentifierClause ident =
- new LocalIdKeyIdentifierClause (ekeyId);
- KeyInfoClause kic = new SecurityTokenReferenceKeyInfo
(ident, serializer, doc);
- edata.KeyInfo.AddClause (kic);
- edata.CipherData.CipherValue = encrypted;
-
- DataReference dr = new DataReference ();
- dr.Uri = "#" + edata.Id;
- refList.Add (dr);
- return edata;
- }
-
- static string GenerateId (XmlDocument doc)
- {
- int i = 1;
- while (doc.SelectSingleNode (String.Format
(CultureInfo.InvariantCulture, "//[EMAIL PROTECTED] = '_{0}']", i)) != null ||
- doc.SelectSingleNode (String.Format
(CultureInfo.InvariantCulture, "//[EMAIL PROTECTED] = '_{0}']", i)) != null)
- i++;
- return "_" + i;
- }
-
- // Decryption
-
public static Message DecryptMessage (Message inputMessage,
MessageSecurityBindingSupport security)
{
Added:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
2007-01-11 07:17:21 UTC (rev 70834)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
2007-01-11 07:20:53 UTC (rev 70835)
@@ -0,0 +1,467 @@
+//
+// MessageSecurityGenerator.cs
+//
+// Author:
+// Atsushi Enomoto <[EMAIL PROTECTED]>
+//
+// 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
+{
+ internal class InitiatorMessageSecurityGenerator :
MessageSecurityGenerator
+ {
+ EndpointAddress message_to;
+
+ public InitiatorMessageSecurityGenerator (
+ Message msg,
+ ISecurityChannelSource securitySource,
+ EndpointAddress remoteAddress)
+ : this (msg, securitySource.Support, remoteAddress)
+ {
+ }
+
+ public InitiatorMessageSecurityGenerator (
+ Message msg,
+ MessageSecurityBindingSupport security,
+ EndpointAddress messageTo)
+ : base (msg, security)
+ {
+ // FIXME: I believe it should be done at channel
+ // creation phase, but WinFX does not.
+ if
(!security.InitiatorParameters.InternalHasAsymmetricKey)
+ throw new InvalidOperationException ("Wrong
security token parameters: it must have an asymmetric key (HasAsymmetricKey).
There is likely a misconfiguration in the custom security binding element.");
+
+ this.message_to = messageTo;
+ }
+
+ public override MessageDirection Direction {
+ get { return MessageDirection.Input; }
+ }
+
+ public override EndpointAddress MessageTo {
+ get { return message_to; }
+ }
+
+ public override bool ShouldIncludeToken
(SecurityTokenInclusionMode mode, bool isInitialized)
+ {
+ switch (mode) {
+ case SecurityTokenInclusionMode.Never:
+ case SecurityTokenInclusionMode.AlwaysToInitiator:
+ return false;
+ case SecurityTokenInclusionMode.AlwaysToRecipient:
+ return true;
+ case SecurityTokenInclusionMode.Once:
+ return !isInitialized;
+ }
+ throw new Exception ("Internal Error: should not
happen.");
+ }
+
+ public override ScopedMessagePartSpecification MessageParts {
+ get { return
Security.ChannelRequirements.IncomingSignatureParts; }
+ }
+
+ public override SupportingTokenInfoCollection
CollectInitiatorSupportingTokens ()
+ {
+ return Security.CollectInitiatorSupportingTokens
(GetAction (), MessageTo);
+ }
+ }
+
+ internal class RecipientMessageSecurityGenerator :
MessageSecurityGenerator
+ {
+ Uri listen_uri;
+
+ public RecipientMessageSecurityGenerator (
+ Message msg,
+ MessageSecurityBindingSupport security,
+ Uri listenUri)
+ : base (msg, security)
+ {
+ this.listen_uri = listenUri;
+ }
+
+ public override MessageDirection Direction {
+ get { return MessageDirection.Output; }
+ }
+
+ public override EndpointAddress MessageTo {
+ get { return null; }
+ }
+
+ public override bool ShouldIncludeToken
(SecurityTokenInclusionMode mode, bool isInitialized)
+ {
+ switch (mode) {
+ case SecurityTokenInclusionMode.Never:
+ case SecurityTokenInclusionMode.AlwaysToRecipient:
+ return false;
+ case SecurityTokenInclusionMode.AlwaysToInitiator:
+ return true;
+ case SecurityTokenInclusionMode.Once:
+ return !isInitialized;
+ }
+ throw new Exception ("Internal Error: should not
happen.");
+ }
+
+ public override ScopedMessagePartSpecification MessageParts {
+ get { return
Security.ChannelRequirements.OutgoingSignatureParts; }
+ }
+
+ public override SupportingTokenInfoCollection
CollectInitiatorSupportingTokens ()
+ {
+ return Security.CollectRecipientSupportingTokens
(GetAction (), listen_uri);
+ }
+ }
+
+ internal abstract class MessageSecurityGenerator
+ {
+ Message msg;
+ MessageSecurityBindingSupport security;
+
+ public MessageSecurityGenerator (Message msg,
+ MessageSecurityBindingSupport security)
+ {
+ this.msg = msg;
+ this.security = security;
+ }
+
+ public Message Message {
+ get { return msg; }
+ }
+
+ public MessageSecurityBindingSupport Security {
+ get { return security; }
+ }
+
+ public abstract MessageDirection Direction { get; }
+
+ public abstract EndpointAddress MessageTo { get; }
+
+ public abstract ScopedMessagePartSpecification MessageParts {
get; }
+
+ public abstract SupportingTokenInfoCollection
CollectInitiatorSupportingTokens ();
+
+ public abstract bool ShouldIncludeToken
(SecurityTokenInclusionMode mode, bool isInitialized);
+
+ public Message SecureMessage ()
+ {
+ SecurityTokenParameters initiatorParams =
+ security.InitiatorParameters;
+ SecurityTokenParameters recipientParams =
+ security.RecipientParameters;
+ SecurityToken encToken =
+ security.EncryptionToken;
+ SecurityToken signToken =
+ security.SigningToken;
+ MessageProtectionOrder protectionOrder =
+ security.MessageProtectionOrder;
+ SecurityTokenSerializer serializer =
+ security.TokenSerializer;
+ SecurityBindingElement element =
+ security.Element;
+ SecurityAlgorithmSuite suite =
element.DefaultAlgorithmSuite;
+
+ ScopedMessagePartSpecification spec = MessageParts;
+ // FIXME: is it correct? anyways we need to encrypt
parts based on supporting tokens too.
+ SecurityTokenParameters securingParams =
+ Direction == MessageDirection.Input ?
+ initiatorParams : recipientParams;
+
+ SupportingTokenInfoCollection tokens =
+ CollectInitiatorSupportingTokens ();
+
+ // SecurityTokenInclusionMode
+ // - Initiator or Recipient
+ // - done or notyet. FIXME: not implemented yet
+ // It also affects on key reference output
+
+ SecurityTokenInclusionMode appliedMode =
+ securingParams.InclusionMode;
+ bool msgIncludesToken = ShouldIncludeToken
(appliedMode, false);
+
+ SecurityKeyIdentifierClause encClause =
+ initiatorParams.CallCreateKeyIdentifierClause
(encToken, msgIncludesToken ? initiatorParams.ReferenceStyle :
SecurityTokenReferenceStyle.External);
+ SecurityKeyIdentifierClause signClause =
+ recipientParams.CallCreateKeyIdentifierClause
(signToken, msgIncludesToken ? recipientParams.ReferenceStyle :
SecurityTokenReferenceStyle.External);
+
+ AsymmetricSecurityKey encKey = (AsymmetricSecurityKey)
+ encToken.ResolveKeyIdentifierClause (encClause);
+ AsymmetricSecurityKey signKey = (AsymmetricSecurityKey)
+ signToken.ResolveKeyIdentifierClause
(signClause);
+ string messageId = "uuid:" + Guid.NewGuid ();
+ int identForMessageId = 1;
+
+ msg.Headers.Add (MessageHeader.CreateHeader
("MessageID", msg.Version.Addressing.Namespace, messageId));
+
+ // FIXME: get correct ReplyTo value
+ msg.Headers.Add (MessageHeader.CreateHeader ("ReplyTo",
msg.Version.Addressing.Namespace, EndpointAddress10.FromEndpointAddress (new
EndpointAddress (Constants.WsaAnonymousUri))));
+
+ if (MessageTo != null)
+ msg.Headers.Add (MessageHeader.CreateHeader
("To", msg.Version.Addressing.Namespace, MessageTo.Uri.AbsoluteUri, true));
+
+ // addition except for wsse:Security is done. Start
securing...
+
+ XmlDocument doc = new XmlDocument ();
+ doc.PreserveWhitespace = true;
+ XPathNavigator nav = doc.CreateNavigator ();
+ using (XmlWriter w = nav.AppendChild ()) {
+ msg.WriteMessage (w);
+ }
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager
(doc.NameTable);
+ nsmgr.AddNamespace ("s",
msg.Version.Envelope.Namespace);
+
+ WrappedKeySecurityToken ekey = null;
+ ReferenceList encRefList = null;
+ Signature sig = null;
+ EncryptedData sigenc = null;
+
+ // wss:Security
+ WSSecurityMessageHeader header =
+ new WSSecurityMessageHeader (serializer);
+ // wss:Security/wsu:Timestamp
+ if (element.IncludeTimestamp) {
+ WsuTimestamp timestamp = new WsuTimestamp ();
+ timestamp.Id = messageId + "-" +
identForMessageId++;
+ timestamp.Created = DateTime.Now;
+ // FIXME: on service side, use
element.LocalServiceSettings.TimestampValidityDuration
+ timestamp.Expires = timestamp.Created.Add
(element.LocalClientSettings.TimestampValidityDuration);
+ header.Contents.Add (timestamp);
+ }
+ msg.Headers.Add (header);
+
+ // FIXME: it needs to choose message parts by
+ // ChannelProtectionRequirements.
+ XmlElement body = doc.SelectSingleNode
("/s:Envelope/s:Body/*", nsmgr) as XmlElement;
+
+ switch (protectionOrder) {
+ case MessageProtectionOrder.EncryptBeforeSign:
+ // FIXME: implement
+ throw new NotImplementedException ();
+ case MessageProtectionOrder.SignBeforeEncrypt:
+ case
MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature:
+
+ MessagePartSpecification sigSpec;
+ if (!spec.TryGetParts (GetAction (), false, out
sigSpec))
+ sigSpec = spec.ChannelParts;
+
+ // encryption key (possibly also used for
signing)
+ // FIXME: get correct SymmetricAlgorithm
according to the algorithm suite
+ RijndaelManaged aes = new RijndaelManaged ();
+ aes.KeySize = 256;
+ aes.Mode = CipherMode.CBC;
+ aes.Padding = PaddingMode.ISO10126;
+
+ // sign
+ SignedXml sxml = new SignedXml (body);
+
+ HMACSHA1 sigHash = null;
+ if (security.DefaultSignatureAlgorithm ==
SignedXml.XmlDsigHMACSHA1Url)
+ sigHash = new HMACSHA1 (aes.Key);
+ else
+ sxml.SigningKey =
signKey.GetAsymmetricAlgorithm (security.DefaultSignatureAlgorithm, true);
+
+ sig = sxml.Signature;
+ sig.SignedInfo.CanonicalizationMethod =
+ suite.DefaultCanonicalizationAlgorithm;
+ foreach (XmlNode n in doc.SelectNodes
("/s:Envelope/s:Header", nsmgr)) {
+ XmlElement el = n as XmlElement;
+ if (el == null)
+ continue;
+ // FIXME: check sigSpec.HeaderTypes and
skip it if not included.
+ sig.SignedInfo.AddReference
(CreateReference (el, suite));
+ }
+ foreach (XmlNode n in body.ChildNodes) {
+ XmlElement el = n as XmlElement;
+ if (el == null)
+ continue;
+ sig.SignedInfo.AddReference
(CreateReference (el, suite));
+ }
+ if (sigHash != null)
+ sxml.ComputeSignature (sigHash);
+ else
+ sxml.ComputeSignature ();
+ sxml.KeyInfo = new KeyInfo ();
+ SecurityTokenReferenceKeyInfo sigKeyInfo = new
SecurityTokenReferenceKeyInfo (signClause, serializer, doc);
+ sxml.KeyInfo.AddClause (sigKeyInfo);
+
+ // encrypt
+ string ekeyId = messageId + "-" +
identForMessageId++;
+
+ EncryptedXml exml = new EncryptedXml ();
+ ekey = new WrappedKeySecurityToken (ekeyId,
+ aes.Key,
+ suite.DefaultAsymmetricKeyWrapAlgorithm,
+ encToken,
+ new SecurityKeyIdentifier (encClause));
+ encRefList = new ReferenceList ();
+ if (!initiatorParams.RequireDerivedKeys)
+ ekey.ReferenceList = encRefList;
+
+ EncryptedData edata = Encrypt (body, aes,
ekeyId, encRefList, encClause, exml, doc);
+ edata.KeyInfo = null;
+ EncryptedXml.ReplaceElement (body, edata,
false);
+
+ // encrypt signature
+ if (protectionOrder ==
MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature) {
+ XmlElement sigxml = sig.GetXml ();
+ sigenc = Encrypt (sigxml, aes, ekeyId,
encRefList, encClause, exml, doc);
+ }
+ break;
+ }
+
+ Message ret = Message.CreateMessage (msg.Version,
msg.Headers.Action, new XmlNodeReader (doc.SelectSingleNode
("/s:Envelope/s:Body/*", nsmgr) as XmlElement));
+
+ ret.Headers.Clear ();
+ ret.Headers.CopyHeadersFrom (msg);
+
+ if (sig != null && msgIncludesToken)
+ header.Contents.Add (signToken);
+ if (signToken != encToken && msgIncludesToken)
+ header.Contents.Add (encToken);
+
+ if (ekey != null)
+ header.Contents.Add (ekey);
+
+ // generate derived key if needed
+ if (initiatorParams.RequireDerivedKeys) {
+ RijndaelManaged deriv = new RijndaelManaged ();
+ deriv.KeySize = 128;
+ deriv.Mode = CipherMode.CBC;
+ deriv.Padding = PaddingMode.ISO10126;
+ deriv.GenerateKey ();
+ WsscDerivedKeyToken derivedKey =
+ new WsscDerivedKeyToken ();
+ derivedKey.Id = GenerateId (doc);
+ derivedKey.Offset = 0;
+ derivedKey.Nonce = deriv.Key;
+ derivedKey.Length = derivedKey.Nonce.Length;
+ if (ekey != null)
+ derivedKey.SecurityTokenReference =
+ new LocalIdKeyIdentifierClause
(ekey.Id);
+ header.Contents.Add (derivedKey);
+ if (encRefList != null)
+ header.Contents.Add (encRefList);
+ }
+
+ if (sigenc != null)
+ header.Contents.Add (sigenc);
+ else if (sig != null)
+ header.Contents.Add (sig);
+
+ return ret;
+ }
+
+ Reference CreateReference (XmlElement el,
SecurityAlgorithmSuite suite)
+ {
+ if (el.GetAttribute ("Id") == String.Empty)
+ el.SetAttribute ("Id", GenerateId
(el.OwnerDocument));
+ Reference r = new Reference ("#" + el.GetAttribute
("Id"));
+ r.AddTransform (CreateTransform
(suite.DefaultCanonicalizationAlgorithm));
+ r.DigestMethod = suite.DefaultDigestAlgorithm;
+ return r;
+ }
+
+ Transform CreateTransform (string url)
+ {
+ switch (url) {
+ case SignedXml.XmlDsigC14NTransformUrl:
+ return new XmlDsigC14NTransform ();
+ case SignedXml.XmlDsigC14NWithCommentsTransformUrl:
+ return new XmlDsigC14NWithCommentsTransform ();
+ case SignedXml.XmlDsigExcC14NTransformUrl:
+ return new XmlDsigExcC14NTransform ();
+ case SignedXml.XmlDsigExcC14NWithCommentsTransformUrl:
+ return new XmlDsigExcC14NWithCommentsTransform
();
+ }
+ throw new Exception (String.Format ("INTERNAL ERROR:
Invalid canonicalization URL: {0}", url));
+ }
+
+ EncryptedData Encrypt (XmlElement target, SymmetricAlgorithm
aes, string ekeyId, ReferenceList refList, SecurityKeyIdentifierClause
encClause, EncryptedXml exml, XmlDocument doc)
+ {
+ SecurityAlgorithmSuite suite =
security.Element.DefaultAlgorithmSuite;
+ SecurityTokenSerializer serializer =
security.TokenSerializer;
+
+ byte [] encrypted = exml.EncryptData (target, aes,
false);
+ EncryptedData edata = new EncryptedData ();
+ edata.Id = GenerateId (doc);
+ edata.Type = EncryptedXml.XmlEncElementUrl;
+ edata.EncryptionMethod = new EncryptionMethod
(suite.DefaultEncryptionAlgorithm);
+ // FIXME: here wsse:DigestMethod should be embedded
+ // inside EncryptionMethod. Since it is not possible
+ // with S.S.C.Xml.EncryptionMethod, we will have to
+ // build our own XML encryption classes.
+
+ edata.KeyInfo = new KeyInfo ();
+ LocalIdKeyIdentifierClause ident =
+ new LocalIdKeyIdentifierClause (ekeyId);
+ KeyInfoClause kic = new SecurityTokenReferenceKeyInfo
(ident, serializer, doc);
+ edata.KeyInfo.AddClause (kic);
+ edata.CipherData.CipherValue = encrypted;
+
+ DataReference dr = new DataReference ();
+ dr.Uri = "#" + edata.Id;
+ refList.Add (dr);
+ return edata;
+ }
+
+ static string GenerateId (XmlDocument doc)
+ {
+ int i = 1;
+ while (doc.SelectSingleNode (String.Format
(CultureInfo.InvariantCulture, "//[EMAIL PROTECTED] = '_{0}']", i)) != null ||
+ doc.SelectSingleNode (String.Format
(CultureInfo.InvariantCulture, "//[EMAIL PROTECTED] = '_{0}']", i)) != null)
+ i++;
+ return "_" + i;
+ }
+
+ public string GetAction ()
+ {
+ string ret = msg.Headers.Action;
+ if (ret == null) {
+ HttpRequestMessageProperty reqprop =
+ msg.Properties ["Action"] as
HttpRequestMessageProperty;
+ if (reqprop != null)
+ ret = reqprop.Headers ["Action"];
+ }
+ return ret;
+ }
+ }
+}
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityOutputChannel.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityOutputChannel.cs
2007-01-11 07:17:21 UTC (rev 70834)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityOutputChannel.cs
2007-01-11 07:20:53 UTC (rev 70835)
@@ -123,10 +123,7 @@
Message SecureMessage (Message msg)
{
- return MessageSecurityUtility.SecureMessage (
- msg,
- security,
- RemoteAddress);
+ return new InitiatorMessageSecurityGenerator (msg,
security, RemoteAddress).SecureMessage ();
}
void AcquireSecurityKey (object o, EventArgs e)
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestChannel.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestChannel.cs
2007-01-11 07:17:21 UTC (rev 70834)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestChannel.cs
2007-01-11 07:20:53 UTC (rev 70835)
@@ -130,10 +130,7 @@
Message SecureMessage (Message msg)
{
- return MessageSecurityUtility.SecureMessage (
- msg,
- security,
- RemoteAddress);
+ return new InitiatorMessageSecurityGenerator (msg,
security, RemoteAddress).SecureMessage ();
}
Message ProcessReply (Message message)
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestContext.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestContext.cs
2007-01-11 07:17:21 UTC (rev 70834)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecurityRequestContext.cs
2007-01-11 07:20:53 UTC (rev 70835)
@@ -109,11 +109,7 @@
Message SecureMessage (Message input)
{
- return MessageSecurityUtility.SecureMessage (
- input,
- null,
- security,
- MessageDirection.Output);
+ return new RecipientMessageSecurityGenerator (input,
security, channel.Source.Uri).SecureMessage ();
}
}
}
Modified: trunk/olive/class/System.ServiceModel/System.ServiceModel.dll.sources
===================================================================
--- trunk/olive/class/System.ServiceModel/System.ServiceModel.dll.sources
2007-01-11 07:17:21 UTC (rev 70834)
+++ trunk/olive/class/System.ServiceModel/System.ServiceModel.dll.sources
2007-01-11 07:20:53 UTC (rev 70835)
@@ -163,6 +163,7 @@
System.ServiceModel.Channels/ReplyChannelBase.cs
System.ServiceModel.Channels/RequestChannelBase.cs
System.ServiceModel.Channels/RequestContext.cs
+System.ServiceModel.Channels/SecureMessageGenerator.cs
System.ServiceModel.Channels/SecurityBindingElement.cs
System.ServiceModel.Channels/SecurityBindingElementImporter.cs
System.ServiceModel.Channels/SecurityChannelFactory.cs
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches