WCF error "The X.509 certificate chain building failed" despite trusted root CA - wcf

I'm getting the error mentioned in this question:
The X.509 certificate CN=Farm chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust.
What I don't understand why I'm getting this error as the certificate I use for my request to the WCF service is added as shown below:
client.ClientCredentials.Peer.PeerAuthentication.CertificateValidationMode =
X509CertificateValidationMode.ChainTrust;
client.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySerialNumber,
"MyCertificatesSerialNumber" );
The certificate itself is a self-signed certificate in the store shown above. When I click on it to show the certification path, no errors are shown (the root certificate is also a self-signed certificate). The root certificate was manually imported into the trusted root certification authorities.
From the error message I would have expected that there was an error in the certification chain with one of my certificates, but there isn't. Any ideas?
Update
I'm using Internet Explorer 9 as my browser to access the webservice. Programmatically I'm using a C# console application.

I had exactly the same problem - my own trusted root CA which signed another certificate. No errors were shown in the certificate store.
It turned out that having a trusted root CA and a certificate is not sufficient! You also need a certificate revocation list! Take a look at this MSDN Link.
So simply create such a .crl and add it also to the trusted root certificate authorities and everything works fine!
makecert -crl -n "CN=CARoot" -r -sv CARoot.pvk CARoot.crl
or simply turn of the revocation list check:
...RevocationMode = X509RevocationMode.NoCheck;

I had this problem - this is what I'd suggest:
On the server, make sure that the root cert is located on the "local computer" side of the computer, not "Current User". The other thing is that the SSL cert needs to be derived from the root cert. I eventually got it all to work using a script that included these lines:
rem creates root authority file and cert in localmachine\root and gives it the right to sign certs
makecert.exe -a sha1 -n CN=RootCert RootCertName -sr LocalMachine -ss Root -sky signature -pe -r -sk MyNewKey -cy authority
rem creates ssl cert, puts it in the currentuser\Personal store, signing it based on the root cert
makecert.exe -n cn=HostURL SSLCertName -is root -ic RootCertName -sky exchange -pe -sv SSLCertPrivateKeyName -eku 1.3.6.1.5.5.7.3.1
It's complicated, tedious stuff. You just have to keep at it.

I faced a similar issue while trying to connect to a self hosted WCF service using net.tcp binding. I already had the self signed root CA certificate installed in the CurrentUser certificate store, client was using a certificate signed by the root CA cert.
Installing the root CA certificate in LocalComputer certificate store fixed the error "A certificate chain could not be built to a trusted root authority". My WCF Server process runs using current user account hence this step was not obvious.
The next error was "The revocation function was unable to check revocation for the certificate"
To fix this, I created an empty Certificate Revocation List for the root CA cert and then installed the CRL in the LocalComputer certificate store. (Please check this link for details : https://msdn.microsoft.com/en-us/library/ff648732.aspx)
I also set the revocation check mode to Offline for both server and client certificates.
defaultCredentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.Offline;
defaultCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.ChainTrust;
Now I don't have to turn off certificate validation or use different validation mode for development (In my case production code will also use self signed certificates for the time being)

Related

Openssl certificate verification stricter/different than browsers? [duplicate]

This question already has answers here:
SSL working in chrome but sometimes in Firefox and not on IOS, Android or Blackberry
(2 answers)
Closed 1 year ago.
I've put together a Linux (Centos 7) server to serve eye-n-sky.net.
Serving content from that site to browsers on Win10 and Linux systems works beautifully. However, when I use openssl to access the site,
openssl s_client -connect eye-n-sky.net:443
the site certificate is rejected,
Verify return code: 21 (unable to verify the first certificate)
I've concluded that the way a browser verifies the certificate is different from what openssl does. Am I on the right track?
I've tested this on three different openssl instances (Debian, Centos, FreeBSD) and have consistent results.
Openssl as a client to other sites, e.g. www.godaddy.com, microsoft.com, work fine, being able to verify the certificate against the installed CA chain.
Believing that I was missing a CA cert, I used the -CAfile option to specify the possibly missing cert, to no effect.
What am I missing? I'm guessing that openssl has a stricter verification discipline, but I don't know where that gets configured.
Thanks,
Andy
Summary: yes, eye-n-sky was providing only it's cert when it needed to include the intermediate and root certs.
However, it took me forever to figure out that my Apache version did not support including the chain in the server cert file. Instead, I had to provide the chain file separately in an SSLCertificateChainFile directive.
OpenSSL's command-line s_client utility has nothing built in to validate the server's certificate. Browsers have a built-in list of trusted certificates to verify the server certificate against.
You have to supply the trusted certificates using options such as -CAfile file or -CApath directory. Per the OpenSSL 1.1.1 s_client man page:
-CApath directory
The directory to use for server certificate verification. This
directory must be in "hash format", see verify(1) for more
information. These are also used when building the client certificate
chain.
-CAfile file
A file containing trusted certificates to use during server
authentication and to use when attempting to build the client
certificate chain.
Note the use of words such as "certificate chain". If you go to godaddy.com you'll see that the server's cert is for *.godaddy.com, but it was signed by Go Daddy Secure Certificate Authority - G2, and that intermediate certificate was signed by Go Daddy Root Certificate Authority - G2 - a different certificate. There's a total of three certificates in that chain.
Verify return code 21 is "no signatures could be verified because the chain contains only one certificate and it is not self signed", so if your CA file only had the certificate from Go Daddy Root Certificate Authority - G2 and not the one from Go Daddy Secure Certificate Authority - G2, OpenSSL would see from the server's cert itself that it was signed by Go Daddy Secure Certificate Authority - G2 and could go no further - it doesn't have that cert to see who signed it.

Root Certificate of website through openssl command

I am trying to obtain the root certificate of various websites for my project, but I am not sure the certificates that I am getting back with this command, contains root certificate or not?
openssl s_client -showcerts -connect google.com:443
I was searching for an answer when I came across a post where wget was used to get the root certificate from the certificate repository of godaddy
wget https://certs.godaddy.com/repository/gd_bundle.crt -O ~/.cert/mail.nixcraft.net/gd.pem
how do i find the repository for every website?
The server must include the certification chain during TLS connection (https). The chain may include the CA root certificate, but it is optional, So you have no guarantee that it will be available. The TLS protocol expects the client to have the certificate in their truststore to verify the trust
You can download the server certificate of every site programmatically, but it is needed to look for the root CA certificate. As you can see, godaddy publish them in its website. In many cases the certificate itself includes a reference to download the root certificate

Mutual certificates authentication fails with error 403.16

I'm using Windows Server 2012 and IIS 8.5. I've set SSL for the website and the SSL Settings are: Require Required and Require Client Certificates.
The client certificate that I'm sending to the server has been issued by a self-signed authority (let's called it MyCompany CA). MyCompany CA certificate has been successfully installed in the Local Computer Account - Trusted Root Certification Authorities. It's expiration date is 2039, so is the client certificate expiration date.
However, with all this setup, I'm getting an error 403.16 as result. I've enabled Failed Request Tracing Rules and managed to log an erroneous request and got some extra details about it:
52.- MODULE_SET_RESPONSE_ERROR_STATUS - Warning
ModuleName - IIS Web Core
Notification - BEGIN_REQUEST
HttpStatus - 403
HttpReason - Forbidden
HttpSubStatus - 16
ErrorCode - A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. (0x800b0109)
ConfigExceptionInfo
I've checked multiple sites regarding the result 403.16 and error code 0x800b0109 and all of them points to the certification authority not been installed in Local Computer - Trusted Root Certification Authorities, but that's not my case.
Thanks!
I have been working on this for a long time and finally found it!
Add a new key to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
Value name: ClientAuthTrustMode
Value type: REG_DWORD
Value data: 2
Refresh the webpage, select the certificate and watch the magic happen.
Research
Using Windows 8 and IIS 8.5 I followed the instructions here http://itq.nl/testing-with-client-certificate-authentication-in-a-development-environment-on-iis-8-5/.
Certificates were created in the correct place and everything configured in IIS properly but I kept getting 403.16 errors.
After the many MSDN articles and other attempts failed I found the following registry setting.
Set HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
Value name: ClientAuthTrustMode
Value type: REG_DWORD
Value data: 2
Set HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
Value name: SendTrustedIssuerList
Value type: REG_DWORD
Value data: 0 (False, or delete this key entirely)
Here is some more information about this specific setting (found here: http://technet.microsoft.com/en-us/library/hh831771.aspx)
Defaults for Trust Modes
There are three Client Authentication Trust Modes supported by the Schannel provider. The trust mode controls how validation of the client’s certificate chain is performed and is a system-wide setting controlled by the REG_DWORD “ClientAuthTrustMode” under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel.
0 Machine Trust (default)
Requires that the client certificate is issued by a certificate in the Trusted Issuers list.
1 Exclusive Root Trust
Requires that a client certificate chains to a root certificate contained in the caller-specified trusted issuer store. The certificate must also be issued by an issuer in the Trusted Issuers list
2 Exclusive CA Trust
Requires that a client certificate chain to either an intermediate CA certificate or root certificate in the caller-specified trusted issuer store.
For information about authentication failures due to trusted issuers configuration issues, see Knowledge Base article 280256.
Hope this work for you as well.
I have tried the solution suggested above and it works fine.
An alternative solution which doesn't involve editing the registry:
https://support.microsoft.com/en-us/help/2795828/lync-server-2013-front-end-service-cannot-start-in-windows-server-2012
The main point from this article is to remove all non-signed certificates from the Local Computer Trusted Root folder.
If you use group policies to deploy certificates, make sure that the Trusted Root Certification Authorities store only contains self-signed certificates (certificates in which the certificate property "Subject" is the same as the certificate property "Issuer"). Move any certificates that are not self-signed certificates from the Trusted Root Certification Authorities store to the Intermediate Certification Authorities store.
If you import new certificates manually, make sure that you select the
computer’s Trusted Root Certification Authorities store for the
self-signed certificates, and the computer’s Intermediate
Certification Authorities store for the certificates that are not
self-signed certificates.
You can find all the non-self signed certificates by using the Powershell script:
Get-Childitem cert:\LocalMachine\root -Recurse | Where-Object {$_.Issuer -ne $_.Subject} | Format-List * | Out-File "c:\computer_filtered.txt"
Move those certs to the Intermediate Certification Authorities folder in mmc.
I had to reboot the server to get the ClientAuthTrustMode setting to apply.
If you use IIS10 on Windows2022, TLS1.3 is turned on by default. Then maybe follwing can answer can help you: https://stackoverflow.com/a/75336463/4994931

Self Signed SSL Certificate 403.7 Error

I have been having this issue for about 2 weeks. I have done a lot of research and tried different ways but no joy. I have a development website on my computer (Windows 7 Pro) with sql server 2008 r2 and using IIS 7.5. There is an actual development server running the database and Webserver but because of my location I cannot use the main development site. I issued a self signed Trusted Root Certificate:
makecert -r -pe -n "CN=ROOT AUTHORITY" -ss my -sr CurrentUser -a sha1 -sky signature -cy authority -sv ca.pvk ca.cer
Then I install that into the trusted root on the local computer. After that I created a certificate for IIS to use.
makecert -pe -n "CN=example.website.name.com" -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -ic ca.cer -iv ca.pvk -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -sv server.pvk server.cer
Then I create the .pfx file for IIS
pvk2pfx -pvk server.pvk -spc server.cer -pfx server.pfx
After I do the above. I import the certificate into IIS and then I bind the website to the SSL certificate (server.pfx)
After all that is done, I go on the website https://example.website.name.com and I get 403.7 forbidden.
Can somebody please help me out with this issue?
take a look at some of these pitfalls...
Server Issue #1 - The client cert passed in has 1 or more certification paths that do NOT exist on the server. Open the cert go to certification path (tab) and make sure each of the root authorities are in the SERVERS trusted root certificate authorities. Note, you DO NOT need to install the cert on the server just the root authorities public keys under Certificates (Local Computer) \ Trusted Root Certification Authorities.
Server Issues #2 (previously mentioned solution) - In IIS, for the site, make sure the SSL Settings are set to Accept OR Require (never ignore). The benefit of using Require is that the IIS logs will show you are 403 7 error where as Accept will just get your the IsPresent == false but with a 200 http code.
Client Issue #1 - Same as server issue #1, got to trust those authorities!
Client Issue #2 - You have the trusted root authorites but NOT the private key for the cert itself. Make sure you install the pfx (private key) into the cert store not the public key (.cer). You can also see if you have the private key by double clicking the cert in the cert store and on the general tab you should see a message saying as much.
Client Issue #3 - You put the cert in the wrong place. Probably best to place your cert in Certificates (Local Computer) \ Personal \ Certificates, rather than (current user). This will make the cert available to process accounts that are running your code and actually need access to it.
Client Issue #4 - Right mouse click the cert (in the store not a .cer file) --> All Tasks --> Manage Private Keys... and make sure the process account running your code has "Read" permission. A quick test of this (but not recommended for production use) is to add "Everyone" as read to see if this is your issue

OpenSSL: unable to verify the first certificate for Experian URL

I am trying to verify an SSL connection to Experian in Ubuntu 10.10 with OpenSSL client.
openssl s_client -CApath /etc/ssl/certs/ -connect dm1.experian.com:443
The problem is that the connection closes with a Verify return code: 21 (unable to verify the first certificate).
I've checked the certificate list, and the Certificate used to sign Experian (VeriSign Class 3 Secure Server CA - G3) is included in the list.
/etc/ssl/certs/ca-certificates.crt
Yet I don't know why it is not able to verify the first certificate.
The entire response could be seen here:
https://gist.github.com/1248790
The first error message is telling you more about the problem:
verify error:num=20:unable to get local issuer certificate
The issuing certificate authority of the end entity server certificate is
VeriSign Class 3 Secure Server CA - G3
Look closely in your CA file - you will not find this certificate since it is an intermediary CA - what you found was a similar-named G3 Public Primary CA of VeriSign.
But why does the other connection succeed, but this one doesn't? The problem is a misconfiguration of the servers (see for yourself using the -debug option). The "good" server sends the entire certificate chain during the handshake, therefore providing you with the necessary intermediate certificates.
But the server that is failing sends you only the end entity certificate, and OpenSSL is not capable of downloading the missing intermediate certificate "on the fly" (which would be possible by interpreting the Authority Information Access extension). Therefore your attempt fails using s_client but it would succeed nevertheless if you browse to the same URL using e.g. FireFox (which does support the "certificate discovery" feature).
Your options to solve the problem are either fixing this on the server side by making the server send the entire chain, too, or by passing the missing intermediate certificate to OpenSSL as a client-side parameter.
Adding additional information to emboss's answer.
To put it simply, there is an incorrect cert in your certificate chain.
For example, your certificate authority will have most likely given you 3 files.
your_domain_name.crt
DigiCertCA.crt # (Or whatever the name of your certificate authority is)
TrustedRoot.crt
You most likely combined all of these files into one bundle.
-----BEGIN CERTIFICATE-----
(Your Primary SSL certificate: your_domain_name.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Intermediate certificate: DigiCertCA.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Root certificate: TrustedRoot.crt)
-----END CERTIFICATE-----
If you create the bundle, but use an old, or an incorrect version of your Intermediate Cert (DigiCertCA.crt in my example), you will get the exact symptoms you are describing.
SSL connections appear to work from browser
SSL connections fail from other clients
Curl fails with error: "curl: (60) SSL certificate : unable to get local issuer certificate"
openssl s_client -connect gives error "verify error:num=20:unable to get local issuer certificate"
Redownload all certs from your certificate authority and make a fresh bundle.
I came across the same issue installing my signed certificate on an Amazon Elastic Load Balancer instance.
All seemed find via a browser (Chrome) but accessing the site via my java client produced the exception javax.net.ssl.SSLPeerUnverifiedException
What I had not done was provide a "certificate chain" file when installing my certificate on my ELB instance (see https://serverfault.com/questions/419432/install-ssl-on-amazon-elastic-load-balancer-with-godaddy-wildcard-certificate)
We were only sent our signed public key from the signing authority so I had to create my own certificate chain file. Using my browser's certificate viewer panel I exported each certificate in the signing chain. (The order of the certificate chain in important, see https://forums.aws.amazon.com/message.jspa?messageID=222086)
Here is what you can do:-
Exim SSL certificates
By default, the /etc/exim.conf will use the cert/key files:
/etc/exim.cert
/etc/exim.key
so if you're wondering where to set your files, that's where.
They're controlled by the exim.conf's options:
tls_certificate = /etc/exim.cert
tls_privatekey = /etc/exim.key
Intermediate Certificates
If you have a CA Root certificate (ca bundle, chain, etc.) you'll add the contents of your CA into the exim.cert, after your actual certificate.
Probably a good idea to make sure you have a copy of everything elsewhere in case you make an error.
Dovecot and ProFtpd should also read it correctly, so dovecot no longer needs the ssl_ca option.
So for both cases, there is no need to make any changes to either the exim.conf or dovecot.conf(/etc/dovecot/conf/ssl.conf)
If you are using MacOS use:
sudo cp /usr/local/etc/openssl/cert.pem /etc/ssl/certs
after this Trust anchor not found error disappears
For those using zerossl.com certificates, drag and drop all certificates (as is) to their respective folders.
Cut and pasting text into existing files, may cause utf8 issues - depending upon OS, format and character spacings.