[gvfs] afp: split out server logic into a separate class
- From: Christian Kellner <gicmo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] afp: split out server logic into a separate class
- Date: Thu, 25 Aug 2011 19:21:36 +0000 (UTC)
commit 92301b7aa9d6c55c17013ecf7261982b82cf3eaf
Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
Date: Mon Jun 13 23:09:12 2011 +0200
afp: split out server logic into a separate class
daemon/Makefile.am | 4 +-
daemon/gvfsafpserver.c | 637 +++++++++++++++++++++++++++++++++++++++++++++++
daemon/gvfsafpserver.h | 83 ++++++
daemon/gvfsbackendafp.c | 580 ++-----------------------------------------
daemon/gvfsbackendafp.h | 33 ---
5 files changed, 746 insertions(+), 591 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 816387e..b5edeb8 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -477,7 +477,9 @@ gvfsd_afp_SOURCES = \
daemon-main.c daemon-main.h \
daemon-main-generic.c \
gvfsafpconnection.h \
- gvfsafpconnection.c
+ gvfsafpconnection.c \
+ gvfsafpserver.h \
+ gvfsafpserver.c
gvfsd_afp_CPPFLAGS = \
-DBACKEND_HEADER=gvfsbackendafp.h \
diff --git a/daemon/gvfsafpserver.c b/daemon/gvfsafpserver.c
new file mode 100644
index 0000000..b8f0059
--- /dev/null
+++ b/daemon/gvfsafpserver.c
@@ -0,0 +1,637 @@
+ /* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) Carl-Anton Ingmarsson 2011 <ca ingmarsson gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+
+#ifdef HAVE_GCRYPT
+#include <gcrypt.h>
+#endif
+
+#include "gvfskeyring.h"
+
+#include "gvfsafpserver.h"
+
+G_DEFINE_TYPE (GVfsAfpServer, g_vfs_afp_server, G_TYPE_OBJECT);
+
+#define AFP_UAM_NO_USER "No User Authent"
+#define AFP_UAM_DHX "DHCAST128"
+#define AFP_UAM_DHX2 "DHX2"
+
+static const char *
+afp_version_to_string (AfpVersion afp_version)
+{
+ const char *version_strings[] = { "AFPX03", "AFP3.1", "AFP3.2", "AFP3.3" };
+
+ return version_strings[afp_version - 1];
+}
+
+static AfpVersion
+string_to_afp_version (const char *str)
+{
+ gint i;
+
+ const char *version_strings[] = { "AFPX03", "AFP3.1", "AFP3.2", "AFP3.3" };
+
+ for (i = 0; i < G_N_ELEMENTS (version_strings); i++)
+ {
+ if (g_str_equal (str, version_strings[i]))
+ return i + 1;
+ }
+
+ return AFP_VERSION_INVALID;
+}
+
+#ifdef HAVE_GCRYPT
+static gboolean
+dhx_login (GVfsAfpServer *afp_serv,
+ const char *username,
+ const char *password,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gcry_error_t gcry_err;
+ gcry_mpi_t prime, base;
+ gcry_mpi_t ra;
+
+ /* Ma */
+ gcry_mpi_t ma;
+ guint8 ma_buf[16];
+
+ GVfsAfpCommand *comm;
+ GVfsAfpReply *reply;
+ AfpResultCode res_code;
+ gboolean res;
+ guint16 id;
+
+ /* Mb */
+ guint8 mb_buf[16];
+ gcry_mpi_t mb;
+
+ /* Nonce */
+ guint8 nonce_buf[32];
+ gcry_mpi_t nonce, nonce1;
+
+ /* Key */
+ gcry_mpi_t key;
+ guint8 key_buf[16];
+
+ gcry_cipher_hd_t cipher;
+ guint8 answer_buf[80] = { 0 };
+ size_t len;
+
+ static const guint8 C2SIV[] = { 0x4c, 0x57, 0x61, 0x6c, 0x6c, 0x61, 0x63, 0x65 };
+ static const guint8 S2CIV[] = { 0x43, 0x4a, 0x61, 0x6c, 0x62, 0x65, 0x72, 0x74 };
+ static const guint8 p[] = { 0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4, 0x3F, 0x20, 0x24, 0x74, 0x4C, 0xEE, 0xE7, 0x5B };
+ static const guint8 g[] = { 0x07 };
+
+ if (strlen (password) > 64)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Server doesn't support passwords longer than 64 characters"));
+ return FALSE;
+ }
+
+ /* create prime and base from vectors */
+ gcry_err = gcry_mpi_scan (&prime, GCRYMPI_FMT_USG, p, G_N_ELEMENTS (p), NULL);
+ g_assert (gcry_err == 0);
+
+ gcry_err = gcry_mpi_scan (&base, GCRYMPI_FMT_USG, g, G_N_ELEMENTS (g), NULL);
+ g_assert (gcry_err == 0);
+
+ /* generate random number ra != 0 */
+ ra = gcry_mpi_new (256);
+ while (gcry_mpi_cmp_ui (ra, 0) == 0)
+ gcry_mpi_randomize (ra, 256, GCRY_STRONG_RANDOM);
+
+ /* Secret key value must be less than half of prime */
+ if (gcry_mpi_get_nbits (ra) > 255)
+ gcry_mpi_clear_highbit (ra, 255);
+
+ /* generate ma */
+ ma = gcry_mpi_new (128);
+ gcry_mpi_powm (ma, base, ra, prime);
+ gcry_mpi_release (base);
+ gcry_err = gcry_mpi_print (GCRYMPI_FMT_USG, ma_buf, G_N_ELEMENTS (ma_buf), NULL,
+ ma);
+ g_assert (gcry_err == 0);
+ gcry_mpi_release (ma);
+
+ /* Create login command */
+ comm = g_vfs_afp_command_new (AFP_COMMAND_LOGIN);
+ g_vfs_afp_command_put_pascal (comm, afp_version_to_string (afp_serv->version));
+ g_vfs_afp_command_put_pascal (comm, AFP_UAM_DHX);
+ g_vfs_afp_command_put_pascal (comm, username);
+ g_vfs_afp_command_pad_to_even (comm);
+ g_output_stream_write_all (G_OUTPUT_STREAM(comm), ma_buf, G_N_ELEMENTS (ma_buf),
+ NULL, NULL, NULL);
+
+ res = g_vfs_afp_connection_send_command_sync (afp_serv->conn, comm,
+ cancellable, error);
+ g_object_unref (comm);
+ if (!res)
+ goto done;
+
+ reply = g_vfs_afp_connection_read_reply_sync (afp_serv->conn, cancellable, error);
+ if (!reply)
+ goto error;
+
+ res_code = g_vfs_afp_reply_get_result_code (reply);
+ if (res_code != AFP_RESULT_AUTH_CONTINUE)
+ {
+ g_object_unref (reply);
+ if (res_code == AFP_RESULT_USER_NOT_AUTH)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("An invalid username was provided"));
+ goto error;
+ }
+ else
+ goto generic_error;
+ }
+
+ id = g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply),
+ NULL, NULL);
+
+ /* read Mb */
+ g_input_stream_read_all (G_INPUT_STREAM (reply), mb_buf, G_N_ELEMENTS (mb_buf),
+ NULL, NULL, NULL);
+ gcry_err = gcry_mpi_scan (&mb, GCRYMPI_FMT_USG, mb_buf, G_N_ELEMENTS (mb_buf), NULL);
+ g_assert (gcry_err == 0);
+
+ /* read Nonce */
+ g_input_stream_read_all (G_INPUT_STREAM (reply), nonce_buf, G_N_ELEMENTS (nonce_buf),
+ NULL, NULL, NULL);
+
+ g_object_unref (reply);
+
+ /* derive key */
+ key = gcry_mpi_new (128);
+ gcry_mpi_powm (key, mb, ra, prime);
+ gcry_mpi_release (mb);
+ gcry_err = gcry_mpi_print (GCRYMPI_FMT_USG, key_buf, G_N_ELEMENTS (key_buf), NULL,
+ key);
+ g_assert (gcry_err == 0);
+ gcry_mpi_release (key);
+
+ /* setup decrypt cipher */
+ gcry_err = gcry_cipher_open (&cipher, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC,
+ 0);
+ g_assert (gcry_err == 0);
+
+ gcry_cipher_setiv (cipher, S2CIV, G_N_ELEMENTS (S2CIV));
+ gcry_cipher_setkey (cipher, key_buf, G_N_ELEMENTS (key_buf));
+
+ /* decrypt Nonce */
+ gcry_err = gcry_cipher_decrypt (cipher, nonce_buf, G_N_ELEMENTS (nonce_buf),
+ NULL, 0);
+ g_assert (gcry_err == 0);
+
+ gcry_err = gcry_mpi_scan (&nonce, GCRYMPI_FMT_USG, nonce_buf, 16, NULL);
+ g_assert (gcry_err == 0);
+
+ /* add one to nonce */
+ nonce1 = gcry_mpi_new (128);
+ gcry_mpi_add_ui (nonce1, nonce, 1);
+ gcry_mpi_release (nonce);
+
+ /* set client->server initialization vector */
+ gcry_cipher_setiv (cipher, C2SIV, G_N_ELEMENTS (C2SIV));
+
+ /* create encrypted answer */
+ gcry_err = gcry_mpi_print (GCRYMPI_FMT_USG, answer_buf, 16, &len, nonce1);
+ g_assert (gcry_err == 0);
+ gcry_mpi_release (nonce1);
+
+ if (len < 16)
+ {
+ memmove(answer_buf + 16 - len, answer_buf, len);
+ memset(answer_buf, 0, 16 - len);
+ }
+
+ memcpy (answer_buf + 16, password, strlen (password));
+
+ gcry_err = gcry_cipher_encrypt (cipher, answer_buf, G_N_ELEMENTS (answer_buf),
+ NULL, 0);
+ g_assert (gcry_err == 0);
+
+
+ /* Create Login Continue command */
+ comm = g_vfs_afp_command_new (AFP_COMMAND_LOGIN_CONT);
+ g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
+ g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (comm), id, NULL, NULL);
+ g_output_stream_write_all (G_OUTPUT_STREAM (comm), answer_buf,
+ G_N_ELEMENTS (answer_buf), NULL, NULL, NULL);
+
+
+ res = g_vfs_afp_connection_send_command_sync (afp_serv->conn, comm,
+ cancellable, error);
+ g_object_unref (comm);
+ if (!res)
+ goto done;
+
+ reply = g_vfs_afp_connection_read_reply_sync (afp_serv->conn, cancellable, error);
+ if (!reply)
+ goto error;
+
+ res_code = g_vfs_afp_reply_get_result_code (reply);
+ g_object_unref (reply);
+ if (res_code != AFP_RESULT_NO_ERROR)
+ {
+ if (res_code == AFP_RESULT_USER_NOT_AUTH)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Server \"%s\" declined the submitted password"),
+ afp_serv->server_name);
+ goto error;
+ }
+ else
+ goto generic_error;
+ }
+
+ res = TRUE;
+
+done:
+ gcry_mpi_release (prime);
+ gcry_mpi_release (ra);
+
+ return res;
+
+error:
+ res = FALSE;
+ goto done;
+
+generic_error:
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Login to server \"%s\" failed"), afp_serv->server_name);
+ res = FALSE;
+ goto done;
+}
+#endif
+
+static gboolean
+do_login (GVfsAfpServer *afp_serv,
+ const char *username,
+ const char *password,
+ gboolean anonymous,
+ GCancellable *cancellable,
+ GError **error)
+{
+ /* anonymous login */
+ if (anonymous)
+ {
+ GVfsAfpCommand *comm;
+ gboolean res;
+ GVfsAfpReply *reply;
+ AfpResultCode res_code;
+
+ if (!g_slist_find_custom (afp_serv->uams, AFP_UAM_NO_USER, g_str_equal))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Server \"%s\" doesn't support anonymous login"),
+ afp_serv->server_name);
+ return FALSE;
+ }
+
+ comm = g_vfs_afp_command_new (AFP_COMMAND_LOGIN);
+
+ g_vfs_afp_command_put_pascal (comm, afp_version_to_string (afp_serv->version));
+ g_vfs_afp_command_put_pascal (comm, AFP_UAM_NO_USER);
+ res = g_vfs_afp_connection_send_command_sync (afp_serv->conn, comm,
+ cancellable, error);
+ g_object_unref (comm);
+ if (!res)
+ return FALSE;
+
+ reply = g_vfs_afp_connection_read_reply_sync (afp_serv->conn, cancellable, error);
+ if (!reply)
+ return FALSE;
+
+ res_code = g_vfs_afp_reply_get_result_code (reply);
+ g_object_unref (reply);
+
+ if (res_code != AFP_RESULT_NO_ERROR)
+ {
+ if (res_code == AFP_RESULT_USER_NOT_AUTH)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Anonymous login on server \"%s\" failed"),
+ afp_serv->server_name);
+ return FALSE;
+ }
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Login to server \"%s\" failed"), afp_serv->server_name);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ else {
+
+#ifdef HAVE_GCRYPT
+ /* Diffie-Hellman */
+ if (g_slist_find_custom (afp_serv->uams, AFP_UAM_DHX, g_str_equal))
+ return dhx_login (afp_serv, username, password, cancellable, error);
+#endif
+
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Login to server \"%s\" failed, no suitable authentication mechanism found"),
+ afp_serv->server_name);
+ return FALSE;
+ }
+}
+
+static gboolean
+get_server_info (GVfsAfpServer *afp_serv,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVfsAfpReply *reply;
+ GError *err = NULL;
+
+ guint16 MachineType_offset, AFPVersionCount_offset, UAMCount_offset;
+ guint8 count;
+ guint i;
+
+ reply = g_vfs_afp_connection_get_server_info (afp_serv->conn, cancellable,
+ &err);
+ if (!reply)
+ return FALSE;
+
+ MachineType_offset =
+ g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+ AFPVersionCount_offset =
+ g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+ UAMCount_offset =
+ g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+ /* VolumeIconAndMask_offset */
+ (void)g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+
+ afp_serv->flags =
+ g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+
+ afp_serv->server_name = g_vfs_afp_reply_read_pascal (reply);
+
+ /* Parse MachineType */
+ g_vfs_afp_reply_seek (reply, MachineType_offset, G_SEEK_SET);
+ afp_serv->machine_type = g_vfs_afp_reply_read_pascal (reply);
+
+ /* Parse Versions */
+ g_vfs_afp_reply_seek (reply, AFPVersionCount_offset, G_SEEK_SET);
+ count = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+ for (i = 0; i < count; i++)
+ {
+ char *version;
+ AfpVersion afp_version;
+
+ version = g_vfs_afp_reply_read_pascal (reply);
+ afp_version = string_to_afp_version (version);
+ if (afp_version > afp_serv->version)
+ afp_serv->version = afp_version;
+ }
+
+ if (afp_serv->version == AFP_VERSION_INVALID)
+ {
+ g_object_unref (reply);
+ g_set_error (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Failed to connect to server (%s)"), "Server doesn't support AFP version 3.0 or later");
+ return FALSE;
+ }
+
+ /* Parse UAMs */
+ g_vfs_afp_reply_seek (reply, UAMCount_offset, G_SEEK_SET);
+ count = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+ for (i = 0; i < count; i++)
+ {
+ char *uam;
+
+ uam = g_vfs_afp_reply_read_pascal (reply);
+ afp_serv->uams = g_slist_prepend (afp_serv->uams, uam);
+ }
+
+ g_object_unref (reply);
+
+ return TRUE;
+}
+
+gboolean
+g_vfs_afp_server_login (GVfsAfpServer *afp_serv,
+ const char *initial_user,
+ GMountSource *mount_source,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean res;
+ char *user, *olduser;
+ char *password;
+ gboolean anonymous;
+ GPasswordSave password_save;
+ char *prompt = NULL;
+ GError *err = NULL;
+
+ res = get_server_info (afp_serv, cancellable, error);
+ if (!res)
+ return FALSE;
+
+ olduser = g_strdup (initial_user);
+
+ if (initial_user)
+ {
+ if (g_str_equal (initial_user, "anonymous"))
+ {
+ user = NULL;
+ password = NULL;
+ anonymous = TRUE;
+ goto try_login;
+ }
+
+ else if (g_vfs_keyring_lookup_password (initial_user,
+ g_network_address_get_hostname (afp_serv->addr),
+ NULL,
+ "afp",
+ NULL,
+ NULL,
+ g_network_address_get_port (afp_serv->addr),
+ &user,
+ NULL,
+ &password) &&
+ user != NULL &&
+ password != NULL)
+ {
+ anonymous = FALSE;
+ goto try_login;
+ }
+ }
+
+ while (TRUE)
+ {
+ GAskPasswordFlags flags;
+ gboolean aborted;
+
+ if (prompt == NULL)
+ {
+ /* create prompt */
+ if (initial_user)
+ /* Translators: the first %s is the username, the second the host name */
+ prompt = g_strdup_printf (_("Enter password for afp as %s on %s"), initial_user, afp_serv->server_name);
+ else
+ /* translators: %s here is the hostname */
+ prompt = g_strdup_printf (_("Enter password for afp on %s"), afp_serv->server_name);
+ }
+
+ flags = G_ASK_PASSWORD_NEED_PASSWORD;
+
+ if (!initial_user)
+ flags |= G_ASK_PASSWORD_NEED_USERNAME | G_ASK_PASSWORD_ANONYMOUS_SUPPORTED;
+
+ if (g_vfs_keyring_is_available ())
+ flags |= G_ASK_PASSWORD_SAVING_SUPPORTED;
+
+ if (!g_mount_source_ask_password (mount_source,
+ prompt,
+ olduser,
+ NULL,
+ flags,
+ &aborted,
+ &password,
+ &user,
+ NULL,
+ &anonymous,
+ &password_save) ||
+ aborted)
+ {
+ g_set_error_literal (&err, G_IO_ERROR,
+ aborted ? G_IO_ERROR_FAILED_HANDLED : G_IO_ERROR_PERMISSION_DENIED,
+ _("Password dialog cancelled"));
+ res = FALSE;
+ break;
+ }
+
+try_login:
+
+ /* Open connection */
+ res = g_vfs_afp_connection_open (afp_serv->conn, cancellable, &err);
+ if (!res)
+ break;
+
+ res = do_login (afp_serv, user, password, anonymous,
+ cancellable, &err);
+ if (!res)
+ {
+ g_vfs_afp_connection_close (afp_serv->conn, cancellable, NULL);
+
+ if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
+ g_clear_error (&err);
+ else
+ break;
+ }
+ else
+ break;
+
+ g_free (olduser);
+ olduser = user;
+
+ g_free (password);
+ }
+
+ g_free (olduser);
+
+ if (!res)
+ {
+ g_free (user);
+ g_free (password);
+
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+
+ if (prompt && !anonymous)
+ {
+ /* a prompt was created, so we have to save the password */
+ g_vfs_keyring_save_password (user,
+ g_network_address_get_hostname (afp_serv->addr),
+ NULL,
+ "afp",
+ NULL,
+ NULL,
+ g_network_address_get_port (afp_serv->addr),
+ password,
+ password_save);
+ g_free (prompt);
+ }
+
+ g_free (user);
+ g_free (password);
+
+ return TRUE;
+}
+
+GVfsAfpServer *
+g_vfs_afp_server_new (GNetworkAddress *addr)
+{
+ GVfsAfpServer *afp_serv;
+
+ afp_serv = g_object_new (G_VFS_TYPE_AFP_SERVER, NULL);
+
+ afp_serv->addr = addr;
+ afp_serv->conn = g_vfs_afp_connection_new (G_SOCKET_CONNECTABLE (addr));
+
+ return afp_serv;
+}
+
+static void
+g_vfs_afp_server_init (GVfsAfpServer *afp_serv)
+{
+ afp_serv->machine_type = NULL;
+ afp_serv->server_name = NULL;
+ afp_serv->uams = NULL;
+ afp_serv->version = AFP_VERSION_INVALID;
+}
+
+static void
+g_vfs_afp_server_finalize (GObject *object)
+{
+ GVfsAfpServer *afp_serv = G_VFS_AFP_SERVER (object);
+
+ g_free (afp_serv->machine_type);
+ g_free (afp_serv->server_name);
+ g_slist_free_full (afp_serv->uams, g_free);
+
+ G_OBJECT_CLASS (g_vfs_afp_server_parent_class)->finalize (object);
+}
+
+static void
+g_vfs_afp_server_class_init (GVfsAfpServerClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = g_vfs_afp_server_finalize;
+}
+
diff --git a/daemon/gvfsafpserver.h b/daemon/gvfsafpserver.h
new file mode 100644
index 0000000..69ecf88
--- /dev/null
+++ b/daemon/gvfsafpserver.h
@@ -0,0 +1,83 @@
+ /* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) Carl-Anton Ingmarsson 2011 <ca ingmarsson gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
+ */
+
+#ifndef _GVFSAFPSERVER_H_
+#define _GVFSAFPSERVER_H_
+
+#include <gio/gio.h>
+
+#include "gmountsource.h"
+#include "gvfsafpconnection.h"
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ AFP_VERSION_INVALID,
+ AFP_VERSION_3_0,
+ AFP_VERSIOM_3_1,
+ AFP_VERSION_3_2,
+ AFP_VERSION_3_3
+} AfpVersion;
+
+#define G_VFS_TYPE_AFP_SERVER (g_vfs_afp_server_get_type ())
+#define G_VFS_AFP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_VFS_TYPE_AFP_SERVER, GVfsAfpServer))
+#define G_VFS_AFP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_VFS_TYPE_AFP_SERVER, GVfsAfpServerClass))
+#define G_VFS_IS_AFP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_VFS_TYPE_AFP_SERVER))
+#define G_VFS_IS_AFP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_VFS_TYPE_AFP_SERVER))
+#define G_VFS_AFP_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_VFS_TYPE_AFP_SERVER, GVfsAfpServerClass))
+
+typedef struct _GVfsAfpServerClass GVfsAfpServerClass;
+typedef struct _GVfsAfpServer GVfsAfpServer;
+
+struct _GVfsAfpServerClass
+{
+ GObjectClass parent_class;
+};
+
+struct _GVfsAfpServer
+{
+ GObject parent_instance;
+
+ GNetworkAddress *addr;
+ GVfsAfpConnection *conn;
+
+ guint16 flags;
+ char *machine_type;
+ char *server_name;
+ GSList *uams;
+ AfpVersion version;
+};
+
+gboolean g_vfs_afp_server_login (GVfsAfpServer *afp_serv,
+ const char *initial_user,
+ GMountSource *mount_source,
+ GCancellable *cancellable,
+ GError **error);
+
+GVfsAfpServer* g_vfs_afp_server_new (GNetworkAddress *addr);
+
+GType g_vfs_afp_server_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* _GVFSAFPSERVER_H_ */
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index 9d1ae5f..f969061 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -33,43 +33,32 @@
#include "gvfsjobmount.h"
#include "gvfsjobenumerate.h"
-#include "gvfskeyring.h"
+#include "gmounttracker.h"
+#include "gvfsafpserver.h"
+#include "gvfsafpconnection.h"
#include "gvfsbackendafp.h"
+struct _GVfsBackendAfpClass
+{
+ GVfsBackendClass parent_class;
+};
-
-G_DEFINE_TYPE (GVfsBackendAfp, g_vfs_backend_afp, G_VFS_TYPE_BACKEND);
-
-
-#define AFP_UAM_NO_USER "No User Authent"
-#define AFP_UAM_DHX "DHCAST128"
-#define AFP_UAM_DHX2 "DHX2"
-
-static const char *
-afp_version_to_string (AfpVersion afp_version)
+struct _GVfsBackendAfp
{
- const char *version_strings[] = { "AFPX03", "AFP3.1", "AFP3.2", "AFP3.3" };
+ GVfsBackend parent_instance;
- return version_strings[afp_version - 1];
-}
+ GNetworkAddress *addr;
+ char *user;
-static AfpVersion
-string_to_afp_version (const char *str)
-{
- gint i;
-
- const char *version_strings[] = { "AFPX03", "AFP3.1", "AFP3.2", "AFP3.3" };
+ GMountTracker *mount_tracker;
+ GVfsAfpServer *server;
+};
- for (i = 0; i < G_N_ELEMENTS (version_strings); i++)
- {
- if (g_str_equal (str, version_strings[i]))
- return i + 1;
- }
- return AFP_VERSION_INVALID;
-}
+G_DEFINE_TYPE (GVfsBackendAfp, g_vfs_backend_afp, G_VFS_TYPE_BACKEND);
+
static void
get_srvr_parms_cb (GVfsAfpConnection *afp_connection,
@@ -200,7 +189,7 @@ try_enumerate (GVfsBackend *backend,
/* pad byte */
g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
- g_vfs_afp_connection_queue_command (afp_backend->conn, comm,
+ g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
get_srvr_parms_cb,
G_VFS_JOB (job)->cancellable, job);
g_object_unref (comm);
@@ -235,464 +224,6 @@ try_query_info (GVfsBackend *backend,
return TRUE;
}
-#ifdef HAVE_GCRYPT
-static gboolean
-dhx_login (GVfsBackendAfp *afp_backend,
- const char *username,
- const char *password,
- GCancellable *cancellable,
- GError **error)
-{
- gcry_error_t gcry_err;
- gcry_mpi_t prime, base;
- gcry_mpi_t ra;
-
- /* Ma */
- gcry_mpi_t ma;
- guint8 ma_buf[16];
-
- GVfsAfpCommand *comm;
- GVfsAfpReply *reply;
- AfpResultCode res_code;
- gboolean res;
- guint16 id;
-
- /* Mb */
- guint8 mb_buf[16];
- gcry_mpi_t mb;
-
- /* Nonce */
- guint8 nonce_buf[32];
- gcry_mpi_t nonce, nonce1;
-
- /* Key */
- gcry_mpi_t key;
- guint8 key_buf[16];
-
- gcry_cipher_hd_t cipher;
- guint8 answer_buf[80] = { 0 };
- size_t len;
-
- static const guint8 C2SIV[] = { 0x4c, 0x57, 0x61, 0x6c, 0x6c, 0x61, 0x63, 0x65 };
- static const guint8 S2CIV[] = { 0x43, 0x4a, 0x61, 0x6c, 0x62, 0x65, 0x72, 0x74 };
- static const guint8 p[] = { 0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4, 0x3F, 0x20, 0x24, 0x74, 0x4C, 0xEE, 0xE7, 0x5B };
- static const guint8 g[] = { 0x07 };
-
- if (strlen (password) > 64)
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
- _("Server doesn't support passwords longer than 64 characters"));
- return FALSE;
- }
-
- /* create prime and base from vectors */
- gcry_err = gcry_mpi_scan (&prime, GCRYMPI_FMT_USG, p, G_N_ELEMENTS (p), NULL);
- g_assert (gcry_err == 0);
-
- gcry_err = gcry_mpi_scan (&base, GCRYMPI_FMT_USG, g, G_N_ELEMENTS (g), NULL);
- g_assert (gcry_err == 0);
-
- /* generate random number ra != 0 */
- ra = gcry_mpi_new (256);
- while (gcry_mpi_cmp_ui (ra, 0) == 0)
- gcry_mpi_randomize (ra, 256, GCRY_STRONG_RANDOM);
-
- /* Secret key value must be less than half of prime */
- if (gcry_mpi_get_nbits (ra) > 255)
- gcry_mpi_clear_highbit (ra, 255);
-
- /* generate ma */
- ma = gcry_mpi_new (128);
- gcry_mpi_powm (ma, base, ra, prime);
- gcry_mpi_release (base);
- gcry_err = gcry_mpi_print (GCRYMPI_FMT_USG, ma_buf, G_N_ELEMENTS (ma_buf), NULL,
- ma);
- g_assert (gcry_err == 0);
- gcry_mpi_release (ma);
-
- /* Create login command */
- comm = g_vfs_afp_command_new (AFP_COMMAND_LOGIN);
- g_vfs_afp_command_put_pascal (comm, afp_version_to_string (afp_backend->version));
- g_vfs_afp_command_put_pascal (comm, AFP_UAM_DHX);
- g_vfs_afp_command_put_pascal (comm, username);
- g_vfs_afp_command_pad_to_even (comm);
- g_output_stream_write_all (G_OUTPUT_STREAM(comm), ma_buf, G_N_ELEMENTS (ma_buf),
- NULL, NULL, NULL);
-
- res = g_vfs_afp_connection_send_command_sync (afp_backend->conn, comm,
- cancellable, error);
- g_object_unref (comm);
- if (!res)
- goto done;
-
- reply = g_vfs_afp_connection_read_reply_sync (afp_backend->conn, cancellable, error);
- if (!reply)
- goto error;
-
- res_code = g_vfs_afp_reply_get_result_code (reply);
- if (res_code != AFP_RESULT_AUTH_CONTINUE)
- {
- g_object_unref (reply);
- if (res_code == AFP_RESULT_USER_NOT_AUTH)
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
- _("An invalid username was provided"));
- goto error;
- }
- else
- goto generic_error;
- }
-
- id = g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply),
- NULL, NULL);
-
- /* read Mb */
- g_input_stream_read_all (G_INPUT_STREAM (reply), mb_buf, G_N_ELEMENTS (mb_buf),
- NULL, NULL, NULL);
- gcry_err = gcry_mpi_scan (&mb, GCRYMPI_FMT_USG, mb_buf, G_N_ELEMENTS (mb_buf), NULL);
- g_assert (gcry_err == 0);
-
- /* read Nonce */
- g_input_stream_read_all (G_INPUT_STREAM (reply), nonce_buf, G_N_ELEMENTS (nonce_buf),
- NULL, NULL, NULL);
-
- g_object_unref (reply);
-
- /* derive key */
- key = gcry_mpi_new (128);
- gcry_mpi_powm (key, mb, ra, prime);
- gcry_mpi_release (mb);
- gcry_err = gcry_mpi_print (GCRYMPI_FMT_USG, key_buf, G_N_ELEMENTS (key_buf), NULL,
- key);
- g_assert (gcry_err == 0);
- gcry_mpi_release (key);
-
- /* setup decrypt cipher */
- gcry_err = gcry_cipher_open (&cipher, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC,
- 0);
- g_assert (gcry_err == 0);
-
- gcry_cipher_setiv (cipher, S2CIV, G_N_ELEMENTS (S2CIV));
- gcry_cipher_setkey (cipher, key_buf, G_N_ELEMENTS (key_buf));
-
- /* decrypt Nonce */
- gcry_err = gcry_cipher_decrypt (cipher, nonce_buf, G_N_ELEMENTS (nonce_buf),
- NULL, 0);
- g_assert (gcry_err == 0);
-
- gcry_err = gcry_mpi_scan (&nonce, GCRYMPI_FMT_USG, nonce_buf, 16, NULL);
- g_assert (gcry_err == 0);
-
- /* add one to nonce */
- nonce1 = gcry_mpi_new (128);
- gcry_mpi_add_ui (nonce1, nonce, 1);
- gcry_mpi_release (nonce);
-
- /* set client->server initialization vector */
- gcry_cipher_setiv (cipher, C2SIV, G_N_ELEMENTS (C2SIV));
-
- /* create encrypted answer */
- gcry_err = gcry_mpi_print (GCRYMPI_FMT_USG, answer_buf, 16, &len, nonce1);
- g_assert (gcry_err == 0);
- gcry_mpi_release (nonce1);
-
- if (len < 16)
- {
- memmove(answer_buf + 16 - len, answer_buf, len);
- memset(answer_buf, 0, 16 - len);
- }
-
- memcpy (answer_buf + 16, password, strlen (password));
-
- gcry_err = gcry_cipher_encrypt (cipher, answer_buf, G_N_ELEMENTS (answer_buf),
- NULL, 0);
- g_assert (gcry_err == 0);
-
-
- /* Create Login Continue command */
- comm = g_vfs_afp_command_new (AFP_COMMAND_LOGIN_CONT);
- g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
- g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (comm), id, NULL, NULL);
- g_output_stream_write_all (G_OUTPUT_STREAM (comm), answer_buf,
- G_N_ELEMENTS (answer_buf), NULL, NULL, NULL);
-
-
- res = g_vfs_afp_connection_send_command_sync (afp_backend->conn, comm,
- cancellable, error);
- g_object_unref (comm);
- if (!res)
- goto done;
-
- reply = g_vfs_afp_connection_read_reply_sync (afp_backend->conn, cancellable, error);
- if (!reply)
- goto error;
-
- res_code = g_vfs_afp_reply_get_result_code (reply);
- g_object_unref (reply);
- if (res_code != AFP_RESULT_NO_ERROR)
- {
- if (res_code == AFP_RESULT_USER_NOT_AUTH)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
- _("Server \"%s\" declined the submitted password"),
- afp_backend->server_name);
- goto error;
- }
- else
- goto generic_error;
- }
-
- res = TRUE;
-
-done:
- gcry_mpi_release (prime);
- gcry_mpi_release (ra);
-
- return res;
-
-error:
- res = FALSE;
- goto done;
-
-generic_error:
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Login to server \"%s\" failed"), afp_backend->server_name);
- res = FALSE;
- goto done;
-}
-#endif
-
-static gboolean
-do_login (GVfsBackendAfp *afp_backend,
- const char *username,
- const char *password,
- gboolean anonymous,
- GCancellable *cancellable,
- GError **error)
-{
- /* anonymous login */
- if (anonymous)
- {
- GVfsAfpCommand *comm;
- gboolean res;
- GVfsAfpReply *reply;
- AfpResultCode res_code;
-
- if (!g_slist_find_custom (afp_backend->uams, AFP_UAM_NO_USER, g_str_equal))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
- _("Server \"%s\" doesn't support anonymous login"),
- afp_backend->server_name);
- return FALSE;
- }
-
- comm = g_vfs_afp_command_new (AFP_COMMAND_LOGIN);
-
- g_vfs_afp_command_put_pascal (comm, afp_version_to_string (afp_backend->version));
- g_vfs_afp_command_put_pascal (comm, AFP_UAM_NO_USER);
- res = g_vfs_afp_connection_send_command_sync (afp_backend->conn, comm,
- cancellable, error);
- g_object_unref (comm);
- if (!res)
- return FALSE;
-
- reply = g_vfs_afp_connection_read_reply_sync (afp_backend->conn, cancellable, error);
- if (!reply)
- return FALSE;
-
- res_code = g_vfs_afp_reply_get_result_code (reply);
- g_object_unref (reply);
-
- if (res_code != AFP_RESULT_NO_ERROR)
- {
- if (res_code == AFP_RESULT_USER_NOT_AUTH)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
- _("Anonymous login on server \"%s\" failed"),
- afp_backend->server_name);
- return FALSE;
- }
- else
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Login to server \"%s\" failed"), afp_backend->server_name);
- return FALSE;
- }
- }
-
- return TRUE;
- }
-
- else {
-
-#ifdef HAVE_GCRYPT
- /* Diffie-Hellman */
- if (g_slist_find_custom (afp_backend->uams, AFP_UAM_DHX, g_str_equal))
- return dhx_login (afp_backend, username, password, cancellable, error);
-#endif
-
- else
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Login to server \"%s\" failed, no suitable authentication mechanism found"),
- afp_backend->server_name);
- return FALSE;
- }
- }
-}
-
-static gboolean
-g_vfs_afp_server_login (GVfsBackendAfp *afp_backend,
- char *initial_user,
- GMountSource *mount_source,
- GCancellable *cancellable,
- GError **error)
-{
- GNetworkAddress *addr;
- char *user, *olduser;
- char *password;
- gboolean anonymous;
- GPasswordSave password_save;
- char *prompt = NULL;
- gboolean res;
- GError *err = NULL;
-
- addr = G_NETWORK_ADDRESS (afp_backend->addr);
-
- olduser = g_strdup (initial_user);
-
- if (initial_user)
- {
- if (g_str_equal (initial_user, "anonymous"))
- {
- user = NULL;
- password = NULL;
- anonymous = TRUE;
- goto try_login;
- }
-
- else if (g_vfs_keyring_lookup_password (initial_user,
- g_network_address_get_hostname (addr),
- NULL,
- "afp",
- NULL,
- NULL,
- g_network_address_get_port (addr),
- &user,
- NULL,
- &password) &&
- user != NULL &&
- password != NULL)
- {
- anonymous = FALSE;
- goto try_login;
- }
- }
-
- while (TRUE)
- {
- GAskPasswordFlags flags;
- gboolean aborted;
-
- if (prompt == NULL)
- {
- /* create prompt */
- if (initial_user)
- /* Translators: the first %s is the username, the second the host name */
- prompt = g_strdup_printf (_("Enter password for afp as %s on %s"), initial_user, afp_backend->server_name);
- else
- /* translators: %s here is the hostname */
- prompt = g_strdup_printf (_("Enter password for afp on %s"), afp_backend->server_name);
- }
-
- flags = G_ASK_PASSWORD_NEED_PASSWORD;
-
- if (!initial_user)
- flags |= G_ASK_PASSWORD_NEED_USERNAME | G_ASK_PASSWORD_ANONYMOUS_SUPPORTED;
-
- if (g_vfs_keyring_is_available ())
- flags |= G_ASK_PASSWORD_SAVING_SUPPORTED;
-
- if (!g_mount_source_ask_password (mount_source,
- prompt,
- olduser,
- NULL,
- flags,
- &aborted,
- &password,
- &user,
- NULL,
- &anonymous,
- &password_save) ||
- aborted)
- {
- g_set_error_literal (&err, G_IO_ERROR,
- aborted ? G_IO_ERROR_FAILED_HANDLED : G_IO_ERROR_PERMISSION_DENIED,
- _("Password dialog cancelled"));
- res = FALSE;
- break;
- }
-
-try_login:
-
- /* Open connection */
- res = g_vfs_afp_connection_open (afp_backend->conn, cancellable, &err);
- if (!res)
- break;
-
- res = do_login (afp_backend, user, password, anonymous,
- cancellable, &err);
- if (!res)
- {
- g_vfs_afp_connection_close (afp_backend->conn, cancellable, NULL);
-
- if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
- g_clear_error (&err);
- else
- break;
- }
- else
- break;
-
-
- g_free (olduser);
- olduser = user;
-
- g_free (password);
- }
-
- g_free (olduser);
-
- if (!res)
- {
- g_free (user);
- g_free (password);
-
- g_propagate_error (error, err);
- return FALSE;
- }
-
- if (prompt && !anonymous)
- {
- /* a prompt was created, so we have to save the password */
- g_vfs_keyring_save_password (user,
- g_network_address_get_hostname (addr),
- NULL,
- "afp",
- NULL,
- NULL,
- g_network_address_get_port (addr),
- password,
- password_save);
- g_free (prompt);
- }
-
- g_free (user);
- g_free (password);
-
- return TRUE;
-}
-
static void
do_mount (GVfsBackend *backend,
GVfsJobMount *job,
@@ -704,73 +235,13 @@ do_mount (GVfsBackend *backend,
gboolean res;
GError *err = NULL;
- GVfsAfpReply *reply;
-
- guint16 MachineType_offset, AFPVersionCount_offset, UAMCount_offset;
- guint16 VolumeIconAndMask_offset, Flags;
- guint8 count;
- guint i;
GMountSpec *afp_mount_spec;
char *display_name;
- afp_backend->conn = g_vfs_afp_connection_new (afp_backend->addr);
+ afp_backend->server = g_vfs_afp_server_new (afp_backend->addr);
- reply = g_vfs_afp_connection_get_server_info (afp_backend->conn,
- G_VFS_JOB (job)->cancellable,
- &err);
- if (!reply)
- goto error;
-
- MachineType_offset =
- g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
- AFPVersionCount_offset =
- g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
- UAMCount_offset =
- g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
- VolumeIconAndMask_offset =
- g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
- Flags =
- g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
-
- afp_backend->server_name = g_vfs_afp_reply_read_pascal (reply);
-
- /* Parse Versions */
- g_vfs_afp_reply_seek (reply, AFPVersionCount_offset, G_SEEK_SET);
- count = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
- for (i = 0; i < count; i++)
- {
- char *version;
- AfpVersion afp_version;
-
- version = g_vfs_afp_reply_read_pascal (reply);
- afp_version = string_to_afp_version (version);
- if (afp_version > afp_backend->version)
- afp_backend->version = afp_version;
- }
-
- if (afp_backend->version == AFP_VERSION_INVALID)
- {
- g_object_unref (reply);
- g_vfs_job_failed (G_VFS_JOB (job),
- G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Failed to connect to server (%s)"), "Server doesn't support AFP version 3.0 or later");
- return;
- }
-
- /* Parse UAMs */
- g_vfs_afp_reply_seek (reply, UAMCount_offset, G_SEEK_SET);
- count = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
- for (i = 0; i < count; i++)
- {
- char *uam;
-
- uam = g_vfs_afp_reply_read_pascal (reply);
- afp_backend->uams = g_slist_prepend (afp_backend->uams, uam);
- }
- g_object_unref (reply);
-
- res = g_vfs_afp_server_login (afp_backend, afp_backend->user, mount_source,
+ res = g_vfs_afp_server_login (afp_backend->server, afp_backend->user, mount_source,
G_VFS_JOB (job)->cancellable, &err);
if (!res)
goto error;
@@ -785,7 +256,7 @@ do_mount (GVfsBackend *backend,
g_vfs_backend_set_mount_spec (backend, afp_mount_spec);
g_mount_spec_unref (afp_mount_spec);
- display_name = g_strdup_printf (_("AFP shares on %s"), afp_backend->server_name);
+ display_name = g_strdup_printf (_("AFP shares on %s"), afp_backend->server->server_name);
g_vfs_backend_set_display_name (backend, display_name);
g_free (display_name);
@@ -827,7 +298,7 @@ try_mount (GVfsBackend *backend,
port = atoi (portstr);
}
- afp_backend->addr = g_network_address_new (host, port);
+ afp_backend->addr = G_NETWORK_ADDRESS (g_network_address_new (host, port));
user = g_mount_spec_get (mount_spec, "user");
afp_backend->user = g_strdup (user);
@@ -841,19 +312,14 @@ g_vfs_backend_afp_init (GVfsBackendAfp *object)
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (object);
afp_backend->mount_tracker = g_mount_tracker_new (NULL);
-
- afp_backend->server_name = NULL;
- afp_backend->uams = NULL;
- afp_backend->version = AFP_VERSION_INVALID;
}
static void
g_vfs_backend_afp_finalize (GObject *object)
{
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (object);
-
- g_free (afp_backend->server_name);
- g_slist_free_full (afp_backend->uams, g_free);
+
+ g_object_unref (afp_backend->mount_tracker);
G_OBJECT_CLASS (g_vfs_backend_afp_parent_class)->finalize (object);
}
diff --git a/daemon/gvfsbackendafp.h b/daemon/gvfsbackendafp.h
index 0e47d55..1928a57 100644
--- a/daemon/gvfsbackendafp.h
+++ b/daemon/gvfsbackendafp.h
@@ -25,21 +25,8 @@
#include <gvfsbackend.h>
-#include "gmounttracker.h"
-
-#include "gvfsafpconnection.h"
-
G_BEGIN_DECLS
-typedef enum
-{
- AFP_VERSION_INVALID,
- AFP_VERSION_3_0,
- AFP_VERSIOM_3_1,
- AFP_VERSION_3_2,
- AFP_VERSION_3_3
-} AfpVersion;
-
#define G_VFS_TYPE_BACKEND_AFP (g_vfs_backend_afp_get_type ())
#define G_VFS_BACKEND_AFP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_VFS_TYPE_BACKEND_AFP, GVfsBackendAfp))
#define G_VFS_BACKEND_AFP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_VFS_TYPE_BACKEND_AFP, GVfsBackendAfpClass))
@@ -50,26 +37,6 @@ typedef enum
typedef struct _GVfsBackendAfpClass GVfsBackendAfpClass;
typedef struct _GVfsBackendAfp GVfsBackendAfp;
-struct _GVfsBackendAfpClass
-{
- GVfsBackendClass parent_class;
-};
-
-struct _GVfsBackendAfp
-{
- GVfsBackend parent_instance;
-
- GSocketConnectable *addr;
- char *user;
-
- GMountTracker *mount_tracker;
- GVfsAfpConnection *conn;
-
- char *server_name;
- GSList *uams;
- AfpVersion version;
-};
-
GType g_vfs_backend_afp_get_type (void) G_GNUC_CONST;
#define BACKEND_SETUP_FUNC g_vfs_afp_daemon_init
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]