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

Re: [gftp] SFTP with dual authentication in gFTP?



Here is a patch against CVS that should implement this functionality for
you. Please let me know if this works or not for you. I couldn't test it fully
since I do not have access to a RSA SecurID SSH server.

I also put my latest code online at http://www.gftp.org/gftp-test.tar.bz2 if you
don't want to apply this patch.

To the other members of the mailing list: if anyone has an AMD64 running Linux,
please try the test code above and report back to me if it still has problems
transfering files via SSH.

Brian


On Mon, Jun 14, 2004 at 03:50:36PM -0400, Randall A. Jones wrote:
> 
> Here is an example sftp login showing the exact passcode and password 
> output.  There is a banner that I've stubbed in for the example, assuming 
> that extraneous text is passed over looking for the specific "password" 
> phrases.
> 
> $ sftp sftpserver
> Connecting to sftpserver...
>  ************** *******************
> 
>     ... stubbed banner ...
> 
>  ***********************************************************************
> 
> Enter PASSCODE: 
> Password: 
> sftp> 
> 
> 
> That's it.  "Enter PASSCODE:" then, after successful passcode, "Password:"
> 
> I hoped it might be easy.
> 
> Thanks!
> Randy
> --
> 
> 
> On Mon, 14 Jun 2004, Brian Masney wrote:
> 
> > On Wed, Jun 09, 2004 at 08:59:25PM -0400, Randall A. Jones wrote:
> > > Is there a way to configure gFTP to work with a dual authentication login 
> > > system?
> > > 
> > > I have an sftp server that requires first a passcode from a securid token 
> > > generator, then a traditional password.  On command line login, it 
> > > presents the passcode prompt first, then the password prompt.
> > > 
> > > I have gFTP configured using the appropriate sftp settings, port 22, ssh2; 
> > > "Need SSH User/Pass" on the FTP->Options-><SSH tab>.
> > > 
> > > After I enter the passcode in the "Enter Password" dialog, 
> > > it seems to connect to the server and await the password.
> > > 
> > > Is it possible for gFTP to prompt for password twice passing the reults to 
> > > each prompt, passcode then password?
> > 
> > This would be easily to implement. Can you tell me the exact message that the
> > server returns when you are prompted for the passcode then the password?
> > 
> > Brian
> > 
> > 
> > 
> 
> -- 
> Randall Jones     GST      NASA Goddard Space Flight Center
> CT Visualization Support            http://ct.gsfc.nasa.gov
> Scientific Visualization Studio    http://svs.gsfc.nasa.gov
> Randall.A.Jones@gsfc.nasa.gov     Code 935     301-286-2239
> 
> 
> 
> 
> 
> 
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gftp/ChangeLog,v
retrieving revision 1.269
diff -u -r1.269 ChangeLog
--- ChangeLog	13 Jun 2004 14:25:18 -0000	1.269
+++ ChangeLog	16 Jun 2004 00:58:13 -0000
@@ -1,3 +1,11 @@
+2004-6-15 Brian Masney <masneyb@gftp.org>
+	* lib/gftp.h lib/sshv2.c src/gtk/gtkui.c src/text/textui.c - added
+	support for RSA SecurID passwords
+
+	* lib/sshv2.c - cleaned up the SSH login sequence even more. Removed
+	ssh2_sftp_path and sshv2_use_sftp_subsys options. The sftp subsystem
+	is now always used.
+
 2004-6-13 Brian Masney <masneyb@gftp.org>
 	* lib/gftp.h lib/misc.c src/gtk/Makefile.am src/gtk/menu-items.c
 	src/gtk/misc-gtk.c src/text/Makefile.am src/uicommon/Makefile.am
Index: lib/gftp.h
===================================================================
RCS file: /cvs/gnome/gftp/lib/gftp.h,v
retrieving revision 1.93
diff -u -r1.93 gftp.h
--- lib/gftp.h	13 Jun 2004 14:25:18 -0000	1.93
+++ lib/gftp.h	16 Jun 2004 00:58:15 -0000
@@ -1044,6 +1044,11 @@
 					  char *title,
 					  char *question );
 
+char *gftpui_protocol_ask_user_input	( gftp_request * request,
+					  char *title,
+					  char *question,
+					  int shown );
+
 void gftpui_protocol_update_timeout 	( gftp_request * request );
 
 #endif
Index: lib/sshv2.c
===================================================================
RCS file: /cvs/gnome/gftp/lib/sshv2.c,v
retrieving revision 1.40
diff -u -r1.40 sshv2.c
--- lib/sshv2.c	15 Apr 2004 00:59:23 -0000	1.40
+++ lib/sshv2.c	16 Jun 2004 00:58:18 -0000
@@ -34,19 +34,11 @@
   {"ssh_extra_params", N_("SSH Extra Params:"), 
    gftp_option_type_text, NULL, NULL, 0,  
    N_("Extra parameters to pass to the SSH program"), GFTP_PORT_ALL, NULL},
-  {"ssh2_sftp_path", N_("SSH2 sftp-server path:"), 
-   gftp_option_type_text, NULL, NULL, GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
-   N_("Default remote SSH2 sftp-server path"), GFTP_PORT_ALL, NULL},
 
   {"ssh_need_userpass", N_("Need SSH User/Pass"), 
    gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 
    GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
    N_("Require a username/password for SSH connections"), GFTP_PORT_ALL, NULL},
-  {"sshv2_use_sftp_subsys", N_("Use SSH2 SFTP subsys"), 
-   gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, 
-   GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
-   N_("Call ssh with the -s sftp flag. This is helpful because you won't have to know the remote path to the remote sftp-server"), 
-   GFTP_PORT_GTK, NULL},
 
   {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
 };
@@ -147,7 +139,6 @@
 #define SSH_LOGIN_BUFSIZE	200
 #define SSH_ERROR_BADPASS	-1
 #define SSH_ERROR_QUESTION	-2
-#define SSH_WARNING 		-3
 
 static void
 sshv2_add_exec_args (char **logstr, size_t *logstr_len, char ***args, 
@@ -210,8 +201,7 @@
 
 
 static char **
-sshv2_gen_exec_args (gftp_request * request, char *execname, 
-                    int use_sftp_subsys)
+sshv2_gen_exec_args (gftp_request * request)
 {
   size_t logstr_len, args_len, args_cur;
   char **args, *tempstr, *logstr;
@@ -243,12 +233,8 @@
   sshv2_add_exec_args (&logstr, &logstr_len, &args, &args_len, &args_cur,
                        " -p %d", request->port);
 
-  if (use_sftp_subsys)
-    sshv2_add_exec_args (&logstr, &logstr_len, &args, &args_len, &args_cur,
-                         " %s -s sftp", request->hostname);
-  else
-    sshv2_add_exec_args (&logstr, &logstr_len, &args, &args_len, &args_cur,
-                         " %s %s", request->hostname, execname);
+  sshv2_add_exec_args (&logstr, &logstr_len, &args, &args_len, &args_cur,
+                       " %s -s sftp", request->hostname);
 
   request->logging_function (gftp_logging_misc, request, 
                              _("Running program %s\n"), logstr);
@@ -260,16 +246,15 @@
 static int
 sshv2_start_login_sequence (gftp_request * request, int fdm, int ptymfd)
 {
-  char *tempstr, *pwstr, *tmppos, *yesstr = "yes\n", *question_pos;
-  size_t rem, len, diff, lastdiff;
-  int wrotepw, ok, maxfd, ret;
+  char *tempstr, *temp1str, *pwstr, *yesstr = "yes\n", *securid_pass;
+  int wrotepw, ok, maxfd, ret, clear_tempstr;
+  size_t rem, len, diff;
   fd_set rset, eset;
   ssize_t rd;
 
-  question_pos = NULL;
   rem = len = SSH_LOGIN_BUFSIZE;
+  diff = 0;
   tempstr = g_malloc0 (len + 1);
-  diff = lastdiff = 0;
   wrotepw = 0;
   ok = 1;
 
@@ -333,50 +318,23 @@
       else if (rd == 0)
         continue;
 
+      tempstr[diff + rd] = '\0'; 
+      request->logging_function (gftp_logging_recv, request, "%s", tempstr + diff);
       rem -= rd;
       diff += rd;
-      tempstr[diff] = '\0'; 
 
-      if ( (strcmp (tempstr, "Password:") == 0) || 
-           (diff >= 10 && strcmp (tempstr + diff - 9, "assword: ") == 0))
+      if (strcmp (tempstr, "Password:") == 0 || 
+          (diff >= 10 && strcmp (tempstr + diff - 9, "assword: ") == 0) ||
+          strstr (tempstr, "Enter passphrase for RSA key") != NULL ||
+          strstr (tempstr, "Enter passphrase for key '") != NULL)
         {
+          clear_tempstr = 1;
           if (wrotepw)
             {
               ok = SSH_ERROR_BADPASS;
               break;
             }
 
-          if (strstr (tempstr, "WARNING") != NULL ||
-              strstr (tempstr, _("WARNING")) != NULL)
-            {
-              ok = SSH_WARNING;
-              break;
-            }
-              
-          wrotepw = 1;
-          if (gftp_fd_write (request, pwstr, strlen (pwstr), ptymfd) < 0)
-            {
-              ok = 0;
-              break;
-            }
-        }
-      else if (diff > 2 && strcmp (tempstr + diff - 2, ": ") == 0 &&
-               ((tmppos = strstr (tempstr, "Enter passphrase for RSA key")) != NULL ||
-                ((tmppos = strstr (tempstr, "Enter passphrase for key '")) != NULL)))
-        {
-          if (wrotepw)
-            {
-              ok = SSH_ERROR_BADPASS;
-              break;
-            }
-
-          if (strstr (tempstr, "WARNING") != NULL ||
-              strstr (tempstr, _("WARNING")) != NULL)
-            {
-              ok = SSH_WARNING;
-              break;
-            }
-
           wrotepw = 1;
           if (gftp_fd_write (request, pwstr, strlen (pwstr), ptymfd) < 0)
             {
@@ -386,7 +344,7 @@
         }
       else if (diff > 10 && strcmp (tempstr + diff - 10, "(yes/no)? ") == 0)
         {
-          question_pos = tempstr + diff;
+          clear_tempstr = 1;
           if (!gftpui_protocol_ask_yes_no (request, request->hostname, tempstr))
             {
               ok = SSH_ERROR_QUESTION;
@@ -401,37 +359,62 @@
                 }
             }
         }
+      else if (strstr (tempstr, "Enter PASSCODE:") != NULL)
+        {
+          clear_tempstr = 1;
+          securid_pass = gftpui_protocol_ask_user_input (request,
+                                             _("Enter Password"),
+                                             _("Enter SecurID Password:"), 0);
+
+          if (securid_pass == NULL || *securid_pass == '\0')
+            {
+              ok = SSH_ERROR_BADPASS;
+              break;
+            }
+
+          temp1str = g_strconcat (securid_pass, "\n", NULL);
+
+          ret = gftp_fd_write (request, yesstr, strlen (yesstr), ptymfd);
+
+          memset (temp1str, 0, strlen (temp1str));
+          g_free (temp1str);
+          memset (securid_pass, 0, strlen (securid_pass));
+          g_free (securid_pass);
+
+          if (ret <= 0)
+            {
+              ok = 0;
+              break;
+            }
+        }
       else if (rem <= 1)
         {
           len += SSH_LOGIN_BUFSIZE;
           rem += SSH_LOGIN_BUFSIZE;
-          lastdiff = diff;
           tempstr = g_realloc (tempstr, len);
           continue;
         }
-    }
-
-  g_free (pwstr);
+      else
+        clear_tempstr = 0;
 
-  if (question_pos != NULL)
-    {
-      if (*question_pos != '\0')
-        request->logging_function (gftp_logging_recv, request, "%s\n",
-                                   question_pos);
+      if (clear_tempstr)
+        {
+          *tempstr = '\0';
+          rem = SSH_LOGIN_BUFSIZE;
+          diff = 0;
+        }
     }
-  else if (*tempstr != '\0')
-    request->logging_function (gftp_logging_recv, request, "%s\n", tempstr);
 
+  g_free (pwstr);
   g_free (tempstr);
 
   if (ok <= 0)
     {
+      request->logging_function (gftp_logging_error, request, "\n");
+
       if (ok == SSH_ERROR_BADPASS)
         request->logging_function (gftp_logging_error, request,
                                _("Error: An incorrect password was entered\n"));
-      else if (ok == SSH_WARNING)
-        request->logging_function (gftp_logging_error, request,
-                                   _("Please correct the above warning to connect to this host.\n"));
 
       gftp_disconnect (request);
       return (GFTP_EFATAL);
@@ -903,12 +886,11 @@
 static int
 sshv2_connect (gftp_request * request)
 {
-  char **args, *p1, p2, *exepath, *ssh2_sftp_path;
-  intptr_t sshv2_use_sftp_subsys;
   int version, ret, fdm, ptymfd;
   struct servent serv_struct;
   sshv2_params * params;
   sshv2_message message;
+  char **args;
   pid_t child;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
@@ -924,21 +906,6 @@
 			     _("Opening SSH connection to %s\n"),
                              request->hostname);
 
-  gftp_lookup_request_option (request, "ssh2_sftp_path", &ssh2_sftp_path);
-  gftp_lookup_request_option (request, "sshv2_use_sftp_subsys", 
-                              &sshv2_use_sftp_subsys);
-
-  if (ssh2_sftp_path == NULL || *ssh2_sftp_path == '\0')
-    {
-      p1 = "";
-      p2 = ' ';
-    }
-  else
-    {
-      p1 = ssh2_sftp_path;
-      p2 = '/';
-    }
-
   if (request->port == 0)
     {
       if (!r_getservbyname ("ssh", "tcp", &serv_struct, NULL))
@@ -951,8 +918,7 @@
         request->port = ntohs (serv_struct.s_port);
     }
 
-  exepath = g_strdup_printf ("%s%csftp-server", p1, p2);
-  args = sshv2_gen_exec_args (request, exepath, sshv2_use_sftp_subsys);
+  args = sshv2_gen_exec_args (request);
 
   child = gftp_exec (request, &fdm, &ptymfd, args);
 
@@ -960,7 +926,6 @@
     exit (0);
 
   sshv2_free_args (args);
-  g_free (exepath);
 
   if (child < 0)
     return (GFTP_ERETRYABLE);
Index: src/gtk/gtkui.c
===================================================================
RCS file: /cvs/gnome/gftp/src/gtk/gtkui.c,v
retrieving revision 1.10
diff -u -r1.10 gtkui.c
--- src/gtk/gtkui.c	16 May 2004 13:34:02 -0000	1.10
+++ src/gtk/gtkui.c	16 Jun 2004 00:58:20 -0000
@@ -486,7 +486,7 @@
 
   if (gftp_protocols[request->protonum].use_threads)
     {
-      /* Otherwise let the main loop in the main thread run the events */
+      /* Let the main loop in the main thread run the events */
       GDK_THREADS_LEAVE ();
 
       while (answer == -1)
@@ -508,5 +508,64 @@
     }
 
   return (answer);
+}
+
+
+static void
+_protocol_ok_answer (char *buf, gftp_dialog_data * ddata)
+{
+  buf[1] = ' '; /* In case this is an empty string entered */
+  strncpy (buf, gtk_entry_get_text (GTK_ENTRY (ddata->edit)), BUFSIZ);
+}
+
+
+static void
+_protocol_cancel_answer (char *buf, gftp_dialog_data * ddata)
+{
+  buf[0] = '\0';
+  buf[1] = '\0';
+}
+
+
+char *
+gftpui_protocol_ask_user_input (gftp_request * request, char *title,
+                                char *question, int shown)
+{
+  char buf[BUFSIZ];
+
+  GDK_THREADS_ENTER ();
+
+  *buf = '\0';
+  *(buf + 1) = ' ';
+  MakeEditDialog (title, question, NULL, shown, NULL, gftp_dialog_button_ok,
+                  _protocol_ok_answer, &buf, _protocol_cancel_answer, &buf);
+
+  if (gftp_protocols[request->protonum].use_threads)
+    {
+      /* Let the main loop in the main thread run the events */
+      GDK_THREADS_LEAVE ();
+
+      while (*buf == '\0' && *(buf + 1) == ' ')
+        {
+          sleep (1);
+        }
+    }
+  else
+    {
+      while (*buf == '\0' && *(buf + 1) == ' ')
+        {
+          GDK_THREADS_LEAVE ();
+#if GTK_MAJOR_VERSION == 1
+          g_main_iteration (TRUE);
+#else
+          g_main_context_iteration (NULL, TRUE);
+#endif
+        }
+    }
+
+  if (*buf != '\0')
+    return (g_strdup (buf));
+  else
+    return (NULL);
 }
 
Index: src/text/textui.c
===================================================================
RCS file: /cvs/gnome/gftp/src/text/textui.c,v
retrieving revision 1.9
diff -u -r1.9 textui.c
--- src/text/textui.c	15 Apr 2004 00:59:23 -0000	1.9
+++ src/text/textui.c	16 Jun 2004 00:58:20 -0000
@@ -265,3 +265,19 @@
   return (ret);
 }
 
+
+char *
+gftpui_protocol_ask_user_input (gftp_request * request, char *title,
+                                char *question, int shown)
+{
+  char buf[255];
+
+  do
+    {
+      gftp_text_ask_question (question, shown, buf, sizeof (buf));
+    }
+  while (*buf == '\0');
+
+  return (g_strdup (buf));
+}
+