#!/bin/sh
#
#  SLapASS!   Simple Linux access point ASSociator
#  Version 1.01
#  Kevin Currie:   kcurrie@undertow.2y.net
#  June, 2004
#
#  A simple program that allows one to either use Kismet to sniff for
#  new networks and then associate with ones it finds, or allows you to switch
#  between various preconfigured networks.  I wrote it primarily to make it easy to
#  associate with different access points, and then added a few features do some things
#  that the Opie Network app doesn't do (like let you set 5 different access point configs).
#
#  Requires:   opie-sh 
#	       
#  Kismet (http://www.kismetwireless.net/) is required if you want to sniff for new networks.
#
#  Configuration is contained INSIDE this script itself.  Any line in the script
#  where lines BEGIN with #IPCFG will be treated as configuration options.  If anybody asks,
#  I could probably be convinced mod it to ALSO consult an external file.
#  There is support for using DHCP to grab an address, as well as prompting 
#  for IP address and default gateway.  It can configure your network card for specific MAC addresses
#  if you need to, or randomly generate MACs.  
#
#  Random MAC address generation:   When ever Kismet is used to search for networks, 
#	the MAC address of your network card is automatically changed to a randomly
#	chosen one.  This can be disabled by changing the variable RANDOMMAC to "n" below.
#	Your list of valid MAC address prefixes is specified by the MANUF variable.  You
#       can use the ap_manuf or client_manuf that comes with Kismet, the larger manuf file
#       that comes with something like ethereal, or you can grab a file I've built from a
#	variety of sources here: http://undertow.2y.net/zaurus/manuf.gz  It contains 8471 
#	lines with 7482 unique prefixes. It's big though: 346242 bytes.   Probably a little
#	excessive by I'm also using it for other programs :-)
#
#  After associating with a new sniffed AP you have several choices regarding what your IP gets set to, including
#	DHCP, Manual (you are prompted for IP and gateway), and several common network settings such as
#       192.168.1.X.   If you choose an entry that contains an "X" the program will then generate 4 random IP addresses
#	for you to choose from.  
#
#  Note that if you choose a random IP address, the gateway will be set to the .1 of that network.  This may or may
#  	not be correct, but is the most common choice.
#
#  If HIDEWEP is set to "n" WEP protected networks will not be shown.  Things that come up as "no ssid" are also not
#  shown, no matter what, if you don't like this, change the grep found in the code.
#
#  If RUNkismetCLIENT is set to "y" then embeddedkonsole will be launched with kismet_client running in it.  This is handy
#	for more indepth examination of networks prior to associating, or even for doing things like turning off channel
#	hopping for that extra hard to lock onto network :-)
#
#  After associating and getting/setting your IP address you have the option to display what your EXTERNALLY visable IP 
#	address is, i.e. what IP address you would appear to be coming from if you visited a random web site.  
#	This check is done by simply visiting this web page which displays your address:   http://checkip.dyndns.org
#
#  Examples of configuration lines for preconfigured networks
#
#  #IPCFG DHCP           <---- Will get all IP configuration via DHCP
#  #IPCFG Manual         <---- Will prompt for IP address and gateway 
#  #IPCFG 192.168.1.32 linksys 3 Managed 192.168.1.1 00:03:5E:A9:B6:22  <---- sets IP, SSID, Channel, Mode, Gateway and MAC address
#  #IPCFG 10.0.0.7 dlink 3 Ad-Hoc 10.0.0.1  <---- sets IP, SSID, Channel, Mode and Gateway 
#  #IPCFG 10.0.0.7 wireless 3 Managed 00:03:5E:A9:B6:22   <---- sets IP, SSID, Channel, Mode and MAC address
#
#
#
#   Bugs:	But of course!  If you find one, let me know.  If you're feeling frisky, fix it too :-)
#		Depending on your setup, you may want/need to tweak the function (procASSOCIATE) that determines if you've 
#		actually associated with a network.  It works for me anyway :-)
#		If anybody knows how to always get opie-sh to center dialog boxes on the screen, please
#		let me know.
#
#    If you find this program useful,  shoot me an email so my time wasn't completely wasted :-)
#	   I am:  Kevin Currie,   kcurrie@undertow.2y.net
#	   
#

#####################################################################
#
#
# BEGIN SLapASS configuration
#IPCFG 10.0.0.55 0xx0 3 Ad-Hoc 10.0.0.1 00:05:5D:F9:B6:61
#IPCFG 10.0.0.55 0xx0 3 Ad-Hoc 10.0.0.1 
#IPCFG 10.0.0.55 0xx0 3 Ad-Hoc 00:05:5D:F9:B6:62
#IPCFG DHCP 0xx0 3 Ad-Hoc
#IPCFG DHCP linksys 6 Managed 
#IPCFG DHCP
#IPCFG Manual
#IPCFG 192.168.1.X
#IPCFG 192.168.0.X
#IPCFG 192.168.250.X
#IPCFG 10.0.0.X
# END  SLapASS configuration


#################################################################
#	Change these variables!
HIDEWEP=n             # do we want to NOT SHOW WEP protected networks?
RANDOMMAC=n           # do we want to randomly choose MAC address before running Kismet?
DUMPDIR="/sd/dump"    # where Kismet is configured to save it's dump files
IFACE=wlan0           # your network interface
MANUF="/sd/etc/manuf" # where we get the list of valid prefixes to use for random MAC generation.  Can use kismet supplied ones (ap_manuf,client_manuf) too
RUNkismetCLIENT=y     # if set to "y" embeddedkonsole will be launced with kismet_client running in it
#################################################################


#don't change these variables
FIND=1   # don't modify
CONFIGURED=2   # don't modify
IP=X   #ignore, just presetting a variable


procCIT() {

# randomly change MAC address to a new valid one
NUM=`wc -l $MANUF |awk '{print $1}'`
LINE=`echo |awk "function randint(n) { srand(); return int($NUM * rand()) } {print randint(10)}"`
PREFIX=`head -$LINE $MANUF |tail -1 |awk '{print $1}' | cut -b1-8`

ifconfig $IFACE down
ifconfig $IFACE hw ether $PREFIX:`head -4 /dev/urandom |md5sum |cut -b1-6` 
ifconfig $IFACE up

}

procDHCP() {

test -f /var/run/udhcp.pid  && kill `cat /var/run/udhcp.pid `
IP=0.0.0.0
# we will try 2 times to get a DHCP address
while [ $IP = '0.0.0.0' ]
do
/sbin/udhcpc -i wlan0 -n -p /var/run/udhcp.pid || /sbin/udhcpc -i wlan0 -n -p /var/run/udhcp.pid
if [ $? = 0 ]; then
	IP=`ifconfig wlan0 |grep inet  |awk -F: '{print $2}'|awk '{print $1}' `
	opie-sh -g -m -M "IP Address is $IP"
	GW=CONFIGURED
else
	opie-sh -g -m -M 'FAILED TO GET LEASE!'   -0 "Quit" -1 "Try AGAIN" 2>/dev/null && exit
fi
done
}



procASSOCIATE() {

iwconfig wlan0 mode `echo $MODE |sed 's/infrastructure/Managed/g'`
iwconfig wlan0 channel $CH

dmesg -c >/dev/null
iwconfig wlan0 essid "$SSID"
iwconfig wlan0 channel $CH


count=1
while [ 1 ] ;
do
        dmesg | tail -20 |grep -v "BSSID=44:44:44:44:44:44" |grep  "LinkStatus: BSSID=" > /dev/null
        [ $? -eq 0 ] && break
	sleep 1
	if [ $count -gt 30 ]; then
		opie-sh -g -m -M "Failed to associate! 
Exiting" 2> /dev/null
		exit 1
	fi
	count=`expr $count + 1`
        done
opie-sh -I -M "Associated with \"$SSID\"" -m 2> /dev/null

}


### Main program
while [ /bin/true ]
do
	opie-sh -g -m -M 'SLapASS! Simple Linux A.P. ASSociator
Comments to: kcurrie@undertow.2y.net'   -0 "Quit" -1 "Find APs!" -2 "Configured APs"  2> /dev/null && exit
	mode=$?
       [ $mode = 255 ] &&  opie-sh -g -m -M "Don't press the OK button,
choose Quit,Find,Configured instead" 2> /dev/null          
       [ $mode -lt 3 ] && break
done


if [ $mode = $FIND ]; then

	if [ $RANDOMMAC = "y" ]; then 
		procCIT
		MAC=`ifconfig wlan0  |grep HWaddr |awk '{print $5}'`
		opie-sh -g -m -t "Random MAC Changer" -M "Changed MAC of $IFACE            
to $MAC"
	fi	
	`kismet_server  -t apASS.$$ -l csv  2> /tmp/aplist` &
	if [ $RUNkismetCLIENT = "y" ]; then
		sleep 3
		qcop QPE/Application/embeddedkonsole 'setDocument(QString)' "kismet_client"
		qcop QPE/Application/embeddedkonsole 'raise()' 
	fi
	opie-sh -g -m -M "Click to kill kismet
and see AP list." 2> /dev/null
	kill `cat /var/run/kismet_server.pid`
	sleep 1

	DATE=`date +%a`
	GREPOPTS="@"
	[ $HIDEWEP = "y" ] && GREPOPTS='-v WEP.Y ' 
	grep "new network " /tmp/aplist |sed 's/.*Found new network //g'|sed 's/bssid .*:.. //g' |egrep -ve ' via |no ssid' | grep -n ${GREPOPTS} > /tmp/ap.txt
	if [ ! -s /tmp/ap.txt ]; then
		 opie-sh -g -m -M "No access points found!
Exiting!"
		exit
	fi
	opie-sh  -g -m -t "Found Networks                             " -M "`cat /tmp/ap.txt`" 2> /dev/null
	choice=`opie-sh -g -i -l -L "Select Access Point" -t "" -F /tmp/ap.txt 2>/dev/null |awk -F: '{print $1}'`
	AP=`head -${choice} /tmp/ap.txt |tail -1`
	CH=`echo $AP |awk -F\" '{print $3}' |awk '{print $4}'`
	SSID=`echo $AP |awk -F\" '{print $2}'`
	FILE=`ls -1t $DUMPDIR/apASS.$$* | head -1`
	MODE=`grep -- $SSID $FILE | head -1 |awk -F\; '{print $2}' `

	procASSOCIATE

	grep ^#IPCFG $0 |egrep -v 'Ad-Hoc|Managed' | awk '{print $2}'  > /tmp/.ipconfig
	C=`opie-sh -g -i -l -L "Select IP config" -t "" -F /tmp/.ipconfig`
	echo $C |grep DHCP >/dev/null 
	if [ $? -eq 0 ]; then 
		procDHCP
	else
		IP=`echo $C |awk '{print $1}'`
	fi

fi

if [ $mode = $CONFIGURED ]; then
	grep ^#IPCFG $0  |egrep  'Managed|Ad-Hoc' |sed 's/#IPCFG //g' > /tmp/.ipconfig
	C=`opie-sh -g -i -l -L "Select Config" -t "" -F /tmp/.ipconfig`
	IP=`echo $C |awk '{print $1}'`
	SSID=`echo $C |awk '{print $2}'`

	CH=`echo $C |awk '{print $3}'`
	MODE=`echo $C |awk '{print $4}'`
	# if #5 has : it's a mac, else a GW
	echo $C |awk '{print $5}' |grep : > /dev/null && MAC=`echo $C |awk '{print $5}'`
	echo $C |awk '{print $5}' |grep '\.' > /dev/null && GW=`echo $C |awk '{print $5}'`
	# same thing for #6
	echo $C |awk '{print $6}' |grep : > /dev/null && MAC=`echo $C |awk '{print $6}'`
	echo $C |awk '{print $6}' |grep '\.' > /dev/null && GW=`echo $C |awk '{print $6}'`

	# if MAC is set, config card
	echo $MAC | grep : >/dev/null 
	if [ $? -eq 0 ]; then
		ifconfig $IFACE down
		ifconfig $IFACE hw ether $MAC 
		ifconfig $IFACE up
		opie-sh -g -m -M "MAC address is $MAC"
	fi
fi
procASSOCIATE

GW=`echo $C |awk '{print $5}'`   #GW might not be set, if not, we'll set it to .1 later
echo $MAC |grep '\.'  >/dev/null &&  MAC=`echo $C |awk '{print $6}'`

echo ${IP}x |grep X  > /dev/null
if [ $? = 0 ]; then  
	# get 4 random numbers, if you want more random IP's, increase the number
	for var in 1 2 3 4
	do
		RANDOM=`echo |awk "function randint(n) { srand(); return int(254* rand()) } {print randint(10)}"`
		sleep 1
		echo $IP|sed "s/X/`echo $RANDOM`/g" >> /tmp/RANDOMIPS.$$
	done
	IP=`opie-sh -g -i -l -L "       Select IP:" -t "Random IP list" -F  /tmp/RANDOMIPS.$$`
	rm /tmp/RANDOMIPS.$$
fi
ifconfig wlan0 $IP
if [ ${MODE}x = x ]; then
	#default to managed
	iwconfig wlan0 mode Managed 
else
	iwconfig wlan0 mode `echo $MODE |sed 's/infrastructure/Managed/g'`
fi
iwconfig wlan0 channel $CH

if [ ${IP}x = DHCPx ]; then
        procDHCP
else
        if [ ${IP}x = Manualx ]; then
	                IP=`opie-sh -i -s  -L "Enter IP address:"`
			GW=`opie-sh -i -s  -L "Enter default gateway:"`
	fi
fi

#if GW not set, set to default gw..
[ ${GW}x = x ] && route add default gw `echo $IP |sed 's/[0-9]*$//g'`1 
echo $GW |grep : >/dev/null  && route add default gw `echo $IP |sed 's/[0-9]*$//g'`1  ||  route add default gw $GW

opie-sh -g -m -M 'Show EXTERNAL IP address?'   -0 "No" -1 "Yes" 2>/dev/null && exit
opie-sh -g -m -M "`wget -q  http://checkip.dyndns.org -O - |sed 's/.*Current //g' |sed 's/<.*//g'`"


