misc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*
  2. * Platform-independent routines shared between all PuTTY programs.
  3. *
  4. * This file contains functions that use the kind of infrastructure
  5. * like conf.c that tends to only live in the main applications, or
  6. * that do things that only something like a main PuTTY application
  7. * would need. So standalone test programs should generally be able to
  8. * avoid linking against it.
  9. *
  10. * More standalone functions that depend on nothing but the C library
  11. * live in utils.c.
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <stdarg.h>
  16. #include <limits.h>
  17. #include <ctype.h>
  18. #include <assert.h>
  19. #include "defs.h"
  20. #include "putty.h"
  21. #include "misc.h"
  22. #define BASE64_CHARS_NOEQ \
  23. "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
  24. #define BASE64_CHARS_ALL BASE64_CHARS_NOEQ "="
  25. void seat_connection_fatal(Seat *seat, const char *fmt, ...)
  26. {
  27. va_list ap;
  28. char *msg;
  29. va_start(ap, fmt);
  30. msg = dupvprintf(fmt, ap);
  31. va_end(ap);
  32. seat->vt->connection_fatal(seat, msg);
  33. sfree(msg); /* if we return */
  34. }
  35. prompts_t *new_prompts(void)
  36. {
  37. prompts_t *p = snew(prompts_t);
  38. p->prompts = NULL;
  39. p->n_prompts = p->prompts_size = 0;
  40. p->data = NULL;
  41. p->to_server = true; /* to be on the safe side */
  42. p->name = p->instruction = NULL;
  43. p->name_reqd = p->instr_reqd = false;
  44. return p;
  45. }
  46. void add_prompt(prompts_t *p, char *promptstr, bool echo)
  47. {
  48. prompt_t *pr = snew(prompt_t);
  49. pr->prompt = promptstr;
  50. pr->echo = echo;
  51. pr->result = strbuf_new_nm();
  52. sgrowarray(p->prompts, p->prompts_size, p->n_prompts);
  53. p->prompts[p->n_prompts++] = pr;
  54. }
  55. void prompt_set_result(prompt_t *pr, const char *newstr)
  56. {
  57. strbuf_clear(pr->result);
  58. put_datapl(pr->result, ptrlen_from_asciz(newstr));
  59. }
  60. const char *prompt_get_result_ref(prompt_t *pr)
  61. {
  62. return pr->result->s;
  63. }
  64. char *prompt_get_result(prompt_t *pr)
  65. {
  66. return dupstr(pr->result->s);
  67. }
  68. void free_prompts(prompts_t *p)
  69. {
  70. size_t i;
  71. for (i=0; i < p->n_prompts; i++) {
  72. prompt_t *pr = p->prompts[i];
  73. strbuf_free(pr->result);
  74. sfree(pr->prompt);
  75. sfree(pr);
  76. }
  77. sfree(p->prompts);
  78. sfree(p->name);
  79. sfree(p->instruction);
  80. sfree(p);
  81. }
  82. /*
  83. * Determine whether or not a Conf represents a session which can
  84. * sensibly be launched right now.
  85. */
  86. bool conf_launchable(Conf *conf)
  87. {
  88. if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
  89. return conf_get_str(conf, CONF_serline)[0] != 0;
  90. else
  91. return conf_get_str(conf, CONF_host)[0] != 0;
  92. }
  93. char const *conf_dest(Conf *conf)
  94. {
  95. if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
  96. return conf_get_str(conf, CONF_serline);
  97. else
  98. return conf_get_str(conf, CONF_host);
  99. }
  100. /*
  101. * Validate a manual host key specification (either entered in the
  102. * GUI, or via -hostkey). If valid, we return true, and update 'key'
  103. * to contain a canonicalised version of the key string in 'key'
  104. * (which is guaranteed to take up at most as much space as the
  105. * original version), suitable for putting into the Conf. If not
  106. * valid, we return false.
  107. */
  108. bool validate_manual_hostkey(char *key)
  109. {
  110. char *p, *q, *r, *s;
  111. /*
  112. * Step through the string word by word, looking for a word that's
  113. * in one of the formats we like.
  114. */
  115. p = key;
  116. while ((p += strspn(p, " \t"))[0]) {
  117. q = p;
  118. p += strcspn(p, " \t");
  119. if (*p) *p++ = '\0';
  120. /*
  121. * Now q is our word.
  122. */
  123. if (strstartswith(q, "SHA256:")) {
  124. /* Test for a valid SHA256 key fingerprint. */
  125. r = q + 7;
  126. if (strlen(r) == 43 && r[strspn(r, BASE64_CHARS_NOEQ)] == 0)
  127. return true;
  128. }
  129. r = q;
  130. if (strstartswith(r, "MD5:"))
  131. r += 4;
  132. if (strlen(r) == 16*3 - 1 &&
  133. r[strspn(r, "0123456789abcdefABCDEF:")] == 0) {
  134. /*
  135. * Test for a valid MD5 key fingerprint. Check the colons
  136. * are in the right places, and if so, return the same
  137. * fingerprint canonicalised into lowercase.
  138. */
  139. int i;
  140. for (i = 0; i < 16; i++)
  141. if (r[3*i] == ':' || r[3*i+1] == ':')
  142. goto not_fingerprint; /* sorry */
  143. for (i = 0; i < 15; i++)
  144. if (r[3*i+2] != ':')
  145. goto not_fingerprint; /* sorry */
  146. for (i = 0; i < 16*3 - 1; i++)
  147. key[i] = tolower(r[i]);
  148. key[16*3 - 1] = '\0';
  149. return true;
  150. }
  151. not_fingerprint:;
  152. /*
  153. * Before we check for a public-key blob, trim newlines out of
  154. * the middle of the word, in case someone's managed to paste
  155. * in a public-key blob _with_ them.
  156. */
  157. for (r = s = q; *r; r++)
  158. if (*r != '\n' && *r != '\r')
  159. *s++ = *r;
  160. *s = '\0';
  161. if (strlen(q) % 4 == 0 && strlen(q) > 2*4 &&
  162. q[strspn(q, BASE64_CHARS_ALL)] == 0) {
  163. /*
  164. * Might be a base64-encoded SSH-2 public key blob. Check
  165. * that it starts with a sensible algorithm string. No
  166. * canonicalisation is necessary for this string type.
  167. *
  168. * The algorithm string must be at most 64 characters long
  169. * (RFC 4251 section 6).
  170. */
  171. unsigned char decoded[6];
  172. unsigned alglen;
  173. int minlen;
  174. int len = 0;
  175. len += base64_decode_atom(q, decoded+len);
  176. if (len < 3)
  177. goto not_ssh2_blob; /* sorry */
  178. len += base64_decode_atom(q+4, decoded+len);
  179. if (len < 4)
  180. goto not_ssh2_blob; /* sorry */
  181. alglen = GET_32BIT_MSB_FIRST(decoded);
  182. if (alglen > 64)
  183. goto not_ssh2_blob; /* sorry */
  184. minlen = ((alglen + 4) + 2) / 3;
  185. if (strlen(q) < minlen)
  186. goto not_ssh2_blob; /* sorry */
  187. strcpy(key, q);
  188. return true;
  189. }
  190. not_ssh2_blob:;
  191. }
  192. return false;
  193. }
  194. #ifndef WINSCP
  195. char *buildinfo(const char *newline)
  196. {
  197. strbuf *buf = strbuf_new();
  198. strbuf_catf(buf, "Build platform: %d-bit %s",
  199. (int)(CHAR_BIT * sizeof(void *)),
  200. BUILDINFO_PLATFORM);
  201. #ifdef __clang_version__
  202. #define FOUND_COMPILER
  203. strbuf_catf(buf, "%sCompiler: clang %s", newline, __clang_version__);
  204. #elif defined __GNUC__ && defined __VERSION__
  205. #define FOUND_COMPILER
  206. strbuf_catf(buf, "%sCompiler: gcc %s", newline, __VERSION__);
  207. #endif
  208. #if defined _MSC_VER
  209. #ifndef FOUND_COMPILER
  210. #define FOUND_COMPILER
  211. strbuf_catf(buf, "%sCompiler: ", newline);
  212. #else
  213. strbuf_catf(buf, ", emulating ");
  214. #endif
  215. strbuf_catf(buf, "Visual Studio");
  216. #if 0
  217. /*
  218. * List of _MSC_VER values and their translations taken from
  219. * https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
  220. *
  221. * The pointless #if 0 branch containing this comment is there so
  222. * that every real clause can start with #elif and there's no
  223. * anomalous first clause. That way the patch looks nicer when you
  224. * add extra ones.
  225. */
  226. #elif _MSC_VER == 1928 && _MSC_FULL_VER >= 192829500
  227. /*
  228. * 16.9 and 16.8 have the same _MSC_VER value, and have to be
  229. * distinguished by _MSC_FULL_VER. As of 2021-03-04 that is not
  230. * mentioned on the above page, but see e.g.
  231. * https://developercommunity.visualstudio.com/t/the-169-cc-compiler-still-uses-the-same-version-nu/1335194#T-N1337120
  232. * which says that 16.9 builds will have versions starting at
  233. * 19.28.29500.* and going up. Hence, 19 28 29500 is what we
  234. * compare _MSC_FULL_VER against above.
  235. */
  236. strbuf_catf(buf, " 2019 (16.9)");
  237. #elif _MSC_VER == 1928
  238. strbuf_catf(buf, " 2019 (16.8)");
  239. #elif _MSC_VER == 1927
  240. strbuf_catf(buf, " 2019 (16.7)");
  241. #elif _MSC_VER == 1926
  242. strbuf_catf(buf, " 2019 (16.6)");
  243. #elif _MSC_VER == 1925
  244. strbuf_catf(buf, " 2019 (16.5)");
  245. #elif _MSC_VER == 1924
  246. strbuf_catf(buf, " 2019 (16.4)");
  247. #elif _MSC_VER == 1923
  248. strbuf_catf(buf, " 2019 (16.3)");
  249. #elif _MSC_VER == 1922
  250. strbuf_catf(buf, " 2019 (16.2)");
  251. #elif _MSC_VER == 1921
  252. strbuf_catf(buf, " 2019 (16.1)");
  253. #elif _MSC_VER == 1920
  254. strbuf_catf(buf, " 2019 (16.0)");
  255. #elif _MSC_VER == 1916
  256. strbuf_catf(buf, " 2017 version 15.9");
  257. #elif _MSC_VER == 1915
  258. strbuf_catf(buf, " 2017 version 15.8");
  259. #elif _MSC_VER == 1914
  260. strbuf_catf(buf, " 2017 version 15.7");
  261. #elif _MSC_VER == 1913
  262. strbuf_catf(buf, " 2017 version 15.6");
  263. #elif _MSC_VER == 1912
  264. strbuf_catf(buf, " 2017 version 15.5");
  265. #elif _MSC_VER == 1911
  266. strbuf_catf(buf, " 2017 version 15.3");
  267. #elif _MSC_VER == 1910
  268. strbuf_catf(buf, " 2017 RTW (15.0)");
  269. #elif _MSC_VER == 1900
  270. strbuf_catf(buf, " 2015 (14.0)");
  271. #elif _MSC_VER == 1800
  272. strbuf_catf(buf, " 2013 (12.0)");
  273. #elif _MSC_VER == 1700
  274. strbuf_catf(buf, " 2012 (11.0)");
  275. #elif _MSC_VER == 1600
  276. strbuf_catf(buf, " 2010 (10.0)");
  277. #elif _MSC_VER == 1500
  278. strbuf_catf(buf, " 2008 (9.0)");
  279. #elif _MSC_VER == 1400
  280. strbuf_catf(buf, " 2005 (8.0)");
  281. #elif _MSC_VER == 1310
  282. strbuf_catf(buf, " .NET 2003 (7.1)");
  283. #elif _MSC_VER == 1300
  284. strbuf_catf(buf, " .NET 2002 (7.0)");
  285. #elif _MSC_VER == 1200
  286. strbuf_catf(buf, " 6.0");
  287. #else
  288. strbuf_catf(buf, ", unrecognised version");
  289. #endif
  290. strbuf_catf(buf, ", _MSC_VER=%d", (int)_MSC_VER);
  291. #endif
  292. #ifdef BUILDINFO_GTK
  293. {
  294. char *gtk_buildinfo = buildinfo_gtk_version();
  295. if (gtk_buildinfo) {
  296. strbuf_catf(buf, "%sCompiled against GTK version %s",
  297. newline, gtk_buildinfo);
  298. sfree(gtk_buildinfo);
  299. }
  300. }
  301. #endif
  302. #if defined _WINDOWS
  303. {
  304. int echm = has_embedded_chm();
  305. if (echm >= 0)
  306. strbuf_catf(buf, "%sEmbedded HTML Help file: %s", newline,
  307. echm ? "yes" : "no");
  308. }
  309. #endif
  310. #if defined _WINDOWS && defined MINEFIELD
  311. strbuf_catf(buf, "%sBuild option: MINEFIELD", newline);
  312. #endif
  313. #ifdef NO_SECURITY
  314. strbuf_catf(buf, "%sBuild option: NO_SECURITY", newline);
  315. #endif
  316. #ifdef NO_SECUREZEROMEMORY
  317. strbuf_catf(buf, "%sBuild option: NO_SECUREZEROMEMORY", newline);
  318. #endif
  319. #ifdef NO_IPV6
  320. strbuf_catf(buf, "%sBuild option: NO_IPV6", newline);
  321. #endif
  322. #ifdef NO_GSSAPI
  323. strbuf_catf(buf, "%sBuild option: NO_GSSAPI", newline);
  324. #endif
  325. #ifdef STATIC_GSSAPI
  326. strbuf_catf(buf, "%sBuild option: STATIC_GSSAPI", newline);
  327. #endif
  328. #ifdef UNPROTECT
  329. strbuf_catf(buf, "%sBuild option: UNPROTECT", newline);
  330. #endif
  331. #ifdef FUZZING
  332. strbuf_catf(buf, "%sBuild option: FUZZING", newline);
  333. #endif
  334. #ifdef DEBUG
  335. strbuf_catf(buf, "%sBuild option: DEBUG", newline);
  336. #endif
  337. strbuf_catf(buf, "%sSource commit: %s", newline, commitid);
  338. return strbuf_to_str(buf);
  339. }
  340. #endif !WINSCP
  341. #ifdef MPEXT
  342. #include "version.h"
  343. const char * get_putty_version()
  344. {
  345. return TEXTVER;
  346. }
  347. #endif
  348. size_t nullseat_output(
  349. Seat *seat, bool is_stderr, const void *data, size_t len) { return 0; }
  350. bool nullseat_eof(Seat *seat) { return true; }
  351. int nullseat_get_userpass_input(
  352. Seat *seat, prompts_t *p, bufchain *input) { return 0; }
  353. void nullseat_notify_remote_exit(Seat *seat) {}
  354. void nullseat_connection_fatal(Seat *seat, const char *message) {}
  355. void nullseat_update_specials_menu(Seat *seat) {}
  356. char *nullseat_get_ttymode(Seat *seat, const char *mode) { return NULL; }
  357. void nullseat_set_busy_status(Seat *seat, BusyStatus status) {}
  358. int nullseat_verify_ssh_host_key(
  359. Seat *seat, const char *host, int port, const char *keytype,
  360. char *keystr, const char *keydisp, char **key_fingerprints,
  361. void (*callback)(void *ctx, int result), void *ctx) { return 0; }
  362. int nullseat_confirm_weak_crypto_primitive(
  363. Seat *seat, const char *algtype, const char *algname,
  364. void (*callback)(void *ctx, int result), void *ctx) { return 0; }
  365. int nullseat_confirm_weak_cached_hostkey(
  366. Seat *seat, const char *algname, const char *betteralgs,
  367. void (*callback)(void *ctx, int result), void *ctx) { return 0; }
  368. bool nullseat_is_never_utf8(Seat *seat) { return false; }
  369. bool nullseat_is_always_utf8(Seat *seat) { return true; }
  370. void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing) {}
  371. const char *nullseat_get_x_display(Seat *seat) { return NULL; }
  372. bool nullseat_get_windowid(Seat *seat, long *id_out) { return false; }
  373. bool nullseat_get_window_pixel_size(
  374. Seat *seat, int *width, int *height) { return false; }
  375. StripCtrlChars *nullseat_stripctrl_new(
  376. Seat *seat, BinarySink *bs_out, SeatInteractionContext sic) {return NULL;}
  377. bool nullseat_set_trust_status(Seat *seat, bool tr) { return false; }
  378. bool nullseat_set_trust_status_vacuously(Seat *seat, bool tr) { return true; }
  379. bool nullseat_verbose_no(Seat *seat) { return false; }
  380. bool nullseat_verbose_yes(Seat *seat) { return true; }
  381. bool nullseat_interactive_no(Seat *seat) { return false; }
  382. bool nullseat_interactive_yes(Seat *seat) { return true; }
  383. bool nullseat_get_cursor_position(Seat *seat, int *x, int *y) { return false; }
  384. bool null_lp_verbose_no(LogPolicy *lp) { return false; }
  385. bool null_lp_verbose_yes(LogPolicy *lp) { return true; }
  386. void sk_free_peer_info(SocketPeerInfo *pi)
  387. {
  388. if (pi) {
  389. sfree((char *)pi->addr_text);
  390. sfree((char *)pi->log_text);
  391. sfree(pi);
  392. }
  393. }
  394. void out_of_memory(void)
  395. {
  396. modalfatalbox("Out of memory");
  397. }