Add another bug workaround, this one for old OpenSSH (<2.3) servers
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 4 Feb 2003 13:02:51 +0000 (13:02 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 4 Feb 2003 13:02:51 +0000 (13:02 +0000)
which have a strange idea of what data should be signed in a PK auth
request. This actually got in my way while doing serious things at
work! :-)

git-svn-id: svn://svn.tartarus.org/sgt/putty@2800 cda61777-01e9-0310-a592-d414129be87e

doc/config.but
putty.h
settings.c
ssh.c
windlg.c

index 6e4539c..77a5566 100644 (file)
@@ -1,4 +1,4 @@
-\versionid $Id: config.but,v 1.53 2003/02/01 02:09:02 jacob Exp $
+\versionid $Id: config.but,v 1.54 2003/02/04 13:02:51 simon Exp $
 
 \C{config} Configuring PuTTY
 
@@ -2172,6 +2172,24 @@ workaround, you need to enable it manually.
 
 This is an SSH2-specific bug.
 
+\S{config-ssh-bug-pksessid2} \q{Misuses the session ID in PK auth}
+
+\cfg{winhelp-topic}{ssh.bugs.rsapad2}
+
+Versions below 2.3 of OpenSSH require SSH2 public-key authentication
+to be done slightly differently: the data to be signed by the client
+contains the session ID formatted in a different way. If public-key
+authentication mysteriously does not work but the Event Log (see
+\k{using-eventlog}) thinks it has successfully sent a signature, it
+might be worth enabling the workaround for this bug to see if it
+helps.
+
+If this bug is detected, PuTTY will sign data in the way OpenSSH
+expects. If this bug is enabled when talking to a correct server,
+SSH2 public-key authentication will fail.
+
+This is an SSH2-specific bug.
+
 \H{config-file} Storing configuration in a file
 
 PuTTY does not currently support storing its configuration in a file
diff --git a/putty.h b/putty.h
index 72d0cd2..5c5b1c1 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -439,7 +439,7 @@ struct config_tag {
     /* SSH bug compatibility modes */
     int sshbug_ignore1, sshbug_plainpw1, sshbug_rsa1,
        sshbug_hmac2, sshbug_derivekey2, sshbug_rsapad2,
-       sshbug_dhgex2;
+       sshbug_dhgex2, sshbug_pksessid2;
     /* Options for pterm. Should split out into platform-dependent part. */
     int stamp_utmp;
     int login_shell;
index a4c514f..790b933 100644 (file)
@@ -343,6 +343,7 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg)
     write_setting_i(sesskey, "BugDeriveKey2", 2-cfg->sshbug_derivekey2);
     write_setting_i(sesskey, "BugRSAPad2", 2-cfg->sshbug_rsapad2);
     write_setting_i(sesskey, "BugDHGEx2", 2-cfg->sshbug_dhgex2);
+    write_setting_i(sesskey, "BugPKSessID2", 2-cfg->sshbug_pksessid2);
     write_setting_i(sesskey, "StampUtmp", cfg->stamp_utmp);
     write_setting_i(sesskey, "LoginShell", cfg->login_shell);
     write_setting_i(sesskey, "ScrollbarOnLeft", cfg->scrollbar_on_left);
@@ -616,6 +617,7 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg)
     gppi(sesskey, "BugDeriveKey2", 0, &i); cfg->sshbug_derivekey2 = 2-i;
     gppi(sesskey, "BugRSAPad2", 0, &i); cfg->sshbug_rsapad2 = 2-i;
     gppi(sesskey, "BugDHGEx2", 0, &i); cfg->sshbug_dhgex2 = 2-i;
+    gppi(sesskey, "BugPKSessID2", 0, &i); cfg->sshbug_pksessid2 = 2-i;
     gppi(sesskey, "StampUtmp", 1, &cfg->stamp_utmp);
     gppi(sesskey, "LoginShell", 1, &cfg->login_shell);
     gppi(sesskey, "ScrollbarOnLeft", 0, &cfg->scrollbar_on_left);
diff --git a/ssh.c b/ssh.c
index 88af248..ba2e075 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -163,6 +163,7 @@ static const char *const ssh2_disconnect_reasons[] = {
 #define BUG_SSH2_RSA_PADDING                    16
 #define BUG_SSH2_DERIVEKEY                       32
 #define BUG_SSH2_DH_GEX                          64
+#define BUG_SSH2_PK_SESSIONID                   128
 
 #define translate(x) if (type == x) return #x
 #define translatec(x,ctx) if (type == x && (pkt_ctx & ctx)) return #x
@@ -1792,6 +1793,17 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version has SSH2 RSA padding bug");
     }
 
+    if (ssh->cfg.sshbug_pksessid2 == FORCE_ON ||
+       (ssh->cfg.sshbug_pksessid2 == AUTO &&
+        wc_match("OpenSSH_2.[0-2]*", imp))) {
+       /*
+        * These versions have the SSH2 session-ID bug in
+        * public-key authentication.
+        */
+       ssh->remote_bugs |= BUG_SSH2_PK_SESSIONID;
+       logevent("We believe remote version has SSH2 public-key-session-ID bug");
+    }
+
     if (ssh->cfg.sshbug_dhgex2 == FORCE_ON) {
        /*
         * User specified the SSH2 DH GEX bug.
@@ -4629,6 +4641,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                        ssh2_pkt_addstring_data(ssh, s->pkblob, s->pklen);
 
                        s->siglen = ssh->pktout.length - 5 + 4 + 20;
+                        if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
+                            s->siglen -= 4;
                        s->len = 1;       /* message type */
                        s->len += 4 + s->pklen; /* key blob */
                        s->len += 4 + s->siglen;        /* data to sign */
@@ -4644,8 +4658,10 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                        PUT_32BIT(s->q, s->siglen);
                        s->q += 4;
                        /* Now the data to be signed... */
-                       PUT_32BIT(s->q, 20);
-                       s->q += 4;
+                        if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
+                            PUT_32BIT(s->q, 20);
+                            s->q += 4;
+                        }
                        memcpy(s->q, ssh->v2_session_id, 20);
                        s->q += 20;
                        memcpy(s->q, ssh->pktout.data + 5,
@@ -4894,6 +4910,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                } else {
                    unsigned char *pkblob, *sigblob, *sigdata;
                    int pkblob_len, sigblob_len, sigdata_len;
+                    int p;
 
                    /*
                     * We have loaded the private key and the server
@@ -4919,11 +4936,19 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                     * outgoing packet.
                     */
                    sigdata_len = ssh->pktout.length - 5 + 4 + 20;
+                    if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
+                        sigdata_len -= 4;
                    sigdata = smalloc(sigdata_len);
-                   PUT_32BIT(sigdata, 20);
-                   memcpy(sigdata + 4, ssh->v2_session_id, 20);
-                   memcpy(sigdata + 24, ssh->pktout.data + 5,
+                    p = 0;
+                    if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
+                        PUT_32BIT(sigdata+p, 20);
+                        p += 4;
+                    }
+                   memcpy(sigdata+p, ssh->v2_session_id, 20); p += 20;
+                   memcpy(sigdata+p, ssh->pktout.data + 5,
                           ssh->pktout.length - 5);
+                    p += ssh->pktout.length - 5;
+                    assert(p == sigdata_len);
                    sigblob = key->alg->sign(key->data, (char *)sigdata,
                                             sigdata_len, &sigblob_len);
                    ssh2_add_sigblob(ssh, pkblob, pkblob_len,
index 944cfda..9299a00 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -559,6 +559,8 @@ enum { IDCX_ABOUT =
     IDC_BUGD_RSAPAD2,
     IDC_BUGS_DHGEX2,
     IDC_BUGD_DHGEX2,
+    IDC_BUGS_PKSESSID2,
+    IDC_BUGD_PKSESSID2,
     sshbugspanelend,
 
     selectionpanelstart,
@@ -1066,6 +1068,9 @@ char *help_context_cmd(int id)
       case IDC_BUGS_DHGEX2:
       case IDC_BUGD_DHGEX2:
        return "JI(`',`ssh.bugs.dhgex2')";
+      case IDC_BUGS_PKSESSID2:
+      case IDC_BUGD_PKSESSID2:
+       return "JI(`',`ssh.bugs.pksessid2')";
 
       default:
         return NULL;
@@ -1426,6 +1431,13 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     SendDlgItemMessage(hwnd, IDC_BUGD_DHGEX2, CB_SETCURSEL,
                       cfg.sshbug_dhgex2 == FORCE_ON ? 2 :
                       cfg.sshbug_dhgex2 == FORCE_OFF ? 1 : 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_PKSESSID2, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_PKSESSID2, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_PKSESSID2, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_PKSESSID2, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_PKSESSID2, CB_SETCURSEL,
+                      cfg.sshbug_pksessid2 == FORCE_ON ? 2 :
+                      cfg.sshbug_pksessid2 == FORCE_OFF ? 1 : 0, 0);
 }
 
 struct treeview_faff {
@@ -2039,6 +2051,8 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      IDC_BUGS_RSAPAD2, IDC_BUGD_RSAPAD2, 20);
            staticddl(&cp, "Chokes on &Diffie-Hellman group exchange",
                      IDC_BUGS_DHGEX2, IDC_BUGD_DHGEX2, 20);
+           staticddl(&cp, "Misuses the sessio&n ID in PK auth",
+                     IDC_BUGS_PKSESSID2, IDC_BUGD_PKSESSID2, 20);
            endbox(&cp);
        }
     }
@@ -3678,6 +3692,14 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                                         index == 1 ? FORCE_OFF : FORCE_ON);
                }
                break;
+             case IDC_BUGD_PKSESSID2:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_PKSESSID2,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_pksessid2 = (index == 0 ? AUTO :
+                                            index == 1 ? FORCE_OFF : FORCE_ON);
+               }
+               break;
            }
        return 0;
       case WM_HELP: