128 lines
3.1 KiB
Go
128 lines
3.1 KiB
Go
package radius // import "layeh.com/radius"
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"net"
|
|
"time"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// The base attribute value formats that are defined in RFC 2865.
|
|
var (
|
|
// string
|
|
AttributeText AttributeCodec
|
|
// []byte
|
|
AttributeString AttributeCodec
|
|
// net.IP
|
|
AttributeAddress AttributeCodec
|
|
// uint32
|
|
AttributeInteger AttributeCodec
|
|
// time.Time
|
|
AttributeTime AttributeCodec
|
|
// []byte
|
|
AttributeUnknown AttributeCodec
|
|
)
|
|
|
|
type attributeText struct{}
|
|
|
|
func (attributeText) Decode(packet *Packet, value []byte) (interface{}, error) {
|
|
if !utf8.Valid(value) {
|
|
return nil, errors.New("radius: text attribute is not valid UTF-8")
|
|
}
|
|
return string(value), nil
|
|
}
|
|
|
|
func (attributeText) Encode(packet *Packet, value interface{}) ([]byte, error) {
|
|
str, ok := value.(string)
|
|
if ok {
|
|
return []byte(str), nil
|
|
}
|
|
raw, ok := value.([]byte)
|
|
if ok {
|
|
return raw, nil
|
|
}
|
|
return nil, errors.New("radius: text attribute must be string or []byte")
|
|
}
|
|
|
|
type attributeString struct{}
|
|
|
|
func (attributeString) Decode(packet *Packet, value []byte) (interface{}, error) {
|
|
v := make([]byte, len(value))
|
|
copy(v, value)
|
|
return v, nil
|
|
}
|
|
|
|
func (attributeString) Encode(packet *Packet, value interface{}) ([]byte, error) {
|
|
raw, ok := value.([]byte)
|
|
if ok {
|
|
return raw, nil
|
|
}
|
|
str, ok := value.(string)
|
|
if ok {
|
|
return []byte(str), nil
|
|
}
|
|
return nil, errors.New("radius: string attribute must be []byte or string")
|
|
}
|
|
|
|
type attributeAddress struct{}
|
|
|
|
func (attributeAddress) Decode(packet *Packet, value []byte) (interface{}, error) {
|
|
if len(value) != net.IPv4len {
|
|
return nil, errors.New("radius: address attribute has invalid size")
|
|
}
|
|
v := make([]byte, len(value))
|
|
copy(v, value)
|
|
return net.IP(v), nil
|
|
}
|
|
|
|
func (attributeAddress) Encode(packet *Packet, value interface{}) ([]byte, error) {
|
|
ip, ok := value.(net.IP)
|
|
if !ok {
|
|
return nil, errors.New("radius: address attribute must be net.IP")
|
|
}
|
|
ip = ip.To4()
|
|
if ip == nil {
|
|
return nil, errors.New("radius: address attribute must be an IPv4 net.IP")
|
|
}
|
|
return []byte(ip), nil
|
|
}
|
|
|
|
type attributeInteger struct{}
|
|
|
|
func (attributeInteger) Decode(packet *Packet, value []byte) (interface{}, error) {
|
|
if len(value) != 4 {
|
|
return nil, errors.New("radius: integer attribute has invalid size")
|
|
}
|
|
return binary.BigEndian.Uint32(value), nil
|
|
}
|
|
|
|
func (attributeInteger) Encode(packet *Packet, value interface{}) ([]byte, error) {
|
|
integer, ok := value.(uint32)
|
|
if !ok {
|
|
return nil, errors.New("radius: integer attribute must be uint32")
|
|
}
|
|
raw := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(raw, integer)
|
|
return raw, nil
|
|
}
|
|
|
|
type attributeTime struct{}
|
|
|
|
func (attributeTime) Decode(packet *Packet, value []byte) (interface{}, error) {
|
|
if len(value) != 4 {
|
|
return nil, errors.New("radius: time attribute has invalid size")
|
|
}
|
|
return time.Unix(int64(binary.BigEndian.Uint32(value)), 0), nil
|
|
}
|
|
|
|
func (attributeTime) Encode(packet *Packet, value interface{}) ([]byte, error) {
|
|
timestamp, ok := value.(time.Time)
|
|
if !ok {
|
|
return nil, errors.New("radius: time attribute must be time.Time")
|
|
}
|
|
raw := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(raw, uint32(timestamp.Unix()))
|
|
return raw, nil
|
|
}
|