ASN1::element

Description

This command returns ASN1.1 record elements from the data in the transport layer (TCP, UDP, or SCTP) payload.

Syntax

ASN1::element init encodingType
ASN1::element next element ?numberOfElements?
ASN1::element byte_offset element ?offset?
ASN1::element tag element
ASN1::element size element
ASN1::element length element ?length?

ASN1::element init encodingType

  • Returns an element (Tcl_Obj) handle used by the remaining commands. encodingType specifies the encoding type that subsequent commands should use (BER|DER).

ASN1::element next element ?numberOfElements?

  • Returns the next element found after element. If numberOfElements is specified, the command will move ahead that many elements, otherwise, the default is 1.

ASN1::element byte_offset element ?offset?

  • Returns the byte offset within the payload. This is often useful when using the encode command along with the TCP::payload replace command where a byte offset is used to indicate the location within the payload. If offset is specified, the element offset is set to the specified value. Changing the byte offset is generally discouraged and should be done with caution as it affects the behavior of any other command which takes an element object as an argument.

ASN1::element tag element

  • Returns the id (integer) of the leading tag found in element.

ASN1::element size element

  • Returns the size (in number of bytes) of the element’s full TLV. This is useful for passing to TCP::release.

ASN1::element length element ?length?

  • Returns the length (in number of bytes) of the element’s value. This is the L coded in the TLV. If length is specified, the length of the element is modified. Changing the byte offset is generally discouraged and should be done with caution as it could affect the behvior of any other command which takes an element object as an argument.

Examples

Shorter version of the binary scan experience discussed in https://devcentral.f5.com/tech-tips/articles/unbind-your-ldap-servers-with-irules:
when CLIENT_ACCEPTED {
  TCP::collect
}
when CLIENT_DATA {
 set ele [ASN1::element init BER]
  # Skip ahead two elements and check for an unbind tag (0x62)
  if { [ASN1::element tag [ASN1::element next $ele 2]] == 0x62 } {
    log local0. "unbind => detach"
    TCP::payload replace 0 [TCP::payload length] ""
    LB::detach
  }
  TCP::release
  TCP::collect
}
LDAP bindRequest:
when CLIENT_ACCEPTED {
  TCP::collect
}
when CLIENT_DATA {
  set ldap_msg [ASN1::element init BER]
  set ele [ASN1::element next $ldap_msg 2]
  set tag [ASN1::element tag $ele]

  if { $tag == 0x60} {  # bindRequest
    # Offset of the version number
    set version_ele [ASN1::element next $ele]
    set offset [ASN1::element byte_offset $version_ele]

    # Set the version to v2
    set buf [ASN1::encode BER "i" 0x02]
    set size [ASN1::element size $version_ele]

    # Replace the original version TLV
    TCP::payload replace $offset $size $buf
  }
  TCP::release
  TCP::collect
}

Since data is pulled from the transport layer payload, to decode data contained within an SSL stream (for example for use with ldaps), create a second virtual server with a clientssl profile, and apply an iRule to it that switches to the TCP server after pulling off the SSL layer:
ltm virtual ldap {
  destination 1.2.3.4:389
  ip-protocol tcp
  profiles { tcp }
  rule { the_asn1_rule_above }
}

ltm virtual ldap-ssl {
   destination 1.2.3.4:636
   ip-protocol tcp
   profiles { tcp clientssl }
   rule { send-to-ldap }
}

ltm rule send-to-ldap {
   when CLIENT_ACCEPTED {
      virtual ldap
   }
}