Skip to content

JRuby-OpenSSL does not decode DERApplicationSpecific objects #36

@mjstrasser

Description

@mjstrasser

I have an LDAP stub server implemented using ruby-ldapserver that I use in performance testing. It works with MRI Ruby but it fails under JRuby (I need to run it on a Solaris host where a suitable native Ruby is not available). The library uses OpenSSL to decode the ASN.1 data structures sent by clients.

I was unable to perform an LDAP bind with the server. I created https://github.com/inscitiv/ruby-ldapserver/issues/3 where I documented what I know so far. (Please ignore the first comments about how IntelliJ IDEA shows byte arrays in MRI Ruby vs. JRuby. That is a red herring.)

The first error message includes unable to decode object: org.bouncycastle.asn1.DERApplicationSpecific.

@dividedmind suggested an addition to ASN1.decodeObject method, but when I tried that I didn’t get much further. I think neither of us is confident we got it right. I am now stuck with the next IO#read not returning and am not sure what to do.

I don’t know which ASN.1 data structures the LDAP bind message conveys so I am not sure what to fix. Any advice will be greatly appreciated.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/9613040-jruby-openssl-does-not-decode-derapplicationspecific-objects?utm_campaign=plugin&utm_content=tracker%2F136995&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F136995&utm_medium=issues&utm_source=github).

Activity

kares

kares commented on Mar 16, 2015

@kares
Member

Hi Michael, I've struggled to get ASN.1 somehow "more-compatible" with MRI recently ... been hitting limitations of what can be done with the underlying (bouncy-castle) APIs -but the changes mentioned at inscitiv/ruby-ldapserver#3 seems good, you should try running our test suite with those and/or possibly extracting the OpenSSL behaviour's from the ldapserver into a test-case or at least pieces of code, that way I can take a quick look (without an LDAP server) if we're able to get this fixes easily. Thanks for reporting!

mjstrasser

mjstrasser commented on Mar 18, 2015

@mjstrasser
Author

Hi Karol, I have done a bit more work in the LDAP context and found the following.

This LDAP bind request:

ldapsearch -D "o=Telstra" -w ess -b "msisdn=61414284256,o=Telstra" "(objectClass=*)"

first sends this array of 26 bytes to perform an LDAP bind:

"0\x18\x02\x01\x01`\x13\x02\x01\x03\x04\to=Telstra\x80\x03ess"

I think this deconstructs as follows:

48, 24, (SEQUENCE in 24 octets)
  2, 1, 1, (INTEGER value 1 = incrementing message counter)
  96, 19, (Application Constructed in 19 octets, tag 0 = LDAP bind)
    2, 1, 3, (INTEGER value 3 = LDAP version)
    4, 9, 111, 61, 84, 101, 108, 115, 116, 114, 97, (OCTET STRING value "o=Telstra")
    -128, 3, 101, 115, 115 (Context-specific in 3 octets, value "ess")

Debugging Ruby-LDAPServer under MRI Ruby and OpenSSL, the Application Constructed (96 = 01100000) data structure is returned with three elements (in a Ruby array):

  1. OpenSSL::ASN1::Integer : tag=2, tag_class=UNIVERSAL, value=3
  2. OpenSSL::ASN1::OctetString : tag=4, tag_class=UNIVERSAL, value="o=Telstra"
  3. OpenSSL::ASN1::ASN1Data : tag=0, tag_class=CONTEXT_SPECIFIC, value="ess"

Under JRuby and JRuby-OpenSSL (with my added code for DERApplicationSpecific objects) the array is mostly the same, except that third element has a value of OpenSSL::ASN1::OctetString instead of a Ruby string. The next read on the IO object never returns.

Does this shed some light on what the org.jruby.ext.openssl.ASN1 class might need to do to decode this correctly?

In this code:

        if ( obj instanceof DERApplicationSpecific) {
            final DERApplicationSpecific appSpecific = (DERApplicationSpecific) obj;
            IRubyObject tag = runtime.newFixnum(appSpecific.getApplicationTag());
            IRubyObject tag_class = runtime.newSymbol("APPLICATION");
            final ASN1Sequence sequence = (ASN1Sequence) appSpecific.getObject(SEQUENCE);
            final RubyArray valArr = decodeObjects(context, ASN1, sequence.getObjects());
            return ASN1.getClass("ASN1Data").callMethod(context, "new",
                new IRubyObject[] { valArr, tag, tag_class }
            );
        }

I wonder if SEQUENCE is the correct argument to getObject() but am not sure what the alternative could be.

self-assigned this
on Mar 20, 2015
kares

kares commented on Mar 20, 2015

@kares
Member

put your patches in (as they do not break anything) ... I'm able to HACK decoding the MRI way but I'm really not sure whether it's not too specific to your case. wasted too much of my life on trying to understand OpenSSL's ASN.1 logic :) and I really do not care except for helping others ... so I recommend you pick this up where I left if you really need it. also you might be able to come up with more encoding-decoding cases.

mjstrasser

mjstrasser commented on Mar 22, 2015

@mjstrasser
Author

Hi Karol, I have an alternative for my need – an LDAP stub server for performance testing. I found I can use a pure Ruby solution by modifying the example LDAP server provided with the net-ldap gem.

Once I learn better how ASN.1 works I will attempt to apply that to JRuby-OpenSSL.

kares

kares commented on Mar 22, 2015

@kares
Member

@mjstrasser excellent, thanks for the update!

removed their assignment
on Jul 7, 2016
kares

kares commented on Jul 25, 2025

@kares
Member

expected to be resolved with #265 (available in jruby-openssl >= 0.15.5)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @kares@mjstrasser

        Issue actions

          JRuby-OpenSSL does not decode DERApplicationSpecific objects · Issue #36 · jruby/jruby-openssl