summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj1
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs36
-rw-r--r--src/DotNetOpenAuth.sln1
-rw-r--r--src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs23
-rw-r--r--src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs11
-rw-r--r--src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs10
-rw-r--r--src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs21
-rw-r--r--src/DotNetOpenAuth/OAuth/WebConsumer.cs3
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,
};