get rid of FS::SSH.pm (became Net::SSH and Net::SCP on CPAN)
[freeside.git] / bin / svc_acct.import
1 #!/usr/bin/perl -Tw
2 #
3 # $Id: svc_acct.import,v 1.12 2001-04-22 01:56:15 ivan Exp $
4 #
5 # ivan@sisd.com 98-mar-9
6 #
7 # changed 'password' field to '_password' because PgSQL 6.3 reserves this word
8 #       bmccane@maxbaud.net  98-Apr-3
9 #
10 # generalized svcparts (still needs radius import) ivan@sisd.com 98-mar-23
11 #
12 # radius import, now an interactive script.  still needs erpcd import?
13 # ivan@sisd.com 98-jun-24
14 #
15 # arbitrary radius attributes ivan@sisd.com 98-aug-9
16 #
17 # don't import /var/spool/freeside/conf/shells!  ivan@sisd.com 98-aug-13
18 #
19 # $Log: svc_acct.import,v $
20 # Revision 1.12  2001-04-22 01:56:15  ivan
21 # get rid of FS::SSH.pm (became Net::SSH and Net::SCP on CPAN)
22 #
23 # Revision 1.11  2000/06/29 12:27:01  ivan
24 # s/password/_password/ for PostgreSQL wasn't done in the import.
25 #
26 # Revision 1.10  2000/06/28 12:32:30  ivan
27 # allow RADIUS lines with "Auth-Type = Local" too
28 #
29 # Revision 1.8  2000/02/03 05:16:52  ivan
30 # beginning of DNS and Apache support
31 #
32 # Revision 1.7  1999/07/08 02:32:26  ivan
33 # import fix, noticed by Ben Leibig and Joel Griffiths
34 #
35 # Revision 1.6  1999/07/08 01:49:00  ivan
36 # updates to avoid -w warnings from Joel Griffiths <griff@aver-computer.com>
37 #
38 # Revision 1.5  1999/03/25 08:42:19  ivan
39 # import stuff uses Term::Query and spits out (some kinds of) nonsensical input
40 #
41 # Revision 1.4  1999/03/24 00:43:38  ivan
42 # die if no relevant services
43 #
44 # Revision 1.3  1998/12/10 07:23:16  ivan
45 # use FS::Conf, need user (for datasrc)
46 #
47 # Revision 1.2  1998/10/13 12:07:51  ivan
48 # Assigns password from the shadow file for RADIUS password "UNIX"
49 #
50
51 use strict;
52 use vars qw(%part_svc);
53 use Date::Parse;
54 use Term::Query qw(query);
55 use Net::SCP qw(iscp);
56 use FS::UID qw(adminsuidsetup datasrc);
57 use FS::Record qw(qsearch);
58 use FS::svc_acct;
59 use FS::part_svc;
60
61 my $user = shift or die &usage;
62 adminsuidsetup $user;
63
64 my($spooldir)="/usr/local/etc/freeside/export.". datasrc;
65
66 $FS::svc_acct::nossh_hack = 1;
67
68 ###
69
70 %part_svc=map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_acct'});
71
72 die "No services with svcdb svc_acct!\n" unless %part_svc;
73
74 print "\n\n", &menu_svc, "\n", <<END;
75 Most accounts probably have entries in passwd and users (with Port-Limit
76 nonexistant or 1).
77 END
78 my($ppp_svcpart)=&getpart;
79
80 print "\n\n", &menu_svc, "\n", <<END;
81 Some accounts have entries in passwd and users, but with Port-Limit 2 (or
82 more).
83 END
84 my($isdn_svcpart)=&getpart;
85
86 print "\n\n", &menu_svc, "\n", <<END;
87 Some accounts might have entries in users only (Port-Limit 1)
88 END
89 my($oppp_svcpart)=&getpart;
90
91 print "\n\n", &menu_svc, "\n", <<END;
92 Some accounts might have entries in users only (Port-Limit >= 2)
93 END
94 my($oisdn_svcpart)=&getpart;
95
96 print "\n\n", &menu_svc, "\n", <<END;
97 POP mail accounts have entries in passwd only, and have a particular shell.
98 END
99 my($pop_shell)=&getvalue("Enter that shell:");
100 my($popmail_svcpart)=&getpart;
101
102 print "\n\n", &menu_svc, "\n", <<END;
103 Everything else in passwd is a shell account.
104 END
105 my($shell_svcpart)=&getpart;
106
107 print "\n\n", <<END;
108 Enter the location and name of your _user_ passwd file, for example
109 "mail.isp.com:/etc/passwd" or "nis.isp.com:/etc/global/passwd"
110 END
111 my($loc_passwd)=&getvalue(":");
112 iscp("root\@$loc_passwd", "$spooldir/passwd.import");
113
114 print "\n\n", <<END;
115 Enter the location and name of your _user_ shadow file, for example
116 "mail.isp.com:/etc/shadow" or "bsd.isp.com:/etc/master.passwd"
117 END
118 my($loc_shadow)=&getvalue(":");
119 iscp("root\@$loc_shadow", "$spooldir/shadow.import");
120
121 print "\n\n", <<END;
122 Enter the location and name of your radius "users" file, for example
123 "radius.isp.com:/etc/raddb/users"
124 END
125 my($loc_users)=&getvalue(":");
126 iscp("root\@$loc_users", "$spooldir/users.import");
127
128 sub menu_svc {
129   ( join "\n", map "$_: ".$part_svc{$_}->svc, sort keys %part_svc ). "\n";
130 }
131 sub getpart {
132   $^W=0; # Term::Query isn't -w-safe
133   my $return = query "Enter part number:", 'irk', [ keys %part_svc ];
134   $^W=1;
135   $return;
136 }
137 sub getvalue {
138   my $prompt = shift;
139   $^W=0; # Term::Query isn't -w-safe
140   my $return = query $prompt, '';
141   $^W=1;
142   $return;
143 }
144
145 print "\n\n";
146
147 ###
148
149 open(PASSWD,"<$spooldir/passwd.import");
150 open(SHADOW,"<$spooldir/shadow.import");
151 open(USERS,"<$spooldir/users.import");
152
153 my(%upassword,%ip,%allparam);
154 my(%param,$username);
155 while (<USERS>) {
156   chop;
157   next if /^\s*$/;
158   next if /^\s*#/;
159   if ( /^\S/ ) {
160     /^(\w+)\s+(Auth-Type\s+=\s+Local,\s+)Password\s+=\s+"([^"]+)"(,\s+Expiration\s+=\s+"([^"]*")\s*)?$/
161       or die "1Unexpected line in users.import: $_";
162     my($password,$expiration);
163     ($username,$password,$expiration)=(lc($1),$3,$5);
164     $password = '' if $password eq 'UNIX';
165     $upassword{$username}=$password;
166     undef %param;
167   } else {
168     die "2Unexpected line in users.import: $_";
169   }
170   while (<USERS>) {
171     chop;
172     if ( /^\s*$/ ) {
173       if ( defined $param{'radius_Framed_IP_Address'} ) {
174         $ip{$username} = $param{'radius_Framed_IP_Address'};
175         delete $param{'radius_Framed_IP_Address'};
176       } else {
177         $ip{$username} = '0e0';
178       }
179       $allparam{$username}={ %param };
180       last;
181     } elsif ( /^\s+([\w\-]+)\s=\s"?([\w\.\-\s]+)"?,?\s*$/ ) {
182       my($attribute,$value)=($1,$2);
183       $attribute =~ s/\-/_/g;
184       $param{'radius_'.$attribute}=$value;
185     } else {
186       die "3Unexpected line in users.import: $_";
187     }
188   }
189 }
190 #? incase there isn't a terminating blank line ?
191 if ( defined $param{'radius_Framed_IP_Address'} ) {
192   $ip{$username} = $param{'radius_Framed_IP_Address'};
193   delete $param{'radius_Framed_IP_Address'};
194 } else {
195   $ip{$username} = '0e0';
196 }
197 $allparam{$username}={ %param };
198
199 my(%password);
200 while (<SHADOW>) {
201   chop;
202   my($username,$password)=split(/:/);
203   $password{$username}=$password;
204 }
205
206 while (<PASSWD>) {
207   chop;
208   my($username,$x,$uid,$gid,$finger,$dir,$shell)=split(/:/);
209   my($password)=$upassword{$username} || $password{$username};
210
211   my($maxb)=${$allparam{$username}}{'radius_Port_Limit'};
212   my($svcpart);
213   if ( exists $upassword{$username} ) {
214     if ( $maxb >= 2 ) {
215       $svcpart = $isdn_svcpart
216     } elsif ( ! $maxb || $maxb == 1 ) {
217       $svcpart = $ppp_svcpart
218     } else {
219       die "Illegal Port-Limit in users ($username)!\n";
220     }
221   } elsif ( $shell eq $pop_shell ) {
222     $svcpart = $popmail_svcpart;
223   } else {
224     $svcpart = $shell_svcpart;
225   }
226
227   my($svc_acct) = new FS::svc_acct ({
228     'svcpart'   => $svcpart,
229     'username'  => $username,
230     '_password' => $password,
231     'uid'       => $uid,
232     'gid'       => $gid,
233     'finger'    => $finger,
234     'dir'       => $dir,
235     'shell'     => $shell,
236     'slipip'    => $ip{$username},
237     %{$allparam{$username}},
238   });
239   my($error);
240   $error=$svc_acct->insert;
241   die $error if $error;
242
243   delete $allparam{$username};
244   delete $upassword{$username};
245 }
246
247 #my($username);
248 foreach $username ( keys %upassword ) {
249   my($password)=$upassword{$username};
250
251   my($maxb)=${$allparam{$username}}{'radius_Port_Limit'} || 0;
252   my($svcpart);
253   if ( $maxb == 2 ) {
254     $svcpart = $oisdn_svcpart
255   } elsif ( ! $maxb || $maxb == 1 ) {
256     $svcpart = $oppp_svcpart
257   } else {
258     die "Illegal Port-Limit in users!\n";
259   }
260
261   my($svc_acct) = new FS::svc_acct ({
262     'svcpart'   => $svcpart,
263     'username'  => $username,
264     '_password' => $password,
265     'slipip'    => $ip{$username},
266     %{$allparam{$username}},
267   });
268   my($error);
269   $error=$svc_acct->insert;
270   die $error, if $error;
271
272   delete $allparam{$username};
273   delete $upassword{$username};
274 }
275
276 #
277
278 sub usage {
279   die "Usage:\n\n  svc_acct.import user\n";
280 }
281