package require asn
namespace eval asn {
namespace eval util {
proc string2hex {string} {
binary scan $string H* t
set res [regexp -inline -all {..} $t]
return [join $res " "]
}
}
# array with the implicit tags definitions
# format:
# tag {type {implicit tag} {decoding proc}}
# this should really be stored in a tree-like structure
array set tags {
02 { INTEGER {} asnGetInteger}
04 { OCTETSTRING {} asnGetOctetString}
05 { NULL {} decodeNull}
06 { {OBJECT IDENTIFIER} {} asnGetObjectIdentifier}
30 { SEQUENCE {} decodeSequence}
40 { NetworkAddress {} asnGetNetworkAddress}
41 { Counter32 02 {}}
43 { TimeTicks 02 {}}
A0 { GetRequest-PDU 30 {}}
A1 { GetNextRequest-PDU 30 {}}
A2 { GetResponse-PDU 30 {}}
A3 { SetRequest-PDU 30 {}}
A4 { Trap-PDU 30 {}}
A6 { InformRequest-PDU 30 {}}
A7 { SNMPv2-Trap-PDU 30 {}}
}
proc decodeBer {raw} {
variable tags
asnPeekByte raw tag
set tag [format %02X $tag]
if {[info exists tags($tag)] } {
set tagInfo $tags($tag)
set type [lindex $tagInfo 0]
set implicitTag [lindex $tagInfo 1]
while {$implicitTag ne {}} {
# if we are handling an implicit type,
# find the corresponding type it derived from that has a decode proc
set tagInfo $tags($implicitTag)
if {[lindex $tagInfo end] ne {}} {
asnRetag raw [expr "0x$implicitTag"]
break
}
set implicitTag [lindex $tagInfo 1]
}
[lindex $tagInfo end] raw res
return [list $type $res]
} else {
asnGetByte raw tag
asnGetLength raw length
asnGetBytes raw $length value
return [list $tag [util::string2hex $value] ]
}
}
proc asnGetTLV { data_var tlv_var } {
# gets a tag/length/value from the start of the data.
# return false if no data available, true if succesful
upvar $data_var data $tlv_var tlv
if {[string length $data] < 2} {
return false
}
asnGetByte data tag
asnGetLength data length
asnGetBytes data $length temp
set tlv [asnTLV $tag $temp]
return true
}
proc asnTLV {tag value} {
set len [string length $value]
return [binary format H2a*a$len [format %02X $tag] [asnLength $len] $value]
}
proc decodeSequence {data res} {
upvar $data raw
upvar $res result
asnGetSequence raw sequence
while {[asnGetTLV sequence element]} {
lappend result [decodeBer $element]
}
return
}
proc decodeNull {data res} {
# we need this proc because asnGetNull takes only one argument
upvar $data raw
upvar $res result
asnGetNull raw
set result {}
return
}
proc asnGetNetworkAddress {data res} {
upvar $data raw
upvar $res result
asnGetByte raw dummy
asnGetByte raw length
asnGetBytes raw $length address
foreach number [split $address ""] {
lappend result [scan $number %c]
}
return
}
}
package provide ber 0.1Sample usage for an SNMPv1 trap PDU
package require base64
set trap [join {MIGXAgEABAZwdWJsaWOkgYkGCCsGAQQBgo17QATAqAAzAgEGAgID6EMBZDBtMBoGDCsFAQQBgo17?\
AQbOEAQKbG9jYWxob3N0IDBPBgwrBQEEAYKNewEGzhEEPyBzdShwYW1fdW5peClbMjUxMTVdOiBz?\
ZXNzaW9uIG9wZW5lZCBmb3IgdXNlciByb290IGJ5ICh1aWQ9NTAwKQ==} {}]
::asn::decodeBer [base64::decode $trap]gives:
SEQUENCE {{INTEGER 0} {OCTETSTRING public} {Trap-PDU {{{OBJECT IDENTIFIER} {1 3 6 1 4 1 34555}}\
{IpAddress {192 168 0 51}} {INTEGER 6} {INTEGER 1000} {TimeTicks 100}\
{SEQUENCE {{SEQUENCE {{{OBJECT IDENTIFIER} {1 3 5 1 4 1 34555 1 6 10000}} {OCTETSTRING {localhost }}}}\
{SEQUENCE {{{OBJECT IDENTIFIER} {1 3 5 1 4 1 34555 1 6 10001}}\
{OCTETSTRING { su(pam_unix)[25115]: session opened for user root by (uid=500)}}}}}}}}}MJ - 14-03-2007: Removed a lot of the redundancy when handling the implicit types.
| Category Parsing | Category Example | Category Networking | Category Package |
|---|

