*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-keyscan.c,v 1.29 2001/08/30 22:22:32 markus Exp $");
+RCSID("$OpenBSD: ssh-keyscan.c,v 1.46 2003/11/23 23:17:34 djm Exp $");
-#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H)
-#include <sys/queue.h>
-#else
-#include "openbsd-compat/fake-queue.h"
-#endif
-#include <errno.h>
+#include "openbsd-compat/sys-queue.h"
#include <openssl/bn.h>
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
Default value is AF_UNSPEC means both IPv4 and IPv6. */
-#ifdef IPV4_DEFAULT
-int IPv4or6 = AF_INET;
-#else
int IPv4or6 = AF_UNSPEC;
-#endif
int ssh_port = SSH_DEFAULT_PORT;
-
-#define KT_RSA1 1
-#define KT_DSA 2
-#define KT_RSA 4
-
-int get_keytypes = KT_RSA1; /* Get only RSA1 keys by default */
+
+#define KT_RSA1 1
+#define KT_DSA 2
+#define KT_RSA 4
+
+int get_keytypes = KT_RSA1; /* Get only RSA1 keys by default */
#define MAXMAXFD 256
if (!(lb = malloc(sizeof(*lb)))) {
if (errfun)
- (*errfun) ("linebuf (%s): malloc failed\n", lb->filename);
+ (*errfun) ("linebuf (%s): malloc failed\n",
+ filename ? filename : "(stdin)");
return (NULL);
}
if (filename) {
Linebuf_getline(Linebuf * lb)
{
int n = 0;
+ void *p;
lb->lineno++;
for (;;) {
/* 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,
+ (*lb->errfun)("%s: %s\n", lb->filename,
strerror(errno));
return (NULL);
}
}
if (n != lb->size - 1) {
if (lb->errfun)
- (*lb->errfun) ("%s: skipping incomplete last line\n",
+ (*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)))) {
+ lb->size *= 2;
+ if ((p = realloc(lb->buf, lb->size)) == NULL) {
+ lb->size /= 2;
if (lb->errfun)
- (*lb->errfun) ("linebuf (%s): realloc failed\n",
+ (*lb->errfun)("linebuf (%s): realloc failed\n",
lb->filename);
return (NULL);
}
+ lb->buf = p;
}
}
if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
return (-1);
if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY)
- return 10000;
+ return SSH_SYSFDMAX;
else
return hard ? rlfd.rlim_max : rlfd.rlim_cur;
-#elif defined (HAVE_SYSCONF)
- return sysconf (_SC_OPEN_MAX);
#else
- return 10000;
+ return SSH_SYSFDMAX;
#endif
}
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
struct rlimit rlfd;
#endif
+
if (lim <= 0)
return (-1);
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA?
"ssh-dss": "ssh-rsa";
c->c_kex = kex_setup(myproposal);
+ c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
+ c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
c->c_kex->verify_host_key = hostjump;
if (!(j = setjmp(kexjmp))) {
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
fatal("getaddrinfo %s: %s", host, gai_strerror(gaierr));
for (ai = aitop; ai; ai = ai->ai_next) {
- s = socket(ai->ai_family, SOCK_STREAM, 0);
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (s < 0) {
error("socket: %s", strerror(errno));
continue;
static int
conalloc(char *iname, char *oname, int keytype)
{
- int s;
char *namebase, *name, *namelist;
+ int s;
namebase = namelist = xstrdup(iname);
static int
conrecycle(int s)
{
- int ret;
con *c = &fdcon[s];
+ int ret;
ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype);
confree(s);
static void
congreet(int s)
{
+ int remote_major, remote_minor, n = 0;
char buf[256], *cp;
+ char remote_version[sizeof buf];
size_t bufsiz;
- int n = 0;
con *c = &fdcon[s];
bufsiz = sizeof(buf);
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) {
- int remote_major, remote_minor;
- char remote_version[sizeof buf];
-
- if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
- &remote_major, &remote_minor, remote_version) == 3)
- compat_datafellows(remote_version);
- else
- datafellows = 0;
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) {
+ if (atomicio(vwrite, s, buf, n) != n) {
error("write (%s): %s", c->c_name, strerror(errno));
confree(s);
return;
static void
conread(int s)
{
- int n;
con *c = &fdcon[s];
+ int n;
if (c->c_status == CS_CON) {
congreet(s);
static void
conloop(void)
{
- fd_set *r, *e;
struct timeval seltime, now;
- int i;
+ fd_set *r, *e;
con *c;
+ int i;
gettimeofday(&now, NULL);
- c = tq.tqh_first;
+ 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))) {
xfree(r);
xfree(e);
- c = tq.tqh_first;
+ 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 = c->c_link.tqe_next;
+ c = TAILQ_NEXT(c, c_link);
conrecycle(s);
}
}
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)
}
}
-static void
-fatal_callback(void *arg)
+void
+fatal(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
+ exit(255);
}
static void
usage(void)
{
- fprintf(stderr, "Usage: %s [options] host ...\n",
+ fprintf(stderr, "usage: %s [-v46] [-p port] [-T timeout] [-t type] [-f file]\n"
+ "\t\t [host | addrlist namelist] [...]\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);
}
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]);
+ __progname = ssh_get_progname(argv[0]);
+ init_rng();
+ seed_rng();
TAILQ_INIT(&tq);
if (argc <= 1)
}
break;
case 'T':
- timeout = atoi(optarg);
- if (timeout <= 0)
+ timeout = convtime(optarg);
+ if (timeout == -1 || timeout == 0) {
+ fprintf(stderr, "Bad timeout '%s'\n", optarg);
usage();
+ }
break;
case 'v':
if (!debug_flag) {
else
fatal("Too high debugging level.");
break;
- case 'f':
+ case 'f':
if (strcmp(optarg, "-") == 0)
optarg = NULL;
argv[fopt_count++] = optarg;
get_keytypes |= KT_RSA;
break;
case KEY_UNSPEC:
- fatal("unknown key type %s\n", tname);
+ fatal("unknown key type %s", tname);
}
tname = strtok(NULL, ",");
}
usage();
log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1);
- fatal_add_cleanup(fatal_callback, NULL);
-
maxfd = fdlim_get(1);
if (maxfd < 0)