示例#1
0
static void
conread(int s)
{
	con *c = &fdcon[s];
	size_t n;

	if (c->c_status == CS_CON) {
		congreet(s);
		return;
	}
	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;
	}
	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;
		default:
			fatal("conread: invalid status %d", c->c_status);
			break;
		}

	contouch(s);
}
示例#2
0
static void
congreet(int s)
{
    int n = 0, remote_major = 0, remote_minor = 0;
    char buf[256], *cp;
    char remote_version[sizeof buf];
    size_t bufsiz;
    con *c = &fdcon[s];

    for (;;) {
        memset(buf, '\0', sizeof(buf));
        bufsiz = sizeof(buf);
        cp = buf;
        while (bufsiz-- &&
                (n = atomicio(read, s, cp, 1)) == 1 && *cp != '\n') {
            if (*cp == '\r')
                *cp = '\n';
            cp++;
        }
        if (n != 1 || strncmp(buf, "SSH-", 4) == 0)
            break;
    }
    if (n == 0) {
        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;
    }
    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 (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;
    }
    if (c->c_keytype != KT_RSA1) {
        keyprint(c, keygrab_ssh2(c));
        confree(s);
        return;
    }
    c->c_status = CS_SIZE;
    contouch(s);
}