/* | 
|
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. | 
|
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|
 * | 
|
 * This code is free software; you can redistribute it and/or modify it | 
|
 * under the terms of the GNU General Public License version 2 only, as | 
|
 * published by the Free Software Foundation.  Oracle designates this | 
|
 * particular file as subject to the "Classpath" exception as provided | 
|
 * by Oracle in the LICENSE file that accompanied this code. | 
|
 * | 
|
 * This code is distributed in the hope that it will be useful, but WITHOUT | 
|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|
 * version 2 for more details (a copy is included in the LICENSE file that | 
|
 * accompanied this code). | 
|
 * | 
|
 * You should have received a copy of the GNU General Public License version | 
|
 * 2 along with this work; if not, write to the Free Software Foundation, | 
|
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|
 * | 
|
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|
 * or visit www.oracle.com if you need additional information or have any | 
|
 * questions. | 
|
*/  | 
|
package org.jcp.xml.dsig.internal.dom;  | 
|
import java.net.URI;  | 
|
import java.net.URISyntaxException;  | 
|
import java.security.AccessController;  | 
|
import java.security.AccessController;  | 
|
import java.security.PrivilegedAction;  | 
|
import java.security.Security;  | 
|
import java.util.Collections;  | 
|
import java.util.HashMap;  | 
|
import java.util.HashSet;  | 
|
import java.util.Locale;  | 
|
import java.util.Map;  | 
|
import java.util.Set;  | 
|
/** | 
|
 * The secure validation policy as specified by the | 
|
 * jdk.xml.dsig.secureValidationPolicy security property. | 
|
*/  | 
|
public final class Policy { | 
|
    // all restrictions are initialized to be unconstrained | 
|
private static Set<URI> disallowedAlgs = new HashSet<>();  | 
|
private static int maxTrans = Integer.MAX_VALUE;  | 
|
private static int maxRefs = Integer.MAX_VALUE;  | 
|
private static Set<String> disallowedRefUriSchemes = new HashSet<>();  | 
|
private static Map<String, Integer> minKeyMap = new HashMap<>();  | 
|
private static boolean noDuplicateIds = false;  | 
|
private static boolean noRMLoops = false;  | 
|
    static { | 
|
        try { | 
|
initialize();  | 
|
} catch (Exception e) {  | 
|
throw new SecurityException(  | 
|
                "Cannot initialize the secure validation policy", e); | 
|
}  | 
|
}  | 
|
    private Policy() {} | 
|
    private static void initialize() { | 
|
String prop =  | 
|
AccessController.doPrivileged((PrivilegedAction<String>) () ->  | 
|
Security.getProperty("jdk.xml.dsig.secureValidationPolicy"));  | 
|
if (prop == null || prop.isEmpty()) {  | 
|
            // no policy specified, so don't enforce any restrictions | 
|
return;  | 
|
}  | 
|
String[] entries = prop.split(",");  | 
|
for (String entry : entries) {  | 
|
String[] tokens = entry.split("\\s");  | 
|
String type = tokens[0];  | 
|
switch(type) {  | 
|
                case "disallowAlg": | 
|
if (tokens.length != 2) {  | 
|
error(entry);  | 
|
}  | 
|
disallowedAlgs.add(URI.create(tokens[1]));  | 
|
break;  | 
|
                case "maxTransforms": | 
|
if (tokens.length != 2) {  | 
|
error(entry);  | 
|
}  | 
|
maxTrans = Integer.parseUnsignedInt(tokens[1]);  | 
|
break;  | 
|
                case "maxReferences": | 
|
if (tokens.length != 2) {  | 
|
error(entry);  | 
|
}  | 
|
maxRefs = Integer.parseUnsignedInt(tokens[1]);  | 
|
break;  | 
|
                case "disallowReferenceUriSchemes": | 
|
if (tokens.length == 1) {  | 
|
error(entry);  | 
|
}  | 
|
for (int i = 1; i < tokens.length; i++) {  | 
|
String scheme = tokens[i];  | 
|
disallowedRefUriSchemes.add(  | 
|
scheme.toLowerCase(Locale.ROOT));  | 
|
}  | 
|
break;  | 
|
                case "minKeySize": | 
|
if (tokens.length != 3) {  | 
|
error(entry);  | 
|
}  | 
|
minKeyMap.put(tokens[1],  | 
|
Integer.parseUnsignedInt(tokens[2]));  | 
|
break;  | 
|
                case "noDuplicateIds": | 
|
if (tokens.length != 1) {  | 
|
error(entry);  | 
|
}  | 
|
noDuplicateIds = true;  | 
|
break;  | 
|
                case "noRetrievalMethodLoops": | 
|
if (tokens.length != 1) {  | 
|
error(entry);  | 
|
}  | 
|
noRMLoops = true;  | 
|
break;  | 
|
default:  | 
|
error(entry);  | 
|
}  | 
|
}  | 
|
}  | 
|
public static boolean restrictAlg(String alg) {  | 
|
        try { | 
|
URI uri = new URI(alg);  | 
|
return disallowedAlgs.contains(uri);  | 
|
} catch (URISyntaxException use) {  | 
|
return false;  | 
|
}  | 
|
}  | 
|
    public static boolean restrictNumTransforms(int numTrans) { | 
|
return (numTrans > maxTrans);  | 
|
}  | 
|
    public static boolean restrictNumReferences(int numRefs) { | 
|
return (numRefs > maxRefs);  | 
|
}  | 
|
public static boolean restrictReferenceUriScheme(String uri) {  | 
|
if (uri != null) {  | 
|
String scheme = java.net.URI.create(uri).getScheme();  | 
|
if (scheme != null) {  | 
|
return disallowedRefUriSchemes.contains(  | 
|
scheme.toLowerCase(Locale.ROOT));  | 
|
}  | 
|
}  | 
|
return false;  | 
|
}  | 
|
public static boolean restrictKey(String type, int size) {  | 
|
return (size < minKeyMap.getOrDefault(type, 0));  | 
|
}  | 
|
    public static boolean restrictDuplicateIds() { | 
|
return noDuplicateIds;  | 
|
}  | 
|
    public static boolean restrictRetrievalMethodLoops() { | 
|
return noRMLoops;  | 
|
}  | 
|
public static Set<URI> disabledAlgs() {  | 
|
return Collections.<URI>unmodifiableSet(disallowedAlgs);  | 
|
}  | 
|
    public static int maxTransforms() { | 
|
return maxTrans;  | 
|
}  | 
|
    public static int maxReferences() { | 
|
return maxRefs;  | 
|
}  | 
|
public static Set<String> disabledReferenceUriSchemes() {  | 
|
return Collections.<String>unmodifiableSet(disallowedRefUriSchemes);  | 
|
}  | 
|
public static int minKeySize(String type) {  | 
|
return minKeyMap.getOrDefault(type, 0);  | 
|
}  | 
|
private static void error(String entry) {  | 
|
throw new IllegalArgumentException(  | 
|
"Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry);  | 
|
}  | 
|
}  |