Synology usage series 33 – Install MOTP and integrate with FreeRadius


MOTP stands for mobile one time password which provides one time password services.

Download and install otp server

  1. Login to DS as root
  2. mkdir -p /opt/usr/local/bin
  3. cd /opt/usr/local/bin
  4. Download otp server script

    # wget http://motp.sourceforge.net/bash/otpverify.sh

  5. Install necessary library

    # ipkg install findutils
    # ipkg install md5deep
    # ipkg install bash

  6. Edit otpverify.sh

    # vi /opt/usr/local/bin/otpverify.sh

    Changes highlighted in red.

    
    #!/opt/bin/bash
    #
    # Mobile One Time Passwords (Mobile-OTP) for Java 2 Micro Edition, J2ME
    # written by Matthias Straub, Heilbronn, Germany, 2003
    # (c) 2003 by Matthias Straub
    #
    # Version 1.05a
    #
    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU Library General Public
    # License as published by the Free Software Foundation; either
    # version 2 of the License, or (at your option) any later version.
    # 
    # This software is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    # Library General Public License for more details.
    #
    # arguments:  $1 $2 $3 $4 $5
    # $1 - username
    # $2 - one-time-password that is to be checked 
    # $3 - init-secred from token (to init token: #**#)
    # $4 - user PIN
    # $5 - time difference between token and server in 10s of seconds (360 = 1 hour)
    #
    # one-time-password must match md5(EPOCHTIME+SECRET+PIN)
    # 
    
    #
    # otpverify.sh version 1.04b, Feb. 2003
    # otpverify.sh version 1.04c, Nov. 2008
    #  changed line 1 to ksh because of problems with todays bash an sh
    # otpverify.sh version 1.05a, Jan. 2011
    #  changed back to bash and added in shopts line to ensure aliases handled
    #  correctly (bash is always available on any modern *nix unlike ksh)
    #
    
    PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/usr/local/bin:/opt/bin:/opt/sbin
    
    # ensure aliases are expanded by bash
    shopt -s expand_aliases
    
    if [ -e "`which md5 2>/dev/null`" ]
    then
    	alias checksum=md5
    	have_md5="true"
    fi
    if [ -e "`which md5sum 2>/dev/null`" ]
    then
    	alias checksum=md5sum
    	have_md5="true"
    fi
    
    
    alias checksum=md5deep
    have_md5="true"
    
    
    if [ $have_md5 != "true" ]
    then
    	echo "No md5 or md5sum available on server!"
    	exit 16
    fi
    
    function chop
    {
    	num=`echo -n "$1" | wc -c | sed 's/ //g' `
    	nummin1=`expr $num "-" 1`
    	echo -n "$1" | cut -b 1-$nummin1 
    }
    
    if [ ! $# -eq 5 ] ; then
    echo "USAGE: otpverify.sh Username, OTP, Init-Secret, PIN, Offset"
    exit 14
    fi
    
    mkdir /opt/var/motp 2>/dev/null
    mkdir /opt/var/motp/cache 2>/dev/null
    mkdir /opt/var/motp/users 2>/dev/null
    chmod og-rxw /opt/var/motp 2>/dev/null || { echo "FAIL! Need write-access to /opt/var/motp"; exit 17; }
    chmod og-rxw /opt/var/motp/cache
    chmod og-rxw /opt/var/motp/users
    
    USERNAME=`echo -n "$1" | sed 's/[^0-9a-zA-Z._-]/X/g' `
    PASSWD=`echo -n "$2" | sed 's/[^0-9a-f]/0/g' `
    SECRET=`echo -n "$3" | sed 's/[^0-9a-f]/0/g' `
    PIN=`echo -n "$4" | sed 's/[^0-9]/0/g' `
    OFFSET=`echo -n "$5" | sed 's/[^0-9]/0/g' `
    EPOCHTIME=`date +%s` ; EPOCHTIME=`chop $EPOCHTIME`
    
    # delete old logins
    /opt/bin/find /opt/var/motp/cache -type f -cmin +5 | xargs rm 2>/dev/null
    
    if [ -e "/opt/var/motp/cache/$PASSWD" ]; then
    	echo "FAIL"
    	exit 15
    fi
    
    # account locked?
    if [ "`cat /opt/var/motp/users/$USERNAME 2>/dev/null`" == "8" ]; then
    	echo "FAIL"
    	exit 13
    fi
    
    I=0
    EPOCHTIME=`expr $EPOCHTIME - 18`
    EPOCHTIME=`expr $EPOCHTIME + $OFFSET`
    while [ $I -lt 36 ] ; do # 3 minutes before and after
    	OTP=`printf $EPOCHTIME$SECRET$PIN|checksum|cut -b 1-6`
    	if [ "$OTP" = "$PASSWD" ] ; then
    		/bin/touch /opt/var/motp/cache/$OTP || { echo "FAIL! Need write-access to /opt/var/motp" ; exit 17; }
    		echo "ACCEPT"
    		rm "/opt/var/motp/users/$USERNAME" 2>/dev/null
    		exit 0
    	fi
    	I=`expr $I + 1`
    	EPOCHTIME=`expr $EPOCHTIME + 1`
    done
    
    echo "FAIL"
    NUMFAILS=`cat "/opt/var/motp/users/$USERNAME" 2>/dev/null`
    if [ "$NUMFAILS" = "" ]; then
    	NUMFAILS=0
    fi
    NUMFAILS=`expr $NUMFAILS + 1`
    echo $NUMFAILS > "/opt/var/motp/users/$USERNAME"
    exit 11
    

    In case there is a newer version of this server script released in the future, here is the summary of changes:

    • line 1 should point to optware bash: /opt/bin/bash
    • The script will only looks for md5 and md5sum binary, however, we are using md5deep from optware instead. Add two lines to assign md5deep as checksum binary.
    • Add 10 to all error code, otherwise it will fail the FreeRadius server
    • Basically I’ve appended /opt to every path inside the script.
    • It need the find binary. We should use the binary provided by optware instead of using the system default binary.
  7. # chmod 755 /opt/usr/local/bin/otpverify.sh

Download and setup Android motp client

Since I’ve an Android phone, I install the motp client to my phone.

  1. Download the android motp client ‘Mobile-OTP’ from url below

    http://motp.sourceforge.net/Mobile-OTP.apk

  2. Install the apk to the phone
  3. Run the Mobile-OTP.
  4. Input #**# and click ‘Calculate OTP’ button. An init-secret value will be generated. Copy the init-secret and paste it to somewhere, i.e. notepad.
  5. Input 1234 and click ‘Calculate OTP’ button again. An one time password will be generated.
  6. Now test the setup, SSH to the DiskStation as root and run the command as below:


    # /opt/usr/local/bin/otpverify.sh testuser [one-time-password] [Init-secret] 1234 0

    If you run the command fast enough, the script should return “ACCEPT”. If you got a “FAIL”, repeats again by generating a new one-time-password and execute the command again couple times until you got “ACCEPT”. Make sure the Init-secret and One-time-password is input correctly.

FreeRadius changes

  1. SSH to DS as root
  2. # cd /opt/etc/raddb
  3. # wget http://motp.sourceforge.net/dictionary.motp
  4. Edit /opt/etc/raddb/dictionary, add following line to the end of the file

    $INCLUDE dictionary.motp

  5. Although I don’t think this step is needed, but it is suggested by the official installation guide.
    # wget http://motp.sourceforge.net/execparams
  6. Add a test user by editing /opt/etc/raddb/users file. Add following lines to the end of the file.
    
    testuser Auth-Type = Accept
        Exec-Program-Wait = "/opt/usr/local/bin/otpverify.sh %{User-Name} %{User-Password} 123412341234 1234 0",
        Fall-Through = Yes,
        Reply-Message = "Hello, %{User-Name}"
    

    where 123412341234 is the init-secret and 1234 is the pin of the test user. Replace the value of init-secret with the one generated by the Android OTP client.

  7. Generate a new One-time-password using the Android OTP client (input 1234 and click ‘Calculate OTP’ button), then test the freeradius setup by executing the command below:


    # radtest testuser [one-time-password] localhost 0 [FreeRadius shared secret password]

    If success, you should got a response similar to below:


    rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=48, length=46
    Reply-Message = "Hello, testuser "

Now my services like OpenVPN and Squid accept OTP login 🙂

Resources





One thought


Leave a Reply

Your email address will not be published. Required fields are marked *