Esempio n. 1
0
const void *
ssh_packet_get_string_ptr(struct ssh *ssh, u_int *length_ptr)
{
	int r;
	size_t len;
	const u_char *val;

	if ((r = sshpkt_get_string_direct(ssh, &val, &len)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));
	if (length_ptr != NULL)
		*length_ptr = (u_int)len;
	return val;
}
Esempio n. 2
0
static int
server_input_hostkeys_prove(struct sshbuf **respp)
{
	struct ssh *ssh = active_state; /* XXX */
	struct sshbuf *resp = NULL;
	struct sshbuf *sigbuf = NULL;
	struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
	int r, ndx, success = 0;
	const u_char *blob;
	u_char *sig = 0;
	size_t blen, slen;

	if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new", __func__);

	while (ssh_packet_remaining(ssh) > 0) {
		sshkey_free(key);
		key = NULL;
		if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
		    (r = sshkey_from_blob(blob, blen, &key)) != 0) {
			error("%s: couldn't parse key: %s",
			    __func__, ssh_err(r));
			goto out;
		}
		/*
		 * Better check that this is actually one of our hostkeys
		 * before attempting to sign anything with it.
		 */
		if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
			error("%s: unknown host %s key",
			    __func__, sshkey_type(key));
			goto out;
		}
		/*
		 * XXX refactor: make kex->sign just use an index rather
		 * than passing in public and private keys
		 */
		if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
		    (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
			error("%s: can't retrieve hostkey %d", __func__, ndx);
			goto out;
		}
		sshbuf_reset(sigbuf);
		free(sig);
		sig = NULL;
		if ((r = sshbuf_put_cstring(sigbuf,
		    "*****@*****.**")) != 0 ||
		    (r = sshbuf_put_string(sigbuf,
		    ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
		    (r = sshkey_puts(key, sigbuf)) != 0 ||
		    (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
		    sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), 0)) != 0 ||
		    (r = sshbuf_put_string(resp, sig, slen)) != 0) {
			error("%s: couldn't prepare signature: %s",
			    __func__, ssh_err(r));
			goto out;
		}
	}
	/* Success */
	*respp = resp;
	resp = NULL; /* don't free it */
	success = 1;
 out:
	free(sig);
	sshbuf_free(resp);
	sshbuf_free(sigbuf);
	sshkey_free(key);
	return success;
}
Esempio n. 3
0
/*
 * Decodes terminal modes for the terminal referenced by fd in a portable
 * manner from a packet being read.
 */
void
ssh_tty_parse_modes(struct ssh *ssh, int fd)
{
	struct termios tio;
	struct sshbuf *buf;
	const u_char *data;
	u_char opcode;
	u_int baud, u;
	int r, failure = 0;
	size_t len;

	if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0)
		fatal("%s: packet error: %s", __func__, ssh_err(r));
	if (len == 0)
		return;
	if ((buf = sshbuf_from(data, len)) == NULL) {
		error("%s: sshbuf_from failed", __func__);
		return;
	}

	/*
	 * Get old attributes for the terminal.  We will modify these
	 * flags. I am hoping that if there are any machine-specific
	 * modes, they will initially have reasonable values.
	 */
	if (tcgetattr(fd, &tio) == -1) {
		logit("tcgetattr: %.100s", strerror(errno));
		failure = -1;
	}

	while (sshbuf_len(buf) > 0) {
		if ((r = sshbuf_get_u8(buf, &opcode)) != 0)
			fatal("%s: packet error: %s", __func__, ssh_err(r));
		switch (opcode) {
		case TTY_OP_END:
			goto set;

		case TTY_OP_ISPEED:
			if ((r = sshbuf_get_u32(buf, &baud)) != 0)
				fatal("%s: packet error: %s",
				    __func__, ssh_err(r));
			if (failure != -1 &&
			    cfsetispeed(&tio, baud_to_speed(baud)) == -1)
				error("cfsetispeed failed for %d", baud);
			break;

		case TTY_OP_OSPEED:
			if ((r = sshbuf_get_u32(buf, &baud)) != 0)
				fatal("%s: packet error: %s",
				    __func__, ssh_err(r));
			if (failure != -1 &&
			    cfsetospeed(&tio, baud_to_speed(baud)) == -1)
				error("cfsetospeed failed for %d", baud);
			break;

#define TTYCHAR(NAME, OP) \
		case OP: \
			if ((r = sshbuf_get_u32(buf, &u)) != 0) \
				fatal("%s: packet error: %s", __func__, \
				    ssh_err(r)); \
			tio.c_cc[NAME] = u; \
			break;
#define TTYMODE(NAME, FIELD, OP) \
		case OP: \
			if ((r = sshbuf_get_u32(buf, &u)) != 0) \
				fatal("%s: packet error: %s", __func__, \
				    ssh_err(r)); \
			if (u) \
				tio.FIELD |= NAME; \
			else \
				tio.FIELD &= ~NAME; \
			break;

#include "ttymodes.h"

#undef TTYCHAR
#undef TTYMODE

		default:
			debug("Ignoring unsupported tty mode opcode %d (0x%x)",
			    opcode, opcode);
			/*
			 * SSH2:
			 * Opcodes 1 to 159 are defined to have a uint32
			 * argument.
			 * Opcodes 160 to 255 are undefined and cause parsing
			 * to stop.
			 */
			if (opcode > 0 && opcode < 160) {
				if ((r = sshbuf_get_u32(buf, NULL)) != 0)
					fatal("%s: packet error: %s", __func__,
					    ssh_err(r));
				break;
			} else {
				logit("%s: unknown opcode %d", __func__,
				    opcode);
				goto set;
			}
		}
	}

set:
	len = sshbuf_len(buf);
	sshbuf_free(buf);
	if (len > 0) {
		logit("%s: %zu bytes left", __func__, len);
		return;		/* Don't process bytes passed */
	}
	if (failure == -1)
		return;		/* Packet parsed ok but tcgetattr() failed */

	/* Set the new modes for the terminal. */
	if (tcsetattr(fd, TCSANOW, &tio) == -1)
		logit("Setting tty modes failed: %.100s", strerror(errno));
}