blob: 1566a6e9c295abcf7361e6d4dc9e8d384979b9e2 [file] [log] [blame]
/*
* 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
};
}