void
server_loop2(Authctxt *authctxt)
{
	fd_set *readset = NULL, *writeset = NULL;
	int rekeying = 0, max_fd, nalloc = 0;

	debug("Entering interactive session for SSH2.");

	mysignal(SIGCHLD, sigchld_handler);
	child_terminated = 0;
	connection_in = packet_get_connection_in();
	connection_out = packet_get_connection_out();

	notify_setup();

	max_fd = MAX(connection_in, connection_out);
	max_fd = MAX(max_fd, notify_pipe[0]);

	xxx_authctxt = authctxt;

	server_init_dispatch();

	for (;;) {
		process_buffered_input_packets();

		rekeying = (xxx_kex != NULL && !xxx_kex->done);

		if (!rekeying && packet_not_very_much_data_to_write())
			channel_output_poll();
		wait_until_can_do_something(&readset, &writeset, &max_fd,
		    &nalloc, 0);

		collect_children();
		if (!rekeying) {
			channel_after_select(readset, writeset);
			if (packet_need_rekeying()) {
				debug("need rekeying");
				xxx_kex->done = 0;
				kex_send_kexinit(xxx_kex);
			}
		}
		process_input(readset);
		if (connection_closed)
			break;
		process_output(writeset);
	}
	collect_children();

	if (readset)
		xfree(readset);
	if (writeset)
		xfree(writeset);

	/* free all channels, no more reads and writes */
	channel_free_all();

	/* free remaining sessions, e.g. remove wtmp entries */
	session_destroy_all(NULL);
}
Example #2
0
/* ARGSUSED */
int
kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
{
	struct ssh *ssh = ctxt;
	struct kex *kex = ssh->kex;
	const u_char *ptr;
	u_int i;
	size_t dlen;
	int r;

	debug("SSH2_MSG_KEXINIT received");
	if (kex == NULL)
		return SSH_ERR_INVALID_ARGUMENT;

	ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
	ptr = sshpkt_ptr(ssh, &dlen);
	if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
		return r;

	/* discard packet */
	for (i = 0; i < KEX_COOKIE_LEN; i++)
		if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
			return r;
	for (i = 0; i < PROPOSAL_MAX; i++)
		if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
			return r;
	/*
	 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
	 * KEX method has the server move first, but a server might be using
	 * a custom method or one that we otherwise don't support. We should
	 * be prepared to remember first_kex_follows here so we can eat a
	 * packet later.
	 * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
	 * for cases where the server *doesn't* go first. I guess we should
	 * ignore it when it is set for these cases, which is what we do now.
	 */
	if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||	/* first_kex_follows */
	    (r = sshpkt_get_u32(ssh, NULL)) != 0 ||	/* reserved */
	    (r = sshpkt_get_end(ssh)) != 0)
			return r;

	if (!(kex->flags & KEX_INIT_SENT))
		if ((r = kex_send_kexinit(ssh)) != 0)
			return r;
	if ((r = kex_choose_conf(ssh)) != 0)
		return r;

	if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
		return (kex->kex[kex->kex_type])(ssh);

	return SSH_ERR_INTERNAL_ERROR;
}
Example #3
0
int
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
{
	int r;

	if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
		return r;
	if ((r = kex_send_kexinit(ssh)) != 0) {		/* we start */
		kex_free(ssh->kex);
		ssh->kex = NULL;
		return r;
	}
	return 0;
}
Example #4
0
/*
 * Request key re-exchange, returns 0 on success or a ssherr.h error
 * code otherwise. Must not be called if KEX is incomplete or in-progress.
 */
int
kex_start_rekex(struct ssh *ssh)
{
	if (ssh->kex == NULL) {
		error("%s: no kex", __func__);
		return SSH_ERR_INTERNAL_ERROR;
	}
	if (ssh->kex->done == 0) {
		error("%s: requested twice", __func__);
		return SSH_ERR_INTERNAL_ERROR;
	}
	ssh->kex->done = 0;
	return kex_send_kexinit(ssh);
}
Example #5
0
static void
kex_kexinit_finish(Kex *kex)
{
	if (!(kex->flags & KEX_INIT_SENT))
		kex_send_kexinit(kex);

	kex_choose_conf(kex);

	if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
	    kex->kex[kex->kex_type] != NULL) {
		(kex->kex[kex->kex_type])(kex);
	} else {
		fatal("Unsupported key exchange %d", kex->kex_type);
	}
}
Example #6
0
Kex *
kex_setup(char *proposal[PROPOSAL_MAX])
{
	Kex *kex;

	kex = xcalloc(1, sizeof(*kex));
	buffer_init(&kex->peer);
	buffer_init(&kex->my);
	kex_prop2buf(&kex->my, proposal);
	kex->done = 0;

	kex_send_kexinit(kex);					/* we start */
	kex_reset_dispatch();

	return kex;
}
Example #7
0
int
kex_setup(ncrack_ssh_state *nstate, char *proposal[PROPOSAL_MAX])
{
	int r;

	if ((r = kex_new(nstate, proposal, &nstate->kex)) != 0) {
		return r;
  }
	if ((r = kex_send_kexinit(nstate)) != 0) {		/* we start */
		kex_free(nstate->kex);
		nstate->kex = NULL;
		return r;
	}

	return 0;
}
Example #8
0
/* ARGSUSED */
int
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
{
	Kex *kex = ssh->kex;
	u_char *ptr;
	u_int i;
	size_t dlen;
	int r;

	debug("SSH2_MSG_KEXINIT received");
	if (kex == NULL)
		return SSH_ERR_INVALID_ARGUMENT;

	ptr = sshpkt_ptr(ssh, &dlen);
	if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
		return r;

	/* discard packet */
	for (i = 0; i < KEX_COOKIE_LEN; i++)
		if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
			return r;
	for (i = 0; i < PROPOSAL_MAX; i++)
		if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
			return r;
	if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
	    (r = sshpkt_get_u32(ssh, NULL)) != 0 ||
	    (r = sshpkt_get_end(ssh)) != 0)
			return r;

	if (!(kex->flags & KEX_INIT_SENT))
		if ((r = kex_send_kexinit(ssh)) != 0)
			return r;
	if ((r = kex_choose_conf(ssh)) != 0)
		return r;

	if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
	    kex->kex[kex->kex_type] != NULL)
		return (kex->kex[kex->kex_type])(ssh);

	return SSH_ERR_INTERNAL_ERROR;
}
Example #9
0
void
server_loop2(Authctxt *authctxt)
{
	fd_set *readset = NULL, *writeset = NULL;
	int rekeying = 0, max_fd;
	u_int nalloc = 0;
	u_int64_t rekey_timeout_ms = 0;

	debug("Entering interactive session for SSH2.");

	mysignal(SIGCHLD, sigchld_handler);
	child_terminated = 0;
	connection_in = packet_get_connection_in();
	connection_out = packet_get_connection_out();

	if (!use_privsep) {
		signal(SIGTERM, sigterm_handler);
		signal(SIGINT, sigterm_handler);
		signal(SIGQUIT, sigterm_handler);
	}

	notify_setup();

	max_fd = MAX(connection_in, connection_out);
	max_fd = MAX(max_fd, notify_pipe[0]);

	server_init_dispatch();
	for (;;) {
		process_buffered_input_packets();

		rekeying = (xxx_kex != NULL && !xxx_kex->done);

		if (!rekeying && packet_not_very_much_data_to_write())
			channel_output_poll();
		if (options.rekey_interval > 0 && compat20 && !rekeying)
			rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
		else
			rekey_timeout_ms = 0;

		wait_until_can_do_something(&readset, &writeset, &max_fd,
		    &nalloc, rekey_timeout_ms);

		if (received_sigterm) {
			logit("Exiting on signal %d", (int)received_sigterm);
			/* Clean up sessions, utmp, etc. */
			cleanup_exit(255);
		}

		collect_children();
		if (!rekeying) {
			channel_after_select(readset, writeset);
			if (packet_need_rekeying()) {
				debug("need rekeying");
				xxx_kex->done = 0;
				kex_send_kexinit(xxx_kex);
			}
		}
		process_input(readset);
		if (connection_closed)
			break;
		process_output(writeset);
	}
	collect_children();

	free(readset);
	free(writeset);

	/* free all channels, no more reads and writes */
	channel_free_all();

	/* free remaining sessions, e.g. remove wtmp entries */
	session_destroy_all(NULL);
}
Example #10
0
static void
do_kex_with_key(char *kex, int keytype, int bits)
{
	struct ssh *client = NULL, *server = NULL, *server2 = NULL;
	struct sshkey *private, *public;
	struct sshbuf *state;
	struct kex_params kex_params;
	char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };

	TEST_START("sshkey_generate");
	ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0);
	TEST_DONE();

	TEST_START("sshkey_from_private");
	ASSERT_INT_EQ(sshkey_from_private(private, &public), 0);
	TEST_DONE();

	TEST_START("ssh_init");
	memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
	if (kex != NULL)
		kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
	ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
	ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
	ASSERT_PTR_NE(client, NULL);
	ASSERT_PTR_NE(server, NULL);
	TEST_DONE();

	TEST_START("ssh_add_hostkey");
	ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0);
	ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0);
	TEST_DONE();

	TEST_START("kex");
	run_kex(client, server);
	TEST_DONE();

	TEST_START("rekeying client");
	ASSERT_INT_EQ(kex_send_kexinit(client), 0);
	run_kex(client, server);
	TEST_DONE();

	TEST_START("rekeying server");
	ASSERT_INT_EQ(kex_send_kexinit(server), 0);
	run_kex(client, server);
	TEST_DONE();

	TEST_START("ssh_packet_get_state");
	state = sshbuf_new();
	ASSERT_PTR_NE(state, NULL);
	ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
	ASSERT_INT_GE(sshbuf_len(state), 1);
	TEST_DONE();

	TEST_START("ssh_packet_set_state");
	server2 = NULL;
	ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
	ASSERT_PTR_NE(server2, NULL);
	ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0);
	kex_free(server2->kex);	/* XXX or should ssh_packet_set_state()? */
	ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
	ASSERT_INT_EQ(sshbuf_len(state), 0);
	sshbuf_free(state);
	ASSERT_PTR_NE(server2->kex, NULL);
	/* XXX we need to set the callbacks */
	server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
	server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
	server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
	server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
#ifdef OPENSSL_HAS_ECC
	server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
#endif
	server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
	server2->kex->load_host_public_key = server->kex->load_host_public_key;
	server2->kex->load_host_private_key = server->kex->load_host_private_key;
	server2->kex->sign = server->kex->sign;
	TEST_DONE();

	TEST_START("rekeying server2");
	ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
	run_kex(client, server2);
	ASSERT_INT_EQ(kex_send_kexinit(client), 0);
	run_kex(client, server2);
	TEST_DONE();

	TEST_START("cleanup");
	sshkey_free(private);
	sshkey_free(public);
	ssh_free(client);
	ssh_free(server);
	ssh_free(server2);
	TEST_DONE();
}
Example #11
0
void
server_loop2(Authctxt *authctxt)
{
    fd_set *readset = NULL, *writeset = NULL;
    int rekeying = 0, max_fd, nalloc = 0;
    double start_time, total_time;

    debug("Entering interactive session for SSH2.");
    start_time = get_current_time();

    mysignal(SIGCHLD, sigchld_handler);
    child_terminated = 0;
    connection_in = packet_get_connection_in();
    connection_out = packet_get_connection_out();

    if (!use_privsep) {
        signal(SIGTERM, sigterm_handler);
        signal(SIGINT, sigterm_handler);
        signal(SIGQUIT, sigterm_handler);
    }

    notify_setup();

    max_fd = MAX(connection_in, connection_out);
    max_fd = MAX(max_fd, notify_pipe[0]);

    server_init_dispatch();

    for (;;) {
        process_buffered_input_packets();

        rekeying = (xxx_kex != NULL && !xxx_kex->done);

        if (!rekeying && packet_not_very_much_data_to_write())
            channel_output_poll();
        wait_until_can_do_something(&readset, &writeset, &max_fd,
                                    &nalloc, 0);

        if (received_sigterm) {
            logit("Exiting on signal %d", received_sigterm);
            /* Clean up sessions, utmp, etc. */
            cleanup_exit(255);
        }

        collect_children();
        if (!rekeying) {
            channel_after_select(readset, writeset);
            if (packet_need_rekeying()) {
                debug("need rekeying");
                xxx_kex->done = 0;
                kex_send_kexinit(xxx_kex);
            }
        }
        process_input(readset);
        if (connection_closed)
            break;
        process_output(writeset);
    }
    collect_children();

    if (readset)
        xfree(readset);
    if (writeset)
        xfree(writeset);

    /* free all channels, no more reads and writes */
    channel_free_all();

    /* free remaining sessions, e.g. remove wtmp entries */
    session_destroy_all(NULL);
    total_time = get_current_time() - start_time;
    logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f",
          get_remote_ipaddr(), get_remote_port(),
          stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time,
          fdout_bytes / total_time);
}
void do_kex2_exchange()
{
	Kex *kex ;
	int seqnr;

	if (options.ciphers != NULL) {
		myproposal[PROPOSAL_ENC_ALGS_CTOS] =
			myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
	}
	myproposal[PROPOSAL_ENC_ALGS_CTOS] =
		compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
	myproposal[PROPOSAL_ENC_ALGS_STOC] =
		compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);

	if (options.macs != NULL) {
		myproposal[PROPOSAL_MAC_ALGS_CTOS] =
			myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
	}
	if (options.compression == COMP_NONE) {
		myproposal[PROPOSAL_COMP_ALGS_CTOS] =
			myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
	} else if (options.compression == COMP_DELAYED) {
		myproposal[PROPOSAL_COMP_ALGS_CTOS] =
			myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,[email protected]";
	}

	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();

	kex = xcalloc(1, sizeof(*kex));
	buffer_init(&kex->peer);
	buffer_init(&kex->my);
	kex_prop2buf(&kex->my, myproposal);
	kex->done = 0;
	kex->server = 1;
	kex->client_version_string=g_data.client_version_string;
	kex->server_version_string=g_data.server_version_string;
	kex->load_host_key=&get_hostkey_by_type;
	kex->host_key_index=&get_hostkey_index;

	kex_send_kexinit(kex);

	//packet_read_expect(SSH2_MSG_KEXINIT);
	if (SSH2_MSG_KEXINIT != packet_read_seqnr(&seqnr)) {
		goto err;
	}
	kex_input_init(0, seqnr, kex);

	kex_choose_conf(kex);

	switch (kex->kex_type) {
		case KEX_DH_GRP1_SHA1:
		case KEX_DH_GRP14_SHA1:
			kexdh_server(kex);
			break;
		case KEX_DH_GEX_SHA1:
		case KEX_DH_GEX_SHA256:
			kexgex_server(kex);
			break;
		default:
			goto err;
	}

	g_data.kex = kex;

err:
	return ;
}
Example #13
0
static void
do_kex_with_key(const char *kex, struct sshkey *prvkey, int *c2s, int *s2c,
    int direction, int packet_index,
    const char *dump_path, struct sshbuf *replace_data)
{
	struct ssh *client = NULL, *server = NULL, *server2 = NULL;
	struct sshkey *pubkey = NULL;
	struct sshbuf *state;
	struct kex_params kex_params;
	char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
	char *keyname = NULL;

	TEST_START("sshkey_from_private");
	ASSERT_INT_EQ(sshkey_from_private(prvkey, &pubkey), 0);
	TEST_DONE();

	TEST_START("ssh_init");
	memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
	if (kex != NULL)
		kex_params.proposal[PROPOSAL_KEX_ALGS] = strdup(kex);
	keyname = strdup(sshkey_ssh_name(prvkey));
	ASSERT_PTR_NE(keyname, NULL);
	kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
	ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
	ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
	ASSERT_PTR_NE(client, NULL);
	ASSERT_PTR_NE(server, NULL);
	TEST_DONE();

	TEST_START("ssh_add_hostkey");
	ASSERT_INT_EQ(ssh_add_hostkey(server, prvkey), 0);
	ASSERT_INT_EQ(ssh_add_hostkey(client, pubkey), 0);
	TEST_DONE();

	TEST_START("kex");
	run_kex(client, server, s2c, c2s, direction, packet_index,
	    dump_path, replace_data);
	TEST_DONE();

	TEST_START("rekeying client");
	ASSERT_INT_EQ(kex_send_kexinit(client), 0);
	run_kex(client, server, s2c, c2s, direction, packet_index,
	    dump_path, replace_data);
	TEST_DONE();

	TEST_START("rekeying server");
	ASSERT_INT_EQ(kex_send_kexinit(server), 0);
	run_kex(client, server, s2c, c2s, direction, packet_index,
	    dump_path, replace_data);
	TEST_DONE();

	TEST_START("ssh_packet_get_state");
	state = sshbuf_new();
	ASSERT_PTR_NE(state, NULL);
	ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
	ASSERT_INT_GE(sshbuf_len(state), 1);
	TEST_DONE();

	TEST_START("ssh_packet_set_state");
	server2 = NULL;
	ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
	ASSERT_PTR_NE(server2, NULL);
	ASSERT_INT_EQ(ssh_add_hostkey(server2, prvkey), 0);
	kex_free(server2->kex);	/* XXX or should ssh_packet_set_state()? */
	ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
	ASSERT_INT_EQ(sshbuf_len(state), 0);
	sshbuf_free(state);
	ASSERT_PTR_NE(server2->kex, NULL);
	/* XXX we need to set the callbacks */
	server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
	server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
	server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
	server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
#ifdef OPENSSL_HAS_ECC
	server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
#endif
	server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
	server2->kex->load_host_public_key = server->kex->load_host_public_key;
	server2->kex->load_host_private_key = server->kex->load_host_private_key;
	server2->kex->sign = server->kex->sign;
	TEST_DONE();

	TEST_START("rekeying server2");
	ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
	run_kex(client, server2, s2c, c2s, direction, packet_index,
	    dump_path, replace_data);
	ASSERT_INT_EQ(kex_send_kexinit(client), 0);
	run_kex(client, server2, s2c, c2s, direction, packet_index,
	    dump_path, replace_data);
	TEST_DONE();

	TEST_START("cleanup");
	sshkey_free(pubkey);
	ssh_free(client);
	ssh_free(server);
	ssh_free(server2);
	free(keyname);
	TEST_DONE();
}