mirror of https://github.com/digint/btrbk
btrbk: generic input validation of command arguments
parent
056f6f9120
commit
372ec90685
57
btrbk
57
btrbk
|
@ -87,6 +87,8 @@ my $loglevel = 1;
|
||||||
my $ip_addr_match = qr/(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/;
|
my $ip_addr_match = qr/(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/;
|
||||||
my $host_name_match = qr/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])/;
|
my $host_name_match = qr/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])/;
|
||||||
my $file_match = qr/[0-9a-zA-Z_\-\.\/]+/;
|
my $file_match = qr/[0-9a-zA-Z_\-\.\/]+/;
|
||||||
|
my $ssh_prefix_match = qr/ssh:\/\/($ip_addr_match|$host_name_match)/;
|
||||||
|
|
||||||
|
|
||||||
$SIG{__DIE__} = sub {
|
$SIG{__DIE__} = sub {
|
||||||
print STDERR "\nERROR: process died unexpectedly (btrbk v$VERSION)";
|
print STDERR "\nERROR: process died unexpectedly (btrbk v$VERSION)";
|
||||||
|
@ -213,7 +215,7 @@ sub check_file($$$$)
|
||||||
my $config_file = shift; # only for error text
|
my $config_file = shift; # only for error text
|
||||||
|
|
||||||
if($accept->{ssh} && ($file =~ /^ssh:\/\//)) {
|
if($accept->{ssh} && ($file =~ /^ssh:\/\//)) {
|
||||||
unless($file =~ /^ssh:\/\/($ip_addr_match|$host_name_match)\/$file_match$/) {
|
unless($file =~ /^$ssh_prefix_match\/$file_match$/) {
|
||||||
ERROR "Ambiguous ssh url for option \"$key\" in \"$config_file\" line $.: $file";
|
ERROR "Ambiguous ssh url for option \"$key\" in \"$config_file\" line $.: $file";
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
@ -971,6 +973,8 @@ MAIN:
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($action_run, $action_info, $action_tree, $action_diff, $action_origin);
|
my ($action_run, $action_info, $action_tree, $action_diff, $action_origin);
|
||||||
|
my @subvol_args;
|
||||||
|
my $args_expected = 0;
|
||||||
if(($command eq "run") || ($command eq "dryrun")) {
|
if(($command eq "run") || ($command eq "dryrun")) {
|
||||||
$action_run = 1;
|
$action_run = 1;
|
||||||
$dryrun = 1 if($command eq "dryrun");
|
$dryrun = 1 if($command eq "dryrun");
|
||||||
|
@ -983,15 +987,36 @@ MAIN:
|
||||||
}
|
}
|
||||||
elsif ($command eq "diff") {
|
elsif ($command eq "diff") {
|
||||||
$action_diff = 1;
|
$action_diff = 1;
|
||||||
|
$args_expected = 2;
|
||||||
|
@subvol_args = @ARGV;
|
||||||
}
|
}
|
||||||
elsif ($command eq "origin") {
|
elsif ($command eq "origin") {
|
||||||
$action_origin = 1;
|
$action_origin = 1;
|
||||||
|
$args_expected = 1;
|
||||||
|
@subvol_args = @ARGV;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ERROR "Unrecognized command: $command";
|
ERROR "Unrecognized command: $command";
|
||||||
HELP_MESSAGE(0);
|
HELP_MESSAGE(0);
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
if($args_expected != scalar(@ARGV)) {
|
||||||
|
ERROR "Incorrect number of arguments";
|
||||||
|
HELP_MESSAGE(0);
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# input validation
|
||||||
|
foreach (@subvol_args) {
|
||||||
|
s/\/+$//; # remove trailing slash
|
||||||
|
unless(/^(($ssh_prefix_match)?\/$file_match)$/) { # matches ssh statement or absolute file
|
||||||
|
ERROR "Bad argument: not a subvolume declaration: $_";
|
||||||
|
HELP_MESSAGE(0);
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
$_ = $1; # untaint argument
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
INFO "$version_info (" . localtime($start_time) . ")";
|
INFO "$version_info (" . localtime($start_time) . ")";
|
||||||
|
|
||||||
|
@ -1000,24 +1025,9 @@ MAIN:
|
||||||
#
|
#
|
||||||
# print snapshot diff
|
# print snapshot diff
|
||||||
#
|
#
|
||||||
my $src_vol = shift @ARGV;
|
my $src_vol = $subvol_args[0] || die;
|
||||||
my $target_vol = shift @ARGV;
|
my $target_vol = $subvol_args[1] || die;
|
||||||
unless($src_vol && $target_vol) {
|
# FIXME: allow ssh:// src/dest (does not work since the configuration is not yet read).
|
||||||
ERROR "Missing subvolume argument for \"diff\" command";
|
|
||||||
HELP_MESSAGE(0);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
# untaint arguments
|
|
||||||
unless($src_vol =~ /^($file_match)$/) {
|
|
||||||
ERROR "bad argument: not a file: $src_vol";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
$src_vol = $1;
|
|
||||||
unless($target_vol =~ /^($file_match)$/) {
|
|
||||||
ERROR "bad argument: not a file: $target_vol";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
$target_vol = $1;
|
|
||||||
|
|
||||||
my $src_detail = btr_subvolume_detail($src_vol);
|
my $src_detail = btr_subvolume_detail($src_vol);
|
||||||
unless($src_detail) { exit 1; }
|
unless($src_detail) { exit 1; }
|
||||||
|
@ -1207,14 +1217,9 @@ MAIN:
|
||||||
#
|
#
|
||||||
# print origin information
|
# print origin information
|
||||||
#
|
#
|
||||||
my $subvol = shift @ARGV;
|
my $subvol = $subvol_args[0] || die;
|
||||||
my $dump_uuid = 0;
|
my $dump_uuid = 0;
|
||||||
unless($subvol) {
|
|
||||||
ERROR "Missing subvolume argument for \"origin\" command";
|
|
||||||
HELP_MESSAGE(0);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
$subvol =~ s/\/+$//; # remove trailing slash
|
|
||||||
my $uuid;
|
my $uuid;
|
||||||
foreach(values %uuid_info) {
|
foreach(values %uuid_info) {
|
||||||
if($_->{FS_PATH} eq $subvol) {
|
if($_->{FS_PATH} eq $subvol) {
|
||||||
|
|
Loading…
Reference in New Issue