r1169 The first ever working switchvlans gateway for the real world, readonly, of...
authorDenis Ovsienko <infrastation@yandex.ru>
Tue, 9 Oct 2007 16:41:27 +0000 (16:41 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Tue, 9 Oct 2007 16:41:27 +0000 (16:41 +0000)
gateways/switchvlans/cisco.connector [new file with mode: 0755]
gateways/switchvlans/cisco.secrets.php [new file with mode: 0644]
gateways/switchvlans/main
gateways/switchvlans/userauth.php [new file with mode: 0644]

diff --git a/gateways/switchvlans/cisco.connector b/gateways/switchvlans/cisco.connector
new file mode 100755 (executable)
index 0000000..ae3d367
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+[ $# = 4 ] || exit 2
+
+ENDPOINT=$1
+COMMAND=$2
+VLANINFO=$3
+PORTINFO=$4
+
+prepare_load_commands()
+{
+       [ $# = 1 ] || exit 1
+       local skip=yes cval
+       while read line; do
+               if [ "$skip" = "yes" -a "$line" = "# S-T-A-R-T" ]; then
+                       skip=no
+                       continue
+               fi
+               if [ "$skip" = "no" -a "$line" = "# S-T-O-P" ]; then
+                       skip=yes
+                       continue
+               fi
+               [ "$skip" = "yes" ] && continue
+               # Allow comments.
+               [ -z "${line###*}" ] && continue
+
+               # First endpoint string/regexp match is sufficient for us.
+               cval=`echo $line | cut -s -d' ' -f1`
+               if [ -z "${1##$cval}" ]; then
+                       # Don't be too smart at the moment, just be able to handle
+                       # the known-good case ;-)
+
+                       echo $line | cut -s -d' ' -f6 > $CMDS1
+                       echo en >> $CMDS1
+                       echo $line | cut -s -d' ' -f7 >> $CMDS1
+
+                       # same for ports
+                       echo $line | cut -s -d' ' -f6 > $CMDS2
+                       echo en >> $CMDS2
+                       echo $line | cut -s -d' ' -f7 >> $CMDS2
+                       break
+               fi
+       done < `dirname $0`/cisco.secrets.php
+       printf 'term len 0\nshow vlan brief\nquit\n' >> $CMDS1
+       printf 'term len 0\nshow int status\nquit\n' >> $CMDS2
+}
+
+do_load()
+{
+       nc $ENDPOINT 23 < $CMDS1 | fgrep active | cut -d' ' -f1 > $VLANINFO
+       nc $ENDPOINT 23 < $CMDS2 | egrep '^(Et|Fa|Gi|Te)' | sed -E 's/ +(notconnect|connected) +/=/;s/=(trunk|([0-9]+)) .*$/=\1/' > $PORTINFO
+}
+
+# This one is for VLAN list.
+CMDS1=`mktemp /tmp/cisco.connector.XXXX`
+[ -f "$CMDS1" ] || exit 2
+
+# And this one holds ports list.
+CMDS2=`mktemp /tmp/cisco.connector.XXXX`
+if ! [ -f "$CMDS2" ]; then
+       rm -f "$CMDS1"
+       exit 2
+fi
+
+case $COMMAND in
+       load)
+               prepare_load_commands $ENDPOINT
+               do_load
+       ;;
+       save)
+               rm -f "$CMDS1" "$CMDS2"
+               exit 1
+       ;;
+       *)
+               rm -f "$CMDS1" "$CMDS2"
+               exit 2
+       ;;
+esac
+
+rm -f "$CMDS1" "$CMDS2"
+exit 0
diff --git a/gateways/switchvlans/cisco.secrets.php b/gateways/switchvlans/cisco.secrets.php
new file mode 100644 (file)
index 0000000..059e08e
--- /dev/null
@@ -0,0 +1,13 @@
+<?
+echo "Unauthorized access attempt has been logged. Cheers.";
+exit();
+# Syntax:
+# <endpoint|*> <telnet> <hostname|-> <port|-> <username|-> <line password> <enable password>
+# FIXME: <endpoint|*> <rsh> <username>
+
+# S-T-A-R-T
+switch1 telnet - - - password2 enablepassword
+switch2 telnet - - - password enablepassword
+# S-T-O-P
+
+?>
index 4eb41cb..736b710 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 # This is a RackTables gateway for changing switch ports membership
 # across VLANs. It works accordingly to the gateway protocol described
 # VLAN ID and tagged ports will be shown as 'trunk' regardless of
 # how many VLANs they are members of.
 
-usage()
+authorized()
 {
-       echo "Usage: $0 <endpoint> <hwtype> <swtype> <username>"
-       exit 1;
+       local endp=$1 user=$2 action=$3 arg1=$4 arg2=$5 skip=yes cval
+       [ -z "$endp" -o -z "$user" -o -z "$action" ] && return 1
+
+       # Now we strip PHP wrapping(s) and process auth rules only.
+       # Accept more than one ruleset on the floor.
+       while read line; do
+               if [ "$skip" = "yes" -a "$line" = "# S-T-A-R-T" ]; then
+                       skip=no
+                       continue
+               fi
+               if [ "$skip" = "no" -a "$line" = "# S-T-O-P" ]; then
+                       skip=yes
+                       continue
+               fi
+               [ "$skip" = "yes" ] && continue
+               # Allow comments.
+               [ -z "${line###*}" ] && continue
+
+               # Parse the line and try to make a decision earliest possible.
+               # Username and endpoint must match values/regexps, action
+               # must exactly match. Action arguments are tested agains values
+               # or regexps, but only for 'change' action.
+               # If the current rule doesn't match, advance to the next one.
+               # We will fail authorization by default anyway.
+
+               # Test action.
+               cval=`echo "$line" | cut -s -d' ' -f3`
+               [ "$action" = "$cval" ] || continue
+
+               # Test username.
+               cval=`echo "$line" | cut -s -d' ' -f2 | cut -s -d'@' -f1`
+               [ -z "${user##$cval}" ] || continue
+
+               # Test endpoint.
+               cval=`echo "$line" | cut -s -d' ' -f2 | cut -s -d'@' -f2`
+               [ -z "${endp##$cval}" ] || continue
+
+               if [ "$caction" = "change" ]; then
+                       [ -z "$arg1" -o -z "$arg2" ] && return 1
+                       cval=`echo "$line" | cut -s -d' ' -f4`
+                       [ -z "${arg1##$cval}" ] || continue
+                       cval=`echo "$line" | cut -s -d' ' -f5`
+                       [ -z "${arg2##$cval}" ] || continue
+               fi
+
+               # All criterias match. Pick the permission and bail out.
+               cval=`echo "$line" | cut -s -d' ' -f1`
+               if [ "$cval" = "allow" ]; then
+                       return 0
+               else
+                       return 1
+               fi
+       done < `dirname $0`/userauth.php
+       return 1
 }
 
-[ $# = 4 ] || usage
+# Not only connect, but gather all the data at once.
+do_connect()
+{
+       # sanity checks
+       local endpoint=`echo $args | cut -s -d' ' -f1`
+       local hw=`echo $args | cut -s -d' ' -f2`
+       local sw=`echo $args | cut -s -d' ' -f3`
+       local user=`echo $args | cut -s -d' ' -f4`
+       if [ -z "$endpoint" -o -z "$hw" -o -z "$sw" -o -z "$user" ]; then
+               echo 'ERR!too few arguments to connect'
+               return
+       fi
+       # authorize user, look for "connect" privilege
+       if ! authorized $endpoint $user connect; then
+               echo "ERR!User $user is not authorized to connect to $endpoint"
+               return
+       fi
+
+       # prepare temp files
+       PORTINFO=`mktemp /tmp/racktables.XXXX`
+       if ! [ -f "$PORTINFO" ]; then
+               echo 'ERR!could not create portinfo tmpfile'
+               return
+       fi
+       VLANINFO=`mktemp /tmp/racktables.XXXX`
+       if ! [ -f "$VLANINFO" ]; then
+               echo 'ERR!could not create vlaninfo tmpfile'
+               rm -f "$PORTINFO"
+               return
+       fi
 
-while read cmd arg1 arg2; do
+       # get the data
+       case "$sw" in
+               Cisco+IOS+12.2)
+                       `dirname $0`/cisco.connector $endpoint load "$VLANINFO" "$PORTINFO"
+                       ret=$?
+                       if [ $ret = 0 ]; then
+                               CONNECTED=1
+                               echo "OK!connected to $endpoint";
+                       else
+                               echo "ERR!Cannot connect to $endpoint, connector returned code $ret"
+                       fi
+               ;;
+               *)
+                       echo "ERR!Don't know how to handle $sw"
+                       rm -f "$PORTINFO" "$VLANINFO"
+               ;;
+       esac
+}
+
+do_listfile()
+{
+       local F=$1
+       if ! [ -f "$F" ]; then
+               echo "ERR!Lost temp file '$F' on the way"
+               return
+       fi
+       echo -n 'OK!'
+       local COMMA=''
+       # tr might do the work, but use our chance to perform filtering once more
+       cat "$F" | while read line; do
+               [ "$line" = "" ] && continue
+               echo -n "$COMMA$line"
+               COMMA=','
+       done
+       echo
+}
+
+do_set()
+{
+       echo 'OK!'
+}
+
+CONNECTED=0
+
+# main loop
+while read cmd args; do
        case $cmd in
+               connect)
+                       if [ $CONNECTED = 1 ]; then
+                               echo 'ERR!Already connected'
+                       else
+                               do_connect $args
+                       fi
+                       ;;
                listvlans)
-                       echo 'OK!200,204,203,202,201,205,333,334'
+                       if [ $CONNECTED = 1 ]; then
+                               do_listfile "$VLANINFO"
+                       else
+                               echo 'ERR!Not connected'
+                       fi
                        ;;
                listports)
-                       echo -n 'OK!fa0/0/1=200,fa0/0/2=205,fa0/0/3=202,fa0/0/4=trunk,fa0/0/5=333,fa0/0/6=334,fa0/0/7=333,fa0/0/8=334,'
-                       echo -n 'fa0/0/9=200,fa0/0/10=205,fa0/0/11=202,fa0/0/12=trunk,fa0/0/13=333,fa0/0/14=334,fa0/0/15=333,fa0/0/16=334,'
-                       echo -n 'fa0/1/1=200,fa0/1/2=205,fa0/1/3=202,fa0/1/4=trunk,fa0/1/5=333,fa0/1/6=334,fa0/1/7=333,fa0/1/8=334,'
-                       echo 'fa0/1/9=200,fa0/1/10=205,fa0/1/11=202,fa0/1/12=trunk,fa0/1/13=333,fa0/1/14=334,fa0/1/15=333,fa0/1/16=334'
+                       if [ $CONNECTED = 1 ]; then
+                               do_listfile "$PORTINFO"
+                       else
+                               echo 'ERR!Not connected'
+                       fi
                        ;;
                set)
-                       echo 'OK!'
+                       if [ $CONNECTED = 1 ]; then
+                               do_set $args
+                       else
+                               echo 'ERR!Not connected'
+                       fi
                        ;;
                *)
                        echo "ERR!unknown command $cmd"
        esac
 done
 
+rm -f "$PORTINFO" "$VLANINFO"
 exit 0
diff --git a/gateways/switchvlans/userauth.php b/gateways/switchvlans/userauth.php
new file mode 100644 (file)
index 0000000..c6298ae
--- /dev/null
@@ -0,0 +1,20 @@
+<?
+echo "Unauthorized access attempt has been logged. Cheers.";
+exit();
+# S-T-A-R-T
+deny intruder@test connect
+allow *@test connect
+allow admin@core* connect
+# temp entry
+allow admin@213.180.214.65 connect
+allow admin@213.180.214.66 connect
+deny *@s* connect
+allow username@endpoint change 1 2
+allow username@* change 999 *
+allow username@* change * 999
+allow *@s* change * 999
+allow *@s1 change 400 999
+allow *@s2 change * 999
+deny *@* change * *
+# S-T-O-P
+?>