/*************************************************************************** * Copyright (c) 2015 VMware, Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ package com.vmware.bdd.cli.http; import com.vmware.bdd.cli.commands.CommandsUtils; import com.vmware.bdd.cli.commands.Constants; import com.vmware.bdd.cli.config.CliProperties; import com.vmware.bdd.cli.config.RunWayConfig; import com.vmware.bdd.utils.ByteArrayUtils; import com.vmware.bdd.utils.CommonUtil; import jline.console.ConsoleReader; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.net.ssl.X509TrustManager; import java.io.*; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by xiaoliangl on 9/16/15. */ @Component public class DefaultTrustManager implements X509TrustManager { private final static Logger logger = Logger.getLogger(DefaultTrustManager.class); private static final String KEY_STORE_FILE = "serengeti.keystore"; private KeyStore keyStore; private static final char[] DEFAULT_PASSWORD = "changeit".toCharArray(); @Autowired private CliProperties cliProperties; public DefaultTrustManager(){} @PostConstruct protected void initKeystore() throws KeyStoreException { this.keyStore = KeyStore.getInstance("jks"); } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { String errorMsg = ""; InputStream in = null; OutputStream out = null; // load key store file try { char[] pwd = cliProperties.readKeyStorePwd(); File file = new File(KEY_STORE_FILE); if (file.exists() && file.isFile()) { keyStore.load(new FileInputStream(file), pwd); } else { //init an empty keystore keyStore.load(null, pwd); } // show certificate informations MessageDigest sha1 = MessageDigest.getInstance("SHA1"); MessageDigest md5 = MessageDigest.getInstance("MD5"); String md5Fingerprint = ""; String sha1Fingerprint = ""; SimpleDateFormat dateFormate = new SimpleDateFormat("yyyy/MM/dd"); for (int i = 0; i < chain.length; i++) { X509Certificate cert = chain[i]; sha1.update(cert.getEncoded()); md5.update(cert.getEncoded()); md5Fingerprint = ByteArrayUtils.byteArrayToHexString(md5.digest()); sha1Fingerprint = ByteArrayUtils.byteArrayToHexString(sha1.digest()); if (keyStore.getCertificate(md5Fingerprint) != null) { if (i == chain.length - 1) { return; } else { continue; } } System.out.println(); System.out.println("Server Certificate"); System.out .println("================================================================"); System.out.println("Subject: " + cert.getSubjectDN()); System.out.println("Issuer: " + cert.getIssuerDN()); System.out.println("SHA Fingerprint: " + sha1Fingerprint); System.out.println("MD5 Fingerprint: " + md5Fingerprint); System.out.println("Issued on: " + dateFormate.format(cert.getNotBefore())); System.out.println("Expires on: " + dateFormate.format(cert.getNotAfter())); System.out.println("Signature: " + cert.getSignature()); System.out.println(); if (checkExpired(cert.getNotBefore(), cert.getNotAfter())) { throw new CertificateException( "The security certificate has expired."); } ConsoleReader reader = new ConsoleReader(); // Set prompt message reader.setPrompt(Constants.PARAM_PROMPT_ADD_CERTIFICATE_MESSAGE); // Read user input String readMsg; if (RunWayConfig.getRunType().equals(RunWayConfig.RunType.MANUAL)) { readMsg = reader.readLine().trim(); } else { readMsg = "yes"; } if ("yes".equalsIgnoreCase(readMsg) || "y".equalsIgnoreCase(readMsg)) { { // add new certificate into key store file. keyStore.setCertificateEntry(md5Fingerprint, cert); out = new FileOutputStream(KEY_STORE_FILE); keyStore.store(out, pwd); CommonUtil.setOwnerOnlyReadWrite(KEY_STORE_FILE); // save keystore password cliProperties.saveKeyStorePwd(pwd); } } else { if (i == chain.length - 1) { throw new CertificateException( "Could not find a valid certificate in the keystore."); } else { continue; } } } } catch (FileNotFoundException e) { errorMsg = "Cannot find the keystore file: " + e.getMessage(); } catch (NoSuchAlgorithmException e) { errorMsg = "SSL Algorithm not supported: " + e.getMessage(); } catch (IOException e) { e.printStackTrace(); errorMsg = "IO error: " + e.getMessage(); } catch (KeyStoreException e) { errorMsg = "Keystore error: " + e.getMessage(); } catch (ConfigurationException e) { errorMsg = "cli.properties access error: " + e.getMessage(); } finally { if (!CommandsUtils.isBlank(errorMsg)) { System.out.println(errorMsg); logger.error(errorMsg); } if (in != null) { try { in.close(); } catch (IOException e) { logger.warn("Input stream of serengeti.keystore close failed."); } } if (out != null) { try { out.close(); } catch (IOException e) { logger.warn("Output stream of serengeti.keystore close failed."); } } } } private boolean checkExpired(Date notBefore, Date notAfter) { Date now = new Date(); if (now.before(notBefore) || now.after(notAfter)) { return true; } return false; } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }