diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj | 1 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs | 36 | ||||
-rw-r--r-- | src/DotNetOpenAuth.sln | 1 | ||||
-rw-r--r-- | src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs | 23 | ||||
-rw-r--r-- | src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs | 11 | ||||
-rw-r--r-- | src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs | 2 | ||||
-rw-r--r-- | src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs | 10 | ||||
-rw-r--r-- | src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs | 21 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OAuth/WebConsumer.cs | 3 |
9 files changed, 90 insertions, 18 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index bd317af..7212008 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -135,6 +135,7 @@ <Compile Include="Messaging\EnumerableCacheTests.cs" /> <Compile Include="Messaging\ErrorUtilitiesTests.cs" /> <Compile Include="Messaging\MessageSerializerTests.cs" /> + <Compile Include="Messaging\OutgoingWebResponseTests.cs" /> <Compile Include="Messaging\Reflection\MessageDescriptionTests.cs" /> <Compile Include="Messaging\Reflection\MessageDictionaryTests.cs" /> <Compile Include="Messaging\MessagingTestBase.cs" /> diff --git a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs new file mode 100644 index 0000000..35f9259 --- /dev/null +++ b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------- +// <copyright file="OutgoingWebResponseTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.Messaging { + using System.Net; + using System.Text; + using DotNetOpenAuth.Messaging; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class OutgoingWebResponseTests { + /// <summary> + /// Verifies that setting the Body property correctly converts to a byte stream. + /// </summary> + [TestMethod] + public void SetBodyToByteStream() { + var response = new OutgoingWebResponse(); + string stringValue = "abc"; + response.Body = stringValue; + Assert.AreEqual(stringValue.Length, response.ResponseStream.Length); + + // Verify that the actual bytes are correct. + Encoding encoding = new UTF8Encoding(false); // avoid emitting a byte-order mark + var expectedBuffer = encoding.GetBytes(stringValue); + var actualBuffer = new byte[stringValue.Length]; + Assert.AreEqual(stringValue.Length, response.ResponseStream.Read(actualBuffer, 0, stringValue.Length)); + CollectionAssert.AreEqual(expectedBuffer, actualBuffer); + + // Verify that the header was set correctly. + Assert.AreEqual(encoding.HeaderName, response.Headers[HttpResponseHeader.ContentEncoding]); + } + } +} diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln index f8d9b8f..e6aff81 100644 --- a/src/DotNetOpenAuth.sln +++ b/src/DotNetOpenAuth.sln @@ -8,6 +8,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{20B5E173-C3C4-49F8-BD25-E69044075B4D}" ProjectSection(SolutionItems) = preProject DotNetOpenAuth.vsmdi = DotNetOpenAuth.vsmdi + ..\LICENSE.txt = ..\LICENSE.txt LocalTestRun.testrunconfig = LocalTestRun.testrunconfig ..\doc\README.Bin.html = ..\doc\README.Bin.html ..\doc\README.html = ..\doc\README.html diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs index 21911fa..fe2c2a2 100644 --- a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs +++ b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs @@ -5,7 +5,7 @@ // </copyright> //----------------------------------------------------------------------- -[assembly: System.Web.UI.WebResource("DotNetOpenAuth.InfoCard.SupportingScript.js", "text/javascript")] +[assembly: System.Web.UI.WebResource(DotNetOpenAuth.InfoCard.InfoCardSelector.ScriptResourceName, "text/javascript")] namespace DotNetOpenAuth.InfoCard { using System; @@ -48,6 +48,11 @@ namespace DotNetOpenAuth.InfoCard { [ToolboxData("<{0}:InfoCardSelector runat=\"server\"><ClaimsRequested><{0}:ClaimType Name=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier\" /></ClaimsRequested><UnsupportedTemplate><p>Your browser does not support Information Cards.</p></UnsupportedTemplate></{0}:InfoCardSelector>")] [ContractVerification(true)] public class InfoCardSelector : CompositeControl, IPostBackEventHandler { + /// <summary> + /// The resource name for getting at the SupportingScript.js embedded manifest stream. + /// </summary> + internal const string ScriptResourceName = "DotNetOpenAuth.InfoCard.SupportingScript.js"; + #region Property constants /// <summary> @@ -172,11 +177,6 @@ namespace DotNetOpenAuth.InfoCard { #endregion /// <summary> - /// The resource name for getting at the SupportingScript.js embedded manifest stream. - /// </summary> - private const string ScriptResourceName = "DotNetOpenAuth.InfoCard.SupportingScript.js"; - - /// <summary> /// The panel containing the controls to display if InfoCard is supported in the user agent. /// </summary> private Panel infoCardSupportedPanel; @@ -413,7 +413,16 @@ namespace DotNetOpenAuth.InfoCard { /// When implemented by a class, enables a server control to process an event raised when a form is posted to the server. /// </summary> /// <param name="eventArgument">A <see cref="T:System.String"/> that represents an optional event argument to be passed to the event handler.</param> - public void RaisePostBackEvent(string eventArgument) { + void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) { + this.RaisePostBackEvent(eventArgument); + } + + /// <summary> + /// When implemented by a class, enables a server control to process an event raised when a form is posted to the server. + /// </summary> + /// <param name="eventArgument">A <see cref="T:System.String"/> that represents an optional event argument to be passed to the event handler.</param> + [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Predefined signature.")] + protected virtual void RaisePostBackEvent(string eventArgument) { if (!string.IsNullOrEmpty(this.TokenXml)) { try { ReceivingTokenEventArgs receivingArgs = this.OnReceivingToken(this.TokenXml); diff --git a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs index 14666f2..0693926 100644 --- a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs +++ b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs @@ -366,7 +366,16 @@ namespace DotNetOpenAuth.Messaging { WebHeaderCollection headers = new WebHeaderCollection(); foreach (string key in pairs) { - headers.Add(key, pairs[key]); + try { + headers.Add(key, pairs[key]); + } catch (ArgumentException ex) { + Logger.Messaging.WarnFormat( + "{0} thrown when trying to add web header \"{1}: {2}\". {3}", + ex.GetType().Name, + key, + pairs[key], + ex.Message); + } } return headers; diff --git a/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs b/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs index dee81dc..e471a06 100644 --- a/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs +++ b/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs @@ -101,7 +101,7 @@ namespace DotNetOpenAuth.Messaging { /// This can be different from the <see cref="RequestUri"/> in cases of /// redirection during the request. /// </remarks> - public Uri FinalUri { get; private set; } + public Uri FinalUri { get; internal set; } /// <summary> /// Gets the headers that must be included in the response to the user agent. diff --git a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs index bad582c..147cd66 100644 --- a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs +++ b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs @@ -30,6 +30,11 @@ namespace DotNetOpenAuth.Messaging { /// </remarks> public class OutgoingWebResponse { /// <summary> + /// The encoder to use for serializing the response body. + /// </summary> + private static Encoding bodyStringEncoder = new UTF8Encoding(false); + + /// <summary> /// Initializes a new instance of the <see cref="OutgoingWebResponse"/> class. /// </summary> internal OutgoingWebResponse() { @@ -210,10 +215,9 @@ namespace DotNetOpenAuth.Messaging { return; } - Encoding encoding = Encoding.UTF8; - this.Headers[HttpResponseHeader.ContentEncoding] = encoding.HeaderName; + this.Headers[HttpResponseHeader.ContentEncoding] = bodyStringEncoder.HeaderName; this.ResponseStream = new MemoryStream(); - StreamWriter writer = new StreamWriter(this.ResponseStream, encoding); + StreamWriter writer = new StreamWriter(this.ResponseStream, bodyStringEncoder); writer.Write(body); writer.Flush(); this.ResponseStream.Seek(0, SeekOrigin.Begin); diff --git a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs index 733b698..1656155 100644 --- a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs +++ b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs @@ -259,6 +259,15 @@ namespace DotNetOpenAuth.Messaging { Uri redirectUri = new Uri(response.FinalUri, response.Headers[HttpResponseHeader.Location]); request = request.Clone(redirectUri); } else { + if (response.FinalUri != request.RequestUri) { + // Since we don't automatically follow redirects, there's only one scenario where this + // can happen: when the server sends a (non-redirecting) Content-Location header in the response. + // It's imperative that we do not trust that header though, so coerce the FinalUri to be + // what we just requested. + Logger.Http.WarnFormat("The response from {0} included an HTTP header indicating it's the same as {1}, but it's not a redirect so we won't trust that.", request.RequestUri, response.FinalUri); + response.FinalUri = request.RequestUri; + } + return response; } } @@ -455,12 +464,14 @@ namespace DotNetOpenAuth.Messaging { request.ReadWriteTimeout = (int)this.ReadWriteTimeout.TotalMilliseconds; request.Timeout = (int)this.Timeout.TotalMilliseconds; request.KeepAlive = false; - - // If SSL is required throughout, we cannot allow auto redirects because - // it may include a pass through an unprotected HTTP request. - // We have to follow redirects manually. - request.AllowAutoRedirect = false; } + + // If SSL is required throughout, we cannot allow auto redirects because + // it may include a pass through an unprotected HTTP request. + // We have to follow redirects manually. + // It also allows us to ignore HttpWebResponse.FinalUri since that can be affected by + // the Content-Location header and open security holes. + request.AllowAutoRedirect = false; } } } diff --git a/src/DotNetOpenAuth/OAuth/WebConsumer.cs b/src/DotNetOpenAuth/OAuth/WebConsumer.cs index 56d3029..d86444d 100644 --- a/src/DotNetOpenAuth/OAuth/WebConsumer.cs +++ b/src/DotNetOpenAuth/OAuth/WebConsumer.cs @@ -120,7 +120,8 @@ namespace DotNetOpenAuth.OAuth { } // Prepare a message to exchange the request token for an access token. - var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, this.ServiceProvider.Version) { + // We are careful to use a v1.0 message version so that the oauth_verifier is not required. + var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, Protocol.V10.Version) { RequestToken = positiveAuthorization.RequestToken, ConsumerKey = this.ConsumerKey, }; |