privacyidea / FreeRADIUS

Add two factor authentication to FreeRADIUS via privacyIDEA
GNU General Public License v2.0
19 stars 17 forks source link

Mangle mapped attributes #9

Closed cornelinux closed 6 years ago

cornelinux commented 6 years ago

The values of mapped attributes should be mangled.

privacyIDEA might return a user attribe (memberOf) like: CN=VPN-Sales,OU=sales,DC=example,DC=com.

We do not need to map the whole value, but maybe only the "Sales" part of the CN. We need to use some regexp magic.

cornelinux commented 6 years ago

The mapping looks like this:

[Mapping]
serial = privacyIDEA-Serial

[Mapping user]
givenname = Class

The value is written in the RADIUS response here: https://github.com/privacyidea/FreeRADIUS/blob/master/privacyidea_radius.pm#L250

We could enhance it like this:

[Mapping user]
givenname = Class
memberOf = FilterId

We could find an enhancement like:

memberOf/CN=VPN-(\w*),OU=sales,DC=example,DC=com/\\1/ = FilterId

Meaning:

Only if the memberOf matches CN=VPN-(\w*),OU=sales,DC=example,DC=com it will be added. And not the complete value will be added but only the matching \\1.

The the RADIUS return attribute will be "FilterId = Sales".

If memberOf was a list, we could also iterate through the list, to see if there is a list entry, that matches. This would also solve issue #8

Problem

The parser of rlm_perl.ini strips after the first occurences of the equal sign.

memberOf/CN=VPN-(\w*),OU=sales,DC=example,DC=com/\1/ = FilterId

will be split into

key: memberOf/CN value: VPN-(\w*),OU=sales,DC=example,DC=com/\1/ = FilterId

cornelinux commented 6 years ago

@fredreichbier please comment on the configuration structure. How should be denote this in the config file.

fredreichbier commented 6 years ago

Hm yeah, I also see that coming up with a configuration format that fits nicely into rlm_perl.ini is pretty hard :/ Another solution could be to keep mangling out of the perl module and do it in unlang instead. Here's a quick-and-dirty solution which does the trick (FreeRADIUS 2.2.8):

rlm_perl.ini:

...
[Mapping user]
memberOf = Class

/etc/freeradius/sites-available/privacyidea:

...
post-auth {
        if ("%{string:reply:Class}" =~ /CN=([^,]+),CN=Users,DC=testfoo,DC=intranet$/i) {
                update reply {
                        Filter-Id := "%{1}"
                }
        }
}

I have a user administrator@dc which has the userinfo attribute memberOf set to CN=Group Policy Creator Owners,CN=Users,DC=testfoo,DC=intranet. Then, with the configuration above:

$ radtest administrator@dc 'test' appliance1.local 1000 test 
Sent Access-Request Id 97 from 0.0.0.0:39189 to 192.168.33.201:1812 length 86
    User-Name = "administrator@dc"
    User-Password = "test"
    NAS-IP-Address = 127.0.0.1
    NAS-Port = 1000
    Message-Authenticator = 0x00
    Cleartext-Password = "test"
Received Access-Accept Id 97 from 192.168.33.201:1812 to 0.0.0.0:0 length 141
    Class = 0x434e3d47726f757020506f6c6963792043726561746f72204f776e6572732c434e3d55736572732c44433d74657374666f6f2c44433d696e7472616e6574
    Reply-Message = "privacyIDEA access granted"
    Filter-Id = "Group Policy Creator Owners"
fredreichbier commented 6 years ago

If we do not want to use unlang and instead integrate the functionality into the perl module, I think using a slightly more verbose approach could improve readability. For example:

[NewAttribute FilterId]
sourceAttribute =  memberOf
regex = CN=VPN-(\w*),OU=sales,DC=example,DC=com
value = \1

or something like that?