Reviewed-by: kcr, prr
This commit is contained in:
Brent Christian 2025-10-21 18:40:24 +00:00
commit b68fa4354c
15 changed files with 216 additions and 51 deletions

View File

@ -132,8 +132,16 @@ bool StackMapTable::match_stackmap(
}
void StackMapTable::check_jump_target(
StackMapFrame* frame, int32_t target, TRAPS) const {
StackMapFrame* frame, int bci, int offset, TRAPS) const {
ErrorContext ctx;
// Jump targets must be within the method and the method size is limited. See JVMS 4.11
int min_offset = -1 * max_method_code_size;
if (offset < min_offset || offset > max_method_code_size) {
frame->verifier()->verify_error(ErrorContext::bad_stackmap(bci, frame),
"Illegal target of jump or branch (bci %d + offset %d)", bci, offset);
return;
}
int target = bci + offset;
bool match = match_stackmap(
frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
if (!match || (target < 0 || target >= _code_length)) {

View File

@ -67,7 +67,7 @@ class StackMapTable : public StackObj {
// Check jump instructions. Make sure there are no uninitialized
// instances on backward branch.
void check_jump_target(StackMapFrame* frame, int32_t target, TRAPS) const;
void check_jump_target(StackMapFrame* frame, int bci, int offset, TRAPS) const;
// The following methods are only used inside this class.

View File

@ -781,7 +781,6 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
// Merge with the next instruction
{
int target;
VerificationType type, type2;
VerificationType atype;
@ -1606,9 +1605,8 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
case Bytecodes::_ifle:
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
target = bcs.dest();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_if_acmpeq :
case Bytecodes::_if_acmpne :
@ -1619,19 +1617,16 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
case Bytecodes::_ifnonnull :
current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this));
target = bcs.dest();
stackmap_table.check_jump_target
(&current_frame, target, CHECK_VERIFY(this));
(&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_goto :
target = bcs.dest();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_goto_w :
target = bcs.dest_w();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_tableswitch :
case Bytecodes::_lookupswitch :
@ -2280,15 +2275,14 @@ void ClassVerifier::verify_switch(
}
}
}
int target = bci + default_offset;
stackmap_table->check_jump_target(current_frame, target, CHECK_VERIFY(this));
stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this));
for (int i = 0; i < keys; i++) {
// Because check_jump_target() may safepoint, the bytecode could have
// moved, which means 'aligned_bcp' is no good and needs to be recalculated.
aligned_bcp = align_up(bcs->bcp() + 1, jintSize);
target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
stackmap_table->check_jump_target(
current_frame, target, CHECK_VERIFY(this));
current_frame, bci, offset, CHECK_VERIFY(this));
}
NOT_PRODUCT(aligned_bcp = nullptr); // no longer valid at this point
}

View File

@ -100,8 +100,23 @@ class BaseBytecodeStream: StackObj {
void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
// Bytecode-specific attributes
int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); }
int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); }
int get_offset_s2() const { return bytecode().get_offset_s2(raw_code()); }
int get_offset_s4() const { return bytecode().get_offset_s4(raw_code()); }
// These methods are not safe to use before or during verification as they may
// have large offsets and cause overflows
int dest() const {
int min_offset = -1 * max_method_code_size;
int offset = bytecode().get_offset_s2(raw_code());
guarantee(offset >= min_offset && offset <= max_method_code_size, "must be");
return bci() + offset;
}
int dest_w() const {
int min_offset = -1 * max_method_code_size;
int offset = bytecode().get_offset_s4(raw_code());
guarantee(offset >= min_offset && offset <= max_method_code_size, "must be");
return bci() + offset;
}
// One-byte indices.
u1 get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }

View File

@ -1448,8 +1448,8 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
shift(currValue, coder, count, dstOffset, len);
count += len;
// Coder of CharSequence may be a mismatch, requiring the value array to be inflated
byte[] newValue = (s instanceof String str)
? putStringAt(currValue, coder, count, dstOffset, str, start, end)
byte[] newValue = (s instanceof String str && str.length() == len)
? putStringAt(currValue, coder, count, dstOffset, str)
: putCharsAt(currValue, coder, count, dstOffset, s, start, end);
if (currValue != newValue) {
this.coder = UTF16;
@ -1928,10 +1928,10 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
* @param index the index to insert the string
* @param str the string
*/
private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str, int off, int end) {
private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str) {
byte[] newValue = inflateIfNeededFor(value, count, coder, str.coder());
coder = (newValue == value) ? coder : UTF16;
str.getBytes(newValue, off, index, coder, end - off);
str.getBytes(newValue, 0, index, coder, str.length());
return newValue;
}

View File

@ -859,6 +859,22 @@ public class DerValue {
return readStringInternal(tag_UniversalString, new UTF_32BE());
}
/**
* Checks that the BMPString does not contain any surrogate characters,
* which are outside the Basic Multilingual Plane.
*
* @throws IOException if illegal characters are detected
*/
public void validateBMPString() throws IOException {
String bmpString = getBMPString();
for (int i = 0; i < bmpString.length(); i++) {
if (Character.isSurrogate(bmpString.charAt(i))) {
throw new IOException(
"Illegal character in BMPString, index: " + i);
}
}
}
/**
* Reads the ASN.1 NULL value
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2025, 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,10 +28,13 @@ package sun.security.x509;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.text.Normalizer;
import java.util.*;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.charset.StandardCharsets.UTF_16BE;
import sun.security.util.*;
import sun.security.pkcs.PKCS9Attribute;
@ -589,6 +592,10 @@ public class AVA implements DerEncoder {
throw new IOException("AVA, extra bytes = "
+ derval.data.available());
}
if (value.tag == DerValue.tag_BMPString) {
value.validateBMPString();
}
}
AVA(DerInputStream in) throws IOException {
@ -713,7 +720,8 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr = new String(value.getDataBytes(), UTF_8);
String valStr =
new String(value.getDataBytes(), getCharset(value, false));
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@ -832,7 +840,8 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr = new String(value.getDataBytes(), UTF_8);
String valStr =
new String(value.getDataBytes(), getCharset(value, true));
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@ -927,6 +936,39 @@ public class AVA implements DerEncoder {
}
}
/*
* Returns the charset that should be used to decode each DN string type.
*
* This method ensures that multi-byte (UTF8String and BMPString) types
* are decoded using the correct charset and the String forms represent
* the correct characters. For 8-bit ASCII-based types (PrintableString
* and IA5String), we return ISO_8859_1 rather than ASCII, so that the
* complete range of characters can be represented, as many certificates
* do not comply with the Internationalized Domain Name ACE format.
*
* NOTE: this method only supports DirectoryStrings of the types returned
* by isDerString().
*/
private static Charset getCharset(DerValue value, boolean canonical) {
if (canonical) {
return switch (value.tag) {
case DerValue.tag_PrintableString -> ISO_8859_1;
case DerValue.tag_UTF8String -> UTF_8;
default -> throw new Error("unexpected tag: " + value.tag);
};
}
return switch (value.tag) {
case DerValue.tag_PrintableString,
DerValue.tag_T61String,
DerValue.tag_IA5String,
DerValue.tag_GeneralString -> ISO_8859_1;
case DerValue.tag_BMPString -> UTF_16BE;
case DerValue.tag_UTF8String -> UTF_8;
default -> throw new Error("unexpected tag: " + value.tag);
};
}
boolean hasRFC2253Keyword() {
return AVAKeyword.hasKeyword(oid, RFC2253);
}

View File

@ -395,7 +395,8 @@ static jboolean is_superclass(context_type *, fullinfo_type);
static void initialize_exception_table(context_type *);
static int instruction_length(unsigned char *iptr, unsigned char *end);
static jboolean isLegalTarget(context_type *, int offset);
static jboolean isLegalOffset(context_type *, int bci, int offset);
static jboolean isLegalTarget(context_type *, int target);
static void verify_constant_pool_type(context_type *, int, unsigned);
static void initialize_dataflow(context_type *);
@ -1154,9 +1155,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
case JVM_OPC_goto: {
/* Set the ->operand to be the instruction number of the target. */
int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2];
int target = offset + jump;
if (!isLegalTarget(context, target))
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
this_idata->operand.i = code_data[target];
break;
}
@ -1170,9 +1171,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
int jump = (((signed char)(code[offset+1])) << 24) +
(code[offset+2] << 16) + (code[offset+3] << 8) +
(code[offset + 4]);
int target = offset + jump;
if (!isLegalTarget(context, target))
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
this_idata->operand.i = code_data[target];
break;
}
@ -1211,13 +1212,16 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
}
}
saved_operand = NEW(int, keys + 2);
if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0])))
int jump = _ck_ntohl(lpc[0]);
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal default target in switch");
saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])];
int target = offset + jump;
saved_operand[keys + 1] = code_data[target];
for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) {
int target = offset + _ck_ntohl(lptr[0]);
if (!isLegalTarget(context, target))
jump = _ck_ntohl(lptr[0]);
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal branch in tableswitch");
target = offset + jump;
saved_operand[k + 1] = code_data[target];
}
saved_operand[0] = keys + 1; /* number of successors */
@ -1746,11 +1750,24 @@ static int instruction_length(unsigned char *iptr, unsigned char *end)
/* Given the target of a branch, make sure that it's a legal target. */
static jboolean
isLegalTarget(context_type *context, int offset)
isLegalTarget(context_type *context, int target)
{
int code_length = context->code_length;
int *code_data = context->code_data;
return (offset >= 0 && offset < code_length && code_data[offset] >= 0);
return (target >= 0 && target < code_length && code_data[target] >= 0);
}
/* Given a bci and offset, make sure the offset is valid and the target is legal */
static jboolean
isLegalOffset(context_type *context, int bci, int offset)
{
int code_length = context->code_length;
int *code_data = context->code_data;
int max_offset = 65535; // JVMS 4.11
int min_offset = -65535;
if (offset < min_offset || offset > max_offset) return JNI_FALSE;
int target = bci + offset;
return (target >= 0 && target < code_length && code_data[target] >= 0);
}

View File

@ -41,7 +41,7 @@ import org.xml.sax.SAXNotSupportedException;
/**
* @author Rajiv Mordani
* @author Edwin Goei
* @LastModified: May 2025
* @LastModified: June 2025
*/
public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
/** These are DocumentBuilderFactory attributes not DOM attributes */
@ -59,11 +59,24 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
XMLSecurityManager fSecurityManager;
XMLSecurityPropertyManager fSecurityPropertyMgr;
/**
* Creates a new {@code DocumentBuilderFactory} instance.
*/
public DocumentBuilderFactoryImpl() {
this(null, null);
}
/**
* Creates a new {@code DocumentBuilderFactory} instance with a {@code XMLSecurityManager}
* and {@code XMLSecurityPropertyManager}.
* @param xsm the {@code XMLSecurityManager}
* @param xspm the {@code XMLSecurityPropertyManager}
*/
public DocumentBuilderFactoryImpl(XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) {
JdkXmlConfig config = JdkXmlConfig.getInstance(false);
// security (property) managers updated with current system properties
fSecurityManager = config.getXMLSecurityManager(true);
fSecurityPropertyMgr = config.getXMLSecurityPropertyManager(true);
fSecurityManager = (xsm == null) ? config.getXMLSecurityManager(true) : xsm;
fSecurityPropertyMgr = (xspm == null) ? config.getXMLSecurityPropertyManager(true) : xspm;
}
/**

View File

@ -35,7 +35,7 @@ import jdk.xml.internal.*;
*
* @author Ramesh Mandava
*
* @LastModified: May 2025
* @LastModified: June 2025
*/
public class XPathFactoryImpl extends XPathFactory {
@ -72,6 +72,7 @@ public class XPathFactoryImpl extends XPathFactory {
* The XML security manager
*/
private XMLSecurityManager _xmlSecMgr;
private XMLSecurityPropertyManager _xmlSecPropMgr;
/**
* javax.xml.xpath.XPathFactory implementation.
@ -80,6 +81,7 @@ public class XPathFactoryImpl extends XPathFactory {
JdkXmlConfig config = JdkXmlConfig.getInstance(false);
_xmlSecMgr = config.getXMLSecurityManager(true);
_featureManager = config.getXMLFeatures(true);
_xmlSecPropMgr = config.getXMLSecurityPropertyManager(true);
}
/**
@ -129,7 +131,7 @@ public class XPathFactoryImpl extends XPathFactory {
*/
public javax.xml.xpath.XPath newXPath() {
return new XPathImpl(xPathVariableResolver, xPathFunctionResolver,
!_isNotSecureProcessing, _featureManager, _xmlSecMgr);
!_isNotSecureProcessing, _featureManager, _xmlSecMgr, _xmlSecPropMgr);
}
/**
@ -183,6 +185,7 @@ public class XPathFactoryImpl extends XPathFactory {
if (value && _featureManager != null) {
_featureManager.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION,
JdkProperty.State.FSP, false);
_xmlSecMgr.setSecureProcessing(value);
}
// all done processing feature
@ -338,8 +341,7 @@ public class XPathFactoryImpl extends XPathFactory {
throw new NullPointerException(fmsg);
}
if (_xmlSecMgr != null &&
_xmlSecMgr.setLimit(name, JdkProperty.State.APIPROPERTY, value)) {
if (JdkXmlUtils.setProperty(_xmlSecMgr, _xmlSecPropMgr, name, value)) {
return;
}

View File

@ -36,6 +36,7 @@ import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlConfig;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityPropertyManager;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
@ -50,7 +51,7 @@ import org.xml.sax.InputSource;
* New methods: evaluateExpression
* Refactored to share code with XPathExpressionImpl.
*
* @LastModified: May 2025
* @LastModified: June 2025
*/
public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
@ -62,12 +63,13 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
this(vr, fr, false,
JdkXmlConfig.getInstance(false).getXMLFeatures(false),
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false));
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false),
JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false));
}
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
boolean featureSecureProcessing, JdkXmlFeatures featureManager,
XMLSecurityManager xmlSecMgr) {
XMLSecurityManager xmlSecMgr, XMLSecurityPropertyManager xmlSecPropMgr) {
this.origVariableResolver = this.variableResolver = vr;
this.origFunctionResolver = this.functionResolver = fr;
this.featureSecureProcessing = featureSecureProcessing;
@ -75,6 +77,7 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
overrideDefaultParser = featureManager.getFeature(
JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
this.xmlSecMgr = xmlSecMgr;
this.xmlSecPropMgr = xmlSecPropMgr;
}

View File

@ -31,6 +31,7 @@ import com.sun.org.apache.xpath.internal.axes.LocPathIterator;
import com.sun.org.apache.xpath.internal.objects.XObject;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@ -44,6 +45,7 @@ import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityPropertyManager;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.NodeIterator;
@ -54,7 +56,7 @@ import org.xml.sax.SAXException;
* This class contains several utility methods used by XPathImpl and
* XPathExpressionImpl
*
* @LastModified: Apr 2025
* @LastModified: June 2025
*/
class XPathImplUtil {
XPathFunctionResolver functionResolver;
@ -67,6 +69,7 @@ class XPathImplUtil {
boolean featureSecureProcessing = false;
JdkXmlFeatures featureManager;
XMLSecurityManager xmlSecMgr;
XMLSecurityPropertyManager xmlSecPropMgr;
/**
* Evaluate an XPath context using the internal XPath engine
@ -128,7 +131,12 @@ class XPathImplUtil {
//
// so we really have to create a fresh DocumentBuilder every time we need one
// - KK
DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser);
DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(
overrideDefaultParser, xmlSecMgr, xmlSecPropMgr);
if (xmlSecMgr != null && xmlSecMgr.isSecureProcessingSet()) {
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,
xmlSecMgr.isSecureProcessing());
}
return dbf.newDocumentBuilder().parse(source);
} catch (ParserConfigurationException | SAXException | IOException e) {
throw new XPathExpressionException (e);

View File

@ -445,6 +445,20 @@ public class JdkXmlUtils {
* @return a DocumentBuilderFactory instance.
*/
public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser) {
return getDOMFactory(overrideDefaultParser, null, null);
}
/**
* {@return a DocumentBuilderFactory instance}
*
* @param overrideDefaultParser a flag indicating whether the system-default
* implementation may be overridden. If the system property of the
* DOM factory ID is set, override is always allowed.
* @param xsm XMLSecurityManager
* @param xspm XMLSecurityPropertyManager
*/
public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser,
XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) {
boolean override = overrideDefaultParser;
String spDOMFactory = SecuritySupport.getJAXPSystemProperty(DOM_FACTORY_ID);
@ -453,7 +467,7 @@ public class JdkXmlUtils {
}
DocumentBuilderFactory dbf
= !override
? new DocumentBuilderFactoryImpl()
? new DocumentBuilderFactoryImpl(xsm, xspm)
: DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
// false is the default setting. This step here is for compatibility

View File

@ -244,6 +244,12 @@ public final class XMLSecurityManager implements Cloneable {
*/
boolean secureProcessing;
/**
* Flag indicating the secure processing is set explicitly through factories'
* setFeature method and then the setSecureProcessing method
*/
boolean secureProcessingSet;
/**
* States that determine if properties are set explicitly
*/
@ -340,6 +346,7 @@ public final class XMLSecurityManager implements Cloneable {
* Setting FEATURE_SECURE_PROCESSING explicitly
*/
public void setSecureProcessing(boolean secure) {
secureProcessingSet = true;
secureProcessing = secure;
for (Limit limit : Limit.values()) {
if (secure) {
@ -358,6 +365,15 @@ public final class XMLSecurityManager implements Cloneable {
return secureProcessing;
}
/**
* Returns the state indicating whether the Secure Processing is set explicitly,
* via factories' setFeature and then this class' setSecureProcessing method.
* @return the state indicating whether the Secure Processing is set explicitly
*/
public boolean isSecureProcessingSet() {
return secureProcessingSet;
}
/**
* Finds a limit's new name with the given property name.
* @param propertyName the property name specified

View File

@ -53,6 +53,7 @@ import sun.security.x509.KeyUsageExtension;
import sun.security.x509.SubjectAlternativeNameExtension;
import sun.security.x509.URIName;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.X500Name;
/**
@ -90,7 +91,7 @@ import sun.security.x509.KeyIdentifier;
public class CertificateBuilder {
private final CertificateFactory factory;
private X500Principal subjectName = null;
private X500Name subjectName = null;
private BigInteger serialNumber = null;
private PublicKey publicKey = null;
private Date notBefore = null;
@ -199,7 +200,7 @@ public class CertificateBuilder {
* on this certificate.
*/
public CertificateBuilder setSubjectName(X500Principal name) {
subjectName = name;
subjectName = X500Name.asX500Name(name);
return this;
}
@ -209,7 +210,23 @@ public class CertificateBuilder {
* @param name The subject name in RFC 2253 format
*/
public CertificateBuilder setSubjectName(String name) {
subjectName = new X500Principal(name);
try {
subjectName = new X500Name(name);
} catch (IOException ioe) {
throw new IllegalArgumentException(ioe);
}
return this;
}
/**
* Set the subject name for the certificate. This method is useful when
* you need more control over the contents of the subject name.
*
* @param name an {@code X500Name} to be used as the subject name
* on this certificate
*/
public CertificateBuilder setSubjectName(X500Name name) {
subjectName = name;
return this;
}