From 10a413574050db39ece41592fc6e4eff73d3d444 Mon Sep 17 00:00:00 2001
From: Benjamin Franzke <ben@bnf.dev>
Date: Fri, 7 Jul 2023 15:09:12 +0200
Subject: [PATCH] [BUGFIX] Fix sudo mode in non-Sec-Fetch-Dest context
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since #94084 all module URLs are automatically framed by
the TYPO3 main controller whenever they are opened in a
Sec-Fetch-Dest aware request. (HTTPS or localhost domain)
The intention of API is to allow module-links
to be opened in a new tab by user intent – but due to
technical limitation that feature is limited to
secure contexts, and must therefore not be relied on
as an API for internal redirects.

sudo mode made use of this API and redirected
via top.location to the privileged module, relying
on the fact that iframe module-requests where detected
to be loaded in the wrong context, to produce
a redirect to the proper backend-frame, this didn't
work for non HTTPS requests.

This workaround has been done to remove "sudo-mode"
from the URL bar. That workaround is no longer needed
as #101287 added support for installtool URL
bar synchronisation.
ContentContainer API is now used to set the URL.

Releases: main, 12.4
Resolves: #101288
Related: #101287
Change-Id: Id8b828662e3cd2739a93eda5f9517f896c65e941
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79921
Tested-by: Benjamin Franzke <ben@bnf.dev>
Reviewed-by: Benjamin Franzke <ben@bnf.dev>
Tested-by: core-ci <typo3@b13.com>
---
 .../Sources/TypeScript/backend/security/element/sudo-mode.ts | 5 ++---
 .../Classes/Controller/Security/SudoModeController.php       | 1 -
 .../Public/JavaScript/security/element/sudo-mode.js          | 4 ++--
 3 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/Build/Sources/TypeScript/backend/security/element/sudo-mode.ts b/Build/Sources/TypeScript/backend/security/element/sudo-mode.ts
index 7c25a62cfd52..47b078d23e4c 100644
--- a/Build/Sources/TypeScript/backend/security/element/sudo-mode.ts
+++ b/Build/Sources/TypeScript/backend/security/element/sudo-mode.ts
@@ -16,12 +16,12 @@ import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';
 import AjaxRequest from '@typo3/core/ajax/ajax-request';
 import { AjaxResponse } from '@typo3/core/ajax/ajax-response';
 import { styleTag, lll } from '@typo3/core/lit-helper';
+import Viewport from '@typo3/backend/viewport';
 
 interface SudoModeResponse {
   message: string;
   redirect?: {
     uri: string,
-    target: string,
   }
 }
 
@@ -100,8 +100,7 @@ export class SudoMode extends LitElement {
       .then(async (ajaxResponse: AjaxResponse) => {
         const response: SudoModeResponse = await ajaxResponse.resolve('application/json');
         if (response.redirect) {
-          const targetDocument = response.redirect.target === 'top' ? top.document : document;
-          targetDocument.location.href = response.redirect.uri;
+          Viewport.ContentContainer.setUrl(response.redirect.uri);
         }
       })
       .catch(async (ajaxResponse: AjaxResponse) => {
diff --git a/typo3/sysext/backend/Classes/Controller/Security/SudoModeController.php b/typo3/sysext/backend/Classes/Controller/Security/SudoModeController.php
index 218622b63bb1..3e6b3f05225e 100644
--- a/typo3/sysext/backend/Classes/Controller/Security/SudoModeController.php
+++ b/typo3/sysext/backend/Classes/Controller/Security/SudoModeController.php
@@ -142,7 +142,6 @@ final class SudoModeController implements LoggerAwareInterface
                 self::ROUTE_PATH_APPLY,
                 $this->buildUriParametersForClaim($claim, 'apply')
             ),
-            'target' => 'top',
         ];
         if ($useInstallToolPassword && $this->passwordVerification->verifyInstallToolPassword($password)) {
             $this->logger->info('Verified with install tool password', $loggerContext);
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/security/element/sudo-mode.js b/typo3/sysext/backend/Resources/Public/JavaScript/security/element/sudo-mode.js
index 32cb19d64222..118e974f705d 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/security/element/sudo-mode.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/security/element/sudo-mode.js
@@ -10,7 +10,7 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-var __decorate=function(e,o,s,t){var r,l=arguments.length,a=l<3?o:null===t?t=Object.getOwnPropertyDescriptor(o,s):t;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,o,s,t);else for(var d=e.length-1;d>=0;d--)(r=e[d])&&(a=(l<3?r(a):l>3?r(o,s,a):r(o,s))||a);return l>3&&a&&Object.defineProperty(o,s,a),a};import{customElement,property,query,state}from"lit/decorators.js";import{html,LitElement,nothing}from"lit";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{styleTag,lll}from"@typo3/core/lit-helper.js";let SudoMode=class extends LitElement{constructor(){super(...arguments),this.useInstallToolPassword=!1,this.errorMessage=null}createRenderRoot(){return this}render(){return html`
+var __decorate=function(e,o,s,t){var r,l=arguments.length,a=l<3?o:null===t?t=Object.getOwnPropertyDescriptor(o,s):t;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,o,s,t);else for(var d=e.length-1;d>=0;d--)(r=e[d])&&(a=(l<3?r(a):l>3?r(o,s,a):r(o,s))||a);return l>3&&a&&Object.defineProperty(o,s,a),a};import{customElement,property,query,state}from"lit/decorators.js";import{html,LitElement,nothing}from"lit";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{styleTag,lll}from"@typo3/core/lit-helper.js";import Viewport from"@typo3/backend/viewport.js";let SudoMode=class extends LitElement{constructor(){super(...arguments),this.useInstallToolPassword=!1,this.errorMessage=null}createRenderRoot(){return this}render(){return html`
       ${styleTag`
         :host { display: block; }
         #sudo-mode-verification { display: block; }
@@ -50,4 +50,4 @@ var __decorate=function(e,o,s,t){var r,l=arguments.length,a=l<3?o:null===t?t=Obj
           </div>
         </div>
       </div>
-    `}firstUpdated(e){super.firstUpdated(e),this.passwordElement.focus()}verifyPassword(e){e.preventDefault(),this.errorMessage=null,new AjaxRequest(this.verifyActionUri).post({password:this.passwordElement.value,useInstallToolPassword:this.useInstallToolPassword?1:0}).then((async e=>{const o=await e.resolve("application/json");if(o.redirect){("top"===o.redirect.target?top.document:document).location.href=o.redirect.uri}})).catch((async e=>{const o=await e.resolve("application/json");this.errorMessage=o.message}))}toggleUseInstallToolPassword(e){e.preventDefault(),this.useInstallToolPassword=!this.useInstallToolPassword}};__decorate([property({type:String})],SudoMode.prototype,"verifyActionUri",void 0),__decorate([state()],SudoMode.prototype,"useInstallToolPassword",void 0),__decorate([state()],SudoMode.prototype,"errorMessage",void 0),__decorate([query("#password")],SudoMode.prototype,"passwordElement",void 0),SudoMode=__decorate([customElement("typo3-backend-security-sudo-mode")],SudoMode);export{SudoMode};
\ No newline at end of file
+    `}firstUpdated(e){super.firstUpdated(e),this.passwordElement.focus()}verifyPassword(e){e.preventDefault(),this.errorMessage=null,new AjaxRequest(this.verifyActionUri).post({password:this.passwordElement.value,useInstallToolPassword:this.useInstallToolPassword?1:0}).then((async e=>{const o=await e.resolve("application/json");o.redirect&&Viewport.ContentContainer.setUrl(o.redirect.uri)})).catch((async e=>{const o=await e.resolve("application/json");this.errorMessage=o.message}))}toggleUseInstallToolPassword(e){e.preventDefault(),this.useInstallToolPassword=!this.useInstallToolPassword}};__decorate([property({type:String})],SudoMode.prototype,"verifyActionUri",void 0),__decorate([state()],SudoMode.prototype,"useInstallToolPassword",void 0),__decorate([state()],SudoMode.prototype,"errorMessage",void 0),__decorate([query("#password")],SudoMode.prototype,"passwordElement",void 0),SudoMode=__decorate([customElement("typo3-backend-security-sudo-mode")],SudoMode);export{SudoMode};
\ No newline at end of file
-- 
GitLab