use the validate_proxy_params() helper everywhere we need to read/split/validate jumphost proxy info

pull/592/head
Stéphane Lesimple 5 days ago
parent 61032fb5f5
commit 7c5444fa92
No known key found for this signature in database
GPG Key ID: 4B4A3289E9D35658

@ -312,36 +312,16 @@ my $fnret;
my $proxyIp = undef;
my $proxyPort = 22;
my $proxyUser = undef;
# Parse proxyjump args if specified
# Parse and validate the proxyjump spec if specified. The "-J [user@]host[:port]" grammar and its
# validation live in OVH::Bastion::validate_proxy_params() (shared with osh.pl and the ACL plugins);
# any error (bad spec, DNS/IP-version disabled, host not found, invalid user) is propagated as-is.
if ($proxyJump) {
if ($proxyJump =~ /^(?:([a-zA-Z0-9._@!-]{1,128})@)?(\[?[a-zA-Z0-9._-]+\]?)(?::(\d+))?$/) {
$proxyUser = $1 if $1;
$proxyIp = $2;
$proxyPort = $3 if $3;
osh_debug("parsed proxyjump: host=$proxyIp port=$proxyPort user=$proxyUser");
}
else {
osh_exit 'ERR_INVALID_PARAMETER', "Invalid proxyjump specification '$proxyJump', should be [user@]host[:port]";
}
$fnret = OVH::Bastion::get_ip(host => $proxyIp, allowSubnets => 0);
if (!$fnret) {
if ($fnret->err eq 'ERR_DNS_DISABLED') {
osh_exit 'ERR_DNS_DISABLED', $fnret->msg;
}
elsif ($fnret->err eq 'ERR_IP_VERSION_DISABLED') {
osh_exit 'ERR_IP_VERSION_DISABLED', $fnret->msg;
}
else {
osh_exit 'ERR_HOST_NOT_FOUND', $fnret->msg;
}
}
$proxyIp = $fnret->value->{'ip'};
osh_debug("Proxyjump host resolved to IP: $proxyIp");
if ($proxyUser && !OVH::Bastion::is_valid_remote_user(user => $proxyUser, allowWildcards => 0)) {
osh_exit 'EXIT_INVALID_REMOTE_USER', 'invalid_proxy_user', "Proxy user name '$proxyUser' seems invalid";
}
$fnret = OVH::Bastion::validate_proxy_params(proxyJump => $proxyJump, allowWildcards => 0);
$fnret or osh_exit($fnret);
$proxyIp = $fnret->value->{'proxyIp'};
$proxyPort = $fnret->value->{'proxyPort'} // 22;
$proxyUser = $fnret->value->{'proxyUser'};
osh_debug("parsed proxyjump: host=$proxyIp port=$proxyPort user=$proxyUser");
}
if (not $host) {

@ -654,40 +654,33 @@ else {
my $proxyIp = undef;
my $proxyPort = undef;
my $proxyUser = $user; # user might be undef. We'll handle that later
# Parse proxyjump args if specified
# Parse and validate the proxyjump spec if specified. The "-J [user@]host[:port]" grammar and its
# validation live in OVH::Bastion::validate_proxy_params() (shared with the scp plugin and the ACL
# plugins); here we just map the library error to the matching osh.pl exit code.
if ($proxyJump) {
if ($proxyJump =~ /^(?:([a-zA-Z0-9._@!-]{1,128})@)?(\[?[a-zA-Z0-9._-]+\]?)(?::(\d+))?$/) {
$proxyUser = $1 if $1;
$proxyIp = $2;
$proxyPort = $3 ? $3 : 22;
osh_debug("parsed proxyjump: host=$proxyIp port=$proxyPort user=$proxyUser");
}
else {
main_exit OVH::Bastion::EXIT_INVALID_PROXYJUMP, 'invalid_proxyjump',
"Invalid proxyjump specification '$proxyJump', should be [user@]host[:port]";
}
$fnret = OVH::Bastion::get_ip(host => $proxyIp, allowSubnets => 0);
$fnret = OVH::Bastion::validate_proxy_params(proxyJump => $proxyJump, allowWildcards => 0);
if (!$fnret) {
if ($fnret->err eq 'ERR_DNS_DISABLED') {
my $err = $fnret->err;
if ($err eq 'ERR_INVALID_PROXYJUMP') {
main_exit OVH::Bastion::EXIT_INVALID_PROXYJUMP, 'invalid_proxyjump', $fnret->msg;
}
elsif ($err eq 'ERR_DNS_DISABLED') {
main_exit OVH::Bastion::EXIT_DNS_DISABLED, 'dns_disabled', $fnret->msg;
}
elsif ($fnret->err eq 'ERR_IP_VERSION_DISABLED') {
elsif ($err eq 'ERR_IP_VERSION_DISABLED') {
main_exit OVH::Bastion::EXIT_IP_VERSION_DISABLED, 'ip_version_disabled', $fnret->msg;
}
elsif ($err eq 'ERR_INVALID_PARAMETER') {
main_exit OVH::Bastion::EXIT_INVALID_REMOTE_USER, 'invalid_proxy_user', $fnret->msg;
}
else {
main_exit OVH::Bastion::EXIT_HOST_NOT_FOUND, 'host_not_found', $fnret->msg;
}
}
osh_debug("Proxyjump host $proxyIp resolved to IP " . $fnret->value->{'ip'});
$proxyIp = $fnret->value->{'ip'};
if ($proxyUser && !OVH::Bastion::is_valid_remote_user(user => $proxyUser, allowWildcards => 0)) {
main_exit OVH::Bastion::EXIT_INVALID_REMOTE_USER, 'invalid_proxy_user',
"Proxy user name '$proxyUser' seems invalid";
}
$ENV{'OSH_PROXYJUMP_CONNECTION'} = 1;
$proxyIp = $fnret->value->{'proxyIp'};
$proxyPort = $fnret->value->{'proxyPort'} // 22;
$proxyUser = $fnret->value->{'proxyUser'} if $fnret->value->{'proxyUser'};
osh_debug("parsed proxyjump: host=$proxyIp port=$proxyPort user=$proxyUser");
}
# for plugins (osh_command), do a first check with allowWildcards, it'll be re-done in Plugin::start with

@ -765,11 +765,29 @@ sub is_valid_remote_user {
sub validate_proxy_params {
my %params = @_;
my $proxyJump = $params{'proxyJump'}; # optional "[user@]host[:port]" spec, parsed below
my $proxyHost = $params{'proxyHost'};
my $proxyPort = $params{'proxyPort'};
my $proxyUser = $params{'proxyUser'};
my $allowWildcards = $params{'allowWildcards'} // 1;
# if we were given a combined proxy-jump spec (the "-J [user@]host[:port]" form used by osh.pl and the
# scp plugin), split it into its host/port/user components here, so the spec grammar lives in exactly
# one place. Callers that already have the components separately (e.g. --proxy-host/--proxy-port/
# --proxy-user) simply don't pass proxyJump; the validation below is shared between both forms.
if (defined $proxyJump && $proxyJump ne '') {
if ($proxyJump =~ /^(?:([a-zA-Z0-9._@!-]{1,128})@)?(\[[0-9a-fA-F:.]+\]|[a-zA-Z0-9._-]+)(?::(\d+))?$/) {
$proxyUser = $1 if $1;
$proxyHost = $2;
$proxyPort = $3 if $3;
$proxyHost =~ s/^\[(.+)\]$/$1/; # strip brackets around an IPv6 literal (e.g. [2001:db8::1])
}
else {
return R('ERR_INVALID_PROXYJUMP',
msg => "Invalid proxyjump specification '$proxyJump', should be [user\@]host[:port]");
}
}
my $proxyIp;
my $fnret;

@ -84,8 +84,15 @@ sub check {
);
}
# check proxy-host and proxy-port parameters
osh_debug("Checking proxy parameters: proxyIp='$proxyIp' proxyPort='$proxyPort' proxyUser='$proxyUser'");
# check proxy-host and proxy-port parameters (proxy* are usually undef: don't warn on interpolation)
osh_debug(
sprintf(
"Checking proxy parameters: proxyIp='%s' proxyPort='%s' proxyUser='%s'",
$proxyIp // '',
$proxyPort // '',
$proxyUser // ''
)
);
if ($proxyIp) {
if (!$proxyPort) {
return R('ERR_MISSING_PARAMETER', msg => "When --proxy-host is specified, --proxy-port becomes mandatory");

Loading…
Cancel
Save