Index: daemon/gvfsbackendsmbbrowse.c
===================================================================
--- daemon/gvfsbackendsmbbrowse.c	(revision 1810)
+++ daemon/gvfsbackendsmbbrowse.c	(working copy)
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include <glib/gstdio.h>
 #include <glib/gi18n.h>
@@ -41,6 +42,7 @@
 #include "gvfsjobqueryinfo.h"
 #include "gvfsjobenumerate.h"
 #include "gvfsdaemonprotocol.h"
+#include "gvfskeyring.h"
 #include "gmounttracker.h"
 
 #include <libsmbclient.h>
@@ -74,6 +76,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 +269,127 @@
 	       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 again if kerberos login fails */
+      backend->mount_try_again = TRUE;
+    }
+  else
+  if (backend->mount_try == 1 &&
+      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,10 +761,20 @@
 {
   GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
   SMBCCTX *smb_context;
+  SMBCFILE *dir;
   char *display_name;
+  const char *debug;
+  int debug_val;
   char *icon;
+  GString *uri;
+  int res;
+  char dirents[1024*4];
   GMountSpec *browse_mount_spec;
-
+  smbc_opendir_fn smbc_opendir;
+  smbc_closedir_fn smbc_closedir;
+  smbc_stat_fn smbc_stat;
+  smbc_getdents_fn smbc_getdents;
+    
   smb_context = smbc_new_context ();
   if (smb_context == NULL)
     {
@@ -650,7 +786,13 @@
 
   smbc_setOptionUserData (smb_context, backend);
 
-  smbc_setDebug (smb_context, 0);
+  debug = g_getenv ("GVFS_SMB_DEBUG");
+  if (debug)
+    debug_val = atoi (debug);
+  else
+    debug_val = 0;
+
+  smbc_setDebug (smb_context, debug_val);
   smbc_setFunctionAuthDataWithContext (smb_context, auth_callback);
   
   smbc_setFunctionAddCachedServer (smb_context, add_cached_server);
@@ -668,7 +810,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 +865,63 @@
   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);
+  smbc_stat = smbc_getFunctionStat (smb_context);
+  smbc_getdents = smbc_getFunctionGetdents (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) {
+        res = smbc_getdents (smb_context, dir, (struct smbc_dirent *)dirents, sizeof (dirents));
+        smbc_closedir (smb_context, dir);
+        if (res > 0) 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 retrieve share list from server"));
+      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));
 }
 
