| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642 | 
							- /*
 
-  * Code to handle the initial SSH version string exchange.
 
-  */
 
- #include <assert.h>
 
- #include <string.h>
 
- #include <stdlib.h>
 
- #include "putty.h"
 
- #include "ssh.h"
 
- #include "bpp.h"
 
- #include "sshcr.h"
 
- #define PREFIX_MAXLEN 64
 
- struct ssh_verstring_state {
 
-     int crState;
 
-     Conf *conf;
 
-     ptrlen prefix_wanted;
 
-     char *our_protoversion;
 
-     struct ssh_version_receiver *receiver;
 
-     bool send_early;
 
-     bool found_prefix;
 
-     int major_protoversion;
 
-     int remote_bugs;
 
-     char prefix[PREFIX_MAXLEN];
 
-     char *impl_name;
 
-     strbuf *vstring;
 
-     char *protoversion;
 
-     const char *softwareversion;
 
-     char *our_vstring;
 
-     int i;
 
-     BinaryPacketProtocol bpp;
 
- };
 
- static void ssh_verstring_free(BinaryPacketProtocol *bpp);
 
- static void ssh_verstring_handle_input(BinaryPacketProtocol *bpp);
 
- static void ssh_verstring_handle_output(BinaryPacketProtocol *bpp);
 
- static PktOut *ssh_verstring_new_pktout(int type);
 
- static void ssh_verstring_queue_disconnect(BinaryPacketProtocol *bpp,
 
-                                            const char *msg, int category);
 
- static const BinaryPacketProtocolVtable ssh_verstring_vtable = {
 
-     .free = ssh_verstring_free,
 
-     .handle_input = ssh_verstring_handle_input,
 
-     .handle_output = ssh_verstring_handle_output,
 
-     .new_pktout = ssh_verstring_new_pktout,
 
-     .queue_disconnect = ssh_verstring_queue_disconnect,
 
-     .packet_size_limit = 0xFFFFFFFF, /* no special limit for this bpp */
 
- };
 
- static void ssh_detect_bugs(struct ssh_verstring_state *s);
 
- static bool ssh_version_includes_v1(const char *ver);
 
- static bool ssh_version_includes_v2(const char *ver);
 
- BinaryPacketProtocol *ssh_verstring_new(
 
-     Conf *conf, LogContext *logctx, bool bare_connection_mode,
 
-     const char *protoversion, struct ssh_version_receiver *rcv,
 
-     bool server_mode, const char *impl_name)
 
- {
 
-     struct ssh_verstring_state *s = snew(struct ssh_verstring_state);
 
-     memset(s, 0, sizeof(struct ssh_verstring_state));
 
-     if (!bare_connection_mode) {
 
-         s->prefix_wanted = PTRLEN_LITERAL("SSH-");
 
-     } else {
 
-         /*
 
-          * Ordinary SSH begins with the banner "SSH-x.y-...". Here,
 
-          * we're going to be speaking just the ssh-connection
 
-          * subprotocol, extracted and given a trivial binary packet
 
-          * protocol, so we need a new banner.
 
-          *
 
-          * The new banner is like the ordinary SSH banner, but
 
-          * replaces the prefix 'SSH-' at the start with a new name. In
 
-          * proper SSH style (though of course this part of the proper
 
-          * SSH protocol _isn't_ subject to this kind of
 
-          * DNS-domain-based extension), we define the new name in our
 
-          * extension space.
 
-          */
 
-         s->prefix_wanted = PTRLEN_LITERAL(
 
-             "[email protected]");
 
-     }
 
-     assert(s->prefix_wanted.len <= PREFIX_MAXLEN);
 
-     s->conf = conf_copy(conf);
 
-     s->bpp.logctx = logctx;
 
-     s->our_protoversion = dupstr(protoversion);
 
-     s->receiver = rcv;
 
-     s->impl_name = dupstr(impl_name);
 
-     s->vstring = strbuf_new();
 
-     /*
 
-      * We send our version string early if we can. But if it includes
 
-      * SSH-1, we can't, because we have to take the other end into
 
-      * account too (see below).
 
-      *
 
-      * In server mode, we do send early.
 
-      */
 
-     s->send_early = server_mode || !ssh_version_includes_v1(protoversion);
 
-     /*
 
-      * Override: we don't send our version string early if the server
 
-      * has a bug that will make it discard it. See for example
 
-      * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=991958
 
-      */
 
-     if (conf_get_int(s->conf, CONF_sshbug_dropstart) == FORCE_ON)
 
-         s->send_early = false;
 
-     s->bpp.vt = &ssh_verstring_vtable;
 
-     ssh_bpp_common_setup(&s->bpp);
 
-     return &s->bpp;
 
- }
 
- void ssh_verstring_free(BinaryPacketProtocol *bpp)
 
- {
 
-     struct ssh_verstring_state *s =
 
-         container_of(bpp, struct ssh_verstring_state, bpp);
 
-     conf_free(s->conf);
 
-     sfree(s->impl_name);
 
-     strbuf_free(s->vstring);
 
-     sfree(s->protoversion);
 
-     sfree(s->our_vstring);
 
-     sfree(s->our_protoversion);
 
-     sfree(s);
 
- }
 
- static int ssh_versioncmp(const char *a, const char *b)
 
- {
 
-     char *ae, *be;
 
-     unsigned long av, bv;
 
-     av = strtoul(a, &ae, 10);
 
-     bv = strtoul(b, &be, 10);
 
-     if (av != bv)
 
-         return (av < bv ? -1 : +1);
 
-     if (*ae == '.')
 
-         ae++;
 
-     if (*be == '.')
 
-         be++;
 
-     av = strtoul(ae, &ae, 10);
 
-     bv = strtoul(be, &be, 10);
 
-     if (av != bv)
 
-         return (av < bv ? -1 : +1);
 
-     return 0;
 
- }
 
- static bool ssh_version_includes_v1(const char *ver)
 
- {
 
-     return ssh_versioncmp(ver, "2.0") < 0;
 
- }
 
- static bool ssh_version_includes_v2(const char *ver)
 
- {
 
-     return ssh_versioncmp(ver, "1.99") >= 0;
 
- }
 
- static void ssh_verstring_send(struct ssh_verstring_state *s)
 
- {
 
-     BinaryPacketProtocol *bpp = &s->bpp; /* for bpp_logevent */
 
-     char *p;
 
-     int sv_pos;
 
-     /*
 
-      * Construct our outgoing version string.
 
-      */
 
-     s->our_vstring = dupprintf(
 
-         "%.*s%s-%s%s",
 
-         (int)s->prefix_wanted.len, (const char *)s->prefix_wanted.ptr,
 
-         s->our_protoversion, s->impl_name, sshver);
 
-     sv_pos = s->prefix_wanted.len + strlen(s->our_protoversion) + 1;
 
-     /* Convert minus signs and spaces in the software version string
 
-      * into underscores. */
 
-     for (p = s->our_vstring + sv_pos; *p; p++) {
 
-         if (*p == '-' || *p == ' ')
 
-             *p = '_';
 
-     }
 
- #ifdef FUZZING
 
-     /*
 
-      * Replace the first character of the string with an "I" if we're
 
-      * compiling this code for fuzzing - i.e. the protocol prefix
 
-      * becomes "ISH-" instead of "SSH-".
 
-      *
 
-      * This is irrelevant to any real client software (the only thing
 
-      * reading the output of PuTTY built for fuzzing is the fuzzer,
 
-      * which can adapt to whatever it sees anyway). But it's a safety
 
-      * precaution making it difficult to accidentally run such a
 
-      * version of PuTTY (which would be hugely insecure) against a
 
-      * live peer implementation.
 
-      *
 
-      * (So the replacement prefix "ISH" notionally stands for
 
-      * 'Insecure Shell', of course.)
 
-      */
 
-     s->our_vstring[0] = 'I';
 
- #endif
 
-     /*
 
-      * Now send that version string, plus trailing \r\n or just \n
 
-      * (the latter in SSH-1 mode).
 
-      */
 
-     bufchain_add(s->bpp.out_raw, s->our_vstring, strlen(s->our_vstring));
 
-     if (ssh_version_includes_v2(s->our_protoversion))
 
-         bufchain_add(s->bpp.out_raw, "\015", 1);
 
-     bufchain_add(s->bpp.out_raw, "\012", 1);
 
-     bpp_logevent("We claim version: %s", s->our_vstring);
 
- }
 
- #define BPP_WAITFOR(minlen) do                          \
 
-     {                                                                   \
 
-         bool success;                                                   \
 
-         crMaybeWaitUntilV(                                              \
 
-             (success = (bufchain_size(s->bpp.in_raw) >= (minlen))) ||   \
 
-             s->bpp.input_eof);                                          \
 
-         if (!success)                                                   \
 
-             goto eof;                                                   \
 
-     } while (0)
 
- void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
 
- {
 
-     struct ssh_verstring_state *s =
 
-         container_of(bpp, struct ssh_verstring_state, bpp);
 
-     crBegin(s->crState);
 
-     /*
 
-      * If we're sending our version string up front before seeing the
 
-      * other side's, then do it now.
 
-      */
 
-     if (s->send_early)
 
-         ssh_verstring_send(s);
 
-     /*
 
-      * Search for a line beginning with the protocol name prefix in
 
-      * the input.
 
-      */
 
-     s->i = 0;
 
-     while (1) {
 
-         /*
 
-          * Every time round this loop, we're at the start of a new
 
-          * line, so look for the prefix.
 
-          */
 
-         BPP_WAITFOR(s->prefix_wanted.len);
 
-         bufchain_fetch(s->bpp.in_raw, s->prefix, s->prefix_wanted.len);
 
-         if (!memcmp(s->prefix, s->prefix_wanted.ptr, s->prefix_wanted.len)) {
 
-             bufchain_consume(s->bpp.in_raw, s->prefix_wanted.len);
 
-             ssh_check_frozen(s->bpp.ssh);
 
-             break;
 
-         }
 
-         /*
 
-          * If we didn't find it, consume data until we see a newline.
 
-          */
 
-         while (1) {
 
-             ptrlen data;
 
-             char *nl;
 
-             /* Wait to receive at least 1 byte, but then consume more
 
-              * than that if it's there. */
 
-             BPP_WAITFOR(1);
 
-             data = bufchain_prefix(s->bpp.in_raw);
 
-             if ((nl = memchr(data.ptr, '\012', data.len)) != NULL) {
 
-                 bufchain_consume(s->bpp.in_raw, nl - (char *)data.ptr + 1);
 
-                 ssh_check_frozen(s->bpp.ssh);
 
-                 break;
 
-             } else {
 
-                 bufchain_consume(s->bpp.in_raw, data.len);
 
-                 ssh_check_frozen(s->bpp.ssh);
 
-             }
 
-         }
 
-     }
 
-     s->found_prefix = true;
 
-     /*
 
-      * Copy the greeting line so far into vstring.
 
-      */
 
-     put_data(s->vstring, s->prefix_wanted.ptr, s->prefix_wanted.len);
 
-     /*
 
-      * Now read the rest of the greeting line.
 
-      */
 
-     s->i = 0;
 
-     do {
 
-         ptrlen data;
 
-         char *nl;
 
-         BPP_WAITFOR(1);
 
-         data = bufchain_prefix(s->bpp.in_raw);
 
-         if ((nl = memchr(data.ptr, '\012', data.len)) != NULL) {
 
-             data.len = nl - (char *)data.ptr + 1;
 
-         }
 
-         put_datapl(s->vstring, data);
 
-         bufchain_consume(s->bpp.in_raw, data.len);
 
-         ssh_check_frozen(s->bpp.ssh);
 
-     } while (s->vstring->s[s->vstring->len-1] != '\012');
 
-     /*
 
-      * Trim \r and \n from the version string, and replace them with
 
-      * a NUL terminator.
 
-      */
 
-     while (s->vstring->len > 0 &&
 
-            (s->vstring->s[s->vstring->len-1] == '\015' ||
 
-             s->vstring->s[s->vstring->len-1] == '\012'))
 
-         strbuf_shrink_by(s->vstring, 1);
 
-     bpp_logevent("Remote version: %s", s->vstring->s);
 
-     /*
 
-      * Pick out the protocol version and software version. The former
 
-      * goes in a separately allocated string, so that s->vstring
 
-      * remains intact for later use in key exchange; the latter is the
 
-      * tail of s->vstring, so it doesn't need to be allocated.
 
-      */
 
-     {
 
-         const char *pv_start = s->vstring->s + s->prefix_wanted.len;
 
-         int pv_len = strcspn(pv_start, "-");
 
-         s->protoversion = dupprintf("%.*s", pv_len, pv_start);
 
-         s->softwareversion = pv_start + pv_len;
 
-         if (*s->softwareversion) {
 
-             assert(*s->softwareversion == '-');
 
-             s->softwareversion++;
 
-         }
 
-     }
 
-     ssh_detect_bugs(s);
 
-     /*
 
-      * Figure out what actual SSH protocol version we're speaking.
 
-      */
 
-     if (ssh_version_includes_v2(s->our_protoversion) &&
 
-         ssh_version_includes_v2(s->protoversion)) {
 
-         /*
 
-          * We're doing SSH-2.
 
-          */
 
-         s->major_protoversion = 2;
 
-     } else if (ssh_version_includes_v1(s->our_protoversion) &&
 
-                ssh_version_includes_v1(s->protoversion)) {
 
-         /*
 
-          * We're doing SSH-1.
 
-          */
 
-         s->major_protoversion = 1;
 
-         /*
 
-          * There are multiple minor versions of SSH-1, and the
 
-          * protocol does not specify that the minimum of client
 
-          * and server versions is used. So we must adjust our
 
-          * outgoing protocol version to be no higher than that of
 
-          * the other side.
 
-          */
 
-         if (!s->send_early &&
 
-             ssh_versioncmp(s->our_protoversion, s->protoversion) > 0) {
 
-             sfree(s->our_protoversion);
 
-             s->our_protoversion = dupstr(s->protoversion);
 
-         }
 
-     } else {
 
-         /*
 
-          * Unable to agree on a major protocol version at all.
 
-          */
 
-         if (!ssh_version_includes_v2(s->our_protoversion)) {
 
-             ssh_sw_abort(s->bpp.ssh,
 
-                          "SSH protocol version 1 required by our "
 
-                          "configuration but not provided by remote");
 
-         } else {
 
-             ssh_sw_abort(s->bpp.ssh,
 
-                          "SSH protocol version 2 required by our "
 
-                          "configuration but remote only provides "
 
-                          "(old, insecure) SSH-1");
 
-         }
 
-         crStopV;
 
-     }
 
-     bpp_logevent("Using SSH protocol version %d", s->major_protoversion);
 
-     if (!s->send_early) {
 
-         /*
 
-          * If we didn't send our version string early, construct and
 
-          * send it now, because now we know what it is.
 
-          */
 
-         ssh_verstring_send(s);
 
-     }
 
-     /*
 
-      * And we're done. Notify our receiver that we now know our
 
-      * protocol version. This will cause it to disconnect us from the
 
-      * input stream and ultimately free us, because our job is now
 
-      * done.
 
-      */
 
-     s->receiver->got_ssh_version(s->receiver, s->major_protoversion);
 
-     return;
 
-   eof:
 
-     ssh_remote_error(s->bpp.ssh,
 
-                      "Remote side unexpectedly closed network connection");
 
-     return;  /* avoid touching s now it's been freed */
 
-     crFinishV;
 
- }
 
- static PktOut *ssh_verstring_new_pktout(int type)
 
- {
 
-     unreachable("Should never try to send packets during SSH version "
 
-                 "string exchange");
 
- }
 
- static void ssh_verstring_handle_output(BinaryPacketProtocol *bpp)
 
- {
 
-     if (pq_peek(&bpp->out_pq)) {
 
-         unreachable("Should never try to send packets during SSH version "
 
-                     "string exchange");
 
-     }
 
- }
 
- /*
 
-  * Examine the remote side's version string, and compare it against a
 
-  * list of known buggy implementations.
 
-  */
 
- static void ssh_detect_bugs(struct ssh_verstring_state *s)
 
- {
 
-     BinaryPacketProtocol *bpp = &s->bpp; /* for bpp_logevent */
 
-     const char *imp = s->softwareversion;
 
-     s->remote_bugs = 0;
 
-     /*
 
-      * General notes on server version strings:
 
-      *  - Not all servers reporting "Cisco-1.25" have all the bugs listed
 
-      *    here -- in particular, we've heard of one that's perfectly happy
 
-      *    with SSH1_MSG_IGNOREs -- but this string never seems to change,
 
-      *    so we can't distinguish them.
 
-      */
 
-     if (conf_get_int(s->conf, CONF_sshbug_ignore1) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_ignore1) == AUTO &&
 
-          (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
 
-           !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
 
-           !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25") ||
 
-           !strcmp(imp, "OSU_1.4alpha3") || !strcmp(imp, "OSU_1.5alpha4")))) {
 
-         /*
 
-          * These versions don't support SSH1_MSG_IGNORE, so we have
 
-          * to use a different defence against password length
 
-          * sniffing.
 
-          */
 
-         s->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;
 
-         bpp_logevent("We believe remote version has SSH-1 ignore bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_plainpw1) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_plainpw1) == AUTO &&
 
-          (!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) {
 
-         /*
 
-          * These versions need a plain password sent; they can't
 
-          * handle having a null and a random length of data after
 
-          * the password.
 
-          */
 
-         s->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
 
-         bpp_logevent("We believe remote version needs a "
 
-                      "plain SSH-1 password");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_rsa1) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_rsa1) == AUTO &&
 
-          (!strcmp(imp, "Cisco-1.25")))) {
 
-         /*
 
-          * These versions apparently have no clue whatever about
 
-          * RSA authentication and will panic and die if they see
 
-          * an AUTH_RSA message.
 
-          */
 
-         s->remote_bugs |= BUG_CHOKES_ON_RSA;
 
-         bpp_logevent("We believe remote version can't handle SSH-1 "
 
-                      "RSA authentication");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_hmac2) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_hmac2) == AUTO &&
 
-          !wc_match("* VShell", imp) &&
 
-          (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
 
-           wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
 
-           wc_match("2.1 *", imp)))) {
 
-         /*
 
-          * These versions have the HMAC bug.
 
-          */
 
-         s->remote_bugs |= BUG_SSH2_HMAC;
 
-         bpp_logevent("We believe remote version has SSH-2 HMAC bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_derivekey2) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_derivekey2) == AUTO &&
 
-          !wc_match("* VShell", imp) &&
 
-          (wc_match("2.0.0*", imp) || wc_match("2.0.10*", imp) ))) {
 
-         /*
 
-          * These versions have the key-derivation bug (failing to
 
-          * include the literal shared secret in the hashes that
 
-          * generate the keys).
 
-          */
 
-         s->remote_bugs |= BUG_SSH2_DERIVEKEY;
 
-         bpp_logevent("We believe remote version has SSH-2 "
 
-                      "key-derivation bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_rsapad2) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_rsapad2) == AUTO &&
 
-          (wc_match("OpenSSH_2.[5-9]*", imp) ||
 
-           wc_match("OpenSSH_3.[0-2]*", imp) ||
 
-           wc_match("mod_sftp/0.[0-8]*", imp) ||
 
-           wc_match("mod_sftp/0.9.[0-8]", imp)))) {
 
-         /*
 
-          * These versions have the SSH-2 RSA padding bug.
 
-          */
 
-         s->remote_bugs |= BUG_SSH2_RSA_PADDING;
 
-         bpp_logevent("We believe remote version has SSH-2 RSA padding bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_pksessid2) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_pksessid2) == AUTO &&
 
-          wc_match("OpenSSH_2.[0-2]*", imp))) {
 
-         /*
 
-          * These versions have the SSH-2 session-ID bug in
 
-          * public-key authentication.
 
-          */
 
-         s->remote_bugs |= BUG_SSH2_PK_SESSIONID;
 
-         bpp_logevent("We believe remote version has SSH-2 "
 
-                      "public-key-session-ID bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_rekey2) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_rekey2) == AUTO &&
 
-          (wc_match("DigiSSH_2.0", imp) ||
 
-           wc_match("OpenSSH_2.[0-4]*", imp) ||
 
-           wc_match("OpenSSH_2.5.[0-3]*", imp) ||
 
-           wc_match("Sun_SSH_1.0", imp) ||
 
-           wc_match("Sun_SSH_1.0.1", imp) ||
 
-           /* All versions <= 1.2.6 (they changed their format in 1.2.7) */
 
-           wc_match("WeOnlyDo-*", imp)))) {
 
-         /*
 
-          * These versions have the SSH-2 rekey bug.
 
-          */
 
-         s->remote_bugs |= BUG_SSH2_REKEY;
 
-         bpp_logevent("We believe remote version has SSH-2 rekey bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_maxpkt2) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_maxpkt2) == AUTO &&
 
-          (wc_match("1.36_sshlib GlobalSCAPE", imp) ||
 
-           wc_match("1.36 sshlib: GlobalScape", imp)))) {
 
-         /*
 
-          * This version ignores our makpkt and needs to be throttled.
 
-          */
 
-         s->remote_bugs |= BUG_SSH2_MAXPKT;
 
-         bpp_logevent("We believe remote version ignores SSH-2 "
 
-                      "maximum packet size");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_ignore2) == FORCE_ON) {
 
-         /*
 
-          * Servers that don't support SSH2_MSG_IGNORE. Currently,
 
-          * none detected automatically.
 
-          */
 
-         s->remote_bugs |= BUG_CHOKES_ON_SSH2_IGNORE;
 
-         bpp_logevent("We believe remote version has SSH-2 ignore bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_oldgex2) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_oldgex2) == AUTO &&
 
-          (wc_match("OpenSSH_2.[235]*", imp)))) {
 
-         /*
 
-          * These versions only support the original (pre-RFC4419)
 
-          * SSH-2 GEX request, and disconnect with a protocol error if
 
-          * we use the newer version.
 
-          */
 
-         s->remote_bugs |= BUG_SSH2_OLDGEX;
 
-         bpp_logevent("We believe remote version has outdated SSH-2 GEX");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_winadj) == FORCE_ON) {
 
-         /*
 
-          * Servers that don't support our winadj request for one
 
-          * reason or another. Currently, none detected automatically.
 
-          */
 
-         s->remote_bugs |= BUG_CHOKES_ON_WINADJ;
 
-         bpp_logevent("We believe remote version has winadj bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_chanreq) == FORCE_ON ||
 
-         (conf_get_int(s->conf, CONF_sshbug_chanreq) == AUTO &&
 
-          (wc_match("OpenSSH_[2-5].*", imp) ||
 
-           wc_match("OpenSSH_6.[0-6]*", imp) ||
 
-           wc_match("dropbear_0.[2-4][0-9]*", imp) ||
 
-           wc_match("dropbear_0.5[01]*", imp)))) {
 
-         /*
 
-          * These versions have the SSH-2 channel request bug.
 
-          * OpenSSH 6.7 and above do not:
 
-          * https://bugzilla.mindrot.org/show_bug.cgi?id=1818
 
-          * dropbear_0.52 and above do not:
 
-          * https://secure.ucc.asn.au/hg/dropbear/rev/cd02449b709c
 
-          */
 
-         s->remote_bugs |= BUG_SENDS_LATE_REQUEST_REPLY;
 
-         bpp_logevent("We believe remote version has SSH-2 "
 
-                      "channel request bug");
 
-     }
 
-     if (conf_get_int(s->conf, CONF_sshbug_filter_kexinit) == FORCE_ON) {
 
-         s->remote_bugs |= BUG_REQUIRES_FILTERED_KEXINIT;
 
-         bpp_logevent("We believe remote version requires us to "
 
-                      "filter our KEXINIT");
 
-     }
 
- }
 
- const char *ssh_verstring_get_remote(BinaryPacketProtocol *bpp)
 
- {
 
-     struct ssh_verstring_state *s =
 
-         container_of(bpp, struct ssh_verstring_state, bpp);
 
-     return s->vstring->s;
 
- }
 
- const char *ssh_verstring_get_local(BinaryPacketProtocol *bpp)
 
- {
 
-     struct ssh_verstring_state *s =
 
-         container_of(bpp, struct ssh_verstring_state, bpp);
 
-     return s->our_vstring;
 
- }
 
- int ssh_verstring_get_bugs(BinaryPacketProtocol *bpp)
 
- {
 
-     struct ssh_verstring_state *s =
 
-         container_of(bpp, struct ssh_verstring_state, bpp);
 
-     return s->remote_bugs;
 
- }
 
- static void ssh_verstring_queue_disconnect(BinaryPacketProtocol *bpp,
 
-                                            const char *msg, int category)
 
- {
 
-     /* No way to send disconnect messages at this stage of the protocol! */
 
- }
 
 
  |