]> git.ozlabs.org Git - ppp.git/blob - pppd/plugins/radius/radiusclient/login.radius/migs/login.radius
Add these files, used with TDB.
[ppp.git] / pppd / plugins / radius / radiusclient / login.radius / migs / login.radius
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
23 use strict;
24 use GDBM_File;
25
26 #### CONFIGURATION SECTION ##################################################
27
28 # Local IP address for the PPP connection.
29 my $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.
33 my $ip_address_begin = "203.176.0.161";
34
35 # IP translation factor; subtract this value from radclient before adding
36 # the beginning IP address.
37 my $ip_translate_factor = 32;
38
39 # Debugging to screen?
40 my $debug = 1;
41
42 # PPP parameters:
43
44 # Async map - this one escapes only XON and XOFF characters.
45 my $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.
50 my ($mtu, $mru) = (296, 296);
51
52 # If we're using proxy ARP, set this to "proxyarp", else leave it blank.
53 # my $proxyarp = "proxyarp";
54 my $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.
59 my $login_host = "203.176.0.4"; # marikit.iphil.net
60
61 # Programs and files.
62 my $prog_pppd     = "/usr/sbin/pppd";
63 my $prog_radacct  = "/usr/local/lib/radiusclient/radacct";
64 my $prog_rlogin   = "/usr/bin/rlogin";
65 my $prog_telnet   = "/bin/telnet";
66 my $prog_tcpclear = "/bin/telnet -e ''";
67 my $prog_tty      = "/usr/bin/tty";
68 my $prog_who      = "/usr/bin/who";
69
70 my $path_portinfo         = "/var/ipoint/acct/portinfo";
71 my $path_radiusclient_map = "/etc/radclient/port-id-map";
72
73 #############################################################################
74
75 # Main program.
76
77 print "Starting.\n" if ($debug);
78
79 # Run 'who am i' to determine the current port.
80 my $port = `$prog_tty`;
81 chomp ($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
87 my ($portid, $line);
88 open (H, $path_radiusclient_map);
89 while (($line = <H>) && (!$portid))
90 {
91     my @info = split (/\s+/, $line);
92     $portid = $info[1] if ($info[0] eq $port);
93 }
94 close (H);
95
96 if ($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
110 my $username = $ENV{"RADIUS_USER_NAME"};
111
112 # Generate a "unique" string for the session ID.
113 my $sessionid = "$$" . time ();
114
115 if ($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 }
187 elsif ($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