radius

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2020 License: MIT Imports: 15 Imported by: 0

README

Radius Go library

Work in progress

Example
package main

import (
	"log"
	"context"

	"github.com/ubogdan/radius"
)

type Server struct {
}

//func (s *Server) RadiusHandle(req *radius.Packet) *radius.Packet {
func (s *Server) ServeRADIUS(response radius.ResponseWriter, req *radius.Request) {
	switch req.Code {
	case radius.CodeAccessRequest:
		username := req.Get(radius.UserName).String()
		nasIPaddr, _ := req.Get(radius.NASIPAddress).IPAddr()
		nasPort, _ := req.Get(radius.NASPort).Integer()
		nasPortId, _ := req.Get(radius.NASPortId).Integer()
		calledStationId := req.Get(radius.CalledStationId).String()
		callingStationId := req.Get(radius.CallingStationId).String()

		log.Printf("Handle user:%s", username)
		log.Printf("Request: %s(%s) port:%d(%d) mac:%s", nasIPaddr, calledStationId,
			nasPort, nasPortId, callingStationId)

		eapAttribute, eapRequest := req.Lookup(radius.EAPMessage)
		if eapRequest {
			eapMessage,err := eapAttribute.EAPMessage()
			if err != nil {
				// Failed to decode EAP Message
				return
			}
			if eapMessage.Type == radius.EapTypeIdentity {
				res := req.Response(radius.CodeAccessAccept)
				message := radius.NewEAPMessage(radius.EapCodeSuccess, eapMessage.Identifier, 0, nil)
				res.Add(radius.EAPMessage, message)
				response.Write(res)
			}
		}

	case radius.CodeAccountingRequest:
		// accounting start or end
		response.Write(req.Response(radius.CodeAccountingResponse))
	}

	response.Write(req.Response(radius.CodeAccessReject))

}

func main() {
	log.Printf("New server")

	srv := radius.NewServer(":1812", []byte("secret1234"), &Server{})

	signalHandler := make(chan os.Signal, 1)
	signal.Notify(signalHandler, syscall.SIGINT, syscall.SIGTERM)
	errHandler := make(chan error)
	go func() {
		fmt.Println("waiting for packets...")
		err := srv.ListenAndServe()
		if err != nil {
			errHandler <- err
		}
	}()
	select {
	case <-signalHandler:
		log.Println("Shuting down ...")
		srv.srv.Shutdown(context.Background())
	case err := <-errHandler:
		log.Println("[ERR] %v", err.Error())
	}

}

Documentation

Index

Constants

View Source
const ACCOUNTING_PORT = 1813
View Source
const AUTH_PORT = 1812
View Source
const MaxPacketLength = 4095

MaxPacketLength is the maximum wire length of a RADIUS packet.

Variables

View Source
var DefaultClient = &Client{
	Retry:           time.Second,
	MaxPacketErrors: 10,
}

DefaultClient is the RADIUS client used by the Exchange function.

View Source
var ErrNoAttribute = errors.New("radius: attribute not found")

ErrNoAttribute is returned when an attribute was not found when one was expected.

Functions

func IsAuthenticRequest

func IsAuthenticRequest(request, secret []byte) bool

IsAuthenticRequest returns if the given RADIUS request is an authentic request using the given secret.

func IsAuthenticResponse

func IsAuthenticResponse(response, request, secret []byte) bool

IsAuthenticResponse returns if the given RADIUS response is an authentic response to the given request.

func ListenAndServe

func ListenAndServe(addr string, handler Handler, secretSource SecretSource) error

ListenAndServe listens on the UDP network address addr and then calls

ListenAndServe always returns a non-nil error.

Types

type Attribute

type Attribute []byte

Attribute is a wire encoded RADIUS attribute.

func NewBytes

func NewBytes(b []byte) (Attribute, error)

NewBytes returns a new Attribute from the given byte slice. An error is returned if the slice is longer than 253.

func NewEAPMessage

func NewEAPMessage(Code EapCode, Identifier uint8, Type EapType, Data Attribute) Attribute

NewEAPMessage godoc

func NewIPAddr

func NewIPAddr(a net.IP) (Attribute, error)

NewIPAddr returns a new Attribute from the given IP address. An error is returned if the given address is not an IPv4 address.

func NewIPv6Addr

func NewIPv6Addr(a net.IP) (Attribute, error)

NewIPv6Addr returns a new Attribute from the given IP address. An error is returned if the given address is not an IPv6 address.

func NewInt

func NewInt(i uint32) Attribute

NewInt creates a new Attribute from the given integer value.

func NewInt64

func NewInt64(i uint64) Attribute

NewInt64 creates a new Attribute from the given integer value.

func NewString

func NewString(s string) (Attribute, error)

NewString returns a new Attribute from the given string. An error is returned if the string length is greater than 253.

func NewTime

func NewTime(t time.Time) (Attribute, error)

NewTime returns a new Attribute from the given time.Time.

func (Attribute) Bytes

func (a Attribute) Bytes() []byte

Bytes returns the given Attribute as a byte slice.

func (Attribute) EAPMessage

func (a Attribute) EAPMessage() (*EapMessage, error)

EAPMessage godoc

func (Attribute) IPAddr

func (a Attribute) IPAddr() (net.IP, error)

IPAddr returns the given Attribute as an IPv4 IP address. An error is returned if the attribute is not 4 bytes long.

func (Attribute) IPv6Addr

func (a Attribute) IPv6Addr() (net.IP, error)

IPv6Addr returns the given Attribute as an IPv6 IP address. An error is returned if the attribute is not 16 bytes long.

func (Attribute) Int64

func (a Attribute) Int64() (uint64, error)

Int64 returns the given attribute as an integer. An error is returned if the attribute is not 8 bytes long.

func (Attribute) Integer

func (a Attribute) Integer() (uint32, error)

Integer returns the given attribute as an integer. An error is returned if the attribute is not 4 bytes long.

func (Attribute) String

func (a Attribute) String() string

String returns the given attribute as a string.

func (Attribute) Time

func (a Attribute) Time() (time.Time, error)

Time returns the given Attribute as time.Time. An error is returned if the attribute is not 4 bytes long.

type Attributes

type Attributes map[Type][]Attribute

Attributes is a map of RADIUS attribute types to slice of Attributes.

func ParseAttributes

func ParseAttributes(b []byte) (Attributes, error)

ParseAttributes parses the wire-encoded RADIUS attributes and returns a new Attributes value. An error is returned if the buffer is malformed.

func (Attributes) Add

func (a Attributes) Add(key Type, value Attribute)

Add appends the given Attribute to the map entry of the given type.

func (Attributes) Del

func (a Attributes) Del(key Type)

Del removes all Attributes of the given type from a.

func (Attributes) Get

func (a Attributes) Get(key Type) Attribute

Get returns the first Attribute of Type key. nil is returned if no Attribute of Type key exists in a.

func (Attributes) Lookup

func (a Attributes) Lookup(key Type) (Attribute, bool)

Lookup returns the first Attribute of Type key. nil and false is returned if no Attribute of Type key exists in a.

func (Attributes) Set

func (a Attributes) Set(key Type, value Attribute)

Set removes all Attributes of Type key and appends value.

type Client

type Client struct {
	// Network on which to make the connection. Defaults to "udp".
	Net string

	// Dialer to use when making the outgoing connections.
	Dialer net.Dialer

	// Interval on which to resend packet (zero or negative value means no
	// retry).
	Retry time.Duration

	// MaxPacketErrors controls how many packet parsing and validation errors
	// the client will ignore before returning the error from Exchange.
	//
	// If zero, Exchange will drop all packet parsing errors.
	MaxPacketErrors int

	// InsecureSkipVerify controls whether the client should skip verifying
	// response packets received.
	InsecureSkipVerify bool
}

Client is a RADIUS client that can exchange packets with a RADIUS server.

func (*Client) Exchange

func (c *Client) Exchange(ctx context.Context, packet *Packet, addr string) (*Packet, error)

Exchange sends the packet to the given server and waits for a response. ctx must be non-nil.

type Code

type Code int

Code defines the RADIUS packet type.

const (
	CodeAccessRequest      Code = 1
	CodeAccessAccept       Code = 2
	CodeAccessReject       Code = 3
	CodeAccountingRequest  Code = 4
	CodeAccountingResponse Code = 5
	CodeAccessChallenge    Code = 11
	CodeStatusServer       Code = 12
	CodeStatusClient       Code = 13
	CodeDisconnectRequest  Code = 40
	CodeDisconnectACK      Code = 41
	CodeDisconnectNAK      Code = 42
	CodeCoARequest         Code = 43
	CodeCoAACK             Code = 44
	CodeCoANAK             Code = 45
	CodeReserved           Code = 255
)

Standard RADIUS packet codes.

func (Code) String

func (c Code) String() string

String returns a string representation of the code.

type EapCode

type EapCode uint8

Code define EAP Packet code

const (
	EapCodeRequest  EapCode = 1
	EapCodeResponse EapCode = 2
	EapCodeSuccess  EapCode = 3
	EapCodeFailure  EapCode = 4
)

func (EapCode) String

func (c EapCode) String() string

type EapMessage

type EapMessage struct {
	Code       EapCode
	Identifier uint8
	Type       EapType
	Data       Attribute
}

type EapType

type EapType uint8

EapType is the EAP attribute type.

const (
	EapTypeIdentity         EapType = 1
	EapTypeNotification     EapType = 2
	EapTypeNak              EapType = 3 //Response only
	EapTypeMd5Challenge     EapType = 4
	EapTypeOneTimePassword  EapType = 5 //otp
	EapTypeGenericTokenCard EapType = 6 //gtc
	EapTypeMSCHAPV2         EapType = 26
	EapTypeExpandedTypes    EapType = 254
	EapTypeExperimentalUse  EapType = 255
)

func (EapType) String

func (c EapType) String() string

type Handler

type Handler interface {
	ServeRADIUS(ResponseWriter, *Request)
}

type HandlerFunc added in v0.0.2

type HandlerFunc func(ResponseWriter, *Request)

The HandlerFunc type is an adapter to allow the use of ordinary functions as RAUDIUS handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler that calls f.

func (HandlerFunc) ServeRADIUS added in v0.0.2

func (f HandlerFunc) ServeRADIUS(w ResponseWriter, r *Request)

ServeHTTP calls f(w, r).

type NonAuthenticResponseError

type NonAuthenticResponseError struct {
}

NonAuthenticResponseError is returned when a client was expecting a valid response but did not receive one.

func (*NonAuthenticResponseError) Error

func (e *NonAuthenticResponseError) Error() string

type Packet

type Packet struct {
	Code          Code
	Identifier    byte
	Authenticator [16]byte
	Secret        []byte
	ClientAddr    string
	Attributes
}

Packet is a RADIUS packet.

func Exchange

func Exchange(ctx context.Context, packet *Packet, addr string) (*Packet, error)

Exchange uses DefaultClient to send the given RADIUS packet to the server at address addr and waits for a response.

func New

func New(code Code, secret []byte) *Packet

New creates a new packet with the Code, Secret fields set to the given values. The returned packet's Identifier and Authenticator fields are filled with random values.

The function panics if not enough random data could be generated.

func Parse

func Parse(b, secret []byte) (*Packet, error)

Parse parses an encoded RADIUS packet b. An error is returned if the packet is malformed.

func (*Packet) Encode

func (p *Packet) Encode() ([]byte, error)

Encode encodes the RADIUS packet to wire format. An error is returned if the encoded packet is too long (due to its Attributes), or if the packet has an unknown Code.

func (*Packet) Response

func (p *Packet) Response(code Code) *Packet

Response returns a new packet that has the same identifier, secret, and authenticator as the current packet.

type Request

type Request struct {
	// LocalAddr is the local address on which the incoming RADIUS request
	// was received.
	LocalAddr net.Addr
	// RemoteAddr is the address from which the incoming RADIUS request
	// was sent.
	RemoteAddr net.Addr

	// Packet is the RADIUS packet sent in the request.
	*Packet
	// contains filtered or unexported fields
}

Request is an incoming RADIUS request that is being handled by the server.

type ResponseWriter

type ResponseWriter interface {
	Write(packet *Packet) error
}

ResponseWriter is used by RADIUS servers when replying to a RADIUS request.

type SecretSource

type SecretSource func(remoteAddr net.Addr) ([]byte, error)

SecretStore supplies RADIUS servers with the secret that should be used for authorizing and decrypting packets.

ctx is canceled if the server's Shutdown method is called.

Returning an empty secret will discard the incoming packet.

type Server

type Server struct {
	Addr         string       // TCP address to listen on, ":radius" if empty
	Handler      Handler      // handler to invoke
	SecretSource SecretSource // Secret source Store
	// contains filtered or unexported fields
}

func NewServer

func NewServer(addr string, secret []byte, handler Handler) *Server

NewServer return a new Server given a addr, secret, and service

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe listen on the UDP network address

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown godoc

type Type

type Type int

Type is the RADIUS attribute type.

const (
	UserName          Type = iota //1
	UserPassword      Type = iota //2
	CHAPPassword      Type = iota //3
	NASIPAddress      Type = iota //4
	NASPort           Type = iota //5
	ServiceType       Type = iota //6
	FramedProtocol    Type = iota //7
	FramedIPAddress   Type = iota //8
	FramedIPNetmask   Type = iota //9
	FramedRouting     Type = iota //10
	FilterId          Type = iota //11
	FramedMTU         Type = iota //12
	FramedCompression Type = iota //13
	LoginIPHost       Type = iota //14
	LoginService      Type = iota //15
	LoginTCPPort      Type = iota //16

	ReplyMessage   Type = iota //18
	CallbackNumber Type = iota //19
	CallbackId     Type = iota //20

	FramedRoute                  Type = iota //22
	FramedIPXNetwork             Type = iota //23
	State                        Type = iota //24
	Class                        Type = iota //25
	VendorSpecific               Type = iota
	SessionTimeout               Type = iota
	IdleTimeout                  Type = iota
	TerminationAction            Type = iota
	CalledStationId              Type = iota
	CallingStationId             Type = iota
	NASIdentifier                Type = iota
	ProxyState                   Type = iota
	LoginLATService              Type = iota
	LoginLATNode                 Type = iota
	LoginLATGroup                Type = iota
	FramedAppleTalkLink          Type = iota
	FramedAppleTalkNetwork       Type = iota
	FramedAppleTalkZone          Type = iota
	AcctStatusType               Type = iota
	AcctDelayTime                Type = iota
	AcctInputOctets              Type = iota
	AcctOutputOctets             Type = iota
	AcctSessionId                Type = iota
	AcctAuthentic                Type = iota
	AcctSessionTime              Type = iota
	AcctInputPackets             Type = iota
	AcctOutputPackets            Type = iota
	AcctTerminateCause           Type = iota
	AcctMultiSessionId           Type = iota
	AcctLinkCount                Type = iota
	AcctInputGigawords           Type = iota //52
	AcctOutputGigawords          Type = iota
	Unassigned1                  Type = iota
	EventTimestamp               Type = iota
	EgressVLANID                 Type = iota
	IngressFilters               Type = iota
	EgressVLANName               Type = iota
	UserPriorityTable            Type = iota //59
	CHAPChallenge                Type = 60
	NASPortType                  Type = 61
	PortLimit                    Type = 62
	LoginLATPort                 Type = 63   //end rfc2865
	TunnelType                   Type = iota // rfc 2866
	TunnelMediumType             Type = iota
	TunnelClientEndpoint         Type = iota
	TunnelServerEndpoint         Type = iota
	AcctTunnelConnection         Type = iota
	TunnelPassword               Type = iota
	ARAPPassword                 Type = iota
	ARAPFeatures                 Type = iota
	ARAPZoneAccess               Type = iota
	ARAPSecurity                 Type = iota
	ARAPSecurityData             Type = iota
	PasswordRetry                Type = iota
	Prompt                       Type = iota
	ConnectInfo                  Type = iota
	ConfigurationToken           Type = iota
	EAPMessage                   Type = iota
	MessageAuthenticator         Type = iota
	TunnelPrivateGroupID         Type = iota
	TunnelAssignmentID           Type = iota
	TunnelPreference             Type = iota
	ARAPChallengeResponse        Type = iota
	AcctInterimInterval          Type = iota
	AcctTunnelPacketsLost        Type = iota
	NASPortId                    Type = iota
	FramedPool                   Type = iota
	CUI                          Type = iota
	TunnelClientAuthID           Type = iota
	TunnelServerAuthID           Type = iota
	NASFilterRule                Type = iota
	Unassigned                   Type = iota
	OriginatingLineInfo          Type = iota
	NASIPv6Address               Type = iota
	FramedInterfaceId            Type = iota
	FramedIPv6Prefix             Type = iota
	LoginIPv6Host                Type = iota
	FramedIPv6Route              Type = iota
	FramedIPv6Pool               Type = iota
	ErrorCause                   Type = iota
	EAPKeyName                   Type = iota
	DigestResponse               Type = iota
	DigestRealm                  Type = iota
	DigestNonce                  Type = iota
	DigestResponseAuth           Type = iota
	DigestNextnonce              Type = iota
	DigestMethod                 Type = iota
	DigestURI                    Type = iota
	DigestQop                    Type = iota
	DigestAlgorithm              Type = iota
	DigestEntityBodyHash         Type = iota
	DigestCNonce                 Type = iota
	DigestNonceCount             Type = iota
	DigestUsername               Type = iota
	DigestOpaque                 Type = iota
	DigestAuthParam              Type = iota
	DigestAKAAuts                Type = iota
	DigestDomain                 Type = iota
	DigestStale                  Type = iota
	DigestHA1                    Type = iota
	SIPAOR                       Type = iota
	DelegatedIPv6Prefix          Type = iota
	MIP6FeatureVector            Type = iota
	MIP6HomeLinkPrefix           Type = iota
	OperatorName                 Type = iota
	LocationInformation          Type = iota
	LocationData                 Type = iota
	BasicLocationPolicyRules     Type = iota
	ExtendedLocationPolicyRules  Type = iota
	LocationCapable              Type = iota
	RequestedLocationInfo        Type = iota
	FramedManagementProtocol     Type = iota
	ManagementTransportProtectio Type = iota
	ManagementPolicyId           Type = iota
	ManagementPrivilegeLevel     Type = iota
	PKMSSCert                    Type = iota
	PKMCACert                    Type = iota
	PKMConfigSettings            Type = iota
	PKMCryptosuiteList           Type = iota
	PKMSAID                      Type = iota
	PKMSADescriptor              Type = iota
	PKMAuthKey                   Type = iota
	DSLiteTunnelName             Type = iota
	MobileNodeIdentifier         Type = iota
	ServiceSelection             Type = iota
	PMIP6HomeLMAIPv6Address      Type = iota
	PMIP6VisitedLMAIPv6Address   Type = iota
	PMIP6HomeLMAIPv4Address      Type = iota
	PMIP6VisitedLMAIPv4Address   Type = iota
	PMIP6HomeHNPrefix            Type = iota
	PMIP6VisitedHNPrefix         Type = iota
	PMIP6HomeInterfaceID         Type = iota
	PMIP6VisitedInterfaceID      Type = iota
	PMIP6HomeIPv4HoA             Type = iota
	PMIP6VisitedIPv4HoA          Type = iota
	PMIP6HomeDHCP4ServerAddress  Type = iota
	PMIP6VisitedDHCP4ServerAddre Type = iota
	PMIP6HomeDHCP6ServerAddress  Type = iota
	PMIP6VisitedDHCP6ServerAddre Type = iota
	UnassignedStart              Type = 161
	UnassignedEnd                Type = 191
	ExperimentalStart            Type = 192
	ExperimentalEnd              Type = 223
	ImplementationSpecificStart  Type = 224
	ImplementationSpecificEnd    Type = 240
	ReservedStart                Type = 241
	ReservedEnd                  Type = 254
)
const TypeInvalid Type = -1

TypeInvalid is a Type that can be used to represent an invalid RADIUS attribute type.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL