]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/ssh-keyscan.c
Merge llvm-project main llvmorg-15-init-17485-ga3e38b4a206b
[FreeBSD/FreeBSD.git] / crypto / openssh / ssh-keyscan.c
1 /* $OpenBSD: ssh-keyscan.c,v 1.149 2022/12/26 19:16:03 jmc Exp $ */
2 /*
3  * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
4  *
5  * Modification and redistribution in source and binary forms is
6  * permitted provided that due credit is given to the author and the
7  * OpenBSD project by leaving this copyright notice intact.
8  */
9
10 #include "includes.h"
11  
12 #include <sys/types.h>
13 #include "openbsd-compat/sys-queue.h"
14 #include <sys/resource.h>
15 #ifdef HAVE_SYS_TIME_H
16 # include <sys/time.h>
17 #endif
18
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21
22 #ifdef WITH_OPENSSL
23 #include <openssl/bn.h>
24 #endif
25
26 #include <netdb.h>
27 #include <errno.h>
28 #ifdef HAVE_POLL_H
29 #include <poll.h>
30 #endif
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <signal.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include "xmalloc.h"
39 #include "ssh.h"
40 #include "sshbuf.h"
41 #include "sshkey.h"
42 #include "cipher.h"
43 #include "kex.h"
44 #include "compat.h"
45 #include "myproposal.h"
46 #include "packet.h"
47 #include "dispatch.h"
48 #include "log.h"
49 #include "atomicio.h"
50 #include "misc.h"
51 #include "hostfile.h"
52 #include "ssherr.h"
53 #include "ssh_api.h"
54 #include "dns.h"
55 #include "addr.h"
56
57 /* Flag indicating whether IPv4 or IPv6.  This can be set on the command line.
58    Default value is AF_UNSPEC means both IPv4 and IPv6. */
59 int IPv4or6 = AF_UNSPEC;
60
61 int ssh_port = SSH_DEFAULT_PORT;
62
63 #define KT_DSA          (1)
64 #define KT_RSA          (1<<1)
65 #define KT_ECDSA        (1<<2)
66 #define KT_ED25519      (1<<3)
67 #define KT_XMSS         (1<<4)
68 #define KT_ECDSA_SK     (1<<5)
69 #define KT_ED25519_SK   (1<<6)
70
71 #define KT_MIN          KT_DSA
72 #define KT_MAX          KT_ED25519_SK
73
74 int get_cert = 0;
75 int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK;
76
77 int hash_hosts = 0;             /* Hash hostname on output */
78
79 int print_sshfp = 0;            /* Print SSHFP records instead of known_hosts */
80
81 int found_one = 0;              /* Successfully found a key */
82
83 #define MAXMAXFD 256
84
85 /* The number of seconds after which to give up on a TCP connection */
86 int timeout = 5;
87
88 int maxfd;
89 #define MAXCON (maxfd - 10)
90
91 extern char *__progname;
92 struct pollfd *read_wait;
93 int ncon;
94
95 /*
96  * Keep a connection structure for each file descriptor.  The state
97  * associated with file descriptor n is held in fdcon[n].
98  */
99 typedef struct Connection {
100         u_char c_status;        /* State of connection on this file desc. */
101 #define CS_UNUSED 0             /* File descriptor unused */
102 #define CS_CON 1                /* Waiting to connect/read greeting */
103 #define CS_SIZE 2               /* Waiting to read initial packet size */
104 #define CS_KEYS 3               /* Waiting to read public key packet */
105         int c_fd;               /* Quick lookup: c->c_fd == c - fdcon */
106         int c_plen;             /* Packet length field for ssh packet */
107         int c_len;              /* Total bytes which must be read. */
108         int c_off;              /* Length of data read so far. */
109         int c_keytype;          /* Only one of KT_* */
110         sig_atomic_t c_done;    /* SSH2 done */
111         char *c_namebase;       /* Address to free for c_name and c_namelist */
112         char *c_name;           /* Hostname of connection for errors */
113         char *c_namelist;       /* Pointer to other possible addresses */
114         char *c_output_name;    /* Hostname of connection for output */
115         char *c_data;           /* Data read from this fd */
116         struct ssh *c_ssh;      /* SSH-connection */
117         struct timespec c_ts;   /* Time at which connection gets aborted */
118         TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */
119 } con;
120
121 TAILQ_HEAD(conlist, Connection) tq;     /* Timeout Queue */
122 con *fdcon;
123
124 static void keyprint(con *c, struct sshkey *key);
125
126 static int
127 fdlim_get(int hard)
128 {
129 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
130         struct rlimit rlfd;
131
132         if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1)
133                 return (-1);
134         if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY)
135                 return SSH_SYSFDMAX;
136         else
137                 return hard ? rlfd.rlim_max : rlfd.rlim_cur;
138 #else
139         return SSH_SYSFDMAX;
140 #endif
141 }
142
143 static int
144 fdlim_set(int lim)
145 {
146 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
147         struct rlimit rlfd;
148 #endif
149
150         if (lim <= 0)
151                 return (-1);
152 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
153         if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1)
154                 return (-1);
155         rlfd.rlim_cur = lim;
156         if (setrlimit(RLIMIT_NOFILE, &rlfd) == -1)
157                 return (-1);
158 #elif defined (HAVE_SETDTABLESIZE)
159         setdtablesize(lim);
160 #endif
161         return (0);
162 }
163
164 /*
165  * This is an strsep function that returns a null field for adjacent
166  * separators.  This is the same as the 4.4BSD strsep, but different from the
167  * one in the GNU libc.
168  */
169 static char *
170 xstrsep(char **str, const char *delim)
171 {
172         char *s, *e;
173
174         if (!**str)
175                 return (NULL);
176
177         s = *str;
178         e = s + strcspn(s, delim);
179
180         if (*e != '\0')
181                 *e++ = '\0';
182         *str = e;
183
184         return (s);
185 }
186
187 /*
188  * Get the next non-null token (like GNU strsep).  Strsep() will return a
189  * null token for two adjacent separators, so we may have to loop.
190  */
191 static char *
192 strnnsep(char **stringp, char *delim)
193 {
194         char *tok;
195
196         do {
197                 tok = xstrsep(stringp, delim);
198         } while (tok && *tok == '\0');
199         return (tok);
200 }
201
202
203 static int
204 key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh)
205 {
206         con *c;
207
208         if ((c = ssh_get_app_data(ssh)) != NULL)
209                 keyprint(c, hostkey);
210         /* always abort key exchange */
211         return -1;
212 }
213
214 static int
215 ssh2_capable(int remote_major, int remote_minor)
216 {
217         switch (remote_major) {
218         case 1:
219                 if (remote_minor == 99)
220                         return 1;
221                 break;
222         case 2:
223                 return 1;
224         default:
225                 break;
226         }
227         return 0;
228 }
229
230 static void
231 keygrab_ssh2(con *c)
232 {
233         char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
234         int r;
235
236         switch (c->c_keytype) {
237         case KT_DSA:
238                 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
239                     "ssh-dss-cert-v01@openssh.com" : "ssh-dss";
240                 break;
241         case KT_RSA:
242                 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
243                     "rsa-sha2-512-cert-v01@openssh.com,"
244                     "rsa-sha2-256-cert-v01@openssh.com,"
245                     "ssh-rsa-cert-v01@openssh.com" :
246                     "rsa-sha2-512,"
247                     "rsa-sha2-256,"
248                     "ssh-rsa";
249                 break;
250         case KT_ED25519:
251                 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
252                     "ssh-ed25519-cert-v01@openssh.com" : "ssh-ed25519";
253                 break;
254         case KT_XMSS:
255                 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
256                     "ssh-xmss-cert-v01@openssh.com" : "ssh-xmss@openssh.com";
257                 break;
258         case KT_ECDSA:
259                 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
260                     "ecdsa-sha2-nistp256-cert-v01@openssh.com,"
261                     "ecdsa-sha2-nistp384-cert-v01@openssh.com,"
262                     "ecdsa-sha2-nistp521-cert-v01@openssh.com" :
263                     "ecdsa-sha2-nistp256,"
264                     "ecdsa-sha2-nistp384,"
265                     "ecdsa-sha2-nistp521";
266                 break;
267         case KT_ECDSA_SK:
268                 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
269                     "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" :
270                     "sk-ecdsa-sha2-nistp256@openssh.com";
271                 break;
272         case KT_ED25519_SK:
273                 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
274                     "sk-ssh-ed25519-cert-v01@openssh.com" :
275                     "sk-ssh-ed25519@openssh.com";
276                 break;
277         default:
278                 fatal("unknown key type %d", c->c_keytype);
279                 break;
280         }
281         if ((r = kex_setup(c->c_ssh, myproposal)) != 0) {
282                 free(c->c_ssh);
283                 fprintf(stderr, "kex_setup: %s\n", ssh_err(r));
284                 exit(1);
285         }
286 #ifdef WITH_OPENSSL
287         c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
288         c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
289         c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
290         c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
291         c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
292         c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
293         c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
294 # ifdef OPENSSL_HAS_ECC
295         c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
296 # endif
297 #endif
298         c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
299         c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client;
300         ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper);
301         /*
302          * do the key-exchange until an error occurs or until
303          * the key_print_wrapper() callback sets c_done.
304          */
305         ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done);
306 }
307
308 static void
309 keyprint_one(const char *host, struct sshkey *key)
310 {
311         char *hostport = NULL, *hashed = NULL;
312         const char *known_host;
313
314         found_one = 1;
315
316         if (print_sshfp) {
317                 export_dns_rr(host, key, stdout, 0);
318                 return;
319         }
320
321         hostport = put_host_port(host, ssh_port);
322         lowercase(hostport);
323         if (hash_hosts && (hashed = host_hash(hostport, NULL, 0)) == NULL)
324                 fatal("host_hash failed");
325         known_host = hash_hosts ? hashed : hostport;
326         if (!get_cert)
327                 fprintf(stdout, "%s ", known_host);
328         sshkey_write(key, stdout);
329         fputs("\n", stdout);
330         free(hashed);
331         free(hostport);
332 }
333
334 static void
335 keyprint(con *c, struct sshkey *key)
336 {
337         char *hosts = c->c_output_name ? c->c_output_name : c->c_name;
338         char *host, *ohosts;
339
340         if (key == NULL)
341                 return;
342         if (get_cert || (!hash_hosts && ssh_port == SSH_DEFAULT_PORT)) {
343                 keyprint_one(hosts, key);
344                 return;
345         }
346         ohosts = hosts = xstrdup(hosts);
347         while ((host = strsep(&hosts, ",")) != NULL)
348                 keyprint_one(host, key);
349         free(ohosts);
350 }
351
352 static int
353 tcpconnect(char *host)
354 {
355         struct addrinfo hints, *ai, *aitop;
356         char strport[NI_MAXSERV];
357         int gaierr, s = -1;
358
359         snprintf(strport, sizeof strport, "%d", ssh_port);
360         memset(&hints, 0, sizeof(hints));
361         hints.ai_family = IPv4or6;
362         hints.ai_socktype = SOCK_STREAM;
363         if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
364                 error("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr));
365                 return -1;
366         }
367         for (ai = aitop; ai; ai = ai->ai_next) {
368                 s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
369                 if (s == -1) {
370                         error("socket: %s", strerror(errno));
371                         continue;
372                 }
373                 if (set_nonblock(s) == -1)
374                         fatal_f("set_nonblock(%d)", s);
375                 if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1 &&
376                     errno != EINPROGRESS)
377                         error("connect (`%s'): %s", host, strerror(errno));
378                 else
379                         break;
380                 close(s);
381                 s = -1;
382         }
383         freeaddrinfo(aitop);
384         return s;
385 }
386
387 static int
388 conalloc(const char *iname, const char *oname, int keytype)
389 {
390         char *namebase, *name, *namelist;
391         int s;
392
393         namebase = namelist = xstrdup(iname);
394
395         do {
396                 name = xstrsep(&namelist, ",");
397                 if (!name) {
398                         free(namebase);
399                         return (-1);
400                 }
401         } while ((s = tcpconnect(name)) < 0);
402
403         if (s >= maxfd)
404                 fatal("conalloc: fdno %d too high", s);
405         if (fdcon[s].c_status)
406                 fatal("conalloc: attempt to reuse fdno %d", s);
407
408         debug3_f("oname %s kt %d", oname, keytype);
409         fdcon[s].c_fd = s;
410         fdcon[s].c_status = CS_CON;
411         fdcon[s].c_namebase = namebase;
412         fdcon[s].c_name = name;
413         fdcon[s].c_namelist = namelist;
414         fdcon[s].c_output_name = xstrdup(oname);
415         fdcon[s].c_data = (char *) &fdcon[s].c_plen;
416         fdcon[s].c_len = 4;
417         fdcon[s].c_off = 0;
418         fdcon[s].c_keytype = keytype;
419         monotime_ts(&fdcon[s].c_ts);
420         fdcon[s].c_ts.tv_sec += timeout;
421         TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
422         read_wait[s].fd = s;
423         read_wait[s].events = POLLIN;
424         ncon++;
425         return (s);
426 }
427
428 static void
429 confree(int s)
430 {
431         if (s >= maxfd || fdcon[s].c_status == CS_UNUSED)
432                 fatal("confree: attempt to free bad fdno %d", s);
433         free(fdcon[s].c_namebase);
434         free(fdcon[s].c_output_name);
435         if (fdcon[s].c_status == CS_KEYS)
436                 free(fdcon[s].c_data);
437         fdcon[s].c_status = CS_UNUSED;
438         fdcon[s].c_keytype = 0;
439         if (fdcon[s].c_ssh) {
440                 ssh_packet_close(fdcon[s].c_ssh);
441                 free(fdcon[s].c_ssh);
442                 fdcon[s].c_ssh = NULL;
443         } else
444                 close(s);
445         TAILQ_REMOVE(&tq, &fdcon[s], c_link);
446         read_wait[s].fd = -1;
447         read_wait[s].events = 0;
448         ncon--;
449 }
450
451 static void
452 contouch(int s)
453 {
454         TAILQ_REMOVE(&tq, &fdcon[s], c_link);
455         monotime_ts(&fdcon[s].c_ts);
456         fdcon[s].c_ts.tv_sec += timeout;
457         TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
458 }
459
460 static int
461 conrecycle(int s)
462 {
463         con *c = &fdcon[s];
464         int ret;
465
466         ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype);
467         confree(s);
468         return (ret);
469 }
470
471 static void
472 congreet(int s)
473 {
474         int n = 0, remote_major = 0, remote_minor = 0;
475         char buf[256], *cp;
476         char remote_version[sizeof buf];
477         size_t bufsiz;
478         con *c = &fdcon[s];
479
480         /* send client banner */
481         n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n",
482             PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
483         if (n < 0 || (size_t)n >= sizeof(buf)) {
484                 error("snprintf: buffer too small");
485                 confree(s);
486                 return;
487         }
488         if (atomicio(vwrite, s, buf, n) != (size_t)n) {
489                 error("write (%s): %s", c->c_name, strerror(errno));
490                 confree(s);
491                 return;
492         }
493
494         /*
495          * Read the server banner as per RFC4253 section 4.2.  The "SSH-"
496          * protocol identification string may be preceeded by an arbitrarily
497          * large banner which we must read and ignore.  Loop while reading
498          * newline-terminated lines until we have one starting with "SSH-".
499          * The ID string cannot be longer than 255 characters although the
500          * preceeding banner lines may (in which case they'll be discarded
501          * in multiple iterations of the outer loop).
502          */
503         for (;;) {
504                 memset(buf, '\0', sizeof(buf));
505                 bufsiz = sizeof(buf);
506                 cp = buf;
507                 while (bufsiz-- &&
508                     (n = atomicio(read, s, cp, 1)) == 1 && *cp != '\n') {
509                         if (*cp == '\r')
510                                 *cp = '\n';
511                         cp++;
512                 }
513                 if (n != 1 || strncmp(buf, "SSH-", 4) == 0)
514                         break;
515         }
516         if (n == 0) {
517                 switch (errno) {
518                 case EPIPE:
519                         error("%s: Connection closed by remote host", c->c_name);
520                         break;
521                 case ECONNREFUSED:
522                         break;
523                 default:
524                         error("read (%s): %s", c->c_name, strerror(errno));
525                         break;
526                 }
527                 conrecycle(s);
528                 return;
529         }
530         if (cp >= buf + sizeof(buf)) {
531                 error("%s: greeting exceeds allowable length", c->c_name);
532                 confree(s);
533                 return;
534         }
535         if (*cp != '\n' && *cp != '\r') {
536                 error("%s: bad greeting", c->c_name);
537                 confree(s);
538                 return;
539         }
540         *cp = '\0';
541         if ((c->c_ssh = ssh_packet_set_connection(NULL, s, s)) == NULL)
542                 fatal("ssh_packet_set_connection failed");
543         ssh_packet_set_timeout(c->c_ssh, timeout, 1);
544         ssh_set_app_data(c->c_ssh, c);  /* back link */
545         c->c_ssh->compat = 0;
546         if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
547             &remote_major, &remote_minor, remote_version) == 3)
548                 compat_banner(c->c_ssh, remote_version);
549         if (!ssh2_capable(remote_major, remote_minor)) {
550                 debug("%s doesn't support ssh2", c->c_name);
551                 confree(s);
552                 return;
553         }
554         fprintf(stderr, "%c %s:%d %s\n", print_sshfp ? ';' : '#',
555             c->c_name, ssh_port, chop(buf));
556         keygrab_ssh2(c);
557         confree(s);
558 }
559
560 static void
561 conread(int s)
562 {
563         con *c = &fdcon[s];
564         size_t n;
565
566         if (c->c_status == CS_CON) {
567                 congreet(s);
568                 return;
569         }
570         n = atomicio(read, s, c->c_data + c->c_off, c->c_len - c->c_off);
571         if (n == 0) {
572                 error("read (%s): %s", c->c_name, strerror(errno));
573                 confree(s);
574                 return;
575         }
576         c->c_off += n;
577
578         if (c->c_off == c->c_len)
579                 switch (c->c_status) {
580                 case CS_SIZE:
581                         c->c_plen = htonl(c->c_plen);
582                         c->c_len = c->c_plen + 8 - (c->c_plen & 7);
583                         c->c_off = 0;
584                         c->c_data = xmalloc(c->c_len);
585                         c->c_status = CS_KEYS;
586                         break;
587                 default:
588                         fatal("conread: invalid status %d", c->c_status);
589                         break;
590                 }
591
592         contouch(s);
593 }
594
595 static void
596 conloop(void)
597 {
598         struct timespec seltime, now;
599         con *c;
600         int i;
601
602         monotime_ts(&now);
603         c = TAILQ_FIRST(&tq);
604
605         if (c && timespeccmp(&c->c_ts, &now, >))
606                 timespecsub(&c->c_ts, &now, &seltime);
607         else
608                 timespecclear(&seltime);
609
610         while (ppoll(read_wait, maxfd, &seltime, NULL) == -1) {
611                 if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)
612                         continue;
613                 error("poll error");
614         }
615
616         for (i = 0; i < maxfd; i++) {
617                 if (read_wait[i].revents & (POLLHUP|POLLERR|POLLNVAL))
618                         confree(i);
619                 else if (read_wait[i].revents & (POLLIN|POLLHUP))
620                         conread(i);
621         }
622
623         c = TAILQ_FIRST(&tq);
624         while (c && timespeccmp(&c->c_ts, &now, <)) {
625                 int s = c->c_fd;
626
627                 c = TAILQ_NEXT(c, c_link);
628                 conrecycle(s);
629         }
630 }
631
632 static void
633 do_one_host(char *host)
634 {
635         char *name = strnnsep(&host, " \t\n");
636         int j;
637
638         if (name == NULL)
639                 return;
640         for (j = KT_MIN; j <= KT_MAX; j *= 2) {
641                 if (get_keytypes & j) {
642                         while (ncon >= MAXCON)
643                                 conloop();
644                         conalloc(name, *host ? host : name, j);
645                 }
646         }
647 }
648
649 static void
650 do_host(char *host)
651 {
652         char daddr[128];
653         struct xaddr addr, end_addr;
654         u_int masklen;
655
656         if (host == NULL)
657                 return;
658         if (addr_pton_cidr(host, &addr, &masklen) != 0) {
659                 /* Assume argument is a hostname */
660                 do_one_host(host);
661         } else {
662                 /* Argument is a CIDR range */
663                 debug("CIDR range %s", host);
664                 end_addr = addr;
665                 if (addr_host_to_all1s(&end_addr, masklen) != 0)
666                         goto badaddr;
667                 /*
668                  * Note: we deliberately include the all-zero/ones addresses.
669                  */
670                 for (;;) {
671                         if (addr_ntop(&addr, daddr, sizeof(daddr)) != 0) {
672  badaddr:
673                                 error("Invalid address %s", host);
674                                 return;
675                         }
676                         debug("CIDR expand: address %s", daddr);
677                         do_one_host(daddr);
678                         if (addr_cmp(&addr, &end_addr) == 0)
679                                 break;
680                         addr_increment(&addr);
681                 };
682         }
683 }
684
685 void
686 sshfatal(const char *file, const char *func, int line, int showfunc,
687     LogLevel level, const char *suffix, const char *fmt, ...)
688 {
689         va_list args;
690
691         va_start(args, fmt);
692         sshlogv(file, func, line, showfunc, level, suffix, fmt, args);
693         va_end(args);
694         cleanup_exit(255);
695 }
696
697 static void
698 usage(void)
699 {
700         fprintf(stderr,
701             "usage: %s [-46cDHv] [-f file] [-p port] [-T timeout] [-t type]\n"
702             "\t\t   [host | addrlist namelist]\n",
703             __progname);
704         exit(1);
705 }
706
707 int
708 main(int argc, char **argv)
709 {
710         int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
711         int opt, fopt_count = 0, j;
712         char *tname, *cp, *line = NULL;
713         size_t linesize = 0;
714         FILE *fp;
715
716         extern int optind;
717         extern char *optarg;
718
719         __progname = ssh_get_progname(argv[0]);
720         seed_rng();
721         TAILQ_INIT(&tq);
722
723         /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
724         sanitise_stdfd();
725
726         if (argc <= 1)
727                 usage();
728
729         while ((opt = getopt(argc, argv, "cDHv46p:T:t:f:")) != -1) {
730                 switch (opt) {
731                 case 'H':
732                         hash_hosts = 1;
733                         break;
734                 case 'c':
735                         get_cert = 1;
736                         break;
737                 case 'D':
738                         print_sshfp = 1;
739                         break;
740                 case 'p':
741                         ssh_port = a2port(optarg);
742                         if (ssh_port <= 0) {
743                                 fprintf(stderr, "Bad port '%s'\n", optarg);
744                                 exit(1);
745                         }
746                         break;
747                 case 'T':
748                         timeout = convtime(optarg);
749                         if (timeout == -1 || timeout == 0) {
750                                 fprintf(stderr, "Bad timeout '%s'\n", optarg);
751                                 usage();
752                         }
753                         break;
754                 case 'v':
755                         if (!debug_flag) {
756                                 debug_flag = 1;
757                                 log_level = SYSLOG_LEVEL_DEBUG1;
758                         }
759                         else if (log_level < SYSLOG_LEVEL_DEBUG3)
760                                 log_level++;
761                         else
762                                 fatal("Too high debugging level.");
763                         break;
764                 case 'f':
765                         if (strcmp(optarg, "-") == 0)
766                                 optarg = NULL;
767                         argv[fopt_count++] = optarg;
768                         break;
769                 case 't':
770                         get_keytypes = 0;
771                         tname = strtok(optarg, ",");
772                         while (tname) {
773                                 int type = sshkey_type_from_name(tname);
774
775                                 switch (type) {
776                                 case KEY_DSA:
777                                         get_keytypes |= KT_DSA;
778                                         break;
779                                 case KEY_ECDSA:
780                                         get_keytypes |= KT_ECDSA;
781                                         break;
782                                 case KEY_RSA:
783                                         get_keytypes |= KT_RSA;
784                                         break;
785                                 case KEY_ED25519:
786                                         get_keytypes |= KT_ED25519;
787                                         break;
788                                 case KEY_XMSS:
789                                         get_keytypes |= KT_XMSS;
790                                         break;
791                                 case KEY_ED25519_SK:
792                                         get_keytypes |= KT_ED25519_SK;
793                                         break;
794                                 case KEY_ECDSA_SK:
795                                         get_keytypes |= KT_ECDSA_SK;
796                                         break;
797                                 case KEY_UNSPEC:
798                                 default:
799                                         fatal("Unknown key type \"%s\"", tname);
800                                 }
801                                 tname = strtok(NULL, ",");
802                         }
803                         break;
804                 case '4':
805                         IPv4or6 = AF_INET;
806                         break;
807                 case '6':
808                         IPv4or6 = AF_INET6;
809                         break;
810                 default:
811                         usage();
812                 }
813         }
814         if (optind == argc && !fopt_count)
815                 usage();
816
817         log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1);
818
819         maxfd = fdlim_get(1);
820         if (maxfd < 0)
821                 fatal("%s: fdlim_get: bad value", __progname);
822         if (maxfd > MAXMAXFD)
823                 maxfd = MAXMAXFD;
824         if (MAXCON <= 0)
825                 fatal("%s: not enough file descriptors", __progname);
826         if (maxfd > fdlim_get(0))
827                 fdlim_set(maxfd);
828         fdcon = xcalloc(maxfd, sizeof(con));
829         read_wait = xcalloc(maxfd, sizeof(struct pollfd));
830         for (j = 0; j < maxfd; j++)
831                 read_wait[j].fd = -1;
832
833         for (j = 0; j < fopt_count; j++) {
834                 if (argv[j] == NULL)
835                         fp = stdin;
836                 else if ((fp = fopen(argv[j], "r")) == NULL)
837                         fatal("%s: %s: %s", __progname, argv[j], strerror(errno));
838
839                 while (getline(&line, &linesize, fp) != -1) {
840                         /* Chomp off trailing whitespace and comments */
841                         if ((cp = strchr(line, '#')) == NULL)
842                                 cp = line + strlen(line) - 1;
843                         while (cp >= line) {
844                                 if (*cp == ' ' || *cp == '\t' ||
845                                     *cp == '\n' || *cp == '#')
846                                         *cp-- = '\0';
847                                 else
848                                         break;
849                         }
850
851                         /* Skip empty lines */
852                         if (*line == '\0')
853                                 continue;
854
855                         do_host(line);
856                 }
857
858                 if (ferror(fp))
859                         fatal("%s: %s: %s", __progname, argv[j], strerror(errno));
860
861                 fclose(fp);
862         }
863         free(line);
864
865         while (optind < argc)
866                 do_host(argv[optind++]);
867
868         while (ncon > 0)
869                 conloop();
870
871         return found_one ? 0 : 1;
872 }