Check for SSL Certificates Before Connection

This method that I wrote seems to throw an error at "con.getResponseCode()" whenever the server certificates are not configured correctly


	private static String sendGetHttps(String url) 
	{
		BufferedReader in = null;
		try{
			logger.info("Connecting to url: " + url);
			URL obj = new URL(url);
			HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

			con.setRequestMethod("GET");
			int responseCode = con.getResponseCode(); 
			logger.info("Response Code after connecting to url: " + responseCode);
			in = new BufferedReader(new InputStreamReader(con.getInputStream()));
			String inputLine;
			StringBuffer response = new StringBuffer();
			while ((inputLine = in.readLine()) != null) {
				response.append(inputLine);
			}
			in.close();
			logger.info("Response String: " + response.toString());
			
			return response.toString();
		}catch(Exception e ){
			throw new PMRException(e.getMessage(),e);
		}
		finally
		{
			if(in!= null)
			{
				try
				{
					in.close();
				}
				catch(Exception e)
				{
				
				}
			}
		}
	}

Open in new window



To configure them I call this method before the one above:
	public static void getSSLCertificate(String keyStoreLocation, String keyStorePassword, String jksPassword) {
		
		final char[] JKS_PASSWORD = jksPassword.toCharArray();
		final char[] KEY_PASSWORD = keyStorePassword.toCharArray();
		
		try {
			
			// Get the JKS contents 
			final KeyStore keyStore = KeyStore.getInstance("JKS");
			keyStore.load(new FileInputStream(new File(keyStoreLocation)), JKS_PASSWORD);
			final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
			kmf.init(keyStore, KEY_PASSWORD);
			final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
			tmf.init(keyStore);
			
			 // Creates a socket factory for HttpsURLConnection using JKS contents
			final SSLContext sc = SSLContext.getInstance("TLS");
			sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new java.security.SecureRandom());
			final SSLSocketFactory socketFactory = sc.getSocketFactory();
			HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
			
		} catch (IOException exc) {
			throw new RuntimeException(exc);
		} catch (GeneralSecurityException e) {
			throw new RuntimeException(e);
		}
	}

Open in new window


The problem that I am having is that if the second method is not called before the first, then the certificates are not in place and I get this error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)

Open in new window


Of course when I call the methods in the right order that error is not there.

My question is can anyone help me write a check that can be done on maybe the HttpsURLConnection con object from the first code that can help me verify that the relevant certificates are properly recognized? Of course, the aim is to find a a more graceful way to exit when there is an error.

A sample test that was written is as follows:
public class ProgramTest {
	public static void main(String[] args){
		try {
			NetUtils.getSSLCertificate("c:/Users/kingw/.keystore", "changeit", "changeit"); 
			NetUtils.sendGet("https://testing.dev.cfed.local/api/auth/" + "c076utf5-2aaa-4b58-92d3-981dyhfefvgyyh" + "/" + "22");
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
}

Open in new window

onaled777Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
Question: why are you using explicit cert handling?
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Apart from CEHJ's valid question above, rather than going to a lot of trouble to check if the certs are configured, why can't you just ensure that you code your app to call the cert setup method before any method that communicates with the server?
onaled777Author Commented:
CEHJ - I really couldnt get it to work any other way
mccarl - Based on the way the code was structured.
CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

CEHJCommented:
If the cert is imported into your regular store then it should all work automatically, in theory. DID you import it?
onaled777Author Commented:
Yes CEHJ - These were my steps:

1. I pasted the https_url in the browser
2. I retrieved the certificate and downloaded it to my local drive
3. I used the keytool utility in the jre bin to create a keystore
4. I imported the downloaded certificate into the newly created keystore.
5. I checked to make sure the certificate was listed in the keystore with the command keytool -list -v

Yet when I dont do the explicit cert handling I get this error:
***
main, SEND TLSv1 ALERT:  fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 2E                               .......
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
CEHJCommented:
3. I used the keytool utility in the jre bin to create a keystore
...
Why? Why are you not importing the cert into the existing one?

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
onaled777Author Commented:
Looks like the issue was one of configuration. The JAVA_HOME property was configured incorrectly and the keytool facility was looking for the cacerts in the wrong location. When reconfigured it worked without the explicit certificate handling. Thanks.
CEHJCommented:
Yep - that would do it

:)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
SSL / HTTPS

From novice to tech pro — start learning today.