HAMMER - Fix reblocking operation of volume removal
[dragonfly.git] / crypto / openssh / ssh-keyscan.c
1 /* $OpenBSD: ssh-keyscan.c,v 1.78 2009/01/22 10:02:34 djm 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 "openbsd-compat/sys-queue.h"
13 #include <sys/resource.h>
14 #ifdef HAVE_SYS_TIME_H
15 # include <sys/time.h>
16 #endif
17
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20
21 #include <openssl/bn.h>
22
23 #include <netdb.h>
24 #include <errno.h>
25 #include <setjmp.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <signal.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "xmalloc.h"
34 #include "ssh.h"
35 #include "ssh1.h"
36 #include "buffer.h"
37 #include "key.h"
38 #include "cipher.h"
39 #include "kex.h"
40 #include "compat.h"
41 #include "myproposal.h"
42 #include "packet.h"
43 #include "dispatch.h"
44 #include "log.h"
45 #include "atomicio.h"
46 #include "misc.h"
47 #include "hostfile.h"
48
49 /* Flag indicating whether IPv4 or IPv6.  This can be set on the command line.
50    Default value is AF_UNSPEC means both IPv4 and IPv6. */
51 int IPv4or6 = AF_UNSPEC;
52
53 int ssh_port = SSH_DEFAULT_PORT;
54
55 #define KT_RSA1 1
56 #define KT_DSA  2
57 #define KT_RSA  4
58
59 int get_keytypes = KT_RSA;      /* Get only RSA keys by default */
60
61 int hash_hosts = 0;             /* Hash hostname on output */
62
63 #define MAXMAXFD 256
64
65 /* The number of seconds after which to give up on a TCP connection */
66 int timeout = 5;
67
68 int maxfd;
69 #define MAXCON (maxfd - 10)
70
71 extern char *__progname;
72 fd_set *read_wait;
73 size_t read_wait_nfdset;
74 int ncon;
75 int nonfatal_fatal = 0;
76 jmp_buf kexjmp;
77 Key *kexjmp_key;
78
79 /*
80  * Keep a connection structure for each file descriptor.  The state
81  * associated with file descriptor n is held in fdcon[n].
82  */
83 typedef struct Connection {
84         u_char c_status;        /* State of connection on this file desc. */
85 #define CS_UNUSED 0             /* File descriptor unused */
86 #define CS_CON 1                /* Waiting to connect/read greeting */
87 #define CS_SIZE 2               /* Waiting to read initial packet size */
88 #define CS_KEYS 3               /* Waiting to read public key packet */
89         int c_fd;               /* Quick lookup: c->c_fd == c - fdcon */
90         int c_plen;             /* Packet length field for ssh packet */
91         int c_len;              /* Total bytes which must be read. */
92         int c_off;              /* Length of data read so far. */
93         int c_keytype;          /* Only one of KT_RSA1, KT_DSA, or KT_RSA */
94         char *c_namebase;       /* Address to free for c_name and c_namelist */
95         char *c_name;           /* Hostname of connection for errors */
96         char *c_namelist;       /* Pointer to other possible addresses */
97         char *c_output_name;    /* Hostname of connection for output */
98         char *c_data;           /* Data read from this fd */
99         Kex *c_kex;             /* The key-exchange struct for ssh2 */
100         struct timeval c_tv;    /* Time at which connection gets aborted */
101         TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */
102 } con;
103
104 TAILQ_HEAD(conlist, Connection) tq;     /* Timeout Queue */
105 con *fdcon;
106
107 /*
108  *  This is just a wrapper around fgets() to make it usable.
109  */
110
111 /* Stress-test.  Increase this later. */
112 #define LINEBUF_SIZE 16
113
114 typedef struct {
115         char *buf;
116         u_int size;
117         int lineno;
118         const char *filename;
119         FILE *stream;
120         void (*errfun) (const char *,...);
121 } Linebuf;
122
123 static Linebuf *
124 Linebuf_alloc(const char *filename, void (*errfun) (const char *,...))
125 {
126         Linebuf *lb;
127
128         if (!(lb = malloc(sizeof(*lb)))) {
129                 if (errfun)
130                         (*errfun) ("linebuf (%s): malloc failed\n",
131                             filename ? filename : "(stdin)");
132                 return (NULL);
133         }
134         if (filename) {
135                 lb->filename = filename;
136                 if (!(lb->stream = fopen(filename, "r"))) {
137                         xfree(lb);
138                         if (errfun)
139                                 (*errfun) ("%s: %s\n", filename, strerror(errno));
140                         return (NULL);
141                 }
142         } else {
143                 lb->filename = "(stdin)";
144                 lb->stream = stdin;
145         }
146
147         if (!(lb->buf = malloc((lb->size = LINEBUF_SIZE)))) {
148                 if (errfun)
149                         (*errfun) ("linebuf (%s): malloc failed\n", lb->filename);
150                 xfree(lb);
151                 return (NULL);
152         }
153         lb->errfun = errfun;
154         lb->lineno = 0;
155         return (lb);
156 }
157
158 static void
159 Linebuf_free(Linebuf * lb)
160 {
161         fclose(lb->stream);
162         xfree(lb->buf);
163         xfree(lb);
164 }
165
166 #if 0
167 static void
168 Linebuf_restart(Linebuf * lb)
169 {
170         clearerr(lb->stream);
171         rewind(lb->stream);
172         lb->lineno = 0;
173 }
174
175 static int
176 Linebuf_lineno(Linebuf * lb)
177 {
178         return (lb->lineno);
179 }
180 #endif
181
182 static char *
183 Linebuf_getline(Linebuf * lb)
184 {
185         size_t n = 0;
186         void *p;
187
188         lb->lineno++;
189         for (;;) {
190                 /* Read a line */
191                 if (!fgets(&lb->buf[n], lb->size - n, lb->stream)) {
192                         if (ferror(lb->stream) && lb->errfun)
193                                 (*lb->errfun)("%s: %s\n", lb->filename,
194                                     strerror(errno));
195                         return (NULL);
196                 }
197                 n = strlen(lb->buf);
198
199                 /* Return it or an error if it fits */
200                 if (n > 0 && lb->buf[n - 1] == '\n') {
201                         lb->buf[n - 1] = '\0';
202                         return (lb->buf);
203                 }
204                 if (n != lb->size - 1) {
205                         if (lb->errfun)
206                                 (*lb->errfun)("%s: skipping incomplete last line\n",
207                                     lb->filename);
208                         return (NULL);
209                 }
210                 /* Double the buffer if we need more space */
211                 lb->size *= 2;
212                 if ((p = realloc(lb->buf, lb->size)) == NULL) {
213                         lb->size /= 2;
214                         if (lb->errfun)
215                                 (*lb->errfun)("linebuf (%s): realloc failed\n",
216                                     lb->filename);
217                         return (NULL);
218                 }
219                 lb->buf = p;
220         }
221 }
222
223 static int
224 fdlim_get(int hard)
225 {
226 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
227         struct rlimit rlfd;
228
229         if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
230                 return (-1);
231         if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY)
232                 return SSH_SYSFDMAX;
233         else
234                 return hard ? rlfd.rlim_max : rlfd.rlim_cur;
235 #else
236         return SSH_SYSFDMAX;
237 #endif
238 }
239
240 static int
241 fdlim_set(int lim)
242 {
243 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
244         struct rlimit rlfd;
245 #endif
246
247         if (lim <= 0)
248                 return (-1);
249 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
250         if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
251                 return (-1);
252         rlfd.rlim_cur = lim;
253         if (setrlimit(RLIMIT_NOFILE, &rlfd) < 0)
254                 return (-1);
255 #elif defined (HAVE_SETDTABLESIZE)
256         setdtablesize(lim);
257 #endif
258         return (0);
259 }
260
261 /*
262  * This is an strsep function that returns a null field for adjacent
263  * separators.  This is the same as the 4.4BSD strsep, but different from the
264  * one in the GNU libc.
265  */
266 static char *
267 xstrsep(char **str, const char *delim)
268 {
269         char *s, *e;
270
271         if (!**str)
272                 return (NULL);
273
274         s = *str;
275         e = s + strcspn(s, delim);
276
277         if (*e != '\0')
278                 *e++ = '\0';
279         *str = e;
280
281         return (s);
282 }
283
284 /*
285  * Get the next non-null token (like GNU strsep).  Strsep() will return a
286  * null token for two adjacent separators, so we may have to loop.
287  */
288 static char *
289 strnnsep(char **stringp, char *delim)
290 {
291         char *tok;
292
293         do {
294                 tok = xstrsep(stringp, delim);
295         } while (tok && *tok == '\0');
296         return (tok);
297 }
298
299 static Key *
300 keygrab_ssh1(con *c)
301 {
302         static Key *rsa;
303         static Buffer msg;
304
305         if (rsa == NULL) {
306                 buffer_init(&msg);
307                 rsa = key_new(KEY_RSA1);
308         }
309         buffer_append(&msg, c->c_data, c->c_plen);
310         buffer_consume(&msg, 8 - (c->c_plen & 7));      /* padding */
311         if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) {
312                 error("%s: invalid packet type", c->c_name);
313                 buffer_clear(&msg);
314                 return NULL;
315         }
316         buffer_consume(&msg, 8);                /* cookie */
317
318         /* server key */
319         (void) buffer_get_int(&msg);
320         buffer_get_bignum(&msg, rsa->rsa->e);
321         buffer_get_bignum(&msg, rsa->rsa->n);
322
323         /* host key */
324         (void) buffer_get_int(&msg);
325         buffer_get_bignum(&msg, rsa->rsa->e);
326         buffer_get_bignum(&msg, rsa->rsa->n);
327
328         buffer_clear(&msg);
329
330         return (rsa);
331 }
332
333 static int
334 hostjump(Key *hostkey)
335 {
336         kexjmp_key = hostkey;
337         longjmp(kexjmp, 1);
338 }
339
340 static int
341 ssh2_capable(int remote_major, int remote_minor)
342 {
343         switch (remote_major) {
344         case 1:
345                 if (remote_minor == 99)
346                         return 1;
347                 break;
348         case 2:
349                 return 1;
350         default:
351                 break;
352         }
353         return 0;
354 }
355
356 static Key *
357 keygrab_ssh2(con *c)
358 {
359         int j;
360
361         packet_set_connection(c->c_fd, c->c_fd);
362         enable_compat20();
363         myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA?
364             "ssh-dss": "ssh-rsa";
365         c->c_kex = kex_setup(myproposal);
366         c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
367         c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
368         c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
369         c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
370         c->c_kex->verify_host_key = hostjump;
371
372         if (!(j = setjmp(kexjmp))) {
373                 nonfatal_fatal = 1;
374                 dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, c->c_kex);
375                 fprintf(stderr, "Impossible! dispatch_run() returned!\n");
376                 exit(1);
377         }
378         nonfatal_fatal = 0;
379         xfree(c->c_kex);
380         c->c_kex = NULL;
381         packet_close();
382
383         return j < 0? NULL : kexjmp_key;
384 }
385
386 static void
387 keyprint(con *c, Key *key)
388 {
389         char *host = c->c_output_name ? c->c_output_name : c->c_name;
390
391         if (!key)
392                 return;
393         if (hash_hosts && (host = host_hash(host, NULL, 0)) == NULL)
394                 fatal("host_hash failed");
395
396         fprintf(stdout, "%s ", host);
397         key_write(key, stdout);
398         fputs("\n", stdout);
399 }
400
401 static int
402 tcpconnect(char *host)
403 {
404         struct addrinfo hints, *ai, *aitop;
405         char strport[NI_MAXSERV];
406         int gaierr, s = -1;
407
408         snprintf(strport, sizeof strport, "%d", ssh_port);
409         memset(&hints, 0, sizeof(hints));
410         hints.ai_family = IPv4or6;
411         hints.ai_socktype = SOCK_STREAM;
412         if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
413                 fatal("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr));
414         for (ai = aitop; ai; ai = ai->ai_next) {
415                 s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
416                 if (s < 0) {
417                         error("socket: %s", strerror(errno));
418                         continue;
419                 }
420                 if (set_nonblock(s) == -1)
421                         fatal("%s: set_nonblock(%d)", __func__, s);
422                 if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0 &&
423                     errno != EINPROGRESS)
424                         error("connect (`%s'): %s", host, strerror(errno));
425                 else
426                         break;
427                 close(s);
428                 s = -1;
429         }
430         freeaddrinfo(aitop);
431         return s;
432 }
433
434 static int
435 conalloc(char *iname, char *oname, int keytype)
436 {
437         char *namebase, *name, *namelist;
438         int s;
439
440         namebase = namelist = xstrdup(iname);
441
442         do {
443                 name = xstrsep(&namelist, ",");
444                 if (!name) {
445                         xfree(namebase);
446                         return (-1);
447                 }
448         } while ((s = tcpconnect(name)) < 0);
449
450         if (s >= maxfd)
451                 fatal("conalloc: fdno %d too high", s);
452         if (fdcon[s].c_status)
453                 fatal("conalloc: attempt to reuse fdno %d", s);
454
455         fdcon[s].c_fd = s;
456         fdcon[s].c_status = CS_CON;
457         fdcon[s].c_namebase = namebase;
458         fdcon[s].c_name = name;
459         fdcon[s].c_namelist = namelist;
460         fdcon[s].c_output_name = xstrdup(oname);
461         fdcon[s].c_data = (char *) &fdcon[s].c_plen;
462         fdcon[s].c_len = 4;
463         fdcon[s].c_off = 0;
464         fdcon[s].c_keytype = keytype;
465         gettimeofday(&fdcon[s].c_tv, NULL);
466         fdcon[s].c_tv.tv_sec += timeout;
467         TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
468         FD_SET(s, read_wait);
469         ncon++;
470         return (s);
471 }
472
473 static void
474 confree(int s)
475 {
476         if (s >= maxfd || fdcon[s].c_status == CS_UNUSED)
477                 fatal("confree: attempt to free bad fdno %d", s);
478         close(s);
479         xfree(fdcon[s].c_namebase);
480         xfree(fdcon[s].c_output_name);
481         if (fdcon[s].c_status == CS_KEYS)
482                 xfree(fdcon[s].c_data);
483         fdcon[s].c_status = CS_UNUSED;
484         fdcon[s].c_keytype = 0;
485         TAILQ_REMOVE(&tq, &fdcon[s], c_link);
486         FD_CLR(s, read_wait);
487         ncon--;
488 }
489
490 static void
491 contouch(int s)
492 {
493         TAILQ_REMOVE(&tq, &fdcon[s], c_link);
494         gettimeofday(&fdcon[s].c_tv, NULL);
495         fdcon[s].c_tv.tv_sec += timeout;
496         TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
497 }
498
499 static int
500 conrecycle(int s)
501 {
502         con *c = &fdcon[s];
503         int ret;
504
505         ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype);
506         confree(s);
507         return (ret);
508 }
509
510 static void
511 congreet(int s)
512 {
513         int n = 0, remote_major = 0, remote_minor = 0;
514         char buf[256], *cp;
515         char remote_version[sizeof buf];
516         size_t bufsiz;
517         con *c = &fdcon[s];
518
519         for (;;) {
520                 memset(buf, '\0', sizeof(buf));
521                 bufsiz = sizeof(buf);
522                 cp = buf;
523                 while (bufsiz-- &&
524                     (n = atomicio(read, s, cp, 1)) == 1 && *cp != '\n') {
525                         if (*cp == '\r')
526                                 *cp = '\n';
527                         cp++;
528                 }
529                 if (n != 1 || strncmp(buf, "SSH-", 4) == 0)
530                         break;
531         }
532         if (n == 0) {
533                 switch (errno) {
534                 case EPIPE:
535                         error("%s: Connection closed by remote host", c->c_name);
536                         break;
537                 case ECONNREFUSED:
538                         break;
539                 default:
540                         error("read (%s): %s", c->c_name, strerror(errno));
541                         break;
542                 }
543                 conrecycle(s);
544                 return;
545         }
546         if (*cp != '\n' && *cp != '\r') {
547                 error("%s: bad greeting", c->c_name);
548                 confree(s);
549                 return;
550         }
551         *cp = '\0';
552         if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
553             &remote_major, &remote_minor, remote_version) == 3)
554                 compat_datafellows(remote_version);
555         else
556                 datafellows = 0;
557         if (c->c_keytype != KT_RSA1) {
558                 if (!ssh2_capable(remote_major, remote_minor)) {
559                         debug("%s doesn't support ssh2", c->c_name);
560                         confree(s);
561                         return;
562                 }
563         } else if (remote_major != 1) {
564                 debug("%s doesn't support ssh1", c->c_name);
565                 confree(s);
566                 return;
567         }
568         fprintf(stderr, "# %s %s\n", c->c_name, chop(buf));
569         n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n",
570             c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2,
571             c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2);
572         if (n < 0 || (size_t)n >= sizeof(buf)) {
573                 error("snprintf: buffer too small");
574                 confree(s);
575                 return;
576         }
577         if (atomicio(vwrite, s, buf, n) != (size_t)n) {
578                 error("write (%s): %s", c->c_name, strerror(errno));
579                 confree(s);
580                 return;
581         }
582         if (c->c_keytype != KT_RSA1) {
583                 keyprint(c, keygrab_ssh2(c));
584                 confree(s);
585                 return;
586         }
587         c->c_status = CS_SIZE;
588         contouch(s);
589 }
590
591 static void
592 conread(int s)
593 {
594         con *c = &fdcon[s];
595         size_t n;
596
597         if (c->c_status == CS_CON) {
598                 congreet(s);
599                 return;
600         }
601         n = atomicio(read, s, c->c_data + c->c_off, c->c_len - c->c_off);
602         if (n == 0) {
603                 error("read (%s): %s", c->c_name, strerror(errno));
604                 confree(s);
605                 return;
606         }
607         c->c_off += n;
608
609         if (c->c_off == c->c_len)
610                 switch (c->c_status) {
611                 case CS_SIZE:
612                         c->c_plen = htonl(c->c_plen);
613                         c->c_len = c->c_plen + 8 - (c->c_plen & 7);
614                         c->c_off = 0;
615                         c->c_data = xmalloc(c->c_len);
616                         c->c_status = CS_KEYS;
617                         break;
618                 case CS_KEYS:
619                         keyprint(c, keygrab_ssh1(c));
620                         confree(s);
621                         return;
622                 default:
623                         fatal("conread: invalid status %d", c->c_status);
624                         break;
625                 }
626
627         contouch(s);
628 }
629
630 static void
631 conloop(void)
632 {
633         struct timeval seltime, now;
634         fd_set *r, *e;
635         con *c;
636         int i;
637
638         gettimeofday(&now, NULL);
639         c = TAILQ_FIRST(&tq);
640
641         if (c && (c->c_tv.tv_sec > now.tv_sec ||
642             (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) {
643                 seltime = c->c_tv;
644                 seltime.tv_sec -= now.tv_sec;
645                 seltime.tv_usec -= now.tv_usec;
646                 if (seltime.tv_usec < 0) {
647                         seltime.tv_usec += 1000000;
648                         seltime.tv_sec--;
649                 }
650         } else
651                 seltime.tv_sec = seltime.tv_usec = 0;
652
653         r = xcalloc(read_wait_nfdset, sizeof(fd_mask));
654         e = xcalloc(read_wait_nfdset, sizeof(fd_mask));
655         memcpy(r, read_wait, read_wait_nfdset * sizeof(fd_mask));
656         memcpy(e, read_wait, read_wait_nfdset * sizeof(fd_mask));
657
658         while (select(maxfd, r, NULL, e, &seltime) == -1 &&
659             (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
660                 ;
661
662         for (i = 0; i < maxfd; i++) {
663                 if (FD_ISSET(i, e)) {
664                         error("%s: exception!", fdcon[i].c_name);
665                         confree(i);
666                 } else if (FD_ISSET(i, r))
667                         conread(i);
668         }
669         xfree(r);
670         xfree(e);
671
672         c = TAILQ_FIRST(&tq);
673         while (c && (c->c_tv.tv_sec < now.tv_sec ||
674             (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) {
675                 int s = c->c_fd;
676
677                 c = TAILQ_NEXT(c, c_link);
678                 conrecycle(s);
679         }
680 }
681
682 static void
683 do_host(char *host)
684 {
685         char *name = strnnsep(&host, " \t\n");
686         int j;
687
688         if (name == NULL)
689                 return;
690         for (j = KT_RSA1; j <= KT_RSA; j *= 2) {
691                 if (get_keytypes & j) {
692                         while (ncon >= MAXCON)
693                                 conloop();
694                         conalloc(name, *host ? host : name, j);
695                 }
696         }
697 }
698
699 void
700 fatal(const char *fmt,...)
701 {
702         va_list args;
703
704         va_start(args, fmt);
705         do_log(SYSLOG_LEVEL_FATAL, fmt, args);
706         va_end(args);
707         if (nonfatal_fatal)
708                 longjmp(kexjmp, -1);
709         else
710                 exit(255);
711 }
712
713 static void
714 usage(void)
715 {
716         fprintf(stderr,
717             "usage: %s [-46Hv] [-f file] [-p port] [-T timeout] [-t type]\n"
718             "\t\t   [host | addrlist namelist] ...\n",
719             __progname);
720         exit(1);
721 }
722
723 int
724 main(int argc, char **argv)
725 {
726         int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
727         int opt, fopt_count = 0;
728         char *tname;
729
730         extern int optind;
731         extern char *optarg;
732
733         __progname = ssh_get_progname(argv[0]);
734         init_rng();
735         seed_rng();
736         TAILQ_INIT(&tq);
737
738         /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
739         sanitise_stdfd();
740
741         if (argc <= 1)
742                 usage();
743
744         while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) {
745                 switch (opt) {
746                 case 'H':
747                         hash_hosts = 1;
748                         break;
749                 case 'p':
750                         ssh_port = a2port(optarg);
751                         if (ssh_port <= 0) {
752                                 fprintf(stderr, "Bad port '%s'\n", optarg);
753                                 exit(1);
754                         }
755                         break;
756                 case 'T':
757                         timeout = convtime(optarg);
758                         if (timeout == -1 || timeout == 0) {
759                                 fprintf(stderr, "Bad timeout '%s'\n", optarg);
760                                 usage();
761                         }
762                         break;
763                 case 'v':
764                         if (!debug_flag) {
765                                 debug_flag = 1;
766                                 log_level = SYSLOG_LEVEL_DEBUG1;
767                         }
768                         else if (log_level < SYSLOG_LEVEL_DEBUG3)
769                                 log_level++;
770                         else
771                                 fatal("Too high debugging level.");
772                         break;
773                 case 'f':
774                         if (strcmp(optarg, "-") == 0)
775                                 optarg = NULL;
776                         argv[fopt_count++] = optarg;
777                         break;
778                 case 't':
779                         get_keytypes = 0;
780                         tname = strtok(optarg, ",");
781                         while (tname) {
782                                 int type = key_type_from_name(tname);
783                                 switch (type) {
784                                 case KEY_RSA1:
785                                         get_keytypes |= KT_RSA1;
786                                         break;
787                                 case KEY_DSA:
788                                         get_keytypes |= KT_DSA;
789                                         break;
790                                 case KEY_RSA:
791                                         get_keytypes |= KT_RSA;
792                                         break;
793                                 case KEY_UNSPEC:
794                                         fatal("unknown key type %s", tname);
795                                 }
796                                 tname = strtok(NULL, ",");
797                         }
798                         break;
799                 case '4':
800                         IPv4or6 = AF_INET;
801                         break;
802                 case '6':
803                         IPv4or6 = AF_INET6;
804                         break;
805                 case '?':
806                 default:
807                         usage();
808                 }
809         }
810         if (optind == argc && !fopt_count)
811                 usage();
812
813         log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1);
814
815         maxfd = fdlim_get(1);
816         if (maxfd < 0)
817                 fatal("%s: fdlim_get: bad value", __progname);
818         if (maxfd > MAXMAXFD)
819                 maxfd = MAXMAXFD;
820         if (MAXCON <= 0)
821                 fatal("%s: not enough file descriptors", __progname);
822         if (maxfd > fdlim_get(0))
823                 fdlim_set(maxfd);
824         fdcon = xcalloc(maxfd, sizeof(con));
825
826         read_wait_nfdset = howmany(maxfd, NFDBITS);
827         read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));
828
829         if (fopt_count) {
830                 Linebuf *lb;
831                 char *line;
832                 int j;
833
834                 for (j = 0; j < fopt_count; j++) {
835                         lb = Linebuf_alloc(argv[j], error);
836                         if (!lb)
837                                 continue;
838                         while ((line = Linebuf_getline(lb)) != NULL)
839                                 do_host(line);
840                         Linebuf_free(lb);
841                 }
842         }
843
844         while (optind < argc)
845                 do_host(argv[optind++]);
846
847         while (ncon > 0)
848                 conloop();
849
850         return (0);
851 }