C#/UWP : How to manage certificate errors with HttpClient? - c#

I've developed an UWP app for a client, which uses WebServices that are hosted in its domain.
Until now, the URL WebServices were related to a test server that don't use SSL
But now, the WebServices URL are related to the prod server that use SSL
As I'm a subcontractor, I don't have an AD account, and I need to use the VPN to access to the client's WebServices.
I didn't get any problem to access to the test server, but it's no longer the case with the prod server.
When I try to access to access to the URL through a navigator, I get a security warning message (DLG_FLAGS_INVALID_CA), but I can "force" the navigation to the URL.
But when I call the WebService from the app with HttpCLient, I also get an error (HttpRequestException) and I don't see how I could fix it.
Here are the details of the exception:
HResult = -2147012851
InnerException =
{System.Runtime.InteropServices.COMException (0x80072F0D): Can't find text related to the error code. The certificate authority is invalid or is incorrect at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) ...
Message = "An error occurred while sending the request."
Source = "System.Net.Http"
I've already tried to install handly the certificates on my computer, but this doesn't fix the issue...
Is there another approach?
Edit: add "user" certificate
The client sent me the "user" certificate and I installed it on my computer in "User\Trusted Root Certification Authorities Certificate Store": there is no longer problem from the navigator. However, in the app, the problem is still present.
Is it normal? Do I need to "attach" the certificate to the app? This is not really usefull, as the client's users don't need this problem: it's only me as I'm a subcontractor using the VPN...
Edit: add "computer" certificate
Finally the client sent me the "computer" certificate and I installed it on my computer in "Computer\Trusted Root Certification Authorities Certificate Store": this time I could use the app without problem.
It's good to know that the UWP app and the navigators don't use the same certificate.

The problem has been fixed by installing the "user" and "computer" certificates that has been sent by the client.

Related

RabbitMq Broker not accepting PFX

After having a working solution of RabbitMq over SSL using the certs generated by OpenSSL, I was given a requirement from our client that we cannot use OpenSSL to generate the certs. The server admin went and created the certificate chain via IIS.
We did the following to the certs after creation:
exported the server certs to a PFX and extracted cert.pem and cert.key
exported the client cert to a PFX and extracted cert.pem and cert.key
exported the Root CA to rootca.pem
updated the config file for RabbitMq
To test the connections and certificates were created properly, we went through the Troubleshooting Steps here.
Everything passed fine. We are able to connect using openssl s_client on port 5671 as expected using the client's cert.pem and cert.key generated from client.pfx. We can see the connection made in management console, as well as in the logs, and they communicate back and forth.
Now, using the client.pfx in the .NET client, we are getting an error about the certificate validation:
MassTransit.RabbitMqTransport.RabbitMqConnectionException: Connect failed: admin#mitvs-atm01:5671/ ---> RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the specified endpoints were reachable ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
How can I be getting an error using the client.pfx but not get an error when using the cert.pem and cert.key that I extracted from it?
This error message means that client can't validate server certificate. Your problem is likely to do with rootca.pem not being trusted on your client's machine. Follow the appropriate OS guide to make the root CA certificate trusted.
When testing the connections through OpenSSL using s_client, it performs no or very basic verification and .NET apps can provide a function that applies any logic. The most common verification type is matching certificate's CN against server's hostname but it really can be anything.
So, even on a trusted Root CA, the CN still needs to match the hostname, which isn't picked up using OpenSSL commands.
Regenerating the cert and amending that fixed the problem.
Also, you could effectively add the code below and it will disregard this error:
h.UseSsl(s =>
{
s.ServerName = SslHostName;
s.CertificatePath = SslFileLocation;
s.CertificatePassphrase = SslPassphrase;
// The below allows the Root CA's CN to be different than the others, but adds vulnerability
s.AllowPolicyErrors(System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch);
});
Please note - Ignoring errors carries the risk of exposing your system to MITM attacks (unless you implement your own verification logic that's not based on CN/hostname matching, of course).

How to validate server SSL certificate for LDAP+SSL connection

Our application works with Active Directory users and groups. We are using LDAP on port 389 for Active Directory operations. Now, one of our clients want us add an option for using LDAP + SSL for Active Directory communication.
They told us that they have a local CA installed on their domain and using self signed certificate for LDAPS. They also told us that they will provide the certificate, no mutual-trust needed and we should use Windows certificate store.
I have developed a test application for LDAP+SSL operations and saw that server sends its certificate when a client initiates an LDAP+SSL connection. I can establish the connection only by returning true from the server certificate verification method.
The questions are;
- Which certificate (root, the ceritificate used for LDAP+SSL...) should the customer give us?
What should be the format of the certificate for working on .Net environment?
How should I verify the server's certificate when connecting the server?
What they mean by "we should use Windows certificate store"? Do they want us add the server's certificate automatically to trusted certificate store of the local machine?
Sample code I used for LDAP+SSL connection,
LdapConnection _connection = new LdapConnection(new LdapDirectoryIdentifier(m_DomainName, m_PortNo));
_connection.Timeout = TimeSpan.FromMinutes(10);
_connection.AuthType = AuthType.Basic;
_connection.Credential = new NetworkCredential(m_UserName, m_Password);
_connection.SessionOptions.ProtocolVersion = 3;
_connection.SessionOptions.SecureSocketLayer = true;
_connection.SessionOptions.VerifyServerCertificate = (ldapCon, serverCertificate) =>
{
//TODO: Verify server certificate
return true;
};
_connection.SessionOptions.QueryClientCertificate = (con, trustedCAs) => null;
_connection.Bind();
Which certificate (root, the ceritificate used for LDAP+SSL...) should the customer give us?
The root certificate that signed the LDAP server cert. They can also give you the whole chain in advance, but that will be sent during TLS handshake anyway. You only need to have the root cert in advance.
What should be the format of the certificate for working on .Net environment?
Anything that you can import into certmgr.msc. Pfx is the usual choice on Windows.
How should I verify the server's certificate when connecting the server?
You should not write validation yourself. Certificate validation is tricky business, and it's already done for you. Use the built-in stuff (also see below).
What they mean by "we should use Windows certificate store"? Do they want us add the server's certificate automatically to trusted certificate store of the local machine?
Yes. They send you the root cert they used for signing the ldap server cert, which you can then import as a trusted root. Once this is done, you don't need to do any manual validation, it will just work™ :) with valid certificates and will not work with invalid ones.
Note that once you add their root cert as trusted, they can forge any server certificate for the client their root is installed on, and anything they sign will be considered valid on that client.
Bonus: adding semi-custom validation and debugging certificate errors
One problem that you may face is that error messages are not very helpful. If the certificate cannot be validated, you will get a very generic error message that has no hint about the actual problem. You may want to hook into the validation process for other reasons too.
For this purpose, you can define your own validation:
private bool VerifyServerCertificate(LdapConnection ldapConnection, X509Certificate certificate)
{
X509Certificate2 certificate2 = new X509Certificate2( certificate );
return certificate2.Verify();
}
And then add it to the ldap connection:
_connection.SessionOptions.VerifyServerCertificate =
new VerifyServerCertificateCallback( VerifyServerCertificate );
This way you can catch exceptions on Verify() etc. But again, if the certificate is valid (can be verified by the client), this is not strictly needed, it's done automatically anyway. You only need this if you want something not implemented, like for example you could just return true in VerifyServerCertificate to accept any cert including the invalid ones (this would be a Bad Idea and makes a secure connection useless, but may be good for debugging, etc).
Another thing you could implement in this method is certificate pinning for additional security, but that's beyond the scope of this answer.
BTW: Since introduction of the StartTLS extended operation for LDAP v3 in May 2000 (RFC 2830) LDAPS (made for LDAP v2) is deprecated.

c# ClientCertificates.Add() certificate not attached to httpwebrequest

I'm grabbing a self-signed piv auth X509certificate from a smart card inserted in a USB reader and am attaching it to the HttpWebRequest via the code below:
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(uriInfo);
Request.ClientCertificates.Add(theCert);
Request.Method = "POST";
//get the response back (the mini driver will prompt for a PIN at this point)
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
Here is the thing that is confusing me, this code works on some machines but not on others. It's worked on Win7 on one machine and not on Win7 on another, it works in Win8. I've even tried running it in a Virtual Machine of Win8 which works, which is a guest of a Win7 host machine that doesn't work.
I've read a lot of articles on stack overflow, and tried many different things to get this to work, but nothing seems to. Since my certificate doesn't contain the private key info, that seems to be why it is not included in the request? Which is similar to this question: HttpWebRequest doesn't seem to be sending a client SSL certificate
Since it works on some machines and not others is this something I need to configure differently on the machines where it is not working?
I know the cert is not being attached because of some wireshark investigating. The certificate I'm using has been set up on the server, so it should trust it (and does in some cases).
Some things I'm doing different than other posts is I'm getting the cert from a piv smart card and simply attaching it to the request. When I call GetResponse, the microsoft minidriver steps in a prompts for a PIN to be entered. But since the certificate is not being attached to the request, I never get the prompt for the PIN and the server returns a 403 Forbidden error.
Any ideas?
(This is my first post here, so please forgive any sins which I've committed)
Ok, I finally found out what the problem was. I noticed that the when the smart card was inserted into the reader, the certificate was not propagated to the personal store. Then I found that the thing responsible for doing this was the a service called "Certificate Propagation".
I noticed that service was not running and when I tried starting it, it would stop right away giving the message,
"The Certificate Propagation service on Local Computer has started
then stopped. Some services stop automatically if they are not in use
by other services or programs."
After some digging on why this service would start but not stay running I found it was due to a Group Policy setting stashed in the registry. Changing the following registry setting from 0 to 1 fixed the issue for me:
HKLM\Software\Policies\Microsoft\Windows\Certprop\CertPropEnabled = 1

A call to SSPI failed - The certificate is revoked

My application was working fine two days ago. I was able to sent the push notification completely fine on live app but suddenly i starts getting this error
{System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> System.ComponentModel.Win32Exception: The certificate is revoked
Here is my code, where i am getting the exception
try
{
stream.AuthenticateAsClient(this.appleSettings.Host,
this.certificates, System.Security.Authentication.SslProtocols.Tls,
false);
}
catch (System.Security.Authentication.AuthenticationException ex)
{
throw new ConnectionFailureException("SSL Stream Failed
to Authenticate as Client", ex);
}
The tried to change the X509Certificate to X509Certificat2 and X509CertificateCollection to X509Certificate2Collection but it didn't help me. I also did not revoked any certificate from my developer account.
We had the same problem, We fixed it by generating the new .p12 certificate file for Apple push notification. Validity of certificate is of one year and it is independent of your app. So you don't need to up the app gain on store to fix the issue. Just find the app id of your app. Use this app id to create a new .p12 certificate file for push notification and upload it on your server.

Azure Scheduler Certification error

I'm using new Azure Scheduler service and I have this issue.
I have one console application that works fine with this few code lines
var credentials = new CertificateCloudCredentials(subscriptionId, certificate);
var schedulerClient= new SchedulerManagementClient(credentials);
var jobCollAvailable = schedulerClient.JobCollections.CheckNameAvailability(cloudServiceName, jobCollectionName_NE);
I use the same code lines in a API service with service stack.
When CheckNameAvailability method is called system throws this exception :
Forbidden Error: The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.
Since Friday everything worked also into the service. I had only changed the certificate with another one.
If I remove certificate from Azure the console app throws the same error( but in this case is correct). I have tried with more than one certificate for to be sure and console app has worked fine.
The Certificate loaded and used from Service has the same thumbprint that the console app one.
Thanks for your suggests

Categories

Resources