Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/sun/security/tools/jarsigner/EntriesOrder.java
41152 views
1
/*
2
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/**
25
* @test
26
* @bug 8031572
27
* @summary jarsigner -verify exits with 0 when a jar file is not properly signed
28
* @modules java.base/sun.security.tools.keytool
29
* jdk.jartool/sun.security.tools.jarsigner
30
* jdk.jartool/sun.tools.jar
31
* @run main EntriesOrder
32
*/
33
34
import java.io.FileInputStream;
35
import java.io.FileOutputStream;
36
import java.nio.file.Files;
37
import java.nio.file.Paths;
38
import java.security.cert.Certificate;
39
import java.util.*;
40
import java.util.jar.JarEntry;
41
import java.util.jar.JarFile;
42
import java.util.jar.JarInputStream;
43
import java.util.zip.ZipEntry;
44
import java.util.zip.ZipOutputStream;
45
46
public class EntriesOrder {
47
48
public static void main(String[] args) throws Exception {
49
50
String[] entries = {
51
"META-INF/",
52
"META-INF/MANIFEST.MF",
53
"META-INF/A.RSA",
54
"META-INF/A.SF",
55
"META-INF/inf",
56
"a"};
57
58
Map<String,byte[]> content = new HashMap<>();
59
60
// We will create a jar containing entries above. Try all permutations
61
// and confirm 1) When opened as a JarFile, we can always get 3 signed
62
// ones (MANIFEST, inf, a), and 2) When opened as a JarInputStream,
63
// when the order is correct (MANIFEST at beginning, followed by RSA/SF,
64
// directory ignored), we can get 2 signed ones (inf, a).
65
66
// Prepares raw files
67
Files.write(Paths.get("a"), List.of("a"));
68
Files.createDirectory(Paths.get("META-INF/"));
69
Files.write(Paths.get("META-INF/inf"), List.of("inf"));
70
71
// Pack, sign, and extract to get all files
72
sun.tools.jar.Main m =
73
new sun.tools.jar.Main(System.out, System.err, "jar");
74
if (!m.run("cvf a.jar a META-INF/inf".split(" "))) {
75
throw new Exception("jar creation failed");
76
}
77
sun.security.tools.keytool.Main.main(
78
("-keystore jks -storepass changeit -keypass changeit -dname" +
79
" CN=A -alias a -genkeypair -keyalg rsa").split(" "));
80
sun.security.tools.jarsigner.Main.main(
81
"-keystore jks -storepass changeit a.jar a".split(" "));
82
m = new sun.tools.jar.Main(System.out, System.err, "jar");
83
if (!m.run("xvf a.jar".split(" "))) {
84
throw new Exception("jar extraction failed");
85
}
86
87
// Data
88
for (String s: entries) {
89
if (!s.endsWith("/")) {
90
content.put(s, Files.readAllBytes(Paths.get(s)));
91
}
92
}
93
94
// Test
95
for (List<String> perm: Permute(entries)) {
96
97
// Recreate a jar
98
try (ZipOutputStream zos
99
= new ZipOutputStream(new FileOutputStream("x.jar"))) {
100
for (String e: perm) {
101
zos.putNextEntry(new ZipEntry(e));
102
if (Paths.get(e).toFile().isDirectory()) continue;
103
zos.write(content.get(e));
104
}
105
}
106
107
// Open with JarFile, number of signed entries should be 3.
108
int cc = 0;
109
try (JarFile jf = new JarFile("x.jar")) {
110
Enumeration<JarEntry> jes = jf.entries();
111
while (jes.hasMoreElements()) {
112
JarEntry je = jes.nextElement();
113
jf.getInputStream(je).readAllBytes();
114
Certificate[] certs = je.getCertificates();
115
if (certs != null && certs.length > 0) {
116
cc++;
117
}
118
}
119
}
120
121
if (cc != 3) {
122
System.out.println(perm + " - jf - " + cc);
123
throw new Exception();
124
}
125
126
// Open with JarInputStream
127
int signed;
128
129
perm.remove("META-INF/");
130
if (perm.get(0).equals("META-INF/MANIFEST.MF") &&
131
perm.get(1).contains("/A.") &&
132
perm.get(2).contains("/A.")) {
133
signed = 2; // Good order
134
} else {
135
signed = 0; // Bad order. In this case, the number of signed
136
// entries is not documented. Just test impl.
137
}
138
139
cc = 0;
140
try (JarInputStream jis
141
= new JarInputStream(new FileInputStream("x.jar"))) {
142
while (true) {
143
JarEntry je = jis.getNextJarEntry();
144
if (je == null) break;
145
jis.readAllBytes();
146
Certificate[] certs = je.getCertificates();
147
if (certs != null && certs.length > 0) {
148
cc++;
149
}
150
}
151
}
152
153
if (cc != signed) {
154
System.out.println(perm + " - jis - " + cc + " " + signed);
155
throw new Exception();
156
}
157
}
158
}
159
160
// Helper method to return all permutations of an array. Each output can
161
// be altered without damaging the iteration process.
162
static Iterable<List<String>> Permute(String[] entries) {
163
return new Iterable<List<String>>() {
164
165
int s = entries.length;
166
long c = factorial(s) - 1; // number of permutations
167
168
private long factorial(int n) {
169
return (n == 1) ? 1: (n * factorial(n-1));
170
}
171
172
@Override
173
public Iterator<List<String>> iterator() {
174
return new Iterator<List<String>>() {
175
@Override
176
public boolean hasNext() {
177
return c >= 0;
178
}
179
180
@Override
181
public List<String> next() {
182
if (c < 0) return null;
183
List<String> result = new ArrayList<>(s);
184
LinkedList<String> source = new LinkedList<>(
185
Arrays.asList(entries));
186
// Treat c as a integer with different radixes at
187
// different digits, i.e. at digit 0, radix is s;
188
// at digit 1, radix is s-1. Thus a s-digit number
189
// is able to represent s! different values.
190
long n = c;
191
for (int i=s; i>=1; i--) {
192
int x = (int)(n % i);
193
result.add(source.remove(x));
194
n = n / i;
195
}
196
c--;
197
return result;
198
}
199
};
200
}
201
};
202
}
203
}
204
205