layeh / radius

a Go (golang) RADIUS client and server implementation
https://pkg.go.dev/layeh.com/radius
Mozilla Public License 2.0
571 stars 181 forks source link

Correct way of adding Vendor-Specific attributes with type to a packet? #86

Closed dvcrn closed 3 years ago

dvcrn commented 3 years ago

I'm very new to RADIUS and while trying to replicate a request I captured I came across this package. The request that I captured with wireshark looks like this:

Screen Shot 2020-11-11 at 22 15 31

So the Vendor-Specific type has it's own type and value, right? If I use

    packet.Set(rfc2865.VendorSpecific_Type, <attr>)

Then I only set the attr as value which isn't a type,value construct.

I saw that attributes has an encodeTo method (here) that could be used to encode to []byte, then use attribute.NewBytes() to turn it into an attribute that can be added to a packet, but encodeTo is private so that's maybe not the way to do it

My question is, how do I set the VendorSpecific attribute so that it matches the type structure from my capture? As in, how can I set a type,value structure as the value of the Vendor-Specific? (If that's how it works) (There are a bunch of those attributes with different types)

ghost commented 3 years ago

The easiest way would be to write the dictionary file for your vendor, generate the code with radius-dict-gen, then use that generated code (see the vendors folder for how you can do this). Example dictionary file:

VENDOR          MyVendorName                <The Hidden Vendor Id>
ATTRIBUTE       MyVendorName-CustomAttr     1    string
END-VENDOR      MyVendorName

After generating the code, you should have a package that has a function like the following:

myvendor.MyVendorNameCustomAttr_Set(p *radius.Packet, value []byte) (err error)
dvcrn commented 3 years ago

Thanks for the reply! I ended up getting it working like this:

    type VS struct {
    Type        int
        StringValue string
    }

    vendorSpecific := []VS{
        {1, "xxx"},
        {2, "yyy"},
        {3, "ffff"},
        {4, "asdf"},
    }

    for _, vss := range vendorSpecific {
        b, err = hex.DecodeString(vss.StringValue)
        if err != nil {
            log.Fatal(err)
        }

        rbytes, _ := radius.NewBytes(b)
        attr := make(radius.Attribute, 2+len(rbytes))
        attr[0] = byte(vss.Type)
        attr[1] = byte(len(attr))
        copy(attr[2:], rbytes)
        vsa, err := radius.NewVendorSpecific("VendorID", attr)
        if err != nil {
            log.Fatal(err)
        }
        packet.Add(rfc2865.VendorSpecific_Type, vsa)
    }