//***************************************************************************** //* //* (c) Copyright 2003. Glub Tech, Incorporated. All Rights Reserved. //* //* $Id: JarUtil.java 37 2009-05-11 22:46:15Z gary $ //* //***************************************************************************** package com.glub.util; import java.io.*; import java.net.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.cert.*; import java.util.*; import java.util.jar.*; public class JarUtil { private static boolean verifiedJar = false; private static String framework; /* private static final String glubCertName = "CN=\"Glub Tech, Inc.\", OU=Secure Application Development, O=\"Glub Tech, Inc.\", L=La Jolla, ST=California, C=US"; private static final String issuingCertName = "EmailAddress=server-certs@thawte.com, CN=Thawte Server CA, OU=Certification Services Division, O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA"; */ private static final int glubHash = 7307316; private static final int issuingHash = 6286758; public static final boolean verifyJar( Class c, String fw ) { return _verifyJar(c, fw); } private static final boolean _verifyJar( Class c, String fw ) { if ( verifiedJar ) { return verifiedJar; } framework = fw; URL jarURL = null; try { final ClassLoader cl = c.getClassLoader(); String classPath = c.toString(); classPath = Util.searchAndReplace( classPath, "class ", "", false ); classPath = Util.searchAndReplace( classPath, ".", "/", true ); classPath += ".class"; final String className = classPath; URL url = (URL)AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return cl.getResource( className ); } }); if ( url == null ) { throw new SecurityException( "Cannot get the " + framework + " framework URL." ); } String urlStr = url.toString(); int per = urlStr.lastIndexOf( ".jar!/" ); if ( per < 0 ) { throw new SecurityException( "The " + framework + " framework is invalid." ); } int slash = per + 5; jarURL = new URL( urlStr.substring(0, slash + 1) ); int beginIndex = 4; URL ju = new URL( urlStr.substring(beginIndex, slash - 1)); if ( !ju.getProtocol().equalsIgnoreCase("file") ) { throw new SecurityException( framework + " should be deployed " + " as an installed extension or on the " + " class path." ); } } catch ( IOException ioe ) { throw new SecurityException( "The " + framework + " framework could " + "not be authenticated." ); } JarFile jf; try { final URL url = jarURL; jf = (JarFile)AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { return ((JarURLConnection)url.openConnection()).getJarFile(); } } ); } catch ( PrivilegedActionException pae ) { throw new SecurityException( "Cannot authenticate the " + framework + " framework: " + pae.getMessage() ); } try { verifySingleJarFile( jf ); } catch ( Exception e ) { throw new SecurityException( "Cannot authenticate the " + framework + " framework: " + e.getMessage() ); } verifiedJar = true; return verifiedJar; } private static void verifySingleJarFile( JarFile jf ) throws IOException, CertificateException { Vector entriesVec = new Vector(); Manifest man = jf.getManifest(); if ( man == null ) { throw new SecurityException( "The jar file is not signed!" ); } byte[] buffer = new byte[8192]; Enumeration entries = jf.entries(); while ( entries.hasMoreElements() ) { JarEntry je = (JarEntry)entries.nextElement(); entriesVec.addElement(je); InputStream is = jf.getInputStream( je ); while ( (is.read(buffer, 0, buffer.length)) != -1 ) { } is.close(); } jf.close(); Enumeration e = entriesVec.elements(); while ( e.hasMoreElements() ) { JarEntry je = (JarEntry)e.nextElement(); if ( je.isDirectory() ) { continue; } Certificate[] certs = je.getCertificates(); if ((certs == null) || (certs.length == 0)) { if ( !je.getName().startsWith("META-INF")) { throw new SecurityException( "The " + framework + " framework has " + "unsigned class files. "); } } else { Certificate[] chainRoots = getChainRoots( certs ); X509Certificate issuingCert = (X509Certificate)chainRoots[0]; //Principal issuingCertPrincipal = issuingCert.getSubjectDN(); X509Certificate signingCert = (X509Certificate)certs[0]; //Principal signingCertPrincipal = signingCert.getSubjectDN(); boolean signedAsExpected = false; if ( issuingCert.hashCode() == issuingHash && signingCert.hashCode() == glubHash ) { signedAsExpected = true; } if ( !signedAsExpected ) { throw new SecurityException( "The " + framework + " framework is " + "not signed by Glub Tech, Inc." ); } } } } private static Certificate[] getChainRoots( Certificate[] certs ) { Vector result = new Vector( 3 ); for ( int i = 0; i < certs.length - 1; i++ ) { if ( !((X509Certificate)certs[i+1]).getSubjectDN().equals( ((X509Certificate)certs[i]).getIssuerDN())) { result.addElement(certs[i]); } } result.addElement( certs[certs.length - 1] ); Certificate[] ret = new Certificate[ result.size() ]; result.copyInto( ret ); return ret; } }