| /* |
| * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /** |
| * @test |
| * @bug 8218021 |
| * @summary Have jarsigner preserve posix permission attributes |
| * @modules jdk.jartool/sun.security.tools.jarsigner |
| * java.base/sun.security.tools.keytool |
| * @library /test/lib |
| * @run main/othervm PosixPermissionsTest |
| */ |
| |
| import java.net.URI; |
| import java.nio.file.*; |
| import java.nio.file.attribute.PosixFilePermissions; |
| import java.util.*; |
| |
| import jdk.test.lib.SecurityTools; |
| |
| public class PosixPermissionsTest { |
| |
| private final static int BYTES_PER_ROW = 8; |
| private final static String ZIPFILENAME = "8218021-test.zip"; |
| private final static String JARFILENAME = "8218021-test.jar"; |
| private final static URI ZIPURI = URI.create("jar:" + Path.of(ZIPFILENAME).toUri()); |
| private static final String WARNING_MSG = "POSIX file permission and/or symlink " + |
| "attributes detected. These attributes are ignored when signing and are not " + |
| "protected by the signature."; |
| |
| public static void main(String[] args) throws Exception { |
| // In JDK 11 we can't create a test zip file with POSIX permissions on the fly as its zipfs has no POSIX support. |
| // So we include the bytes of such a file in a static field. The file can be generated by calling main with an |
| // argument, using a JDK where zipfs supports POSIX. This will also print out the bytes. |
| if (args.length > 0) { |
| generateZipFileWithPosixAttributes(); |
| System.exit(0); |
| } |
| |
| createFiles(); |
| |
| SecurityTools.keytool( |
| "-genkey", |
| "-keyalg", "RSA", |
| "-dname", "CN=Coffey, OU=JPG, O=Oracle, L=Santa Clara, ST=California, C=US", |
| "-alias", "examplekey", |
| "-storepass", "password", |
| "-keypass", "password", |
| "-keystore", "examplekeystore", |
| "-validity", "365") |
| .shouldHaveExitValue(0); |
| |
| SecurityTools.jarsigner( |
| "-keystore", "examplekeystore", |
| "-verbose", ZIPFILENAME, |
| "-storepass", "password", |
| "-keypass", "password", |
| "examplekey") |
| .shouldHaveExitValue(0) |
| .shouldContain(WARNING_MSG); |
| |
| // sign jar file - no posix warning message expected |
| SecurityTools.jarsigner("-keystore", "examplekeystore", |
| "-verbose", JARFILENAME, |
| "-storepass", "password", |
| "-keypass", "password", |
| "examplekey") |
| .shouldHaveExitValue(0) |
| .shouldNotContain(WARNING_MSG); |
| |
| SecurityTools.jarsigner("-keystore", "examplekeystore", |
| "-storepass", "password", |
| "-keypass", "password", |
| "-verbose", |
| "-verify", ZIPFILENAME) |
| .shouldHaveExitValue(0) |
| .shouldContain(WARNING_MSG); |
| |
| // no warning expected for regular jar file |
| SecurityTools.jarsigner("-keystore", "examplekeystore", |
| "-storepass", "password", |
| "-keypass", "password", |
| "-verbose", |
| "-verify", JARFILENAME) |
| .shouldHaveExitValue(0) |
| .shouldNotContain(WARNING_MSG); |
| } |
| |
| private static void createFiles() throws Exception { |
| Files.write(Path.of(ZIPFILENAME), ZIPBYTES); |
| |
| // create jar file for testing |
| Path file = Path.of("f"); |
| Files.createFile(file); |
| SecurityTools.jar("cf " + JARFILENAME + " " + file); |
| } |
| |
| private static void generateZipFileWithPosixAttributes() throws Exception { |
| Map<String, String> env = new HashMap<>(); |
| env.put("create", "true"); |
| env.put("enablePosixFileAttributes", "true"); |
| |
| Path file = Path.of("f"); |
| Files.createFile(file); |
| |
| try (FileSystem zipfs = FileSystems.newFileSystem(ZIPURI, env)) { |
| Files.copy(file, |
| zipfs.getPath(file.toString()), |
| StandardCopyOption.COPY_ATTRIBUTES); |
| Files.setPosixFilePermissions(zipfs.getPath(file.toString()), |
| PosixFilePermissions.fromString("------r--")); |
| } |
| |
| System.out.println("Bytes of " + ZIPFILENAME + ":"); |
| System.out.println(createByteArray(Files.readAllBytes(Path.of(ZIPFILENAME)), "ZIPBYTES")); |
| } |
| |
| /** |
| * Utility method which takes an byte array and converts to byte array |
| * declaration. For example: |
| * <pre> |
| * {@code |
| * var fooJar = Files.readAllBytes(Path.of("foo.jar")); |
| * var result = createByteArray(fooJar, "FOOBYTES"); |
| * } |
| * </pre> |
| * @param bytes A byte array used to create a byte array declaration |
| * @param name Name to be used in the byte array declaration |
| * @return The formatted byte array declaration |
| */ |
| private static String createByteArray(byte[] bytes, String name) { |
| StringBuilder sb = new StringBuilder(); |
| try (Formatter fmt = new Formatter(sb)) { |
| fmt.format(" public final static byte[] %s = {", name); |
| for (int i = 0; i < bytes.length; i++) { |
| int mod = i % BYTES_PER_ROW; |
| if (mod == 0) { |
| fmt.format("%n "); |
| } else { |
| fmt.format(" "); |
| } |
| fmt.format("(byte)0x%02x", bytes[i]); |
| if (i != bytes.length - 1) { |
| fmt.format(","); |
| } |
| } |
| fmt.format("%n };%n"); |
| } |
| return sb.toString(); |
| } |
| |
| /* |
| * The byte array representation was generated using the createByteArray |
| * utility method with a higher JDK: |
| * $ <jdk15>/bin/java PosixPermissionsTest generate |
| */ |
| public final static byte[] ZIPBYTES = { |
| (byte)0x50, (byte)0x4b, (byte)0x03, (byte)0x04, (byte)0x14, (byte)0x00, (byte)0x08, (byte)0x08, |
| (byte)0x08, (byte)0x00, (byte)0x4b, (byte)0x9e, (byte)0x6a, (byte)0x51, (byte)0x00, (byte)0x00, |
| (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, |
| (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x24, (byte)0x00, (byte)0x66, (byte)0x0a, |
| (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, |
| (byte)0x00, (byte)0x18, (byte)0x00, (byte)0x40, (byte)0xdb, (byte)0xfb, (byte)0x57, (byte)0x92, |
| (byte)0xb7, (byte)0xd6, (byte)0x01, (byte)0x40, (byte)0xdb, (byte)0xfb, (byte)0x57, (byte)0x92, |
| (byte)0xb7, (byte)0xd6, (byte)0x01, (byte)0x40, (byte)0xdb, (byte)0xfb, (byte)0x57, (byte)0x92, |
| (byte)0xb7, (byte)0xd6, (byte)0x01, (byte)0x03, (byte)0x00, (byte)0x50, (byte)0x4b, (byte)0x07, |
| (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x00, |
| (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x50, (byte)0x4b, (byte)0x01, |
| (byte)0x02, (byte)0x14, (byte)0x03, (byte)0x14, (byte)0x00, (byte)0x08, (byte)0x08, (byte)0x08, |
| (byte)0x00, (byte)0x4b, (byte)0x9e, (byte)0x6a, (byte)0x51, (byte)0x00, (byte)0x00, (byte)0x00, |
| (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, |
| (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x24, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, |
| (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x00, |
| (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x66, (byte)0x0a, (byte)0x00, (byte)0x20, (byte)0x00, |
| (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x18, (byte)0x00, |
| (byte)0x40, (byte)0xdb, (byte)0xfb, (byte)0x57, (byte)0x92, (byte)0xb7, (byte)0xd6, (byte)0x01, |
| (byte)0x40, (byte)0xdb, (byte)0xfb, (byte)0x57, (byte)0x92, (byte)0xb7, (byte)0xd6, (byte)0x01, |
| (byte)0x40, (byte)0xdb, (byte)0xfb, (byte)0x57, (byte)0x92, (byte)0xb7, (byte)0xd6, (byte)0x01, |
| (byte)0x50, (byte)0x4b, (byte)0x05, (byte)0x06, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, |
| (byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x00, (byte)0x00, |
| (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 |
| }; |
| } |