summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--doc/security.mdwn13
-rwxr-xr-xikiwiki101
3 files changed, 91 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index b235d6bda..3a39c957c 100644
--- 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
diff --git a/doc/security.mdwn b/doc/security.mdwn
index 575ccbad8..e7936b5a0 100644
--- a/doc/security.mdwn
+++ b/doc/security.mdwn
@@ -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 72b1021ec..65934edd1 100755
--- 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();