# radiusd and PEAP: certificate validation?



## zirias@ (May 16, 2021)

I'm using net/freeradius3 to provide authentication with PEAP for wifi clients. Previously, I used certificates issued by my own local CA. This worked well when installing the CA certificate on the clients (including my android phone). They were issued for the name of my local domain, let's say `home.mydomain.invalid`, although the radiusd is running on a host inside that domain, e.g. `auth.home.mydomain.invalid`.

Now, a persisting problem was that the older android phone of my wife would never accept the certificate. I read about the risks of using certificates issued by a public CA (which would be someone managing to get a "fake" certificate for my domain name somehow and use it to setup a fake AP stealing user credentials, well…) and decided that risk was small enough, so I now tried to use a "letsencrypt" certificate on the radiusd instead.

Unfortunately, the problem got worse: My own phone won't accept that certificate either. So far I tried a certificate issued for `home.mydomain.invalid` as well as one issued for both `auth.home.mydomain.invalid` _and_ `home.mydomain.invalid`.

The first thing I don't understand is: how does a client know which name to expect? In the APs, you only configure the IP-Address(!) of the radius server, and give it a "radius profile name" (which I set to `home.mydomain.invalid`). And then, could there be other things "wrong" with the certificate so clients trying to authenticate with PEAP would reject it?


----------



## covacat (May 16, 2021)

i have similar setup with a real tld and domain using a letsencrypt cert
iirc there was  a problem with one android phone i tested but cant remember how i solved it (if i solved it)
it works on mac / windows 10 / latest ios
mac is prompting me to accept the cert everytime i renew it 
but the certificate is a vanilla one which i use for lots of services (web / imap / smtp / ike)
i can test again on  monday with an android phone


----------



## zirias@ (May 16, 2021)

JFTR, of course I use a real TLD/domain here as well, `mydomain.invalid.` just used for not disclosing it unnecessarily  Thanks for confirming that it _should_ work.


----------



## covacat (May 16, 2021)

i dont think clients care about the cn . they care about the signing chain and if root ca and intermediates are trusted
also they may barf if certs are md5 signed and other stuff
this is what i have in mods-enabled/eap

private_key_file = ${certdir}/privkey.pem
dh_file = ${certdir}/dh
certificate_file = ${certdir}/cert.pem
ca_file = ${certdir}/chain.pem
cert and chain is what you get from letsencrypt with same names


----------



## zirias@ (May 16, 2021)

covacat said:


> i dont think clients care about the cn . they care about the signing chain and if root ca and intermediates are trusted


If that's true, it would be a major security risk. A fake AP could use any valid certificate for _any_ name to "trick" clients into authenticating with MSCHAPv2. So, if that's really the case, I'm back to my own local CA


----------



## covacat (May 16, 2021)

you are presented with the cert its not accepted without user consent
or at least mine were not


----------



## zirias@ (May 16, 2021)

Oh, of course, that's a way to solve it. But not a good one…

So, with PEAP, there's no mechanism for the client to know which certificate subject to expect? Can anyone confirm this? In that case, I really think using your own CA and configuring clients to only accept certificates signed by this CA is the only sane approach


----------



## covacat (May 16, 2021)

PEAP-MSCHAPv2 Vulnerability Allows For Credential Theft
					

PEAP-MSCHAPv2 is inherently vulnerable to credential theft via over-the-air attacks. Here's a brief on the issue and a potential solution.




					www.securew2.com
				



so the risk exists but for a home network its probably acceptable if the users are careful enough
the solution is eap-tls but you have to install certs on every client or have an automated distribution method


----------



## zirias@ (May 16, 2021)

covacat said:


> so the risk exists but for a home network its probably acceptable if the users are careful enough


Mostly. But asking the user about every new server certificate is not what I had in mind. I'm still hoping there _is_ a way for the client to determine an expected subject/SAN on the cert and verify against that (which would only leave the attack vector via a fake certificate obtained somehow, quite similar to basic auth via https).

Right now, the situation on my android phone is pretty bad. When telling it to use system certificates, it asks for a domain. I tried putting `home.mydomain.invalid` there, so it matches the certificate. Still, the phone doesn't accept it  You can also select a CA certificate, but android only offers user-installed CA certificates for that (back to square one). The only way to log in right now is setting my phone to accept _any_ certificate (yep, no way to have the phone _ask_ me either  ), so, this is really unacceptable.



covacat said:


> the solution is eap-tls but you have to install certs on every client or have an automated distribution method


Sure, but if I have to configure all clients anyways, I'll rather go with deploying my CA cert there and still use PEAP, restricted to that CA… which didn't work on this one old android phone, which is where I started. Ah, crap…   

Guess I have to check what `wpa_supplicant` on FreeBSD and my Win10 notebook from work make of the new letsencrypt cert, just to get further hints…


----------



## covacat (May 17, 2021)

tested the android phone, galaxy a51 / android 11
it connects to wpa enterprise only if the domain is cert CN or cert DNS
i used use system ca, domain one of cert DNS names and request status
i use GTC for phase 2

if i put in an bogus domain wont connect (invalid credentials)


----------



## zirias@ (May 17, 2021)

Thanks, that's good news! But I still don't understand: What _is_ the domain name in this context? A domain part in the login credentials (like `myuser@home.mydomain.invalid`)?


----------



## covacat (May 17, 2021)

for me it works with the domain for which the cert was issued
user does not have to have @domain.com
it works with both www.dom.com and dom.com


----------



## zirias@ (May 17, 2021)

Hm I guess you misunderstood my question: How does the client know which domain to expect? It connects to an SSID… Or is there a way to explicitly configure a domain on the client? My android phone offers my a "domain" input field, but unfortunately, it doesn't work with my letsencrypt cert


----------



## covacat (May 17, 2021)

image


----------



## covacat (May 17, 2021)

the client expects the domain you type to be cn of cert


----------



## zirias@ (May 17, 2021)

Ok thanks again, that's this input field I was referring to. So, I have yet another problem on my phone, cause putting the correct name there doesn't make it work


----------



## covacat (May 17, 2021)

what error do you get?
because any crap i put in i only get invalid credentials


----------



## zirias@ (May 17, 2021)

Part of the problem is android not giving any meaningful error messages, no matter what's wrong, it's "authentication problem".

But I can see in the radiusd logs it's a TLS problem. When I don't check the cert at all, authentication works.


----------



## covacat (May 17, 2021)

do you send both ca files as root-ca from radius or just the first ?
i send both
also i have

/usr/local/etc/raddb/mods-enabled/eap:        tls_min_version = "1.2"
/usr/local/etc/raddb/mods-enabled/eap:        tls_max_version = "1.2"


----------



## covacat (May 17, 2021)

ok, failed on android 9, because it was either a certificate from an empty list or no verification (which worked)
probably you have to install the CA somehow to make it available for selection (the use system ca's and domain selection is not present)

also non english error messages are even shittier than english ones


----------



## zirias@ (May 17, 2021)

covacat: CA shouldn't be relevant on the server side if you don't intend to verify client certificates. Of course it's important to have the full chain, but I checked what I got from letsencrypt, it contains the whole chain and local verification works correctly. What I found is that you should set `auto_chain = no` to disable any magic constructing the chain, which I did, but doesn't help either. I also have the same TLS version settings. Right now, I think it's my phone's fault – will test with other devices soon.

But:


covacat said:


> ok, failed on android 9, because it was either a certificate from an empty list or no verification (which worked)
> probably you have to install the CA somehow to make it available for selection (the use system ca's and domain selection is not present)


This tells me the whole idea to use letsencrypt doesn't help me after all for the problem with the older phone. So, will probably just switch back to my own CA for PEAP then…


----------



## covacat (May 17, 2021)

its not relevant for veryfing but you still serve the chain for client veification (like for apache ssl) clients may not know the intermediary CAs from their built in/os provided list but know the root one and then trust your cert

letsencrypt works well for imap ssl and ike (better than self signed)


----------



## zirias@ (May 17, 2021)

covacat said:


> its not relevant for veryfing but you still serve the chain for client veification (like for apache ssl) clients may not know the intermediary CAs from their built in/os provided list but know the root one and then trust your cert


Yes, but I checked the cert file obtained from letsencrypt, it contains the whole chain in the correct order, so _that_ is not the problem  I guess the problem is shitty android phones


----------

