From 0ab7ac8c6bb624273563741cfe4fd5fdf5231822 Mon Sep 17 00:00:00 2001 From: Jacob Bachmeyer Date: Fri, 4 Nov 2022 23:05:40 -0500 Subject: [PATCH] Use File::Spec for symlink operations --- gatekeeper.pl | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/gatekeeper.pl b/gatekeeper.pl index e3bc841..0a0672b 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -2441,6 +2441,7 @@ sub execute_commands { ftp_abort("invalid internal operation list") unless $oplist->[0][0] eq 'header'; my $header = $oplist->[0][1]; + my @directory = File::Spec::Unix->splitdir($header->{directory}); my $destdir = "$Public_dir/$header->{directory}"; foreach my $step (@{$oplist}[1..$#$oplist]) { # skip the header @@ -2450,38 +2451,27 @@ sub execute_commands { } elsif ($step->[0] eq 'symlink') { my $target = $step->[1]; my $linkname = $step->[2]; - # Get current working dir - my $cwd = getcwd; - # Make sure there are no double dots in the path, and that it is absolute. - # A bit paranoid, but hey... - fatal("invalid directory $cwd",1,'') - if (($cwd =~ /\.\./) || (!($cwd =~ m,^/,))); - # Now untaint the getcwd output - $cwd =~ /^(.*)$/; - $cwd = $1; - chomp($cwd); - # change to destination dir - chdir($destdir); + my $abslinkname = + File::Spec->catfile($Public_dir, @directory, $linkname); # if the symlink already exists, remove it - if (-l $linkname) { - unlink $linkname + if (-l $abslinkname) { + unlink $abslinkname or fatal("removal of symlink $linkname failed: $!",1); } # symlink away! - symlink $target, $linkname + symlink $target, $abslinkname or fatal("creation of symlink $linkname " - ."to $target in $destdir failed: $!",1); - # go back to current working dir - ftp_syslog('info', "added symlink $destdir/" - .$linkname . " pointing to $destdir/$target"); - chdir($cwd) - or fatal("chdir to $cwd failed: $!",1); + ."to $target in $header->{directory} failed: $!",1); + ftp_syslog('info', "added symlink $linkname pointing to " + ."$target in $header->{directory}"); } elsif ($step->[0] eq 'rmsymlink') { + my $abslinkname = + File::Spec->catfile($Public_dir, @directory, $step->[1]); fatal("refusing to remove a non-symlink file",1) - unless -l "$destdir/$step->[1]"; - unlink("$destdir/$step->[1]") + unless -l $abslinkname; + unlink $abslinkname or fatal("removal of symlink $step->[1] failed: $!",1); - ftp_syslog('info', "removed symlink $destdir/$step->[1]"); + ftp_syslog('info', "removed symlink $step->[1] in $header->{directory}"); } elsif ($step->[0] eq 'archive') { # We now also allow archiving entire directories archive($destdir, $header->{directory}, $step->[1].'.sig') -- 2.25.1