diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-04-10 19:31:58 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-04-10 19:31:58 -0700 |
commit | c550dae3f973b551ab4988b20768eefa967bbce4 (patch) | |
tree | 32791a2857df2d587e914d50873b2f899063a105 | |
parent | 82781e309db03f8afd09629f2b1bbce10fa355c5 (diff) | |
download | DotNetOpenAuth-c550dae3f973b551ab4988b20768eefa967bbce4.zip DotNetOpenAuth-c550dae3f973b551ab4988b20768eefa967bbce4.tar.gz DotNetOpenAuth-c550dae3f973b551ab4988b20768eefa967bbce4.tar.bz2 |
Fixed OpenIdAjaxTextBox extension passing to Javascript.
The underlying problem was that we were not actually using a non-verifying OpenID channel as we thought we were, and this is a requirement.
Fixes Google Code issue 236.
4 files changed, 123 insertions, 12 deletions
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index 75abc40..a15b3a8 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -314,6 +314,7 @@ <Compile Include="OpenId\ChannelElements\OpenIdChannel.cs" /> <Compile Include="OpenId\ChannelElements\OpenIdMessageFactory.cs" /> <Compile Include="OpenId\ChannelElements\ReturnToSignatureBindingElement.cs" /> + <Compile Include="OpenId\ChannelElements\SkipSecurityBindingElement.cs" /> <Compile Include="OpenId\Extensions\AliasManager.cs" /> <Compile Include="OpenId\Extensions\AttributeExchange\AttributeRequest.cs" /> <Compile Include="OpenId\Extensions\AttributeExchange\AttributeValues.cs" /> diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs index f89ac73..d1c5db4 100644 --- a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs +++ b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs @@ -49,7 +49,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// <param name="nonceStore">The nonce store to use.</param> /// <param name="securitySettings">The security settings to apply.</param> internal OpenIdChannel(IAssociationStore<Uri> associationStore, INonceStore nonceStore, RelyingPartySecuritySettings securitySettings) - : this(associationStore, nonceStore, new OpenIdMessageFactory(), securitySettings) { + : this(associationStore, nonceStore, new OpenIdMessageFactory(), securitySettings, false) { Contract.Requires(securitySettings != null); } @@ -73,8 +73,9 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// <param name="nonceStore">The nonce store to use.</param> /// <param name="messageTypeProvider">An object that knows how to distinguish the various OpenID message types for deserialization purposes.</param> /// <param name="securitySettings">The security settings to apply.</param> - private OpenIdChannel(IAssociationStore<Uri> associationStore, INonceStore nonceStore, IMessageFactory messageTypeProvider, RelyingPartySecuritySettings securitySettings) : - this(messageTypeProvider, InitializeBindingElements(associationStore, nonceStore, securitySettings)) { + /// <param name="nonVerifying">A value indicating whether the channel is set up with no functional security binding elements.</param> + private OpenIdChannel(IAssociationStore<Uri> associationStore, INonceStore nonceStore, IMessageFactory messageTypeProvider, RelyingPartySecuritySettings securitySettings, bool nonVerifying) : + this(messageTypeProvider, InitializeBindingElements(associationStore, nonceStore, securitySettings, nonVerifying)) { Contract.Requires(messageTypeProvider != null); Contract.Requires(securitySettings != null); } @@ -88,7 +89,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// <param name="messageTypeProvider">An object that knows how to distinguish the various OpenID message types for deserialization purposes.</param> /// <param name="securitySettings">The security settings.</param> private OpenIdChannel(IAssociationStore<AssociationRelyingPartyType> associationStore, INonceStore nonceStore, IMessageFactory messageTypeProvider, ProviderSecuritySettings securitySettings) : - this(messageTypeProvider, InitializeBindingElements(associationStore, nonceStore, securitySettings)) { + this(messageTypeProvider, InitializeBindingElements(associationStore, nonceStore, securitySettings, false)) { Contract.Requires(messageTypeProvider != null); Contract.Requires(securitySettings != null); } @@ -130,6 +131,21 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { } /// <summary> + /// A value indicating whether the channel is set up + /// with no functional security binding elements. + /// </summary> + /// <remarks> + /// <para>A value of <c>true</c> allows the relying party to preview incoming + /// messages without invalidating nonces or checking signatures.</para> + /// <para>Setting this to <c>true</c> poses a great security risk and is only + /// present to support the <see cref="OpenIdAjaxTextBox"/> which needs to preview + /// messages, and will validate them later.</para> + /// </remarks> + internal static OpenIdChannel CreateNonVerifyingChannel() { + return new OpenIdChannel(null, null, new OpenIdMessageFactory(), new RelyingPartySecuritySettings(), true); + } + + /// <summary> /// Verifies the integrity and applicability of an incoming message. /// </summary> /// <param name="message">The message just received.</param> @@ -291,16 +307,19 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// <param name="associationStore">The association store.</param> /// <param name="nonceStore">The nonce store to use.</param> /// <param name="securitySettings">The security settings to apply. Must be an instance of either <see cref="RelyingPartySecuritySettings"/> or <see cref="ProviderSecuritySettings"/>.</param> + /// <param name="nonVerifying">A value indicating whether the channel is set up with no functional security binding elements.</param> /// <returns> /// An array of binding elements which may be used to construct the channel. /// </returns> - private static IChannelBindingElement[] InitializeBindingElements<T>(IAssociationStore<T> associationStore, INonceStore nonceStore, SecuritySettings securitySettings) { + private static IChannelBindingElement[] InitializeBindingElements<T>(IAssociationStore<T> associationStore, INonceStore nonceStore, SecuritySettings securitySettings, bool nonVerifying) { Contract.Requires(securitySettings != null); + Contract.Requires(!nonVerifying || securitySettings is RelyingPartySecuritySettings); ErrorUtilities.VerifyArgumentNotNull(securitySettings, "securitySettings"); var rpSecuritySettings = securitySettings as RelyingPartySecuritySettings; var opSecuritySettings = securitySettings as ProviderSecuritySettings; ErrorUtilities.VerifyInternal(rpSecuritySettings != null || opSecuritySettings != null, "Expected an RP or OP security settings instance."); + ErrorUtilities.VerifyInternal(!nonVerifying || rpSecuritySettings != null, "Non-verifying channels can only be constructed for relying parties."); bool isRelyingPartyRole = rpSecuritySettings != null; var rpAssociationStore = associationStore as IAssociationStore<Uri>; @@ -309,7 +328,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { SigningBindingElement signingElement; if (isRelyingPartyRole) { - signingElement = new SigningBindingElement(rpAssociationStore); + signingElement = nonVerifying ? null : new SigningBindingElement(rpAssociationStore); } else { signingElement = new SigningBindingElement(opAssociationStore, opSecuritySettings); } @@ -338,12 +357,16 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { ErrorUtilities.VerifyArgumentNotNull(nonceStore, "nonceStore"); } - if (nonceStore != null) { - elements.Add(new StandardReplayProtectionBindingElement(nonceStore, true)); - } + if (nonVerifying) { + elements.Add(new SkipSecurityBindingElement()); + } else { + if (nonceStore != null) { + elements.Add(new StandardReplayProtectionBindingElement(nonceStore, true)); + } - elements.Add(new StandardExpirationBindingElement()); - elements.Add(signingElement); + elements.Add(new StandardExpirationBindingElement()); + elements.Add(signingElement); + } return elements.ToArray(); } diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/SkipSecurityBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/SkipSecurityBindingElement.cs new file mode 100644 index 0000000..ad65a83 --- /dev/null +++ b/src/DotNetOpenAuth/OpenId/ChannelElements/SkipSecurityBindingElement.cs @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------- +// <copyright file="SkipSecurityBindingElement.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.ChannelElements { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// Spoofs security checks on incoming OpenID messages. + /// </summary> + internal class SkipSecurityBindingElement : IChannelBindingElement { + #region IChannelBindingElement Members + + /// <summary> + /// Gets or sets the channel that this binding element belongs to. + /// </summary> + /// <value></value> + /// <remarks> + /// This property is set by the channel when it is first constructed. + /// </remarks> + public Channel Channel { get; set; } + + /// <summary> + /// Gets the protection commonly offered (if any) by this binding element. + /// </summary> + /// <value><see cref="MessageProtections.All"/></value> + /// <remarks> + /// This value is used to assist in sorting binding elements in the channel stack. + /// </remarks> + public MessageProtections Protection { + get { return MessageProtections.All; } + } + + /// <summary> + /// Prepares a message for sending based on the rules of this channel binding element. + /// </summary> + /// <param name="message">The message to prepare for sending.</param> + /// <returns> + /// The protections (if any) that this binding element applied to the message. + /// Null if this binding element did not even apply to this binding element. + /// </returns> + /// <remarks> + /// Implementations that provide message protection must honor the + /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. + /// </remarks> + public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { + Debug.Fail("SkipSecurityBindingElement.ProcessOutgoingMessage should never be called."); + return null; + } + + /// <summary> + /// Performs any transformation on an incoming message that may be necessary and/or + /// validates an incoming message based on the rules of this channel binding element. + /// </summary> + /// <param name="message">The incoming message to process.</param> + /// <returns> + /// The protections (if any) that this binding element applied to the message. + /// Null if this binding element did not even apply to this binding element. + /// </returns> + /// <exception cref="ProtocolException"> + /// Thrown when the binding element rules indicate that this message is invalid and should + /// NOT be processed. + /// </exception> + /// <remarks> + /// Implementations that provide message protection must honor the + /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. + /// </remarks> + public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { + var signedMessage = message as ITamperResistantOpenIdMessage; + if (signedMessage != null) { + Logger.Bindings.DebugFormat("Skipped security checks of incoming {0} message for preview purposes.", message.GetType().Name); + return this.Protection; + } + + return null; + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs index 167a7fe..a78c2e9 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs @@ -385,7 +385,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </remarks> internal static OpenIdRelyingParty CreateNonVerifying() { OpenIdRelyingParty rp = new OpenIdRelyingParty(); - rp.Channel = new OpenIdChannel(null, null, rp.SecuritySettings); + rp.Channel = OpenIdChannel.CreateNonVerifyingChannel(); return rp; } |