📄 ssh-keyscan.c
字号:
}static intconalloc(char *iname, char *oname, int keytype){ int s; char *namebase, *name, *namelist; namebase = namelist = xstrdup(iname); do { name = xstrsep(&namelist, ","); if (!name) { xfree(namebase); return (-1); } } while ((s = tcpconnect(name)) < 0); if (s >= maxfd) fatal("conalloc: fdno %d too high", s); if (fdcon[s].c_status) fatal("conalloc: attempt to reuse fdno %d", s); fdcon[s].c_fd = s; fdcon[s].c_status = CS_CON; fdcon[s].c_namebase = namebase; fdcon[s].c_name = name; fdcon[s].c_namelist = namelist; fdcon[s].c_output_name = xstrdup(oname); fdcon[s].c_data = (char *) &fdcon[s].c_plen; fdcon[s].c_len = 4; fdcon[s].c_off = 0; fdcon[s].c_keytype = keytype; 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); ncon++; return (s);}static voidconfree(int s){ if (s >= maxfd || fdcon[s].c_status == CS_UNUSED) fatal("confree: attempt to free bad fdno %d", s); close(s); xfree(fdcon[s].c_namebase); xfree(fdcon[s].c_output_name); if (fdcon[s].c_status == CS_KEYS) xfree(fdcon[s].c_data); fdcon[s].c_status = CS_UNUSED; fdcon[s].c_keytype = 0; TAILQ_REMOVE(&tq, &fdcon[s], c_link); FD_CLR(s, read_wait); ncon--;}static voidcontouch(int s){ TAILQ_REMOVE(&tq, &fdcon[s], c_link); gettimeofday(&fdcon[s].c_tv, NULL); fdcon[s].c_tv.tv_sec += timeout; TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);}static intconrecycle(int s){ int ret; con *c = &fdcon[s]; ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); confree(s); return (ret);}static voidcongreet(int s){ char buf[256], *cp; char remote_version[sizeof buf]; size_t bufsiz; int remote_major, remote_minor, n = 0; con *c = &fdcon[s]; bufsiz = sizeof(buf); cp = buf; while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n') { if (*cp == '\r') *cp = '\n'; cp++; } if (n < 0) { if (errno != ECONNREFUSED) error("read (%s): %s", c->c_name, strerror(errno)); conrecycle(s); return; } if (n == 0) { error("%s: Connection closed by remote host", c->c_name); conrecycle(s); return; } if (*cp != '\n' && *cp != '\r') { error("%s: bad greeting", c->c_name); confree(s); return; } *cp = '\0'; if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) == 3) compat_datafellows(remote_version); else datafellows = 0; if (c->c_keytype != KT_RSA1) { if (!ssh2_capable(remote_major, remote_minor)) { debug("%s doesn't support ssh2", c->c_name); confree(s); return; } } else if (remote_major != 1) { debug("%s doesn't support ssh1", c->c_name); confree(s); return; } fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); if (atomicio(write, s, buf, n) != n) { error("write (%s): %s", c->c_name, strerror(errno)); confree(s); return; } if (c->c_keytype != KT_RSA1) { keyprint(c, keygrab_ssh2(c)); confree(s); return; } c->c_status = CS_SIZE; contouch(s);}static voidconread(int s){ int n; con *c = &fdcon[s]; if (c->c_status == CS_CON) { congreet(s); return; } n = read(s, c->c_data + c->c_off, c->c_len - c->c_off); if (n < 0) { error("read (%s): %s", c->c_name, strerror(errno)); confree(s); return; } c->c_off += n; if (c->c_off == c->c_len) switch (c->c_status) { case CS_SIZE: c->c_plen = htonl(c->c_plen); c->c_len = c->c_plen + 8 - (c->c_plen & 7); c->c_off = 0; c->c_data = xmalloc(c->c_len); c->c_status = CS_KEYS; break; case CS_KEYS: keyprint(c, keygrab_ssh1(c)); confree(s); return; break; default: fatal("conread: invalid status %d", c->c_status); break; } contouch(s);}static voidconloop(void){ fd_set *r, *e; struct timeval seltime, now; int i; con *c; gettimeofday(&now, NULL); c = TAILQ_FIRST(&tq); 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 (seltime.tv_usec < 0) { seltime.tv_usec += 1000000; seltime.tv_sec--; } } else seltime.tv_sec = seltime.tv_usec = 0; 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)) conread(i); } xfree(r); xfree(e); c = TAILQ_FIRST(&tq); 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 = TAILQ_NEXT(c, c_link); conrecycle(s); }}static voiddo_host(char *host){ char *name = strnnsep(&host, " \t\n"); int j; if (name == NULL) return; for (j = KT_RSA1; j <= KT_RSA; j *= 2) { if (get_keytypes & j) { while (ncon >= MAXCON) conloop(); conalloc(name, *host ? host : name, j); } }}voidfatal(const char *fmt,...){ va_list args; va_start(args, fmt); do_log(SYSLOG_LEVEL_FATAL, fmt, args); va_end(args); if (nonfatal_fatal) longjmp(kexjmp, -1); else fatal_cleanup();}static voidusage(void){ fprintf(stderr, "Usage: %s [options] host ...\n", __progname); fprintf(stderr, "Options:\n"); fprintf(stderr, " -f file Read hosts or addresses from file.\n"); fprintf(stderr, " -p port Connect to the specified port.\n"); fprintf(stderr, " -t keytype Specify the host key type.\n"); fprintf(stderr, " -T timeout Set connection timeout.\n"); fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); fprintf(stderr, " -4 Use IPv4 only.\n"); fprintf(stderr, " -6 Use IPv6 only.\n"); exit(1);}intmain(int argc, char **argv){ int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO; int opt, fopt_count = 0; char *tname; extern int optind; extern char *optarg; __progname = get_progname(argv[0]); init_rng(); seed_rng(); TAILQ_INIT(&tq); if (argc <= 1) usage(); while ((opt = getopt(argc, argv, "v46p:T:t:f:")) != -1) { switch (opt) { case 'p': ssh_port = a2port(optarg); if (ssh_port == 0) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(1); } break; case 'T': timeout = atoi(optarg); if (timeout <= 0) usage(); break; case 'v': if (!debug_flag) { debug_flag = 1; log_level = SYSLOG_LEVEL_DEBUG1; } else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; else fatal("Too high debugging level."); break; case 'f': if (strcmp(optarg, "-") == 0) optarg = NULL; argv[fopt_count++] = optarg; break; case 't': get_keytypes = 0; tname = strtok(optarg, ","); while (tname) { int type = key_type_from_name(tname); switch (type) { case KEY_RSA1: get_keytypes |= KT_RSA1; break; case KEY_DSA: get_keytypes |= KT_DSA; break; case KEY_RSA: get_keytypes |= KT_RSA; break; case KEY_UNSPEC: fatal("unknown key type %s", tname); } tname = strtok(NULL, ","); } break; case '4': IPv4or6 = AF_INET; break; case '6': IPv4or6 = AF_INET6; break; case '?': default: usage(); } } if (optind == argc && !fopt_count) usage(); log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1); maxfd = fdlim_get(1); if (maxfd < 0) fatal("%s: fdlim_get: bad value", __progname); if (maxfd > MAXMAXFD) maxfd = MAXMAXFD; 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); if (fopt_count) { Linebuf *lb; char *line; int j; for (j = 0; j < fopt_count; j++) { lb = Linebuf_alloc(argv[j], error); if (!lb) continue; while ((line = Linebuf_getline(lb)) != NULL) do_host(line); Linebuf_free(lb); } } while (optind < argc) do_host(argv[optind++]); while (ncon > 0) conloop(); return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -