Implement OpenSSH-compatible RSA key fingerprints and use them throughout
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index fddb68d..0db92fc 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -2,7 +2,13 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <assert.h>
+#ifndef AUTO_WINSOCK
+#ifdef WINSOCK_TWO
+#include <winsock2.h>
+#else
 #include <winsock.h>
+#endif
+#endif
 
 #include "putty.h"
 #include "tree234.h"
@@ -1094,21 +1100,15 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
     j = makekey(pktin.body+8+i, &hostkey, &keystr2, 0);
 
     /*
-     * Hash the host key and print the hash in the log box. Just as
-     * a last resort in case the registry's host key checking is
-     * compromised, we'll allow the user some ability to verify
-     * host keys by eye.
+     * Log the host key fingerprint.
      */
-    MD5Init(&md5c);
-    MD5Update(&md5c, keystr2, hostkey.bytes);
-    MD5Final(session_id, &md5c);
     {
        char logmsg[80];
-       int i;
-       logevent("Host key MD5 is:");
+       logevent("Host key fingerprint is:");
        strcpy(logmsg, "      ");
-       for (i = 0; i < 16; i++)
-           sprintf(logmsg+strlen(logmsg), "%02x", session_id[i]);
+        hostkey.comment = NULL;
+        rsa_fingerprint(logmsg+strlen(logmsg), sizeof(logmsg)-strlen(logmsg),
+                        &hostkey);
        logevent(logmsg);
     }
 
@@ -1267,6 +1267,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
 
     while (pktin.type == SSH1_SMSG_FAILURE) {
        static char password[100];
+       static char prompt[200];
        static int pos;
        static char c;
         static int pwpkt_type;
@@ -1351,10 +1352,12 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
                                 crWaitUntil(ispkt);
                                 if (pktin.type == SSH1_SMSG_SUCCESS) {
                                     logevent("Pageant's response accepted");
-                                    c_write("Authenticated using RSA key \"",
-                                            29);
-                                    c_write(commentp, commentlen);
-                                    c_write("\" from agent\r\n", 14);
+                                    if (flags & FLAG_VERBOSE) {
+                                        c_write("Authenticated using RSA key \"",
+                                                29);
+                                        c_write(commentp, commentlen);
+                                        c_write("\" from agent\r\n", 14);
+                                    }
                                     authed = TRUE;
                                 } else
                                     logevent("Pageant's response not accepted");
@@ -1379,10 +1382,71 @@ 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 &&
-            !(flags & FLAG_INTERACTIVE)) {
-           char prompt[200];
-           sprintf(prompt, "%s@%s's password: ", cfg.username, savedhost);
+        if (pktin.type == SSH1_SMSG_FAILURE &&
+            cfg.try_tis_auth &&
+            (supported_auths_mask & (1<<SSH1_AUTH_TIS))) {
+            pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
+            logevent("Requested TIS authentication");
+            send_packet(SSH1_CMSG_AUTH_TIS, PKT_END);
+            crWaitUntil(ispkt);
+            if (pktin.type != SSH1_SMSG_AUTH_TIS_CHALLENGE) {
+                logevent("TIS authentication declined");
+                if (flags & FLAG_INTERACTIVE)
+                    c_write("TIS authentication refused.\r\n", 29);
+            } else {
+                int challengelen = ((pktin.body[0] << 24) |
+                                    (pktin.body[1] << 16) |
+                                    (pktin.body[2] << 8) |
+                                    (pktin.body[3]));
+                logevent("Received TIS challenge");
+                if (challengelen > sizeof(prompt)-1)
+                    challengelen = sizeof(prompt)-1;   /* prevent overrun */
+                memcpy(prompt, pktin.body+4, challengelen);
+                prompt[challengelen] = '\0';
+            }
+        }
+        if (pktin.type == SSH1_SMSG_FAILURE &&
+            cfg.try_tis_auth &&
+            (supported_auths_mask & (1<<SSH1_AUTH_CCARD))) {
+            pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
+            logevent("Requested CryptoCard authentication");
+            send_packet(SSH1_CMSG_AUTH_CCARD, PKT_END);
+            crWaitUntil(ispkt);
+            if (pktin.type != SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
+                logevent("CryptoCard authentication declined");
+                c_write("CryptoCard authentication refused.\r\n", 29);
+            } else {
+                int challengelen = ((pktin.body[0] << 24) |
+                                    (pktin.body[1] << 16) |
+                                    (pktin.body[2] << 8) |
+                                    (pktin.body[3]));
+                logevent("Received CryptoCard challenge");
+                if (challengelen > sizeof(prompt)-1)
+                    challengelen = sizeof(prompt)-1;   /* prevent overrun */
+                memcpy(prompt, pktin.body+4, challengelen);
+                strncpy(prompt + challengelen, "\r\nResponse : ",
+                        sizeof(prompt)-challengelen);
+                prompt[sizeof(prompt)-1] = '\0';
+            }
+        }
+        if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD) {
+            sprintf(prompt, "%.90s@%.90s's password: ",
+                    cfg.username, savedhost);
+        }
+        if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
+            char *comment = NULL;
+            if (flags & FLAG_VERBOSE)
+                c_write("Trying public key authentication.\r\n", 35);
+            if (!rsakey_encrypted(cfg.keyfile, &comment)) {
+                if (flags & FLAG_VERBOSE)
+                    c_write("No passphrase required.\r\n", 25);
+                goto tryauth;
+            }
+            sprintf(prompt, "Passphrase for key \"%.100s\": ", comment);
+            free(comment);
+        }
+
+       if (!(flags & FLAG_INTERACTIVE)) {
            if (!ssh_get_password(prompt, password, sizeof(password))) {
                 /*
                  * get_password failed to get a password (for
@@ -1395,59 +1459,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
                 crReturn(1);
             }
        } else {
-
-            if (pktin.type == SSH1_SMSG_FAILURE &&
-                cfg.try_tis_auth &&
-                (supported_auths_mask & (1<<SSH1_AUTH_TIS))) {
-                pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
-                logevent("Requested TIS authentication");
-                send_packet(SSH1_CMSG_AUTH_TIS, PKT_END);
-                crWaitUntil(ispkt);
-                if (pktin.type != SSH1_SMSG_AUTH_TIS_CHALLENGE) {
-                    logevent("TIS authentication declined");
-                    c_write("TIS authentication refused.\r\n", 29);
-                } else {
-                    int challengelen = ((pktin.body[0] << 24) |
-                                        (pktin.body[1] << 16) |
-                                        (pktin.body[2] << 8) |
-                                        (pktin.body[3]));
-                    logevent("Received TIS challenge");
-                    c_write(pktin.body+4, challengelen);
-                }
-            }
-            if (pktin.type == SSH1_SMSG_FAILURE &&
-                cfg.try_tis_auth &&
-                (supported_auths_mask & (1<<SSH1_AUTH_CCARD))) {
-                pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
-                logevent("Requested CryptoCard authentication");
-                send_packet(SSH1_CMSG_AUTH_CCARD, PKT_END);
-                crWaitUntil(ispkt);
-                if (pktin.type != SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
-                    logevent("CryptoCard authentication declined");
-                    c_write("CryptoCard authentication refused.\r\n", 29);
-                } else {
-                    int challengelen = ((pktin.body[0] << 24) |
-                                        (pktin.body[1] << 16) |
-                                        (pktin.body[2] << 8) |
-                                        (pktin.body[3]));
-                    logevent("Received CryptoCard challenge");
-                    c_write(pktin.body+4, challengelen);
-                    c_write("\r\nResponse : ", 13);
-                }
-            }
-            if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD)
-                c_write("password: ", 10);
-            if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
-                if (flags & FLAG_VERBOSE)
-                    c_write("Trying public key authentication.\r\n", 35);
-                if (!rsakey_encrypted(cfg.keyfile)) {
-                    if (flags & FLAG_VERBOSE)
-                        c_write("No passphrase required.\r\n", 25);
-                    goto tryauth;
-                }
-                c_write("passphrase: ", 12);
-            }
-
+            c_write(prompt, strlen(prompt));
             pos = 0;
             ssh_send_ok = 1;
             while (pos >= 0) {
@@ -1476,8 +1488,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
                 }
             }
             c_write("\r\n", 2);
-
-       }
+        }
 
         tryauth:
        if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
@@ -1512,8 +1523,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
 
             crWaitUntil(ispkt);
             if (pktin.type == SSH1_SMSG_FAILURE) {
-                if (flags & FLAG_VERBOSE)
-                    c_write("Server refused our public key.\r\n", 32);
+                c_write("Server refused our public key.\r\n", 32);
                 continue;              /* go and try password */
             }
             if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
@@ -1628,6 +1638,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
 
     ssh_send_ok = 1;
     ssh_channels = newtree234(ssh_channelcmp);
+    begin_session();
     while (1) {
        crReturnV;
        if (ispkt) {
@@ -1654,6 +1665,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
                 c->localid = i;
                 c->closes = 0;
                 c->type = SSH1_SMSG_AGENT_OPEN;   /* identify channel type */
+                c->u.a.lensofar = 0;
                 add234(ssh_channels, c);
                 send_packet(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
                             PKT_INT, c->remoteid, PKT_INT, c->localid,
@@ -2335,6 +2347,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
      * Transfer data!
      */
     ssh_send_ok = 1;
+    begin_session();
     while (1) {
         static int try_send;
        crReturnV;