Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/pippo-java/pippo into fix…
Browse files Browse the repository at this point in the history
…_454_2
  • Loading branch information
rygel committed Nov 1, 2018
2 parents c2f030d + 2eadf21 commit a233889
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package ro.pippo.xstream;

import com.thoughtworks.xstream.security.NoTypePermission;
import org.kohsuke.MetaInfServices;
import ro.pippo.core.Application;
import ro.pippo.core.ContentTypeEngine;
Expand Down Expand Up @@ -49,6 +50,9 @@ private XStream xstream() {
// prevent xstream from creating complex XML graphs
xstream.setMode(XStream.NO_REFERENCES);

// clear out existing permissions and set own ones
xstream.addPermission(NoTypePermission.NONE);

//setup security
xstream.allowTypes((String[]) WhitelistObjectInputStream.getWhitelistedClassNames().toArray());
xstream.allowTypesByRegExp((Pattern[]) WhitelistObjectInputStream.getWhitelistedRegExp().toArray());
Expand Down
6 changes: 5 additions & 1 deletion pippo-core/src/main/java/ro/pippo/core/gzip/GZipFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package ro.pippo.core.gzip;

import ro.pippo.core.util.StringUtils;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
Expand Down Expand Up @@ -62,7 +64,9 @@ public void destroy() {
protected boolean acceptsGZipEncoding(HttpServletRequest request) {
String acceptEncoding = request.getHeader("accept-encoding");

return acceptEncoding != null && acceptEncoding.contains("gzip");
return !StringUtils.isNullOrEmpty(acceptEncoding) && (
acceptEncoding.contains("gzip") || acceptEncoding.contains("*")
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import ro.pippo.core.RequestResponse;
import ro.pippo.core.RequestResponseFactory;
import ro.pippo.core.Response;
import ro.pippo.core.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -53,7 +54,9 @@ public RequestResponse createRequestResponse(HttpServletRequest httpServletReque
protected boolean acceptsGZipEncoding(HttpServletRequest httpServletRequest) {
String acceptEncoding = httpServletRequest.getHeader("accept-encoding");

return acceptEncoding != null && acceptEncoding.contains("gzip");
return !StringUtils.isNullOrEmpty(acceptEncoding) && (
acceptEncoding.contains("gzip") || acceptEncoding.contains("*")
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

/**
Expand All @@ -33,8 +33,8 @@
*/
public class WhitelistObjectInputStream extends ObjectInputStream {

private static List<String> whiteClassNames;
private static List<Pattern> whiteRegExp;
private static Set<String> whiteClassNames;
private static Set<Pattern> whiteRegEx;

static {
loadWhitelist(WhitelistObjectInputStream.class.getResourceAsStream(PippoConstants.LOCATION_OF_PIPPO_WHITELIST_SERIALIZATION));
Expand All @@ -46,25 +46,23 @@ public WhitelistObjectInputStream(InputStream in) throws IOException {

protected Class<?> resolveClass(ObjectStreamClass descriptor) throws ClassNotFoundException, IOException {
String className = descriptor.getName();
if ((!isWhiteListed(className)) && (!isWhiteListedRegex(className))) {
if (!isWhiteClass(className)) {
throw new InvalidClassException("Unauthorized deserialization attempt", className);
}

return super.resolveClass(descriptor);
}

private boolean isWhiteListed(String className) {
private boolean isWhiteClass(String className) {
// check in list with white classes
for (String name : whiteClassNames) {
if (name.equals(className)) {
return true;
}
}

return false;
}

private boolean isWhiteListedRegex(String className) {
for (Pattern pattern : whiteRegExp) {
// check in list with white regex
for (Pattern pattern : whiteRegEx) {
if (pattern.matcher(className).matches()) {
return true;
}
Expand All @@ -80,16 +78,16 @@ private boolean isWhiteListedRegex(String className) {
* # Java
* java.util.ArrayList
* java.util.HashMap
* A regular expression whitelisting the whole java.lang package and its sub-packages.
* /java.lang.* /
* # A regular expression whitelisting the whole "java.lang" package and its sub-packages
* >java.lang.*
*
* # Pippo
* ro.pippo.session.DefaultSessionData
* ro.pippo.core.Flash
* }
*
* A line that starts with {@code #} is a comment and will be ignored.
* A line that starts and ends with {@code /} is interpreted as a regular expression.
* A line that starts with {@code >} is interpreted as a regular expression.
*/
private static void loadWhitelist(InputStream input) {
String content;
Expand All @@ -99,43 +97,51 @@ private static void loadWhitelist(InputStream input) {
throw new RuntimeException("Error loading the whitelist input", e);
}

whiteClassNames = new ArrayList<>();
whiteClassNames = new HashSet<>();
whiteRegEx = new HashSet<>();

String[] lines = content.split("[\\r\\n]+");
for (String line : lines) {
// check for comment
if (line.startsWith("#")) {
// it's a comment; ignore line
continue;
} else if (line.startsWith("/") && (line.endsWith("/"))) {
addWhiteRegExp(Pattern.compile(line.substring(1, line.length() - 2)));
}

addWhiteClassName(line);
if (line.startsWith(">")) {
// it's a regexp
addWhiteRegEx(line.substring(1).trim());
} else {
// it's a regular (full) class name
addWhiteClassName(line.trim());
}
}
}

private static void addWhiteClassName(String className) {
whiteClassNames.add(className);
}

private static void addWhiteRegExp(Pattern pattern) {
whiteRegExp.add(pattern);
private static void addWhiteRegEx(String regex) {
whiteRegEx.add(Pattern.compile(regex));
}

/**
* Returns the whitelisted class names.
* @return the whitelisted class names.
* Returns the white class names.
*
* @return the white class names.
*/
public static List<String> getWhitelistedClassNames() {
return whiteClassNames;
public static String[] getWhiteClassNames() {
return whiteClassNames.toArray(new String[0]);
}

/**
* Returns the whitelisted regular expressions.
* @return the whitelisted regular expressions.
* Returns the white regular expressions.
*
* @return the white regular expressions.
*/
public static List<Pattern> getWhitelistedRegExp() {
return whiteRegExp;
public static Pattern[] getWhiteRegEx() {
return whiteRegEx.toArray(new Pattern[0]);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.pippo.core.gzip;

import org.junit.Test;
import org.mockito.Mockito;
import ro.pippo.core.Application;

import javax.servlet.http.HttpServletRequest;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class GZipRequestResponseFactoryTest {

@Test
public void testAcceptGzipEncoding() {
GZipRequestResponseFactory requestResponseFactory = new GZipRequestResponseFactory(new Application());
HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class);

// Accept-Encoding not specified
Mockito.doReturn(null).when(httpServletRequest).getHeader("accept-encoding");
assertFalse(requestResponseFactory.acceptsGZipEncoding(httpServletRequest));

// Accept-Encoding specified
Mockito.doReturn("gzip,deflate,identity").when(httpServletRequest).getHeader("accept-encoding");
assertTrue(requestResponseFactory.acceptsGZipEncoding(httpServletRequest));

// Explicit Accept-Encoding:*
Mockito.doReturn("*").when(httpServletRequest).getHeader("accept-encoding");
assertTrue(requestResponseFactory.acceptsGZipEncoding(httpServletRequest));

// No Gzip
Mockito.doReturn("deflate,identity").when(httpServletRequest).getHeader("accept-encoding");
assertFalse(requestResponseFactory.acceptsGZipEncoding(httpServletRequest));
}
}

0 comments on commit a233889

Please sign in to comment.