eap
EAP method registry and built-in method implementations.
This package replaces the single-file pyrad2/eap.py that shipped
through 3.0. All historical names — build_eap_identity,
inject_eap_identity, apply_eap_md5_challenge,
password_from_packet, EAP_MESSAGE_ATTR, STATE_ATTR,
USER_NAME_ATTR, USER_PASSWORD_ATTR — remain importable from
pyrad2.eap so existing call sites need no change.
The new surface is the EapMethod ABC plus a small registry
(register_method / get_method). Both the sync Client and
async ClientAsync (and the RadSec client) look up the method by
the auth_type set on the outgoing AuthPacket and drive it
through a transport-neutral challenge loop, so adding a new method is
a matter of subclassing EapMethod and calling
register_method — no client changes required.
To add a new method::
from pyrad2.eap import EapMethod, register_method
class MschapV2Method(EapMethod):
def start(self, pkt): ...
def respond(self, pkt, challenge): ...
register_method("eap-mschapv2", MschapV2Method)
Callers then set pkt.auth_type = "eap-mschapv2" and the rest is
automatic.
EapMethod
Bases: ABC
Pluggable EAP method driving a RADIUS client's challenge loop.
Implementations mutate the same AuthPacket object in place
across the round-trips that span one EAP conversation. The client
handles transport concerns (id allocation, authenticator
regeneration, Message-Authenticator); the method handles only the
EAP payload.
Source code in pyrad2/eap/base.py
start(pkt)
abstractmethod
Seed the initial Access-Request with this method's payload.
Called once before the first send. Typically populates the
EAP-Message attribute on pkt.
respond(pkt, challenge)
abstractmethod
Answer an Access-Challenge by mutating pkt in place.
Implementations are responsible for copying the EAP State
attribute (RFC 2865 §5.24) from challenge when the server
sent one — every multi-roundtrip EAP exchange needs it to keep
the server's session bookkeeping consistent across replies.
Source code in pyrad2/eap/base.py
GtcMethod
Bases: EapMethod
EAP-GTC plaintext-token method.
Stateless. start reuses the shared EAP-Identity helper so the
initial Access-Request looks identical to every other EAP method
pyrad2 ships; respond handles the one round of GTC traffic.
Source code in pyrad2/eap/gtc.py
MschapV2Method
Bases: EapMethod
EAP-MSCHAPv2 driver, stateful per conversation.
Carries the authenticator challenge, peer challenge, and computed NT-Response across the Challenge → Response → Success rounds so the Authenticator Response check on the final Success-Request can use the same inputs the Response was built from.
Source code in pyrad2/eap/mschapv2.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | |
Md5Method
Bases: EapMethod
EAP-MD5 challenge/response (RFC 3748 §5.4).
Stateless — the entire exchange is one round and every input lives
in the packet objects passed to start/respond.
Source code in pyrad2/eap/md5.py
get_method(name)
Return a fresh instance of the method registered under name.
Returns None when name is None or unregistered so the
caller can branch into a non-EAP send path without raising.
Source code in pyrad2/eap/base.py
register_method(name, factory)
Register a method factory under an auth_type string.
name is the value callers set on AuthPacket.auth_type to
select the method. Re-registering the same name replaces the
previous factory, which lets tests swap a method's implementation
without restarting the process.
Source code in pyrad2/eap/base.py
registered_methods()
Return a sorted list of registered auth_type names.
Exposed mainly for diagnostics and tests — production code should
look up by name through get_method.
apply_eap_gtc_challenge(pkt, reply)
Mutate pkt in place to answer an EAP-GTC prompt.
Reads the EAP id from the server's EAP-Request/GTC so the
response echoes it (RFC 3748 §4.2 requires the id to round-trip),
then writes the password back as the GTC data field. The
prompt text after the header is ignored — pyrad2 doesn't surface
it because the client already has the credential to send.
Source code in pyrad2/eap/gtc.py
build_eap_gtc_response(eap_id, password)
Build an EAP-Response/GTC payload.
Layout (5-byte header + N-byte data):
code(1) + id(1) + length(2) + type(1) + data(N)
where length is the total payload length including the header.
Source code in pyrad2/eap/gtc.py
apply_eap_md5_challenge(pkt, reply)
Mutate pkt in place to answer an EAP-MD5 Access-Challenge.
Source code in pyrad2/eap/md5.py
build_eap_identity(password)
Build an EAP-Identity Response payload from a password.
Matches the sync client's historic behaviour: the EAP identifier is
taken from the module-level packet.CURRENT_ID rolling counter.
Source code in pyrad2/eap/md5.py
build_eap_md5_challenge(eap_id, password, eap_md5)
Build an EAP-Type-MD5-Challenge response payload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eap_id
|
int
|
EAP identifier copied from the Access-Challenge. |
required |
password
|
bytes
|
User password (used as the MD5 secret). |
required |
eap_md5
|
bytes
|
Raw EAP-MD5 attribute payload from the challenge, starting with the length-prefix byte the server sent. |
required |
Source code in pyrad2/eap/md5.py
inject_eap_identity(pkt)
password_from_packet(pkt)
Extract the user password from an AuthPacket for EAP framing.
Raises PacketError if no User-Password is present. The
legacy fall-back to User-Name silently mis-keyed the EAP-MD5
challenge with the username, downgrading authentication to a value
that anyone observing the request could reproduce.