Error codes for CryptographicExceptions? - encryption

I'm trying to map different CryptographicExceptions to custom exceptions and messages. For example, "Object already exists" ==> "Not enough permissions to access an existing RSA key container". However, when I examine CryptographicException class, I don't find any error code collection like other exception types have. I'm running on 3.5, so HResult is not available either. Finally, I cannot rely on the message, since it can be localized. Any other ideas?

public Exception GetMappedCryptographicException(CryptographicException e)
{
uint hresult = (uint)Marshal.GetHRForException(e);
switch (hresult)
{
case 0x8009000F; // OBJECT_ALREADY_EXISTS
return new Exception(e, "Not enough permissions to access RSA key container.");
default:
return new Exception(e, "Unexpected cryptographic exception occurred.");
}
}

Related

Realm doesn’t work with xUnite and .net core

I’m having issues running realm with xUnite and Net core. Here is a very simple test that I want to run
public class UnitTest1
{
[Scenario]
public void Test1()
{
var realm = Realm.GetInstance(new InMemoryConfiguration("Test123"));
realm.Write(() =>
{
realm.Add(new Product());
});
var test = realm.All<Product>().First();
realm.Write(() => realm.RemoveAll());
}
}
I get different exceptions on different machines (Windows & Mac) on line where I try to create a Realm instace with InMemoryConfiguration.
On Mac I get the following exception
libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.
On Windows I get the following exception when running
ERROR Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. at
System.Net.Sockets.NetworkStream.Read(Span1 destination) at
System.Net.Sockets.NetworkStream.ReadByte() at
System.IO.BinaryReader.ReadByte() at
System.IO.BinaryReader.Read7BitEncodedInt() at
System.IO.BinaryReader.ReadString() at
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.LengthPrefixCommunicationChannel.NotifyDataAvailable() at
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TcpClientExtensions.MessageLoopAsync(TcpClient client, ICommunicationChannel channel, Action1 errorHandler, CancellationToken cancellationToken) Source: System.Net.Sockets HResult: -2146232800 Inner Exception: An existing connection was forcibly closed by the remote host HResult: -2147467259
I’m using Realm 3.3.0 and xUnit 2.4.1
I’ve tried downgrading to Realm 2.2.0, and it didn’t work either.
The solution to this problem was found in this Github post
The piece of code from that helped me to solve the issue
Realm GetInstanceWithoutCapturingContext(RealmConfiguration config)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
Realm realm = null;
try
{
realm = Realm.GetInstance(config);
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}
Though it took a while for me to apply this to my solution.
First and foremost, instead of just setting the context to null I am using Nito.AsyncEx.AsyncContext. Because otherwise automatic changes will not be propagated through threads, as realm needs a non-null SynchronizationContext for that feature to work. So, in my case the method looks something like this
public class MockRealmFactory : IRealmFactory
{
private readonly SynchronizationContext _synchronizationContext;
private readonly string _defaultDatabaseId;
public MockRealmFactory()
{
_synchronizationContext = new AsyncContext().SynchronizationContext;
_defaultDatabaseId = Guid.NewGuid().ToString();
}
public Realm GetRealmWithPath(string realmDbPath)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
Realm realm;
try
{
realm = Realm.GetInstance(new InMemoryConfiguration(realmDbPath));
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}
}
Further, this fixed a lot of failing unit tests. But I was still receiving that same exception - Realm accessed from incorrect thread. And I had no clue why, cause everything was set correctly. Then I found that the tests that were failing were related to methods where I was using async realm api, in particular realm.WriteAsync. After some more digging I found the following lines in the realm documentation.
It is not a problem if you have set SynchronisationContext.Current but
it will cause WriteAsync to dispatch again on the thread pool, which
may create another worker thread. So, if you are using Current in your
threads, consider calling just Write instead of WriteAsync.
In my code there was no direct need of using the async API. I removed and replaced with sync Write and all the tests became green again! I guess if I find myself in a situation that I do need to use the async API because of some kind of bulk insertions, I'd either mock that specific API, or replace with my own background thread using Task.Run instead of using Realm's version.

Uploaded 'multipart/form-data' to ASP.NET Web API action, not readable in bufferless mode

I'm building an ASP.NET Web API endpoint that accepts 'multipart/form-data' requests. I implemented it as described in this article using .NET Framework 4.5 and Web API 2.1. A simplified version of the action method I created, looks like this:
public async Task<HttpResponseMessage> PostFile()
{
if (!Request.Content.IsMimeMultipartContent()) throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
var rootPath = System.Configuration.ConfigurationManager.AppSettings["StorageLocation"].ToString();
var provider = new MultipartFormDataStreamProvider(rootPath);
var response = Request.CreateResponse(HttpStatusCode.OK);
try
{
await Request.Content.ReadAsMultipartAsync(provider);
// Imagine awesome logic here, unicorns and rainbows! Instead of that, we do the following:
response.Content = new StringContent("You uploaded " + provider.FileData.Count.ToString() + " files.");
}
catch (Exception e) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e)); }
return response;
}
Because the uploaded files can be very big (up to 2GiB), I want my requests to not be buffered by ASP.NET, thus avoiding high memory usage. To realize this I told Web API to stream incoming requests, instead of buffering them, as described in this article. The custom WebHostBufferPolicySelector looks something like this:
public class CustomWebHostBufferPolicySelector : WebHostBufferPolicySelector
{
public override bool UseBufferedInputStream(object hostContext)
{
System.Web.HttpContextBase contextBase = hostContext as System.Web.HttpContextBase;
if (contextBase != null && contextBase.Request.ContentType != null && contextBase.Request.ContentType.Contains("multipart")) return false;
else return base.UseBufferedInputStream(hostContext);
}
public override bool UseBufferedOutputStream(System.Net.Http.HttpResponseMessage response)
{
return base.UseBufferedOutputStream(response);
}
}
I load this guy in the Global.asax, at application start, like this:
protected void Application_Start(object sender, EventArgs e)
{
// Here, other stuff got did.
GlobalConfiguration.Configuration.Services.Replace(typeof(IHostBufferPolicySelector), new CustomWebHostBufferPolicySelector());
}
Alright, the board is set, lets get the pieces moving. If I don't use my CustomWebHostBufferPolicySelector, everything works just fine. However, when its used, I get the following exception:
Message: "An error has occurred."
ExceptionMessage: "Error reading MIME multipart body part."
ExceptionType: "System.IO.IOException"
StackTrace: " at System.Net.Http.HttpContentMultipartExtensions.<ReadAsMultipartAsync>d__0`1.MoveNext()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\ \ at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\ \ at ..."
With the following inner exception:
Message: "An error has occurred."
ExceptionMessage: "Unable to read the entity body in Bufferless mode. The request stream has already been buffered."
ExceptionType: "System.InvalidOperationException"
StackTrace: " at System.Web.Http.WebHost.HttpControllerHandler.<>c__DisplayClass13.<GetStreamContent>b__10()\ \ at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.get_StreamContent()\ \ at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.CreateContentReadStreamAsync()\ \ at System.Net.Http.HttpContent.ReadAsStreamAsync()\ \ at System.Net.Http.HttpContentMultipartExtensions.<ReadAsMultipartAsync>d__0`1.MoveNext()"
It looks like the request is still buffered somehow, by something else. Is there another place in the ASP.NET pipeline I should be looking? Or even IIS maybe? What are the other places in this request's lifecycle where it can be buffered, and how do I control them?
In an attempt to make the problem more clear and shareable with others, I created a simple project to try and reproduce the problem. While doing this I found the answer: disable all kinds of tracing.
In my case I had ASP.NET's own tracing functionality enabled, and also Glimpse. Both of these buffer the request before it arrives at the Web API action.
For completeness' sake, here the proper way to turn them off in your Web.Config, while testing and in production.
<configuration>
<system.web>
<trace enabled="false" />
</system.web>
<glimpse defaultRuntimePolicy="Off">
</glimpse>
</configuration>
In my case, these two were the culprits, but I can imagine there may be others, so be wary of this.

Authentication and Custom Error pages

I have a site that is using Azure ACS for authentication, backed by ADFS. When things are going well and people do things they are supposed to its great but that doesn't happen always so we have been implementing custom error pages.
The problem is, it doesn't seem to catch authentication errors, such as
ID3206: A SignInResponse message may only redirect within the current web application
Key not valid for use in specified state.
These errors still produce the ugly yellow error screen no matter what I say in my web.config. They are clearly ASP.NET errors and not IIS errors, so my question is how and where can I put custom error pages to display such errors in a 'pretty' way, as setting a page in web.config isn't working?
EDIT: To be clear, we have ACS set up to use an error page, have customErrors on with a different error page, neither or being used.
You have to have an action on a controller in your web app that accepts a POST from ACS and takes a parameter of type string. You must also configure your relying party application in ACS to point to that action for errors. Then in the action code you can do something like this:
namespace ASPNETSimpleMVC.Controllers
{
public class ErrorController : Controller
{
// Errors can be mapped to custom strings here.
static Dictionary<string, string> ErrorCodeMapping = new Dictionary<string, string>();
static ErrorController()
{
ErrorCodeMapping["ACS50019"] = "You chose to cancel log-in to the identity provider.";
ErrorCodeMapping["ACS60001"] = "No output claims were generated. You may be unauthorized to visit this site.";
}
//
// POST: /Error/
//
// If an error occurs during sign-in, ACS will post JSON-encoded errors to this endpoint.
// This function displays the error details, mapping specific error codes to custom strings.
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Index( string ErrorDetails )
{
// The error details contain an array of errors with unique error codes to indicate what went wrong.
// Additionally, the error details contain a suggested HTTP return code, trace ID, and timestamp, which may be useful for logging purposes.
ErrorDetails parsedErrorDetails = new JavaScriptSerializer().Deserialize<ErrorDetails>( ErrorDetails );
ViewData["ErrorMessage"] = String.Format( "An error occurred during sign-in to {0}. ", parsedErrorDetails.identityProvider );
// Loop through all ACS errors, looking for ones that are mapped to custom strings.
// When a mapped error is found, stop looking and append the custom string to the error message.
foreach ( ErrorDetails.Error error in parsedErrorDetails.errors )
{
if ( ErrorCodeMapping.ContainsKey( error.errorCode ) )
{
ViewData["ErrorMessage"] += ErrorCodeMapping[error.errorCode];
break;
}
}
return View( "Error" );
}
}
}
You may also find this article helpful.

ASP.NET Web API removing HttpError from responses

I'm building RESTful service using Microsoft ASP.NET Web API.
My problem concerns HttpErrors that Web API throws back to user when something go wrong (e.g. 400 Bad Request or 404 Not Found).
The problem is, that I don't want to get serialized HttpError in response content, as it sometimes provides too much information, therefore it violates OWASP security rules, for example:
Request:
http://localhost/Service/api/something/555555555555555555555555555555555555555555555555555555555555555555555
As a response, I get 400 of course, but with following content information:
{
"$id": "1",
"Message": "The request is invalid.",
"MessageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'MyNamespaceAndMethodHere(Int32)' in 'Service.Controllers.MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}
Something like this not only indicates that my WebService is based on ASP.NET WebAPI technology (which isn't that bad), but also it gives some information about my namespaces, method names, parameters, etc.
I tried to set IncludeErrorDetailPolicy in Global.asax
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never;
Yeah, that did somehow good, now the result doesn't contain MessageDetail section, but still, I don't want to get this HttpError at all.
I also built my custom DelegatingHandler, but it also affects 400s and 404s that I myself generate in controllers, which I don't want to happen.
My question is:
Is there any convinient way to get rid of serialized HttpError from response content? All I want user to get back for his bad requests is response code.
What about using a custom IHttpActionInvoker ?
Basically, you just have to send an empty HttpResponseMessage.
Here is a very basic example :
public class MyApiControllerActionInvoker : ApiControllerActionInvoker
{
public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
{
var result = base.InvokeActionAsync(actionContext, cancellationToken);
if (result.Exception != null)
{
//Log critical error
Debug.WriteLine("unhandled Exception ");
return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError));
}
else if (result.Result.StatusCode!= HttpStatusCode.OK)
{
//Log critical error
Debug.WriteLine("invalid response status");
return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(result.Result.StatusCode));
}
return result;
}
}
In Global.asax
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker());
One other important thing you could do, not related to Web Api, is to remove excessive asp.net & IIS HTTP headers. Here is a good explanation.
I believe your approach of using the message handler is correct because regardless of the component in the Web API pipeline that sets the status code to 4xx, message handler can clear out response body. However, you do want to differentiate between the ones you explicitly set versus the ones set by the other components. Here is my suggestion and I admit it is a bit hacky. If you don't get any other better solution, give this a try.
In your ApiController classes, when you throw a HttpResponseException, set a flag in request properties, like so.
Request.Properties["myexception"] = true;
throw new HttpResponseException(...);
In the message handler, check for the property and do not clear the response body, if the property is set.
var response = await base.SendAsync(request, cancellationToken);
if((int)response.StatusCode > 399 && !request.Properties.Any(p => p.Key == "myException"))
response.Content = null;
return response;
You can package this a bit nicely by adding an extension method to HttpRequestMessage so that neither the ApiController nor the message handler knows anything about the hard-coded string "myException" that I use above.

SignalR Catching Exceptions

I have a simple login hub which clients may submit a username. The hub throws a exception if the username is already in use. On the client I am trying to handle the exception and read the message. However the message I am reading is 'One or more errors has occurred'.
try
{
await Client.SignIn(user);
UserName = SignInInput;
}
catch (Exception ex)
{ //One or more errors has occurred }
I asked this message on the SignalR github and I received the response:
You need to unwrap the errors. We provide this functionality via the SignalRError object. Here's a sample of how you can unwrap an Exception e.
using (var error = e.GetError())
{
Console.Error.WriteLine(error);
}
In the future please ask questions on sites such as Stackoverflow or chat with us in http://jabbr.net/#/rooms/signalr.
Now I'm looking through my Object Browser and I can't seem to find any such method or class anywhere.
It's an extension method, in SignalR.Client.ErrorExtensions.

Resources