Miscellaneous ssh2 fixes. plink is now relatively sane
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Thu, 21 Sep 2000 14:34:32 +0000 (14:34 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Thu, 21 Sep 2000 14:34:32 +0000 (14:34 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@608 cda61777-01e9-0310-a592-d414129be87e

plink.c
putty.h
scp.c
scp.h
ssh.c
window.c

diff --git a/plink.c b/plink.c
index 5022761..70aab6d 100644 (file)
--- a/plink.c
+++ b/plink.c
@@ -43,6 +43,50 @@ struct input_data {
     HANDLE event;
 };
 
+static int get_password(const char *prompt, char *str, int maxlen)
+{
+    HANDLE hin, hout;
+    DWORD savemode, i;
+
+#if 0 /* this allows specifying a password some other way */
+    if (password) {
+        static int tried_once = 0;
+
+        if (tried_once) {
+            return 0;
+        } else {
+            strncpy(str, password, maxlen);
+            str[maxlen-1] = '\0';
+            tried_once = 1;
+            return 1;
+        }
+    }
+#endif
+
+    hin = GetStdHandle(STD_INPUT_HANDLE);
+    hout = GetStdHandle(STD_OUTPUT_HANDLE);
+    if (hin == INVALID_HANDLE_VALUE || hout == INVALID_HANDLE_VALUE) {
+        fprintf(stderr, "Cannot get standard input/output handles");
+        return 0;
+    }
+
+    GetConsoleMode(hin, &savemode);
+    SetConsoleMode(hin, (savemode & (~ENABLE_ECHO_INPUT)) |
+                   ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT);
+
+    WriteFile(hout, prompt, strlen(prompt), &i, NULL);
+    ReadFile(hin, str, maxlen-1, &i, NULL);
+
+    SetConsoleMode(hin, savemode);
+
+    if ((int)i > maxlen) i = maxlen-1; else i = i - 2;
+    str[i] = '\0';
+
+    WriteFile(hout, "\r\n", 2, &i, NULL);
+
+    return 1;
+}
+
 int WINAPI stdin_read_thread(void *param) {
     struct input_data *idata = (struct input_data *)param;
     HANDLE inhandle;
@@ -70,7 +114,9 @@ int main(int argc, char **argv) {
     struct input_data idata;
     int sending;
 
-    flags = FLAG_CONNECTION;
+    ssh_get_password = get_password;
+
+    flags = FLAG_STDERR;
     /*
      * Process the command line.
      */
@@ -83,6 +129,8 @@ int main(int argc, char **argv) {
             if (!strcmp(p, "-ssh")) {
                default_protocol = cfg.protocol = PROT_SSH;
                default_port = cfg.port = 22;
+           } else if (!strcmp(p, "-v")) {
+                flags |= FLAG_VERBOSE;
            } else if (!strcmp(p, "-log")) {
                 logfile = "putty.log";
            }
@@ -165,6 +213,9 @@ int main(int argc, char **argv) {
        }
     }
 
+    if (!*cfg.remote_cmd)
+        flags |= FLAG_INTERACTIVE;
+
     /*
      * Select protocol. This is farmed out into a table in a
      * separate file to enable an ssh-free variant.
diff --git a/putty.h b/putty.h
index 4b9c30f..bc9d689 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -203,10 +203,21 @@ typedef struct {
 
 /*
  * Some global flags denoting the type of application.
+ * 
+ * FLAG_VERBOSE is set when the user requests verbose details.
+ * 
+ * FLAG_STDERR is set in command-line applications (which have a
+ * functioning stderr that it makes sense to write to) and not in
+ * GUI applications (which don't).
+ * 
+ * FLAG_INTERACTIVE is set when a full interactive shell session is
+ * being run, _either_ because no remote command has been provided
+ * _or_ because the application is GUI and can't run non-
+ * interactively.
  */
-#define FLAG_VERBOSE  0x0001
-#define FLAG_WINDOWED 0x0002
-#define FLAG_CONNECTION 0x0004
+#define FLAG_VERBOSE     0x0001
+#define FLAG_STDERR      0x0002
+#define FLAG_INTERACTIVE 0x0004
 GLOBAL int flags;
 
 GLOBAL Config cfg;
@@ -292,6 +303,7 @@ extern Backend telnet_backend;
  * Exports from ssh.c.
  */
 
+extern int (*ssh_get_password)(const char *prompt, char *str, int maxlen);
 extern Backend ssh_backend;
 
 /*
diff --git a/scp.c b/scp.c
index b1cae2f..1160139 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -957,7 +957,7 @@ int main(int argc, char *argv[])
 
     default_protocol = PROT_TELNET;
 
-    flags = 0;
+    flags = FLAG_STDERR;
     ssh_get_password = &get_password;
     init_winsock();
 
diff --git a/scp.h b/scp.h
index a3eabf5..bb7c0f7 100644 (file)
--- a/scp.h
+++ b/scp.h
@@ -5,7 +5,6 @@
 
 /* Exported from ssh.c */
 extern int scp_flags;
-extern int (*ssh_get_password)(const char *prompt, char *str, int maxlen);
 char * ssh_scp_init(char *host, int port, char *cmd, char **realhost);
 int ssh_scp_recv(unsigned char *buf, int len);
 void ssh_scp_send(unsigned char *buf, int len);
diff --git a/ssh.c b/ssh.c
index ff6e837..88379c5 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -17,7 +17,7 @@
 #endif
 
 #define logevent(s) { logevent(s); \
-                      if (!(flags & FLAG_CONNECTION) && (flags & FLAG_VERBOSE)) \
+                      if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \
                       fprintf(stderr, "%s\n", s); }
 
 #define SSH1_MSG_DISCONNECT                       1    /* 0x1 */
@@ -269,7 +269,7 @@ static int s_read (char *buf, int len) {
 }
 
 static void c_write (char *buf, int len) {
-    if (!(flags & FLAG_CONNECTION)) {
+    if ((flags & FLAG_STDERR)) {
         int i;
         for (i = 0; i < len; i++)
             if (buf[i] != '\r')
@@ -1190,8 +1190,9 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
        static char username[100];
        static int pos = 0;
        static char c;
-       if ((flags & FLAG_CONNECTION) && !*cfg.username) {
+       if ((flags & FLAG_INTERACTIVE) && !*cfg.username) {
            c_write("login as: ", 10);
+            ssh_send_ok = 1;
            while (pos >= 0) {
                crWaitUntil(!ispkt);
                while (inlen--) switch (c = *in++) {
@@ -1230,7 +1231,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
            char stuff[200];
            strncpy(username, cfg.username, 99);
            username[99] = '\0';
-            if (flags & FLAG_VERBOSE) {
+            if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
                sprintf(stuff, "Sent username \"%s\".\r\n", username);
                 c_write(stuff, strlen(stuff));
            }
@@ -1362,7 +1363,8 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
         if (*cfg.keyfile && !tried_publickey)
             pwpkt_type = SSH1_CMSG_AUTH_RSA;
 
-       if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD && !FLAG_WINDOWED) {
+       if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD &&
+            !(flags & FLAG_INTERACTIVE)) {
            char prompt[200];
            sprintf(prompt, "%s@%s's password: ", cfg.username, savedhost);
            if (!ssh_get_password(prompt, password, sizeof(password))) {
@@ -1431,6 +1433,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
             }
 
             pos = 0;
+            ssh_send_ok = 1;
             while (pos >= 0) {
                 crWaitUntil(!ispkt);
                 while (inlen--) switch (c = *in++) {
@@ -2079,8 +2082,9 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
        static int pos = 0;
        static char c;
 
-       if ((flags & FLAG_CONNECTION) && !*cfg.username) {
+       if ((flags & FLAG_INTERACTIVE) && !*cfg.username) {
            c_write("login as: ", 10);
+            ssh_send_ok = 1;
            while (pos >= 0) {
                crWaitUntilV(!ispkt);
                while (inlen--) switch (c = *in++) {
@@ -2119,13 +2123,13 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
            char stuff[200];
            strncpy(username, cfg.username, 99);
            username[99] = '\0';
-           if (flags & FLAG_VERBOSE) {
+            if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
                sprintf(stuff, "Using username \"%s\".\r\n", username);
                c_write(stuff, strlen(stuff));
            }
        }
 
-       if (!(flags & FLAG_WINDOWED)) {
+       if (!(flags & FLAG_INTERACTIVE)) {
            char prompt[200];
            sprintf(prompt, "%s@%s's password: ", cfg.username, savedhost);
            if (!ssh_get_password(prompt, password, sizeof(password))) {
@@ -2141,6 +2145,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
             }
        } else {
             c_write("password: ", 10);
+            ssh_send_ok = 1;
 
             pos = 0;
             while (pos >= 0) {
@@ -2222,39 +2227,53 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
     /*
      * Now allocate a pty for the session.
      */
-    ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
-    ssh2_pkt_adduint32(mainchan->remoteid); /* recipient channel */
-    ssh2_pkt_addstring("pty-req");
-    ssh2_pkt_addbool(1);               /* want reply */
-    ssh2_pkt_addstring(cfg.termtype);
-    ssh2_pkt_adduint32(cols);
-    ssh2_pkt_adduint32(rows);
-    ssh2_pkt_adduint32(0);             /* pixel width */
-    ssh2_pkt_adduint32(0);             /* pixel height */
-    ssh2_pkt_addstring_start();
-    ssh2_pkt_addstring_data("\0", 1);  /* TTY_OP_END, no special options */
-    ssh2_pkt_send();
+    if (!cfg.nopty) {
+        ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
+        ssh2_pkt_adduint32(mainchan->remoteid); /* recipient channel */
+        ssh2_pkt_addstring("pty-req");
+        ssh2_pkt_addbool(1);           /* want reply */
+        ssh2_pkt_addstring(cfg.termtype);
+        ssh2_pkt_adduint32(cols);
+        ssh2_pkt_adduint32(rows);
+        ssh2_pkt_adduint32(0);         /* pixel width */
+        ssh2_pkt_adduint32(0);         /* pixel height */
+        ssh2_pkt_addstring_start();
+        ssh2_pkt_addstring_data("\0", 1);/* TTY_OP_END, no special options */
+        ssh2_pkt_send();
 
-    do {                               /* FIXME: pay attention to these */
-        crWaitUntilV(ispkt);
-    } while (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
+        do {
+            crWaitUntilV(ispkt);
+            if (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
+                /* FIXME: be able to handle other channels here */
+                if (ssh2_pkt_getuint32() != mainchan->localid)
+                    continue;          /* wrong channel */
+                mainchan->u.v2.remwindow += ssh2_pkt_getuint32();
+            }
+        } while (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
 
-    if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
-        if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
-            fatalbox("Server got confused by pty request");
+        if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
+            if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
+                fatalbox("Server got confused by pty request");
+            }
+            c_write("Server refused to allocate pty\r\n", 32);
+        } else {
+            logevent("Allocated pty");
         }
-        c_write("Server refused to allocate pty\r\n", 32);
-    } else {
-        logevent("Allocated pty");
     }
 
     /*
-     * Start a shell.
+     * Start a shell or a remote command.
      */
     ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
     ssh2_pkt_adduint32(mainchan->remoteid); /* recipient channel */
-    ssh2_pkt_addstring("shell");
-    ssh2_pkt_addbool(1);               /* want reply */
+    if (*cfg.remote_cmd) {
+        ssh2_pkt_addstring("exec");
+        ssh2_pkt_addbool(1);           /* want reply */
+        ssh2_pkt_addstring(cfg.remote_cmd);
+    } else {
+        ssh2_pkt_addstring("shell");
+        ssh2_pkt_addbool(1);           /* want reply */
+    }
     ssh2_pkt_send();
     do {
         crWaitUntilV(ispkt);
@@ -2502,13 +2521,14 @@ static void ssh_size(void) {
  */
 static void ssh_special (Telnet_Special code) {
     if (code == TS_EOF) {
-        if (ssh_version = 1) {
+        if (ssh_version == 1) {
             send_packet(SSH1_CMSG_EOF, PKT_END);
         } else {
             ssh2_pkt_init(SSH2_MSG_CHANNEL_EOF);
             ssh2_pkt_adduint32(mainchan->remoteid);
             ssh2_pkt_send();
         }
+        logevent("Sent EOF message");
     } else {
         /* do nothing */
     }
index 4e70dfe..685b4f3 100644 (file)
--- a/window.c
+++ b/window.c
@@ -90,7 +90,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
     int guess_width, guess_height;
 
     putty_inst = inst;
-    flags = FLAG_VERBOSE | FLAG_WINDOWED | FLAG_CONNECTION;
+    flags = FLAG_VERBOSE | FLAG_INTERACTIVE;
 
     winsock_ver = MAKEWORD(1, 1);
     if (WSAStartup(winsock_ver, &wsadata)) {