• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asus-wl-520gu-7.0.1.45/src/router/pppd.mppe/pppd/plugins/radius/radiusclient/login.radius/migs/
1#!/usr/bin/perl
2#
3# login program to invoke PPP.
4# RADIUS accounting is NOT handled by this; it is handled by /etc/ppp/
5# ip-up and ip-down which are invoked when the TCP/IP connection is up.
6
7# version 0.1   November 5 1996
8# clean up the code, minor features.
9
10# version 0.02  May 8 1996
11#
12# start implementing other types of logins, not only Framed.
13# Also honor static IP addresses.
14#
15# version 0.01  April 1 1996
16#
17# - ignore RADIUS server requests for Framed-User, just
18#   do PPP.  Later, this should be honored.  For now,
19#   just use RADIUS for authentication; it's much simpler.
20#   Always use dynamic addresses.
21#
22
23use strict;
24use GDBM_File;
25
26#### CONFIGURATION SECTION ##################################################
27
28# Local IP address for the PPP connection.
29my $ip_address_local = "203.176.0.3";
30
31# First IP address for this terminal server, if dynamic addressing
32# is requested, or if nothing is specified for Framed-IP-Address.
33my $ip_address_begin = "203.176.0.161";
34
35# IP translation factor; subtract this value from radclient before adding
36# the beginning IP address.
37my $ip_translate_factor = 32;
38
39# Debugging to screen?
40my $debug = 1;
41
42# PPP parameters:
43
44# Async map - this one escapes only XON and XOFF characters.
45my $asyncmap = "0x000A0000";
46
47# MTU and MRU. 296 is good for interactive performance,
48# but larger ones will lead to less overhead for file transfers.
49# Maximum is 1500.
50my ($mtu, $mru) = (296, 296);
51
52# If we're using proxy ARP, set this to "proxyarp", else leave it blank.
53# my $proxyarp = "proxyarp";
54my $proxyarp = "";
55
56# Login host for non-framed connections.
57# This should only be an IP address, since that's what
58# Login-IP-Host should be.
59my $login_host = "203.176.0.4"; # marikit.iphil.net
60
61# Programs and files.
62my $prog_pppd     = "/usr/sbin/pppd";
63my $prog_radacct  = "/usr/local/lib/radiusclient/radacct";
64my $prog_rlogin   = "/usr/bin/rlogin";
65my $prog_telnet   = "/bin/telnet";
66my $prog_tcpclear = "/bin/telnet -e ''";
67my $prog_tty      = "/usr/bin/tty";
68my $prog_who      = "/usr/bin/who";
69
70my $path_portinfo         = "/var/ipoint/acct/portinfo";
71my $path_radiusclient_map = "/etc/radclient/port-id-map";
72
73#############################################################################
74
75# Main program.
76
77print "Starting.\n" if ($debug);
78
79# Run 'who am i' to determine the current port.
80my $port = `$prog_tty`;
81chomp ($port);
82
83# Translate port numbers to numbers for RADIUS.
84# This translation is done again by radacct, but it may be useful here.
85# Remove if CPU time is a problem.
86
87my ($portid, $line);
88open (H, $path_radiusclient_map);
89while (($line = <H>) && (!$portid))
90{
91    my @info = split (/\s+/, $line);
92    $portid = $info[1] if ($info[0] eq $port);
93}
94close (H);
95
96if ($debug)
97{
98    # Print out all the RADIUS variables.
99    my @el = grep (/^RADIUS/, keys (%ENV));
100    my $e;
101    foreach $e (@el)
102    {
103	print "$e = " . $ENV{$e} . "\n";
104    }
105}
106
107# If the service type is Framed, then give them PPP.
108# SLIP is not implemented (and will probably never be).
109
110my $username = $ENV{"RADIUS_USER_NAME"};
111
112# Generate a "unique" string for the session ID.
113my $sessionid = "$$" . time ();
114
115if ($ENV{"RADIUS_SERVICE_TYPE"} =~ /^Framed$/)
116{
117   
118# Use the specified IP address, or generate one if none is specified,
119# or a dynamic one requested.  Or, let the user negotiate the address.
120
121    my $ip_address = $ENV{"RADIUS_FRAMED_IP_ADDRESS"};
122
123    if (!$ip_address || ($ip_address eq "255.255.255.254"))
124    {
125	my @ipn = split (/\./, $ip_address_begin);
126	$ipn[3] += $portid - $ip_translate_factor;
127	$ip_address = join ('.', @ipn);
128
129	if ($debug)
130	{
131	    print "port: $port\n";
132	    print "portid: $portid\n";
133	    print "ip_translate_factor: $ip_translate_factor\n";
134	    print "ip_address: $ip_address\n";
135	    print "mru: $mru\n";
136	}
137
138    }
139    elsif ($ip_address eq "255.255.255.255")
140    {
141	# Clear it out so that pppd will let the remote end specify the
142	# IP address.
143	$ip_address = "";
144    }
145
146    # Override the specified MTU.
147    $mtu = $ENV{"RADIUS_FRAMED_MTU"} if $ENV{"RADIUS_FRAMED_MTU"};
148
149    # If no compression is specified, turn it off.
150    my $compress;
151    if (!$ENV{"RADIUS_FRAMED_COMPRESSION"})
152    {
153	$compress = "-vj";
154    }
155
156# Fix up the parameters to be passed to ip-up.  Include Framed-Route.
157# Escape spaces with %20's.
158
159    # Split up the framed route into multiple parts.
160    # Separate the different given routes with bars.
161    my $routelist = join ("@", map {$ENV{$_}}
162			     grep {/^RADIUS_FRAMED_ROUTE/} keys (%ENV)
163			    );
164    $routelist =~ s/ /%20/g;
165
166    my $param = join (':', $sessionid, $username, $port, $portid,
167		      $ENV{"RADIUS_SESSION_TIMEOUT"}, $routelist);
168
169		      
170# Run pppd through exec, so that it grabs hold of the terminal
171# and catches disconnections.
172
173    # Portmaster-style prompt.
174    if ($ENV{"RADIUS_SESSION_TIMEOUT"})
175    {
176	print "Session timeout: " . $ENV{"RADIUS_SESSION_TIMEOUT"} .
177	    " seconds.\n";
178    }
179    print "PPP session from ($ip_address_local) to $ip_address beginning....";
180    my $pppdcmd =
181	"$prog_pppd $ip_address_local:$ip_address modem crtscts " .
182	"asyncmap $asyncmap lock -detach $compress " .
183	"ipparam $param mtu $mtu mru $mru $proxyarp";
184
185    exec ($pppdcmd);
186}
187elsif ($ENV{"RADIUS_SERVICE_TYPE"} =~ /Login/)
188{
189    # Warning:  This code has not been tested as well as the PPP version,
190    # as of now (19961107).
191
192    # Determine what host to connect to.
193    if (($ENV{"RADIUS_LOGIN_IP_HOST"} eq "0.0.0.0") ||
194	!defined ($ENV{"RADIUS_LOGIN_IP_HOST"}))
195    {
196	# Do nothing, it's already specified above in the config section.
197    }
198    elsif ($ENV{"RADIUS_LOGIN_IP_HOST"} eq "255.255.255.255")
199    {
200	# The user should be able to choose.  Prompt the user.
201	print "Host to connect to?  ";
202	$login_host = <STDIN>;
203	chomp ($login_host);
204    }
205    else
206    {
207	# Use what's specified by the RADIUS server.
208	$login_host = $ENV{"RADIUS_LOGIN_IP_HOST"};
209    }
210    
211    # Log into a host.  Default to telnet.  Do the accounting
212    # now, since the target of the login wouldn't know how to
213    # account for it.
214
215    # Start accounting.  Send the record.
216    open  (H, "| $prog_radacct") || die ("Cannot run $prog_radacct");
217
218    my $login_service = $ENV{"RADIUS_LOGIN_SERVICE"};
219
220    my $cmd =
221	"Acct-Session-ID = \"$sessionid\"\n" .
222	"User-Name = \"$username\"\n" .
223	"Acct-Status-Type = Start\n" .
224        "Acct-Authentic = RADIUS\n" .
225        "Service-Type = Login\n" .
226        "Login-Service = " . $login_service . "\n" .
227        "Login-IP-Host = $login_host\n";
228
229    print H $cmd;
230    close (H);
231
232    # Time.
233    my $timestart = time ();
234
235    # What protocol are we running?
236    my ($prog_run, $login_port);
237
238    if ($login_service eq "Rlogin")
239    {
240	$prog_run = $prog_rlogin;
241    }
242    elsif ($login_service eq "Telnet")
243    {
244	$prog_run = $prog_telnet;
245	$login_port = $ENV{"RADIUS_LOGIN_PORT"};
246    }
247    elsif ($login_service eq "TCP-Clear")
248    {
249	$prog_run = $prog_tcpclear;
250	$login_port = $ENV{"RADIUS_LOGIN_PORT"};
251    }
252
253    # Store the user information into portinfo.  We need to
254    # manually fork, since we have to know the PID of the program.
255
256    my $pid = fork ();
257    if ($pid == 0)
258    {
259	# Child.  Run the program.
260	# print "Connecting to $login_host:\n";
261	my $cmd = "$prog_run $login_host $login_port";
262	exec ("$cmd");
263    }
264    else
265    {
266	# Parent.  
267	# Create the portinfo record, which needs the pid of the program
268	# to kill.
269	# The IP address is all zero, as it is not applicable here.
270	# Store the time now, and the Session-Timeout.
271
272	my %db_portinfo;
273
274	tie (%db_portinfo, "GDBM_File", $path_portinfo, GDBM_WRCREAT, 0600);
275	$db_portinfo{$portid} =
276	    join (':', $username, "Login/$login_service",
277		  "0.0.0.0", $pid, $timestart, $ENV{"RADIUS_SESSION_TIMEOUT"});
278	untie (%db_portinfo);
279
280	# Wait for the session to finish.
281	waitpid ($pid, 0);
282    }
283    # Stop.  Send the record.
284    open  (H, "| $prog_radacct") || die ("Cannot run $prog_radacct");
285
286    my $timespent = time () - $timestart;
287
288    my $cmd =
289	"Acct-Session-ID = \"$sessionid\"\n" .
290	"User-Name = \"$username\"\n" .
291	"Acct-Status-Type = Stop\n" .
292        "Acct-Authentic = RADIUS\n" .
293        "Service-Type = Login\n" .
294        "Login-Service = " . $login_service . "\n" .
295        "Login-IP-Host = $login_host\n" .
296        "Acct-Session-Time = $timespent\n";
297
298    print H $cmd;
299    close (H);
300
301    # Remove the record from portinfo.
302    my %db_portinfo;
303    tie (%db_portinfo, "GDBM_File", $path_portinfo, GDBM_WRCREAT, 0600);
304    delete $db_portinfo{$portid};
305    untie (%db_portinfo);
306}
307
308### END ####
309
310
311
312
313