PEAP correct client certificate
Hello, I'm currently setting up a RADIUS server(v. 2.2.8) for the first time. I followed the instructions and could connect with EAP and PEAP to my server. Since I only want to use PEAP I disabled every other authentication method by commenting out everything else in /sites-enabled/default. This works fine, since I cant connect with normal EAP anymore. I went through the process of creating my own certificate with openssl and set everything up in eap.conf under eap-tls{}. In peap{} I added EAP-TLS-Require-Client-Cert = Yes. The problem is, that the client can connect to the server even though he doesnt have the correct client certificate. How can I tell the server to check the client certificate?
On Nov 20, 2017, at 2:53 AM, Oliver Tollning <oliver@tollning.com> wrote:
Since I only want to use PEAP I disabled every other authentication method by commenting out everything else in /sites-enabled/default. This works fine, since I cant connect with normal EAP anymore.
OK...
I went through the process of creating my own certificate with openssl and set everything up in eap.conf under eap-tls{}. In peap{} I added EAP-TLS-Require-Client-Cert = Yes.
Why? Nothing in that file suggested you could do that.
The problem is, that the client can connect to the server even though he doesnt have the correct client certificate.
How can I tell the server to check the client certificate?
Read the comments in the "eap.conf" file. They tell you what to do. The attribute has to go into the "control" list. See "man unlang". e.g. Somewhere in the "authorize" section, add: update control { EAP-TLS-Require-Client-Cert = Yes } But be aware that many clients *cannot* do client certificates with PEAP. Alan DeKok.
Alan Dekok wrote:
e.g. Somewhere in the "authorize" section, add:
update control { EAP-TLS-Require-Client-Cert = Yes }
But be aware that many clients *cannot* do client certificates with PEAP.
Alan DeKok.
As an aside/tangent to this, I'm wondering if I am reading the code right or missing something... every place that SSL_VERIFY_CLIENT is set, SSL_VERIFY_FAIL_IF_NO_PEER_CERT is also set. So as far as I can see, there is no way to make client certificates optional with PEAP. Not that I expect MS or Google or Apple to suddenly come down with a case of sanity and start allowing this as an option, but it would seem to me that if you had a mixed environment of machines that can and cannot do client certs with PEAP (that is, some number of professionally configured wpa_supplicants) you might want to do something like this in post-auth: 1) Send any mschap-authed client that offered no certificate to a guest VLAN or some other restricted area. 2) Assuming you encoded the expected CSIDs and/or usernames in a cert attribute when you issued it, alert/quarantine on any mismatches. 3) Send any mschap-authed client with an expired certificate to a VLAN where SCEP/NAC/remediation servers are accessible. 4) Send mschap-authed clients with valid certificates onto various vlans based on username and/or csid and/or cert attributes. Well, anyway, a guy can dream. However as things currently stand you cannot get the TLS-Client-* attributes, even for clients that do offer a cert, without requiring a cert and thus kicking cert-less users off the SSID entirely. Am I reading the current situation right? If so I'll add that to my wishlist for one of my rare moods when I suddenly get an inspiration to do something productive for a change. Or... am I missing a switcharoo trick where you can somehow check for cert presence and then run the validation outside the OpenSSL API? - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
On Nov 20, 2017, at 3:16 PM, Brian Julin <BJulin@clarku.edu> wrote:
As an aside/tangent to this, I'm wondering if I am reading the code right or missing something... every place that SSL_VERIFY_CLIENT is set, SSL_VERIFY_FAIL_IF_NO_PEER_CERT is also set. So as far as I can see, there is no way to make client certificates optional with PEAP.\
Those flags are set in the SSL* structure. i.e. the one setting up *this* connection. The function creating the default SSL_CTX *does* set those flags. But the "create this SSL" function clears them, if there's no requirement for client certs. I've tested PEAP using eapol_text with / without client certs. It works.
Not that I expect MS or Google or Apple to suddenly come down with a case of sanity and start allowing this as an option, but it would seem to me that if you had a mixed environment of machines that can and cannot do client certs with PEAP (that is, some number of professionally configured wpa_supplicants) you might want to do something like this in post-auth:
1) Send any mschap-authed client that offered no certificate to a guest VLAN or some other restricted area. 2) Assuming you encoded the expected CSIDs and/or usernames in a cert attribute when you issued it, alert/quarantine on any mismatches. 3) Send any mschap-authed client with an expired certificate to a VLAN where SCEP/NAC/remediation servers are accessible.
If the client cert has expired, you don't really get MSCHAP auth. The connection usually just drops in the TLS layer.
4) Send mschap-authed clients with valid certificates onto various vlans based on username and/or csid and/or cert attributes.
Well, anyway, a guy can dream.
However as things currently stand you cannot get the TLS-Client-* attributes, even for clients that do offer a cert, without requiring a cert and thus kicking cert-less users off the SSID entirely.
No.. the client *doesn't* send a client certificate unless it's (a) been configured on the client, and (b) requested by the server.
Am I reading the current situation right? If so I'll add that to my wishlist for one of my rare moods when I suddenly get an inspiration to do something productive for a change.
see tls_new_session() for details. It sets the verify mode.
Or... am I missing a switcharoo trick where you can somehow check for cert presence and then run the validation outside the OpenSSL API?
That's actually allowed by OpenSSL. We don't really use it... Alan DeKok.
Alan DeKok wrote:
On Nov 20, 2017, at 3:16 PM, Brian Julin <BJulin@clarku.edu> wrote:
As an aside/tangent to this, I'm wondering if I am reading the code right or missing something... every place that SSL_VERIFY_CLIENT is set, SSL_VERIFY_FAIL_IF_NO_PEER_CERT is also set. So as far as I can see, there is no way to make client certificates optional with PEAP.\
Those flags are set in the SSL* structure. i.e. the one setting up *this* connection.
The function creating the default SSL_CTX *does* set those flags. But the "create this SSL" function clears them, if there's no requirement for client certs.
I've tested PEAP using eapol_text with / without client certs. It works.
I can see that the flags only get set in tls_new_session if the client_cert boolean is asserted. But in that case it also unconditionally sets SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Maybe I'm just missing exactly where that can get cleared. Is the "create this SSL" function something other than that? What I'm talking about here is the same server serving both PEAP clients with certificates and PEAP clients without certificates, and still being able to access the TLS-Client-* variables in post-auth if/when the client did provide a cert.
If the client cert has expired, you don't really get MSCHAP auth. The connection usually just drops in the TLS layer.
I'm assuming one could teach their validator to "ignore" the expiry date so a decision about what to do about that could be deferred until unlang. I have no idea whether the OpenSSL utility makes that easy or not.
No.. the client *doesn't* send a client certificate unless it's (a) been configured on the client, and (b) requested by the server.
My understanding is that SSL_VERIFY_PEER controls whether the server requests a certificate, and that FreeRADIUS only sets that when it is requiring certificates, so there's no avenue for "request a certificate, validate it if the client responds with one, but if no certificate was offered proceed anyway and decide what to do about that later on in unlang." if (client_cert) { RDEBUG2("Requiring client certificate"); verify_mode = SSL_VERIFY_PEER; verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; verify_mode |= SSL_VERIFY_CLIENT_ONCE; } ...pretty much the same thing as in both other places where those flags are referenced. Nothing sets SSL_VERIFY_PEER without also setting SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Is it something internal to OpenSSL? I admit I don't know that API much at all. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
On Nov 20, 2017, at 3:58 PM, Brian Julin <BJulin@clarku.edu> wrote:
I can see that the flags only get set in tls_new_session if the client_cert boolean is asserted. But in that case it also unconditionally sets SSL_VERIFY_FAIL_IF_NO_PEER_CERT.
Yes. But again... that's only for the case when a client cert is required.
What I'm talking about here is the same server serving both PEAP clients with certificates and PEAP clients without certificates, and still being able to access the TLS-Client-* variables in post-auth if/when the client did provide a cert.
Yes, that works. I've tested it. If you require a client cert for user A, you *don't* need to require a client cert for user B.
My understanding is that SSL_VERIFY_PEER controls whether the server requests a certificate, and that FreeRADIUS only sets that when it is requiring certificates, so there's no avenue for "request a certificate, validate it if the client responds with one, but if no certificate was offered proceed anyway and decide what to do about that later on in unlang."
Pretty much.
...pretty much the same thing as in both other places where those flags are referenced. Nothing sets SSL_VERIFY_PEER without also setting SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Is it something internal to OpenSSL? I admit I don't know that API much at all.
It's in our code, it's not in OpenSSL. I suppose with a bit of poking, you could add a FreeRADIUS flag saying "request client cert, but don't require it" I'm not sure why that would be useful, tho. Alan DeKok.
Alan DeKoK wrote:
On Nov 20, 2017, at 3:58 PM, Brian Julin <BJulin@clarku.edu> wrote:
What I'm talking about here is the same server serving both PEAP clients with certificates and PEAP clients without certificates, and still being able to access the TLS-Client-* variables in post-auth if/when the client did provide a cert.
Yes, that works. I've tested it.
If you require a client cert for user A, you *don't* need to require a client cert for user B.
Oh... are you talking about setting the EAP-TLS-Require-Client-Cert control item? If so, the problem with that is: how do you know when to do that? It's undoubtably a useful feature for people who have a reliably consistent database of all identifiers that should present a cert, but in some environments that's just too chaotic to pull off... e.g. when users can nuke and reinstall an OS or multi-boot. Anyway I didn't mean to derail the user list. I could take this to a github issue unless there's a better place for wishlist stuff. Thanks for the clarifications. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
On Nov 20, 2017, at 4:27 PM, Brian Julin <BJulin@clarku.edu> wrote:
Oh... are you talking about setting the EAP-TLS-Require-Client-Cert control item?
Yes.
If so, the problem with that is: how do you know when to do that?
Policy... usually looking up user name / device / whatever in a DB.
It's undoubtably a useful feature for people who have a reliably consistent database of all identifiers that should present a cert, but in some environments that's just too chaotic to pull off... e.g. when users can nuke and reinstall an OS or multi-boot.
Well... if the user screws up their system, the safest thing to do is reject them. If they should have a cert, then the server shouldn't make it optional. If they shouldn't have a cert, why would they present one? Where would they get it from? It's always better to understand what to do, and to do it right. Guessing is almost always bad.
Anyway I didn't mean to derail the user list. I could take this to a github issue unless there's a better place for wishlist stuff. Thanks for the clarifications.
That's fine. Alan DeKok.
Alright, I took your suggestions to heart and installed ubuntu+freeradius 3.0 from scratch. configured the users and clients configs so that I can connect. Testing with peap: Access-Accept. OK Then used the CA.pl with -newca -newreq-nodes -sign Made a dh file and copied the random with dd to another folder for easier access eap.conf eap default_eap_type = peap tls-config tls-common put in the key file, certificate file, dh file, random file and ca file ca_path =/etc/freeradius/3.0/eap/eapCA/ then enabled verify { tmpdir = /etc/freeradius/3.0/tmp client = "/usr/bin/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" } no change in peap peap { tls = tls-common .... } Now if I start freeradius -X and connect I still get an Access-Accept even though my client doesnt have the correct client certificate (because I never created it). And if I scroll up in the debug mode I get a eap_peap: [eaptls verify] = ok Why does my server not verify the client correctly (or at all) Thanks for any input/help Tweet
On Nov 23, 2017, at 3:38 PM, Oliver Tollning <oliver@tollning.com> wrote:
Alright, I took your suggestions to heart and installed ubuntu+freeradius 3.0 from scratch.
That's good...
configured the users and clients configs so that I can connect.
Testing with peap: Access-Accept. OK
Then used the CA.pl with -newca -newreq-nodes -sign
The server comes with scripts to create certs. See raddb/certs/
Made a dh file and copied the random with dd to another folder for easier access
eap.conf eap default_eap_type = peap
tls-config tls-common put in the key file, certificate file, dh file, random file and ca file
ca_path =/etc/freeradius/3.0/eap/eapCA/
then enabled verify { tmpdir = /etc/freeradius/3.0/tmp client = "/usr/bin/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" }
Which runs the external verification command... if there's a client certificate.
no change in peap peap { tls = tls-common .... }
Now if I start freeradius -X and connect I still get an Access-Accept even though my client doesnt have the correct client certificate (because I never created it).
That's exactly how it's supposed to work. You didn't tell the server to require a client certificate. So it didn't.
And if I scroll up in the debug mode I get a eap_peap: [eaptls verify] = ok
Why does my server not verify the client correctly (or at all)
The server doesn't magically know that PEAP is supposed to have a client certificate. You have to tell it. Put this into the "authorize" section of raddb/sites-enabled/default: update control { EAP-TLS-Require-Client-Cert = Yes } It's what I told you to do in a message a few days ago. Following instructions helps you solve problems. Alan DeKok.
Which runs the external verification command... if there's a client certificate.
no change in peap peap { tls = tls-common .... }
Now if I start freeradius -X and connect I still get an Access-Accept even though my client doesnt have the correct client certificate (because I never created it). That's exactly how it's supposed to work.
You didn't tell the server to require a client certificate. So it didn't.
good
And if I scroll up in the debug mode I get a eap_peap: [eaptls verify] = ok
Why does my server not verify the client correctly (or at all) The server doesn't magically know that PEAP is supposed to have a client certificate. You have to tell it.
Put this into the "authorize" section of raddb/sites-enabled/default:
update control { EAP-TLS-Require-Client-Cert = Yes }
It's what I told you to do in a message a few days ago.
Following instructions helps you solve problems.
Alan DeKok. I did add it to sites-enabled/default but I accidently put it under authenticate *dumb me*
Now the client gets rejected, thats good. I installed a client certificate on the client but he still gets rejected :mhmhmh: Its either 1) I accidently did something else stupid somewhere in the config files 2) the radius server cant access the CA file, even though he correctly starts or 3) The client didnt handle the certificate correty, read as: I did something wrong. I'm leaning heavily towards 3), seems to me its a client problem. Anyways, will investigate some more until the problem is found :) Thank you guys so much for your help, really appreciate it. Tweet.
On Nov 23, 2017, at 5:19 PM, Oliver Tollning <oliver@tollning.com> wrote:
Now the client gets rejected, thats good.
That's good...
I installed a client certificate on the client but he still gets rejected :mhmhmh:
The debug output will *mostly* tell you why. Sometimes the client just stops EAP without any message. But in this case, it's likely that the debug output will tell you what's going on.
Its either 1) I accidently did something else stupid somewhere in the config files 2) the radius server cant access the CA file, even though he correctly starts or 3) The client didnt handle the certificate correty, read as: I did something wrong.
I'm leaning heavily towards 3), seems to me its a client problem.
If the client is Windows, it won't do PEAP with client certificates Alan DeKok.
On 20 November 2017 07:53:15 GMT+00:00, Oliver Tollning <oliver@tollning.com> wrote:
I'm currently setting up a RADIUS server(v. 2.2.8) for the first time. I followed the instructions and could connect with EAP and PEAP to my server.
To add to what Alan said, if you're installing a new server, please don't use version 2. It's obsolete and end of life. Version 3.0.15 should be your starting point. -- Matthew
participants (4)
-
Alan DeKok -
Brian Julin -
Matthew Newton -
Oliver Tollning