rasn1 icon indicating copy to clipboard operation
rasn1 copied to clipboard

root_options not available for octet string

Open adfoster-r7 opened this issue 1 year ago • 1 comments

Environment

  • [x] Ruby version: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22]
  • [x] rasn1 version: Custom Branch: c41fea550b3d83f40039dba2604035850366c764

Description

Context

I am trying to implement the LDAP DelRequest specification:

4.8. Delete Operation

DelRequest ::= [APPLICATION 10] LDAPDN

https://www.rfc-editor.org/rfc/rfc4511#section-4.8

Example:

MCwCAQJKJ3VpZD1iamVuc2VuLG91PVBlb3BsZSxkYz1leGFtcGxlLGRjPWNvbQ==

Parsed: https://lapo.it/asn1js/#MCwCAQJKJ3VpZD1iamVuc2VuLG91PVBlb3BsZSxkYz1leGFtcGxlLGRjPWNvbQ

Wireshark:

image

Csharp approach: https://github.com/microsoft/WindowsProtocolTestSuites/blob/061e708767b42dfc085356c190f34ee3788f1180/ProtoSDK/MS-ADTS-LDAP/AdtsLdapV2Asn1Codec/DelRequest.cs

What I've tried

I have tried implementing it with rasn1 in various ways:

  1. Try to use root_options
RASN1::Types.define_type('LdapString', from: RASN1::Types::OctetString, in_module: self)
RASN1::Types.define_type('LdapDN', from: LdapString, in_module: self)

class DelRequest < LdapDN
  root_options name: 'DelRequest',
               class: :application,
               implicit: 10
end

# Usage:

class ProtocolOp < LdapModel
  choice model_name,
         content: [
           model(:del_request, DelRequest),
         ]
end

But this approach above gives the following error:

undefined method `root_options' for class Ldap::DelRequest
  1. Trying to use the wrapper approach - but this approach is further away from the original ASN1 specification, and doesn't seem to work either (potentially pebkac):
RASN1::Types.define_type('LdapString', from: RASN1::Types::OctetString, in_module: self)
RASN1::Types.define_type('LdapDN', from: LdapString, in_module: self)

class DelRequest < LdapDN
end

# Usage:

class ProtocolOp < LdapModel
  choice model_name,
         content: [
             wrapper(model(:del_request, DelRequest), implicit: 10, class: :application),
         ]
end

test failure:

       CHOICE protocol_op: no type matching "J'uid=bjensen,ou=People,dc=example,dc=com"

Expected behavior

Parsed successfully:

{
  LdapMessage: {
    message_id: 2,
    protocol_op: {
      del_request: "euid=bjensen,ou=People,dc=example,dc=com"
    }
  }

Actual behavior

For attempt 1 - root_options API is not available for the defined type approach - but it is available for models For attempt 2 - The parsing does not work, potentially pebkac

Suggested fix

Potentially this is a feature request to add root_options to defined types, or there's a maybe in a bug in the wrapper around a OctetString

Code to reproduce

https://github.com/adfoster-r7/rasn1/blob/4671183d66a91617f62cb6f75a84f5b6b9d58542/spec/ldap_spec.rb#L199-L212

Failure:

  1) Ldap Ldap::LdapMessage when a DelRequest is parsed #parse parses the data successfully
     Failure/Error: raise ASN1Error, "CHOICE #{@name}: no type matching #{der.inspect}" unless optional?
     
     RASN1::ASN1Error:
       CHOICE protocol_op: no type matching "J'uid=bjensen,ou=People,dc=example,dc=com"

adfoster-r7 avatar Jan 07 '25 02:01 adfoster-r7

#root_option is a Model method, so it cannot be used on base types.

To handle your case, you should define a model embdedding a single octet string:

class DelRequest < RASN1::Model
  octet_string :DelRequest, implicit: 10, class: :application   # ldap_dn should work too
end

Then, you can use this model in ProtocolOp:

class ProtocolOp < LdapModel
  choice model_name,
         content: [
           model(:del_request, DelRequest),
         ]
end

lemontree55 avatar Jan 13 '25 11:01 lemontree55