Merge
This commit is contained in:
commit
6f54947a2d
jdk
src
java.base/share/classes
com/sun/crypto/provider
java
jdk/internal/misc
sun
java.desktop/share/native/libfontmanager/layout
java.management/share/classes
javax/management/remote/rmi
sun/management/jmxremote
java.rmi/share/classes/sun/rmi/server
java.security.jgss/share/classes/sun/security/jgss/wrapper
test
@ -512,11 +512,17 @@ final class GaloisCounterMode extends FeedbackCipher {
|
||||
byte[] sOut = new byte[s.length];
|
||||
GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock);
|
||||
gctrForSToTag.doFinal(s, 0, s.length, sOut, 0);
|
||||
|
||||
// check entire authentication tag for time-consistency
|
||||
int mismatch = 0;
|
||||
for (int i = 0; i < tagLenBytes; i++) {
|
||||
if (tag[i] != sOut[i]) {
|
||||
throw new AEADBadTagException("Tag mismatch!");
|
||||
}
|
||||
mismatch |= tag[i] ^ sOut[i];
|
||||
}
|
||||
|
||||
if (mismatch != 0) {
|
||||
throw new AEADBadTagException("Tag mismatch!");
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,9 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import static java.io.ObjectStreamClass.processQueue;
|
||||
import jdk.internal.misc.JavaObjectInputStreamAccess;
|
||||
import jdk.internal.misc.ObjectStreamClassValidator;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
@ -1509,23 +1512,28 @@ public class ObjectInputStream
|
||||
throws IOException
|
||||
{
|
||||
byte tc = bin.peekByte();
|
||||
ObjectStreamClass descriptor;
|
||||
switch (tc) {
|
||||
case TC_NULL:
|
||||
return (ObjectStreamClass) readNull();
|
||||
|
||||
descriptor = (ObjectStreamClass) readNull();
|
||||
break;
|
||||
case TC_REFERENCE:
|
||||
return (ObjectStreamClass) readHandle(unshared);
|
||||
|
||||
descriptor = (ObjectStreamClass) readHandle(unshared);
|
||||
break;
|
||||
case TC_PROXYCLASSDESC:
|
||||
return readProxyDesc(unshared);
|
||||
|
||||
descriptor = readProxyDesc(unshared);
|
||||
break;
|
||||
case TC_CLASSDESC:
|
||||
return readNonProxyDesc(unshared);
|
||||
|
||||
descriptor = readNonProxyDesc(unshared);
|
||||
break;
|
||||
default:
|
||||
throw new StreamCorruptedException(
|
||||
String.format("invalid type code: %02X", tc));
|
||||
}
|
||||
if (descriptor != null) {
|
||||
validateDescriptor(descriptor);
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
private boolean isCustomSubclass() {
|
||||
@ -1915,6 +1923,8 @@ public class ObjectInputStream
|
||||
if (obj == null || handles.lookupException(passHandle) != null) {
|
||||
defaultReadFields(null, slotDesc); // skip field values
|
||||
} else if (slotDesc.hasReadObjectMethod()) {
|
||||
ThreadDeath t = null;
|
||||
boolean reset = false;
|
||||
SerialCallbackContext oldContext = curContext;
|
||||
if (oldContext != null)
|
||||
oldContext.check();
|
||||
@ -1933,10 +1943,19 @@ public class ObjectInputStream
|
||||
*/
|
||||
handles.markException(passHandle, ex);
|
||||
} finally {
|
||||
curContext.setUsed();
|
||||
if (oldContext!= null)
|
||||
oldContext.check();
|
||||
curContext = oldContext;
|
||||
do {
|
||||
try {
|
||||
curContext.setUsed();
|
||||
if (oldContext!= null)
|
||||
oldContext.check();
|
||||
curContext = oldContext;
|
||||
reset = true;
|
||||
} catch (ThreadDeath x) {
|
||||
t = x; // defer until reset is true
|
||||
}
|
||||
} while (!reset);
|
||||
if (t != null)
|
||||
throw t;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3647,4 +3666,20 @@ public class ObjectInputStream
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDescriptor(ObjectStreamClass descriptor) {
|
||||
ObjectStreamClassValidator validating = validator;
|
||||
if (validating != null) {
|
||||
validating.validateDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// controlled access to ObjectStreamClassValidator
|
||||
private volatile ObjectStreamClassValidator validator;
|
||||
|
||||
private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
|
||||
ois.validator = validator;
|
||||
}
|
||||
static {
|
||||
SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
|
||||
}
|
||||
}
|
||||
|
@ -817,6 +817,9 @@ public abstract class ClassLoader {
|
||||
if (!checkName(name))
|
||||
throw new NoClassDefFoundError("IllegalName: " + name);
|
||||
|
||||
// Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
|
||||
// relies on the fact that spoofing is impossible if a class has a name
|
||||
// of the form "java.*"
|
||||
if ((name != null) && name.startsWith("java.")
|
||||
&& this != getBuiltinPlatformClassLoader()) {
|
||||
throw new SecurityException
|
||||
|
@ -827,7 +827,7 @@ import java.util.Objects;
|
||||
assert(isResolved() == isResolved);
|
||||
}
|
||||
|
||||
void checkForTypeAlias() {
|
||||
void checkForTypeAlias(Class<?> refc) {
|
||||
if (isInvocable()) {
|
||||
MethodType type;
|
||||
if (this.type instanceof MethodType)
|
||||
@ -835,16 +835,16 @@ import java.util.Objects;
|
||||
else
|
||||
this.type = type = getMethodType();
|
||||
if (type.erase() == type) return;
|
||||
if (VerifyAccess.isTypeVisible(type, clazz)) return;
|
||||
throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
|
||||
if (VerifyAccess.isTypeVisible(type, refc)) return;
|
||||
throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
|
||||
} else {
|
||||
Class<?> type;
|
||||
if (this.type instanceof Class<?>)
|
||||
type = (Class<?>) this.type;
|
||||
else
|
||||
this.type = type = getFieldType();
|
||||
if (VerifyAccess.isTypeVisible(type, clazz)) return;
|
||||
throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
|
||||
if (VerifyAccess.isTypeVisible(type, refc)) return;
|
||||
throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1016,10 +1016,25 @@ import java.util.Objects;
|
||||
MemberName m = ref.clone(); // JVM will side-effect the ref
|
||||
assert(refKind == m.getReferenceKind());
|
||||
try {
|
||||
// There are 4 entities in play here:
|
||||
// * LC: lookupClass
|
||||
// * REFC: symbolic reference class (MN.clazz before resolution);
|
||||
// * DEFC: resolved method holder (MN.clazz after resolution);
|
||||
// * PTYPES: parameter types (MN.type)
|
||||
//
|
||||
// What we care about when resolving a MemberName is consistency between DEFC and PTYPES.
|
||||
// We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM
|
||||
// finishes the resolution, so do TA checks right after MHN.resolve() is over.
|
||||
//
|
||||
// All parameters passed by a caller are checked against MH type (PTYPES) on every invocation,
|
||||
// so it is safe to call a MH from any context.
|
||||
//
|
||||
// REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
|
||||
// participate in method selection.
|
||||
m = MethodHandleNatives.resolve(m, lookupClass);
|
||||
m.checkForTypeAlias();
|
||||
m.checkForTypeAlias(m.getDeclaringClass());
|
||||
m.resolution = null;
|
||||
} catch (LinkageError ex) {
|
||||
} catch (ClassNotFoundException | LinkageError ex) {
|
||||
// JVM reports that the "bytecode behavior" would get an error
|
||||
assert(!m.isResolved());
|
||||
m.resolution = ex;
|
||||
|
@ -49,7 +49,7 @@ class MethodHandleNatives {
|
||||
|
||||
static native void init(MemberName self, Object ref);
|
||||
static native void expand(MemberName self);
|
||||
static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError;
|
||||
static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException;
|
||||
static native int getMembers(Class<?> defc, String matchName, String matchSig,
|
||||
int matchFlags, Class<?> caller, int skip, MemberName[] results);
|
||||
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 jdk.internal.misc;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
/**
|
||||
* The interface to specify methods for accessing {@code ObjectInputStream}
|
||||
* @author sjiang
|
||||
*/
|
||||
public interface JavaObjectInputStreamAccess {
|
||||
/**
|
||||
* Sets a descriptor validating.
|
||||
* @param ois stream to have the descriptors validated
|
||||
* @param validator validator used to validate a descriptor.
|
||||
*/
|
||||
public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator);
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 jdk.internal.misc;
|
||||
|
||||
import java.io.ObjectStreamClass;
|
||||
|
||||
/**
|
||||
* A callback used by {@code ObjectInputStream} to do descriptor validation.
|
||||
*
|
||||
* @author sjiang
|
||||
*/
|
||||
public interface ObjectStreamClassValidator {
|
||||
/**
|
||||
* This method will be called by ObjectInputStream to
|
||||
* check a descriptor just before creating an object described by this descriptor.
|
||||
* The object will not be created if this method throws a {@code RuntimeException}.
|
||||
* @param descriptor descriptor to be checked.
|
||||
*/
|
||||
public void validateDescriptor(ObjectStreamClass descriptor);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 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
|
||||
@ -29,9 +29,9 @@ import java.lang.module.ModuleDescriptor;
|
||||
import java.util.jar.JarFile;
|
||||
import java.io.Console;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.AccessController;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/** A repository of "shared secrets", which are a mechanism for
|
||||
calling implementation-private methods in another package without
|
||||
@ -63,6 +63,7 @@ public class SharedSecrets {
|
||||
private static JavaAWTAccess javaAWTAccess;
|
||||
private static JavaAWTFontAccess javaAWTFontAccess;
|
||||
private static JavaBeansAccess javaBeansAccess;
|
||||
private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
|
||||
|
||||
public static JavaUtilJarAccess javaUtilJarAccess() {
|
||||
if (javaUtilJarAccess == null) {
|
||||
@ -262,4 +263,15 @@ public class SharedSecrets {
|
||||
public static void setJavaUtilResourceBundleAccess(JavaUtilResourceBundleAccess access) {
|
||||
javaUtilResourceBundleAccess = access;
|
||||
}
|
||||
|
||||
public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
|
||||
if (javaObjectInputStreamAccess == null) {
|
||||
unsafe.ensureClassInitialized(ObjectInputStream.class);
|
||||
}
|
||||
return javaObjectInputStreamAccess;
|
||||
}
|
||||
|
||||
public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) {
|
||||
javaObjectInputStreamAccess = access;
|
||||
}
|
||||
}
|
||||
|
@ -231,22 +231,66 @@ public class VerifyAccess {
|
||||
* @param refc the class attempting to make the reference
|
||||
*/
|
||||
public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
|
||||
if (type == refc) return true; // easy check
|
||||
if (type == refc) {
|
||||
return true; // easy check
|
||||
}
|
||||
while (type.isArray()) type = type.getComponentType();
|
||||
if (type.isPrimitive() || type == Object.class) return true;
|
||||
ClassLoader parent = type.getClassLoader();
|
||||
if (parent == null) return true;
|
||||
ClassLoader child = refc.getClassLoader();
|
||||
if (child == null) return false;
|
||||
if (parent == child || loadersAreRelated(parent, child, true))
|
||||
if (type.isPrimitive() || type == Object.class) {
|
||||
return true;
|
||||
// Do it the hard way: Look up the type name from the refc loader.
|
||||
try {
|
||||
Class<?> res = child.loadClass(type.getName());
|
||||
return (type == res);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
ClassLoader typeLoader = type.getClassLoader();
|
||||
ClassLoader refcLoader = refc.getClassLoader();
|
||||
if (typeLoader == refcLoader) {
|
||||
return true;
|
||||
}
|
||||
if (refcLoader == null && typeLoader != null) {
|
||||
return false;
|
||||
}
|
||||
if (typeLoader == null && type.getName().startsWith("java.")) {
|
||||
// Note: The API for actually loading classes, ClassLoader.defineClass,
|
||||
// guarantees that classes with names beginning "java." cannot be aliased,
|
||||
// because class loaders cannot load them directly.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do it the hard way: Look up the type name from the refc loader.
|
||||
//
|
||||
// Force the refc loader to report and commit to a particular binding for this type name (type.getName()).
|
||||
//
|
||||
// In principle, this query might force the loader to load some unrelated class,
|
||||
// which would cause this query to fail (and the original caller to give up).
|
||||
// This would be wasted effort, but it is expected to be very rare, occurring
|
||||
// only when an attacker is attempting to create a type alias.
|
||||
// In the normal case, one class loader will simply delegate to the other,
|
||||
// and the same type will be visible through both, with no extra loading.
|
||||
//
|
||||
// It is important to go through Class.forName instead of ClassLoader.loadClass
|
||||
// because Class.forName goes through the JVM system dictionary, which records
|
||||
// the class lookup once for all. This means that even if a not-well-behaved class loader
|
||||
// would "change its mind" about the meaning of the name, the Class.forName request
|
||||
// will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
|
||||
// will record the first successful result. Unsuccessful results are not stored.
|
||||
//
|
||||
// We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
|
||||
// class loader about the binding of the proposed name (type.getName()).
|
||||
// The looked up type ("res") is compared for equality against the proposed
|
||||
// type ("type") and then is discarded. Thus, the worst that can happen to
|
||||
// the "child" class loader is that it is bothered to load and report a class
|
||||
// that differs from "type"; this happens once due to JVM system dictionary
|
||||
// memoization. And the caller never gets to look at the alternate type binding
|
||||
// ("res"), whether it exists or not.
|
||||
final String name = type.getName();
|
||||
Class<?> res = java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<>() {
|
||||
public Class<?> run() {
|
||||
try {
|
||||
return Class.forName(name, false, refcLoader);
|
||||
} catch (ClassNotFoundException | LinkageError e) {
|
||||
return null; // Assume the class is not found
|
||||
}
|
||||
}
|
||||
});
|
||||
return (type == res);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,6 +106,18 @@ abstract class DSA extends SignatureSpi {
|
||||
this.p1363Format = p1363Format;
|
||||
}
|
||||
|
||||
private static void checkKey(DSAParams params, int digestLen, String mdAlgo)
|
||||
throws InvalidKeyException {
|
||||
// FIPS186-3 states in sec4.2 that a hash function which provides
|
||||
// a lower security strength than the (L, N) pair ordinarily should
|
||||
// not be used.
|
||||
int valueN = params.getQ().bitLength();
|
||||
if (valueN > digestLen) {
|
||||
throw new InvalidKeyException("The security strength of " +
|
||||
mdAlgo + " digest algorithm is not sufficient for this key size");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the DSA object with a DSA private key.
|
||||
*
|
||||
@ -130,6 +142,12 @@ abstract class DSA extends SignatureSpi {
|
||||
throw new InvalidKeyException("DSA private key lacks parameters");
|
||||
}
|
||||
|
||||
// check key size against hash output size for signing
|
||||
// skip this check for verification to minimize impact on existing apps
|
||||
if (md.getAlgorithm() != "NullDigest20") {
|
||||
checkKey(params, md.getDigestLength()*8, md.getAlgorithm());
|
||||
}
|
||||
|
||||
this.params = params;
|
||||
this.presetX = priv.getX();
|
||||
this.presetY = null;
|
||||
@ -160,7 +178,6 @@ abstract class DSA extends SignatureSpi {
|
||||
if (params == null) {
|
||||
throw new InvalidKeyException("DSA public key lacks parameters");
|
||||
}
|
||||
|
||||
this.params = params;
|
||||
this.presetY = pub.getY();
|
||||
this.presetX = null;
|
||||
@ -406,20 +423,13 @@ abstract class DSA extends SignatureSpi {
|
||||
return t5.mod(q);
|
||||
}
|
||||
|
||||
// NOTE: This following impl is defined in FIPS 186-3 AppendixB.2.2.
|
||||
// Original DSS algos such as SHA1withDSA and RawDSA uses a different
|
||||
// algorithm defined in FIPS 186-1 Sec3.2, and thus need to override this.
|
||||
// NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1.
|
||||
protected BigInteger generateK(BigInteger q) {
|
||||
SecureRandom random = getSigningRandom();
|
||||
byte[] kValue = new byte[q.bitLength()/8];
|
||||
byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
|
||||
|
||||
while (true) {
|
||||
random.nextBytes(kValue);
|
||||
BigInteger k = new BigInteger(1, kValue).mod(q);
|
||||
if (k.signum() > 0 && k.compareTo(q) < 0) {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
random.nextBytes(kValue);
|
||||
return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
|
||||
}
|
||||
|
||||
// Use the application-specified SecureRandom Object if provided.
|
||||
@ -504,222 +514,10 @@ abstract class DSA extends SignatureSpi {
|
||||
}
|
||||
}
|
||||
|
||||
static class LegacyDSA extends DSA {
|
||||
/* The random seed used to generate k */
|
||||
private int[] kSeed;
|
||||
/* The random seed used to generate k (specified by application) */
|
||||
private byte[] kSeedAsByteArray;
|
||||
/*
|
||||
* The random seed used to generate k
|
||||
* (prevent the same Kseed from being used twice in a row
|
||||
*/
|
||||
private int[] kSeedLast;
|
||||
|
||||
public LegacyDSA(MessageDigest md) throws NoSuchAlgorithmException {
|
||||
this(md, false);
|
||||
}
|
||||
|
||||
private LegacyDSA(MessageDigest md, boolean p1363Format)
|
||||
throws NoSuchAlgorithmException {
|
||||
super(md, p1363Format);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected void engineSetParameter(String key, Object param) {
|
||||
if (key.equals("KSEED")) {
|
||||
if (param instanceof byte[]) {
|
||||
kSeed = byteArray2IntArray((byte[])param);
|
||||
kSeedAsByteArray = (byte[])param;
|
||||
} else {
|
||||
debug("unrecognized param: " + key);
|
||||
throw new InvalidParameterException("kSeed not a byte array");
|
||||
}
|
||||
} else {
|
||||
throw new InvalidParameterException("Unsupported parameter");
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected Object engineGetParameter(String key) {
|
||||
if (key.equals("KSEED")) {
|
||||
return kSeedAsByteArray;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Please read bug report 4044247 for an alternative, faster,
|
||||
* NON-FIPS approved method to generate K
|
||||
*/
|
||||
@Override
|
||||
protected BigInteger generateK(BigInteger q) {
|
||||
BigInteger k = null;
|
||||
|
||||
// The application specified a kSeed for us to use.
|
||||
// Note: we dis-allow usage of the same Kseed twice in a row
|
||||
if (kSeed != null && !Arrays.equals(kSeed, kSeedLast)) {
|
||||
k = generateKUsingKSeed(kSeed, q);
|
||||
if (k.signum() > 0 && k.compareTo(q) < 0) {
|
||||
kSeedLast = kSeed.clone();
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
||||
// The application did not specify a Kseed for us to use.
|
||||
// We'll generate a new Kseed by getting random bytes from
|
||||
// a SecureRandom object.
|
||||
SecureRandom random = getSigningRandom();
|
||||
|
||||
while (true) {
|
||||
int[] seed = new int[5];
|
||||
|
||||
for (int i = 0; i < 5; i++) seed[i] = random.nextInt();
|
||||
|
||||
k = generateKUsingKSeed(seed, q);
|
||||
if (k.signum() > 0 && k.compareTo(q) < 0) {
|
||||
kSeedLast = seed;
|
||||
return k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute k for the DSA signature as defined in the original DSS,
|
||||
* i.e. FIPS186.
|
||||
*
|
||||
* @param seed the seed for generating k. This seed should be
|
||||
* secure. This is what is referred to as the KSEED in the DSA
|
||||
* specification.
|
||||
*
|
||||
* @param g the g parameter from the DSA key pair.
|
||||
*/
|
||||
private BigInteger generateKUsingKSeed(int[] seed, BigInteger q) {
|
||||
|
||||
// check out t in the spec.
|
||||
int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476,
|
||||
0xC3D2E1F0, 0x67452301 };
|
||||
//
|
||||
int[] tmp = SHA_7(seed, t);
|
||||
byte[] tmpBytes = new byte[tmp.length * 4];
|
||||
for (int i = 0; i < tmp.length; i++) {
|
||||
int k = tmp[i];
|
||||
for (int j = 0; j < 4; j++) {
|
||||
tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8)));
|
||||
}
|
||||
}
|
||||
BigInteger k = new BigInteger(1, tmpBytes).mod(q);
|
||||
return k;
|
||||
}
|
||||
|
||||
// Constants for each round
|
||||
private static final int round1_kt = 0x5a827999;
|
||||
private static final int round2_kt = 0x6ed9eba1;
|
||||
private static final int round3_kt = 0x8f1bbcdc;
|
||||
private static final int round4_kt = 0xca62c1d6;
|
||||
|
||||
/**
|
||||
* Computes set 1 thru 7 of SHA-1 on m1. */
|
||||
static int[] SHA_7(int[] m1, int[] h) {
|
||||
|
||||
int[] W = new int[80];
|
||||
System.arraycopy(m1,0,W,0,m1.length);
|
||||
int temp = 0;
|
||||
|
||||
for (int t = 16; t <= 79; t++){
|
||||
temp = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
|
||||
W[t] = ((temp << 1) | (temp >>>(32 - 1)));
|
||||
}
|
||||
|
||||
int a = h[0],b = h[1],c = h[2], d = h[3], e = h[4];
|
||||
for (int i = 0; i < 20; i++) {
|
||||
temp = ((a<<5) | (a>>>(32-5))) +
|
||||
((b&c)|((~b)&d))+ e + W[i] + round1_kt;
|
||||
e = d;
|
||||
d = c;
|
||||
c = ((b<<30) | (b>>>(32-30)));
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
// Round 2
|
||||
for (int i = 20; i < 40; i++) {
|
||||
temp = ((a<<5) | (a>>>(32-5))) +
|
||||
(b ^ c ^ d) + e + W[i] + round2_kt;
|
||||
e = d;
|
||||
d = c;
|
||||
c = ((b<<30) | (b>>>(32-30)));
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
// Round 3
|
||||
for (int i = 40; i < 60; i++) {
|
||||
temp = ((a<<5) | (a>>>(32-5))) +
|
||||
((b&c)|(b&d)|(c&d)) + e + W[i] + round3_kt;
|
||||
e = d;
|
||||
d = c;
|
||||
c = ((b<<30) | (b>>>(32-30)));
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
// Round 4
|
||||
for (int i = 60; i < 80; i++) {
|
||||
temp = ((a<<5) | (a>>>(32-5))) +
|
||||
(b ^ c ^ d) + e + W[i] + round4_kt;
|
||||
e = d;
|
||||
d = c;
|
||||
c = ((b<<30) | (b>>>(32-30)));
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
int[] md = new int[5];
|
||||
md[0] = h[0] + a;
|
||||
md[1] = h[1] + b;
|
||||
md[2] = h[2] + c;
|
||||
md[3] = h[3] + d;
|
||||
md[4] = h[4] + e;
|
||||
return md;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility routine for converting a byte array into an int array
|
||||
*/
|
||||
private int[] byteArray2IntArray(byte[] byteArray) {
|
||||
|
||||
int j = 0;
|
||||
byte[] newBA;
|
||||
int mod = byteArray.length % 4;
|
||||
|
||||
// guarantee that the incoming byteArray is a multiple of 4
|
||||
// (pad with 0's)
|
||||
switch (mod) {
|
||||
case 3: newBA = new byte[byteArray.length + 1]; break;
|
||||
case 2: newBA = new byte[byteArray.length + 2]; break;
|
||||
case 1: newBA = new byte[byteArray.length + 3]; break;
|
||||
default: newBA = new byte[byteArray.length + 0]; break;
|
||||
}
|
||||
System.arraycopy(byteArray, 0, newBA, 0, byteArray.length);
|
||||
|
||||
// copy each set of 4 bytes in the byte array into an integer
|
||||
int[] newSeed = new int[newBA.length / 4];
|
||||
for (int i = 0; i < newBA.length; i += 4) {
|
||||
newSeed[j] = newBA[i + 3] & 0xFF;
|
||||
newSeed[j] |= (newBA[i + 2] << 8) & 0xFF00;
|
||||
newSeed[j] |= (newBA[i + 1] << 16) & 0xFF0000;
|
||||
newSeed[j] |= (newBA[i + 0] << 24) & 0xFF000000;
|
||||
j++;
|
||||
}
|
||||
|
||||
return newSeed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard SHA1withDSA implementation.
|
||||
*/
|
||||
public static final class SHA1withDSA extends LegacyDSA {
|
||||
public static final class SHA1withDSA extends DSA {
|
||||
public SHA1withDSA() throws NoSuchAlgorithmException {
|
||||
super(MessageDigest.getInstance("SHA-1"));
|
||||
}
|
||||
@ -728,7 +526,7 @@ abstract class DSA extends SignatureSpi {
|
||||
/**
|
||||
* SHA1withDSA implementation that uses the IEEE P1363 format.
|
||||
*/
|
||||
public static final class SHA1withDSAinP1363Format extends LegacyDSA {
|
||||
public static final class SHA1withDSAinP1363Format extends DSA {
|
||||
public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException {
|
||||
super(MessageDigest.getInstance("SHA-1"), true);
|
||||
}
|
||||
@ -741,7 +539,7 @@ abstract class DSA extends SignatureSpi {
|
||||
* not, a SignatureException is thrown when sign()/verify() is called
|
||||
* per JCA spec.
|
||||
*/
|
||||
static class Raw extends LegacyDSA {
|
||||
static class Raw extends DSA {
|
||||
// Internal special-purpose MessageDigest impl for RawDSA
|
||||
// Only override whatever methods used
|
||||
// NOTE: no clone support
|
||||
|
@ -45,9 +45,12 @@ const le_uint16 DeviceTable::fieldBits[] = { 2, 4, 8};
|
||||
|
||||
le_int16 DeviceTable::getAdjustment(const LEReferenceTo<DeviceTable>&base, le_uint16 ppem, LEErrorCode &success) const
|
||||
{
|
||||
le_int16 result = 0;
|
||||
if (LE_FAILURE(success)) {
|
||||
return result;
|
||||
}
|
||||
le_uint16 start = SWAPW(startSize);
|
||||
le_uint16 format = SWAPW(deltaFormat) - 1;
|
||||
le_int16 result = 0;
|
||||
|
||||
if (ppem >= start && ppem <= SWAPW(endSize) && format < FORMAT_COUNT) {
|
||||
le_uint16 sizeIndex = ppem - start;
|
||||
|
@ -71,6 +71,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
|
||||
{
|
||||
LEErrorCode success = LE_NO_ERROR;
|
||||
const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ByteOffset newState = SWAPW(entry->newStateOffset);
|
||||
le_uint16 flags = SWAPW(entry->flags);
|
||||
@ -91,6 +95,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
|
||||
|
||||
if (actionOffset != 0) {
|
||||
LEReferenceTo<LigatureActionEntry> ap(stHeader, success, actionOffset);
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph++;
|
||||
return newState;
|
||||
}
|
||||
LigatureActionEntry action;
|
||||
le_int32 offset, i = 0, j = 0;
|
||||
le_int32 stack[nComponents];
|
||||
@ -101,6 +109,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
|
||||
|
||||
if (j++ > 0) {
|
||||
ap.addObject(success);
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph++;
|
||||
return newState;
|
||||
}
|
||||
}
|
||||
|
||||
action = SWAPL(*ap.getAlias());
|
||||
@ -124,9 +136,17 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
|
||||
return newState; // get out! bad font
|
||||
}
|
||||
i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success));
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph++;
|
||||
return newState;
|
||||
}
|
||||
|
||||
if (action & (lafLast | lafStore)) {
|
||||
LEReferenceTo<TTGlyphID> ligatureOffset(stHeader, success, i);
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph++;
|
||||
return newState;
|
||||
}
|
||||
TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias());
|
||||
|
||||
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
|
||||
|
@ -95,6 +95,10 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
|
||||
|
||||
if (actionOffset != 0) {
|
||||
LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex;
|
||||
}
|
||||
ap.addObject(ligActionIndex, success);
|
||||
LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY);
|
||||
LigatureActionEntry action;
|
||||
@ -104,8 +108,8 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
|
||||
|
||||
LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY);
|
||||
if(LE_FAILURE(success)) {
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex; // get out! bad font
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex; // get out! bad font
|
||||
}
|
||||
|
||||
do {
|
||||
@ -114,6 +118,10 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
|
||||
if (j++ > 0) {
|
||||
ap.addObject(success);
|
||||
}
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex;
|
||||
}
|
||||
|
||||
action = SWAPL(*ap.getAlias());
|
||||
|
||||
@ -129,9 +137,17 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
|
||||
return nextStateIndex; // get out! bad font
|
||||
}
|
||||
i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success));
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex;
|
||||
}
|
||||
|
||||
if (action & (lafLast | lafStore)) {
|
||||
TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success));
|
||||
if (LE_FAILURE(success)) {
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex;
|
||||
}
|
||||
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
|
||||
if(mm==nComponents) {
|
||||
LE_DEBUG_BAD_FONT("exceeded nComponents");
|
||||
|
@ -60,6 +60,7 @@ StateTableProcessor2::StateTableProcessor2(const LEReferenceTo<MorphSubtableHead
|
||||
entryTableOffset = SWAPL(stHeader->entryTableOffset);
|
||||
|
||||
classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset);
|
||||
if (LE_FAILURE(success)) return;
|
||||
format = SWAPW(classTable->format);
|
||||
|
||||
stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 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
|
||||
@ -45,6 +45,7 @@ import java.util.Set;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.remote.JMXAuthenticator;
|
||||
|
||||
import javax.management.remote.JMXConnectionNotification;
|
||||
import javax.management.remote.JMXConnector;
|
||||
@ -99,6 +100,21 @@ public class RMIConnectorServer extends JMXConnectorServer {
|
||||
public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
|
||||
"jmx.remote.rmi.server.socket.factory";
|
||||
|
||||
/**
|
||||
* Name of the attribute that specifies a list of class names acceptable
|
||||
* as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
|
||||
* remote method call.
|
||||
* <p>
|
||||
* This list of classes should correspond to the transitive closure of the
|
||||
* credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
|
||||
* associated with the {@linkplain RMIServer} implementation.
|
||||
* <p>
|
||||
* If the attribute is not set, or is null, then any class is
|
||||
* deemed acceptable.
|
||||
*/
|
||||
public static final String CREDENTIAL_TYPES =
|
||||
"jmx.remote.rmi.server.credential.types";
|
||||
|
||||
/**
|
||||
* <p>Makes an <code>RMIConnectorServer</code>.
|
||||
* This is equivalent to calling {@link #RMIConnectorServer(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 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
|
||||
@ -39,6 +39,13 @@ import javax.security.auth.Subject;
|
||||
|
||||
import com.sun.jmx.remote.internal.RMIExporter;
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
import sun.rmi.server.DeserializationChecker;
|
||||
import sun.rmi.server.UnicastServerRef;
|
||||
import sun.rmi.server.UnicastServerRef2;
|
||||
|
||||
@ -52,6 +59,9 @@ import sun.rmi.server.UnicastServerRef2;
|
||||
* @since 1.5
|
||||
*/
|
||||
public class RMIJRMPServerImpl extends RMIServerImpl {
|
||||
|
||||
private final ExportedWrapper exportedWrapper;
|
||||
|
||||
/**
|
||||
* <p>Creates a new {@link RMIServer} object that will be exported
|
||||
* on the given port using the given socket factories.</p>
|
||||
@ -89,10 +99,31 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
||||
this.csf = csf;
|
||||
this.ssf = ssf;
|
||||
this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
|
||||
|
||||
String[] credentialsTypes
|
||||
= (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
|
||||
List<String> types = null;
|
||||
if (credentialsTypes != null) {
|
||||
types = new ArrayList<>();
|
||||
for (String type : credentialsTypes) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("A credential type is null.");
|
||||
}
|
||||
ReflectUtil.checkPackageAccess(type);
|
||||
types.add(type);
|
||||
}
|
||||
}
|
||||
exportedWrapper = types != null ?
|
||||
new ExportedWrapper(this, types) :
|
||||
null;
|
||||
}
|
||||
|
||||
protected void export() throws IOException {
|
||||
export(this);
|
||||
if (exportedWrapper != null) {
|
||||
export(exportedWrapper);
|
||||
} else {
|
||||
export(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void export(Remote obj) throws RemoteException {
|
||||
@ -142,7 +173,11 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
||||
* RMIJRMPServerImpl has not been exported yet.
|
||||
*/
|
||||
public Remote toStub() throws IOException {
|
||||
return RemoteObject.toStub(this);
|
||||
if (exportedWrapper != null) {
|
||||
return RemoteObject.toStub(exportedWrapper);
|
||||
} else {
|
||||
return RemoteObject.toStub(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,11 +224,56 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
||||
* server failed.
|
||||
*/
|
||||
protected void closeServer() throws IOException {
|
||||
unexport(this, true);
|
||||
if (exportedWrapper != null) {
|
||||
unexport(exportedWrapper, true);
|
||||
} else {
|
||||
unexport(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
private final int port;
|
||||
private final RMIClientSocketFactory csf;
|
||||
private final RMIServerSocketFactory ssf;
|
||||
private final Map<String, ?> env;
|
||||
|
||||
private static class ExportedWrapper implements RMIServer, DeserializationChecker {
|
||||
private final RMIServer impl;
|
||||
private final List<String> allowedTypes;
|
||||
|
||||
private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
|
||||
this.impl = impl;
|
||||
allowedTypes = credentialsTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() throws RemoteException {
|
||||
return impl.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RMIConnection newClient(Object credentials) throws IOException {
|
||||
return impl.newClient(credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(Method method, ObjectStreamClass descriptor,
|
||||
int paramIndex, int callID) {
|
||||
String type = descriptor.getName();
|
||||
if (!allowedTypes.contains(type)) {
|
||||
throw new ClassCastException("Unsupported type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkProxyClass(Method method, String[] ifaces,
|
||||
int paramIndex, int callID) {
|
||||
if (ifaces != null && ifaces.length > 0) {
|
||||
for (String iface : ifaces) {
|
||||
if (!allowedTypes.contains(iface)) {
|
||||
throw new ClassCastException("Unsupported type: " + iface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -510,6 +510,9 @@ public final class ConnectorBootstrap {
|
||||
// This RMI server should not keep the VM alive
|
||||
Map<String, Object> env = new HashMap<>();
|
||||
env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter());
|
||||
env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
|
||||
String[].class.getName(), String.class.getName()
|
||||
});
|
||||
|
||||
// The local connector server need only be available via the
|
||||
// loopback connection.
|
||||
@ -740,6 +743,9 @@ public final class ConnectorBootstrap {
|
||||
PermanentExporter exporter = new PermanentExporter();
|
||||
|
||||
env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
|
||||
env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
|
||||
String[].class.getName(), String.class.getName()
|
||||
});
|
||||
|
||||
boolean useSocketFactory = bindAddress != null && !useSsl;
|
||||
|
||||
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 sun.rmi.server;
|
||||
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Implementing this interface to have a deserialization control when RMI
|
||||
* dispatches a remote request. If an exported object implements this interface,
|
||||
* RMI dispatching mechanism will call the method {@code check} every time
|
||||
* deserialising a remote object for invoking a method of the exported object.
|
||||
*
|
||||
* @author sjiang
|
||||
*/
|
||||
public interface DeserializationChecker {
|
||||
/**
|
||||
* Will be called to check a descriptor.
|
||||
* This method may be called 2 times, the first time is when a descriptor is read
|
||||
* from the stream, the second is just before creating an object described
|
||||
* by this descriptor.
|
||||
*
|
||||
* @param method the method invoked from a remote request.
|
||||
* @param descriptor The descriptor of the class of any object deserialised
|
||||
* while deserialising the parameter. The first descriptor will be that of
|
||||
* the top level object (the concrete class of the parameter itself);
|
||||
* Subsequent calls with the same {@code method}, {@code paramIndex} and
|
||||
* {@code callID} will correspond to objects contained in the parameter.
|
||||
* @param paramIndex an index indicates the position of a parameter in the
|
||||
* method. This index will be reused for deserialising all
|
||||
* objects contained in the parameter object. For example, the parameter
|
||||
* being deserialised is a {@code List}, all deserialisation calls for its
|
||||
* elements will have same index.
|
||||
* @param callID a unique ID identifying one
|
||||
* time method invocation, the same ID is used for deserialization call of
|
||||
* all parameters within the method.
|
||||
*/
|
||||
public void check(Method method,
|
||||
ObjectStreamClass descriptor,
|
||||
int paramIndex,
|
||||
int callID);
|
||||
|
||||
/**
|
||||
* Will be called to validate a Proxy interfaces from a remote user before loading it.
|
||||
* @param method the method invoked from a remote request.
|
||||
* @param ifaces a string table of all interfaces implemented by the proxy to be checked.
|
||||
* @param paramIndex an index indicates the position of a parameter in the
|
||||
* method. This index will be reused for deserialising all
|
||||
* objects contained in the parameter object. For example, the parameter
|
||||
* being deserialised is a {@code List}, all deserialisation calls for its
|
||||
* elements will have same index.
|
||||
* @param callID a unique ID identifying one
|
||||
* time method invocation, the same ID is used for deserialization call of
|
||||
* all parameters within the method.
|
||||
*/
|
||||
public void checkProxyClass(Method method,
|
||||
String[] ifaces,
|
||||
int paramIndex,
|
||||
int callID);
|
||||
|
||||
/**
|
||||
* Inform of the completion of parameter deserialisation for a method invocation.
|
||||
* This is useful if the last parameter is a complex object, like a {@code List}
|
||||
* which elements are complex object too.
|
||||
*
|
||||
* The default implementation does nothing.
|
||||
* @param callID the ID identifying a method invocation.
|
||||
*/
|
||||
public default void end(int callID) {}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 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
|
||||
@ -30,13 +30,13 @@ import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.security.AccessControlException;
|
||||
import java.security.Permission;
|
||||
|
||||
import java.rmi.server.RMIClassLoader;
|
||||
import java.security.PrivilegedAction;
|
||||
import jdk.internal.misc.ObjectStreamClassValidator;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
|
||||
/**
|
||||
* MarshalInputStream is an extension of ObjectInputStream. When resolving
|
||||
@ -54,6 +54,11 @@ import java.security.PrivilegedAction;
|
||||
* @author Peter Jones
|
||||
*/
|
||||
public class MarshalInputStream extends ObjectInputStream {
|
||||
interface StreamChecker extends ObjectStreamClassValidator {
|
||||
void checkProxyInterfaceNames(String[] ifaces);
|
||||
}
|
||||
|
||||
private volatile StreamChecker streamChecker = null;
|
||||
|
||||
/**
|
||||
* Value of "java.rmi.server.useCodebaseOnly" property,
|
||||
@ -123,7 +128,7 @@ public class MarshalInputStream extends ObjectInputStream {
|
||||
throws IOException, StreamCorruptedException
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a callback previously registered via the setDoneCallback
|
||||
@ -240,6 +245,11 @@ public class MarshalInputStream extends ObjectInputStream {
|
||||
protected Class<?> resolveProxyClass(String[] interfaces)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
StreamChecker checker = streamChecker;
|
||||
if (checker != null) {
|
||||
checker.checkProxyInterfaceNames(interfaces);
|
||||
}
|
||||
|
||||
/*
|
||||
* Always read annotation written by MarshalOutputStream.
|
||||
*/
|
||||
@ -319,4 +329,28 @@ public class MarshalInputStream extends ObjectInputStream {
|
||||
void useCodebaseOnly() {
|
||||
useCodebaseOnly = true;
|
||||
}
|
||||
|
||||
synchronized void setStreamChecker(StreamChecker checker) {
|
||||
streamChecker = checker;
|
||||
SharedSecrets.getJavaObjectInputStreamAccess().setValidator(this, checker);
|
||||
}
|
||||
@Override
|
||||
protected ObjectStreamClass readClassDescriptor() throws IOException,
|
||||
ClassNotFoundException {
|
||||
ObjectStreamClass descriptor = super.readClassDescriptor();
|
||||
|
||||
validateDesc(descriptor);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
private void validateDesc(ObjectStreamClass descriptor) {
|
||||
StreamChecker checker;
|
||||
synchronized (this) {
|
||||
checker = streamChecker;
|
||||
}
|
||||
if (checker != null) {
|
||||
checker.validateDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 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
|
||||
@ -28,7 +28,7 @@ package sun.rmi.server;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.PrintStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.rmi.MarshalException;
|
||||
@ -52,6 +52,7 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import sun.rmi.runtime.Log;
|
||||
import sun.rmi.transport.LiveRef;
|
||||
import sun.rmi.transport.Target;
|
||||
@ -116,6 +117,8 @@ public class UnicastServerRef extends UnicastRef
|
||||
private static final Map<Class<?>,?> withoutSkeletons =
|
||||
Collections.synchronizedMap(new WeakHashMap<Class<?>,Void>());
|
||||
|
||||
private final AtomicInteger methodCallIDCount = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* Create a new (empty) Unicast server remote reference.
|
||||
*/
|
||||
@ -297,14 +300,11 @@ public class UnicastServerRef extends UnicastRef
|
||||
logCall(obj, method);
|
||||
|
||||
// unmarshal parameters
|
||||
Class<?>[] types = method.getParameterTypes();
|
||||
Object[] params = new Object[types.length];
|
||||
Object[] params = null;
|
||||
|
||||
try {
|
||||
unmarshalCustomCallData(in);
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
params[i] = unmarshalValue(types[i], in);
|
||||
}
|
||||
params = unmarshalParameters(obj, method, marshalStream);
|
||||
} catch (java.io.IOException e) {
|
||||
throw new UnmarshalException(
|
||||
"error unmarshalling arguments", e);
|
||||
@ -565,4 +565,85 @@ public class UnicastServerRef extends UnicastRef
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshal parameters for the given method of the given instance over
|
||||
* the given marshalinputstream. Perform any necessary checks.
|
||||
*/
|
||||
private Object[] unmarshalParameters(Object obj, Method method, MarshalInputStream in)
|
||||
throws IOException, ClassNotFoundException {
|
||||
return (obj instanceof DeserializationChecker) ?
|
||||
unmarshalParametersChecked((DeserializationChecker)obj, method, in) :
|
||||
unmarshalParametersUnchecked(method, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshal parameters for the given method of the given instance over
|
||||
* the given marshalinputstream. Do not perform any additional checks.
|
||||
*/
|
||||
private Object[] unmarshalParametersUnchecked(Method method, ObjectInput in)
|
||||
throws IOException, ClassNotFoundException {
|
||||
Class<?>[] types = method.getParameterTypes();
|
||||
Object[] params = new Object[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
params[i] = unmarshalValue(types[i], in);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshal parameters for the given method of the given instance over
|
||||
* the given marshalinputstream. Do perform all additional checks.
|
||||
*/
|
||||
private Object[] unmarshalParametersChecked(
|
||||
DeserializationChecker checker,
|
||||
Method method, MarshalInputStream in)
|
||||
throws IOException, ClassNotFoundException {
|
||||
int callID = methodCallIDCount.getAndIncrement();
|
||||
MyChecker myChecker = new MyChecker(checker, method, callID);
|
||||
in.setStreamChecker(myChecker);
|
||||
try {
|
||||
Class<?>[] types = method.getParameterTypes();
|
||||
Object[] values = new Object[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
myChecker.setIndex(i);
|
||||
values[i] = unmarshalValue(types[i], in);
|
||||
}
|
||||
myChecker.end(callID);
|
||||
return values;
|
||||
} finally {
|
||||
in.setStreamChecker(null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyChecker implements MarshalInputStream.StreamChecker {
|
||||
private final DeserializationChecker descriptorCheck;
|
||||
private final Method method;
|
||||
private final int callID;
|
||||
private int parameterIndex;
|
||||
|
||||
MyChecker(DeserializationChecker descriptorCheck, Method method, int callID) {
|
||||
this.descriptorCheck = descriptorCheck;
|
||||
this.method = method;
|
||||
this.callID = callID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateDescriptor(ObjectStreamClass descriptor) {
|
||||
descriptorCheck.check(method, descriptor, parameterIndex, callID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkProxyInterfaceNames(String[] ifaces) {
|
||||
descriptorCheck.checkProxyClass(method, ifaces, parameterIndex, callID);
|
||||
}
|
||||
|
||||
void setIndex(int parameterIndex) {
|
||||
this.parameterIndex = parameterIndex;
|
||||
}
|
||||
|
||||
void end(int callId) {
|
||||
descriptorCheck.end(callId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,9 @@ public class GSSNameElement implements GSSNameSpi {
|
||||
int atPos = krbName.lastIndexOf('@');
|
||||
if (atPos != -1) {
|
||||
String atRealm = krbName.substring(atPos);
|
||||
if (nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL)
|
||||
// getNativeNameType() can modify NT_GSS_KRB5_PRINCIPAL to null
|
||||
if ((nameType == null
|
||||
|| nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL))
|
||||
&& new String(nameBytes).endsWith(atRealm)) {
|
||||
// Created from Kerberos name with realm, no need to check
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2015, 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
|
||||
@ -55,9 +55,9 @@ class TestRandomSource extends SecureRandom {
|
||||
|
||||
int count = 0;
|
||||
|
||||
public int nextInt() {
|
||||
@Override
|
||||
public void nextBytes(byte[] rs) {
|
||||
count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isUsed() {
|
||||
|
@ -60,8 +60,8 @@ public class TestDSA2 {
|
||||
boolean[] expectedToPass = { true, true, true, true,
|
||||
true, true, true, true };
|
||||
test(1024, expectedToPass);
|
||||
boolean[] expectedToPass2 = { true, true, true, true,
|
||||
true, true, true, true };
|
||||
boolean[] expectedToPass2 = { true, false, true, true,
|
||||
true, false, true, true };
|
||||
test(2048, expectedToPass2);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user