#!/bin/sh #Copyright (C) The openNDS Contributors 2004-2020 #Copyright (C) BlueWave Projects and Services 2015-2020 #This software is released under the GNU GPL license. # # Warning - shebang sh is for compatibliity with busybox ash (eg on OpenWrt) # This is changed to bash automatically by Makefile for Debian # # Customise the Logfile location: # # mountpoint is the mount point for the storage the log is to be kept on # # /tmp on OpenWrt is tmpfs (ram disk) and does not survive a reboot. # # /run on Raspbian is also tmpfs and also does not survive a reboot. # # These choices for OpenWrt and Raspbian are a good default for testing purposes # as long term use on internal flash could cause memory wear # In a production system, use the mount point of a usb drive for example # # # logdir is the directory path for the log file # # # logname is the name of the log file # #For Openwrt: mountpoint="/tmp" logdir="/tmp/ndslog/" logname="ndslog.log" #For Raspbian: #mountpoint="/run" #logdir="/run/ndslog/" #logname="ndslog.log" #For logging ndspid=$(ps | grep '/usr/bin/opennds' | awk -F ' ' 'NR==2 {print $1}') # functions: validate_client() { #Add your custom client validation here #For example check all the clent entered data against a database # we have: # $username, $phone, $emailaddr, $addr, $code # # Return either 0 if validation successful or 1 if not userlist="/etc/opennds/htdocs/images/wlan1/userpass.dat" varlist="username password Firstname Lastname" while read user; do for var in $varlist; do nextvar=$(echo "$varlist" | awk '{for(i=1;i<=NF;i++) if ($i=="'$var'") printf $(i+1)}') eval $var=$(echo "$user" | awk -F "$var=" '{print $2}' | awk -F ", $nextvar=" '{print $1}') done if [ "$username" = "$1" -a "$password" = "$2" ]; then exit_code=0 break else exit_code=1 fi done < $userlist return $exit_code } htmlentityencode() { entitylist="s/\"/\"/ s/>/\>/ s// s/\</ $logfile fi filesize=$(ls -s -1 $logfile | awk -F' ' '{print $1}') available=$(df | grep "$mountpoint" | eval "$awkcmd") sizeratio=$(($available/$filesize)) if [ $sizeratio -ge $min_freespace_to_log_ratio ]; then userinfo="username=$username, password=$password" clientinfo="macaddress=$clientmac, clientzone=$client_zone, useragent=$user_agent" echo "$datetime, $userinfo, $clientinfo" >> $logfile else echo "PreAuth - log file too big, please archive contents" | logger -p "daemon.err" -s -t "opennds[$ndspid]: " fi } # Get the urlencoded querystring and user_agent query_enc=$(echo "$1" | sed "s/%3f/%20/") user_agent_enc="$2" # The query string is sent to us from NDS in a urlencoded form, # we can decode it or parts of it using something like the following: # query=$(printf "${query_enc//%/\\x}") # The User Agent string is sent urlencoded also: user_agent=$(printf "${user_agent_enc//%/\\x}") # In this example script we want to ask the client user for # their username and email address. # # We could ask for anything we like and add our own variables to the html forms # we generate. # # If we want to show a sequence of forms or information pages we can do this easily. # # To return to this script and show additional pages, the form action must be set to: #
# Note: quotes ( " ) must be escaped with the "\" character. # # Any variables we need to preserve and pass back to ourselves or NDS must be added # to the form as hidden: # " # # We must also send NDS the client token as a hidden variable, but first we must obtain # the token from ndsctl using a suitable command such as: # tok="$(ndsctl json $clientip | grep token | cut -c 10- | cut -c -8)" # # In a similar manner we can obtain any client or NDS information that ndsctl provides. # The query string NDS sends to us will always be of the following form (with a "comma space" separator): # ?clientip=[clientipaddress], gatewayname=[gatewayname], redir=[originalurl], var4=[data], var5=[data], var6...... # # The first three variables will be clientip, gatewayname and redir # # We have chosen to name redir as $requested here as it is actually the originally requested url. # # There is one exception to this. If the client presses "back" on their browser NDS detects this # and tells us by returning status=authenticated instead of redir=[originalurl] # If we detect this we show a page telling the client they are already logged in. # # Additional variables returned by NDS will be those we define here and send to NDS via an # html form method=get # See the examples here for $username and $emailaddress # # There is no limit to the number of variables we can define dynamically # as long as the query string does not exceed 2048 bytes. # # The query string will be truncated if it does exceed this length. # Parse for the variables returned by NDS: hid_present=$(echo "$query_enc" | grep "hid") status_present=$(echo "$query_enc" | grep "status") if [ ! -z "$status_present" ]; then queryvarlist="clientip gatewayname gatewayaddress status" elif [ -z "$hid_present" ]; then hid="0" gatewayaddress="0" queryvarlist="clientip gatewayname splashpagetitle acceptancepolicy loginsuccesstext redirecturl redir username password" else queryvarlist="clientip gatewayname hid splashpagetitle acceptancepolicy loginsuccesstext redirecturl redir gatewayaddress username password" fi for var in $queryvarlist; do nextvar=$(echo "$queryvarlist" | awk '{for(i=1;i<=NF;i++) if ($i=="'$var'") printf $(i+1)}') eval $var=$(echo "$query_enc" | awk -F "%20$var%3d" '{print $2}' | awk -F "%2c%20$nextvar%3d" '{print $1}') done # URL decode and htmlentity encode vars that need it: splashpagetitle=$(printf "${splashpagetitle//%/\\x}") htmlentityencode "$splashpagetitle" splashpagetitlehtml=$entityencoded acceptancepolicy=$(printf "${acceptancepolicy//%/\\x}") htmlentityencode "$acceptancepolicy" acceptancepolicyhtml=$entityencoded browsertitle=$(printf "${browsertitle//%/\\x}") htmlentityencode "$browsertitle" browsertitlehtml=$entityencoded loginsuccesstext=$(printf "${loginsuccesstext//%/\\x}") htmlentityencode "$loginsuccesstext" loginsuccesstexthtml=$entityencoded redirecturl=$(printf "${redirecturl//%/\\x}") htmlentityencode "$redirecturl" redirecturlhtml=$entityencoded gatewayname=$(printf "${gatewayname//%/\\x}") htmlentityencode "$gatewayname" gatewaynamehtml=$entityencoded username=$(printf "${username//%/\\x}") htmlentityencode "$username" usernamehtml=$entityencoded password=$(printf "${password//%/\\x}") htmlentityencode "$password" passwordhtml=$entityencoded #requested might have trailing comma space separated, user defined parameters - so remove them as well as decoding #requested=$(printf "${redir//%/\\x}" | awk -F ', ' '{print $1}') #Get the client zone, local wired, local wireless or remote mesh node get_client_zone # Define some common html as the first part of the page to be served by NDS # # Note this example uses the default splash.css provided by NDS and uses splash.jpg # as the browser shortcut icon. # # You can decide how your PreAuth splash page will look # by incorporating your own css and images. # # Note however that the output of this script will be displayed on the client device screen via the CPD process on that device. # It should be noted when designing a custom splash page that for security reasons many client device CPD implementations: # # Immediately close the browser when the client has authenticated. # Prohibit the use of href links. # Prohibit downloading of external files (including .css and .js, even if they are allowed in NDS firewall settings). # Prohibit the execution of javascript. # if [ "$status" = "authenticated" ]; then gatewaynamehtml="Welcome!" fi header=" $gatewaynamehtml
$gatewaynamehtml

" # Define a common footer for every page served version="$(ndsctl status | grep Version)" year="$(date | awk -F ' ' '{print $(6)}')" footer=" \"Splash

openNDS $version.
" # Define a login form login_form="
User Name


Password


" # Output the page common header echo -e "$header" # Check if the client is already logged in and has tapped "back" on their browser # Make this a friendly message explaining they are good to go if [ "$status" = "authenticated" ]; then echo "

You are already logged in and have access to the Internet.

" echo "
" echo "

You can use your Browser, Email and other network Apps as you normally would.

" echo -e "$footer" exit 0 fi # For this simple example, we check that both the username and email address fields have been filled in. # If not then serve the initial page, again if necessary. # We are not doing any specific validation in this example, but here is the place to do it if you need to. # # Note if only one of username or email address fields is entered then that value will be preserved # and displayed on the page when it is re-served. # # Note also $clientip, $gatewayname and $requested (redir) must always be preserved # if [ -z "$username" ] || [ -z "$password" ]; then echo "Welcome to $splashpagetitle!
You are connected to $client_zone
To access the Internet you must complete all fields
$acceptancepolicy

" echo -e "$login_form" else # If we got here, we have all fields as completed on the login page on the client, # so we will now validate the client and if sucessful we will call ndsctl # to get client data we need to authenticate and add to our log. validate_client $username $password if [ $? = 1 ]; then echo "Sorry! Validation failed, please try again.
" echo -e "$login_form" echo -e "$footer" exit 0 fi # Variables returned from ndsctl are listed in $varlist. # We at least need the client token to authenticate. # In this example we will also log the client mac address. varlist="id ip mac added active duration token state downloaded avg_down_speed uploaded avg_up_speed" clientinfo=$(ndsctl json $clientip) if [ -z "$clientinfo" ]; then echo "Sorry! The portal is busy, please try again.
" echo -e "$login_form" echo -e "$footer" exit 0 else for var in $varlist; do eval $var=$(echo "$clientinfo" | grep $var | awk -F'"' '{print $4}') done fi tok=$token clientmac=$mac # We now output the "Thankyou page" with a "Continue" button. # This is the place to include information or advertising on this page, # as this page will stay open until the client user taps or clicks "Continue" # Be aware that many devices will close the login browser as soon as # the client user continues, so now is the time to deliver your message. echo "Thankyou!" echo "
Welcome $usernamehtml" # Add your message here: # You could retrieve text or images from a remote server using wget or curl # as this router has Internet access whilst the client device does not (yet). # You can also send a custom data string to BinAuth. Set the variable $custom to the desired value # Max length 256 characters custom="Custom data sent to BinAuth" #echo "
Your News or Advertising could be here, contact the owners of this Hotspot to find out how!" # If you want to redirect the client somewhere other than the url they originally requested, you can overide # the $requested value here. # NOTE: Many implementations of the client CPD will immediately close the CPD browser once authenticated by NDS. # eg: requested="$redirecturl" echo "
" echo "" echo "
" #echo "" echo "" echo "

" # In this example we have decided to log all clients who are granted access write_log fi # Output the page footer echo -e "$footer" # The output of this script could of course be much more complex and # could easily be used to conduct a dialogue with the client user. #