From dcce0673ff568c5a7cc82fa65ab7962cd42af902 Mon Sep 17 00:00:00 2001
From: Brian Wolff <bawolff+wn@gmail.com>
Date: Mon, 13 Jun 2016 03:07:48 -0400
Subject: [PATCH] [PATCH] SECURITY: Do not allow users to undelete a page they
can't  edit or create

If the page exists, it only checks edit rights, otherwise it
checks both edit and create rights.

This would only matter on wikis that have a non-default rights
configuration where there are users with undelete rights but a
restriction level enabled that prevents them from creating/editing
pages (or they otherwise aren't allowed to edit/create)

It should be noted that the error messages aren't used in the
normal UI currently, but they could be in the future, and
extensions could potentially be using them (The backend functions
return them, but the UI functions in Special:Undelete ignore
them)

Bug: T108138
Change-Id: I164b80534cf89e0afca264e9de07431484af8508
---
 includes/Title.php           | 11 +++++++++++
 includes/api/ApiUndelete.php |  5 ++++-
 languages/i18n/en.json       |  4 +++-
 languages/i18n/qqq.json      |  4 +++-
 4 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/includes/Title.php b/includes/Title.php
index a5bb9c6..4082bd5 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -2287,6 +2287,17 @@ class Title implements LinkTarget {
 			) {
 				$errors[] = [ 'delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ];
 			}
+		} elseif ( $action === 'undelete' ) {
+			if ( count( $this->getUserPermissionsErrorsInternal( 'edit', $user, $rigor, true ) ) ) {
+				// Undeleting implies editing
+				$errors[] = [ 'undelete-cantedit' ];
+			}
+			if ( !$this->exists()
+				&& count( $this->getUserPermissionsErrorsInternal( 'create', $user, $rigor, true ) )
+			) {
+				// Undeleting where nothing currently exists implies creating
+				$errors[] = [ 'undelete-cantcreate' ];
+			}
 		}
 		return $errors;
 	}
diff --git a/includes/api/ApiUndelete.php b/includes/api/ApiUndelete.php
index 7fda1ea..0208bbe 100644
--- a/includes/api/ApiUndelete.php
+++ b/includes/api/ApiUndelete.php
@@ -33,7 +33,6 @@ class ApiUndelete extends ApiBase {
 		$this->useTransactionalTimeLimit();
 
 		$params = $this->extractRequestParams();
-		$this->checkUserRightsAny( 'undelete' );
 
 		$user = $this->getUser();
 		if ( $user->isBlocked() ) {
@@ -45,6 +44,10 @@ class ApiUndelete extends ApiBase {
 			$this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
 		}
 
+		if ( !$titleObj->userCan( 'undelete', $user, 'secure' ) ) {
+			$this->dieWithError( 'permdenied-undelete' );
+		}
+
 		// Check if user can add tags
 		if ( !is_null( $params['tags'] ) ) {
 			$ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
diff --git a/languages/i18n/en.json b/languages/i18n/en.json
index eb43cdb..8753858 100644
--- a/languages/i18n/en.json
+++ b/languages/i18n/en.json
@@ -4278,5 +4278,7 @@
 	"restrictionsfield-label": "Allowed IP ranges:",
 	"restrictionsfield-help": "One IP address or CIDR range per line. To enable everything, use:<pre>0.0.0.0/0\n::/0</pre>",
 	"revid": "revision $1",
-	"pageid": "page ID $1"
+	"pageid": "page ID $1",
+	"undelete-cantedit": "You cannot undelete this page as you are not allowed to edit this page.",
+	"undelete-cantcreate": "You cannot undelete this page as there is no existing page with this name and you are not allowed to create this page."
 }
diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json
index f123189..c83eb40d 100644
--- a/languages/i18n/qqq.json
+++ b/languages/i18n/qqq.json
@@ -4465,5 +4465,7 @@
 	"restrictionsfield-label": "Field label shown for restriction fields (e.g. on Special:BotPassword).",
 	"restrictionsfield-help": "Placeholder text displayed in restriction fields (e.g. on Special:BotPassword).",
 	"revid": "Used to format a revision ID number in text. Parameters:\n* $1 - Revision ID number.\n{{Identical|Revision}}",
-	"pageid": "Used to format a page ID number in text. Parameters:\n* $1 - Page ID number."
+	"pageid": "Used to format a page ID number in text. Parameters:\n* $1 - Page ID number.",
+	"undelete-cantedit": "Shown if the user tries to undelete a page that they cannot edit",
+	"undelete-cantcreate": "Shown if the user tries to undelete a page which currently does not exist, and they are not allowed to create it. This could for example happen on a wiki with custom protection levels where the page name has been create-protected and the user has the right to undelete but not the right to edit protected pages."
 }
-- 
2.9.3

