########################################################################### # # BEHAVIOUR - Expression that defines the server's operating rules # # This is compiled at startup and ran for every request that comes in. # Upon entry, the REQUEST list of A/V pairs is already populated with # information from and about the request. Upon exit, the REPLY list is # used to build a response to send to the client. # # Other than the attributes / fixed fields you want to send, you need # to set the first instance of the attribute 'Secret' (see subdicts/dict. # internal) to the shared secret to be used for signing the response. # You also need to set the first instance of the RAD-Authenticator # attribute to the value that this attribute had in the original request; # i.e. copying the attribute from the REQUEST list to the REPLY list. # The same goes for the RAD-Identifier attribute and all instances of # the Proxy-State attribute. See RFC 2865 why. # # Then, when the expression completes (that is without being aborted), # the server will first build the packet only based on the attributes # on the REPLY list, so at first also putting in the original request # authenticator as the response authenticator. It will then sign the # packet using the shared secret provided on the reply list, putting the # signature over the original response authenticator, to create a valid # RADIUS response. # # See openradius-language.html for a list neatly showing all operators, # with contexts, precedence, association and auto-conversion properties. # # The 'and' and 'or' operators do short-circuit boolean evaluation as they do # in C, Perl and shell scripts - that's how conditional subexpressions # are implemented. # # This language has hardly any syntax, other than that a term may be # not be directly followed by another term. # ## # # This is an example expression file that goes together with the distributed # file 'configuration.sample-ldap-authbind'. It allows RADIUS clients to be # listed in LDAP as well as the users. See modules/radldap/radldap.attrmap, # modules/radldap/radldap.schema and modules/radldap/radldap-ldif.sample # for more information. # # The difference between this set (sample-ldap-authbind) and sample-ldap is # that we take advantage of LDAP's hashing mechanisms here by authenticating # using a bind. The drawback is the overhead and the fact that you can only # do PAP. ########################################################################### # # Step 1 & 2: Look up client's secret by packet's source IP address; log # error and drop request if not found Ldap(str = "dc=e-advies,dc=nl", str = "(&(objectclass=openradiusClient)(cn=" . IP-Source . "))"), delall str, delall REP:int, delall REP:str, # del args & most ret values REP:Secret or ( Errorlogger(str = Timestamp as "%c" . ": Request from unknown client " . IP-Source . " identified as NAS " . (NAS-Identifier or NAS-IP-Address) . " for user " . User-Name . " - ignored."), abort ), ########################################################################### # # Step 3: Initialise reply list RAD-Code = Access-Reject, RAD-Identifier = RAD-Identifier, RAD-Authenticator = "" . RAD-Authenticator, # we need a copy moveall Proxy-State, ########################################################################### # # Step 4: Handle accounting RAD-Code == Accounting-Request and ( # Handle accounting. First verify request authenticator. Note that # REP:RAD-Authenticator contains a saved copy of REQ:RAD-Authenticator REQ:Acct-Authenticator = Mismatch, REQ:RAD-Authenticator pokedwith "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", REP:RAD-Authenticator == md5 (RAD-Packet . REP:Secret) and REQ:Acct-Authenticator := Verified, # Always log it; drop request if that fails Acctlogger(str = Timestamp as "%c", REQ:Record-Unique-Key = hex (NAS-IP-Address toraw . Timestamp toraw) . Acct-Session-Id), int or abort, del str, del REP:int, # Set response code and halt the expression RAD-Code = Accounting-Response, acctresp ), ########################################################################### # # Step 5: Now we know we're authenticating, set defaults to reject when halted, # so we can do so at anytime RAD-Code = Access-Reject, Reply-Message = "I don't know you. Go away.\n", ########################################################################### # # Step 6: Decrypt PAP password; reject if none present. User-Password or reject, REQ:User-Password := (User-Password papdecrypt (REP:Secret . RAD-Authenticator) . "\x00") beforefirst "\x00", ########################################################################### # # Step 7: Log the request using the Stdlogger interface #Stdlogger(str=Timestamp as "%c"), #del str, del REP:int, ########################################################################### # # Step 9: Authenticate user against LDAP and get attributes. Reject if bind # failure or the search doesn't return any objects. # # RadLDAP Expects base DN for search in first 'str', filter in second 'str'; # returns attributes from to LDAP node, translated using radldap's map file. # If it receives a User-Name and User-Password attribute, it will do a bind # using User-Name as the bind DN, so we rewrite it here. delall REQ:str, delall REP:int, REQ:User-Name := "cn=" . User-Name . ",ou=radiusUsers,dc=e-advies,dc=nl", Ldapusers(str = User-Name, str = "(objectclass=openradiusUser)"), int or reject, delall str, delall REP:int, # Convert temporary string attributes from LDAP to real ones, if any. # You can safely uncomment all of this if you're using the 'radradiusXxxYyy' # attributes in LDAP. str-Service-Type and (Service-Type = str-Service-Type), str-Framed-Protocol and (Framed-Protocol = str-Framed-Protocol), str-Framed-IP-Address and (Framed-IP-Address = str-Framed-IP-Address), str-Framed-IP-Netmask and (Framed-IP-Netmask = str-Framed-IP-Netmask), str-Login-IP-Host and (Login-IP-Host = str-Login-IP-Host), str-Login-Service and (Login-Service = str-Login-Service), str-Login-TCP-Port and (Login-TCP-Port = str-Login-TCP-Port), str-Session-Timeout and (Session-Timeout = str-Session-Timeout), str-Idle-Timeout and (Idle-Timeout = str-Idle-Timeout), str-Port-Limit and (Port-Limit = str-Port-Limit), ########################################################################### # # Halt, accepting the user Reply-Message := "Welcome, PAP/Login user authenticated by an LDAP bind!\n", accept