Austin Shijo

epestrmTvare6iitk · statistics · ’24–’28

A WiFi outage that traced back to a 2012 cryptography conf

“Permissive fallback” is a supposed feature where standard network managers silently downgrade your security to keep you online. Some tool like wpa_supplicant ignores a rotated certificate or a deprecated hash setup without throwing a single error. The standard assumption is that developers prioritize the appearance of functionality over actual security.

Okay, so my WiFi broke on a Tuesday afternoon, 13:29 IST, April 22, and the daemon I had installed specifically for its reliability couldn’t reconnect. Chasing why pulled me through multiple layers of misconfiguration involving a rotated server certificate, a deprecated authentication method, and a hash protocol running on borrowed time for a decade.

In a hostel with dense access-point coverage, roaming gets noisy. As you walk between buildings, the supplicant program on your device scans for the strongest signal and decides when to switch. Standing between several nodes all broadcasting iitk-sec, a supplicant like wpa_supplicant will oscillate between them on marginal signal differences and degrade your connection. I had migrated my machine to iwd (iNet Wireless Daemon) to avoid exactly this given its newer roaming algorithm is less twitchy.

This is the divide between permissive and strict software. wpa_supplicant is permissive in that it tolerates unsafe states and insecure fallbacks to keep the appearance of functionality. My laptop and the campus WiFi have to agree on how to authenticate. That day, they disagreed. Because iwd refuses unsafe fallbacks, the connection just failed.

Authentication

Enterprise WiFi like iitk-sec uses the Extensible Authentication Protocol (EAP) for negotiation. It happens at layer 2, so before you ever touch the internet your laptop has to prove its identity to a central server. You have the bouncer (RADIUS) checking credentials against a directory service like Active Directory and the tunnel (PEAP or TTLS) creating an encrypted TLS channel between your laptop and the RADIUS server. And you have the payload, the inner method actually verifying your password. PEAP almost always forces MSCHAPv2. TTLS is flexible enough to allow protocols like PAP to pass plaintext straight down the tunnel.

Certificate Validation

First thing I ran was dmesg, then journalctl -u iwd. The logs had the answer in it, which I missed it the first time.

PEAP: Tunnel has disconnected with alert: bad_certificate

My university’s Computer Center’s (the CC, which manages IT infra) setup guide tells you to set the CA certificate to “Do not validate” if the system certificate fails. wpa_supplicant lets you do that. iwd deliberately doesn’t expose the option, at least not easily. Certificate validation matters because skipping it leaves you open to evil-twin attacks where a device faking the iitk-sec SSID can intercept your authentication and walk away with your credentials. iwd enforces server-side identity verification to prevent that. The most charitable read is that the CC had rotated the RADIUS server certificate, and iwd couldn’t validate the new chain against my certificate store, so it terminated the connection.

I needed the new certificate. The usual move would be openssl s_client, but EAP runs at layer 2 before the system has an IP, so there’s no TCP endpoint to query. I could have pulled the cert off another device, but iwd itself made it easier. Running iwd with the TLS debug flag flips on certificate dumping in its ell backend, which I got to know reading the source, and the rejected server certificate ends up in /tmp.

sudo IWD_TLS_DEBUG=1 /usr/lib/iwd/iwd -d

After triggering a connection attempt, the fix involves moving iwd-tls-debug-server-cert.pem from /tmp to /etc/ssl/certs/iitk-radius.pem and pointing the iwd profile at it explicitly. Then NetworkManager will keep overwriting it because it’s modifiable still. Once you mark the file immutable with chattr +i, NetworkManager stops trying.

Restart, and the TLS tunnel comes up:

TTLS: tls_rsa_verify:240 Peer signature verified

But the connection still dropped.

The Protocol Shift

The real failure was deeper in the EAP negotiation:

EAP server tried method 4 while client was configured for method 25 EAP completed with eapFail

The server rejected PEAP (Method 25) and proposed EAP-MD5 (Method 4) instead. iwd correctly refused. In enterprise networks, EAP-MD5 is what gets offered when nothing better matches, a default that triggers when the server’s modern config breaks. Refusing it is the right call given EAP-MD5 has no mutual authentication. It’s not particularly safe when the server demands verification from you, and you don’t get the same right.

But why would a server that negotiated PEAP that morning suddenly reject it that afternoon? I don’t have access to the CC servers, so the exact cause isn’t confirmable. It could be a misconfigured policy update. But there is a more interesting explanation in how PEAP authenticates the inside of its tunnel. PEAP wraps MSCHAPv2, and to evaluate an MSCHAPv2 challenge the RADIUS backend has to compute the response itself, which means it needs either the plaintext password or an NT-hash-equivalent credential on hand.

Unsalted NT hashes are a well-known liability, and modern identity providers and LDAP backends strongly prefer irreversible ones. There are caching workarounds that keep MSCHAPv2 working in mixed environments, but the most charitable read here is that the CC tightened backend hashing and MSCHAPv2 collapsed as a side effect. Once MSCHAPv2 is unavailable, PEAP, which has no other inner method to fall back to, fails along with it.

Resolution

Without MSCHAPv2, the outer method has to change. The CC guide lists TTLS as a fallback, so I switched to EAP-TTLS with PAP. PAP transmits the password as plaintext through the TLS tunnel, which allows the server to hash it dynamically against the modern identity provider.

This shifts the security burden to the TLS tunnel. Skipping certificate validation here hands the password to anyone running a fake AP. Since iwd already forced the validation of the server’s identity in the first step, the tradeoff is safe.

Profile update:

[Security] EAP-Method=TTLS EAP-Identity=username
EAP-TTLS-Phase2-Method=Tunneled-PAP
EAP-TTLS-Phase2-Identity=username
EAP-TTLS-Phase2-Password=password
EAP-TTLS-CACert=/etc/ssl/certs/iitk-radius.pem

After updating the profile and restarting the service, the handshake finished and the interface connected.

Using wpa_supplicant with “Do not validate” and ignoring insecure fallbacks would have been easier. But permissive software obscures the underlying state. iwd forced an evaluation of why the network dropped. Permissive software hides broken systems, and strict software forces you to fix them.

← all posts