autowrapper

master
joey 2006-03-10 09:02:09 +00:00
parent 65e3686ead
commit 9ab1c273f6
3 changed files with 91 additions and 25 deletions

View File

@ -1,5 +1,5 @@
all:
./ikiwiki doc html --wikiname="ikiwiki" --verbose
./ikiwiki doc html --wikiname="ikiwiki" --verbose --offline
clean:
rm -rf html

View File

@ -1,3 +1,5 @@
Let's do an ikiwiki security analysis..
If you are using ikiwiki to render pages that only you can edit, then there
are no more security issues with this program than with cat(1). If,
however, you let others edit pages in your wiki, then some security issues
@ -37,3 +39,14 @@ hopefully your web server will not run it.
If your web server does any parsing of special sorts of files (for example,
server parsed html files), then if you let anyone else add files to the wiki,
they can try to use this to exploit your web server.
## --gen-wrapper might generate insecure wrappers
ikiwiki --gen-wrapper is instended to generate a wrapper program that
runs ikiwiki to update a given wiki. The wrapper can in turn be made suid,
for example to be used in a [[post-commit]] hook by people who cannot write
to the html pages, etc.
If the wrapper script is made suid, then any bugs in this wrapper would be
security holes. The wrapper is written as securely as I know how and
there's been no problems yet.

101
ikiwiki
View File

@ -6,40 +6,23 @@ use File::Find;
use Memoize;
use File::Spec;
$ENV{PATH}="/usr/local/bin:/usr/bin:/bin";
BEGIN {
$blosxom::version="is a proper perl module too much to ask?";
do "/usr/bin/markdown";
}
memoize('pagename');
memoize('bestlink');
my ($srcdir, $destdir, %links, %oldlinks, %oldpagemtime, %renderedfiles,
%pagesources);
my $link=qr/\[\[([^\s]+)\]\]/;
my $verbose=0;
my $wikiname="wiki";
sub usage {
die "usage: ikiwiki [options] source dest\n";
}
my $link=qr/\[\[([^\s]+)\]\]/;
my $verbose=0;
my $rebuild=0;
my $wikiname="wiki";
if (grep /^-/, @ARGV) {
eval {use Getopt::Long};
GetOptions(
"wikiname=s" => \$wikiname,
"verbose|v" => \$verbose,
"rebuild" => \$rebuild,
) || usage();
}
usage() unless @ARGV == 2;
my ($srcdir) = shift =~ /(.*)/; # untaint
my ($destdir) = shift =~ /(.*)/; # untaint
my %links;
my %oldlinks;
my %oldpagemtime;
my %renderedfiles;
my %pagesources;
sub error ($) {
die @_;
}
@ -454,6 +437,76 @@ FILE: foreach my $file (@files) {
}
}
# Generates a C wrapper program for running ikiwiki in a specific way.
# The wrapper may be safely made suid.
sub gen_wrapper ($$) {
my ($offline, $rebuild)=@_;
eval {use Cwd 'abs_path'};
$srcdir=abs_path($srcdir);
$destdir=abs_path($destdir);
my $this=abs_path($0);
if (! -x $this) {
error("$this doesn't seem to be executable");
}
my $call=qq{"$this", "$this", "$srcdir", "$destdir", "--wikiname=$wikiname"};
$call.=', "--verbose"' if $verbose;
$call.=', "--rebuild"' if $rebuild;
$call.=', "--offline"' if $offline;
open(OUT, ">ikiwiki-wrap.c") || error("failed to write ikiwiki-wrap.c: $!");;
print OUT <<"EOF";
/* A suid wraper for ikiwiki */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main (void) {
unsetenv("PERLIO_DEBUG"); /* CAN-2005-0155 */
execl($call, NULL);
perror("failed to run $this");
exit(1);
}
EOF
close OUT;
if (system("gcc", "ikiwiki-wrap.c", "-o", "ikiwiki-wrap") != 0) {
error("failed to compile ikiwiki-wrap.c");
}
unlink("ikiwiki-wrap.c");
print "successfully generated ikiwiki-wrap\n";
exit 0;
}
sub update () {
if (-d "$srcdir/.svn") {
if (system("svn", "update", "--quiet", $srcdir) != 0) {
warn("svn update failed\n");
}
}
}
my $rebuild=0;
my $offline=0;
my $gen_wrapper=0;
if (grep /^-/, @ARGV) {
eval {use Getopt::Long};
GetOptions(
"wikiname=s" => \$wikiname,
"verbose|v" => \$verbose,
"rebuild" => \$rebuild,
"gen-wrapper" => \$gen_wrapper,
"offline" => \$offline,
) || usage();
}
usage() unless @ARGV == 2;
($srcdir) = shift =~ /(.*)/; # untaint
($destdir) = shift =~ /(.*)/; # untaint
gen_wrapper($offline, $rebuild) if $gen_wrapper;
memoize('pagename');
memoize('bestlink');
update() unless $offline;
loadindex() unless $rebuild;
refresh();
saveindex();