8302111: Serialization considerations

Reviewed-by: skoivu, rhalade, weijun, wetmore
This commit is contained in:
Valerie Peng 2024-02-05 22:53:51 +00:00 committed by Jaikiran Pai
parent df7d6e081f
commit 369c573383
21 changed files with 747 additions and 468 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -407,6 +407,11 @@ implements Serializable
@SuppressWarnings("unchecked")
Hashtable<Class<?>, PermissionCollection> perms =
(Hashtable<Class<?>, PermissionCollection>)gfields.get("perms", null);
if (perms == null) {
throw new InvalidObjectException("perms can't be null");
}
permsMap = new ConcurrentHashMap<>(perms.size()*2);
permsMap.putAll(perms);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -152,20 +152,20 @@ public final class SignedObject implements Serializable {
*/
public SignedObject(Serializable object, PrivateKey signingKey,
Signature signingEngine)
throws IOException, InvalidKeyException, SignatureException {
// creating a stream pipe-line, from a to b
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutput a = new ObjectOutputStream(b);
throws IOException, InvalidKeyException, SignatureException {
// creating a stream pipe-line, from a to b
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutput a = new ObjectOutputStream(b);
// write and flush the object content to byte array
a.writeObject(object);
a.flush();
a.close();
this.content = b.toByteArray();
b.close();
// write and flush the object content to byte array
a.writeObject(object);
a.flush();
a.close();
this.content = b.toByteArray();
b.close();
// now sign the encapsulated object
this.sign(signingKey, signingEngine);
// now sign the encapsulated object
this.sign(signingKey, signingEngine);
}
/**
@ -245,12 +245,12 @@ public final class SignedObject implements Serializable {
* @throws SignatureException if signing fails.
*/
private void sign(PrivateKey signingKey, Signature signingEngine)
throws InvalidKeyException, SignatureException {
// initialize the signing engine
signingEngine.initSign(signingKey);
signingEngine.update(this.content.clone());
this.signature = signingEngine.sign().clone();
this.thealgorithm = signingEngine.getAlgorithm();
throws InvalidKeyException, SignatureException {
// initialize the signing engine
signingEngine.initSign(signingKey);
signingEngine.update(this.content.clone());
this.signature = signingEngine.sign();
this.thealgorithm = signingEngine.getAlgorithm();
}
/**
@ -263,10 +263,16 @@ public final class SignedObject implements Serializable {
*/
@Serial
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
content = ((byte[])fields.get("content", null)).clone();
signature = ((byte[])fields.get("signature", null)).clone();
thealgorithm = (String)fields.get("thealgorithm", null);
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
byte[] c = (byte[]) fields.get("content", null);
byte[] sig = (byte[]) fields.get("signature", null);
String a = (String) fields.get("thealgorithm", null);
if (c == null || sig == null || a == null) {
throw new InvalidObjectException("One or more null fields");
}
content = c.clone();
signature = sig.clone();
thealgorithm = a;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, 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
@ -27,6 +27,7 @@ package java.security;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
@ -78,7 +79,7 @@ public final class Timestamp implements Serializable {
* {@code null}.
*/
public Timestamp(Date timestamp, CertPath signerCertPath) {
if (timestamp == null || signerCertPath == null) {
if (isNull(timestamp, signerCertPath)) {
throw new NullPointerException();
}
this.timestamp = new Date(timestamp.getTime()); // clone
@ -166,9 +167,16 @@ public final class Timestamp implements Serializable {
*/
@java.io.Serial
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
if (isNull(timestamp, signerCertPath)) {
throw new InvalidObjectException("Invalid null field(s)");
}
myhash = -1;
timestamp = new Date(timestamp.getTime());
}
private static boolean isNull(Date d, CertPath c) {
return (d == null || c == null);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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,6 +29,7 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.InvalidObjectException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@ -196,23 +197,32 @@ implements java.io.Serializable
ObjectInputStream.GetField gfields = in.readFields();
// Get permissions
@SuppressWarnings("unchecked")
// writeObject writes a Hashtable<String, Vector<UnresolvedPermission>>
// for the permissions key, so this cast is safe, unless the data is corrupt.
Hashtable<String, Vector<UnresolvedPermission>> permissions =
(Hashtable<String, Vector<UnresolvedPermission>>)
gfields.get("permissions", null);
perms = new ConcurrentHashMap<>(permissions.size()*2);
try {
@SuppressWarnings("unchecked")
Hashtable<String, Vector<UnresolvedPermission>> permissions =
(Hashtable<String, Vector<UnresolvedPermission>>)
gfields.get("permissions", null);
// Convert each entry (Vector) into a List
Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
// Convert Vector into ArrayList
Vector<UnresolvedPermission> vec = e.getValue();
List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec);
if (permissions == null) {
throw new InvalidObjectException("Invalid null permissions");
}
// Add to Hashtable being serialized
perms.put(e.getKey(), list);
perms = new ConcurrentHashMap<>(permissions.size()*2);
// Convert each entry (Vector) into a List
Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
// Convert Vector into ArrayList
Vector<UnresolvedPermission> vec = e.getValue();
List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec);
// Add to Hashtable being serialized
perms.put(e.getKey(), list);
}
} catch (ClassCastException cce) {
throw new InvalidObjectException("Invalid type for permissions");
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2024, 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,6 +28,7 @@ package java.security.cert;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@ -70,6 +71,13 @@ public class CertificateRevokedException extends CertificateException {
private transient Map<String, Extension> extensions;
private static boolean isNull(Date revocationDate,
CRLReason reason, X500Principal authority,
Map<String, Extension> extensions) {
return (revocationDate == null || reason == null || authority == null
|| extensions == null);
}
/**
* Constructs a {@code CertificateRevokedException} with
* the specified revocation date, reason code, authority name, and map
@ -92,8 +100,7 @@ public class CertificateRevokedException extends CertificateException {
*/
public CertificateRevokedException(Date revocationDate, CRLReason reason,
X500Principal authority, Map<String, Extension> extensions) {
if (revocationDate == null || reason == null || authority == null ||
extensions == null) {
if (isNull(revocationDate, reason, authority, extensions)) {
throw new NullPointerException();
}
this.revocationDate = new Date(revocationDate.getTime());
@ -234,9 +241,6 @@ public class CertificateRevokedException extends CertificateException {
// (revocationDate, reason, authority)
ois.defaultReadObject();
// Defensively copy the revocation date
revocationDate = new Date(revocationDate.getTime());
// Read in the size (number of mappings) of the extensions map
// and create the extensions map
int size = ois.readInt();
@ -247,6 +251,13 @@ public class CertificateRevokedException extends CertificateException {
} else {
extensions = HashMap.newHashMap(Math.min(size, 20));
}
// make sure all fields are set before checking
if (isNull(revocationDate, reason, authority, extensions)) {
throw new InvalidObjectException("Invalid null field(s)");
}
// Defensively copy the revocation date
revocationDate = new Date(revocationDate.getTime());
// Read in the extensions and put the mappings in the extensions map
for (int i = 0; i < size; i++) {