Skip to content

Commit

Permalink
[fix] ASN1::EndOfContent ancestor hierarchy
Browse files Browse the repository at this point in the history
also started using @indefinite_length for better compatibility
  • Loading branch information
kares committed May 13, 2022
1 parent 2e7ff4d commit def8609
Showing 1 changed file with 40 additions and 29 deletions.
69 changes: 40 additions & 29 deletions src/main/java/org/jruby/ext/openssl/ASN1.java
Original file line number Diff line number Diff line change
Expand Up @@ -708,19 +708,22 @@ public static void createASN1(final Ruby runtime, final RubyModule OpenSSL, fina
_ASN1Data.addReadWriteAttribute(context, "value");
_ASN1Data.addReadWriteAttribute(context, "tag");
_ASN1Data.addReadWriteAttribute(context, "tag_class");
_ASN1Data.addReadWriteAttribute(context, "indefinite_length");
_ASN1Data.defineAlias( "infinite_length", "indefinite_length");
_ASN1Data.defineAlias( "infinite_length=", "indefinite_length=");
_ASN1Data.defineAnnotatedMethods(ASN1Data.class);

final ObjectAllocator primitiveAllocator = Primitive.ALLOCATOR;
RubyClass Primitive = ASN1.defineClassUnder("Primitive", _ASN1Data, primitiveAllocator);
Primitive.addReadWriteAttribute(context, "tagging");
Primitive.addReadAttribute(context, "infinite_length");
Primitive.undefineMethod("infinite_length=");
Primitive.undefineMethod("indefinite_length=");
Primitive.defineAnnotatedMethods(Primitive.class);

final ObjectAllocator constructiveAllocator = Constructive.ALLOCATOR;
RubyClass Constructive = ASN1.defineClassUnder("Constructive", _ASN1Data, constructiveAllocator);
Constructive.includeModule( runtime.getModule("Enumerable") );
Constructive.addReadWriteAttribute(context, "tagging");
Constructive.addReadWriteAttribute(context, "infinite_length");
Constructive.defineAnnotatedMethods(Constructive.class);

ASN1.defineClassUnder("Boolean", Primitive, primitiveAllocator); // OpenSSL::ASN1::Boolean <=> value is a Boolean
Expand All @@ -747,10 +750,11 @@ public static void createASN1(final Ruby runtime, final RubyModule OpenSSL, fina
ASN1.defineClassUnder("UTCTime", Primitive, primitiveAllocator); // OpenSSL::ASN1::UTCTime <=> value is a Time
ASN1.defineClassUnder("GeneralizedTime", Primitive, primitiveAllocator); // OpenSSL::ASN1::GeneralizedTime <=> value is a Time

ASN1.defineClassUnder("EndOfContent", Primitive, primitiveAllocator); // OpenSSL::ASN1::EndOfContent <=> value is always nil
ASN1.defineClassUnder("EndOfContent", _ASN1Data, asn1DataAllocator). // OpenSSL::ASN1::EndOfContent <=> value is always nil
defineAnnotatedMethods(EndOfContent.class);

RubyClass ObjectId = ASN1.defineClassUnder("ObjectId", Primitive, primitiveAllocator);
ObjectId.defineAnnotatedMethods(ObjectId.class);
ASN1.defineClassUnder("ObjectId", Primitive, primitiveAllocator).
defineAnnotatedMethods(ObjectId.class);

ASN1.defineClassUnder("Sequence", Constructive, Constructive.getAllocator());
ASN1.defineClassUnder("Set", Constructive, Constructive.getAllocator());
Expand Down Expand Up @@ -1361,7 +1365,9 @@ private void checkTag(final Ruby runtime, final IRubyObject tag,
}
}

boolean isEOC() { return false; }
boolean isEOC() {
return "EndOfContent".equals( getClassBaseName() );
}

boolean isExplicitTagging() { return ! isImplicitTagging(); }

Expand Down Expand Up @@ -1412,6 +1418,7 @@ public IRubyObject to_der(final ThreadContext context) {
}

byte[] toDER(final ThreadContext context) throws IOException {
if ( isEOC() ) return new byte[] { 0x00, 0x00 };
return toASN1(context).toASN1Primitive().getEncoded(ASN1Encoding.DER);
}

Expand Down Expand Up @@ -1464,6 +1471,26 @@ static void printArray(final PrintStream out, final int indent, final RubyArray

}

public static class EndOfContent {

private EndOfContent() {}

@JRubyMethod(visibility = Visibility.PRIVATE)
public static IRubyObject initialize(final ThreadContext context, final IRubyObject self) {
final Ruby runtime = context.runtime;
self.getInstanceVariables().setInstanceVariable("@tag", runtime.newFixnum(0));
self.getInstanceVariables().setInstanceVariable("@value", RubyString.newEmptyString(context.runtime));
self.getInstanceVariables().setInstanceVariable("@tag_class", runtime.newSymbol("UNIVERSAL"));
return self;
}

static IRubyObject newInstance(final ThreadContext context) {
RubyClass klass = _ASN1(context.runtime).getClass("EndOfContent");
return klass.newInstance(context, Block.NULL_BLOCK);
}

}

public static class Primitive extends ASN1Data {
private static final long serialVersionUID = 8489625559339190259L;

Expand Down Expand Up @@ -1556,7 +1583,7 @@ static void initializeImpl(final ThreadContext context,
self.setInstanceVariable("@value", value);
self.setInstanceVariable("@tag_class", tag_class);
self.setInstanceVariable("@tagging", tagging);
self.setInstanceVariable("@infinite_length", runtime.getFalse());
self.setInstanceVariable("@indefinite_length", runtime.getFalse());
}

@Override
Expand All @@ -1573,27 +1600,14 @@ boolean isImplicitTagging() {

@Override
boolean isEOC() {
return "EndOfContent".equals( getClassBaseName() );
return false;
}

@Override
byte[] toDER(final ThreadContext context) throws IOException {
if ( isEOC() ) return new byte[] { 0x00, 0x00 };
return toASN1(context).toASN1Primitive().getEncoded(ASN1Encoding.DER);
}

static Primitive newInstance(final ThreadContext context, final String type,
final IRubyObject value) {
RubyClass klass = _ASN1(context.runtime).getClass(type);
final Primitive self = new Primitive(context.runtime, klass);
if ( value != null ) self.setInstanceVariable("@value", value);
return self;
}

static Primitive newEndOfContent(final ThreadContext context) {
return newInstance(context, "EndOfContent", null);
}

/*
private static final Class DERBooleanClass;
static {
Expand Down Expand Up @@ -1756,7 +1770,7 @@ static Constructive newInfiniteConstructive(final ThreadContext context,

final RubyArray values = runtime.newArray(value.size());
for ( final IRubyObject val : value ) values.append(val);
// values.append( Primitive.newEndOfContent(context) );
// values.append( EndOfContent.newInstance(context) );

self.setInstanceVariable("@tag", runtime.newFixnum(defaultTag));
self.setInstanceVariable("@value", values);
Expand All @@ -1768,11 +1782,9 @@ static Constructive newInfiniteConstructive(final ThreadContext context,

static Constructive setInfiniteLength(final ThreadContext context, final IRubyObject constructive) {
final Constructive instance = ((Constructive) constructive);
final IRubyObject eoc = Primitive.newEndOfContent(context);
final IRubyObject value = instance.value(context);
if ( value instanceof RubyArray ) ((RubyArray) value).append(eoc);
else value.callMethod(context, "<<", eoc);
instance.setInstanceVariable("@infinite_length", context.runtime.getTrue());
value.callMethod(context, "<<", EndOfContent.newInstance(context));
instance.setInstanceVariable("@indefinite_length", context.runtime.getTrue());
return instance;
}

Expand All @@ -1789,7 +1801,7 @@ private boolean isSet() {
}

private boolean isInfiniteLength() {
return getInstanceVariable("@infinite_length").isTrue();
return getInstanceVariable("@indefinite_length").isTrue();
}

@Override
Expand Down Expand Up @@ -1838,8 +1850,7 @@ public IRubyObject to_der(final ThreadContext context) {
if ( rawConstructive() ) { // MRI compatibility
if ( ! isInfiniteLength() && ! super.value(context).isNil() ) {
final Ruby runtime = context.runtime;
throw newASN1Error(runtime, "Constructive shall only be used"
+ " with infinite length");
throw newASN1Error(runtime, "Constructive shall only be used with indefinite length");
}
}
return super.to_der(context);
Expand Down

0 comments on commit def8609

Please sign in to comment.