File Coverage

blib/lib/Plugtools/Plugins/Samba.pm
Criterion Covered Total %
statement 12 249 4.8
branch 0 90 0.0
condition n/a
subroutine 4 11 36.3
pod 7 7 100.0
total 23 357 6.4


line stmt bran cond sub pod time code
1             package Plugtools::Plugins::Samba;
2              
3 4     4   31342 use warnings;
  4         11  
  4         124  
4 4     4   21 use strict;
  4         8  
  4         126  
5 4     4   3501 use Samba::SIDhelper;
  4         3135  
  4         173  
6 4     4   3555 use Crypt::SmbHash qw(lmhash nthash);
  4         87102  
  4         9133  
7              
8             =head1 NAME
9              
10             Plugtools::Plugins::Samba - Provides various methods used by the plugins in this.
11              
12             =head1 VERSION
13              
14             Version 0.1.1
15              
16             =cut
17              
18             our $VERSION = '0.1.1';
19              
20              
21             =head1 SYNOPSIS
22              
23             This module provides a collection of methods used by the Samba plugins for
24             Plugtools.
25              
26             use Plugtools::Plugins::Samba;
27             use Plugtools;
28              
29             my $pt=Plugtools->new;
30              
31             my $ldap=$pt->connect;
32              
33             my $pts = Plugtools::Plugins::Samba->new({
34             pt=>$pt,
35             ldap=>$ldap
36             });
37             ...
38              
39             =head1 METHODS
40              
41             =head2 new
42              
43             This initiates it.
44              
45             =head3 args hash
46              
47             =head4 pt
48              
49             This is a Plugtools object that has been successfully initiated.
50              
51             =head4 ldap
52              
53             This is the LDAP connection to use.
54              
55             my $pts = Plugtools::Plugins::Samba->new({
56             pt=>$pt,
57             ldap=>$ldap
58             });
59             if($pts->{error}){
60             print "Error!\n";
61             }
62              
63             =cut
64              
65             sub new {
66 0     0 1   my %args;
67 0 0         if(defined($_[1])){
68 0           %args= %{$_[1]};
  0            
69             };
70              
71 0           my $self = {error=>undef, errorString=>""};
72 0           bless $self;
73              
74             #make sure we have a Plugtools object and if we do, get it
75 0 0         if (!defined($args{pt})) {
76 0           $self->{error}=1;
77 0           $self->{errorString}='$args{pt} is undefined';
78 0           warn('Plugtools new:1: '.$self->{errorString});
79 0           return $self;
80             }
81 0           $self->{pt}=$args{pt};
82              
83             #make sure a SID is specified in the config file
84 0 0         if (!defined( $self->{pt}->{ini}->{samba}->{sid} )) {
85 0           $self->{error}=4;
86 0           $self->{errorString}='No value for "sid" defined in the section "samba" of the config file.';
87 0           warn('Plugtools-Plugins-Samba new:4: '.$self->{errorString});
88 0           return $self;
89             }
90              
91 0           $self->{sidhelper}=Samba::SIDhelper->new( { sid=>$self->{pt}->{ini}->{samba}->{sid} } );
92 0 0         if ($self->{sidhelper}->{error}) {
93 0           $self->{error}=5;
94 0           $self->{errorString}='Samba::SIDhelper errored. $self->{sidhelper}->{error}="'.$self->{sidhelper}->{error}
95             .'" $self->{sidhelper}->{errorString}="'.$self->{sidhelper}->{error}.'"';
96 0           warn('Plugtools-Plugins-Samba new:5: ',$self->{errorString});
97 0           return $self;
98             }
99              
100             #make sure we got a LDAP connection
101 0 0         if (!defined($args{ldap})) {
102 0           $self->{error}=2;
103 0           $self->{errorString}='$args{pt} is undefined';
104 0           warn('Plugtools new:1: '.$self->{errorString});
105 0           return $self;
106             }
107 0           $self->{ldap}=$args{ldap};
108              
109 0           return $self;
110             }
111              
112             =head2 isSambaAccountEntry
113              
114             This check if all the basic stuff is present for it to
115             be useful in regards to Samba. This checks to make sure
116             the objectclass 'sambaSamAccount' and the attributes 'sambaSID'
117             and 'sambaPrimaryGroupSID' are present.
118              
119             =head3 args hash
120              
121             =head4 entry
122              
123             This is the LDAP entry that will be used.
124              
125             my $returned=$pts->isSambaAccountEntry({entry=>$entry});
126             if($pts->{error}){
127             print "Error!\n";
128             }else{
129             if($returned){
130             print "It is!\n";
131             }
132             }
133              
134             =cut
135              
136             sub isSambaAccountEntry{
137 0     0 1   my $self=$_[0];
138 0           my %args;
139 0 0         if(defined($_[1])){
140 0           %args= %{$_[1]};
  0            
141             };
142              
143 0           $self->errorblank;
144              
145             #make sure we have a LDAP entry
146 0 0         if (!defined($args{entry})) {
147 0           $self->{error}=3;
148 0           $self->{errorString}='No LDAP entry defined';
149 0           warn('Plugtools-Plugins-Samba isSambaAccountEntry:3: '.$self->{errorString});
150 0           return undef;
151             }
152              
153             #check if any of the object classes are the correct type
154 0           my @objectClasses=$args{entry}->get_value('objectClass');
155 0           my $int=0;
156 0           my $found=0;
157 0           while (defined($objectClasses[$int])) {
158 0 0         if ($objectClasses[$int] eq 'sambaSamAccount') {
159 0           $found=1;
160             }
161              
162 0           $int++;
163             }
164 0 0         if (!$found) {
165 0           return undef;
166             }
167              
168             #make sure we have a SID
169 0           my $sid=$args{entry}->get_value('sambaSID');
170 0 0         if (!defined($sid)) {
171 0           return undef;
172             }
173              
174             #make sure we have a primary group SID
175 0           my $pgsid=$args{entry}->get_value('sambaPrimaryGroupSID');
176 0 0         if (!defined($pgsid)) {
177 0           return undef;
178             }
179              
180 0           return 1;
181             }
182              
183             =head2 makeSambaAccountEntry
184              
185             If a entry is not already a Samba account, make it one.
186              
187             If it already is, it will error.
188              
189             This will not update the entry that is passed to it. That will
190             need to be done upon this returning with out any errors being
191             set.
192              
193             =head3 args hash
194              
195             =head4 entry
196              
197             This is the Net::LDAP::Entry object to work on.
198              
199             =head4 sid
200              
201             This is the SID to use for the entry.
202              
203             =head4 pgsid
204              
205             This is the primary group SID to use.
206              
207             $pts->makeSambaAccountEntry({ entry=>$entry });
208             if($pts->{error}){
209             print "Error!\n";
210             }
211              
212             $pts->makeSambaAccountEntry({
213             entry=>$entry,
214             sid=>$sid,
215             pgsid=>$pgsid,
216             });
217             if($pts->{error}){
218             print "Error!\n";
219             }
220              
221             =cut
222              
223             sub makeSambaAccountEntry{
224 0     0 1   my $self=$_[0];
225 0           my %args;
226 0 0         if(defined($_[1])){
227 0           %args= %{$_[1]};
  0            
228             };
229              
230             #make sure we have a LDAP entry
231 0 0         if (!defined($args{entry})) {
232 0           $self->{error}=3;
233 0           $self->{errorString}='No LDAP entry defined';
234 0           warn('Plugtools-Plugins-Samba makeSambaAccountEntry:3: '.$self->{errorString});
235 0           return undef;
236             }
237              
238             #check if it is already a samba account or not
239 0           my $returned=$self->isSambaAccountEntry({ entry=>$args{entry} });
240 0 0         if ($self->{error}) {
241 0           warn('Plugtools-Plugins-Samba makeSambaAccountEntry: isSambaAccountEntry failed');
242 0           return undef;
243             }
244 0 0         if ($returned) {
245 0           $self->{error}=7;
246 0           $self->{errorString}='The entry, "'.$args{entry}->dn.'", is already a samba account';
247 0           warn('Plugtools-Plugins-Samba makeSambaAccountEntry:7: '.$self->{errorString});
248 0           return undef;
249             }
250            
251             #make sure we have a SID
252 0 0         if (!defined($args{sid})) {
253 0           my $uid=$args{entry}->get_value('uidNumber');
254 0 0         if (!defined($uid)) {
255 0           $self->{error}=6;
256 0           $self->{errorString}='No "uidNumber" attribute present for "'.$args{entry}->dn.'"';
257 0           warn('Plugtools-Plugins-Samba makeSambaAccountEntry:6: '.$self->{errorString});
258 0           return undef;
259             }
260              
261 0           $args{sid}=$self->{sidhelper}->uid2sid($uid);
262 0 0         if ($self->{sidhelper}->{error}) {
263 0           $self->{error}=5;
264 0           $self->{errorString}='Samba::SIDhelper errored. $self->{sidhelper}->{error}="'.$self->{sidhelper}->{error}
265             .'" $self->{sidhelper}->{errorString}="'.$self->{sidhelper}->{error}.'"';
266 0           warn('Plugtools-Plugins-Samba makeSanbaAccountEntry:5: ',$self->{errorString});
267 0           return undef;
268             }
269             }
270              
271             #make sure we have a pgsid
272 0 0         if (!defined($args{pgsid})) {
273 0           my $gid=$args{entry}->get_value('gidNumber');
274 0 0         if (!defined($gid)) {
275 0           $self->{error}=8;
276 0           $self->{errorString}='No "gidNumber" attribute present for "'.$args{entry}->dn.'"';
277 0           warn('Plugtools-Plugins-Samba makeSambaAccountEntry:8: '.$self->{errorString});
278 0           return undef;
279             }
280              
281 0           $args{pgsid}=$self->{sidhelper}->gid2sid($gid);
282 0 0         if ($self->{sidhelper}->{error}) {
283 0           $self->{error}=5;
284 0           $self->{errorString}='Samba::SIDhelper errored. $self->{sidhelper}->{error}="'.$self->{sidhelper}->{error}
285             .'" $self->{sidhelper}->{errorString}="'.$self->{sidhelper}->{error}.'"';
286 0           warn('Plugtools-Plugins-Samba makeSanbaAccountEntry:5: ',$self->{errorString});
287 0           return undef;
288             }
289             }
290            
291             #isSambaAccountEntry just checks if it is properly setup... if one of the following is missing,
292             #then it should be removed and then re-added
293 0           my $sid=$args{entry}->get_value('sambaSID');
294 0 0         if (defined($sid)) {
295 0           $args{entry}->delete('sambaSID');
296             }
297 0           my $pgsid=$args{entry}->get_value('sambaPrimaryGroupSID');
298 0 0         if (defined($pgsid)) {
299 0           $args{entry}->delete('sambaPrimaryGroupSID');
300             }
301 0           my @ocA=$args{entry}->get_value('objectClass');
302 0           my $int=0;
303 0           while (defined($ocA[$int])) {
304 0 0         if ($ocA[$int] eq 'sambaSamAccount') {
305 0           $args{entry}->delete('objectClass'=>'sambaSamAccount');
306             }
307              
308 0           $int++;
309             }
310              
311 0           $args{entry}->add('objectClass'=>'sambaSamAccount');
312 0           $args{entry}->add('sambaSID'=>$args{sid});
313 0           $args{entry}->add('sambaPrimaryGroupSID'=>$args{pgsid});
314              
315 0           return 1;
316             }
317              
318             =head2 removeSambaAcctEntry
319              
320             Remove the samba stuff from a user.
321              
322             =head3 entry
323              
324             This is a Net::LDAP::Entry to remove attributes
325             related to sambaSamAccount from.
326              
327             =cut
328              
329             sub removeSambaAcctEntry{
330 0     0 1   my $self=$_[0];
331 0           my %args;
332 0 0         if(defined($_[1])){
333 0           %args= %{$_[1]};
  0            
334             };
335              
336             #make sure we have a LDAP entry
337 0 0         if (!defined($args{entry})) {
338 0           $self->{error}=3;
339 0           $self->{errorString}='No LDAP entry defined';
340 0           warn('Plugtools-Plugins-Samba makeSambaAccountEntry:3: '.$self->{errorString});
341 0           return undef;
342             }
343              
344 0           my @OCs=$args{entry}->get_value('objectClass');
345 0           my $int=0;
346 0           my $matched=0;
347 0           while (defined($OCs[$int])) {
348 0 0         if ($OCs[$int] eq 'sambaSamAccount') {
349 0           $matched=1;
350             }
351              
352 0           $int++;
353             }
354              
355             #nothing to do
356 0 0         if (!$matched) {
357 0           return 1;
358             }
359              
360 0           $args{entry}->delete('objectClass'=>'sambaSamAccount');
361              
362 0           my @attributes=(
363             'sambaLMPassword',
364             'sambaNTPassword',
365             'sambaPwdLastSet',
366             'sambaLogonTime',
367             'sambaLogoffTime',
368             'sambaKickoffTime',
369             'sambaPwdCanChange',
370             'sambaPwdMustChange',
371             'sambaAcctFlags',
372             'sambaHomePath',
373             'sambaHomeDrive',
374             'sambaLogonScript',
375             'sambaProfilePath',
376             'sambaUserWorkstations',
377             'sambaPrimaryGroupSID',
378             'sambaDomainName',
379             'sambaMungedDial',
380             'sambaBadPasswordCount',
381             'sambaBadPasswordTime',
382             'sambaPasswordHistory',
383             'sambaLogonHours',
384             );
385              
386             #tests for any possible attributes
387 0           $int=0;
388 0           while ($attributes[$int]) {
389 0           my $test=$args{entry}=get_value($attributes[$int]);
390              
391             #if it is is present, remove it
392 0 0         if (defined($test)) {
393 0           $args{entry}->delete($attributes[$int]);
394             }
395              
396 0           $int++;
397             }
398              
399 0           return 1;
400             }
401              
402             =head2 setPassEntry
403              
404             This sets the password for a Samba account.
405              
406             =head3 args hash
407              
408             =head4 entry
409              
410             This is the Net::LDAP::Entry object to work on.
411              
412             =head4 pass
413              
414             This is the password to set.
415              
416             $pts->setPassEntry({
417             entry=>$entry,
418             pass=>'somepass',
419             });
420             if($pts->{error}){
421             print "Error!\n";
422             }
423              
424             =cut
425              
426             sub setPassEntry{
427 0     0 1   my $self=$_[0];
428 0           my %args;
429 0 0         if(defined($_[1])){
430 0           %args= %{$_[1]};
  0            
431             };
432              
433 0           $self->errorblank;
434              
435             #make sure we have a LDAP entry
436 0 0         if (!defined($args{entry})) {
437 0           $self->{error}=3;
438 0           $self->{errorString}='No LDAP entry defined';
439 0           warn('Plugtools-Plugins-Samba setPassEntry:3: '.$self->{errorString});
440 0           return undef;
441             }
442              
443             #check if it is already a samba account or not
444 0           my $returned=$self->isSambaAccountEntry({ entry=>$args{entry} });
445 0 0         if ($self->{error}) {
446 0           warn('Plugtools-Plugins-Samba makeSambaAccountEntry: isSambaAccountEntry failed');
447 0           return undef;
448             }
449 0 0         if (!$returned) {
450 0           $self->{error}=10;
451 0           $self->{errorString}='The entry, "'.$args{entry}->dn.'", is not a samba account';
452 0           warn('Plugtools-Plugins-Samba setPassEntry:10: '.$self->{errorString});
453 0           return undef;
454             }
455              
456             #make sure we have a password
457 0 0         if (!defined($args{pass})) {
458 0           $self->{error}=9;
459 0           $self->{errorString}='No password specified';
460 0           warn('Plugtools-Plugins-Samba setPAssEntry:9: '.$self->{errorString});
461 0           return undef;
462             }
463              
464 0           my $ntp=$args{entry}->get_value('sambaNTPassword');
465 0 0         if ($ntp) {
466 0           $args{entry}->delete('sambaNTPassword');
467             }
468              
469 0           my $lmp=$args{entry}->get_value('sambaLMPassword');
470 0 0         if ($lmp) {
471 0           $args{entry}->delete('sambaLMPassword');
472             }
473              
474 0           $lmp=$args{entry}->get_value('sambaPwdLastSet');
475 0 0         if ($lmp) {
476 0           $args{entry}->delete('sambaPwdLastSet');
477             }
478              
479 0           $args{entry}->add('sambaNTPassword'=>nthash($args{pass}));
480 0           $args{entry}->add('sambaLMPassword'=>lmhash($args{pass}));
481 0           $args{entry}->add('sambaPwdLastSet'=>time());
482              
483 0           return 1;
484             }
485              
486             =head2 sidUpdateEntry
487              
488             =head3 args hash
489              
490             =head4 entry
491              
492             This is the Net::LDAP::Entry object to work on.
493              
494             =cut
495              
496             sub sidUpdateEntry{
497 0     0 1   my $self=$_[0];
498 0           my %args;
499 0 0         if(defined($_[1])){
500 0           %args= %{$_[1]};
  0            
501             };
502              
503 0           $self->errorblank;
504              
505             #make sure we have a LDAP entry
506 0 0         if (!defined($args{entry})) {
507 0           $self->{error}=3;
508 0           $self->{errorString}='No LDAP entry defined';
509 0           warn('Plugtools-Plugins-Samba sidUpdateEntry:3: '.$self->{errorString});
510 0           return undef;
511             }
512              
513             #check if it is already a samba account or not
514 0           my $returned=$self->isSambaAccountEntry({ entry=>$args{entry} });
515 0 0         if ($self->{error}) {
516 0           warn('Plugtools-Plugins-Samba sidUpdateEntry: isSambaAccountEntry failed');
517 0           return undef;
518             }
519 0 0         if (!$returned) {
520 0           $self->{error}=10;
521 0           $self->{errorString}='The entry, "'.$args{entry}->dn.'", is not a samba account';
522 0           warn('Plugtools-Plugins-Samba sidUpdateEntry:10: '.$self->{errorString});
523 0           return undef;
524             }
525              
526             #make sure we have a uid
527 0           my $uid=$args{entry}->get_value('uidNumber');
528 0 0         if (!defined($uid)) {
529 0           $self->{error}=11;
530 0           $self->{errorString}='"'.$args{entry}->dn.'" lacks a uidNumber attribute';
531 0           warn('Plugtools-Plugins-Samba sidUpdateEntry:11: '.$self->{errorString});
532 0           return undef;
533             }
534              
535             #make sure we have a gid
536 0           my $gid=$args{entry}->get_value('gidNumber');
537 0 0         if (!defined($gid)) {
538 0           $self->{error}=12;
539 0           $self->{errorString}='"'.$args{entry}->dn.'" lacks a gidNumber attribute';
540 0           warn('Plugtools-Plugins-Samba sidUpdateEntry:12: '.$self->{errorString});
541 0           return undef;
542             }
543              
544             #remove the old values
545 0           $args{entry}->delete('sambaSID');
546 0           $args{entry}->delete('sambaPrimaryGroupSID');
547              
548             #convert the uid
549 0           my $sid=$self->{sidhelper}->uid2sid($uid);
550 0 0         if ($self->{sidhelper}->{error}) {
551 0           $self->{error}=5;
552 0           $self->{errorString}='Samba::SIDhelper errored. $self->{sidhelper}->{error}="'.$self->{sidhelper}->{error}
553             .'" $self->{sidhelper}->{errorString}="'.$self->{sidhelper}->{error}.'"';
554 0           warn('Plugtools-Plugins-Samba sidUpdateEntry:5: ',$self->{errorString});
555 0           return undef;
556             }
557              
558             #convert the gid
559 0           my $pgsid=$self->{sidhelper}->gid2sid($gid);
560 0 0         if ($self->{sidhelper}->{error}) {
561 0           $self->{error}=5;
562 0           $self->{errorString}='Samba::SIDhelper errored. $self->{sidhelper}->{error}="'.$self->{sidhelper}->{error}
563             .'" $self->{sidhelper}->{errorString}="'.$self->{sidhelper}->{error}.'"';
564 0           warn('Plugtools-Plugins-Samba sidUpdateEntry:5: ',$self->{errorString});
565 0           return undef;
566             }
567              
568             #add the new values
569 0           $args{entry}->add('sambaSID'=>$sid);
570 0           $args{entry}->add('sambaPrimaryGroupSID'=>$pgsid);
571              
572 0           return 1;
573             }
574              
575             =head2 errorblank
576              
577             This is a internal function and should not be called.
578              
579             =cut
580              
581             #blanks the error flags
582             sub errorblank{
583 0     0 1   my $self=$_[0];
584              
585 0           $self->{error}=undef;
586 0           $self->{errorString}="";
587              
588 0           return 1;
589             };
590              
591             =head1 ERROR CODES
592              
593             =head2 1
594              
595             No Plugtools object given.
596              
597             =head2 2
598              
599             No LDAP connection specified.
600              
601             =head2 3
602              
603             No entry given.
604              
605             =head2 4
606              
607             No value for 'sid' defined in the section 'samba' of the config file.
608              
609             =head2 5
610              
611             Samba::SIDhelper errored.
612              
613             =head2 6
614              
615             The LDAP entry lacks a uidNumber attribute.
616              
617             =head2 7
618              
619             Already a samba a account.
620              
621             =head2 8
622              
623             The LDAP entry lacks a gidNumber attribute.
624              
625             =head2 9
626              
627             No password specified.
628              
629             =head2 10
630              
631             The LDAP entry is not a samba account.
632              
633             =head2 11
634              
635             The entry lacks a uidNumber attribute.
636              
637             =head2 12
638              
639             The entry lacks a uidNumber attribute.
640              
641             =head1 Plugtools CONFIG
642              
643             Only one additional setting is needed. That is 'sid' setup in the secion 'samba'.
644              
645             The SID can be gotten by running 'net getlocalsid'.
646              
647             pluginUserSetPass=Plugtools::Plugins::Samba::setPass
648             pluginUserGIDchange=Plugtools::Plugins::Samba::SIDupdate
649             pluginUserUIDchange=Plugtools::Plugins::Samba::SIDupdate
650             pluginAddUser=Plugtools::Plugins::Samba::makeSambaAccount
651             [samba]
652             sid=S-1-5-21-1234-5678-91011
653              
654             =head1 AUTHOR
655              
656             Zane C. Bowers, C<< >>
657              
658             =head1 BUGS
659              
660             Please report any bugs or feature requests to C, or through
661             the web interface at L. I will be notified, and then you'll
662             automatically be notified of progress on your bug as I make changes.
663              
664              
665              
666              
667             =head1 SUPPORT
668              
669             You can find documentation for this module with the perldoc command.
670              
671             perldoc Plugtools::Plugins::Samba
672              
673              
674             You can also look for information at:
675              
676             =over 4
677              
678             =item * RT: CPAN's request tracker
679              
680             L
681              
682             =item * AnnoCPAN: Annotated CPAN documentation
683              
684             L
685              
686             =item * CPAN Ratings
687              
688             L
689              
690             =item * Search CPAN
691              
692             L
693              
694             =back
695              
696              
697             =head1 ACKNOWLEDGEMENTS
698              
699              
700             =head1 COPYRIGHT & LICENSE
701              
702             Copyright 2009 Zane C. Bowers, all rights reserved.
703              
704             This program is free software; you can redistribute it and/or modify it
705             under the same terms as Perl itself.
706              
707              
708             =cut
709              
710             1; # End of Plugtools::Plugins::Samba