| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800 |
- //
- // 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.Security
- {
- internal class InitiatorMessageSecurityGenerator : MessageSecurityGenerator
- {
- EndpointAddress message_to;
- InitiatorMessageSecurityBindingSupport security;
- public InitiatorMessageSecurityGenerator (
- Message msg,
- InitiatorMessageSecurityBindingSupport 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.security = security;
- this.message_to = messageTo;
- }
- public override SecurityTokenParameters Parameters {
- get { return security.InitiatorParameters; }
- }
- public override SecurityTokenParameters CounterParameters {
- get { return security.RecipientParameters; }
- }
- 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 SignatureParts {
- get { return Security.ChannelRequirements.IncomingSignatureParts; }
- }
- public override ScopedMessagePartSpecification EncryptionParts {
- get { return Security.ChannelRequirements.IncomingEncryptionParts; }
- }
- }
- internal class RecipientMessageSecurityGenerator : MessageSecurityGenerator
- {
- RecipientMessageSecurityBindingSupport security;
- public RecipientMessageSecurityGenerator (
- Message msg,
- SecurityMessageProperty requestSecProp,
- RecipientMessageSecurityBindingSupport security)
- : base (msg, security)
- {
- this.security = security;
- SecurityMessageProperty secprop =
- (SecurityMessageProperty) requestSecProp.CreateCopy ();
- msg.Properties.Security = secprop;
- }
- public override SecurityTokenParameters Parameters {
- get { return security.RecipientParameters; }
- }
- public override SecurityTokenParameters CounterParameters {
- get { return security.InitiatorParameters; }
- }
- 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 SignatureParts {
- get { return Security.ChannelRequirements.OutgoingSignatureParts; }
- }
- public override ScopedMessagePartSpecification EncryptionParts {
- get { return Security.ChannelRequirements.OutgoingEncryptionParts; }
- }
- }
- internal abstract class MessageSecurityGenerator
- {
- Message msg;
- SecurityMessageProperty secprop;
- MessageSecurityBindingSupport security;
- int idbase;
- 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 SecurityTokenParameters Parameters { get; }
- public abstract SecurityTokenParameters CounterParameters { get; }
- public abstract MessageDirection Direction { get; }
- public abstract EndpointAddress MessageTo { get; }
- public abstract ScopedMessagePartSpecification SignatureParts { get; }
- public abstract ScopedMessagePartSpecification EncryptionParts { get; }
- public MessagePartSpecification SignaturePart {
- get {
- MessagePartSpecification spec;
- if (!SignatureParts.TryGetParts (GetAction (), false, out spec))
- spec = SignatureParts.ChannelParts;
- return spec;
- }
- }
- public MessagePartSpecification EncryptionPart {
- get {
- MessagePartSpecification spec;
- if (!EncryptionParts.TryGetParts (GetAction (), false, out spec))
- spec = EncryptionParts.ChannelParts;
- return spec;
- }
- }
- public abstract bool ShouldIncludeToken (SecurityTokenInclusionMode mode, bool isInitialized);
- public bool ShouldOutputEncryptedKey {
- get { return Direction == MessageDirection.Input || secprop.ProtectionToken == null; } //security.Element is AsymmetricSecurityBindingElement; }
- }
- public Message SecureMessage ()
- {
- secprop = Message.Properties.Security ?? new SecurityMessageProperty ();
- SecurityToken encToken =
- secprop.InitiatorToken != null ? secprop.InitiatorToken.SecurityToken : security.EncryptionToken;
- // FIXME: it might be still incorrect.
- SecurityToken signToken =
- Parameters == CounterParameters ? null :
- security.SigningToken;
- MessageProtectionOrder protectionOrder =
- security.MessageProtectionOrder;
- SecurityBindingElement element =
- security.Element;
- SecurityAlgorithmSuite suite = element.DefaultAlgorithmSuite;
- string messageId = "uuid-" + Guid.NewGuid ();
- int identForMessageId = 1;
- XmlDocument doc = new XmlDocument ();
- doc.PreserveWhitespace = true;
- var action = msg.Headers.Action;
- if (msg.Version.Addressing != AddressingVersion.None) {
- AddAddressingToHeader (msg.Headers);
- }
-
- // wss:Security
- WSSecurityMessageHeader header =
- new WSSecurityMessageHeader (security.TokenSerializer);
- msg.Headers.Add (header);
- // 1. [Timestamp]
- if (element.IncludeTimestamp) {
- AddTimestampToHeader (header, messageId + "-" + identForMessageId++);
- }
- XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
- nsmgr.AddNamespace ("s", msg.Version.Envelope.Namespace);
- nsmgr.AddNamespace ("o", Constants.WssNamespace);
- nsmgr.AddNamespace ("u", Constants.WsuNamespace);
- nsmgr.AddNamespace ("o11", Constants.Wss11Namespace);
- /*WrappedKey*/SecurityToken primaryToken = null;
- SecurityToken actualToken = null;
- SecurityKeyIdentifierClause actualClause = null;
-
- SymmetricAlgorithm masterKey = new RijndaelManaged ();
- masterKey.KeySize = suite.DefaultSymmetricKeyLength;
- masterKey.Mode = CipherMode.CBC;
- masterKey.Padding = PaddingMode.ISO10126;
- SymmetricAlgorithm actualKey = masterKey;
- // 2. [Encryption Token]
- // SecurityTokenInclusionMode
- // - Initiator or Recipient
- // - done or notyet. FIXME: not implemented yet
- // It also affects on key reference output
- bool includeEncToken = // /* FIXME: remove this hack */Parameters is SslSecurityTokenParameters ? false :
- ShouldIncludeToken (
- Security.RecipientParameters.InclusionMode, false);
- bool includeSigToken = // /* FIXME: remove this hack */ Parameters is SslSecurityTokenParameters ? false :
- ShouldIncludeToken (
- Security.InitiatorParameters.InclusionMode, false);
- SecurityKeyIdentifierClause encClause = ShouldOutputEncryptedKey ?
- CounterParameters.CallCreateKeyIdentifierClause (encToken, !ShouldOutputEncryptedKey ? SecurityTokenReferenceStyle.Internal : includeEncToken ? Parameters.ReferenceStyle : SecurityTokenReferenceStyle.External) : null;
- MessagePartSpecification encSpec = EncryptionPart;
- // encryption key (possibly also used for signing)
- // FIXME: get correct SymmetricAlgorithm according to the algorithm suite
- if (secprop.EncryptionKey != null)
- actualKey.Key = secprop.EncryptionKey;
- // FIXME: remove thid hack
- if (!ShouldOutputEncryptedKey)
- primaryToken = secprop.ProtectionToken.SecurityToken as WrappedKeySecurityToken;
- else
- primaryToken =
- // FIXME: remove this hack?
- encToken is SecurityContextSecurityToken ? encToken :
- new WrappedKeySecurityToken (messageId + "-" + identForMessageId++,
- actualKey.Key,
- // security.DefaultKeyWrapAlgorithm,
- Parameters.InternalHasAsymmetricKey ?
- suite.DefaultAsymmetricKeyWrapAlgorithm :
- suite.DefaultSymmetricKeyWrapAlgorithm,
- encToken,
- encClause != null ? new SecurityKeyIdentifier (encClause) : null);
- // If it reuses request's encryption key, do not output.
- if (ShouldOutputEncryptedKey)
- header.AddContent (primaryToken);
- actualToken = primaryToken;
- // FIXME: I doubt it is correct...
- WrappedKeySecurityToken requestEncKey = ShouldOutputEncryptedKey ? null : primaryToken as WrappedKeySecurityToken;
- actualClause = requestEncKey == null ? (SecurityKeyIdentifierClause)
- new LocalIdKeyIdentifierClause (actualToken.Id, typeof (WrappedKeySecurityToken)) :
- new InternalEncryptedKeyIdentifierClause (SHA1.Create ().ComputeHash (requestEncKey.GetWrappedKey ()));
- // generate derived key if needed
- if (CounterParameters.RequireDerivedKeys) {
- var dkeyToken = CreateDerivedKey (GenerateId (doc), actualClause, actualKey);
- actualToken = dkeyToken;
- actualKey.Key = ((SymmetricSecurityKey)dkeyToken.SecurityKeys [0]).GetSymmetricKey ();
- actualClause = new LocalIdKeyIdentifierClause (dkeyToken.Id);
- header.AddContent (dkeyToken);
- }
- ReferenceList refList = new ReferenceList ();
- // When encrypted with DerivedKeyToken, put references
- // immediately after the derived token (not inside the
- // primary token).
- // Similarly, when we do not output EncryptedKey,
- // output ReferenceList in the same way.
- if (CounterParameters.RequireDerivedKeys ||
- !ShouldOutputEncryptedKey)
- header.AddContent (refList);
- else
- ((WrappedKeySecurityToken) primaryToken).ReferenceList = refList;
- // [Signature Confirmation]
- if (security.RequireSignatureConfirmation && secprop.ConfirmedSignatures.Count > 0)
- foreach (string value in secprop.ConfirmedSignatures)
- header.AddContent (new Wss11SignatureConfirmation (GenerateId (doc), value));
- SupportingTokenInfoCollection tokenInfos =
- Direction == MessageDirection.Input ?
- security.CollectSupportingTokens (GetAction ()) :
- new SupportingTokenInfoCollection (); // empty
- foreach (SupportingTokenInfo tinfo in tokenInfos)
- header.AddContent (tinfo.Token);
- // populate DOM to sign.
- XPathNavigator nav = doc.CreateNavigator ();
- using (XmlWriter w = nav.AppendChild ()) {
- msg.WriteMessage (w);
- }
- XmlElement body = doc.SelectSingleNode ("/s:Envelope/s:Body/*", nsmgr) as XmlElement;
- string bodyId = null;
- Collection<WSSignedXml> endorsedSignatures =
- new Collection<WSSignedXml> ();
- bool signatureProtection = (protectionOrder == MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature);
- // Below are o:Security contents that are not signed...
- if (includeSigToken && signToken != null)
- header.AddContent (signToken);
- switch (protectionOrder) {
- case MessageProtectionOrder.EncryptBeforeSign:
- // FIXME: implement
- throw new NotImplementedException ();
- case MessageProtectionOrder.SignBeforeEncrypt:
- case MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature:
-
- var sig = CreateSignature (doc, body, nsmgr, tokenInfos,
- actualClause, actualKey, signToken, includeSigToken,
- signatureProtection, header, endorsedSignatures,
- ref bodyId);
-
- // encrypt
- WSEncryptedXml exml = new WSEncryptedXml (doc);
- EncryptedData edata = Encrypt (body, actualKey, actualToken.Id, refList, actualClause, exml, doc, EncryptedXml.XmlEncElementContentUrl);
- EncryptedXml.ReplaceElement (body, edata, false);
- // encrypt signature
- if (signatureProtection) {
- XmlElement sigxml = sig.GetXml ();
- edata = Encrypt (sigxml, actualKey, actualToken.Id, refList, actualClause, exml, doc, EncryptedXml.XmlEncElementUrl);
- header.AddContent (edata);
- foreach (WSSignedXml ssxml in endorsedSignatures) {
- sigxml = ssxml.GetXml ();
- edata = Encrypt (sigxml, actualKey, actualToken.Id, refList, actualClause, exml, doc, EncryptedXml.XmlEncElementUrl);
- header.AddContent (edata);
- }
- if (security.RequireSignatureConfirmation) {
- Collection<Wss11SignatureConfirmation> confs = header.FindAll<Wss11SignatureConfirmation> ();
- int count = 0;
- foreach (XmlElement elem in doc.SelectNodes ("/s:Envelope/s:Header/o:Security/o11:SignatureConfirmation", nsmgr)) {
- edata = Encrypt (elem, actualKey, confs [count].Id, refList, actualClause, exml, doc, EncryptedXml.XmlEncElementUrl);
- EncryptedXml.ReplaceElement (elem, edata, false);
- header.Contents.Insert (header.Contents.IndexOf (confs [count]), edata);
- header.Contents.Remove (confs [count++]);
- }
- }
- }
- // encrypt Encrypted supporting tokens
- foreach (SupportingTokenInfo tinfo in tokenInfos) {
- if (tinfo.Mode == SecurityTokenAttachmentMode.SignedEncrypted) {
- XmlElement el = exml.GetIdElement (doc, tinfo.Token.Id);
- tinfo.Encrypted = Encrypt (el, actualKey, actualToken.Id, refList, actualClause, exml, doc, EncryptedXml.XmlEncElementUrl);
- EncryptedXml.ReplaceElement (el, tinfo.Encrypted, false);
- header.Contents.Insert (header.Contents.IndexOf (tinfo.Token), tinfo.Encrypted);
- header.Contents.Remove (tinfo.Token);
- }
- }
- break;
- }
-
- Message ret = new WSSecurityMessage (Message.CreateMessage (msg.Version, action, new XmlNodeReader (doc.SelectSingleNode ("/s:Envelope/s:Body/*", nsmgr) as XmlElement)), bodyId);
- ret.Properties.Security = (SecurityMessageProperty) secprop.CreateCopy ();
- ret.Properties.Security.EncryptionKey = masterKey.Key;
- // FIXME: can we support TransportToken here?
- if (element is AsymmetricSecurityBindingElement) {
- ret.Properties.Security.InitiatorToken = new SecurityTokenSpecification (encToken, null); // FIXME: second argument
- ret.Properties.Security.InitiatorToken = new SecurityTokenSpecification (signToken, null); // FIXME: second argument
- }
- else
- ret.Properties.Security.ProtectionToken = new SecurityTokenSpecification (primaryToken, null);
- ret.Headers.Clear ();
- ret.Headers.CopyHeadersFrom (msg);
-
- // Header contents are:
- // - Timestamp
- // - SignatureConfirmation if required
- // - EncryptionToken if included
- // - derived key token for EncryptionToken
- // - ReferenceList for encrypted items
- // - signed supporting tokens
- // - signed endorsing supporting tokens
- // (i.e. Signed/SignedEncrypted/SignedEndorsing)
- // - Signature Token if different from enc token.
- // - derived key token for sig token if different
- // - Signature for:
- // - Timestamp
- // - supporting tokens (regardless of
- // its inclusion)
- // - message parts in SignedParts
- // - SignatureToken if TokenProtection
- // (regardless of its inclusion)
- // - Signatures for the main signature (above),
- // for every endorsing token and signed
- // endorsing token.
- //
- //MessageBuffer zzz = ret.CreateBufferedCopy (100000);
- //ret = zzz.CreateMessage ();
- //Console.WriteLine (zzz.CreateMessage ());
- return ret;
- }
- Signature CreateSignature (XmlDocument doc, XmlElement body,
- XmlNamespaceManager nsmgr,
- SupportingTokenInfoCollection tokenInfos,
- SecurityKeyIdentifierClause actualClause,
- SymmetricAlgorithm actualKey,
- SecurityToken signToken,
- bool includeSigToken,
- bool signatureProtection,
- WSSecurityMessageHeader header,
- Collection<WSSignedXml> endorsedSignatures,
- ref string bodyId)
- {
- // sign
- // see clause 8 of WS-SecurityPolicy C.2.2
- WSSignedXml sxml = new WSSignedXml (doc);
- SecurityTokenReferenceKeyInfo sigKeyInfo;
- XmlElement secElem = null;
- var sigSpec = SignaturePart;
- var serializer = security.TokenSerializer;
- var suite = security.Element.DefaultAlgorithmSuite;
- var sig = sxml.Signature;
- sig.SignedInfo.CanonicalizationMethod =
- suite.DefaultCanonicalizationAlgorithm;
- foreach (XmlElement elem in doc.SelectNodes ("/s:Envelope/s:Header/o:Security/u:Timestamp", nsmgr))
- CreateReference(sig, elem, elem.GetAttribute ("Id", Constants.WsuNamespace));
- foreach (XmlElement elem in doc.SelectNodes ("/s:Envelope/s:Header/o:Security/o11:SignatureConfirmation", nsmgr))
- CreateReference(sig, elem, elem.GetAttribute ("Id", Constants.WsuNamespace));
- foreach (SupportingTokenInfo tinfo in tokenInfos)
- if (tinfo.Mode != SecurityTokenAttachmentMode.Endorsing) {
- XmlElement el = sxml.GetIdElement (doc, tinfo.Token.Id);
- CreateReference (sig, el, el.GetAttribute ("Id", Constants.WsuNamespace));
- }
- XmlNodeList nodes = doc.SelectNodes ("/s:Envelope/s:Header/*", nsmgr);
- for (int i = 0; i < msg.Headers.Count; i++) {
- MessageHeaderInfo h = msg.Headers [i];
- if (h.Name == "Security" && h.Namespace == Constants.WssNamespace)
- secElem = nodes [i] as XmlElement;
- else if ((sigSpec.HeaderTypes.Count == 0 ||
- sigSpec.HeaderTypes.Contains (new XmlQualifiedName(h.Name, h.Namespace))) &&
- (msg.Version.Addressing != AddressingVersion.None ||
- !String.Equals (h.Name, "Action", StringComparison.Ordinal))) {
- string id = GenerateId (doc);
- h.Id = id;
- CreateReference (sig, nodes [i] as XmlElement, id);
- }
- }
- if (sigSpec.IsBodyIncluded) {
- bodyId = GenerateId (doc);
- CreateReference (sig, body.ParentNode as XmlElement, bodyId);
- }
- if (security.DefaultSignatureAlgorithm == SignedXml.XmlDsigHMACSHA1Url) {
- // FIXME: use appropriate hash algorithm
- sxml.ComputeSignature (new HMACSHA1(actualKey.Key));
- sigKeyInfo = new SecurityTokenReferenceKeyInfo (actualClause, serializer, doc);
- } else {
- SecurityKeyIdentifierClause signClause =
- CounterParameters.CallCreateKeyIdentifierClause (signToken, includeSigToken ? CounterParameters.ReferenceStyle : SecurityTokenReferenceStyle.External);
- AsymmetricSecurityKey signKey = (AsymmetricSecurityKey)signToken.ResolveKeyIdentifierClause (signClause);
- sxml.SigningKey = signKey.GetAsymmetricAlgorithm (security.DefaultSignatureAlgorithm, true);
- sxml.ComputeSignature ();
- sigKeyInfo = new SecurityTokenReferenceKeyInfo (signClause, serializer, doc);
- }
- sxml.KeyInfo = new KeyInfo ();
- sxml.KeyInfo.AddClause (sigKeyInfo);
- if (!signatureProtection)
- header.AddContent (sig);
- // endorse the signature with (signed)endorsing
- // supporting tokens.
- foreach (SupportingTokenInfo tinfo in tokenInfos) {
- switch (tinfo.Mode) {
- case SecurityTokenAttachmentMode.Endorsing:
- case SecurityTokenAttachmentMode.SignedEndorsing:
- if (sxml.Signature.Id == null) {
- sig.Id = GenerateId (doc);
- secElem.AppendChild (sxml.GetXml ());
- }
- WSSignedXml ssxml = new WSSignedXml (doc);
- ssxml.Signature.SignedInfo.CanonicalizationMethod = suite.DefaultCanonicalizationAlgorithm;
- CreateReference (ssxml.Signature, doc, sig.Id);
- SecurityToken sst = tinfo.Token;
- SecurityKey ssk = sst.SecurityKeys [0]; // FIXME: could be different?
- SecurityKeyIdentifierClause tclause = new LocalIdKeyIdentifierClause (sst.Id); // FIXME: could be different?
- if (ssk is SymmetricSecurityKey) {
- SymmetricSecurityKey signKey = (SymmetricSecurityKey)ssk;
- ssxml.ComputeSignature (signKey.GetKeyedHashAlgorithm(suite.DefaultSymmetricSignatureAlgorithm));
- } else {
- AsymmetricSecurityKey signKey = (AsymmetricSecurityKey)ssk;
- ssxml.SigningKey = signKey.GetAsymmetricAlgorithm (suite.DefaultAsymmetricSignatureAlgorithm, true);
- ssxml.ComputeSignature ();
- }
- ssxml.KeyInfo.AddClause (new SecurityTokenReferenceKeyInfo (tclause, serializer, doc));
- if (!signatureProtection)
- header.AddContent (ssxml.Signature);
- endorsedSignatures.Add (ssxml);
- break;
- }
- }
- return sig;
- }
- void AddAddressingToHeader (MessageHeaders headers)
- {
- // FIXME: get correct ReplyTo value
- if (Direction == MessageDirection.Input)
- headers.ReplyTo = new EndpointAddress (Constants.WsaAnonymousUri);
- if (MessageTo != null)
- headers.To = MessageTo.Uri;
- }
- DerivedKeySecurityToken CreateDerivedKey (string id,
- SecurityKeyIdentifierClause actualClause,
- SymmetricAlgorithm actualKey)
- {
- RijndaelManaged deriv = new RijndaelManaged ();
- deriv.KeySize = security.Element.DefaultAlgorithmSuite.DefaultEncryptionKeyDerivationLength;
- deriv.Mode = CipherMode.CBC;
- deriv.Padding = PaddingMode.ISO10126;
- deriv.GenerateKey ();
- var dkeyToken = new DerivedKeySecurityToken (
- id,
- null, // algorithm
- actualClause,
- new InMemorySymmetricSecurityKey (actualKey.Key),
- null, // name
- null, // generation
- null, // offset
- deriv.Key.Length,
- null, // label
- deriv.Key);
- return dkeyToken;
- }
- void AddTimestampToHeader (WSSecurityMessageHeader header, string id)
- {
- WsuTimestamp timestamp = new WsuTimestamp ();
- timestamp.Id = id;
- timestamp.Created = DateTime.Now;
- // FIXME: on service side, use element.LocalServiceSettings.TimestampValidityDuration
- timestamp.Expires = timestamp.Created.Add (security.Element.LocalClientSettings.TimestampValidityDuration);
- header.AddContent (timestamp);
- }
- void CreateReference (Signature sig, XmlElement el, string id)
- {
- CreateReference (sig, el.OwnerDocument, id);
- if (el.GetAttribute ("Id", Constants.WsuNamespace) != id) {
- XmlAttribute a = el.SetAttributeNode ("Id", Constants.WsuNamespace);
- a.Prefix = "u";
- a.Value = id;
- }
- }
- void CreateReference (Signature sig, XmlDocument doc, string id)
- {
- SecurityAlgorithmSuite suite = security.Element.DefaultAlgorithmSuite;
- if (id == String.Empty)
- id = GenerateId (doc);
- Reference r = new Reference ("#" + id);
- r.AddTransform (CreateTransform (suite.DefaultCanonicalizationAlgorithm));
- r.DigestMethod = suite.DefaultDigestAlgorithm;
- sig.SignedInfo.AddReference (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 actualKey, string ekeyId, ReferenceList refList, SecurityKeyIdentifierClause encClause, EncryptedXml exml, XmlDocument doc, string elementType)
- {
- SecurityAlgorithmSuite suite = security.Element.DefaultAlgorithmSuite;
- SecurityTokenSerializer serializer = security.TokenSerializer;
- byte [] encrypted = exml.EncryptData (target, actualKey, false);
- EncryptedData edata = new EncryptedData ();
- edata.Id = GenerateId (doc);
- edata.Type = elementType;
- 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.CipherData.CipherValue = encrypted;
- DataReference dr = new DataReference ();
- dr.Uri = "#" + edata.Id;
- refList.Add (dr);
- if (ShouldOutputEncryptedKey && !CounterParameters.RequireDerivedKeys)
- edata.KeyInfo = null;
- else {
- edata.KeyInfo = new KeyInfo ();
- edata.KeyInfo.AddClause (new SecurityTokenReferenceKeyInfo (encClause, serializer, doc));
- }
- return edata;
- }
- string GenerateId (XmlDocument doc)
- {
- idbase++;
- return secprop.SenderIdPrefix + idbase;
- }
- public string GetAction ()
- {
- string ret = msg.Headers.Action;
- if (ret == null) {
- HttpRequestMessageProperty reqprop =
- msg.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
- if (reqprop != null)
- ret = reqprop.Headers ["Action"];
- }
- return ret;
- }
- }
- internal class WSSecurityMessage : Message
- {
- Message msg;
- string body_id;
- public WSSecurityMessage (Message msg, string bodyId)
- {
- this.msg = msg;
- this.body_id = bodyId;
- }
- public override MessageVersion Version {
- get { return msg.Version; }
- }
- public override MessageHeaders Headers {
- get { return msg.Headers; }
- }
- public override MessageProperties Properties {
- get { return msg.Properties; }
- }
- protected override MessageBuffer OnCreateBufferedCopy (int maxBufferSize)
- {
- return new WSSecurityMessageBuffer (msg.CreateBufferedCopy (maxBufferSize), body_id);
- }
- protected override string OnGetBodyAttribute (string localName, string ns)
- {
- if (localName == "Id" && ns == Constants.WsuNamespace)
- return body_id;
- return msg.GetBodyAttribute (localName, ns);
- }
- protected override void OnWriteStartBody (
- XmlDictionaryWriter writer)
- {
- var dic = Constants.SoapDictionary;
- writer.WriteStartElement ("s", dic.Add ("Body"), dic.Add (Version.Envelope.Namespace));
- if (body_id != null)
- writer.WriteAttributeString ("u", "Id", Constants.WsuNamespace, body_id);
-
- }
- protected override void OnWriteBodyContents (XmlDictionaryWriter w)
- {
- msg.WriteBodyContents (w);
- }
- }
-
- internal class WSSecurityMessageBuffer : MessageBuffer
- {
- public WSSecurityMessageBuffer (MessageBuffer mb, string bodyId)
- {
- buffer = mb;
- body_id = bodyId;
- }
-
- MessageBuffer buffer;
- string body_id;
-
- public override int BufferSize {
- get { return buffer.BufferSize; }
- }
-
- public override void Close ()
- {
- buffer.Close ();
- }
-
- public override Message CreateMessage ()
- {
- return new WSSecurityMessage (buffer.CreateMessage (), body_id);
- }
- }
- }
|