Browse Source

Merge branch 'thirdparty'

Source commit: b9b21a03857190846c383f21387a297f6f5eaf25
Martin Prikryl 2 years ago
parent
commit
fd87a21d8e

+ 1 - 0
source/putty/putty.h

@@ -2030,6 +2030,7 @@ NORETURN void cleanup_exit(int);
     X(INT, NONE, sshbug_chanreq) \
     X(INT, NONE, sshbug_dropstart) \
     X(INT, NONE, sshbug_filter_kexinit) \
+    X(INT, NONE, sshbug_rsa_sha2_cert_userauth) \
     /*                                                                \
      * ssh_simple means that we promise never to open any channel     \
      * other than the main one, which means it can safely use a very  \

+ 2 - 0
source/putty/settings.c

@@ -785,6 +785,7 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
     write_setting_i(sesskey, "BugOldGex2", 2-conf_get_int(conf, CONF_sshbug_oldgex2));
     write_setting_i(sesskey, "BugWinadj", 2-conf_get_int(conf, CONF_sshbug_winadj));
     write_setting_i(sesskey, "BugChanReq", 2-conf_get_int(conf, CONF_sshbug_chanreq));
+    write_setting_i(sesskey, "BugRSASHA2CertUserauth", 2-conf_get_int(conf, CONF_sshbug_rsa_sha2_cert_userauth));
     write_setting_i(sesskey, "BugDropStart", 2-conf_get_int(conf, CONF_sshbug_dropstart));
     write_setting_i(sesskey, "BugFilterKexinit", 2-conf_get_int(conf, CONF_sshbug_filter_kexinit));
     write_setting_b(sesskey, "StampUtmp", conf_get_bool(conf, CONF_stamp_utmp));
@@ -1268,6 +1269,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
     i = gppi_raw(sesskey, "BugOldGex2", 0); conf_set_int(conf, CONF_sshbug_oldgex2, 2-i);
     i = gppi_raw(sesskey, "BugWinadj", 0); conf_set_int(conf, CONF_sshbug_winadj, 2-i);
     i = gppi_raw(sesskey, "BugChanReq", 0); conf_set_int(conf, CONF_sshbug_chanreq, 2-i);
+    i = gppi_raw(sesskey, "BugRSASHA2CertUserauth", 0); conf_set_int(conf, CONF_sshbug_rsa_sha2_cert_userauth, 2-i);
     i = gppi_raw(sesskey, "BugDropStart", 1); conf_set_int(conf, CONF_sshbug_dropstart, 2-i);
     i = gppi_raw(sesskey, "BugFilterKexinit", 1); conf_set_int(conf, CONF_sshbug_filter_kexinit, 2-i);
     conf_set_bool(conf, CONF_ssh_simple, false);

+ 1 - 0
source/putty/ssh.h

@@ -1929,6 +1929,7 @@ void old_keyfile_warning(void);
     X(BUG_SENDS_LATE_REQUEST_REPLY)             \
     X(BUG_SSH2_OLDGEX)                          \
     X(BUG_REQUIRES_FILTERED_KEXINIT)            \
+    X(BUG_RSA_SHA2_CERT_USERAUTH)               \
     /* end of list */
 #define TMP_DECLARE_LOG2_ENUM(thing) log2_##thing,
 enum { SSH_IMPL_BUG_LIST(TMP_DECLARE_LOG2_ENUM) };

+ 45 - 2
source/putty/ssh/userauth2-client.c

@@ -137,6 +137,9 @@ static bool ssh2_userauth_ki_run_prompts(struct ssh2_userauth_state *s);
 static void ssh2_userauth_ki_write_responses(
     struct ssh2_userauth_state *s, BinarySink *bs);
 
+static ptrlen workaround_rsa_sha2_cert_userauth(
+    struct ssh2_userauth_state *s, ptrlen id);
+
 static const PacketProtocolLayerVtable ssh2_userauth_vtable = {
     // WINSCP
     /*.free =*/ ssh2_userauth_free,
@@ -2454,7 +2457,28 @@ static void ssh2_userauth_add_alg_and_publickey(
             ppl_logevent("Sending public key with certificate from \"%s\"",
                          filename_to_str(s->detached_cert_file));
         }
-        put_stringz(pkt, ssh_keyalg_related_alg(certalg, pkalg)->ssh_id);
+        {
+            /* Strip off any existing certificate-nature from pkalg,
+             * for the case where we're replacing a cert embedded in
+             * the key with the detached one. The second argument of
+             * ssh_keyalg_related_alg is expected to be one of the
+             * bare key algorithms, or nothing useful will happen. */
+            const ssh_keyalg *pkalg_base =
+                pkalg->base_alg ? pkalg->base_alg : pkalg;
+
+            /* Construct an algorithm string that includes both the
+             * signature subtype (e.g. rsa-sha2-512) and the
+             * certificate-ness. Exception: in earlier versions of
+             * OpenSSH we don't want to do that, and must send just
+             * ssh-rsa-cert-... even when we're delivering a non-SHA-1
+             * signature. */
+            const ssh_keyalg *output_alg =
+                ssh_keyalg_related_alg(certalg, pkalg_base);
+            ptrlen output_id = ptrlen_from_asciz(output_alg->ssh_id);
+            output_id = workaround_rsa_sha2_cert_userauth(s, output_id);
+
+            put_stringpl(pkt, output_id);
+        }
         put_stringpl(pkt, ptrlen_from_strbuf(s->detached_cert_blob));
         done = true;
         goto out;
@@ -2501,11 +2525,30 @@ static void ssh2_userauth_add_alg_and_publickey(
         } // WINSCP
     }
 
-    /* In all other cases, just put in what we were given. */
+    /* In all other cases, basically just put in what we were given -
+     * except for the same bug workaround as above. */
+    alg = workaround_rsa_sha2_cert_userauth(s, alg);
     put_stringpl(pkt, alg);
     put_stringpl(pkt, pkblob);
 }
 
+static ptrlen workaround_rsa_sha2_cert_userauth(
+    struct ssh2_userauth_state *s, ptrlen id)
+{
+    if (!(s->ppl.remote_bugs & BUG_RSA_SHA2_CERT_USERAUTH))
+        return id;
+/*
+     * No need to try to do this in a general way based on the
+     * relations between ssh_keyalgs; we know there are a limited
+     * number of affected versions of OpenSSH, so this doesn't have to
+     * be futureproof against later additions to the family.
+     */
+    if (ptrlen_eq_string(id, "[email protected]") ||
+        ptrlen_eq_string(id, "[email protected]"))
+        return PTRLEN_LITERAL("[email protected]");
+    return id;
+}
+
 /*
  * Helper function to add an SSH-2 signature blob to a packet. Expects
  * to be shown the public key blob as well as the signature blob.

+ 22 - 0
source/putty/ssh/verstring.c

@@ -613,6 +613,28 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
         bpp_logevent("We believe remote version requires us to "
                      "filter our KEXINIT");
     }
+
+    if (conf_get_int(s->conf, CONF_sshbug_rsa_sha2_cert_userauth) == FORCE_ON ||
+        (conf_get_int(s->conf, CONF_sshbug_rsa_sha2_cert_userauth) == AUTO &&
+         (wc_match("OpenSSH_7.[2-7]*", imp)))) {
+        /*
+         * These versions have the bug in which using RSA/SHA-2
+         * authentication with a certified key requires the key
+         * algorithm to be sent as ssh-rsa-cert-... instead of
+         * rsa-sha2-NNN-cert-...
+         *
+         * OpenSSH 7.8 wants rsa-sha2-NNN-cert-...:
+         * https://github.com/openssh/openssh-portable/commit/4ba0d54794814ec0de1ec87987d0c3b89379b436
+         * (also labelled "OpenBSD-Commit-ID:
+         * c6e9f6d45eed8962ad502d315d7eaef32c419dde")
+         *
+         * OpenSSH 7.2 was the first release supporting RSA/SHA-2
+         * at all, so this bug is irrelevant to anything before that.
+         */
+        s->remote_bugs |= BUG_RSA_SHA2_CERT_USERAUTH;
+        bpp_logevent("We believe remote version has SSH-2 "
+                     "RSA/SHA-2/certificate userauth bug");
+    }
 }
 
 const char *ssh_verstring_get_remote(BinaryPacketProtocol *bpp)