From ecefa12e59eecff512d2401cb881228db2709ee8 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Tue, 21 Jan 2020 14:38:32 -0500 Subject: [PATCH 01/10] Change Value.Number from a signed int to an unsigned it --- debug/debug.go | 4 ++-- dictionary/dictionary.go | 2 +- dictionary/parser.go | 4 ++-- dictionarygen/attributes.go | 2 +- dictionarygen/generator.go | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/debug/debug.go b/debug/debug.go index 7a756ae..24c1386 100644 --- a/debug/debug.go +++ b/debug/debug.go @@ -92,7 +92,7 @@ func dumpAttrs(w io.Writer, c *Config, p *radius.Packet) { case dictionary.AttributeInteger: switch len(attr) { case 4: - intVal := int(binary.BigEndian.Uint32(attr)) + intVal := uint(binary.BigEndian.Uint32(attr)) if dictAttr != nil { var matchedNames []string for _, value := range dictionary.ValuesByAttribute(searchValues, dictAttr.Name) { @@ -106,7 +106,7 @@ func dumpAttrs(w io.Writer, c *Config, p *radius.Packet) { break } } - attrStr = strconv.Itoa(intVal) + attrStr = strconv.FormatUint(uint64(intVal), 10) case 8: attrStr = strconv.Itoa(int(binary.BigEndian.Uint64(attr))) } diff --git a/dictionary/dictionary.go b/dictionary/dictionary.go index 057d77b..5fb5657 100644 --- a/dictionary/dictionary.go +++ b/dictionary/dictionary.go @@ -213,7 +213,7 @@ func (a *Attribute) GoString() string { type Value struct { Attribute string Name string - Number int + Number uint } type Vendor struct { diff --git a/dictionary/parser.go b/dictionary/parser.go index d25b5de..6d0f1de 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -424,11 +424,11 @@ func (p *Parser) parseValue(f []string) (*Value, error) { Name: f[2], } - number, err := strconv.ParseInt(f[3], 10, 32) + number, err := strconv.ParseUint(f[3], 10, 32) if err != nil { return nil, err } - value.Number = int(number) + value.Number = uint(number) return value, nil } diff --git a/dictionarygen/attributes.go b/dictionarygen/attributes.go index 0d27a9d..44b52e5 100644 --- a/dictionarygen/attributes.go +++ b/dictionarygen/attributes.go @@ -873,7 +873,7 @@ func (g *Generator) genAttributeInteger(w io.Writer, attr *dictionary.Attribute, p(w, `const (`) for _, value := range values { valueIdent := identifier(value.Name) - p(w, ` `, ident, `_Value_`, valueIdent, ` `, ident, ` = `, strconv.Itoa(value.Number)) + p(w, ` `, ident, `_Value_`, valueIdent, ` `, ident, ` = `, strconv.FormatUint(uint64(value.Number), 10)) } p(w, `)`) } diff --git a/dictionarygen/generator.go b/dictionarygen/generator.go index 11b8955..c7658b1 100644 --- a/dictionarygen/generator.go +++ b/dictionarygen/generator.go @@ -292,7 +292,7 @@ func (g *Generator) Generate(dict *dictionary.Dictionary) ([]byte, error) { for _, value := range exAttr.Values { attrIdent := identifier(value.Attribute) valueIdent := identifier(value.Name) - p(&w, ` `, attrIdent, `_Value_`, valueIdent, ` `, attrIdent, ` = `, strconv.Itoa(value.Number)) + p(&w, ` `, attrIdent, `_Value_`, valueIdent, ` `, attrIdent, ` = `, strconv.FormatUint(uint64(value.Number), 10)) } p(&w, `)`) } From 844e4ddf902739ee1aa2c612a36941966c509e21 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Tue, 21 Jan 2020 14:44:17 -0500 Subject: [PATCH 02/10] Trim whitespace in front of the line --- dictionary/parser.go | 1 + dictionary/testdata/simple.dictionary | 3 +++ 2 files changed, 4 insertions(+) diff --git a/dictionary/parser.go b/dictionary/parser.go index 6d0f1de..4b34aae 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -62,6 +62,7 @@ func (p *Parser) parse(dict *Dictionary, parsedFiles map[string]struct{}, f File lineNo := 1 for ; s.Scan(); lineNo++ { line := s.Text() + line = strings.TrimLeft(line, " ") if idx := strings.IndexByte(line, '#'); idx >= 0 { line = line[:idx] } diff --git a/dictionary/testdata/simple.dictionary b/dictionary/testdata/simple.dictionary index 01b82c6..abb3a40 100644 --- a/dictionary/testdata/simple.dictionary +++ b/dictionary/testdata/simple.dictionary @@ -1,6 +1,9 @@ ATTRIBUTE User-Name 1 string ATTRIBUTE User-Password 2 octets encrypt=1 +#Skip comment + #Skip comment with spaces in front + ATTRIBUTE Mode 127 integer VALUE Mode Full 1 VALUE Mode Half 2 From fdfb9cb13d4d768504dba4f47b5502b0938226e0 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Tue, 21 Jan 2020 15:06:17 -0500 Subject: [PATCH 03/10] New func Vendor.Equals --- dictionary/dictionary.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dictionary/dictionary.go b/dictionary/dictionary.go index 5fb5657..ad912c8 100644 --- a/dictionary/dictionary.go +++ b/dictionary/dictionary.go @@ -227,6 +227,18 @@ type Vendor struct { Values []*Value } +func (a *Vendor) Equals(b *Vendor) bool { + if a == b { + return true + } + + if a == nil || b == nil { + return false + } + + return a.Name == b.Name && a.Number == a.Number +} + func (v *Vendor) GetTypeOctets() int { if v.TypeOctets == nil { return 1 From 39c4850844201e5fca0a6c12c0baeb5b9dcc416b Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Tue, 21 Jan 2020 15:12:01 -0500 Subject: [PATCH 04/10] Allow the same vendor id to have different names --- dictionary/parser.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/dictionary/parser.go b/dictionary/parser.go index 4b34aae..2525b79 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -135,18 +135,10 @@ func (p *Parser) parse(dict *Dictionary, parsedFiles map[string]struct{}, f File } } - if existing := vendorByNameOrNumber(dict.Vendors, vendor.Name, vendor.Number); existing != nil { - return &ParseError{ - Inner: &DuplicateVendorError{ - Vendor: vendor, - }, - File: f, - Line: lineNo, - } + if existing := vendorByNameOrNumber(dict.Vendors, vendor.Name, vendor.Number); existing == nil || !vendor.Equals(existing) { + dict.Vendors = append(dict.Vendors, vendor) } - dict.Vendors = append(dict.Vendors, vendor) - case len(fields) == 2 && fields[0] == "BEGIN-VENDOR": // TODO: support RFC 6929 extended VSA? From df0bd4fdd8f5ab416c52dbf12384579a2505fea1 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Tue, 21 Jan 2020 15:39:05 -0500 Subject: [PATCH 05/10] Allow hex decimal numbers to be used as values --- dictionary/parser.go | 9 ++++++++- dictionary/parser_test.go | 5 +++++ dictionary/testdata/simple.dictionary | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/dictionary/parser.go b/dictionary/parser.go index 2525b79..5045d9c 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -417,7 +417,14 @@ func (p *Parser) parseValue(f []string) (*Value, error) { Name: f[2], } - number, err := strconv.ParseUint(f[3], 10, 32) + numStr := f[3] + base := 10 + if len(numStr) > 2 && (numStr[0] == '0' && (numStr[1] == 'x' || numStr[1] == 'X')) { + base = 16 + numStr = numStr[2:] + } + + number, err := strconv.ParseUint(numStr, base, 32) if err != nil { return nil, err } diff --git a/dictionary/parser_test.go b/dictionary/parser_test.go index 58717a2..eff8415 100644 --- a/dictionary/parser_test.go +++ b/dictionary/parser_test.go @@ -80,6 +80,11 @@ func TestParser(t *testing.T) { Name: "Half", Number: 2, }, + { + Attribute: "Mode", + Name: "Quarter", + Number: 4, + }, }, } diff --git a/dictionary/testdata/simple.dictionary b/dictionary/testdata/simple.dictionary index abb3a40..37f4229 100644 --- a/dictionary/testdata/simple.dictionary +++ b/dictionary/testdata/simple.dictionary @@ -7,5 +7,6 @@ ATTRIBUTE User-Password 2 octets encrypt=1 ATTRIBUTE Mode 127 integer VALUE Mode Full 1 VALUE Mode Half 2 +VALUE Mode Quarter 0x4 ATTRIBUTE ARAP-Challenge-Response 84 octets[8] From 493829d2f68d7247c1ddf0fe3dc6c7f1947fa3ed Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Wed, 22 Jan 2020 13:08:34 -0500 Subject: [PATCH 06/10] Allow hex in attribute OID --- dictionary/parser.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dictionary/parser.go b/dictionary/parser.go index 5045d9c..1053070 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -269,6 +269,16 @@ func (p *Parser) ParseFile(filename string) (*Dictionary, error) { func parseOID(s string) OID { var o OID + if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { + num, err := strconv.ParseInt(s[2:], 16, 32) + if err != nil { + return nil + } + + o = append(o, int(num)) + return o + } + for i, ch := range s { switch ch { case '.': From 15d452d86845157d8228c3f9091aa4c60d3d42b1 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Wed, 22 Jan 2020 13:18:15 -0500 Subject: [PATCH 07/10] Add support for the freeradius virtual flag --- dictionary/parser.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dictionary/parser.go b/dictionary/parser.go index 1053070..ec22d45 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -408,6 +408,8 @@ func (p *Parser) parseAttribute(f []string) (*Attribute, error) { Valid: true, Bool: true, } + case f == "virtual": + continue default: return nil, &UnknownAttributeFlagError{ Flag: f, From e72a68adddf8875a1f6cc6a629ccf283734ad957 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Wed, 22 Jan 2020 13:22:13 -0500 Subject: [PATCH 08/10] Support the freeradius style format= --- dictionary/parser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dictionary/parser.go b/dictionary/parser.go index ec22d45..2fe7c8a 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -462,7 +462,7 @@ func (p *Parser) parseVendor(f []string) (*Vendor, error) { // "format=t,l" // t ∈ [1, 2, 4] // l ∈ [0, 1, 2] - if !strings.HasPrefix(f[3], "format=") || len(f[3]) != 10 || f[3][8] != ',' || (f[3][7] != '1' && f[3][7] != '2' && f[3][7] != '4') || (f[3][9] < '0' && f[3][9] > '2') { + if !strings.HasPrefix(f[3], "format=") || len(f[3]) < 10 || f[3][8] != ',' || (f[3][7] != '1' && f[3][7] != '2' && f[3][7] != '4') || (f[3][9] < '0' || f[3][9] > '2') { return nil, &InvalidVendorFormatError{ Format: f[3], } From eb3194226e16a94cc6094c939daf789d671fbfe2 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Wed, 22 Jan 2020 13:24:48 -0500 Subject: [PATCH 09/10] Add support for ignoring unknown attribute types --- dictionary/parser.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dictionary/parser.go b/dictionary/parser.go index 2fe7c8a..4401c71 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -40,7 +40,8 @@ type Parser struct { // IgnoreIdenticalAttributes specifies whether identical attributes are // ignored, rather than a parse error being emitted. - IgnoreIdenticalAttributes bool + IgnoreIdenticalAttributes bool + IgnoreUnknownAttributeType bool } func (p *Parser) Parse(f File) (*Dictionary, error) { @@ -75,6 +76,12 @@ func (p *Parser) parse(dict *Dictionary, parsedFiles map[string]struct{}, f File case (len(fields) == 4 || len(fields) == 5) && fields[0] == "ATTRIBUTE": attr, err := p.parseAttribute(fields) if err != nil { + switch err.(type) { + case *UnknownAttributeTypeError: + if p.IgnoreUnknownAttributeType { + continue + } + } return &ParseError{ Inner: err, File: f, From b90838d8470ba85638d1d089b025da99566b9da8 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Wed, 22 Jan 2020 13:27:23 -0500 Subject: [PATCH 10/10] Treat strings and octects as the same types --- dictionary/dictionary.go | 31 +++++++++++++++++++++++++++++++ dictionary/parser.go | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/dictionary/dictionary.go b/dictionary/dictionary.go index ad912c8..e7fd7bc 100644 --- a/dictionary/dictionary.go +++ b/dictionary/dictionary.go @@ -184,6 +184,37 @@ func (a *Attribute) Equals(o *Attribute) bool { return true } +func normalizedType(t AttributeType) AttributeType { + if t == AttributeString { + return AttributeOctets + } + + return t +} + +func (a *Attribute) MostlyEquals(o *Attribute) bool { + if a == o { + return true + } + if a == nil || o == nil { + return false + } + + if a.Name != o.Name || !a.OID.Equals(o.OID) { + return false + } + + if normalizedType(a.Type) != normalizedType(o.Type) { + return false + } + + if a.FlagEncrypt != o.FlagEncrypt || a.FlagHasTag != o.FlagHasTag || a.FlagConcat != o.FlagConcat { + return false + } + + return true +} + func (a *Attribute) GoString() string { var b bytes.Buffer b.WriteString("&dictionary.Attribute{") diff --git a/dictionary/parser.go b/dictionary/parser.go index 4401c71..622d019 100644 --- a/dictionary/parser.go +++ b/dictionary/parser.go @@ -96,7 +96,7 @@ func (p *Parser) parse(dict *Dictionary, parsedFiles map[string]struct{}, f File existing = AttributeByName(vendorBlock.Attributes, attr.Name) } if existing != nil { - if p.IgnoreIdenticalAttributes && attr.Equals(existing) { + if p.IgnoreIdenticalAttributes && attr.MostlyEquals(existing) { break } return &ParseError{