From 94d0e7550867ee740173cb3df122dd210b242841 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Mon, 8 Feb 2010 17:17:44 +0000 Subject: [PATCH] - ftp: backport several PASV/EPSV fixes from master (#542205, #555033) --- gvfs-1.5.2-ftp-PASV-EPASV-v4-v6.patch | 36 +++++++ gvfs-1.5.2-ftp-PASV-v4.patch | 96 +++++++++++++++++++ ....5.2-ftp-name-data-connection-method.patch | 33 +++++++ ...ate-data-connection-method-supported.patch | 50 ++++++++++ ...1.5.2-ftp-symlink-target-not-defined.patch | 47 +++++++++ gvfs.spec | 18 +++- 6 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 gvfs-1.5.2-ftp-PASV-EPASV-v4-v6.patch create mode 100644 gvfs-1.5.2-ftp-PASV-v4.patch create mode 100644 gvfs-1.5.2-ftp-name-data-connection-method.patch create mode 100644 gvfs-1.5.2-ftp-separate-data-connection-method-supported.patch create mode 100644 gvfs-1.5.2-ftp-symlink-target-not-defined.patch diff --git a/gvfs-1.5.2-ftp-PASV-EPASV-v4-v6.patch b/gvfs-1.5.2-ftp-PASV-EPASV-v4-v6.patch new file mode 100644 index 0000000..3959e48 --- /dev/null +++ b/gvfs-1.5.2-ftp-PASV-EPASV-v4-v6.patch @@ -0,0 +1,36 @@ +From b1423ef4ae8883bc38a510fd606377a91fbe6201 Mon Sep 17 00:00:00 2001 +From: Benjamin Otte +Date: Sun, 07 Feb 2010 19:01:06 +0000 +Subject: ftp: Prefer PASV/PORT to EPSV/EPRT for IPv4 + +As PASV and PORT are older, there's a higher chance that they are +supported. As only IPv4 connections can use these commands, IPv6 will +still prefer EPSV/EPRT. + +The order of methods now looks like this (assuming EPSV and EPRT are +supported): +IPv4: PASV EPSV PORT EPRT +IPv6: EPSV EPRT PASV +Note that PASV for IPv6 will try the returned port and the known remote +address since the IP is not reliable (That's the fallback part in IPv4). +--- +diff --git a/daemon/gvfsftptask.c b/daemon/gvfsftptask.c +index 3e37bf1..8c5f7fb 100644 +--- a/daemon/gvfsftptask.c ++++ b/daemon/gvfsftptask.c +@@ -1027,10 +1027,10 @@ static GVfsFtpMethod + g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unused) + { + static const GVfsFtpOpenDataConnectionMethod funcs_ordered[] = { +- { G_VFS_FTP_FEATURE_EPSV, G_SOCKET_FAMILY_INVALID, g_vfs_ftp_task_setup_data_connection_epsv }, + { 0, G_SOCKET_FAMILY_IPV4, g_vfs_ftp_task_setup_data_connection_pasv }, +- { G_VFS_FTP_FEATURE_EPRT, G_SOCKET_FAMILY_INVALID, g_vfs_ftp_task_setup_data_connection_eprt }, +- { 0, G_SOCKET_FAMILY_IPV4, g_vfs_ftp_task_setup_data_connection_port } ++ { G_VFS_FTP_FEATURE_EPSV, G_SOCKET_FAMILY_INVALID, g_vfs_ftp_task_setup_data_connection_epsv }, ++ { 0, G_SOCKET_FAMILY_IPV4, g_vfs_ftp_task_setup_data_connection_port }, ++ { G_VFS_FTP_FEATURE_EPRT, G_SOCKET_FAMILY_INVALID, g_vfs_ftp_task_setup_data_connection_eprt } + }; + GVfsFtpMethod method; + GSocketFamily family; +-- +cgit v0.8.3.1 diff --git a/gvfs-1.5.2-ftp-PASV-v4.patch b/gvfs-1.5.2-ftp-PASV-v4.patch new file mode 100644 index 0000000..03d8d66 --- /dev/null +++ b/gvfs-1.5.2-ftp-PASV-v4.patch @@ -0,0 +1,96 @@ +From cc97f892cecceaea38e981c63cc37a9c3d2e37b1 Mon Sep 17 00:00:00 2001 +From: Benjamin Otte +Date: Sun, 07 Feb 2010 19:00:23 +0000 +Subject: ftp: Require IPv4 connections for PASV/PORT commands + +--- +diff --git a/daemon/gvfsftptask.c b/daemon/gvfsftptask.c +index 5393d0c..3e37bf1 100644 +--- a/daemon/gvfsftptask.c ++++ b/daemon/gvfsftptask.c +@@ -980,36 +980,68 @@ typedef GVfsFtpMethod (* GVfsFtpOpenDataConnectionFunc) (GVfsFtpTask *task, GVfs + typedef struct _GVfsFtpOpenDataConnectionMethod GVfsFtpOpenDataConnectionMethod; + struct _GVfsFtpOpenDataConnectionMethod { + GVfsFtpFeature required_feature; ++ GSocketFamily required_family; + GVfsFtpOpenDataConnectionFunc func; + }; + + static gboolean + g_vfs_ftp_task_open_data_connection_method_is_supported (const GVfsFtpOpenDataConnectionMethod *method, +- GVfsFtpTask * task) ++ GVfsFtpTask * task, ++ GSocketFamily family) + { + if (method->required_feature && + !g_vfs_backend_ftp_has_feature (task->backend, method->required_feature)) + return FALSE; + ++ if (method->required_family != G_SOCKET_FAMILY_INVALID && ++ method->required_family != family) ++ return FALSE; ++ + return TRUE; + } + ++static GSocketFamily ++g_vfs_ftp_task_get_socket_family (GVfsFtpTask *task) ++{ ++ GSocketAddress *addr; ++ GSocketFamily family; ++ ++ /* workaround for the task not having a connection yet */ ++ if (task->conn == NULL && ++ g_vfs_ftp_task_send (task, 0, "NOOP") == 0) ++ { ++ g_vfs_ftp_task_clear_error (task); ++ return G_SOCKET_FAMILY_INVALID; ++ } ++ ++ addr = g_vfs_ftp_connection_get_address (task->conn, NULL); ++ if (addr == NULL) ++ return G_SOCKET_FAMILY_INVALID; ++ ++ family = g_socket_address_get_family (addr); ++ g_object_unref (addr); ++ return family; ++} ++ + static GVfsFtpMethod + g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unused) + { + static const GVfsFtpOpenDataConnectionMethod funcs_ordered[] = { +- { G_VFS_FTP_FEATURE_EPSV, g_vfs_ftp_task_setup_data_connection_epsv }, +- { 0, g_vfs_ftp_task_setup_data_connection_pasv }, +- { G_VFS_FTP_FEATURE_EPRT, g_vfs_ftp_task_setup_data_connection_eprt }, +- { 0, g_vfs_ftp_task_setup_data_connection_port } ++ { G_VFS_FTP_FEATURE_EPSV, G_SOCKET_FAMILY_INVALID, g_vfs_ftp_task_setup_data_connection_epsv }, ++ { 0, G_SOCKET_FAMILY_IPV4, g_vfs_ftp_task_setup_data_connection_pasv }, ++ { G_VFS_FTP_FEATURE_EPRT, G_SOCKET_FAMILY_INVALID, g_vfs_ftp_task_setup_data_connection_eprt }, ++ { 0, G_SOCKET_FAMILY_IPV4, g_vfs_ftp_task_setup_data_connection_port } + }; + GVfsFtpMethod method; ++ GSocketFamily family; + guint i; + ++ family = g_vfs_ftp_task_get_socket_family (task); ++ + /* first try all advertised features */ + for (i = 0; i < G_N_ELEMENTS (funcs_ordered); i++) + { +- if (!g_vfs_ftp_task_open_data_connection_method_is_supported (&funcs_ordered[i], task)) ++ if (!g_vfs_ftp_task_open_data_connection_method_is_supported (&funcs_ordered[i], task, family)) + continue; + method = funcs_ordered[i].func (task, G_VFS_FTP_METHOD_ANY); + if (method != G_VFS_FTP_METHOD_ANY) +@@ -1021,7 +1053,7 @@ g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unuse + /* then try if the non-advertised features work */ + for (i = 0; i < G_N_ELEMENTS (funcs_ordered); i++) + { +- if (g_vfs_ftp_task_open_data_connection_method_is_supported (&funcs_ordered[i], task)) ++ if (g_vfs_ftp_task_open_data_connection_method_is_supported (&funcs_ordered[i], task, family)) + continue; + method = funcs_ordered[i].func (task, G_VFS_FTP_METHOD_ANY); + if (method != G_VFS_FTP_METHOD_ANY) +-- +cgit v0.8.3.1 diff --git a/gvfs-1.5.2-ftp-name-data-connection-method.patch b/gvfs-1.5.2-ftp-name-data-connection-method.patch new file mode 100644 index 0000000..ef6a6c4 --- /dev/null +++ b/gvfs-1.5.2-ftp-name-data-connection-method.patch @@ -0,0 +1,33 @@ +From 4113a6fd0e4b628a71a7144e4009012523945cc9 Mon Sep 17 00:00:00 2001 +From: Benjamin Otte +Date: Sun, 07 Feb 2010 18:34:53 +0000 +Subject: ftp: Name the struct used for selecting the data connection method + +--- +diff --git a/daemon/gvfsftptask.c b/daemon/gvfsftptask.c +index 4cabf14..fcf01ab 100644 +--- a/daemon/gvfsftptask.c ++++ b/daemon/gvfsftptask.c +@@ -977,14 +977,16 @@ g_vfs_ftp_task_setup_data_connection_port (GVfsFtpTask *task, GVfsFtpMethod unus + } + + typedef GVfsFtpMethod (* GVfsFtpOpenDataConnectionFunc) (GVfsFtpTask *task, GVfsFtpMethod method); ++typedef struct _GVfsFtpOpenDataConnectionMethod GVfsFtpOpenDataConnectionMethod; ++struct _GVfsFtpOpenDataConnectionMethod { ++ GVfsFtpFeature required_feature; ++ GVfsFtpOpenDataConnectionFunc func; ++}; + + static GVfsFtpMethod + g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unused) + { +- static const struct { +- GVfsFtpFeature required_feature; +- GVfsFtpOpenDataConnectionFunc func; +- } funcs_ordered[] = { ++ static const GVfsFtpOpenDataConnectionMethod funcs_ordered[] = { + { G_VFS_FTP_FEATURE_EPSV, g_vfs_ftp_task_setup_data_connection_epsv }, + { 0, g_vfs_ftp_task_setup_data_connection_pasv }, + { G_VFS_FTP_FEATURE_EPRT, g_vfs_ftp_task_setup_data_connection_eprt }, +-- +cgit v0.8.3.1 diff --git a/gvfs-1.5.2-ftp-separate-data-connection-method-supported.patch b/gvfs-1.5.2-ftp-separate-data-connection-method-supported.patch new file mode 100644 index 0000000..67432e8 --- /dev/null +++ b/gvfs-1.5.2-ftp-separate-data-connection-method-supported.patch @@ -0,0 +1,50 @@ +From 153fae8d1f6796686d46de0ecbd58281738f30e9 Mon Sep 17 00:00:00 2001 +From: Benjamin Otte +Date: Sun, 07 Feb 2010 18:53:11 +0000 +Subject: ftp: put check if a method is supported into its own function + +--- +diff --git a/daemon/gvfsftptask.c b/daemon/gvfsftptask.c +index fcf01ab..5393d0c 100644 +--- a/daemon/gvfsftptask.c ++++ b/daemon/gvfsftptask.c +@@ -983,6 +983,17 @@ struct _GVfsFtpOpenDataConnectionMethod { + GVfsFtpOpenDataConnectionFunc func; + }; + ++static gboolean ++g_vfs_ftp_task_open_data_connection_method_is_supported (const GVfsFtpOpenDataConnectionMethod *method, ++ GVfsFtpTask * task) ++{ ++ if (method->required_feature && ++ !g_vfs_backend_ftp_has_feature (task->backend, method->required_feature)) ++ return FALSE; ++ ++ return TRUE; ++} ++ + static GVfsFtpMethod + g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unused) + { +@@ -998,8 +1009,7 @@ g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unuse + /* first try all advertised features */ + for (i = 0; i < G_N_ELEMENTS (funcs_ordered); i++) + { +- if (funcs_ordered[i].required_feature && +- !g_vfs_backend_ftp_has_feature (task->backend, funcs_ordered[i].required_feature)) ++ if (!g_vfs_ftp_task_open_data_connection_method_is_supported (&funcs_ordered[i], task)) + continue; + method = funcs_ordered[i].func (task, G_VFS_FTP_METHOD_ANY); + if (method != G_VFS_FTP_METHOD_ANY) +@@ -1011,8 +1021,7 @@ g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unuse + /* then try if the non-advertised features work */ + for (i = 0; i < G_N_ELEMENTS (funcs_ordered); i++) + { +- if (!funcs_ordered[i].required_feature || +- g_vfs_backend_ftp_has_feature (task->backend, funcs_ordered[i].required_feature)) ++ if (g_vfs_ftp_task_open_data_connection_method_is_supported (&funcs_ordered[i], task)) + continue; + method = funcs_ordered[i].func (task, G_VFS_FTP_METHOD_ANY); + if (method != G_VFS_FTP_METHOD_ANY) +-- +cgit v0.8.3.1 diff --git a/gvfs-1.5.2-ftp-symlink-target-not-defined.patch b/gvfs-1.5.2-ftp-symlink-target-not-defined.patch new file mode 100644 index 0000000..f08e938 --- /dev/null +++ b/gvfs-1.5.2-ftp-symlink-target-not-defined.patch @@ -0,0 +1,47 @@ +From d3f5454a53127b5c73738e394db461070c81942f Mon Sep 17 00:00:00 2001 +From: Benjamin Otte +Date: Sun, 07 Feb 2010 17:11:50 +0000 +Subject: ftp: Handle cases where symlink target is not defined + +This can happen when systems emulate ls -l output but fail. +Surprisingly, ProFtpd seems to be one of these. + +https://bugzilla.gnome.org/show_bug.cgi?id=608621 +--- +diff --git a/daemon/gvfsftpdircache.c b/daemon/gvfsftpdircache.c +index dffebbc..8ae963a 100644 +--- a/daemon/gvfsftpdircache.c ++++ b/daemon/gvfsftpdircache.c +@@ -241,6 +241,7 @@ g_vfs_ftp_dir_cache_resolve_symlink (GVfsFtpDirCache * cache, + GFileInfo *info, *result; + GVfsFtpFile *tmp, *link; + guint i, lookups = 0; ++ const char *target; + + if (!g_file_info_get_is_symlink (original) || + g_vfs_ftp_task_is_in_error (task)) +@@ -248,10 +249,18 @@ g_vfs_ftp_dir_cache_resolve_symlink (GVfsFtpDirCache * cache, + + info = g_object_ref (original); + link = g_vfs_ftp_file_copy (file); +- do +- { +- /* This must not happen, as we use one of our own GFileInfos */ +- g_assert (g_file_info_get_symlink_target (info) != NULL); ++ do { ++ target = g_file_info_get_symlink_target (info); ++ if (target == NULL) ++ { ++ /* This happens when bad servers don't report a symlink target. ++ * We now want to figure out if this is a directory or regular file, ++ * so we can at least report something useful. ++ */ ++ g_object_unref (info); ++ info = cache->funcs->lookup_uncached (task, file); ++ break; ++ } + tmp = link; + link = cache->funcs->resolve_symlink (task, tmp, g_file_info_get_symlink_target (info)); + g_vfs_ftp_file_free (tmp); +-- +cgit v0.8.3.1 diff --git a/gvfs.spec b/gvfs.spec index 2467ff4..57ad7a0 100644 --- a/gvfs.spec +++ b/gvfs.spec @@ -1,7 +1,7 @@ Summary: Backends for the gio framework in GLib Name: gvfs Version: 1.5.2 -Release: 4%{?dist} +Release: 5%{?dist} License: LGPLv2+ Group: System Environment/Libraries URL: http://www.gtk.org @@ -41,6 +41,13 @@ Patch2: gvfs-1.5.3-use-libimobiledevice.patch # https://bugzilla.redhat.com/show_bug.cgi?id=552856 Patch15: gvfs-1.5.1-gphoto2-no-storageinfo-support.patch +# from upstream +Patch19: gvfs-1.5.2-ftp-symlink-target-not-defined.patch +Patch20: gvfs-1.5.2-ftp-name-data-connection-method.patch +Patch21: gvfs-1.5.2-ftp-separate-data-connection-method-supported.patch +Patch22: gvfs-1.5.2-ftp-PASV-v4.patch +Patch23: gvfs-1.5.2-ftp-PASV-EPASV-v4-v6.patch + Obsoletes: gnome-mount <= 0.8 @@ -140,6 +147,12 @@ including phones and music players to applications using gvfs. %patch1 -p1 -b .afc-buildfix %patch2 -p1 -b .afc-libimobiledevice %patch15 -p1 -b .gphoto2-storageinfo +%patch19 -p1 -b .ftp-symlink-target-not-defined +%patch20 -p1 -b .ftp-name-data-connection-method +%patch21 -p1 -b .ftp-separate-data-connection-method-supported +%patch22 -p1 -b .ftp-PASV-v4 +%patch23 -p1 -b .ftp-PASV-EPASV-v4-v6 + %build @@ -319,6 +332,9 @@ killall -USR1 gvfsd >&/dev/null || : %{_datadir}/gvfs/remote-volume-monitors/afc.monitor %changelog +* Mon Feb 8 2010 Tomas Bzatek - 1.5.2-5 +- ftp: backport several PASV/EPSV fixes from master (#542205, #555033) + * Fri Feb 5 2010 Tomas Bzatek - 1.5.2-4 - AFC: Use new libimobiledevice library