# HG changeset patch # User masneyb # Date 1081610086 0 # Node ID 656a0b3d1403a6f14c988da44be8c2a1bfe2e006 # Parent afa37403af96d2854f1b4a1ad59e4dfc1f31f0b2 2004-4-10 Brian Masney * lib/gftp.h lib/pty.c lib/sshv2.c - added gftp_exec() that will always open a pseudo terminal and a separate socket pair for the stdin/stdout file descriptors. The banner and password request will come through the pseudo terminal while the sftp protocol specific data will always come through the socket pair. This allows for a much cleaner SSH login sequence that does not require echo xsftp to capture a login banner. Removed option ssh_use_askpass since it is no longer needed. This code is based off of a suggestion from Gertjan Halkes * src/text/gftp-text.c - removed setting the options ssh_use_askpass and sshv2_use_sftp_subsys diff -r afa37403af96 -r 656a0b3d1403 ChangeLog --- a/ChangeLog Sat Apr 10 00:28:31 2004 +0000 +++ b/ChangeLog Sat Apr 10 15:14:46 2004 +0000 @@ -1,3 +1,16 @@ +2004-4-10 Brian Masney + * lib/gftp.h lib/pty.c lib/sshv2.c - added gftp_exec() that will always + open a pseudo terminal and a separate socket pair for the stdin/stdout + file descriptors. The banner and password request will come through the + pseudo terminal while the sftp protocol specific data will always come + through the socket pair. This allows for a much cleaner SSH login + sequence that does not require echo xsftp to capture a login banner. + Removed option ssh_use_askpass since it is no longer needed. + This code is based off of a suggestion from Gertjan Halkes + + * src/text/gftp-text.c - removed setting the options ssh_use_askpass + and sshv2_use_sftp_subsys + 2004-03-30 Gareth Owen * configure.in: Added en_GB to ALL_LINGUAS @@ -2406,7 +2419,7 @@ * cvsclean - added this script - * *.[ch] - added $Id: ChangeLog,v 1.256 2004/03/31 04:14:33 gowen Exp $ tags + * *.[ch] - added $Id: ChangeLog,v 1.257 2004/04/10 15:14:45 masneyb Exp $ tags * debian/* - updated files from Debian maintainer diff -r afa37403af96 -r 656a0b3d1403 lib/gftp.h --- a/lib/gftp.h Sat Apr 10 00:28:31 2004 +0000 +++ b/lib/gftp.h Sat Apr 10 15:14:46 2004 +0000 @@ -1007,12 +1007,9 @@ /* pty.c */ char * gftp_get_pty_impl ( void ); -pid_t gftp_exec_with_new_pty ( gftp_request * request, - int *fdm, - char **args ); - -pid_t gftp_exec_without_new_pty ( gftp_request * request, - int *fdm, +pid_t gftp_exec ( gftp_request * request, + int *fdm, + int *ptymfd, char **args ); #ifdef USE_SSL diff -r afa37403af96 -r 656a0b3d1403 lib/pty.c --- a/lib/pty.c Sat Apr 10 00:28:31 2004 +0000 +++ b/lib/pty.c Sat Apr 10 15:14:46 2004 +0000 @@ -259,7 +259,7 @@ static void -_gftp_close_all_fds (void) +_gftp_close_all_fds (int ptysfd) { int i, maxfds; @@ -272,16 +272,32 @@ #endif for (i=3; ilogging_function (gftp_logging_error, request->user_data, + _("Cannot open master pty %s: %s\n"), pts_name, + g_strerror (errno)); + return (-1); + } + if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) { request->logging_function (gftp_logging_error, request, @@ -294,24 +310,36 @@ { setsid (); + if ((ptysfd = _gftp_ptys_open (*ptymfd, ptysfd, pts_name)) < 0) + { + printf ("Cannot open slave pts %s: %s\n", pts_name, + g_strerror (errno)); + return (-1); + } + close (s[0]); + close (*ptymfd); _gftp_tty_raw (s[1]); + _gftp_tty_raw (ptysfd); + dup2 (s[1], 0); dup2 (s[1], 1); - dup2 (s[1], 2); - _gftp_close_all_fds (); + _gftp_close_all_fds (ptysfd); execvp (args[0], args); printf (_("Error: Cannot execute ssh: %s\n"), g_strerror (errno)); - exit (1); + _exit (1); } else if (child > 0) { close (s[1]); + + *fdm = s[0]; _gftp_tty_raw (s[0]); - *fdm = s[0]; + _gftp_tty_raw (*ptymfd); + return (child); } else @@ -323,58 +351,3 @@ } } - -pid_t -gftp_exec_with_new_pty (gftp_request * request, int *fdm, char **args) -{ - char pts_name[64]; - pid_t child; - int fds; - - *pts_name = '\0'; - if ((*fdm = _gftp_ptym_open (pts_name, sizeof (pts_name), &fds)) < 0) - { - request->logging_function (gftp_logging_error, request->user_data, - _("Cannot open master pty %s: %s\n"), pts_name, - g_strerror (errno)); - return (-1); - } - - if ((child = fork ()) == 0) - { - setsid (); - - if ((fds = _gftp_ptys_open (*fdm, fds, pts_name)) < 0) - { - printf ("Cannot open slave pts %s: %s\n", pts_name, - g_strerror (errno)); - return (-1); - } - - close (*fdm); - - _gftp_tty_raw (fds); - dup2 (fds, 0); - dup2 (fds, 1); - dup2 (fds, 2); - _gftp_close_all_fds (); - - execvp (args[0], args); - - printf (_("Error: Cannot execute ssh: %s\n"), g_strerror (errno)); - exit (1); - } - else if (child > 0) - { - _gftp_tty_raw (*fdm); - return (child); - } - else - { - request->logging_function (gftp_logging_error, request->user_data, - _("Cannot fork another process: %s\n"), - g_strerror (errno)); - return (-1); - } -} - diff -r afa37403af96 -r 656a0b3d1403 lib/sshv2.c --- a/lib/sshv2.c Sat Apr 10 00:28:31 2004 +0000 +++ b/lib/sshv2.c Sat Apr 10 15:14:46 2004 +0000 @@ -42,11 +42,6 @@ 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}, - {"ssh_use_askpass", N_("Use ssh-askpass utility"), - gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, - GFTP_CVARS_FLAGS_SHOW_BOOKMARK, - N_("Use the ssh-askpass utility to supply the remote password"), GFTP_PORT_GTK, - NULL}, {"sshv2_use_sftp_subsys", N_("Use SSH2 SFTP subsys"), gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, GFTP_CVARS_FLAGS_SHOW_BOOKMARK, @@ -253,7 +248,7 @@ " %s -s sftp", request->hostname); else sshv2_add_exec_args (&logstr, &logstr_len, &args, &args_len, &args_cur, - " %s \"%s\"", request->hostname, execname); + " %s %s", request->hostname, execname); request->logging_function (gftp_logging_misc, request, _("Running program %s\n"), logstr); @@ -262,33 +257,81 @@ } -static char * -sshv2_start_login_sequence (gftp_request * request, int fd) +static int +sshv2_start_login_sequence (gftp_request * request, int fdm, int ptymfd) { + size_t rem, len, diff, lastdiff; char *tempstr, *pwstr, *tmppos; - size_t rem, len, diff, lastdiff, key_pos; - int wrotepw, ok; + int wrotepw, ok, maxfd, ret; + fd_set rset, eset; ssize_t rd; rem = len = SSH_LOGIN_BUFSIZE; tempstr = g_malloc0 (len + 1); - key_pos = diff = lastdiff = 0; + diff = lastdiff = 0; wrotepw = 0; ok = 1; - if (gftp_fd_set_sockblocking (request, fd, 1) == -1) - return (NULL); + if (gftp_fd_set_sockblocking (request, fdm, 1) == -1) + return (GFTP_ERETRYABLE); + + if (gftp_fd_set_sockblocking (request, ptymfd, 1) == -1) + return (GFTP_ERETRYABLE); - pwstr = g_strconcat (request->password, "\n", NULL); + if (request->password == NULL) + pwstr = g_strdup ("\n"); + else + pwstr = g_strconcat (request->password, "\n", NULL); + + FD_ZERO (&rset); + FD_ZERO (&eset); + maxfd = fdm > ptymfd ? fdm : ptymfd; errno = 0; while (1) { - if ((rd = gftp_fd_read (request, tempstr + diff, rem - 1, fd)) <= 0) + FD_SET (fdm, &rset); + FD_SET (ptymfd, &rset); + + FD_SET (fdm, &eset); + FD_SET (ptymfd, &eset); + + ret = select (maxfd + 1, &rset, NULL, &eset, NULL); + if (ret < 0 && errno == EINTR) + continue; + + if (ret < 0) { - ok = 0; + request->logging_function (gftp_logging_error, request, + _("Connection to %s timed out\n"), + request->hostname); + gftp_disconnect (request); + return (GFTP_ERETRYABLE); + } + + if (FD_ISSET (fdm, &eset) || FD_ISSET (ptymfd, &eset)) + { + request->logging_function (gftp_logging_error, request, + _("Error: Could not read from socket: %s\n"), + g_strerror (errno)); + gftp_disconnect (request); + return (GFTP_ERETRYABLE); + } + + if (FD_ISSET (fdm, &rset)) + { + ok = 1; break; } + else if (!FD_ISSET (ptymfd, &rset)) + continue; + + rd = gftp_fd_read (request, tempstr + diff, rem - 1, ptymfd); + if (rd < 0) + return (rd); + else if (rd == 0) + continue; + rem -= rd; diff += rd; tempstr[diff] = '\0'; @@ -310,17 +353,16 @@ } wrotepw = 1; - if (gftp_fd_write (request, pwstr, strlen (pwstr), fd) < 0) + 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 + key_pos, "Enter passphrase for RSA key")) != NULL || - ((tmppos = strstr (tempstr + key_pos, "Enter passphrase for key '")) != NULL))) + ((tmppos = strstr (tempstr, "Enter passphrase for RSA key")) != NULL || + ((tmppos = strstr (tempstr, "Enter passphrase for key '")) != NULL))) { - key_pos = diff; if (wrotepw) { ok = SSH_ERROR_BADPASS; @@ -335,7 +377,7 @@ } wrotepw = 1; - if (gftp_fd_write (request, pwstr, strlen (pwstr), fd) < 0) + if (gftp_fd_write (request, pwstr, strlen (pwstr), ptymfd) < 0) { ok = 0; break; @@ -346,8 +388,6 @@ ok = SSH_ERROR_QUESTION; break; } - else if (diff >= 5 && strcmp (tempstr + diff - 5, "xsftp") == 0) - break; else if (rem <= 1) { request->logging_function (gftp_logging_recv, request, @@ -366,6 +406,8 @@ request->logging_function (gftp_logging_recv, request, "%s\n", tempstr + lastdiff); + g_free (tempstr); + if (ok <= 0) { if (ok == SSH_ERROR_BADPASS) @@ -378,11 +420,10 @@ request->logging_function (gftp_logging_error, request, _("Please correct the above warning to connect to this host.\n")); - g_free (tempstr); - return (NULL); + return (GFTP_EFATAL); } - return (tempstr); + return (0); } @@ -585,7 +626,7 @@ buf[len + 5] = '\0'; #ifdef DEBUG - printf ("\rSending: "); + printf ("\rSending to FD %d: ", request->datafd); for (clen=0; clenhostname); - /* Ugh!! We don't get a login banner from sftp-server, and if we are - using ssh-agent to cache a users password, then we won't receive - any initial text from the server, and we'll block. So I just send a - xsftp server banner over. I hope this works on most Unices */ - gftp_lookup_request_option (request, "ssh2_sftp_path", &ssh2_sftp_path); - gftp_lookup_request_option (request, "ssh_use_askpass", &ssh_use_askpass); gftp_lookup_request_option (request, "sshv2_use_sftp_subsys", &sshv2_use_sftp_subsys); @@ -902,35 +937,20 @@ request->port = ntohs (serv_struct.s_port); } - exepath = g_strdup_printf ("echo -n xsftp ; %s%csftp-server", p1, p2); + exepath = g_strdup_printf ("%s%csftp-server", p1, p2); args = sshv2_gen_exec_args (request, exepath, sshv2_use_sftp_subsys); - if (ssh_use_askpass || sshv2_use_sftp_subsys) - child = gftp_exec_without_new_pty (request, &fdm, args); - else - child = gftp_exec_with_new_pty (request, &fdm, args); + child = gftp_exec (request, &fdm, &ptymfd, args); if (child == 0) exit (0); - else if (child < 0) - return (GFTP_ERETRYABLE); - - if (!sshv2_use_sftp_subsys) - { - tempstr = sshv2_start_login_sequence (request, fdm); - if (!tempstr || !(strlen (tempstr) > 4 && strcmp (tempstr + strlen (tempstr) - 5, - "xsftp") == 0)) - { - sshv2_free_args (args); - g_free (exepath); - return (GFTP_EFATAL); - } - g_free (tempstr); - } sshv2_free_args (args); g_free (exepath); + if (child < 0) + return (GFTP_ERETRYABLE); + request->datafd = fdm; version = htonl (SSH_MY_VERSION); @@ -938,6 +958,10 @@ &version, 4)) < 0) return (ret); + ret = sshv2_start_login_sequence (request, fdm, ptymfd); + if (ret < 0) + return (ret); + memset (&message, 0, sizeof (message)); ret = sshv2_read_response (request, &message, -1); if (ret < 0) diff -r afa37403af96 -r 656a0b3d1403 src/text/gftp-text.c --- a/src/text/gftp-text.c Sat Apr 10 00:28:31 2004 +0000 +++ b/src/text/gftp-text.c Sat Apr 10 15:14:46 2004 +0000 @@ -238,20 +238,12 @@ gftp_text_remreq = gftp_request_new (); remuidata = gftp_text_remreq; - gftp_set_request_option (gftp_text_remreq, "ssh_use_askpass", - GINT_TO_POINTER(0)); - gftp_set_request_option (gftp_text_remreq, "sshv2_use_sftp_subsys", - GINT_TO_POINTER(0)); gftp_text_remreq->logging_function = gftp_text_log; gftp_text_locreq = gftp_request_new (); locuidata = gftp_text_locreq; - gftp_set_request_option (gftp_text_locreq, "ssh_use_askpass", - GINT_TO_POINTER(0)); - gftp_set_request_option (gftp_text_locreq, "sshv2_use_sftp_subsys", - GINT_TO_POINTER(0)); + gftp_text_locreq->logging_function = gftp_text_log; - gftp_text_locreq->logging_function = gftp_text_log; if (gftp_protocols[GFTP_LOCAL_NUM].init (gftp_text_locreq) == 0) { gftp_setup_startup_directory (gftp_text_locreq);