Modifying User-Name and User-Password attributes in a module
Hi, I've been working on a freeradius module which will operate in pre-proxy and post-proxy mode. I need to modify the user-password (PW_USER_PASSWORD) attribute in pre-proxy and return an RLM_MODULE_UPDATED. My first question is, Do I only need to update the user-password attribute in proxy packet ? or I also have to update user-password vp in packet structure ? I mean vp = pairfind (request->packet->vps, PW_USER_PASSWORD); Also, what are those "username" and "password" value pairs in main request structure ? AFAIK, they're not just pointers to values in packet, proxy, reply and proxy_reply. Do I have to update them too ? And last question, Is it safe to modify the Proxy-State attribute in pre-proxy stage? somewhere in event.c, the comments says that, RFC requires it (Proxy-State) but freeradius doesn't need it, and just fills it with packet->id (which is a random number). Since RFC forbids adding more than one Proxy-State too the packet, and also having in mind that I don't want to introduce a new attribute (bothering dictionary files), Can I use the same Proxy-State (filed by freeradius with packet->id) to store my own data in it ? Thanks,
Hi,
I've been working on a freeradius module which will operate in pre-proxy and post-proxy mode. I need to modify the user-password (PW_USER_PASSWORD) attribute in pre-proxy and return an RLM_MODULE_UPDATED.
Hm, why doesn't updating this stuff with update request { User-Name := whatever User-Password := wh4t3v3r } in the pre-proxy section work? No need for a module then... And if I may ask, why would you need to modify name and password for proxying? If it's just about cutting out realms, there is an excellent realm module to do that for you.
And last question, Is it safe to modify the Proxy-State attribute in pre-proxy stage? somewhere in event.c, the comments says that, RFC requires it (Proxy-State) but freeradius doesn't need it, and just fills it with packet->id (which is a random number). Since RFC forbids adding more than one Proxy-State too the packet, and also having in mind that I don't want to introduce a new attribute (bothering dictionary files), Can I use the same Proxy-State (filed by freeradius with packet->id) to store my own data in it ?
Again, why on earth would you want to do that? If you want to send information in a packet, there's no need to abuse Proxy-State... define your own attribute. Stefan Winter -- Stefan WINTER Stiftung RESTENA - Réseau Téléinformatique de l'Education Nationale et de la Recherche Ingenieur Forschung & Entwicklung 6, rue Richard Coudenhove-Kalergi L-1359 Luxembourg E-Mail: stefan.winter@restena.lu Tel.: +352 424409-1 http://www.restena.lu Fax: +352 422473
Thanks for the answer, Stefan Winter wrote:
Hi,
I've been working on a freeradius module which will operate in pre-proxy and post-proxy mode. I need to modify the user-password (PW_USER_PASSWORD) attribute in pre-proxy and return an RLM_MODULE_UPDATED.
Hm, why doesn't updating this stuff with
update request { User-Name := whatever User-Password := wh4t3v3r }
in the pre-proxy section work? No need for a module then... And if I may ask, why would you need to modify name and password for proxying? If it's just about cutting out realms, there is an excellent realm module to do that for you.
Yes, I can do that for static modifications, but in my case I have to split the password and extract N bytes from it, which is a One-time password for 2 factor authentication. I have to receive AUTH_ACK from main radius server using the original password and then process the second authentication stage with a 2 factor authentication manager using that N bytes long OTP. (Connecting to 2FA server, sending OTP and receiving result) This is why I need to do it in a module. Now, any ideas on which of the user-password vp's I have to change ?
And last question, Is it safe to modify the Proxy-State attribute in pre-proxy stage? somewhere in event.c, the comments says that, RFC requires it (Proxy-State) but freeradius doesn't need it, and just fills it with packet->id (which is a random number). Since RFC forbids adding more than one Proxy-State too the packet, and also having in mind that I don't want to introduce a new attribute (bothering dictionary files), Can I use the same Proxy-State (filed by freeradius with packet->id) to store my own data in it ?
Again, why on earth would you want to do that? If you want to send information in a packet, there's no need to abuse Proxy-State... define your own attribute.
I know this is ugly. So, If I define my own attributes, is it necessary for main RADIUS server (which we proxy to) to have modified dictionary files ? or it will simply ignore those unknown attributes ?
Stefan Winter
------------------------------------------------------------------------
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
update request { User-Name := whatever User-Password := wh4t3v3r }
in the pre-proxy section work? No need for a module then... And if I may ask, why would you need to modify name and password for proxying? If it's just about cutting out realms, there is an excellent realm module to do that for you.
Yes, I can do that for static modifications, but in my case I have to split the password and extract N bytes from it, which is a One-time password for 2 factor authentication. I have to receive AUTH_ACK from main radius server using the original password and then process the second authentication stage with a 2 factor authentication manager using that N bytes long OTP. (Connecting to 2FA server, sending OTP and receiving result) This is why I need to do it in a module.
unlang can do WAY more than just static replacements. Use a regular expression. if ( %{request:User-Password} =~ (.*)(......) ) update request { User-Password := %{2} } ... or something close to that. My syntax may be imperfect, maybe someone can provide a more bullet-proof/correct one. This here is supposed to mean: if the password is at least 6 characters long, change the password so that it only is those last six characters (%{1} would be: only the first part, without the trailing OTP). If it is less than six, this expression does nothing. I guess in your scenario you would want to discard those outright, because they don't contain a valid OTP. Add another rule for this case then. I'm ssuming your "N" to be = 6 because that's a common length for OTPs. Put more/less dots at the end of the regexp if you have a different setup.
Now, any ideas on which of the user-password vp's I have to change ?
I'm trying to prepare you for the tough conclusion that you may not need any code changes here at all. That's why I changed the recipient to -users, not -devel.
I know this is ugly. So, If I define my own attributes, is it necessary for main RADIUS server (which we proxy to) to have modified dictionary files ? or it will simply ignore those unknown attributes ?
It should. See RFC2865 section 5.26 and RFC5080 section 2.5 for details. But, to be honest, the pragmatically best approach is: TRY IT. Define a VSA, send it, and look what happens. Greetings, Stefan Winter -- Stefan WINTER Stiftung RESTENA - Réseau Téléinformatique de l'Education Nationale et de la Recherche Ingenieur Forschung & Entwicklung 6, rue Richard Coudenhove-Kalergi L-1359 Luxembourg E-Mail: stefan.winter@restena.lu Tel.: +352 424409-1 http://www.restena.lu Fax: +352 422473
Stefan Winter wrote:
update request { User-Name := whatever User-Password := wh4t3v3r }
in the pre-proxy section work? No need for a module then... And if I may ask, why would you need to modify name and password for proxying? If it's just about cutting out realms, there is an excellent realm module to do that for you.
Yes, I can do that for static modifications, but in my case I have to split the password and extract N bytes from it, which is a One-time password for 2 factor authentication. I have to receive AUTH_ACK from main radius server using the original password and then process the second authentication stage with a 2 factor authentication manager using that N bytes long OTP. (Connecting to 2FA server, sending OTP and receiving result) This is why I need to do it in a module.
unlang can do WAY more than just static replacements. Use a regular expression.
if ( %{request:User-Password} =~ (.*)(......) ) update request { User-Password := %{2} }
... or something close to that. My syntax may be imperfect, maybe someone can provide a more bullet-proof/correct one.
This here is supposed to mean: if the password is at least 6 characters long, change the password so that it only is those last six characters (%{1} would be: only the first part, without the trailing OTP). If it is less than six, this expression does nothing. I guess in your scenario you would want to discard those outright, because they don't contain a valid OTP. Add another rule for this case then. I'm ssuming your "N" to be = 6 because that's a common length for OTPs. Put more/less dots at the end of the regexp if you have a different setup.
Thanks, You're right, unlang is a powerful tool. I just finished reading it's man page. it has very interesting features. (accessing run-time variables is wonderful). Your assumptions on my scenario is almost true and I do believe that your suggestion (regex in unlang) can completely remove any need for using a module in order to modify a request. However, In this specific scenario, I need much more further processing which should be done before I can decide to send a REJECT or ACCEPT. For example, I have to send extracted OTP to a remote authentication manager which it's answer would determine final authentication result. In more detail it should be something like: open a socket, create a specific request packet, send it, wait for answer, parse the answer packet, and do further processing based on received answer from 2FA server. Also, if we consider multi threading operation, there might be more issues that need to be taken care of. Nevertheless, I believe even using a powerful tool like unlang cannot eliminate the need for an extra module. However, having a significant part of the whole job done by unlang this might only need a small python or perl module.
Now, any ideas on which of the user-password vp's I have to change ?
I'm trying to prepare you for the tough conclusion that you may not need any code changes here at all. That's why I changed the recipient to -users, not -devel.
Well, even if I just need to use a "update" in configuration files to do the job, I need to do it in right the place, I mean request, reply, proxy or proxy_reply. candidates for this one (password modification) are "request" and "proxy". I wonder if doing it in "proxy" can confuse freeradius for doing further process on it.
I know this is ugly. So, If I define my own attributes, is it necessary for main RADIUS server (which we proxy to) to have modified dictionary files ? or it will simply ignore those unknown attributes ?
It should. See RFC2865 section 5.26 and RFC5080 section 2.5 for details. But, to be honest, the pragmatically best approach is: TRY IT. Define a VSA, send it, and look what happens.
Thanks for references, according to these RFC's servers MUST ignore unknown VSA. However, I think you're completely right, I need to arrange a test case and see what would happen. Again. Thanks for your great and helpful suggestions.
Greetings,
Stefan Winter
------------------------------------------------------------------------
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
Hi!
Thanks, You're right, unlang is a powerful tool. I just finished reading it's man page. it has very interesting features. (accessing run-time
The suggested way of working with this software is 1. read the man page and other documentation 2. ask the mailing list 3. modify source code Your complete inversion of this order didn't seem to work well.
variables is wonderful). Your assumptions on my scenario is almost true and I do believe that your suggestion (regex in unlang) can completely remove any need for using a module in order to modify a request. However, In this specific scenario, I need much more further processing which should be done before I can decide to send a REJECT or ACCEPT. For example, I have to send extracted OTP to a remote authentication manager which it's answer would determine final authentication result. In more detail it should be something like: open a socket, create a specific request packet, send it, wait for answer, parse the answer packet, and do further processing based on received answer from 2FA server. Also, if we consider multi threading operation, there might be more issues that need to be taken care of. Nevertheless, I believe even using a powerful tool like unlang cannot eliminate the need for an extra module. However, having a significant part of the whole job done by unlang this might only need a small python or perl module.
Yes. rlm_perl can be used to safely embed perl into pakcet processing, and it should even be thread-safe, if perl is compiled accordingly. In your scenario, I guess you would want to use the mangling we talked about to send the request to the remote RADIUS proxy, and then when its answer comes back do your out-of-band perl post-processing. The place for this is in the post-auth { } section. Yes, in post-auth you can turn a Access-Accept from a remote reply into a reject. Make your rlm_perl module return failure as return code and you're done.
Well, even if I just need to use a "update" in configuration files to do the job, I need to do it in right the place, I mean request, reply, proxy or proxy_reply. candidates for this one (password modification) are "request" and "proxy". I wonder if doing it in "proxy" can confuse freeradius for doing further process on it.
I'm not sure. All I can say is that I do all my mangling during authorize { }, and it works. pre-proxy might as well, you just have to try it.
Again. Thanks for your great and helpful suggestions.
Sometimes I'm tempted to kick my butt because I give free consultancy. I accept Ferraris as gratuity gifts, you know? ;-) Stefan -- Stefan WINTER Stiftung RESTENA - Réseau Téléinformatique de l'Education Nationale et de la Recherche Ingenieur Forschung & Entwicklung 6, rue Richard Coudenhove-Kalergi L-1359 Luxembourg E-Mail: stefan.winter@restena.lu Tel.: +352 424409-1 http://www.restena.lu Fax: +352 422473
Yes, I can do that for static modifications, but in my case I have to split the password and extract N bytes from it, which is a One-time password for 2 factor authentication. I have to receive AUTH_ACK from main radius server using the original password and then process the second authentication stage with a 2 factor authentication manager using that N bytes long OTP. (Connecting to 2FA server, sending OTP and receiving result) This is why I need to do it in a module. Now, any ideas on which of the user-password vp's I have to change ? I know reusing Proxy-State is ugly. So, If I define my own attributes, is it necessary for main RADIUS server (which we proxy to) to have modified dictionary files ? or it will simply ignore those unknown attributes ? Thanks, Stefan Winter wrote:
Hi,
I've been working on a freeradius module which will operate in pre-proxy and post-proxy mode. I need to modify the user-password (PW_USER_PASSWORD) attribute in pre-proxy and return an RLM_MODULE_UPDATED.
Hm, why doesn't updating this stuff with
update request { User-Name := whatever User-Password := wh4t3v3r }
in the pre-proxy section work? No need for a module then... And if I may ask, why would you need to modify name and password for proxying? If it's just about cutting out realms, there is an excellent realm module to do that for you.
And last question, Is it safe to modify the Proxy-State attribute in pre-proxy stage? somewhere in event.c, the comments says that, RFC requires it (Proxy-State) but freeradius doesn't need it, and just fills it with packet->id (which is a random number). Since RFC forbids adding more than one Proxy-State too the packet, and also having in mind that I don't want to introduce a new attribute (bothering dictionary files), Can I use the same Proxy-State (filed by freeradius with packet->id) to store my own data in it ?
Again, why on earth would you want to do that? If you want to send information in a packet, there's no need to abuse Proxy-State... define your own attribute.
Stefan Winter
------------------------------------------------------------------------
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html
participants (2)
-
Arash Yadegarnia -
Stefan Winter