Use File::Spec for symlink operations
authorJacob Bachmeyer <jcb@gnu.org>
Sat, 5 Nov 2022 04:05:40 +0000 (23:05 -0500)
committerJacob Bachmeyer <jcb@gnu.org>
Sat, 5 Nov 2022 04:05:40 +0000 (23:05 -0500)
gatekeeper.pl

index e3bc84199a67aee9435c3febd03e9290edffc088..0a0672b725c49d9171cc498b34724a350dd83d07 100755 (executable)
@@ -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')