Skip to content

Commit

Permalink
MSHARED-314 - Unsign jar still have some signatures in the manisfest
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/maven/shared/trunk@1553841 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
Tony Chemit committed Dec 28, 2013
1 parent d1796fb commit a1ef914
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 3 deletions.
76 changes: 73 additions & 3 deletions src/main/java/org/apache/maven/shared/jarsigner/JarSignerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -82,7 +85,7 @@ public static boolean isZipFile( final File file )
* 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
Expand All @@ -107,6 +110,18 @@ public static void unsignArchive( File jarFile )

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 );
}

Expand All @@ -121,12 +136,49 @@ public static void unsignArchive( File jarFile )

}

/**
* 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 )
Expand Down Expand Up @@ -183,7 +235,7 @@ public static boolean isArchiveSigned( final File jarFile )
* @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 ) )
Expand Down Expand Up @@ -212,4 +264,22 @@ else if ( entryName.regionMatches( true, entryName.length() - 3, ".EC", 0, 3 ) )
}
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -52,9 +54,28 @@ public void testUnsignArchive()

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 ) );


}
}

0 comments on commit a1ef914

Please sign in to comment.