Skip to content

Commit 376f20b

Browse files
Check services in legacy security providers
Legacy security providers do not use the more modern getService() and putService() methods, but rather other more map based methods. Further checks are added to restrict through RestrictedSecurity the registration and retrieval of services through legacy providers. Tests are, also, added to verify these checks. Signed-off-by: Kostas Tsiounis <kostas.tsiounis@ibm.com>
1 parent 5e141f3 commit 376f20b

3 files changed

Lines changed: 479 additions & 3 deletions

File tree

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
/*
2+
* ===========================================================================
3+
* (c) Copyright IBM Corp. 2026, 2026 All Rights Reserved
4+
* ===========================================================================
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* IBM designates this particular file as subject to the "Classpath" exception
11+
* as provided by IBM in the LICENSE file that accompanied this code.
12+
*
13+
* This code is distributed in the hope that it will be useful, but WITHOUT
14+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16+
* version 2 for more details (a copy is included in the LICENSE file that
17+
* accompanied this code).
18+
*
19+
* You should have received a copy of the GNU General Public License version
20+
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
21+
*
22+
* ===========================================================================
23+
*/
24+
25+
/*
26+
* @test
27+
* @summary Test Restricted Security Mode with Legacy Providers
28+
* @library /test/lib
29+
* @run junit TestConstraintsSuccess
30+
*/
31+
import org.junit.jupiter.api.Test;
32+
33+
import java.security.Provider;
34+
import java.security.Security;
35+
import java.util.Collection;
36+
import java.util.Enumeration;
37+
import java.util.List;
38+
import java.util.Map;
39+
import java.util.Set;
40+
41+
import jdk.test.lib.process.OutputAnalyzer;
42+
import jdk.test.lib.process.ProcessTools;
43+
44+
public class TestLegacyProviders {
45+
public static class LegacyProvider extends Provider {
46+
public LegacyProvider() {
47+
super("LegacyProvider", "1", "Test provider");
48+
put("Signature.Test", "example.class.MyClass");
49+
put("Signature.Test2", "example.class.MyClass2");
50+
put("Signature.Test3", "example.class.MyClass3");
51+
52+
putIfAbsent("Signature.Test4", "example.class.MyClass4");
53+
54+
replace("Signature.Test2", "example.class.MyClass2New");
55+
replace("Signature.Test2", "example.class.MyClass2New", "example.class.MyClass2");
56+
57+
replace("Signature.Test3", "example.class.MyClass3New");
58+
replace("Signature.Test3", "example.class.MyClass3", "example.class.MyClass3New");
59+
60+
merge("Signature.Test5", "example.class.MyClass5", (a,b) -> b);
61+
62+
}
63+
}
64+
65+
private static Provider legacyProvider;
66+
67+
private static void useLegacyPaths() throws RuntimeException {
68+
// Check get operation.
69+
String response = (String) legacyProvider.get("Signature.Test");
70+
if ((response == null) || !"example.class.MyClass".equals(response)) {
71+
throw new RuntimeException("Incorrect response for get()");
72+
}
73+
74+
response = (String) legacyProvider.get("Signature.Test2");
75+
if ((response == null) || !"example.class.MyClass2".equals(response)) {
76+
throw new RuntimeException("Incorrect response for get()");
77+
}
78+
79+
response = (String) legacyProvider.get("Signature.Test3");
80+
if (response != null) {
81+
throw new RuntimeException("Incorrect response for get()");
82+
}
83+
84+
response = (String) legacyProvider.get("Signature.Test4");
85+
if ((response == null) || !"example.class.MyClass4".equals(response)) {
86+
throw new RuntimeException("Incorrect response for get()");
87+
}
88+
89+
response = (String) legacyProvider.get("Signature.Test5");
90+
if ((response == null) || !"example.class.MyClass5".equals(response)) {
91+
throw new RuntimeException("Incorrect response for get()");
92+
}
93+
94+
95+
96+
String[] acceptedValues = {"example.class.MyClass",
97+
"example.class.MyClass2",
98+
"example.class.MyClass4",
99+
"example.class.MyClass5"};
100+
101+
102+
// Check entrySet operation.
103+
Set<Map.Entry<Object,Object>> es = legacyProvider.entrySet();
104+
System.out.println(es.toString());
105+
for (Map.Entry<Object,Object> entry : es) {
106+
String stringValue = (String) entry.getValue();
107+
boolean found = false;
108+
for (String acceptedValue : acceptedValues) {
109+
if (stringValue.equals(acceptedValue)) {
110+
found = true;
111+
break;
112+
}
113+
}
114+
if (!found) {
115+
throw new RuntimeException("Incorrect values returned from entrySet()");
116+
}
117+
}
118+
119+
// Check values operation.
120+
Collection<Object> values = legacyProvider.values();
121+
System.out.println(values.toString());
122+
for (Object value : values) {
123+
String stringValue = (String) value;
124+
boolean found = false;
125+
for (String acceptedValue : acceptedValues) {
126+
if (stringValue.equals(acceptedValue)
127+
|| "1".equals(stringValue) // Version from constructor
128+
|| "com.ibm.test.TestLegacy$LegacyProvider".equals(stringValue) // Classname from constructor
129+
|| "LegacyProvider".equals(stringValue) // Provider name from constructor
130+
|| "Test provider".equals(stringValue) // Info from constructor
131+
) {
132+
found = true;
133+
break;
134+
}
135+
}
136+
if (!found) {
137+
throw new RuntimeException("Incorrect values returned from values()");
138+
}
139+
}
140+
141+
// Check elements operation.
142+
Enumeration<Object> elements = legacyProvider.elements();
143+
while (elements.hasMoreElements()) {
144+
String stringElement = (String) elements.nextElement();
145+
boolean found = false;
146+
for (String acceptedValue : acceptedValues) {
147+
if (stringElement.equals(acceptedValue)) {
148+
found = true;
149+
break;
150+
}
151+
}
152+
if (!found) {
153+
throw new RuntimeException("Incorrect values returned from elements()");
154+
}
155+
}
156+
157+
158+
// Check getProperty operation.
159+
response = (String) legacyProvider.getProperty("Signature.Test");
160+
if ((response == null) || !"example.class.MyClass".equals(response)) {
161+
throw new RuntimeException("Incorrect response for getProperty()");
162+
}
163+
164+
response = (String) legacyProvider.getProperty("Signature.Test2");
165+
if ((response == null) || !"example.class.MyClass2".equals(response)) {
166+
throw new RuntimeException("Incorrect response for getProperty()");
167+
}
168+
169+
response = (String) legacyProvider.getProperty("Signature.Test3");
170+
if (response != null) {
171+
throw new RuntimeException("Incorrect response for getProperty()");
172+
}
173+
174+
response = (String) legacyProvider.getProperty("Signature.Test4");
175+
if ((response == null) || !"example.class.MyClass4".equals(response)) {
176+
throw new RuntimeException("Incorrect response for getProperty()");
177+
}
178+
179+
response = (String) legacyProvider.getProperty("Signature.Test5");
180+
if ((response == null) || !"example.class.MyClass5".equals(response)) {
181+
throw new RuntimeException("Incorrect response for getProperty()");
182+
}
183+
184+
185+
// Check compute operation.
186+
response = (String) legacyProvider.compute("Signature.Test", (a, b) -> (b + "New"));
187+
if ((response == null) || !"example.class.MyClassNew".equals(response)) {
188+
throw new RuntimeException("Incorrect response for compute()");
189+
}
190+
191+
response = (String) legacyProvider.compute("Signature.Test3", (a, b) -> (b + "New"));
192+
if (response != null) {
193+
throw new RuntimeException("Incorrect response for compute()");
194+
}
195+
196+
// Check computeIfAbsent operation.
197+
legacyProvider.remove("Signature.Test");
198+
response = (String) legacyProvider.computeIfAbsent("Signature.Test", a -> "example.class.MyClass");
199+
if ((response == null) || !"example.class.MyClass".equals(response)) {
200+
throw new RuntimeException("Incorrect response for computeIfAbsent()");
201+
}
202+
203+
response = (String) legacyProvider.computeIfAbsent("Signature.Test3", a -> "example.class.MyClass3");
204+
if (response != null) {
205+
throw new RuntimeException("Incorrect response for computeIfAbsent()");
206+
}
207+
208+
// Check computeIfPresent operation.
209+
response = (String) legacyProvider.computeIfPresent("Signature.Test", (a, b) -> (b + "New"));
210+
if ((response == null) || !"example.class.MyClassNew".equals(response)) {
211+
throw new RuntimeException("Incorrect response for computeIfPresent()");
212+
}
213+
214+
response = (String) legacyProvider.computeIfPresent("Signature.Test3", (a, b) -> (b + "New"));
215+
if (response != null) {
216+
throw new RuntimeException("Incorrect response for computeIfPresent()");
217+
}
218+
219+
String[] acceptedKeys = {"Signature.Test",
220+
"Signature.Test2",
221+
"Signature.Test4",
222+
"Signature.Test5"};
223+
224+
// Check keys operation.
225+
Enumeration<Object> keys = legacyProvider.keys();
226+
while (keys.hasMoreElements()) {
227+
String stringKey = (String) keys.nextElement();
228+
boolean found = false;
229+
for (String acceptedKey : acceptedKeys) {
230+
if (stringKey.equals(acceptedKey)
231+
|| "Provider.id version".equals(stringKey) // Version from constructor
232+
|| "Provider.id className".equals(stringKey) // Provider classname from constructor
233+
|| "Provider.id info".equals(stringKey) // Info from constructor
234+
|| "Provider.id name".equals(stringKey) // Provider name from constructor
235+
) {
236+
found = true;
237+
break;
238+
}
239+
}
240+
if (!found) {
241+
throw new RuntimeException("Incorrect values returned from keys()");
242+
}
243+
}
244+
}
245+
246+
@Test
247+
public void runWithConstraints() throws RuntimeException {
248+
OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava(
249+
"-Dsemeru.customprofile=TestLegacy.Version",
250+
"-Djava.security.properties=" + System.getProperty("test.src") + "/legacy-java.security",
251+
"TestLegacyProviders"
252+
);
253+
outputAnalyzer.reportDiagnosticSummary();
254+
outputAnalyzer.shouldHaveExitValue(0);
255+
}
256+
257+
public static void main(String[] args) throws RuntimeException {
258+
Security.getProviders();
259+
Security.addProvider(new LegacyProvider());
260+
legacyProvider = Security.getProvider("LegacyProvider");
261+
useLegacyPaths();
262+
}
263+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# ===========================================================================
2+
# (c) Copyright IBM Corp. 2026, 2026 All Rights Reserved
3+
# ===========================================================================
4+
# This code is free software; you can redistribute it and/or modify it
5+
# under the terms of the GNU General Public License version 2 only, as
6+
# published by the Free Software Foundation.
7+
#
8+
# IBM designates this particular file as subject to the "Classpath" exception
9+
# as provided by IBM in the LICENSE file that accompanied this code.
10+
#
11+
# This code is distributed in the hope that it will be useful, but WITHOUT
12+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
# version 2 for more details (a copy is included in the LICENSE file that
15+
# accompanied this code).
16+
#
17+
# You should have received a copy of the GNU General Public License version
18+
# 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
19+
# ===========================================================================
20+
21+
RestrictedSecurity.TestLegacy.Version.desc.name = Test legacy profile
22+
RestrictedSecurity.TestLegacy.Version.desc.default = true
23+
RestrictedSecurity.TestLegacy.Version.desc.fips = false
24+
RestrictedSecurity.TestLegacy.Version.desc.hash = SHA256:31587712450e410300bb21c1bd60327e85adbd404d980428a6d6064938545e1f
25+
RestrictedSecurity.TestLegacy.Version.jce.provider.1 = com.ibm.test.TestLegacy$LegacyProvider [ \
26+
{Signature, Test, *}, \
27+
{Signature, Test2, *, FullClassName:com.ibm.test.TestLegacy}, \
28+
{Signature, Test4, *, FullClassName:com.ibm.test.TestLegacy}, \
29+
{Signature, Test5, *, FullClassName:com.ibm.test.TestLegacy}]
30+
RestrictedSecurity.TestLegacy.Version.jce.provider.2 = sun.security.provider.Sun [{MessageDigest, SHA-256, *}]
31+
RestrictedSecurity.TestLegacy.Version.securerandom.provider = SUN
32+
RestrictedSecurity.TestLegacy.Version.securerandom.algorithm = SHA512DRBG

0 commit comments

Comments
 (0)