From 84fbecdbfaebc4a21d3f615d5438a65eb18faaac Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Thu, 31 Oct 2013 16:27:05 -0700 Subject: [PATCH] Ticket #47555 - db2bak.pl issue when specifying non-default directory Bug description: db2bak.pl takes an option "-a backupdir", which is supposed to be generated by the server and used as a backup directory. But since the created directory inherits the parent's selinux context, it fails to store the backup files in the directory. Fix description: As the reporter agaviola suggested, it should be a good idea to add one more level to the archive directory. $archivedir = "${archivedir}/ID-${yr}_${mn}_${dy}_${h}_${m}_${s}"; But to keep the backward compatibility, introducing a new option "-A backupdir" and when "-A" is given, storing the backup files in the nested backup directory. If the option is "-a backupdir", the backup files are stored in the backupdir. Respecting the selinux policy, the server and its utilities are not supposed to create a file/directory where it is not allowed. This patch creates a symlink from the back up location to the specified path by a user. bak2db.pl follows the symlink and restore from the back up directory. --- ldap/admin/src/scripts/bak2db.pl.in | 3 +++ ldap/admin/src/scripts/db2bak.pl.in | 43 +++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/ldap/admin/src/scripts/bak2db.pl.in b/ldap/admin/src/scripts/bak2db.pl.in index 7e76838..f442493 100644 --- a/ldap/admin/src/scripts/bak2db.pl.in +++ b/ldap/admin/src/scripts/bak2db.pl.in @@ -112,6 +112,9 @@ if ($archivedir eq ""){ &usage; exit(1); } +if ((-e $archivedir) && (-l $archivedir)) { # symlink + $archivedir = readlink($archivedir); +} # # Contruct the task entry diff --git a/ldap/admin/src/scripts/db2bak.pl.in b/ldap/admin/src/scripts/db2bak.pl.in index aee8486..2ba056d 100644 --- a/ldap/admin/src/scripts/db2bak.pl.in +++ b/ldap/admin/src/scripts/db2bak.pl.in @@ -40,6 +40,7 @@ # use lib qw(@perlpath@); +use File::Basename; use DSUtil; DSUtil::libpath_add("@nss_libdir@"); @@ -61,6 +62,7 @@ sub usage { print(STDERR " -w - - Prompt for Directory Manager's password\n"); print(STDERR " -Z serverID - Server instance identifier\n"); print(STDERR " -j filename - Read Directory Manager's password from file\n"); + print(STDERR " -A backupdir - Backup directory (backupdir/ID-)\n"); print(STDERR " -a backupdir - Backup directory\n"); print(STDERR " -t dbtype - Database type (default: ldbm database)\n"); print(STDERR " -P protocol - STARTTLS, LDAPS, LDAPI, LDAP (default: uses most secure protocol available)\n"); @@ -68,9 +70,13 @@ sub usage { print(STDERR " -h - Display usage\n"); } +$nestit = 0; while ($i <= $#ARGV) { if ("$ARGV[$i]" eq "-a") { # backup directory $i++; $archivedir = $ARGV[$i]; + } elsif ("$ARGV[$i]" eq "-A") { # backup directory + $nestit = 1; + $i++; $archivedir = $ARGV[$i]; } elsif ("$ARGV[$i]" eq "-D") { # Directory Manager $i++; $rootdn = $ARGV[$i]; } elsif ("$ARGV[$i]" eq "-w") { # Directory Manager's password @@ -114,9 +120,32 @@ $mybakdir = "@localstatedir@/lib/@PACKAGE_NAME@/slapd-$servid/bak"; ($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time); $mn++; $yr += 1900; $taskname = "backup_${yr}_${mn}_${dy}_${h}_${m}_${s}"; +$symname = ""; +$dirname = ""; if ($archivedir eq "") { $archivedir = "${mybakdir}/$servid-${yr}_${mn}_${dy}_${h}_${m}_${s}"; + print("Back up directory: $archivedir\n"); +} else { + if ($nestit == 1) { + $archivebase = "${servid}-${yr}_${mn}_${dy}_${h}_${m}_${s}"; + $dirname = "${archivedir}"; + $archivedir = "${dirname}/${archivebase}"; + } else { + my @archivedirs = split(/\//, $archivedir); + $archivebase = $archivedirs[-1]; + $dirname = dirname(${archivedir}); + } + if ($mybakdir =~ /^$dirname/) { # $mybakdir is parent; no symlink needed + $symname = ""; + } else { + $symname = $archivedir; + } + print("Back up directory: $archivedir\n"); + # If an archive dir is specified, create it as a symlink pointing + # to the default backup dir not to violate the selinux policy. + $archivedir = "${mybakdir}/${archivebase}"; } + $dn = "dn: cn=$taskname, cn=backup, cn=tasks, cn=config\n"; $misc = "objectclass: top\nobjectclass: extensibleObject\n"; $cn = "cn: $taskname\n"; @@ -124,14 +153,24 @@ $nsarchivedir = "nsArchiveDir: $archivedir\n"; $nsdbtype = "nsDatabaseType: $dbtype\n"; $entry = "${dn}${misc}${cn}${nsarchivedir}${nsdbtype}"; -print("Back up directory: $archivedir\n"); - $rc = DSUtil::ldapmod($entry, %info); $dn =~ s/^dn: //; $dn =~ s/\n//; if($rc == 0){ print "Successfully added task entry \"$dn\"\n"; + if (($symname ne "") && ($dirname ne "")) { + if (!(-d $dirname)) { + mkdir ($dirname); + } + if (-e $symname) { + unlink ($symname); + } + if (!symlink($archivedir, $symname)) { + print "Failed to create a symlink from $archivedir to $symname\n"; + exit(1); + } + } } else { print "Failed to add task entry \"$dn\" error ($rc)\n"; } -- 1.8.1.4