FreeRADIUS PAP Challenge Authentication using rlm_perl

Let's see how to configure the FreeRADIUS2.x application to respond with an Access-Challenge for incoming Access-Request messages using the rlm_perl module scripting

System Specifications:

Ubuntu 12.04 LTS (i686 i686 i386 GNU/Linux)
FreeRADIUS v2.1.10


Configuration:

Step 1:

Edit the “clients.conf” file in the /etc/freeradius directory and add the Client's IP details as below

client 192.168.3.33 {
 secret = testing123   < -- Shared secret between Client and Radius server
 shortname = NodeToBeAuth
 netmask = 32
}


Step 2:

Edit the “users” file in the /etc/freeradius directory and add the users to be authenticated as below

user1 Auth-Type := Perl   < -- Use rlm_perl module for Authentication
user2 Cleartext-Password := "abc#123"  < -- Use plain text password for Authentication


Step 3:

Edit the “perl” file in the in the /etc/freeradius/modules directory and specify the script you would like to execute when the Auth Type is set to Perl as above in the users file

perl {
 module = ${confdir}/challenge.pl < -- Perl script on the /etc/freeradius directory
}


Step 4:

Enable the rlm_perl module by editing the “inner-tunnel” and the “default” files in the /etc/freeradius/sites-available directory as follows. Add the perl module under the authenticate section so that the perl module will be included and loaded when FreeRADIUS is started

authenticate {
 Auth-Type Perl {
  perl
 }
.
.
.
.
}


Script for Authentication:

Copy the example code posted on the official FreeRADIUS website and paste into a file named as challenge.pl in the /etc/freeradius directory

http://wiki.freeradius.org/modules/Rlm_perl

Edit the subroutine authenticate() as follows

# Function to handle authenticate
sub authenticate {
    # For debugging purposes only
    if ($RAD_REQUEST{'User-Name'} =~ /^baduser/i) {
            # Reject user and tell him why
             $RAD_REPLY{'Reply-Message'} = "Denied access by rlm_perl function";
             return RLM_MODULE_REJECT;
    } else {        < -- Any user except a bad user
            # Accept/Challenge user and set some attribute
  $RAD_REPLY{'State'} = "some state code here";
              $RAD_REPLY{'Reply-Message'} = "Enter the pin number";
  $RAD_CHECK{'Response-Packet-Type'} = "Access-Challenge"; < -- Send challenge back
  return RLM_MODULE_HANDLED;
    }
}


The above logic can be extended for the case of a user responding to the Access-Challenge by handling the condition of verifying the user response to the challenge found in the RADIUS attributes of the response message

Verification:

Start the RADIUS server in debug mode. Make sure that no freeradius daemon already running in the background before starting the server

# freeradius –X
{or}
#LD_PRELOAD=/usr/lib/libperl.so.5.14 /usr/sbin/freeradius –X  < -- Ubuntu 12.04 bug


Now test plaintext password authentication for user 2 as below

# radtest user2 abc#123 127.0.0.1 0 testing123
Sending Access-Request of id 203 to 127.0.0.1 port 1812
    User-Name = "user2"
    User-Password = "abc#123"
    NAS-IP-Address = 127.0.1.1
    NAS-Port = 0


rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=203, length=20

Now test challenge authentication for user 1 as below
# radtest user1 doesntmatter 127.0.0.1 0 testing123
Sending Access-Request of id 33 to 127.0.0.1 port 1812
    User-Name = "user1"
    User-Password = "doesntmatter"
    NAS-IP-Address = 127.0.1.1
    NAS-Port = 0

rad_recv: Access-Challenge packet from host 127.0.0.1 port 1812, id=33, length=60
    Reply-Message = "Enter pin number"
    State = 0x736f6d6520727461746524636f66652068657265


Please note that we are doing this testing using localhost (127.0.0.1) and the NAS-IP-Address should point to the RADIUS server IP address for remote RADIUS server. Please refer to the wiki page of FreeRADIUS for configuration details of FreeRADIUS 3.x or higher

References:

http://wiki.freeradius.org/modules/Rlm_perl