X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/eea39c0272a730e084139c86449282fb2f03fa60..da89cf4dea90eaed324c80b9062f1eed13acd107:/ssh-keyscan.c diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 5d5427aa..3f6c2313 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -8,44 +8,45 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-keyscan.c,v 1.7 2001/01/08 22:03:23 markus Exp $"); +RCSID("$OpenBSD: ssh-keyscan.c,v 1.22 2001/03/06 06:11:18 deraadt Exp $"); -#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) +#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) #include #else -#include "bsd-queue.h" +#include "openbsd-compat/fake-queue.h" #endif #include #include -#include -#include #include "xmalloc.h" #include "ssh.h" +#include "ssh1.h" #include "key.h" #include "buffer.h" #include "bufaux.h" +#include "log.h" +#include "atomicio.h" static int argno = 1; /* Number of argument currently being parsed */ int family = AF_UNSPEC; /* IPv4, IPv6 or both */ -#define PORT 22 #define MAXMAXFD 256 /* The number of seconds after which to give up on a TCP connection */ int timeout = 5; int maxfd; -#define maxcon (maxfd - 10) +#define MAXCON (maxfd - 10) #ifdef HAVE___PROGNAME extern char *__progname; #else char *__progname; #endif -fd_set read_wait; +fd_set *read_wait; +size_t read_wait_size; int ncon; /* @@ -90,7 +91,7 @@ typedef struct { void (*errfun) (const char *,...); } Linebuf; -static inline Linebuf * +Linebuf * Linebuf_alloc(const char *filename, void (*errfun) (const char *,...)) { Linebuf *lb; @@ -103,7 +104,7 @@ Linebuf_alloc(const char *filename, void (*errfun) (const char *,...)) if (filename) { lb->filename = filename; if (!(lb->stream = fopen(filename, "r"))) { - free(lb); + xfree(lb); if (errfun) (*errfun) ("%s: %s\n", filename, strerror(errno)); return (NULL); @@ -116,7 +117,7 @@ Linebuf_alloc(const char *filename, void (*errfun) (const char *,...)) if (!(lb->buf = malloc(lb->size = LINEBUF_SIZE))) { if (errfun) (*errfun) ("linebuf (%s): malloc failed\n", lb->filename); - free(lb); + xfree(lb); return (NULL); } lb->errfun = errfun; @@ -124,15 +125,15 @@ Linebuf_alloc(const char *filename, void (*errfun) (const char *,...)) return (lb); } -static inline void +void Linebuf_free(Linebuf * lb) { fclose(lb->stream); - free(lb->buf); - free(lb); + xfree(lb->buf); + xfree(lb); } -static inline void +void Linebuf_restart(Linebuf * lb) { clearerr(lb->stream); @@ -140,14 +141,14 @@ Linebuf_restart(Linebuf * lb) lb->lineno = 0; } -static inline int +int Linebuf_lineno(Linebuf * lb) { return (lb->lineno); } -static inline char * -getline(Linebuf * lb) +char * +Linebuf_getline(Linebuf * lb) { int n = 0; @@ -156,7 +157,8 @@ getline(Linebuf * lb) /* Read a line */ if (!fgets(&lb->buf[n], lb->size - n, lb->stream)) { if (ferror(lb->stream) && lb->errfun) - (*lb->errfun) ("%s: %s\n", lb->filename, strerror(errno)); + (*lb->errfun) ("%s: %s\n", lb->filename, + strerror(errno)); return (NULL); } n = strlen(lb->buf); @@ -168,23 +170,26 @@ getline(Linebuf * lb) } if (n != lb->size - 1) { if (lb->errfun) - (*lb->errfun) ("%s: skipping incomplete last line\n", lb->filename); + (*lb->errfun) ("%s: skipping incomplete last line\n", + lb->filename); return (NULL); } /* Double the buffer if we need more space */ if (!(lb->buf = realloc(lb->buf, (lb->size *= 2)))) { if (lb->errfun) - (*lb->errfun) ("linebuf (%s): realloc failed\n", lb->filename); + (*lb->errfun) ("linebuf (%s): realloc failed\n", + lb->filename); return (NULL); } } } -static int +int fdlim_get(int hard) { #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) struct rlimit rlfd; + if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0) return (-1); if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY) @@ -198,7 +203,7 @@ fdlim_get(int hard) #endif } -static int +int fdlim_set(int lim) { #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) @@ -213,7 +218,7 @@ fdlim_set(int lim) if (setrlimit(RLIMIT_NOFILE, &rlfd) < 0) return (-1); #elif defined (HAVE_SETDTABLESIZE) - setdtablesize (lim); + setdtablesize(lim); #endif return (0); } @@ -223,7 +228,7 @@ fdlim_set(int lim) * separators. This is the same as the 4.4BSD strsep, but different from the * one in the GNU libc. */ -inline char * +char * xstrsep(char **str, const char *delim) { char *s, *e; @@ -298,7 +303,7 @@ tcpconnect(char *host) char strport[NI_MAXSERV]; int gaierr, s = -1; - snprintf(strport, sizeof strport, "%d", PORT); + snprintf(strport, sizeof strport, "%d", SSH_DEFAULT_PORT); memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; @@ -335,7 +340,7 @@ conalloc(char *iname, char *oname) do { name = xstrsep(&namelist, ","); if (!name) { - free(namebase); + xfree(namebase); return (-1); } } while ((s = tcpconnect(name)) < 0); @@ -357,7 +362,7 @@ conalloc(char *iname, char *oname) gettimeofday(&fdcon[s].c_tv, NULL); fdcon[s].c_tv.tv_sec += timeout; TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); - FD_SET(s, &read_wait); + FD_SET(s, read_wait); ncon++; return (s); } @@ -365,16 +370,16 @@ conalloc(char *iname, char *oname) void confree(int s) { - close(s); if (s >= maxfd || fdcon[s].c_status == CS_UNUSED) fatal("confree: attempt to free bad fdno %d", s); - free(fdcon[s].c_namebase); - free(fdcon[s].c_output_name); + close(s); + xfree(fdcon[s].c_namebase); + xfree(fdcon[s].c_output_name); if (fdcon[s].c_status == CS_KEYS) - free(fdcon[s].c_data); + xfree(fdcon[s].c_data); fdcon[s].c_status = CS_UNUSED; TAILQ_REMOVE(&tq, &fdcon[s], c_link); - FD_CLR(s, &read_wait); + FD_CLR(s, read_wait); ncon--; } @@ -395,37 +400,41 @@ conrecycle(int s) char *iname, *oname; iname = xstrdup(c->c_namelist); - oname = c->c_output_name; - c->c_output_name = NULL;/* prevent it from being freed */ + oname = xstrdup(c->c_output_name); confree(s); ret = conalloc(iname, oname); - free(iname); + xfree(iname); + xfree(oname); return (ret); } void congreet(int s) { - char buf[80]; - int n; + char buf[80], *cp; + size_t bufsiz; + int n = 0; con *c = &fdcon[s]; - n = read(s, buf, sizeof(buf)); + bufsiz = sizeof(buf); + cp = buf; + while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n' && *cp != '\r') + cp++; if (n < 0) { if (errno != ECONNREFUSED) error("read (%s): %s", c->c_name, strerror(errno)); conrecycle(s); return; } - if (buf[n - 1] != '\n') { + if (*cp != '\n' && *cp != '\r') { error("%s: bad greeting", c->c_name); confree(s); return; } - buf[n - 1] = '\0'; + *cp = '\0'; fprintf(stderr, "# %s %s\n", c->c_name, buf); n = snprintf(buf, sizeof buf, "SSH-1.5-OpenSSH-keyscan\r\n"); - if (write(s, buf, n) != n) { + if (atomicio(write, s, buf, n) != n) { error("write (%s): %s", c->c_name, strerror(errno)); confree(s); return; @@ -477,7 +486,7 @@ conread(int s) void conloop(void) { - fd_set r, e; + fd_set *r, *e; struct timeval seltime, now; int i; con *c; @@ -485,33 +494,42 @@ conloop(void) gettimeofday(&now, NULL); c = tq.tqh_first; - if (c && - (c->c_tv.tv_sec > now.tv_sec || - (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) { + if (c && (c->c_tv.tv_sec > now.tv_sec || + (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) { seltime = c->c_tv; seltime.tv_sec -= now.tv_sec; seltime.tv_usec -= now.tv_usec; - if ((int) seltime.tv_usec < 0) { + if (seltime.tv_usec < 0) { seltime.tv_usec += 1000000; seltime.tv_sec--; } } else seltime.tv_sec = seltime.tv_usec = 0; - r = e = read_wait; - select(maxfd, &r, NULL, &e, &seltime); - for (i = 0; i < maxfd; i++) - if (FD_ISSET(i, &e)) { + r = xmalloc(read_wait_size); + memcpy(r, read_wait, read_wait_size); + e = xmalloc(read_wait_size); + memcpy(e, read_wait, read_wait_size); + + while (select(maxfd, r, NULL, e, &seltime) == -1 && + (errno == EAGAIN || errno == EINTR)) + ; + + for (i = 0; i < maxfd; i++) { + if (FD_ISSET(i, e)) { error("%s: exception!", fdcon[i].c_name); confree(i); - } else if (FD_ISSET(i, &r)) + } else if (FD_ISSET(i, r)) conread(i); + } + xfree(r); + xfree(e); c = tq.tqh_first; - while (c && - (c->c_tv.tv_sec < now.tv_sec || - (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) { + while (c && (c->c_tv.tv_sec < now.tv_sec || + (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) { int s = c->c_fd; + c = c->c_link.tqe_next; conrecycle(s); } @@ -534,6 +552,7 @@ nexthost(int argc, char **argv) return (argv[argno++]); } else if (!strncmp(argv[argno], "-f", 2)) { char *fname; + if (argv[argno][2]) fname = &argv[argno++][2]; else if (++argno >= argc) { @@ -545,10 +564,12 @@ nexthost(int argc, char **argv) fname = NULL; lb = Linebuf_alloc(fname, error); } else - error("ignoring invalid/misplaced option `%s'", argv[argno++]); + error("ignoring invalid/misplaced option `%s'", + argv[argno++]); } else { char *line; - line = getline(lb); + + line = Linebuf_getline(lb); if (line) return (line); Linebuf_free(lb); @@ -557,7 +578,7 @@ nexthost(int argc, char **argv) } } -static void +void usage(void) { fatal("usage: %s [-t timeout] { [--] host | -f file } ...", __progname); @@ -595,14 +616,19 @@ main(int argc, char **argv) fatal("%s: fdlim_get: bad value", __progname); if (maxfd > MAXMAXFD) maxfd = MAXMAXFD; - if (maxcon <= 0) + if (MAXCON <= 0) fatal("%s: not enough file descriptors", __progname); if (maxfd > fdlim_get(0)) fdlim_set(maxfd); fdcon = xmalloc(maxfd * sizeof(con)); + memset(fdcon, 0, maxfd * sizeof(con)); + + read_wait_size = howmany(maxfd, NFDBITS) * sizeof(fd_mask); + read_wait = xmalloc(read_wait_size); + memset(read_wait, 0, read_wait_size); do { - while (ncon < maxcon) { + while (ncon < MAXCON) { char *name; host = nexthost(argc, argv);