Skip to content

Commit 1ad07c1

Browse files
committed
[fix] handle invalid type when creating X509::Name
1 parent 8702c89 commit 1ad07c1

File tree

3 files changed

+53
-26
lines changed

3 files changed

+53
-26
lines changed

src/main/java/org/jruby/ext/openssl/ASN1.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,11 @@ static Class<? extends ASN1Encodable> typeClass(final int typeId) {
633633
return (Class<? extends ASN1Encodable>) ASN1_INFO[typeId][1];
634634
}
635635

636+
static Class<? extends ASN1Encodable> typeClassSafe(final int typeId) {
637+
if (typeId >= ASN1_INFO.length || typeId < 0) return null;
638+
return typeClass(typeId);
639+
}
640+
636641
static ASN1Encodable typeInstance(Class<? extends ASN1Encodable> type, Object value)
637642
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
638643
Method getInstance = null;

src/main/java/org/jruby/ext/openssl/X509Name.java

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public X509Name(Ruby runtime, RubyClass type) {
167167

168168
private final List<ASN1ObjectIdentifier> oids;
169169
private final List<ASN1Encodable> values; // <ASN1String>
170-
private final List<RubyInteger> types;
170+
private final List<Integer> types;
171171

172172
private transient X500Name name;
173173
private transient X500Name canonicalName;
@@ -239,17 +239,14 @@ private void addType(final Ruby runtime, final ASN1Encodable value) {
239239
this.name = null; // NOTE: each fromX factory calls this ...
240240
this.canonicalName = null;
241241
final Integer type = ASN1.typeId(value);
242-
if ( type == null ) {
242+
if (type == null) {
243243
warn(runtime.getCurrentContext(), this + " addType() could not resolve type for: " +
244244
value + " (" + (value == null ? "" : value.getClass().getName()) + ")");
245-
((List) this.types).add( runtime.getNil() );
246-
}
247-
else {
248-
this.types.add( runtime.newFixnum( type.intValue() ) );
249245
}
246+
this.types.add(type);
250247
}
251248

252-
private void addEntry(ASN1ObjectIdentifier oid, RubyString value, RubyInteger type) throws RuntimeException {
249+
private void addEntry(ASN1ObjectIdentifier oid, RubyString value, final int type) throws RuntimeException {
253250
this.name = null;
254251
this.canonicalName = null;
255252
this.oids.add(oid);
@@ -279,9 +276,7 @@ public IRubyObject initialize(final ThreadContext context, IRubyObject dn, IRuby
279276
if ( dn instanceof RubyArray ) {
280277
RubyArray ary = (RubyArray) dn;
281278

282-
final RubyClass _Name = _Name(runtime);
283-
284-
if ( template.isNil() ) template = _Name.getConstant("OBJECT_TYPE_TEMPLATE");
279+
if (template.isNil()) template = _Name(runtime).getConstant("OBJECT_TYPE_TEMPLATE");
285280

286281
for (int i = 0; i < ary.size(); i++) {
287282
IRubyObject obj = ary.eltOk(i);
@@ -297,8 +292,7 @@ public IRubyObject initialize(final ThreadContext context, IRubyObject dn, IRuby
297292
value = arr.size() > 1 ? arr.eltOk(1) : context.nil;
298293
type = arr.size() > 2 ? arr.eltOk(2) : context.nil;
299294

300-
if (type.isNil()) type = template.callMethod(context, "[]", name);
301-
if (type.isNil()) type = _Name.getConstant("DEFAULT_OBJECT_TYPE");
295+
if (type.isNil()) type = getDefaultType(context, name, template);
302296

303297
add_entry(context, name, value, type);
304298
}
@@ -343,7 +337,7 @@ else if ( obj instanceof ASN1Set ) {
343337

344338
@JRubyMethod
345339
public IRubyObject add_entry(ThreadContext context, IRubyObject oid, IRubyObject value) {
346-
return add_entry(context, oid, value, null);
340+
return add_entry(context, oid, value, context.nil);
347341
}
348342

349343
@JRubyMethod
@@ -353,7 +347,7 @@ public IRubyObject add_entry(final ThreadContext context,
353347

354348
final RubyString oidStr = oid.asString();
355349

356-
if ( type == null || type.isNil() ) type = getDefaultType(context, oidStr);
350+
if ( type.isNil() ) type = getDefaultType(context, oidStr);
357351

358352
final ASN1ObjectIdentifier objectId;
359353
try {
@@ -365,22 +359,30 @@ public IRubyObject add_entry(final ThreadContext context,
365359
// NOTE: won't reach here :
366360
if ( objectId == null ) throw newNameError(runtime, "invalid field name");
367361

362+
final int typeInt = type.convertToInteger().getIntValue();
363+
if (ASN1.typeClassSafe(typeInt) == null) {
364+
throw newNameError(runtime, "invalid type: " + typeInt);
365+
}
366+
368367
try {
369-
addEntry(objectId, value.asString(), (RubyInteger) type);
368+
addEntry(objectId, value.asString(), typeInt);
370369
}
371370
catch (RuntimeException e) {
371+
debugStackTrace(runtime, e);
372372
String msg = e.getMessage(); // X509DefaultEntryConverted: "can't recode value for oid " + oid.getId()
373373
throw newNameError(runtime, msg == null ? "invalid value" : msg, e);
374374
}
375375
return this;
376376
}
377377

378-
private static IRubyObject getDefaultType(final ThreadContext context, final RubyString oid) {
379-
IRubyObject template = _Name(context.runtime).getConstant("OBJECT_TYPE_TEMPLATE");
380-
if ( template instanceof RubyHash ) {
381-
return ((RubyHash) template).op_aref(context, oid);
382-
}
383-
return template.callMethod(context, "[]", oid);
378+
private IRubyObject getDefaultType(final ThreadContext context, final RubyString oid) {
379+
return getDefaultType(context, oid, _Name(context.runtime).getConstant("OBJECT_TYPE_TEMPLATE"));
380+
}
381+
382+
private IRubyObject getDefaultType(final ThreadContext context, final IRubyObject oid, final IRubyObject template) {
383+
final IRubyObject type = template instanceof RubyHash ?
384+
((RubyHash) template).op_aref(context, oid) : template.callMethod(context, "[]", oid);
385+
return type.isNil() ? _Name(context.runtime).getConstant("DEFAULT_OBJECT_TYPE") : type;
384386
}
385387

386388
@SuppressWarnings("unchecked")
@@ -496,19 +498,18 @@ public RubyArray to_a() {
496498
final Ruby runtime = getRuntime();
497499
final RubyArray entries = runtime.newArray( oids.size() );
498500
final Iterator<ASN1ObjectIdentifier> oidsIter = oids.iterator();
499-
@SuppressWarnings("unchecked")
500-
final Iterator<Object> valuesIter = (Iterator) values.iterator();
501-
final Iterator<RubyInteger> typesIter = types.iterator();
501+
final Iterator<ASN1Encodable> valuesIter = values.iterator();
502+
final Iterator<Integer> typesIter = types.iterator();
502503
while ( oidsIter.hasNext() ) {
503504
final ASN1ObjectIdentifier oid = oidsIter.next();
504505
String oName = name(runtime, oid);
505506
if ( oName == null ) oName = oid.toString();
506507
final String value = valuesIter.next().toString();
507-
final IRubyObject type = typesIter.next();
508+
final Integer type = typesIter.next();
508509
final IRubyObject[] entry = new IRubyObject[] {
509510
StringHelper.newUTF8String(runtime, oName),
510511
StringHelper.newUTF8String(runtime, value),
511-
type
512+
type == null ? runtime.getNil() : runtime.newFixnum(type)
512513
};
513514
entries.append( runtime.newArrayNoCopy(entry) );
514515
}

src/test/ruby/x509/test_x509name.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,27 @@ def test_new_from_der
6868
assert_equal [["DC", "org", 22], ["DC", "ruby-lang", 22], ["CN", "TestCA", 12]], name.to_a
6969
end
7070

71+
def test_new_with_type
72+
name = OpenSSL::X509::Name.new [['CN', 'a foo', OpenSSL::ASN1::PRINTABLESTRING],
73+
['DC', 'bar', OpenSSL::ASN1::UTF8STRING],
74+
['DC', 'bar.baz']]
75+
assert_equal [["CN", "a foo", OpenSSL::ASN1::PRINTABLESTRING],
76+
["DC", "bar", OpenSSL::ASN1::UTF8STRING],
77+
["DC", "bar.baz", 22]
78+
], name.to_a
79+
assert_equal [["CN", "foo", 12]], OpenSSL::X509::Name.new([['CN', 'foo', nil]]).to_a
80+
end
81+
82+
def test_new_with_invalid_type
83+
begin
84+
OpenSSL::X509::Name.new [['CN', 'foo', 111], ['DC', 'bar.baz']]
85+
fail 'NameError expected'
86+
rescue OpenSSL::X509::NameError => e
87+
# MRI: "X509_NAME_add_entry_by_txt: nested asn1 error"
88+
assert e
89+
end
90+
end
91+
7192
def test_hash_empty
7293
name = OpenSSL::X509::Name.new
7394
assert_equal 4003674586, name.hash

0 commit comments

Comments
 (0)