summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--IkiWiki/CGI.pm2
-rw-r--r--IkiWiki/Render.pm6
-rw-r--r--doc/security.mdwn3
-rwxr-xr-xikiwiki17
4 files changed, 17 insertions, 11 deletions
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index b47c8e803..f360b6778 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -425,7 +425,7 @@ sub cgi_editpage ($$) { #{{{
my $content=$form->field('content');
$content=~s/\r\n/\n/g;
$content=~s/\r/\n/g;
- writefile("$config{srcdir}/$file", $content);
+ writefile($file, $config{srcdir}, $content);
my $message="web commit ";
if (length $session->param("name")) {
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 3d827d341..9e340c26e 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -349,7 +349,7 @@ sub render ($) { #{{{
$content=htmlize($type, $content);
check_overwrite("$config{destdir}/".htmlpage($page), $page);
- writefile("$config{destdir}/".htmlpage($page),
+ writefile(htmlpage($page), $config{destdir},
genpage($content, $page, mtime($srcfile)));
$oldpagemtime{$page}=time;
$renderedfiles{$page}=htmlpage($page);
@@ -358,14 +358,14 @@ sub render ($) { #{{{
# check_overwrite, as above, but currently renderedfiles
# only supports listing one file per page.
if ($config{rss} && exists $inlinepages{$page}) {
- writefile("$config{destdir}/".rsspage($page),
+ writefile(rsspage($page), $config{destdir},
genrss($content, $page, mtime($srcfile)));
}
}
else {
$links{$file}=[];
check_overwrite("$config{destdir}/$file", $file);
- writefile("$config{destdir}/$file", $content);
+ writefile($file, $config{destdir}, $content);
$oldpagemtime{$file}=time;
$renderedfiles{$file}=$file;
}
diff --git a/doc/security.mdwn b/doc/security.mdwn
index 0f8861d0d..3743adea1 100644
--- a/doc/security.mdwn
+++ b/doc/security.mdwn
@@ -161,7 +161,8 @@ page from the web, which follows the symlink when reading the page, and
again when saving the changed page.
This was fixed by making ikiwiki refuse to read or write to files that are
-symlinks, combined with the above locking.
+symlinks, or that are in subdirectories that are symlinks, combined with
+the above locking.
## underlaydir override attacks
diff --git a/ikiwiki b/ikiwiki
index 4ef6ceba3..b1bc9984f 100755
--- a/ikiwiki
+++ b/ikiwiki
@@ -202,15 +202,20 @@ sub readfile ($) { #{{{
return $ret;
} #}}}
-sub writefile ($$) { #{{{
- my $file=shift;
+sub writefile ($$$) { #{{{
+ my $file=shift; # can include subdirs
+ my $destdir=shift; # directory to put file in
my $content=shift;
- if (-l $file) {
- error("cannot write to a symlink ($file)");
+ my $test=$file;
+ while (length $test) {
+ if (-l "$destdir/$test") {
+ error("cannot write to a symlink ($test)");
+ }
+ $test=dirname($test);
}
- my $dir=dirname($file);
+ my $dir=dirname("$destdir/$file");
if (! -d $dir) {
my $d="";
foreach my $s (split(m!/+!, $dir)) {
@@ -221,7 +226,7 @@ sub writefile ($$) { #{{{
}
}
- open (OUT, ">$file") || error("failed to write $file: $!");
+ open (OUT, ">$destdir/$file") || error("failed to write $destdir/$file: $!");
print OUT $content;
close OUT;
} #}}}