LDAP Extended Query with multiple parameters in 2.1
-
Hey, so I just managed to get something working that had been really frustrating for a while, so I thought I'd post here just in case someone else was hitting their head against the same wall!
We're using OpenVPN to let people into our network, and we also want to use our OpenLDAP server to authenticate users. But we don't want to just let everyone in our LDAP directory in, only people who should have VPN priveleges, and also we want to make sure their account is still active.
So all of the regular guides out there about how to setup an LDAP server are pretty much spot-on. For the record, you need to set Base DN: and Authentication containers. In my example, this would be:
Base DN: dc=fishpuzzle,dc=com
Authentication containers: ou=People
User naming attribute: uidThe problem is that this won't have a way to restrict the which users who can authenticate. We have two extra fields in our LDAP database which we use; userStatus and userService. We want users to have BOTH userStatus=active AND userService=vpn in order for us to want you get in our vpn. userStatus is used to immediately deny services to someone when we don't want to completely delete them from our LDAP directory; we can just toggle userStatus=disabled and leave everything else still present. And userService=vpn is granted only to the people who should have vpn access; we don't give it to people who are just in our directory for having a phone number and email address for example. So here's an example of a user named snoopy who we want to have access:
dn: uid=snoopy,ou=People,dc=fishpuzzle,dc=com uid: snoopy cn: Snoopy Dog userStatus=active userService=vpn
In normal LDAP queries, the way to make sure that both fields are present is to use a query string like this:
(&(uid=snoopy)(userStatus=active)(userService=vpn))
The big mystery to me was, how do we get this query restriction into our pfSense config?
Well, reading through the authentication code (/etc/inc/auth.inc) had the answer. Partway through the code, I see where the External Query contents get put in the query:
$ldapfilter = "(&({$ldapnameattribute}={$username})({$ldapextendedquery}))";
The uid part is already there for you as part of the standard ldap and openvpn gui which fills out the $ldapnameattribute and $username. The trick is getting the right value for $ldapextendedquery which happens to already be enclosed in parenthesis.
Now this turns out to be very easy if you only have one query parameter you want, like userService=vpn.
If that's the case, all you need to put in Extended Query is```
userService=vpnBut what if you need two attributes? What you need to put inside the extended query field on the ldap page is:
userStatus=active)(userService=vpn
Yes, you're reading that right - it is *missing* the leading left parenthesis and the right parenthesis symbols! As you can guess, you can string any number of these together to make a bunch of required parameters to be present for a specific LDAP record to make sure it only authenticates to a subset of users by doing it this way. You just have to make sure to realize that whatever the expression is, it's going to be surrounded by a single set of parenthesis! Hopefully this helps someone! - jalano