open-vault/vendor/layeh.com/radius/attributes_builtin.go
2017-02-07 16:04:27 -05:00

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
}