From 22600126bef6ad8aa565a61df56efbdc445157e5 Mon Sep 17 00:00:00 2001 From: Christopher Puschmann Date: Sun, 7 Apr 2024 11:36:23 +0200 Subject: [PATCH] fix: Replace DER with ASN1 BER encoding when parsing distinguishedNames (#505) * fix: Replace DER with ASN1 BER encoding when parsing distinguishedNames * Remove leftover comment --- dn.go | 17 +++++------------ dn_test.go | 2 +- v3/dn.go | 17 +++++------------ v3/dn_test.go | 2 +- 4 files changed, 12 insertions(+), 26 deletions(-) diff --git a/dn.go b/dn.go index 39b6833..6520b8e 100644 --- a/dn.go +++ b/dn.go @@ -1,10 +1,10 @@ package ldap import ( - "encoding/asn1" "encoding/hex" "errors" "fmt" + ber "github.com/go-asn1-ber/asn1-ber" "sort" "strings" "unicode" @@ -35,9 +35,6 @@ func (a *AttributeTypeAndValue) setValue(s string) error { // AttributeValue is represented by an number sign ('#' U+0023) // character followed by the hexadecimal encoding of each of the octets // of the BER encoding of the X.500 AttributeValue. - // - // WARNING: we only support hex-encoded ASN.1 DER values here, not - // BER encoding. This is a deviation from the RFC. if len(s) > 0 && s[0] == '#' { decodedString, err := decodeEncodedString(s[1:]) if err != nil { @@ -233,19 +230,15 @@ func encodeString(value string, isValue bool) string { func decodeEncodedString(str string) (string, error) { decoded, err := hex.DecodeString(str) if err != nil { - return "", fmt.Errorf("failed to decode BER encoding: %s", err) + return "", fmt.Errorf("failed to decode BER encoding: %w", err) } - var rawValue asn1.RawValue - result, err := asn1.Unmarshal(decoded, &rawValue) + packet, err := ber.DecodePacketErr(decoded) if err != nil { - return "", fmt.Errorf("failed to unmarshal hex-encoded string: %s", err) - } - if len(result) != 0 { - return "", errors.New("trailing data after unmarshalling hex-encoded string") + return "", fmt.Errorf("failed to decode BER encoding: %w", err) } - return string(rawValue.Bytes), nil + return packet.Data.String(), nil } // ParseDN returns a distinguishedName or an error. diff --git a/dn_test.go b/dn_test.go index f02d4c1..da367d8 100644 --- a/dn_test.go +++ b/dn_test.go @@ -154,7 +154,7 @@ func TestErrorDNParsing(t *testing.T) { "1.3.6.1.4.1.1466.0=test+": "DN ended with incomplete type, value pair", `1.3.6.1.4.1.1466.0=test;`: "DN ended with incomplete type, value pair", "1.3.6.1.4.1.1466.0=test+,": "incomplete type, value pair", - "DF=#6666666666665006838820013100000746939546349182108463491821809FBFFFFFFFFF": "failed to unmarshal hex-encoded string: asn1: syntax error: data truncated", + "DF=#6666666666665006838820013100000746939546349182108463491821809FBFFFFFFFFF": "failed to decode BER encoding: unexpected EOF", } for test, answer := range testcases { diff --git a/v3/dn.go b/v3/dn.go index 39b6833..6520b8e 100644 --- a/v3/dn.go +++ b/v3/dn.go @@ -1,10 +1,10 @@ package ldap import ( - "encoding/asn1" "encoding/hex" "errors" "fmt" + ber "github.com/go-asn1-ber/asn1-ber" "sort" "strings" "unicode" @@ -35,9 +35,6 @@ func (a *AttributeTypeAndValue) setValue(s string) error { // AttributeValue is represented by an number sign ('#' U+0023) // character followed by the hexadecimal encoding of each of the octets // of the BER encoding of the X.500 AttributeValue. - // - // WARNING: we only support hex-encoded ASN.1 DER values here, not - // BER encoding. This is a deviation from the RFC. if len(s) > 0 && s[0] == '#' { decodedString, err := decodeEncodedString(s[1:]) if err != nil { @@ -233,19 +230,15 @@ func encodeString(value string, isValue bool) string { func decodeEncodedString(str string) (string, error) { decoded, err := hex.DecodeString(str) if err != nil { - return "", fmt.Errorf("failed to decode BER encoding: %s", err) + return "", fmt.Errorf("failed to decode BER encoding: %w", err) } - var rawValue asn1.RawValue - result, err := asn1.Unmarshal(decoded, &rawValue) + packet, err := ber.DecodePacketErr(decoded) if err != nil { - return "", fmt.Errorf("failed to unmarshal hex-encoded string: %s", err) - } - if len(result) != 0 { - return "", errors.New("trailing data after unmarshalling hex-encoded string") + return "", fmt.Errorf("failed to decode BER encoding: %w", err) } - return string(rawValue.Bytes), nil + return packet.Data.String(), nil } // ParseDN returns a distinguishedName or an error. diff --git a/v3/dn_test.go b/v3/dn_test.go index f02d4c1..da367d8 100644 --- a/v3/dn_test.go +++ b/v3/dn_test.go @@ -154,7 +154,7 @@ func TestErrorDNParsing(t *testing.T) { "1.3.6.1.4.1.1466.0=test+": "DN ended with incomplete type, value pair", `1.3.6.1.4.1.1466.0=test;`: "DN ended with incomplete type, value pair", "1.3.6.1.4.1.1466.0=test+,": "incomplete type, value pair", - "DF=#6666666666665006838820013100000746939546349182108463491821809FBFFFFFFFFF": "failed to unmarshal hex-encoded string: asn1: syntax error: data truncated", + "DF=#6666666666665006838820013100000746939546349182108463491821809FBFFFFFFFFF": "failed to decode BER encoding: unexpected EOF", } for test, answer := range testcases {