summaryrefslogtreecommitdiffstats
path: root/src/main/checkrad.in
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/main/checkrad.in1515
1 files changed, 1515 insertions, 0 deletions
diff --git a/src/main/checkrad.in b/src/main/checkrad.in
new file mode 100644
index 0000000..c0cf440
--- /dev/null
+++ b/src/main/checkrad.in
@@ -0,0 +1,1515 @@
+#!@PERL@
+#
+# checkrad See if a user is (still) logged in on a certain port.
+#
+# This is used by the FreeRADIUS server to check
+# if its idea of a user logged in on a certain port/nas
+# is correct if a double login is detected.
+#
+# Called as: nas_type nas_ip nas_port login session_id
+#
+# Returns: 0 = no duplicate, 1 = duplicate, >1 = error.
+#
+# Version: $Id$
+#
+# livingston_snmp 1.2 Author: miquels@cistron.nl
+# cvx_snmp 1.0 Author: miquels@cistron.nl
+# portslave_finger 1.0 Author: miquels@cistron.nl
+# max40xx_finger 1.0 Author: costa@mdi.ca
+# ascend_snmp 1.1 Author: blaz@amis.net
+# computone_finger 1.2 Author: pacman@world.std.com
+# sub tc_tccheck 1.1 Author: alexisv@compass.com.ph
+# cyclades_telnet 1.2 Author: accdias@sst.com.br
+# patton_snmp 1.0 Author: accdias@sst.com.br
+# digitro_rusers 1.1 Author: accdias@sst.com.br
+# cyclades_snmp 1.0 Author: accdias@sst.com.br
+# usrhiper_snmp 1.0 Author: igor@ipass.net
+# juniper_e_snmp 1.1 Author: guilhermefranco@gmail.com
+# multitech_snmp 1.0 Author: ehonzay@willmar.com
+# netserver_telnet 1.0 Author: mts@interplanet.es
+# versanet_snmp 1.0 Author: support@versanetcomm.com
+# bay_finger 1.0 Author: chris@shenton.org
+# cisco_l2tp 1.14 Author: paul@distributel.net
+# mikrotik_telnet 1.1 Author: Evren Yurtesen <yurtesen@ispro.net.tr>
+# mikrotik_snmp 1.0 Author: Evren Yurtesen <yurtesen@ispro.net.tr>
+# redback_telnet Author: Eduardo Roldan
+#
+# Config: $debug is the file you want to put debug messages in
+# $snmpget is the location of your ``snmpget'' program
+# $snmpwalk is the location of your ``snmpwalk'' program
+# $snmp_timeout is the timeout for snmp queries
+# $snmp_retries is the number of retries for timed out snmp queries
+# $snmp_version is the version of to use for snmp queries [1,2c,3]
+# $rusers is the location of your ``rusers'' program
+# $naspass is the location of your NAS admin password file
+#
+
+$prefix = "@prefix@";
+$localstatedir = "@localstatedir@";
+$logdir = "@logdir@";
+$sysconfdir = "@sysconfdir@";
+$raddbdir = "@raddbdir@";
+
+$debug = "";
+#$debug = "$logdir/checkrad.log";
+
+$snmpget = "@SNMPGET@";
+$snmpwalk = "@SNMPWALK@";
+$snmp_timeout = 5;
+$snmp_retries = 1;
+$snmp_version = "2c";
+$rusers = "@RUSERS@";
+$naspass = "$raddbdir/naspasswd";
+
+# Community string. Change this if yours isn't "public".
+$cmmty_string = "public";
+# path to finger command
+$finger = "/usr/bin/finger";
+
+# Extremely slow way of converting port descriptions to actual indexes
+$portisdescr = 0;
+
+# Realm used by Cisco sub
+$realm = '';
+
+#
+# USR-Hiper: $hiper_density is the reported port density (default 256
+# but 24 makes more sense)
+#
+$hiper_density = 256;
+
+#
+# Try to load Net::Telnet, SNMP_Session etc.
+# Do not complain if we cannot find it.
+# Prefer a locally installed copy.
+#
+BEGIN {
+ unshift @INC, "/usr/local/lib/site_perl";
+
+ eval "use Net::Telnet 3.00;";
+ $::HAVE_NET_TELNET = ($@ eq "");
+
+ eval "use SNMP_Session;";
+ if ($@ eq "") {
+ eval "use BER;";
+ $::HAVE_SNMP_SESSION = ($@ eq "");
+ eval "use Socket;";
+ }
+};
+
+#
+# Get password from /etc/raddb/naspasswd file.
+# Returns (login, password).
+#
+sub naspasswd {
+ my ($terminalserver, $emptyok) = @_;
+ my ($login, $password);
+ my ($ts, $log, $pass);
+
+ unless (open(NFD, $naspass)) {
+ if (!$emptyok) {
+ print LOG "checkrad: naspasswd file not found; " .
+ "possible match for $ARGV[3]\n" if ($debug);
+ print STDERR "checkrad: naspasswd file not found; " .
+ "possible match for $ARGV[3]\n";
+ }
+ return ();
+ }
+ while (<NFD>) {
+ chop;
+ next if (m/^(#|$|[\t ]+$)/);
+ ($ts, $log, $pass) = split(/\s+/, $_, 3);
+ if ($ts eq $terminalserver) {
+ $login = $log;
+ $password = $pass;
+ last;
+ }
+ }
+ close NFD;
+ if ($password eq "" && !$emptyok) {
+ print LOG "checkrad: password for $ARGV[1] is null; " .
+ "possible match for $ARGV[3] on " .
+ "port $ARGV[2]\n" if ($debug);
+ print STDERR "checkrad: password for $ARGV[1] is null; " .
+ "possible match for $ARGV[3] on port $ARGV[2]\n";
+ }
+ ($login, $password);
+}
+
+#
+# See if Net::Telnet is there.
+#
+sub check_net_telnet {
+ if (!$::HAVE_NET_TELNET) {
+ print LOG
+ " checkrad: Net::Telnet 3.00+ CPAN module not installed\n"
+ if ($debug);
+ print STDERR
+ "checkrad: Net::Telnet 3.00+ CPAN module not installed\n";
+ return 0;
+ }
+ 1;
+}
+
+#
+# Do snmpwalk by calling snmpwalk.
+#
+sub snmpwalk_prog {
+ my ($host, $community, $oid) = @_;
+ local $_;
+
+ print LOG "snpwalk: $snmpwalk -r $snmp_retries -t $snmp_timeout -v$snmp_version -c '$community' $host $oid\n";
+ $_ = `$snmpwalk -r $snmp_retries -t $snmp_timeout -v$snmp_version -c '$community' $host $oid`;
+
+ return $_;
+}
+
+#
+# Do snmpwalk.
+#
+sub snmpwalk {
+ my $ret;
+
+ if (-x $snmpwalk) {
+ $ret = snmpwalk_prog(@_);
+ } else {
+ $e = "$snmpwalk not found!";
+ print LOG "$e\n" if ($debug);
+ print STDERR "checkrad: $e\n";
+ $ret = "";
+ }
+ $ret;
+}
+
+
+#
+# Do snmpget by calling snmpget.
+#
+sub snmpget_prog {
+ my ($host, $community, $oid) = @_;
+ my ($ret);
+ local $_;
+
+ print LOG "snmpget: $snmpget -r $snmp_retries -t $snmp_timeout -v$snmp_version -c '$community' $host $oid\n";
+ $_ = `$snmpget -r $snmp_retries -t $snmp_timeout -v$snmp_version -c '$community' $host $oid`;
+ if (/^.*(\s|\")([0-9A-Za-z]{8})(\s|\"|$).*$/) {
+ # Session ID format.
+ $ret = $2;
+ } elsif (/^.*=.*"(.*)"/) {
+ # oid = "...." junk format.
+ $ret = $1;
+ } elsif (/^.*=\s*(?:.*:\s*)?(\S+)/) {
+ # oid = string format
+ $ret = $1;
+ }
+
+ # Strip trailing junk if any.
+ $ret =~ s/\s*Hex:.*$//;
+ $ret;
+}
+
+#
+# Do snmpget by using SNMP_Session.
+# Coded by Jerry Workman <jerry@newwave.net>
+#
+sub snmpget_session {
+ my ($host, $community, $OID) = @_;
+ my ($ret);
+ local $_;
+ my (@enoid, $var,$response, $bindings, $binding, $value);
+ my ($inoid, $outoid, $upoid, $oid, @retvals);
+
+ $OID =~ s/^.iso.org.dod.internet.private.enterprises/.1.3.6.1.4.1/;
+
+ push @enoid, encode_oid((split /\./, $OID));
+ srand();
+
+ my $session = SNMP_Session->open($host, $community, 161);
+ if (!$session->get_request_response(@enoid)) {
+ $e = "No SNMP answer from $ARGV[0].";
+ print LOG "$e\n" if ($debug);
+ print STDERR "checkrad: $e\n";
+ return "";
+ }
+ $response = $session->pdu_buffer;
+ ($bindings) = $session->decode_get_response ($response);
+ $session->close ();
+ while ($bindings) {
+ ($binding,$bindings) = decode_sequence ($bindings);
+ ($oid,$value) = decode_by_template ($binding, "%O%@");
+ my $tempo = pretty_print($value);
+ $tempo=~s/\t/ /g;
+ $tempo=~s/\n/ /g;
+ $tempo=~s/^\s+//;
+ $tempo=~s/\s+$//;
+
+ push @retvals, $tempo;
+ }
+ $retvals[0];
+}
+
+#
+# Do snmpget
+#
+sub snmpget {
+ my $ret;
+
+ if ($::HAVE_SNMP_SESSION) {
+ $ret = snmpget_session(@_);
+ } elsif (-x $snmpget) {
+ $ret = snmpget_prog(@_);
+ } else {
+ $e = "Neither SNMP_Session module or $snmpget found!";
+ print LOG "$e\n" if ($debug);
+ print STDERR "checkrad: $e\n";
+ $ret = "";
+ }
+ $ret;
+}
+
+#
+# Get ifindex from description
+#
+sub ifindex {
+ my $port = shift;
+
+ # If its not an integer, portisdescr lies!
+ return $port unless $portisdescr || $port !~ /^[0-9]*$/;
+
+ $_ = snmpwalk($ARGV[1], "$cmmty_string", ".1.3.6.1.2.1.2.2.1.2");
+
+ foreach (split /\n/){
+ if(/\.([0-9]+)\s*=.*$port"?$/){
+ print LOG " port descr $port is at SNMP ifIndex $1\n" if ($debug);
+ return $1;
+ }
+ }
+
+
+ return $port;
+}
+
+#
+# Strip domains, prefixes and suffixes from username
+#
+# Known prefixes: (P)PP, (S)LIP e (C)SLIP
+# Known suffixes: .ppp, .slip e .cslip
+#
+# Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub strip_username {
+ my ($user) = @_;
+ #
+ # Trim white spaces.
+ #
+ $user =~ s/^\s*(.*?)\s*$/$1/;
+ #
+ # Strip out domains, prefix and suffixes
+ #
+ $user =~ s/\@(.)*$//;
+ $user =~ s/^[PSC]//;
+ $user =~ s/\.(ppp|slip|cslip)$//;
+ $user;
+}
+
+#
+# Check whether a session is current on any device which implements the standard IEEE 802.1X MIB
+#
+# Note: Vendors use different formats for the session ID, and it often doesn't map
+# between Acct-Session-ID so can't be used to identify and 802.1X session (we ignore it).
+#
+# If a session matching the username is found on the port specified, and the
+# session is still active then thats good enough...
+#
+# Author: Arran Cudbard-Bell <arran.cudbard-bell@freeradius.org>
+#
+$ieeedot1m = '.iso.0.8802.1.1';
+sub dot1x_snmp {
+ $ifIndex = ifindex($ARGV[2]);
+
+ # User matches and not terminated yet?
+ if(
+ snmpget($ARGV[1], "$cmmty_string", "$ieeedot1m.1.1.2.4.1.9.$ifIndex") eq $ARGV[3] &&
+ snmpget($ARGV[1], "$cmmty_string", "$ieeedot1m.1.1.2.4.1.8.$ifIndex") eq '999'
+ ){
+ print LOG " found user $ARGV[3] at port $ARGV[2] ($ifIndex)" if $debug;
+ return 1;
+ }
+
+ 0;
+}
+
+#
+# See if the user is logged in using the Livingston MIB.
+# We don't check the username but the session ID.
+#
+$lvm = '.iso.org.dod.internet.private.enterprises.307';
+sub livingston_snmp {
+
+ #
+ # We don't know at which ifIndex S0 is, and
+ # there might be a hole at S23, or at S30+S31.
+ # So we figure out dynamically which offset to use.
+ #
+ # If the port < S23, probe ifIndex 5.
+ # If the port < S30, probe IfIndex 23.
+ # Otherwise probe ifIndex 32.
+ #
+ my $ifIndex;
+ my $test_index;
+ if ($ARGV[2] < 23) {
+ $test_index = 5;
+ } elsif ($ARGV[2] < 30) {
+ $test_index = 23;
+ } else {
+ $test_index = 32;
+ }
+ $_ = snmpget($ARGV[1], "$cmmty_string", "$lvm.3.2.1.1.1.2.$test_index");
+ /S([0-9]+)/;
+ $xport = $1 + 0;
+ $ifIndex = $ARGV[2] + ($test_index - $xport);
+
+ print LOG " port S$ARGV[2] at SNMP ifIndex $ifIndex\n"
+ if ($debug);
+
+ #
+ # Now get the session id from the terminal server.
+ #
+ $sessid = snmpget($ARGV[1], "$cmmty_string", "$lvm.3.2.1.1.1.5.$ifIndex");
+
+ print LOG " session id at port S$ARGV[2]: $sessid\n" if ($debug);
+
+ ($sessid eq $ARGV[4]) ? 1 : 0;
+}
+
+#
+# See if the user is logged in using the Aptis MIB.
+# We don't check the username but the session ID.
+#
+# sessionStatusActiveName
+$apm1 = '.iso.org.dod.internet.private.enterprises.2637.2.2.102.1.12';
+# sessionStatusActiveStopTime
+$apm2 = '.iso.org.dod.internet.private.enterprises.2637.2.2.102.1.20';
+sub cvx_snmp {
+
+ # Remove unique identifier, then take remainder of the
+ # session-id as a hex number, convert that to decimal.
+ my $sessid = $ARGV[4];
+ $sessid =~ s/^.*://;
+ $sessid =~ s/^0*//;
+ $sessid = "0" if ($sessid eq '');
+
+ #
+ # Now get the login from the terminal server.
+ # Blech - the SNMP table is called 'sessionStatusActiveTable,
+ # but it sometimes lists inactive sessions too.
+ # However an active session doesn't have a Stop time,
+ # so we can differentiate that way.
+ #
+ my $login = snmpget($ARGV[1], "$cmmty_string", "$apm1." . hex($sessid));
+ my $stopt = snmpget($ARGV[1], "$cmmty_string", "$apm2." . hex($sessid));
+ $login = "--" if ($stopt > 0);
+
+ print LOG " login with session-id $ARGV[4]: $login\n" if ($debug);
+
+ (strip_username($login) eq strip_username($ARGV[3])) ? 1 : 0;
+}
+
+#
+# See if the user is logged in using the Cisco MIB
+#
+$csm = '.iso.org.dod.internet.private.enterprises.9';
+sub cisco_snmp {
+
+ # Look up community string in naspasswd file.
+ my ($login, $pass) = naspasswd($ARGV[1], 1);
+ if ($login eq '') {
+ $pass = $cmmty_string;
+ } elsif ($login ne 'SNMP') {
+ if ($debug) {
+ print LOG
+ " Error: Need SNMP community string for $ARGV[1]\n";
+ }
+ return 2;
+ }
+
+ my $port = $ARGV[2];
+ my $sess_id = hex($ARGV[4]);
+
+ if ($port < 20000) {
+ #
+ # The AS5350 doesn't support polling the session ID,
+ # so we do it based on nas-port-id. This only works
+ # for analog sessions where port < 20000.
+ # Yes, this means that simultaneous-use on the as5350
+ # doesn't work for ISDN users.
+ #
+ $login = snmpget($ARGV[1], $pass, "$csm.2.9.2.1.18.$port");
+ print LOG " user at port S$port: $login\n" if ($debug);
+ } else {
+ $login = snmpget($ARGV[1], $pass,
+ "$csm.9.150.1.1.3.1.2.$sess_id");
+ print LOG " user with session id $ARGV[4] ($sess_id): " .
+ "$login\n" if ($debug);
+ }
+
+ # ($login eq $ARGV[3]) ? 1 : 0;
+ if($login eq $ARGV[3]) {
+ return 1;
+ }else{
+ $out=snmpwalk($ARGV[1],$pass,".iso.org.dod.internet.private.enterprises.9.10.19.1.3.1.1.3");
+ if($out=~/\"$ARGV[3]\"/){
+ return 1;
+ }else{
+ return 0;
+ }
+ }
+}
+
+#
+# Check the subscriber name on a Juniper JunosE E-Series BRAS (ERX, E120, E320). Requires "radius acct-session-id-format decimal" configuration in the BRAS.
+#
+# Author: Guilherme Franco <guilhermefranco@gmail.com>
+#
+sub juniper_e_snmp {
+ #receives acct_session
+ my $temp = $ARGV[4];
+ #removes the leading 0s
+ my $clean_temp = int $temp;
+
+ $out=snmpget($ARGV[1], $cmmty_string, ".1.3.6.1.4.1.4874.2.2.20.1.8.4.1.2.$clean_temp");
+ if($out=~/\"$ARGV[3]\"/){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
+#
+# Check a MultiTech CommPlete Server ( CC9600 & CC2400 )
+#
+# Author: Eric Honzay of Bennett Office Products <ehonzay@willmar.com>
+#
+$msm = '.iso.org.dod.internet.private.enterprises.995';
+sub multitech_snmp {
+ my $temp = $ARGV[2] + 1;
+
+ $login = snmpget($ARGV[1], "$cmmty_string", "$msm.2.31.1.1.1.$temp");
+ print LOG " user at port S$ARGV[2]: $login\n" if ($debug);
+
+ ($login eq $ARGV[3]) ? 1 : 0;
+}
+
+#
+# Check a Computone Powerrack via finger
+#
+# Old Author: Shiloh Costa of MDI Internet Inc. <costa@mdi.ca>
+# New Author: Alan Curry <pacman@world.std.com>
+#
+# The finger response format is version-dependent. To do this *right*, you
+# need to know exactly where the port number and username are. I know that
+# for 1.7.2, and 3.0.4 but for others I just guess.
+# Oh yeah and on top of it all, the thing truncates usernames. --Pac.
+#
+# 1.7.2 and 3.0.4 both look like this:
+#
+# 0 0 000 00:56 luser pppfsm Incoming PPP, ppp00, 10.0.0.1
+#
+# and the truncated ones look like this:
+#
+# 25 0 000 00:15 longnameluse..pppfsm Incoming PPP, ppp25, 10.0.0.26
+#
+# Yes, the fields run together. Long Usernames Considered Harmful.
+#
+sub computone_finger {
+ my $trunc, $ver;
+
+ open(FD, "$finger \@$ARGV[1]|") or return 2;
+ <FD>; # the [hostname] line is definitely uninteresting
+ $trunc = substr($ARGV[3], 0, 12);
+ $ver = "";
+ while(<FD>) {
+ if(/cnx kernel release ([^ ,]+)[, ]/) {
+ $ver = $1;
+ next;
+ }
+ # Check for known versions
+ if ($ver eq '1.7.2' || $ver eq '3.0.4') {
+ if (/^\Q$ARGV[2]\E\s+\S+\s+\S+\s+\S+\s+\Q$trunc\E(\s+|\.\.)/) {
+ close FD;
+ return 1;
+ }
+ next;
+ }
+ # All others.
+ if (/^\s*\Q$ARGV[2]\E\s+.*\s+\Q$trunc\E\s+/) {
+ close FD;
+ return 1;
+ }
+ }
+
+ close FD;
+ return 0;
+}
+
+#
+# Check an Ascend Max4000 or similar model via finger
+#
+# Note: Not all software revisions support finger
+# You may also need to enable the finger option.
+#
+# Author: Shiloh Costa of MDI Internet Inc. <costa@mdi.ca>
+#
+sub max40xx_finger {
+ open(FD, "$finger $ARGV[3]\@$ARGV[1]|");
+ while(<FD>) {
+ $line = $_;
+ if( $line =~ /Session/ ){
+ next;
+ }
+
+ if( $line =~ /$ARGV[4]/ ){
+ return 1; # user is online
+ }
+ }
+ close FD;
+ return 0; # user is offline
+}
+
+
+#
+# Check an Ascend Max4000 or similar model via SNMP
+#
+# Author: Blaz Zupan of Medinet <blaz@amis.net>
+#
+$asm = '.iso.org.dod.internet.private.enterprises.529';
+sub ascend_snmp {
+ my $sess_id;
+ my $l1, $l2;
+
+ $l1 = '';
+ $l2 = '';
+
+ #
+ # If it looks like hex, only try it as hex,
+ # otherwise try it as both decimal and hex.
+ #
+ $sess_id = $ARGV[4];
+ if ($sess_id !~ /^0/ && $sess_id !~ /[a-f]/i) {
+ $l1 = snmpget($ARGV[1], "$cmmty_string", "$asm.12.3.1.4.$sess_id");
+ }
+ if (!$l1){
+ $sess_id = hex $ARGV[4];
+ $l2 = snmpget($ARGV[1], "$cmmty_string", "$asm.12.3.1.4.$sess_id");
+ }
+
+ print LOG " user at port S$ARGV[2]: $l1 (dec)\n" if ($debug && $l1);
+ print LOG " user at port S$ARGV[2]: $l2 (hex)\n" if ($debug && $l2);
+
+ (($l1 && $l1 eq $ARGV[3]) || ($l2 && $l2 eq $ARGV[3])) ? 1 : 0;
+}
+
+
+#
+# See if the user is logged in using the portslave finger.
+#
+sub portslave_finger {
+ my ($Port_seen);
+
+ $Port_seen = 0;
+
+ open(FD, "$finger \@$ARGV[1]|");
+ while(<FD>) {
+ #
+ # Check for ^Port. If we don't see it we
+ # wont get confused by non-portslave-finger
+ # output too.
+ #
+ if (/^Port/) {
+ $Port_seen++;
+ next;
+ }
+ next if (!$Port_seen);
+ next if (/^---/);
+
+ ($port, $user) = /^.(...) (...............)/;
+
+ $port =~ s/ .*//;
+ $user =~ s/ .*//;
+ $ulen = length($user);
+ #
+ # HACK: strip [PSC] from the front of the username,
+ # and things like .ppp from the end.
+ #
+ $user =~ s/^[PSC]//;
+ $user =~ s/\.(ppp|slip|cslip)$//;
+
+ #
+ # HACK: because ut_user usually has max. 8 characters
+ # we only compare up the the length of $user if the
+ # unstripped name had 8 chars.
+ #
+ $argv_user = $ARGV[3];
+ if ($ulen == 8) {
+ $ulen = length($user);
+ $argv_user = substr($ARGV[3], 0, $ulen);
+ }
+
+ if ($port == $ARGV[2]) {
+ if ($user eq $argv_user) {
+ print LOG " $user matches $argv_user " .
+ "on port $port" if ($debug);
+ close FD;
+ return 1;
+ } else {
+ print LOG " $user doesn't match $argv_user " .
+ "on port $port" if ($debug);
+ close FD;
+ return 0;
+ }
+ }
+ }
+ close FD;
+ 0;
+}
+
+#
+# See if the user is already logged-in at the 3Com/USR Total Control.
+# (this routine by Alexis C. Villalon <alexisv@compass.com.ph>).
+# You must have the Net::Telnet module from CPAN for this to work.
+# You must also have your /etc/raddb/naspasswd made up.
+#
+sub tc_tccheck {
+ #
+ # Localize all variables first.
+ #
+ my ($Port_seen, $ts, $terminalserver, $log, $login, $pass, $password);
+ my ($telnet, $curprompt, $curline, $ok, $totlines, $ccntr);
+ my (@curlines, @cltok, $user, $port, $ulen);
+
+ return 2 unless (check_net_telnet());
+
+ $terminalserver = $ARGV[1];
+ $Port_seen = 0;
+ #
+ # Get login name and password for a certain NAS from $naspass.
+ #
+ ($login, $password) = naspasswd($terminalserver, 1);
+ return 2 if ($password eq "");
+
+ #
+ # Communicate with NAS using Net::Telnet, then issue
+ # the command "show sessions" to see who are logged in.
+ # Thanks to Chris Jackson <chrisj@tidewater.net> for the
+ # for the "-- Press Return for More --" workaround.
+ #
+ $telnet = new Net::Telnet (Timeout => 5,
+ Prompt => '/\>/');
+ $telnet->open($terminalserver);
+ $telnet->login($login, $password);
+ $telnet->print("show sessions");
+ while ($curprompt ne "\>") {
+ ($curline, $curprompt) = $telnet->waitfor
+ (String => "-- Press Return for More --",
+ String => "\>",
+ Timeout => 5);
+ $ok = $telnet->print("");
+ push @curlines, split(/^/m, $curline);
+ }
+ $telnet->close;
+ #
+ # Telnet closed. We got the info. Let's examine it.
+ #
+ $totlines = @curlines;
+ $ccntr = 0;
+ while($ccntr < $totlines) {
+ #
+ # Check for ^Port.
+ #
+ if ($curlines[$ccntr] =~ /^Port/) {
+ $Port_seen++;
+ $ccntr++;
+ next;
+ }
+ #
+ # Ignore all unnecessary lines.
+ #
+ if (!$Port_seen || $curlines[$ccntr] =~ /^---/ ||
+ $curlines[$ccntr] =~ /^ .*$/) {
+ $ccntr++;
+ next;
+ }
+ #
+ # Parse the current line for the port# and username.
+ #
+ @cltok = split(/\s+/, $curlines[$ccntr]);
+ $ccntr++;
+ $port = $cltok[0];
+ $user = $cltok[1];
+ $ulen = length($user);
+ #
+ # HACK: strip [PSC] from the front of the username,
+ # and things like .ppp from the end. Strip S from
+ # the front of the port number.
+ #
+ $user =~ s/^[PSC]//;
+ $user =~ s/\.(ppp|slip|cslip)$//;
+ $port =~ s/^S//;
+ #
+ # HACK: because "show sessions" shows max. 15 characters
+ # we only compare up to the length of $user if the
+ # unstripped name had 15 chars.
+ #
+ $argv_user = $ARGV[3];
+ if ($ulen == 15) {
+ $ulen = length($user);
+ $argv_user = substr($ARGV[3], 0, $ulen);
+ }
+ if ($port == $ARGV[2]) {
+ if ($user eq $argv_user) {
+ print LOG " $user matches $argv_user " .
+ "on port $port" if ($debug);
+ return 1;
+ } else {
+ print LOG " $user doesn't match $argv_user " .
+ "on port $port" if ($debug);
+ return 0;
+ }
+ }
+ }
+ 0;
+}
+
+#
+# Check a Cyclades PathRAS via telnet
+#
+# Version: 1.2
+#
+# Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub cyclades_telnet {
+ #
+ # Localize all variables first.
+ #
+ my ($pr, $pr_login, $pr_passwd, $pr_prompt, $endlist, @list, $port, $user);
+ #
+ # This variable must match PathRAS' command prompt
+ # string as entered in menu option 6.2.
+ # The value below matches the default command prompt.
+ #
+ $pr_prompt = '/Select option ==\>$/i';
+
+ #
+ # This variable match the end of userslist.
+ #
+ $endlist = '/Type \<enter\>/i';
+
+ #
+ # Do we have Net::Telnet installed?
+ #
+ return 2 unless (check_net_telnet());
+
+ #
+ # Get login name and password for NAS
+ # from $naspass file.
+ #
+ ($pr_login, $pr_passwd) = naspasswd($ARGV[1], 1);
+
+ #
+ # Communicate with PathRAS using Net::Telnet, then access
+ # menu option 6.8 to see who are logged in.
+ # Based on PathRAS firmware version 1.2.3
+ #
+ $pr = new Net::Telnet (
+ Timeout => 5,
+ Host => $ARGV[1],
+ ErrMode => 'return'
+ ) || return 2;
+
+ #
+ # Force PathRAS shows its banner.
+ #
+ $pr->break();
+
+ #
+ # Log on PathRAS
+ #
+ if ($pr->waitfor(Match => '/login : $/i') == 1) {
+ $pr->print($pr_login);
+ } else {
+ print LOG " Error: sending login name to PathRAS\n" if ($debug);
+ $pr->close;
+ return 2;
+ }
+
+ if ($pr->waitfor(Match => '/password : $/i') == 1) {
+ $pr->print($pr_passwd);
+ } else {
+ print LOG " Error: sending password to PathRAS.\n" if ($debug);
+ $pr->close;
+ return 2;
+ }
+
+ $pr->print();
+
+ #
+ # Access menu option 6 "PathRAS Management"
+ #
+ if ($pr->waitfor(Match => $pr_prompt) == 1) {
+ $pr->print('6');
+ } else {
+ print LOG " Error: accessing menu option '6'.\n" if ($debug);
+ $pr->close;
+ return 2;
+ }
+ #
+ # Access menu option 8 "Show Active Ports"
+ #
+ if ($pr->waitfor(Match => $pr_prompt) == 1) {
+ @list = $pr->cmd(String => '8', Prompt => $endlist);
+ } else {
+ print LOG " Error: accessing menu option '8'.\n" if ($debug);
+ $pr->close;
+ return 2;
+ }
+ #
+ # Since we got the info we want, let's close
+ # the telnet session
+ #
+ $pr->close;
+
+ #
+ # Lets examine the userlist stored in @list
+ #
+ foreach(@list) {
+ #
+ # We are interested in active sessions only
+ #
+ if (/Active/i) {
+ ($port, $user) = split;
+ #
+ # Strip out any prefix, suffix and
+ # realm from $user check to see if
+ # $ARGV[3] matches.
+ #
+ if(strip_username($ARGV[3]) eq strip_username($user)) {
+ print LOG " User '$ARGV[3]' found on '$ARGV[1]:$port'.\n" if ($debug);
+ return 1;
+ }
+ }
+ }
+ print LOG " User '$ARGV[3]' not found on '$ARGV[1]'.\n" if ($debug);
+ 0;
+}
+
+#
+# Check a Patton 2800 via SNMP
+#
+# Version: 1.0
+#
+# Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub patton_snmp {
+ my($oid);
+
+ #$oid = '.1.3.6.1.4.1.1768.5.100.1.40.' . hex $ARGV[4];
+ # Reported by "Andria Legon" <andria@patton.com>
+ # The OID below should be the correct one instead of the one above.
+ $oid = '.1.3.6.1.4.1.1768.5.100.1.56.' . hex $ARGV[4];
+ #
+ # Check if the session still active
+ #
+ if (snmpget($ARGV[1], "monitor", "$oid") == 0) {
+ print LOG " Session $ARGV[4] still active on NAS " .
+ "$ARGV[1], port $ARGV[2], for user $ARGV[3].\n" if ($debug);
+ return 1;
+ }
+ 0;
+}
+
+#
+# Check a Digitro BXS via rusers
+#
+# Version: 1.1
+#
+# Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub digitro_rusers {
+ my ($ret);
+ local $_;
+
+ if (-e $rusers && -x $rusers) {
+ #
+ # Get a list of users logged in via rusers
+ #
+ $_ = `$rusers $ARGV[1]`;
+ $ret = ((/$ARGV[3]/) ? 1 : 0);
+ } else {
+ print LOG " Error: can't execute $rusers\n" if $debug;
+ $ret = 2;
+ }
+ $ret;
+}
+
+#
+# Check Cyclades PR3000 and PR4000 via SNMP
+#
+# Version: 1.0
+#
+# Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub cyclades_snmp {
+ my ($oid, $ret);
+ local $_;
+
+ $oid = ".1.3.6.1.4.1.2925.3.3.6.1.1.2";
+
+ $_ = snmpwalk($ARGV[1],"$cmmty_string",$oid);
+ $ret = ((/$ARGV[3]/) ? 1 : 0);
+ $ret;
+}
+
+#
+# 3Com/USR HiPer Arc Total Control.
+# This works with HiPer Arc 4.0.30
+# (this routine by Igor Brezac <igor@ipass.net>)
+#
+
+# This routine modified by Dan Halverson <danh@tbc.net>
+# to support additional versions of Hiper Arc
+#
+
+$usrm = '.iso.org.dod.internet.private.enterprises.429';
+sub usrhiper_snmp {
+ my ($login,$password,$oidext);
+
+ # Look up community string in naspasswd file.
+ ($login, $password) = naspasswd($ARGV[1], 1);
+ if ($login && $login ne 'SNMP') {
+ if($debug) {
+ print LOG
+ " Error: Need SNMP community string for $ARGV[1]\n";
+ }
+ return 2;
+ } else {
+# If password is defined in naspasswd file, use it as community, otherwise use $cmmty_string
+ if ($password eq '') {
+ $password = "$cmmty_string";
+ }
+ }
+ my ($ver) = get_hiper_ver(usrm=>$usrm, target=>$ARGV[1], community=>$password);
+ $oidext = get_oidext(ver=>$ver, tty=>$ARGV[2]);
+ my ($login);
+
+ $login = snmpget($ARGV[1], $password, "$usrm.4.10.1.1.18.$oidext");
+ if ($login =~ /\"/) {
+ $login =~ /^.*\"([^"]+)\"/;
+ $login = $1;
+ }
+
+ print LOG " user at port S$ARGV[2]: $login\n" if ($debug);
+
+ ($login eq $ARGV[3]) ? 1 : 0;
+}
+
+#
+# get_hiper_ver and get_oidext by Dan Halverson <danh@tbc.net>
+#
+sub get_hiper_ver {
+ my (%args) = @_;
+ my ($ver
+ );
+ $ver = snmpget ($args{'target'}, $args{'community'}, $args{'usrm'}.".4.1.14.0");
+ return($ver);
+}
+
+#
+# Add additional OID checks below before the else.
+# Else is for 4.0.30
+#
+sub get_oidext {
+ my (%args) = @_;
+ my ($oid
+ );
+ if ($args{'ver'} =~ /V5.1.99/) {
+ $oid = $args{'tty'}+1257-1;
+ }
+ else {
+ $oid = 1257 + 256*int(($args{'tty'}-1) / $hiper_density) +
+ (($args{'tty'}-1) % $hiper_density);
+ }
+ return($oid);
+}
+
+#
+# Check USR Netserver with Telnet - based on tc_tccheck.
+# By "Marti" <mts@interplanet.es>
+#
+sub usrnet_telnet {
+ #
+ # Localize all variables first.
+ #
+ my ($ts, $terminalserver, $login, $password);
+ my ($telnet, $curprompt, $curline, $ok);
+ my (@curlines, $user, $port);
+
+ return 2 unless (check_net_telnet());
+
+ $terminalserver = $ARGV[1];
+ $Port_seen = 0;
+ #
+ # Get login name and password for a certain NAS from $naspass.
+ #
+ ($login, $password) = naspasswd($terminalserver, 1);
+ return 2 if ($password eq "");
+
+ #
+ # Communicate with Netserver using Net::Telnet, then access
+ # list connectionsto see who are logged in.
+ #
+ $telnet = new Net::Telnet (Timeout => 5,
+ Prompt => '/\>/');
+ $telnet->open($terminalserver);
+
+ #
+ # Log on Netserver
+ #
+ $telnet->login($login, $password);
+
+ #
+ # Launch list connections command
+
+ $telnet->print("list connections");
+
+ while ($curprompt ne "\>") {
+ ($curline, $curprompt) = $telnet->waitfor
+ ( String => "\>",
+ Timeout => 5);
+ $ok = $telnet->print("");
+ push @curlines, split(/^/m, $curline);
+ }
+
+ $telnet->close;
+ #
+ # Telnet closed. We got the info. Let's examine it.
+ #
+ foreach(@curlines) {
+ if ( /mod\:/ ) {
+ ($port, $user, $dummy) = split;
+ #
+ # Strip out any prefixes and suffixes
+ # from the username
+ #
+ # uncomment this if you use the standard
+ # prefixes
+ #$user =~ s/^[PSC]//;
+ #$user =~ s/\.(ppp|slip|cslip)$//;
+ #
+ # Check to see if $user is already connected
+ #
+ if ($user eq $ARGV[3]) {
+ print LOG " $user matches $ARGV[3] " .
+ "on port $port" if ($debug);
+ return 1;
+ };
+ };
+ };
+ print LOG
+ " $ARGV[3] not found on Netserver logged users list " if ($debug);
+ 0;
+}
+
+#
+# Versanet's Perl Script Support:
+#
+# ___ versanet_snmp 1.0 by support@versanetcomm.com ___ July 1999
+# Versanet Enterprise MIB Base: 1.3.6.1.4.1.2180
+#
+# VN2001/2002 use slot/port number to locate modems. To use snmp get we
+# have to translate the original port number into a slot/port pair.
+#
+$vsm = '.iso.org.dod.internet.private.enterprises.2180';
+sub versanet_snmp {
+
+ print LOG "argv[2] = $ARGV[2] " if ($debug);
+ $port = $ARGV[2]%8;
+ $port = 8 if ($port eq 0);
+ print LOG "port = $port " if ($debug);
+ $slot = (($ARGV[2]-$port)/8)+1;
+ print LOG "slot = $slot" if ($debug);
+ $loginname = snmpget($ARGV[1], "$cmmty_string", "$vsm.27.1.1.3.$slot.$port");
+#
+# Note: the "$cmmty_string" string above could be replaced by the public
+# community string defined in Versanet VN2001/VN2002.
+#
+ print LOG " user at slot $slot port $port: $loginname\n" if ($debug); ($loginname eq $ARGV[3]) ? 1 : 0;
+}
+
+
+# 1999/08/24 Chris Shenton <chris@shenton.org>
+# Check Bay8000 NAS (aka: Annex) using finger.
+# Returns from "finger @bay" like:
+# Port What User Location When Idle Address
+# asy2 PPP bill --- 9:33am :08 192.0.2.194
+# asy4 PPP hillary --- 9:36am :04 192.0.2.195
+# [...]
+# But also returns partial-match users if you say like "finger g@bay":
+# Port What User Location When Idle Address
+# asy2 PPP gore --- 9:33am :09 192.0.2.194
+# asy22 PPP gwbush --- Mon 9:19am :07 192.0.2.80
+# So check exact match of username!
+
+sub bay_finger { # ARGV: 1=nas_ip, 2=nas_port, 3=login, 4=sessid
+ open(FINGER, "$finger $ARGV[3]\@$ARGV[1]|") || return 2; # error
+ while(<FINGER>) {
+ my ($Asy, $PPP, $User) = split;
+ if( $User =~ /^$ARGV[3]$/ ){
+ close FINGER;
+ print LOG "checkrad:bay_finger: ONLINE $ARGV[3]\@$ARGV[1]"
+ if ($debug);
+ return 1; # online
+ }
+ }
+ close FINGER;
+ print LOG "checkrad:bay_finger: offline $ARGV[3]\@$ARGV[1]" if ($debug);
+ return 0; # offline
+}
+
+#
+# Cisco L2TP support
+# This is for PPP sessions coming from an L2TP tunnel from a Dial
+# or DSL wholesale provider
+# Paul Khavkine <paul@distributel.net>
+# July 19 2001
+#
+# find_l2tp_login() walks a part of cisco vpdn tree to find out what session
+# and tunnel ID's are for a given Virtual-Access interface to construct
+# the following OID: .1.3.6.1.4.1.9.10.24.1.3.2.1.2.2.$tunID.$sessID
+# Then gets the username from that OID.
+# Make sure you set the $realm variable at the begining of the file if
+# needed. The new type for naslist is cisco_l2tp
+
+sub find_l2tp_login
+{
+ my($host, $community, $port_num) = @_;
+ my $l2tp_oid = '.1.3.6.1.4.1.9.10.24.1.3.2.1.2.2';
+ my $port_oid = '.iso.org.dod.internet.private.enterprises.9.10.51.1.2.1.1.2.2';
+ my $port = 'Vi' . $port_num;
+
+ my $sess = new SNMP::Session(DestHost => $host, Community => $community);
+ my $snmp_var = new SNMP::Varbind(["$port_oid"]);
+ my $val = $sess->getnext($snmp_var);
+
+ do
+ {
+ $sess->getnext($snmp_var);
+ } until ($snmp_var->[$SNMP::Varbind::val_f] =~ /$port/) ||
+ (!($snmp_var->[$SNMP::Varbind::ref_f] =~ /^$port_oid\.(\d+)\.(\d+)$/)) ||
+ ($sess->{ErrorNum});
+
+ my $val1 = $snmp_var->[$SNMP::Varbind::ref_f];
+
+ if ($val1 =~ /^$port_oid/) {
+ $result = substr($val1, length($port_oid));
+ $result =~ /^\.(\d+)\.(\d+)$/;
+ $tunID = $1;
+ $sessID = $2;
+ }
+
+ my $snmp_var1 = new SNMP::Varbind(["$l2tp_oid\.$tunID\.$sessID"]);
+ $val = $sess->get($snmp_var1);
+ my $login = $snmp_var1->[$SNMP::Varbind::val_f];
+
+ return $login;
+}
+
+sub cisco_l2tp_snmp
+{
+ my $login = find_l2tp_login("$ARGV[1]", $cmmty_string, "$ARGV[2]");
+ print LOG " user at port S$ARGV[2]: $login\n" if ($debug);
+ ($login eq "$ARGV[3]\@$realm") ? 1 : 0;
+}
+
+sub mikrotik_snmp {
+
+ # Set SNMP version
+ # MikroTik only supports version 1
+ $snmp_version = "1";
+
+ # Look up community string in naspasswd file.
+ ($login, $password) = naspasswd($ARGV[1], 1);
+ if ($login && $login ne 'SNMP') {
+ if($debug) {
+ print LOG "Error: Need SNMP community string for $ARGV[1]\n";
+ }
+ return 2;
+ } else {
+ # If password is defined in naspasswd file, use it as community,
+ # otherwise use $cmmty_string
+ if ($password eq '') {
+ $password = "$cmmty_string";
+ }
+ }
+
+ # We want mtxrInterfaceStatsName from MIKROTIK-MIB
+ $oid = "1.3.6.1.4.1.14988.1.1.14.1.1.2";
+
+ # Mikrotik doesnt give port IDs correctly to RADIUS :(
+ # practically this would limit us to a simple only-one user limit for
+ # this script to work properly.
+ @output = snmpwalk_prog($ARGV[1], $password, "$oid");
+
+ foreach $line ( @output ) {
+ #remove newline
+ chomp $line;
+ #remove trailing whitespace
+ ($line = $line) =~ s/\s+$//;
+ if( $line =~ /<.*-$ARGV[3]>/ ) {
+ $username_seen++;
+ }
+ }
+
+ #lets return something
+ if ($username_seen > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+sub mikrotik_telnet {
+ # Localize all variables first.
+ my ($t, $login, $password);
+ my (@fields, @output, $output, $username_seen, $user);
+
+ return 2 unless (check_net_telnet());
+
+ $terminalserver = $ARGV[1];
+ $user = $ARGV[3];
+
+ # Get login name and password for a certain NAS from $naspass.
+ ($login, $password) = naspasswd($terminalserver, 1);
+ return 2 if ($password eq "");
+
+ # MikroTik routeros doesnt tell us to which port the user is connected
+ # practically this would limit us to a simple only-one user limit for
+ # this script to work properly.
+ $t = new Net::Telnet (Timeout => 5,
+ Prompt => '//\[.*@.*\] > /');
+
+ # Dont just exit when there is error
+ $t->errmode('return');
+
+ # Telnet to terminal server
+ $t->open($terminalserver) or return 2;
+
+ #Send login and password etc.
+ $t->login(Name => $login,
+ Password => $password,
+ # We must detect if we are logged in from the login banner.
+ # Because if routeros is with a free license the command
+ # prompt dont come. Instead it waits us to press "Enter".
+ Prompt => '/MikroTik/');
+
+ # Just be sure that routeros isn't waiting for us to press "Enter"
+ $t->print("");
+
+ # Wait for the real prompt
+ $t->waitfor('/\[.*@.*\] > /');
+
+ # It is not possible to get the line numbers etc.
+ # Thus we cant support if simultaneous-use is over 1
+ # At least I was using pppoe so it wasnt possible.
+ $t->print('ppp active print column name detail');
+
+ # Somehow routeros echo'es our commands 2 times. We dont want to mix
+ # this with the real command prompt.
+ $t->waitfor('/\[.*@.*\] > ppp active print column name detail/');
+
+ # Now lets get the list of online ppp users.
+ ( $output ) = $t->waitfor('/\[.*@.*\] > /');
+
+ # For debugging we can print the list to stdout
+# print $output;
+
+ #Lets logout to make everybody happy.
+ #If we close the connection without logging out then routeros
+ #starts to complain after a while. Saying;
+ #telnetd: All network ports in use.
+ $t->print("quit");
+ $t->close;
+
+ #check for # of $user in output
+ #the output includes only one = between name and username so we can
+ #safely use it as a seperator.
+
+#disabled until mikrotik starts to send newline after each line...
+# @output = $output;
+# foreach $line ( @output ) {
+# #remove newline
+# chomp $line;
+# #remove trailing whitespace
+# ($line = $line) =~ s/\s+$//;
+# if( $line =~ /name=/ ) {
+# print($line);
+# @fields = split( /=/, $line );
+# if( $fields[1] == "\"$user\"") {
+# $username_seen++;
+# }
+# }
+# }
+
+ if( $output =~ /name="$user"/ ) {
+ $username_seen++;
+ }
+
+ #lets return something
+ if ($username_seen > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+sub redback_telnet {
+ #Localize all variables first.
+ my ($terminalserver, $login, $password);
+ my ($user, $context, $operprompt, $adminprompt, $t);
+ return 2 unless (check_net_telnet());
+ $terminalserver = $ARGV[1];
+ ($user, $context) = split /@/, $ARGV[3];
+ if (not $user) {
+ print LOG " Error: No user defined\n" if ($debug);
+ return 2;
+ }
+ if (not $context) {
+ print LOG " Error: No context defined\n" if ($debug);
+ return 2;
+ }
+
+ # Get loggin information
+ ($root, $password) = naspasswd($terminalserver, 1);
+ return 2 if ($password eq "");
+
+ $operprompt = '/\[.*\].*>$/';
+ $adminprompt = '/\[.*\].*#$/';
+
+ # Logging to the RedBack NAS
+ $t = new Net::Telnet (Timeout => 5, Prompt => $operprompt);
+ $t->input_log("./debug");
+ $t->open($terminalserver);
+ $t->login($root, $password);
+
+ #Enable us
+ $t->print('ena');
+ $t->waitfor('/Password/');
+ $t->print($password);
+ $t->waitfor($adminprompt);
+ $t->prompt($adminprompt);
+
+ #Switch context
+ $t->cmd(String => "context $context");
+
+ #Ask the question
+ @lines = $t->cmd(String => "show subscribers active $user\@$context");
+ if ($lines[0] =~ /subscriber $user\@$context/ ) {
+ return 1;
+ }
+ return 0;
+}
+
+###############################################################################
+
+# Poor man's getopt (for -d)
+if ($ARGV[0] eq '-d') {
+ shift @ARGV;
+ $debug = "stdout";
+}
+
+if ($debug) {
+ if ($debug eq 'stdout') {
+ open(LOG, ">&STDOUT");
+ } elsif ($debug eq 'stderr') {
+ open(LOG, ">&STDERR");
+ } else {
+ open(LOG, ">>$debug");
+ $now = localtime;
+ print LOG "$now checkrad @ARGV\n";
+ }
+}
+
+if ($#ARGV != 4) {
+ print LOG "Usage: checkrad nas_type nas_ip " .
+ "nas_port login session_id\n" if ($debug);
+ print STDERR "Usage: checkrad nas_type nas_ip " .
+ "nas_port login session_id\n"
+ unless ($debug =~ m/^(stdout|stderr)$/);
+ close LOG if ($debug);
+ exit(2);
+}
+
+if ($ARGV[0] eq 'livingston') {
+ $ret = &livingston_snmp;
+} elsif ($ARGV[0] eq 'cisco') {
+ $ret = &cisco_snmp;
+} elsif ($ARGV[0] eq 'cvx') {
+ $ret = &cvx_snmp;
+} elsif ($ARGV[0] eq 'juniper') {
+ $ret = &juniper_e_snmp;
+} elsif ($ARGV[0] eq 'multitech') {
+ $ret = &multitech_snmp;
+} elsif ($ARGV[0] eq 'computone') {
+ $ret = &computone_finger;
+} elsif ($ARGV[0] eq 'max40xx') {
+ $ret = &max40xx_finger;
+} elsif ($ARGV[0] eq 'ascend' || $ARGV[0] eq 'max40xx_snmp') {
+ $ret = &ascend_snmp;
+} elsif ($ARGV[0] eq 'portslave') {
+ $ret = &portslave_finger;
+} elsif ($ARGV[0] eq 'tc') {
+ $ret = &tc_tccheck;
+} elsif ($ARGV[0] eq 'pathras') {
+ $ret = &cyclades_telnet;
+} elsif ($ARGV[0] eq 'pr3000') {
+ $ret = &cyclades_snmp;
+} elsif ($ARGV[0] eq 'pr4000') {
+ $ret = &cyclades_snmp;
+} elsif ($ARGV[0] eq 'patton') {
+ $ret = &patton_snmp;
+} elsif ($ARGV[0] eq 'digitro') {
+ $ret = &digitro_rusers;
+} elsif ($ARGV[0] eq 'usrhiper') {
+ $ret = &usrhiper_snmp;
+} elsif ($ARGV[0] eq 'netserver') {
+ $ret = &usrnet_telnet;
+} elsif ($ARGV[0] eq 'versanet') {
+ $ret = &versanet_snmp;
+} elsif ($ARGV[0] eq 'bay') {
+ $ret = &bay_finger;
+} elsif ($ARGV[0] eq 'cisco_l2tp'){
+ $ret = &cisco_l2tp_snmp;
+} elsif ($ARGV[0] eq 'mikrotik'){
+ $ret = &mikrotik_telnet;
+} elsif ($ARGV[0] eq 'mikrotik_snmp'){
+ $ret = &mikrotik_snmp;
+} elsif ($ARGV[0] eq 'redback'){
+ $ret = &redback_telnet;
+} elsif ($ARGV[0] eq 'dot1x'){
+ $ret = &dot1x_snmp;
+} elsif ($ARGV[0] eq 'other') {
+ $ret = 1;
+} else {
+ print LOG " checkrad: unknown NAS type $ARGV[0]\n" if ($debug);
+ print STDERR "checkrad: unknown NAS type $ARGV[0]\n";
+ $ret = 2;
+}
+
+if ($debug) {
+ $mn = "login ok";
+ $mn = "double detected" if ($ret == 1);
+ $mn = "error detected" if ($ret == 2);
+ print LOG " Returning $ret ($mn)\n";
+ close LOG;
+}
+
+exit($ret);