File gvfs-CVE-2026-28295.patch of Package gvfs.43109

commit 20db8173252ea88a4af05dc9a24aad6f29b807ad
Author: Ondrej Holy <oholy@redhat.com>
Date:   Thu Feb 19 15:45:53 2026 +0100

    ftp: Use control connection address for PASV data
    
    Currently, `PASV` uses the IP from the server reply when creating data
    connection. This may allow FTP bounce attacks. Let's always use only the
    port from the PASV reply and connect to the control connection address.
    
    Co-Authored-By: Cursor <cursoragent@cursor.com>
    
    Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/832
    Part-of: <https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/298>

--- a/daemon/gvfsbackendftp.c
+++ b/daemon/gvfsbackendftp.c
@@ -63,9 +63,8 @@
  * GVfsFtpMethod:
  * @G_VFS_FTP_METHOD_UNKNOWN: method has not yet been determined
  * @G_VFS_FTP_METHOD_EPSV: use EPSV command
- * @G_VFS_FTP_METHOD_PASV: use PASV command
- * @G_VFS_FTP_METHOD_PASV_ADDR: use PASV command, but ignore the returned 
- *                              address and only use it's port
+ * @G_VFS_FTP_METHOD_PASV: use PASV command, but ignore the returned address
+ *                         and only use it's port (bounce attack prevention)
  * @G_VFS_FTP_METHOD_EPRT: use the EPRT command
  * @G_VFS_FTP_METHOD_PORT: use the PORT command
  *

--- a/daemon/gvfsbackendftp.h
+++ b/daemon/gvfsbackendftp.h
@@ -61,7 +61,6 @@ typedef enum {
   G_VFS_FTP_METHOD_ANY = 0,
   G_VFS_FTP_METHOD_EPSV,
   G_VFS_FTP_METHOD_PASV,
-  G_VFS_FTP_METHOD_PASV_ADDR,
   G_VFS_FTP_METHOD_EPRT,
   G_VFS_FTP_METHOD_PORT
 } GVfsFtpMethod;

--- a/daemon/gvfsftptask.c
+++ b/daemon/gvfsftptask.c
@@ -850,7 +850,7 @@ fail:
 static GVfsFtpMethod
 g_vfs_ftp_task_setup_data_connection_pasv (GVfsFtpTask *task, GVfsFtpMethod method)
 {
-  guint ip1, ip2, ip3, ip4, port1, port2;
+  guint port1, port2;
   char **reply;
   const char *s;
   GSocketAddress *addr;
@@ -866,10 +866,8 @@ g_vfs_ftp_task_setup_data_connection_pas
    */
   for (s = reply[0]; *s; s++)
     {
-      if (sscanf (s, "%u,%u,%u,%u,%u,%u",
-        	 &ip1, &ip2, &ip3, &ip4,
-        	 &port1, &port2) == 6)
-       break;
+      if (sscanf (s, "%*u,%*u,%*u,%*u,%u,%u", &port1, &port2) == 2)
+        break;
     }
   if (*s == 0)
     {
@@ -880,52 +878,16 @@ g_vfs_ftp_task_setup_data_connection_pas
     }
   g_strfreev (reply);
 
-  if (method == G_VFS_FTP_METHOD_PASV || method == G_VFS_FTP_METHOD_ANY)
-    {
-      guint8 ip[4];
-      GInetAddress *inet_addr;
-
-      ip[0] = ip1;
-      ip[1] = ip2;
-      ip[2] = ip3;
-      ip[3] = ip4;
-      inet_addr = g_inet_address_new_from_bytes (ip, G_SOCKET_FAMILY_IPV4);
-      addr = g_inet_socket_address_new (inet_addr, port1 << 8 | port2);
-      g_object_unref (inet_addr);
-
-      success = g_vfs_ftp_connection_open_data_connection (task->conn,
-                                                           addr,
-                                                           task->cancellable,
-                                                           &task->error);
-      g_object_unref (addr);
-      if (success)
-        return G_VFS_FTP_METHOD_PASV;
-      if (g_vfs_ftp_task_is_in_error (task) && method != G_VFS_FTP_METHOD_ANY)
-        return G_VFS_FTP_METHOD_ANY;
-
-      g_vfs_ftp_task_clear_error (task);
-    }
-
-  if (method == G_VFS_FTP_METHOD_PASV_ADDR || method == G_VFS_FTP_METHOD_ANY)
-    {
-      /* Workaround code:
-       * Various ftp servers aren't setup correctly when behind a NAT. They report
-       * their own IP address (like 10.0.0.4) and not the address in front of the
-       * NAT. But this is likely the same address that we connected to with our
-       * command connetion. So if the address given by PASV fails, we fall back
-       * to the address of the command stream.
-       */
-      addr = g_vfs_ftp_task_create_remote_address (task, port1 << 8 | port2);
-      if (addr == NULL)
-        return G_VFS_FTP_METHOD_ANY;
-      success = g_vfs_ftp_connection_open_data_connection (task->conn,
-                                                           addr,
-                                                           task->cancellable,
-                                                           &task->error);
-      g_object_unref (addr);
-      if (success)
-        return G_VFS_FTP_METHOD_PASV_ADDR;
-    }
+  addr = g_vfs_ftp_task_create_remote_address (task, port1 << 8 | port2);
+  if (addr == NULL)
+    return G_VFS_FTP_METHOD_ANY;
+  success = g_vfs_ftp_connection_open_data_connection (task->conn,
+                                                       addr,
+                                                       task->cancellable,
+                                                       &task->error);
+  g_object_unref (addr);
+  if (success)
+    return G_VFS_FTP_METHOD_PASV;
 
   return G_VFS_FTP_METHOD_ANY;
 }
@@ -1121,7 +1083,6 @@ g_vfs_ftp_task_setup_data_connection (GV
     [G_VFS_FTP_METHOD_ANY]       = g_vfs_ftp_task_setup_data_connection_any,
     [G_VFS_FTP_METHOD_EPSV]      = g_vfs_ftp_task_setup_data_connection_epsv,
     [G_VFS_FTP_METHOD_PASV]      = g_vfs_ftp_task_setup_data_connection_pasv,
-    [G_VFS_FTP_METHOD_PASV_ADDR] = g_vfs_ftp_task_setup_data_connection_pasv,
     [G_VFS_FTP_METHOD_EPRT]      = g_vfs_ftp_task_setup_data_connection_eprt,
     [G_VFS_FTP_METHOD_PORT]      = g_vfs_ftp_task_setup_data_connection_port
   };
@@ -1152,7 +1113,6 @@ g_vfs_ftp_task_setup_data_connection (GV
         [G_VFS_FTP_METHOD_ANY] = "any",
         [G_VFS_FTP_METHOD_EPSV] = "EPSV",
         [G_VFS_FTP_METHOD_PASV] = "PASV",
-        [G_VFS_FTP_METHOD_PASV_ADDR] = "PASV with workaround",
         [G_VFS_FTP_METHOD_EPRT] = "EPRT",
         [G_VFS_FTP_METHOD_PORT] = "PORT"
       };
openSUSE Build Service is sponsored by