Author: tchemit Date: Sat Dec 28 14:50:33 2013 New Revision: 1553841 URL: http://svn.apache.org/r1553841 Log: MSHARED-314 - Unsign jar still have some signatures in the manisfest
Modified: maven/shared/trunk/maven-jarsigner/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java maven/shared/trunk/maven-jarsigner/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java Modified: maven/shared/trunk/maven-jarsigner/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-jarsigner/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java?rev=1553841&r1=1553840&r2=1553841&view=diff ============================================================================== --- maven/shared/trunk/maven-jarsigner/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java (original) +++ maven/shared/trunk/maven-jarsigner/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java Sat Dec 28 14:50:33 2013 @@ -28,6 +28,9 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -82,7 +85,7 @@ public class JarSignerUtil * output JAR to retain as much metadata from the original JAR as possible. * * @param jarFile The JAR file to unsign, must not be <code>null</code>. - * @throws java.io.IOException + * @throws IOException */ public static void unsignArchive( File jarFile ) throws IOException @@ -107,6 +110,18 @@ public class JarSignerUtil zos.putNextEntry( new ZipEntry( ze.getName() ) ); + if ( isManifestFile( ze.getName() ) ) + { + + // build a new manifest while removing all digest entries + // see https://jira.codehaus.org/browse/MSHARED-314 + Manifest oldManifest = new Manifest( zis ); + Manifest newManifest = buildUnsignedManifest( oldManifest ); + newManifest.write( zos ); + + continue; + } + IOUtil.copy( zis, zos ); } @@ -122,11 +137,48 @@ public class JarSignerUtil } /** + * Build a new manifest from the given one removing any signing information inside it. + * + * This is done by removing any attributes containing some digest informations. + * If a entry has then no more attributes, then it will not be readd in the result manifest. + * + * @param manifest manifest to clean + * @return the build manifest with no digest attributes + * @since 1.3 + */ + protected static Manifest buildUnsignedManifest( Manifest manifest ) { + + Manifest result = new Manifest( manifest ); + result.getMainAttributes().clear(); + + for ( Map.Entry<String, Attributes> entry : manifest.getEntries().entrySet() ) + { + Attributes oldAttributes = entry.getValue(); + Attributes newAttributes = new Attributes(); + for ( Map.Entry<Object, Object> objectEntry : oldAttributes.entrySet() ) + { + String attributeKey = String.valueOf( objectEntry.getKey() ); + if ( !attributeKey.contains( "-Digest" ) ) + { + // can add this attribute + newAttributes.put( objectEntry.getKey(), objectEntry.getValue() ); + } + } + if ( !newAttributes.isEmpty() ) + { + // can add this entry + result.getEntries().put( entry.getKey(), newAttributes ); + } + } + return result; + } + + /** * Scans an archive for existing signatures. * * @param jarFile The archive to scan, must not be <code>null</code>. * @return <code>true</code>, if the archive contains at least one signature file; <code>false</code>, if the archive - * does not contain any signature files. + * does not contain any signature files. * @throws IOException if scanning <code>jarFile</code> fails. */ public static boolean isArchiveSigned( final File jarFile ) @@ -183,7 +235,7 @@ public class JarSignerUtil * @param entryName The name of the JAR file entry to check, must not be <code>null</code>. * @return <code>true</code> if the entry is related to a signature, <code>false</code> otherwise. */ - private static boolean isSignatureFile( String entryName ) + protected static boolean isSignatureFile( String entryName ) { boolean result = false; if ( entryName.regionMatches( true, 0, "META-INF", 0, 8 ) ) @@ -212,4 +264,22 @@ public class JarSignerUtil } return result; } + + protected static boolean isManifestFile( String entryName ) + { + boolean result = false; + if ( entryName.regionMatches( true, 0, "META-INF", 0, 8 ) ) + { + entryName = entryName.replace( '\\', '/' ); + + if ( entryName.indexOf( '/' ) == 8 && entryName.lastIndexOf( '/' ) == 8 ) + { + if ( entryName.regionMatches( true, entryName.length() - 11, "MANIFEST.MF", 0, 11 ) ) + { + result = true; + } + } + } + return result; + } } Modified: maven/shared/trunk/maven-jarsigner/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-jarsigner/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java?rev=1553841&r1=1553840&r2=1553841&view=diff ============================================================================== --- maven/shared/trunk/maven-jarsigner/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java (original) +++ maven/shared/trunk/maven-jarsigner/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java Sat Dec 28 14:50:33 2013 @@ -23,6 +23,8 @@ import junit.framework.TestCase; import org.apache.maven.shared.utils.io.FileUtils; import java.io.File; +import java.util.jar.JarFile; +import java.util.jar.Manifest; /** * Created on 11/8/13. @@ -52,9 +54,28 @@ public class JarSignerUtilTest assertTrue( JarSignerUtil.isArchiveSigned( target ) ); + // check that manifest contains some digest attributes + JarFile originalJarFile = new JarFile( file ); + Manifest originalManifest = originalJarFile.getManifest(); + originalJarFile.close(); + + Manifest originalCleanManifest = JarSignerUtil.buildUnsignedManifest( originalManifest ); + assertFalse( originalManifest.equals( originalCleanManifest ) ); + assertTrue( originalCleanManifest.equals( JarSignerUtil.buildUnsignedManifest( originalCleanManifest ) ) ); + JarSignerUtil.unsignArchive( target ); assertFalse( JarSignerUtil.isArchiveSigned( target ) ); + // check that manifest has no digest entry + // see https://jira.codehaus.org/browse/MSHARED-314 + JarFile jarFile = new JarFile( target ); + Manifest manifest = jarFile.getManifest(); + jarFile.close(); + Manifest cleanManifest = JarSignerUtil.buildUnsignedManifest( manifest ); + assertTrue( manifest.equals( cleanManifest ) ); + assertTrue( manifest.equals( originalCleanManifest ) ); + + } }