java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.NETWORK - ssl

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.NETWORK
Hi i got this error while i am calling one API service from retrofit , i am searching a lot and found answer like
private static void setupRestClient() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(ROOT)
//.setClient(new OkClient(new com.squareup.okhttp.OkHttpClient()))
//.setClient(getOkClient())
.setClient(setSSLFactoryForClient(new com.squareup.okhttp.OkHttpClient()))
.setRequestInterceptor(new SessionRequestInterceptor())
.setLogLevel(RestAdapter.LogLevel.FULL)
.setLog(new AndroidLog(NetworkUtil.APP_TAG))
.build();
REST_CLIENT = restAdapter.create(Restapi.class);
}
// SET SSL
public static OkClient setSSLFactoryForClient(OkHttpClient client) {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
client.setSslSocketFactory(sslSocketFactory);
client.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
return new OkClient(client);
}
After using setSSLFactoryForClient method it work fine but i couldn't understand whats going wrong and what this method does i know the problem is related to SSL Certificate Authentication but Can any one explain me this in brief Please

This is disabling the security of SSL. This is ok for local testing but not appropriate for use with real users.
If you run your local dev server with a self signed cert then this is how you can tell it to connect to it with minimal pain.
More generally any user agent (Firefox on Windows, Safari on Mac, Android) will have a list of root CAs it trusts to verify a sites certificates. Some newer services like let's encrypt will not be trusted on older platforms so you can add your own certificates that you know ahead of time.
The hostname verification means that the cert it serves could be for a different site even.
For real traffic this code means your users are susceptible to man in the middle attacks.

Related

Enable SSL certificate revocation checking in OpenJDK 11

Is there some quick "declarative" way in Java 11, instead of a tedious manual implementation, to enable checking if a certificate is revoked?
I tried to use properties from this answer:
Check X509 certificate revocation status in Spring-Security before authenticating
with this dummy revoked certificate: https://revoked.badssl.com
but the code always accepts the certificate. Am I doing something wrong or these properties are no more actual for Java 11? If so, do we have any alternatives?
Below is my code:
public static void validateOnCertificateRevocation(boolean check) {
if (check) {
System.setProperty("com.sun.net.ssl.checkRevocation", "true");
System.setProperty("com.sun.security.enableCRLDP", "true");
Security.setProperty("ocsp.enable", "true");
}
try {
new URL("https://revoked.badssl.com").openConnection().connect();
} catch (IOException e) {
e.printStackTrace();
}
}
It seems like those options have to be set before the first request has been performed.
Therefore the following code as standalone Java program throws an CertPathValidatorException: Certificate has been revoked (tested using OpenJDK 11.0.2 x64 on Windows):
public static void main(String[] args) {
validateOnCertificateRevocation(true); // throws CertPathValidatorException
}
However the following code does not cause any errors/Exceptions:
public static void main(String[] args) {
validateOnCertificateRevocation(false);
validateOnCertificateRevocation(true); // nothing happens
}
You can see the changing the options after the first request has been processed isn't effective. I assume that those options are processed in a static { ... } block of some certificate validation related class.
If you still want to enable/disable certificate revocation checking on a per-request base you can do so by implementing your own X509TrustManager that uses CertPathValidator (for which you can enable/disable certificate revocation checking via PKIXParameters.setRevocationEnabled(boolean).
Alternatively there is the solution to globally enable certificate revocation checking and explicitly handle the CertificateRevokedException:
private boolean checkOnCertificateRevocation;
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
try {
getDefaultTrustManager().checkServerTrusted(certs, authType);
} catch (CertificateException e) {
if (checkOnCertificateRevocation) {
if (getRootCause(e) instanceof CertificateRevokedException) {
throw e;
}
}
}
}

Fabric Crashlytics Error javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException

This Error is related to Fabric Crashlytics, not direct RestFul API consumptions.
I'm getting this error when initiating the Fabric Crashlytics on Android Emulator
E/Fabric: Settings request failed.
io.fabric.sdk.android.services.network.HttpRequest$HttpRequestException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at io.fabric.sdk.android.services.network.HttpRequest.code(HttpRequest.java:1355)
at io.fabric.sdk.android.services.settings.DefaultSettingsSpiCall.handleResponse(DefaultSettingsSpiCall.java:104)
at io.fabric.sdk.android.services.settings.DefaultSettingsSpiCall.invoke(DefaultSettingsSpiCall.java:88)
at io.fabric.sdk.android.services.settings.DefaultSettingsController.loadSettingsData(DefaultSettingsController.java:80)
at io.fabric.sdk.android.services.settings.DefaultSettingsController.loadSettingsData(DefaultSettingsController.java:64)
at io.fabric.sdk.android.services.settings.Settings.loadSettingsData(Settings.java:153)
at io.fabric.sdk.android.Onboarding.retrieveSettingsData(Onboarding.java:126)
at io.fabric.sdk.android.Onboarding.doInBackground(Onboarding.java:99)
at io.fabric.sdk.android.Onboarding.doInBackground(Onboarding.java:45)
at io.fabric.sdk.android.InitializationTask.doInBackground(InitializationTask.java:63)
at io.fabric.sdk.android.InitializationTask.doInBackground(InitializationTask.java:28)
at io.fabric.sdk.android.services.concurrency.AsyncTask$2.call(AsyncTask.java:311)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:563)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:444)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:508)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:401)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:375)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:304)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
E/Fabric: at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:178)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:596)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
... 30 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
... 42 more
E/Answers: Failed to retrieve settings
Any Idea how to resolve this, or add custom SSlSocketFactory to Fabric HttpRequest class?
For anyone else experiencing this issue: This error occurred for me when the wifi password was outdated and my device switched to a different (open) network. Try switching to another (closed) network.
Ran into the same issue, the same Crashlytics setup in Fabric and Firebase, tried with different versions of Crashlytics up to 2.9.2, it worked fine on API 22+, but not on API 21 and below. In the end, it is resolved by a workaround, not ideal and not recommended for production, which is bypassing the ssl check all together by calling the function below in the onCreate() in app's Application class.
public void trustAllCertificates() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] myTrustedAnchors = new X509Certificate[0];
return myTrustedAnchors;
}
#Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
} catch (Exception e) {
}
}
References: https://androidlad.blogspot.com/2017/08/how-to-trust-all-certificates-or-bypass.html

Apache Camel CXF: add TlsClientParameters programmatically

I am using Apache Camel CXF as producer to call a SOAP Webservice. I do not use Spring configuration but do everything programmatically (I am a beginner and wanted to prevent having to learn both Spring and Apache Camel). The Webservice uses SSL with a self signed certificate. I added it to a truststore and hoped to be able to add that to the CxfEndpoint similar to how I did it with https4:
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("src/main/resources/truststore.jks");
ksp.setPassword("...");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("...");
SSLContextParameters scp = new SSLContextParameters();
scp.setKeyManagers(kmp);
CamelContext context = new DefaultCamelContext();
context.addRoutes(routeBuilder);
HttpComponent httpComponent = context.getComponent("https4", HttpComponent.class);
httpComponent.setSslContextParameters(scp);
– but that does not seem to work with the CxfComponent. I found a lot of documentation about adding TlsClientParameters using Spring and configuring the CxfEndpoint, for example here: apache camel cxf https not working
and here Calling secure webservice using CXF and Camel. However I do not find any hint on how to simply add a truststore to the component as I did with https4 or even in the route definition, which is:
from(ENDPOINT_URI)
.setProperty(SecurityConstants.PASSWORD, constant(PASSWORD))
.setProperty(SecurityConstants.USERNAME, constant(USERNAME))
.to("cxf://" + SERVICE_URL + "?" +
"wsdlURL=" + WSDL_URL + "&" +
"serviceName=" + SERVICE_NAME + "&" +
"portName=" + PORT_NAME + "&" +
"dataFormat=CXF_MESSAGE&" +
"synchronous=true&" +
"defaultOperationName=" + DEFAULT_OPERATION_NAME)
.streamCaching();
I think this must be a very simple problem, so I still expect there is some neat way to simply add the truststore (or even accepting any certificate, since its not really relevant in our use case). I would be really happy if there was a simple programmatic way. Does anyone know?
I solved the issue by adding the certificate to the JVMs truststore in jre/lib/cacerts. That is feasable since I have access to the JVM on the machine the application will be running on. It seems to be the simplest solution.
Update
If anyone is interested in a more proper solution: CxfEndpoint provides a means to influence the HTTPConduit and its TLS Parameters. This is the revised code:
add "cxfEndpointConfigurer=SageEndpointConfigurer" to the cxf endpoint parameters
when creating the endpoint "SageEndpointConfigurer" will be resolved using TypeConverters
add a TypeConverter to the TypeConverter Registry of the context, i.e. directly in the RouteBuilder
getContext().getTypeConverterRegistry().addTypeConverter(CxfEndpointConfigurer.class, String.class, new SageEndpointConfigurerConverter());
configure TLSParameters and simply return the CxfEndpointConfigurer from the TypeConverter
private class SageEndpointConfigurerConverter extends TypeConverterSupport {
#Override
public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {
CxfEndpointConfigurer configurer = new CxfEndpointConfigurer() {
#Override
public void configure(AbstractWSDLBasedEndpointFactory factoryBean) {
// do nothing
}
#Override
public void configureClient(Client client) {
URLConnectionHTTPConduit conduit = (URLConnectionHTTPConduit) client.getConduit();
TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setDisableCNCheck(true);
tlsParams.setTrustManagers(new TrustManager[]{new TrustAllTrustManager()});
conduit.setTlsClientParameters(tlsParams);
}
#Override
public void configureServer(Server server) {
//do nothing
}
};
return (T) configurer;
}
}
the TrustAllManager is implemented like that
public class TrustAllTrustManager implements X509TrustManager {
private static Logger LOG = LoggerFactory.getLogger(TrustAllTrustManager.class);
#Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
//do nothing, trust all certificates
logMessage(x509Certificates, authType);
}
#Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
//do nothing, trust all certificates
logMessage(x509Certificates, authType);
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
private void logMessage(X509Certificate[] x509Certificates, String authType) {
StringBuilder message = new StringBuilder();
String lineSeparator = System.getProperty("line.separator");
message.append("Trusted following certificates for authentication type '").append(authType).append("'").append(lineSeparator);
for (X509Certificate certificate : x509Certificates) {
message.append(certificate).append(lineSeparator);
}
LOG.trace(message.toString());
}
}

.net WebService, bypass ssl validation!

Well im working agains a webservice that has a certificate that is not 100% correctly setup the certificate is setup for the domain *.domain1.com and the api is located at soap.shop.domain1.com/SOAP now i cant connect to this webservice as i then get a WebException "Could Not establish trush relationship for the SSL/TLS secure channel. -->
The remote certificate is invalid according to the validation procedure.
Now my question is there any way to bypass this check i use a normal Web Reference (2.0) not a Service Reference..
For those who can't determine where to start with this answer, it may not be obvious. The posters above are getting it right, but it wasn't apparent upfront on what to do with the given code.
Let's say you have a class somewhere that needs to call a web service with a certificate.
Here's my finished solution:
public class MyClass
{
public bool TrustAllCertificatesCallback(object sender, X509Certificate cert,
X509Chain chain, SslPolicyErrors errors)
{
return true;
}
public string CallSomeWebService(string someParam)
{
try
{
ServicePointManager.ServerCertificateValidationCallback = TrustAllCertificatesCallback;
RemoteWebService ws = new RemoteWebService();
//add the client cert to the web service call.
ws.ClientCertificates.Add(GetMyCert());
//call the web service
string response = ws.SomeMethod(someParam);
return response.ToString();
}
catch (Exception ex)
{throw;}
}
public X509Certificate GetMyCert()
{
try
{
string certPath = #"C:\MyCerts\MyCert.cer";
var cert = X509Certificate.CreateFromCertFile(certPath);
return cert;
}
catch (Exception ex)
{throw;}
}
}
Yes, you can use the following to have ASP.NET ignore the certificate warnings:
using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
namespace YourNamespace
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy() {}
public bool CheckValidationResult(ServicePoint sp, X509Certificate cert,WebRequest req, int problem)
{
return true;
}
}
}
System.Net.ServicePointManager.ServerCertificateValidationCallback = _
Function(a, b, c, d) True
pick you flavor..
lambda expresions
//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
// trust sender (more secure)
System.Net.ServicePointManager.ServerCertificateValidationCallback
= ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));
or plain clode (better for testing)
// validate cert
// allows for validation of SSL conversations
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);
// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
bool result = false;
if (cert.Subject.ToUpper().Contains("YourServerName"))
{
result = true;
}
return result;
}
You need to handle the event that validates the certificate and just set it to always return true. See the following post for details:
http://8r13n.wordpress.com/2007/07/24/bypassing-certificate-validation-in-net/

How to turn off certificate revocation for a WCF service's client?

How can I turn off certificate revocation for a WCF service's client?
The client proxy was generated by wsdl.exe and inherits SoapHttpClientProtocol.
I think you're looking for ServicePointManager.ServerCertificateValidationCallback:
http://msdn.microsoft.com/en-gb/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx
Which takes a RemoteCertificateValidationCallback Delegate:
http://msdn.microsoft.com/en-gb/library/system.net.security.remotecertificatevalidationcallback.aspx
I've never dealt with a revoked certificate before (I have hand to handle other issues such as expired SSL's), but I'm guessing you'd just do something like:
class Program
{
static void Main(string[] args)
{
ServicePointManager.ServerCertificateValidationCallback +=
new RemoteCertificateValidationCallback(ValidateCertificate);
// Do WCF calls...
}
public static bool ValidateCertificate(object sender, X509Certificate cert,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if(sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
{
foreach(X509ChainStatus chainStatus in chain.ChainStatus)
{
if(chainStatus.Status == X509ChainStatusFlags.Revoked)
{
return true;
}
}
}
/*
WARNING!
You should perform other cert validation checks here and not blindly
override your cert validation by returning true.
Otherwise the secure channel between your client and service
may not be secure.
*/
return false;
}
}
You can set certificate validation and revocation options in the config file for your application:
http://www.request-response.com/blog/PermaLink,guid,e9bb929b-d0b4-4626-b302-1d2715fc344a.aspx