sshverstring.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /*
  2. * Code to handle the initial SSH version string exchange.
  3. */
  4. #include <assert.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include "putty.h"
  8. #include "ssh.h"
  9. #include "sshbpp.h"
  10. #include "sshcr.h"
  11. #define PREFIX_MAXLEN 64
  12. struct ssh_verstring_state {
  13. int crState;
  14. Conf *conf;
  15. ptrlen prefix_wanted;
  16. char *our_protoversion;
  17. struct ssh_version_receiver *receiver;
  18. bool send_early;
  19. bool found_prefix;
  20. int major_protoversion;
  21. int remote_bugs;
  22. char prefix[PREFIX_MAXLEN];
  23. char *impl_name;
  24. char *vstring;
  25. size_t vslen, vstrsize;
  26. char *protoversion;
  27. const char *softwareversion;
  28. char *our_vstring;
  29. int i;
  30. BinaryPacketProtocol bpp;
  31. };
  32. static void ssh_verstring_free(BinaryPacketProtocol *bpp);
  33. static void ssh_verstring_handle_input(BinaryPacketProtocol *bpp);
  34. static void ssh_verstring_handle_output(BinaryPacketProtocol *bpp);
  35. static PktOut *ssh_verstring_new_pktout(int type);
  36. static void ssh_verstring_queue_disconnect(BinaryPacketProtocol *bpp,
  37. const char *msg, int category);
  38. static const struct BinaryPacketProtocolVtable ssh_verstring_vtable = {
  39. ssh_verstring_free,
  40. ssh_verstring_handle_input,
  41. ssh_verstring_handle_output,
  42. ssh_verstring_new_pktout,
  43. ssh_verstring_queue_disconnect,
  44. };
  45. static void ssh_detect_bugs(struct ssh_verstring_state *s);
  46. static bool ssh_version_includes_v1(const char *ver);
  47. static bool ssh_version_includes_v2(const char *ver);
  48. BinaryPacketProtocol *ssh_verstring_new(
  49. Conf *conf, LogContext *logctx, bool bare_connection_mode,
  50. const char *protoversion, struct ssh_version_receiver *rcv,
  51. bool server_mode, const char *impl_name)
  52. {
  53. struct ssh_verstring_state *s = snew(struct ssh_verstring_state);
  54. memset(s, 0, sizeof(struct ssh_verstring_state));
  55. if (!bare_connection_mode) {
  56. s->prefix_wanted = PTRLEN_LITERAL("SSH-");
  57. } else {
  58. /*
  59. * Ordinary SSH begins with the banner "SSH-x.y-...". Here,
  60. * we're going to be speaking just the ssh-connection
  61. * subprotocol, extracted and given a trivial binary packet
  62. * protocol, so we need a new banner.
  63. *
  64. * The new banner is like the ordinary SSH banner, but
  65. * replaces the prefix 'SSH-' at the start with a new name. In
  66. * proper SSH style (though of course this part of the proper
  67. * SSH protocol _isn't_ subject to this kind of
  68. * DNS-domain-based extension), we define the new name in our
  69. * extension space.
  70. */
  71. s->prefix_wanted = PTRLEN_LITERAL(
  72. "[email protected]");
  73. }
  74. assert(s->prefix_wanted.len <= PREFIX_MAXLEN);
  75. s->conf = conf_copy(conf);
  76. s->bpp.logctx = logctx;
  77. s->our_protoversion = dupstr(protoversion);
  78. s->receiver = rcv;
  79. s->impl_name = dupstr(impl_name);
  80. /*
  81. * We send our version string early if we can. But if it includes
  82. * SSH-1, we can't, because we have to take the other end into
  83. * account too (see below).
  84. *
  85. * In server mode, we do send early.
  86. */
  87. s->send_early = server_mode || !ssh_version_includes_v1(protoversion);
  88. s->bpp.vt = &ssh_verstring_vtable;
  89. ssh_bpp_common_setup(&s->bpp);
  90. return &s->bpp;
  91. }
  92. void ssh_verstring_free(BinaryPacketProtocol *bpp)
  93. {
  94. struct ssh_verstring_state *s =
  95. container_of(bpp, struct ssh_verstring_state, bpp);
  96. conf_free(s->conf);
  97. sfree(s->impl_name);
  98. sfree(s->vstring);
  99. sfree(s->protoversion);
  100. sfree(s->our_vstring);
  101. sfree(s->our_protoversion);
  102. sfree(s);
  103. }
  104. static int ssh_versioncmp(const char *a, const char *b)
  105. {
  106. char *ae, *be;
  107. unsigned long av, bv;
  108. av = strtoul(a, &ae, 10);
  109. bv = strtoul(b, &be, 10);
  110. if (av != bv)
  111. return (av < bv ? -1 : +1);
  112. if (*ae == '.')
  113. ae++;
  114. if (*be == '.')
  115. be++;
  116. av = strtoul(ae, &ae, 10);
  117. bv = strtoul(be, &be, 10);
  118. if (av != bv)
  119. return (av < bv ? -1 : +1);
  120. return 0;
  121. }
  122. static bool ssh_version_includes_v1(const char *ver)
  123. {
  124. return ssh_versioncmp(ver, "2.0") < 0;
  125. }
  126. static bool ssh_version_includes_v2(const char *ver)
  127. {
  128. return ssh_versioncmp(ver, "1.99") >= 0;
  129. }
  130. static void ssh_verstring_send(struct ssh_verstring_state *s)
  131. {
  132. BinaryPacketProtocol *bpp = &s->bpp; /* for bpp_logevent */
  133. char *p;
  134. int sv_pos;
  135. /*
  136. * Construct our outgoing version string.
  137. */
  138. s->our_vstring = dupprintf(
  139. "%.*s%s-%s%s",
  140. (int)s->prefix_wanted.len, (const char *)s->prefix_wanted.ptr,
  141. s->our_protoversion, s->impl_name, sshver);
  142. sv_pos = s->prefix_wanted.len + strlen(s->our_protoversion) + 1;
  143. /* Convert minus signs and spaces in the software version string
  144. * into underscores. */
  145. for (p = s->our_vstring + sv_pos; *p; p++) {
  146. if (*p == '-' || *p == ' ')
  147. *p = '_';
  148. }
  149. #ifdef FUZZING
  150. /*
  151. * Replace the first character of the string with an "I" if we're
  152. * compiling this code for fuzzing - i.e. the protocol prefix
  153. * becomes "ISH-" instead of "SSH-".
  154. *
  155. * This is irrelevant to any real client software (the only thing
  156. * reading the output of PuTTY built for fuzzing is the fuzzer,
  157. * which can adapt to whatever it sees anyway). But it's a safety
  158. * precaution making it difficult to accidentally run such a
  159. * version of PuTTY (which would be hugely insecure) against a
  160. * live peer implementation.
  161. *
  162. * (So the replacement prefix "ISH" notionally stands for
  163. * 'Insecure Shell', of course.)
  164. */
  165. s->our_vstring[0] = 'I';
  166. #endif
  167. /*
  168. * Now send that version string, plus trailing \r\n or just \n
  169. * (the latter in SSH-1 mode).
  170. */
  171. bufchain_add(s->bpp.out_raw, s->our_vstring, strlen(s->our_vstring));
  172. if (ssh_version_includes_v2(s->our_protoversion))
  173. bufchain_add(s->bpp.out_raw, "\015", 1);
  174. bufchain_add(s->bpp.out_raw, "\012", 1);
  175. bpp_logevent("We claim version: %s", s->our_vstring);
  176. }
  177. #define BPP_WAITFOR(minlen) do \
  178. { \
  179. bool success; \
  180. crMaybeWaitUntilV( \
  181. (success = (bufchain_size(s->bpp.in_raw) >= (minlen))) || \
  182. s->bpp.input_eof); \
  183. if (!success) \
  184. goto eof; \
  185. } while (0)
  186. void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
  187. {
  188. struct ssh_verstring_state *s =
  189. container_of(bpp, struct ssh_verstring_state, bpp);
  190. crBegin(s->crState);
  191. /*
  192. * If we're sending our version string up front before seeing the
  193. * other side's, then do it now.
  194. */
  195. if (s->send_early)
  196. ssh_verstring_send(s);
  197. /*
  198. * Search for a line beginning with the protocol name prefix in
  199. * the input.
  200. */
  201. s->i = 0;
  202. while (1) {
  203. /*
  204. * Every time round this loop, we're at the start of a new
  205. * line, so look for the prefix.
  206. */
  207. BPP_WAITFOR(s->prefix_wanted.len);
  208. bufchain_fetch(s->bpp.in_raw, s->prefix, s->prefix_wanted.len);
  209. if (!memcmp(s->prefix, s->prefix_wanted.ptr, s->prefix_wanted.len)) {
  210. bufchain_consume(s->bpp.in_raw, s->prefix_wanted.len);
  211. break;
  212. }
  213. /*
  214. * If we didn't find it, consume data until we see a newline.
  215. */
  216. while (1) {
  217. ptrlen data;
  218. char *nl;
  219. /* Wait to receive at least 1 byte, but then consume more
  220. * than that if it's there. */
  221. BPP_WAITFOR(1);
  222. data = bufchain_prefix(s->bpp.in_raw);
  223. if ((nl = memchr(data.ptr, '\012', data.len)) != NULL) {
  224. bufchain_consume(s->bpp.in_raw, nl - (char *)data.ptr + 1);
  225. break;
  226. } else {
  227. bufchain_consume(s->bpp.in_raw, data.len);
  228. }
  229. }
  230. }
  231. s->found_prefix = true;
  232. /*
  233. * Start a buffer to store the full greeting line.
  234. */
  235. s->vstrsize = s->prefix_wanted.len + 16;
  236. s->vstring = snewn(s->vstrsize, char);
  237. memcpy(s->vstring, s->prefix_wanted.ptr, s->prefix_wanted.len);
  238. s->vslen = s->prefix_wanted.len;
  239. /*
  240. * Now read the rest of the greeting line.
  241. */
  242. s->i = 0;
  243. do {
  244. ptrlen data;
  245. char *nl;
  246. BPP_WAITFOR(1);
  247. data = bufchain_prefix(s->bpp.in_raw);
  248. if ((nl = memchr(data.ptr, '\012', data.len)) != NULL) {
  249. data.len = nl - (char *)data.ptr + 1;
  250. }
  251. if (s->vslen >= s->vstrsize - 1 ||
  252. data.len >= s->vstrsize - 1 - s->vslen) {
  253. s->vstrsize = (s->vslen + data.len) * 5 / 4 + 32;
  254. s->vstring = sresize(s->vstring, s->vstrsize, char);
  255. }
  256. memcpy(s->vstring + s->vslen, data.ptr, data.len);
  257. s->vslen += data.len;
  258. bufchain_consume(s->bpp.in_raw, data.len);
  259. } while (s->vstring[s->vslen-1] != '\012');
  260. /*
  261. * Trim \r and \n from the version string, and replace them with
  262. * a NUL terminator.
  263. */
  264. while (s->vslen > 0 &&
  265. (s->vstring[s->vslen-1] == '\r' ||
  266. s->vstring[s->vslen-1] == '\n'))
  267. s->vslen--;
  268. s->vstring[s->vslen] = '\0';
  269. bpp_logevent("Remote version: %s", s->vstring);
  270. /*
  271. * Pick out the protocol version and software version. The former
  272. * goes in a separately allocated string, so that s->vstring
  273. * remains intact for later use in key exchange; the latter is the
  274. * tail of s->vstring, so it doesn't need to be allocated.
  275. */
  276. {
  277. const char *pv_start = s->vstring + s->prefix_wanted.len;
  278. int pv_len = strcspn(pv_start, "-");
  279. s->protoversion = dupprintf("%.*s", pv_len, pv_start);
  280. s->softwareversion = pv_start + pv_len;
  281. if (*s->softwareversion) {
  282. assert(*s->softwareversion == '-');
  283. s->softwareversion++;
  284. }
  285. }
  286. ssh_detect_bugs(s);
  287. /*
  288. * Figure out what actual SSH protocol version we're speaking.
  289. */
  290. if (ssh_version_includes_v2(s->our_protoversion) &&
  291. ssh_version_includes_v2(s->protoversion)) {
  292. /*
  293. * We're doing SSH-2.
  294. */
  295. s->major_protoversion = 2;
  296. } else if (ssh_version_includes_v1(s->our_protoversion) &&
  297. ssh_version_includes_v1(s->protoversion)) {
  298. /*
  299. * We're doing SSH-1.
  300. */
  301. s->major_protoversion = 1;
  302. /*
  303. * There are multiple minor versions of SSH-1, and the
  304. * protocol does not specify that the minimum of client
  305. * and server versions is used. So we must adjust our
  306. * outgoing protocol version to be no higher than that of
  307. * the other side.
  308. */
  309. if (!s->send_early &&
  310. ssh_versioncmp(s->our_protoversion, s->protoversion) > 0) {
  311. sfree(s->our_protoversion);
  312. s->our_protoversion = dupstr(s->protoversion);
  313. }
  314. } else {
  315. /*
  316. * Unable to agree on a major protocol version at all.
  317. */
  318. if (!ssh_version_includes_v2(s->our_protoversion)) {
  319. ssh_sw_abort(s->bpp.ssh,
  320. "SSH protocol version 1 required by our "
  321. "configuration but not provided by remote");
  322. } else {
  323. ssh_sw_abort(s->bpp.ssh,
  324. "SSH protocol version 2 required by our "
  325. "configuration but remote only provides "
  326. "(old, insecure) SSH-1");
  327. }
  328. crStopV;
  329. }
  330. bpp_logevent("Using SSH protocol version %d", s->major_protoversion);
  331. if (!s->send_early) {
  332. /*
  333. * If we didn't send our version string early, construct and
  334. * send it now, because now we know what it is.
  335. */
  336. ssh_verstring_send(s);
  337. }
  338. /*
  339. * And we're done. Notify our receiver that we now know our
  340. * protocol version. This will cause it to disconnect us from the
  341. * input stream and ultimately free us, because our job is now
  342. * done.
  343. */
  344. s->receiver->got_ssh_version(s->receiver, s->major_protoversion);
  345. return;
  346. eof:
  347. ssh_remote_error(s->bpp.ssh,
  348. "Remote side unexpectedly closed network connection");
  349. return; /* avoid touching s now it's been freed */
  350. crFinishV;
  351. }
  352. static PktOut *ssh_verstring_new_pktout(int type)
  353. {
  354. unreachable("Should never try to send packets during SSH version "
  355. "string exchange");
  356. }
  357. static void ssh_verstring_handle_output(BinaryPacketProtocol *bpp)
  358. {
  359. if (pq_peek(&bpp->out_pq)) {
  360. unreachable("Should never try to send packets during SSH version "
  361. "string exchange");
  362. }
  363. }
  364. /*
  365. * Examine the remote side's version string, and compare it against a
  366. * list of known buggy implementations.
  367. */
  368. static void ssh_detect_bugs(struct ssh_verstring_state *s)
  369. {
  370. BinaryPacketProtocol *bpp = &s->bpp; /* for bpp_logevent */
  371. const char *imp = s->softwareversion;
  372. s->remote_bugs = 0;
  373. /*
  374. * General notes on server version strings:
  375. * - Not all servers reporting "Cisco-1.25" have all the bugs listed
  376. * here -- in particular, we've heard of one that's perfectly happy
  377. * with SSH1_MSG_IGNOREs -- but this string never seems to change,
  378. * so we can't distinguish them.
  379. */
  380. if (conf_get_int(s->conf, CONF_sshbug_ignore1) == FORCE_ON ||
  381. (conf_get_int(s->conf, CONF_sshbug_ignore1) == AUTO &&
  382. (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
  383. !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
  384. !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25") ||
  385. !strcmp(imp, "OSU_1.4alpha3") || !strcmp(imp, "OSU_1.5alpha4")))) {
  386. /*
  387. * These versions don't support SSH1_MSG_IGNORE, so we have
  388. * to use a different defence against password length
  389. * sniffing.
  390. */
  391. s->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;
  392. bpp_logevent("We believe remote version has SSH-1 ignore bug");
  393. }
  394. if (conf_get_int(s->conf, CONF_sshbug_plainpw1) == FORCE_ON ||
  395. (conf_get_int(s->conf, CONF_sshbug_plainpw1) == AUTO &&
  396. (!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) {
  397. /*
  398. * These versions need a plain password sent; they can't
  399. * handle having a null and a random length of data after
  400. * the password.
  401. */
  402. s->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
  403. bpp_logevent("We believe remote version needs a "
  404. "plain SSH-1 password");
  405. }
  406. if (conf_get_int(s->conf, CONF_sshbug_rsa1) == FORCE_ON ||
  407. (conf_get_int(s->conf, CONF_sshbug_rsa1) == AUTO &&
  408. (!strcmp(imp, "Cisco-1.25")))) {
  409. /*
  410. * These versions apparently have no clue whatever about
  411. * RSA authentication and will panic and die if they see
  412. * an AUTH_RSA message.
  413. */
  414. s->remote_bugs |= BUG_CHOKES_ON_RSA;
  415. bpp_logevent("We believe remote version can't handle SSH-1 "
  416. "RSA authentication");
  417. }
  418. if (conf_get_int(s->conf, CONF_sshbug_hmac2) == FORCE_ON ||
  419. (conf_get_int(s->conf, CONF_sshbug_hmac2) == AUTO &&
  420. !wc_match("* VShell", imp) &&
  421. (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
  422. wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
  423. wc_match("2.1 *", imp)))) {
  424. /*
  425. * These versions have the HMAC bug.
  426. */
  427. s->remote_bugs |= BUG_SSH2_HMAC;
  428. bpp_logevent("We believe remote version has SSH-2 HMAC bug");
  429. }
  430. if (conf_get_int(s->conf, CONF_sshbug_derivekey2) == FORCE_ON ||
  431. (conf_get_int(s->conf, CONF_sshbug_derivekey2) == AUTO &&
  432. !wc_match("* VShell", imp) &&
  433. (wc_match("2.0.0*", imp) || wc_match("2.0.10*", imp) ))) {
  434. /*
  435. * These versions have the key-derivation bug (failing to
  436. * include the literal shared secret in the hashes that
  437. * generate the keys).
  438. */
  439. s->remote_bugs |= BUG_SSH2_DERIVEKEY;
  440. bpp_logevent("We believe remote version has SSH-2 "
  441. "key-derivation bug");
  442. }
  443. if (conf_get_int(s->conf, CONF_sshbug_rsapad2) == FORCE_ON ||
  444. (conf_get_int(s->conf, CONF_sshbug_rsapad2) == AUTO &&
  445. (wc_match("OpenSSH_2.[5-9]*", imp) ||
  446. wc_match("OpenSSH_3.[0-2]*", imp) ||
  447. wc_match("mod_sftp/0.[0-8]*", imp) ||
  448. wc_match("mod_sftp/0.9.[0-8]", imp)))) {
  449. /*
  450. * These versions have the SSH-2 RSA padding bug.
  451. */
  452. s->remote_bugs |= BUG_SSH2_RSA_PADDING;
  453. bpp_logevent("We believe remote version has SSH-2 RSA padding bug");
  454. }
  455. if (conf_get_int(s->conf, CONF_sshbug_pksessid2) == FORCE_ON ||
  456. (conf_get_int(s->conf, CONF_sshbug_pksessid2) == AUTO &&
  457. wc_match("OpenSSH_2.[0-2]*", imp))) {
  458. /*
  459. * These versions have the SSH-2 session-ID bug in
  460. * public-key authentication.
  461. */
  462. s->remote_bugs |= BUG_SSH2_PK_SESSIONID;
  463. bpp_logevent("We believe remote version has SSH-2 "
  464. "public-key-session-ID bug");
  465. }
  466. if (conf_get_int(s->conf, CONF_sshbug_rekey2) == FORCE_ON ||
  467. (conf_get_int(s->conf, CONF_sshbug_rekey2) == AUTO &&
  468. (wc_match("DigiSSH_2.0", imp) ||
  469. wc_match("OpenSSH_2.[0-4]*", imp) ||
  470. wc_match("OpenSSH_2.5.[0-3]*", imp) ||
  471. wc_match("Sun_SSH_1.0", imp) ||
  472. wc_match("Sun_SSH_1.0.1", imp) ||
  473. /* All versions <= 1.2.6 (they changed their format in 1.2.7) */
  474. wc_match("WeOnlyDo-*", imp)))) {
  475. /*
  476. * These versions have the SSH-2 rekey bug.
  477. */
  478. s->remote_bugs |= BUG_SSH2_REKEY;
  479. bpp_logevent("We believe remote version has SSH-2 rekey bug");
  480. }
  481. if (conf_get_int(s->conf, CONF_sshbug_maxpkt2) == FORCE_ON ||
  482. (conf_get_int(s->conf, CONF_sshbug_maxpkt2) == AUTO &&
  483. (wc_match("1.36_sshlib GlobalSCAPE", imp) ||
  484. wc_match("1.36 sshlib: GlobalScape", imp)))) {
  485. /*
  486. * This version ignores our makpkt and needs to be throttled.
  487. */
  488. s->remote_bugs |= BUG_SSH2_MAXPKT;
  489. bpp_logevent("We believe remote version ignores SSH-2 "
  490. "maximum packet size");
  491. }
  492. if (conf_get_int(s->conf, CONF_sshbug_ignore2) == FORCE_ON) {
  493. /*
  494. * Servers that don't support SSH2_MSG_IGNORE. Currently,
  495. * none detected automatically.
  496. */
  497. s->remote_bugs |= BUG_CHOKES_ON_SSH2_IGNORE;
  498. bpp_logevent("We believe remote version has SSH-2 ignore bug");
  499. }
  500. if (conf_get_int(s->conf, CONF_sshbug_oldgex2) == FORCE_ON ||
  501. (conf_get_int(s->conf, CONF_sshbug_oldgex2) == AUTO &&
  502. (wc_match("OpenSSH_2.[235]*", imp)))) {
  503. /*
  504. * These versions only support the original (pre-RFC4419)
  505. * SSH-2 GEX request, and disconnect with a protocol error if
  506. * we use the newer version.
  507. */
  508. s->remote_bugs |= BUG_SSH2_OLDGEX;
  509. bpp_logevent("We believe remote version has outdated SSH-2 GEX");
  510. }
  511. if (conf_get_int(s->conf, CONF_sshbug_winadj) == FORCE_ON) {
  512. /*
  513. * Servers that don't support our winadj request for one
  514. * reason or another. Currently, none detected automatically.
  515. */
  516. s->remote_bugs |= BUG_CHOKES_ON_WINADJ;
  517. bpp_logevent("We believe remote version has winadj bug");
  518. }
  519. if (conf_get_int(s->conf, CONF_sshbug_chanreq) == FORCE_ON ||
  520. (conf_get_int(s->conf, CONF_sshbug_chanreq) == AUTO &&
  521. (wc_match("OpenSSH_[2-5].*", imp) ||
  522. wc_match("OpenSSH_6.[0-6]*", imp) ||
  523. wc_match("dropbear_0.[2-4][0-9]*", imp) ||
  524. wc_match("dropbear_0.5[01]*", imp)))) {
  525. /*
  526. * These versions have the SSH-2 channel request bug.
  527. * OpenSSH 6.7 and above do not:
  528. * https://bugzilla.mindrot.org/show_bug.cgi?id=1818
  529. * dropbear_0.52 and above do not:
  530. * https://secure.ucc.asn.au/hg/dropbear/rev/cd02449b709c
  531. */
  532. s->remote_bugs |= BUG_SENDS_LATE_REQUEST_REPLY;
  533. bpp_logevent("We believe remote version has SSH-2 "
  534. "channel request bug");
  535. }
  536. }
  537. const char *ssh_verstring_get_remote(BinaryPacketProtocol *bpp)
  538. {
  539. struct ssh_verstring_state *s =
  540. container_of(bpp, struct ssh_verstring_state, bpp);
  541. return s->vstring;
  542. }
  543. const char *ssh_verstring_get_local(BinaryPacketProtocol *bpp)
  544. {
  545. struct ssh_verstring_state *s =
  546. container_of(bpp, struct ssh_verstring_state, bpp);
  547. return s->our_vstring;
  548. }
  549. int ssh_verstring_get_bugs(BinaryPacketProtocol *bpp)
  550. {
  551. struct ssh_verstring_state *s =
  552. container_of(bpp, struct ssh_verstring_state, bpp);
  553. return s->remote_bugs;
  554. }
  555. static void ssh_verstring_queue_disconnect(BinaryPacketProtocol *bpp,
  556. const char *msg, int category)
  557. {
  558. /* No way to send disconnect messages at this stage of the protocol! */
  559. }