Multivalued (LDAP) Attributes and string matching, or regexes
Greetings, I have to control authorization based on a (possibly) multi-valued LDAP reply attribute called employeeType. I have all of the LDAP code working fine, but seem to have hit a snag. Each user has 1 to ??? (usually a max of 5 or so) employeeType values. The pertinent ones include "STAFF", "STAFF TEMPORARY", "STAFF OFFSITE", and "STAFF RETIRED". I need to allow all "STAFF" types access, unless their one and only "STAFF*" is "STAFF RETIRED" (yes, don't get me started, but it's considered "perfectly valid" for someone to have employeeTypes of staff, staff retired, and staff offsite). So essentially, I need to allow in anyone with "STAFF", not followed by " RETIRED". At the moment, I'm using %{reply:employeeType[*]} which works fine for reged matching all of the other funky attributes that should grant access. But I can't seem to figure out how to say, either with unlang comparisons or regexes (I'm on CentOS/RedHat, so I assume it would be POSIX, either BRE or ERE) or both, how to exclude that one condition. Examples: STAFF, STAFF RETIRED, SALARIED -> Accept STAFF -> Accept STAFF RETIRED -> Reject STAFF, STAFF TEMPORARY -> Accept FOO, STAFF RETIRED, BAR -> Reject FOO, STAFF, BAR -> Accept Any hints or guidance would be greatly appreciated. I've searched through all of the regex material I could find, and asked on #regex IRC and as many regex gurus as I could find, and the best answer I got was to combine regexes with some sort of unlang construct... but I can't seem to think of anything which will match my logical need... "the string STAFF not followed immediately by the string RETIRED". Thanks, Jason Antman PS - I know the Right answer here is "fix your LDAP schema". Unfortunately, I don't have any control over that. Or even the power to make suggestions. All I have is a directive of who gets in and who doesn't.
I find the easist way to do it is to use a custom "users" file to allow / prevent access based on exact matches of LDAP attributes. then you can say if STAFF = Accept, if STAFF OFFSITE Accept, otherwise reject. This is how we do it here: http://lists.freeradius.org/pipermail/freeradius-users/2010-September/msg003... On Thu, Jun 16, 2011 at 9:23 AM, Jason Antman <jantman@oit.rutgers.edu>wrote:
Greetings,
I have to control authorization based on a (possibly) multi-valued LDAP reply attribute called employeeType. I have all of the LDAP code working fine, but seem to have hit a snag. Each user has 1 to ??? (usually a max of 5 or so) employeeType values. The pertinent ones include "STAFF", "STAFF TEMPORARY", "STAFF OFFSITE", and "STAFF RETIRED". I need to allow all "STAFF" types access, unless their one and only "STAFF*" is "STAFF RETIRED" (yes, don't get me started, but it's considered "perfectly valid" for someone to have employeeTypes of staff, staff retired, and staff offsite).
So essentially, I need to allow in anyone with "STAFF", not followed by " RETIRED". At the moment, I'm using %{reply:employeeType[*]} which works fine for reged matching all of the other funky attributes that should grant access. But I can't seem to figure out how to say, either with unlang comparisons or regexes (I'm on CentOS/RedHat, so I assume it would be POSIX, either BRE or ERE) or both, how to exclude that one condition.
Examples: STAFF, STAFF RETIRED, SALARIED -> Accept STAFF -> Accept STAFF RETIRED -> Reject STAFF, STAFF TEMPORARY -> Accept FOO, STAFF RETIRED, BAR -> Reject FOO, STAFF, BAR -> Accept
Any hints or guidance would be greatly appreciated. I've searched through all of the regex material I could find, and asked on #regex IRC and as many regex gurus as I could find, and the best answer I got was to combine regexes with some sort of unlang construct... but I can't seem to think of anything which will match my logical need... "the string STAFF not followed immediately by the string RETIRED".
Thanks, Jason Antman
PS - I know the Right answer here is "fix your LDAP schema". Unfortunately, I don't have any control over that. Or even the power to make suggestions. All I have is a directive of who gets in and who doesn't. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
Peter Lambrechtsen <plambrechtsen@gmail.com> wrote:
I find the easist way to do it is to use a custom "users" file to allow / prevent access based on exact matches of LDAP attributes.
then you can say if STAFF = Accept, if STAFF OFFSITE Accept, otherwise reject.
This is how we do it here:
http://lists.freeradius.org/pipermail/freeradius-users/2010-September/msg003...
Depending on how you have things set up locally and how you are trying to skin this particular cat, but you could just use an LDAP filter to get all this done and keep the logic out of FreeRADIUS (although I probably would *not* recommend it): ---- filter = "(&(objectClass=Person)(employeeType=staff*)(!(employeeType=staff retired))(|(!(loginDisabled=*))(loginDisabled=FALSE))(cn=%{Stripped-User-Name}))" ---- Means you get the effect as if the user did not even exist. Just throwing another option out there...although I would recommend the users file with a bunch of fall throughs personally. Cheers -- Alexander Clouter .sigmonster says: All phone calls are obscene. -- Karen Elizabeth Gordon
Alexander Clouter wrote:
Peter Lambrechtsen <plambrechtsen@gmail.com> wrote:
I find the easist way to do it is to use a custom "users" file to allow / prevent access based on exact matches of LDAP attributes.
then you can say if STAFF = Accept, if STAFF OFFSITE Accept, otherwise reject.
This is how we do it here:
http://lists.freeradius.org/pipermail/freeradius-users/2010-September/msg003...
Peter... but how does that work with multivalued attributes? If someone has employeeType[0] = "FooBar" and employeeType[1] = "STAFF OFFSITE" it doesn't seem like it would work...
Also, at the moment, I don't have a users file... I'm using LDAP only, with the little configuration I need in unlang.
Depending on how you have things set up locally and how you are trying to skin this particular cat, but you could just use an LDAP filter to get all this done and keep the logic out of FreeRADIUS (although I probably would *not* recommend it): ---- filter = "(&(objectClass=Person)(employeeType=staff*)(!(employeeType=staff retired))(|(!(loginDisabled=*))(loginDisabled=FALSE))(cn=%{Stripped-User-Name}))" ----
Means you get the effect as if the user did not even exist.
Just throwing another option out there...although I would recommend the users file with a bunch of fall throughs personally.
Cheers
I know I didn't specify it in my original message, but that loses the verbose (SQL-ized) logging that I need... I don't really know anything about it, and haven't seen mention of it outside of the modules list, but perhaps I could use rlm_perl or rlm_python? Does anyone know about the efficiency of these? I know I'm approaching this from the standpoint of a traditional programming language, but the way I see it, I just need to loop over the values of the employeeType[] attribute, and have some sort of variable to store state... -Jason
Jason Antman <jantman@oit.rutgers.edu> wrote:
I don't really know anything about it, and haven't seen mention of it outside of the modules list, but perhaps I could use rlm_perl or rlm_python? Does anyone know about the efficiency of these? I know I'm approaching this from the standpoint of a traditional programming language, but the way I see it, I just need to loop over the values of the employeeType[] attribute, and have some sort of variable to store state...
I thought I remembered this popping up recently, I would have mentioned it earlier but my Google-Fu at the time was weak and I though I was imagining things. If you checkout v2.1.x[1] and then type: ---- $ git checkout -b foreach $ git cherry-pick a3221304 $ git cherry-pick 11aa4442 $ git cherry-pick ba18f024 $ git cherry-pick de60e732 $ <mumble, compile, mumble, install, mumble> ---- It will either: * give you foreach[2] ('man 5 unlang') * make your pants explode[3] Cheers [1] http://git.freeradius.org/ [2] http://freeradius.1045715.n5.nabble.com/regex-matching-can-be-convinced-to-b... [3] http://www.youtube.com/watch?v=Ysw4Xv6JI_w (0:00 -> 0:30 seconds) -- Alexander Clouter .sigmonster says: BOFH excuse #138: BNC (brain not connected)
Alexander Clouter wrote:
I thought I remembered this popping up recently, I would have mentioned it earlier but my Google-Fu at the time was weak and I though I was imagining things.
If you checkout v2.1.x[1] and then type: ---- $ git checkout -b foreach $ git cherry-pick a3221304 $ git cherry-pick 11aa4442 $ git cherry-pick ba18f024 $ git cherry-pick de60e732 $ <mumble, compile, mumble, install, mumble> ----
It will either: * give you foreach[2] ('man 5 unlang') * make your pants explode[3]
Cheers
[1] http://git.freeradius.org/ [2] http://freeradius.1045715.n5.nabble.com/regex-matching-can-be-convinced-to-b... [3] http://www.youtube.com/watch?v=Ysw4Xv6JI_w (0:00 -> 0:30 seconds)
Thanks for the heads-up. I know this won't be of much help to anyone else as a generic solution, but in a rlm_perl-induced fit of rage (I have about as much experience with and fondness for perl as ... someone who has nothing of something) I decided to step back and whiteboard the problem. I ended up managing to get a hold of the department that runs LDAP, got a list of all of the possible attribute values, and just did a update reply { employeeType -= badValueHere } to get rid of the values I don't want, before doing case-insensitive regex string comparisons on reply:employeeType[*]. With a default of reject (oversimplified) this works fine. But thanks to everyone for the advice... hopefully it will be useful for the next person with these questions. -Jason Antman PS - Unfortunately my overcomplicated unlang authenticate{} section is because I'm required to log to SQL in realtime (i.e. not parsing text log files) the result of each authentication attempt, and *why* - i.e. what specific rule was used to deny someone access, or what rule triggered successful authentication. FreeRadius doesn't seem to have any support for this, other than lots of updates{} to custom local attributes.
participants (3)
-
Alexander Clouter -
Jason Antman -
Peter Lambrechtsen