📄 checkrad.pl.in
字号:
#!@PERL@## checkrad.pl 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: checkrad.pl.in,v 1.33 2004/05/01 09:32:14 phampson Exp $## 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# 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";## 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+)/) { # 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;}## 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;}## 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 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;}#
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -