示例#1
0
void
kex_send_kexinit(Kex *kex)
{
	u_int32_t rand = 0;
	u_char *cookie;
	int i;

	if (kex == NULL) {
		error("kex_send_kexinit: no kex, cannot rekey");
		return;
	}
	if (kex->flags & KEX_INIT_SENT) {
		debug("KEX_INIT_SENT");
		return;
	}
	kex->done = 0;

	/* generate a random cookie */
	if (buffer_len(&kex->my) < KEX_COOKIE_LEN)
		fatal("kex_send_kexinit: kex proposal too short");
	cookie = buffer_ptr(&kex->my);
	for (i = 0; i < KEX_COOKIE_LEN; i++) {
		if (i % 4 == 0)
			rand = arc4random();
		cookie[i] = rand;
		rand >>= 8;
	}
	packet_start(SSH2_MSG_KEXINIT);
	packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
	packet_send();
	debug("SSH2_MSG_KEXINIT sent");
	kex->flags |= KEX_INIT_SENT;
}
示例#2
0
static void
roaming_auth_required(void)
{
	u_char digest[SSH_DIGEST_MAX_LENGTH];
	Buffer b;
	u_int64_t chall, oldchall;

	chall = packet_get_int64();
	oldchall = packet_get_int64();
	if (oldchall != lastseenchall) {
		key1 = oldkey1;
		key2 = oldkey2;
	}
	lastseenchall = chall;

	buffer_init(&b);
	buffer_put_int64(&b, cookie);
	buffer_put_int64(&b, chall);
	if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, digest, sizeof(digest)) != 0)
		fatal("%s: ssh_digest_buffer failed", __func__);
	buffer_free(&b);

	packet_start(SSH2_MSG_KEX_ROAMING_AUTH);
	packet_put_int64(key1 ^ get_recv_bytes());
	packet_put_raw(digest, ssh_digest_bytes(SSH_DIGEST_SHA1));
	packet_send();

	oldkey1 = key1;
	oldkey2 = key2;
	calculate_new_key(&key1, cookie, chall);
	calculate_new_key(&key2, cookie, chall);

	debug("Received %llu bytes", (unsigned long long)get_recv_bytes());
	debug("Sent roaming_auth packet");
}
示例#3
0
static void
roaming_auth_required(void)
{
	u_char digest[SHA_DIGEST_LENGTH];
	EVP_MD_CTX md;
	Buffer b;
	const EVP_MD *evp_md = EVP_sha1();
	u_int64_t chall, oldchall;

	chall = packet_get_int64();
	oldchall = packet_get_int64();
	if (oldchall != lastseenchall) {
		key1 = oldkey1;
		key2 = oldkey2;
	}
	lastseenchall = chall;

	buffer_init(&b);
	buffer_put_int64(&b, cookie);
	buffer_put_int64(&b, chall);
	EVP_DigestInit(&md, evp_md);
	EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
	EVP_DigestFinal(&md, digest, NULL);
	buffer_free(&b);

	packet_start(SSH2_MSG_KEX_ROAMING_AUTH);
	packet_put_int64(key1 ^ get_recv_bytes());
	packet_put_raw(digest, sizeof(digest));
	packet_send();

	oldkey1 = key1;
	oldkey2 = key2;
	calculate_new_key(&key1, cookie, chall);
	calculate_new_key(&key2, cookie, chall);

#ifdef WIN32_FIXME
	debug("Received %I64u bytes", (unsigned long long)get_recv_bytes());
#else
	debug("Received %llu bytes", (unsigned long long)get_recv_bytes());
#endif
	debug("Sent roaming_auth packet");
}
示例#4
0
int 
userauth_gssapi(Authctxt *authctxt)
{
	Gssctxt *gssctxt = NULL;
	static int initialized = 0;
	static int mech_idx = 0;
	static gss_OID_set supported = GSS_C_NULL_OID_SET;
	gss_OID mech = GSS_C_NULL_OID;

	/* Things work better if we send one mechanism at a time, rather
	 * than them all at once. This means that if we fail at some point
	 * in the middle of a negotiation, we can come back and try something
	 * different. */

	if (datafellows & SSH_OLD_GSSAPI) return 0;
	
	/* Before we offer a mechanism, check that we can support it. Don't
	 * bother trying to get credentials - as the standard fallback will
	 * deal with that kind of failure.
	 */

	if (!initialized) {
		initialized = 1;
		ssh_gssapi_client_mechs(authctxt->host, &supported);
		if (supported == GSS_C_NULL_OID_SET || supported->count == 0)
			return (0);
	} else if (supported != GSS_C_NULL_OID_SET) {
		/* Try next mech, if any */
		mech_idx++;

		if (mech_idx >= supported->count)
			return (0);
	} else {
		return (0);
	}

	mech = &supported->elements[mech_idx];

	ssh_gssapi_build_ctx(&gssctxt, 1, mech);
	authctxt->methoddata=(void *)gssctxt;
		
	packet_start(SSH2_MSG_USERAUTH_REQUEST);
	packet_put_cstring(authctxt->server_user);
	packet_put_cstring(authctxt->service);
        packet_put_cstring(authctxt->method->name);
	
	packet_put_int(1);

	/* The newest gsskeyex draft stipulates that OIDs should
	 * be DER encoded, so we need to add the object type and
	 * length information back on */
	if (datafellows & SSH_BUG_GSSAPI_BER) {
		packet_put_string(mech->elements, mech->length);
	} else {
		packet_put_int((mech->length)+2);
		packet_put_char(0x06);
		packet_put_char(mech->length);
		packet_put_raw(mech->elements, mech->length);
	}

        packet_send();
        packet_write_wait();

        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,&input_gssapi_response);

        return 1;
}
示例#5
0
static int
sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
{
	Buffer b;
	u_char *blob, *signature;
	u_int bloblen, slen;
	int skip = 0;
	int ret = -1;
	int have_sig = 1;

	debug3("sign_and_send_pubkey");

	if (key_to_blob(k, &blob, &bloblen) == 0) {
		/* we cannot handle this key */
		debug3("sign_and_send_pubkey: cannot handle key");
		return 0;
	}
	/* data to be signed */
	buffer_init(&b);
	if (datafellows & SSH_OLD_SESSIONID) {
		buffer_append(&b, session_id2, session_id2_len);
		skip = session_id2_len;
	} else {
		buffer_put_string(&b, session_id2, session_id2_len);
		skip = buffer_len(&b);
	}
	buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
	buffer_put_cstring(&b, authctxt->server_user);
	buffer_put_cstring(&b,
	    datafellows & SSH_BUG_PKSERVICE ?
	    "ssh-userauth" :
	    authctxt->service);
	if (datafellows & SSH_BUG_PKAUTH) {
		buffer_put_char(&b, have_sig);
	} else {
		buffer_put_cstring(&b, authctxt->method->name);
		buffer_put_char(&b, have_sig);
		buffer_put_cstring(&b, key_ssh_name(k));
	}
	buffer_put_string(&b, blob, bloblen);

	/* generate signature */
	ret = (*sign_callback)(authctxt, k, &signature, &slen,
	    buffer_ptr(&b), buffer_len(&b));
	if (ret == -1) {
		xfree(blob);
		buffer_free(&b);
		return 0;
	}
#ifdef DEBUG_PK
	buffer_dump(&b);
#endif
	if (datafellows & SSH_BUG_PKSERVICE) {
		buffer_clear(&b);
		buffer_append(&b, session_id2, session_id2_len);
		skip = session_id2_len;
		buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
		buffer_put_cstring(&b, authctxt->server_user);
		buffer_put_cstring(&b, authctxt->service);
		buffer_put_cstring(&b, authctxt->method->name);
		buffer_put_char(&b, have_sig);
		if (!(datafellows & SSH_BUG_PKAUTH))
			buffer_put_cstring(&b, key_ssh_name(k));
		buffer_put_string(&b, blob, bloblen);
	}
	xfree(blob);

	/* append signature */
	buffer_put_string(&b, signature, slen);
	xfree(signature);

	/* skip session id and packet type */
	if (buffer_len(&b) < skip + 1)
		fatal("userauth_pubkey: internal error");
	buffer_consume(&b, skip + 1);

	/* put remaining data from buffer into packet */
	packet_start(SSH2_MSG_USERAUTH_REQUEST);
	packet_put_raw(buffer_ptr(&b), buffer_len(&b));
	buffer_free(&b);
	packet_send();

	return 1;
}
示例#6
0
/*
 * Encodes terminal modes for the terminal referenced by fd
 * or tiop in a portable manner, and appends the modes to a packet
 * being constructed.
 */
void
tty_make_modes(int fd, struct termios *tiop)
{
	struct termios tio;
	int baud;
	Buffer buf;
	int tty_op_ospeed, tty_op_ispeed;
	void (*put_arg)(Buffer *, u_int);

	buffer_init(&buf);
	if (compat20) {
		tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
		tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
		put_arg = buffer_put_int;
	} else {
		tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
		tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
		put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
	}

	if (tiop == NULL) {
		if (fd == -1) {
			debug("tty_make_modes: no fd or tio");
			goto end;
		}
		if (tcgetattr(fd, &tio) == -1) {
			logit("tcgetattr: %.100s", strerror(errno));
			goto end;
		}
	} else
		tio = *tiop;

	/* Store input and output baud rates. */
	baud = speed_to_baud(cfgetospeed(&tio));
	buffer_put_char(&buf, tty_op_ospeed);
	buffer_put_int(&buf, baud);
	baud = speed_to_baud(cfgetispeed(&tio));
	buffer_put_char(&buf, tty_op_ispeed);
	buffer_put_int(&buf, baud);

	/* Store values of mode flags. */
#define TTYCHAR(NAME, OP) \
	buffer_put_char(&buf, OP); \
	put_arg(&buf, special_char_encode(tio.c_cc[NAME]));

#define TTYMODE(NAME, FIELD, OP) \
	buffer_put_char(&buf, OP); \
	put_arg(&buf, ((tio.FIELD & NAME) != 0));

#include "ttymodes.h"

#undef TTYCHAR
#undef TTYMODE

end:
	/* Mark end of mode data. */
	buffer_put_char(&buf, TTY_OP_END);
	if (compat20)
		packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
	else
		packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
	buffer_free(&buf);
}