[gvfs/wip/oholy/dav-nextcloud-workaround] dav: Drop user from URI as a workaround for Nextcloud bug




commit db95be024758b9edd020afc33242a938567a3c3b
Author: Ondrej Holy <oholy redhat com>
Date:   Fri Apr 22 09:50:36 2022 +0200

    dav: Drop user from URI as a workaround for Nextcloud bug
    
    Currently, it is not possible to connect to some Nextcloud servers when
    a username is part of URI. So this also affects volumes configured over
    GOA. The main problem seems to be that Nextcloud doesn't send the
    `WWW-Authenticate` header as a part of 401 response in certain cases (e.g.
    when 2FA is enabled). A recent libsoup change leads to the situation that
    DAV backend doesn't have a chance to specify a password as the `authenticate`
    signal is not called at all. This is because libsoup tries to authenticate
    with an empty password first. Let's drop the username from URI to avoid the
    password-less login attempt so the backend has at least one chance to try
    some password in this case...
    
    Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/617

 daemon/gvfsbackenddav.c | 56 ++++++++++++++++++++++++++-----------------------
 1 file changed, 30 insertions(+), 26 deletions(-)
---
diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c
index fd58b2c9..d45cf89a 100644
--- a/daemon/gvfsbackenddav.c
+++ b/daemon/gvfsbackenddav.c
@@ -1845,7 +1845,6 @@ g_mount_spec_to_dav_uri (GMountSpec *spec)
 {
   GUri           *uri;
   const char     *host;
-  const char     *user;
   const char     *port;
   const char     *ssl;
   const char     *path;
@@ -1855,7 +1854,6 @@ g_mount_spec_to_dav_uri (GMountSpec *spec)
   gint            port_num;
 
   host = g_mount_spec_get (spec, "host");
-  user = g_mount_spec_get (spec, "user");
   port = g_mount_spec_get (spec, "port");
   ssl  = g_mount_spec_get (spec, "ssl");
   path = spec->mount_prefix;
@@ -1882,16 +1880,17 @@ g_mount_spec_to_dav_uri (GMountSpec *spec)
 
   path_str = dav_uri_encode (path);
 
-  uri = g_uri_build_with_user (SOUP_HTTP_URI_FLAGS,
-                               scheme,
-                               user,
-                               NULL,
-                               NULL,
-                               host_str,
-                               port_num,
-                               path_str,
-                               NULL,
-                               NULL);
+  /* A username is not part of URI as a workaround for:
+   * https://gitlab.gnome.org/GNOME/gvfs/-/issues/617.
+   */
+  uri = g_uri_build (SOUP_HTTP_URI_FLAGS,
+                     scheme,
+                     NULL,
+                     host_str,
+                     port_num,
+                     path_str,
+                     NULL,
+                     NULL);
 
   g_free (host_str);
   g_free (path_str);
@@ -1906,7 +1905,6 @@ g_mount_spec_from_dav_uri (GVfsBackendDav *dav_backend,
   GMountSpec *spec;
   char *local_path;
   gboolean ssl;
-  const gchar *user;
   gint port_num;
 
 #ifdef HAVE_AVAHI
@@ -1945,10 +1943,6 @@ g_mount_spec_from_dav_uri (GVfsBackendDav *dav_backend,
 
   g_mount_spec_set (spec, "ssl", ssl ? "true" : "false");
 
-  user = g_uri_get_user (uri);
-  if (user != NULL)
-    g_mount_spec_set (spec, "user", user);
-
   port_num = g_uri_get_port (uri);
   if (port_num > 0 && port_num != (ssl ? 443 : 80))
     {
@@ -2047,7 +2041,7 @@ dns_sd_resolver_changed (GVfsDnsSdResolver *resolver,
 /* Backend Functions */
 
 static void
-mount_success (GVfsBackend *backend, GVfsJob *job)
+mount_success (GVfsBackend *backend, GVfsJobMount *job)
 {
   GVfsBackendDav *dav_backend = G_VFS_BACKEND_DAV (backend);
   GVfsBackendHttp *http_backend = G_VFS_BACKEND_HTTP (backend);
@@ -2069,6 +2063,14 @@ mount_success (GVfsBackend *backend, GVfsJob *job)
   /* dup the mountspec, but only copy known fields */
   mount_spec = g_mount_spec_from_dav_uri (dav_backend, http_backend->mount_base);
 
+  /* A username is not part of URI as a workaround for:
+   * https://gitlab.gnome.org/GNOME/gvfs/-/issues/617
+   * So it has to be restored here in order to avoid:
+   * https://gitlab.gnome.org/GNOME/gvfs/-/issues/614
+   */
+  g_mount_spec_set (mount_spec, "user",
+                    g_mount_spec_get (job->mount_spec, "user"));
+
   g_vfs_backend_set_mount_spec (backend, mount_spec);
   g_vfs_backend_set_icon_name (backend, "folder-remote");
   g_vfs_backend_set_symbolic_icon_name (backend, "folder-remote-symbolic");
@@ -2119,7 +2121,7 @@ try_mount_stat_cb (GObject *source, GAsyncResult *result, gpointer user_data)
       if (dav_backend->last_good_path == NULL)
         g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
       else
-        mount_success (backend, G_VFS_JOB (job));
+        mount_success (backend, job);
       g_error_free (error);
       goto clear_msg;
     }
@@ -2133,7 +2135,7 @@ try_mount_stat_cb (GObject *source, GAsyncResult *result, gpointer user_data)
 
   if ((is_collection == FALSE) && (dav_backend->last_good_path != NULL))
     {
-      mount_success (backend, G_VFS_JOB (job));
+      mount_success (backend, job);
       goto clear_msg;
     }
   else if (res == FALSE)
@@ -2175,7 +2177,7 @@ try_mount_stat_cb (GObject *source, GAsyncResult *result, gpointer user_data)
   /* break out */
   if (g_strcmp0 (dav_backend->last_good_path, "/") == 0)
     {
-      mount_success (backend, G_VFS_JOB (job));
+      mount_success (backend, job);
       goto clear_msg;
     }
 
@@ -2248,7 +2250,7 @@ try_mount_opts_cb (GObject *source, GAsyncResult *result, gpointer user_data)
       if (dav_backend->last_good_path == NULL)
         g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
       else
-        mount_success (backend, G_VFS_JOB (job));
+        mount_success (backend, job);
       g_error_free (error);
       goto clear_msgs;
     }
@@ -2295,7 +2297,7 @@ try_mount_opts_cb (GObject *source, GAsyncResult *result, gpointer user_data)
                           G_IO_ERROR, G_IO_ERROR_FAILED,
                           _("Not a WebDAV enabled share"));
       else
-        mount_success (backend, G_VFS_JOB (job));
+        mount_success (backend, job);
       goto clear_msgs;
     }
   else if (!is_success)
@@ -2308,7 +2310,7 @@ try_mount_opts_cb (GObject *source, GAsyncResult *result, gpointer user_data)
                           _("HTTP Error: %s"),
                           soup_message_get_reason_phrase (msg_opts));
       else
-        mount_success (backend, G_VFS_JOB (job));
+        mount_success (backend, job);
       goto clear_msgs;
     }
 
@@ -2317,7 +2319,7 @@ try_mount_opts_cb (GObject *source, GAsyncResult *result, gpointer user_data)
       if (dav_backend->last_good_path == NULL)
         g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
       else
-        mount_success (backend, G_VFS_JOB (job));
+        mount_success (backend, job);
       g_error_free (error);
       goto clear_msgs;
     }
@@ -2351,11 +2353,13 @@ try_mount (GVfsBackend  *backend,
   GUri            *mount_base;
   const char      *host;
   const char      *type;
+  const char      *user;
 
   g_debug ("+ mount\n");
 
   host = g_mount_spec_get (mount_spec, "host");
   type = g_mount_spec_get (mount_spec, "type");
+  user = g_mount_spec_get (mount_spec, "user");
 
 #ifdef HAVE_AVAHI
   /* resolve DNS-SD style URIs */
@@ -2401,7 +2405,7 @@ try_mount (GVfsBackend  *backend,
                                     SOUP_TYPE_AUTH_NTLM);
 
   dav_backend->auth_info.mount_source = g_object_ref (mount_source);
-  dav_backend->auth_info.server_auth.username = g_strdup (g_uri_get_user (mount_base));
+  dav_backend->auth_info.server_auth.username = g_strdup (user);
   dav_backend->auth_info.server_auth.pw_save = G_PASSWORD_SAVE_NEVER;
   dav_backend->auth_info.proxy_auth.pw_save = G_PASSWORD_SAVE_NEVER;
   dav_backend->auth_info.interactive = TRUE;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]