[gvfs] afp: implement user authentication using Diffie-Hellman 1



commit d32a6848e01be79f38e41206f1989924d1344bb2
Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
Date:   Mon Jun 13 16:12:44 2011 +0200

    afp: implement user authentication using Diffie-Hellman 1

 configure.ac               |   15 ++
 daemon/Makefile.am         |    8 +-
 daemon/gvfsafpconnection.c |   65 ++++++++--
 daemon/gvfsafpconnection.h |   16 ++-
 daemon/gvfsbackendafp.c    |  312 ++++++++++++++++++++++++++++++++++++++------
 daemon/gvfsbackendafp.h    |    3 +
 6 files changed, 361 insertions(+), 58 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index dea6913..9951ab0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -554,6 +554,21 @@ AM_CONDITIONAL(HAVE_ARCHIVE, test "$msg_archive" = "yes")
 AC_SUBST(ARCHIVE_CFLAGS)
 AC_SUBST(ARCHIVE_LIBS)
 
+dnl ***************************
+dnl *** Check for libgcrypt ***
+dnl ***************************
+GCRYPT_VERSION=1.2.2
+GCRYPT_LIBVER=1
+
+AM_PATH_LIBGCRYPT($GCRYPT_LIBVER:$GCRYPT_VERSION, have_gcrypt="yes",
+	      have_gcrypt="no")
+
+if test "x$have_gcrypt" != "xno"; then
+  AC_DEFINE(HAVE_GCRYPT, 1, [Define to 1 if libgcrypt is available])
+fi
+AC_SUBST([LIBGCRYPT_CFLAGS])
+AC_SUBST([LIBGCRYPT_LIBS])
+
 dnl Install bash-completion file?
 AC_ARG_ENABLE([bash-completion],
 	      AC_HELP_STRING([--disable-bash-completion],
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index b47e1d0..816387e 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -483,9 +483,13 @@ gvfsd_afp_CPPFLAGS = \
 	-DBACKEND_HEADER=gvfsbackendafp.h \
 	-DDEFAULT_BACKEND_TYPE=afp \
 	-DMAX_JOB_THREADS=1 \
-	-DBACKEND_TYPES='"afp-server", G_VFS_TYPE_BACKEND_AFP,'
+	-DBACKEND_TYPES='"afp-server", G_VFS_TYPE_BACKEND_AFP,' \
+	$(LIBGCRYPT_CFLAGS)
+
+gvfsd_afp_LDADD = \
+	$(libraries) \
+	$(LIBGCRYPT_LIBS)
 
-gvfsd_afp_LDADD = $(libraries)
 
 # GSettings stuff
 gsettings_ENUM_NAMESPACE = org.gnome.system.gvfs
diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
index 7fed840..5bbeb80 100644
--- a/daemon/gvfsafpconnection.c
+++ b/daemon/gvfsafpconnection.c
@@ -21,6 +21,7 @@
  */
 
 #include <string.h>
+#include <glib/gi18n.h>
 
 
 #include "gvfsafpconnection.h"
@@ -38,7 +39,7 @@ struct _GVfsAfpReply
 {
 	GDataInputStream parent_instance;
 
-  AfpErrorCode error_code;
+  AfpResultCode result_code;
 };
 
 G_DEFINE_TYPE (GVfsAfpReply, g_vfs_afp_reply, G_TYPE_DATA_INPUT_STREAM);
@@ -54,7 +55,7 @@ g_vfs_afp_reply_class_init (GVfsAfpReplyClass *klass)
 }
 
 static GVfsAfpReply *
-g_vfs_afp_reply_new (AfpErrorCode error_code, const char *data, gsize len)
+g_vfs_afp_reply_new (AfpResultCode result_code, const char *data, gsize len)
 {
   GVfsAfpReply *reply;
 
@@ -67,7 +68,7 @@ g_vfs_afp_reply_new (AfpErrorCode error_code, const char *data, gsize len)
                           g_memory_input_stream_new (), NULL);
   
 
-  reply->error_code = error_code;
+  reply->result_code = result_code;
   
   return reply;
 }
@@ -117,10 +118,10 @@ g_vfs_afp_reply_seek (GVfsAfpReply *reply, goffset offset, GSeekType type)
   return g_seekable_seek (G_SEEKABLE (mem_stream), offset, type, NULL, NULL);
 }
 
-AfpErrorCode
-g_vfs_afp_reply_get_error_code (GVfsAfpReply *reply)
+AfpResultCode
+g_vfs_afp_reply_get_result_code (GVfsAfpReply *reply)
 {
-  return reply->error_code;
+  return reply->result_code;
 }
 
 /*
@@ -588,8 +589,15 @@ read_reply_sync (GInputStream      *input,
   read_count = sizeof (DSIHeader);
   res = g_input_stream_read_all (input, dsi_header, read_count, &bytes_read,
                                  cancellable, error);
-  if (!res || bytes_read < read_count)
+  if (!res)
+    return FALSE;
+
+  if (bytes_read < read_count)
+  {
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                         _("Got EOS"));
     return FALSE;
+  }
 
   dsi_header->requestID = GUINT16_FROM_BE (dsi_header->requestID);
   dsi_header->errorCode = GUINT32_FROM_BE (dsi_header->errorCode);
@@ -605,9 +613,16 @@ read_reply_sync (GInputStream      *input,
   read_count = dsi_header->totalDataLength;
 
   res = g_input_stream_read_all (input, *data, read_count, &bytes_read, cancellable, error);
-  if (!res || bytes_read < read_count)
+  if (!res)
+  {
+    g_free (*data);
+    return FALSE;
+  }
+  if (bytes_read < read_count)
   {
     g_free (*data);
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                         _("Got EOS"));
     return FALSE;
   }
 
@@ -639,7 +654,7 @@ send_request_sync (GOutputStream     *output,
                    guint16           request_id,
                    guint32           writeOffset,
                    gsize             len,
-                   char              *data,
+                   const char        *data,
                    GCancellable      *cancellable,
                    GError            **error)
 {
@@ -657,7 +672,7 @@ send_request_sync (GOutputStream     *output,
   write_count = sizeof (DSIHeader);
   res = g_output_stream_write_all (output, &dsi_header, write_count,
                                    &bytes_written, cancellable, error);
-  if (!res || bytes_written < write_count)
+  if (!res)
     return FALSE;
 
   if (data == NULL)
@@ -666,7 +681,7 @@ send_request_sync (GOutputStream     *output,
   write_count = len;
   res = g_output_stream_write_all (output, data, write_count, &bytes_written,
                                    cancellable, error);
-  if (!res || bytes_written < write_count)
+  if (!res)
     return FALSE;
 
   return TRUE;
@@ -711,6 +726,34 @@ g_vfs_afp_connection_send_command_sync (GVfsAfpConnection *afp_connection,
 }
 
 gboolean
+g_vfs_afp_connection_close (GVfsAfpConnection *afp_connection,
+                            GCancellable      *cancellable,
+                            GError            **error)
+{
+  GVfsAfpConnectionPrivate *priv = afp_connection->priv;
+  
+  guint16 req_id;
+  gboolean res;
+  
+  /* close DSI session */
+  req_id = get_request_id (afp_connection);
+  res = send_request_sync (g_io_stream_get_output_stream (priv->conn),
+                           DSI_CLOSE_SESSION, req_id, 0, 0, NULL,
+                           cancellable, error);
+  if (!res)
+  {
+    g_io_stream_close (priv->conn, cancellable, NULL);
+    g_object_unref (priv->conn);
+    return FALSE;
+  }
+
+  res = g_io_stream_close (priv->conn, cancellable, error);
+  g_object_unref (priv->conn);
+  
+  return res;
+}
+
+gboolean
 g_vfs_afp_connection_open (GVfsAfpConnection *afp_connection,
                            GCancellable      *cancellable,
                            GError            **error)
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
index 4c1d518..26fa832 100644
--- a/daemon/gvfsafpconnection.h
+++ b/daemon/gvfsafpconnection.h
@@ -32,16 +32,18 @@ typedef enum
   AFP_COMMAND_GET_SRVR_INFO = 15,
   AFP_COMMAND_GET_SRVR_PARMS = 16,
   AFP_COMMAND_LOGIN = 18,
+  AFP_COMMAND_LOGIN_CONT = 19,
   AFP_COMMAND_WRITE = 33,
   AFP_COMMAND_WRITE_EXT = 61
 } AfpCommandType;
 
 typedef enum
 {
-  AFP_ERROR_NONE = 0,
-  AFP_ERROR_USER_NOT_AUTH = -5023,
-  AFP_ERROR_NO_MORE_SESSIONS = -1068
-} AfpErrorCode;
+  AFP_RESULT_NO_ERROR = 0,
+  AFP_RESULT_USER_NOT_AUTH = -5023,
+  AFP_RESULT_AUTH_CONTINUE = -5001,
+  AFP_RESULT_NO_MORE_SESSIONS = -1068
+} AfpResultCode;
 
 /*
  * GVfsAfpReply
@@ -59,7 +61,7 @@ typedef struct _GVfsAfpReply      GVfsAfpReply;
 char *          g_vfs_afp_reply_read_pascal      (GVfsAfpReply *reply);
 gboolean        g_vfs_afp_reply_seek             (GVfsAfpReply *reply, goffset offset, GSeekType type);
 
-AfpErrorCode    g_vfs_afp_reply_get_error_code   (GVfsAfpReply *reply);
+AfpResultCode   g_vfs_afp_reply_get_result_code   (GVfsAfpReply *reply);
 
 GType           g_vfs_afp_reply_get_type         (void) G_GNUC_CONST;
 
@@ -135,6 +137,10 @@ gboolean           g_vfs_afp_connection_open              (GVfsAfpConnection *af
                                                            GCancellable      *cancellable,
                                                            GError            **error);
 
+gboolean           g_vfs_afp_connection_close             (GVfsAfpConnection *afp_connection,
+                                                           GCancellable      *cancellable,
+                                                           GError            **error);
+
 gboolean           g_vfs_afp_connection_send_command_sync (GVfsAfpConnection *afp_connection,
                                                            GVfsAfpCommand    *afp_command,
                                                            GCancellable      *cancellable,
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index 87c83d1..9d1ae5f 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -27,6 +27,10 @@
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 
+#ifdef HAVE_GCRYPT
+#include <gcrypt.h>
+#endif
+
 #include "gvfsjobmount.h"
 #include "gvfsjobenumerate.h"
 #include "gvfskeyring.h"
@@ -76,7 +80,7 @@ get_srvr_parms_cb (GVfsAfpConnection *afp_connection,
   GVfsJobEnumerate *job = G_VFS_JOB_ENUMERATE (user_data);
   GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (job->backend);
 
-  AfpErrorCode error_code;
+  AfpResultCode res_code;
   guint8 num_volumes, i;
 
   if (!reply)
@@ -85,8 +89,8 @@ get_srvr_parms_cb (GVfsAfpConnection *afp_connection,
     return;
   }
 
-  error_code = g_vfs_afp_reply_get_error_code (reply);
-  if (error_code != AFP_ERROR_NONE)
+  res_code = g_vfs_afp_reply_get_result_code (reply);
+  if (res_code != AFP_RESULT_NO_ERROR)
   {
     g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
                               G_IO_ERROR_FAILED, _("Volume enumeration failed"));
@@ -231,6 +235,233 @@ 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,
@@ -243,8 +474,9 @@ do_login (GVfsBackendAfp *afp_backend,
   if (anonymous)
   {
     GVfsAfpCommand *comm;
+    gboolean res;
     GVfsAfpReply *reply;
-    guint32 error_code;
+    AfpResultCode res_code;
     
     if (!g_slist_find_custom (afp_backend->uams, AFP_UAM_NO_USER, g_str_equal))
     {
@@ -256,23 +488,24 @@ do_login (GVfsBackendAfp *afp_backend,
 
     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_version_to_string (afp_backend->version));
     g_vfs_afp_command_put_pascal (comm, AFP_UAM_NO_USER);
-    if (!g_vfs_afp_connection_send_command_sync (afp_backend->conn, comm,
-                                                 cancellable, error))
+    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;
 
-    error_code = g_vfs_afp_reply_get_error_code (reply);
+    res_code = g_vfs_afp_reply_get_result_code (reply);
     g_object_unref (reply);
     
-    if (error_code != AFP_ERROR_NONE)
+    if (res_code != AFP_RESULT_NO_ERROR)
     {
-      if (error_code == AFP_ERROR_USER_NOT_AUTH)
+      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"),
@@ -286,22 +519,18 @@ do_login (GVfsBackendAfp *afp_backend,
         return FALSE;
       }
     }
+
+    return TRUE;
   }
 
   else {
 
-    /* Diffie-Hellman 2 */
-    if (g_slist_find_custom (afp_backend->uams, AFP_UAM_DHX2, g_str_equal))
-    {
-      g_debug ("Diffie-Hellman 2\n");
-    }
-
+#ifdef HAVE_GCRYPT
     /* Diffie-Hellman */
-    else if (g_slist_find_custom (afp_backend->uams, AFP_UAM_DHX, g_str_equal))
-    {
-      g_debug ("Diffie-Hellman\n");
-    }
-
+    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,
@@ -309,14 +538,7 @@ do_login (GVfsBackendAfp *afp_backend,
                    afp_backend->server_name);
       return FALSE;
     }
-
-    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
-                         "Non anonymous login not implemented yet");
-    return FALSE;
-    
   }
-
-  return TRUE;
 }
 
 static gboolean
@@ -332,6 +554,7 @@ g_vfs_afp_server_login (GVfsBackendAfp *afp_backend,
   gboolean anonymous;
   GPasswordSave password_save;
   char *prompt = NULL;
+  gboolean res;
   GError *err = NULL;
 
   addr = G_NETWORK_ADDRESS (afp_backend->addr);
@@ -370,7 +593,6 @@ g_vfs_afp_server_login (GVfsBackendAfp *afp_backend,
   {
     GAskPasswordFlags flags;
     gboolean aborted;
-    gboolean res;
 
     if (prompt == NULL)
     {
@@ -380,7 +602,7 @@ g_vfs_afp_server_login (GVfsBackendAfp *afp_backend,
         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 ftp on %s"), afp_backend->server_name);
+        prompt = g_strdup_printf (_("Enter password for afp on %s"), afp_backend->server_name);
     }
     
     flags = G_ASK_PASSWORD_NEED_PASSWORD;
@@ -407,15 +629,23 @@ g_vfs_afp_server_login (GVfsBackendAfp *afp_backend,
       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
@@ -428,13 +658,12 @@ try_login:
     g_free (olduser);
     olduser = user;
 
-
     g_free (password);
   }
 
   g_free (olduser);
 
-  if (err != NULL)
+  if (!res)
   {
     g_free (user);
     g_free (password);
@@ -541,13 +770,6 @@ do_mount (GVfsBackend *backend,
   }
   g_object_unref (reply);
 
-
-  /* Open connection */
-  res = g_vfs_afp_connection_open (afp_backend->conn, G_VFS_JOB (job)->cancellable,
-                                   &err);
-  if (!res)
-    goto error;
-
   res = g_vfs_afp_server_login (afp_backend, afp_backend->user, mount_source,
                                 G_VFS_JOB (job)->cancellable, &err);
   if (!res)
@@ -650,3 +872,13 @@ g_vfs_backend_afp_class_init (GVfsBackendAfpClass *klass)
   backend_class->try_enumerate = try_enumerate;
 }
 
+void
+g_vfs_afp_daemon_init (void)
+{
+  g_set_application_name (_("Apple Filing Protocol Service"));
+
+#ifdef HAVE_GCRYPT
+  gcry_check_version (NULL);
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+#endif
+}
diff --git a/daemon/gvfsbackendafp.h b/daemon/gvfsbackendafp.h
index 03d73bd..0e47d55 100644
--- a/daemon/gvfsbackendafp.h
+++ b/daemon/gvfsbackendafp.h
@@ -72,6 +72,9 @@ struct _GVfsBackendAfp
 
 GType g_vfs_backend_afp_get_type (void) G_GNUC_CONST;
 
+#define BACKEND_SETUP_FUNC g_vfs_afp_daemon_init
+void g_vfs_afp_daemon_init (void);
+
 G_END_DECLS
 
 #endif /* _GVFSBACKENDAFP_H_ */



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