*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-keyscan.c,v 1.41 2003/02/16 17:09:57 markus Exp $");
+RCSID("$OpenBSD: ssh-keyscan.c,v 1.56 2005/09/13 23:40:07 djm Exp $");
#include "openbsd-compat/sys-queue.h"
#include "log.h"
#include "atomicio.h"
#include "misc.h"
+#include "hostfile.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;
int get_keytypes = KT_RSA1; /* Get only RSA1 keys by default */
+int hash_hosts = 0; /* Hash hostname on output */
+
#define MAXMAXFD 256
/* The number of seconds after which to give up on a TCP connection */
int maxfd;
#define MAXCON (maxfd - 10)
-#ifdef HAVE___PROGNAME
extern char *__progname;
-#else
-char *__progname;
-#endif
fd_set *read_wait;
size_t read_wait_size;
int ncon;
static char *
Linebuf_getline(Linebuf * lb)
{
- int n = 0;
+ size_t n = 0;
void *p;
lb->lineno++;
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
}
"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_GRP14_SHA1] = kexdh_client;
c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
c->c_kex->verify_host_key = hostjump;
static void
keyprint(con *c, Key *key)
{
+ char *host = c->c_output_name ? c->c_output_name : c->c_name;
+
if (!key)
return;
+ if (hash_hosts && (host = host_hash(host, NULL, 0)) == NULL)
+ fatal("host_hash failed");
- fprintf(stdout, "%s ", c->c_output_name ? c->c_output_name : c->c_name);
+ fprintf(stdout, "%s ", host);
key_write(key, stdout);
fputs("\n", stdout);
}
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;
}
- if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
- fatal("F_SETFL: %s", strerror(errno));
+ if (set_nonblock(s) == -1)
+ fatal("%s: set_nonblock(%d)", __func__, s);
if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0 &&
errno != EINPROGRESS)
error("connect (`%s'): %s", host, strerror(errno));
static void
congreet(int s)
{
- int remote_major, remote_minor, n = 0;
+ int n = 0, remote_major = 0, remote_minor = 0;
char buf[256], *cp;
char remote_version[sizeof buf];
size_t bufsiz;
bufsiz = sizeof(buf);
cp = buf;
- while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n') {
+ while (bufsiz-- && (n = atomicio(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);
+ switch (errno) {
+ case EPIPE:
+ error("%s: Connection closed by remote host", c->c_name);
+ break;
+ case ECONNREFUSED:
+ break;
+ default:
+ error("read (%s): %s", c->c_name, strerror(errno));
+ break;
+ }
conrecycle(s);
return;
}
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 (n < 0 || (size_t)n >= sizeof(buf)) {
+ error("snprintf: buffer too small");
+ confree(s);
+ return;
+ }
+ if (atomicio(vwrite, s, buf, n) != (size_t)n) {
error("write (%s): %s", c->c_name, strerror(errno));
confree(s);
return;
conread(int s)
{
con *c = &fdcon[s];
- int n;
+ size_t n;
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) {
+ n = atomicio(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;
if (nonfatal_fatal)
longjmp(kexjmp, -1);
else
- fatal_cleanup();
+ exit(255);
}
static void
usage(void)
{
- fprintf(stderr, "usage: %s [-v46] [-p port] [-T timeout] [-f file]\n"
+ fprintf(stderr, "usage: %s [-46Hv] [-f file] [-p port] [-T timeout] [-t type]\n"
"\t\t [host | addrlist namelist] [...]\n",
__progname);
exit(1);
extern int optind;
extern char *optarg;
- __progname = get_progname(argv[0]);
+ __progname = ssh_get_progname(argv[0]);
init_rng();
seed_rng();
TAILQ_INIT(&tq);
+ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+ sanitise_stdfd();
+
if (argc <= 1)
usage();
- while ((opt = getopt(argc, argv, "v46p:T:t:f:")) != -1) {
+ while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) {
switch (opt) {
+ case 'H':
+ hash_hosts = 1;
+ break;
case 'p':
ssh_port = a2port(optarg);
if (ssh_port == 0) {