fix big in RADIUS session viewing when using an ignored-accounting export
[freeside.git] / bin / svc_acct.import
1 #!/usr/bin/perl -Tw
2 # $Id: svc_acct.import,v 1.17 2001-08-19 10:25:44 ivan Exp $
3
4 use strict;
5 use vars qw(%part_svc);
6 use Date::Parse;
7 use Term::Query qw(query);
8 use Net::SCP qw(iscp);
9 use FS::UID qw(adminsuidsetup datasrc);
10 use FS::Record qw(qsearch);
11 use FS::svc_acct;
12 use FS::part_svc;
13
14 my $user = shift or die &usage;
15 adminsuidsetup $user;
16
17 push @FS::svc_acct::shells, qw(/bin/sync /sbin/shuddown /bin/halt); #others?
18
19 my($spooldir)="/usr/local/etc/freeside/export.". datasrc;
20
21 $FS::svc_acct::nossh_hack = 1;
22
23 ###
24
25 %part_svc=map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_acct'});
26
27 die "No services with svcdb svc_acct!\n" unless %part_svc;
28
29 print "\n\n", &menu_svc, "\n", <<END;
30 Most accounts probably have entries in passwd and users (with Port-Limit
31 nonexistant or 1).
32 END
33 my($ppp_svcpart)=&getpart;
34
35 print "\n\n", &menu_svc, "\n", <<END;
36 Some accounts have entries in passwd and users, but with Port-Limit 2 (or
37 more).
38 END
39 my($isdn_svcpart)=&getpart;
40
41 print "\n\n", &menu_svc, "\n", <<END;
42 Some accounts might have entries in users only (Port-Limit 1)
43 END
44 my($oppp_svcpart)=&getpart;
45
46 print "\n\n", &menu_svc, "\n", <<END;
47 Some accounts might have entries in users only (Port-Limit >= 2)
48 END
49 my($oisdn_svcpart)=&getpart;
50
51 print "\n\n", &menu_svc, "\n", <<END;
52 POP mail accounts have entries in passwd only, and have a particular shell.
53 END
54 my($pop_shell)=&getvalue("Enter that shell:");
55 my($popmail_svcpart)=&getpart;
56
57 print "\n\n", &menu_svc, "\n", <<END;
58 Everything else in passwd is a shell account.
59 END
60 my($shell_svcpart)=&getpart;
61
62 print "\n\n", <<END;
63 Enter the location and name of your _user_ passwd file, for example
64 "mail.isp.com:/etc/passwd" or "nis.isp.com:/etc/global/passwd"
65 END
66 my($loc_passwd)=&getvalue(":");
67 iscp("root\@$loc_passwd", "$spooldir/passwd.import");
68
69 print "\n\n", <<END;
70 Enter the location and name of your _user_ shadow file, for example
71 "mail.isp.com:/etc/shadow" or "bsd.isp.com:/etc/master.passwd"
72 END
73 my($loc_shadow)=&getvalue(":");
74 iscp("root\@$loc_shadow", "$spooldir/shadow.import");
75
76 print "\n\n", <<END;
77 Enter the location and name of your radius "users" file, for example
78 "radius.isp.com:/etc/raddb/users"
79 END
80 my($loc_users)=&getvalue(":");
81 iscp("root\@$loc_users", "$spooldir/users.import");
82
83 sub menu_svc {
84   ( join "\n", map "$_: ".$part_svc{$_}->svc, sort keys %part_svc ). "\n";
85 }
86 sub getpart {
87   $^W=0; # Term::Query isn't -w-safe
88   my $return = query "Enter part number:", 'irk', [ keys %part_svc ];
89   $^W=1;
90   $return;
91 }
92 sub getvalue {
93   my $prompt = shift;
94   $^W=0; # Term::Query isn't -w-safe
95   my $return = query $prompt, '';
96   $^W=1;
97   $return;
98 }
99
100 print "\n\n";
101
102 ###
103
104 open(PASSWD,"<$spooldir/passwd.import");
105 open(SHADOW,"<$spooldir/shadow.import");
106 open(USERS,"<$spooldir/users.import");
107
108 my(%upassword,%ip,%allparam);
109 my(%param,$username);
110 while (<USERS>) {
111   chop;
112   next if /^\s*$/;
113   next if /^\s*#/;
114   if ( /^\S/ ) {
115     /^(\w+)\s+(Auth-Type\s+=\s+Local,\s+)?Password\s+=\s+"([^"]+)"(,\s+Expiration\s+=\s+"([^"]*")\s*)?$/
116       or die "1Unexpected line in users.import: $_";
117     my($password,$expiration);
118     ($username,$password,$expiration)=(lc($1),$3,$5);
119     $password = '' if $password eq 'UNIX';
120     $upassword{$username}=$password;
121     undef %param;
122   } else {
123     die "2Unexpected line in users.import: $_";
124   }
125   while (<USERS>) {
126     chop;
127     if ( /^\s*$/ ) {
128       if ( defined $param{'radius_Framed_IP_Address'} ) {
129         $ip{$username} = $param{'radius_Framed_IP_Address'};
130         delete $param{'radius_Framed_IP_Address'};
131       } else {
132         $ip{$username} = '0e0';
133       }
134       $allparam{$username}={ %param };
135       last;
136     } elsif ( /^\s+([\w\-]+)\s=\s"?([\w\.\-\s]+)"?,?\s*$/ ) {
137       my($attribute,$value)=($1,$2);
138       $attribute =~ s/\-/_/g;
139       $param{'radius_'.$attribute}=$value;
140     } else {
141       die "3Unexpected line in users.import: $_";
142     }
143   }
144 }
145 #? incase there isn't a terminating blank line ?
146 if ( defined $param{'radius_Framed_IP_Address'} ) {
147   $ip{$username} = $param{'radius_Framed_IP_Address'};
148   delete $param{'radius_Framed_IP_Address'};
149 } else {
150   $ip{$username} = '0e0';
151 }
152 $allparam{$username}={ %param };
153
154 my(%password);
155 while (<SHADOW>) {
156   chop;
157   my($username,$password)=split(/:/);
158   #$password =~ s/^\!$/\*/;
159   #$password =~ s/\!+/\*SUSPENDED\* /;
160   $password{$username}=$password;
161 }
162
163 while (<PASSWD>) {
164   chop;
165   my($username,$x,$uid,$gid,$finger,$dir,$shell)=split(/:/);
166   my($password)=$upassword{$username} || $password{$username};
167
168   my($maxb)=${$allparam{$username}}{'radius_Port_Limit'};
169   my($svcpart);
170   if ( exists $upassword{$username} ) {
171     if ( $maxb >= 2 ) {
172       $svcpart = $isdn_svcpart
173     } elsif ( ! $maxb || $maxb == 1 ) {
174       $svcpart = $ppp_svcpart
175     } else {
176       die "Illegal Port-Limit in users ($username)!\n";
177     }
178   } elsif ( $shell eq $pop_shell ) {
179     $svcpart = $popmail_svcpart;
180   } else {
181     $svcpart = $shell_svcpart;
182   }
183
184   my($svc_acct) = new FS::svc_acct ({
185     'svcpart'   => $svcpart,
186     'username'  => $username,
187     '_password' => $password,
188     'uid'       => $uid,
189     'gid'       => $gid,
190     'finger'    => $finger,
191     'dir'       => $dir,
192     'shell'     => $shell,
193     'slipip'    => $ip{$username},
194     %{$allparam{$username}},
195   });
196   my($error);
197   $error=$svc_acct->insert;
198   die $error if $error;
199
200   delete $allparam{$username};
201   delete $upassword{$username};
202 }
203
204 #my($username);
205 foreach $username ( keys %upassword ) {
206   my($password)=$upassword{$username};
207
208   my($maxb)=${$allparam{$username}}{'radius_Port_Limit'} || 0;
209   my($svcpart);
210   if ( $maxb == 2 ) {
211     $svcpart = $oisdn_svcpart
212   } elsif ( ! $maxb || $maxb == 1 ) {
213     $svcpart = $oppp_svcpart
214   } else {
215     die "Illegal Port-Limit in users!\n";
216   }
217
218   my($svc_acct) = new FS::svc_acct ({
219     'svcpart'   => $svcpart,
220     'username'  => $username,
221     '_password' => $password,
222     'slipip'    => $ip{$username},
223     %{$allparam{$username}},
224   });
225   my($error);
226   $error=$svc_acct->insert;
227   die $error, if $error;
228
229   delete $allparam{$username};
230   delete $upassword{$username};
231 }
232
233 #
234
235 sub usage {
236   die "Usage:\n\n  svc_acct.import user\n";
237 }
238