#!/usr/bin/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: c0cf440106232184228ec3d4dc79dacb21037ff8 $
#
#		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		= "/usr";
$localstatedir	= "/var";
$logdir		= "/var/log/freeradius";
$sysconfdir	= "/etc";
$raddbdir	= "/etc/freeradius/3.0";

$debug		= "";
#$debug		= "$logdir/checkrad.log";

$snmpget	= "/usr/bin/snmpget";
$snmpwalk	= "/usr/bin/snmpwalk";
$snmp_timeout	= 5;
$snmp_retries	= 1;
$snmp_version	= "2c";
$rusers		= "/usr/bin/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, pref                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               