freeradius-client/login.example

245 lines
6.5 KiB
Perl

#!/usr/bin/perl
#
# Sample login-Script for use with radlogin
#
# Copyright (c) 1998 S.u.S.E. GmbH Fuerth, Germany.
#
# please send bugfixes or comments to feedback@suse.de.
#
# derived partly from login.radius/migs/login.radius
# currently does not do anything useful - for testing purposes only
# It only sets up Accounting for a simple Rlogin-User
#
# You can install this is /usr/sbin/login.radius for testing with
# radlogin
use strict;
# Programs and files.
my $prog_radacct = "/usr/bin/radacct";
my $prog_rlogin = "/usr/bin/rlogin";
my $prog_telnet = "/usr/bin/telnet";
my $prog_tcpclear = "/usr/bin/telnet -e ''";
my $prog_tty = "/usr/bin/tty";
my $prog_who = "/usr/bin/who";
my $debug = 1;
my $path_radiusclient_map = "/etc/radclient/port-id-map";
my $login_host = "0.0.0.0";
#############################################################################
# Main program.
print "Starting.\n" if ($debug);
# Run 'who am i' to determine the current port.
my $port = `$prog_tty`;
chomp ($port);
# Translate port numbers to numbers for RADIUS.
# This translation is done again by radacct, but it may be useful here.
# Remove if CPU time is a problem.
my ($portid, $line);
open (H, $path_radiusclient_map);
while (($line = <H>) && (!$portid))
{
my @info = split (/\s+/, $line);
$portid = $info[1] if ($info[0] eq $port);
}
close (H);
if ($debug)
{
# Print out all the RADIUS variables.
my @el = grep (/^RADIUS/, keys (%ENV));
my $e;
foreach $e (@el)
{
print "$e = " . $ENV{$e} . "\n";
}
}
# If the service type is Framed, then give them PPP.
# SLIP is not implemented (and will probably never be).
my $username = $ENV{"RADIUS_USER_NAME"};
# Generate a "unique" string for the session ID.
my $sessionid = "$$" . time ();
if ($ENV{"RADIUS_SERVICE_TYPE"} =~ /Login/)
{
# Warning: This code has not been tested as well as the PPP version,
# as of now (19961107).
# Determine what host to connect to.
if (($ENV{"RADIUS_LOGIN_IP_HOST"} eq "0.0.0.0") ||
!defined ($ENV{"RADIUS_LOGIN_IP_HOST"}))
{
die ("login_host not defined");
}
elsif ($ENV{"RADIUS_LOGIN_IP_HOST"} eq "255.255.255.255")
{
# The user should be able to choose. Prompt the user.
print "Host to connect to? ";
$login_host = <STDIN>;
chomp ($login_host);
}
else
{
# Use what's specified by the RADIUS server.
$login_host = $ENV{"RADIUS_LOGIN_IP_HOST"};
}
# Log into a host. Default to telnet. Do the accounting
# now, since the target of the login wouldn't know how to
# account for it.
# Time.
my $timestart = time ();
my $login_service = $ENV{"RADIUS_LOGIN_SERVICE"};
# What protocol are we running?
my ($prog_run, $login_port);
if ($login_service eq "Rlogin")
{
$prog_run = $prog_rlogin;
}
elsif ($login_service eq "Telnet")
{
$prog_run = $prog_telnet;
$login_port = $ENV{"RADIUS_LOGIN_PORT"};
}
elsif ($login_service eq "TCP-Clear")
{
$prog_run = $prog_tcpclear;
$login_port = $ENV{"RADIUS_LOGIN_PORT"};
} else {
die "unkown login_service $login_service\n";
}
# Start accounting. Send the record.
open (H, "| $prog_radacct") || die ("Cannot run $prog_radacct");
my $cmd =
"Acct-Session-ID = \"$sessionid\"\n" .
"User-Name = \"$username\"\n" .
"Acct-Status-Type = Start\n" .
"Acct-Authentic = RADIUS\n" .
"Service-Type = Login-User\n" .
"Login-Service = " . $login_service . "\n" .
"Login-IP-Host = $login_host\n";
print H $cmd;
close (H);
# Store the user information into portinfo. We need to
# manually fork, since we have to know the PID of the program.
my $pid = fork ();
if ($pid == 0)
{
# Child. Run the program.
# print "Connecting to $login_host:\n";
my $cmd = "$prog_run $login_host $login_port";
print "Running $cmd\n" if ($debug);
exec ("$cmd");
}
else
{
# Parent.
$login_host = $ENV{"RADIUS_LOGIN_IP_HOST"};
}
# Log into a host. Default to telnet. Do the accounting
# now, since the target of the login wouldn't know how to
# account for it.
# Time.
my $timestart = time ();
my $login_service = $ENV{"RADIUS_LOGIN_SERVICE"};
# What protocol are we running?
my ($prog_run, $login_port);
if ($login_service eq "Rlogin")
{
$prog_run = $prog_rlogin;
}
elsif ($login_service eq "Telnet")
{
$prog_run = $prog_telnet;
$login_port = $ENV{"RADIUS_LOGIN_PORT"};
}
elsif ($login_service eq "TCP-Clear")
{
$prog_run = $prog_tcpclear;
$login_port = $ENV{"RADIUS_LOGIN_PORT"};
} else {
die "unkown login_service $login_service\n";
}
# Start accounting. Send the record.
open (H, "| $prog_radacct") || die ("Cannot run $prog_radacct");
my $cmd =
"Acct-Session-ID = \"$sessionid\"\n" .
"User-Name = \"$username\"\n" .
"Acct-Status-Type = Start\n" .
"Acct-Authentic = RADIUS\n" .
"Service-Type = Login-User\n" .
"Login-Service = " . $login_service . "\n" .
"Login-IP-Host = $login_host\n";
print H $cmd;
close (H);
# Store the user information into portinfo. We need to
# manually fork, since we have to know the PID of the program.
my $pid = fork ();
if ($pid == 0)
{
# Child. Run the program.
# print "Connecting to $login_host:\n";
my $cmd = "$prog_run $login_host $login_port";
print "Running $cmd\n" if ($debug);
exec ("$cmd");
}
else
{
# Parent.
# Create the portinfo record, which needs the pid of the program
# to kill.
# The IP address is all zero, as it is not applicable here.
# Store the time now, and the Session-Timeout.
# Wait for the session to finish.
waitpid ($pid, 0);
}
# Stop. Send the record.
open (H, "| $prog_radacct") || die ("Cannot run $prog_radacct");
my $timespent = time () - $timestart;
my $cmd =
"Acct-Session-ID = \"$sessionid\"\n" .
"User-Name = \"$username\"\n" .
"Acct-Status-Type = Stop\n" .
"Acct-Authentic = RADIUS\n" .
"Service-Type = Login-User\n" .
"Login-Service = " . $login_service . "\n" .
"Login-IP-Host = $login_host\n" .
"Acct-Session-Time = $timespent\n";
print H $cmd;
close (H);
} else {
my $r = $ENV{"RADIUS_SERVICE_TYP"};
print "Unhandled Service-Type $r\n";
}
### END ####