Example #1
0
int
kex_send_kexinit(struct ssh *ssh)
{
	u_char *cookie;
	Kex *kex = ssh->kex;
	int r;

	if (kex == NULL)
		return SSH_ERR_INTERNAL_ERROR;
	if (kex->flags & KEX_INIT_SENT)
		return 0;
	kex->done = 0;

	/* generate a random cookie */
	if (sshbuf_len(kex->my) < KEX_COOKIE_LEN)
		return SSH_ERR_INVALID_FORMAT;
	if ((cookie = sshbuf_ptr(kex->my)) == NULL)
		return SSH_ERR_INTERNAL_ERROR;
	arc4random_buf(cookie, KEX_COOKIE_LEN);

	if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0)
		return r;
	if ((r = sshpkt_put(ssh, sshbuf_ptr(kex->my),
	    sshbuf_len(kex->my))) != 0)
		return r;
	if ((r = sshpkt_send(ssh)) != 0)
		return r;
	debug("SSH2_MSG_KEXINIT sent");
	kex->flags |= KEX_INIT_SENT;
	return 0;
}
Example #2
0
/*
 * Wait until all buffered output has been sent to the client.
 * This is used when the program terminates.
 */
static void
drain_output(struct ssh *ssh)
{
	int r;

	/* Send any buffered stdout data to the client. */
	if (sshbuf_len(stdout_buffer) > 0) {
		if ((r = sshpkt_start(ssh, SSH_SMSG_STDOUT_DATA)) != 0 ||
		    (r = sshpkt_put_string(ssh, sshbuf_ptr(stdout_buffer),
		    sshbuf_len(stdout_buffer))) != 0 ||
		    (r = sshpkt_send(ssh)) != 0)
			fatal("%s: %s", __func__, ssh_err(r));
		/* Update the count of sent bytes. */
		stdout_bytes += sshbuf_len(stdout_buffer);
	}
	/* Send any buffered stderr data to the client. */
	if (sshbuf_len(stderr_buffer) > 0) {
		if ((r = sshpkt_start(ssh, SSH_SMSG_STDERR_DATA)) != 0 ||
		    (r = sshpkt_put_string(ssh, sshbuf_ptr(stderr_buffer),
		    sshbuf_len(stderr_buffer))) != 0 ||
		    (r = sshpkt_send(ssh)) != 0)
		/* Update the count of sent bytes. */
		stderr_bytes += sshbuf_len(stderr_buffer);
	}
	/* Wait until all buffered data has been written to the client. */
	ssh_packet_write_wait(ssh);
}
Example #3
0
int
kex_c25519_dec(struct kex *kex, const struct sshbuf *server_blob,
    struct sshbuf **shared_secretp)
{
	struct sshbuf *buf = NULL;
	const u_char *server_pub;
	int r;

	*shared_secretp = NULL;

	if (sshbuf_len(server_blob) != CURVE25519_SIZE) {
		r = SSH_ERR_SIGNATURE_INVALID;
		goto out;
	}
	server_pub = sshbuf_ptr(server_blob);
#ifdef DEBUG_KEXECDH
	dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
#endif
	/* shared secret */
	if ((buf = sshbuf_new()) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
	    buf, 0)) < 0)
		goto out;
#ifdef DEBUG_KEXECDH
	dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
#endif
	*shared_secretp = buf;
	buf = NULL;
 out:
	sshbuf_free(buf);
	return r;
}
Example #4
0
int
kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob,
   struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
{
	struct sshbuf *server_blob = NULL;
	struct sshbuf *buf = NULL;
	const u_char *client_pub;
	u_char *server_pub;
	u_char server_key[CURVE25519_SIZE];
	int r;

	*server_blobp = NULL;
	*shared_secretp = NULL;

	if (sshbuf_len(client_blob) != CURVE25519_SIZE) {
		r = SSH_ERR_SIGNATURE_INVALID;
		goto out;
	}
	client_pub = sshbuf_ptr(client_blob);
#ifdef DEBUG_KEXECDH
	dump_digest("client public key 25519:", client_pub, CURVE25519_SIZE);
#endif
	/* allocate space for encrypted KEM key and ECDH pub key */
	if ((server_blob = sshbuf_new()) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0)
		goto out;
	kexc25519_keygen(server_key, server_pub);
	/* allocate shared secret */
	if ((buf = sshbuf_new()) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 0)) < 0)
		goto out;
#ifdef DEBUG_KEXECDH
	dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
	dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
#endif
	*server_blobp = server_blob;
	*shared_secretp = buf;
	server_blob = NULL;
	buf = NULL;
 out:
	explicit_bzero(server_key, sizeof(server_key));
	sshbuf_free(server_blob);
	sshbuf_free(buf);
	return r;
}
Example #5
0
int
sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp,
    size_t *lenp)
{
	u_int32_t len;
	const u_char *p = sshbuf_ptr(buf);

	if (valp != NULL)
		*valp = NULL;
	if (lenp != NULL)
		*lenp = 0;
	if (sshbuf_len(buf) < 4) {
		SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
		return SSH_ERR_MESSAGE_INCOMPLETE;
	}
	len = PEEK_U32(p);
	if (len > SSHBUF_SIZE_MAX - 4) {
		SSHBUF_DBG(("SSH_ERR_STRING_TOO_LARGE"));
		return SSH_ERR_STRING_TOO_LARGE;
	}
	if (sshbuf_len(buf) - 4 < len) {
		SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
		return SSH_ERR_MESSAGE_INCOMPLETE;
	}
	if (valp != 0)
		*valp = p + 4;
	if (lenp != NULL)
		*lenp = len;
	return 0;
}
int
sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp)
{
	u_int32_t len;
	const u_char *p = sshbuf_ptr(buf), *z;
	int r;

	if (sshbuf_len(buf) < 4) {
		SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
		return SSH_ERR_MESSAGE_INCOMPLETE;
	}
	len = PEEK_U32(p);
	if (sshbuf_len(buf) < (size_t)len + 4) {
		SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
		return SSH_ERR_MESSAGE_INCOMPLETE;
	}
	/* Allow a \0 only at the end of the string */
	if ((z = memchr(p + 4, '\0', len)) != NULL && z < p + 4 + len - 1) {
		SSHBUF_DBG(("SSH_ERR_INVALID_FORMAT"));
		return SSH_ERR_INVALID_FORMAT;
	}
	if ((r = sshbuf_consume(buf, 4 + (size_t)len)) < 0)
		return -1;
	if (valp != NULL) {
		if ((*valp = malloc(len + 1)) == NULL) {
			SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
			return SSH_ERR_ALLOC_FAIL;
		}
		memcpy(*valp, p + 4, len);
		(*valp)[len] = '\0';
	}
	if (lenp != NULL)
		*lenp = (size_t)len;
	return 0;
}
Example #7
0
static char *
authmethods_get(struct authctxt *authctxt)
{
    struct sshbuf *b;
    char *list;
    int i, r;

    if ((b = sshbuf_new()) == NULL)
        fatal("%s: sshbuf_new failed", __func__);
    for (i = 0; authmethods[i] != NULL; i++) {
        if (strcmp(authmethods[i]->name, "none") == 0)
            continue;
        if (authmethods[i]->enabled == NULL ||
                *(authmethods[i]->enabled) == 0)
            continue;
        if (!auth2_method_allowed(authctxt, authmethods[i]->name,
                                  NULL))
            continue;
        if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "",
                             authmethods[i]->name)) != 0)
            fatal("%s: buffer error: %s", __func__, ssh_err(r));
    }
    if ((r = sshbuf_put_u8(b, 0)) != 0)
        fatal("%s: buffer error: %s", __func__, ssh_err(r));
    list = xstrdup((const char *)sshbuf_ptr(b));
    sshbuf_free(b);
    return list;
}
Example #8
0
int
sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v)
{
	const u_char *d = sshbuf_ptr(buf);
	u_int16_t len_bits;
	size_t len_bytes;

	/* Length in bits */
	if (sshbuf_len(buf) < 2)
		return SSH_ERR_MESSAGE_INCOMPLETE;
	len_bits = PEEK_U16(d);
	len_bytes = (len_bits + 7) >> 3;
	if (len_bytes > SSHBUF_MAX_BIGNUM)
		return SSH_ERR_BIGNUM_TOO_LARGE;
	if (sshbuf_len(buf) < 2 + len_bytes)
		return SSH_ERR_MESSAGE_INCOMPLETE;
	if (v != NULL && BN_bin2bn(d + 2, len_bytes, v) == NULL)
		return SSH_ERR_ALLOC_FAIL;
	if (sshbuf_consume(buf, 2 + len_bytes) != 0) {
		SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
		SSHBUF_ABORT();
		return SSH_ERR_INTERNAL_ERROR;
	}
	return 0;
}
static void
public_fuzz(struct sshkey *k)
{
	struct sshkey *k1;
	struct sshbuf *buf;
	struct fuzz *fuzz;
	u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;

	if (test_is_fast())
		fuzzers &= ~FUZZ_1_BIT_FLIP;
	if (test_is_slow())
		fuzzers |= FUZZ_2_BIT_FLIP | FUZZ_2_BYTE_FLIP;
	ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
	ASSERT_INT_EQ(sshkey_putb(k, buf), 0);
	fuzz = fuzz_begin(fuzzers, sshbuf_mutable_ptr(buf), sshbuf_len(buf));
	ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf),
	    &k1), 0);
	sshkey_free(k1);
	sshbuf_free(buf);
	TEST_ONERROR(onerror, fuzz);
	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
		if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0)
			sshkey_free(k1);
	}
	fuzz_cleanup(fuzz);
}
Example #10
0
static struct kbdintctxt *
kbdint_alloc(const char *devs)
{
	struct kbdintctxt *kbdintctxt;
	struct sshbuf *b;
	int i, r;

	kbdintctxt = xcalloc(1, sizeof(struct kbdintctxt));
	if (strcmp(devs, "") == 0) {
		if ((b = sshbuf_new()) == NULL)
			fatal("%s: sshbuf_new failed", __func__);
		for (i = 0; devices[i]; i++) {
			if ((r = sshbuf_putf(b, "%s%s",
			    sshbuf_len(b) ? "," : "", devices[i]->name)) != 0)
				fatal("%s: buffer error: %s",
				    __func__, ssh_err(r));
		}
		if ((r = sshbuf_put_u8(b, 0)) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
		kbdintctxt->devices = xstrdup((const char *)sshbuf_ptr(b));
		sshbuf_free(b);
	} else {
		kbdintctxt->devices = xstrdup(devs);
	}
	debug("kbdint_alloc: devices '%s'", kbdintctxt->devices);
	kbdintctxt->ctxt = NULL;
	kbdintctxt->device = NULL;
	kbdintctxt->nreq = 0;

	return kbdintctxt;
}
Example #11
0
static void
build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
    const struct sshkey *sign_key, const struct sshkey *ca_key,
    const char *sig_alg)
{
	struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts;
	u_char *sigblob;
	size_t siglen;

	ca_buf = sshbuf_new();
	ASSERT_PTR_NE(ca_buf, NULL);
	ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0);

	/*
	 * Get the public key serialisation by rendering the key and skipping
	 * the type string. This is a bit of a hack :/
	 */
	pk = sshbuf_new();
	ASSERT_PTR_NE(pk, NULL);
	ASSERT_INT_EQ(sshkey_putb_plain(k, pk), 0);
	ASSERT_INT_EQ(sshbuf_skip_string(pk), 0);

	principals = sshbuf_new();
	ASSERT_PTR_NE(principals, NULL);
	ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0);
	ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0);

	critopts = sshbuf_new();
	ASSERT_PTR_NE(critopts, NULL);
	put_opt(critopts, "force-command", "/usr/local/bin/nethack");
	put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1");

	exts = sshbuf_new();
	ASSERT_PTR_NE(exts, NULL);
	put_opt(critopts, "permit-X11-forwarding", NULL);

	ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0);
	ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */
	ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */
	ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */
	ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */
	ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */
	ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */
	ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */
	ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */
	ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen,
	    sshbuf_ptr(b), sshbuf_len(b), sig_alg, 0), 0);
	ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */

	free(sigblob);
	sshbuf_free(ca_buf);
	sshbuf_free(exts);
	sshbuf_free(critopts);
	sshbuf_free(principals);
	sshbuf_free(pk);
}
Example #12
0
/*
 * Make packets from buffered stdout data, and buffer it for sending to the
 * client.
 */
static void
make_packets_from_stdout_data(struct ssh *ssh)
{
	size_t len;
	int r;

	/* Send buffered stdout data to the client. */
	while (sshbuf_len(stdout_buffer) > 0 &&
	    ssh_packet_not_very_much_data_to_write(ssh)) {
		len = sshbuf_len(stdout_buffer);
		if (ssh_packet_is_interactive(ssh)) {
			if (len > 512)
				len = 512;
		} else {
			/* Keep the packets at reasonable size. */
			if (len > ssh_packet_get_maxsize(ssh))
				len = ssh_packet_get_maxsize(ssh);
		}
		if ((r = sshpkt_start(ssh, SSH_SMSG_STDOUT_DATA)) != 0 ||
		    (r = sshpkt_put_string(ssh, sshbuf_ptr(stdout_buffer),
		    len)) != 0 ||
		    (r = sshpkt_send(ssh)) != 0)
			fatal("%s: %s", __func__, ssh_err(r));
		if ((r = sshbuf_consume(stdout_buffer, len)) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
		stdout_bytes += len;
	}
}
Example #13
0
/* Confirmation hash calculation */
void
jpake_confirm_hash(const BIGNUM *k,
    const u_char *endpoint_id, u_int endpoint_id_len,
    const u_char *sess_id, u_int sess_id_len,
    u_char **confirm_hash, u_int *confirm_hash_len)
{
	struct sshbuf *b;
	int r;

	/*
	 * Calculate confirmation proof:
	 *     client: H(k || client_id || session_id)
	 *     server: H(k || server_id || session_id)
	 */
	if ((b = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);
	if ((r = sshbuf_put_bignum2(b, k)) != 0 ||
	    (r = sshbuf_put_string(b, endpoint_id, endpoint_id_len)) != 0 ||
	    (r = sshbuf_put_string(b, sess_id, sess_id_len)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	if (hash_buffer(sshbuf_ptr(b), sshbuf_len(b), EVP_sha256(),
	    confirm_hash, confirm_hash_len) != 0)
		fatal("%s: hash_buffer", __func__);
	sshbuf_free(b);
}
Example #14
0
static void
public_fuzz(struct sshkey *k)
{
	struct sshkey *k1;
	struct sshbuf *buf;
	struct fuzz *fuzz;

	ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
	ASSERT_INT_EQ(sshkey_to_blob_buf(k, buf), 0);
	/* XXX need a way to run the tests in "slow, but complete" mode */
	fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */
	    FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */
	    FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
	    sshbuf_mutable_ptr(buf), sshbuf_len(buf));
	ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf),
	    &k1), 0);
	sshkey_free(k1);
	sshbuf_free(buf);
	TEST_ONERROR(onerror, fuzz);
	for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
		if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0)
			sshkey_free(k1);
	}
	fuzz_cleanup(fuzz);
}
Example #15
0
/*
 * Caclulate a new key after a reconnect
 */
void
calculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge)
{
	int r;

	const EVP_MD *md = EVP_sha1();
	EVP_MD_CTX ctx;
	char hash[EVP_MAX_MD_SIZE];
	struct sshbuf *b;

	if ((b = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);
	if ((r = sshbuf_put_u64(b, *key)) != 0 ||
	    (r = sshbuf_put_u64(b, cookie)) != 0 ||
	    (r = sshbuf_put_u64(b, challenge)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));

	EVP_DigestInit(&ctx, md);
	EVP_DigestUpdate(&ctx, sshbuf_ptr(b), sshbuf_len(b));
	EVP_DigestFinal(&ctx, hash, NULL);

	sshbuf_reset(b);
	if ((r = sshbuf_put(b, hash, EVP_MD_size(md))) != 0 ||
	    (r = sshbuf_get_u64(b, key)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	sshbuf_free(b);
}
Example #16
0
/*
 * Parse the public, unencrypted portion of a RSA1 key.
 */
int
sshkey_parse_public_rsa1(struct sshbuf *blob,
    struct sshkey **keyp, char **commentp)
{
	int r;
	struct sshkey *pub = NULL;
	struct sshbuf *copy = NULL;

	*keyp = NULL;
	if (commentp != NULL)
		*commentp = NULL;

	/* Check that it is at least big enough to contain the ID string. */
	if (sshbuf_len(blob) < sizeof(authfile_id_string))
		return SSH_ERR_INVALID_FORMAT;

	/*
	 * Make sure it begins with the id string.  Consume the id string
	 * from the buffer.
	 */
	if (memcmp(sshbuf_ptr(blob), authfile_id_string,
	    sizeof(authfile_id_string)) != 0)
		return SSH_ERR_INVALID_FORMAT;
	/* Make a working copy of the keyblob and skip past the magic */
	if ((copy = sshbuf_fromb(blob)) == NULL)
		return SSH_ERR_ALLOC_FAIL;
	if ((r = sshbuf_consume(copy, sizeof(authfile_id_string))) != 0)
		goto out;

	/* Skip cipher type, reserved data and key bits. */
	if ((r = sshbuf_get_u8(copy, NULL)) != 0 ||	/* cipher type */
	    (r = sshbuf_get_u32(copy, NULL)) != 0 ||	/* reserved */
	    (r = sshbuf_get_u32(copy, NULL)) != 0)	/* key bits */
		goto out;

	/* Read the public key from the buffer. */
	if ((pub = sshkey_new(KEY_RSA1)) == NULL ||
	    (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 ||
	    (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0)
		goto out;

	/* Finally, the comment */
	if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0)
		goto out;

	/* The encrypted private part is not parsed by this function. */

	r = 0;
	*keyp = pub;
	pub = NULL;

 out:
	if (copy != NULL)
		sshbuf_free(copy);
	if (pub != NULL)
		sshkey_free(pub);
	return r;
}
Example #17
0
int
ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
    const u_char *data, size_t datalen, u_int compat)
{
	u_char *sig = NULL;
	size_t slen = 0, len;
	unsigned long long smlen;
	int r, ret;
	struct sshbuf *b = NULL;

	if (lenp != NULL)
		*lenp = 0;
	if (sigp != NULL)
		*sigp = NULL;

	if (key == NULL ||
	    sshkey_type_plain(key->type) != KEY_ED25519 ||
	    key->ed25519_sk == NULL ||
	    datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
		return SSH_ERR_INVALID_ARGUMENT;
	smlen = slen = datalen + crypto_sign_ed25519_BYTES;
	if ((sig = malloc(slen)) == NULL)
		return SSH_ERR_ALLOC_FAIL;

	if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen,
	    key->ed25519_sk)) != 0 || smlen <= datalen) {
		r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
		goto out;
	}
	/* encode signature */
	if ((b = sshbuf_new()) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 ||
	    (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
		goto out;
	len = sshbuf_len(b);
	if (sigp != NULL) {
		if ((*sigp = malloc(len)) == NULL) {
			r = SSH_ERR_ALLOC_FAIL;
			goto out;
		}
		memcpy(*sigp, sshbuf_ptr(b), len);
	}
	if (lenp != NULL)
		*lenp = len;
	/* success */
	r = 0;
 out:
	sshbuf_free(b);
	if (sig != NULL) {
		explicit_bzero(sig, slen);
		free(sig);
	}

	return r;
}
Example #18
0
static int
do_send_and_receive(struct ssh *from, struct ssh *to, int mydirection,
    int *packet_count, int trigger_direction, int packet_index,
    const char *dump_path, struct sshbuf *replace_data)
{
	u_char type;
	size_t len, olen;
	const u_char *buf;
	int r;
	FILE *dumpfile;

	for (;;) {
		if ((r = ssh_packet_next(from, &type)) != 0) {
			fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
			return r;
		}
		if (type != 0)
			return 0;
		buf = ssh_output_ptr(from, &len);
		olen = len;
		if (do_debug) {
			printf("%s packet %d type %u len %zu:\n",
			    mydirection == S2C ? "s2c" : "c2s",
			    *packet_count, type, len);
			sshbuf_dump_data(buf, len, stdout);
		}
		if (mydirection == trigger_direction &&
		    packet_index == *packet_count) {
			if (replace_data != NULL) {
				buf = sshbuf_ptr(replace_data);
				len = sshbuf_len(replace_data);
				if (do_debug) {
					printf("***** replaced packet "
					    "len %zu\n", len);
					sshbuf_dump_data(buf, len, stdout);
				}
			} else if (dump_path != NULL) {
				if ((dumpfile = fopen(dump_path, "w+")) == NULL)
					err(1, "fopen %s", dump_path);
				if (len != 0 &&
				    fwrite(buf, len, 1, dumpfile) != 1)
					err(1, "fwrite %s", dump_path);
				if (do_debug)
					printf("***** dumped packet "
					    "len %zu\n", len);
				fclose(dumpfile);
				exit(0);
			}
		}
		(*packet_count)++;
		if (len == 0)
			return 0;
		if ((r = ssh_input_append(to, buf, len)) != 0 ||
		    (r = ssh_output_consume(from, olen)) != 0)
			return r;
	}
}
Example #19
0
int
kex_ecdh_hash(
    const EVP_MD *evp_md,
    const EC_GROUP *ec_group,
    const char *client_version_string,
    const char *server_version_string,
    const u_char *ckexinit, size_t ckexinitlen,
    const u_char *skexinit, size_t skexinitlen,
    const u_char *serverhostkeyblob, size_t sbloblen,
    const EC_POINT *client_dh_pub,
    const EC_POINT *server_dh_pub,
    const BIGNUM *shared_secret,
    u_char **hash, size_t *hashlen)
{
	struct sshbuf *b;
	EVP_MD_CTX md;
	static u_char digest[EVP_MAX_MD_SIZE];
	int r;

	if ((b = sshbuf_new()) == NULL)
		return SSH_ERR_ALLOC_FAIL;
	if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
	    (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
	    /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
	    (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
	    (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
	    (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
	    (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
	    (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
	    (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 ||
	    (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 ||
	    (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
		sshbuf_free(b);
		return r;
	}
#ifdef DEBUG_KEX
	sshbuf_dump(b, stderr);
#endif
	if (EVP_DigestInit(&md, evp_md) != 1 ||
	    EVP_DigestUpdate(&md, sshbuf_ptr(b), sshbuf_len(b)) != 1 ||
	    EVP_DigestFinal(&md, digest, NULL) != 1) {
		sshbuf_free(b);
		return SSH_ERR_LIBCRYPTO_ERROR;
	}
	sshbuf_free(b);
#ifdef DEBUG_KEX
	dump_digest("hash", digest, EVP_MD_size(evp_md));
#endif
	*hash = digest;
	*hashlen = EVP_MD_size(evp_md);
	return 0;
}
Example #20
0
BIGNUM *
load_bignum(const char *name)
{
	BIGNUM *ret = NULL;
	struct sshbuf *buf;

	buf = load_text_file(name);
	ASSERT_INT_NE(BN_hex2bn(&ret, (const char *)sshbuf_ptr(buf)), 0);
	sshbuf_free(buf);
	return ret;
}
Example #21
0
static void
build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
    const struct sshkey *sign_key, const struct sshkey *ca_key)
{
	struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts;
	u_char *sigblob;
	size_t siglen;

	ca_buf = sshbuf_new();
	ASSERT_INT_EQ(sshkey_to_blob_buf(ca_key, ca_buf), 0);

	/*
	 * Get the public key serialisation by rendering the key and skipping
	 * the type string. This is a bit of a hack :/
	 */
	pk = sshbuf_new();
	ASSERT_INT_EQ(sshkey_plain_to_blob_buf(k, pk), 0);
	ASSERT_INT_EQ(sshbuf_skip_string(pk), 0);

	principals = sshbuf_new();
	ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0);
	ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0);

	critopts = sshbuf_new();
	/* XXX fill this in */

	exts = sshbuf_new();
	/* XXX fill this in */

	ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0);
	ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */
	ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */
	ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */
	ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */
	ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */
	ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */
	ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */
	ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */
	ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */
	ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen,
	    sshbuf_ptr(b), sshbuf_len(b), 0), 0);
	ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */

	free(sigblob);
	sshbuf_free(ca_buf);
	sshbuf_free(exts);
	sshbuf_free(critopts);
	sshbuf_free(principals);
	sshbuf_free(pk);
}
Example #22
0
int
sshbuf_get_u8(struct sshbuf *buf, u_char *valp)
{
	const u_char *p = sshbuf_ptr(buf);
	int r;

	if ((r = sshbuf_consume(buf, 1)) < 0)
		return r;
	if (valp != NULL)
		*valp = (u_int8_t)*p;
	return 0;
}
Example #23
0
int
sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp)
{
	const u_char *p = sshbuf_ptr(buf);
	int r;

	if ((r = sshbuf_consume(buf, 2)) < 0)
		return r;
	if (valp != NULL)
		*valp = PEEK_U16(p);
	return 0;
}
Example #24
0
int
sshbuf_get(struct sshbuf *buf, void *v, size_t len)
{
	const u_char *p = sshbuf_ptr(buf);
	int r;

	if ((r = sshbuf_consume(buf, len)) < 0)
		return r;
	if (v != NULL)
		memcpy(v, p, len);
	return 0;
}
Example #25
0
/*
 * Derive fake salt as H(username || first_private_host_key)
 * This provides relatively stable fake salts for non-existent
 * users and avoids the jpake method becoming an account validity
 * oracle.
 */
static void
derive_rawsalt(const char *username, u_char *rawsalt, u_int len)
{
	u_char *digest;
	u_int digest_len;
	struct sshbuf *b;
	struct sshkey *k;
	int r;

	if ((b = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);
	if ((r = sshbuf_put_cstring(b, username)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	if ((k = get_hostkey_by_index(0)) == NULL ||
	    (k->flags & SSHKEY_FLAG_EXT))
		fatal("%s: no hostkeys", __func__);
	switch (k->type) {
	case KEY_RSA1:
	case KEY_RSA:
		if (k->rsa->p == NULL || k->rsa->q == NULL)
			fatal("%s: RSA key missing p and/or q", __func__);
		if ((r = sshbuf_put_bignum2(b, k->rsa->p)) != 0 ||
		    (r = sshbuf_put_bignum2(b, k->rsa->q)) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
		break;
	case KEY_DSA:
		if (k->dsa->priv_key == NULL)
			fatal("%s: DSA key missing priv_key", __func__);
		if ((r = sshbuf_put_bignum2(b, k->dsa->priv_key)) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
		break;
	case KEY_ECDSA:
		if (EC_KEY_get0_private_key(k->ecdsa) == NULL)
			fatal("%s: ECDSA key missing priv_key", __func__);
		if ((r = sshbuf_put_bignum2(b,
		    EC_KEY_get0_private_key(k->ecdsa))) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
		break;
	default:
		fatal("%s: unknown key type %d", __func__, k->type);
	}
	if (hash_buffer(sshbuf_ptr(b), sshbuf_len(b), EVP_sha256(),
	    &digest, &digest_len) != 0)
		fatal("%s: hash_buffer", __func__);
	sshbuf_free(b);
	if (len > digest_len)
		fatal("%s: not enough bytes for rawsalt (want %u have %u)",
		    __func__, len, digest_len);
	memcpy(rawsalt, digest, len);
	bzero(digest, digest_len);
	xfree(digest);
}
Example #26
0
char *
ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
    OM_uint32 *minor_status)
{
	OM_uint32 lmin;
	gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
	OM_uint32 ctx;
	struct sshbuf *b;
	char *ret;
	int r;

	if ((b = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);

	if (major_status != NULL)
		*major_status = ctxt->major;
	if (minor_status != NULL)
		*minor_status = ctxt->minor;

	ctx = 0;
	/* The GSSAPI error */
	do {
		gss_display_status(&lmin, ctxt->major,
		    GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg);

		if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 ||
		    (r = sshbuf_put_u8(b, '\n')) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));

		gss_release_buffer(&lmin, &msg);
	} while (ctx != 0);

	/* The mechanism specific error */
	do {
		gss_display_status(&lmin, ctxt->minor,
		    GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg);

		if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 ||
		    (r = sshbuf_put_u8(b, '\n')) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));

		gss_release_buffer(&lmin, &msg);
	} while (ctx != 0);

	if ((r = sshbuf_put_u8(b, '\n')) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	ret = xstrdup((const char *)sshbuf_ptr(b));
	sshbuf_free(b);
	return (ret);
}
Example #27
0
/*
 * Reassemble an argument vector into a string, quoting and escaping as
 * necessary. Caller must free returned string.
 */
static char *
assemble_argv(int argc, char **argv)
{
	int i, j, ws, r;
	char c, *ret;
	struct sshbuf *buf, *arg;

	if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);

	for (i = 0; i < argc; i++) {
		ws = 0;
		sshbuf_reset(arg);
		for (j = 0; argv[i][j] != '\0'; j++) {
			r = 0;
			c = argv[i][j];
			switch (c) {
			case ' ':
			case '\t':
				ws = 1;
				r = sshbuf_put_u8(arg, c);
				break;
			case '\\':
			case '\'':
			case '"':
				if ((r = sshbuf_put_u8(arg, '\\')) != 0)
					break;
				/* FALLTHROUGH */
			default:
				r = sshbuf_put_u8(arg, c);
				break;
			}
			if (r != 0)
				fatal("%s: sshbuf_put_u8: %s",
				    __func__, ssh_err(r));
		}
		if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
		    (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
		    (r = sshbuf_putb(buf, arg)) != 0 ||
		    (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
	}
	if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
		fatal("%s: malloc failed", __func__);
	memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
	ret[sshbuf_len(buf)] = '\0';
	sshbuf_free(buf);
	sshbuf_free(arg);
	return ret;
}
Example #28
0
static void
send_msg(struct sshbuf *m)
{
	u_char buf[4];
	size_t mlen = sshbuf_len(m);
	int r;

	POKE_U32(buf, mlen);
	if (atomicio(vwrite, fd, buf, 4) != 4 ||
	    atomicio(vwrite, fd, (u_char *)sshbuf_ptr(m),
	    sshbuf_len(m)) != sshbuf_len(m))
		error("write to helper failed");
	if ((r = sshbuf_consume(m, mlen)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
Example #29
0
struct sshbuf *
sshbuf_fromb(struct sshbuf *buf)
{
	struct sshbuf *ret;

	if (sshbuf_check_sanity(buf) != 0)
		return NULL;
	if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL)
		return NULL;
	if (sshbuf_set_parent(ret, buf) != 0) {
		sshbuf_free(ret);
		return NULL;
	}
	return ret;
}
Example #30
0
int
kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
    const BIGNUM *secret)
{
	struct sshbuf *shared_secret;
	int r;

	if ((shared_secret = sshbuf_new()) == NULL)
		return SSH_ERR_ALLOC_FAIL;
	if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0) {
		r = kex_derive_keys(ssh, hash, hashlen,
		    sshbuf_ptr(shared_secret), sshbuf_len(shared_secret));
	}
	sshbuf_free(shared_secret);
	return r;
}