Re: Authentication Cache for libsmb (gnome-vfs-extras)



Am Mit, 2002-11-20 um 04.00 schrieb Alex Graveley:
> Hi,
> 
> On Tue, 2002-11-19 at 18:45, Knut Neumann rz uni-duesseldorf de wrote:
> > the attached patch will add an authentication cache system to libsmb:
> 
> No patch attached :-)

Ok. I will try it again...hopefully it works this time. I have to add
that from what I have seen in a quick look I would vote to replace head
with ximian-smb. It seems to be a quite clean codebase.

-Knut
-- 
Knut Neumann <knut neumann uni-duesseldorf de>
Physikalische Grundpraktika - Heinrich-Heine Universitaet Duesseldorf
Raum 25.33.01.63  -   Universitaetsstrasse 1   -  D-40225 Duesseldorf
fon: +49-211-81-11314                           fax: +49-211-81-13105








--- gnome-vfs-extras.virgin/smb-method.c	2002-11-13 16:27:33.000000000 +0100
+++ gnome-vfs-extras/smb-method.c	2002-11-20 23:39:10.000000000 +0100
@@ -162,7 +162,7 @@
 extern pstring global_myname;
 
 static GHashTable *virtual_hash = NULL;
-static GHashTable *server_auth_infos = NULL;
+static GHashTable *auth_info_cache = NULL;
 
 #undef DEBUG_SMB_ENABLE
 #undef DEBUG_SMB_LOCKS
@@ -181,8 +181,188 @@
 #define UNLOCK_SAMBA() 	g_mutex_unlock (samba_lock)
 #endif
 
+static void
+auth_info_cache_destroy_value (SmbAuthInfo *auth_info) {
+
+	g_free (auth_info->user);
+	g_free (auth_info->password);
+	g_free (auth_info);
+}
+
+static void
+put_auth_to_cache (SmbAuthInfo *auth_info, gchar *server, gchar *share)
+{
+	gchar *key;
+	
+	DEBUG_SMB (("put_auth_to_cache\n"));
+
+	if (!server)
+		return;
+	
+	if (share) {
+		key = g_strdup_printf ("smb://%s%s", server, share);
+		g_hash_table_insert (auth_info_cache, key, auth_info);
+		key = g_strdup_printf ("smb://%s/<lastshare>", server);
+		g_hash_table_insert (auth_info_cache, key, auth_info);
+	} else {
+		key = g_strdup_printf ("smb://%s", server);
+		g_hash_table_insert (auth_info_cache, key, auth_info);
+	}
+}
+
+SmbAuthInfo *
+get_auth_from_cache (gchar *server, gchar *share)
+{
+	SmbAuthInfo *auth_info = NULL;
+	gchar *key;
+	
+	DEBUG_SMB (("get_auth_from_cache\n"));
+
+	if (!server)
+		return auth_info;
+	
+	if (share) {
+		key = g_strdup_printf ("smb://%s%s", server, share);
+		auth_info = g_hash_table_lookup (auth_info_cache, key);
+		g_free (key);
+		if (!auth_info) {
+			key = g_strdup_printf ("smb://%s/<lastshare>", server);
+			auth_info = g_hash_table_lookup (auth_info_cache, key);
+			g_free (key);
+		}
+	} else {
+		key = g_strdup_printf ("smb://%s", server);
+		auth_info = g_hash_table_lookup (auth_info_cache, key);
+		g_free (key);
+	}
+
+	return auth_info;
+}
+
+SmbAuthInfo *
+get_auth_from_dialog (gchar *server, gchar *share)
+{
+	GnomeVFSModuleCallbackAuthenticationIn in_args;
+	GnomeVFSModuleCallbackAuthenticationOut out_args;
+	SmbAuthInfo *auth_info = NULL;
+	GnomeVFSResult res = 0;
+	
+	DEBUG_SMB (("get_auth_from_dialog\n"));
 
+	memset (&in_args, 0, sizeof (in_args));
+	memset (&out_args, 0, sizeof (out_args));
+
+	if (share) {
+		in_args.uri = g_strdup_printf ("smb://%s%s", server, share);
+	}
+	else {
+		in_args.uri = g_strdup_printf ("smb://%s", server);
+	}
+	
+	UNLOCK_SAMBA();
+		
+	res = gnome_vfs_module_callback_invoke (GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
+						&in_args, sizeof (in_args), 
+						&out_args, sizeof (out_args));
+	
+	LOCK_SAMBA();
+
+	g_free (in_args.uri);
+
+	if (res && out_args.username)
+	{
+		auth_info = g_new (SmbAuthInfo, 1);
+		
+		auth_info->user = out_args.username;
+		auth_info->password = out_args.password;
+	}
+	
+	return auth_info;
+}
+
+SmbAuthInfo *
+get_auth_from_uri (GnomeVFSURI *uri)
+{
+	SmbAuthInfo *auth_info = NULL;
+	gchar *user;
+	
+	DEBUG_SMB (("get_auth_from_uri\n"));
+
+	user = gnome_vfs_unescape_string (gnome_vfs_uri_get_user_name (uri), NULL);
+	
+	if (user) {
+		auth_info = g_new (SmbAuthInfo, 1);
+		auth_info->user = user;
+		auth_info->password = gnome_vfs_unescape_string (gnome_vfs_uri_get_password (uri), NULL);
+	}
+	
+	return auth_info;
+}
 
+static int
+get_auth_by_server (SmbAuthInfo *auth_info, gchar *server, gchar *share, gboolean previous_failed)
+{
+	SmbAuthInfo *auth = NULL;
+	
+	DEBUG_SMB (("get_auth_by_server\n"));
+
+	auth_info->user = NULL;
+	auth_info->password = NULL;
+	
+	if (previous_failed) {
+		auth = get_auth_from_dialog (server, share);
+		if (auth)
+			put_auth_to_cache (auth, server, share);
+	}
+	else
+		auth = get_auth_from_cache (server, share);
+	
+	if (auth) {
+		auth_info->user = auth->user;
+		auth_info->password = auth->password;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static int
+get_auth_by_uri (SmbAuthInfo *auth_info, GnomeVFSURI *uri, gboolean previous_failed)
+{
+	SmbAuthInfo *auth = NULL;
+	gchar *server;
+	gchar *share;
+	int res = 0;
+	
+	DEBUG_SMB (("get_auth_by_uri\n"));
+
+	auth_info->user = NULL;
+	auth_info->password = NULL;
+
+	server = gnome_vfs_unescape_string (gnome_vfs_uri_get_host_name (uri), NULL);
+	share = gnome_vfs_unescape_string (gnome_vfs_uri_get_path (uri), NULL);
+
+	if (!previous_failed) {
+		auth = get_auth_from_uri (uri);
+		if (auth) {
+			put_auth_to_cache (auth, server, share);
+
+			auth_info->user = auth->user;
+			auth_info->password = auth->password;
+
+			return TRUE;
+		}
+	}
+
+	res = get_auth_by_server (auth_info, server, share, previous_failed);
+
+	g_free (server);
+	g_free (share);
+
+	return res;
+}
+		
 /* FIXME / TODO:
  *
  * Free unused virtual roots + connections after a while
@@ -874,6 +1054,7 @@
 	dir->u.directory.dir_contents =
 		g_list_prepend (dir->u.directory.dir_contents, file);
 }
+
 static GnomeVFSResult
 build_server_tree (SmbVirtualFile **out, const char *name)
 {
@@ -885,10 +1066,7 @@
 	struct in_addr ip;
 	SmbConnection *connection;
 	gboolean found_workgroup;
-	SmbAuthInfo *auth_info;
-	char *user, *password;
-	GnomeVFSModuleCallbackAuthenticationIn in_args;
-	GnomeVFSModuleCallbackAuthenticationOut out_args;
+	SmbAuthInfo auth_info;
 	gboolean got_shares;
 	
 	DEBUG_SMB (("build_server_tree (%s)\n", name));
@@ -929,27 +1107,16 @@
 
 	DEBUG_SMB (("Enumerating shares in server %s\n", name));
 
-	user = NULL;
-	password = NULL;
-	
-	auth_info = g_hash_table_lookup (server_auth_infos, name);
-
-	if (auth_info) {
-		user = g_strdup (auth_info->user);
-		password = g_strdup (auth_info->password);
-	}
-
-	memset (&in_args, 0, sizeof (in_args));
-
-	in_args.uri = g_strdup_printf ("smb://%s", name);
 	got_shares = FALSE;
+
+	get_auth_by_server (&auth_info, (gchar *) name, NULL, FALSE);
 	
 	while (TRUE) {
 		/* Look for shares in the server named name */
 		res = smb_server_connection_new (name,
 						 "IPC$",
-						 user /* user */,
-						 password /* pwd */,
+						 auth_info.user /* user */,
+						 auth_info.password /* pwd */,
 						 &connection);
 		if (!res) {
 			ret = cli_RNetShareEnum (connection->cli,
@@ -957,21 +1124,9 @@
 			if (ret == -1) {
 				error = cli_error(connection->cli, NULL, NULL, NULL);
 				if (error == EACCES) {
-					memset (&out_args, 0, sizeof (out_args));
-					UNLOCK_SAMBA();
-					res = gnome_vfs_module_callback_invoke (GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
-										&in_args, sizeof (in_args), 
-										&out_args, sizeof (out_args));
-					LOCK_SAMBA();
-					if (!res || (out_args.username == NULL)) {
+					if (!get_auth_by_server (&auth_info, (gchar *) name, NULL, TRUE)) {
 						break;
 					} else {
-						g_free (user);
-						g_free (password);
-						
-						user = out_args.username;
-						password = out_args.password;
-						
 						smb_connection_unref (connection);
 						
 						continue;
@@ -989,32 +1144,6 @@
 	}
 	DEBUG_SMB (("Done enumerating shares in server %s\n", name));
 
-	g_free (in_args.uri);
-
-	if (!got_shares) {
-		if (auth_info == NULL || auth_info->user != user)
-			g_free (user);
-		if (auth_info == NULL || auth_info->password != password)
-			g_free (password);
-	} else if (user != NULL || password != NULL) {
-		if (auth_info == NULL) {
-			auth_info = g_new (SmbAuthInfo, 1);
-			auth_info->user = user;
-			auth_info->password = password;
-			g_hash_table_insert (server_auth_infos, g_strdup (name), auth_info);
-		}
-
-		if (auth_info->user != user) {
-			g_free (auth_info->user);
-			auth_info->user = user;
-		}
-		
-		if (auth_info->password != password) {
-			g_free (auth_info->password);
-			auth_info->password = password;
-		}
-	}
-	
 	/* Add .directory file */
 	file = smb_virtual_file_new (SMB_VIRTUAL_TYPE_FILE);
 	file->name = g_strdup (".directory");
@@ -1076,8 +1205,7 @@
 	SmbVirtualRoot key;
 	time_t now;
 	GnomeVFSResult res;
-	char *user;
-	char *password;
+	SmbAuthInfo auth_info;
 	
 	DEBUG_SMB (("lookup_uri (uri: %s)\n", gnome_vfs_uri_to_string (uri, 0)));
 	
@@ -1150,58 +1278,21 @@
 	    ((path_remainder != NULL) ||
 	     open_connection_for_share_file)) {
 		if ((*file)->u.share.connection == NULL) {
-			GnomeVFSModuleCallbackAuthenticationIn in_args;
-			GnomeVFSModuleCallbackAuthenticationOut out_args;
-			gboolean previous_attempt_failed;
-
-			memset (&in_args, 0, sizeof (in_args));
-			
-			in_args.uri = g_strdup_printf ("smb://%s/%s",
-						       (*file)->u.share.server,
-						       (*file)->u.share.share);
-
-			user = gnome_vfs_unescape_string (gnome_vfs_uri_get_user_name (uri), NULL);
-			password = gnome_vfs_unescape_string (gnome_vfs_uri_get_password (uri), NULL);
-
-			/* Don't consider it failed if it was an anon try */
-			previous_attempt_failed = (user == NULL) ? FALSE : TRUE;
-
+			get_auth_by_uri (&auth_info, uri, FALSE);
 			while (TRUE) {
 				res = smb_server_connection_new ((*file)->u.share.server,
 								 (*file)->u.share.share,
-								 user,
-								 password,
+								 auth_info.user,
+								 auth_info.password,
 								 &(*file)->u.share.connection);
 				if (res == GNOME_VFS_ERROR_LOGIN_FAILED) {
-					memset (&out_args, 0, sizeof (out_args));
-					UNLOCK_SAMBA();
-					res = gnome_vfs_module_callback_invoke (GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
-										&in_args, sizeof (in_args), 
-										&out_args, sizeof (out_args));
-					LOCK_SAMBA();
-					if (res == FALSE) {
-						res = GNOME_VFS_ERROR_ACCESS_DENIED;
-						break;
-					} else if (out_args.username == NULL) {
-						res = GNOME_VFS_ERROR_ACCESS_DENIED;
+					if (!get_auth_by_uri (&auth_info, uri, TRUE))
 						break;
-					} else {
-						g_free (user);
-						g_free (password);
-						
-						user = out_args.username;
-						password = out_args.password;
-					}
-					previous_attempt_failed = TRUE;
 				} else {
 					/* Error, or logged in ok */
 					break;
 				}
 			}
-
-			g_free (in_args.uri);
-			g_free (user);
-			g_free (password);
 			
 			if (res != GNOME_VFS_OK) {
 				(*file)->u.share.connection = NULL;
@@ -2504,7 +2595,7 @@
 		DEBUG_SMB (("Couldn't load smb config file"));
 	}
 
-	server_auth_infos = g_hash_table_new (g_str_hash, g_str_equal);
+	auth_info_cache = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) auth_info_cache_destroy_value);
 	
 	codepage_initialise (lp_client_code_page());
 
@@ -2525,5 +2616,6 @@
 vfs_module_shutdown (GnomeVFSMethod *method)
 {
 	DEBUG_SMB (("<-- smb module shutdown called -->\n"));
+	g_hash_table_destroy (auth_info_cache);
 }
 


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