File Coverage

blib/lib/Wizard/LDAP/User.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             # -*- perl -*-
2              
3 1     1   799 use strict;
  1         2  
  1         40  
4              
5 1     1   5 use Net::LDAP ();
  1         2  
  1         17  
6 1     1   5 use Socket ();
  1         2  
  1         15  
7 1     1   618 use Wizard ();
  0            
  0            
8             use Wizard::State ();
9             use Wizard::SaveAble ();
10             use Wizard::SaveAble::LDAP ();
11             use Wizard::LDAP ();
12             use Wizard::LDAP::Config ();
13              
14             @Wizard::LDAP::User::ISA = qw(Wizard::LDAP);
15             $Wizard::LDAP::User::VERSION = '0.01';
16              
17             package Wizard::LDAP::User;
18              
19             my $RESOLVE_SHELL = { 'mail' => '/bin/mailonly', 'ftp' => '/bin/ftp_mail',
20             'admin' => '/bin/bash'};
21              
22             sub init {
23             my $self = shift;
24             return ($self->SUPER::init(1)) unless shift;
25             my $item = $self->{'user'} || die "Missing user";
26             ($self->SUPER::init(1), $item);
27             }
28              
29              
30             sub ShowMe {
31             my($self, $wiz, $prefs, $user) = @_;
32             (['Wizard::Elem::Title',
33             'value' => $user->CreateMe() ?
34             'LDAP Wizard: Create a new user' :
35             'LDAP Wizard: Edit an existing user'],
36             ['Wizard::Elem::Data',
37             'value' => $user->{'ldap-user-uidnumber'},
38             'descr' => 'Users UID'],
39             ['Wizard::Elem::Data',
40             'value' => $user->{'ldap-user-gidnumber'},
41             'descr' => 'Users GID'],
42             ['Wizard::Elem::Data',
43             'value' => $user->{'ldap-user-homedirectory'},
44             'descr' => 'Users home directory'],
45             ['Wizard::Elem::Text', 'name' => 'ldap-user-uid',
46             'value' => $user->{'ldap-user-uid'},
47             'descr' => 'Users login'],
48             ['Wizard::Elem::Text', 'name' => 'ldap-user-userpassword',
49             'value' => $user->{'ldap-user-userpassword'},
50             'descr' => 'Users password'],
51             ['Wizard::Elem::Text', 'name' => 'ldap-user-cn',
52             'value' => $user->{'ldap-user-cn'},
53             'descr' => 'Users real name'],
54             ['Wizard::Elem::Text', 'name' => 'ldap-user-description',
55             'value' => $user->{'ldap-user-description'},
56             'descr' => 'A single-line description of the user'],
57             ['Wizard::Elem::Text', 'name' => 'ldap-user-mail',
58             'value' => $user->{'ldap-user-mail'},
59             'descr' => 'Users email adress'],
60             ['Wizard::Elem::Text', 'name' => 'ldap-user-mailforward',
61             'value' => $user->{'ldap-user-mailforward'},
62             'descr' => 'Users email forward address'],
63             ['Wizard::Elem::Select', 'name' => 'ldap-user-mailforwardtype',
64             'value' => $user->{'ldap-user-mailforwardtype'} || 'always',
65             'options' => ['after 1 day', 'after 2 days', 'after 3 days',
66             'after 4 days', 'after 5 days', 'always'],
67             'descr' => 'Users email forward type'],
68             ['Wizard::Elem::Text', 'name' => 'ldap-user-pop3box',
69             'value' => $user->{'ldap-user-pop3box'},
70             'descr' => 'External POP3 box to fetch mail from'],
71             ['Wizard::Elem::Text', 'name' => 'ldap-user-pop3password',
72             'value' => $user->{'ldap-user-pop3password'},
73             'descr' => 'Password of the external POP3 box'],
74             ['Wizard::Elem::Select', 'name' => 'ldap-user-status',
75             'value' => $user->{'ldap-user-status'},
76             'options' => ['mail', 'ftp', 'admin'],
77             'descr' => 'Users status'],
78             ['Wizard::Elem::Submit', 'name' => 'Action_UserSave',
79             'value' => 'Save these settings', 'id' => 1],
80             ['Wizard::Elem::BR'],
81             ['Wizard::Elem::Submit', 'name' => 'Action_Reset',
82             'value' => 'Return to User menu', 'id' => 98],
83             ['Wizard::Elem::Submit', 'name' => 'Wizard::LDAP::Action_Reset',
84             'value' => 'Return to top menu', 'id' => 99]);
85             }
86              
87              
88             sub Action_Reset {
89             my($self, $wiz) = @_;
90             $self->init();
91              
92             delete $self->{'user'};
93             $self->Store($wiz);
94              
95             # Return the initial menu.
96             (['Wizard::Elem::Title', 'value' => 'LDAP Wizard User Menu'],
97             ['Wizard::Elem::Submit', 'value' => 'Create a new user',
98             'name' => 'Action_CreateUser',
99             'id' => 1],
100             ['Wizard::Elem::Submit', 'value' => 'Modify an existing user',
101             'name' => 'Action_ModifyUser',
102             'id' => 2],
103             ['Wizard::Elem::Submit', 'value' => 'Delete an existing user',
104             'name' => 'Action_DeleteUser',
105             'id' => 3],
106             ['Wizard::Elem::BR'],
107             ['Wizard::Elem::Submit', 'value' => 'Return to Top Menu',
108             'name' => 'Wizard::LDAP::Action_Reset',
109             'id' => 98],
110             ['Wizard::Elem::Submit', 'value' => 'Exit LDAP Wizard',
111             'id' => 99]);
112             }
113              
114             sub Action_CreateUser {
115             my($self, $wiz) = @_;
116             my ($prefs, $admin) = $self->init();
117             my $attr = { 'ldap-user-uidnumber' => $prefs->{'ldap-prefs-nextuid'},
118             'ldap-user-gidnumber' => $prefs->{'ldap-prefs-gid'},
119             'ldap-user-homedirectory' => $prefs->{'ldap-prefs-home'} . '/'};
120             my $user = Wizard::SaveAble::LDAP->new('adminDN' => $admin->{'ldap-admin-dn'},
121             'adminPassword' => $admin->{'ldap-admin-password'},
122             'prefix' => 'ldap-user-',
123             'serverip' => $prefs->{'ldap-prefs-serverip'},
124             'serverport' => $prefs->{'ldap-prefs-serverport'},
125             %$attr);
126             $user->CreateMe(1);
127             $self->{'user'} = $user;
128             $self->Store($wiz);
129             $self->ShowMe($wiz, $prefs, $user);
130             }
131              
132             sub Action_UserSave {
133             my($self, $wiz) = @_;
134             my ($prefs, $admin, $user) = $self->init(1);
135             my $base = $prefs->{'ldap-prefs-userbase'};
136             my $oldlogin = $user->{'ldap-user-uid'} || '';
137              
138             foreach my $opt ($wiz->param()) {
139             $user->{$opt} = $wiz->param($opt)
140             if (($opt =~ /^ldap\-user/) && (defined($wiz->param($opt))));
141             }
142              
143             # Verify settings
144             my $errors = '';
145             my $login = $user->{'ldap-user-uid'}
146             or ($errors .= "Missing user login.\n");
147             my $pwd = $user->{'ldap-user-userpassword'};
148             $errors .= "Empty user password.\n"
149             if $pwd eq '' && $prefs->{'ldap-prefs-passwordcheck'};
150             my $uid = $user->{'ldap-user-uidnumber'}
151             or ($errors .= "Missing user UID (internal error).\n");
152             my $gid = $user->{'ldap-user-gidnumber'}
153             or ($errors .= "Missing user GID (internal error).\n");
154             my $home = $user->{'ldap-user-homedirectory'}
155             or ($errors .= "Missing user home (internal error).\n");
156             my $name = $user->{'ldap-user-cn'}
157             or ($errors .= "Missing users name.\n");
158             my $status = $user->{'ldap-user-status'}
159             or ($errors .= "Missing users status.\n");
160             my $mail = $user->{'ldap-user-mail'}
161             or ($errors .= "Missing users email adress.\n");
162             $mail .= $prefs->{'ldap-prefs-domain'} unless $mail =~ /\@/;
163             my $mailforward = $user->{'ldap-user-mailforward'};
164             my $mailforwardtype = $user->{'ldap-user-mailforwardtype'};
165             $user->{'ldap-user-objectClass'} = 'posixAccount';
166             $errors .= "Invalid login name: $login.\n"
167             unless ($login =~ /^[\d\w]{1,8}$/);
168             $errors .= "Invalid status: $status.\n"
169             unless exists($RESOLVE_SHELL->{$status});
170             die $errors if $errors;
171             $user->{'ldap-user-maildrop'} = $login;
172             $user->{'ldap-user-maildrop'} = $mailforward
173             if(($mailforwardtype eq 'always') && ($mailforward ne ''));
174              
175             $user->{'ldap-user-gecos'} = $name;
176             $user->{'ldap-user-loginshell'} = $RESOLVE_SHELL->{$status};
177             $user->{'ldap-user-homedirectory'} = $prefs->{'ldap-prefs-home'} . '/' . $login;
178             $user->AttrScalar2Ref('mail', 'mailforward', 'maildrop');
179              
180             my $cmd;
181             if ($user->CreateMe()) {
182             $prefs->{'ldap-prefs-nextuid'} = $uid + 1;
183             $prefs->Modified(1);
184             $cmd = $prefs->{'ldap-prefs-userchange-new'};
185             } else {
186             $cmd = $prefs->{'ldap-prefs-userchange-modify'};
187             }
188             $user->DN('cn=' . $login . ', ' . $base);
189              
190             $cmd =~ s/\$olduid\b/$oldlogin/g;
191             $cmd =~ s/\$(\w+)/$user->{"ldap-user-$1"}/g;
192             my $opts = delete $user->{'_options'} || {};
193             my $opt = delete $user->{'ldap-user-chooseopt'} || '';
194             $opt = $opts->{$opt} if exists($opts->{$opt});
195             my $program = $cmd;
196             $program =~ s/\s.*//;
197             print STDERR "LDAP wizard: Running command $cmd\n";
198             my $str = `$cmd 2>&1` if -x $program;
199             if (defined($str)) {
200             my $opts = $user->{'_options'} = {};
201             my $items = [];
202             my $msg = '';
203             foreach my $line (split(/\n/, $str)) {
204             next if $line =~ /^\s*$/;
205             if ($line =~ /^Message:\s*(.*)$/) {
206             $msg .= "$1
\n";
207             } elsif ($line =~ /^Option\:\s*(.*)=(.*?)\s*$/) {
208             $opts->{$2} = "--$1";
209             push(@$items, $2);
210             } else {
211             die "Executing command $cmd failed:\n$str\n";
212             }
213             }
214             if (@$items) {
215             $self->Store($wiz);
216             return $self->ChooseMenu($wiz, $items, $msg) if @$items;
217             }
218             }
219              
220             $user->Modified(1);
221             $self->Store($wiz, 1);
222             $self->Action_Reset($wiz);
223             }
224              
225             sub ChooseMenu {
226             my($self, $wiz, $items, $msg) = @_;
227             (['Wizard::Elem::Title', 'value' => "LDAP Wizard User: Decision required"],
228             ['Wizard::Elem::Message', 'msg' => $msg],
229             ['Wizard::Elem::Select', 'options' => [@$items],
230             'name' => 'ldap-user-chooseopt',
231             'descr' => 'Select how to proceed'],
232             ['Wizard::Elem::Submit', 'value' => 'Proceed',
233             'name' => 'Action_UserSave',
234             'id' => 1]);
235             }
236              
237              
238             sub Action_ModifyUser {
239             my $self = shift; my $wiz = shift;
240             my $button = shift || 'Modify User';
241             my $action = shift || 'Action_EditUser';
242             my ($prefs, $admin) = $self->init();
243             my $base = $prefs->{'ldap-prefs-userbase'};
244              
245             my @items = $self->ItemList($prefs, $admin,
246             $prefs->{'ldap-prefs-userbase'}, 'uid');
247             return $self->Action_Reset($wiz) unless @items;
248             if(@items == 1) {
249             $wiz->param('ldap-user', $items[0]);
250             return $self->$action($wiz);
251             }
252             @items = sort @items;
253            
254             # Return the initial menu.
255             (['Wizard::Elem::Title', 'value' => "LDAP Wizard User Selection"],
256             ['Wizard::Elem::Select', 'options' => \@items, 'name' => 'ldap-user',
257             'descr' => 'Select an user'],
258             ['Wizard::Elem::Submit', 'value' => $button, 'name' => $action,
259             'id' => 1]);
260             }
261              
262             sub Load {
263             my($self, $wiz, $prefs, $admin, $dn) = @_;
264             my $user = Wizard::SaveAble::LDAP->new('adminDN' => $admin->{'ldap-admin-dn'},
265             'adminPassword' => $admin->{'ldap-admin-password'},
266             'prefix' => 'ldap-user-',
267             'serverip' => $prefs->{'ldap-prefs-serverip'},
268             'serverport' => $prefs->{'ldap-prefs-serverport'},
269             'dn' => $dn, 'load' => 1);
270             $user->DN($dn);
271             $self->{'user'} = $user;
272             $self->Store($wiz);
273             $user->AttrRef2Scalar('mail', 'mailforward');
274             $user;
275             }
276              
277              
278             sub Action_EditUser {
279             my($self, $wiz) = @_;
280             my($prefs, $admin) = $self->init();
281             my $login = $wiz->param('ldap-user') || die "Missing login.";
282             my $dn = "cn=$login, " . $prefs->{'ldap-prefs-userbase'};
283             my $user = $self->Load($wiz, $prefs, $admin, $dn);
284             $self->ShowMe($wiz, $prefs, $user);
285             }
286              
287             sub Action_DeleteUser {
288             shift->Action_ModifyUser(shift, 'Delete user', 'Action_DeleteUser2');
289             }
290              
291             sub Action_DeleteUser2 {
292             my ($self, $wiz) = @_;
293             my($prefs, $admin) = $self->init();
294             my $login = $wiz->param('ldap-user') || die "Missing login.";
295             my $dn = "cn=$login, " . $prefs->{'ldap-prefs-userbase'};
296             my $user = $self->Load($wiz, $prefs, $admin, $dn);
297            
298             (['Wizard::Elem::Title', 'value' => 'Deleting an LDAP user'],
299             ['Wizard::Elem::Data', 'descr' => 'Users login',
300             'value' => $user->{'ldap-user-uid'}],
301             ['Wizard::Elem::Data',
302             'value' => $user->{'ldap-user-userpassword'},
303             'descr' => 'Users password'],
304             ['Wizard::Elem::Data',
305             'value' => $user->{'ldap-user-uidnumber'},
306             'descr' => 'Users UID'],
307             ['Wizard::Elem::Data',
308             'value' => $user->{'ldap-user-gidnumber'},
309             'descr' => 'Users GID'],
310             ['Wizard::Elem::Data',
311             'value' => $user->{'ldap-user-homedirectory'},
312             'descr' => 'Users home'],
313             ['Wizard::Elem::Data',
314             'value' => $user->{'ldap-user-cn'},
315             'descr' => 'Users name'],
316             ['Wizard::Elem::Data',
317             'value' => $user->{'ldap-user-description'},
318             'descr' => 'Users logical group'],
319             ['Wizard::Elem::Data',
320             'value' => $user->{'ldap-user-mail'},
321             'descr' => 'Users email adress'],
322             ['Wizard::Elem::Data',
323             'value' => $user->{'ldap-user-mailforwardtype'},
324             'descr' => 'Users email forward type'],
325             ['Wizard::Elem::Data',
326             'value' => $user->{'ldap-user-mailforward'},
327             'descr' => 'Users email forward adress'],
328             ['Wizard::Elem::Data',
329             'value' => $user->{'ldap-user-pop3box'},
330             'descr' => 'External POP3 box to fetch mail from'],
331             ['Wizard::Elem::Data',
332             'value' => $user->{'ldap-user-pop3password'},
333             'descr' => 'Password of the external POP3'],
334             ['Wizard::Elem::Data',
335             'value' => $user->{'ldap-user-status'},
336             'descr' => 'Users status'],
337             ['Wizard::Elem::Data',
338             'value' => $user->{'ldap-user-loginshell'},
339             'descr' => 'Users login shell'],
340             ['Wizard::Elem::Submit', 'value' => 'Yes, delete it',
341             'id' => 1, 'name' => 'Action_DeleteUser3'],
342             ['Wizard::Elem::Submit', 'value' => 'Return to User Menu',
343             'id' => 98, 'name' => 'Action_Reset'],
344             ['Wizard::Elem::Submit', 'value' => 'Return to Top Menu',
345             'id' => 99, 'name' => 'Wizard::LDAP::Action_Reset']);
346             }
347              
348             sub Action_DeleteUser3 {
349             my($self, $wiz) = @_;
350             my($prefs, $admin, $user) = $self->init(1);
351             $user->Delete();
352             $self->OnChange('user', '-delete', {'user' => $user->{'ldap-user-uid'}, 'options' =>
353             ''});
354             $self->Action_Reset($wiz);
355             }