📄 login.radius
字号:
#!/usr/bin/perl## login program to invoke PPP.# RADIUS accounting is NOT handled by this; it is handled by /etc/ppp/# ip-up and ip-down which are invoked when the TCP/IP connection is up.# version 0.1 November 5 1996# clean up the code, minor features.# version 0.02 May 8 1996## start implementing other types of logins, not only Framed.# Also honor static IP addresses.## version 0.01 April 1 1996## - ignore RADIUS server requests for Framed-User, just# do PPP. Later, this should be honored. For now,# just use RADIUS for authentication; it's much simpler.# Always use dynamic addresses.#use strict;use GDBM_File;#### CONFIGURATION SECTION ################################################### Local IP address for the PPP connection.my $ip_address_local = "203.176.0.3";# First IP address for this terminal server, if dynamic addressing# is requested, or if nothing is specified for Framed-IP-Address.my $ip_address_begin = "203.176.0.161";# IP translation factor; subtract this value from radclient before adding# the beginning IP address.my $ip_translate_factor = 32;# Debugging to screen?my $debug = 1;# PPP parameters:# Async map - this one escapes only XON and XOFF characters.my $asyncmap = "0x000A0000";# MTU and MRU. 296 is good for interactive performance,# but larger ones will lead to less overhead for file transfers.# Maximum is 1500.my ($mtu, $mru) = (296, 296);# If we're using proxy ARP, set this to "proxyarp", else leave it blank.# my $proxyarp = "proxyarp";my $proxyarp = "";# Login host for non-framed connections.# This should only be an IP address, since that's what# Login-IP-Host should be.my $login_host = "203.176.0.4"; # marikit.iphil.net# Programs and files.my $prog_pppd = "/usr/sbin/pppd";my $prog_radacct = "/usr/local/lib/radiusclient/radacct";my $prog_rlogin = "/usr/bin/rlogin";my $prog_telnet = "/bin/telnet";my $prog_tcpclear = "/bin/telnet -e ''";my $prog_tty = "/usr/bin/tty";my $prog_who = "/usr/bin/who";my $path_portinfo = "/var/ipoint/acct/portinfo";my $path_radiusclient_map = "/etc/radclient/port-id-map";############################################################################## 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"} =~ /^Framed$/){ # Use the specified IP address, or generate one if none is specified,# or a dynamic one requested. Or, let the user negotiate the address. my $ip_address = $ENV{"RADIUS_FRAMED_IP_ADDRESS"}; if (!$ip_address || ($ip_address eq "255.255.255.254")) { my @ipn = split (/\./, $ip_address_begin); $ipn[3] += $portid - $ip_translate_factor; $ip_address = join ('.', @ipn); if ($debug) { print "port: $port\n"; print "portid: $portid\n"; print "ip_translate_factor: $ip_translate_factor\n"; print "ip_address: $ip_address\n"; print "mru: $mru\n"; } } elsif ($ip_address eq "255.255.255.255") { # Clear it out so that pppd will let the remote end specify the # IP address. $ip_address = ""; } # Override the specified MTU. $mtu = $ENV{"RADIUS_FRAMED_MTU"} if $ENV{"RADIUS_FRAMED_MTU"}; # If no compression is specified, turn it off. my $compress; if (!$ENV{"RADIUS_FRAMED_COMPRESSION"}) { $compress = "-vj"; }# Fix up the parameters to be passed to ip-up. Include Framed-Route.# Escape spaces with %20's. # Split up the framed route into multiple parts. # Separate the different given routes with bars. my $routelist = join ("@", map {$ENV{$_}} grep {/^RADIUS_FRAMED_ROUTE/} keys (%ENV) ); $routelist =~ s/ /%20/g; my $param = join (':', $sessionid, $username, $port, $portid, $ENV{"RADIUS_SESSION_TIMEOUT"}, $routelist); # Run pppd through exec, so that it grabs hold of the terminal# and catches disconnections. # Portmaster-style prompt. if ($ENV{"RADIUS_SESSION_TIMEOUT"}) { print "Session timeout: " . $ENV{"RADIUS_SESSION_TIMEOUT"} . " seconds.\n"; } print "PPP session from ($ip_address_local) to $ip_address beginning...."; my $pppdcmd = "$prog_pppd $ip_address_local:$ip_address modem crtscts " . "asyncmap $asyncmap lock -detach $compress " . "ipparam $param mtu $mtu mru $mru $proxyarp"; exec ($pppdcmd);}elsif ($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"})) { # Do nothing, it's already specified above in the config section. } 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. # Start accounting. Send the record. open (H, "| $prog_radacct") || die ("Cannot run $prog_radacct"); my $login_service = $ENV{"RADIUS_LOGIN_SERVICE"}; my $cmd = "Acct-Session-ID = \"$sessionid\"\n" . "User-Name = \"$username\"\n" . "Acct-Status-Type = Start\n" . "Acct-Authentic = RADIUS\n" . "Service-Type = Login\n" . "Login-Service = " . $login_service . "\n" . "Login-IP-Host = $login_host\n"; print H $cmd; close (H); # Time. my $timestart = time (); # 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"}; } # 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"; 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. my %db_portinfo; tie (%db_portinfo, "GDBM_File", $path_portinfo, GDBM_WRCREAT, 0600); $db_portinfo{$portid} = join (':', $username, "Login/$login_service", "0.0.0.0", $pid, $timestart, $ENV{"RADIUS_SESSION_TIMEOUT"}); untie (%db_portinfo); # 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\n" . "Login-Service = " . $login_service . "\n" . "Login-IP-Host = $login_host\n" . "Acct-Session-Time = $timespent\n"; print H $cmd; close (H); # Remove the record from portinfo. my %db_portinfo; tie (%db_portinfo, "GDBM_File", $path_portinfo, GDBM_WRCREAT, 0600); delete $db_portinfo{$portid}; untie (%db_portinfo);}### END ####
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -