sshconnect.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. /* $OpenBSD: sshconnect.c,v 1.344 2020/11/22 22:37:11 djm Exp $ */
  2. /*
  3. * Author: Tatu Ylonen <ylo@cs.hut.fi>
  4. * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  5. * All rights reserved
  6. * Code to connect to a remote host, and to perform the client side of the
  7. * login (authentication) dialog.
  8. *
  9. * As far as I am concerned, the code I have written for this software
  10. * can be used freely for any purpose. Any derived versions of this
  11. * software must be clearly marked as such, and if the derived work is
  12. * incompatible with the protocol description in the RFC file, it must be
  13. * called by a name other than "ssh" or "Secure Shell".
  14. */
  15. #include "includes.h"
  16. #include <sys/types.h>
  17. #include <sys/wait.h>
  18. #include <sys/stat.h>
  19. #include <sys/socket.h>
  20. #ifdef HAVE_SYS_TIME_H
  21. # include <sys/time.h>
  22. #endif
  23. #include <net/if.h>
  24. #include <netinet/in.h>
  25. #include <arpa/inet.h>
  26. #include <ctype.h>
  27. #include <errno.h>
  28. #include <fcntl.h>
  29. #include <netdb.h>
  30. #ifdef HAVE_PATHS_H
  31. #include <paths.h>
  32. #endif
  33. #include <pwd.h>
  34. #ifdef HAVE_POLL_H
  35. #include <poll.h>
  36. #endif
  37. #include <signal.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <stdarg.h>
  41. #include <string.h>
  42. #include <unistd.h>
  43. #ifdef HAVE_IFADDRS_H
  44. # include <ifaddrs.h>
  45. #endif
  46. #include "xmalloc.h"
  47. #include "hostfile.h"
  48. #include "ssh.h"
  49. #include "sshbuf.h"
  50. #include "packet.h"
  51. #include "compat.h"
  52. #include "sshkey.h"
  53. #include "sshconnect.h"
  54. #include "log.h"
  55. #include "misc.h"
  56. #include "readconf.h"
  57. #include "atomicio.h"
  58. #include "dns.h"
  59. #include "monitor_fdpass.h"
  60. #include "ssh2.h"
  61. #include "version.h"
  62. #include "authfile.h"
  63. #include "ssherr.h"
  64. #include "authfd.h"
  65. #include "kex.h"
  66. struct sshkey *previous_host_key = NULL;
  67. static int matching_host_key_dns = 0;
  68. static pid_t proxy_command_pid = 0;
  69. /* import */
  70. extern int debug_flag;
  71. extern Options options;
  72. extern char *__progname;
  73. static int show_other_keys(struct hostkeys *, struct sshkey *);
  74. static void warn_changed_key(struct sshkey *);
  75. /* Expand a proxy command */
  76. static char *
  77. expand_proxy_command(const char *proxy_command, const char *user,
  78. const char *host, const char *host_arg, int port)
  79. {
  80. char *tmp, *ret, strport[NI_MAXSERV];
  81. const char *keyalias = options.host_key_alias ?
  82. options.host_key_alias : host_arg;
  83. snprintf(strport, sizeof strport, "%d", port);
  84. xasprintf(&tmp, "exec %s", proxy_command);
  85. ret = percent_expand(tmp,
  86. "h", host,
  87. "k", keyalias,
  88. "n", host_arg,
  89. "p", strport,
  90. "r", options.user,
  91. (char *)NULL);
  92. free(tmp);
  93. return ret;
  94. }
  95. static void
  96. stderr_null(void)
  97. {
  98. int devnull;
  99. if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
  100. error("Can't open %s for stderr redirection: %s",
  101. _PATH_DEVNULL, strerror(errno));
  102. return;
  103. }
  104. if (devnull == STDERR_FILENO)
  105. return;
  106. if (dup2(devnull, STDERR_FILENO) == -1)
  107. error("Cannot redirect stderr to %s", _PATH_DEVNULL);
  108. if (devnull > STDERR_FILENO)
  109. close(devnull);
  110. }
  111. /*
  112. * Connect to the given ssh server using a proxy command that passes a
  113. * a connected fd back to us.
  114. */
  115. static int
  116. ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host,
  117. const char *host_arg, u_short port, const char *proxy_command)
  118. {
  119. char *command_string;
  120. int sp[2], sock;
  121. pid_t pid;
  122. char *shell;
  123. if ((shell = getenv("SHELL")) == NULL)
  124. shell = _PATH_BSHELL;
  125. if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1)
  126. fatal("Could not create socketpair to communicate with "
  127. "proxy dialer: %.100s", strerror(errno));
  128. command_string = expand_proxy_command(proxy_command, options.user,
  129. host, host_arg, port);
  130. debug("Executing proxy dialer command: %.500s", command_string);
  131. /* Fork and execute the proxy command. */
  132. if ((pid = fork()) == 0) {
  133. char *argv[10];
  134. close(sp[1]);
  135. /* Redirect stdin and stdout. */
  136. if (sp[0] != 0) {
  137. if (dup2(sp[0], 0) == -1)
  138. perror("dup2 stdin");
  139. }
  140. if (sp[0] != 1) {
  141. if (dup2(sp[0], 1) == -1)
  142. perror("dup2 stdout");
  143. }
  144. if (sp[0] >= 2)
  145. close(sp[0]);
  146. /*
  147. * Stderr is left for non-ControlPersist connections is so
  148. * error messages may be printed on the user's terminal.
  149. */
  150. if (!debug_flag && options.control_path != NULL &&
  151. options.control_persist)
  152. stderr_null();
  153. argv[0] = shell;
  154. argv[1] = "-c";
  155. argv[2] = command_string;
  156. argv[3] = NULL;
  157. /*
  158. * Execute the proxy command.
  159. * Note that we gave up any extra privileges above.
  160. */
  161. execv(argv[0], argv);
  162. perror(argv[0]);
  163. exit(1);
  164. }
  165. /* Parent. */
  166. if (pid == -1)
  167. fatal("fork failed: %.100s", strerror(errno));
  168. close(sp[0]);
  169. free(command_string);
  170. if ((sock = mm_receive_fd(sp[1])) == -1)
  171. fatal("proxy dialer did not pass back a connection");
  172. close(sp[1]);
  173. while (waitpid(pid, NULL, 0) == -1)
  174. if (errno != EINTR)
  175. fatal("Couldn't wait for child: %s", strerror(errno));
  176. /* Set the connection file descriptors. */
  177. if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
  178. return -1; /* ssh_packet_set_connection logs error */
  179. return 0;
  180. }
  181. /*
  182. * Connect to the given ssh server using a proxy command.
  183. */
  184. static int
  185. ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg,
  186. u_short port, const char *proxy_command)
  187. {
  188. char *command_string;
  189. int pin[2], pout[2];
  190. pid_t pid;
  191. char *shell;
  192. if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
  193. shell = _PATH_BSHELL;
  194. /* Create pipes for communicating with the proxy. */
  195. if (pipe(pin) == -1 || pipe(pout) == -1)
  196. fatal("Could not create pipes to communicate with the proxy: %.100s",
  197. strerror(errno));
  198. command_string = expand_proxy_command(proxy_command, options.user,
  199. host, host_arg, port);
  200. debug("Executing proxy command: %.500s", command_string);
  201. /* Fork and execute the proxy command. */
  202. if ((pid = fork()) == 0) {
  203. char *argv[10];
  204. /* Redirect stdin and stdout. */
  205. close(pin[1]);
  206. if (pin[0] != 0) {
  207. if (dup2(pin[0], 0) == -1)
  208. perror("dup2 stdin");
  209. close(pin[0]);
  210. }
  211. close(pout[0]);
  212. if (dup2(pout[1], 1) == -1)
  213. perror("dup2 stdout");
  214. /* Cannot be 1 because pin allocated two descriptors. */
  215. close(pout[1]);
  216. /*
  217. * Stderr is left for non-ControlPersist connections is so
  218. * error messages may be printed on the user's terminal.
  219. */
  220. if (!debug_flag && options.control_path != NULL &&
  221. options.control_persist)
  222. stderr_null();
  223. argv[0] = shell;
  224. argv[1] = "-c";
  225. argv[2] = command_string;
  226. argv[3] = NULL;
  227. /* Execute the proxy command. Note that we gave up any
  228. extra privileges above. */
  229. ssh_signal(SIGPIPE, SIG_DFL);
  230. execvp(argv[0], argv);
  231. perror(argv[0]);
  232. exit(1);
  233. }
  234. /* Parent. */
  235. if (pid == -1)
  236. fatal("fork failed: %.100s", strerror(errno));
  237. else
  238. proxy_command_pid = pid; /* save pid to clean up later */
  239. /* Close child side of the descriptors. */
  240. close(pin[0]);
  241. close(pout[1]);
  242. /* Free the command name. */
  243. free(command_string);
  244. /* Set the connection file descriptors. */
  245. if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL)
  246. return -1; /* ssh_packet_set_connection logs error */
  247. return 0;
  248. }
  249. void
  250. ssh_kill_proxy_command(void)
  251. {
  252. /*
  253. * Send SIGHUP to proxy command if used. We don't wait() in
  254. * case it hangs and instead rely on init to reap the child
  255. */
  256. if (proxy_command_pid > 1)
  257. kill(proxy_command_pid, SIGHUP);
  258. }
  259. #ifdef HAVE_IFADDRS_H
  260. /*
  261. * Search a interface address list (returned from getifaddrs(3)) for an
  262. * address that matches the desired address family on the specified interface.
  263. * Returns 0 and fills in *resultp and *rlenp on success. Returns -1 on failure.
  264. */
  265. static int
  266. check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs,
  267. struct sockaddr_storage *resultp, socklen_t *rlenp)
  268. {
  269. struct sockaddr_in6 *sa6;
  270. struct sockaddr_in *sa;
  271. struct in6_addr *v6addr;
  272. const struct ifaddrs *ifa;
  273. int allow_local;
  274. /*
  275. * Prefer addresses that are not loopback or linklocal, but use them
  276. * if nothing else matches.
  277. */
  278. for (allow_local = 0; allow_local < 2; allow_local++) {
  279. for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
  280. if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
  281. (ifa->ifa_flags & IFF_UP) == 0 ||
  282. ifa->ifa_addr->sa_family != af ||
  283. strcmp(ifa->ifa_name, options.bind_interface) != 0)
  284. continue;
  285. switch (ifa->ifa_addr->sa_family) {
  286. case AF_INET:
  287. sa = (struct sockaddr_in *)ifa->ifa_addr;
  288. if (!allow_local && sa->sin_addr.s_addr ==
  289. htonl(INADDR_LOOPBACK))
  290. continue;
  291. if (*rlenp < sizeof(struct sockaddr_in)) {
  292. error("%s: v4 addr doesn't fit",
  293. __func__);
  294. return -1;
  295. }
  296. *rlenp = sizeof(struct sockaddr_in);
  297. memcpy(resultp, sa, *rlenp);
  298. return 0;
  299. case AF_INET6:
  300. sa6 = (struct sockaddr_in6 *)ifa->ifa_addr;
  301. v6addr = &sa6->sin6_addr;
  302. if (!allow_local &&
  303. (IN6_IS_ADDR_LINKLOCAL(v6addr) ||
  304. IN6_IS_ADDR_LOOPBACK(v6addr)))
  305. continue;
  306. if (*rlenp < sizeof(struct sockaddr_in6)) {
  307. error("%s: v6 addr doesn't fit",
  308. __func__);
  309. return -1;
  310. }
  311. *rlenp = sizeof(struct sockaddr_in6);
  312. memcpy(resultp, sa6, *rlenp);
  313. return 0;
  314. }
  315. }
  316. }
  317. return -1;
  318. }
  319. #endif
  320. /*
  321. * Set TCP receive buffer if requested.
  322. * Note: tuning needs to happen after the socket is
  323. * created but before the connection happens
  324. * so winscale is negotiated properly -cjr
  325. */
  326. static void
  327. ssh_set_socket_recvbuf(int sock)
  328. {
  329. void *buf = (void *)&options.tcp_rcv_buf;
  330. int sz = sizeof(options.tcp_rcv_buf);
  331. int socksize;
  332. int socksizelen = sizeof(int);
  333. debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf);
  334. if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) {
  335. getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen);
  336. debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize);
  337. }
  338. else
  339. error("Couldn't set socket receive buffer to %d: %.100s",
  340. options.tcp_rcv_buf, strerror(errno));
  341. }
  342. /*
  343. * Creates a socket for use as the ssh connection.
  344. */
  345. static int
  346. ssh_create_socket(struct addrinfo *ai)
  347. {
  348. int sock, r;
  349. struct sockaddr_storage bindaddr;
  350. socklen_t bindaddrlen = 0;
  351. struct addrinfo hints, *res = NULL;
  352. #ifdef HAVE_IFADDRS_H
  353. struct ifaddrs *ifaddrs = NULL;
  354. #endif
  355. char ntop[NI_MAXHOST];
  356. sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  357. if (sock == -1) {
  358. error("socket: %s", strerror(errno));
  359. return -1;
  360. }
  361. fcntl(sock, F_SETFD, FD_CLOEXEC);
  362. if (options.tcp_rcv_buf > 0)
  363. ssh_set_socket_recvbuf(sock);
  364. /* Bind the socket to an alternative local IP address */
  365. if (options.bind_address == NULL && options.bind_interface == NULL)
  366. return sock;
  367. if (options.bind_address != NULL) {
  368. memset(&hints, 0, sizeof(hints));
  369. hints.ai_family = ai->ai_family;
  370. hints.ai_socktype = ai->ai_socktype;
  371. hints.ai_protocol = ai->ai_protocol;
  372. hints.ai_flags = AI_PASSIVE;
  373. if ((r = getaddrinfo(options.bind_address, NULL,
  374. &hints, &res)) != 0) {
  375. error("getaddrinfo: %s: %s", options.bind_address,
  376. ssh_gai_strerror(r));
  377. goto fail;
  378. }
  379. if (res == NULL) {
  380. error("getaddrinfo: no addrs");
  381. goto fail;
  382. }
  383. memcpy(&bindaddr, res->ai_addr, res->ai_addrlen);
  384. bindaddrlen = res->ai_addrlen;
  385. } else if (options.bind_interface != NULL) {
  386. #ifdef HAVE_IFADDRS_H
  387. if ((r = getifaddrs(&ifaddrs)) != 0) {
  388. error("getifaddrs: %s: %s", options.bind_interface,
  389. strerror(errno));
  390. goto fail;
  391. }
  392. bindaddrlen = sizeof(bindaddr);
  393. if (check_ifaddrs(options.bind_interface, ai->ai_family,
  394. ifaddrs, &bindaddr, &bindaddrlen) != 0) {
  395. logit("getifaddrs: %s: no suitable addresses",
  396. options.bind_interface);
  397. goto fail;
  398. }
  399. #else
  400. error("BindInterface not supported on this platform.");
  401. #endif
  402. }
  403. if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen,
  404. ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) {
  405. error("%s: getnameinfo failed: %s", __func__,
  406. ssh_gai_strerror(r));
  407. goto fail;
  408. }
  409. if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) {
  410. error("bind %s: %s", ntop, strerror(errno));
  411. goto fail;
  412. }
  413. debug("%s: bound to %s", __func__, ntop);
  414. /* success */
  415. goto out;
  416. fail:
  417. close(sock);
  418. sock = -1;
  419. out:
  420. if (res != NULL)
  421. freeaddrinfo(res);
  422. #ifdef HAVE_IFADDRS_H
  423. if (ifaddrs != NULL)
  424. freeifaddrs(ifaddrs);
  425. #endif
  426. return sock;
  427. }
  428. /*
  429. * Opens a TCP/IP connection to the remote server on the given host.
  430. * The address of the remote host will be returned in hostaddr.
  431. * If port is 0, the default port will be used.
  432. * Connection_attempts specifies the maximum number of tries (one per
  433. * second). If proxy_command is non-NULL, it specifies the command (with %h
  434. * and %p substituted for host and port, respectively) to use to contact
  435. * the daemon.
  436. */
  437. static int
  438. ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
  439. struct sockaddr_storage *hostaddr, u_short port, int connection_attempts,
  440. int *timeout_ms, int want_keepalive)
  441. {
  442. int on = 1, saved_timeout_ms = *timeout_ms;
  443. int oerrno, sock = -1, attempt;
  444. char ntop[NI_MAXHOST], strport[NI_MAXSERV];
  445. struct addrinfo *ai;
  446. debug2("%s", __func__);
  447. memset(ntop, 0, sizeof(ntop));
  448. memset(strport, 0, sizeof(strport));
  449. for (attempt = 0; attempt < connection_attempts; attempt++) {
  450. if (attempt > 0) {
  451. /* Sleep a moment before retrying. */
  452. sleep(1);
  453. debug("Trying again...");
  454. }
  455. /*
  456. * Loop through addresses for this host, and try each one in
  457. * sequence until the connection succeeds.
  458. */
  459. for (ai = aitop; ai; ai = ai->ai_next) {
  460. if (ai->ai_family != AF_INET &&
  461. ai->ai_family != AF_INET6) {
  462. errno = EAFNOSUPPORT;
  463. continue;
  464. }
  465. if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
  466. ntop, sizeof(ntop), strport, sizeof(strport),
  467. NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
  468. oerrno = errno;
  469. error("%s: getnameinfo failed", __func__);
  470. errno = oerrno;
  471. continue;
  472. }
  473. debug("Connecting to %.200s [%.100s] port %s.",
  474. host, ntop, strport);
  475. /* Create a socket for connecting. */
  476. sock = ssh_create_socket(ai);
  477. if (sock < 0) {
  478. /* Any error is already output */
  479. errno = 0;
  480. continue;
  481. }
  482. *timeout_ms = saved_timeout_ms;
  483. if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
  484. timeout_ms) >= 0) {
  485. /* Successful connection. */
  486. memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
  487. break;
  488. } else {
  489. oerrno = errno;
  490. debug("connect to address %s port %s: %s",
  491. ntop, strport, strerror(errno));
  492. close(sock);
  493. sock = -1;
  494. errno = oerrno;
  495. }
  496. }
  497. if (sock != -1)
  498. break; /* Successful connection. */
  499. }
  500. /* Return failure if we didn't get a successful connection. */
  501. if (sock == -1) {
  502. error("ssh: connect to host %s port %s: %s",
  503. host, strport, errno == 0 ? "failure" : strerror(errno));
  504. return -1;
  505. }
  506. debug("Connection established.");
  507. /* Set SO_KEEPALIVE if requested. */
  508. if (want_keepalive &&
  509. setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
  510. sizeof(on)) == -1)
  511. error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
  512. /* Set the connection. */
  513. if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
  514. return -1; /* ssh_packet_set_connection logs error */
  515. return 0;
  516. }
  517. int
  518. ssh_connect(struct ssh *ssh, const char *host, const char *host_arg,
  519. struct addrinfo *addrs, struct sockaddr_storage *hostaddr, u_short port,
  520. int connection_attempts, int *timeout_ms, int want_keepalive)
  521. {
  522. int in, out;
  523. if (options.proxy_command == NULL) {
  524. return ssh_connect_direct(ssh, host, addrs, hostaddr, port,
  525. connection_attempts, timeout_ms, want_keepalive);
  526. } else if (strcmp(options.proxy_command, "-") == 0) {
  527. if ((in = dup(STDIN_FILENO)) == -1 ||
  528. (out = dup(STDOUT_FILENO)) == -1) {
  529. if (in >= 0)
  530. close(in);
  531. error("%s: dup() in/out failed", __func__);
  532. return -1; /* ssh_packet_set_connection logs error */
  533. }
  534. if ((ssh_packet_set_connection(ssh, in, out)) == NULL)
  535. return -1; /* ssh_packet_set_connection logs error */
  536. return 0;
  537. } else if (options.proxy_use_fdpass) {
  538. return ssh_proxy_fdpass_connect(ssh, host, host_arg, port,
  539. options.proxy_command);
  540. }
  541. return ssh_proxy_connect(ssh, host, host_arg, port,
  542. options.proxy_command);
  543. }
  544. /* defaults to 'no' */
  545. static int
  546. confirm(const char *prompt, const char *fingerprint)
  547. {
  548. const char *msg, *again = "Please type 'yes' or 'no': ";
  549. const char *again_fp = "Please type 'yes', 'no' or the fingerprint: ";
  550. char *p, *cp;
  551. int ret = -1;
  552. if (options.batch_mode)
  553. return 0;
  554. for (msg = prompt;;msg = fingerprint ? again_fp : again) {
  555. cp = p = read_passphrase(msg, RP_ECHO);
  556. if (p == NULL)
  557. return 0;
  558. p += strspn(p, " \t"); /* skip leading whitespace */
  559. p[strcspn(p, " \t\n")] = '\0'; /* remove trailing whitespace */
  560. if (p[0] == '\0' || strcasecmp(p, "no") == 0)
  561. ret = 0;
  562. else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL &&
  563. strcmp(p, fingerprint) == 0))
  564. ret = 1;
  565. free(cp);
  566. if (ret != -1)
  567. return ret;
  568. }
  569. }
  570. static int
  571. sockaddr_is_local(struct sockaddr *hostaddr)
  572. {
  573. switch (hostaddr->sa_family) {
  574. case AF_INET:
  575. return (ntohl(((struct sockaddr_in *)hostaddr)->
  576. sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
  577. case AF_INET6:
  578. return IN6_IS_ADDR_LOOPBACK(
  579. &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
  580. default:
  581. return 0;
  582. }
  583. }
  584. /*
  585. * Prepare the hostname and ip address strings that are used to lookup
  586. * host keys in known_hosts files. These may have a port number appended.
  587. */
  588. void
  589. get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
  590. u_short port, char **hostfile_hostname, char **hostfile_ipaddr)
  591. {
  592. char ntop[NI_MAXHOST];
  593. socklen_t addrlen;
  594. switch (hostaddr == NULL ? -1 : hostaddr->sa_family) {
  595. case -1:
  596. addrlen = 0;
  597. break;
  598. case AF_INET:
  599. addrlen = sizeof(struct sockaddr_in);
  600. break;
  601. case AF_INET6:
  602. addrlen = sizeof(struct sockaddr_in6);
  603. break;
  604. default:
  605. addrlen = sizeof(struct sockaddr);
  606. break;
  607. }
  608. /*
  609. * We don't have the remote ip-address for connections
  610. * using a proxy command
  611. */
  612. if (hostfile_ipaddr != NULL) {
  613. if (options.proxy_command == NULL) {
  614. if (getnameinfo(hostaddr, addrlen,
  615. ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
  616. fatal("%s: getnameinfo failed", __func__);
  617. *hostfile_ipaddr = put_host_port(ntop, port);
  618. } else {
  619. *hostfile_ipaddr = xstrdup("<no hostip for proxy "
  620. "command>");
  621. }
  622. }
  623. /*
  624. * Allow the user to record the key under a different name or
  625. * differentiate a non-standard port. This is useful for ssh
  626. * tunneling over forwarded connections or if you run multiple
  627. * sshd's on different ports on the same machine.
  628. */
  629. if (hostfile_hostname != NULL) {
  630. if (options.host_key_alias != NULL) {
  631. *hostfile_hostname = xstrdup(options.host_key_alias);
  632. debug("using hostkeyalias: %s", *hostfile_hostname);
  633. } else {
  634. *hostfile_hostname = put_host_port(hostname, port);
  635. }
  636. }
  637. }
  638. /*
  639. * check whether the supplied host key is valid, return -1 if the key
  640. * is not valid. user_hostfile[0] will not be updated if 'readonly' is true.
  641. */
  642. #define RDRW 0
  643. #define RDONLY 1
  644. #define ROQUIET 2
  645. static int
  646. check_host_key(char *hostname, const struct ssh_conn_info *cinfo,
  647. struct sockaddr *hostaddr, u_short port,
  648. struct sshkey *host_key, int readonly, int clobber_port,
  649. char **user_hostfiles, u_int num_user_hostfiles,
  650. char **system_hostfiles, u_int num_system_hostfiles)
  651. {
  652. HostStatus host_status;
  653. HostStatus ip_status;
  654. struct sshkey *raw_key = NULL;
  655. char *ip = NULL, *host = NULL;
  656. char hostline[1000], *hostp, *fp, *ra;
  657. char msg[1024];
  658. const char *type, *fail_reason;
  659. const struct hostkey_entry *host_found, *ip_found;
  660. int len, cancelled_forwarding = 0, confirmed;
  661. int local = sockaddr_is_local(hostaddr);
  662. int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0;
  663. int hostkey_trusted = 0; /* Known or explicitly accepted by user */
  664. struct hostkeys *host_hostkeys, *ip_hostkeys;
  665. u_int i;
  666. /*
  667. * Force accepting of the host key for loopback/localhost. The
  668. * problem is that if the home directory is NFS-mounted to multiple
  669. * machines, localhost will refer to a different machine in each of
  670. * them, and the user will get bogus HOST_CHANGED warnings. This
  671. * essentially disables host authentication for localhost; however,
  672. * this is probably not a real problem.
  673. */
  674. if (options.no_host_authentication_for_localhost == 1 && local &&
  675. options.host_key_alias == NULL) {
  676. debug("Forcing accepting of host key for "
  677. "loopback/localhost.");
  678. return 0;
  679. }
  680. /*
  681. * Prepare the hostname and address strings used for hostkey lookup.
  682. * In some cases, these will have a port number appended.
  683. */
  684. get_hostfile_hostname_ipaddr(hostname, hostaddr,
  685. clobber_port ? 0 : port, &host, &ip);
  686. /*
  687. * Turn off check_host_ip if the connection is to localhost, via proxy
  688. * command or if we don't have a hostname to compare with
  689. */
  690. if (options.check_host_ip && (local ||
  691. strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
  692. options.check_host_ip = 0;
  693. host_hostkeys = init_hostkeys();
  694. for (i = 0; i < num_user_hostfiles; i++)
  695. load_hostkeys(host_hostkeys, host, user_hostfiles[i]);
  696. for (i = 0; i < num_system_hostfiles; i++)
  697. load_hostkeys(host_hostkeys, host, system_hostfiles[i]);
  698. ip_hostkeys = NULL;
  699. if (!want_cert && options.check_host_ip) {
  700. ip_hostkeys = init_hostkeys();
  701. for (i = 0; i < num_user_hostfiles; i++)
  702. load_hostkeys(ip_hostkeys, ip, user_hostfiles[i]);
  703. for (i = 0; i < num_system_hostfiles; i++)
  704. load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]);
  705. }
  706. retry:
  707. /* Reload these as they may have changed on cert->key downgrade */
  708. want_cert = sshkey_is_cert(host_key);
  709. type = sshkey_type(host_key);
  710. /*
  711. * Check if the host key is present in the user's list of known
  712. * hosts or in the systemwide list.
  713. */
  714. host_status = check_key_in_hostkeys(host_hostkeys, host_key,
  715. &host_found);
  716. /* If no host files were specified, then don't try to touch them */
  717. if (!readonly && num_user_hostfiles == 0)
  718. readonly = RDONLY;
  719. /*
  720. * Also perform check for the ip address, skip the check if we are
  721. * localhost, looking for a certificate, or the hostname was an ip
  722. * address to begin with.
  723. */
  724. if (!want_cert && ip_hostkeys != NULL) {
  725. ip_status = check_key_in_hostkeys(ip_hostkeys, host_key,
  726. &ip_found);
  727. if (host_status == HOST_CHANGED &&
  728. (ip_status != HOST_CHANGED ||
  729. (ip_found != NULL &&
  730. !sshkey_equal(ip_found->key, host_found->key))))
  731. host_ip_differ = 1;
  732. } else
  733. ip_status = host_status;
  734. switch (host_status) {
  735. case HOST_OK:
  736. /* The host is known and the key matches. */
  737. debug("Host '%.200s' is known and matches the %s host %s.",
  738. host, type, want_cert ? "certificate" : "key");
  739. debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
  740. host_found->file, host_found->line);
  741. if (want_cert) {
  742. if (sshkey_cert_check_host(host_key,
  743. options.host_key_alias == NULL ?
  744. hostname : options.host_key_alias, 0,
  745. options.ca_sign_algorithms, &fail_reason) != 0) {
  746. error("%s", fail_reason);
  747. goto fail;
  748. }
  749. /*
  750. * Do not attempt hostkey update if a certificate was
  751. * successfully matched.
  752. */
  753. if (options.update_hostkeys != 0) {
  754. options.update_hostkeys = 0;
  755. debug3("certificate host key in use; "
  756. "disabling UpdateHostkeys");
  757. }
  758. }
  759. if (options.check_host_ip && ip_status == HOST_NEW) {
  760. if (readonly || want_cert)
  761. logit("%s host key for IP address "
  762. "'%.128s' not in list of known hosts.",
  763. type, ip);
  764. else if (!add_host_to_hostfile(user_hostfiles[0], ip,
  765. host_key, options.hash_known_hosts))
  766. logit("Failed to add the %s host key for IP "
  767. "address '%.128s' to the list of known "
  768. "hosts (%.500s).", type, ip,
  769. user_hostfiles[0]);
  770. else
  771. logit("Warning: Permanently added the %s host "
  772. "key for IP address '%.128s' to the list "
  773. "of known hosts.", type, ip);
  774. } else if (options.visual_host_key) {
  775. fp = sshkey_fingerprint(host_key,
  776. options.fingerprint_hash, SSH_FP_DEFAULT);
  777. ra = sshkey_fingerprint(host_key,
  778. options.fingerprint_hash, SSH_FP_RANDOMART);
  779. if (fp == NULL || ra == NULL)
  780. fatal("%s: sshkey_fingerprint fail", __func__);
  781. logit("Host key fingerprint is %s\n%s", fp, ra);
  782. free(ra);
  783. free(fp);
  784. }
  785. hostkey_trusted = 1;
  786. break;
  787. case HOST_NEW:
  788. if (options.host_key_alias == NULL && port != 0 &&
  789. port != SSH_DEFAULT_PORT && !clobber_port) {
  790. debug("checking without port identifier");
  791. if (check_host_key(hostname, cinfo, hostaddr, 0,
  792. host_key, ROQUIET, 1,
  793. user_hostfiles, num_user_hostfiles,
  794. system_hostfiles, num_system_hostfiles) == 0) {
  795. debug("found matching key w/out port");
  796. break;
  797. }
  798. }
  799. if (readonly || want_cert)
  800. goto fail;
  801. /* The host is new. */
  802. if (options.strict_host_key_checking ==
  803. SSH_STRICT_HOSTKEY_YES) {
  804. /*
  805. * User has requested strict host key checking. We
  806. * will not add the host key automatically. The only
  807. * alternative left is to abort.
  808. */
  809. error("No %s host key is known for %.200s and you "
  810. "have requested strict checking.", type, host);
  811. goto fail;
  812. } else if (options.strict_host_key_checking ==
  813. SSH_STRICT_HOSTKEY_ASK) {
  814. char msg1[1024], msg2[1024];
  815. if (show_other_keys(host_hostkeys, host_key))
  816. snprintf(msg1, sizeof(msg1),
  817. "\nbut keys of different type are already"
  818. " known for this host.");
  819. else
  820. snprintf(msg1, sizeof(msg1), ".");
  821. /* The default */
  822. fp = sshkey_fingerprint(host_key,
  823. options.fingerprint_hash, SSH_FP_DEFAULT);
  824. ra = sshkey_fingerprint(host_key,
  825. options.fingerprint_hash, SSH_FP_RANDOMART);
  826. if (fp == NULL || ra == NULL)
  827. fatal("%s: sshkey_fingerprint fail", __func__);
  828. msg2[0] = '\0';
  829. if (options.verify_host_key_dns) {
  830. if (matching_host_key_dns)
  831. snprintf(msg2, sizeof(msg2),
  832. "Matching host key fingerprint"
  833. " found in DNS.\n");
  834. else
  835. snprintf(msg2, sizeof(msg2),
  836. "No matching host key fingerprint"
  837. " found in DNS.\n");
  838. }
  839. snprintf(msg, sizeof(msg),
  840. "The authenticity of host '%.200s (%s)' can't be "
  841. "established%s\n"
  842. "%s key fingerprint is %s.%s%s\n%s"
  843. "Are you sure you want to continue connecting "
  844. "(yes/no/[fingerprint])? ",
  845. host, ip, msg1, type, fp,
  846. options.visual_host_key ? "\n" : "",
  847. options.visual_host_key ? ra : "",
  848. msg2);
  849. free(ra);
  850. confirmed = confirm(msg, fp);
  851. free(fp);
  852. if (!confirmed)
  853. goto fail;
  854. hostkey_trusted = 1; /* user explicitly confirmed */
  855. }
  856. /*
  857. * If in "new" or "off" strict mode, add the key automatically
  858. * to the local known_hosts file.
  859. */
  860. if (options.check_host_ip && ip_status == HOST_NEW) {
  861. snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
  862. hostp = hostline;
  863. if (options.hash_known_hosts) {
  864. /* Add hash of host and IP separately */
  865. r = add_host_to_hostfile(user_hostfiles[0],
  866. host, host_key, options.hash_known_hosts) &&
  867. add_host_to_hostfile(user_hostfiles[0], ip,
  868. host_key, options.hash_known_hosts);
  869. } else {
  870. /* Add unhashed "host,ip" */
  871. r = add_host_to_hostfile(user_hostfiles[0],
  872. hostline, host_key,
  873. options.hash_known_hosts);
  874. }
  875. } else {
  876. r = add_host_to_hostfile(user_hostfiles[0], host,
  877. host_key, options.hash_known_hosts);
  878. hostp = host;
  879. }
  880. if (!r)
  881. logit("Failed to add the host to the list of known "
  882. "hosts (%.500s).", user_hostfiles[0]);
  883. else
  884. logit("Warning: Permanently added '%.200s' (%s) to the "
  885. "list of known hosts.", hostp, type);
  886. break;
  887. case HOST_REVOKED:
  888. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  889. error("@ WARNING: REVOKED HOST KEY DETECTED! @");
  890. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  891. error("The %s host key for %s is marked as revoked.", type, host);
  892. error("This could mean that a stolen key is being used to");
  893. error("impersonate this host.");
  894. /*
  895. * If strict host key checking is in use, the user will have
  896. * to edit the key manually and we can only abort.
  897. */
  898. if (options.strict_host_key_checking !=
  899. SSH_STRICT_HOSTKEY_OFF) {
  900. error("%s host key for %.200s was revoked and you have "
  901. "requested strict checking.", type, host);
  902. goto fail;
  903. }
  904. goto continue_unsafe;
  905. case HOST_CHANGED:
  906. if (want_cert) {
  907. /*
  908. * This is only a debug() since it is valid to have
  909. * CAs with wildcard DNS matches that don't match
  910. * all hosts that one might visit.
  911. */
  912. debug("Host certificate authority does not "
  913. "match %s in %s:%lu", CA_MARKER,
  914. host_found->file, host_found->line);
  915. goto fail;
  916. }
  917. if (readonly == ROQUIET)
  918. goto fail;
  919. if (options.check_host_ip && host_ip_differ) {
  920. char *key_msg;
  921. if (ip_status == HOST_NEW)
  922. key_msg = "is unknown";
  923. else if (ip_status == HOST_OK)
  924. key_msg = "is unchanged";
  925. else
  926. key_msg = "has a different value";
  927. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  928. error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
  929. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  930. error("The %s host key for %s has changed,", type, host);
  931. error("and the key for the corresponding IP address %s", ip);
  932. error("%s. This could either mean that", key_msg);
  933. error("DNS SPOOFING is happening or the IP address for the host");
  934. error("and its host key have changed at the same time.");
  935. if (ip_status != HOST_NEW) {
  936. error("Offending key for IP in %s:%lu",
  937. ip_found->file, ip_found->line);
  938. error(" remove with:");
  939. error(" ssh-keygen -f \"%s\" -R \"%s\"",
  940. ip_found->file, ip);
  941. }
  942. }
  943. /* The host key has changed. */
  944. warn_changed_key(host_key);
  945. error("Add correct host key in %.100s to get rid of this message.",
  946. user_hostfiles[0]);
  947. error("Offending %s key in %s:%lu",
  948. sshkey_type(host_found->key),
  949. host_found->file, host_found->line);
  950. error(" remove with:");
  951. error(" ssh-keygen -f \"%s\" -R \"%s\"",
  952. host_found->file, host);
  953. /*
  954. * If strict host key checking is in use, the user will have
  955. * to edit the key manually and we can only abort.
  956. */
  957. if (options.strict_host_key_checking !=
  958. SSH_STRICT_HOSTKEY_OFF) {
  959. error("Host key for %.200s has changed and you have "
  960. "requested strict checking.", host);
  961. goto fail;
  962. }
  963. continue_unsafe:
  964. /*
  965. * If strict host key checking has not been requested, allow
  966. * the connection but without MITM-able authentication or
  967. * forwarding.
  968. */
  969. if (options.password_authentication) {
  970. error("Password authentication is disabled to avoid "
  971. "man-in-the-middle attacks.");
  972. options.password_authentication = 0;
  973. cancelled_forwarding = 1;
  974. }
  975. if (options.kbd_interactive_authentication) {
  976. error("Keyboard-interactive authentication is disabled"
  977. " to avoid man-in-the-middle attacks.");
  978. options.kbd_interactive_authentication = 0;
  979. options.challenge_response_authentication = 0;
  980. cancelled_forwarding = 1;
  981. }
  982. if (options.challenge_response_authentication) {
  983. error("Challenge/response authentication is disabled"
  984. " to avoid man-in-the-middle attacks.");
  985. options.challenge_response_authentication = 0;
  986. cancelled_forwarding = 1;
  987. }
  988. if (options.forward_agent) {
  989. error("Agent forwarding is disabled to avoid "
  990. "man-in-the-middle attacks.");
  991. options.forward_agent = 0;
  992. cancelled_forwarding = 1;
  993. }
  994. if (options.forward_x11) {
  995. error("X11 forwarding is disabled to avoid "
  996. "man-in-the-middle attacks.");
  997. options.forward_x11 = 0;
  998. cancelled_forwarding = 1;
  999. }
  1000. if (options.num_local_forwards > 0 ||
  1001. options.num_remote_forwards > 0) {
  1002. error("Port forwarding is disabled to avoid "
  1003. "man-in-the-middle attacks.");
  1004. options.num_local_forwards =
  1005. options.num_remote_forwards = 0;
  1006. cancelled_forwarding = 1;
  1007. }
  1008. if (options.tun_open != SSH_TUNMODE_NO) {
  1009. error("Tunnel forwarding is disabled to avoid "
  1010. "man-in-the-middle attacks.");
  1011. options.tun_open = SSH_TUNMODE_NO;
  1012. cancelled_forwarding = 1;
  1013. }
  1014. if (options.update_hostkeys != 0) {
  1015. error("UpdateHostkeys is disabled because the host "
  1016. "key is not trusted.");
  1017. options.update_hostkeys = 0;
  1018. }
  1019. if (options.exit_on_forward_failure && cancelled_forwarding)
  1020. fatal("Error: forwarding disabled due to host key "
  1021. "check failure");
  1022. /*
  1023. * XXX Should permit the user to change to use the new id.
  1024. * This could be done by converting the host key to an
  1025. * identifying sentence, tell that the host identifies itself
  1026. * by that sentence, and ask the user if he/she wishes to
  1027. * accept the authentication.
  1028. */
  1029. break;
  1030. case HOST_FOUND:
  1031. fatal("internal error");
  1032. break;
  1033. }
  1034. if (options.check_host_ip && host_status != HOST_CHANGED &&
  1035. ip_status == HOST_CHANGED) {
  1036. snprintf(msg, sizeof(msg),
  1037. "Warning: the %s host key for '%.200s' "
  1038. "differs from the key for the IP address '%.128s'"
  1039. "\nOffending key for IP in %s:%lu",
  1040. type, host, ip, ip_found->file, ip_found->line);
  1041. if (host_status == HOST_OK) {
  1042. len = strlen(msg);
  1043. snprintf(msg + len, sizeof(msg) - len,
  1044. "\nMatching host key in %s:%lu",
  1045. host_found->file, host_found->line);
  1046. }
  1047. if (options.strict_host_key_checking ==
  1048. SSH_STRICT_HOSTKEY_ASK) {
  1049. strlcat(msg, "\nAre you sure you want "
  1050. "to continue connecting (yes/no)? ", sizeof(msg));
  1051. if (!confirm(msg, NULL))
  1052. goto fail;
  1053. } else if (options.strict_host_key_checking !=
  1054. SSH_STRICT_HOSTKEY_OFF) {
  1055. logit("%s", msg);
  1056. error("Exiting, you have requested strict checking.");
  1057. goto fail;
  1058. } else {
  1059. logit("%s", msg);
  1060. }
  1061. }
  1062. if (!hostkey_trusted && options.update_hostkeys) {
  1063. debug("%s: hostkey not known or explicitly trusted: "
  1064. "disabling UpdateHostkeys", __func__);
  1065. options.update_hostkeys = 0;
  1066. }
  1067. free(ip);
  1068. free(host);
  1069. if (host_hostkeys != NULL)
  1070. free_hostkeys(host_hostkeys);
  1071. if (ip_hostkeys != NULL)
  1072. free_hostkeys(ip_hostkeys);
  1073. return 0;
  1074. fail:
  1075. if (want_cert && host_status != HOST_REVOKED) {
  1076. /*
  1077. * No matching certificate. Downgrade cert to raw key and
  1078. * search normally.
  1079. */
  1080. debug("No matching CA found. Retry with plain key");
  1081. if ((r = sshkey_from_private(host_key, &raw_key)) != 0)
  1082. fatal("%s: sshkey_from_private: %s",
  1083. __func__, ssh_err(r));
  1084. if ((r = sshkey_drop_cert(raw_key)) != 0)
  1085. fatal("Couldn't drop certificate: %s", ssh_err(r));
  1086. host_key = raw_key;
  1087. goto retry;
  1088. }
  1089. sshkey_free(raw_key);
  1090. free(ip);
  1091. free(host);
  1092. if (host_hostkeys != NULL)
  1093. free_hostkeys(host_hostkeys);
  1094. if (ip_hostkeys != NULL)
  1095. free_hostkeys(ip_hostkeys);
  1096. return -1;
  1097. }
  1098. /* returns 0 if key verifies or -1 if key does NOT verify */
  1099. int
  1100. verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key,
  1101. const struct ssh_conn_info *cinfo)
  1102. {
  1103. u_int i;
  1104. int r = -1, flags = 0;
  1105. char valid[64], *fp = NULL, *cafp = NULL;
  1106. struct sshkey *plain = NULL;
  1107. if ((fp = sshkey_fingerprint(host_key,
  1108. options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
  1109. error("%s: fingerprint host key: %s", __func__, ssh_err(r));
  1110. r = -1;
  1111. goto out;
  1112. }
  1113. if (sshkey_is_cert(host_key)) {
  1114. if ((cafp = sshkey_fingerprint(host_key->cert->signature_key,
  1115. options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
  1116. error("%s: fingerprint CA key: %s",
  1117. __func__, ssh_err(r));
  1118. r = -1;
  1119. goto out;
  1120. }
  1121. sshkey_format_cert_validity(host_key->cert,
  1122. valid, sizeof(valid));
  1123. debug("Server host certificate: %s %s, serial %llu "
  1124. "ID \"%s\" CA %s %s valid %s",
  1125. sshkey_ssh_name(host_key), fp,
  1126. (unsigned long long)host_key->cert->serial,
  1127. host_key->cert->key_id,
  1128. sshkey_ssh_name(host_key->cert->signature_key), cafp,
  1129. valid);
  1130. for (i = 0; i < host_key->cert->nprincipals; i++) {
  1131. debug2("Server host certificate hostname: %s",
  1132. host_key->cert->principals[i]);
  1133. }
  1134. } else {
  1135. debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp);
  1136. }
  1137. if (sshkey_equal(previous_host_key, host_key)) {
  1138. debug2("%s: server host key %s %s matches cached key",
  1139. __func__, sshkey_type(host_key), fp);
  1140. r = 0;
  1141. goto out;
  1142. }
  1143. /* Check in RevokedHostKeys file if specified */
  1144. if (options.revoked_host_keys != NULL) {
  1145. r = sshkey_check_revoked(host_key, options.revoked_host_keys);
  1146. switch (r) {
  1147. case 0:
  1148. break; /* not revoked */
  1149. case SSH_ERR_KEY_REVOKED:
  1150. error("Host key %s %s revoked by file %s",
  1151. sshkey_type(host_key), fp,
  1152. options.revoked_host_keys);
  1153. r = -1;
  1154. goto out;
  1155. default:
  1156. error("Error checking host key %s %s in "
  1157. "revoked keys file %s: %s", sshkey_type(host_key),
  1158. fp, options.revoked_host_keys, ssh_err(r));
  1159. r = -1;
  1160. goto out;
  1161. }
  1162. }
  1163. if (options.verify_host_key_dns) {
  1164. /*
  1165. * XXX certs are not yet supported for DNS, so downgrade
  1166. * them and try the plain key.
  1167. */
  1168. flags = options.verify_host_key_dns;
  1169. if ((r = sshkey_from_private(host_key, &plain)) != 0)
  1170. goto out;
  1171. if (sshkey_is_cert(plain))
  1172. sshkey_drop_cert(plain);
  1173. if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) {
  1174. if (flags & DNS_VERIFY_FOUND) {
  1175. if (options.verify_host_key_dns == 1 &&
  1176. flags & DNS_VERIFY_MATCH &&
  1177. flags & DNS_VERIFY_SECURE) {
  1178. r = 0;
  1179. goto out;
  1180. }
  1181. if (flags & DNS_VERIFY_MATCH) {
  1182. matching_host_key_dns = 1;
  1183. } else {
  1184. warn_changed_key(plain);
  1185. error("Update the SSHFP RR in DNS "
  1186. "with the new host key to get rid "
  1187. "of this message.");
  1188. }
  1189. }
  1190. }
  1191. }
  1192. r = check_host_key(host, cinfo, hostaddr, options.port, host_key,
  1193. RDRW, 0, options.user_hostfiles, options.num_user_hostfiles,
  1194. options.system_hostfiles, options.num_system_hostfiles);
  1195. out:
  1196. sshkey_free(plain);
  1197. free(fp);
  1198. free(cafp);
  1199. if (r == 0 && host_key != NULL) {
  1200. sshkey_free(previous_host_key);
  1201. r = sshkey_from_private(host_key, &previous_host_key);
  1202. }
  1203. return r;
  1204. }
  1205. /*
  1206. * Starts a dialog with the server, and authenticates the current user on the
  1207. * server. This does not need any extra privileges. The basic connection
  1208. * to the server must already have been established before this is called.
  1209. * If login fails, this function prints an error and never returns.
  1210. * This function does not require super-user privileges.
  1211. */
  1212. void
  1213. ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
  1214. struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms,
  1215. const struct ssh_conn_info *cinfo)
  1216. {
  1217. char *host;
  1218. char *server_user, *local_user;
  1219. int r;
  1220. local_user = xstrdup(pw->pw_name);
  1221. server_user = options.user ? options.user : local_user;
  1222. /* Convert the user-supplied hostname into all lowercase. */
  1223. host = xstrdup(orighost);
  1224. lowercase(host);
  1225. /* Exchange protocol version identification strings with the server. */
  1226. if ((r = kex_exchange_identification(ssh, timeout_ms, NULL)) != 0)
  1227. sshpkt_fatal(ssh, r, "banner exchange");
  1228. /* Put the connection into non-blocking mode. */
  1229. ssh_packet_set_nonblocking(ssh);
  1230. /* key exchange */
  1231. /* authenticate user */
  1232. debug("Authenticating to %s:%d as '%s'", host, port, server_user);
  1233. ssh_kex2(ssh, host, hostaddr, port, cinfo);
  1234. ssh_userauth2(ssh, local_user, server_user, host, sensitive);
  1235. free(local_user);
  1236. free(host);
  1237. }
  1238. /* print all known host keys for a given host, but skip keys of given type */
  1239. static int
  1240. show_other_keys(struct hostkeys *hostkeys, struct sshkey *key)
  1241. {
  1242. int type[] = {
  1243. KEY_RSA,
  1244. KEY_DSA,
  1245. KEY_ECDSA,
  1246. KEY_ED25519,
  1247. KEY_XMSS,
  1248. -1
  1249. };
  1250. int i, ret = 0;
  1251. char *fp, *ra;
  1252. const struct hostkey_entry *found;
  1253. for (i = 0; type[i] != -1; i++) {
  1254. if (type[i] == key->type)
  1255. continue;
  1256. if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i],
  1257. -1, &found))
  1258. continue;
  1259. fp = sshkey_fingerprint(found->key,
  1260. options.fingerprint_hash, SSH_FP_DEFAULT);
  1261. ra = sshkey_fingerprint(found->key,
  1262. options.fingerprint_hash, SSH_FP_RANDOMART);
  1263. if (fp == NULL || ra == NULL)
  1264. fatal("%s: sshkey_fingerprint fail", __func__);
  1265. logit("WARNING: %s key found for host %s\n"
  1266. "in %s:%lu\n"
  1267. "%s key fingerprint %s.",
  1268. sshkey_type(found->key),
  1269. found->host, found->file, found->line,
  1270. sshkey_type(found->key), fp);
  1271. if (options.visual_host_key)
  1272. logit("%s", ra);
  1273. free(ra);
  1274. free(fp);
  1275. ret = 1;
  1276. }
  1277. return ret;
  1278. }
  1279. static void
  1280. warn_changed_key(struct sshkey *host_key)
  1281. {
  1282. char *fp;
  1283. fp = sshkey_fingerprint(host_key, options.fingerprint_hash,
  1284. SSH_FP_DEFAULT);
  1285. if (fp == NULL)
  1286. fatal("%s: sshkey_fingerprint fail", __func__);
  1287. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  1288. error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
  1289. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  1290. error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
  1291. error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
  1292. error("It is also possible that a host key has just been changed.");
  1293. error("The fingerprint for the %s key sent by the remote host is\n%s.",
  1294. sshkey_type(host_key), fp);
  1295. error("Please contact your system administrator.");
  1296. free(fp);
  1297. }
  1298. /*
  1299. * Execute a local command
  1300. */
  1301. int
  1302. ssh_local_cmd(const char *args)
  1303. {
  1304. char *shell;
  1305. pid_t pid;
  1306. int status;
  1307. void (*osighand)(int);
  1308. if (!options.permit_local_command ||
  1309. args == NULL || !*args)
  1310. return (1);
  1311. if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
  1312. shell = _PATH_BSHELL;
  1313. osighand = ssh_signal(SIGCHLD, SIG_DFL);
  1314. pid = fork();
  1315. if (pid == 0) {
  1316. ssh_signal(SIGPIPE, SIG_DFL);
  1317. debug3("Executing %s -c \"%s\"", shell, args);
  1318. execlp(shell, shell, "-c", args, (char *)NULL);
  1319. error("Couldn't execute %s -c \"%s\": %s",
  1320. shell, args, strerror(errno));
  1321. _exit(1);
  1322. } else if (pid == -1)
  1323. fatal("fork failed: %.100s", strerror(errno));
  1324. while (waitpid(pid, &status, 0) == -1)
  1325. if (errno != EINTR)
  1326. fatal("Couldn't wait for child: %s", strerror(errno));
  1327. ssh_signal(SIGCHLD, osighand);
  1328. if (!WIFEXITED(status))
  1329. return (1);
  1330. return (WEXITSTATUS(status));
  1331. }
  1332. void
  1333. maybe_add_key_to_agent(const char *authfile, struct sshkey *private,
  1334. const char *comment, const char *passphrase)
  1335. {
  1336. int auth_sock = -1, r;
  1337. const char *skprovider = NULL;
  1338. if (options.add_keys_to_agent == 0)
  1339. return;
  1340. if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
  1341. debug3("no authentication agent, not adding key");
  1342. return;
  1343. }
  1344. if (options.add_keys_to_agent == 2 &&
  1345. !ask_permission("Add key %s (%s) to agent?", authfile, comment)) {
  1346. debug3("user denied adding this key");
  1347. close(auth_sock);
  1348. return;
  1349. }
  1350. if (sshkey_is_sk(private))
  1351. skprovider = options.sk_provider;
  1352. if ((r = ssh_add_identity_constrained(auth_sock, private,
  1353. comment == NULL ? authfile : comment,
  1354. options.add_keys_to_agent_lifespan,
  1355. (options.add_keys_to_agent == 3), 0, skprovider)) == 0)
  1356. debug("identity added to agent: %s", authfile);
  1357. else
  1358. debug("could not add identity to agent: %s (%d)", authfile, r);
  1359. close(auth_sock);
  1360. }