Author: atsushi
Date: 2007-02-06 17:14:54 -0500 (Tue, 06 Feb 2007)
New Revision: 72381
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityBindingSupport.cs
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageDecryptor.cs
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/ChangeLog
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/WSSecurityTokenSerializerTest.cs
Log:
2007-02-06 Atsushi Enomoto <[EMAIL PROTECTED]>
* MessageSecurityBindingSupport.cs : added CreateTokenAuthenticator()
for supporting 'supporting tokens' .
* SecureMessageGenerator.cs : Supporting token creation is done only
at initiator (not sure if it is supposed that, but for now it is).
Removed extraneous CollectSupportingTokens().
* SecureMessageDecryptor.cs : implemented supporting token
authentication (partly). "Signed" supporting tokens are expected
to work fine.
* WSSecurityTokenSerializerTest.cs: some tests for writing derived-
key-involved key identifier clauses.
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
2007-02-06 22:09:28 UTC (rev 72380)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
2007-02-06 22:14:54 UTC (rev 72381)
@@ -1,5 +1,16 @@
2007-02-06 Atsushi Enomoto <[EMAIL PROTECTED]>
+ * MessageSecurityBindingSupport.cs : added CreateTokenAuthenticator()
+ for supporting 'supporting tokens' .
+ * SecureMessageGenerator.cs : Supporting token creation is done only
+ at initiator (not sure if it is supposed that, but for now it is).
+ Removed extraneous CollectSupportingTokens().
+ * SecureMessageDecryptor.cs : implemented supporting token
+ authentication (partly). "Signed" supporting tokens are expected
+ to work fine.
+
+2007-02-06 Atsushi Enomoto <[EMAIL PROTECTED]>
+
* SecureMessageGenerator.cs :
make SignBeforeEncryptAndEncryptSignature working.
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityBindingSupport.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityBindingSupport.cs
2007-02-06 22:09:28 UTC (rev 72380)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/MessageSecurityBindingSupport.cs
2007-02-06 22:14:54 UTC (rev 72381)
@@ -174,6 +174,13 @@
return manager.CreateSecurityTokenProvider
(requirement);
}
+ public SecurityTokenAuthenticator CreateTokenAuthenticator
(SecurityTokenParameters p, out SecurityTokenResolver resolver)
+ {
+ SecurityTokenRequirement r = CreateRequirement ();
+ p.CallInitializeSecurityTokenRequirement (r);
+ return manager.CreateSecurityTokenAuthenticator (r, out
resolver);
+ }
+
public void CreateTokenAuthenticator (SecurityTokenRequirement
requirement)
{
authenticator =
manager.CreateSecurityTokenAuthenticator (requirement, out auth_token_resolver);
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageDecryptor.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageDecryptor.cs
2007-02-06 22:09:28 UTC (rev 72380)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageDecryptor.cs
2007-02-06 22:14:54 UTC (rev 72381)
@@ -60,6 +60,10 @@
this.security = security;
}
+ public override MessageDirection Direction {
+ get { return MessageDirection.Input; }
+ }
+
public override byte [] ActiveKey {
get { return null; }
}
@@ -90,6 +94,10 @@
get { return active_key; }
}
+ public override MessageDirection Direction {
+ get { return MessageDirection.Output; }
+ }
+
public override SecurityTokenParameters Parameters {
get { return security.InitiatorParameters; }
}
@@ -136,6 +144,7 @@
}
+ public abstract MessageDirection Direction { get; }
public abstract SecurityTokenParameters Parameters { get; }
public abstract SecurityTokenParameters CounterParameters {
get; }
public abstract byte [] ActiveKey { get; }
@@ -160,7 +169,7 @@
XmlNodeList securityHeaders = doc.SelectNodes
("/s:Envelope/s:Header/o:Security", nsmgr);
foreach (XmlElement secElem in securityHeaders)
- // FIXME: check Actor.
+ // FIXME: check Actor. There is only one
o:Security which we should handle.
ExtractSecurity (secElem);
Message msg = Message.CreateMessage (new XmlNodeReader
(doc), srcmsg.Headers.Count, srcmsg.Version);
@@ -283,7 +292,6 @@
ed2.LoadXml (el);
byte [] key = GetEncryptionKeyForData (ed2,
encXml, map);
aes.Key = key != null ? key : decryptedKey;
- if (ed2.GetXml () == null) throw new Exception
("Gyabo");
encXml.ReplaceData (el, DecryptLax (encXml,
ed2, aes));
}
@@ -297,8 +305,6 @@
if (sigElem == null)
throw new MessageSecurityException ("The the
message signature is expected but not found.");
- // FIXME: the security tokens must be authenticated.
-
WSSignedXml sxml = new WSSignedXml (nsmgr, doc);
sxml.LoadXml (sigElem);
SecurityTokenSerializer serializer =
@@ -318,25 +324,126 @@
if (security.DefaultSignatureAlgorithm ==
SignedXml.XmlDsigHMACSHA1Url)
confirmed = sxml.CheckSignature (new HMACSHA1
(aes.Key));
else {
+ // my guess is that this could also apply to
symmetric binding case i.e. key resolution could be done as
WrappedKeySecurityToken resolution.
SecurityKey signKey;
SecurityTokenResolver outband =
security.OutOfBandTokenResolver;
SecurityToken signToken;
if (!in_band_resolver.TryResolveToken
(sigClause, out signToken) &&
(outband == null ||
!outband.TryResolveToken (sigClause, out signToken)))
throw new MessageSecurityException
(String.Format ("The signing key could not be resolved from {0}", signKey));
+ signKey = signToken.ResolveKeyIdentifierClause
(sigClause);
+ AsymmetricAlgorithm sigalg =
((AsymmetricSecurityKey) signKey).GetAsymmetricAlgorithm
(security.DefaultSignatureAlgorithm, false);
+ confirmed = sxml.CheckSignature (sigalg);
+
+ // FIXME: it should not apply only to
asymmetric case.
sec_prop.InitiatorToken = new
SecurityTokenSpecification (
signToken,
security.TokenAuthenticator.ValidateToken (signToken));
- signKey = signToken.ResolveKeyIdentifierClause
(sigClause);
- AsymmetricAlgorithm sigalg =
((AsymmetricSecurityKey) signKey).GetAsymmetricAlgorithm
(security.DefaultSignatureAlgorithm, false);
- confirmed = sxml.CheckSignature (sigalg);
}
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 = decryptedKey;
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 ();
+ 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);
+ ValidateTokensByParameters (supp.Signed, tokens,
optional);
+ ValidateTokensByParameters (supp.SignedEndorsing,
tokens, optional);
+ ValidateTokensByParameters (supp.SignedEncrypted,
tokens, optional);
+ }
+
+ void ValidateTokensByParameters
(IEnumerable<SecurityTokenParameters> plist, List<SupportingTokenInfo> tokens,
bool optional)
+ {
+ 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 ("Security token '{0}' cannot be validated according
to the security settings.");
+ }
+ sec_prop.IncomingSupportingTokens.Add (spec);
+ }
+ }
+
+ 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
+
byte [] GetEncryptionKeyForData (EncryptedData ed2,
EncryptedXml encXml, Dictionary<string,byte[]> map)
{
SecurityTokenSerializer serializer =
Modified:
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
2007-02-06 22:09:28 UTC (rev 72380)
+++
trunk/olive/class/System.ServiceModel/System.ServiceModel.Channels/SecureMessageGenerator.cs
2007-02-06 22:14:54 UTC (rev 72381)
@@ -110,11 +110,6 @@
public override ScopedMessagePartSpecification EncryptionParts
{
get { return
Security.ChannelRequirements.IncomingEncryptionParts; }
}
-
- public override SupportingTokenInfoCollection
CollectSupportingTokens ()
- {
- return security.CollectSupportingTokens (GetAction ());
- }
}
internal class RecipientMessageSecurityGenerator :
MessageSecurityGenerator
@@ -176,11 +171,6 @@
public override ScopedMessagePartSpecification EncryptionParts
{
get { return
Security.ChannelRequirements.OutgoingEncryptionParts; }
}
-
- public override SupportingTokenInfoCollection
CollectSupportingTokens ()
- {
- return security.CollectSupportingTokens (GetAction ());
- }
}
internal abstract class MessageSecurityGenerator
@@ -235,8 +225,6 @@
}
}
- public abstract SupportingTokenInfoCollection
CollectSupportingTokens ();
-
public abstract bool ShouldIncludeToken
(SecurityTokenInclusionMode mode, bool isInitialized);
public bool ShouldOutputEncryptedKey {
@@ -300,6 +288,14 @@
foreach (string value in
secprop.ConfirmedSignatures)
header.Contents.Add (new
Wss11SignatureConfirmation (GenerateId (doc), value));
+ SupportingTokenInfoCollection tokenInfos =
+ Direction == MessageDirection.Input ?
+ security.CollectSupportingTokens (GetAction ())
:
+ new SupportingTokenInfoCollection (); // empty
+ foreach (SupportingTokenInfo tokenInfo in tokenInfos)
+ if (tokenInfo.Mode !=
SecurityTokenAttachmentMode.Endorsing)
+ header.Contents.Add (tokenInfo.Token);
+
// populate DOM to sign.
XPathNavigator nav = doc.CreateNavigator ();
using (XmlWriter w = nav.AppendChild ()) {
@@ -317,8 +313,6 @@
EncryptedData sigenc = null;
- SupportingTokenInfoCollection tokens =
CollectSupportingTokens ();
-
List<WsscDerivedKeyToken> derivedKeys =
new List<WsscDerivedKeyToken> ();
Modified:
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/ChangeLog
===================================================================
---
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/ChangeLog
2007-02-06 22:09:28 UTC (rev 72380)
+++
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/ChangeLog
2007-02-06 22:14:54 UTC (rev 72381)
@@ -1,6 +1,11 @@
2007-02-06 Atsushi Enomoto <[EMAIL PROTECTED]>
* WSSecurityTokenSerializerTest.cs : added test for reading
+ empty (invalid) UsernameToken.
+
+2007-02-06 Atsushi Enomoto <[EMAIL PROTECTED]>
+
+ * WSSecurityTokenSerializerTest.cs : added test for reading
EncryptedKeySHA1 embedded key.
2007-02-05 Atsushi Enomoto <[EMAIL PROTECTED]>
Modified:
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/WSSecurityTokenSerializerTest.cs
===================================================================
---
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/WSSecurityTokenSerializerTest.cs
2007-02-06 22:09:28 UTC (rev 72380)
+++
trunk/olive/class/System.ServiceModel/Test/System.ServiceModel.Security/WSSecurityTokenSerializerTest.cs
2007-02-06 22:14:54 UTC (rev 72381)
@@ -46,6 +46,9 @@
[TestFixture]
public class WSSecurityTokenSerializerTest
{
+ const string wssNS =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
+ const string wsuNS =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
+
static X509Certificate2 cert = new X509Certificate2
("Test/Resources/test.pfx", "mono");
const string derived_key_token1 = @"<c:DerivedKeyToken
xmlns:c='http://schemas.xmlsoap.org/ws/2005/02/sc'>
@@ -553,6 +556,17 @@
}
[Test]
+ [ExpectedException (typeof (XmlException))] // not sure how
this exception type makes sense...
+ public void ReadEmptyUsernameToken ()
+ {
+ WSSecurityTokenSerializer serializer =
+ WSSecurityTokenSerializer.DefaultInstance;
+ using (XmlReader xr = XmlReader.Create (new
StringReader (String.Format ("<o:UsernameToken u:Id='urn:foo' xmlns:o='{0}'
xmlns:u='{1}' />", wssNS, wsuNS)))) {
+ SecurityToken token = serializer.ReadToken (xr,
null);
+ }
+ }
+
+ [Test]
[ExpectedException (typeof (XmlException))] // tokenResolver is
null
[Category ("NotWorking")]
public void ReadTokenDerivedKeyTokenNullResolver ()
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches