From 481a9c2142cc07875dba9c6b88ea8d74c79b5d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Boutemy?= Date: Wed, 12 Jul 2023 09:37:59 +0200 Subject: [PATCH] detect permissions for addFile --- .../plexus/archiver/AbstractArchiver.java | 20 +++++++- .../plexus/archiver/jar/JarArchiverTest.java | 46 ++++++++++++++++++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java index 65ca26220..217212ba4 100755 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java @@ -40,6 +40,7 @@ import org.codehaus.plexus.archiver.manager.ArchiverManager; import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; +import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributeUtils; import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributes; import org.codehaus.plexus.components.io.attributes.SimpleResourceAttributes; import org.codehaus.plexus.components.io.functions.ResourceAttributeSupplier; @@ -364,9 +365,20 @@ public void addFileSet(@Nonnull final FileSet fileSet) throws ArchiverException @Override public void addFile(@Nonnull final File inputFile, @Nonnull final String destFileName) throws ArchiverException { - final int fileMode = getOverrideFileMode(); + int permissions; + if (forcedFileMode > 0) { + permissions = forcedFileMode; + } else { + permissions = PlexusIoResourceAttributes.UNKNOWN_OCTAL_MODE; + try { + permissions = PlexusIoResourceAttributeUtils.getFileAttributes(inputFile) + .getOctalMode(); + } catch (IOException ioe) { + // ignore + } + } - addFile(inputFile, destFileName, fileMode); + addFile(inputFile, destFileName, permissions); } @Override @@ -462,6 +474,10 @@ public void addFile(@Nonnull final File inputFile, @Nonnull String destFileName, permissions = getOverrideFileMode(); } + if (umask > 0 && permissions != PlexusIoResourceAttributes.UNKNOWN_OCTAL_MODE) { + permissions &= ~umask; + } + try { // do a null check here, to avoid creating a file stream if there are no filters... ArchiveEntry entry = ArchiveEntry.createFileEntry(destFileName, inputFile, permissions, getDirectoryMode()); diff --git a/src/test/java/org/codehaus/plexus/archiver/jar/JarArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/jar/JarArchiverTest.java index b98210928..61dc2bbd7 100644 --- a/src/test/java/org/codehaus/plexus/archiver/jar/JarArchiverTest.java +++ b/src/test/java/org/codehaus/plexus/archiver/jar/JarArchiverTest.java @@ -14,6 +14,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.codehaus.plexus.archiver.ArchiverException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -123,14 +124,16 @@ private void createReproducibleBuild(String timeZoneId) throws IOException, Mani JarArchiver archiver = getJarArchiver(); archiver.setDestFile(jarFile.toFile()); - archiver.addConfiguredManifest(manifest); - archiver.addDirectory(new File("src/test/resources/java-classes")); SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); long parsedTime = isoFormat.parse("2038-01-19T03:14:08Z").getTime(); FileTime lastModTime = FileTime.fromMillis(parsedTime); archiver.configureReproducibleBuild(lastModTime); + + archiver.addConfiguredManifest(manifest); + archiver.addDirectory(new File("src/test/resources/java-classes")); + archiver.createArchive(); // zip 2 seconds precision, normalized to UTC @@ -148,6 +151,45 @@ private void createReproducibleBuild(String timeZoneId) throws IOException, Mani } } + /** + * Check group not writable for reproducible archive. + * + * @throws IOException + * @throws ParseException + */ + @Test + public void testReproducibleUmask() throws IOException, ParseException { + Path jarFile = Files.createTempFile(tempDir, "JarArchiverTest-umask", ".jar"); + + JarArchiver archiver = getJarArchiver(); + archiver.setDestFile(jarFile.toFile()); + + SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + long parsedTime = isoFormat.parse("2038-01-19T03:14:08Z").getTime(); + FileTime lastModTime = FileTime.fromMillis(parsedTime); + + archiver.configureReproducibleBuild(lastModTime); + + archiver.addDirectory(new File("src/test/resources/java-classes")); + archiver.addFile(new File("src/test/resources/world-writable/foo.txt"), "addFile.txt"); + + archiver.createArchive(); + + try (org.apache.commons.compress.archivers.zip.ZipFile zip = + new org.apache.commons.compress.archivers.zip.ZipFile(jarFile.toFile())) { + Enumeration entries = zip.getEntries(); + while (entries.hasMoreElements()) { + ZipArchiveEntry entry = entries.nextElement(); + int mode = entry.getUnixMode(); + assertEquals( + 0, + mode & 0_020, + entry.getName() + " group should not be writable in reproducible mode: " + + Integer.toOctalString(mode)); + } + } + } + @Override protected JarArchiver getJarArchiver() { return new JarArchiver();