gotacacs

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2026 License: MIT Imports: 12 Imported by: 0

README

gotacacs

A Go implementation of the TACACS+ protocol as defined in RFC 8907, with TLS 1.3 transport support per RFC 9887.

Provides both client and server SDK interfaces for Authentication, Authorization, and Accounting (AAA) services.

Features

  • Full TACACS+ protocol implementation (RFC 8907)
  • TLS 1.3 transport compliance (RFC 9887)
  • Client SDK with high-level API (PAP and ASCII interactive authentication)
  • Server SDK with pluggable handler interfaces
  • TCP and TLS transport support
  • Body obfuscation (MD5-based pseudo-pad)
  • Single-connect mode for connection reuse
  • Per-client secret provider with custom user data
  • Graceful server shutdown

Requirements

  • Go 1.25 or later

Installation

go get github.com/vitalvas/gotacacs

Quick Start

Client
client := gotacacs.NewClient(
    gotacacs.WithAddress("tacacs.example.com:49"),
    gotacacs.WithSecret("sharedsecret"),
)

// Authentication (PAP)
reply, err := client.Authenticate(ctx, "username", "password")
if err != nil {
    log.Fatal(err)
}
if reply.IsPass() {
    fmt.Println("Authentication successful")
}

// Authorization
resp, err := client.Authorize(ctx, "username", []string{"service=shell", "cmd=show"})
if err != nil {
    log.Fatal(err)
}
if resp.IsPass() {
    fmt.Println("Authorization granted")
}

// Accounting
acctReply, err := client.Accounting(ctx, gotacacs.AcctFlagStart, "username", []string{"task_id=123"})
if err != nil {
    log.Fatal(err)
}
if acctReply.IsSuccess() {
    fmt.Println("Accounting recorded")
}
Server
ln, err := gotacacs.ListenTCP(":49")
if err != nil {
    log.Fatal(err)
}

server := gotacacs.NewServer(
    gotacacs.WithServerListener(ln),
    gotacacs.WithServerSecret("sharedsecret"),
    gotacacs.WithHandler(&myHandler{}),
)

if err := server.Serve(); err != nil {
    log.Fatal(err)
}

Implement the Handler interface:

type myHandler struct{}

func (h *myHandler) HandleAuthenStart(_ context.Context, req *gotacacs.AuthenRequest) *gotacacs.AuthenReply {
    if string(req.Start.User) == "admin" && string(req.Start.Data) == "secret" {
        return &gotacacs.AuthenReply{Status: gotacacs.AuthenStatusPass}
    }
    return &gotacacs.AuthenReply{Status: gotacacs.AuthenStatusFail}
}

func (h *myHandler) HandleAuthenContinue(_ context.Context, _ *gotacacs.AuthenContinueRequest) *gotacacs.AuthenReply {
    return &gotacacs.AuthenReply{Status: gotacacs.AuthenStatusPass}
}

func (h *myHandler) HandleAuthorRequest(_ context.Context, _ *gotacacs.AuthorRequestContext) *gotacacs.AuthorResponse {
    return &gotacacs.AuthorResponse{
        Status: gotacacs.AuthorStatusPassAdd,
        Args:   [][]byte{[]byte("priv-lvl=15")},
    }
}

func (h *myHandler) HandleAcctRequest(_ context.Context, _ *gotacacs.AcctRequestContext) *gotacacs.AcctReply {
    return &gotacacs.AcctReply{Status: gotacacs.AcctStatusSuccess}
}
Per-Client Secret Provider
secretProvider := gotacacs.SecretProviderFunc(func(ctx context.Context, req gotacacs.SecretRequest) gotacacs.SecretResponse {
    return gotacacs.SecretResponse{
        Secret: []byte("sharedsecret"),
        UserData: map[string]string{
            "client_ip": req.RemoteAddr.String(),
            "local_ip":  req.LocalAddr.String(),
        },
    }
})

server := gotacacs.NewServer(
    gotacacs.WithServerListener(ln),
    gotacacs.WithSecretProvider(secretProvider),
    gotacacs.WithHandler(&myHandler{}),
)
TLS 1.3 (RFC 9887)
// Client with TLS 1.3
client := gotacacs.NewClient(
    gotacacs.WithAddress("tacacs.example.com:300"),
    gotacacs.WithTLSConfig(&tls.Config{
        RootCAs: certPool,
    }),
)

// Server with TLS
ln, err := gotacacs.ListenTLS(":300", tlsConfig)
if err != nil {
    log.Fatal(err)
}

When using TLS, the FlagUnencrypted header flag is set automatically and body obfuscation is disabled, as specified by RFC 9887.

Examples

The package includes example binaries in examples/:

# TCP mode
go run ./examples/tacacs-server -addr :49 -secret sharedsecret
go run ./examples/tacacs-client -addr localhost:49 -secret sharedsecret

# TLS mode (RFC 9887)
go run ./examples/tacacs-server-tls -addr :300 -cert server.crt -key server.key
go run ./examples/tacacs-client-tls -addr localhost:300

Documentation

Protocol Reference

Documentation

Overview

Package gotacacs implements the TACACS+ protocol as defined in RFC8907. It provides both client and server SDK interfaces for Authentication, Authorization, and Accounting (AAA) services.

TACACS+ is a security protocol that provides centralized access control for network devices. This package supports TCP and TLS transports with body obfuscation using MD5-based pseudo-pad generation.

Client Usage

Create a client to connect to a TACACS+ server:

client := gotacacs.NewClient(
	gotacacs.WithAddress("tacacs.example.com:49"),
	gotacacs.WithSecret("sharedsecret"),
	gotacacs.WithTimeout(30*time.Second),
)

// Authenticate a user
reply, err := client.Authenticate(ctx, "username", "password")
if err != nil {
	log.Fatal(err)
}
if reply.IsPass() {
	fmt.Println("Authentication successful")
}

// Authorize a user
resp, err := client.Authorize(ctx, "username", []string{"service=shell", "cmd=show"})
if err != nil {
	log.Fatal(err)
}
if resp.IsPass() {
	fmt.Println("Authorization granted")
}

// Send accounting records
acctReply, err := client.Accounting(ctx, gotacacs.AcctFlagStart, "username", []string{"task_id=123"})
if err != nil {
	log.Fatal(err)
}
if acctReply.IsSuccess() {
	fmt.Println("Accounting recorded")
}

Server Usage

Create a server with custom handlers:

ln, err := gotacacs.ListenTCP(":49")
if err != nil {
	log.Fatal(err)
}

server := gotacacs.NewServer(
	gotacacs.WithServerListener(ln),
	gotacacs.WithServerSecret("sharedsecret"),
	gotacacs.WithHandler(&myHandler{}),
)

if err := server.Serve(); err != nil {
	log.Fatal(err)
}

Handler Implementation

Implement the Handler interface to process requests:

type myHandler struct{}

func (h *myHandler) HandleAuthenStart(_ context.Context, req *gotacacs.AuthenRequest) *gotacacs.AuthenReply {
	if string(req.Start.User) == "admin" && string(req.Start.Data) == "password" {
		return &gotacacs.AuthenReply{Status: gotacacs.AuthenStatusPass}
	}
	return &gotacacs.AuthenReply{Status: gotacacs.AuthenStatusFail}
}

func (h *myHandler) HandleAuthenContinue(_ context.Context, _ *gotacacs.AuthenContinueRequest) *gotacacs.AuthenReply {
	return &gotacacs.AuthenReply{Status: gotacacs.AuthenStatusPass}
}

func (h *myHandler) HandleAuthorRequest(_ context.Context, req *gotacacs.AuthorRequestContext) *gotacacs.AuthorResponse {
	return &gotacacs.AuthorResponse{
		Status: gotacacs.AuthorStatusPassAdd,
		Args:   [][]byte{[]byte("priv-lvl=15")},
	}
}

func (h *myHandler) HandleAcctRequest(_ context.Context, req *gotacacs.AcctRequestContext) *gotacacs.AcctReply {
	return &gotacacs.AcctReply{Status: gotacacs.AcctStatusSuccess}
}

Per-Client Secret Provider

Use SecretProviderFunc to return different secrets and custom user data per client:

secretProvider := gotacacs.SecretProviderFunc(func(ctx context.Context, req gotacacs.SecretRequest) gotacacs.SecretResponse {
	return gotacacs.SecretResponse{
		Secret: []byte("sharedsecret"),
		UserData: map[string]string{
			"client_ip": req.RemoteAddr.String(),
			"local_ip":  req.LocalAddr.String(),
		},
	}
})

server := gotacacs.NewServer(
	gotacacs.WithServerListener(ln),
	gotacacs.WithSecretProvider(secretProvider),
	gotacacs.WithHandler(&myHandler{}),
)

The UserData map is available in all handler request contexts via req.UserData.

TLS Support (RFC 9887) RFC 9887)" aria-label="Go to TLS Support (RFC 9887)">¶

Both client and server support TLS 1.3 for secure communication. When using TLS, the shared secret is not needed as TLS provides encryption:

// Client with TLS
tlsConfig := &tls.Config{
	RootCAs: certPool,
}
client := gotacacs.NewClient(
	gotacacs.WithAddress("tacacs.example.com:300"),
	gotacacs.WithTLSConfig(tlsConfig),
)

// Server with TLS
ln, err := gotacacs.ListenTLS(":300", tlsConfig)

Single-Connect Mode

Enable single-connect mode to reuse connections for multiple requests:

client := gotacacs.NewClient(
	gotacacs.WithAddress("tacacs.example.com:49"),
	gotacacs.WithSecret("sharedsecret"),
	gotacacs.WithSingleConnect(true),
)
defer client.Close()

For more information about the TACACS+ protocol, see RFC8907: https://datatracker.ietf.org/doc/html/rfc8907

Index

Constants

View Source
const (
	// MajorVersion is the TACACS+ major version (0x0c).
	MajorVersion = 0x0c

	// MinorVersionDefault is the default minor version.
	MinorVersionDefault = 0x00

	// MinorVersionOne indicates minor version 1.
	MinorVersionOne = 0x01
)

TACACS+ protocol version constants as defined in RFC8907.

View Source
const (
	// PacketTypeAuthen indicates an authentication packet.
	PacketTypeAuthen = 0x01

	// PacketTypeAuthor indicates an authorization packet.
	PacketTypeAuthor = 0x02

	// PacketTypeAcct indicates an accounting packet.
	PacketTypeAcct = 0x03
)

Packet type constants as defined in RFC8907 Section 4.1.

View Source
const (
	// FlagUnencrypted indicates the packet body is not obfuscated.
	FlagUnencrypted = 0x01

	// FlagSingleConnect indicates the client wants to use single-connection mode.
	FlagSingleConnect = 0x04
)

Header flag constants as defined in RFC8907 Section 4.1.

View Source
const (
	// AuthenActionLogin indicates a login action.
	AuthenActionLogin = 0x01

	// AuthenActionChPass indicates a password change action.
	AuthenActionChPass = 0x02

	// AuthenActionSendAuth indicates a send authentication action.
	AuthenActionSendAuth = 0x04
)

Authentication action types as defined in RFC8907 Section 5.1.

View Source
const (
	// AuthenTypeASCII indicates ASCII authentication.
	AuthenTypeASCII = 0x01

	// AuthenTypePAP indicates PAP authentication.
	AuthenTypePAP = 0x02

	// AuthenTypeCHAP indicates CHAP authentication.
	AuthenTypeCHAP = 0x03

	// AuthenTypeMSCHAP indicates MS-CHAP v1 authentication.
	AuthenTypeMSCHAP = 0x05

	// AuthenTypeMSCHAPV2 indicates MS-CHAP v2 authentication.
	AuthenTypeMSCHAPV2 = 0x06
)

Authentication types as defined in RFC8907 Section 5.1.

View Source
const (
	// AuthenServiceNone indicates no service.
	AuthenServiceNone = 0x00

	// AuthenServiceLogin indicates login service.
	AuthenServiceLogin = 0x01

	// AuthenServiceEnable indicates enable service.
	AuthenServiceEnable = 0x02

	// AuthenServicePPP indicates PPP service.
	AuthenServicePPP = 0x03

	// AuthenServicePT indicates PT service.
	AuthenServicePT = 0x05

	// AuthenServiceRCMD indicates RCMD service.
	AuthenServiceRCMD = 0x06

	// AuthenServiceX25 indicates X25 service.
	AuthenServiceX25 = 0x07

	// AuthenServiceNASI indicates NASI service.
	AuthenServiceNASI = 0x08
)

Authentication service types as defined in RFC8907 Section 5.1.

View Source
const (
	// AuthenStatusPass indicates authentication passed.
	AuthenStatusPass = 0x01

	// AuthenStatusFail indicates authentication failed.
	AuthenStatusFail = 0x02

	// AuthenStatusGetData indicates server needs more data.
	AuthenStatusGetData = 0x03

	// AuthenStatusGetUser indicates server needs the username.
	AuthenStatusGetUser = 0x04

	// AuthenStatusGetPass indicates server needs the password.
	AuthenStatusGetPass = 0x05

	// AuthenStatusRestart indicates authentication should restart.
	AuthenStatusRestart = 0x06

	// AuthenStatusError indicates an error occurred.
	AuthenStatusError = 0x07

	// AuthenStatusFollow indicates the client should follow to another server.
	AuthenStatusFollow = 0x21
)

Authentication status codes as defined in RFC8907 Section 5.2.

View Source
const (
	// AuthenMethodNotSet indicates the authentication method was not set.
	AuthenMethodNotSet = 0x00

	// AuthenMethodNone indicates no authentication was performed.
	AuthenMethodNone = 0x01

	// AuthenMethodKRB5 indicates Kerberos 5 authentication.
	AuthenMethodKRB5 = 0x02

	// AuthenMethodLine indicates line authentication (e.g., console password).
	AuthenMethodLine = 0x03

	// AuthenMethodEnable indicates enable authentication.
	AuthenMethodEnable = 0x04

	// AuthenMethodLocal indicates local database authentication.
	AuthenMethodLocal = 0x05

	// AuthenMethodTACACSPlus indicates TACACS+ authentication.
	AuthenMethodTACACSPlus = 0x06

	// AuthenMethodGuest indicates guest authentication.
	AuthenMethodGuest = 0x08

	// AuthenMethodRadius indicates RADIUS authentication.
	AuthenMethodRadius = 0x10

	// AuthenMethodKRB4 indicates Kerberos 4 authentication.
	AuthenMethodKRB4 = 0x11

	// AuthenMethodRCMD indicates RCMD authentication.
	AuthenMethodRCMD = 0x20
)

Authentication method constants as defined in RFC8907 Section 6.1. These indicate how the user was authenticated in authorization/accounting requests.

View Source
const (
	// AuthorStatusPassAdd indicates authorization passed with additional arguments.
	AuthorStatusPassAdd = 0x01

	// AuthorStatusPassRepl indicates authorization passed with replacement arguments.
	AuthorStatusPassRepl = 0x02

	// AuthorStatusFail indicates authorization failed.
	AuthorStatusFail = 0x10

	// AuthorStatusError indicates an error occurred.
	AuthorStatusError = 0x11

	// AuthorStatusFollow indicates the client should follow to another server.
	AuthorStatusFollow = 0x21
)

Authorization status codes as defined in RFC8907 Section 6.2.

View Source
const (
	// AcctFlagStart indicates the start of a task.
	AcctFlagStart = 0x02

	// AcctFlagStop indicates the end of a task.
	AcctFlagStop = 0x04

	// AcctFlagWatchdog indicates an update for an ongoing task.
	AcctFlagWatchdog = 0x08
)

Accounting flags as defined in RFC8907 Section 7.1.

View Source
const (
	// AcctStatusSuccess indicates the accounting record was accepted.
	AcctStatusSuccess = 0x01

	// AcctStatusError indicates an error occurred.
	AcctStatusError = 0x02

	// AcctStatusFollow indicates the client should follow to another server.
	AcctStatusFollow = 0x21
)

Accounting status codes as defined in RFC8907 Section 7.2.

View Source
const (
	// AuthenContinueFlagAbort indicates the client wants to abort authentication.
	AuthenContinueFlagAbort = 0x01
)

Authentication continue flags as defined in RFC8907 Section 5.3.

View Source
const (
	// AuthenReplyFlagNoEcho indicates the server wants no echo of user input.
	AuthenReplyFlagNoEcho = 0x01
)

Authentication reply flags as defined in RFC8907 Section 5.2.

View Source
const DefaultMaxBodyLength = 256 * 1024

DefaultMaxBodyLength is the default maximum allowed body length (256KB). This prevents memory exhaustion attacks from malicious peers.

View Source
const DefaultPort = 49

DefaultPort is the default TACACS+ port as defined in RFC8907.

View Source
const DefaultTLSPort = 300

DefaultTLSPort is the default TACACS+ over TLS port as defined in RFC9887. RFC 9887 specifies port 300 for TLS-secured TACACS+ connections (service name "tacacss").

View Source
const HeaderLength = 12

HeaderLength is the fixed size of a TACACS+ header in bytes.

View Source
const MinPSKLength = 16

MinPSKLength is the minimum Pre-Shared Key length required by RFC 9887. RFC 9887 specifies a minimum of 16 octets for PSK.

View Source
const TLSSessionTicketKeyLength = 32

TLSSessionTicketKeyLength is the required length for TLS session ticket keys. Go's TLS implementation requires 32 bytes for session ticket keys.

Variables

View Source
var (
	// ErrInvalidHeader indicates the packet header is malformed or invalid.
	ErrInvalidHeader = errors.New("invalid header")

	// ErrInvalidPacket indicates the packet body is malformed or invalid.
	ErrInvalidPacket = errors.New("invalid packet")

	// ErrInvalidVersion indicates an unsupported protocol version.
	ErrInvalidVersion = errors.New("invalid version")

	// ErrInvalidType indicates an unsupported packet type.
	ErrInvalidType = errors.New("invalid packet type")

	// ErrInvalidSequence indicates a sequence number violation.
	ErrInvalidSequence = errors.New("invalid sequence number")

	// ErrSessionNotFound indicates the session ID is unknown.
	ErrSessionNotFound = errors.New("session not found")

	// ErrConnectionClosed indicates the connection was terminated.
	ErrConnectionClosed = errors.New("connection closed")

	// ErrTimeout indicates an operation timed out.
	ErrTimeout = errors.New("operation timeout")

	// ErrAuthenticationFailed indicates authentication failed.
	ErrAuthenticationFailed = errors.New("authentication failed")

	// ErrAuthorizationDenied indicates authorization was denied.
	ErrAuthorizationDenied = errors.New("authorization denied")

	// ErrAccountingFailed indicates accounting operation failed.
	ErrAccountingFailed = errors.New("accounting failed")

	// ErrBufferTooShort indicates the buffer is too short for the operation.
	ErrBufferTooShort = errors.New("buffer too short")

	// ErrBodyTooLarge indicates the packet body exceeds maximum size.
	ErrBodyTooLarge = errors.New("body too large")

	// ErrAuthenFollow indicates the server requested authentication follow.
	// The client should connect to an alternate server specified in ServerMsg.
	ErrAuthenFollow = errors.New("authentication follow requested")

	// ErrAuthenRestart indicates the server requested authentication restart.
	// The client should restart authentication from the beginning.
	ErrAuthenRestart = errors.New("authentication restart requested")

	// ErrSequenceOverflow indicates the sequence number would overflow.
	// This happens after 255 packets in a session.
	ErrSequenceOverflow = errors.New("sequence number overflow")

	// ErrBadSecret indicates the shared secret may be incorrect.
	// This error is returned when packet parsing fails in a way that
	// suggests the body was deobfuscated with the wrong secret,
	// resulting in garbage length fields.
	ErrBadSecret = errors.New("bad secret")
)

Protocol errors for TACACS+ operations.

Functions

func IsClientPacket

func IsClientPacket(p Packet) bool

IsClientPacket returns true if the packet is sent by the client.

func IsServerPacket

func IsServerPacket(p Packet) bool

IsServerPacket returns true if the packet is sent by the server.

func IsTLSConn

func IsTLSConn(conn Conn) bool

IsTLSConn returns true if the connection is TLS-secured.

func Obfuscate

func Obfuscate(header *Header, secret, body []byte) []byte

Obfuscate obfuscates or deobfuscates the body using the TACACS+ pseudo-pad algorithm. The operation is symmetric (XOR), so the same function is used for both operations. As defined in RFC8907 Section 4.5, the pseudo-pad is computed as:

pseudo_pad = {MD5(session_id + secret + version + seq_no) +
              MD5(session_id + secret + version + seq_no + pseudo_pad[0..15]) +
              MD5(session_id + secret + version + seq_no + pseudo_pad[0..31]) + ...}

The body is XORed with the pseudo-pad to produce the obfuscated/deobfuscated result.

If secret is empty or the header has FlagUnencrypted set, the body is returned unchanged.

func PacketType

func PacketType(p Packet) uint8

PacketType returns the packet type constant for a given packet.

Types

type AccountingHandler

type AccountingHandler interface {
	// HandleAcctRequest handles an accounting REQUEST packet.
	HandleAcctRequest(ctx context.Context, req *AcctRequestContext) *AcctReply
}

AccountingHandler handles accounting requests.

type AcctHandlerFunc

type AcctHandlerFunc func(ctx context.Context, req *AcctRequestContext) *AcctReply

AcctHandlerFunc is an adapter for simple accounting handlers.

func (AcctHandlerFunc) HandleAcctRequest

func (f AcctHandlerFunc) HandleAcctRequest(ctx context.Context, req *AcctRequestContext) *AcctReply

HandleAcctRequest implements AccountingHandler.

type AcctReply

type AcctReply struct {
	Status    uint8  // Accounting status
	ServerMsg []byte // Server message (optional)
	Data      []byte // Additional data (optional)
}

AcctReply represents a TACACS+ accounting REPLY packet as defined in RFC8907 Section 7.2. This packet is sent by the server in response to an accounting request.

func NewAcctReply

func NewAcctReply(status uint8) *AcctReply

NewAcctReply creates a new AcctReply packet with the specified status.

func (*AcctReply) IsError

func (p *AcctReply) IsError() bool

IsError returns true if the status indicates an error.

func (*AcctReply) IsSuccess

func (p *AcctReply) IsSuccess() bool

IsSuccess returns true if the status indicates success.

func (*AcctReply) MarshalBinary

func (p *AcctReply) MarshalBinary() ([]byte, error)

MarshalBinary encodes the AcctReply packet to binary format.

func (*AcctReply) UnmarshalBinary

func (p *AcctReply) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the AcctReply packet from binary format.

type AcctRequest

type AcctRequest struct {
	Flags        uint8    // Accounting flags (START, STOP, WATCHDOG)
	AuthenMethod uint8    // Authentication method used
	PrivLevel    uint8    // Privilege level
	AuthenType   uint8    // Authentication type
	Service      uint8    // Authentication service
	User         []byte   // Username
	Port         []byte   // Port identifier
	RemoteAddr   []byte   // Remote address
	Args         [][]byte // Accounting arguments
}

AcctRequest represents a TACACS+ accounting REQUEST packet as defined in RFC8907 Section 7.1. This packet is sent by the client to send accounting records to the server.

func NewAcctRequest

func NewAcctRequest(flags, authenMethod, authenType, service uint8, user string) *AcctRequest

NewAcctRequest creates a new AcctRequest packet with the specified parameters.

func (*AcctRequest) AddArg

func (p *AcctRequest) AddArg(arg string)

AddArg adds an argument to the accounting request.

func (*AcctRequest) GetArgs

func (p *AcctRequest) GetArgs() []string

GetArgs returns the arguments as strings.

func (*AcctRequest) IsStart

func (p *AcctRequest) IsStart() bool

IsStart returns true if the START flag is set.

func (*AcctRequest) IsStop

func (p *AcctRequest) IsStop() bool

IsStop returns true if the STOP flag is set.

func (*AcctRequest) IsWatchdog

func (p *AcctRequest) IsWatchdog() bool

IsWatchdog returns true if the WATCHDOG flag is set.

func (*AcctRequest) MarshalBinary

func (p *AcctRequest) MarshalBinary() ([]byte, error)

MarshalBinary encodes the AcctRequest packet to binary format.

func (*AcctRequest) UnmarshalBinary

func (p *AcctRequest) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the AcctRequest packet from binary format.

type AcctRequestContext

type AcctRequestContext struct {
	SessionID  uint32
	RemoteAddr net.Addr
	Header     *Header
	Request    *AcctRequest
	UserData   map[string]string
}

AcctRequestContext represents an accounting request context.

type AuthenContinue

type AuthenContinue struct {
	Flags   uint8  // Continue flags (ABORT)
	UserMsg []byte // User message/response (optional)
	Data    []byte // Authentication data (optional)
}

AuthenContinue represents a TACACS+ authentication CONTINUE packet as defined in RFC8907 Section 5.3. This packet is sent by the client in response to a REPLY requesting more data.

func NewAuthenContinue

func NewAuthenContinue(userMsg string) *AuthenContinue

NewAuthenContinue creates a new AuthenContinue packet with the specified user message.

func (*AuthenContinue) IsAbort

func (p *AuthenContinue) IsAbort() bool

IsAbort returns true if the ABORT flag is set.

func (*AuthenContinue) MarshalBinary

func (p *AuthenContinue) MarshalBinary() ([]byte, error)

MarshalBinary encodes the AuthenContinue packet to binary format.

func (*AuthenContinue) SetAbort

func (p *AuthenContinue) SetAbort(abort bool)

SetAbort sets or clears the ABORT flag.

func (*AuthenContinue) UnmarshalBinary

func (p *AuthenContinue) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the AuthenContinue packet from binary format.

type AuthenContinueRequest

type AuthenContinueRequest struct {
	SessionID  uint32
	RemoteAddr net.Addr
	Header     *Header
	Continue   *AuthenContinue
	UserData   map[string]string
}

AuthenContinueRequest represents an authentication continue request context.

type AuthenHandlerFunc

type AuthenHandlerFunc func(ctx context.Context, req *AuthenRequest) *AuthenReply

AuthenHandlerFunc is an adapter for simple authentication handlers.

func (AuthenHandlerFunc) HandleAuthenContinue

func (f AuthenHandlerFunc) HandleAuthenContinue(_ context.Context, _ *AuthenContinueRequest) *AuthenReply

HandleAuthenContinue implements AuthenticationHandler (returns ERROR by default).

func (AuthenHandlerFunc) HandleAuthenStart

func (f AuthenHandlerFunc) HandleAuthenStart(ctx context.Context, req *AuthenRequest) *AuthenReply

HandleAuthenStart implements AuthenticationHandler.

type AuthenReply

type AuthenReply struct {
	Status    uint8  // Authentication status (PASS, FAIL, GETDATA, etc.)
	Flags     uint8  // Reply flags (NOECHO)
	ServerMsg []byte // Server message to display (optional)
	Data      []byte // Authentication data (optional)
}

AuthenReply represents a TACACS+ authentication REPLY packet as defined in RFC8907 Section 5.2. This packet is sent by the server in response to START or CONTINUE packets.

func NewAuthenReply

func NewAuthenReply(status uint8) *AuthenReply

NewAuthenReply creates a new AuthenReply packet with the specified status.

func (*AuthenReply) IsError

func (p *AuthenReply) IsError() bool

IsError returns true if the status indicates an error occurred.

func (*AuthenReply) IsFail

func (p *AuthenReply) IsFail() bool

IsFail returns true if the status indicates authentication failed.

func (*AuthenReply) IsPass

func (p *AuthenReply) IsPass() bool

IsPass returns true if the status indicates authentication passed.

func (*AuthenReply) MarshalBinary

func (p *AuthenReply) MarshalBinary() ([]byte, error)

MarshalBinary encodes the AuthenReply packet to binary format.

func (*AuthenReply) NeedsInput

func (p *AuthenReply) NeedsInput() bool

NeedsInput returns true if the server is requesting more input.

func (*AuthenReply) NoEcho

func (p *AuthenReply) NoEcho() bool

NoEcho returns true if the NOECHO flag is set.

func (*AuthenReply) UnmarshalBinary

func (p *AuthenReply) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the AuthenReply packet from binary format.

type AuthenRequest

type AuthenRequest struct {
	SessionID  uint32
	RemoteAddr net.Addr
	Header     *Header
	Start      *AuthenStart
	UserData   map[string]string
}

AuthenRequest represents an authentication request context.

type AuthenStart

type AuthenStart struct {
	Action     uint8  // Authentication action (LOGIN, CHPASS, SENDAUTH)
	PrivLevel  uint8  // Privilege level
	AuthenType uint8  // Authentication type (ASCII, PAP, CHAP, etc.)
	Service    uint8  // Authentication service (LOGIN, ENABLE, etc.)
	User       []byte // Username (optional)
	Port       []byte // Port identifier (optional)
	RemoteAddr []byte // Remote address (optional)
	Data       []byte // Authentication data (optional)
}

AuthenStart represents a TACACS+ authentication START packet as defined in RFC8907 Section 5.1. This packet is sent by the client to initiate an authentication session.

func NewAuthenStart

func NewAuthenStart(action, authenType, service uint8, user string) *AuthenStart

NewAuthenStart creates a new AuthenStart packet with the specified parameters.

func (*AuthenStart) MarshalBinary

func (p *AuthenStart) MarshalBinary() ([]byte, error)

MarshalBinary encodes the AuthenStart packet to binary format.

func (*AuthenStart) UnmarshalBinary

func (p *AuthenStart) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the AuthenStart packet from binary format.

type AuthenticateContext

type AuthenticateContext struct {
	Session    *Session
	Username   string
	Password   string
	Port       string
	RemoteAddr string
}

AuthenticateContext holds the context for multi-step authentication.

type AuthenticationHandler

type AuthenticationHandler interface {
	// HandleAuthenStart handles an authentication START packet.
	HandleAuthenStart(ctx context.Context, req *AuthenRequest) *AuthenReply

	// HandleAuthenContinue handles an authentication CONTINUE packet.
	HandleAuthenContinue(ctx context.Context, req *AuthenContinueRequest) *AuthenReply
}

AuthenticationHandler handles authentication requests.

type AuthorHandlerFunc

type AuthorHandlerFunc func(ctx context.Context, req *AuthorRequestContext) *AuthorResponse

AuthorHandlerFunc is an adapter for simple authorization handlers.

func (AuthorHandlerFunc) HandleAuthorRequest

func (f AuthorHandlerFunc) HandleAuthorRequest(ctx context.Context, req *AuthorRequestContext) *AuthorResponse

HandleAuthorRequest implements AuthorizationHandler.

type AuthorRequest

type AuthorRequest struct {
	AuthenMethod uint8    // Authentication method used
	PrivLevel    uint8    // Privilege level
	AuthenType   uint8    // Authentication type
	Service      uint8    // Authentication service
	User         []byte   // Username
	Port         []byte   // Port identifier
	RemoteAddr   []byte   // Remote address
	Args         [][]byte // Authorization arguments
}

AuthorRequest represents a TACACS+ authorization REQUEST packet as defined in RFC8907 Section 6.1. This packet is sent by the client to request authorization for a specific action.

func NewAuthorRequest

func NewAuthorRequest(authenMethod, authenType, service uint8, user string) *AuthorRequest

NewAuthorRequest creates a new AuthorRequest packet with the specified parameters.

func (*AuthorRequest) AddArg

func (p *AuthorRequest) AddArg(arg string)

AddArg adds an argument to the authorization request.

func (*AuthorRequest) GetArgs

func (p *AuthorRequest) GetArgs() []string

GetArgs returns the arguments as strings.

func (*AuthorRequest) MarshalBinary

func (p *AuthorRequest) MarshalBinary() ([]byte, error)

MarshalBinary encodes the AuthorRequest packet to binary format.

func (*AuthorRequest) UnmarshalBinary

func (p *AuthorRequest) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the AuthorRequest packet from binary format.

type AuthorRequestContext

type AuthorRequestContext struct {
	SessionID  uint32
	RemoteAddr net.Addr
	Header     *Header
	Request    *AuthorRequest
	UserData   map[string]string
}

AuthorRequestContext represents an authorization request context.

type AuthorResponse

type AuthorResponse struct {
	Status    uint8    // Authorization status
	Args      [][]byte // Authorization arguments (may be modified from request)
	ServerMsg []byte   // Server message (optional)
	Data      []byte   // Additional data (optional)
}

AuthorResponse represents a TACACS+ authorization RESPONSE packet as defined in RFC8907 Section 6.2. This packet is sent by the server in response to an authorization request.

func NewAuthorResponse

func NewAuthorResponse(status uint8) *AuthorResponse

NewAuthorResponse creates a new AuthorResponse packet with the specified status.

func (*AuthorResponse) AddArg

func (p *AuthorResponse) AddArg(arg string)

AddArg adds an argument to the authorization response.

func (*AuthorResponse) GetArgs

func (p *AuthorResponse) GetArgs() []string

GetArgs returns the arguments as strings.

func (*AuthorResponse) IsError

func (p *AuthorResponse) IsError() bool

IsError returns true if an error occurred.

func (*AuthorResponse) IsFail

func (p *AuthorResponse) IsFail() bool

IsFail returns true if the authorization failed.

func (*AuthorResponse) IsPass

func (p *AuthorResponse) IsPass() bool

IsPass returns true if the authorization passed (either PASS_ADD or PASS_REPL).

func (*AuthorResponse) IsPassAdd

func (p *AuthorResponse) IsPassAdd() bool

IsPassAdd returns true if the status is PASS_ADD.

func (*AuthorResponse) IsPassRepl

func (p *AuthorResponse) IsPassRepl() bool

IsPassRepl returns true if the status is PASS_REPL.

func (*AuthorResponse) MarshalBinary

func (p *AuthorResponse) MarshalBinary() ([]byte, error)

MarshalBinary encodes the AuthorResponse packet to binary format.

func (*AuthorResponse) UnmarshalBinary

func (p *AuthorResponse) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the AuthorResponse packet from binary format.

type AuthorizationHandler

type AuthorizationHandler interface {
	// HandleAuthorRequest handles an authorization REQUEST packet.
	HandleAuthorRequest(ctx context.Context, req *AuthorRequestContext) *AuthorResponse
}

AuthorizationHandler handles authorization requests.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client represents a TACACS+ client for communicating with a TACACS+ server.

func NewClient

func NewClient(opts ...ClientOption) *Client

NewClient creates a new TACACS+ client.

func (*Client) Accounting

func (c *Client) Accounting(ctx context.Context, flags uint8, username string, args []string) (*AcctReply, error)

Accounting sends an accounting record to the TACACS+ server.

func (*Client) Address

func (c *Client) Address() string

Address returns the server address.

func (*Client) Authenticate

func (c *Client) Authenticate(ctx context.Context, username, password string) (*AuthenReply, error)

Authenticate performs authentication with the TACACS+ server. It handles the complete authentication flow including multi-step interactions.

func (*Client) AuthenticateASCII

func (c *Client) AuthenticateASCII(ctx context.Context, username string, promptHandler func(prompt string, noEcho bool) (string, error)) (*AuthenReply, error)

AuthenticateASCII performs ASCII authentication with interactive prompts. The promptHandler is called for each GETDATA/GETUSER/GETPASS request.

func (*Client) AuthenticateWithContext

func (c *Client) AuthenticateWithContext(ctx context.Context, authCtx *AuthenticateContext) (*AuthenReply, error)

AuthenticateWithContext performs authentication with additional context.

func (*Client) Authorize

func (c *Client) Authorize(ctx context.Context, username string, args []string) (*AuthorResponse, error)

Authorize performs authorization with the TACACS+ server.

func (*Client) Close

func (c *Client) Close() error

Close closes the connection to the server.

func (*Client) Connect

func (c *Client) Connect(ctx context.Context) error

Connect establishes a connection to the TACACS+ server.

func (*Client) IsConnected

func (c *Client) IsConnected() bool

IsConnected returns true if the client has an active connection.

func (*Client) IsTLSConnection

func (c *Client) IsTLSConnection() bool

IsTLSConnection returns true if the current connection is TLS-secured.

func (*Client) IsTLSMode

func (c *Client) IsTLSMode() bool

IsTLSMode returns true if the client is using RFC 9887 TLS mode.

func (*Client) LocalAddr

func (c *Client) LocalAddr() net.Addr

LocalAddr returns the local address of the connection.

func (*Client) RemoteAddr

func (c *Client) RemoteAddr() net.Addr

RemoteAddr returns the remote address of the connection.

type ClientOption

type ClientOption func(*Client)

ClientOption is a function that configures a Client.

func WithAddress

func WithAddress(address string) ClientOption

WithAddress sets the server address to connect to.

func WithDialer

func WithDialer(dialer Dialer) ClientOption

WithDialer sets a custom dialer for connections. If dialer is nil, the default TCP dialer is retained.

func WithMaxBodyLength

func WithMaxBodyLength(maxLength uint32) ClientOption

WithMaxBodyLength sets the maximum allowed body length for incoming packets. This prevents memory exhaustion attacks from malicious servers.

func WithSecret

func WithSecret(secret string) ClientOption

WithSecret sets the shared secret for packet obfuscation.

func WithSecretBytes

func WithSecretBytes(secret []byte) ClientOption

WithSecretBytes sets the shared secret as bytes for packet obfuscation.

func WithSingleConnect

func WithSingleConnect(enabled bool) ClientOption

WithSingleConnect enables single-connect mode. In this mode, the connection is reused across multiple sessions.

func WithTLSConfig

func WithTLSConfig(config *tls.Config) ClientOption

WithTLSConfig sets the TLS 1.3 configuration for RFC 9887 compliant connections. When using TLS mode, the unencrypted flag is automatically set and packet obfuscation is disabled since TLS provides encryption. This function enforces TLS 1.3 as required by RFC 9887. If config is nil, a default TLS 1.3 configuration is used.

func WithTimeout

func WithTimeout(timeout time.Duration) ClientOption

WithTimeout sets the connection and operation timeout.

type Conn

type Conn interface {
	net.Conn
}

Conn represents a network connection for TACACS+ communication. It extends net.Conn with additional context awareness.

type Dialer

type Dialer interface {
	// Dial connects to the address on the named network.
	Dial(ctx context.Context, network, address string) (Conn, error)
}

Dialer represents a dialer for establishing TACACS+ connections.

type Handler

Handler combines all handler interfaces.

type Header struct {
	Version   uint8
	Type      uint8
	SeqNo     uint8
	Flags     uint8
	SessionID uint32
	Length    uint32
}

Header represents a TACACS+ packet header as defined in RFC8907 Section 4.1. The header is 12 bytes and contains the following fields:

  • Version (1 byte): major version (high nibble) and minor version (low nibble)
  • Type (1 byte): packet type (authentication, authorization, or accounting)
  • SeqNo (1 byte): sequence number for the session
  • Flags (1 byte): various flags (unencrypted, single-connect)
  • SessionID (4 bytes): session identifier
  • Length (4 bytes): length of the packet body

func NewHeader

func NewHeader(packetType uint8, sessionID uint32) *Header

NewHeader creates a new Header with the specified packet type and session ID. It sets the default version and initializes sequence number to 1.

func (*Header) IsSingleConnect

func (h *Header) IsSingleConnect() bool

IsSingleConnect returns true if the single-connect flag is set.

func (*Header) IsUnencrypted

func (h *Header) IsUnencrypted() bool

IsUnencrypted returns true if the unencrypted flag is set.

func (*Header) MajorVersionNumber

func (h *Header) MajorVersionNumber() uint8

MajorVersionNumber returns the major version from the version byte.

func (*Header) MarshalBinary

func (h *Header) MarshalBinary() ([]byte, error)

MarshalBinary encodes the header to binary format (big-endian).

func (*Header) MinorVersionNumber

func (h *Header) MinorVersionNumber() uint8

MinorVersionNumber returns the minor version from the version byte.

func (*Header) SetSingleConnect

func (h *Header) SetSingleConnect(singleConnect bool)

SetSingleConnect sets or clears the single-connect flag.

func (*Header) SetUnencrypted

func (h *Header) SetUnencrypted(unencrypted bool)

SetUnencrypted sets or clears the unencrypted flag.

func (*Header) UnmarshalBinary

func (h *Header) UnmarshalBinary(data []byte) error

UnmarshalBinary decodes the header from binary format.

func (*Header) Validate

func (h *Header) Validate() error

Validate checks if the header contains valid values according to RFC8907.

type Listener

type Listener interface {
	// Accept waits for and returns the next connection to the listener.
	Accept() (Conn, error)

	// Close closes the listener.
	Close() error

	// Addr returns the listener's network address.
	Addr() net.Addr
}

Listener represents a network listener for accepting TACACS+ connections.

func ListenTCP

func ListenTCP(address string) (Listener, error)

ListenTCP creates a TCP listener on the specified address.

func ListenTLS

func ListenTLS(address string, config *tls.Config) (Listener, error)

ListenTLS creates a TLS listener on the specified address.

type MemorySessionStore

type MemorySessionStore struct {
	// contains filtered or unexported fields
}

MemorySessionStore is an in-memory implementation of SessionStore.

func NewMemorySessionStore

func NewMemorySessionStore() *MemorySessionStore

NewMemorySessionStore creates a new in-memory session store.

func (*MemorySessionStore) Cleanup

func (s *MemorySessionStore) Cleanup(maxAge time.Duration) int

Cleanup removes expired sessions older than the given duration. Returns the number of sessions removed.

func (*MemorySessionStore) Count

func (s *MemorySessionStore) Count() int

Count returns the number of sessions in the store.

func (*MemorySessionStore) Delete

func (s *MemorySessionStore) Delete(id uint32)

Delete removes a session by ID.

func (*MemorySessionStore) Get

func (s *MemorySessionStore) Get(id uint32) (*Session, bool)

Get retrieves a session by ID.

func (*MemorySessionStore) Put

func (s *MemorySessionStore) Put(session *Session)

Put stores a session.

type Packet

Packet is the interface that all TACACS+ packet types implement.

func ParseAcctPacket

func ParseAcctPacket(seqNo uint8, data []byte) (Packet, error)

ParseAcctPacket parses an accounting packet body based on the sequence number. Sequence number 1 indicates a REQUEST. Sequence number 2 indicates a REPLY.

func ParseAuthenPacket

func ParseAuthenPacket(seqNo uint8, data []byte) (Packet, error)

ParseAuthenPacket parses an authentication packet body based on the sequence number. Odd sequence numbers indicate client packets (START, CONTINUE). Even sequence numbers indicate server packets (REPLY).

func ParseAuthorPacket

func ParseAuthorPacket(seqNo uint8, data []byte) (Packet, error)

ParseAuthorPacket parses an authorization packet body based on the sequence number. Sequence number 1 indicates a REQUEST. Sequence number 2 indicates a RESPONSE.

func ParsePacket

func ParsePacket(header *Header, data []byte) (Packet, error)

ParsePacket parses a packet body based on the header information. It determines the packet type from the header and delegates to the appropriate parser.

type SecretProvider

type SecretProvider interface {
	// GetSecret returns the shared secret and optional user data for the given request.
	GetSecret(ctx context.Context, req SecretRequest) SecretResponse
}

SecretProvider provides per-client shared secrets and optional user data.

type SecretProviderFunc

type SecretProviderFunc func(ctx context.Context, req SecretRequest) SecretResponse

SecretProviderFunc is an adapter to allow ordinary functions to be used as SecretProvider.

func (SecretProviderFunc) GetSecret

GetSecret implements SecretProvider.

type SecretRequest

type SecretRequest struct {
	// RemoteAddr is the remote address of the client.
	RemoteAddr net.Addr
	// LocalAddr is the local address of the server connection.
	LocalAddr net.Addr
	// Attempt is the 0-based secret attempt index for secret rotation.
	// The server calls GetSecret multiple times with increasing Attempt values
	// when the first secret fails to deobfuscate the packet.
	Attempt int
}

SecretRequest contains information about the client connection for secret lookup.

type SecretResponse

type SecretResponse struct {
	// Secret is the shared secret for packet obfuscation.
	// If nil, packets will not be obfuscated.
	Secret []byte
	// UserData is optional metadata passed to handlers.
	UserData map[string]string
	// Attempts is the total number of secrets available for rotation.
	// A value of 0 or 1 means no rotation (single secret).
	// When greater than 1, the server will try each secret in order
	// on the first packet of a connection until one succeeds.
	Attempts int
}

SecretResponse contains the secret and optional user data for a client.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is a TACACS+ server.

func NewServer

func NewServer(opts ...ServerOption) *Server

NewServer creates a new TACACS+ server with the given options.

func (*Server) Addr

func (s *Server) Addr() net.Addr

Addr returns the server's listener address.

func (*Server) IsRunning

func (s *Server) IsRunning() bool

IsRunning returns true if the server is currently running.

func (*Server) Serve

func (s *Server) Serve() error

Serve starts accepting connections on the configured listener. This method blocks until the server is shut down.

func (*Server) Shutdown

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

Shutdown gracefully shuts down the server.

type ServerOption

type ServerOption func(*Server)

ServerOption configures a Server.

func WithAccountingHandler

func WithAccountingHandler(handler AccountingHandler) ServerOption

WithAccountingHandler sets the accounting handler.

func WithAuthenticationHandler

func WithAuthenticationHandler(handler AuthenticationHandler) ServerOption

WithAuthenticationHandler sets the authentication handler.

func WithAuthorizationHandler

func WithAuthorizationHandler(handler AuthorizationHandler) ServerOption

WithAuthorizationHandler sets the authorization handler.

func WithHandler

func WithHandler(handler Handler) ServerOption

WithHandler sets a combined handler for all request types.

func WithSecretProvider

func WithSecretProvider(provider SecretProvider) ServerOption

WithSecretProvider sets the secret provider for the server.

func WithServerListener

func WithServerListener(ln Listener) ServerOption

WithServerListener sets the listener for the server.

func WithServerMaxBodyLength

func WithServerMaxBodyLength(maxLength uint32) ServerOption

WithServerMaxBodyLength sets the maximum allowed body length for incoming packets.

func WithServerReadTimeout

func WithServerReadTimeout(timeout time.Duration) ServerOption

WithServerReadTimeout sets the read timeout for client connections.

func WithServerSecret

func WithServerSecret(secret string) ServerOption

WithServerSecret sets a static secret for all clients.

func WithServerSecretBytes

func WithServerSecretBytes(secret []byte) ServerOption

WithServerSecretBytes sets a static secret for all clients.

func WithServerSessionStore

func WithServerSessionStore(store SessionStore) ServerOption

WithServerSessionStore sets the session store. If store is nil, the default memory session store is retained.

func WithServerWriteTimeout

func WithServerWriteTimeout(timeout time.Duration) ServerOption

WithServerWriteTimeout sets the write timeout for client connections.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session represents a TACACS+ session. A session is identified by a unique session ID and tracks the sequence of packets.

func NewSession

func NewSession(isClient bool) (*Session, error)

NewSession creates a new session with a randomly generated session ID. If isClient is true, the session is for a client (odd sequence numbers). If isClient is false, the session is for a server (even sequence numbers).

func NewSessionWithID

func NewSessionWithID(id uint32, isClient bool) *Session

NewSessionWithID creates a new session with the specified session ID.

func (*Session) Created

func (s *Session) Created() time.Time

Created returns the time when the session was created.

func (*Session) ID

func (s *Session) ID() uint32

ID returns the session ID.

func (*Session) IsClient

func (s *Session) IsClient() bool

IsClient returns true if this is a client session.

func (*Session) LastActivity

func (s *Session) LastActivity() time.Time

LastActivity returns the time of the last activity on this session.

func (*Session) NextSeqNo

func (s *Session) NextSeqNo() (uint8, error)

NextSeqNo returns the next sequence number and increments the internal counter. For clients: 1, 3, 5, ... (odd numbers) For servers: 2, 4, 6, ... (even numbers) Returns ErrSequenceOverflow if the sequence number would wrap around.

func (*Session) SeqNo

func (s *Session) SeqNo() uint8

SeqNo returns the current sequence number.

func (*Session) SetState

func (s *Session) SetState(state SessionState)

SetState sets the session state.

func (*Session) State

func (s *Session) State() SessionState

State returns the current session state.

func (*Session) Touch

func (s *Session) Touch()

Touch updates the last activity time.

func (*Session) UpdateSeqNo

func (s *Session) UpdateSeqNo(seqNo uint8)

UpdateSeqNo updates the sequence number after receiving a packet.

func (*Session) ValidateSeqNo

func (s *Session) ValidateSeqNo(seqNo uint8) bool

ValidateSeqNo validates an incoming sequence number. Returns true if the sequence number is valid for the current session state.

type SessionState

type SessionState uint8

SessionState represents the current state of a TACACS+ session.

const (
	// SessionStateNew indicates a newly created session.
	SessionStateNew SessionState = iota

	// SessionStateActive indicates an active session with ongoing communication.
	SessionStateActive

	// SessionStateComplete indicates a successfully completed session.
	SessionStateComplete

	// SessionStateError indicates a session that ended with an error.
	SessionStateError
)

func (SessionState) String

func (s SessionState) String() string

String returns a string representation of the session state.

type SessionStore

type SessionStore interface {
	// Get retrieves a session by ID.
	Get(id uint32) (*Session, bool)

	// Put stores a session.
	Put(session *Session)

	// Delete removes a session by ID.
	Delete(id uint32)

	// Cleanup removes expired sessions older than the given duration.
	Cleanup(maxAge time.Duration) int
}

SessionStore is the interface for session storage.

type TCPDialer

type TCPDialer struct {
	// Timeout is the maximum duration for the dial to complete.
	// If zero, no timeout is applied.
	Timeout time.Duration

	// LocalAddr is the local address to use when dialing.
	// If nil, a local address is automatically chosen.
	LocalAddr *net.TCPAddr
}

TCPDialer implements Dialer for TCP connections.

func (*TCPDialer) Dial

func (d *TCPDialer) Dial(ctx context.Context, network, address string) (Conn, error)

Dial connects to the address using TCP.

type TLSConn

type TLSConn interface {
	Conn
	// ConnectionState returns the TLS connection state.
	ConnectionState() tls.ConnectionState
}

TLSConn represents a TLS-secured connection. Use IsTLSConn to check if a Conn is TLS-secured.

type TLSDialer

type TLSDialer struct {
	// Timeout is the maximum duration for the dial to complete.
	Timeout time.Duration

	// Config is the TLS configuration to use.
	// If nil, a default configuration is used.
	Config *tls.Config
}

TLSDialer implements Dialer for TLS connections.

func (*TLSDialer) Dial

func (d *TLSDialer) Dial(ctx context.Context, network, address string) (Conn, error)

Dial connects to the address using TLS.

Directories

Path Synopsis
examples
tacacs-client command
Package main provides an example TACACS+ client.
Package main provides an example TACACS+ client.
tacacs-client-tls command
Package main provides an example TACACS+ client using TLS 1.3 (RFC 9887).
Package main provides an example TACACS+ client using TLS 1.3 (RFC 9887).
tacacs-server command
Package main provides an example TACACS+ server.
Package main provides an example TACACS+ server.
tacacs-server-tls command
Package main provides an example TACACS+ server using TLS 1.3 (RFC 9887).
Package main provides an example TACACS+ server using TLS 1.3 (RFC 9887).

Jump to

Keyboard shortcuts

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