Skip to content

Commit fb14ecb

Browse files
author
cbarratt
committed
* various FTP fixes
* added more shell escaping to bin/BackupPC_archiveHost * updates to FTP conf/config.pl comments * minor path change to configure.pl
1 parent 0e6be99 commit fb14ecb

File tree

5 files changed

+97
-50
lines changed

5 files changed

+97
-50
lines changed

ChangeLog

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@
7575

7676
* Modified bin/BackupPC_archiveHost to shell escape the output file
7777
name. That allows it to contain spaces and other special characters.
78-
Requested by Toni Van Remortel.
78+
Requested by Toni Van Remortel. Also updated bin/BackupPC_archiveHost
79+
to shell escape and check other arguments.
7980

8081
* Added $Conf{CmdQueueNice} to specify nice level for command queue
8182
commands (eg: BackupPC_link and BackupPC_nightly). Suggested by

bin/BackupPC_archiveHost

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/perl
1+
#!/usr/bin/perl
22
#=============================================================
33
#
44
# BackupPC_archiveHost: Archive files for a single host
@@ -38,7 +38,7 @@
3838
#
3939
#========================================================================
4040
#
41-
# Version 3.1.0, released 25 Nov 2007.
41+
# Version 3.2.0beta0, released 29 Mar 2009.
4242
#
4343
# See http://backuppc.sourceforge.net.
4444
#
@@ -77,6 +77,10 @@ die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
7777
# Make sure the specified programs are executable
7878
#
7979
foreach my $prog ( ($tarCreate, $compPath, $splitPath, $parPath) ) {
80+
if ( $prog =~ /[][;&()<>{}|^\n\r\t *\$\\'"`?]/ ) {
81+
print("Error: executable path $prog contains suspicious characters\n");
82+
exit(1);
83+
}
8084
next if ( $prog eq "" || -x $prog );
8185
print("Error: $prog is not an executable program\n");
8286
exit(1);
@@ -88,6 +92,10 @@ my $mesg = "Writing tar archive for host $host, backup #$bkupNum";
8892
#
8993
$share = $bpc->shellEscape($share);
9094
$host = $bpc->shellEscape($host);
95+
$bkupNum = $bpc->shellEscape($bkupNum);
96+
$fileExt = $bpc->shellEscape($fileExt);
97+
$splitSize = $bpc->shellEscape($splitSize);
98+
$parfile = $bpc->shellEscape($parfile);
9199
my $outLocE = $bpc->shellEscape($outLoc);
92100

93101
#
@@ -114,7 +122,7 @@ if ( -b $outLoc || -c $outLoc || -f $outLoc ) {
114122
# Output file is a device or a regular file, so don't use split
115123
#
116124
$cmd .= ">> $outLocE";
117-
$mesg .= " to $outLocE";
125+
$mesg .= " to $outLoc";
118126
} else {
119127
mkpath($outLoc) if ( !-d $outLoc );
120128
if ( !-d $outLoc ) {
@@ -146,7 +154,7 @@ if ( $ret ) {
146154
# ie: not a tape device).
147155
#
148156
if ( -d $outLoc && -x $parPath ) {
149-
if ( $parfile != 0 ) {
157+
if ( length($parfile) ) {
150158
print("Running $parPath to create parity files\n");
151159
my $parCmd = "$parPath c -r$parfile $outLocE/$host.$bkupNum.tar$fileExt.par2 $outLocE/$host.$bkupNum.tar$fileExt*";
152160
$ret = system($parCmd);

conf/config.pl

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,12 @@
717717
# Users report that for smbclient you should specify a directory
718718
# followed by "/*", eg: "/proc/*", instead of just "/proc".
719719
#
720+
# FTP servers are traversed recursively so excluding directories will
721+
# also exclude its contents. You can use the wildcard characters "*"
722+
# and "?" to define files for inclusion and exclusion. Both
723+
# attributes $Conf{BackupFilesOnly} and $Conf{BackupFilesExclude} can
724+
# be defined for the same share.
725+
#
720726
# If a hash is used, a special key "*" means it applies to all
721727
# shares that don't have a specific entry.
722728
#
@@ -1384,12 +1390,33 @@
13841390
# (can be overwritten in the per-PC log file)
13851391
##########################################################################
13861392
#
1387-
# Name of the host share that is backed up when using FTP. This can be a
1393+
# Which host directories to backup when using FTP. This can be a
13881394
# string or an array of strings if there are multiple shares per host.
1389-
# Examples:
13901395
#
1391-
# $Conf{FtpShareName} = 'c'; # backup 'c' share
1392-
# $Conf{FtpShareName} = ['c', 'd']; # backup 'c' and 'd' shares
1396+
# This value must be specified in one of two ways: either as a
1397+
# subdirectory of the 'share root' on the server, or as the absolute
1398+
# path of the directory.
1399+
#
1400+
# In the following example, if the directory /home/username is the
1401+
# root share of the ftp server with the given username, the following
1402+
# two values will back up the same directory:
1403+
#
1404+
# $Conf{FtpShareName} = 'www'; # www directory
1405+
# $Conf{FtpShareName} = '/home/username/www'; # same directory
1406+
#
1407+
# Path resolution is not supported; i.e.; you may not have an ftp
1408+
# share path defined as '../otheruser' or '~/games'.
1409+
#
1410+
# Multiple shares may also be specified, as with other protocols:
1411+
#
1412+
# $Conf{FtpShareName} = [ 'www',
1413+
# 'bin',
1414+
# 'config' ];
1415+
#
1416+
# Note also that you can also use $Conf{BackupFilesOnly} to specify
1417+
# a specific list of directories to backup. It's more efficient to
1418+
# use this option instead of $Conf{FtpShareName} since a new tar is
1419+
# run for each entry in $Conf{FtpShareName}.
13931420
#
13941421
# This setting only matters if $Conf{XferMethod} = 'ftp'.
13951422
#

configure.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@
266266
foreach my $prog ( sort(keys(%Programs)) ) {
267267
my $path;
268268
foreach my $subProg ( split(/\//, $prog) ) {
269-
$path = FindProgram("$ENV{PATH}:/bin:/usr/bin:/sbin:/usr/sbin",
269+
$path = FindProgram("$ENV{PATH}:/usr/bin:/bin:/sbin:/usr/sbin",
270270
$subProg) if ( !length($path) );
271271
}
272272
$Conf{$Programs{$prog}} = $path if ( !length($Conf{$Programs{$prog}}) );

lib/BackupPC/Xfer/Ftp.pm

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ sub start
168168
# Convert the encoding type of the names if at all possible
169169
#
170170
from_to( $args->{shareName}, "utf8", $conf->{ClientCharset} )
171-
if ( $conf->{ClientCharset} ne "" );
171+
if ( $conf->{ClientCharset} ne "" );
172172

173173
#
174174
# Collect FTP configuration arguments and translate them for
@@ -187,7 +187,7 @@ sub start
187187
: Net::FTP->new(%$args);
188188
};
189189
if ($@) {
190-
$t->{_errStr} = "Can't open connection to $args->{Host}: $!";
190+
$t->{_errStr} = "Can't open connection to $args->{host}: $!";
191191
$t->{xferErrCnt}++;
192192
return;
193193
}
@@ -198,7 +198,7 @@ sub start
198198
undef $@;
199199
eval { $t->{ftp}->login( $conf->{FtpUserName}, $conf->{FtpPasswd} ); };
200200
if ( $@ ) {
201-
$t->{_errStr} = "Can't login to $args->{Host}: $!";
201+
$t->{_errStr} = "Can't login to $args->{host}: $!";
202202
$t->{xferErrCnt}++;
203203
return;
204204
}
@@ -207,7 +207,7 @@ sub start
207207
eval { $t->{ftp}->binary(); };
208208
if ($@) {
209209
$t->{_errStr} =
210-
"Can't enable binary transfer mode to $args->{Host}: $!";
210+
"Can't enable binary transfer mode to $args->{host}: $!";
211211
$t->{xferErrCnt}++;
212212
return;
213213
}
@@ -234,36 +234,38 @@ sub start
234234
# log the beginning of action based on type
235235
#
236236
if ( $t->{type} eq 'restore' ) {
237-
$logMsg = "restore started on directory $t->{shareName}";
237+
$logMsg = "ftp restore for host $t->{host} started on directory "
238+
. "$t->{shareName}\n";
238239

239240
} elsif ( $t->{type} eq 'full' ) {
240-
$logMsg = "full backup started on directory $t->{shareName}";
241+
$logMsg = "ftp full backup for host $t->{host} started on directory "
242+
. "$t->{shareName}\n";
241243

242244
} elsif ( $t->{type} eq 'incr' ) {
243-
244245
$incrDate = $bpc->timeStamp( $t->{incrBaseTime} - 3600, 1 );
245-
$logMsg = "incremental backup started back to $incrDate" .
246-
" (backup #$t->{incrBaseBkupNum}) for directory" . "
247-
$t->{shareName}";
246+
$logMsg = "ftp incremental backup for $t->{host} started back to "
247+
. "$incrDate (backup #$t->{incrBaseBkupNum}) for directory "
248+
. "$t->{shareName}\n";
248249
}
250+
$t->logWrite($logMsg, 1);
249251

250252
#
251253
# call the recursive function based on the type of action
252254
#
253255
if ( $t->{type} eq 'restore' ) {
254256

255257
$t->restore();
256-
$logMsg = "Restore of $args->{Host} complete";
258+
$logMsg = "Restore of $t->{host} complete";
257259

258260
} elsif ( $t->{type} eq 'incr' ) {
259261

260262
$t->backup();
261-
$logMsg = "Incremental backup of $args->{Host} complete";
263+
$logMsg = "Incremental backup of $t->{host} complete";
262264

263265
} elsif ( $t->{type} eq 'full' ) {
264266

265267
$t->backup();
266-
$logMsg = "Full backup of $args->{Host} complete";
268+
$logMsg = "Full backup of $t->{host} complete";
267269
}
268270

269271
delete $t->{_errStr};
@@ -297,8 +299,8 @@ sub run
297299
return ( $t->{fileCnt}, $t->{byteCnt}, 0, 0 );
298300

299301
} else {
300-
return \( $tarErrs, $nFilesExist, $sizeExist,
301-
$sizeExistCom, $nFilesTotal, $sizeTotal );
302+
return ( $tarErrs, $nFilesExist, $sizeExist,
303+
$sizeExistCom, $nFilesTotal, $sizeTotal );
302304
}
303305
}
304306

@@ -587,7 +589,8 @@ sub remotels
587589
};
588590

589591
$f->{utf8name} = $f->{name};
590-
from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" );
592+
from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" )
593+
if ( $conf->{ClientCharset} ne "" );
591594

592595
$f->{fullName} = "$t->{sharePath}/$path/$f->{name}";
593596
$f->{fullName} =~ s/\/+/\//g;
@@ -709,7 +712,8 @@ sub handleSymFile
709712
};
710713

711714
$f->{utf8name} = $fSym->{name};
712-
from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" );
715+
from_to( $f->{utf8name}, $conf->{ClientCharset}, "utf8" )
716+
if ( $conf->{ClientCharset} ne "" );
713717

714718
$f->{relPath} = $fSym->{relPath};
715719
$f->{fullName} = "$t->{shareName}/$fSym->{relPath}/$fSym->{name}";
@@ -755,7 +759,7 @@ sub handleDir
755759
}
756760
}
757761

758-
$attrib = BackupPC::Attrib->new( { compress => $t->{Compress} } );
762+
$attrib = BackupPC::Attrib->new( { compress => $t->{compress} } );
759763
$remoteDir = $t->remotels( $dir->{relPath} );
760764

761765
if ( $t->{type} eq "incr" ) {
@@ -828,7 +832,7 @@ sub handleDir
828832
my $data = $attrib->writeData();
829833

830834
$poolWrite = BackupPC::PoolWrite->new( $bpc, $fileName, length($data),
831-
$t->{Compress} );
835+
$t->{compress} );
832836
$poolWrite->write( \$data );
833837
( $exists, $digest, $outSize, $errs ) = $poolWrite->close();
834838

@@ -867,13 +871,12 @@ sub handleFile
867871
}
868872

869873
my $attribInfo = {
870-
type => BPC_FTYPE_FILE,
871-
mode => $f->{mode},
872-
uid => undef, # unsupported
873-
gid => undef, # unsupported
874-
size => $f->{size},
875-
mtime => $f->{mtime},
876-
};
874+
%$f,
875+
type => BPC_FTYPE_FILE,
876+
uid => undef, # unsupported
877+
gid => undef, # unsupported
878+
};
879+
delete $attribInfo->{utf8name}; # unused value
877880

878881
#
879882
# If this is a full backup or the file has changed on the host,
@@ -882,15 +885,15 @@ sub handleFile
882885
undef $@;
883886
eval { tie ( *FTP, 'Net::FTP::RetrHandle', $ftp, $f->{fullName} ); };
884887
if ( !*FTP || $@ ) {
885-
$t->handleFileAction( "fail", $attribInfo );
888+
$t->logFileAction( "fail", $f->{utf8name}, $attribInfo );
886889
$t->{xferBadFileCnt}++;
887890
$stats->{errCnt}++;
888891
return;
889892
}
890893

891-
$poolFile = $OutDir . "/" . $bpc->fileNameMangle( $f->{name} );
892-
$poolWrite = BackupPC::PoolWrite->new( $bpc, $poolFile, $f->{size},
893-
$bpc->{xfer}{compress} );
894+
$poolFile = $OutDir . "/" . $bpc->fileNameMangle( $f->{name} );
895+
$poolWrite = BackupPC::PoolWrite->new( $bpc, $poolFile, $f->{size},
896+
$t->{compress} );
894897

895898
$localSize = 0;
896899

@@ -916,7 +919,7 @@ sub handleFile
916919
#
917920
if ( $localSize != $f->{size} ) {
918921
$t->logFileAction( "fail", $f->{utf8name}, $attribInfo );
919-
unklink($poolFile);
922+
unlink($poolFile);
920923
$stats->{xferBadFileCnt}++;
921924
$stats->{errCnt}++;
922925
return;
@@ -928,7 +931,12 @@ sub handleFile
928931
$attrib->set( $f->{utf8name}, $attribInfo );
929932
$t->logFileAction( $exists ? "pool" : "create",
930933
$f->{utf8name}, $attribInfo );
931-
print $newFilesFH "$digest $f->{size} $poolFile\n" unless $exists;
934+
935+
my $relPoolFile = $bpc->fileNameEltMangle( $t->{shareName} )
936+
. "/"
937+
. $bpc->fileNameMangle($attribInfo->{relPath});
938+
939+
print $newFilesFH "$digest $f->{size} $relPoolFile\n" unless $exists;
932940

933941
#
934942
# Cumulate the stats
@@ -955,12 +963,13 @@ sub incrFileExistCheck
955963
my $view = $t->{view};
956964

957965
my $oldAttribInfo = $view->fileAttrib( $t->{incrBaseBkupNum},
958-
$t->{shareName}, $f->{relPath} );
966+
$t->{shareName}, "/" . $f->{relPath} );
959967

960-
#print STDERR "*" x 50 . "\n";
961-
#print STDERR "Old data:\n" . Dumper($oldAttribInfo);
962-
#print STDERR "New data:\n" . Dumper($f);
963-
#print STDERR "$f->{fullName}: $oldAttribInfo->{mtime} ?= $f->{mtime}, $oldAttribInfo->{size} ?= $f->{size}\n";
968+
##$t->logWrite( "Old attrib:\n" . Dumper($oldAttribInfo), 1 );
969+
##$t->logWrite( "New attrib:\n" . Dumper($f), 1 );
970+
##$t->logWrite( sprintf("%s: mtime %d vs %d, size %d vs %d\n", $f->{fullName},
971+
## $oldAttribInfo->{mtime}, $f->{mtime},
972+
## $oldAttribInfo->{size}, $f->{size}), 1);
964973

965974
return ( $oldAttribInfo->{mtime} == $f->{mtime}
966975
&& $oldAttribInfo->{size} == $f->{size} );
@@ -983,9 +992,11 @@ sub logFileAction
983992
$name = "." if ( $name eq "" );
984993
$owner = "-/-" if ( $owner eq "/" );
985994

986-
my $fileAction = sprintf( " %-6s %1s%4o %9s %11.0f %s\n",
987-
$action, $type, $attrib->{mode} & 07777,
988-
$owner, $attrib->{size}, $name );
995+
my $fileAction = sprintf(
996+
" %-6s %1s%4o %9s %11.0f %s\n",
997+
$action, $type, $attrib->{mode} & 07777,
998+
$owner, $attrib->{size}, $attrib->{relPath}
999+
);
9891000

9901001
return $t->logWrite( $fileAction, 1 );
9911002
}

0 commit comments

Comments
 (0)