autowrapper
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 10 Mar 2006 09:02:09 +0000 (09:02 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 10 Mar 2006 09:02:09 +0000 (09:02 +0000)
Makefile
doc/security.mdwn
ikiwiki

index b235d6bda0e0cbbdbf91bfdca5dc42da6d85963f..3a39c957ca46090d525ca5f4ae8e8b07767aeaa0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 all:
-       ./ikiwiki doc html --wikiname="ikiwiki" --verbose
+       ./ikiwiki doc html --wikiname="ikiwiki" --verbose --offline
 
 clean:
        rm -rf html
index 575ccbad8075ba32ab8b3590ada760f491d1aaa6..e7936b5a09475dd3f6fba83368394d98b3c4ecd4 100644 (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.
diff --git a/ikiwiki b/ikiwiki
index 72b1021eca97a323bc14724f98c29cab8d285b3e..65934edd1af0a0da450d7ab78bcbef6a7acbf247 100755 (executable)
--- a/ikiwiki
+++ b/ikiwiki
@@ -6,39 +6,22 @@ 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');
-
-sub usage {
-       die "usage: ikiwiki [options] source dest\n";
-}
-
+my ($srcdir, $destdir, %links, %oldlinks, %oldpagemtime, %renderedfiles,
+    %pagesources);
 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 usage {
+       die "usage: ikiwiki [options] source dest\n";
+}
 
 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();