Documentation
¶
Overview ¶
Package eap implements the EAP authentication framework and its MSCHAPv2 and TLS methods for IKEv2.
Index ¶
- Constants
- Variables
- func DeriveMSK(password string, ntResponse [24]byte) [64]byte
- func GenerateAuthenticatorResponse(password string, ntResponse [24]byte, peerChallenge, authChallenge [16]byte, ...) [20]byte
- func GenerateNTResponse(authChallenge, peerChallenge [16]byte, userName, password string) [24]byte
- func GetAsymmetricStartKey(masterKey [16]byte, keyLen int, isSend, isServer bool) []byte
- func GetMasterKey(password string, ntResponse [24]byte) [16]byte
- type AllocateResult
- type Method
- type MethodConfig
- type MethodResult
- type Packet
- type PeerResult
- type PeerSession
- type PeerTLSConfig
- type Pool
- type Session
Constants ¶
const ( TypeIdentity uint8 = 1 TypeNAK uint8 = 3 TypeTLS uint8 = 13 TypeMSCHAPv2 uint8 = 26 TypeExpandedEAP uint8 = 254 )
EAP type codes.
const ( CodeRequest uint8 = 1 CodeResponse uint8 = 2 CodeSuccess uint8 = 3 CodeFailure uint8 = 4 )
EAP codes.
Variables ¶
var ( ErrUnsupportedMethod = errors.New("eap: unsupported method") ErrIdentityRequired = errors.New("eap: identity response required first") ErrMethodFailed = errors.New("eap: method authentication failed") )
var ( ErrTooManyRounds = errors.New("eap: exceeded maximum exchange rounds") ErrEAPFailure = errors.New("eap: authenticator sent Failure") )
var ( ErrPoolExhausted = errors.New("pool: all addresses allocated") ErrNotAllocated = errors.New("pool: address not allocated") )
Functions ¶
func DeriveMSK ¶
DeriveMSK constructs the 64-octet EAP MSK from MS-CHAPv2 credentials. RFC 3079 Section 3 + RFC 3748 Section 7.10. MSK = MasterReceiveKey(16) || MasterSendKey(16) || zeroPadding(32). strongSwan and Windows use zero-padded MSK per draft-kamath-pppext-eap-mschapv2-02.
func GenerateAuthenticatorResponse ¶
func GenerateAuthenticatorResponse(password string, ntResponse [24]byte, peerChallenge, authChallenge [16]byte, userName string) [20]byte
GenerateAuthenticatorResponse computes the mutual authentication proof (S= value). RFC 2759 Section 8: GenerateAuthenticatorResponse. Returns 20 raw bytes.
func GenerateNTResponse ¶
GenerateNTResponse computes the full NT-Response for an MS-CHAPv2 exchange. RFC 2759 Section 8: GenerateNTResponse.
func GetAsymmetricStartKey ¶
GetAsymmetricStartKey derives a session key of the requested length. RFC 3079 Section 3: GetAsymmetricStartKey.
func GetMasterKey ¶
GetMasterKey derives the 16-byte MPPE master key from MS-CHAPv2 credentials. RFC 3079 Section 3: GetMasterKey.
Types ¶
type AllocateResult ¶
AllocateResult holds the addresses allocated to a client.
type Method ¶
type Method interface {
// Type returns the EAP type code for this method.
Type() uint8
// Start generates the first EAP-Request for this method.
Start(identifier uint8) *Packet
// Process handles an EAP-Response from the peer and returns the next action.
Process(response *Packet) MethodResult
// Close releases every resource the method holds. The caller MUST call it
// once the exchange has ended, for ANY reason: success, failure, refusal or
// abandonment. A method that starts a goroutine leaks it otherwise.
//
// Close is idempotent and safe on a method that was never started.
Close()
}
Method is the interface for an EAP authentication method (server/authenticator side).
type MethodConfig ¶
type MethodConfig struct {
// For EAP-MSCHAPv2.
Password string `json:"-"` //nolint:gosec // EAP credential, never serialized
// For EAP-TLS.
CACertPEM []byte
ServerCertPEM []byte
ServerKeyPEM []byte
}
MethodConfig holds configuration needed by EAP methods.
type MethodResult ¶
MethodResult is the outcome of processing one EAP exchange round.
Session.handleMethod reads the fields in this order, and the four outcomes they name are mutually exclusive:
FinalRequest send it as the method's last word, then fail with Err Done the exchange succeeded and MSK carries the key Err the exchange failed, and an EAP-Failure answers the peer Response the exchange continues with this EAP-Request
FinalRequest is the method's last word: a packet the method owes the peer on a refusal, sent by an exchange that has already failed. The EAP-Failure that RFC 3748 Section 4.2 obliges follows it on the next round, and nothing else can. A method that sets FinalRequest MUST set Err too, because the packet carries the protocol's reason and Err carries the operator's.
Setting Response BESIDE Err puts the packet nowhere: the Err branch answers with an EAP-Failure and the Response is discarded. That is why the last word has a field of its own rather than a flag over Response, and it is a defect this package has already paid for once (see the EAP-TLS alert in tlsMethod.Process, eap_tls.go).
type Packet ¶
Packet is a parsed EAP packet (Code, Identifier, Type, TypeData). RFC 3748 Section 4: Success/Failure packets have no Type field.
func DecodePacket ¶
DecodePacket parses raw EAP bytes into a Packet.
type PeerResult ¶
PeerResult is the outcome of processing one EAP-Request from the authenticator.
Four outcomes, and the caller reads them in this order (handleEAPResponse, internal/component/ike/engine/fsm.go):
Err the exchange failed, and the IKE SA is put in StateDead Done the exchange succeeded and MSK carries the key Response the exchange continues with this EAP-Response Discarded the packet was dropped and the exchange waits for the next one
Discarded is a field rather than the absence of the other three. RFC 3748 Section 4.2 makes a peer drop several packets in silence, and the wire behavior of dropping one is indistinguishable from a result that fell out of a branch nobody wrote: both send nothing and both end no exchange. A zero value that reads as a valid answer is what ai/rules/principles.md forbids, so the drop says so, and the caller logs it because a forged EAP-Success is a thing an operator wants named.
type PeerSession ¶
type PeerSession struct {
// contains filtered or unexported fields
}
PeerSession manages the EAP peer (client/initiator) side of an exchange.
func NewPeerSession ¶
func NewPeerSession(method uint8, identity, password string) *PeerSession
NewPeerSession creates an EAP peer session for the given method.
func NewPeerSessionTLS ¶
func NewPeerSessionTLS(identity string, cfg *PeerTLSConfig) *PeerSession
NewPeerSessionTLS creates an EAP-TLS peer session with certificate material.
func (*PeerSession) Close ¶
func (ps *PeerSession) Close()
Close releases every resource the peer session holds.
The caller MUST call it once the exchange has ended, for ANY reason: an EAP-Success, an EAP-Failure, a refused method, or an authenticator that stopped answering. The EAP-TLS client runs its TLS engine on a goroutine parked in eapTLSTransport.Read, and only closing the transport releases it, so an exchange that ends without this call strands that goroutine together with the tls.Conn and the handshake secrets it holds.
The guard reads tlsStarted rather than the pointer, because startTLSClient runs on the engine's dispatch goroutine while this runs on the session's owner goroutine. startTLSClient assigns tlsTransport BEFORE it stores that flag, so a load that sees true also sees the assignment.
Idempotent, and safe on an MS-CHAPv2 session or on one whose TLS client never started.
func (*PeerSession) Process ¶
func (ps *PeerSession) Process(request *Packet) PeerResult
Process handles an incoming EAP packet (Request or Success/Failure) from the authenticator and returns the peer's response. On EAP-Success, Done is true and MSK is set.
func (*PeerSession) Succeeded ¶
func (ps *PeerSession) Succeeded() bool
Succeeded reports whether the exchange completed successfully.
type PeerTLSConfig ¶
PeerTLSConfig holds certificate material for the EAP-TLS peer (client).
type Pool ¶
type Pool struct {
// contains filtered or unexported fields
}
Pool manages virtual IP address allocation for road warrior clients.
func NewPool ¶
NewPool creates a pool from IPv4 CIDR, optional IPv6 CIDR, DNS servers, and search domain.
func (*Pool) Allocate ¶
func (p *Pool) Allocate() (*AllocateResult, error)
Allocate assigns the next available address(es) from the pool.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session manages a single EAP exchange (authenticator side).
func NewSession ¶
func NewSession(methodType uint8, config MethodConfig) (*Session, error)
NewSession creates an EAP session for the given method type.
func (*Session) Begin ¶
Begin returns the initial EAP-Request/Identity packet. RFC 3748 Section 5.1: authenticator starts with Identity request.
func (*Session) Close ¶
func (s *Session) Close()
Close releases every resource the exchange holds.
The caller MUST call it once the exchange has ended, for ANY reason: an EAP-Success, an EAP-Failure, a refused method, or a peer that stopped answering. EAP-TLS runs its TLS engine on a goroutine parked in a read that only this call can release, so an exchange that ends without it leaks that goroutine and the TLS keys it holds. The peer decides how many exchanges start and how many of them it abandons, and it is unauthenticated while it does so, which is what makes the omission reachable from the network.
Close is idempotent and safe on a session whose method never started.
func (*Session) Err ¶
Err returns why the method refused the peer, or nil when the exchange failed for a reason the method never saw: a peer that answered the Identity request with something else, or a NAK of the offered method. The caller MUST log it beside its own failure line, because RFC 3748 Section 4.2 leaves an EAP-Failure packet no field to carry a reason in and this is the only place one exists.
func (*Session) Identity ¶
Identity returns the peer identity extracted from the EAP-Response/Identity.