File Coverage

blib/lib/Plugtools.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Plugtools;
2              
3 1     1   21522 use warnings;
  1         3  
  1         29  
4 1     1   5 use strict;
  1         2  
  1         28  
5 1     1   402 use Config::IniHash;
  0            
  0            
6             use File::BaseDir qw/xdg_config_home/;
7             use Sys::User::UIDhelper;
8             use Sys::Group::GIDhelper;
9             use Net::LDAP;
10             use Net::LDAP::posixAccount;
11             use Net::LDAP::posixGroup;
12             use String::ShellQuote;
13             use Net::LDAP::Extension::SetPassword;
14              
15             =head1 NAME
16              
17             Plugtools - LDAP and Posix
18              
19             =head1 VERSION
20              
21             Version 1.3.0
22              
23             =cut
24              
25             our $VERSION = '1.3.0';
26              
27              
28             =head1 SYNOPSIS
29              
30             use Plugtools;
31              
32             my $pt = Plugtools->new();
33             ...
34              
35             =head1 METHODS
36              
37             =head2 new
38              
39             Initiate Plugtools.
40              
41             Only one arguement is accepted and that is a hash.
42              
43             =head3 args hash
44              
45             At this time, none of these values are required.
46              
47             =head4 config
48              
49             This specifies a config file to read other than the default.
50              
51             #initilize it and read the default config
52             my $pt=Plugtools->new();
53             if($pt->{error}){
54             print "Error!\n";
55             }
56              
57             #initilize it and read '/some/config'
58             my $pt=Plugtools->new({ config=>'/some/config' });
59             if($pt->{error}){
60             print "Error!\n";
61             }
62              
63             =cut
64              
65             sub new {
66             my %args;
67             if(defined($_[1])){
68             %args= %{$_[1]};
69             };
70              
71             my $self = {error=>undef, errorString=>"", module=>'Plugtools'};
72             bless $self;
73              
74             if (!defined($args{config})) {
75             $args{config}=xdg_config_home().'/plugtoolsrc';
76             }
77              
78             $self->readConfig($args{config});
79              
80             return $self;
81             }
82              
83             =head2 addGroup
84              
85             =head3 args hash
86              
87             =head4 group
88              
89             This is the group name to add.
90              
91             =head4 gid
92              
93             This is the numeric ID of the group to add. If it is
94             not defined, it will automatically be added.
95              
96             =head4 dump
97              
98             If this is true, call the dump method on the create Net::LDAP::Entry object.
99              
100             #the most basic form
101             $pt->addGroup({
102             group=>'someGroup',
103             })
104             if($pt->{errpr}){
105             print "Error!\n";
106             }
107              
108             #do more
109             $pt->addGroup({
110             group=>'someGroup',
111             gid=>'4444',
112             dump=>'1',
113             })
114             if($pt->{errpr}){
115             print "Error!\n";
116             }
117              
118             =cut
119              
120             sub addGroup{
121             my $self=$_[0];
122             my %args;
123             if(defined($_[1])){
124             %args= %{$_[1]};
125             };
126              
127             #blanks any previous errors
128             $self->errorblank;
129              
130             #error if we don't have a group name
131             if (!defined($args{group})) {
132             $self->{error}=6;
133             $self->{errorString}='No group name specified';
134             warn('Plugtools addGroup:6: '.$self->{errorString});
135             return undef;
136             }
137              
138             #error if the user already exists
139             my ($gname,$gpasswd,$gid,$members) = getgrnam($args{group});
140             if (defined($gname)) {
141             $self->{error}=10;
142             $self->{errorString}='The group "'.$args{group}.'" already exists';
143             warn('Plugtools addUser:10: '.$self->{errorString});
144             return undef;
145             }
146              
147             #if we don't have a GID, find the first free one
148             if (!defined($args{gid})) {
149             my $gidhelper=Sys::Group::GIDhelper->new({min=>$self->{ini}->{''}->{GIDstart}});
150             my $gid=$gidhelper->firstfree();
151             if (!defined($gid)) {
152             $self->{error}=4;
153             $self->{errorString}='Could not locate a free GID';
154             warn('Plugtools addUser:4: '.$self->{errorString});
155             return undef;
156             }
157             $args{gid}=$gid;
158             }
159              
160             ($gname,$gpasswd,$gid,$members) = getgrnam($args{gid});
161             if (defined($gid)) {
162             $self->{error}=20;
163             $self->{errorString}='The GID "'.$args{gid}.'" already exists.';
164             warn('Plugtools addGroup:20: '.$self->{error});
165             return undef;
166             }
167              
168             #make sure the GID is complete numeric
169             if (!($args{gid}=~/^[0123456789]*$/)) {
170             $self->{error}=8;
171             $self->{errorString}='The specified GID, "'.$args{gid}.'", is not numeric';
172             warn('Plugtools addUser:8: '.$self->{errorString});
173             return undef;
174             }
175              
176             #initiates the Net::LDAP::posixAccount
177             my $entrycreator=Net::LDAP::posixGroup->new({ baseDN=>$self->{ini}->{''}->{groupbase} });
178             if ((!defined($entrycreator))||(defined($entrycreator->{error}))) {
179             $self->{error}=12;
180             if(!defined($entrycreator)){
181             $self->{errorString}='Net::LDAP::posixGroup->create returned a undefined object';
182             }else {
183             $self->{errorString}='Net::LDAP::posixGroup->create errored. error="'.
184             $entrycreator->{error}.'" errorString="'.
185             $entrycreator->{errorString}.'"';
186             }
187             warn('Plugtools addGroup:12: '.$self->{errorString});
188             return undef;
189             }
190             my $entry=$entrycreator->create({
191             name=>$args{group},
192             gid=>$args{gid},
193             primary=>$self->{ini}->{''}->{groupPrimary},
194             });
195             if (defined($entrycreator->{error})) {
196             $self->{error}=12;
197             $self->{errorString}='Net::LDAP::posixGroup->create errored. error="'.
198             $entrycreator->{error}.'" errorString="'.
199             $entrycreator->{errorString}.'"';
200             warn('Plugtools addGroup:12: '.$self->{errorString});
201             return undef;
202             }
203              
204             #dump it if asked
205             if ($args{dump}) {
206             $entry->dump;
207             }
208              
209             #connect to the LDAP server
210             my $ldap=$self->connect();
211             if ($self->{error}) {
212             warn('Plugtools addGroup: Failed to connect to LDAP');
213             return undef;
214             }
215              
216             #call a plugin if needed
217             if (defined($self->{ini}->{''}->{pluginAddGroup})) {
218             $self->plugin({
219             ldap=>$ldap,
220             entry=>$entry,
221             do=>'pluginAddGroup',
222             },
223             \%args);
224             if ($self->{error}) {
225             warn('Plugtools addGroup: plugin errored');
226             return undef;
227             }
228             }
229              
230             #add it
231             my $mesg=$entry->update($ldap);
232             if (!$mesg->{errorMessage} eq '') {
233             $self->{error}=19;
234             $self->{errorString}='$entry->update($ldap) failed. $mesg->{errorMessage}="'.
235             $mesg->{errorMessage}.'"';
236             warn('Plugtools addGroup:19: '.$self->{errorString});
237             return undef;
238             }
239            
240             return 1;
241             }
242              
243             =head2 addUser
244              
245             =head3 args hash
246              
247             =head4 user
248              
249             The user to create.
250              
251             =head4 uid
252              
253             The numeric user ID for the new user. If this is note defined,
254             the first free one will be used.
255              
256             =head4 group
257              
258             The primary group of user. If this is not defined, the username is
259             used. If the user is this is not defined, it will be set to the same
260             as the user.
261              
262             =head4 gid
263              
264             If this is defined, the specified GID will be used instead of automatically
265             assigning one.
266              
267             =head4 gecos
268              
269             The gecos field for the user. If this is not defined, it is set to
270             the user name.
271              
272             =head4 shell
273              
274             This is the shell for the user. If this is not defined, the default
275             one is used.
276              
277             =head4 home
278              
279             This is the home directory for the user. If this is not defined, the
280             home prototype is used.
281              
282             =head4 createHome
283              
284             If this is specified, the default value for createHome will be overrode the
285             defaults or what is specified in the config.
286              
287             If it exists, it assumes it does not need to be created, but it will still be
288             chowned.
289              
290             =head4 skel
291              
292             Use this instead of the default skeleton or the one specified in the config file.
293              
294             This is skipped, if the home already exists.
295              
296             =head4 chmodValue
297              
298             Overrides the default value for this or the one specified in the config.
299              
300             =head4 chmodHome
301              
302             Overrides the default value for this or the one specified in the config.
303              
304             =head4 chownHome
305              
306             If home should be chowned. This overrides the value specified in the
307             config or the default one.
308              
309             =head4 dump
310              
311             If this is true, call the dump method on the create Net::LDAP::Entry object.
312              
313             #the most basic form
314             $pt->addUser({
315             user=>'someUser',
316             })
317             if($pt->{errpr}){
318             print "Error!\n";
319             }
320              
321             #do more
322             $pt->addUser({
323             user=>'someUser',
324             uid=>'3333',
325             group=>'someGroup',
326             gid=>'4444',
327             dump=>'1',
328             })
329             if($pt->{errpr}){
330             print "Error!\n";
331             }
332              
333             =cut
334              
335             sub addUser{
336             my $self=$_[0];
337             my %args;
338             if(defined($_[1])){
339             %args= %{$_[1]};
340             };
341              
342             #blank any previous errors
343             $self->errorblank;
344              
345             #error if no user has been specified
346             if (!defined($args{user})) {
347             $self->{error}=5;
348             $self->{errorString}='No user name specified';
349             warn('Plugtools addUser:5: '.$self->{errorString});
350             return undef;
351             }
352              
353             #error if the user already exists
354             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($args{user});
355             if (defined($name)) {
356             $self->{error}=9;
357             $self->{errorString}='The user "'.$args{user}.'" already exists';
358             warn('Plugtools addUser:9: '.$self->{errorString});
359             return undef;
360             }
361              
362             #make sure we have gecos
363             if (!defined($args{gecos})) {
364             $args{gecos}=$args{user};
365             }
366              
367             #make sure we have a shell
368             if (!defined($args{shell})) {
369             $args{shell}=$self->{ini}->{''}->{defaultShell};
370             }
371              
372             #make sure we have a group name
373             if (!defined($args{group})) {
374             $args{group}=$args{user};
375             }
376              
377             #makes sure the UID is defined
378             if (!defined($args{uid})) {
379             #gets it if it not defined
380             my $uidhelper=Sys::User::UIDhelper->new({
381             min=>$self->{ini}->{''}->{UIDstart}
382             });
383             my $uid=$uidhelper->firstfree();
384             if (!defined($uid)) {
385             $self->{error}=3;
386             $self->{errorString}='Could not locate a free UID';
387             warn('Plugtools addUser:3: '.$self->{errorString});
388             return undef;
389             }
390             $args{uid}=$uid;
391             }
392              
393             #make sure the UID is complete numeric
394             if (!($args{uid}=~/^[0123456789]*$/)) {
395             $self->{error}=7;
396             $self->{errorString}='The specified UID, "'.$args{uid}.'", is not numeric';
397             warn('Plugtools addUser:7: '.$self->{errorString});
398             return undef;
399             }
400              
401             #check if the group exists or not
402             my ($gname,$gpasswd,$ggid,$members) = getgrnam($args{group});
403             if (!defined($gname)) {
404             $self->addGroup({
405             group=>$args{group},
406             gid=>$args{gid},
407             dump=>$args{dump},
408             });
409             if ($self->{error}) {
410             warn('Plugtools addUser: addGroup failed');
411             return undef;
412             }
413             }
414              
415             #gets the GID
416             ($gname,$gpasswd,$args{gid},$members) = getgrnam($args{group});
417              
418             #build the user
419             $args{home}=$self->{ini}->{''}->{HOMEproto};
420             $args{home}=~s/\%\%USERNAME\%\%/$args{user}/g;
421              
422             #initiates the Net::LDAP::posixAccount
423             my $entrycreator=Net::LDAP::posixAccount->new({ baseDN=>$self->{ini}->{''}->{userbase} });
424             my $entry=$entrycreator->create({
425             name=>$args{user},
426             uid=>$args{uid},
427             gid=>$args{gid},
428             home=>$args{home},
429             loginShell=>$args{shell},
430             primary=>$self->{ini}->{''}->{userPrimary},
431             });
432              
433             #connect to the LDAP server
434             my $ldap=$self->connect();
435             if ($self->{error}) {
436             warn('Plugtools addUser: Failed to connect to LDAP');
437             return undef;
438             }
439              
440             #call a plugin if needed
441             if (defined($self->{ini}->{''}->{pluginAddUser})) {
442             $self->plugin({
443             ldap=>$ldap,
444             entry=>$entry,
445             do=>'pluginAddUser',
446             },
447             \%args);
448             if ($self->{error}) {
449             warn('Plugtools addUser: plugin errored');
450             return undef;
451             }
452             }
453              
454             #add it
455             my $mesg=$entry->update($ldap);
456             if (!$mesg->{errorMessage} eq '') {
457             $self->{error}=19;
458             $self->{errorString}='$entry->update($ldap) failed. $mesg->{errorMessage}="'.
459             $mesg->{errorMessage}.'"';
460             warn('Plugtools addUser:19: '.$self->{errorString});
461             return undef;
462             }
463              
464             #dump it if needed
465             if ($args{dump}) {
466             $entry->dump;
467             }
468              
469             #create the home directory if needed, after getting the required values
470             if (!defined($args{createHome})) {
471             $args{createHome}=$self->{ini}->{''}->{createHome};
472             }
473             if (!defined($args{skel})) {
474             $args{skel}=$self->{ini}->{''}->{skeletonHome};
475             }
476             if (!defined($args{chownHome})) {
477             $args{chownHome}=$self->{ini}->{''}->{chownHome};
478             }
479             if (!defined($args{chmodHome})) {
480             $args{chmodHome}=$self->{ini}->{''}->{chmodHome};
481             }
482             if (!defined($args{chmodValue})) {
483             $args{chmodValue}=$self->{ini}->{''}->{chmodValue};
484             }
485             if ($args{createHome}) {
486             if (! -e $args{home}) {
487             #copy it
488             system( 'cp -r '.shell_quote($args{skel}).' '.shell_quote($args{home}) );
489             if ($? ne '0') {
490             $self->{error}=22;
491             $self->{errorString}='Copying home from "'.$args{skel}.'" to "'.$args{home}.'" failed';
492             warn('Plugtools addUser:22: '.$self->{errorString});
493             return undef;
494             }
495              
496             #chown it if needed
497             if ($args{chownHome}) {
498             system( 'chown -R '.shell_quote($args{user}).':'.shell_quote($args{group})
499             .' '.shell_quote($args{home}) );
500             if ($? ne '0') {
501             $self->{error}=23;
502             $self->{errorString}='Chowning "'.$args{home}.'" to "'.$args{chmodValue}.'" failed';
503             warn('Plugtools addUser:22: '.$self->{errorString});
504             return undef;
505             }
506             }
507              
508             #chmod it if needed
509             if ($args{chmodHome}) {
510             system( 'chmod -R '.shell_quote($args{chmodValue}).' '.shell_quote($args{home}) );
511             if ($? ne '0') {
512             $self->{error}=24;
513             $self->{errorString}='Chmoding "'.$args{home}.'" to "'.$args{chmodValue}.'" failed';
514             warn('Plugtools addUser:22: '.$self->{errorString});
515             return undef;
516             }
517             }
518             }
519             }
520              
521            
522              
523             return 1;
524             }
525              
526             =head2 connect
527              
528             This forms a LDAP connection using the information in
529             config file.
530              
531             my $ldap=$pt->connect;
532             if($pt->{error}){
533             print "Error!\n";
534             }
535              
536             =cut
537              
538             sub connect{
539             my $self=$_[0];
540              
541             #blanks any previous errors
542             $self->errorblank;
543              
544             #try to connect
545             my $ldap = Net::LDAP->new($self->{ini}->{''}->{server}, port=>$self->{ini}->{''}->{port});
546              
547             #check if it connected or not
548             if (!$ldap) {
549             $self->{error}=11;
550             $self->{errorString}='Failed to connect to LDAP';
551             warn('Plugtools connect:11: '.$self->{errorString});
552             return undef;
553             }
554              
555             #start TLS if it is needed
556             my $mesg;
557             if ($self->{ini}->{''}->{starttls}) {
558             $mesg=$ldap->start_tls(
559             verify=>$self->{ini}->{''}->{TLSverify},
560             sslversion=>$self->{ini}->{''}->{SSLversion},
561             ciphers=>$self->{ini}->{''}->{SSLciphers},
562             );
563              
564             if (!$mesg->{errorMessage} eq '') {
565             $self->{error}=13;
566             $self->{errorString}='$ldap->start_tls failed. $mesg->{errorMessage}="'.
567             $mesg->{errorMessage}.'"';
568             warn('Plugtools connect:13: '.$self->{errorString});
569             return undef;
570             }
571             }
572              
573             #bind
574             $mesg=$ldap->bind($self->{ini}->{''}->{bind},
575             password=>$self->{ini}->{''}->{pass},
576             );
577             if (!$mesg->{errorMessage} eq '') {
578             $self->{error}=13;
579             $self->{errorString}='Binding to the LDAP server failed. $mesg->{errorMessage}="'.
580             $mesg->{errorMessage}.'"';
581             warn('Plugtools connect:13: '.$self->{errorString});
582             return undef;
583             }
584              
585             return $ldap;
586             }
587              
588             =head2 deleteGroup
589              
590             This removes a group.
591              
592             $pt->deleteGroup('someGroup');
593             if($pt->{error}){
594             print "Error!\n";
595             }
596              
597             =cut
598              
599             sub deleteGroup{
600             my $self=$_[0];
601             my $group=$_[1];
602              
603             #blank any previous errors
604             $self->errorblank;
605              
606             #error if we don't have a group name
607             if (!defined($group)) {
608             $self->{error}=6;
609             $self->{errorString}='No group name specified';
610             warn('Plugtools deleteGroup:6: '.$self->{errorString});
611             return undef;
612             }
613              
614             #error if the user does not exists
615             my ($gname,$gpasswd,$gid,$members) = getgrnam($group);
616             if (!defined($gname)) {
617             $self->{error}=10;
618             $self->{errorString}='The group "'.$group.'" does not exist';
619             warn('Plugtools deleteGroup:10: '.$self->{errorString});
620             return undef;
621             }
622              
623             #connect to the LDAP server
624             my $ldap=$self->connect();
625             if ($self->{error}) {
626             warn('Plugtools deleteGroup: Failed to connect to LDAP');
627             return undef;
628             }
629              
630             #search and get the first entry
631             my $mesg=$ldap->search(
632             base=>$self->{ini}->{''}->{groupbase},
633             filter=>'(&(cn='.$group.') (gidNumber='.$gid.'))'
634             );
635             my $entry=$mesg->pop_entry;
636              
637             #if $entry is not defined or does not exist under the specified base
638             if (!defined($entry)) {
639             $self->{error}=15;
640             $self->{errorString}='The group "'.$group.'" does not exist in specified group base, "'.
641             $self->{ini}->{''}->{groupbase}.'", ';
642             warn('Plugtools findGroupDN:15: '.$self->{errorString});
643             return undef;
644             }
645              
646             #call a plugin if needed
647             if (defined($self->{ini}->{''}->{pluginDeleteGroup})) {
648             $self->plugin({
649             ldap=>$ldap,
650             entry=>$entry,
651             do=>'pluginDeleteGroup',
652             },
653             {
654             group=>$group,
655             });
656             if ($self->{error}) {
657             warn('Plugtools deleteGroup: plugin errored');
658             return undef;
659             }
660             }
661              
662             #delete the entry
663             $entry->delete();
664             $mesg=$entry->update($ldap);
665             if (!$mesg->{errorMessage} eq '') {
666             $self->{error}=13;
667             $self->{errorString}='Deleting entry "'.$entry->dn.'" failed. $mesg->{errorMessage}="'.
668             $mesg->{errorMessage}.'"';
669             warn('Plugtools connect:13: '.$self->{errorString});
670             return undef;
671             }
672            
673             return 1;
674             }
675              
676             =head2 deleteUser
677              
678             This removes a user.
679              
680             Only LDAP is touched at this time, so if a user is a member of a group
681             setup in '/etc/groups', then it won't be removed from that group.
682              
683             This does not remove the user's old home directory.
684              
685             =head3 arge hash
686              
687             'user' is the only required value.
688              
689             =head4 user
690              
691             This is the user to be removed.
692              
693             =head4 removeHome
694              
695             This removes the home directory of the user.
696              
697             =head4 removeGroup
698              
699             Remove the primary group if it is empty.
700              
701             #the most basic form
702             $pt->deleteUser({
703             user=>'someUser',
704             })
705             if($pt->{errpr}){
706             print "Error!\n";
707             }
708              
709             #do more
710             $pt->deleteUser({
711             user=>'someUser',
712             removeHome=>'1',
713             removeGroup=>'0',
714             })
715             if($pt->{errpr}){
716             print "Error!\n";
717             }
718              
719             =cut
720              
721             sub deleteUser{
722             my $self=$_[0];
723             my %args;
724             if(defined($_[1])){
725             %args= %{$_[1]};
726             };
727              
728             #blank any previous errors
729             $self->errorblank;
730              
731             #make sure a group if specifed
732             if (!defined($args{user})) {
733             $self->{error}=5;
734             $self->{errorString}='No user name specified';
735             warn('Plugtools deleteUser:5: '.$self->{errorString});
736             return undef;
737             }
738              
739             #error if the user already exists
740             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($args{user});
741             if (!defined($name)) {
742             $self->{error}=17;
743             $self->{errorString}='The user "'.$args{user}.'" does not exists';
744             warn('Plugtools deleteUser:17: '.$self->{errorString});
745             return undef;
746             }
747              
748             #check if the group exists or not
749             my ($gname,$gpasswd,$ggid,$members) = getgrgid($gid);
750             my $removeGroup=0;
751             #set the group to be removed if it exists
752             if (defined($ggid)) {
753             $removeGroup=1;
754             }
755              
756             #connect to the LDAP server
757             my $ldap=$self->connect();
758             if ($self->{error}) {
759             warn('Plugtools deleteUser: Failed to connect to LDAP');
760             return undef;
761             }
762              
763             #search and get the first entry
764             my $mesg=$ldap->search(
765             base=>$self->{ini}->{''}->{userbase},
766             filter=>'(&(uid='.$args{user}.') (uidNumber='.$uid.'))'
767             );
768             my $entry=$mesg->pop_entry;
769              
770             #if $entry is not defined or does not exist under the specified base
771             if (!defined($entry)) {
772             $self->{error}=18;
773             $self->{errorString}='The user "'.$args{user}.'" does not exist in specified group base, "'.
774             $self->{ini}->{''}->{userbase}.'", ';
775             warn('Plugtools deleteUser:18: '.$self->{errorString});
776             return undef;
777             }
778              
779             #we check this here as checking it after wards after deleting the user does not work
780             my $onlyMember;
781             if (!defined($args{removeGroup})) {
782             $args{removeGroup}=$self->{ini}->{''}->{removeGroup};
783             }
784             if ($args{removeGroup}) {
785             #check if it the only member of that group
786             $onlyMember=$self->onlyMember({
787             user=>$args{user},
788             group=>$gname,
789             });
790             if ($self->{error}) {
791             warn('Plugtools deleteUser: onlyMember errored');
792             return undef;
793             }
794             }
795              
796             #call a plugin if needed
797             if (defined($self->{ini}->{''}->{pluginDeleteUser})) {
798             $self->plugin({
799             ldap=>$ldap,
800             entry=>$entry,
801             do=>'pluginDeleteUser',
802             },
803             \%args);
804             if ($self->{error}) {
805             warn('Plugtools deleteUser: plugin errored');
806             return undef;
807             }
808             }
809              
810              
811             #delete the entry
812             $entry->delete();
813             $mesg=$entry->update($ldap);
814             if (!$mesg->{errorMessage} eq '') {
815             $self->{error}=13;
816             $self->{errorString}='Deleting entry "'.$entry->dn.'" failed. $mesg->{errorMessage}="'.
817             $mesg->{errorMessage}.'"';
818             warn('Plugtools deleteUser:13: '.$self->{errorString});
819             return undef;
820             }
821              
822             #remove the primary group if requested...
823             if ($args{removeGroup}) {
824             #proceede further if it is the only member
825             if ($onlyMember) {
826             #figure out if it is a LDAP group or not
827             my $returned=$self->isLDAPgroup($gname);
828             if ($self->{error}) {
829             warn('Plugtools deleteUser: isLDAPgroup errored');
830             return undef;
831             }
832             #if it is a LDAP group, remove it
833             if ($returned) {
834             $self->deleteGroup($gname);
835             if ($self->{error}) {
836             warn('Plugtools deleteUser: deleteGroup failed');
837             return undef;
838             }
839             }
840             }
841             }
842              
843             #remove the user from what ever groups they are in, in LDAP
844             $self->removeUserFromGroups($args{user});
845             if ($self->{error}) {
846             warn('Plugtools deleteUser: removeUserFromGroups failed');
847             return undef;
848             }
849              
850             #remove the primary group if requested...
851             if (!defined($args{removeHome})) {
852             $args{removeHome}=$self->{ini}->{''}->{removeHome};
853             }
854             if ($args{removeHome}) {
855             system( 'rm -rf '.shell_quote($dir) );
856             if ($? ne '0') {
857             $self->{error}=26;
858             $self->{errorString}='rm -rf '.shell_quote($dir).' has failed failed';
859             warn('Plugtools deleteUser:26: '.$self->{errorString});
860             return undef;
861             }
862             }
863            
864             return 1;
865             }
866              
867             =head2 findGroupDN
868              
869             This locates a DN for a already setup group.
870              
871             my $dn=$pt->findGroupDN('someGroup');
872             if($pt->{error}){
873             print "Error!";
874             }
875              
876             =cut
877              
878             sub findGroupDN{
879             my $self=$_[0];
880             my $group=$_[1];
881              
882             #blank any previous errors
883             $self->errorblank;
884              
885             #make sure a group if specifed
886             if (!defined($group)) {
887             $self->{error}=6;
888             $self->{errorString}='No group name specified';
889             warn('Plugtools findGroupDN:6: '.$self->{errorString});
890             return undef;
891             }
892              
893             #error if the user does not exists
894             my ($gname,$gpasswd,$gid,$members) = getgrnam($group);
895             if (!defined($gname)) {
896             $self->{error}=14;
897             $self->{errorString}='The group "'.$group.'" does not exist';
898             warn('Plugtools findGroupDN:14: '.$self->{errorString});
899             return undef;
900             }
901            
902             #connect to the LDAP server
903             my $ldap=$self->connect();
904             if ($self->{error}) {
905             warn('Plugtools findGroupDN: Failed to connect to LDAP');
906             return undef;
907             }
908              
909             #search and get the first entry
910             my $mesg=$ldap->search(
911             base=>$self->{ini}->{''}->{groupbase},
912             filter=>'(&(cn='.$group.') (gidNumber='.$gid.'))'
913             );
914             my $entry=$mesg->pop_entry;
915              
916             #if $entry is not defined or does not exist under the specified base
917             if (!defined($entry)) {
918             $self->{error}=15;
919             $self->{errorString}='The group "'.$group.'" does not exist in specified group base, "'.
920             $self->{ini}->{''}->{groupbase}.'", ';
921             warn('Plugtools findGroupDN:15: '.$self->{errorString});
922             return undef;
923             }
924            
925             #if we get here, it means we have a entry... thus we have a DN
926             return $entry->dn;
927             }
928              
929             =head2 findUserDN
930              
931             This locates a DN for a already setup group.
932              
933             my $dn=$pt->findUserDN('someUser');
934             if($pt->{error}){
935             print "Error!";
936             }
937              
938             =cut
939              
940             sub findUserDN{
941             my $self=$_[0];
942             my $user=$_[1];
943              
944             #blank any previous errors
945             $self->errorblank;
946              
947             #make sure a group if specifed
948             if (!defined($user)) {
949             $self->{error}=5;
950             $self->{errorString}='No user name specified';
951             warn('Plugtools findUserDN:5: '.$self->{errorString});
952             return undef;
953             }
954              
955             #error if the user already exists
956             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user);
957             if (!defined($name)) {
958             $self->{error}=17;
959             $self->{errorString}='The user "'.$user.'" does not exists';
960             warn('Plugtools findUserDN:17: '.$self->{errorString});
961             return undef;
962             }
963            
964             #connect to the LDAP server
965             my $ldap=$self->connect();
966             if ($self->{error}) {
967             warn('Plugtools findUserDN: Failed to connect to LDAP');
968             return undef;
969             }
970              
971             #search and get the first entry
972             my $mesg=$ldap->search(
973             base=>$self->{ini}->{''}->{userbase},
974             filter=>'(&(uid='.$user.') (uidNumber='.$uid.'))'
975             );
976             my $entry=$mesg->pop_entry;
977              
978             #if $entry is not defined or does not exist under the specified base
979             if (!defined($entry)) {
980             $self->{error}=18;
981             $self->{errorString}='The user "'.$user.'" does not exist in specified group base, "'.
982             $self->{ini}->{''}->{userbase}.'", ';
983             warn('Plugtools findUserDN:18: '.$self->{errorString});
984             return undef;
985             }
986            
987             #if we get here, it means we have a entry... thus we have a DN
988             return $entry->dn;
989             }
990              
991             =head2 getUserEntry
992              
993             Fetch a Net::LDAP::Entry object of a user.
994              
995             =head3 args hash
996              
997             =head4 user
998              
999             This is the user to fetch a Net::LDAP::Entry
1000             of.
1001              
1002             my $entry=$pt->getUserEntry({
1003             user=>'someUser',
1004             });
1005             if($pt->{error}){
1006             print "Error!\n";
1007             }
1008              
1009             =cut
1010              
1011             sub getUserEntry{
1012             my $self=$_[0];
1013             my %args;
1014             if(defined($_[1])){
1015             %args= %{$_[1]};
1016             };
1017              
1018              
1019             #blank any previous errors
1020             $self->errorblank;
1021              
1022             #error if we don't have a group name
1023             if (!defined($args{user})) {
1024             $self->{error}=5;
1025             $self->{errorString}='No user name specified';
1026             warn('Plugtools getUserEntry:5: '.$self->{errorString});
1027             return undef;
1028             }
1029              
1030             #error if the user already exists
1031             my ($name,$passwd,$uid,$gid,$quota,$comment,$gecos,$dir,$shell,$expire) = getpwnam($args{user});
1032             if (!defined($name)) {
1033             $self->{error}=17;
1034             $self->{errorString}='The user "'.$args{user}.'" does not exists';
1035             warn('Plugtools getUserEntry:17: '.$self->{errorString});
1036             return undef;
1037             }
1038              
1039             #connect to the LDAP server
1040             my $ldap=$self->connect();
1041             if ($self->{error}) {
1042             warn('Plugtools getUserEntry: Failed to connect to LDAP');
1043             return undef;
1044             }
1045              
1046             #search and get the first entry
1047             my $mesg=$ldap->search(
1048             base=>$self->{ini}->{''}->{userbase},
1049             filter=>'(&(uid='.$args{user}.') (uidNumber='.$uid.'))'
1050             );
1051             if (!$mesg->{errorMessage} eq '') {
1052             $self->{error}=32;
1053             $self->{errorString}='Fetching the entry for the user failed under "'.
1054             $self->{ini}->{''}->{userbase}.'"'.
1055             $mesg->{errorMessage}.'"';
1056             warn('Plugtools userGIDchange:32: '.$self->{errorString});
1057             return undef;
1058             }
1059             my $entry=$mesg->pop_entry;
1060              
1061             if (!defined($entry)) {
1062             $self->{error}=18;
1063             $self->{errorString}='The user "'.$args{user}.'" was not found under'.
1064             'the base "'.$self->{ini}->{''}->{userbase}.'"';
1065             warn('Plugtools getUserEntry:18: '.$self->{errorString});
1066             return undef;
1067             }
1068              
1069             return $entry;
1070             }
1071              
1072             =head2 groupAddUser
1073              
1074             This adds a user from a group.
1075              
1076             =head3 args hash
1077              
1078             =head4 group
1079              
1080             The group to act on.
1081              
1082             =head4 user
1083              
1084             The user to act remove from the group.
1085              
1086             =head4 dump
1087              
1088             Call the dump method on the entry afterwards.
1089              
1090             $pt->groupAddUser({
1091             group=>'someGroup',
1092             user=>'someUser',
1093             })
1094             if($pt->{errpr}){
1095             print "Error!\n";
1096             }
1097              
1098             =cut
1099              
1100             sub groupAddUser{
1101             my $self=$_[0];
1102             my %args;
1103             if(defined($_[1])){
1104             %args= %{$_[1]};
1105             };
1106              
1107             #blank any previous errors
1108             $self->errorblank;
1109              
1110             #error if we don't have a group name
1111             if (!defined($args{group})) {
1112             $self->{error}=6;
1113             $self->{errorString}='No group name specified';
1114             warn('Plugtools groupAddUser:6: '.$self->{errorString});
1115             return undef;
1116             }
1117              
1118             #error if no user has been specified
1119             if (!defined($args{user})) {
1120             $self->{error}=5;
1121             $self->{errorString}='No user name specified';
1122             warn('Plugtools groupAddUser:5: '.$self->{errorString});
1123             return undef;
1124             }
1125              
1126             #error if the user does not exists
1127             my ($gname,$gpasswd,$gid,$members) = getgrnam($args{group});
1128             if (!defined($gname)) {
1129             $self->{error}=14;
1130             $self->{errorString}='The group "'.$args{group}.'" does not exist';
1131             warn('Plugtools groupAddUser:14: '.$self->{errorString});
1132             return undef;
1133             }
1134              
1135             #connect to the LDAP server
1136             my $ldap=$self->connect();
1137             if ($self->{error}) {
1138             warn('Plugtools groupAddUser: Failed to connect to LDAP');
1139             return undef;
1140             }
1141              
1142             #search and get the first entry
1143             my $mesg=$ldap->search(
1144             base=>$self->{ini}->{''}->{groupbase},
1145             filter=>'(&(cn='.$args{group}.') (gidNumber='.$gid.'))'
1146             );
1147             if (!$mesg->{errorMessage} eq '') {
1148             $self->{error}=27;
1149             $self->{errorString}='Fetching a list of posixGroup objects under "'.
1150             $self->{ini}->{''}->{groupbase}.'"'.
1151             $mesg->{errorMessage}.'"';
1152             warn('Plugtools groupAddUser:27: '.$self->{errorString});
1153             return undef;
1154             }
1155             my $entry=$mesg->pop_entry;
1156            
1157             #if $entry is not defined or does not exist under the specified base
1158             if (!defined($entry)) {
1159             $self->{error}=15;
1160             $self->{errorString}='The group "'.$args{group}.'" does not exist in specified group base, "'.
1161             $self->{ini}->{''}->{groupbase}.'", ';
1162             warn('Plugtools groupAddUser:15: '.$self->{errorString});
1163             return undef;
1164             }
1165              
1166             $entry->add(memberUid=>$args{user});
1167              
1168             #call a plugin if needed
1169             if (defined($self->{ini}->{''}->{pluginGroupAddUser})) {
1170             $self->plugin({
1171             ldap=>$ldap,
1172             entry=>$entry,
1173             do=>'pluginGroupAddUser',
1174             },
1175             \%args);
1176             if ($self->{error}) {
1177             warn('Plugtools groupAddUser: plugin errored');
1178             return undef;
1179             }
1180             }
1181              
1182             #update the entry
1183             my $mesg2=$entry->update($ldap);
1184             if (!$mesg2->{errorMessage} eq '') {
1185             $self->{error}=13;
1186             $self->{errorString}='Adding the user, "'.$args{user}.'", to "'.$entry->dn.'" failed. $mesg2->{errorMessage}="'.
1187             $mesg2->{errorMessage}.'"';
1188             warn('Plugtools groupAddUser:13: '.$self->{errorString});
1189             return undef;
1190             }
1191              
1192             #dump the entry if asked
1193             if ($args{dump}) {
1194             $entry->dump;
1195             }
1196              
1197             return 1;
1198             }
1199              
1200             =head2 groupGIDchange
1201              
1202             This changes the GID for a group.
1203              
1204             =head3 args hash
1205              
1206             =head4 group
1207              
1208             The group to act on.
1209              
1210             =head4 gid
1211              
1212             The GID to change this group to.
1213              
1214             =head4 userUpdate
1215              
1216             Update any user that has the old GID as their primary GID. This defaults to
1217             true, '1'.
1218              
1219             =head4 dump
1220              
1221             Call the dump method on the group afterwards.
1222              
1223             $pt->groupGIDchange({
1224             group=>'someGroup',
1225             gid=>'2222',
1226             })
1227             if($pt->{errpr}){
1228             print "Error!\n";
1229             }
1230              
1231              
1232             =cut
1233              
1234             sub groupGIDchange {
1235             my $self=$_[0];
1236             my %args;
1237             if(defined($_[1])){
1238             %args= %{$_[1]};
1239             };
1240              
1241             #blank any previous errors
1242             $self->errorblank;
1243              
1244             #error if we don't have a group name
1245             if (!defined($args{group})) {
1246             $self->{error}=6;
1247             $self->{errorString}='No group name specified';
1248             warn('Plugtools groupGIDchange:6: '.$self->{errorString});
1249             return undef;
1250             }
1251              
1252             #error if no user has been specified
1253             if (!defined($args{gid})){
1254             $self->{error}=28;
1255             $self->{errorString}='No GID specified';
1256             warn('Plugtools groupGIDchange:28: '.$self->{errorString});
1257             return undef;
1258             }
1259              
1260             #make sure the GID is complete numeric
1261             if (!($args{gid}=~/^[0123456789]*$/)) {
1262             $self->{error}=8;
1263             $self->{errorString}='The specified GID, "'.$args{gid}.'", is not numeric';
1264             warn('Plugtools groupGIDchange:8: '.$self->{errorString});
1265             return undef;
1266             }
1267              
1268             #error if the user does not exists
1269             my ($gname,$gpasswd,$gid,$members) = getgrnam($args{group});
1270             if (!defined($gname)) {
1271             $self->{error}=14;
1272             $self->{errorString}='The group "'.$args{group}.'" does not exist';
1273             warn('Plugtools groupGIDchange:14: '.$self->{errorString});
1274             return undef;
1275             }
1276              
1277             #connect to the LDAP server
1278             my $ldap=$self->connect();
1279             if ($self->{error}) {
1280             warn('Plugtools groupGIDchange: Failed to connect to LDAP');
1281             return undef;
1282             }
1283              
1284             #search and get the first entry
1285             my $mesg=$ldap->search(
1286             base=>$self->{ini}->{''}->{groupbase},
1287             filter=>'(&(cn='.$args{group}.') (gidNumber='.$gid.'))'
1288             );
1289             if (!$mesg->{errorMessage} eq '') {
1290             $self->{error}=27;
1291             $self->{errorString}='Fetching a list of posixGroup objects under "'.
1292             $self->{ini}->{''}->{groupbase}.'"'.
1293             $mesg->{errorMessage}.'"';
1294             warn('Plugtools groupGIDchange:27: '.$self->{errorString});
1295             return undef;
1296             }
1297             my $entry=$mesg->pop_entry;
1298            
1299             #if $entry is not defined or does not exist under the specified base
1300             if (!defined($entry)) {
1301             $self->{error}=15;
1302             $self->{errorString}='The group "'.$args{group}.'" does not exist in specified group base, "'.
1303             $self->{ini}->{''}->{groupbase}.'", ';
1304             warn('Plugtools groupGIDchange:15: '.$self->{errorString});
1305             return undef;
1306             }
1307              
1308             $entry->delete(gidNumber=>$gid);
1309             $entry->add(gidNumber=>$args{gid});
1310              
1311             #call a plugin if needed
1312             if (defined($self->{ini}->{''}->{pluginGroupGIDchange})) {
1313             $self->plugin({
1314             ldap=>$ldap,
1315             entry=>$entry,
1316             do=>'pluginGroupGIDchange',
1317             },
1318             \%args);
1319             if ($self->{error}) {
1320             warn('Plugtools groupGIDchange: plugin errored');
1321             return undef;
1322             }
1323             }
1324              
1325             #update the entry
1326             my $mesg2=$entry->update($ldap);
1327             if (!$mesg2->{errorMessage} eq '') {
1328             $self->{error}=29;
1329             $self->{errorString}='Updating the GID from "'.$gid.'" to "'.$args{gid}.
1330             '" for "'.$entry->dn.'" failed. $mesg2->{errorMEssage}="'.
1331             $mesg2->{errorMessage}.'"';
1332             warn('Plugtools groupGIDchange:29: '.$self->{errorString});
1333             return undef;
1334             }
1335              
1336             #dump the entry if asked
1337             if ($args{dump}) {
1338             $entry->dump;
1339             }
1340              
1341             #return successfully now if don't have to update any possible users
1342             if (!defined($args{userUpdate})) {
1343             $args{userUpdate}=$self->{ini}->{''}->{userUpdate};
1344             }
1345             if (!$args{userUpdate}) {
1346             return 1;
1347             }
1348              
1349             #we now do another search for the purpose of updating any users with the old GID
1350             my $mesg3=$ldap->search(
1351             base=>$self->{ini}->{''}->{userbase},
1352             filter=>'(&(objectClass=posixAccount) (gidNumber='.$gid.'))'
1353             );
1354             if (!$mesg->{errorMessage} eq '') {
1355             $self->{error}=37;
1356             $self->{errorString}='The search for posixAccounts entries that need updating failed. base="'.
1357             $self->{ini}->{''}->{userbase}.'" $mesg3->{errorMessage}="'.
1358             $mesg3->{errorMessage}.'"';
1359             warn('Plugtools groupGIDchange:37: '.$self->{errorString});
1360             return undef;
1361             }
1362             $entry=$mesg3->pop_entry;
1363              
1364             #if no entries are found, nothing needs updated
1365             if (!defined($entry)) {
1366             return 1;
1367             }
1368              
1369             #go through each one and update it
1370             my $loop=1;
1371             while ($loop) {
1372             $entry->delete('gidNumber'=>$gid);
1373             $entry->add(gidNumber=>$args{gid});
1374              
1375             #update the entry
1376             my $mesg4=$entry->update($ldap);
1377             if (!$mesg2->{errorMessage} eq '') {
1378             $self->{error}=29;
1379             $self->{errorString}='Changing the GID to "'.$args{gid}.'" from "'.$gid
1380             .'" for "'.$entry->dn.'" failed. $mesg4->{errorMessage}="'.
1381             $mesg4->{errorMessage}.'"';
1382             warn('Plugtools groupGIDchange:29: '.$self->{errorString});
1383             return undef;
1384             }
1385              
1386             #dump the entry if asked
1387             if ($args{dump}) {
1388             $entry->dump;
1389             }
1390            
1391             #get the next entry and decide it it should continue or not
1392             $entry=$mesg3->pop_entry;
1393             if (!defined($entry)) {
1394             $loop=0;
1395             }
1396             }
1397            
1398              
1399              
1400             return 1;
1401             }
1402              
1403             =head2 groupRemoveUser
1404              
1405             This removes a user from a group.
1406              
1407             =head3 args hash
1408              
1409             =head4 group
1410              
1411             The group to act on.
1412              
1413             =head4 user
1414              
1415             The user to act remove from the group.
1416              
1417             =head4 dump
1418              
1419             Call the dump method on the group afterwards.
1420              
1421             $pt->groupRemoveUser({
1422             group=>'someGroup',
1423             user=>'someUser',
1424             })
1425             if($pt->{errpr}){
1426             print "Error!\n";
1427             }
1428              
1429             =cut
1430              
1431             sub groupRemoveUser{
1432             my $self=$_[0];
1433             my %args;
1434             if(defined($_[1])){
1435             %args= %{$_[1]};
1436             };
1437              
1438             #blank any previous errors
1439             $self->errorblank;
1440              
1441             #error if we don't have a group name
1442             if (!defined($args{group})) {
1443             $self->{error}=6;
1444             $self->{errorString}='No group name specified';
1445             warn('Plugtools groupRemoveUser:6: '.$self->{errorString});
1446             return undef;
1447             }
1448              
1449             #error if no user has been specified
1450             if (!defined($args{user})) {
1451             $self->{error}=5;
1452             $self->{errorString}='No user name specified';
1453             warn('Plugtools groupRemoveUser:5: '.$self->{errorString});
1454             return undef;
1455             }
1456              
1457             #error if the user does not exists
1458             my ($gname,$gpasswd,$gid,$members) = getgrnam($args{group});
1459             if (!defined($gname)) {
1460             $self->{error}=14;
1461             $self->{errorString}='The group "'.$args{group}.'" does not exist';
1462             warn('Plugtools groupRemoveUser:14: '.$self->{errorString});
1463             return undef;
1464             }
1465              
1466             #connect to the LDAP server
1467             my $ldap=$self->connect();
1468             if ($self->{error}) {
1469             warn('Plugtools groupRemoveUser: Failed to connect to LDAP');
1470             return undef;
1471             }
1472              
1473             #search and get the first entry
1474             my $mesg=$ldap->search(
1475             base=>$self->{ini}->{''}->{groupbase},
1476             filter=>'(&(cn='.$args{group}.') (gidNumber='.$gid.'))'
1477             );
1478             if (!$mesg->{errorMessage} eq '') {
1479             $self->{error}=27;
1480             $self->{errorString}='Fetching a list of posixGroup objects under "'.
1481             $self->{ini}->{''}->{groupbase}.'"'.
1482             $mesg->{errorMessage}.'"';
1483             warn('Plugtools groupRemoveUser:27: '.$self->{errorString});
1484             return undef;
1485             }
1486             my $entry=$mesg->pop_entry;
1487            
1488             #if $entry is not defined or does not exist under the specified base
1489             if (!defined($entry)) {
1490             $self->{error}=15;
1491             $self->{errorString}='The group "'.$args{group}.'" does not exist in specified group base, "'.
1492             $self->{ini}->{''}->{groupbase}.'", ';
1493             warn('Plugtools groupRemoveUser:15: '.$self->{errorString});
1494             return undef;
1495             }
1496              
1497             $entry->delete(memberUid=>$args{user});
1498              
1499             #call a plugin if needed
1500             if (defined($self->{ini}->{''}->{pluginGroupRemoveUser})) {
1501             $self->plugin({
1502             ldap=>$ldap,
1503             entry=>$entry,
1504             do=>'pluginGroupRemoveUser',
1505             },
1506             \%args);
1507             if ($self->{error}) {
1508             warn('Plugtools groupRemoveUser: plugin errored');
1509             return undef;
1510             }
1511             }
1512              
1513             #update the entry
1514             my $mesg2=$entry->update($ldap);
1515             if (!$mesg2->{errorMessage} eq '') {
1516             $self->{error}=13;
1517             $self->{errorString}='Removing the user, "'.$args{user}.'", from "'.$entry->dn.'" failed. $mesg2->{errorMessage}="'.
1518             $mesg2->{errorMessage}.'"';
1519             warn('Plugtools deleteUser:13: '.$self->{errorString});
1520             return undef;
1521             }
1522              
1523             #dump the entry if asked
1524             if ($args{dump}) {
1525             $entry->dump;
1526             }
1527              
1528             return 1;
1529             }
1530              
1531             =head2 groupClean
1532              
1533             This checks through the groups setup in LDAP and removes any group that does not exist.
1534              
1535             =head3 args hash
1536              
1537             =head4 dump
1538              
1539             If this is specified, the dump method is called on any updated entry. If this is not
1540             defined, it defaults to false.
1541              
1542             $pt->groupClean;
1543             if($pt->{error}){
1544             print "Error!\n";
1545             }
1546              
1547             #do the same thing as above, but do $entry->dump for any changed entry
1548             $pt->groupClean({dump=>'1'});
1549             if($pt->{error}){
1550             print "Error!\n";
1551             }
1552              
1553             =cut
1554              
1555             sub groupClean{
1556             my $self=$_[0];
1557             my %args;
1558             if(defined($_[1])){
1559             %args= %{$_[1]};
1560             };
1561              
1562             #blank any previous errors
1563             $self->errorblank;
1564              
1565             #connect to the LDAP server
1566             my $ldap=$self->connect();
1567             if ($self->{error}) {
1568             warn('Plugtools groupClean: Failed to connect to LDAP');
1569             return undef;
1570             }
1571              
1572             #search and get the first entry
1573             my $mesg=$ldap->search(
1574             base=>$self->{ini}->{''}->{groupbase},
1575             filter=>'(objectClass=posixGroup)',
1576             );
1577             if (!$mesg->{errorMessage} eq '') {
1578             $self->{error}=27;
1579             $self->{errorString}='Fetching a list of posixGroup objects under "'.
1580             $self->{ini}->{''}->{groupbase}.'"'.
1581             $mesg->{errorMessage}.'"';
1582             warn('Plugtools groupClean:27: '.$self->{errorString});
1583             return undef;
1584             }
1585              
1586             #get the first entry
1587             my $entry=$mesg->pop_entry;
1588            
1589             #if the entry is not defined, there are no groups
1590             if (!defined($entry)) {
1591             return 1;
1592             }
1593              
1594             #process each one
1595             my $loop=1;
1596             while ($loop) {
1597             my @members=$entry->get_value('memberUid');
1598             #if there is no $members[0], it means the group
1599             #has no members listed
1600             if (defined($members[0])) {
1601             my $int=0;
1602             my $changed=0;#records if any changes have happened or not
1603             while (defined($members[$int])) {
1604             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($members[$int]);
1605             #if it is not defined, it means the user does not exist
1606             if (!defined($name)) {
1607             $entry->delete('memberUid'=>$members[$int]);
1608             $changed=1;
1609             }
1610              
1611             $int++;
1612             }
1613              
1614             #if it changed, update it
1615             if ($changed) {
1616             my $mesg2=$entry->update($ldap);
1617             if (!$mesg->{errorMessage} eq '') {
1618             $self->{error}=28;
1619             $self->{errorString}='Failed to update the entry, "'.$entry->dn.'". $mesg2->{errorMessage}="'.
1620             $mesg2->{errorMessage}.'"';
1621             warn('Plugtools groupClean:27: '.$self->{errorString});
1622             return undef;
1623             }
1624             if ($args{dump}) {
1625             $entry->dump;
1626             }
1627             }
1628             }
1629              
1630             #get the next entry
1631             $entry=$mesg->pop_entry;
1632             #exit this loop if it is not defined... meaning we reached the end
1633             if (!defined($entry)) {
1634             $loop=0;
1635             }
1636             }
1637              
1638             return 1;
1639             }
1640              
1641             =head2 isLDAPgroup
1642              
1643             This tests if a group is in LDAP or not.
1644              
1645             my $returned=$pt->isLDAPgroup('someGroup');
1646             if($pt->{error}){
1647             print "Error!\n";
1648             }else{
1649             if($returned){
1650             print "Yes!\n";
1651             }else{
1652             print "No!\n";
1653             }
1654             }
1655              
1656             =cut
1657              
1658             sub isLDAPgroup{
1659             my $self=$_[0];
1660             my $group=$_[1];
1661              
1662             #blank any previous errors
1663             $self->errorblank;
1664              
1665             #make sure a group if specifed
1666             if (!defined($group)) {
1667             $self->{error}=6;
1668             $self->{errorString}='No group name specified';
1669             warn('Plugtools isLDAPgroup:6: '.$self->{errorString});
1670             return undef;
1671             }
1672              
1673             #error if the user does not exists
1674             my ($gname,$gpasswd,$gid,$members) = getgrnam($group);
1675             if (!defined($gname)) {
1676             $self->{error}=10;
1677             $self->{errorString}='The group "'.$group.'" does not exist';
1678             warn('Plugtools isLDAPgroup:10: '.$self->{errorString});
1679             return undef;
1680             }
1681            
1682             #connect to the LDAP server
1683             my $ldap=$self->connect();
1684             if ($self->{error}) {
1685             warn('Plugtools isLDAPgroup: Failed to connect to LDAP');
1686             return undef;
1687             }
1688              
1689             #search and get the first entry
1690             my $mesg=$ldap->search(
1691             base=>$self->{ini}->{''}->{groupbase},
1692             filter=>'(&(cn='.$group.') (gidNumber='.$gid.'))'
1693             );
1694             my $entry=$mesg->pop_entry;
1695              
1696             #if $entry is not defined or does not exist under the specified base
1697             if (!defined($entry)) {
1698             return undef;
1699             }
1700            
1701             return 1;
1702             }
1703              
1704             =head2 isLDAPuser
1705              
1706             This tests if a group is in LDAP or not.
1707              
1708             my $returned=$pt->isLDAPuser('someUser');
1709             if($pt->{error}){
1710             print "Error!\n";
1711             }else{
1712             if($returned){
1713             print "Yes!\n";
1714             }else{
1715             print "No!\n";
1716             }
1717             }
1718              
1719             =cut
1720              
1721             sub isLDAPuser{
1722             my $self=$_[0];
1723             my $user=$_[1];
1724              
1725             #blank any previous errors
1726             $self->errorblank;
1727              
1728             #make sure a group if specifed
1729             if (!defined($user)) {
1730             $self->{error}=5;
1731             $self->{errorString}='No user name specified';
1732             warn('Plugtools isLDAPuser:5: '.$self->{errorString});
1733             return undef;
1734             }
1735              
1736             #error if the user already exists
1737             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user);
1738             if (!defined($name)) {
1739             $self->{error}=17;
1740             $self->{errorString}='The user "'.$user.'" does not exists';
1741             warn('Plugtools isLDAPuser:17: '.$self->{errorString});
1742             return undef;
1743             }
1744            
1745             #connect to the LDAP server
1746             my $ldap=$self->connect();
1747             if ($self->{error}) {
1748             warn('Plugtools isLDAPuser: Failed to connect to LDAP');
1749             return undef;
1750             }
1751              
1752             #search and get the first entry
1753             my $mesg=$ldap->search(
1754             base=>$self->{ini}->{''}->{userbase},
1755             filter=>'(&(uid='.$user.') (uidNumber='.$uid.'))'
1756             );
1757             my $entry=$mesg->pop_entry;
1758              
1759             #if $entry is not defined or does not exist under the specified base
1760             if (!defined($entry)) {
1761             return undef;
1762             }
1763              
1764             return 1;
1765             }
1766              
1767             =head2 onlyMember
1768              
1769             This figures out if a user is the only member of a group.
1770              
1771             This returns true if the user is the only member of that group. A value
1772             of false means that user is not in that group and there are no members or
1773             that it that there are other members.
1774              
1775             =head3 args hash
1776              
1777             Both 'user' and 'group' are required.
1778              
1779             =head4 user
1780              
1781             This is the user it is checking to see if it is the only member of a
1782             group.
1783              
1784             =head4 group
1785              
1786             This is the group to check.
1787              
1788             my $returned=$pt->onlyMember({
1789             user=>'someUser',
1790             group=>'someGroup',
1791             });
1792             if($pt->{error}){
1793             print "Error!\n";
1794             }
1795              
1796              
1797             =cut
1798              
1799             sub onlyMember{
1800             my $self=$_[0];
1801             my %args;
1802             if(defined($_[1])){
1803             %args= %{$_[1]};
1804             };
1805              
1806             #blank any previous errors
1807             $self->errorblank;
1808              
1809             #error is no group is specified
1810             if (!defined($args{user})) {
1811             $self->{error}=5;
1812             $self->{errorString}='No user name specified.';
1813             warn('Plugtools onlyMember:5: '.$self->{errorString});
1814             return undef;
1815             }
1816              
1817              
1818             #error is no group is specified
1819             if (!defined($args{group})) {
1820             $self->{error}=6;
1821             $self->{errorString}='No group name specified.';
1822             warn('Plugtools onlyMember:6: '.$self->{errorString});
1823             return undef;
1824             }
1825              
1826             #error if the user already exists
1827             my ($gname,$gpasswd,$ggid,$members) = getgrnam($args{group});
1828             if (!defined($gname)) {
1829             $self->{error}=14;
1830             $self->{errorString}='The group "'.$args{group}.'" does not exist';
1831             warn('Plugtools onlyMember:14: '.$self->{errorString});
1832             return undef;
1833             }
1834              
1835             #error if the user already exists
1836             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($args{user});
1837             if (!defined($name)) {
1838             $self->{error}=17;
1839             $self->{errorString}='The user "'.$args{user}.'" does not exists';
1840             warn('Plugtools onlyMember:17: '.$self->{errorString});
1841             return undef;
1842             }
1843              
1844             #break the list of members apart
1845             my @membersA=split(/,/, $members);
1846              
1847             #handle it if there are no group members
1848             if (!defined($membersA[0])) {
1849             #if the group's GID and the user's primary GID are the same
1850             #here then it means the user is not explicityly as a member of that group
1851             if ($ggid eq $gid) {
1852             return 1;
1853             }
1854              
1855             #if we get here, the group has no explicityly listed members
1856             #and the user is not a member of the group
1857             return undef;
1858             }
1859            
1860             #check each member to see if it is not the user in question
1861             #while this may seem stupid, there is a possibiltiy that the user
1862             #has been listed in a group more than once...
1863             my $int=0;
1864             while (defined($membersA[$int])) {
1865             if ($membersA[$int] ne $args{user}) {
1866             return undef;
1867             }
1868              
1869             $int++;
1870             }
1871              
1872             return 1;
1873             }
1874              
1875             =head2 plugin
1876              
1877             This processes series plugins.
1878              
1879             =head3 opts hash
1880              
1881             This is the first required hash.
1882              
1883             =head4 ldap
1884              
1885             This is the current LDAP connect.
1886              
1887             =head4 do
1888              
1889             This contains the variable it should reference for what plugins to run.
1890              
1891             =head4 entry
1892              
1893             This is the LDAP entry to work on.
1894              
1895             =head3 args hash
1896              
1897             This is the hash that was passed to the function calling the plugin.
1898              
1899             =cut
1900              
1901             sub plugin{
1902             my $self=$_[0];
1903             my $opts;
1904             my %opts;
1905             if(defined($_[1])){
1906             %opts= %{$_[1]};
1907             };
1908             my %args;
1909             if(defined($_[2])){
1910             %args= %{$_[2]};
1911             };
1912              
1913             #blank any previous errors
1914             $self->errorblank;
1915              
1916             #error if no LDAP connection is present
1917             if (!defined($opts{ldap})) {
1918             $self->{error}=38;
1919             $self->{errorString}='No LDAP connection passed';
1920             warn('Plugtools plugin:38: '.$self->{errorString});
1921             return undef;
1922             }
1923              
1924             #error if no LDAP connection is present
1925             if (!defined($opts{do})) {
1926             $self->{error}=39;
1927             $self->{errorString}='What selection of plugins to process has not been specified. $opts{do} is undefined';
1928             warn('Plugtools plugin:39: '.$self->{errorString});
1929             return undef;
1930             }
1931              
1932             #error if no LDAP connection is present
1933             if (!defined($opts{entry})) {
1934             $self->{error}=42;
1935             $self->{errorString}='No Net::LDAP::Entry passed. $opts{entry} is undefined';
1936             warn('Plugtools plugin:42: '.$self->{errorString});
1937             return undef;
1938             }
1939              
1940             #error if the LDAP entry that is specified is not a Net::LDAP::Entry object
1941             if (ref($opts{entry}) ne 'Net::LDAP::Entry') {
1942             $self->{error}=43;
1943             $self->{errorString}='$opts{entry} is not a Net::LDAP::Entry object';
1944             warn('Plugtools plugin:43: '.$self->{errorString});
1945             return undef;
1946             }
1947              
1948             #error if no entry connection is present
1949             if (ref($opts{ldap}) ne 'Net::LDAP') {
1950             $self->{error}=44;
1951             $self->{errorString}='$opts{ldap} is not a Net::LDAP object';
1952             warn('Plugtools plugin:44: '.$self->{errorString});
1953             return undef;
1954             }
1955              
1956             #
1957             $opts{self}=$self;
1958              
1959             #make sure the specified config exists
1960             if (!defined( $self->{ini}->{''}->{$opts{do}} )) {
1961             $self->{error}=40;
1962             $self->{errorString}='The variable "'.$opts{do}.'" does not exist in the config';
1963             warn('Plugtools plugin:40: '.$self->{errorString});
1964             return undef;
1965             }
1966              
1967             #split the plugin apart
1968             my @plugins=split(/,/ , $self->{ini}->{''}->{$opts{do}});
1969              
1970             #process each one
1971             my $int=0;
1972             while (defined($plugins[$int])) {
1973             my %returned;
1974             my $run='use '.$plugins[$int].';'."\n".
1975             'my %returned='.$plugins[$int].'->plugin(\%opts, \%args);';
1976            
1977             #run it
1978             my $ran=eval($run);
1979            
1980             #If we did not get a boolean true, then it failed
1981             if (!$ran) {
1982             $self->{error}=41;
1983             $self->{errorString}='Executing the plugin "'.$plugins[$int].'" failed. $run="'.$run.'"';
1984             warn('Plugtools plugins:41: '.$self->{errorString});
1985             return undef;
1986             }
1987            
1988             #it errored...
1989             if ($returned{error}) {
1990             $self->{error}=45;
1991             $self->{errorString}='The plugin returned a error. $returned{error}="'.$returned{error}.'" '.
1992             '$returned{errorString}="'.$returned{errorString}.'"';
1993             warn('Plugtools plugins:45: '.$self->{errorString});
1994             return undef;
1995             }
1996            
1997             $int++;
1998             }
1999              
2000             return 1;
2001             }
2002              
2003             =head2 removeUserFromGroups
2004              
2005             This removes a user from any group in LDAP they are a member of.
2006              
2007             No checks are made to see if the user exists or not.
2008              
2009             $pt->removeUserFromGroups('someUser');
2010             if($pt->{error}){
2011             print "Error!\n";
2012             }
2013              
2014             =cut
2015              
2016             sub removeUserFromGroups{
2017             my $self=$_[0];
2018             my $user=$_[1];
2019              
2020             #blank any previous errors
2021             $self->errorblank;
2022              
2023             #make sure a group if specifed
2024             if (!defined($user)) {
2025             $self->{error}=5;
2026             $self->{errorString}='No user name specified';
2027             warn('Plugtools removeUserFromGroups:5: '.$self->{errorString});
2028             return undef;
2029             }
2030              
2031             #connect to the LDAP server
2032             my $ldap=$self->connect();
2033             if ($self->{error}) {
2034             warn('Plugtools findGroupDN: Failed to connect to LDAP');
2035             return undef;
2036             }
2037              
2038             #search and get the first entry
2039             my $mesg=$ldap->search(
2040             base=>$self->{ini}->{''}->{groupbase},
2041             filter=>'(&(objectClass=posixGroup) (memberUid='.$user.'))'
2042             );
2043             my $entry=$mesg->pop_entry;
2044              
2045             #no groups with this user in them were found
2046             if (!defined($entry)) {
2047             return 1;
2048             }
2049            
2050             #exit it
2051             my $loop=1;
2052             while ($loop) {
2053             #remove the memberUid attribute that is equal to the user in question and update it
2054             $entry->delete('memberUid'=>$user);
2055             my $mesg2=$entry->update($ldap);
2056             #handles any errors
2057             if (!$mesg2->{errorMessage} eq '') {
2058             $self->{error}=25;
2059             $self->{errorString}='Deleting memberUid='.$user.' from the entry "'.$entry->dn.'" failed. $mesg2->{errorMessage}="'.
2060             $mesg2->{errorMessage}.'"';
2061             warn('Plugtools removeUserFromGroups:25: '.$self->{errorString});
2062             return undef;
2063             }
2064            
2065             #get the next entry
2066             $entry=$mesg->pop_entry;
2067             #if the next entry is not defined, there are no more so we exit the loop
2068             if (!defined($entry)) {
2069             $loop=0;
2070             }
2071             }
2072              
2073             return 1;
2074             }
2075              
2076             =head2 readConfig
2077              
2078             This reads the specified config.
2079              
2080             #reads the default config
2081             $pt->readConfig();
2082             if($pt->{error}){
2083             print "Error!";
2084             }
2085              
2086             #reads the config '/some/config'
2087             $pt->readConfig('/some/config');
2088             if($pt->{error}){
2089             print "Error!";
2090             }
2091              
2092             =cut
2093              
2094             sub readConfig{
2095             my $self=$_[0];
2096             my $config=$_[1];
2097              
2098             #blanks any previous errors
2099             $self->errorblank;
2100              
2101             #if it is not defined, use the default one
2102             if (!defined($config)) {
2103             $config=xdg_config_home().'/plugtoolsrc';
2104             }
2105              
2106             #reads the config
2107             my $ini=ReadINI($config);
2108              
2109             #errors if it is not defined... meaning it errored
2110             if (!defined($ini)) {
2111             $self->{error}=1;
2112             $self->{errorString}='Failed to read the config';
2113             warn('Plugtools readConfig:1: '.$self->{errorString});
2114             return undef;
2115             }
2116              
2117             #puts together a array to check for the required ones
2118             my @required;
2119             push(@required, 'bind');
2120             push(@required, 'pass');
2121             push(@required, 'userbase');
2122             push(@required, 'groupbase');
2123            
2124              
2125             #make sure they are all defined
2126             my $int=0;
2127             while (defined($required[$int])) {
2128             #error if it is not defined
2129             if (!defined($ini->{''}->{$required[$int]})) {
2130             $self->{error}=2;
2131             $self->{errorString}='The required variable "'.$required[$int].'" is not defined in the config, "'.$config.'",';
2132             warn('Plugtools readConfig:2: '.$self->{errorString});
2133             return undef;
2134             }
2135              
2136             $int++;
2137             }
2138              
2139             #define the defaults if they are not defined
2140             if (!defined($ini->{''}->{UIDstart})) {
2141             $ini->{''}->{UIDstart}='1001';
2142             }
2143             if (!defined($ini->{''}->{GIDstart})) {
2144             $ini->{''}->{GIDstart}='1001';
2145             }
2146             if (!defined($ini->{''}->{defaultShell})) {
2147             $ini->{''}->{defaultShell}='/bin/tcsh';
2148             }
2149             if (!defined($ini->{''}->{HOMEproto})) {
2150             $ini->{''}->{HOMEproto}='/home/%%USERNAME%%/';
2151             }
2152             if (!defined($ini->{''}->{skeletonHome})) {
2153             $ini->{''}->{skeletonHome}='/etc/skel/';
2154             }
2155             if (!defined($ini->{''}->{chmodValue})) {
2156             $ini->{''}->{chmodValue}='640';
2157             }
2158             if (!defined($ini->{''}->{chmodHome})) {
2159             $ini->{''}->{chmodHome}='1';
2160             }
2161             if (!defined($ini->{''}->{chownHome})) {
2162             $ini->{''}->{chownHome}='1';
2163             }
2164             if (!defined($ini->{''}->{createHome})) {
2165             $ini->{''}->{createHome}='1';
2166             }
2167             if (!defined($ini->{''}->{groupPrimary})) {
2168             $ini->{''}->{groupPrimary}='cn';
2169             }
2170             if (!defined($ini->{''}->{userPrimary})) {
2171             $ini->{''}->{userPrimary}='uid';
2172             }
2173             if (!defined($ini->{''}->{server})) {
2174             $ini->{''}->{server}='127.0.0.1';
2175             }
2176             if (!defined($ini->{''}->{port})) {
2177             $ini->{''}->{port}='389';
2178             }
2179             if (!defined($ini->{''}->{TLSverify})) {
2180             $ini->{''}->{TLSverify}='none';
2181             }
2182             if (!defined($ini->{''}->{SSLversion})) {
2183             $ini->{''}->{SSLversion}='tlsv1';
2184             }
2185             if (!defined($ini->{''}->{SSLciphers})) {
2186             $ini->{''}->{SSLciphers}='ALL';
2187             }
2188             if (!defined($ini->{''}->{removeHome})) {
2189             $ini->{''}->{removeHome}='0';
2190             }
2191             if (!defined($ini->{''}->{removeGroup})) {
2192             $ini->{''}->{removeGroup}='1';
2193             }
2194             if (!defined($ini->{''}->{userUpdate})) {
2195             $ini->{''}->{userUpdate}='1';
2196             }
2197              
2198             #if we get here, the ini is good... so we save it
2199             $self->{ini}=$ini;
2200              
2201             return 1;
2202             }
2203              
2204             =head2 userGECOSchange
2205              
2206             This changes the UID for a user.
2207              
2208             =head3 args hash
2209              
2210             =head4 user
2211              
2212             The user to act on.
2213              
2214             =head4 gecos
2215              
2216             The GECOS to change this user to.
2217              
2218             =head4 dump
2219              
2220             Call the dump method on the group afterwards.
2221              
2222             $pt->userGECOSchange({
2223             user=>'someUser',
2224             gecos=>'whatever',
2225             });
2226             if($pt->{error}){
2227             print "Error!\n";
2228             }
2229              
2230             =cut
2231              
2232             sub userGECOSchange{
2233             my $self=$_[0];
2234             my %args;
2235             if(defined($_[1])){
2236             %args= %{$_[1]};
2237             };
2238              
2239             #blank any previous errors
2240             $self->errorblank;
2241              
2242             #error if we don't have a group name
2243             if (!defined($args{user})) {
2244             $self->{error}=5;
2245             $self->{errorString}='No user name specified';
2246             warn('Plugtools userGECOSchange:5: '.$self->{errorString});
2247             return undef;
2248             }
2249              
2250             #error if no user has been specified
2251             if (!defined($args{gecos})){
2252             $self->{error}=33;
2253             $self->{errorString}='No GECOS specified';
2254             warn('Plugtools userGECOSchange:33: '.$self->{errorString});
2255             return undef;
2256             }
2257              
2258             #error if the user already exists
2259             my ($name,$passwd,$uid,$gid,$quota,$comment,$gecos,$dir,$shell,$expire) = getpwnam($args{user});
2260             if (!defined($name)) {
2261             $self->{error}=17;
2262             $self->{errorString}='The user "'.$args{user}.'" does not exists';
2263             warn('Plugtools userGECOSchange:17: '.$self->{errorString});
2264             return undef;
2265             }
2266              
2267             #connect to the LDAP server
2268             my $ldap=$self->connect();
2269             if ($self->{error}) {
2270             warn('Plugtools userGECOSchange: Failed to connect to LDAP');
2271             return undef;
2272             }
2273              
2274             #search and get the first entry
2275             my $mesg=$ldap->search(
2276             base=>$self->{ini}->{''}->{userbase},
2277             filter=>'(&(uid='.$args{user}.') (uidNumber='.$uid.'))'
2278             );
2279             if (!$mesg->{errorMessage} eq '') {
2280             $self->{error}=32;
2281             $self->{errorString}='Fetching the entry for the user failed under "'.
2282             $self->{ini}->{''}->{groupbase}.'"'.
2283             $mesg->{errorMessage}.'"';
2284             warn('Plugtools userGECOSchange:32: '.$self->{errorString});
2285             return undef;
2286             }
2287             my $entry=$mesg->pop_entry;
2288            
2289             #if $entry is not defined or does not exist under the specified base
2290             if (!defined($entry)) {
2291             $self->{error}=18;
2292             $self->{errorString}='The user "'.$args{user}.'" does not exist in specified group base, "'.
2293             $self->{ini}->{''}->{userbase}.'", ';
2294             warn('Plugtools userGECOSchange:18: '.$self->{errorString});
2295             return undef;
2296             }
2297              
2298             $entry->delete(gecos=>$gecos);
2299             $entry->add(gecos=>$args{gecos});
2300              
2301             #call a plugin if needed
2302             if (defined($self->{ini}->{''}->{pluginUserGECOSchange})) {
2303             $entry=$self->plugin({
2304             ldap=>$ldap,
2305             entry=>$entry,
2306             do=>'pluginUserGECOSchange',
2307             },
2308             \%args);
2309             if ($self->{error}) {
2310             warn('Plugtools userGECOSchange: plugin errored');
2311             return undef;
2312             }
2313             }
2314              
2315             #call a plugin if needed
2316             if (defined($self->{ini}->{''}->{pluginUserGECOSchange})) {
2317             $self->plugin({
2318             ldap=>$ldap,
2319             entry=>$entry,
2320             do=>'pluginUserGECOSchange',
2321             },
2322             \%args);
2323             if ($self->{error}) {
2324             warn('Plugtools userGECOSchange: plugin errored');
2325             return undef;
2326             }
2327             }
2328              
2329             #update the entry
2330             my $mesg2=$entry->update($ldap);
2331             if (!$mesg2->{errorMessage} eq '') {
2332             $self->{error}=34;
2333             $self->{errorString}='Changing the GECOS to "'.$args{gecos}.'" from "'.$gecos
2334             .'" for "'.$entry->dn.'" failed. $mesg2->{errorMessage}="'.
2335             $mesg2->{errorMessage}.'"';
2336             warn('Plugtools userGECOSchange:34: '.$self->{errorString});
2337             return undef;
2338             }
2339              
2340             #dump the entry if asked
2341             if ($args{dump}) {
2342             $entry->dump;
2343             }
2344              
2345             return 1;
2346             }
2347              
2348             =head2 userShellChange
2349              
2350             This changes the UID for a user.
2351              
2352             =head3 args hash
2353              
2354             =head4 user
2355              
2356             The user to act on.
2357              
2358             =head4 shell
2359              
2360             The shell to change this user to.
2361              
2362             =head4 dump
2363              
2364             Call the dump method on the group afterwards.
2365              
2366             $pt->userShellChange({
2367             user=>'someUser',
2368             shell=>'/bin/tcsh',
2369             });
2370             if($pt->error){
2371             print "Error!\n";
2372             }
2373              
2374             =cut
2375              
2376             sub userShellChange{
2377             my $self=$_[0];
2378             my %args;
2379             if(defined($_[1])){
2380             %args= %{$_[1]};
2381             }
2382             my $method='userShellChange';
2383              
2384             #blank any previous errors
2385             $self->errorblank;
2386              
2387             #error if we don't have a group name
2388             if (!defined($args{user})) {
2389             $self->{error}=5;
2390             $self->{errorString}='No user name specified';
2391             warn($self->{module}.' '.$method.':'.$self->error.': '.$self->errorString);
2392             return undef;
2393             }
2394              
2395             #error if no user has been specified
2396             if (!defined($args{shell})){
2397             $self->{error}=47;
2398             $self->{errorString}='No shell specified';
2399             warn($self->{module}.' '.$method.':'.$self->error.': '.$self->errorString);
2400             return undef;
2401             }
2402              
2403             #error if the user already exists
2404             my ($name,$passwd,$uid,$gid,$quota,$comment,$gecos,$dir,$shell,$expire) = getpwnam($args{user});
2405             if (!defined($name)) {
2406             $self->{error}=17;
2407             $self->{errorString}='The user "'.$args{user}.'" does not exists';
2408             warn($self->{module}.' '.$method.':'.$self->error.': '.$self->errorString);
2409             return undef;
2410             }
2411              
2412             #connect to the LDAP server
2413             my $ldap=$self->connect();
2414             if ($self->{error}) {
2415             warn('Plugtools userGECOSchange: Failed to connect to LDAP');
2416             return undef;
2417             }
2418              
2419             #search and get the first entry
2420             my $mesg=$ldap->search(
2421             base=>$self->{ini}->{''}->{userbase},
2422             filter=>'(&(uid='.$args{user}.') (uidNumber='.$uid.'))'
2423             );
2424             if (!$mesg->{errorMessage} eq '') {
2425             $self->{error}=32;
2426             $self->{errorString}='Fetching the entry for the user failed under "'.
2427             $self->{ini}->{''}->{groupbase}.'"'.
2428             $mesg->{errorMessage}.'"';
2429             warn($self->{module}.' '.$method.':'.$self->error.': '.$self->errorString);
2430             return undef;
2431             }
2432             my $entry=$mesg->pop_entry;
2433            
2434             #if $entry is not defined or does not exist under the specified base
2435             if (!defined($entry)) {
2436             $self->{error}=18;
2437             $self->{errorString}='The user "'.$args{user}.'" does not exist in specified group base, "'.
2438             $self->{ini}->{''}->{userbase}.'", ';
2439             warn($self->{module}.' '.$method.':'.$self->error.': '.$self->errorString);
2440             return undef;
2441             }
2442              
2443             $entry->delete(loginShell=>$shell);
2444             $entry->add(loginShell=>$args{shell});
2445              
2446             #call a plugin if needed
2447             if (defined($self->{ini}->{''}->{pluginUserShellChange})) {
2448             $entry=$self->plugin({
2449             ldap=>$ldap,
2450             entry=>$entry,
2451             do=>'pluginUserShellChange',
2452             },
2453             \%args);
2454             if ($self->{error}) {
2455             warn('Plugtools userShellChange: plugin errored');
2456             return undef;
2457             }
2458             }
2459              
2460             #call a plugin if needed
2461             if (defined($self->{ini}->{''}->{pluginUserShellChange})) {
2462             $self->plugin({
2463             ldap=>$ldap,
2464             entry=>$entry,
2465             do=>'pluginUserShellChange',
2466             },
2467             \%args);
2468             if ($self->{error}) {
2469             warn('Plugtools userShellChange: plugin errored');
2470             return undef;
2471             }
2472             }
2473              
2474             #update the entry
2475             my $mesg2=$entry->update($ldap);
2476             if (!$mesg2->{errorMessage} eq '') {
2477             $self->{error}=34;
2478             $self->{errorString}='Changing the Shell to "'.$args{shell}.'" from "'.$shell
2479             .'" for "'.$entry->dn.'" failed. $mesg2->{errorMessage}="'.
2480             $mesg2->{errorMessage}.'"';
2481             warn($self->{module}.' '.$method.':'.$self->error.': '.$self->errorString);
2482             return undef;
2483             }
2484              
2485             #dump the entry if asked
2486             if ($args{dump}) {
2487             $entry->dump;
2488             }
2489              
2490             return 1;
2491             }
2492              
2493             =head2 userSetPass
2494              
2495             This changes the password for a user.
2496              
2497             =head3 args hash
2498              
2499             =head4 user
2500              
2501             This is the user to act on.
2502              
2503             =head4 pass
2504              
2505             This is the new password to set.
2506              
2507             $pt->userSetPass({
2508             user=>'someUser',
2509             pass=>'whatever',
2510             });
2511             if($pt->{error}){
2512             print "Error!\n";
2513             }
2514              
2515             =cut
2516              
2517             sub userSetPass{
2518             my $self=$_[0];
2519             my %args;
2520             if(defined($_[1])){
2521             %args= %{$_[1]};
2522             };
2523              
2524             #blank any previous errors
2525             $self->errorblank;
2526              
2527             #error if we don't have a group name
2528             if (!defined($args{user})) {
2529             $self->{error}=5;
2530             $self->{errorString}='No user name specified';
2531             warn('Plugtools userGIDchange:5: '.$self->{errorString});
2532             return undef;
2533             }
2534              
2535             #error if we don't have a group name
2536             if (!defined($args{user})) {
2537             $self->{error}=35;
2538             $self->{errorString}='No password specified.';
2539             warn('Plugtools userSetPass:35: '.$self->{errorString});
2540             return undef;
2541             }
2542              
2543             #error if the user already exists
2544             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($args{user});
2545             if (!defined($name)) {
2546             $self->{error}=17;
2547             $self->{errorString}='The user "'.$args{user}.'" does not exists';
2548             warn('Plugtools userSetPass:17: '.$self->{errorString});
2549             return undef;
2550             }
2551              
2552             #connect to the LDAP server
2553             my $ldap=$self->connect();
2554             if ($self->{error}) {
2555             warn('Plugtools userSetPass: Failed to connect to LDAP');
2556             return undef;
2557             }
2558              
2559             #search and get the first entry
2560             my $mesg=$ldap->search(
2561             base=>$self->{ini}->{''}->{userbase},
2562             filter=>'(&(uid='.$args{user}.') (uidNumber='.$uid.'))'
2563             );
2564             if (!$mesg->{errorMessage} eq '') {
2565             $self->{error}=32;
2566             $self->{errorString}='Fetching the entry for the user under "'.
2567             $self->{ini}->{''}->{userbase}.'"'.
2568             $mesg->{errorMessage}.'"';
2569             warn('Plugtools userSetPass:32: '.$self->{errorString});
2570             return undef;
2571             }
2572             my $entry=$mesg->pop_entry;
2573              
2574             #get the DN of the entry we will be changing
2575             my $dn=$entry->dn;
2576              
2577             my $mesg2=$ldap->set_password(user=>$dn, newpasswd=>$args{pass});
2578             if (!$mesg->{errorMessage} eq '') {
2579             $self->{error}=36;
2580             $self->{errorString}='Fetching the entry for the user under "'.
2581             $self->{ini}->{''}->{userbase}.'"'.
2582             $mesg->{errorMessage}.'"';
2583             warn('Plugtools userSetPass:36: '.$self->{errorString});
2584             return undef;
2585             }
2586              
2587             #call a plugin if needed
2588             if (defined($self->{ini}->{''}->{pluginUserSetPass})) {
2589             $self->plugin({
2590             ldap=>$ldap,
2591             entry=>$entry,
2592             do=>'pluginUserSetPass',
2593             },
2594             \%args);
2595             if ($self->{error}) {
2596             warn('Plugtools userSetPass: plugin errored');
2597             return undef;
2598             }
2599             }else {
2600             return 1;
2601             }
2602              
2603             #update the entry
2604             my $mesg3=$entry->update($ldap);
2605             if (!$mesg3->{errorMessage} eq '') {
2606             $self->{error}=34;
2607             $self->{errorString}='Calling the update method on the entry, "'.$entry->dn.'", failed. $mesg3->{errorMessage}="'.
2608             $mesg3->{errorMessage}.'"';
2609             warn('Plugtools userSetPass:34: '.$self->{errorString});
2610             return undef;
2611             }
2612              
2613             return 1;
2614             }
2615              
2616             =head2 userGIDchange
2617              
2618             This changes the UID for a user.
2619              
2620             =head3 args hash
2621              
2622             =head4 user
2623              
2624             The user to act on.
2625              
2626             =head4 gid
2627              
2628             The GID to change this user to. This GID must already exist.
2629              
2630             =head4 dump
2631              
2632             Call the dump method on the group afterwards.
2633              
2634             $pt->userGIDchange({
2635             user=>'someUser',
2636             gid=>'1234',
2637             });
2638             if($pt->{error}){
2639             print "Error!\n";
2640             }
2641              
2642             =cut
2643              
2644             sub userGIDchange{
2645             my $self=$_[0];
2646             my %args;
2647             if(defined($_[1])){
2648             %args= %{$_[1]};
2649             };
2650              
2651             #blank any previous errors
2652             $self->errorblank;
2653              
2654             #error if we don't have a group name
2655             if (!defined($args{user})) {
2656             $self->{error}=5;
2657             $self->{errorString}='No user name specified';
2658             warn('Plugtools userGIDchange:5: '.$self->{errorString});
2659             return undef;
2660             }
2661              
2662             #error if no user has been specified
2663             if (!defined($args{gid})){
2664             $self->{error}=28;
2665             $self->{errorString}='No GID specified';
2666             warn('Plugtools userGIDchange:30: '.$self->{errorString});
2667             return undef;
2668             }
2669              
2670             #make sure the GID is complete numeric
2671             if (!($args{gid}=~/^[0123456789]*$/)) {
2672             $self->{error}=8;
2673             $self->{errorString}='The specified GID, "'.$args{gid}.'", is not numeric';
2674             warn('Plugtools groupGIDchange:8: '.$self->{errorString});
2675             return undef;
2676             }
2677              
2678             #error if the user already exists
2679             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($args{user});
2680             if (!defined($name)) {
2681             $self->{error}=17;
2682             $self->{errorString}='The user "'.$args{user}.'" does not exists';
2683             warn('Plugtools userGIDchange:17: '.$self->{errorString});
2684             return undef;
2685             }
2686              
2687             #error if the user does not exists
2688             my ($gname,$gpasswd,$ggid,$members) = getgrgid($args{gid});
2689             if (!defined($gname)) {
2690             $self->{error}=14;
2691             $self->{errorString}='The group specified by GID "'.$args{gid}.'" does not exist';
2692             warn('Plugtools userGIDchange:14: '.$self->{errorString});
2693             return undef;
2694             }
2695              
2696             #connect to the LDAP server
2697             my $ldap=$self->connect();
2698             if ($self->{error}) {
2699             warn('Plugtools userGIDchange: Failed to connect to LDAP');
2700             return undef;
2701             }
2702              
2703             #search and get the first entry
2704             my $mesg=$ldap->search(
2705             base=>$self->{ini}->{''}->{userbase},
2706             filter=>'(&(uid='.$args{user}.') (uidNumber='.$uid.'))'
2707             );
2708             if (!$mesg->{errorMessage} eq '') {
2709             $self->{error}=32;
2710             $self->{errorString}='Fetching the entry for the user failed under "'.
2711             $self->{ini}->{''}->{userbase}.'"'.
2712             $mesg->{errorMessage}.'"';
2713             warn('Plugtools userGIDchange:32: '.$self->{errorString});
2714             return undef;
2715             }
2716             my $entry=$mesg->pop_entry;
2717            
2718             #if $entry is not defined or does not exist under the specified base
2719             if (!defined($entry)) {
2720             $self->{error}=18;
2721             $self->{errorString}='The user "'.$args{user}.'" does not exist in specified group base, "'.
2722             $self->{ini}->{''}->{userbase}.'", ';
2723             warn('Plugtools userGIDchange:18: '.$self->{errorString});
2724             return undef;
2725             }
2726              
2727             $entry->delete(gidNumber=>$gid);
2728             $entry->add(gidNumber=>$args{gid});
2729              
2730             #call a plugin if needed
2731             if (defined($self->{ini}->{''}->{pluginUserGIDchange})) {
2732             $self->plugin({
2733             ldap=>$ldap,
2734             entry=>$entry,
2735             do=>'pluginUserGIDchange',
2736             },
2737             \%args);
2738             if ($self->{error}) {
2739             warn('Plugtools userGIDchange: plugin errored');
2740             return undef;
2741             }
2742             }
2743              
2744             #update the entry
2745             my $mesg2=$entry->update($ldap);
2746             if (!$mesg2->{errorMessage} eq '') {
2747             $self->{error}=29;
2748             $self->{errorString}='Changing the GID to "'.$args{gid}.'" from "'.$gid
2749             .'" for "'.$entry->dn.'" failed. $mesg2->{errorMessage}="'.
2750             $mesg2->{errorMessage}.'"';
2751             warn('Plugtools userGIDchange:29: '.$self->{errorString});
2752             return undef;
2753             }
2754              
2755             #dump the entry if asked
2756             if ($args{dump}) {
2757             $entry->dump;
2758             }
2759              
2760             return 1;
2761             }
2762              
2763             =head2 userUIDchange
2764              
2765             This changes the UID for a user.
2766              
2767             =head3 args hash
2768              
2769             =head4 user
2770              
2771             The user to act on.
2772              
2773             =head4 uid
2774              
2775             The UID to change this user to.
2776              
2777             =head4 dump
2778              
2779             Call the dump method on the group afterwards.
2780              
2781             $pt->userUIDchange({
2782             user=>'someUser',
2783             uid=>'1234',
2784             });
2785             if($pt->{error}){
2786             print "Error!\n";
2787             }
2788              
2789             =cut
2790              
2791             sub userUIDchange{
2792             my $self=$_[0];
2793             my %args;
2794             if(defined($_[1])){
2795             %args= %{$_[1]};
2796             };
2797              
2798             #blank any previous errors
2799             $self->errorblank;
2800              
2801             #error if we don't have a group name
2802             if (!defined($args{user})) {
2803             $self->{error}=5;
2804             $self->{errorString}='No user name specified';
2805             warn('Plugtools userUIDchange:5: '.$self->{errorString});
2806             return undef;
2807             }
2808              
2809             #error if no user has been specified
2810             if (!defined($args{uid})){
2811             $self->{error}=30;
2812             $self->{errorString}='No GID specified';
2813             warn('Plugtools userUIDchange:30: '.$self->{errorString});
2814             return undef;
2815             }
2816              
2817             #make sure the UID is complete numeric
2818             if (!($args{uid}=~/^[0123456789]*$/)) {
2819             $self->{error}=7;
2820             $self->{errorString}='The specified UID, "'.$args{uid}.'", is not numeric';
2821             warn('Plugtools userUIDchange:7: '.$self->{errorString});
2822             return undef;
2823             }
2824              
2825             #error if the user already exists
2826             my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($args{user});
2827             if (!defined($name)) {
2828             $self->{error}=17;
2829             $self->{errorString}='The user "'.$args{user}.'" does not exists';
2830             warn('Plugtools userUIDchange:17: '.$self->{errorString});
2831             return undef;
2832             }
2833              
2834             #connect to the LDAP server
2835             my $ldap=$self->connect();
2836             if ($self->{error}) {
2837             warn('Plugtools userUIDchange: Failed to connect to LDAP');
2838             return undef;
2839             }
2840              
2841             #search and get the first entry
2842             my $mesg=$ldap->search(
2843             base=>$self->{ini}->{''}->{userbase},
2844             filter=>'(&(uid='.$args{user}.') (uidNumber='.$uid.'))'
2845             );
2846             if (!$mesg->{errorMessage} eq '') {
2847             $self->{error}=32;
2848             $self->{errorString}='Fetching the entry for the user under "'.
2849             $self->{ini}->{''}->{userbase}.'"'.
2850             $mesg->{errorMessage}.'"';
2851             warn('Plugtools userUIDchange:32: '.$self->{errorString});
2852             return undef;
2853             }
2854             my $entry=$mesg->pop_entry;
2855            
2856             #if $entry is not defined or does not exist under the specified base
2857             if (!defined($entry)) {
2858             $self->{error}=18;
2859             $self->{errorString}='The user "'.$args{user}.'" does not exist in specified group base, "'.
2860             $self->{ini}->{''}->{userbase}.'", ';
2861             warn('Plugtools userUIDchange:18: '.$self->{errorString});
2862             return undef;
2863             }
2864              
2865             $entry->delete(uidNumber=>$uid);
2866             $entry->add(uidNumber=>$args{uid});
2867              
2868             #call a plugin if needed
2869             if (defined($self->{ini}->{''}->{pluginUserUIDchange})) {
2870             $self->plugin({
2871             ldap=>$ldap,
2872             entry=>$entry,
2873             do=>'pluginUserGIDchange',
2874             },
2875             \%args);
2876             if ($self->{error}) {
2877             warn('Plugtools userUIDchange: plugin errored');
2878             return undef;
2879             }
2880             }
2881              
2882             #update the entry
2883             my $mesg2=$entry->update($ldap);
2884             if (!$mesg2->{errorMessage} eq '') {
2885             $self->{error}=31;
2886             $self->{errorString}='Changing the UID to "'.$args{uid}.'" from "'.$uid
2887             .'" for "'.$entry->dn.'" failed. $mesg2->{errorMessage}="'.
2888             $mesg2->{errorMessage}.'"';
2889             warn('Plugtools userUIDchange:31: '.$self->{errorString});
2890             return undef;
2891             }
2892              
2893             #dump the entry if asked
2894             if ($args{dump}) {
2895             $entry->dump;
2896             }
2897              
2898             return 1;
2899             }
2900              
2901             =head2 error
2902              
2903             Returns the current error code and true if there is an error.
2904              
2905             If there is no error, undef is returned.
2906              
2907             my $error=$foo->error;
2908             if($error){
2909             print 'error code: '.$error."\n";
2910             }
2911              
2912             =cut
2913              
2914             sub error{
2915             return $_[0]->{error};
2916             }
2917              
2918             =head2 errorblank
2919              
2920             This is a internal function and should not be called.
2921              
2922             =cut
2923              
2924             #blanks the error flags
2925             sub errorblank{
2926             my $self=$_[0];
2927              
2928             $self->{error}=undef;
2929             $self->{errorString}="";
2930              
2931             return 1;
2932             }
2933              
2934             =head2 errorString
2935              
2936             Returns the error string if there is one. If there is not,
2937             it will return ''.
2938              
2939             my $error=$foo->error;
2940             if($error){
2941             print 'error code:'.$error.': '.$foo->errorString."\n";
2942             }
2943              
2944             =cut
2945              
2946             sub errorString{
2947             return $_[0]->{errorString};
2948             }
2949              
2950             =head1 ERROR CODES
2951              
2952             =head2 1
2953              
2954             Could not read config.
2955              
2956             =head2 2
2957              
2958             Missing required variable.
2959              
2960             =head2 3
2961              
2962             Can't find a free UID.
2963              
2964             =head2 4
2965              
2966             Can't find a free GID.
2967              
2968             =head2 5
2969              
2970             No user name specified.
2971              
2972             =head2 6
2973              
2974             No group name specified.
2975              
2976             =head2 7
2977              
2978             UID is not numeric.
2979              
2980             =head2 8
2981              
2982             GID is not numeric.
2983              
2984             =head2 9
2985              
2986             User already exists.
2987              
2988             =head2 10
2989              
2990             Group already exists.
2991              
2992             =head2 11
2993              
2994             Connecting to LDAP failed.
2995              
2996             =head2 12
2997              
2998             Net::LDAP::posixGroup failed.
2999              
3000             =head2 13
3001              
3002             Failed to bind to the LDAP server.
3003              
3004             =head2 14
3005              
3006             The group does not exist.
3007              
3008             =head2 15
3009              
3010             The group does not exist in LDAP or under specified group base.
3011              
3012             =head2 16
3013              
3014             Failed to delete the group's entry.
3015              
3016             =head2 17
3017              
3018             The user does not exist.
3019              
3020             =head2 18
3021              
3022             The user does not exist in LDAP or under specified user base.
3023              
3024             =head2 19
3025              
3026             Adding the new entry failed.
3027              
3028             =head2 20
3029              
3030             The GID already exists.
3031              
3032             =head2 21
3033              
3034             Failed to create home.
3035              
3036             =head2 22
3037              
3038             Copying the skeleton to the home location failed.
3039              
3040             =head2 23
3041              
3042             Failed to chown the new home directory.
3043              
3044             =head2 24
3045              
3046             Failed to chmod the new home directory.
3047              
3048             =head2 25
3049              
3050             Failed to update a entry when removing a memberUid.
3051              
3052             =head2 26
3053              
3054             Failed to remove the users home directory.
3055              
3056             =head2 27
3057              
3058             Faild to fetch a list posixGroup objects.
3059              
3060             =head2 28
3061              
3062             No GID specified.
3063              
3064             =head2 29
3065              
3066             Failed to update the entry when changing the GID.
3067              
3068             =head2 30
3069              
3070             No UID specified.
3071              
3072             =head2 31
3073              
3074             Failed to update the entry when changing the UID.
3075              
3076             =head2 32
3077              
3078             Failed to fetch the user entry.
3079              
3080             =head2 33
3081              
3082             No GECOS specified.
3083              
3084             =head2 34
3085              
3086             Failed to update the entry when changing the GECOS.
3087              
3088             =head2 35
3089              
3090             No password specified.
3091              
3092             =head2 36
3093              
3094             Updating the password for the user failed.
3095              
3096             =head2 37
3097              
3098             Errored when fetching a list of users that may possibly need updated.
3099              
3100             =head2 38
3101              
3102             No LDAP object given.
3103              
3104             =head2 39
3105              
3106             $opts{do} has not been specified.
3107              
3108             =head2 40
3109              
3110             The specified selection of plugins to run does not exist.
3111              
3112             =head2 41
3113              
3114             Exectuting a plugin failed.
3115              
3116             =head2 42
3117              
3118             $opts{entry} is not defined.
3119              
3120             =head2 43
3121              
3122             $opts{entry} is not a Net::LDAP::Entry object.
3123              
3124             =head2 44
3125              
3126             $opts{ldap} is not a Net::LDAP object.
3127              
3128             =head2 45
3129              
3130             $returned{error} is set to true.
3131              
3132             =head2 46
3133              
3134             Calling the LDAP update function on the entry modified by the userSetPass
3135             plugin failed. The unix password has been set though.
3136              
3137             =head2 47
3138              
3139             No shell specified.
3140              
3141             =head1 CONFIG FILE
3142              
3143             The default is xdg_config_home().'/plugtoolsrc', which wraps
3144             around to "~/.config/plugtoolsrc". The file format is ini.
3145              
3146             The only required ones are 'bind', 'pass', 'groupbase', and
3147             'userbase'.
3148              
3149             bind=cn=admin,dc=foo,dc=bar
3150             pass=somebl00dyp@ssw0rd
3151             userbase=ou=users,dc=foo,dc=bar
3152             groupbase=ou=groups,dc=foo,dc=bar
3153              
3154             =head2 bind
3155              
3156             This is the DN to bind as.
3157              
3158             =head2 pass
3159              
3160             This is the password for the bind DN.
3161              
3162             =head2 userbase
3163              
3164             This is the base for where the users are located.
3165              
3166             =head2 groupbase
3167              
3168             This is the base where the groups are located.
3169              
3170             =head2 server
3171              
3172             This is the LDAP server to connect to. If the server is not
3173             specified, '127.0.0.1' is used.
3174              
3175             =head2 port
3176              
3177             This is the LDAP port to use. If the port is not specified, '389'
3178             is used.
3179              
3180             =head2 UIDstart
3181              
3182             This is the first UID to start checking for existing users at. The default is '1001'.
3183              
3184             =head2 GIDstart
3185              
3186             This is the first GID to start checking for existing groups at. The default is '1001'.
3187              
3188             =head2 defaultShell
3189              
3190             This is the default shell for a user. The default is '/bin/tcsh'.
3191              
3192             =head2 HOMEproto
3193              
3194             The prototype for the home directory. %%USERNAME%% is replaced with
3195             the username. The default is '/home/%%USERNAME%%/'.
3196              
3197             =head2 skeletonHome
3198              
3199             This is the location that will be copied for when creating a new home directory. If this is not defined,
3200             a blanked one will be created. The default is '/etc/skel'.
3201              
3202             =head2 chmodValue
3203              
3204             This is the numeric value the newly created home directory will be chmoded to. The default is '640'.
3205              
3206             =head2 chmodHome
3207              
3208             If home should be chmoded. The default value is '1', true.
3209              
3210             =head2 chownHome
3211              
3212             If home should be chowned. The default value is '1', true.
3213              
3214             =head2 createHome
3215              
3216             If this is true, it the home directory for the user will be created. The default is '1'.
3217              
3218             =head2 groupPrimary
3219              
3220             This is the attribute to use for when creating the DN for the group entry. Either 'cn' or
3221             'gidNumber' are currently accepted. The default is 'cn'.
3222              
3223             =head2 userPrimary
3224              
3225             This is the attribute to use for when creating the DN for the user entry. Either
3226             'cn', 'uid', or 'uidNumber' are currently accepted. The default is 'uid'.
3227              
3228             =head2 starttls
3229              
3230             Wether or not it should try to do start_tls.
3231              
3232             =head2 TLSverify
3233              
3234             The verify mode for TLS. The default is 'none'.
3235              
3236             =head3 none
3237              
3238             The server may provide a certificate but it will not be
3239             checked - this may mean you are be connected to the wrong
3240             server.
3241              
3242             =head3 optional
3243              
3244             Verify only when the server offers a certificate.
3245              
3246             =head3 require
3247              
3248             The server must provide a certificate, and it must be valid.
3249              
3250             =head2 SSLversion
3251              
3252             This is the SSL versions accepted.
3253              
3254             'sslv2', 'sslv3', 'sslv2/3', or 'tlsv1' are the possible values. The default
3255             is 'tlsv1'.
3256              
3257             =head2 SSLciphers
3258              
3259             This is a list of ciphers to accept. The string is in the standard OpenSSL
3260             format. The default value is 'ALL'.
3261              
3262             =head2 removeGroup
3263              
3264             This determines if it should try to remove the user's primary group after removing the
3265             user.
3266              
3267             The default value is '1', true.
3268              
3269             =head2 removeHome
3270              
3271             This determines if it should try to remove a user's home directory when deleting the
3272             user.
3273              
3274             The default value is '0', false.
3275              
3276             =head2 userUpdate
3277              
3278             This determines if it should update the primary GIDs for users after groupGIDchange
3279             has been called.
3280              
3281             The default value is '1', true.
3282              
3283             =head2 pluginAddGroup
3284              
3285             A comma seperated list of plugins to run when addGroup is called.
3286              
3287             =head2 pluginAddUser
3288              
3289             A comma seperated list of plugins to run when addUser is called.
3290              
3291             =head2 pluginGroupAddUser
3292              
3293             A comma seperated list of plugins to run when groupAddUser is called.
3294              
3295             =head2 pluginGroupGIDchange
3296              
3297             A comma seperated list of plugins to run when groupGIDchange is called.
3298              
3299             =head2 pluginGroupRemoveUser
3300              
3301             A comma seperated list of plugins to run when groupRemoveUser is called.
3302              
3303             =head2 pluginUserGECOSchange
3304              
3305             A comma seperated list of plugins to run when userGECOSchange is called.
3306              
3307             =head2 pluginUserSetPass
3308              
3309             A comma seperated list of plugins to run when userSetPass is called.
3310              
3311             =head2 pluginUserGIDchange
3312              
3313             A comma seperated list of plugins to run when userGIDchange is called.
3314              
3315             =head2 pluginUserShellChange
3316              
3317             A comma seperated list of plugins to run when userShellChange is called.
3318              
3319             =head2 pluginUserUIDchange
3320              
3321             A comma seperated list of plugins to run when userUIDchange is called.
3322              
3323             =head2 pluginDeleteUser
3324              
3325             A comma seperated list of plugins to run when deleteUser is called.
3326              
3327             =head2 pluginDeleteGroup
3328              
3329             A comma seperated list of plugins to run when deleteGroup is called.
3330              
3331             =head1 PLUGINS
3332              
3333             Plugins are supported by the functions specified in the config section.
3334              
3335             A plugin may be specified for any of those by setting that value to a comma seperated
3336             list of plugins. For example if you wanted to call 'Plugtools::Plugins::Dump' and then
3337             'Foo::Bar' for a userSetPass, you would set the value 'pluginsUserSetPass' equal to
3338             'Plugtools::Plugins::Dump,Foo::Bar'.
3339              
3340             Both hashes specified in the section covering the plugin function. The key 'self' is added
3341             to %opts before it is passed to the plugin. That key contains a copy of the Plugtools object.
3342              
3343             A plugin is a Perl module that is used via eval and then the function 'plugin' is called on
3344             it. The expected return is
3345              
3346             The plugin is called before the update method is called on a Net::LDAP::Entry object, except for
3347             the function 'userSetPass'. It is called after the password is updated.
3348              
3349             =head2 example
3350              
3351             What is shown below is copied from Plugtools::Plugins::Dump. This is a simple plugin
3352             that calls Data::Dumper->Dumper on what is passed to it.
3353              
3354             package Plugtools::Plugins::Dump;
3355             use warnings;
3356             use strict;
3357             use Data::Dumper;
3358             our $VERSION = '0.0.0';
3359             sub plugin{
3360             my %opts;
3361             if(defined($_[1])){
3362             %opts= %{$_[1]};
3363             };
3364             my %args;
3365             if(defined($_[2])){
3366             %args= %{$_[2]};
3367             };
3368             print '%opts=...'."\n".Dumper(\%opts)."\n\n".'%args=...'."\n".Dumper(\%args);
3369             my %returned;
3370             $returned{error}=undef;
3371             return %returned;
3372             }
3373             1;
3374              
3375              
3376             =head1 AUTHOR
3377              
3378             Zane C. Bowers, C<< >>
3379              
3380             =head1 BUGS
3381              
3382             Please report any bugs or feature requests to C, or through
3383             the web interface at L. I will be notified, and then you'll
3384             automatically be notified of progress on your bug as I make changes.
3385              
3386              
3387              
3388              
3389             =head1 SUPPORT
3390              
3391             You can find documentation for this module with the perldoc command.
3392              
3393             perldoc Plugtools
3394              
3395              
3396             You can also look for information at:
3397              
3398             =over 4
3399              
3400             =item * RT: CPAN's request tracker
3401              
3402             L
3403              
3404             =item * AnnoCPAN: Annotated CPAN documentation
3405              
3406             L
3407              
3408             =item * CPAN Ratings
3409              
3410             L
3411              
3412             =item * Search CPAN
3413              
3414             L
3415              
3416             =back
3417              
3418              
3419             =head1 ACKNOWLEDGEMENTS
3420              
3421              
3422             =head1 COPYRIGHT & LICENSE
3423              
3424             Copyright 2010 Zane C. Bowers, all rights reserved.
3425              
3426             This program is free software; you can redistribute it and/or modify it
3427             under the same terms as Perl itself.
3428              
3429              
3430             =cut
3431              
3432             1; # End of Plugtools