#!/bin/bash
# yet another port scanner
# by shudder <shudder@gbg.bg>
# dedicated to a very special girl

_exit() {
  rm -f ~/.$name.ports
}
trap _exit 0
name="`basename $0`"
hname="`basename $0 | tr a-z A-Z`"
fname="$0"

usage() {
  case $1 in
    -*) echo "invalid option: $1";;
  esac

  echo "usage:   $name [[1m-i[0m|[1m-c[0m|[1m-a[0m] <[1maddress[0m> <[1mstart port[0m> <[1mend port[0m>"
  echo "           [1m-i[0m	interactive mode"
  echo "           [1m-c[0m	check if address is up"
  echo "           [1m-a[0m	about [1m$name[0m"
  exit 1
}

help() {
  echo "[1mscan[0m		begin scanning"
  echo "[1msave[0m		save port information to file"
  echo "[1mcheck[0m		check if address is up"
  echo "[1mclear[0m		clear screen"
  echo "[1mhelp[0m		get help"
  echo "[1mabout[0m		about this program"
  echo "[1mquit[0m		exit the program"
}

about() {
  echo "        __________________________________"
  echo "       (${hname}__[1myet_another_po[1;31mr[1;33mt_[1;35ms[1;36mc[1;39manner[0m_**_)"
  echo
  echo "      ____________               ____________ "
  echo "    _(_greetings__)________     (_by shudder_)_____ "
  echo "   (_jeux,_ZeaN,_ultrafina_)      (_shudder@gbg.bg_) "
  echo "         (_sonne,_Elessar_)"
  echo
}

[ ! "$1" ] && usage

if [ "$1" = "-i" ]; then
  prompt="$name"
  echo "Interactive mode.Type [1mhelp[0m for help"
  while true; do
    read -p "[1m$prompt[0m> " line
    if [ "$line" ]; then
      set $line
    else
      continue
    fi
    command="`echo $1 | tr A-Z a-z`"
    case $command in
     help)
       help;;
     scan)
       if [ ! "$address" ] || [ ! "$sport" ] || [ ! "$eport" ] || [ "$2" = "-n" ]; then
         echo "writing database.use option -n next time to provide new information"
         read -p "[1maddress[0m: " address
         read -p "[1mstart port[0m: " sport
         read -p "[1mend port[0m: " eport
       fi

       if [ "$address" ] && [ "$sport" ] && [ "$eport" ]; then
         $0 $address $sport $eport
         prompt="$address"
         save="yes"
       else
         echo "cannot scan" 
         echo "address: [1m$address[0m" 
         echo "start port: [1m$sport[0m"
         echo "end port: [1m$eport[0m"
         prompt="$name"
       fi;;
     save)
       if [ "$save" = "yes" ]; then
         read -p "[1mfilename[0m: " filename
         [ "$filename" ] && cp ~/.$name.ports $filename || echo "no filename given"
       else
         echo "nothing to save"
       fi;;
     check)
       read -p "[1maddress[0m: " adr
       $fname -c $adr;;
     clear)
       echo -n "[H[J";;
     about)
       about;;
     quit)
       exit 0;;
     *)
      echo "$1: Unknown command."
    esac
  done
fi

if [ "$1" = "-c" ]; then
  if [ ! "$2" ]; then
    echo "$name: No address given"
    exit 1
  fi

  # This may stall for a while.You could send INT to stop it.
  if ping -c 1 $2 &> /dev/null ; then
    echo "$2 is up!"
    exit 0
  else
    echo "$2 is down."
    exit 1
  fi
fi

if [ "$1" = "-a" ]; then
  about
  exit 0
fi

if [ "$2" ] && [ "$3" ]; then
  host="$1"          # Hostname
  start="$2"         # Port from where to start
  stop="$[$3+1]"     # End port
  range1="$2"
  range2="$3"

  if ! (which nc &> /dev/null) ; then
    echo "$name: netcat was not found.$name can't continue"
    exit 1
  fi

  # Our ports are numerical, aren't they?!
  if [ "$[$range1]" = "0" ] || [ "$[$range2]" = "0" ]; then
    echo "invalid ports!"
    exit 172
  fi

  echo "Scanning $host for open ports"
  rm -f ~/.$name.ports
 
  # Checking if hostname is reachable
  if ! (ping -c 1 $host &> /dev/null) ; then
    echo "$name: can't connect to $host"
    exit 1
  fi
  logger -i "Scanning $host for open ports"
  echo "SERVICE		PORT" >> ~/.$name.ports
  while [ "$start" -lt "$stop" ]; do
    if nc -z $host $start ; then

      # I grep twice because the service name might be tabulated from the port
      # So just to make sure I'm doing 'em both
      pname1="`grep \" ${start}/tcp\" /etc/services`"
      pname2="`grep \"	${start}/tcp\" /etc/services`"
      if [ "$pname1" ] || [ "$pname2" ]; then
        [ "$pname1" ] && set $pname1
        [ "$pname2" ] && set $pname2
        echo "[1m$1		$2[0m" >> ~/.$name.ports
        pcount="$[$pcount+1]"
      else

        # We don't know what kinda service lays here.So we print - unknown
        echo "[1munknown		$start/tcp[0m" >> ~/.$name.ports
        pcount="$[$pcount+1]"
      fi
    fi

    # Increase the port by one then start all over again
    start="$[$start+1]"
  done
  if [ ! "$pcount" ]; then
    echo "There are no open ports in this range"
    exit 0
  fi

  # Check what to write in the summary.
  if [ "$pcount" -gt "1" ]; then
    str1="are"
    str2="s"
  else
    str1="is"
  fi

  # Summary
  echo "There $str1 $pcount open port$str2 on $host \
in the range of $range1-$range2" >> ~/.$name.ports
  cat ~/.$name.ports
else
  usage $1
fi




