#!/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 = ) && (!$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 = ; 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 ####