How to trust a self-signed server certificate with the node-opcua client - ssl

I have a simple node-opcua client and it wants to connect to a server via Basic128Rsa15 policy.
I have created a self-signed certificate and the server does receive this cert and I can move it on the server to the trusted pki directory.
At my client - the node-opcua - I also see a new directory "pki/rejected" with the cert from the server.
My question is now: What do I have to do now so that the client will trust this self-signed cert from the server?
I have already tried to create a "trusted" directory and move it to there, but this does not help, I also have tried to add an option (which I have found via google): serverCertificate=crypto_utils.readCertificate("pki/trusted/04c9f401be19e5a2349460306579c692e777cea5.pem"); But that also didn't help. When I start the client it creates again the cert in the "rejected" folder.
My node-opcua options for the connection:
options:
securityMode: 3 # None = 1, Sign = 2, SignAndEncrypt = 3
securityPolicy: "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"
certificateFile: certificates/cert.pem
privateKeyFile: certificates/key.pem

[EDITED]
version 2.30 onward: node-opcua clients now perform full certificate validation coming from servers:
if a server certificate has been generated by a CA, the CA certificate must appear in the PKI of the client ( in the issuer folder) along side with the corresponding CRL.
by default the client certificate manager accepts valid unknown server certificate for backward compatibility with previous version. This can be reverted by setting the automaticallyAcceptUnknownCertificates to false.
other checks are performed to verify that the certificate of the server strictly complies to the requirements of OPCUA, such as subjectAltName.uniqueResourceIdentify must match server's applicationUri, keyUsage, key length etc ...
if server certificate is known and in rejected folder, client will reject connection with server.
version 2.28 and below: node-opcua clients did not perform server certificate trust/reject checks yet, nor full certificate validation, just basic validate (date, signature ...)

Related

Signed client certificate not accepted by websocket server

Want to set up authentication in a python websocket server which builds up its ssl context like:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain('certificates/server_cert.pem', 'certificates/server_key.pem')
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations('certificates/bob_cert.pem')
Following the example in here (only for the creation of certificates) I created three keypairs and certificates, one for the websocket server and two client certs. As stated in the example I signed alice's cert with the server cert and bob's cert is self-signed.
If I now connect via bob's cert and set verify_locations in the server as above, bob magically gets into the server (which doesn't do more then echo back what you sent).
But if I connect via alice's cert (signed by server cert) I do not get accepted - getting a ConnectionResetError, the parameter verify_locations in the above code is then of course set to accept alice_cert.pem. For completion, below you find the code for ssl context creation of the client side (here for bob):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = True
ctx.load_verify_locations('certificates/server_cert.pem')
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_cert_chain('certificates/bob_cert.pem', 'certificates/bob_key.pem')
What am I doing wrong or where did I misunderstand the tutorial I followed (link above), how can the unrelated (to the server cert) self-signed certificate used by bob (ISSUER CN=bob, SUBJ CN=bob) get access whereas alice cert which is signed by the server cert (ISSUER CN=localhost, SUBJ CN=alice) does get rejected?
Ok, issue found. As the example stated, people should put the server_cert.pem in load_verify_locations in the websocket server ssl context. Works now as expected when doing so.. Alice gets in, Bob does not.

How to enforce tomcat server not to share SSL public certificate to clients(Browsers) requesting for it?

A Certified Domain should be accessible only if SSL public certificate of the domain is already present in client's trust store. If not, client should prompt to import server certificate instead of getting it from tomcat server automatically(Via SSL handshake)
This will not work: the server has no knowledge which CA certificates are known to the client so the server cannot decide what to send to the client. Also, the server can only send a certificate to the client but not make the client import a new root CA - no matter if with or without prompt.
Apart from that it makes no sense: the idea of TLS/HTTPS is that the client will only connect to a server which identity can be verified. If the server can make a client import a new trusted root CA an attacker could do the same and thusman in the middle attacks would be possible.
If one instead just want to know if the client will trust a specific certificate or not one could include a resource (image, script...) served with this certificate into a known good HTML page and then check with some script in the page if the resource was loaded successfully. This check could also result in a redirect of the client, for example to some page describing the problem and linking to the correct root CA.

How to setup IIS to verify a client certificate and pass it to the backend as an http header?

I've read quite a few articles on the client certificate authentication in IIS but they mostly talk about the Required mode for the client certificate. In this case, the authentication is fully done on the web server side and the user is redirected to the error page in case the certificate is missing or invalid. What I need is to configure IIS to check the client certificate if it exists and pass the results as http headers to my backend. It can be easily done with nginx or apache web servers. The client authentication can be set up as optional. Then, the web server checks the certificate and pass the results of the check as SSL_CLIENT_CERT (PEM representation of the certificate) and SSL_CLIENT_VERIFY (the result of the check - SUCCESS, NONE,...) headers to the application backend. So, on the backend part, I can read the headers and use the values to do the actual authentication -- find a user in the database, issue an auth token. Is it possible in IIS? If yes, is there any documentation on how to bypass the certificate and the check state as http headers?
After a while, I'm writing an answer to my question.
IIS has to be set up with ARR extension to act as a reverse proxy. Then, the client certificate authentication can be enabled for the default web site. Here are several links to instructions how to achieve it:
https://blogs.msdn.microsoft.com/benjaminperkins/2014/06/02/configure-application-request-routing-arr-with-client-certificates/
https://blogs.msdn.microsoft.com/asiatech/2014/01/27/configuring-arr-with-client-certificate/
and couple of links to very solid explanations of the SSL/TLS handshake and certificates in general:
https://blogs.msdn.microsoft.com/kaushal/2013/08/02/ssl-handshake-and-https-bindings-on-iis/
https://blogs.msdn.microsoft.com/kaushal/2013/01/09/self-signed-root-ca-and-intermediate-ca-certificates/
https://blogs.msdn.microsoft.com/kaushal/2015/05/27/client-certificate-authentication-part-1/
Basically, the Application Request Routing (ARR) extension should be enabled for the IIS to act as a proxy. Then, you set up proxy bypass routes. Next, you need to set up a valid server certificate for the IIS server and use it in the Default Web Site https bindings. The certificate should be issued by a CA which certificate should be placed into the Trusted Root Certification Authorities and Intermediate Certification Authorities of the Local Computer. Then, you should require SSL in the SSL settings of the Default Web Site with the client certificates setting equal to Accept. In this case, any client that connects to the web server will be asked for a valid client certificate that has been issued by the same CA as the server certificate.
Actually, IIS sends a list of distinguished names of root issuers that are trusted by the web server to the client browser. The browser finds an intersection of this names with client trusted certificate issuers and looks for valid certificates that have been issued by the issuers in the intersection. After that, the user selects one of them (or none) and the selected certificate is checked against the CA certificate. If the certificate passes the check the request is "redirected" to the backend application with the certificate in the X-ARR-ClientCert header. The name of the header can be changed in the Server -> Configuration Editor -> system.webServer/proxy -> clientCertHeaderName IIS parameter. In case the user selects (or has) none of the required certificates, the request is "redirected" to the app backend without the header.
Seems, there is no need in the SSL_CLIENT_VERIFY header with the state of the check at all. If the certificate is valid it is passed in the header. If the certificate is missing the header is empty. If the certificate is provided by the client but is invalid then the request fails and is not "redirected" to the backend app server at all. Seems, it is a rare case but I have an example.
Imagine, a server certificate is issued by a CA with a distinguished name XXX, and there is a client certificate YYY (on the client computer) that is issued by a CA with the distinguished name XXX but those CAs are not the same (one or both of them are self-signed). In this case, the YYY certificate is present in the certificate selection dialog that is shown by a browser but the certificate doesn't pass the further validation against the real web server CA.
That's it. Also, seems IIS has no way to require (or accept) a client certificate for some app endpoints (addresses) only. I haven't found any other option apart from enabling in for the whole web site.
IIS ARR can also be configured with a client certificate for the backend or upstream server. In this case users connecting to this IIS do not need to provide the certificate as it will be attached by IIS automatically.
This configuration is available on IIS server level only.

SSL Certificate Expires

My idea of the SSL communication is a bit hazy and I needed some clarifications.
Architecture of my application - Internal Machine which has the application running is exposed to internet via a BIG IP server.
The certificate hierarchy on my website - Root (expires in 2040) R - Intermediate( expires in 2036) I - xxxx.com (expires in 2 days) F
I have the new certificate created with the same root and intermediate CAs. It is created with a different key. I also have the key.
My questions are :
1) When I perform a HTTP Post using a stand alone application from computer X (some random machine on internet) onto the exposed URL, the SSL handshake should occur at two places. a) Computer X and BIG -IP b) BIG-IP and the internal machine that has the application running. The standalone application should have the public certificates of the URL i.e., R and I, in its key store. Correct? Or should I have the xxxx.com certificate as well i.e., F as well? Who decides this?
2) This is a different scenario. I have placed the newly created certificate of xxxx.com (it has same Root and Intermediate certificates R and I) on the BIG IP server. The start period of this certificate is 1st Aug 2014. My internal instance, although, still has the old certificate. It expires on 3rd Sept 2014. I am able to post successfully even in this scenario. Why is it so? Since the keys are different for the new and old ones, the requests should fail during the SSL handshake of BIG-IP and Internal instance.
Kindly help me understand these two scenarios. I will be grateful.
Thanks
The root CAs should be in the client machine's trusted certificate repository. The server (BIG-IP) should have the intermediate cert and the cert for the fqdn (or SAN/wildcard) if you are offloading. If you are offloading at the BIG-IP and not re-encrypting to the origin server, then you don't need any certificates on the origin server. If you are, then it would be the same setup as the BIG-IP with intermediate and server cert.
In the event your intermediate and server certs are signed by a root NOT trusted by your client (internal certs or custom clients without the standard trusted CAs), you'll need to make sure your clients install the root CA manually or push it.

How to generate an SSL client certificate from a disconnected network?

I have a unique situation where I need to implement client certificate authentication over HTTPS between IE browser and IIS 6. The browser and IIS are separated by a firewall that only allows the browser to connect to IIS on the SSL port.
We have an internal certificate server on the same network as IIS. I've generated an SSL server cert for IIS and that is installed. I configured IIS to only allow SSL, require client certificates.
The limitation here is the browser machine is on a disconnected network, so I can't go to the CA's http://caserver/CertSrv URL and request a client cert like you normally would.
I figured if there were a way that I could generate a CSR against the Root CA's public key, I can copy it to the CA server to generate the client cert. But, there appears to be no provision in IE or the Certificates MMC to do this. The Certificates MMC seems to require a direct connection to the CA.
Has anyone solved this before?
FYI, All servers referenced run Windows Server 2003.
Update: Thanks to Jonas Oberschweiber and Mark Sutton for pointing out the CertReq.exe command line tool. Using this, I've generated a CSR, and consequently a client certificate that installs successfully. However, IE is apparently not sending this client cert when accessing the IIS server in question; it still generates a 403.7 "Forbidden: SSL client certificate is required." I suspect that the reason is that the Subject field of the client cert does not match the user id of the account running IE, thus perhaps not sending a mismatching client cert. The Subject matches that of the user I used to submit the CSR and generate the client cert on the other end of the firewall.
Does the Subject field matter? Is there something else I need to do to enable IE to send this cert?
Use the certreq command on your client as follows
certreq -new -f filein c:\certrequest.req
Here is and example of the filein
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject="CN=dc1.extranet.frbrikam.com"
EncipherOnly = False
Exportable = False
KeyLength = 1024
KeySpec = 1
KeyUsage = 0xA0
MachineKeySet = True
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = CMC
[RequestAttributes]
CertificateTemplate=TLSServer
Replace the CertificateTemplate with the name of your certificate template
Once you have your request file you need to take it to the certificate authority on a usb stick and use the web enrolment interface as usual to process the request file.
Take the output certificate back to the client open it and click install.
You sound like you have already tried a couple of things so my guess is that you are already aware of these, but I'm going to post them anyway, just in case: Certificate Command Line Tools. I am not sure, however, if they do what you want.
Go the http://caserver/CertSrv site that you mentioned using a 3rd computer that can see the CA server. Select the 3rd option, download a CA cert, cert chai, or CRL. On the next page select 'Download CA Certificate Chain', which will download the p7b file. Using a flash drive (or email, etc) transfer this to the other computer which will allow you to import it into the trusted root servers in IE.
http://technet.microsoft.com/en-us/library/cc787796.aspx
Suggestiong for the update, just in case - what is the trusted cert list of in the server?
Subject DN being the same as Windows username has never been a problem for me - although I don't use IIS much. However, somewhere in IIS there is sure to be a trusted certificate list. This error sounds to me like the server's trusted certs list does not include the CA or Root CA that issued the client certificate.
This is particularly true if you never get a certificate selection popup window in IE when you hit the IIS server - even though you have a certificate configured in your IE cert store. That means that the client hit the server, the server gave a list of trusted certs and the client didn't have a cert that fit the list. So the SSL session went to the Forbidden error state.
If the certificate selection window popped up, and you selected and sent the cert, there may be other configuration problems on the server side..