[solved] FreeRADIUS 3.x package LDAP/OTP problem
-
Hi folks,
I just updated to the new pfsense 2.4 and my freeradius suddenly stopped working. I couldn't even start it, telling me "ssl version mismatch".
After a bit of fiddling, I figured I'd try freeradius 3 instead.It installed successfully and it also started up just fine. However our setup from before did not work at all.
We seem to have a pretty "uncommon" setup here. We're using OpenLDAP + Gauth. As this was not working with freerad2 out of the box we used a pam plugin to do ldap + gauth. Somewhat similar to this old post:
http://www.supertechguy.com/help/security/freeradius-google-authSo I "googled around" noticing that gauth made it into the auth options of pfsense, this is just great. However, I can't figure out how to use it with LDAP auth. Seems I can not use both at the same time. Is this possible at all?
I just tried setting up the LDAP Login, which is easy and works just fine. But then I do not have a list of users, so I can't define the gauth secrets for them.
I used to have one folder where all of the secrets were listed for each user and the folder was chosen based on the user login name.
I could try to adjust the python script, but I'd really love to have this function purely from the GUI so I won't have to modify stuff each update (which I always had to using freerad2)Any ideas from you guys?
-
Is anyone using LDAP + OTP and could give me a hint? :-\
EDIT: Never mind :-) I wrote my own python script and replaced the gauth one.
If anyone has the same problem let me know and I'm happy to share it -
Can you share your python script with me?
-
@avs262 Sorry I did not get any notification from the forum, so I've only seen it now.
Of course I can. This is what I came up with.
I added the following packages:
pkg add http://pkg.freebsd.org/freebsd:11:x86:64/latest/All/py27-setuptools-36.5.0.txz pkg add http://pkg.freebsd.org/freebsd:11:x86:64/latest/All/py27-pyasn1-0.3.7.txz pkg add http://pkg.freebsd.org/freebsd:11:x86:64/latest/All/py27-pyasn1-modules-0.1.5.txz pkg add http://pkg.freebsd.org/freebsd:11:x86:64/latest/All/py27-ldap-2.4.45.txz
Then I changed the googleauth plugin of FreeRADIUS to use my custom script:
exec googleauth { wait = yes #program = "/usr/local/etc/raddb/scripts/googleauth.py %{request:User-Name} %{reply:MOTP-Init-Secret} %{reply:MOTP-PIN} %{request:User-Password}" program = "/usr/local/etc/raddb/scripts/googleauth-ldap.py %{request:User-Name} %{reply:MOTP-Init-Secret} %{request:User-Password}" }
Finally the script itself, located in /usr/local/etc/raddb/scripts/googleauth-ldap.py
#!/usr/local/bin/python2.7 # Copyright of the original script: www.brool.com (http://www.brool.com/post/using-google-authenticator-for-your-website/) # License: CC0 1.0 Universal License import sys import time import struct import hmac import hashlib import base64 import syslog import ldap def check_credentials(username, password, ldap_server="ldap://ldapserverurl:389"): ldap_server_failover = "ldap://urloffailoverldapserver:389" base_dn = 'dc=whatever' user_dn = "uid="+username+",ou=People,"+base_dn ldap_filter = 'uid=%s' % username try: ldap_client = ldap.initialize(ldap_server) ldap_client.start_tls_s() ldap_client.set_option(ldap.OPT_REFERRALS,0) ldap_client.set_option(ldap.OPT_X_TLS,1) ldap_client.set_option(ldap.OPT_X_TLS_CACERTDIR, "/usr/local/etc/raddb/certs/ca_ldap1_cert.pem") ldap_client.set_option(ldap.OPT_X_TLS_CACERTFILE, "/usr/local/etc/raddb/certs/") ldap_client.simple_bind_s(user_dn, password) except ldap.INVALID_CREDENTIALS: ldap_client.unbind() syslog.syslog(syslog.LOG_ERR, 'Wrong username or password') return False except ldap.SERVER_DOWN: if ldap_server != ldap_server_failover: syslog.syslog(syslog.LOG_ERR, 'Main LDAP server not available - Trying Failover') return check_credentials(username, password, ldap_server_failover) else: syslog.syslog(syslog.LOG_ERR, 'Both LDAP servers not available') return False except Exception, error: syslog.syslog(syslog.LOG_ERR, error) return False ldap_client.unbind() syslog.syslog(syslog.LOG_NOTICE, "freeRADIUS: LDAP Authenticator - Password validation successful for user: " + username) return True def authenticate(username, secretkey, code_attempt): #split 6 digitas from the end -> code password = code_attempt[:len(code_attempt)-6] if check_credentials(username, password) == False: syslog.syslog(syslog.LOG_ERR, "freeRADIUS: Google Authenticator - Authentication failed. User: " + username + ", Reason: Wrong Password") return False code_attempt = code_attempt[len(code_attempt)-6:] tm = int(time.time() / 30) secretkey = base64.b32decode(secretkey) # try 30 seconds behind and ahead as well for ix in [-1, 0, 1]: # convert timestamp to raw bytes b = struct.pack(">q", tm + ix) # generate HMAC-SHA1 from timestamp based on secret key hm = hmac.HMAC(secretkey, b, hashlib.sha1).digest() # extract 4 bytes from digest based on LSB offset = ord(hm[-1]) & 0x0F truncatedHash = hm[offset:offset+4] # get the code from it code = struct.unpack(">L", truncatedHash)[0] code &= 0x7FFFFFFF; code %= 1000000; if ("%06d" % code) == str(code_attempt): syslog.syslog(syslog.LOG_NOTICE, "freeRADIUS: Google Authenticator - Authentication successful for user: " + username) return True syslog.syslog(syslog.LOG_ERR, "freeRADIUS: Google Authenticator - Authentication failed. User: " + username + ", Reason: wrong tokencode") return False # Check the length of the parameters if len(sys.argv) != 4: syslog.syslog(syslog.LOG_ERR, "freeRADIUS: Google Authenticator - wrong syntax - USAGE: googleauth.py Username, Secret-Key, Auth-Attempt") exit(1) auth = authenticate(sys.argv[1], sys.argv[2], sys.argv[3]) if auth == True: exit(0) exit(1)
Of course you need to adapt the URL(s) of the ldap server and the dns to fit your environment.
It works pretty well in our setup, but as always suggestions or improvements are welcome :)Reminder: After upgrading pfsense both files will get overwritten! So be sure you create a backup before and restore it after upgrading ;-)
-
@waterstorm Thanks for your documentation!
It helped me a lot with the setup, and with minor adjustments it also works with pfSense 2.7.2.But is this still the way to go or is there now a more elegant solution?
-
@lawern Good to hear :) I think I also updated it once or twice to be compatible, but we used it until we replaced the gateway. Until then I think there was no easy alternative to this.