Xref: feenix.metronet.com comp.unix.questions:10239 comp.unix.admin:5249 comp.unix.shell:3972
Newsgroups: comp.unix.questions,comp.unix.admin,comp.unix.shell
Path: feenix.metronet.com!news.utdallas.edu!wupost!howland.reston.ans.net!agate!boulder!wraeththu.cs.colorado.edu!tchrist
From: Tom Christiansen <[email protected]>
Subject: Re: rvi - restricted vi??
Message-ID: <[email protected]>
Originator: [email protected]
Sender: [email protected] (The Daily Planet)
Nntp-Posting-Host: wraeththu.cs.colorado.edu
Reply-To: [email protected] (Tom Christiansen)
Organization: University of Colorado, Boulder
References: <[email protected]>
Date: Wed, 1 Sep 1993 15:55:12 GMT
Lines: 120

From the keyboard of [email protected] (Cindy Wang):
:I know someone who is setting up restricted shell.  He'd like
:to have vi in /usr/rbin but couldn't because of the :!shell feature
:in vi.  Is there a rvi -- restricted vi somewhere?

I've used this, which is a wrapper around any editor.

--tom

#!/usr/bin/perl
#
# seced  -- secure editor wrapper
# Tom Christiansen <[email protected]>
# based on an idea by Ray Davis <[email protected]>
#
# install suid root or with a suid wrapper

%ok = ( '/usr/ucb/vi',          1,
       '/usr/ucb/ex',          1,
       '/bin/ed',              1,
       '/usr/local/bin/emacs', 1,
     );

$tmpdir = "/tmp/seced.$$";

die "$0: Not superuser\n" if $>;
die "usage: $0 file ...\n" if $#ARGV < 0;

chop($cwd = `pwd`);

mkdir($tmpdir,0700) || die "can't mkdir $tmpdir: $!";
chdir($tmpdir)      || die "can't chdir $tmpdir: $!";
mkdir('tmp',  0777) || die "can't mkdir $tmpdir/tmp: $!";

&cp_editor;
&cp_files;

if ($kid = fork) {
   die "cannot fork: $!"       if $kid == -1;
   $pid = wait until $pid == $kid || $pid == -1;
   die "wait: no kids"         if $pid == -1;
   warn "$0: edit failed with status " . ($? >> 8) . "\n"
       if $?;
} else {
   chroot($tmpdir) || die "can't chroot $tmpdir: $!";
   exec($editor, @ARGV);
   # NOT REACHED
}

&replace_files unless $?;

chdir('/')         || die "absurd failure to chdir to /: $!";

exec('/bin/rm', '-rf', $tmpdir);

# NOT REACHED

sub cp_editor {
   $editor =  $ENV{'SECED'}
           || $ENV{'VISUAL'}
           || $ENV{'EDITOR'}
           || '/usr/ucb/vi';

   die "$0: need full path for \$EDITOR: $editor\n"
       unless $editor =~ m#^/#;

   die "$0: illegal \$EDITOR: $editor\n"
       unless defined $ok{$editor};

   system('/bin/cp', $editor, '.')
       && die "$0: couldn't cp editor\n";

   if ($editor eq '/usr/ucb/vi' || $editor eq '/usr/ucb/ex') {
       $home = $ENV{'HOME'} || '/';
       $startup = "$home/.exrc";
       if (-e $startup && -O _) {
           system('/bin/cp', $startup, '.')
               && die "$0: couldn't cp $startup\n";
           chown($<, -1, '.exrc');
       }
   }

   $editor =~ s#.*(/[^/]+)$#.$1#;
}

sub cp_files {
   @files = grep(/^[^-]/, @ARGV);
   grep(s#^[^/]#$cwd/$&#, @files);

   die "no files to edit" if $#files < 0;

   system('/bin/cp', @files, '.')
       && die "couldn't cp files";

   chown($<, -1, <*>)
       || die "couldn't chown files to uid $<";

   for (@files) {
       ($local = $_) =~ s#.*/##;
       unless (-T) {
           warn "$0: WARNING: $_ not a text file\n";
           sleep(1);
       }
       $mtime{$_} = (stat($local))[9];
   }
}

sub replace_files {
   for (@files) {
       ($local = $_) =~ s#.*/##;
       if ((stat($local))[9] == $mtime{$_}) {
           warn "$0: $_ unmodified\n";
           next;
       }
       system('/bin/cp', $local, $_)
           && die "$0: can't cp $local $_\n";
   }
}
--
   Tom Christiansen      [email protected]       303-444-3212