At long last: PuTTY will now report its version to the server
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index 549a1e5..1077b33 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1193,7 +1193,8 @@ static int do_ssh_init(unsigned char c) {
         /*
          * This is a v2 server. Begin v2 protocol.
          */
-        char *verstring = "SSH-2.0-PuTTY";
+        char verstring[80];
+        sprintf(verstring, "SSH-2.0-%s", sshver);
         SHA_Init(&exhashbase);
         /*
          * Hash our version string and their version string.
@@ -1212,8 +1213,9 @@ static int do_ssh_init(unsigned char c) {
         /*
          * This is a v1 server. Begin v1 protocol.
          */
-        sprintf(vstring, "SSH-%s-PuTTY\n",
-                (ssh_versioncmp(version, "1.5") <= 0 ? version : "1.5"));
+        sprintf(vstring, "SSH-%s-%s\n",
+                (ssh_versioncmp(version, "1.5") <= 0 ? version : "1.5"),
+                sshver);
         sprintf(vlog, "We claim version: %s", vstring);
         vlog[strcspn(vlog, "\r\n")] = '\0';
         logevent(vlog);
@@ -1270,21 +1272,20 @@ static void ssh_gotdata(unsigned char *data, int datalen)
     crFinishV;
 }
 
-static int ssh_receive(Socket skt, int urgent, char *data, int len) {
-    if (urgent==3) {
+static int ssh_closing (Plug plug, char *error_msg, int error_code, int calling_back) {
+    ssh_state = SSH_STATE_CLOSED;
+    sk_close(s);
+    s = NULL;
+    if (error_msg) {
         /* A socket error has occurred. */
-        ssh_state = SSH_STATE_CLOSED;
-        sk_close(s);
-        s = NULL;
-        connection_fatal(data);
-        return 0;
-    } else if (!len) {
-       /* Connection has closed. */
-       ssh_state = SSH_STATE_CLOSED;
-       sk_close(s);
-       s = NULL;
-       return 0;
+        connection_fatal (error_msg);
+    } else {
+       /* Otherwise, the remote side closed the connection normally. */
     }
+    return 0;
+}
+
+static int ssh_receive(Plug plug, int urgent, char *data, int len) {
     ssh_gotdata (data, len);
     if (ssh_state == SSH_STATE_CLOSED) {
         if (s) {
@@ -1303,6 +1304,11 @@ static int ssh_receive(Socket skt, int urgent, char *data, int len) {
  */
 static char *connect_to_host(char *host, int port, char **realhost)
 {
+    static struct plug_function_table fn_table = {
+       ssh_closing,
+       ssh_receive
+    }, *fn_table_ptr = &fn_table;
+
     SockAddr addr;
     char *err;
 #ifdef FWHACK
@@ -1340,7 +1346,7 @@ static char *connect_to_host(char *host, int port, char **realhost)
     /*
      * Open socket.
      */
-    s = sk_new(addr, port, 0, 1, ssh_receive);
+    s = sk_new(addr, port, 0, 1, &fn_table_ptr);
     if ( (err = sk_socket_error(s)) )
        return err;
 
@@ -1604,7 +1610,8 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
             request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
             agent_query(request, 5, &r, &responselen);
             response = (unsigned char *)r;
-            if (response) {
+            if (response && responselen >= 5 &&
+                response[4] == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
                 p = response + 5;
                 nkeys = GET_32BIT(p); p += 4;
                 { char buf[64]; sprintf(buf, "Pageant has %d SSH1 keys", nkeys);
@@ -1978,7 +1985,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
 }
 
 void sshfwd_close(struct ssh_channel *c) {
-    if (c) {
+    if (c && !c->closes) {
         if (ssh_version == 1) {
             send_packet(SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid, PKT_END);
         } else {
@@ -2865,7 +2872,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
                      */
                     logevent("No username provided. Abandoning session.");
                     ssh_state = SSH_STATE_CLOSED;
-                    crReturn(1);
+                    crReturnV;
                 }
             } else {
                 c_write_str("login as: ");
@@ -3031,7 +3038,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
                request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
                agent_query(request, 5, &r, &responselen);
                response = (unsigned char *)r;
-               if (response) {
+               if (response && responselen >= 5 &&
+                    response[4] == SSH2_AGENT_IDENTITIES_ANSWER) {
                    p = response + 5;
                    nkeys = GET_32BIT(p); p += 4;
                    { char buf[64]; sprintf(buf, "Pageant has %d SSH2 keys", nkeys);
@@ -3452,9 +3460,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
      * Potentially enable agent forwarding.
      */
     if (cfg.agentfwd && agent_exists()) {
-        char proto[20], data[64];
         logevent("Requesting OpenSSH-style agent forwarding");
-        x11_invent_auth(proto, sizeof(proto), data, sizeof(data));
         ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
         ssh2_pkt_adduint32(mainchan->remoteid);
         ssh2_pkt_addstring("auth-agent-req@openssh.com");