public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/dokuwiki] f43: Fix media upload not working (rhbz#2532550)
@ 2026-09-20 14:31 Artur Frenszek-Iwicki
  0 siblings, 0 replies; only message in thread
From: Artur Frenszek-Iwicki @ 2026-09-20 14:31 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/dokuwiki
Branch : f43
Commit : e411f3b84d71ae22b5faf72c629f1a67ecb7130d
Author : Artur Frenszek-Iwicki <fedora@svgames.pl>
Date   : 2026-09-20T16:16:16+02:00
Stats  : +237/-4 in 2 file(s)
URL    : https://src.fedoraproject.org/rpms/dokuwiki/c/e411f3b84d71ae22b5faf72c629f1a67ecb7130d?branch=f43

Log:
Fix media upload not working (rhbz#2532550)

---
diff --git a/4648.patch b/4648.patch
new file mode 100644
index 0000000..5fc452a
--- /dev/null
+++ b/4648.patch
@@ -0,0 +1,223 @@
+From 7e687fd85a40bd8453b39b64bae8e989ab32fd36 Mon Sep 17 00:00:00 2001
+From: Andreas Gohr <andi@splitbrain.org>
+Date: Fri, 29 May 2026 11:17:21 +0200
+Subject: [PATCH] fix(auth): scope media ACL checks to the namespace
+
+Media files have no per-file ACLs; permissions must be evaluated against
+the namespace they live in. Several call sites passed the raw media ID
+to auth_quickaclcheck(), so a page-intended exact-ID rule (e.g. on
+wiki:secret.png) could silently apply to a media file sharing that ID.
+
+Introduce mediaAclPath() that builds the correct namespace wildcard
+path (handling root-namespace media) and route all media-related ACL
+checks through it. Also normalize the lone `:X` sentinel variant in
+fetch.functions.php to the standard `:*` form.
+
+fixes: #4647
+
+diff --git a/inc/File/MediaFile.php b/inc/File/MediaFile.php
+index 8a1495d3c4..d0ffc43989 100644
+--- a/inc/File/MediaFile.php
++++ b/inc/File/MediaFile.php
+@@ -185,7 +185,7 @@ public function getDisplayDimensions($w = 0, $h = 0, $crop = false)
+      */
+     public function userPermission()
+     {
+-        return auth_quickaclcheck(getNS($this->id) . ':*');
++        return auth_quickaclcheck(mediaAclPath($this->id));
+     }
+ 
+     /** @return JpegMeta */
+diff --git a/inc/Remote/ApiCore.php b/inc/Remote/ApiCore.php
+index 8ca0e8be7f..aa1e310309 100644
+--- a/inc/Remote/ApiCore.php
++++ b/inc/Remote/ApiCore.php
+@@ -838,7 +838,7 @@ public function getRecentMediaChanges($timestamp = 0)
+     public function getMedia($media, $rev = 0)
+     {
+         $media = cleanID($media);
+-        if (auth_quickaclcheck($media) < AUTH_READ) {
++        if (auth_quickaclcheck(mediaAclPath($media)) < AUTH_READ) {
+             throw new AccessDeniedException('You are not allowed to read this media file', 211);
+         }
+ 
+@@ -875,7 +875,7 @@ public function getMedia($media, $rev = 0)
+     public function getMediaInfo($media, $rev = 0, $author = false, $hash = false)
+     {
+         $media = cleanID($media);
+-        if (auth_quickaclcheck($media) < AUTH_READ) {
++        if (auth_quickaclcheck(mediaAclPath($media)) < AUTH_READ) {
+             throw new AccessDeniedException('You are not allowed to read this media file', 211);
+         }
+ 
+@@ -912,7 +912,7 @@ public function getMediaInfo($media, $rev = 0, $author = false, $hash = false)
+     public function getMediaUsage($media)
+     {
+         $media = cleanID($media);
+-        if (auth_quickaclcheck($media) < AUTH_READ) {
++        if (auth_quickaclcheck(mediaAclPath($media)) < AUTH_READ) {
+             throw new AccessDeniedException('You are not allowed to read this media file', 211);
+         }
+         if (!media_exists($media)) {
+@@ -944,7 +944,7 @@ public function getMediaHistory($media, $first = 0)
+ 
+         $media = cleanID($media);
+         // check that this media exists
+-        if (auth_quickaclcheck($media) < AUTH_READ) {
++        if (auth_quickaclcheck(mediaAclPath($media)) < AUTH_READ) {
+             throw new AccessDeniedException('You are not allowed to read this media file', 211);
+         }
+         if (!media_exists($media, 0)) {
+@@ -994,7 +994,7 @@ public function getMediaHistory($media, $first = 0)
+     public function saveMedia($media, $base64, $overwrite = false)
+     {
+         $media = cleanID($media);
+-        $auth = auth_quickaclcheck(getNS($media) . ':*');
++        $auth = auth_quickaclcheck(mediaAclPath($media));
+ 
+         if ($media === '') {
+             throw new RemoteException('Empty or invalid media ID given', 231);
+@@ -1047,7 +1047,7 @@ public function deleteMedia($media)
+     {
+         $media = cleanID($media);
+ 
+-        $auth = auth_quickaclcheck($media);
++        $auth = auth_quickaclcheck(mediaAclPath($media));
+         $res = media_delete($media, $auth);
+         if ($res & DOKU_MEDIA_DELETED) {
+             return true;
+diff --git a/inc/Remote/LegacyApiCore.php b/inc/Remote/LegacyApiCore.php
+index 48d4c05eb3..f35c3ef0e0 100644
+--- a/inc/Remote/LegacyApiCore.php
++++ b/inc/Remote/LegacyApiCore.php
+@@ -477,7 +477,7 @@ public function legacyGetRecentMediaChanges($timestamp)
+                 'lastModified' => $this->toDate($recent->revision),
+                 'author' => $recent->author,
+                 'version' => $recent->revision,
+-                'perms' => auth_quickaclcheck($recent->id),
++                'perms' => auth_quickaclcheck(mediaAclPath($recent->id)),
+                 'size' => @filesize(mediaFN($recent->id)),
+             ];
+         }
+diff --git a/inc/Remote/Response/Media.php b/inc/Remote/Response/Media.php
+index ca9137d67e..b1b92cad66 100644
+--- a/inc/Remote/Response/Media.php
++++ b/inc/Remote/Response/Media.php
+@@ -52,7 +52,7 @@ public function __construct(
+         $this->file = mediaFN($this->id, $revision);
+         $this->revision = $revision ?: $mtime ?: filemtime($this->file);
+         $this->size = $size ?? filesize($this->file);
+-        $this->permission = $perms ?? auth_quickaclcheck($this->id);
++        $this->permission = $perms ?? auth_quickaclcheck(mediaAclPath($this->id));
+         ;
+         $this->isimage = (bool)($isimage ?? preg_match("/\.(jpe?g|gif|png)$/", $id));
+         $this->hash = $hash;
+diff --git a/inc/auth.php b/inc/auth.php
+index bf70531aac..f83943ea4c 100644
+--- a/inc/auth.php
++++ b/inc/auth.php
+@@ -701,6 +701,21 @@ function auth_quickaclcheck($id)
+     return auth_aclcheck($id, $INPUT->server->str('REMOTE_USER'), is_array($USERINFO) ? $USERINFO['grps'] : []);
+ }
+ 
++/**
++ * Build the ACL path for a media file.
++ *
++ * Media files do not have per-file ACLs; permissions are always evaluated against the namespace
++ * they live in. This returns the namespace wildcard path (e.g. "wiki:*" or "*" for root-namespace
++ * media) suitable for passing to auth_quickaclcheck() or auth_aclcheck().
++ *
++ * @param string $id media ID (needs to be resolved and cleaned)
++ * @return string the ACL path to check
++ */
++function mediaAclPath($id)
++{
++    return ltrim(getNS($id) . ':*', ':');
++}
++
+ /**
+  * Returns the maximum rights a user has for the given ID or its namespace
+  *
+diff --git a/inc/changelog.php b/inc/changelog.php
+index a0f3ae4f81..a742bfe415 100644
+--- a/inc/changelog.php
++++ b/inc/changelog.php
+@@ -356,7 +356,7 @@ function _handleRecentLogLine($line, $ns, $flags, &$seen)
+ 
+     // check ACL
+     if ($flags & RECENTS_MEDIA_CHANGES) {
+-        $recent['perms'] = auth_quickaclcheck(getNS($recent['id']) . ':*');
++        $recent['perms'] = auth_quickaclcheck(mediaAclPath($recent['id']));
+     } else {
+         $recent['perms'] = auth_quickaclcheck($recent['id']);
+     }
+diff --git a/inc/fetch.functions.php b/inc/fetch.functions.php
+index d7acd243e0..7d3697ab92 100644
+--- a/inc/fetch.functions.php
++++ b/inc/fetch.functions.php
+@@ -174,7 +174,7 @@ function checkFileStatus(&$media, &$file, $rev = '', $width = 0, $height = 0)
+         }
+ 
+         //check permissions (namespace only)
+-        if (auth_quickaclcheck(getNS($media) . ':X') < AUTH_READ) {
++        if (auth_quickaclcheck(mediaAclPath($media)) < AUTH_READ) {
+             return [403, 'Forbidden'];
+         }
+         $file = mediaFN($media, $rev);
+diff --git a/inc/media.php b/inc/media.php
+index be3ad3d5e4..ea740667f7 100644
+--- a/inc/media.php
++++ b/inc/media.php
+@@ -138,7 +138,7 @@ function media_ispublic($id)
+ {
+     if (media_isexternal($id)) return true;
+     $id = cleanID($id);
+-    if (auth_aclcheck(getNS($id) . ':*', '', []) >= AUTH_READ) return true;
++    if (auth_aclcheck(mediaAclPath($id), '', []) >= AUTH_READ) return true;
+     return false;
+ }
+ 
+@@ -261,7 +261,7 @@ function media_inuse($id)
+ function media_delete($id, $auth)
+ {
+     global $lang;
+-    $auth = auth_quickaclcheck(ltrim(getNS($id) . ':*', ':'));
++    $auth = auth_quickaclcheck(mediaAclPath($id));
+     if ($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH;
+     if (media_inuse($id)) return DOKU_MEDIA_INUSE;
+ 
+diff --git a/inc/search.php b/inc/search.php
+index 1a105a52a3..6f6c79992b 100644
+--- a/inc/search.php
++++ b/inc/search.php
+@@ -209,7 +209,7 @@ function search_media(&$data, $base, $file, $type, $lvl, $opts)
+     }
+ 
+     //check ACL for namespace (we have no ACL for mediafiles)
+-    $info['perm'] = auth_quickaclcheck(getNS($info['id']) . ':*');
++    $info['perm'] = auth_quickaclcheck(mediaAclPath($info['id']));
+     if (empty($opts['skipacl']) && $info['perm'] < AUTH_READ) {
+         return false;
+     }
+@@ -276,7 +276,7 @@ function search_mediafiles(&$data, $base, $file, $type, $lvl, $opts)
+     }
+ 
+     //check ACL for namespace (we have no ACL for mediafiles)
+-    $info['perm'] = auth_quickaclcheck(getNS($id) . ':*');
++    $info['perm'] = auth_quickaclcheck(mediaAclPath($id));
+     if (empty($opts['skipacl']) && $info['perm'] < AUTH_READ) {
+         return false;
+     }
+diff --git a/lib/exe/detail.php b/lib/exe/detail.php
+index 6851dec800..48a5cd61ba 100644
+--- a/lib/exe/detail.php
++++ b/lib/exe/detail.php
+@@ -26,7 +26,7 @@
+ 
+ $ERROR = false;
+ // check image permissions
+-$AUTH = auth_quickaclcheck($IMG);
++$AUTH = auth_quickaclcheck(mediaAclPath($IMG));
+ if ($AUTH >= AUTH_READ) {
+     // check if image exists
+     $SRC = mediaFN($IMG, $REV);

diff --git a/dokuwiki.spec b/dokuwiki.spec
index 79d49a9..8c89b38 100644
--- a/dokuwiki.spec
+++ b/dokuwiki.spec
@@ -5,7 +5,7 @@ License:	GPL-2.0-only
 %global		releasenum 2025-05-14b
 %global		releasetag %(rel="%{releasenum}"; echo "${rel//-/}")
 Version:	%{releasetag}
-Release:	6%{?dist}
+Release:	7%{?dist}
 
 %global php_min_version 7.4
 
@@ -26,23 +26,30 @@ Patch2:		CVE-2026-26477.patch
 # https://github.com/dokuwiki/dokuwiki/commit/ed28f990b6e1705dab522ad34afa8c02b188dc91
 Patch3:		CVE-2026-37106.patch
 
+# Media ACL scope changes. This is needed mostly because it introduces the mediaAclPath()
+# function, which is used by some security fixes included in latter patches.
+#
+# Backport from upstream. Edited to remove changed to tests.
+# https://github.com/dokuwiki/dokuwiki/pull/4648
+Patch4:     4648.patch
+
 # Assortment of security fixes.
 #
 # Backport from upstream. Edited to remove changes to tests.
 # https://github.com/dokuwiki/dokuwiki/pull/4703
-Patch4:		4703.patch
+Patch5:		4703.patch
 
 # Fix bypass of "disableactions" mechanism.
 #
 # Backport from upstream. Edited to remove changes to tests.
 # https://github.com/dokuwiki/dokuwiki/commit/012ec40c0d41cdbe5cb81aec13089eb9b8c86788
-Patch5:     4731.patch
+Patch6:     4731.patch
 
 # Fix object injection, potentially leading to RCE.
 #
 # Backport from upstream:
 # https://github.com/dokuwiki/dokuwiki/commit/1531802afb2ac3eea147a887600fa5750e74e681
-Patch6:     4752.patch
+Patch7:     4752.patch
 
 BuildArch:	noarch
 
@@ -305,6 +312,9 @@ fi
 %doc DOKUWIKI-SELINUX.README
 
 %changelog
+* Sun Sep 20 2026 Artur Frenszek-Iwicki <fedora@svgames.pl> - 20250514b-7
+- Fix media upload not working (rhbz#2532550)
+
 * Wed Sep 02 2026 Artur Frenszek-Iwicki <fedora@svgames.pl> - 20250514b-6
 - Backport object injection vulnerability fix
 

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-20 14:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-20 14:31 [rpms/dokuwiki] f43: Fix media upload not working (rhbz#2532550) Artur Frenszek-Iwicki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox