MSHARED-314 - Unsign jar still have some signatures in the manisfest
git-svn-id: https://svn.apache.org/repos/asf/maven/shared/trunk@1553841 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java b/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java
index 9fc267c..f0b509e 100644
--- a/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java
+++ b/src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java
@@ -28,6 +28,9 @@
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 @@
* 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 @@
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 @@
}
/**
+ * 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 @@
* @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 @@
}
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;
+ }
}
diff --git a/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java b/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java
index 885e3c4..9e3b579 100644
--- a/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java
+++ b/src/test/java/org/apache/maven/shared/jarsigner/JarSignerUtilTest.java
@@ -23,6 +23,8 @@
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 @@
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 ) );
+
+
}
}