From e54bacdcac3ccad8fcb5d73db6e02e32bdd233b3 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Thu, 26 May 2022 01:12:51 +0100
Subject: [PATCH] page-edit: fix user page permissions check to also occur in
 the save action

---
 Changelog.md          |  1 +
 modules/page-edit.php | 27 +++++++++++++++++++--------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/Changelog.md b/Changelog.md
index bda1e8a..4f3dce9 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -23,6 +23,7 @@ This file holds the changelog for Pepperminty Wiki. This is the master list of t
  - [security] Ensured that the `returnto` GET parameter leads you only to another place on your Pepperminty Wiki instance (thanks, @JamieSlome)
  - [security] Ensure that Javascript in SVGs never gets executed (it's too challenging to strip it, since it could be lurking in many different places - according to [this answer](https://stackoverflow.com/a/68505306/1460422) even Inkscape doesn't strip all Javascript when asked to)
  - [security] Fixed XSS when the `action` GET param doesn't match a known action
+ - [security] User pages are now only savable in the HTTP API by either a moderator or the owning user (previously only the `edit` action was protected, so if you made a request direct to the `save` action, you could bypass the check)
  - StorageBox: Create SQLite DB if it doesn't exist explicitly with `touch()`, because some systems are weird
  - StorageBox: Fix crash when `index.php` is a symbolic link
  - Fixed erroneous additional entries in complex tables of contents
diff --git a/modules/page-edit.php b/modules/page-edit.php
index d04a6c2..06f42c3 100644
--- a/modules/page-edit.php
+++ b/modules/page-edit.php
@@ -5,7 +5,7 @@
 
 register_module([
 	"name" => "Page editor",
-	"version" => "0.18.1",
+	"version" => "0.19",
 	"author" => "Starbeamrainbowlabs",
 	"description" => "Allows you to edit pages by adding the edit and save actions. You should probably include this one.",
 	"id" => "page-edit",
@@ -60,16 +60,11 @@ register_module([
 			if(!$unknownpagename)
 				$page_tags = htmlentities(implode(", ", (!empty($pageindex->{$env->page}->tags)) ? $pageindex->{$env->page}->tags : []));
 			
-			$isOtherUsersPage = false;
-			if(
-				$settings->user_page_prefix == mb_substr($env->page, 0, mb_strlen($settings->user_page_prefix)) and // The current page is a user page of some sort
+			$isOtherUsersPage = $settings->user_page_prefix == mb_substr($env->page, 0, mb_strlen($settings->user_page_prefix)) and // The current page is a user page of some sort
 				(
 					!$env->is_logged_in or // the user isn't logged in.....
 					extract_user_from_userpage($env->page) !== $env->user // ...or it's not under this user's own name
-				)
-			) {
-				$isOtherUsersPage = true;
-			}
+				);
 			
 			if((!$env->is_logged_in and !$settings->anonedits) or // if we aren't logged in and anonymous edits are disabled
 				!$settings->editing or // or editing is disabled
@@ -387,6 +382,7 @@ window.addEventListener("load", function(event) {
 			
 			if(!$settings->editing)
 			{
+				http_response_code(403);
 				header("x-failure-reason: editing-disabled");
 				header("location: index.php?page=" . rawurlencode($env->page));
 				exit(page_renderer::render_main("Error saving edit", "<p>Editing is currently disabled on this wiki.</p>"));
@@ -406,12 +402,27 @@ window.addEventListener("load", function(event) {
 			{
 				http_response_code(403);
 				header("refresh: 5; url=index.php?page=" . rawurlencode($env->page));
+				header("x-failure-reason: protected-page");
 				exit(htmlentities($env->page) . " is protected, and you aren't logged in as an administrator or moderator. Your edit was not saved. Redirecting in 5 seconds...");
 			}
+			if($settings->user_page_prefix == mb_substr($env->page, 0, mb_strlen($settings->user_page_prefix)) and ( // The current page is a user page of some sort
+				!$env->is_logged_in or // the user isn't logged in.....
+				(
+					extract_user_from_userpage($env->page) !== $env->user and // ...or it's not under this user's own name
+					!$env->is_admin // ....and the user is not an admin/moderator
+				)
+			) ) {
+				http_response_code(403);
+				header("x-failure-reason: permissions-other-user-page");
+				header("content-type: text-plain");
+				exit("Error: The page {$env->page} is a user page. You must be logged in as either that user or a moderator in order to edit it.");
+			}
 			if(!isset($_POST["content"]))
 			{
 				http_response_code(400);
 				header("refresh: 5; url=index.php?page=" . rawurlencode($env->page));
+				header("x-failure-reason: no-content");
+				header("content-type: text-plain");
 				exit("Bad request: No content specified.");
 			}
 			if(isset($_POST["prevent_save_if_exists"]) && isset($pageindex->{$env->page})) {
