Using X.509 Cert. subject and issuer for authorization with EAP-TLS
Hi,
From my understanding (don't hesitate to correct me), the authorization step being done before the authentication step (for the purpose of selecting the allowed authentication method), it does not seem possible to use attributes from the X.509 Certificate provided by the client for the purpose of authorization (it comes too late).
I expected I would be able to extract the information from the client Cert during authentication and make it available for Post-Auth in order to decide what to do in a more precise manner (change attribute, reject, ...). The main idea is to be able to put users from unknown subtrees of my PKI in some guest VLANs by pushing specific attribute to the NAS (a switch or AP). Known users would be put in a specific VLAN associated with their profile. Other users would be rejected. After looking at the source code, I decided to define some specific vendor attributes that I would expect to have only a local meaning (not seen on the cable but infered from the TLS exchange) but I basically failed to see how to do the following *properly*: - where to store the information grabbed in the SSL callback, - how to make that information usable in a transparent fashion for Post-Auth modules like rlm_files, ... - how to force a reject and not only change attributes, ... Thanks for your time. Don't hesitate if you have questions. Cheers, a+
Arnaud Ebalard wrote:
From my understanding (don't hesitate to correct me), the authorization step being done before the authentication step (for the purpose of selecting the allowed authentication method), it does not seem possible to use attributes from the X.509 Certificate provided by the client for the purpose of authorization (it comes too late).
No... there are multiple packet exchanges involved. You can check the certificate ONLY after you've received all of it. This happens during one of the authorization phases, and before authentication happens.
I expected I would be able to extract the information from the client Cert during authentication and make it available for Post-Auth in order to decide what to do in a more precise manner (change attribute, reject, ...).
That's a great feature. As always, patches are welcome.
- where to store the information grabbed in the SSL callback,
Don't. There's no reason to grab that information if no one is looking for it. Instead, save a pointer to the SSL session, and register a callback that can dynamically expand the strings, if, and when, someone asks for it. See xlat.c, and other examples of registering a callback.
- how to make that information usable in a transparent fashion for Post-Auth modules like rlm_files, ...
That's the purpose of the callbacks: to be transparent.
- how to force a reject and not only change attributes, ...
That's a policy. It has nothing to do with certificates. Alan DeKok.
Hi and thanks for your help, Alan DeKok <aland@deployingradius.com> writes:
Arnaud Ebalard wrote:
From my understanding (don't hesitate to correct me), the authorization step being done before the authentication step (for the purpose of selecting the allowed authentication method), it does not seem possible to use attributes from the X.509 Certificate provided by the client for the purpose of authorization (it comes too late).
No... there are multiple packet exchanges involved. You can check the certificate ONLY after you've received all of it. This happens during one of the authorization phases, and before authentication happens.
I might be missing something but the certificates get available during the TLS exchange, i.e. long after the decision from the authorization modules. From the debug I added in the code, the rlm_files module returns OK before the beginning of the authentication steps (implying rcode has been set). This rcode is conditioned by the issue of the authentication (if authentication fails, the Accept will change to a Reject). In my case, the idea is to authorize *unknown* people to authenticate with EAP-TLS and decide later what to do with them (i.e. been someone from my PKI should not automatically imply an Accept). Obviously, I would like to be able to kick people or return specific attributes based on the content of their certificate (where more information is available than simply its username) even if they have been authorized to authenticate. It seems to require actions *after* authentication has happened (i.e. after the certificate gets available).
I expected I would be able to extract the information from the client Cert during authentication and make it available for Post-Auth in order to decide what to do in a more precise manner (change attribute, reject, ...).
That's a great feature. As always, patches are welcome.
If it's feasible (i.e. leads to functional code), i'll post it here.
- where to store the information grabbed in the SSL callback,
Don't. There's no reason to grab that information if no one is looking for it. Instead, save a pointer to the SSL session, and register a callback that can dynamically expand the strings, if, and when, someone asks for it.
See xlat.c, and other examples of registering a callback.
ok. Thanks, i'll take a look and see if it helps.
- how to make that information usable in a transparent fashion for Post-Auth modules like rlm_files, ...
That's the purpose of the callbacks: to be transparent.
ok.
- how to force a reject and not only change attributes, ...
That's a policy. It has nothing to do with certificates.
ok. Is there a place after authentication (i.e. not authorization) where I can act on rcode? If not (and if policy prevents action in Post-Auth), it seems I am stuck. Thanks again for your comments and your time. a+
Arnaud Ebalard wrote:
I might be missing something but the certificates get available during the TLS exchange, i.e. long after the decision from the authorization modules.
Please read what I read. There are MULTIPLE packet exchanges. The certificate is available during ONE of those packet exchanges.
From the debug I added in the code, the rlm_files module returns OK before the beginning of the authentication steps (implying rcode has been set).
Yes. So? Do you understand that multiple packets go back and forth?
This rcode is conditioned by the issue of the authentication (if authentication fails, the Accept will change to a Reject). In my case, the idea is to authorize *unknown* people to authenticate with EAP-TLS
That's not the way EAP-TLS works. They need a client certificate in order to be authenticated.
and decide later what to do with them (i.e. been someone from my PKI should not automatically imply an Accept).
You can turn an Accept into a Reject. You can't turn a Reject into an Accept.
Obviously, I would like to be able to kick people or return specific attributes based on the content of their certificate (where more information is available than simply its username) even if they have been authorized to authenticate. It seems to require actions *after* authentication has happened (i.e. after the certificate gets available).
As I said. This is possible. But... only for known users. If you're trying to authenticate unknown people with EAP-TLS, then it won't work. Stop trying to do the impossible.
- how to force a reject and not only change attributes, ... That's a policy. It has nothing to do with certificates.
ok. Is there a place after authentication (i.e. not authorization) where I can act on rcode? If not (and if policy prevents action in Post-Auth), it seems I am stuck.
$ man unlang Alan DeKok.
Hi, Alan DeKok <aland@deployingradius.com> writes:
Arnaud Ebalard wrote:
I might be missing something but the certificates get available during the TLS exchange, i.e. long after the decision from the authorization modules.
Please read what I read. There are MULTIPLE packet exchanges. The certificate is available during ONE of those packet exchanges.
[...]
Yes. So? Do you understand that multiple packets go back and forth?
Yes, perfectly. Sorry if my response was imprecise or misleading. I clarify things below.
This rcode is conditioned by the issue of the authentication (if authentication fails, the Accept will change to a Reject). In my case, the idea is to authorize *unknown* people to authenticate with EAP-TLS
That's not the way EAP-TLS works. They need a client certificate in order to be authenticated.
Yes, perfectly. To be more precise: - they come with an unknow username in their request but I don't want to kick them at that point (that's what I meant by "authorize *unknown* people"). - they provide a valid certificate during authentication with enough information to act (an OU, a CN, ...)
and decide later what to do with them (i.e. been someone from my PKI should not automatically imply an Accept).
You can turn an Accept into a Reject. You can't turn a Reject into an Accept.
Good. That's all I need.
Obviously, I would like to be able to kick people or return specific attributes based on the content of their certificate (where more information is available than simply its username) even if they have been authorized to authenticate. It seems to require actions *after* authentication has happened (i.e. after the certificate gets available).
As I said. This is possible.
But... only for known users. If you're trying to authenticate unknown people with EAP-TLS, then it won't work. Stop trying to do the impossible.
Their username is unknown but they are not unknown if I have enough information in their certificate to act. The problem is that the certificate is not a radius attribute. At the moment, to have a complete chain of trust when using EAP-TLS with freeradius, one has to use check_cert_cn so that a known user (user name in EAP) matches in some way the content of its certificate's CN. Otherwise, if you have a valid certificate, you can simply pretend you are someone else by presenting another username and get associated attributes during authorization. Perhaps I am wrong, but this is why I try to have some kind of authorization happening after the authentication.
$ man unlang
ack. thanks again. Now, I stop bothering you and will come back with code or definitive conclusions. a+
Arnaud Ebalard wrote:
- they come with an unknow username in their request but I don't want to kick them at that point (that's what I meant by "authorize *unknown* people").
Are they using EAP? If so, you can either reject them, or perform full authentication. You CANNOT simply "let them in". EAP doesn't work like that.
Their username is unknown but they are not unknown if I have enough information in their certificate to act. The problem is that the certificate is not a radius attribute.
Perhaps you are not clear on how EAP-TLS works. The user has a client certificate. If it is signed by the appropriate issuer, then the user is known. It doesn't matter what their User-Name is.
At the moment, to have a complete chain of trust when using EAP-TLS with freeradius, one has to use check_cert_cn so that a known user (user name in EAP) matches in some way the content of its certificate's CN. Otherwise, if you have a valid certificate, you can simply pretend you are someone else by presenting another username and get associated attributes during authorization.
I think you are not clear on how EAP-TLS works. The RADIUS User-Name is almost irrelevant. All that matters is the certificate that they present. And they can only present the right certificate if they (a) have it, and (b) have the password used to decrypt the private keys. An attacker *can't* just copy the certificate and expect to get authenticated. The EAP-TLS designers know a little bit about what they're doing. If you want to do *additional* checks, on top of certificate validation, you can. But this is not turning "unknown users" into "known users", and it is not "authorizing unknown users".
Perhaps I am wrong, but this is why I try to have some kind of authorization happening after the authentication.
You are trying to do all sorts of additional work because you don't understand how EAP-TLS works, and you think that the designers of EAP-TLS didn't know what they were doing. Alan DeKok.
Hi, Alan DeKok <aland@deployingradius.com> writes:
Their username is unknown but they are not unknown if I have enough information in their certificate to act. The problem is that the certificate is not a radius attribute.
Perhaps you are not clear on how EAP-TLS works. The user has a client certificate. If it is signed by the appropriate issuer, then the user is known. It doesn't matter what their User-Name is.
I do not mean to be rude or arrogant, but I am perfectly clear on how EAP-TLS. I just fail to explain my point. Just consider for 2 seconds that you have alice and bob who both have their own certificate and keys (valid and different) and see how you will handle the following with freeradius (using for instance rlm_files for authorization): Put alice in VLAN 23 and bob in VLAN 24 (by having the associated set of attributes returned to the NAS) after a successful authentication using EAP-TLS, *and* be sure that alice will NOT be able to be put in bob's VLAN. I am very curious to see how/if you would use the Radius User-Name to do that, and how you would provide a strong association between attributes and real identity (i.e. certificate and ability to use associated private key). A simple example is provided below. Don't hesitate to comment if this is the wrong way to do it, if there is a better way, or if you see errors: users file: ----------- .... alice Auth-Type == EAP, EAP-Type == EAP-TLS Reply-Message = "Hello, Alice.", Tunnel-Medium-Type = "IEEE-802", Tunnel-private-group-id = 23, Tunnel-Type = VLAN, Fall-Through = No bob Auth-Type == EAP, EAP-Type == EAP-TLS Reply-Message = "Hello, Bob.", Tunnel-Medium-Type = "IEEE-802", Tunnel-private-group-id = 24, Tunnel-Type = VLAN, Fall-Through = No DEFAULT Auth-Type := Reject Reply-Message = "You're not allowed to enter!", Fall-Through = Yes eap.conf file: -------------- .... eap { default_eap_type = tls tls { .... check_cert_cn = %{User-Name} .... } } .... radiusd.conf file: ------------------ .... authorize { preprocess auth_log eap files } authenticate { eap } .... The trick presented in previous example could be avoided if the authorization and setting of RADIUS attributes could be made based on the content of the certificate (CN, OU, ...).
At the moment, to have a complete chain of trust when using EAP-TLS with freeradius, one has to use check_cert_cn so that a known user (user name in EAP) matches in some way the content of its certificate's CN. Otherwise, if you have a valid certificate, you can simply pretend you are someone else by presenting another username and get associated attributes during authorization.
I think you are not clear on how EAP-TLS works.
I am clear on how it works.
The RADIUS User-Name is almost irrelevant.
Yes, that's the point. So, how can user specific attributes be set in the Access-Accept? RADIUS User-Name is the only *RADIUS* element that gives a clue about the user.
present. And they can only present the right certificate if they (a) have it, and (b) have the password used to decrypt the private keys.
An attacker *can't* just copy the certificate and expect to get authenticated. The EAP-TLS designers know a little bit about what they're doing.
I know that perfectly. Just consider my previous example and show me a simple way to be sure that alice will not be able to be put in bob's VLAN.
If you want to do *additional* checks, on top of certificate validation, you can. But this is not turning "unknown users" into "known users", and it is not "authorizing unknown users".
Either you consider all users with a certificate (and associate key) equal (no attribute specific to that user), or you MUST use check_cert_cn in relation with the RADIUS User-Name.
Perhaps I am wrong, but this is why I try to have some kind of authorization happening after the authentication.
You are trying to do all sorts of additional work because you don't understand how EAP-TLS works, and you think that the designers of EAP-TLS didn't know what they were doing.
Sorry if my replies make you feel that way but this is really not the case, i.e. I am not that arrogant ;-) Cheers, a+
Arnaud Ebalard wrote:
I am very curious to see how/if you would use the Radius User-Name to do that, and how you would provide a strong association between attributes and real identity (i.e. certificate and ability to use associated private key).
Yes, I would use the User-Name for VLAN assignment. I would also use check_cert_cn to be sure that they didn't lie about the User-Name. If they lie, check_cert_cn rejects them. If they don't lie, they get put in the correct VLAN.
alice Auth-Type == EAP, EAP-Type == EAP-TLS Reply-Message = "Hello, Alice.",
You are mixing multiple policies. This is a bad idea. If you want to enforce that only EAP-TLS is being used, then do that. As a separate step, perform VLAN assignment.
DEFAULT Auth-Type := Reject
The server automatically rejects unknown users. You do NOT need this line.
The trick presented in previous example could be avoided if the authorization and setting of RADIUS attributes could be made based on the content of the certificate (CN, OU, ...).
As always, patches are welcome.
The RADIUS User-Name is almost irrelevant.
Yes, that's the point. So, how can user specific attributes be set in the Access-Accept? RADIUS User-Name is the only *RADIUS* element that gives a clue about the user.
The server lets you create policies on non-RADIUS elements, too. That's why it integrates with LDAP and SQL databases. If you need to check more than the CN of the cert, write a patch.
An attacker *can't* just copy the certificate and expect to get authenticated. The EAP-TLS designers know a little bit about what they're doing.
I know that perfectly. Just consider my previous example and show me a simple way to be sure that alice will not be able to be put in bob's VLAN.
You use check_cert_cn? That's why it exists...
Either you consider all users with a certificate (and associate key) equal (no attribute specific to that user),
If they all have the SAME certificate and key, then YES, they are identical. If they have seperate certs && keys, then the CN's are different.
or you MUST use check_cert_cn in relation with the RADIUS User-Name.
Which is why it's there. Honestly, I don't see why you're so shocked about it. You seem to be saying that check_cert_cn is a bad idea, because you have to *use* it to prevent people from lying. Well... the "User-Password" attribute has exactly the same properties. If you don't check it, people might lie, and get authenticated. Oh no! Alan DeKok.
On Sat, Apr 12, 2008 at 05:41:44PM +0200, Alan DeKok wrote:
Yes, I would use the User-Name for VLAN assignment. I would also use check_cert_cn to be sure that they didn't lie about the User-Name.
There should not really be any requirement for User-Name (EAP-Response/Identity) to match with CN in case of EAP-TLS.. The EAP-Response/Identity is mainly for routing and it is sent in clear, so requiring it to match with CN would prevent identity privacy.
Which is why it's there. Honestly, I don't see why you're so shocked about it. You seem to be saying that check_cert_cn is a bad idea, because you have to *use* it to prevent people from lying.
But check_cert_cn is indeed a bad idea in many cases.. RFC 2716bis draft is changing the identity verification to "SHOULD NOT" require identities (EAP-Identity and CN) to be identical.. Identity from EAP-Response/Identity is mainly for routing purposes and things like VLAN selection should really use information from the client certificate (in case of EAP-TLS) instead. If someone is willing to write a submission for this, it would be very useful to be able to use information from various certificate attributes to decide what to do with the request after the EAP-TLS authentication has been completed. This would make it possible to disable check_cert_cn and would even allow use of groups (i.e., not just list of every possible identity string) for VLAN assignment. -- Jouni Malinen PGP id EFC895FA
Jouni Malinen wrote:
There should not really be any requirement for User-Name (EAP-Response/Identity) to match with CN in case of EAP-TLS.. The EAP-Response/Identity is mainly for routing and it is sent in clear, so requiring it to match with CN would prevent identity privacy.
Sure, but it hasn't seemed to be a problem so far.
But check_cert_cn is indeed a bad idea in many cases.. RFC 2716bis draft is changing the identity verification to "SHOULD NOT" require identities (EAP-Identity and CN) to be identical.. Identity from EAP-Response/Identity is mainly for routing purposes and things like VLAN selection should really use information from the client certificate (in case of EAP-TLS) instead.
Ugh. OK.
If someone is willing to write a submission for this, it would be very useful to be able to use information from various certificate attributes to decide what to do with the request after the EAP-TLS authentication has been completed. This would make it possible to disable check_cert_cn and would even allow use of groups (i.e., not just list of every possible identity string) for VLAN assignment.
Yes. The idea is to set up callbacks after the client cert has been received, to allow dynamic expansion of certificate attributes on request. The main issue in doing that is figuring out how to take the SSL context (buried inside of the EAP code), and make it available when the dynamic expansion code is called... Alan DeKok.
Hi, Jouni Malinen <j@w1.fi> writes:
On Sat, Apr 12, 2008 at 05:41:44PM +0200, Alan DeKok wrote:
Yes, I would use the User-Name for VLAN assignment. I would also use check_cert_cn to be sure that they didn't lie about the User-Name.
There should not really be any requirement for User-Name (EAP-Response/Identity) to match with CN in case of EAP-TLS..
+1
The EAP-Response/Identity is mainly for routing and it is sent in clear, so requiring it to match with CN would prevent identity privacy.
I agree with the routing part, i.e. the User-Name allows freeradius to decide which specific authentication method should be used for that user. Regarding the identity privacy argument: usually, the certificate leaks more information (DN, issuer, ...) than the User-Name itself. As it sent in clear during the TLS handshake, there is simple way to provide identity privacy. If someone has access to the EAP-Response/Identity, it also has access to client and server certificates.
Which is why it's there. Honestly, I don't see why you're so shocked about it. You seem to be saying that check_cert_cn is a bad idea, because you have to *use* it to prevent people from lying.
But check_cert_cn is indeed a bad idea in many cases.. RFC 2716bis draft is changing the identity verification to "SHOULD NOT" require identities (EAP-Identity and CN) to be identical.. Identity from EAP-Response/Identity is mainly for routing purposes and things like VLAN selection should really use information from the client certificate (in case of EAP-TLS) instead.
+1
If someone is willing to write a submission for this, it would be very useful to be able to use information from various certificate attributes to decide what to do with the request after the EAP-TLS authentication has been completed. This would make it possible to disable check_cert_cn and would even allow use of groups (i.e., not just list of every possible identity string) for VLAN assignment.
IMHO, the design is not that easy to deal with: - this basically imply doing an additional step of authorization *after* authentication, which is not the way freeradius expects it to be. - TLS session context is freed at the end of authentication. Making associated information available after that point will probably require extracting them during authentication (in cbtls_verify() in in rlm_eap_tls.c for instance) and store them somewhere. The "somewhere" part is still unknown to me -). - elements extracted from the TLS session (including certificates info) are not RADIUS attributes. Should they be seen by the administrator as radius attributes to make their use transparent? It looks like a hack. Alan already pointed possible leads (xlat and unlang) I will follow for some of previous items. a+
Regarding the identity privacy argument: usually, the certificate leaks more information (DN, issuer, ...) than the User-Name itself. As it sent in clear during the TLS handshake, there is simple way to provide ^^^^^^^^^^ pre-coffee bug : should be "no simple way"
Arnaud Ebalard wrote:
Regarding the identity privacy argument: usually, the certificate leaks more information (DN, issuer, ...) than the User-Name itself. As it sent in clear during the TLS handshake, there is simple way to provide identity privacy. If someone has access to the EAP-Response/Identity, it also has access to client and server certificates.
That's what I had thought...
IMHO, the design is not that easy to deal with:
- this basically imply doing an additional step of authorization *after* authentication, which is not the way freeradius expects it to be.
No. The "post-auth" section exists for precisely that purpose.
- TLS session context is freed at the end of authentication. Making associated information available after that point will probably require extracting them during authentication (in cbtls_verify() in in rlm_eap_tls.c for instance) and store them somewhere. The "somewhere" part is still unknown to me -).
Yes. But the SSL context can be removed from the EAP handler, and placed elsewhere. See request_data_add() and request_data_get(). This can make the SSL context available until the current request has finished being processed.
- elements extracted from the TLS session (including certificates info) are not RADIUS attributes. Should they be seen by the administrator as radius attributes to make their use transparent? It looks like a hack.
That's what xlat is for. %{Certificate:foo} can be dynamically expanded to the relevant field of the certificate. These changes are probably only about 300 lines of code. Most of that will be the parsing of the certificate field names, and calling of the correct OpenSSL function. Alan DeKok.
Hi, Alan DeKok <aland@deployingradius.com> writes:
- this basically imply doing an additional step of authorization *after* authentication, which is not the way freeradius expects it to be.
No. The "post-auth" section exists for precisely that purpose.
For attributes, yes. For rcode, no ;-) Thanks for the other pointers and design proposals, Alan. I'll try to spend some time on that in the next few days. Cheers, a+
No. The "post-auth" section exists for precisely that purpose.
Well, ish... it seems it's still undergoing a bit of an existential crisis in 2.*. "Hi I'm the post-auth section, i'm here to assign service authorization attributes after my friend the auth section has determined the validity of the users authentication attempt. But oh no, rlm_sql why are you logging requests here... no no no, you should be *authorizing* requests here and, arg someones already formulated a response; what am I for why am I here, so many questions..." Maybe in 3.* ;-)
Alan DeKok. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
Arran
On Sun, Apr 13, 2008 at 12:11:20PM +0200, Arnaud Ebalard wrote:
Regarding the identity privacy argument: usually, the certificate leaks more information (DN, issuer, ...) than the User-Name itself. As it sent in clear during the TLS handshake, there is simple way to provide identity privacy. If someone has access to the EAP-Response/Identity, it also has access to client and server certificates.
Agreed as far as EAP-TLS as defined in RFC 2716 is concerned. However, RFC 2716bis (i.e., RFC 5216; it was published last month) introduces support for client privacy. This allows the client certificate to be sent encrypted and only after having validated server certificate chain. As long as both the EAP-TLS server and peer implement RFC 5216 and support the optional privacy, there is a way to provide client identity privacy. -- Jouni Malinen PGP id EFC895FA
Hi, Jouni Malinen <j@w1.fi> writes:
On Sun, Apr 13, 2008 at 12:11:20PM +0200, Arnaud Ebalard wrote:
Regarding the identity privacy argument: usually, the certificate leaks more information (DN, issuer, ...) than the User-Name itself. As it sent in clear during the TLS handshake, there is simple way to provide identity privacy. If someone has access to the EAP-Response/Identity, it also has access to client and server certificates.
Agreed as far as EAP-TLS as defined in RFC 2716 is concerned. However, RFC 2716bis (i.e., RFC 5216; it was published last month) introduces support for client privacy. This allows the client certificate to be sent encrypted and only after having validated server certificate chain. As long as both the EAP-TLS server and peer implement RFC 5216 and support the optional privacy, there is a way to provide client identity privacy.
Interesting. Thanks, Jouni. I just took a quick look at section 2.1.4 of RFC 5216. Too bad (both in term of performance and latency) that the only way to support privacy for the client is by performing a first TLS handshake to protect a complete second one which provides the client authentication. This puts a price on privacy :-( Cheers, a+
participants (4)
-
Alan DeKok -
arno@natisbad.org -
Arran Cudbard-Bell -
Jouni Malinen