diff options
Diffstat (limited to 'ldap/admin/src/scripts')
| -rw-r--r-- | ldap/admin/src/scripts/DSCreate.pm.in | 39 | ||||
| -rw-r--r-- | ldap/admin/src/scripts/DSMigration.pm.in | 15 | ||||
| -rw-r--r-- | ldap/admin/src/scripts/FileConn.pm | 34 | ||||
| -rw-r--r-- | ldap/admin/src/scripts/Util.pm.in | 160 | ||||
| -rwxr-xr-x | ldap/admin/src/scripts/remove-ds.pl.in | 4 | ||||
| -rw-r--r-- | ldap/admin/src/scripts/setup-ds.res.in | 4 |
6 files changed, 122 insertions, 134 deletions
diff --git a/ldap/admin/src/scripts/DSCreate.pm.in b/ldap/admin/src/scripts/DSCreate.pm.in index efb1fa65..89f0ba00 100644 --- a/ldap/admin/src/scripts/DSCreate.pm.in +++ b/ldap/admin/src/scripts/DSCreate.pm.in @@ -215,6 +215,28 @@ sub makeDSDirs { return @errs; } } + # run_dir is a special case because it is usually shared among + # all instances and the admin server + # all instances must be able to write to it + # if the SuiteSpotUserID is root or 0, we can just skip + # this because root will have access to it - we really + # shouldn't be using root anyway, primarily just for + # legacy migration support + # if there are two different user IDs that need access + # to this directory, then SuiteSpotGroup must be defined, + # and both users must be members of the SuiteSpotGroup + if (($inf->{General}->{SuiteSpotUserID} eq 'root') || + (defined($inf->{General}->{SuiteSpotUserID}) && + ($inf->{General}->{SuiteSpotUserID} =~ /^0$/))) { + # skip + debug(3, "Root user " . $inf->{General}->{SuiteSpotUserID} . " already has access to $inf->{slapd}->{run_dir} - skipping\n"); + } else { + my $dir = $inf->{slapd}->{run_dir}; + # rwx by user only, or by user & group if a group is defined + @errs = changeOwnerMode($inf, 7, $dir, 7); + debug(3, "Changed owner of $dir to " . $inf->{General}->{SuiteSpotUserID} . ": error @errs\n"); + debug(3, "\t" . `/bin/ls -ld $dir`); + } # set the group of the parent dir of config_dir and inst_dir if (defined($inf->{General}->{SuiteSpotGroup})) { for (qw(inst_dir config_dir)) { @@ -372,7 +394,10 @@ sub createConfigFile { } } - $conn->write($conffile); + if (!$conn->write($conffile)) { + $conn->close(); + return ("error_writing_ldif", $conffile, $!); + } $conn->close(); if (@errs = changeOwnerMode($inf, 6, $conffile)) { @@ -506,11 +531,21 @@ sub initDatabase { my ($fh, $templdif) = tempfile("ldifXXXXXX", SUFFIX => ".ldif", OPEN => 0, DIR => File::Spec->tmpdir); + if (!$templdif) { + return ('error_creating_templdif', $!); + } my $conn = new FileConn; $conn->setNamingContext($inf->{slapd}->{Suffix}); getMappedEntries($mapper, \@ldiffiles, \@errs, \&check_and_add_entry, [$conn]); - $conn->write($templdif); + if (@errs) { + $conn->close(); + return @errs; + } + if (!$conn->write($templdif)) { + $conn->close(); + return ('error_writing_ldif', $templdif, $!); + } $conn->close(); if (@errs) { return @errs; diff --git a/ldap/admin/src/scripts/DSMigration.pm.in b/ldap/admin/src/scripts/DSMigration.pm.in index dd6f74af..da51d4df 100644 --- a/ldap/admin/src/scripts/DSMigration.pm.in +++ b/ldap/admin/src/scripts/DSMigration.pm.in @@ -938,11 +938,15 @@ sub migrateDS { # extract the information needed for ds_newinst.pl my $oldconfigdir = "$mig->{oldsroot}/$inst/config"; my $inf = createInfFromConfig($oldconfigdir, $inst, \@errs); - debug(2, "Using inffile $inf->{filename} created from $oldconfigdir\n"); if (@errs) { $mig->msg(@errs); return 0; } + if (!$inf) { + $mig->msg($FATAL, 'error_opening_dseldif', "$oldconfigdir/dse.ldif", $!); + return 0; + } + debug(2, "Using inffile $inf->{filename} created from $oldconfigdir\n"); # create servers but do not start them until after databases # have been migrated @@ -960,7 +964,16 @@ sub migrateDS { } my $src = new FileConn("$oldconfigdir/dse.ldif", 1); # read-only + if (!$src) { + $mig->msg($FATAL, 'error_opening_dseldif', "$oldconfigdir/dse.ldif", $!); + return 0; + } my $dest = new FileConn("$mig->{configdir}/$inst/dse.ldif"); + if (!$dest) { + $src->close(); + $mig->msg($FATAL, 'error_opening_dseldif', "$mig->{configdir}/$inst/dse.ldif", $!); + return 0; + } @errs = migrateDSInstance($mig, $inst, $src, $dest); $src->close(); diff --git a/ldap/admin/src/scripts/FileConn.pm b/ldap/admin/src/scripts/FileConn.pm index 447f4aaf..f1ac4d2d 100644 --- a/ldap/admin/src/scripts/FileConn.pm +++ b/ldap/admin/src/scripts/FileConn.pm @@ -67,7 +67,9 @@ sub new { $self->setNamingContext($_); } $self->setNamingContext(""); # root DSE - $self->read($filename); + if (!$self->read($filename)) { + return; + } return $self; } @@ -90,10 +92,14 @@ sub read { } if (!$self->{filename}) { - return; + return 1; # no filename given - ok + } + + if (!open( MYLDIF, "$filename" )) { + confess "Can't open $filename: $!"; + return 0; } - open( MYLDIF, "$filename" ) || confess "Can't open $filename: $!"; my $in = new Mozilla::LDAP::LDIF(*MYLDIF); $self->{reading} = 1; while ($ent = readOneEntry $in) { @@ -103,6 +109,8 @@ sub read { } delete $self->{reading}; close( MYLDIF ); + + return 1; } sub setNamingContext { @@ -175,16 +183,22 @@ sub write { } if (!$self->{filename} or $self->{readonly} or $self->{reading}) { - return; + return 1; # ok - no filename given - just ignore + } + + if (!open( MYLDIF, ">$filename" )) { + confess "Can't write $filename: $!"; + return 0; } - open( MYLDIF, ">$filename" ) || confess "Can't write $filename: $!"; $self->iterate("", LDAP_SCOPE_SUBTREE, \&writecb, \*MYLDIF); for (keys %{$self->{namingContexts}}) { next if (!$_); # skip "" - we already did that $self->iterate($_, LDAP_SCOPE_SUBTREE, \&writecb, \*MYLDIF); } close( MYLDIF ); + + return 1; } sub setErrorCode { @@ -372,8 +386,7 @@ sub add { if ($self->isNamingContext($ndn) and !exists($self->{$ndn}->{data})) { $self->{$ndn}->{data} = $entry; - $self->write(); - return 1; + return $self->write(); } if (exists($self->{$ndn})) { @@ -415,9 +428,7 @@ sub update { # process omits the deleted attrs via the Entry FETCH, FIRSTKEY, and NEXTKEY # methods $self->{$ndn}->{data} = cloneEntry($entry); - $self->write(); - - return 1; + return $self->write(); } sub delete { @@ -464,8 +475,7 @@ sub delete { # delete this node delete $self->{$ndn}; - $self->write(); - return 1; + return $self->write(); } 1; diff --git a/ldap/admin/src/scripts/Util.pm.in b/ldap/admin/src/scripts/Util.pm.in index 20aea64b..660461e7 100644 --- a/ldap/admin/src/scripts/Util.pm.in +++ b/ldap/admin/src/scripts/Util.pm.in @@ -40,7 +40,7 @@ package Util; use Mozilla::LDAP::Conn; use Mozilla::LDAP::Utils qw(normalizeDN); -use Mozilla::LDAP::API; # Direct access to C API +use Mozilla::LDAP::API qw(:constant ldap_explode_dn ldap_err2string) ; # Direct access to C API use Mozilla::LDAP::LDIF; require Exporter; @@ -172,85 +172,6 @@ sub delete_all return 0; } -my %ignorelist = ( - "nsslapd-directory", "nsslapd-directory", - "nsslapd-require-index", "nsslapd-require-index", - "nsslapd-readonly", "nsslapd-readonly", - "modifytimestamp", "modifyTimestamp", - "createtimestamp", "createTimestamp", - "installationtimestamp", "installationTimestamp", - "creatorsname", "creatorsName", - "modifiersname", "modifiersName", - "numsubordinates", "numSubordinates" -); - -my %speciallist = ( - "uniquemember", 1, - "aci", 1 -); - -# compare 2 entries -# return 0 if they match 100% (exception: %ignorelist). -# return 1 if they match except %speciallist. -# return -1 if they do not match. -sub comp_entries -{ - my ($e0, $e1) = @_; - my $rc = 0; - foreach my $akey ( keys %{$e0} ) - { - next if ( $ignorelist{lc($akey)} ); - my $aval0 = $e0->{$akey}; - my $aval1 = $e1->{$akey}; - my $a0max = $#{$aval0}; - my $a1max = $#{$aval1}; - my $amin = $#{$aval0}; - if ( $a0max != $a1max ) - { - if ( $speciallist{lc($akey)} ) - { - $rc = 1; - if ( $a0max < $a1max ) - { - $amin = $a0max; - } - else - { - $amin = $a1max; - } - } - else - { - $rc = -1; - return $rc; - } - } - my @sval0 = sort { $a cmp $b } @{$aval0}; - my @sval1 = sort { $a cmp $b } @{$aval1}; - for ( my $i = 0; $i <= $amin; $i++ ) - { - my $isspecial = -1; - if ( $sval0[$i] ne $sval1[$i] ) - { - if ( 0 > $isspecial ) - { - $isspecial = $speciallist{lc($akey)}; - } - if ( $isspecial ) - { - $rc = 1; - } - else - { - $rc = -1; - return $rc; - } - } - } - } - return $rc; -} - # if the entry does not exist on the server, add the entry. # otherwise, do nothing # you can use this as the callback to getMappedEntries, so @@ -272,9 +193,18 @@ sub check_and_add_entry my $sentry = $conn->search($aentry->{dn}, "base", "(objectclass=*)", 0, ("*", "aci")); if ($sentry) { debug(3, "check_and_add_entry: Found entry " . $sentry->getDN() . "\n"); + if (! @ctypes) { # entry exists, and this is not a modify op + debug(3, "check_and_add_entry: skipping entry " . $sentry->getDN() . "\n"); + return 1; # ignore - return success + } } else { debug(3, "check_and_add_entry: Entry not found " . $aentry->{dn} . " error " . $conn->getErrorString() . "\n"); + if (@ctypes) { # uh oh - attempt to del/mod an entry that doesn't exist + debug(3, "check_and_add_entry: attepting to @ctypes the entry " . $aentry->{dn} . + " that does not exist\n"); + return 1; # ignore - return success + } } do { @@ -289,39 +219,7 @@ sub check_and_add_entry my $op = $OP_NONE; if ( 0 > $#ctypes ) # aentry: complete entry { - $op = $OP_ADD; - - my $rc = -1; - if ( $sentry && !$fresh ) - { - $rc = comp_entries( $sentry, $aentry ); - } - if ( 0 == $rc && !$fresh ) - { - # the identical entry exists on the configuration DS. - # no need to add the entry. - $op = $OP_NONE; - goto out; - } - elsif ( (1 == $rc) && !$fresh ) - { - $op = $OP_MOD; - @addtypes = keys %{$aentry}; # add all attrs - } - elsif ( $sentry && $sentry->{dn} ) - { - # $fresh || $rc == -1 - # an entry having the same DN exists, but the attributes do not - # match. remove the entry and the subtree underneath. - debug(1, "Deleting an entry dn: $sentry->{dn} ...\n"); - $rc = delete_all($conn, $sentry); - if ( 0 != $rc ) - { - push @{$errs}, 'error_deleteall_entries', $sentry->{dn}, $conn->getErrorString(); - debug(1, "Error deleting $sentry->{dn}\n"); - return 0; - } - } + $op = $OP_ADD; # just add the entry } else # aentry: modify format { @@ -371,9 +269,13 @@ sub check_and_add_entry } debug(1, "Entry $aentry->{dn} is deleted\n"); } - elsif ( 0 < $op ) # $sentry exists + elsif ( 0 < $op ) # modify op { my $attr; + my @errsToIgnore; + if (@addtypes) { + push @errsToIgnore, LDAP_TYPE_OR_VALUE_EXISTS; + } foreach $attr ( @addtypes ) { foreach my $val ($aentry->getValues($attr)) @@ -388,6 +290,9 @@ sub check_and_add_entry debug(3, "Replacing attr=$attr values=" . $aentry->getValues($attr) . " to entry $aentry->{dn}\n"); $sentry->setValues($attr, @vals); } + if (@deltypes) { + push @errsToIgnore, LDAP_NO_SUCH_ATTRIBUTE; + } foreach $attr ( @deltypes ) { # removeValue takes a single value only @@ -410,11 +315,15 @@ sub check_and_add_entry if ( $rc != 0 ) { my $string = $conn->getErrorString(); - push @{$errs}, 'error_updating_entry', $sentry->{dn}, $string; debug(1, "ERROR: updating an entry $sentry->{dn} failed, error: $string\n"); - $aentry->printLDIF(); - $conn->close(); - return 0; + if (grep /^$rc$/, @errsToIgnore) { + debug(1, "Ignoring error $rc returned by adding @addtypes deleting @deltypes\n"); + } else { + push @{$errs}, 'error_updating_entry', $sentry->{dn}, $string; + $aentry->printLDIF(); + $conn->close(); + return 0; + } } } if ( $sentry ) @@ -793,19 +702,32 @@ sub createInfFromConfig { my $fname = "$configdir/dse.ldif"; my $id; ($id = $inst) =~ s/^slapd-//; - if (! -f $fname) { + if (! -f $fname || ! -r $fname) { push @{$errs}, "error_opening_dseldif", $fname, $!; return 0; } my $conn = new FileConn($fname, 1); + if (!$conn) { + push @{$errs}, "error_opening_dseldif", $fname, $!; + return 0; + } my $ent = $conn->search("cn=config", "base", "(objectclass=*)"); if (!$ent) { push @{$errs}, "error_opening_dseldif", $fname, $!; + $conn->close(); return 0; } my ($outfh, $inffile) = tempfile(SUFFIX => '.inf'); + if (!$outfh || !$inffile) { + push @{$errs}, "error_opening_tempinf", $fname, $!; + if ($outfh) { + close $outfh; + } + $conn->close(); + return 0; + } print $outfh "[General]\n"; print $outfh "FullMachineName = ", $ent->getValues('nsslapd-localhost'), "\n"; print $outfh "SuiteSpotUserID = ", $ent->getValues('nsslapd-localuser'), "\n"; diff --git a/ldap/admin/src/scripts/remove-ds.pl.in b/ldap/admin/src/scripts/remove-ds.pl.in index fadbbe90..492ccc7e 100755 --- a/ldap/admin/src/scripts/remove-ds.pl.in +++ b/ldap/admin/src/scripts/remove-ds.pl.in @@ -162,6 +162,10 @@ if ( ! -d $configdir ) # read the config file to find out the paths my $dseldif = "@instconfigdir@/$instname/dse.ldif"; my $conn = new FileConn($dseldif); +if (!$conn) { + print STDERR "Error: Could not open config file $dseldif: Error $!\n"; + exit 1; +} my $dn = "cn=config"; my $entry = $conn->search($dn, "base", "(cn=*)", 0); diff --git a/ldap/admin/src/scripts/setup-ds.res.in b/ldap/admin/src/scripts/setup-ds.res.in index fa256275..a89b1274 100644 --- a/ldap/admin/src/scripts/setup-ds.res.in +++ b/ldap/admin/src/scripts/setup-ds.res.in @@ -127,3 +127,7 @@ Please remove it first if you really want to recreate it,\ or use a different ServerIdentifier to create another instance.\n error_opening_init_ldif = Could not open the initial LDIF file '%s'.\ The file was not found or could not be read.\n +error_opening_dseldif = Could not open the DSE config file '%s'. Error: %s\n +error_opening_tempinf = Could not create temporary .inf file for config. Error: %s\n +error_writing_ldif = Could not write the LDIF file '%s'. Error: %s\n +error_creating_templdif = Could not create temporary LDIF file. Error: %s\n |
