diff -ur gvfs-orig/gvfs-0.2.2svn20080403/daemon/gvfsbackendsmbbrowse.c gvfs/gvfs-0.2.2svn20080403/daemon/gvfsbackendsmbbrowse.c --- gvfs-orig/gvfs-0.2.2svn20080403/daemon/gvfsbackendsmbbrowse.c 2008-04-02 13:10:59.000000000 -0700 +++ gvfs/gvfs-0.2.2svn20080403/daemon/gvfsbackendsmbbrowse.c 2008-04-03 20:36:18.000000000 -0700 @@ -41,6 +41,7 @@ #include "gvfsjobqueryinfo.h" #include "gvfsjobenumerate.h" #include "gvfsdaemonprotocol.h" +#include "gvfskeyring.h" #include "gmounttracker.h" #include @@ -74,6 +75,17 @@ char *mounted_server; /* server or DEFAULT_WORKGROUP_NAME */ SMBCCTX *smb_context; + char *last_user; + char *last_domain; + char *last_password; + + GMountSource *mount_source; + int mount_try; + gboolean mount_try_again; + + gboolean password_in_keyring; + GPasswordSave password_save; + GMutex *entries_lock; time_t last_entry_update; GList *entries; @@ -256,14 +268,118 @@ char *password_out, int pwmaxlen) { GVfsBackendSmbBrowse *backend; + char *ask_password, *ask_user, *ask_domain; + gboolean handled, abort; backend = smbc_getOptionUserData (context); + strncpy (password_out, "", pwmaxlen); + if (backend->domain) strncpy (domain_out, backend->domain, domainmaxlen); if (backend->user) strncpy (username_out, backend->user, unmaxlen); - strncpy (password_out, "", pwmaxlen); + + if (backend->mount_source == NULL) + { + /* Not during mount, use last password */ + if (backend->last_user) + strncpy (username_out, backend->last_user, unmaxlen); + if (backend->last_domain) + strncpy (domain_out, backend->last_domain, domainmaxlen); + if (backend->last_password) + strncpy (password_out, backend->last_password, pwmaxlen); + + return; + } + + if (backend->mount_try == 0 && + backend->user == NULL && + backend->domain == NULL) + { + /* Try anon login */ + strncpy (username_out, "", unmaxlen); + strncpy (password_out, "", pwmaxlen); + /* Try again if anon login fails */ + backend->mount_try_again = TRUE; + } + else + { + gboolean in_keyring = FALSE; + + if (!backend->password_in_keyring) + { + in_keyring = g_vfs_keyring_lookup_password (backend->user, + backend->server, + backend->domain, + "smb", + NULL, + NULL, + 0, + &ask_user, + &ask_domain, + &ask_password); + backend->password_in_keyring = in_keyring; + } + + + if (!in_keyring) + { + GAskPasswordFlags flags = G_ASK_PASSWORD_NEED_PASSWORD; + char *message; + + if (g_vfs_keyring_is_available ()) + flags |= G_ASK_PASSWORD_SAVING_SUPPORTED; + if (backend->domain == NULL) + flags |= G_ASK_PASSWORD_NEED_DOMAIN; + if (backend->user == NULL) + flags |= G_ASK_PASSWORD_NEED_USERNAME; + + /* translators: %s is a server name */ + message = g_strdup_printf (_("Password required for %s"), + server_name); + handled = g_mount_source_ask_password (backend->mount_source, + message, + username_out, + domain_out, + flags, + &abort, + &ask_password, + &ask_user, + &ask_domain, + NULL, + &(backend->password_save)); + g_free (message); + if (!handled) + goto out; + + if (abort) + { + strncpy (username_out, "ABORT", unmaxlen); + strncpy (password_out, "", pwmaxlen); + goto out; + } + } + + /* Try again if this fails */ + backend->mount_try_again = TRUE; + + strncpy (password_out, ask_password, pwmaxlen); + if (ask_user && *ask_user) + strncpy (username_out, ask_user, unmaxlen); + if (ask_domain && *ask_domain) + strncpy (domain_out, ask_domain, domainmaxlen); + + out: + g_free (ask_password); + g_free (ask_user); + g_free (ask_domain); + } + + backend->last_user = g_strdup (username_out); + backend->last_domain = g_strdup (domain_out); + backend->last_password = g_strdup (password_out); + } /* Add a server to the cache system @@ -635,9 +751,13 @@ { GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend); SMBCCTX *smb_context; + SMBCFILE *dir; char *display_name; char *icon; + GString *uri; GMountSpec *browse_mount_spec; + smbc_opendir_fn smbc_opendir; + smbc_closedir_fn smbc_closedir; smb_context = smbc_new_context (); if (smb_context == NULL) @@ -668,7 +788,7 @@ smbc_setOptionUseKerberos (smb_context, 1); smbc_setOptionFallbackAfterKerberos (smb_context, 1); - //smbc_setOptionNoAutoAnonymousLogin (smb_context, 1); + smbc_setOptionNoAutoAnonymousLogin (smb_context, 1); #if 0 @@ -723,6 +843,61 @@ g_vfs_backend_set_mount_spec (backend, browse_mount_spec); g_mount_spec_unref (browse_mount_spec); + op_backend->mount_source = mount_source; + op_backend->mount_try = 0; + op_backend->password_save = G_PASSWORD_SAVE_NEVER; + + smbc_opendir = smbc_getFunctionOpendir (smb_context); + smbc_closedir = smbc_getFunctionClosedir (smb_context); + + uri = g_string_new ("smb://"); + + if (op_backend->server) + { + g_string_append_encoded (uri, op_backend->server, NULL, NULL); + g_string_append_c (uri, '/'); + } + + do + { + op_backend->mount_try_again = FALSE; + + dir = smbc_opendir (smb_context, uri->str); + + if (dir != NULL) { + smbc_closedir (smb_context, dir); + break; + } + + op_backend->mount_try ++; + } + while (op_backend->mount_try_again); + + g_string_free (uri, TRUE); + + op_backend->mount_source = NULL; + + if (dir == NULL) + { + /* TODO: Error from errno? */ + op_backend->mount_source = NULL; + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, G_IO_ERROR_FAILED, + /* translators: We tried to mount a windows (samba) share, but failed */ + _("Failed to mount Windows share")); + return; + } + + g_vfs_keyring_save_password (op_backend->last_user, + op_backend->server, + op_backend->last_domain, + "smb", + NULL, + NULL, + 0, + op_backend->last_password, + op_backend->password_save); + g_vfs_job_succeeded (G_VFS_JOB (job)); }