Skip to content

Linux installer: EAP authentication breaks on recent Linux versions (tested on Ubuntu 26.04, among others) — stale embedded CA bundle fails cert validation #385

Description

@m4r4d0n4

The Linux installer pins RADIUS server certificate validation to a CA bundle embedded in the
script at generation time (Config.CA, passed as 802-1x.ca-cert). When the certificate
chain presented during EAP-TLS ends up not covered by that embedded bundle, EAP authentication
fails instantly and 100% reproducibly with no useful error surfaced to the user —
NetworkManager just reports no-secrets, which misleadingly suggests a credentials problem.
We've confirmed this on Ubuntu 26.04 (NetworkManager 1.54.3); given the mechanism is generic
(OpenSSL/wpa_supplicant chain-building from a standalone ca-cert file), we'd expect it to
reproduce on any recent Linux distro shipping current NetworkManager/wpa_supplicant.

This is a regression, not a longstanding issue: the same installer, same embedded CA
bundle, and same credentials work correctly without any changes on older Ubuntu releases and
on many older Linux distro/NetworkManager/wpa_supplicant combinations we tested against. The
failure only shows up on recent versions, which points at a behavior change somewhere in how
newer OpenSSL/wpa_supplicant build the trust chain from a standalone ca-cert PEM file (rather
than at anything wrong with the embedded bundle itself, which validates fine elsewhere).

This is distinct from #354 (NUL-terminated file:// URIs) — we found this with the NUL fix
applied and it still failed, confirming it's a separate root cause. See our writeup in that
PR thread.

Important environment detail: in our deployment, this failure only happens when the client
authenticates through a RADIUS proxy on an AP controller — specifically Extreme Networks
XCC and Identity Engines
sitting in front of our RADIUS backend. Access points from other
vendors on the same network (Aerohive and Juniper/Mist) connect successfully with the
same installer, same embedded CA bundle, same credentials — the only difference being
those APs don't route authentication through that proxy layer. This strongly suggests the issue
is in how the certificate chain is presented/reconstructed by the Extreme RADIUS proxy
(possibly re-signing or forwarding a different/longer chain than the backend RADIUS server
would present directly), not in the RADIUS backend itself or in the client's EAP config.

Environment

  • Fails on: Ubuntu 26.04 LTS, NetworkManager 1.54.3 (netplan-managed), wpa_supplicant 2.11.
  • Works fine on: older Ubuntu releases and other, older Linux/NetworkManager/wpa_supplicant
    combinations, with the exact same installer and CA bundle — narrowing this down to a change
    in recent NM/wpa_supplicant/OpenSSL versions, not the institution's cert setup.
  • Institution realm urjc.es, EAP-PEAP/MSCHAPv2.
  • Fails: APs behind Extreme Networks XCC / Identity Engines RADIUS proxy.
  • Works: APs behind Aerohive and Juniper controllers (no RADIUS proxy hop for auth).

Evidence

CTRL-EVENT-EAP-PEER-CERT depth=1 subject='/C=AT/O=ZeroSSL GmbH/CN=ZeroSSL RSA DV SSL CA 2'
CTRL-EVENT-EAP-PEER-CERT depth=0 subject='/CN=europa.urjc.es'
CTRL-EVENT-EAP-TLS-CERT-ERROR reason=1 depth=1 subject='...ZeroSSL...' err='unable to get local issuer certificate'
CTRL-EVENT-EAP-FAILURE EAP authentication failed

The server's cert chains through a ZeroSSL intermediate to Sectigo Public Server
Authentication Root R46
. The bundle embedded in our institution's installer (Comodo AAA +
Sectigo R46 + HARICA) technically already includes that same Sectigo root — yet
The server's cert chains through a ZeroSSL intermediate to Sectigo Public Server
Authentication Root R46
. The bundle embedded in our institution's installer (Comodo AAA +
Sectigo R46 + HARICA) technically already includes that same Sectigo root — yet
wpa_supplicant/OpenSSL fails to build the trust chain when it's supplied as a loose ca-cert
file, but only for the APs whose auth goes through the Extreme XCC/Identity Engines proxy, and
only on recent NM/wpa_supplicant versions. We haven't fully pinned down why (possibly the proxy
presents a different/incomplete chain, or newer OpenSSL is stricter about chain building from a
standalone PEM), but the failure is deterministic and 100% reproducible on that path.

What worked

Using the OS's own trust store instead of the embedded bundle:

 s_8021x_data = {
     'eap': [Config.eap_outer.lower()],
     'identity': self.user_data.username,
-    'ca-cert': dbus.ByteArray(f"file://{self.cacert_file}\0".encode()),
+    'system-ca-certs': True,
     match_key: match_value}

Ubuntu already trusts Sectigo R46 by default, so this validates correctly and connects in ~5s,
including through the Extreme proxy path that previously failed. Tested end-to-end (profile
deleted and recreated from scratch).

Discussion

We understand system-ca-certs=True trades "pin exactly the CA the institution intended" for
"trust whatever the OS trusts", which is a real regression in strictness — we've paired it with
domain-suffix-match on our end to limit the blast radius. But this still doesn't explain why
only the Extreme XCC/Identity Engines proxy path fails, only on recent NM/wpa_supplicant, while
direct-to-backend paths (Aerohive, Juniper) and older client versions succeed with the exact
same embedded bundle. Options we can see:

  1. Default to system-ca-certs=True and drop the embedded bundle entirely — simplest, works
    around the issue regardless of which proxy/controller or client version is involved, but
    loses the pinning CAT is presumably designed to provide.
  2. Keep the embedded bundle as the primary ca-cert, but fall back to system-ca-certs if the
    embedded one fails to validate — closer to current behavior, but adds installer complexity.
  3. If this turns out to be specific to how Extreme XCC/Identity Engines proxies present the
    chain (truncated/reordered intermediates) combined with stricter chain-building in recent
    OpenSSL/wpa_supplicant, that may warrant a separate report to Extreme rather than a CAT-side
    fix — but from the client's perspective the installer's rigid pinning to a single embedded
    bundle is what turns a proxy quirk (that only newer clients are sensitive to) into a hard
    authentication failure, so we think it's still worth CAT being more resilient here regardless
    of root cause on the network side.

Happy to open a PR for whichever direction maintainers think fits CAT's design goals, and can
gather more diagnostics on the proxy side if useful (e.g. packet capture of the EAP-TLS
handshake through the Extreme proxy vs. direct, and on older vs. newer clients).

Reproduction

  1. Generate an installer for an institution whose deployment includes a RADIUS proxy layer on
    the AP controller (in our case Extreme XCC / Identity Engines) in front of the actual RADIUS
    backend.
  2. Connect via an AP that routes authentication through that proxy, from a recent Linux client
    (e.g. Ubuntu 26.04) — observe instant CTRL-EVENT-EAP-TLS-CERT-ERROR /
    unable to get local issuer certificate in wpa_supplicant debug logs despite correct
    credentials.
  3. Connect via an AP that does not route through the proxy (in our case Aerohive/Juniper), or
    from an older Linux client — same installer, same credentials, connects successfully.
  4. Reconfigure the NetworkManager profile with 802-1x.system-ca-certs=yes and no ca-cert —
    connects successfully through both paths.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions