I'm downloading files from a FTPS server and the server sends a certificate back to me.
Microsoft states:
When custom validation is not used, the certificate name is compared with host name used to create the request. For example, if Create(String) was passed a parameter of "https://www.contoso.com/default.hmtl", the default behavior is for the client to check the certificate against www.contoso.com.
The certificate does not pass the default validation (RemoteCertificateNameMismatch). Right now I use the ServicePointManager.ServerCertificateValidationCallback delegate and provide a delegate that returns true, just "to pass" without any validation. How do I validate the certificate using C#?
One of the parameters to the delgate mentioned above, X509Certificate certificate, contains two public properties of interest: Issuer and Subject. None of the two properties contains any data matching the hostname.
Usually you must have a valid certificate against the right host name to pass the validation instead of overwriting the callback.
What target address did you use to access the FTP server? It should be different from the subject according to your description.
You may consider to use the subject hostname to access the server instead of current one. You could also set your client hosts file if you have DNS issues with that.
Related
I am trying to connect to Bloomberg FIX (EMSX) through SSL using QuickFIX/n.
I have got 3 .pem files from Bloomberg using which I have to configure the SSL connectivity. I have gone through all the available reference material on the internet but in vain.
Can anybody help in doing this configuration??
Thanks in advance.
Have a look at using Stunnel and check out this question...
QuickFIX/n expects .pfx extension files. See http://quickfixn.org/tutorial/configuration.html#ssl
This extension is normally used for PKCS #12 encoded files which contain the certificate and the private key, protected by a password.
You may need to convert your .pem files so that you have one .pfx file which contains your private key and the certificate and another file which contains your CA Certificate. The SSLCertificate and SSLCACertificate configuration parameters of the QuickFIX/n session should then be set to the path of these two files. SSLCertificatePassword should contain the password.
QuickFIX/n is strict and requires the FIX Acceptor (Bloomberg EMSX in this case) to have the x509v3 extended key attribute "TLS Web Server Authentication" (1.3.6.1.5.5.7.3.1) to be explicitly present in the server certificate that is presented during the SSL handshake.
If not present, you will get an error message in the QuickFIX/n session event log:
Remote certificate is not intended for server authentication: It is
missing enhanced key usage 1.3.6.1.5.5.7.3.1
Some FIX Acceptors still don't define this in their server certificate, so even if you go to the effort of converting your PEM files to PFX, it still won't work.
You can use Stunnel which doesn't seem to mind what purpose was intended for the server certificate that is presented. As an added bonus Stunnel understands PEM files so no need to convert. However, you should be aware that if your end goal is end-to-end encryption, the hop between your QuickFIX/n application and Stunnel will be in clear text.
I have a p12 certificate for a WebService (I've tested the certificate with SoapUI and it works, and I can access the URL with a WebBrowser).
The problem is that I can't consume the WebService with my c# development. When I try to access the webservice, returns the error message "Cannot create DNS identity probably due to the lack of CN parameter".
How can I override this? I've tried the CreateX509CertificateIdentity, but the error remains.
When you access your webservice on i.e. http://localhost/webservice url then your CN=localhost. If you want to make the webservice available at multiple urls then you need to specify all DNS addresses in subject alternative name (SAN) in the extensions of your certificate. Of course the certificate has to be trusted by client and server.
While working on this question, I identified that the problem is slightly different than initially stated, so I am changing title and description
I'm trying to authenticate myself against WebService using my client certificate. I am using WebRequest for that purpose. I need to use self-signed certificate, without registering it in Windows X509 trusted root store.
The way I know if client certificate is presented or not is by examining request object on the server
I tried to use code from this question as a guidance. It doesn't work on .NET. Here is my code:
var certificate = new X509Certificate2(Properties.Resources.MyCert);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
req.ClientCertificates.Add(certificate);
WebResponse resp = req.GetResponse();
var stream = resp.GetResponseStream();
What I observe is that even though req.ClientCertificates does contain certificate with a valid private key, that certificate is never presented to server. I get no indication from WebClient that certificate is not used during handshake.
If I put certificate into "trusted root", the code will work (even when certificate is not in "personal").
My questions are:
Since certificate is usable when it's placed in "trusted root", I assume it is likely due to policy or something of that kind. Is it possible to coerce .NET to ignore policy settings and use supplied client certificate during TLS negotiation?
If abovementioned coercion is not possible, is there a call which will tell me ahead of time, that certificate I am about to use is not usable, and will be ignored? Alternatively, if such call is not available, could I make WebClient fail indicating a certificate error, instead of silently skipping over?
NOTE: I am aware that configuring certificates as described by Microsoft will work. This is NOT what I am looking for. I don't want to register potentially insecure certificate in trusted root, because this is potentially security hazard. I want to use cert on client without registering in store, or at least to get an exception indicating that certificate cannot be used. I realize that there can be multiple reasons why certificate cannot be used for a session, but there must be an exception, or at least some sort of indication on the client side that it cannot use specified cert. Instead, client simply doesn't present one.
When you instantiate your X509Certificate2, is the PrivateKey property set? If it is null, you are missing the private key, meaning the SSL/TLS client will be unable to authenticate you.
Make sure you are loading the certificate from a PFX file (or similar) instead of a CER. These contain the private key, too. They are usually password protected for that purpose. See How to retrieve certificates from a pfx file with c#? for more info.
I'm trying to develop an ASP.net site that reads the clientCertificate to ensure a smart card was used to access the website (trying to do away with username/password login).
The process I have in my mind is:
User registers an account and C# records user's clientCertificate (public).
The user can then log in the next time with that same clientCertificate, and they are now an authenticated user if hash valid.
I will use the code below to ensure authenticity of certificate. The browser should deal with private keys and ensure the certificate was NOT faked.
Based on Subject+certificate combination, C# assigns them their role-access.
The following code can be used for authenticity of certificate right?
X509Certificate x509Cert = new X509Certificate(Request.ClientCertificate.Certificate);
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] hashvalue = sha.ComputeHash(Request.ClientCertificate.Certificate);
byte[] x509Hash = x509Cert.GetCertHash();
// compare x509Hash WITH hashvalue to ensure they are a match.
// If not, possibly faked certificate, not a real smartcard???
Is this how SmartCard authentication process should work???
If you just need to authenticate users with client certificates you should do this in IIS. You do not need to add any code at all to your application:
Specify Whether to Use Client Certificates (IIS 7)
Unless you need to link client certificates with database accounts or perform an additional validation step. But still for client certificate authentication I would stick with IIS settings.
Update:
In case you need to manipulate the client certificate you can do:
X509Certificate2 x509Cert2 = new X509Certificate2(Page.Request.ClientCertificate.Certificate);
And then access its properties such as:
x509Cert2.Subject
However, leave the validation piece up to IIS. If the client presents a bad certificate your asp.net code will not even execute since IIS will reject it
See this thread, sir. You do not need to verify authenticity explicitly in your code. IIS will do it for you.
Does IIS do the SSL certificate check or do I have to verify it?
IIS even tries to check revocation lists (however, this is often disabled if the CRL is large). An OCSP responder should be used to validate in cases where the CRL is very large or latency in checking it is high http://www.axway.com/products-solutions/email-identity-security/identity-security/va-suite.
Client-certificate authentication is done during the SSL/TLS handshake.
It is usually done using a Public Key Infrastructure, whereby the server has a (fixed) list of trusted CA certificates which it uses to verify the client certificate (in the same way as clients to it for the server). Once the certificate is presented to your application after this stage, you will know that:
the client has the private key for that certificate (guaranteed by the Certificate Verify message in the TLS handhsake (the SSL/TLS stack will verify this for you, no need to implement anything);
the client has the identity described in the certificate, because you will have verified it against your trusted CA.
The verification against a trusted CA requires the user to be registered with that CA in advance. You can't just authenticate any certificate if it hasn't been issued by a CA you trust. (Mapping the certificate's subject to a local user ID is another matter: you could do this upon first connection if needed: have your own database or directory service to map the Subject DN to another kind of user ID in your application, for example.)
User registers an account and C# records user's clientCertificate
(public). The user can then log in the next time with that same
clientCertificate, and they are now an authenticated user if hash
valid.
It sounds like you want to allow any certificate to be presented and use it for the initial registration, without necessarily resorting to a commonly trusted CA.
This is possible in principle, and I've done this to explore alternatives to PKI in Java.
To do this, you need to let any certificate through as far as the SSL/TLS handshake is concerned, and verify the certificate itself later. (You do need to use some form of verification.) You are still guaranteed with this that the client has the private key for the public key certificate it has presented.
Doing this requires two steps:
You need to be able to advertise the fact that you're going to accept any certificate, by sending an empty list of certification authorities in the Certificate Request TLS message (explicitly allowed by TLS 1.1).
Configure the SSL/TLS stack to trust any certificate (once again, when you do this, do not forget to implement your own verification system within your application, otherwise anything will really get through).
In .Net, while it should be possible to address the second point using a remote certificate validation callback, I have never found a way to alter the first point (this was also asked in this question).
In Java, the JSSE's X509TrustManager allows you to address both points.
I am attempting to use the .Net System.Security.SslStream class to process the server side of a SSL/TLS stream with client authentication.
To perform the handshake, I am using this code:
SslStream sslStream = new SslStream(innerStream, false, RemoteCertificateValidation, LocalCertificateSelectionCallback);
sslStream.AuthenticateAsServer(serverCertificate, true, SslProtocols.Default, false);
Unfortunately, this results in the SslStream transmitting a CertificateRequest containing the subjectnames of all certificates in my CryptoAPI Trusted Root Store.
I would like to be able to override this. It is not an option for me to require the user to install or remove certificates from the Trusted Root Store.
It looks like the SslStream uses SSPI/SecureChannel underneath, so if anyone knows how to do the equivalent with that API, that would be helpful, too.
Any ideas?
It does not look like this is currently possible using the .NET libraries.
I solved it by using the Mono class library implementation of System.Security.SslStream, which gives better access to overriding the servers behavior during the handshake.
What the certificate validation is doing is validating all certificates in the chain. In order to truely do that it just contact the root store of each of those cerficates.
If that's not something you want to happen you can deploy your own root store locally.
It is not the validation part I want to change. The problem is in the initial handshake, the server transmits the message informing the client that client authentication is required (that is the CertificateRequest message). As part of this message, the server sends the names of CAs that it will accept as issuers of the client certificate. It is that list which per default contains all the Trusted Roots in the store.
But if is possible to override the certificate root store for a single application, that would probably fix the problem. Is that what you mean? And if so, how do I do that?