summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.Core/Messaging
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.Core/Messaging')
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs6
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/HmacAlgorithms.cs60
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs65
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs47
4 files changed, 170 insertions, 8 deletions
diff --git a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs
index c9ceb81..69ee8dc 100644
--- a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs
@@ -286,7 +286,7 @@ namespace DotNetOpenAuth.Messaging {
Requires.NotNull(signature, "signature");
if (this.asymmetricSigning != null) {
- using (var hasher = new SHA1CryptoServiceProvider()) {
+ using (var hasher = SHA1.Create()) {
return this.asymmetricSigning.VerifyData(signedData, hasher, signature);
}
} else {
@@ -309,13 +309,13 @@ namespace DotNetOpenAuth.Messaging {
Contract.Ensures(Contract.Result<byte[]>() != null);
if (this.asymmetricSigning != null) {
- using (var hasher = new SHA1CryptoServiceProvider()) {
+ using (var hasher = SHA1.Create()) {
return this.asymmetricSigning.SignData(bytesToSign, hasher);
}
} else {
var key = this.cryptoKeyStore.GetKey(this.cryptoKeyBucket, symmetricSecretHandle);
ErrorUtilities.VerifyProtocol(key != null, MessagingStrings.MissingDecryptionKeyForHandle, this.cryptoKeyBucket, symmetricSecretHandle);
- using (var symmetricHasher = new HMACSHA256(key.Key)) {
+ using (var symmetricHasher = HmacAlgorithms.Create(HmacAlgorithms.HmacSha256, key.Key)) {
return symmetricHasher.ComputeHash(bytesToSign);
}
}
diff --git a/src/DotNetOpenAuth.Core/Messaging/HmacAlgorithms.cs b/src/DotNetOpenAuth.Core/Messaging/HmacAlgorithms.cs
new file mode 100644
index 0000000..872b4ac
--- /dev/null
+++ b/src/DotNetOpenAuth.Core/Messaging/HmacAlgorithms.cs
@@ -0,0 +1,60 @@
+//-----------------------------------------------------------------------
+// <copyright file="HmacAlgorithms.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Security.Cryptography;
+ using System.Text;
+
+ /// <summary>
+ /// HMAC-SHA algorithm names that can be passed to the <see cref="HMAC.Create(string)"/> method.
+ /// </summary>
+ internal static class HmacAlgorithms {
+ /// <summary>
+ /// The name of the HMAC-SHA1 algorithm.
+ /// </summary>
+ internal const string HmacSha1 = "HMACSHA1";
+
+ /// <summary>
+ /// The name of the HMAC-SHA256 algorithm.
+ /// </summary>
+ internal const string HmacSha256 = "HMACSHA256";
+
+ /// <summary>
+ /// The name of the HMAC-SHA384 algorithm.
+ /// </summary>
+ internal const string HmacSha384 = "HMACSHA384";
+
+ /// <summary>
+ /// The name of the HMAC-SHA512 algorithm.
+ /// </summary>
+ internal const string HmacSha512 = "HMACSHA512";
+
+ /// <summary>
+ /// Creates an HMAC-SHA algorithm with the specified name and key.
+ /// </summary>
+ /// <param name="algorithmName">A name from the available choices in the static const members of this class.</param>
+ /// <param name="key">The secret key used as the HMAC.</param>
+ /// <returns>The HMAC algorithm instance.</returns>
+ internal static HMAC Create(string algorithmName, byte[] key) {
+ Requires.NotNullOrEmpty(algorithmName, "algorithmName");
+ Requires.NotNull(key, "key");
+
+ HMAC hmac = HMAC.Create(algorithmName);
+ try {
+ hmac.Key = key;
+ return hmac;
+ } catch {
+#if CLR4
+ hmac.Dispose();
+#endif
+ throw;
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs
index f613dc5..4b4a3fe 100644
--- a/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs
@@ -13,6 +13,10 @@ namespace DotNetOpenAuth.Messaging {
using System.Globalization;
using System.IO;
using System.Net;
+#if CLR4
+ using System.Net.Http;
+ using System.Net.Http.Headers;
+#endif
using System.Net.Mime;
using System.ServiceModel.Channels;
using System.Web;
@@ -105,12 +109,33 @@ namespace DotNetOpenAuth.Messaging {
this.requestUri = listenerRequest.Url;
this.queryString = listenerRequest.QueryString;
this.headers = listenerRequest.Headers;
- this.form = ParseFormData(listenerRequest.HttpMethod, listenerRequest.Headers, listenerRequest.InputStream);
+ this.form = ParseFormData(listenerRequest.HttpMethod, listenerRequest.Headers, () => listenerRequest.InputStream);
this.serverVariables = new NameValueCollection();
Reporting.RecordRequestStatistics(this);
}
+#if CLR4
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HttpRequestInfo" /> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal HttpRequestInfo(HttpRequestMessage request) {
+ Requires.NotNull(request, "request");
+
+ this.httpMethod = request.Method.ToString();
+ this.requestUri = request.RequestUri;
+ this.queryString = HttpUtility.ParseQueryString(request.RequestUri.Query);
+ this.headers = new NameValueCollection();
+ AddHeaders(this.headers, request.Headers);
+ AddHeaders(this.headers, request.Content.Headers);
+ this.form = ParseFormData(this.httpMethod, this.headers, () => request.Content.ReadAsStreamAsync().Result);
+ this.serverVariables = new NameValueCollection();
+
+ Reporting.RecordRequestStatistics(this);
+ }
+#endif
+
/// <summary>
/// Initializes a new instance of the <see cref="HttpRequestInfo"/> class.
/// </summary>
@@ -126,7 +151,7 @@ namespace DotNetOpenAuth.Messaging {
this.requestUri = requestUri;
this.headers = headers;
this.queryString = HttpUtility.ParseQueryString(requestUri.Query);
- this.form = ParseFormData(httpMethod, headers, inputStream);
+ this.form = ParseFormData(httpMethod, headers, () => inputStream);
this.serverVariables = new NameValueCollection();
Reporting.RecordRequestStatistics(this);
@@ -200,6 +225,17 @@ namespace DotNetOpenAuth.Messaging {
return new HttpRequestInfo(listenerRequest);
}
+#if CLR4
+ /// <summary>
+ /// Creates an <see cref="HttpRequestBase"/> instance that describes the specified HTTP request.
+ /// </summary>
+ /// <param name="request">The HTTP request.</param>
+ /// <returns>An instance of <see cref="HttpRequestBase"/>.</returns>
+ public static HttpRequestBase Create(HttpRequestMessage request) {
+ return new HttpRequestInfo(request);
+ }
+#endif
+
/// <summary>
/// Creates an <see cref="HttpRequestBase"/> instance that describes the specified HTTP request.
/// </summary>
@@ -229,14 +265,15 @@ namespace DotNetOpenAuth.Messaging {
/// </summary>
/// <param name="httpMethod">The HTTP method.</param>
/// <param name="headers">The headers.</param>
- /// <param name="inputStream">The input stream.</param>
+ /// <param name="inputStreamFunc">A function that returns the input stream.</param>
/// <returns>The non-null collection of form variables.</returns>
- private static NameValueCollection ParseFormData(string httpMethod, NameValueCollection headers, Stream inputStream) {
+ private static NameValueCollection ParseFormData(string httpMethod, NameValueCollection headers, Func<Stream> inputStreamFunc) {
Requires.NotNullOrEmpty(httpMethod, "httpMethod");
Requires.NotNull(headers, "headers");
ContentType contentType = string.IsNullOrEmpty(headers[HttpRequestHeaders.ContentType]) ? null : new ContentType(headers[HttpRequestHeaders.ContentType]);
- if (inputStream != null && httpMethod == "POST" && contentType != null && string.Equals(contentType.MediaType, Channel.HttpFormUrlEncoded, StringComparison.Ordinal)) {
+ if (httpMethod == "POST" && contentType != null && string.Equals(contentType.MediaType, Channel.HttpFormUrlEncoded, StringComparison.Ordinal) && inputStreamFunc != null) {
+ var inputStream = inputStreamFunc();
var reader = new StreamReader(inputStream);
long originalPosition = 0;
if (inputStream.CanSeek) {
@@ -252,5 +289,23 @@ namespace DotNetOpenAuth.Messaging {
return new NameValueCollection();
}
+
+#if CLR4
+ /// <summary>
+ /// Adds HTTP headers to a <see cref="NameValueCollection"/>.
+ /// </summary>
+ /// <param name="collectionToFill">The collection to be modified with added entries.</param>
+ /// <param name="headers">The collection to read from.</param>
+ private static void AddHeaders(NameValueCollection collectionToFill, HttpHeaders headers) {
+ Requires.NotNull(collectionToFill, "collectionToFill");
+ Requires.NotNull(headers, "headers");
+
+ foreach (var header in headers) {
+ foreach (var value in header.Value) {
+ collectionToFill.Add(header.Key, value);
+ }
+ }
+ }
+#endif
}
}
diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs
index 2d049c1..7c03555 100644
--- a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs
@@ -15,6 +15,9 @@ namespace DotNetOpenAuth.Messaging {
using System.IO.Compression;
using System.Linq;
using System.Net;
+#if CLR4
+ using System.Net.Http;
+#endif
using System.Net.Mime;
using System.Runtime.Serialization.Json;
using System.Security;
@@ -161,6 +164,28 @@ namespace DotNetOpenAuth.Messaging {
return new OutgoingWebResponseActionResult(response);
}
+#if CLR4
+ /// <summary>
+ /// Transforms an OutgoingWebResponse to a Web API-friendly HttpResponseMessage.
+ /// </summary>
+ /// <param name="outgoingResponse">The response to send to the user agent.</param>
+ /// <returns>The <see cref="HttpResponseMessage"/> instance to be returned by the Web API method.</returns>
+ public static HttpResponseMessage AsHttpResponseMessage(this OutgoingWebResponse outgoingResponse) {
+ HttpResponseMessage response = new HttpResponseMessage(outgoingResponse.Status) {
+ Content = new StreamContent(outgoingResponse.ResponseStream)
+ };
+
+ var responseHeaders = outgoingResponse.Headers;
+ foreach (var header in responseHeaders.AllKeys) {
+ if (!response.Headers.TryAddWithoutValidation(header, responseHeaders[header])) {
+ response.Content.Headers.TryAddWithoutValidation(header, responseHeaders[header]);
+ }
+ }
+
+ return response;
+ }
+#endif
+
/// <summary>
/// Gets the original request URL, as seen from the browser before any URL rewrites on the server if any.
/// Cookieless session directory (if applicable) is also included.
@@ -357,6 +382,28 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Creates the XML reader settings to use for reading XML from untrusted sources.
+ /// </summary>
+ /// <returns>
+ /// The new instance of <see cref="XmlReaderSettings"/>.
+ /// </returns>
+ /// <remarks>
+ /// The default values set here are based on recommendations from
+ /// http://msdn.microsoft.com/en-us/magazine/ee335713.aspx
+ /// </remarks>
+ internal static XmlReaderSettings CreateUntrustedXmlReaderSettings() {
+ return new XmlReaderSettings {
+ MaxCharactersFromEntities = 1024,
+ XmlResolver = null,
+#if CLR4
+ DtdProcessing = DtdProcessing.Prohibit,
+#else
+ ProhibitDtd = true,
+#endif
+ };
+ }
+
+ /// <summary>
/// Clears any existing elements in a collection and fills the collection with a given set of values.
/// </summary>
/// <typeparam name="T">The type of value kept in the collection.</typeparam>