Skip to content

Commit 896d2c1

Browse files
authored
Merge pull request #84 from cip4/sec1
added whitelist to resource handler
2 parents efe2e40 + f499763 commit 896d2c1

File tree

4 files changed

+150
-67
lines changed

4 files changed

+150
-67
lines changed

src/main/java/org/cip4/jdfutility/server/JettyServer.java

Lines changed: 14 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import org.apache.commons.logging.Log;
5353
import org.apache.commons.logging.LogFactory;
5454
import org.cip4.jdflib.util.FileUtil;
55-
import org.cip4.jdflib.util.StringUtil;
5655
import org.eclipse.jetty.http.HttpVersion;
5756
import org.eclipse.jetty.server.HttpConfiguration;
5857
import org.eclipse.jetty.server.HttpConnectionFactory;
@@ -68,7 +67,6 @@
6867
import org.eclipse.jetty.server.handler.RequestLogHandler;
6968
import org.eclipse.jetty.server.handler.ResourceHandler;
7069
import org.eclipse.jetty.servlet.ServletContextHandler;
71-
import org.eclipse.jetty.util.resource.Resource;
7270
import org.eclipse.jetty.util.ssl.SslContextFactory;
7371

7472
/**
@@ -95,7 +93,7 @@ public String getKeystoreType()
9593
return keystoreType;
9694
}
9795

98-
public void setKeystoreType(String keystoretype)
96+
public void setKeystoreType(final String keystoretype)
9997
{
10098
this.keystoreType = keystoretype;
10199
}
@@ -117,7 +115,7 @@ public String getPassword()
117115
return password;
118116
}
119117

120-
public void setPassword(String password)
118+
public void setPassword(final String password)
121119
{
122120
this.password = password;
123121
}
@@ -132,7 +130,7 @@ public boolean isAllowFlakySSL()
132130
*
133131
* @param allowFlakySSL
134132
*/
135-
public void setAllowFlakySSL(boolean allowFlakySSL)
133+
public void setAllowFlakySSL(final boolean allowFlakySSL)
136134
{
137135
this.allowFlakySSL = allowFlakySSL;
138136
}
@@ -158,12 +156,12 @@ KeyStore getKeystore()
158156
try
159157
{
160158
log.info("Reading " + f.getAbsolutePath());
161-
BufferedInputStream bufferedInputStream = FileUtil.getBufferedInputStream(f);
159+
final BufferedInputStream bufferedInputStream = FileUtil.getBufferedInputStream(f);
162160
keyStore.load(bufferedInputStream, password.toCharArray());
163161
bufferedInputStream.close();
164162
return keyStore;
165163
}
166-
catch (Exception e)
164+
catch (final Exception e)
167165
{
168166
log.warn("Cannot load keystore at: " + f.getAbsolutePath(), e);
169167
}
@@ -180,7 +178,7 @@ public String getKeystorePath()
180178
return keystorePath;
181179
}
182180

183-
public void setKeystorePath(String keystorePath)
181+
public void setKeystorePath(final String keystorePath)
184182
{
185183
this.keystorePath = keystorePath;
186184
}
@@ -269,7 +267,7 @@ public void setSSLPort(final int port)
269267
* @return may be used for additional setup
270268
*/
271269
@Deprecated
272-
public void setSSLPort(final int port, String dummy)
270+
public void setSSLPort(final int port, final String dummy)
273271
{
274272
sslPort = port;
275273
}
@@ -328,13 +326,13 @@ protected void updateHTTP()
328326

329327
final HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
330328

331-
SecureRequestCustomizer customizer = getRequestCustomizer();
329+
final SecureRequestCustomizer customizer = getRequestCustomizer();
332330
customizer.setSniHostCheck(!sslData.allowFlakySSL);
333331
customizer.setSniRequired(!sslData.allowFlakySSL);
334332
customizer.setStsIncludeSubDomains(sslData.allowFlakySSL);
335333
httpsConfig.addCustomizer(customizer);
336334

337-
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
335+
final SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
338336
sslContextFactory.setKeyStore(sslData.getKeystore());
339337
sslContextFactory.setKeyStorePassword(sslData.getPassword());
340338

@@ -350,7 +348,7 @@ protected void updateHTTP()
350348
{
351349
log.info("Updating standard port to: " + thePort);
352350
final HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory(httpConfig);
353-
ServerConnector connector = new ServerConnector(server, httpConnectionFactory);
351+
final ServerConnector connector = new ServerConnector(server, httpConnectionFactory);
354352
connector.setPort(thePort);
355353
server.addConnector(connector);
356354
}
@@ -443,7 +441,7 @@ protected RequestLog createRequestLog()
443441
*
444442
* @return
445443
*/
446-
public String getBaseURL(boolean ssl)
444+
public String getBaseURL(final boolean ssl)
447445
{
448446
try
449447
{
@@ -466,59 +464,13 @@ public String getBaseURL(boolean ssl)
466464
*/
467465
public String getBaseURL()
468466
{
469-
String http = getBaseURL(false);
470-
String ssl = getBaseURL(true);
467+
final String http = getBaseURL(false);
468+
final String ssl = getBaseURL(true);
471469
if (http == null)
472470
return ssl;
473471
return http;
474472
}
475473

476-
/**
477-
* simple resource (file) handler that tweeks the url to match the context, thus allowing servlets to emulate a war file without actually requiring the war file
478-
*
479-
* @author rainer prosi
480-
* @date Dec 10, 2010
481-
*/
482-
public class MyResourceHandler extends ResourceHandler
483-
{
484-
485-
public MyResourceHandler(final String strip)
486-
{
487-
super();
488-
this.strip = StringUtil.getNonEmpty(strip);
489-
}
490-
491-
private final String strip;
492-
493-
@Override
494-
public Resource getResource(String url)
495-
{
496-
497-
if (strip != null && url.startsWith(strip) && (url.length() == strip.length() || url.charAt(strip.length()) == '/'))
498-
{
499-
url = url.substring(strip.length());
500-
}
501-
try
502-
{
503-
if ("".equals(url) || "/".equals(url))
504-
{
505-
return super.getResource(getHome());
506-
}
507-
return super.getResource(url);
508-
}
509-
catch (Exception x)
510-
{
511-
return null;
512-
}
513-
}
514-
515-
@Override
516-
public String toString()
517-
{
518-
return "MyResourceHandler [strip=" + strip + ", getResourceBase()=" + getResourceBase() + "]";
519-
}
520-
}
521-
522474
/**
523475
* @author rainer prosi
524476
*/
@@ -542,7 +494,7 @@ public void handle(final String pathInContext, final Request arg1, final HttpSer
542494
*/
543495
protected ResourceHandler createResourceHandler()
544496
{
545-
final ResourceHandler resourceHandler = new MyResourceHandler(context);
497+
final ResourceHandler resourceHandler = new MyResourceHandler(context, getHome());
546498
resourceHandler.setResourceBase(".");
547499
return resourceHandler;
548500
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/**
2+
* The CIP4 Software License, Version 1.0
3+
*
4+
* Copyright (c) 2001-2024 The International Cooperation for the Integration of Processes in Prepress, Press and Postpress (CIP4). All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9+
*
10+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the
11+
* distribution.
12+
*
13+
* 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the The International Cooperation for
14+
* the Integration of Processes in Prepress, Press and Postpress (www.cip4.org)" Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments
15+
* normally appear.
16+
*
17+
* 4. The names "CIP4" and "The International Cooperation for the Integration of Processes in Prepress, Press and Postpress" must not be used to endorse or promote products derived from this software
18+
* without prior written permission. For written permission, please contact [email protected].
19+
*
20+
* 5. Products derived from this software may not be called "CIP4", nor may "CIP4" appear in their name, without prior written permission of the CIP4 organization
21+
*
22+
* Usage of this software in commercial products is subject to restrictions. For details please consult [email protected].
23+
*
24+
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25+
* DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COOPERATION FOR THE INTEGRATION OF PROCESSES IN PREPRESS, PRESS AND POSTPRESS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28+
* OF SUCH DAMAGE. ====================================================================
29+
*
30+
* This software consists of voluntary contributions made by many individuals on behalf of the The International Cooperation for the Integration of Processes in Prepress, Press and Postpress and was
31+
* originally based on software copyright (c) 1999-2001, Heidelberger Druckmaschinen AG copyright (c) 1999-2001, Agfa-Gevaert N.V.
32+
*
33+
* For more information on The International Cooperation for the Integration of Processes in Prepress, Press and Postpress , please see <http://www.cip4.org/>.
34+
*
35+
*
36+
*/
37+
38+
package org.cip4.jdfutility.server;
39+
40+
import java.io.File;
41+
import java.util.ArrayList;
42+
import java.util.Collection;
43+
44+
import org.cip4.jdflib.util.StringUtil;
45+
import org.eclipse.jetty.server.handler.ResourceHandler;
46+
import org.eclipse.jetty.util.resource.Resource;
47+
48+
/**
49+
* simple resource (file) handler that tweeks the url to match the context, thus allowing servlets to emulate a war file without actually requiring the war file
50+
*
51+
* @author rainer prosi
52+
* @date Dec 10, 2010
53+
*/
54+
public class MyResourceHandler extends ResourceHandler
55+
{
56+
57+
private final String home;
58+
private final Collection<File> whiteList;
59+
60+
public MyResourceHandler(final String strip, final String home)
61+
{
62+
super();
63+
this.strip = StringUtil.getNonEmpty(strip);
64+
this.home = home;
65+
whiteList = new ArrayList<>();
66+
}
67+
68+
private final String strip;
69+
70+
@Override
71+
public Resource getResource(String url)
72+
{
73+
74+
if (strip != null && url.startsWith(strip) && (url.length() == strip.length() || url.charAt(strip.length()) == '/'))
75+
{
76+
url = url.substring(strip.length());
77+
}
78+
try
79+
{
80+
if ("".equals(url) || "/".equals(url))
81+
{
82+
return super.getResource(home);
83+
}
84+
else if (!whiteList.isEmpty())
85+
{
86+
final String base = StringUtil.token(url, 0, "/");
87+
if (!whiteList.contains(new File(base)))
88+
{
89+
return null;
90+
}
91+
}
92+
93+
return super.getResource(url);
94+
}
95+
catch (final Exception x)
96+
{
97+
return null;
98+
}
99+
}
100+
101+
/**
102+
* add a base file to the whitelist. after adding one, all others are blocked
103+
*
104+
* @param base
105+
*/
106+
public void addBase(final String base)
107+
{
108+
whiteList.add(new File(base));
109+
}
110+
111+
@Override
112+
public String toString()
113+
{
114+
return "MyResourceHandler [strip=" + strip + ", getResourceBase()=" + getResourceBase() + "]";
115+
}
116+
}

src/test/java/org/cip4/jdfutility/schema/JDFSchemaUtilTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ public void testschema()
9595
final File f19 = new File(sm_dirTestDataTemp + "tmp/schema/1.9/JDF.xsd");
9696
final File f19a = JDFSchemaUtil.downloadschema(f19, EnumVersion.Version_1_9, 123456);
9797
assertTrue(f19a.exists());
98+
final File f20 = new File(sm_dirTestDataTemp + "tmp/schema/2.0/xjdf.xsd");
99+
final File f20a = JDFSchemaUtil.downloadschema(f20, EnumVersion.Version_2_0, 123456);
100+
assertTrue(f20a.exists());
98101
final File f21 = new File(sm_dirTestDataTemp + "tmp/schema/2.1/xjdf.xsd");
99102
final File f21a = JDFSchemaUtil.downloadschema(f21, EnumVersion.Version_2_1, 123456);
100103
assertTrue(f21a.exists());
@@ -109,6 +112,8 @@ public void testschema()
109112
final File f12a = JDFSchemaUtil.downloadschema(f12, EnumVersion.Version_1_2, 123456);
110113
final File f19 = new File(sm_dirTestDataTemp + "tmp/schema/1.9/JDF.xsd");
111114
final File f19a = JDFSchemaUtil.downloadschema(f19, EnumVersion.Version_1_9, 123456);
115+
final File f20 = new File(sm_dirTestDataTemp + "tmp/schema/2.0/xjdf.xsd");
116+
final File f20a = JDFSchemaUtil.downloadschema(f20, EnumVersion.Version_2_0, 123456);
112117
final File f21 = new File(sm_dirTestDataTemp + "tmp/schema/2.1/xjdf.xsd");
113118
final File f21a = JDFSchemaUtil.downloadschema(f21, EnumVersion.Version_2_1, 123456);
114119
final File f22 = new File(sm_dirTestDataTemp + "tmp/schema/2.2/xjdf.xsd");

src/test/java/org/cip4/jdfutility/server/JettyServerTest.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import org.cip4.jdfutility.JDFUtilityTestBase;
4747
import org.cip4.jdfutility.exe.HTTPDump;
4848
import org.cip4.jdfutility.server.JettyServer.JettySSLData;
49-
import org.cip4.jdfutility.server.JettyServer.MyResourceHandler;
5049
import org.junit.jupiter.api.Test;
5150

5251
public class JettyServerTest extends JDFUtilityTestBase
@@ -106,7 +105,7 @@ public synchronized void testSSLData()
106105
{
107106
final HTTPDump ns = new HTTPDump();
108107
ns.setSSLPort(443);
109-
JettySSLData sslData = ns.getSSLData();
108+
final JettySSLData sslData = ns.getSSLData();
110109
assertNotNull(sslData.toString());
111110
sslData.setAllowFlakySSL(true);
112111
assertTrue(sslData.isAllowFlakySSL());
@@ -124,7 +123,7 @@ public void testSSLDataKeystore()
124123
{
125124
final HTTPDump ns = new HTTPDump();
126125
ns.setSSLPort(443);
127-
JettySSLData sslData = ns.getSSLData();
126+
final JettySSLData sslData = ns.getSSLData();
128127
assertNotNull(sslData.getKeystore());
129128

130129
}
@@ -172,16 +171,27 @@ public void testResHandler() throws InterruptedException
172171
{
173172
final HTTPDump ns = new HTTPDump();
174173
ns.setPort(getPort());
175-
MyResourceHandler rh = ns.new MyResourceHandler("foo");
174+
final MyResourceHandler rh = new MyResourceHandler("foo", "dummy");
176175
assertNull(rh.getResource("nix"));
177176
}
178177

178+
@Test
179+
public void testResHandlerWL() throws InterruptedException
180+
{
181+
final HTTPDump ns = new HTTPDump();
182+
ns.setPort(getPort());
183+
final MyResourceHandler rh = new MyResourceHandler("foo", "dummy");
184+
rh.addBase("boo");
185+
assertNull(rh.getResource("foo/nix"));
186+
assertNull(rh.getResource("foo/boo"));
187+
}
188+
179189
@Test
180190
public void testResHandlerString() throws InterruptedException
181191
{
182192
final HTTPDump ns = new HTTPDump();
183193
ns.setPort(getPort());
184-
MyResourceHandler rh = ns.new MyResourceHandler("foo");
194+
final MyResourceHandler rh = new MyResourceHandler("foo", "bar");
185195
assertNotNull(rh.toString());
186196
}
187197

0 commit comments

Comments
 (0)