diff options
Diffstat (limited to 'src/DotNetOpenAuth.Core')
10 files changed, 181 insertions, 42 deletions
diff --git a/src/DotNetOpenAuth.Core/Loggers/Log4NetLogger.cs b/src/DotNetOpenAuth.Core/Loggers/Log4NetLogger.cs index 293a6b2..01da034 100644 --- a/src/DotNetOpenAuth.Core/Loggers/Log4NetLogger.cs +++ b/src/DotNetOpenAuth.Core/Loggers/Log4NetLogger.cs @@ -201,6 +201,8 @@ namespace DotNetOpenAuth.Loggers { return IsLog4NetPresent ? CreateLogger(name) : null; } catch (FileLoadException) { // wrong log4net.dll version return null; + } catch (TargetInvocationException) { // Thrown due to some security issues on .NET 4.5. + return null; } catch (TypeLoadException) { // Thrown by mono (http://stackoverflow.com/questions/10805773/error-when-pushing-dotnetopenauth-to-staging-or-production-environment) return null; } diff --git a/src/DotNetOpenAuth.Core/Loggers/TraceLogger.cs b/src/DotNetOpenAuth.Core/Loggers/TraceLogger.cs index 9b0bb0f..1b80c7d 100644 --- a/src/DotNetOpenAuth.Core/Loggers/TraceLogger.cs +++ b/src/DotNetOpenAuth.Core/Loggers/TraceLogger.cs @@ -77,210 +77,270 @@ namespace DotNetOpenAuth.Loggers { /// See <see cref="ILog"/>. /// </summary> public void Debug(object message) { - Trace.TraceInformation(message.ToString()); + if (this.IsDebugEnabled) { + Trace.TraceInformation(message.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Debug(object message, Exception exception) { - Trace.TraceInformation(message + ": " + exception.ToString()); + if (this.IsDebugEnabled) { + Trace.TraceInformation(message + ": " + exception.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void DebugFormat(string format, params object[] args) { - Trace.TraceInformation(format, args); + if (this.IsDebugEnabled) { + Trace.TraceInformation(format, args); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void DebugFormat(string format, object arg0) { - Trace.TraceInformation(format, arg0); + if (this.IsDebugEnabled) { + Trace.TraceInformation(format, arg0); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void DebugFormat(string format, object arg0, object arg1) { - Trace.TraceInformation(format, arg0, arg1); + if (this.IsDebugEnabled) { + Trace.TraceInformation(format, arg0, arg1); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void DebugFormat(string format, object arg0, object arg1, object arg2) { - Trace.TraceInformation(format, arg0, arg1, arg2); + if (this.IsDebugEnabled) { + Trace.TraceInformation(format, arg0, arg1, arg2); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Info(object message) { - Trace.TraceInformation(message.ToString()); + if (this.IsInfoEnabled) { + Trace.TraceInformation(message.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Info(object message, Exception exception) { - Trace.TraceInformation(message + ": " + exception.ToString()); + if (this.IsInfoEnabled) { + Trace.TraceInformation(message + ": " + exception.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void InfoFormat(string format, params object[] args) { - Trace.TraceInformation(format, args); + if (this.IsInfoEnabled) { + Trace.TraceInformation(format, args); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void InfoFormat(string format, object arg0) { - Trace.TraceInformation(format, arg0); + if (this.IsInfoEnabled) { + Trace.TraceInformation(format, arg0); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void InfoFormat(string format, object arg0, object arg1) { - Trace.TraceInformation(format, arg0, arg1); + if (this.IsInfoEnabled) { + Trace.TraceInformation(format, arg0, arg1); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void InfoFormat(string format, object arg0, object arg1, object arg2) { - Trace.TraceInformation(format, arg0, arg1, arg2); + if (this.IsInfoEnabled) { + Trace.TraceInformation(format, arg0, arg1, arg2); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Warn(object message) { - Trace.TraceWarning(message.ToString()); + if (this.IsWarnEnabled) { + Trace.TraceWarning(message.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Warn(object message, Exception exception) { - Trace.TraceWarning(message + ": " + exception.ToString()); + if (this.IsWarnEnabled) { + Trace.TraceWarning(message + ": " + exception.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void WarnFormat(string format, params object[] args) { - Trace.TraceWarning(format, args); + if (this.IsWarnEnabled) { + Trace.TraceWarning(format, args); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void WarnFormat(string format, object arg0) { - Trace.TraceWarning(format, arg0); + if (this.IsWarnEnabled) { + Trace.TraceWarning(format, arg0); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void WarnFormat(string format, object arg0, object arg1) { - Trace.TraceWarning(format, arg0, arg1); + if (this.IsWarnEnabled) { + Trace.TraceWarning(format, arg0, arg1); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void WarnFormat(string format, object arg0, object arg1, object arg2) { - Trace.TraceWarning(format, arg0, arg1, arg2); + if (this.IsWarnEnabled) { + Trace.TraceWarning(format, arg0, arg1, arg2); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Error(object message) { - Trace.TraceError(message.ToString()); + if (this.IsErrorEnabled) { + Trace.TraceError(message.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Error(object message, Exception exception) { - Trace.TraceError(message + ": " + exception.ToString()); + if (this.IsErrorEnabled) { + Trace.TraceError(message + ": " + exception.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void ErrorFormat(string format, params object[] args) { - Trace.TraceError(format, args); + if (this.IsErrorEnabled) { + Trace.TraceError(format, args); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void ErrorFormat(string format, object arg0) { - Trace.TraceError(format, arg0); + if (this.IsErrorEnabled) { + Trace.TraceError(format, arg0); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void ErrorFormat(string format, object arg0, object arg1) { - Trace.TraceError(format, arg0, arg1); + if (this.IsErrorEnabled) { + Trace.TraceError(format, arg0, arg1); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void ErrorFormat(string format, object arg0, object arg1, object arg2) { - Trace.TraceError(format, arg0, arg1, arg2); + if (this.IsErrorEnabled) { + Trace.TraceError(format, arg0, arg1, arg2); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Fatal(object message) { - Trace.TraceError(message.ToString()); + if (this.IsFatalEnabled) { + Trace.TraceError(message.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void Fatal(object message, Exception exception) { - Trace.TraceError(message + ": " + exception.ToString()); + if (this.IsFatalEnabled) { + Trace.TraceError(message + ": " + exception.ToString()); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void FatalFormat(string format, params object[] args) { - Trace.TraceError(format, args); + if (this.IsFatalEnabled) { + Trace.TraceError(format, args); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void FatalFormat(string format, object arg0) { - Trace.TraceError(format, arg0); + if (this.IsFatalEnabled) { + Trace.TraceError(format, arg0); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void FatalFormat(string format, object arg0, object arg1) { - Trace.TraceError(format, arg0, arg1); + if (this.IsFatalEnabled) { + Trace.TraceError(format, arg0, arg1); + } } /// <summary> /// See <see cref="ILog"/>. /// </summary> public void FatalFormat(string format, object arg0, object arg1, object arg2) { - Trace.TraceError(format, arg0, arg1, arg2); + if (this.IsFatalEnabled) { + Trace.TraceError(format, arg0, arg1, arg2); + } } #endregion diff --git a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs index 69ee8dc..2452502 100644 --- a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs +++ b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs @@ -217,8 +217,8 @@ namespace DotNetOpenAuth.Messaging { if (this.signed) { using (var dataStream = new MemoryStream(data)) { var dataReader = new BinaryReader(dataStream); - signature = dataReader.ReadBuffer(); - data = dataReader.ReadBuffer(); + signature = dataReader.ReadBuffer(1024); + data = dataReader.ReadBuffer(8 * 1024); } // Verify that the verification code was issued by message authorization server. diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagePartAttribute.cs b/src/DotNetOpenAuth.Core/Messaging/MessagePartAttribute.cs index 6fd95ee..8ef9b7e 100644 --- a/src/DotNetOpenAuth.Core/Messaging/MessagePartAttribute.cs +++ b/src/DotNetOpenAuth.Core/Messaging/MessagePartAttribute.cs @@ -101,6 +101,15 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Gets or sets a value indicating whether the value contained by this property contains + /// sensitive information that should generally not be logged. + /// </summary> + /// <value> + /// <c>true</c> if this instance is security sensitive; otherwise, <c>false</c>. + /// </value> + public bool IsSecuritySensitive { get; set; } + + /// <summary> /// Gets or sets the minimum version of the protocol this attribute applies to /// and overrides any attributes with lower values for this property. /// </summary> diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.Designer.cs b/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.Designer.cs index 2fe273f..4f89589 100644 --- a/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.Designer.cs +++ b/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:4.0.30319.239 +// Runtime Version:4.0.30319.18010 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -106,6 +106,15 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Looks up a localized string similar to Decoding failed due to data corruption.. + /// </summary> + internal static string DataCorruptionDetected { + get { + return ResourceManager.GetString("DataCorruptionDetected", resourceCulture); + } + } + + /// <summary> /// Looks up a localized string similar to An instance of type {0} was expected, but received unexpected derived type {1}.. /// </summary> internal static string DerivedTypeNotExpected { diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.resx b/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.resx index fbdb63d..15ca046 100644 --- a/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.resx +++ b/src/DotNetOpenAuth.Core/Messaging/MessagingStrings.resx @@ -112,10 +112,10 @@ <value>2.0</value> </resheader> <resheader name="reader"> - <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> - <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <data name="ArgumentPropertyMissing" xml:space="preserve"> <value>Argument's {0}.{1} property is required but is empty or null.</value> @@ -333,4 +333,7 @@ <data name="UnexpectedBufferLength" xml:space="preserve"> <value>Unexpected buffer length.</value> </data> + <data name="DataCorruptionDetected" xml:space="preserve"> + <value>Decoding failed due to data corruption.</value> + </data> </root>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs index 5390da5..7aa4469 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,29 @@ 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); + if (outgoingResponse.ResponseStream != null) { + response.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. @@ -797,7 +823,7 @@ namespace DotNetOpenAuth.Messaging { using (var encryptedStream = new MemoryStream(buffer)) { var encryptedStreamReader = new BinaryReader(encryptedStream); - byte[] encryptedPrequel = encryptedStreamReader.ReadBytes(encryptedStreamReader.ReadInt32()); + byte[] encryptedPrequel = encryptedStreamReader.ReadBuffer(4096); byte[] prequel = crypto.Decrypt(encryptedPrequel, false); using (var symmetricCrypto = new RijndaelManaged()) { @@ -989,7 +1015,7 @@ namespace DotNetOpenAuth.Messaging { missingPaddingCharacters = 0; break; default: - throw ErrorUtilities.ThrowInternal("No more than two padding characters should be present for base64."); + throw new ProtocolException(MessagingStrings.DataCorruptionDetected, new ArgumentException("No more than two padding characters should be present for base64.")); } var builder = new StringBuilder(base64WebSafe, base64WebSafe.Length + missingPaddingCharacters); builder.Replace('-', '+').Replace('_', '/'); @@ -1659,10 +1685,17 @@ namespace DotNetOpenAuth.Messaging { /// Reads a buffer that is prefixed with its own length. /// </summary> /// <param name="reader">The binary reader positioned at the buffer length.</param> + /// <param name="maxBufferSize"> + /// The maximum size of the buffer that should be permitted. + /// Although the stream will indicate the size of the buffer, this mitigates data corruption + /// or DoS attacks causing the web server to allocate too much memory for a small data packet. + /// </param> /// <returns>The read buffer.</returns> - internal static byte[] ReadBuffer(this BinaryReader reader) { + internal static byte[] ReadBuffer(this BinaryReader reader, int maxBufferSize) { Requires.NotNull(reader, "reader"); + Requires.InRange(maxBufferSize > 0 && maxBufferSize < 1024 * 1024, "maxBufferSize"); int length = reader.ReadInt32(); + ErrorUtilities.VerifyProtocol(length <= maxBufferSize, MessagingStrings.DataCorruptionDetected); byte[] buffer = new byte[length]; ErrorUtilities.VerifyProtocol(reader.Read(buffer, 0, length) == length, MessagingStrings.UnexpectedBufferLength); return buffer; @@ -1894,7 +1927,8 @@ namespace DotNetOpenAuth.Messaging { // the public URL: if (serverVariables["HTTP_HOST"] != null) { ErrorUtilities.VerifySupported(request.Url.Scheme == Uri.UriSchemeHttps || request.Url.Scheme == Uri.UriSchemeHttp, "Only HTTP and HTTPS are supported protocols."); - string scheme = serverVariables["HTTP_X_FORWARDED_PROTO"] ?? request.Url.Scheme; + string scheme = serverVariables["HTTP_X_FORWARDED_PROTO"] ?? + (string.Equals(serverVariables["HTTP_FRONT_END_HTTPS"], "on", StringComparison.OrdinalIgnoreCase) ? Uri.UriSchemeHttps : request.Url.Scheme); Uri hostAndPort = new Uri(scheme + Uri.SchemeDelimiter + serverVariables["HTTP_HOST"]); UriBuilder publicRequestUri = new UriBuilder(request.Url); publicRequestUri.Scheme = scheme; diff --git a/src/DotNetOpenAuth.Core/Messaging/Reflection/MessagePart.cs b/src/DotNetOpenAuth.Core/Messaging/Reflection/MessagePart.cs index b2c4664..0f140d6 100644 --- a/src/DotNetOpenAuth.Core/Messaging/Reflection/MessagePart.cs +++ b/src/DotNetOpenAuth.Core/Messaging/Reflection/MessagePart.cs @@ -115,6 +115,7 @@ namespace DotNetOpenAuth.Messaging.Reflection { this.RequiredProtection = attribute.RequiredProtection; this.IsRequired = attribute.IsRequired; this.AllowEmpty = attribute.AllowEmpty; + this.IsSecuritySensitive = attribute.IsSecuritySensitive; this.memberDeclaredType = (this.field != null) ? this.field.FieldType : this.property.PropertyType; this.defaultMemberValue = DeriveDefaultValue(this.memberDeclaredType); @@ -189,6 +190,15 @@ namespace DotNetOpenAuth.Messaging.Reflection { internal bool IsConstantValueAvailableStatically { get; set; } /// <summary> + /// Gets or sets a value indicating whether the value contained by this property contains + /// sensitive information that should generally not be logged. + /// </summary> + /// <value> + /// <c>true</c> if this instance is security sensitive; otherwise, <c>false</c>. + /// </value> + internal bool IsSecuritySensitive { get; set; } + + /// <summary> /// Gets the static constant value for this message part without a message instance. /// </summary> internal string StaticConstantValue { diff --git a/src/DotNetOpenAuth.Core/Reporting.cs b/src/DotNetOpenAuth.Core/Reporting.cs index 951bb7c..80a3374 100644 --- a/src/DotNetOpenAuth.Core/Reporting.cs +++ b/src/DotNetOpenAuth.Core/Reporting.cs @@ -519,8 +519,12 @@ namespace DotNetOpenAuth { SendStats(); } catch (Exception ex) { // Something bad and unexpected happened. Just deactivate to avoid more trouble. - Logger.Library.Error("Error while trying to submit statistical report.", ex); - broken = true; + try { + broken = true; + Logger.Library.Error("Error while trying to submit statistical report.", ex); + } catch (Exception) { + // swallow exceptions to prevent a crash. + } } }); } diff --git a/src/DotNetOpenAuth.Core/Util.cs b/src/DotNetOpenAuth.Core/Util.cs index e9d617a..26b7b45 100644 --- a/src/DotNetOpenAuth.Core/Util.cs +++ b/src/DotNetOpenAuth.Core/Util.cs @@ -16,6 +16,7 @@ namespace DotNetOpenAuth { using DotNetOpenAuth.Configuration; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.Messaging.Reflection; /// <summary> /// A grab-bag utility class. @@ -105,9 +106,16 @@ namespace DotNetOpenAuth { ////Contract.Requires(pairs != null); // CC: anonymous method can't handle it ErrorUtilities.VerifyArgumentNotNull(pairs, "pairs"); var dictionary = pairs as IDictionary<K, V>; + var messageDictionary = pairs as MessageDictionary; StringBuilder sb = new StringBuilder(dictionary != null ? dictionary.Count * 40 : 200); foreach (var pair in pairs) { - sb.AppendFormat("\t{0}: {1}{2}", pair.Key, pair.Value, Environment.NewLine); + var key = pair.Key.ToString(); + string value = pair.Value.ToString(); + if (messageDictionary != null && messageDictionary.Description.Mapping.ContainsKey(key) && messageDictionary.Description.Mapping[key].IsSecuritySensitive) { + value = "********"; + } + + sb.AppendFormat("\t{0}: {1}{2}", key, value, Environment.NewLine); } return sb.ToString(); }); |