Skip to content

Commit f7275f8

Browse files
authored
Switch XML Security CryptoLoader to use URIResolver (#3280)
1 parent 4d64e04 commit f7275f8

3 files changed

Lines changed: 87 additions & 4 deletions

File tree

core/src/main/java/org/apache/cxf/resource/URIResolver.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,10 @@ private void tryRemote(String uriStr) throws IOException {
450450
}
451451
}
452452

453-
private static void checkAllowedScheme(URL targetUrl) throws IOException {
453+
/**
454+
* Verifies that the URL scheme is permitted by URIResolver allowlist policy.
455+
*/
456+
public static void checkAllowedScheme(URL targetUrl) throws IOException {
454457
String scheme = targetUrl.getProtocol();
455458
if (scheme == null) {
456459
return;

rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.cxf.endpoint.Endpoint;
3030
import org.apache.cxf.helpers.CastUtils;
3131
import org.apache.cxf.message.Message;
32+
import org.apache.cxf.resource.URIResolver;
3233
import org.apache.cxf.service.model.EndpointInfo;
3334
import org.apache.wss4j.common.crypto.Crypto;
3435
import org.apache.wss4j.common.crypto.CryptoFactory;
@@ -85,10 +86,11 @@ public Crypto getCrypto(Message message,
8586
}
8687

8788
public static Crypto loadCryptoFromURL(URL url) throws IOException, WSSecurityException {
89+
URIResolver.checkAllowedScheme(url);
8890
Properties props = new Properties();
89-
InputStream in = url.openStream();
90-
props.load(in);
91-
in.close();
91+
try (InputStream in = url.openStream()) {
92+
props.load(in);
93+
}
9294
return CryptoFactory.getInstance(props);
9395
}
9496

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.cxf.rs.security.common;
21+
22+
import java.io.File;
23+
import java.io.FileOutputStream;
24+
import java.io.IOException;
25+
import java.net.URL;
26+
import java.nio.charset.StandardCharsets;
27+
28+
import org.apache.wss4j.common.crypto.Crypto;
29+
import org.apache.wss4j.common.ext.WSSecurityException;
30+
31+
import org.junit.Test;
32+
33+
import static org.junit.Assert.assertNotNull;
34+
import static org.junit.Assert.assertTrue;
35+
import static org.junit.Assert.fail;
36+
37+
public class CryptoLoaderTest {
38+
39+
@Test
40+
public void testDisallowedSchemeRejected() throws Exception {
41+
URL url = new URL("ftp://example.com/crypto.properties");
42+
43+
try {
44+
CryptoLoader.loadCryptoFromURL(url);
45+
fail("Expected IOException for disallowed scheme");
46+
} catch (IOException ex) {
47+
assertTrue(ex.getMessage().contains("not permitted for URIResolver"));
48+
}
49+
}
50+
51+
@Test
52+
public void testAllowedFileSchemeLoadsCrypto() throws Exception {
53+
File tmp = File.createTempFile("cxf-crypto", ".properties");
54+
tmp.deleteOnExit();
55+
56+
String props = "org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin\n"
57+
+ "org.apache.wss4j.crypto.merlin.keystore.type=jks\n";
58+
59+
try (FileOutputStream out = new FileOutputStream(tmp)) {
60+
out.write(props.getBytes(StandardCharsets.UTF_8));
61+
}
62+
63+
Crypto crypto = CryptoLoader.loadCryptoFromURL(tmp.toURI().toURL());
64+
assertNotNull(crypto);
65+
}
66+
67+
@Test(expected = WSSecurityException.class)
68+
public void testAllowedFileSchemeWithBadPropertiesFailsInCryptoFactory() throws Exception {
69+
File tmp = File.createTempFile("cxf-crypto-invalid", ".properties");
70+
tmp.deleteOnExit();
71+
72+
try (FileOutputStream out = new FileOutputStream(tmp)) {
73+
out.write("org.apache.wss4j.crypto.provider=bad.Provider\n".getBytes(StandardCharsets.UTF_8));
74+
}
75+
76+
CryptoLoader.loadCryptoFromURL(tmp.toURI().toURL());
77+
}
78+
}

0 commit comments

Comments
 (0)