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