package epsos.ccd.gnomon.configmanager; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.Charset; import java.security.KeyStore; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Hashtable; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import epsos.ccd.netsmart.securitymanager.SignatureManager; /** * Helper utils form validating xnl, extracting nodes from xml * * @author Kostas Karkaletsis * @author Organization: Gnomon * @author mail:k.karkaletsis@gnomon.com.gr * @version 1.0, 2010, 30 Jun */ public class TSLUtils { static Logger logger = Logger.getLogger(TSLUtils.class); static private BASE64Encoder encode = new BASE64Encoder(); static private BASE64Decoder decode = new BASE64Decoder(); private static String KEY_STORE_TYPE = "JKS"; private static String KEY_STORE_NAME = "C://mesa//test_keystore_server1.jks"; private static String KEY_STORE_PASS = "spirit"; private static String PRIVATE_KEY_PASS = "spirit"; private static String KEY_ALIAS = "server1"; private static String TRUST_STORE = "C://mesa//test_keystore_server1.jks"; private static String TRUST_STORE_PASS = "spirit"; public static void init_variables() { ConfigurationManagerService cms = ConfigurationManagerService.getInstance(); KEY_STORE_NAME = cms.getProperty("javax.net.ssl.keyStore"); KEY_STORE_PASS = cms.getProperty("javax.net.ssl.keyStorePassword"); PRIVATE_KEY_PASS = cms.getProperty("javax.net.ssl.privateKeyPassword"); KEY_ALIAS = cms.getProperty("javax.net.ssl.key.alias"); TRUST_STORE = cms.getProperty("javax.net.ssl.trustStore"); TRUST_STORE_PASS = cms.getProperty("javax.net.ssl.trustStorePassword"); } /** * Given the path of the tsl file and the service name, this method exports its certifivate to der format * * @param filename * is the path of the tsl file * @return in a hashtable the services defined in the thsl file */ public static void exportSSLFromTSL(String filename, String countrycode) { // TODO check TSPTradeName to see if it is NCP-A String tagValue = ""; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); InputStream is = new URL(filename).openStream(); Document doc = db.parse(is); is.close(); doc.getDocumentElement().normalize(); NodeList nodeLst = doc.getElementsByTagName("tsl:TSPServices"); for (int s = 0; s < nodeLst.getLength(); s++) { Node fstNode = nodeLst.item(s); if (fstNode.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) fstNode; NodeList services = eElement.getElementsByTagName("tsl:ServiceInformation"); for (int s1 = 0; s1 < services.getLength(); s1++) { Node secNode = services.item(s1); if (secNode.getNodeType() == Node.ELEMENT_NODE) { Element bElement = (Element) secNode; tagValue = getServiceNameFromURL(getTagValue("tsl:ServiceTypeIdentifier", bElement)); if (tagValue.equals("PatientIdenitificationService")) tagValue = "PatientIdentificationService"; NodeList sn = bElement.getElementsByTagName("tsl:ServiceName"); String tdValue = ""; for (int t1 = 0; t1 < sn.getLength(); t1++) { Node snNode = sn.item(t1); Element snElement = (Element) snNode; NodeList tradeNames = snElement.getElementsByTagName("tsl:Name"); Node td = tradeNames.item(0); Element tdElement = (Element) td; tdValue = tdElement.getTextContent(); } if (!(tdValue.startsWith("NCP-B"))) { NodeList xmlSigs = bElement.getElementsByTagName("tsl:ServiceDigitalIdentity"); for (int s2 = 0; s2 < xmlSigs.getLength(); s2++) { Node thirdNode = xmlSigs.item(s2); Element cElement = (Element) thirdNode; NodeList digitalids = cElement.getElementsByTagName("tsl:DigitalId"); for (int s3 = 0; s3 < digitalids.getLength(); s3++) { Node fourthNode = digitalids.item(s3); Element dElement = (Element) fourthNode; NodeList certs = dElement.getElementsByTagName("tsl:X509Certificate"); for (int s4 = 0; s4 < certs.getLength(); s4++) { Node certNode = certs.item(s4); InputStream in = new ByteArrayInputStream(decode.decodeBuffer(certNode .getTextContent())); X509Certificate t = TSLUtils.getCertificateFromIS(in); // create a keypair value with certid and country code ConfigurationManagerService cm = ConfigurationManagerService.getInstance(); String storepath = cm.getProperty("certificates.storepath"); cm.updateProperty(t.getSerialNumber() + "", getNCP(s + "") + "_" + countrycode + "_" + tagValue.trim()); // export the certificate to der format TSLUtils.exportCertificate(t, new File(storepath + getNCP(s + "") + "_" + countrycode + "_" + tagValue.trim() + "_" + s3 + ".der"), true); logger.info(getNCP(s + "") + "_" + countrycode + "_" + tagValue.trim() + "_" + s3 + ".der" + " exported successfully"); TSLUtils.storeCertificateToTrustStore(t, tdValue + getNCP(s + "") + "_" + countrycode + "_" + s3 + "_" + tagValue.trim()); logger.info("### TRUSTSTORE ### " + getNCP(s + "") + "_" + countrycode + "_" + tagValue.trim() + "_" + s3 + ".der" + " imported successfully"); } } } } } } } } } catch (Exception e) { logger.error(countrycode + "_" + tagValue.trim() + " NOT processed successfully"); } } public static void exportNCPSignFromTSL(String filename, String countrycode) { // TODO check TSPTradeName to see if it is NCP-A String tagValue = ""; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db; db = dbf.newDocumentBuilder(); InputStream is = new URL(filename).openStream(); Document doc = db.parse(is); is.close(); doc.getDocumentElement().normalize(); NodeList certs = doc.getElementsByTagName("ds:X509Certificate"); for (int s4 = 0; s4 < certs.getLength(); s4++) { Node certNode = certs.item(s4); InputStream in = new ByteArrayInputStream(decode.decodeBuffer(certNode.getTextContent())); X509Certificate t = TSLUtils.getCertificateFromIS(in); ConfigurationManagerService cm = ConfigurationManagerService.getInstance(); String storepath = cm.getProperty("certificates.storepath"); // export the certificate to der format TSLUtils.exportCertificate(t, new File(storepath + countrycode + "_" + "NCPSign" + "_" + s4 + ".der"), true); logger.info(countrycode + "_" + tagValue.trim() + "_" + s4 + " exported successfully"); TSLUtils.storeCertificateToTrustStore(t, "NCPSign " + "_" + "_" + countrycode); logger.info(countrycode + "_" + "NCPSign" + "_" + s4 + " imported successfully"); } } catch (Exception e) { logger.error(countrycode + "_" + "NCP Signature NOT processed successfully"); } } /** * Extracts the service names defined in the tsl file. As A service name defined the last part of the service url. E.g if the service URL is http://epsos.e/ccd/PatientService the service name is * PatientService * * @param filename * is the path stored the tsl file * @return a hashtable of the service names and the endpoints */ public static Hashtable getServicesFromTSL(String filename) { Hashtable serviceNames = new Hashtable(); try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); InputStream is = new URL(filename).openStream(); Document doc = db.parse(is); is.close(); doc.getDocumentElement().normalize(); System.out.println("Root element " + doc.getDocumentElement().getNodeName()); NodeList nodeLst = doc.getElementsByTagName("tsl:TSPServices"); // System.out.println("Information of all services"); for (int s = 0; s < nodeLst.getLength(); s++) { Node fstNode = nodeLst.item(s); if (fstNode.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) fstNode; NodeList services = eElement.getElementsByTagName("tsl:ServiceInformation"); for (int s1 = 0; s1 < services.getLength(); s1++) { Node secNode = services.item(s1); if (secNode.getNodeType() == Node.ELEMENT_NODE) { Element bElement = (Element) secNode; NodeList sn = bElement.getElementsByTagName("tsl:ServiceName"); String tdValue = ""; for (int t1 = 0; t1 < sn.getLength(); t1++) { tdValue = ""; Node snNode = sn.item(t1); Element snElement = (Element) snNode; NodeList tradeNames = snElement.getElementsByTagName("tsl:Name"); Node td = tradeNames.item(0); Element tdElement = (Element) td; try { tdValue = tdElement.getTextContent(); } catch (Exception e) { logger.error(e.getMessage()); } } if (!tdValue.startsWith("NCP-B")) { tdValue = ""; String sname = getTagValue("tsl:ServiceTypeIdentifier", bElement); NodeList suppnodes = bElement.getElementsByTagName("tsl:ServiceSupplyPoints"); for (int t1 = 0; t1 < suppnodes.getLength(); t1++) { Node suppNode = suppnodes.item(t1); Element snElement = (Element) suppNode; NodeList suppnode = snElement.getElementsByTagName("tsl:ServiceSupplyPoint"); Node td = suppnode.item(0); Element tdElement = (Element) td; try { tdValue = tdElement.getTextContent(); } catch (Exception e) { logger.error(sname + " " + e.getMessage()); } } sname = tdValue; if (!tdValue.equals("")) { serviceNames.put( getNCP(s + "") + getServiceNameFromURL(getTagValue("tsl:ServiceTypeIdentifier", bElement)), sname); logger.info("Service URL " + sname + " added to configuration " + getServiceNameFromURL(getTagValue("tsl:ServiceTypeIdentifier", bElement))); } } else { logger.info("IGNORED: It was an NCP-B Service " + getServiceNameFromURL(getTagValue("tsl:ServiceTypeIdentifier", bElement))); } } } } } } catch (Exception e) { logger.error(e.getMessage()); e.printStackTrace(); } return serviceNames; } public static String getNCP(String s) { String ret = "_"; if (s.equals("0")) ret = ""; if (s.equals("1")) ret = "NCPB_"; return ret; } private static String getServiceNameFromURL(String url) { String[] parts = url.split("/"); int partsLength = parts.length; String serviceName = parts[partsLength - 1]; return serviceName; } /** * * @param sTag * the tag name of an element of a dom * @param eElement * the selected dom element * @return the value of the specific element */ private static String getTagValue(String sTag, Element eElement) { NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes(); Node nValue = (Node) nlList.item(0); return nValue.getNodeValue(); } /** * Given an inputstream we can extract the x509 certificate included * * @param in * @return the x509 certificate */ public static X509Certificate getCertificateFromIS(InputStream in) { X509Certificate t = null; try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); java.security.cert.Certificate c = cf.generateCertificate(in); in.close(); t = (X509Certificate) c; } catch (Exception e) { logger.info(e.getMessage()); } return t; } /** * This method takes a certificate and imports it to the truststore defined in the configuration file * * @param cert * the certificate to be imported */ public static void storeCertificateToTrustStore(java.security.cert.Certificate cert, String certalias) { init_variables(); try { KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); File keystoreFile = new File(TRUST_STORE); // Load the keystore contents FileInputStream in = new FileInputStream(keystoreFile); keystore.load(in, TRUST_STORE_PASS.toCharArray()); in.close(); keystore.setCertificateEntry(certalias, cert); System.out.println("CERTALIAS: " + certalias); // Save the new keystore contents FileOutputStream out = new FileOutputStream(keystoreFile); keystore.store(out, TRUST_STORE_PASS.toCharArray()); out.close(); } catch (Exception e) { logger.debug(e.getMessage()); e.printStackTrace(); } } /** * This method exports a certificate either to text (pem format), either to binary (der format) * * @param cert * @param file * @param binary */ public static void exportCertificate(java.security.cert.Certificate cert, File file, boolean binary) { try { // Get the encoded form which is suitable for exporting byte[] buf = cert.getEncoded(); FileOutputStream os = new FileOutputStream(file); if (binary) { // Write in binary form os.write(buf); } else { // Write in text form Writer wr = new OutputStreamWriter(os, Charset.forName("UTF-8")); wr.write("-----BEGIN CERTIFICATE-----\n"); wr.write(new sun.misc.BASE64Encoder().encode(buf)); wr.write("\n-----END CERTIFICATE-----\n"); wr.flush(); } os.close(); } catch (CertificateEncodingException e) { } catch (Exception e) { e.printStackTrace(); logger.error(e.getMessage()); } } /** * Wrapper method to Security Manager * */ public static boolean VerifyTSL(Document doc) { boolean verified = false; try { SignatureManager sm = new SignatureManager(); sm.verifyEnvelopedSignature(doc); verified = true; } catch (Exception e) { logger.error("Error validating the signature"); } return verified; } /** * Given a URL containing an xml file, it parses it and returns the dom object * * @param inputFile * the url path as String * @return org.w3c.dom.Document */ public static Document createDomFromURL(String strURL) { init_variables(); Document doc = null; // Instantiate the document to be signed try { URL url = new URL(strURL); // Getting URL to invoke HttpURLConnection urlCon = (HttpURLConnection) url.openConnection(); // Opening connection with the URL specified urlCon.setReadTimeout(10000); // Set Read Time out in milliseconds, Setting 1 second as read timeout urlCon.connect(); // Connecting InputStream iStream = urlCon.getInputStream(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setNamespaceAware(true); doc = dbFactory.newDocumentBuilder().parse(iStream); } catch (Exception e) { logger.error(e.getMessage()); } return doc; } public static Document createDomFromURLUsingHttps(String strURL) { init_variables(); Document doc = null; TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } } }; try { SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); // URL url = new URL("https://econfig.nczisk.sk:8443"); URL url = new URL(strURL); HttpsURLConnection urlCon = (HttpsURLConnection) url.openConnection(); urlCon.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); // Instantiate the document to be signed urlCon.setReadTimeout(10000); // Set Read Time out in milliseconds, Setting 1 second as read timeout urlCon.connect(); // Connecting InputStream iStream = urlCon.getInputStream(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setNamespaceAware(true); doc = dbFactory.newDocumentBuilder().parse(iStream); } catch (Exception e) { logger.error(e.getMessage()); } return doc; } /** * Given the pem string of the signature this method returns the X509 Certificate of the signature * * @param pem * String fortmat of the signature * @return the X509 certificate */ // public static X509Certificate getCertificateFromString(String pem) // { // X509Certificate t = null; // try // { // CertificateFactory cf = CertificateFactory.getInstance("X.509"); // InputStream in = StringToStream(pem); // java.security.cert.Certificate c = cf. generateCertificate(in); // in.close(); // t = (X509Certificate) c; // } // catch (Exception e) // {logger.info(e.getMessage());} // return t; // } }