From f8d44e0458e7be47de1c6513b3f6fa555ee98cde Mon Sep 17 00:00:00 2001 From: Laurent Goujon Date: Tue, 7 May 2024 21:47:55 -0700 Subject: [PATCH] Fix modular jar final permissions (#333) * Fix modular jar final permissions When a new modular jar file is generated with maven-jar-plugin with Java 11, the final permissions of the file are restricted to the current user instead of using the environment umask which usually allows for group and other users to access the file as well. This is caused by the use of Files#createTempFile() which has a restrictive file permission model for security reason but as the temporary file is generated next to the original jar file, and there's no sensitive reason to restrict its access, the restrictive file permission should not be needed. Instead of relying on current umask property, read mjar permissions and provide it to Files#createTempFile(...) * Clean temporary file if an error occurs * Do not follow symlink when reading jar attributes --- .../jar/JarToolModularJarArchiver.java | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.java b/src/main/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.java index b936ed318..93c95a51c 100644 --- a/src/main/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.java @@ -23,9 +23,14 @@ import java.io.PrintStream; import java.lang.reflect.Method; import java.nio.file.Files; +import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFileAttributes; +import java.nio.file.attribute.PosixFilePermissions; import java.util.ArrayList; import java.util.Calendar; import java.util.Enumeration; @@ -147,23 +152,43 @@ protected void postCreateArchive() throws ArchiverException { private void fixLastModifiedTimeZipEntries() throws IOException { long timeMillis = getLastModifiedTime().toMillis(); Path destFile = getDestFile().toPath(); - Path tmpZip = Files.createTempFile(destFile.getParent(), null, null); - try (ZipFile zipFile = new ZipFile(getDestFile()); - ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(tmpZip))) { - Enumeration entries = zipFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - // Not using setLastModifiedTime(FileTime) as it sets the extended timestamp - // which is not compatible with the jar tool output. - entry.setTime(timeMillis); - out.putNextEntry(entry); - if (!entry.isDirectory()) { - IOUtil.copy(zipFile.getInputStream(entry), out); + PosixFileAttributes posixFileAttributes = Files.getFileAttributeView( + destFile, PosixFileAttributeView.class, LinkOption.NOFOLLOW_LINKS) + .readAttributes(); + FileAttribute[] attributes; + if (posixFileAttributes != null) { + attributes = new FileAttribute[1]; + attributes[0] = PosixFilePermissions.asFileAttribute(posixFileAttributes.permissions()); + } else { + attributes = new FileAttribute[0]; + } + Path tmpZip = Files.createTempFile(destFile.getParent(), null, null, attributes); + try { + try (ZipFile zipFile = new ZipFile(getDestFile()); + ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(tmpZip))) { + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + // Not using setLastModifiedTime(FileTime) as it sets the extended timestamp + // which is not compatible with the jar tool output. + entry.setTime(timeMillis); + out.putNextEntry(entry); + if (!entry.isDirectory()) { + IOUtil.copy(zipFile.getInputStream(entry), out); + } + out.closeEntry(); } - out.closeEntry(); } + Files.move(tmpZip, destFile, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + // Clean up temporary file if an error occurs + try { + Files.delete(tmpZip); + } catch (IOException ioe) { + e.addSuppressed(ioe); + } + throw e; } - Files.move(tmpZip, destFile, StandardCopyOption.REPLACE_EXISTING); } /**