File Coverage

blib/lib/ZConf/backends/ldap.pm
Criterion Covered Total %
statement 33 913 3.6
branch 0 358 0.0
condition n/a
subroutine 11 33 33.3
pod 22 22 100.0
total 66 1326 4.9


line stmt bran cond sub pod time code
1             package ZConf::backends::ldap;
2              
3 1     1   41622 use Net::LDAP;
  1         198965  
  1         7  
4 1     1   1016 use Net::LDAP::LDAPhash;
  1         559  
  1         51  
5 1     1   780 use Net::LDAP::Makepath;
  1         4356  
  1         47  
6 1     1   853 use Chooser;
  1         74166  
  1         86  
7 1     1   16 use warnings;
  1         2  
  1         34  
8 1     1   6 use strict;
  1         1  
  1         31  
9 1     1   1020 use ZML;
  1         6218  
  1         35  
10 1     1   10 use Sys::Hostname;
  1         2  
  1         69  
11 1     1   937 use Net::LDAP::AutoDNs;
  1         1641  
  1         31  
12 1     1   872 use Net::LDAP::AutoServer;
  1         85258  
  1         38  
13 1     1   12 use base 'Error::Helper';
  1         2  
  1         12481  
14              
15             =head1 NAME
16              
17             ZConf::backends::ldap - This provides LDAP backend for ZConf.
18              
19             =head1 VERSION
20              
21             Version 0.1.0
22              
23             =cut
24              
25             our $VERSION = '0.1.0';
26              
27             =head1 METHODS
28              
29             =head2 new
30              
31             my $zconf=ZConf->(\%args);
32              
33             This initiates the ZConf object. If it can't be initiated, a value of undef
34             is returned. The hash can contain various initization options.
35              
36             When it is run for the first time, it creates a filesystem only config file.
37              
38             =head3 args hash
39              
40             =head4 sys
41              
42             This turns system mode on. And sets it to the specified system name.
43              
44             This is incompatible with the file option.
45              
46             =head4 self
47              
48             This is the copy of the ZConf object intiating it.
49              
50             =head4 zconf
51              
52             This is the variables found in the ~/.config/zconf.zml.
53              
54             my $backend=ZConf::backends::ldap->new( \%args );
55             if($zconf->{error}){
56             warn('error: '.$zconf->error.":".$zconf->errorString);
57             }
58              
59             =cut
60              
61             #create it...
62             sub new {
63 0     0 1   my %args;
64 0 0         if(defined($_[1])){
65 0           %args= %{$_[1]};
  0            
66             };
67              
68             #The thing that will be returned.
69             #conf holds configs
70             #args holds the arguements passed to new as well as runtime parameters
71             #set contains what set is in use for any loaded config
72             #zconf contains the parsed contents of zconf.zml
73             #user is space reserved for what ever the user of this package may wish to
74             # use it for... if they ever find the need to or etc... reserved for
75             # the prevention of poeple shoving stuff into $self->{} where ever
76             # they please... probally some one still will... but this is intented
77             # to help minimize it...
78             #error this is undef if, otherwise it is a integer for the error in question
79             #errorString this is a string describing the error
80             #meta holds meta variable information
81 0           my $self = {conf=>{}, args=>\%args, set=>{}, zconf=>{}, user=>{}, error=>undef,
82             errorString=>"", meta=>{}, comment=>{}, module=>__PACKAGE__,
83             revision=>{}, locked=>{}, autoupdateGlobal=>1, autoupdate=>{}};
84 0           bless $self;
85 0           $self->{module}=~s/\:\:/\-/g;
86              
87             #####################################
88             #real in the stuff from the arguments
89             #make sure we have a ZConf object
90 0 0         if (!defined( $args{self} )) {
91 0           $self->{error}=47;
92 0           $self->{errorString}='No ZConf object passed';
93 0           $self->warn;
94 0           return $self;
95             }
96 0 0         if ( ref($args{self}) ne 'ZConf' ) {
97 0           $self->{error}=47;
98 0           $self->{errorString}='No ZConf object passed. ref returned "'.ref( $args{self} ).'"';
99 0           $self->warn;
100 0           return $self;
101             }
102 0           $self->{self}=$args{self};
103 0 0         if (!defined( $args{zconf} )) {
104 0           $self->{error}=48;
105 0           $self->{errorString}='No zconf.zml var hash passed';
106 0           $self->warn;
107 0           return $self;
108             }
109 0 0         if ( ref($args{zconf}) ne 'HASH' ) {
110 0           $self->{error}=48;
111 0           $self->{errorString}='No zconf.zml var hash passed. ref returned "'.ref( $args{zconf} ).'"';
112 0           $self->warn;
113 0           return $self;
114             }
115 0           $self->{zconf}=$args{zconf};
116             #####################################
117              
118             #if defaultChooser is defined, use it to find what the default should be
119 0 0         if(defined($self->{zconf}{defaultChooser})){
120             #runs choose if it is defined
121 0           my ($success, $choosen)=choose($self->{zconf}{defaultChooser});
122 0 0         if($success){
123             #check if the choosen has a legit name
124             #if it does not, set it to default
125 0 0         if($self->{self}->setNameLegit($choosen)){
126 0           $self->{args}{default}=$choosen;
127             }else{
128 0           $self->{args}{default}="default";
129             }
130             }else{
131 0           $self->{args}{default}="default";
132             }
133             }else{
134 0 0         if(defined($self->{zconf}{default})){
135 0           $self->{args}{default}=$self->{zconf}{default};
136             }else{
137 0           $self->{args}{default}="default";
138             }
139             }
140              
141             #figures out what profile to use
142 0 0         if (defined($self->{zconf}{LDAPprofileChooser})) {
143             #run the chooser to get the LDAP profile to use
144 0           my ($success, $choosen)=choose($self->{zconf}{LDAPprofileChooser});
145             #if the chooser fails, set the profile to default
146 0 0         if (!$success) {
147 0           $self->{args}{LDAPprofile}="default";
148             } else {
149 0           $self->{args}{LDAPprofile}=$choosen;
150             }
151             } else {
152             #if LDAPprofile is defined, use it, if not set it to default
153 0 0         if (defined($self->{zconf}{LDAPprofile})) {
154 0           $self->{args}{LDAPprofile}=$self->{zconf}{LDAPprofile};
155             } else {
156 0           $self->{args}{LDAPprofile}="default";
157             }
158             }
159              
160             #will be used for auto population
161 0           my $autoDNs=Net::LDAP::AutoDNs->new;
162 0           my $autoserver=Net::LDAP::AutoServer->new;
163              
164             #gets the host
165 0 0         if(defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/host"})){
166 0           $self->{args}{"ldap/host"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/host"};
167             }else{
168             #sets it to localhost if not defined
169 0 0         if (defined( $autoserver->{server} )) {
170 0           $self->{args}{'ldap/host'}=$autoserver->{server};
171             }else {
172 0           $self->{args}{'ldap/host'}='127.0.0.1';
173             }
174             }
175            
176             #gets the capath
177 0 0         if(defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/capath"})){
178 0           $self->{args}{"ldap/capath"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/capath"};
179             }else{
180             #sets it to localhost if not defined
181 0 0         if (defined( $autoserver->{CApath} )) {
182 0           $self->{args}{"ldap/capath"}=$autoserver->{CApath};
183             }else {
184 0           $self->{args}{"ldap/capath"}=undef;
185             }
186             }
187            
188             #gets the cafile
189 0 0         if(defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/cafile"})){
190 0           $self->{args}{"ldap/cafile"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/cafile"};
191             }else{
192             #sets it to localhost if not defined
193 0 0         if (defined( $autoserver->{CAfile} )) {
194 0           $self->{args}{"ldap/cafile"}=$autoserver->{CAfile};
195             }else {
196 0           $self->{args}{"ldap/cafile"}=undef;
197             }
198             }
199            
200             #gets the checkcrl
201 0 0         if(defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/checkcrl"})){
202 0           $self->{args}{"ldap/checkcrl"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/checkcrl"};
203             }else{
204             #sets it to localhost if not defined
205 0 0         if (defined( $autoserver->{checkCRL} )) {
206 0           $self->{args}{"ldap/checkcrl"}=$autoserver->{checkCRL};
207             }else {
208 0           $self->{args}{"ldap/checkcrl"}=undef;
209             }
210             }
211            
212             #gets the clientcert
213 0 0         if(defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/clientcert"})){
214 0           $self->{args}{"ldap/clientcert"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/clientcert"};
215             }else{
216             #sets it to localhost if not defined
217 0 0         if (defined( $autoserver->{clientCert} )) {
218 0           $self->{args}{"ldap/clientcert"}=$autoserver->{clientCert};
219             }else {
220 0           $self->{args}{"ldap/clientcert"}=undef;
221             }
222             }
223              
224             #gets the clientkey
225 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/clientkey"})) {
226 0           $self->{args}{"ldap/clientkey"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/clientkey"};
227             } else {
228             #sets it to localhost if not defined
229 0 0         if (defined( $autoserver->{clientKey} )) {
230 0           $self->{args}{"ldap/clientkey"}=$autoserver->{clientKey};
231             } else {
232 0           $self->{args}{"ldap/clientkey"}=undef;
233             }
234             }
235              
236             #gets the starttls
237 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/starttls"})) {
238 0           $self->{args}{"ldap/starttls"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/starttls"};
239             } else {
240             #sets it to localhost if not defined
241 0 0         if (defined( $autoserver->{startTLS} )) {
242 0           $self->{args}{"ldap/starttls"}=$autoserver->{startTLS};
243             } else {
244 0           $self->{args}{"ldap/starttls"}=undef;
245             }
246             }
247              
248             #gets the TLSverify
249 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/TLSverify"})) {
250 0           $self->{args}{"ldap/TLSverify"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/TLSverify"};
251             } else {
252             #sets it to localhost if not defined
253 0           $self->{args}{"ldap/TLSverify"}='none';
254             }
255              
256             #gets the SSL version to use
257 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/SSLversion"})) {
258 0           $self->{args}{"ldap/SSLversion"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/SSLversion"};
259             } else {
260             #sets it to localhost if not defined
261 0           $self->{args}{"ldap/SSLversion"}='tlsv1';
262             }
263              
264             #gets the SSL ciphers to use
265 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/SSLciphers"})) {
266 0           $self->{args}{"ldap/SSLciphers"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/SSLciphers"};
267             } else {
268             #sets it to localhost if not defined
269 0           $self->{args}{"ldap/SSLciphers"}='ALL';
270             }
271              
272             #gets the password value to use
273 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/password"})) {
274 0           $self->{args}{"ldap/password"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/password"};
275             } else {
276             #sets it to localhost if not defined
277 0 0         if (defined( $autoserver->{pass} )) {
278 0           $self->{args}{"ldap/password"}=$autoserver->{pass};
279             } else {
280 0           $self->{args}{"ldap/password"}="";
281             }
282             }
283              
284             #gets the password value to use
285 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/passwordfile"})) {
286 0           $self->{args}{"ldap/passwordfile"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/passwordfile"};
287 0 0         if (open( PASSWORDFILE, $self->{args}{"ldap/passwordfile"} )) {
288 0           $self->{args}{"ldap/password"}=join( "\n", );
289 0           close(PASSWORDFILE);
290             } else {
291 0           $self->warnString('Failed to open the password file, "'.
292             $self->{args}{"ldap/passwordfile"}.'",');
293             }
294             }
295              
296             #gets the home DN
297 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/homeDN"})) {
298 0           $self->{args}{"ldap/homeDN"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/homeDN"};
299             } else {
300 0 0         if (defined( $autoDNs->{home} )) {
301 0           $self->{args}{"ldap/homeDN"}='ou='.$ENV{USER}.','.$autoDNs->{home};
302             } else {
303 0           $self->{args}{"ldap/homeDN"}=`hostname`;
304 0           chomp($self->{args}{"ldap/bind"});
305             #the next three lines can result in double comas.
306 0           $self->{args}{"ldap/homeDN"}=~s/^.*\././ ;
307 0           $self->{args}{"ldap/homeDN"}=~s/\./,dc=/g ;
308 0           $self->{args}{"ldap/homeDN"}="ou=".$ENV{USER}.",ou=home,".$self->{args}{"ldap/bind"};
309             #remove any double comas if they crop up
310 0           $self->{args}{"ldap/homeDN"}=~s/,,/,/g;
311             }
312             }
313              
314             #get the LDAP base
315 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/base"})) {
316 0           $self->{args}{"ldap/base"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/base"};
317             }else {
318 0           $self->{args}{"ldap/base"}="ou=zconf,ou=.config,".$self->{args}{"ldap/homeDN"};
319             }
320              
321             #gets bind to use
322 0 0         if (defined($self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/bind"})) {
323 0           $self->{args}{"ldap/bind"}=$self->{zconf}{"ldap/".$self->{args}{LDAPprofile}."/bind"};
324             } else {
325 0 0         if (defined( $autoserver->{bind} )) {
326 0           $self->{args}{"ldap/bind"}=$autoserver->{bind};
327             } else {
328 0           $self->{args}{"ldap/bind"}=hostname;
329 0           chomp($self->{args}{"ldap/bind"});
330             #the next three lines can result in double comas.
331 0           $self->{args}{"ldap/bind"}=~s/^[0-9a-zA-Z\-\_]*\././ ;
332 0           $self->{args}{"ldap/bind"}=~s/\./,dc=/g ;
333 0           $self->{args}{"ldap/bind"}="uid=".$ENV{USER}.",ou=users,".$self->{args}{"ldap/bind"};
334             #remove any double comas if they crop up
335 0           $self->{args}{"ldap/bind"}=~s/,,/,/g;
336             }
337            
338             #tests the connection
339 0           my $ldap=$self->LDAPconnect;
340 0 0         if ($self->error) {
341 0           $self->warnString('LDAPconnect errored');
342 0           return $self;
343             }
344            
345             #tests if "ou=.config,".$self->{args}{"ldap/homeDN"} exists or nnot...
346             #if it does not, try to create it...
347 0           my $ldapmesg=$ldap->search(scope=>"base", base=>"ou=.config,".$self->{args}{"ldap/homeDN"},
348             filter => "(objectClass=*)");
349 0           my %hashedmesg=LDAPhash($ldapmesg);
350 0 0         if (!defined($hashedmesg{"ou=.config,".$self->{args}{"ldap/homeDN"}})) {
351 0           my $entry = Net::LDAP::Entry->new();
352 0           $entry->dn("ou=.config,".$self->{args}{"ldap/homeDN"});
353 0           $entry->add(objectClass => [ "top", "organizationalUnit" ], ou=>".config");
354 0           my $result = $ldap->update($entry);
355 0 0         if ($ldap->error()) {
356 0           $self->{error}=16;
357 0           $self->{errorString}="Unable to create one of the required entries for initializing this backend. error: ".$self->{args}{"ldap/base"}." ".$ldap->error."; code ",$ldap->errcode;
358 0           $self->warn;
359 0           return $self;
360             }
361             }
362            
363             #tests if "ldap/base" exists... try to create it if it does not
364 0           $ldapmesg=$ldap->search(scope=>"base", base=>$self->{args}{"ldap/base"},filter => "(objectClass=*)");
365 0           %hashedmesg=LDAPhash($ldapmesg);
366 0 0         if (!defined($hashedmesg{$self->{args}{"ldap/base"}})) {
367 0           my $entry = Net::LDAP::Entry->new();
368 0           $entry->dn($self->{args}{"ldap/base"});
369 0           $entry->add(objectClass => [ "top", "organizationalUnit" ], ou=>"zconf");
370 0           my $result = $ldap->update($entry);
371 0 0         if ($ldap->error()) {
372 0           $self->{error}=16;
373 0           $self->{errorString}="Unable to create one of the required entries for initializing this backend. error: ".$self->{args}{"ldap/base"}." ".$ldap->error."; code ",$ldap->errcode;
374 0           $self->warn;
375 0           return $self;
376             }
377             }
378            
379             #disconnects from the LDAP server
380 0           $ldap->unbind;
381             }
382              
383 0           return $self;
384             }
385              
386             =head2 config2dn
387              
388             This method converts the config name into part of a DN string. IT
389             is largely only for internal use and is used by the LDAP backend.
390              
391             my $partialDN = $zconf->config2dn("foo/bar");
392             if($zconf->error){
393             warn('error: '.$zconf->error.":".$zconf->errorString);
394             }
395              
396             =cut
397              
398             #converts the config to a DN
399             sub config2dn(){
400 0     0 1   my $self=$_[0];
401 0           my $config=$_[1];
402              
403 0           $self->errorblank;
404              
405 0 0         if ($config eq '') {
406 0           return '';
407             }
408              
409 0           my ($error, $errorString)=$self->{self}->configNameCheck($config);
410 0 0         if(defined($error)){
411 0           $self->{error}=$error;
412 0           $self->{errorString}=$errorString;
413 0           $self->warn;
414 0           return undef;
415             }
416              
417             #splits the config at every /
418 0           my @configSplit=split(/\//, $config);
419              
420 0           my $dn=undef; #stores the DN
421              
422 0           my $int=0; #used for intering through @configSplit
423             #does the conversion
424 0           while(defined($configSplit[$int])){
425 0 0         if(defined($dn)){
426 0           $dn="cn=".$configSplit[$int].",".$dn;
427             }else{
428 0           $dn="cn=".$configSplit[$int];
429             }
430            
431 0           $int++;
432             }
433            
434 0           return $dn;
435             }
436              
437             =head2 configExists
438              
439             This method methods exactly the same as configExists, but
440             for the LDAP backend.
441              
442             No config name checking is done to verify if it is a legit name or not
443             as that is done in configExists. The same is true for calling errorBlank.
444              
445             $zconf->configExistsLDAP("foo/bar")
446             if($zconf->error){
447             warn('error: '.$zconf->error.":".$zconf->errorString);
448             }
449              
450             =cut
451              
452             #check if a LDAP config exists
453             sub configExists{
454 0     0 1   my ($self, $config) = @_;
455              
456 0           $self->errorblank;
457              
458 0           my @lastitemA=split(/\//, $config);
459 0           my $lastitem=$lastitemA[$#lastitemA];
460              
461             #gets the LDAP message
462 0           my $ldapmesg=$self->LDAPgetConfMessage($config);
463             #return upon error
464 0 0         if (defined($self->{error})) {
465 0           return undef;
466             }
467              
468 0           my %hashedmesg=LDAPhash($ldapmesg);
469             # $ldap->unbind;
470 0           my $dn=$self->config2dn($config);
471 0           $dn=$dn.",".$self->{args}{"ldap/base"};
472              
473 0 0         if(!defined($hashedmesg{$dn})){
474 0           return undef;
475             }
476              
477 0           return 1;
478             }
479              
480             =head2 createConfig
481              
482             This methods just like createConfig, but is for the LDAP backend.
483             This is not really meant for external use. The config name passed
484             is not checked to see if it is legit or not.
485              
486             $zconf->createConfigLDAP("foo/bar")
487             if($zconf->error){
488             warn('error: '.$zconf->error.":".$zconf->errorString);
489             };
490              
491             =cut
492              
493             #creates a new LDAP enty if it is not defined
494             sub createConfig{
495 0     0 1   my ($self, $config) = @_;
496              
497 0           $self->errorblank;
498              
499             #converts the config name to a DN
500 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
501              
502 0           my @lastitemA=split(/\//, $config);
503 0           my $lastitem=$lastitemA[$#lastitemA];
504              
505             #connects up to LDAP
506 0           my $ldap=$self->LDAPconnect();
507 0 0         if ($self->error) {
508 0           $self->warnString('LDAPconnect errored');
509 0           return undef;
510             }
511              
512             #gets the LDAP message
513 0           my $ldapmesg=$self->LDAPgetConfMessage($config, $ldap);
514             #return upon error
515 0 0         if (defined($self->error)) {
516 0           $self->warnString('LDAPgetConfMessage errored');
517 0           return undef;
518             }
519              
520 0           my %hashedmesg=LDAPhash($ldapmesg);
521 0 0         if(!defined($hashedmesg{$dn})){
522 0           my $path=$config; #used with for with LDAPmakepathSimple
523 0           $path=~s/\//,/g; #converts the / into , as required by LDAPmakepathSimple
524 0           my $returned=LDAPmakepathSimple($ldap, ["top", "zconf"], "cn",
525             $path, $self->{args}{"ldap/base"});
526 0 0         if(!$returned){
527 0           $self->{errorString}="zconf createLDAPConfig:22: Adding '".$dn."' failed when executing LDAPmakepathSimple.\n";
528 0           $self->{error}=22;
529 0           $self->warn;
530 0           return undef;
531             }
532             }else{
533 0           $self->{error}=11;
534 0           $self->{errorString}=" DN '".$dn."' already exists.";
535 0           $self->warn;
536 0           return undef;
537              
538             }
539 0           return 1;
540             }
541              
542             =head2 delConfig
543              
544             This removes a config. Any sub configs will need to removes first. If any are
545             present, this method will error.
546              
547             #removes 'foo/bar'
548             $zconf->delConfig('foo/bar');
549             if($zconf->error){
550             warn('error: '.$zconf->error.":".$zconf->errorString);
551             }
552              
553             =cut
554              
555             sub delConfig{
556 0     0 1   my $self=$_[0];
557 0           my $config=$_[1];
558              
559 0           $self->errorblank;
560              
561 0           my @subs=$self->getSubConfigs($config);
562             #return if there are any sub configs
563 0 0         if (defined($subs[0])) {
564 0           $self->{error}='33';
565 0           $self->{errorString}='Could not remove the config as it has sub configs';
566 0           $self->warn;
567 0           return undef;
568             }
569              
570             #makes sure it exists before continuing
571             #This will also make sure the config exists.
572 0           my $returned = $self->configExists($config);
573 0 0         if (defined($self->{error})){
574 0           $self->{error}='12';
575 0           $self->{errorString}='The config, "'.$config.'", does not exist';
576 0           $self->warn;
577 0           return undef;
578             }
579              
580             #connects up to LDAP... will be used later
581 0           my $ldap=$self->LDAPconnect;
582            
583             #gets the DN and use $ldap since it is already setup
584 0           my $entry=$self->LDAPgetConfEntry($config, $ldap);
585              
586             #if $entry is undefined, it was not found
587 0 0         if (!defined($entry)){
588 0           $self->{error}='13';
589 0           $self->{errorString}='The expected DN was not found';
590 0           $self->warn;
591 0           return undef;
592             }
593              
594             #remove it
595 0           $entry->delete();
596 0           my $results=$entry->update($ldap);
597              
598             #return if it could not be removed
599 0 0         if($results->is_error){
600 0           $self->{error}='34';
601 0           $self->{errorString}=' Could not delete the LDAP entry, "'.
602             $entry->dn.'". LDAP return an error of "'.$results->is_error.
603             '" and an error code of "'.$ldap->errcode.'"';
604 0           $self->warn;
605 0           return undef;
606             }
607              
608 0           return 1;
609             }
610              
611             =head2 delSet
612              
613             This deletes a specified set, for the LDAP backend.
614              
615             Two arguements are required. The first one is the name of the config and the and
616             the second is the name of the set.
617              
618             $zconf->delSet("foo/bar", "someset");
619             if($zconf->error){
620             warn('error: '.$zconf->error.":".$zconf->errorString);
621             }
622              
623              
624             =cut
625              
626             sub delSet{
627 0     0 1   my $self=$_[0];
628 0           my $config=$_[1];
629 0           my $set=$_[2];
630              
631 0           $self->errorblank;
632              
633             #return if no config is given
634 0 0         if (!defined($config)){
635 0           $self->{error}=25;
636 0           $self->{errorString}='$config not defined';
637 0           $self->warn;
638 0           return undef;
639             }
640              
641             #creates the DN from the config
642 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
643              
644             #connects up to LDAP
645 0           my $ldap=$self->LDAPconnect();
646 0 0         if (defined($self->{error})) {
647 0           $self->warnString('LDAPconnect errored');
648 0           return undef;
649             }
650              
651             #gets the entry
652 0           my $entry=$self->LDAPgetConfEntry($config, $ldap);
653             #return upon error
654 0 0         if ($self->error) {
655 0           $self->warnString('LDAPgetConfEntry errored');
656 0           return undef;
657             }
658              
659 0 0         if(!defined($entry->dn)){
660 0           $self->{error}=13;
661 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
662 0           $self->warn;
663 0           return undef;
664             }else{
665 0 0         if($entry->dn ne $dn){
666 0           $self->{error}=13;
667 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
668 0           $self->warn;
669 0           return undef;
670             }
671             }
672            
673             #makes sure the zconfSet attribute is set for the config in question
674 0           my @attributes=$entry->get_value('zconfSet');
675             #if the 0th is not defined, it means this config does not have any sets or it is wrong
676 0 0         if(defined($attributes[0])){
677             #if $attributes dues contain enteries, make sure that one of them is the proper set
678 0           my $attributesInt=0;
679 0           my $setFound=0;#set to one if the loop finds the set
680 0           while(defined($attributes[$attributesInt])){
681 0 0         if($attributes[$attributesInt] eq $set){
682 0           $setFound=1;
683 0           $entry->delete(zconfSet=>[$attributes[$attributesInt]]);
684             }
685 0           $attributesInt++;
686             }
687             }
688              
689             #
690 0           @attributes=$entry->get_value('zconfData');
691             #if the 0th is not defined, it means there are no sets
692 0 0         if(defined($attributes[0])){
693             #if $attributes dues contain enteries, make sure that one of them is the proper set
694 0           my $attributesInt=0;
695 0           my $setFound=undef;#set to one if the loop finds the set
696 0           while(defined($attributes[$attributesInt])){
697 0 0         if($attributes[$attributesInt] =~ /^$set\n/){
698 0           $setFound=1;
699 0           $entry->delete(zconfData=>[$attributes[$attributesInt]]);
700             };
701 0           $attributesInt++;
702             };
703             #if the config is not found, add it
704 0 0         if(!$setFound){
705 0           $self->{error}=31;
706 0           $self->{errorString}='The specified set, "'.$set.'" was not found for "'.$config.'".';
707 0           $self->warn;
708 0           return undef;
709             }
710             }else{
711 0           $self->{error}=30;
712 0           $self->{errorString}='No zconfData attributes exist for "'.$dn.'" and thus no sets exist.';
713 0           $self->warn;
714 0           return undef;
715             }
716              
717             #write the entry to LDAP
718 0           my $results=$entry->update($ldap);
719              
720 0           return 1;
721             }
722              
723             =head2 getAvailableSets
724              
725             This is exactly the same as getAvailableSets, but for the file back end.
726             For the most part it is not intended to be called directly.
727              
728             my @sets = $zconf->getAvailableSetsLDAP("foo/bar");
729             if($zconf->error){
730             warn('error: '.$zconf->error.":".$zconf->errorString);
731             }
732              
733             =cut
734              
735             sub getAvailableSets{
736 0     0 1   my ($self, $config) = @_;
737              
738 0           $self->errorblank;
739              
740             #converts the config name to a DN
741 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
742              
743             #gets the message
744 0           my $ldapmesg=$self->LDAPgetConfMessage($config);
745             #return upon error
746 0 0         if ($self->error) {
747 0           $self->warnString('LDAPgetConfMessage errored');
748 0           return undef;
749             }
750              
751 0           my %hashedmesg=LDAPhash($ldapmesg);
752 0 0         if(!defined($hashedmesg{$dn})){
753 0           $self->{error}=13;
754 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
755 0           $self->warn;
756 0           return undef;
757             }
758            
759 0           my $setint=0;
760 0           my @sets=();
761 0           while(defined($hashedmesg{$dn}{ldap}{zconfSet}[$setint])){
762 0           $sets[$setint]=$hashedmesg{$dn}{ldap}{zconfSet}[$setint];
763 0           $setint++;
764             }
765            
766 0           return @sets;
767             }
768              
769             =head2 getConfigRevision
770              
771             This fetches the revision for the speified config using
772             the LDAP backend.
773              
774             A return of undef means that the config has no sets created for it
775             yet or it has not been read yet by 2.0.0 or newer.
776              
777             my $revision=$zconf->getConfigRevision('some/config');
778             if($zconf->error){
779             warn('error: '.$zconf->error.":".$zconf->errorString);
780             }
781             if(!defined($revision)){
782             print "This config has had no sets added since being created or is from a old version of ZConf.\n";
783             }
784              
785             =cut
786              
787             sub getConfigRevision{
788 0     0 1   my $self=$_[0];
789 0           my $config=$_[1];
790              
791 0           $self->errorblank;
792              
793             #return false if the config is not set
794 0 0         if (!defined($config)){
795 0           $self->{error}=25;
796 0           $self->{errorString}='No config specified';
797 0           $self->warn;
798 0           return undef;
799             }
800              
801             #checks to make sure the config does exist
802 0 0         if(!$self->configExists($config)){
803 0           $self->{error}=12;
804 0           $self->{errorString}="'".$config."' does not exist.";
805 0           $self->warn;
806 0           return undef;
807             }
808              
809             #gets the LDAP entry
810 0           my $entry=$self->LDAPgetConfEntry($config);
811             #return upon error
812 0 0         if ($self->error) {
813 0           $self->warnString('LDAPgetConfEntry errored');
814 0           return undef;
815             }
816              
817             #gets the revisions
818 0           my @revs=$entry->get_value('zconfLock');
819 0 0         if (!defined($revs[0])) {
820 0           return undef;
821             }
822              
823 0           return $revs[0];
824             }
825              
826             =head2 getSubConfigs
827              
828             This gets any sub configs for a config. "" can be used to get a list of configs
829             under the root.
830              
831             One arguement is accepted and that is the config to look under.
832              
833             #lets assume 'foo/bar' exists, this would return
834             my @subConfigs=$zconf->getSubConfigs("foo");
835             if($zconf->error){
836             warn('error: '.$zconf->error.":".$zconf->errorString);
837             }
838              
839             =cut
840              
841             #gets the configs under a config
842             sub getSubConfigs{
843 0     0 1   my ($self, $config)= @_;
844              
845 0           $self->errorblank;
846              
847 0           my $dn;
848             #converts the config name to a DN
849 0 0         if ($config eq "") {
850             #this is done as using config2dn results in an error
851 0           $dn=$self->{args}{"ldap/base"};
852             }else{
853 0           $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
854             }
855              
856             #gets the message
857 0           my $ldapmesg=$self->LDAPgetConfMessageOne($config);
858             #return upon error
859 0 0         if (defined($self->{error})) {
860 0           return undef;
861             }
862              
863 0           my %hashedmesg=LDAPhash($ldapmesg);
864              
865             #
866 0           my @keys=keys(%hashedmesg);
867              
868             #holds the returned sets
869 0           my @sets;
870              
871 0           my $keysInt=0;
872 0           while ($keys[$keysInt]){
873             #only process ones that start with 'cn='
874 0 0         if ($keys[$keysInt] =~ /^cn=/) {
875             #remove the begining config DN chunk
876 0           $keys[$keysInt]=~s/,$dn$//;
877             #removes the cn= at the begining
878 0           $keys[$keysInt]=~s/^cn=//;
879             #push the processed key onto @sets
880 0           push(@sets, $keys[$keysInt]);
881             }
882            
883 0           $keysInt++;
884             }
885              
886 0           return @sets;
887             }
888              
889             =head2 isConfigLocked
890              
891             This checks if a config is locked or not for the LDAP backend.
892              
893             One arguement is required and it is the name of the config.
894              
895             The returned value is a boolean value.
896              
897             my $locked=$zconf->isConfigLockedLDAP('some/config');
898             if($zconf->error){
899             warn('error: '.$zconf->error.":".$zconf->errorString);
900             }
901             if($locked){
902             print "The config is locked\n";
903             }
904              
905             =cut
906              
907             sub isConfigLocked{
908 0     0 1   my $self=$_[0];
909 0           my $config=$_[1];
910              
911 0           $self->errorblank;
912              
913             #return false if the config is not set
914 0 0         if (!defined($config)){
915 0           $self->{error}=25;
916 0           $self->{errorString}='No config specified';
917 0           $self->warn;
918 0           return undef;
919             }
920              
921             #makes sure it exists
922 0           my $exists=$self->configExists($config);
923 0 0         if ($self->{error}) {
924 0           $self->warnString('configExists errored');
925 0           return undef;
926             }
927 0 0         if (!$exists) {
928 0           $self->{error}=12;
929 0           $self->{errorString}='The config, "'.$config.'", does not exist';
930 0           $self->warn;
931 0           return undef;
932             }
933              
934 0           my $entry=$self->LDAPgetConfEntry($config);
935             #return upon error
936 0 0         if ($self->error) {
937 0           $self->warnString('LDAPgetConfEntry errored');
938 0           return undef;
939             }
940              
941             #check if it is locked or not
942 0           my @locks=$entry->get_value('zconfLock');
943 0 0         if (defined($locks[0])) {
944             #it is locked
945 0           return 1;
946             }
947              
948             #it is not locked
949 0           return undef;
950             }
951              
952             =head2 LDAPconnect
953              
954             This generates a Net::LDAP object based on the LDAP backend.
955              
956             my $ldap=$zconf->LDAPconnect();
957             if($zconf->error){
958             warn('error: '.$zconf->error.":".$zconf->errorString);
959             }
960              
961             =cut
962              
963             sub LDAPconnect{
964 0     0 1   my $self=$_[0];
965              
966 0           $self->errorblank;
967              
968             #connects up to LDAP
969 0           my $ldap=Net::LDAP->new(
970             $self->{args}{"ldap/host"},
971             port=>$self->{args}{"ldap/port"},
972             );
973              
974             #make sure we connected
975 0 0         if (!$ldap) {
976 0           $self->{error}=1;
977 0           $self->{errorString}='Failed to connect to LDAP';
978 0           $self->warn;
979 0           return undef;
980             }
981              
982             #start tls stuff if needed
983 0           my $mesg;
984 0 0         if ($self->{args}{"ldap/starttls"}) {
985 0           $mesg=$ldap->start_tls(
986             verify=>$self->{args}{'larc/TLSverify'},
987             sslversion=>$self->{args}{'ldap/SSLversion'},
988             ciphers=>$self->{args}{'ldap/SSLciphers'},
989             cafile=>$self->{args}{'ldap/cafile'},
990             capath=>$self->{args}{'ldap/capath'},
991             checkcrl=>$self->{args}{'ldap/checkcrl'},
992             clientcert=>$self->{args}{'ldap/clientcert'},
993             clientkey=>$self->{args}{'ldap/clientkey'},
994             );
995              
996 0 0         if (!$mesg->{errorMessage} eq '') {
997 0           $self->{error}=1;
998 0           $self->{errorString}='$ldap->start_tls failed. $mesg->{errorMessage}="'.
999             $mesg->{errorMessage}.'"';
1000 0           $self->warn;
1001 0           return undef;
1002             }
1003             }
1004              
1005             #bind
1006 0           $mesg=$ldap->bind($self->{args}{"ldap/bind"},
1007             password=>$self->{args}{"ldap/password"},
1008             );
1009 0 0         if (!$mesg->{errorMessage} eq '') {
1010 0           $self->{error}=13;
1011 0           $self->{errorString}='Binding to the LDAP server failed. $mesg->{errorMessage}="'.
1012             $mesg->{errorMessage}.'"';
1013 0           $self->warn;
1014 0           return undef;
1015             }
1016              
1017 0           return $ldap;
1018             }
1019              
1020             =head2 LDAPgetConfMessage
1021              
1022             Gets a Net::LDAP::Message object that was created doing a search for the config with
1023             the scope set to base.
1024              
1025             #gets it for 'foo/bar'
1026             my $mesg=$zconf->LDAPgetConfMessage('foo/bar');
1027             #gets it using $ldap for the connection
1028             my $mesg=$zconf->LDAPgetConfMessage('foo/bar', $ldap);
1029             if($zconf->error){
1030             warn('error: '.$zconf->error.":".$zconf->errorString);
1031             }
1032              
1033             =cut
1034              
1035             sub LDAPgetConfMessage{
1036 0     0 1   my $self=$_[0];
1037 0           my $config=$_[1];
1038 0           my $ldap=$_[2];
1039              
1040 0           $self->errorblank;
1041              
1042             #only connect to LDAP if needed
1043 0 0         if (!defined($ldap)) {
1044             #connects up to LDAP
1045 0           $ldap=$self->LDAPconnect;
1046             #return upon error
1047 0 0         if (defined($self->{error})) {
1048 0           return undef;
1049             }
1050             }
1051              
1052             #creates the DN from the config
1053 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
1054              
1055             #gets the message
1056 0           my $ldapmesg=$ldap->search(scope=>"base", base=>$dn,filter => "(objectClass=*)");
1057              
1058 0           return $ldapmesg;
1059             }
1060              
1061             =head2 LDAPgetConfMessageOne
1062              
1063             Gets a Net::LDAP::Message object that was created doing a search for the config with
1064             the scope set to one.
1065              
1066             #gets it for 'foo/bar'
1067             my $mesg=$zconf->LDAPgetConfMessageOne('foo/bar');
1068             #gets it using $ldap for the connection
1069             my $mesg=$zconf->LDAPgetConfMessageOne('foo/bar', $ldap);
1070             if($zconf->error){
1071             warn('error: '.$zconf->error.":".$zconf->errorString);
1072             }
1073              
1074             =cut
1075              
1076             sub LDAPgetConfMessageOne{
1077 0     0 1   my $self=$_[0];
1078 0           my $config=$_[1];
1079 0           my $ldap=$_[2];
1080              
1081 0           $self->errorblank;
1082              
1083             #only connect to LDAP if needed
1084 0 0         if (!defined($ldap)) {
1085             #connects up to LDAP
1086 0           $ldap=$self->LDAPconnect;
1087             #return upon error
1088 0 0         if ($self->error) {
1089 0           $self->warnString('LDAPconnect errored');
1090 0           return undef;
1091             }
1092             }
1093              
1094             #creates the DN from the config
1095 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
1096              
1097 0           $dn =~ s/^,//;
1098              
1099             #gets the message
1100 0           my $ldapmesg=$ldap->search(scope=>"one", base=>$dn,filter => "(objectClass=*)");
1101              
1102 0           return $ldapmesg;
1103             }
1104              
1105             =head2 LDAPgetConfEntry
1106              
1107             Gets a Net::LDAP::Message object that was created doing a search for the config with
1108             the scope set to base.
1109              
1110             It returns undef if it is not found.
1111              
1112             #gets it for 'foo/bar'
1113             my $entry=$zconf->LDAPgetConfEntry('foo/bar');
1114             #gets it using $ldap for the connection
1115             my $entry=$zconf->LDAPgetConfEntry('foo/bar', $ldap);
1116             if($zconf->error){
1117             warn('error: '.$zconf->error.":".$zconf->errorString);
1118             }
1119              
1120             =cut
1121              
1122             sub LDAPgetConfEntry{
1123 0     0 1   my $self=$_[0];
1124 0           my $config=$_[1];
1125 0           my $ldap=$_[2];
1126              
1127 0           $self->errorblank;
1128              
1129             #only connect to LDAP if needed
1130 0 0         if (!defined($ldap)) {
1131             #connects up to LDAP
1132 0           $ldap=$self->LDAPconnect;
1133             #return upon error
1134 0 0         if (defined($self->{error})) {
1135 0           return undef;
1136             }
1137             }
1138              
1139             #creates the DN from the config
1140 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
1141              
1142             #gets the message
1143 0           my $ldapmesg=$ldap->search(scope=>"base", base=>$dn,filter => "(objectClass=*)");
1144 0           my $entry=$ldapmesg->entry;
1145              
1146 0           return $entry;
1147             }
1148              
1149             =head2 read
1150              
1151             readFile methods just like read, but is mainly intended for internal use
1152             only. This reads the config from the LDAP backend.
1153              
1154             =head3 hash args
1155              
1156             =head4 config
1157              
1158             The config to load.
1159              
1160             =head4 override
1161              
1162             This specifies if override should be ran not.
1163              
1164             If this is not specified, it defaults to 1, true.
1165              
1166             =head4 set
1167              
1168             The set for that config to load.
1169              
1170             $zconf->readLDAP({config=>"foo/bar"})
1171             if($zconf->error){
1172             warn('error: '.$zconf->error.":".$zconf->errorString);
1173             }
1174              
1175             =cut
1176              
1177             #read a config from a file
1178             sub read{
1179 0     0 1   my $self=$_[0];
1180 0           my %args=%{$_[1]};
  0            
1181              
1182 0           $self->errorblank;
1183              
1184             #return false if the config is not set
1185 0 0         if (!defined($args{config})){
1186 0           $self->{error}=25;
1187 0           $self->{errorString}='$config not defined';
1188 0           $self->warn;
1189 0           return undef;
1190             }
1191              
1192             #return false if the config is not set
1193 0 0         if (!defined($args{set})){
1194 0           $self->{error}=24;
1195 0           $self->{errorString}='$arg{set} not defined';
1196 0           $self->warn;
1197 0           return undef;
1198             }
1199              
1200             #default to overriding
1201 0 0         if (!defined($args{override})) {
1202 0           $args{override}=1;
1203             }
1204              
1205             #creates the DN from the config
1206 0           my $dn=$self->config2dn($args{config}).",".$self->{args}{"ldap/base"};
1207              
1208             #gets the LDAP entry
1209 0           my $entry=$self->LDAPgetConfEntry($args{config});
1210             #return upon error
1211 0 0         if ($self->error) {
1212 0           $self->warnString('LDAPgetConfEntry errored');
1213 0           return undef;
1214             }
1215              
1216 0 0         if(!defined($entry->dn())){
1217 0           $self->{error}=13;
1218 0           $self->{errorString}="Expected DN, '".$dn."' not found";
1219 0           $self->warn;
1220 0           return undef;
1221             }else{
1222 0 0         if($entry->dn ne $dn){
1223 0           $self->{error}=13;
1224 0           $self->{errorString}="Expected DN, '".$dn."' not found";
1225 0           $self->warn;
1226 0           return undef;
1227             }
1228             }
1229              
1230 0           my @attributes=$entry->get_value('zconfData');
1231 0           my $data=undef;#unset from undef if matched
1232 0 0         if(defined($attributes[0])){
1233             #if @attributes has entries, go through them looking for a match
1234 0           my $attributesInt=0;
1235 0           my $setFound=undef;#set to one if the loop finds the set
1236 0           while(defined($attributes[$attributesInt])){
1237 0 0         if($attributes[$attributesInt] =~ /^$args{set}\n/){
1238             #if a match is found, save it to data for continued processing
1239 0           $data=$attributes[$attributesInt];
1240             };
1241 0           $attributesInt++;
1242             }
1243             }else{
1244             #If we end up here, it means it is a bad LDAP enty
1245 0           $self->{error}=13;
1246 0           $self->{errorString}="No zconfData entry found in '".$dn."'";
1247 0           $self->warn;
1248 0           return undef;
1249             }
1250              
1251             #error out if $data is undefined
1252 0 0         if(!defined($data)){
1253 0           $self->{error}=13;
1254 0           $self->{errorString}="No matching sets found in '".$args{config}."'";
1255 0           $self->warn;
1256 0           return undef;
1257             }
1258              
1259             #removes the firstline from the data
1260 0           $data=~s/^$args{set}\n//;
1261            
1262             #parse the ZML stuff
1263 0           my $zml=ZML->new;
1264 0           $zml->parse($data);
1265 0 0         if ($zml->{error}) {
1266 0           $self->{error}=28;
1267 0           $self->{errorString}='$zml->parse errored. $zml->{error}="'.$zml->{error}.'" '.
1268             '$zml->{errorString}="'.$zml->{errorString}.'"';
1269 0           $self->warn;
1270 0           return undef;
1271             }
1272 0           $self->{self}->{conf}{$args{config}}=\%{$zml->{var}};
  0            
1273 0           $self->{self}->{meta}{$args{config}}=\%{$zml->{meta}};
  0            
1274 0           $self->{self}->{comment}{$args{config}}=\%{$zml->{comment}};
  0            
1275              
1276             #sets the loaded config
1277 0           $self->{self}->{set}{$args{config}}=$args{set};
1278              
1279             #gets the revisions
1280 0           my @revs=$entry->get_value('zconfRev');
1281 0 0         if (!defined($revs[0])) {
1282 0           my $revision=time.' '.hostname.' '.rand();
1283 0           $self->{revision}{$args{config}}=$revision;
1284 0           $entry->add(zconfRev=>[$revision]);
1285              
1286             #connects to LDAP
1287 0           my $ldap=$self->LDAPconnect();
1288 0 0         if ($self->error) {
1289 0           $self->warnString('LDAPconnect failed for the purpose of updating');
1290 0           return $self->{revision}{$args{config}};
1291             }
1292              
1293 0           $entry->update($ldap);
1294             }else {
1295 0           $self->{revision}{$args{config}}=$revs[0];
1296             }
1297              
1298             #checks if it is locked or not and save it
1299 0           my $locked=$self->isConfigLocked($args{config});
1300 0 0         if ($locked) {
1301 0           $self->{self}->{locked}{$args{config}}=1;
1302             }
1303              
1304             #run the overrides if requested tox
1305 0 0         if ($args{override}) {
1306             #runs the override if not locked
1307 0 0         if (!$locked) {
1308 0           $self->{self}->override({ config=>$args{config} });
1309             }
1310             }
1311              
1312 0           return $self->{self}->{revision}{$args{config}};
1313             }
1314              
1315             =head2 readChooser
1316              
1317             This methods just like readChooser, but methods on the LDAP backend
1318             and only really intended for internal use.
1319              
1320             my $chooser = $zconf->readChooserLDAP("foo/bar");
1321             if($zconf->error){
1322             warn('error: '.$zconf->error.":".$zconf->errorString);
1323             }
1324              
1325             =cut
1326              
1327             #this gets the chooser for a the config... for the file backend
1328             sub readChooser{
1329 0     0 1   my ($self, $config)= @_;
1330              
1331 0           $self->errorblank;
1332              
1333             #return false if the config is not set
1334 0 0         if (!defined($config)) {
1335 0           $self->{error}=25;
1336 0           $self->{errorString}='$config not defined';
1337 0           $self->warn;
1338 0           return undef;
1339             }
1340              
1341             #make sure the config name is legit
1342 0           my ($error, $errorString)=$self->{self}->configNameCheck($config);
1343 0 0         if ($error) {
1344 0           $self->{error}=$error;
1345 0           $self->{errorString}=$errorString;
1346 0           $self->warn;
1347 0           return undef;
1348             }
1349              
1350             #checks to make sure the config does exist
1351 0 0         if (!$self->configExists($config)) {
1352 0           $self->{error}=12;
1353 0           $self->{errorString}="'".$config."' does not exist.";
1354 0           $self->warn;
1355 0           return undef;
1356             }
1357              
1358             #creates the DN from the config
1359 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
1360              
1361             #gets the LDAP mesg
1362 0           my $ldapmesg=$self->LDAPgetConfMessage($config);
1363             #return upon error
1364 0 0         if ($self->error) {
1365 0           return undef;
1366             }
1367              
1368 0           my %hashedmesg=LDAPhash($ldapmesg);
1369 0 0         if (!defined($hashedmesg{$dn})) {
1370 0           $self->{error}=13;
1371 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
1372 0           $self->warn;
1373 0           return undef;
1374             }
1375              
1376 0 0         if (defined($hashedmesg{$dn}{ldap}{zconfChooser}[0])) {
1377 0           return($hashedmesg{$dn}{ldap}{zconfChooser}[0]);
1378             } else {
1379 0           return("");
1380             }
1381             }
1382              
1383             =head2 setExists
1384              
1385             This checks if the specified set exists.
1386              
1387             Two arguements are required. The first arguement is the name of the config.
1388             The second arguement is the name of the set. If no set is specified, the default
1389             set is used. This is done by calling 'defaultSetExists'.
1390              
1391             my $return=$zconf->setExists("foo/bar", "fubar");
1392             if($zconf->error){
1393             warn('error: '.$zconf->error.":".$zconf->errorString);
1394             }else{
1395             if($return){
1396             print "It exists.\n";
1397             }
1398             }
1399              
1400             =cut
1401              
1402             sub setExists{
1403 0     0 1   my ($self, $config, $set)= @_;
1404              
1405             #blank any errors
1406 0           $self->errorblank;
1407              
1408             #this will get what set to use if it is not specified
1409 0 0         if (!defined($set)) {
1410 0           return $self->defaultSetExists($config);
1411 0 0         if ($self->error) {
1412 0           $self->warnString('No set specified and defaultSetExists errored');
1413 0           return undef;
1414             }
1415             }
1416              
1417             #We don't do any config name checking here or even if it exists as getAvailableSets
1418             #will do that.
1419              
1420 0           my @sets = $self->getAvailableSets($config);
1421 0 0         if ($self->error) {
1422 0           $self->warnString('getAvailableSets errored');
1423 0           return undef;
1424             }
1425              
1426              
1427 0           my $setsInt=0;#used for intering through $sets
1428             #go through @sets and check for matches
1429 0           while (defined($sets[$setsInt])) {
1430             #return true if the current one matches
1431 0 0         if ($sets[$setsInt] eq $set) {
1432 0           return 1;
1433             }
1434              
1435 0           $setsInt++;
1436             }
1437              
1438             #if we get here, it means it was not found in the loop
1439 0           return undef;
1440             }
1441              
1442             =head2 setLockConfig
1443              
1444             This unlocks or logs a config for the LDAP backend.
1445              
1446             Two arguements are taken. The first is a
1447             the config name, required, and the second is
1448             if it should be locked or unlocked
1449              
1450             #lock 'some/config'
1451             $zconf->setLockConfigLDAP('some/config', 1);
1452             if($zconf->{error}){
1453             warn('error: '.$zconf->error.":".$zconf->errorString);
1454             }
1455              
1456             #unlock 'some/config'
1457             $zconf->setLockConfigLDAP('some/config', 0);
1458             if($zconf->{error}){
1459             warn('error: '.$zconf->error.":".$zconf->errorString);
1460             }
1461              
1462             #unlock 'some/config'
1463             $zconf->setLockConfigLDAP('some/config');
1464             if($zconf->{error}){
1465             warn('error: '.$zconf->error.":".$zconf->errorString);
1466             }
1467              
1468             =cut
1469              
1470             sub setLockConfig{
1471 0     0 1   my $self=$_[0];
1472 0           my $config=$_[1];
1473 0           my $lock=$_[2];
1474              
1475 0           $self->errorblank;
1476              
1477             #return false if the config is not set
1478 0 0         if (!defined($config)){
1479 0           $self->{error}=25;
1480 0           $self->{errorString}='No config specified';
1481 0           $self->warn;
1482 0           return undef;
1483             }
1484              
1485             #makes sure it exists
1486 0           my $exists=$self->configExists($config);
1487 0 0         if ($self->error) {
1488 0           $self->warnString('configExists errored');
1489 0           return undef;
1490             }
1491 0 0         if (!$exists) {
1492 0           $self->{error}=12;
1493 0           $self->{errorString}='The config, "'.$config.'", does not exist';
1494 0           $self->warn;
1495 0           return undef;
1496             }
1497              
1498 0           my $entry=$self->LDAPgetConfEntry($config);
1499             #return upon error
1500 0 0         if ($self->error) {
1501 0           $self->warnString('LDAPgetConfEntry errored');
1502 0           return undef;
1503             }
1504              
1505             #adds a lock
1506 0 0         if ($lock) {
1507 0           $entry->add(zconfLock=>[time."\n".hostname]);
1508             }
1509              
1510             #removes a lock
1511 0 0         if (!$lock) {
1512 0           $entry->delete('zconfLock');
1513             }
1514            
1515             #connects to LDAP
1516 0           my $ldap=$self->LDAPconnect;
1517 0 0         if ($self->{error}) {
1518 0           $self->warnString('LDAPconnect errored... returning...');
1519 0           return undef;
1520             }
1521              
1522 0           $entry->update($ldap);
1523              
1524 0           return 1;
1525             }
1526              
1527             =head2 writeChooser
1528              
1529             This method is a internal method and largely meant to only be called
1530             writeChooser, which it methods the same as. It works on the LDAP backend.
1531              
1532             $zconf->writeChooserLDAP("foo/bar", $chooserString)
1533             if($zconf->error){
1534             warn('error: '.$zconf->error.":".$zconf->errorString);
1535             }
1536              
1537             =cut
1538              
1539             sub writeChooser{
1540 0     0 1   my ($self, $config, $chooserstring)= @_;
1541              
1542 0           $self->errorblank;
1543              
1544             #return false if the config is not set
1545 0 0         if (!defined($config)){
1546 0           $self->{error}=25;
1547 0           $self->{errorString}='$config not defined';
1548 0           $self->warn;
1549 0           return undef;
1550             }
1551              
1552             #return false if the config is not set
1553 0 0         if (!defined($chooserstring)){
1554 0           $self->{error}=40;
1555 0           $self->{errorString}='\$chooserstring not defined';
1556 0           $self->warn;
1557 0           return undef;
1558             }
1559              
1560             #make sure the config name is legit
1561 0           my ($error, $errorString)=$self->{self}->configNameCheck($config);
1562 0 0         if($error){
1563 0           $self->{error}=$error;
1564 0           $self->{errorString}=$errorString;
1565 0           $self->warn;
1566 0           return undef;
1567             }
1568              
1569             #checks to make sure the config does exist
1570 0 0         if(!$self->configExists($config)){
1571 0           $self->{error}=12;
1572 0           $self->{errorString}="'".$config."' does not exist.";
1573 0           $self->warn;
1574 0           return undef;
1575             }
1576              
1577             #checks if it is locked or not
1578 0           my $locked=$self->isConfigLocked($config);
1579 0 0         if ($self->error) {
1580 0           $self->warnString('isconfigLockedLDAP errored');
1581 0           return undef;
1582             }
1583 0 0         if ($locked) {
1584 0           $self->{error}=45;
1585 0           $self->{errorString}='The config "'.$config.'" is locked';
1586 0           $self->warn;
1587 0           return undef;
1588             }
1589              
1590             #creates the DN from the config
1591 0           my $dn=$self->config2dn($config).",".$self->{args}{"ldap/base"};
1592              
1593             #connects to LDAP
1594 0           my $ldap=$self->LDAPconnect;
1595 0 0         if ($self->error) {
1596 0           $self->warnString('LDAPconnect errored... returning...');
1597 0           return undef;
1598             }
1599              
1600             #gets the LDAP entry
1601 0           my $entry=$self->LDAPgetConfEntry($config, $ldap);
1602             #return upon error
1603 0 0         if ($self->error) {
1604 0           return undef;
1605             }
1606              
1607 0 0         if(!defined($entry->dn)){
1608 0           $self->{error}=13;
1609 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
1610 0           $self->warn;
1611 0           return undef;
1612             }else{
1613 0 0         if($entry->dn ne $dn){
1614 0           $self->{error}=13;
1615 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
1616 0           $self->warn;
1617 0           return undef;
1618             }
1619             }
1620              
1621             #replace the zconfChooser entry and updated it
1622 0           $entry->replace(zconfChooser=>$chooserstring);
1623 0           $entry->update($ldap);
1624              
1625 0           return (1);
1626             }
1627              
1628             =head2 writeSetFromHash
1629              
1630              
1631             This takes a hash and writes it to a config for the file backend.
1632             It takes two arguements, both of which are hashes.
1633              
1634             The first hash contains
1635              
1636             The second hash is the hash to be written to the config.
1637              
1638             =head2 args hash
1639              
1640             =head3 config
1641              
1642             The config to write it to.
1643              
1644             This is required.
1645              
1646             =head3 set
1647              
1648             This is the set name to use.
1649              
1650             If not defined, the one will be choosen.
1651              
1652             =head3 revision
1653              
1654             This is the revision string to use.
1655              
1656             This is primarily meant for internal usage and is suggested
1657             that you don't touch this unless you really know what you
1658             are doing.
1659              
1660             $zconf->writeSetFromHashLDAP({config=>"foo/bar"}, \%hash);
1661             if($zconf->error){
1662             warn('error: '.$zconf->error.":".$zconf->errorString);
1663             }
1664              
1665             =cut
1666              
1667             #write out a config from a hash to the LDAP backend
1668             sub writeSetFromHash{
1669 0     0 1   my $self = $_[0];
1670 0           my %args=%{$_[1]};
  0            
1671 0           my %hash = %{$_[2]};
  0            
1672              
1673 0           $self->errorblank;
1674              
1675             #return false if the config is not set
1676 0 0         if (!defined($args{config})){
1677 0           $self->{error}=25;
1678 0           $self->{errorString}='$config not defined';
1679 0           $self->warn;
1680 0           return undef;
1681             }
1682              
1683             #make sure the config name is legit
1684 0           my ($error, $errorString)=$self->{self}->configNameCheck($args{config});
1685 0 0         if($error){
1686 0           $self->{error}=$error;
1687 0           $self->{errorString}=$errorString;
1688 0           $self->warn;
1689 0           return undef;
1690             }
1691              
1692             #sets the set to default if it is not defined
1693 0 0         if (!defined($args{set})){
1694 0           $args{set}=$self->chooseSet($args{set});
1695             }else{
1696 0 0         if($self->{self}->setNameLegit($args{set})){
1697 0           $self->{args}{default}=$args{set};
1698             }else{
1699 0           $self->{error}=27;
1700 0           $self->{errorString}="'".$args{set}."' is not a legit set name.";
1701 0           $self->warn;
1702             return undef
1703 0           }
1704             }
1705              
1706             #checks to make sure the config does exist
1707 0 0         if(!$self->configExists($args{config})){
1708 0           $self->{error}=12;
1709 0           $self->{errorString}="'".$args{config}."' does not exist.";
1710 0           $self->warn;
1711 0           return undef;
1712             }
1713              
1714             #checks if it is locked or not
1715 0           my $locked=$self->isConfigLocked($args{config});
1716 0 0         if ($self->error) {
1717 0           $self->warnString('isConfigLocked errored');
1718 0           return undef;
1719             }
1720 0 0         if ($locked) {
1721 0           $self->{error}=45;
1722 0           $self->{errorString}='The config "'.$args{config}.'" is locked';
1723 0           $self->warn;
1724 0           return undef;
1725             }
1726              
1727             #sets the set to default if it is not defined
1728 0 0         if (!defined($args{set})){
1729 0           $args{set}="default";
1730             }
1731            
1732             #sets the set to default if it is not defined
1733 0 0         if (!defined($args{autoCreateConfig})){
1734 0           $args{autoCreateConfig}="0";
1735             }
1736              
1737             #update the revision if needed
1738 0 0         if (!defined($args{revision})) {
1739 0           $args{revision}=time.' '.hostname.' '.rand();
1740             }
1741              
1742 0           my $zml=ZML->new;
1743              
1744 0           my $hashkeysInt=0;#used for intering through the list of hash keys
1745             #builds the ZML object
1746 0           my @hashkeys=keys(%hash);
1747 0           while(defined($hashkeys[$hashkeysInt])){
1748             #attempts to add the variable
1749 0 0         if ($hashkeys[$hashkeysInt] =~ /^\#/) {
1750             #process a meta variable
1751 0 0         if ($hashkeys[$hashkeysInt] =~ /^\#\!/) {
1752 0           my @metakeys=keys(%{$hash{ $hashkeys[$hashkeysInt] }});
  0            
1753 0           my $metaInt=0;
1754 0           while (defined( $metakeys[$metaInt] )) {
1755 0           $zml->addMeta($hashkeys[$hashkeysInt], $metakeys[$metaInt], $hash{ $hashkeys[$hashkeysInt] }{ $metakeys[$metaInt] } );
1756             #checks to verify there was no error
1757             #this is not a fatal error... skips it if it is not legit
1758 0 0         if($zml->error){
1759 0           $self->warnString(':23: $zml->addMeta() returned '.
1760             $zml->error.", '".$zml->errorString."'. Skipping variable '".
1761             $hashkeys[$hashkeysInt]."' in '".$args{config}."'.");
1762             }
1763 0           $metaInt++;
1764             }
1765             }
1766             #process a meta variable
1767 0 0         if ($hashkeys[$hashkeysInt] =~ /^\#\#/) {
1768 0           my @metakeys=keys(%{$hash{ $hashkeys[$hashkeysInt] }});
  0            
1769 0           my $metaInt=0;
1770 0           while (defined( $metakeys[$metaInt] )) {
1771 0           $zml->addComment($hashkeys[$hashkeysInt], $metakeys[$metaInt], $hash{ $hashkeys[$hashkeysInt] }{ $metakeys[$metaInt] } );
1772             #checks to verify there was no error
1773             #this is not a fatal error... skips it if it is not legit
1774 0 0         if($zml->error){
1775 0           $self->warnString(':23: $zml->addComment() returned '.
1776             $zml->error.", '".$zml->errorString."'. Skipping variable '".
1777             $hashkeys[$hashkeysInt]."' in '".$args{config}."'.");
1778             }
1779 0           $metaInt++;
1780             }
1781             }
1782             }else {
1783 0           $zml->addVar($hashkeys[$hashkeysInt], $hash{$hashkeys[$hashkeysInt]});
1784             #checks to verify there was no error
1785             #this is not a fatal error... skips it if it is not legit
1786 0 0         if($zml->error){
1787 0           $self->warnString(':23: $zml->addVar returned '.
1788             $zml->error.", '".$zml->errorString."'. Skipping variable '".
1789             $hashkeys[$hashkeysInt]."' in '".$args{config}."'.");
1790             }
1791             }
1792            
1793 0           $hashkeysInt++;
1794             };
1795              
1796             #update the revision
1797 0 0         if (!defined($args{revision})) {
1798 0           $args{revision}=time.' '.hostname.' '.rand();
1799             }
1800              
1801             #write out the ZML config
1802 0           $args{zml}=$zml;
1803 0           $self->writeSetFromZML(\%args);
1804 0 0         if ($self->error) {
1805 0           $self->warnString('writeSetFromZML failed');
1806             return undef
1807 0           }
1808              
1809 0           return $args{revision};
1810             }
1811              
1812             =head2 writeSetFromLoadedConfig
1813              
1814             This method writes a loaded config to a to a set,
1815             for the LDAP backend.
1816              
1817             One arguement is required.
1818              
1819             =head2 args hash
1820              
1821             =head3 config
1822              
1823             The config to write it to.
1824              
1825             This is required.
1826              
1827             =head3 set
1828              
1829             This is the set name to use.
1830              
1831             If not defined, the one will be choosen.
1832              
1833             =head3 revision
1834              
1835             This is the revision string to use.
1836              
1837             This is primarily meant for internal usage and is suggested
1838             that you don't touch this unless you really know what you
1839             are doing.
1840              
1841             $zconf->writeSetFromLoadedConfigLDAP({config=>"foo/bar"});
1842             if(defined($zconf->error)){
1843             warn('error: '.$zconf->error.":".$zconf->errorString);
1844             }
1845              
1846             =cut
1847              
1848             #write a set out to LDAP
1849             sub writeSetFromLoadedConfig{
1850 0     0 1   my $self = $_[0];
1851 0           my %args=%{$_[1]};
  0            
1852              
1853 0           $self->errorblank;
1854              
1855             #return false if the config is not set
1856 0 0         if (!defined($args{config})){
1857 0           $self->{error}=25;
1858 0           $self->{errorString}='$config not defined';
1859 0           $self->warn;
1860 0           return undef;
1861             }
1862              
1863 0 0         if(! $self->{self}->isConfigLoaded( $args{config} ) ){
1864 0           $self->{error}=25;
1865 0           $self->{errorString}="Config '".$args{config}."' is not loaded";
1866 0           $self->warn;
1867 0           return undef;
1868             }
1869              
1870             #checks if it is locked or not
1871 0           my $locked=$self->isConfigLocked($args{config});
1872 0 0         if ($self->error) {
1873 0           $self->warnString('isconfigLockedLDAP errored');
1874 0           return undef;
1875             }
1876 0 0         if ($locked) {
1877 0           $self->{error}=45;
1878 0           $self->{errorString}='The config "'.$args{config}.'" is locked';
1879 0           $self->warn;
1880 0           return undef;
1881             }
1882              
1883             #sets the set to default if it is not defined
1884 0 0         if (!defined($args{set})){
1885 0           $args{set}=$self->{set}{$args{config}};
1886             }else{
1887 0 0         if($self->{self}->setNameLegit($args{set})){
1888 0           $self->{args}{default}=$args{set};
1889             }else{
1890 0           $self->{error}=27;
1891 0           $self->{errorString}="'".$args{set}."' is not a legit set name.";
1892 0           $self->warn;
1893             return undef
1894 0           }
1895             }
1896              
1897             #update the revision if needed
1898 0 0         if (!defined($args{revision})) {
1899 0           $args{revision}=time.' '.hostname.' '.rand();
1900             }
1901              
1902             #get the config in a ZML format
1903 0           my $zml=$self->{self}->dumpToZML($args{config});
1904 0 0         if ($self->{self}->error) {
1905 0           $self->{error}=14;
1906 0           $self->{errorString}='Failed to dump to ZML. error='.$self->{self}->error.' errorString='.$self->{self}->errorString;
1907 0           $self->warn;
1908             return undef
1909 0           }
1910 0           $args{zml}=$zml;
1911            
1912             #write out the config
1913 0           $self->writeSetFromZML(\%args);
1914 0 0         if ($self->error) {
1915 0           $self->warnString('writeSetFromZML failed');
1916             return undef
1917 0           }
1918              
1919 0           return $args{revision};
1920             }
1921              
1922             =head2 writeSetFromZML
1923              
1924             This writes a config set from a ZML object.
1925              
1926             One arguement is required.
1927              
1928             =head2 args hash
1929              
1930             =head3 config
1931              
1932             The config to write it to.
1933              
1934             This is required.
1935              
1936             =head3 set
1937              
1938             This is the set name to use.
1939              
1940             If not defined, the one will be choosen.
1941              
1942             =head3 zml
1943              
1944             This is the ZML object to use.
1945              
1946             =head3 revision
1947              
1948             This is the revision string to use.
1949              
1950             This is primarily meant for internal usage and is suggested
1951             that you don't touch this unless you really know what you
1952             are doing.
1953              
1954             $zconf->writeSetFromZML({config=>"foo/bar", zml=>$zml});
1955             if(defined($zconf->error)){
1956             warn('error: '.$zconf->error.":".$zconf->errorString);
1957             }
1958              
1959             =cut
1960              
1961             #write a set out to LDAP
1962             sub writeSetFromZML{
1963 0     0 1   my $self = $_[0];
1964 0           my %args=%{$_[1]};
  0            
1965              
1966 0           $self->errorblank;
1967              
1968             #return false if the config is not set
1969 0 0         if (!defined($args{config})){
1970 0           $self->{error}=25;
1971 0           $self->{errorString}='$args{config} not defined';
1972 0           $self->warn;
1973 0           return undef;
1974             }
1975              
1976             #makes sure ZML is passed
1977 0 0         if (!defined( $args{zml} )) {
1978 0           $self->{error}=15;
1979 0           $self->{errorString}='$args{zml} is not defined';
1980 0           $self->warn;
1981 0           return undef;
1982             }
1983 0 0         if ( ref($args{zml}) ne "ZML" ) {
1984 0           $self->{error}=15;
1985 0           $self->{errorString}='$args{zml} is not a ZML';
1986 0           $self->warn;
1987 0           return undef;
1988             }
1989              
1990             #checks if it is locked or not
1991 0           my $locked=$self->isConfigLocked($args{config});
1992 0 0         if ($self->error) {
1993 0           $self->warnString('isconfigLockedLDAP errored');
1994 0           return undef;
1995             }
1996 0 0         if ($locked) {
1997 0           $self->{error}=45;
1998 0           $self->{errorString}='The config "'.$args{config}.'" is locked';
1999 0           $self->warn;
2000 0           return undef;
2001             }
2002              
2003             #sets the set to default if it is not defined
2004 0 0         if (!defined($args{set})){
2005 0           $args{set}=$self->{set}{$args{config}};
2006             }else{
2007 0 0         if($self->{self}->setNameLegit($args{set})){
2008 0           $self->{args}{default}=$args{set};
2009             }else{
2010 0           $self->{error}=27;
2011 0           $self->{errorString}="'".$args{set}."' is not a legit set name.";
2012 0           $self->warn;
2013             return undef
2014 0           }
2015             }
2016              
2017              
2018              
2019             #small hack as this was copied writeSetFromLoadedConfig
2020 0           my $zml=$args{zml};
2021              
2022 0           my $setstring=$args{set}."\n".$zml->string;
2023              
2024             #creates the DN from the config
2025 0           my $dn=$self->config2dn($args{config}).",".$self->{args}{"ldap/base"};
2026              
2027             #connects to LDAP
2028 0           my $ldap=$self->LDAPconnect;
2029 0 0         if ($self->error) {
2030 0           warn('zconf writeSetFromLoadedConfigLDAP: LDAPconnect errored... returning...');
2031 0           return undef;
2032             }
2033              
2034             #gets the LDAP entry
2035 0           my $entry=$self->LDAPgetConfEntry($args{config}, $ldap);
2036             #return upon error
2037 0 0         if ($self->error) {
2038 0           $self->warnString('LDAPgetConfEntry errored');
2039 0           return undef;
2040             }
2041              
2042 0 0         if(!defined($entry->dn)){
2043 0           $self->{error}=13;
2044 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
2045 0           $self->warn;
2046 0           return undef;
2047             }else{
2048 0 0         if($entry->dn ne $dn){
2049 0           $self->{error}=13;
2050 0           $self->{errorString}="Expected DN, '".$dn."' not found.";
2051 0           $self->warn;
2052 0           return undef;
2053             }
2054             }
2055              
2056             #makes sure the zconfSet attribute is set for the config in question
2057 0           my @attributes=$entry->get_value('zconfSet');
2058             #if the 0th is not defined, it this zconf entry is borked and it needs to have the set value added
2059 0 0         if(defined($attributes[0])){
2060             #if $attributes dues contain enteries, make sure that one of them is the proper set
2061 0           my $attributesInt=0;
2062 0           my $setFound=0;#set to one if the loop finds the set
2063 0           while(defined($attributes[$attributesInt])){
2064 0 0         if($attributes[$attributesInt] eq $args{set}){
2065 0           $setFound=1;
2066             };
2067 0           $attributesInt++;
2068             }
2069             #if the set was not found, add it
2070 0 0         if(!$setFound){
2071 0           $entry->add(zconfSet=>$args{set});
2072             }
2073             }else{
2074 0           $entry->add(zconfSet=>$args{set});
2075             }
2076              
2077             #
2078 0           @attributes=$entry->get_value('zconfData');
2079             #if the 0th is not defined, it this zconf entry is borked and it needs to have it added...
2080 0 0         if(defined($attributes[0])){
2081             #if $attributes dues contain enteries, make sure that one of them is the proper set
2082 0           my $attributesInt=0;
2083 0           my $setFound=undef;#set to one if the loop finds the set
2084 0           while(defined($attributes[$attributesInt])){
2085 0 0         if($attributes[$attributesInt] =~ /^$args{set}\n/){
2086             #delete it the attribute and readd it, if it has not been found yet...
2087             #if it has been found it means this entry is borked and the duplicate
2088             #set needs removed...
2089 0 0         if(!$setFound){
2090 0           $entry->delete(zconfData=>[$attributes[$attributesInt]]);
2091 0           $entry->add(zconfData=>[$setstring]);
2092             }else{
2093 0 0         if($setstring ne $attributes[$attributesInt]){
2094 0           $entry->delete(zconfData=>[$attributes[$attributesInt]]);
2095             }
2096             }
2097 0           $setFound=1;
2098             }
2099 0           $attributesInt++;
2100             }
2101             #if the config is not found, add it
2102 0 0         if(!$setFound){
2103 0           $entry->add(zconfData=>[$setstring]);
2104             }
2105             }else{
2106 0           $entry->add(zconfData=>$setstring);
2107             }
2108              
2109             #update the revision
2110 0 0         if (!defined($args{revision})) {
2111 0           $args{revision}=time.' '.hostname.' '.rand();
2112             }
2113 0           $entry->delete('zconfRev');
2114 0           $entry->add(zconfRev=>[$args{revision}]);
2115              
2116 0           my $results=$entry->update($ldap);
2117              
2118             #save the revision info
2119 0           $self->{self}->{revision}{$args{config}}=$args{revision};
2120              
2121 0           return $args{revision};
2122             }
2123              
2124             =head1 ERROR HANDLING/CODES
2125              
2126             This module uses L for error handling. Below are the
2127             error codes returned by the error method.
2128              
2129             =head2 1
2130              
2131             config name contains ,
2132              
2133             =head2 2
2134              
2135             config name contains /.
2136              
2137             =head2 3
2138              
2139             config name contains //
2140              
2141             =head2 4
2142              
2143             config name contains ../
2144              
2145             =head2 5
2146              
2147             config name contains /..
2148              
2149             =head2 6
2150              
2151             config name contains ^./
2152              
2153             =head2 7
2154              
2155             config name ends in /
2156              
2157             =head2 8
2158              
2159             config name starts with /
2160              
2161             =head2 9
2162              
2163             could not sync to file
2164              
2165             =head2 10
2166              
2167             config name contains a \n
2168              
2169             =head2 11
2170              
2171             LDAP entry already exists
2172              
2173             =head2 12
2174              
2175             config does not exist
2176              
2177             =head2 13
2178              
2179             Expected LDAP DN not found
2180              
2181             =head2 14
2182              
2183             ZML dump failed.
2184              
2185             =head2 15
2186              
2187             ZML object not passed.
2188              
2189             =head2 16
2190              
2191             Unable to create some of the required DN entries.
2192              
2193             =head2 18
2194              
2195             No variable name specified.
2196              
2197             =head2 19
2198              
2199             config key starts with a ' '
2200              
2201             =head2 20
2202              
2203             LDAP entry has no sets
2204              
2205             =head2 21
2206              
2207             set not found for config
2208              
2209             =head2 22
2210              
2211             LDAPmakepathSimple failed
2212              
2213             =head2 23
2214              
2215             skilling variable as it is not a legit name
2216              
2217             =head2 24
2218              
2219             set is not defined
2220              
2221             =head2 25
2222              
2223             Config is undefined.
2224              
2225             =head2 26
2226              
2227             Config not loaded.
2228              
2229             =head2 27
2230              
2231             Set name is not a legit name.
2232              
2233             =head2 28
2234              
2235             ZML->parse error.
2236              
2237             =head2 29
2238              
2239             Could not unlink the unlink the set.
2240              
2241             =head2 30
2242              
2243             The sets exist for the specified config.
2244              
2245             =head2 31
2246              
2247             Did not find a matching set.
2248              
2249             =head2 32
2250              
2251             Unable to choose a set.
2252              
2253             =head2 33
2254              
2255             Unable to remove the config as it has sub configs.
2256              
2257             =head2 34
2258              
2259             LDAP connection error
2260              
2261             =head2 35
2262              
2263             Can't use system mode and file together.
2264              
2265             =head2 36
2266              
2267             Could not create '/var/db/zconf'. This is a permanent error.
2268              
2269             =head2 37
2270              
2271             Could not create '/var/db/zconf/'. This is a permanent error.
2272              
2273             =head2 38
2274              
2275             Sys name matched /\//.
2276              
2277             =head2 39
2278              
2279             Sys name matched /\./.
2280              
2281             =head2 40
2282              
2283             No chooser string specified.
2284              
2285             =head2 41
2286              
2287             No comment specified.
2288              
2289             =head2 42
2290              
2291             No meta specified.
2292              
2293             =head2 43
2294              
2295             Failed to open the revision file for the set.
2296              
2297             =head2 44
2298              
2299             Failed to open or unlink lock file.
2300              
2301             =head2 45
2302              
2303             Config is locked.
2304              
2305             =head2 46
2306              
2307             LDAP entry update failed.
2308              
2309             =head2 47
2310              
2311             No ZConf object passed.
2312              
2313             =head2 48
2314              
2315             No zconf.zml var hash passed.
2316              
2317             =head1 ERROR CHECKING
2318              
2319             This can be done by checking $zconf->{error} to see if it is defined. If it is defined,
2320             The number it contains is the corresponding error code. A description of the error can also
2321             be found in $zconf->{errorString}, which is set to "" when there is no error.
2322              
2323             =head1 zconf.zml
2324              
2325             The default is 'xdf_config_home/zconf.zml', which is generally '~/.config/zconf.zml'. See perldoc
2326             ZML for more information on the file format. The keys are listed below.
2327              
2328             =head2 zconf.zml LDAP backend keys
2329              
2330             =head3 backend
2331              
2332             This should be set to 'ldap' to use this backend.
2333              
2334             =head3 LDAPprofileChooser
2335              
2336             This is a chooser string that chooses what LDAP profile to use. If this is not present, 'default'
2337             will be used for the profile.
2338              
2339             =head3 ldap//bind
2340              
2341             This is the DN to bind to the server as.
2342              
2343             =head3 ldap//cafile
2344              
2345             When verifying the server's certificate, either set capath to the pathname of the directory containing
2346             CA certificates, or set cafile to the filename containing the certificate of the CA who signed the
2347             server's certificate. These certificates must all be in PEM format.
2348              
2349             =head3 ldap//capath
2350              
2351             The directory in 'capath' must contain certificates named using the hash value of the certificates'
2352             subject names. To generate these names, use OpenSSL like this in Unix:
2353              
2354             ln -s cacert.pem `openssl x509 -hash -noout < cacert.pem`.0
2355              
2356             (assuming that the certificate of the CA is in cacert.pem.)
2357              
2358             =head3 ldap//checkcrl
2359              
2360             If capath has been configured, then it will also be searched for certificate revocation lists (CRLs)
2361             when verifying the server's certificate. The CRLs' names must follow the form hash.rnum where hash
2362             is the hash over the issuer's DN and num is a number starting with 0.
2363              
2364             =head3 ldap//clientcert
2365              
2366             This client cert to use.
2367              
2368             =head3 ldap//clientkey
2369              
2370             The client key to use.
2371              
2372             Encrypted keys are not currently supported at this time.
2373              
2374             =head3 ldap//homeDN
2375              
2376             This is the home DN of the user in question. The user needs be able to write to it. ZConf
2377             will attempt to create 'ou=zconf,ou=.config,$homeDN' for operating out of.
2378              
2379             =head3 ldap//host
2380              
2381             This is the server to use for LDAP connections.
2382              
2383             =head3 ldap//password
2384              
2385             This is the password to use for when connecting to the server.
2386              
2387             =head3 ldap//passwordfile
2388              
2389             Read the password from this file. If both this and password is set,
2390             then this will write over it.
2391              
2392             =head3 ldap//starttls
2393              
2394             This is if it should use starttls or not. It defaults to undefined, 'false'.
2395              
2396             =head3 ldap//SSLciphers
2397              
2398             This is a list of ciphers to accept. The string is in the standard OpenSSL
2399             format. The default value is 'ALL'.
2400              
2401             =head3 ldap//SSLversion
2402              
2403             This is the SSL versions accepted.
2404              
2405             'sslv2', 'sslv3', 'sslv2/3', or 'tlsv1' are the possible values. The default
2406             is 'tlsv1'.
2407              
2408             =head3 ldap//TLSverify
2409              
2410             The verify mode for TLS. The default is 'none'.
2411              
2412             =head1 ZConf LDAP Schema
2413              
2414             # 1.3.6.1.4.1.26481 Zane C. Bowers
2415             # .2 ldap
2416             # .7 zconf
2417             # .0 zconfData
2418             # .1 zconfChooser
2419             # .2 zconfSet
2420             # .3 zconfRev
2421             # .4 zconfLock
2422            
2423             attributeType ( 1.3.6.1.4.1.26481.2.7.0
2424             NAME 'zconfData'
2425             DESC 'Data attribute for a zconf entry.'
2426             SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
2427             EQUALITY caseExactMatch
2428             )
2429            
2430             attributeType ( 1.3.6.1.4.1.26481.2.7.1
2431             NAME 'zconfChooser'
2432             DESC 'Chooser attribute for a zconf entry.'
2433             SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
2434             EQUALITY caseExactMatch
2435             )
2436            
2437             attributeType ( 1.3.6.1.4.1.26481.2.7.2
2438             NAME 'zconfSet'
2439             DESC 'A zconf set name available in a entry.'
2440             SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
2441             EQUALITY caseExactMatch
2442             )
2443            
2444             attributeType ( 1.3.6.1.4.1.26481.2.7.3
2445             NAME 'zconfRev'
2446             DESC 'The revision number for a ZConf config. Bumped with each update.'
2447             SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
2448             EQUALITY caseExactMatch
2449             )
2450            
2451             attributeType ( 1.3.6.1.4.1.26481.2.7.4
2452             NAME 'zconfLock'
2453             DESC 'If this is present, this config is locked.'
2454             SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
2455             EQUALITY caseExactMatch
2456             )
2457            
2458             objectclass ( 1.3.6.1.4.1.26481.2.7
2459             NAME 'zconf'
2460             DESC 'A zconf entry.'
2461             MAY ( cn $ zconfData $ zconfChooser $ zconfSet $ zconfRev $ zconfLock )
2462             )
2463              
2464             =head1 SYSTEM MODE
2465              
2466             This is for deamons or the like. This will read
2467             '/var/db/zconf/$sys/zconf.zml' for it's options and store
2468             the file backend stuff in '/var/db/zconf/$sys/'.
2469              
2470             It will create '/var/db/zconf' or the sys directory, but not
2471             '/var/db'.
2472              
2473             =head1 UTILITIES
2474              
2475             There are several scripts installed with this module. Please see the perldocs for
2476             the utilities listed below.
2477              
2478             zcchooser-edit
2479             zcchooser-get
2480             zcchooser-run
2481             zcchooser-set
2482             zccreate
2483             zcget
2484             zcls
2485             zcrm
2486             zcset
2487             zcvdel
2488             zcvls
2489              
2490              
2491             =head1 AUTHOR
2492              
2493             Zane C. Bowers-Hadley, C<< >>
2494              
2495             =head1 BUGS
2496              
2497             Please report any bugs or feature requests to C, or through
2498             the web interface at L. I will be notified, and then you'll
2499             automatically be notified of progress on your bug as I make changes.
2500              
2501             =head1 SUPPORT
2502              
2503             You can find documentation for this module with the perldoc command.
2504              
2505             perldoc ZConf
2506              
2507              
2508             You can also look for information at:
2509              
2510             =over 4
2511              
2512             =item * RT: CPAN's request tracker
2513              
2514             L
2515              
2516             =item * AnnoCPAN: Annotated CPAN documentation
2517              
2518             L
2519              
2520             =item * CPAN Ratings
2521              
2522             L
2523              
2524             =item * Search CPAN
2525              
2526             L
2527              
2528             =item * Subversion Repository
2529              
2530             L
2531              
2532             =back
2533              
2534             =head1 ACKNOWLEDGEMENTS
2535              
2536             =head1 COPYRIGHT & LICENSE
2537              
2538             Copyright 2011 Zane C. Bowers-Hadley, all rights reserved.
2539              
2540             This program is free software; you can redistribute it and/or modify it
2541             under the same terms as Perl itself.
2542              
2543              
2544             =cut
2545              
2546             1; # End of ZConf