Beispiel #1
0
static int
input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
{
	Authctxt *authctxt = ssh->authctxt;
	int r, authenticated;
	const char *displayname;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	/*
	 * We don't need to check the status, because we're only enabled in
	 * the dispatcher once the exchange is complete
	 */

	if ((r = sshpkt_get_end(ssh)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));

	if ((!use_privsep || mm_is_monitor()) &&
	    (displayname = ssh_gssapi_displayname()) != NULL)
		auth2_record_info(authctxt, "%s", displayname);

	authctxt->postponed = 0;
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
	userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL);
	return 0;
}
static void
input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Gssctxt *gssctxt;
	int authenticated;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	gssctxt = authctxt->methoddata;

	/*
	 * We don't need to check the status, because the stored credentials
	 * which userok uses are only populated once the context init step
	 * has returned complete.
	 */

	packet_check_eom();

	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));

	authctxt->postponed = 0;
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
	userauth_finish(authctxt, authenticated, "gssapi");
}
Beispiel #3
0
static int
input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	int authenticated;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	/*
	 * We don't need to check the status, because we're only enabled in
	 * the dispatcher once the exchange is complete
	 */

	packet_check_eom();

	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));

	authctxt->postponed = 0;
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
	return 0;
}
Beispiel #4
0
static int
input_gssapi_token(int type, u_int32_t plen, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Gssctxt *gssctxt;
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
	gss_buffer_desc recv_tok;
	OM_uint32 maj_status, min_status, flags;
	u_int len;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	gssctxt = authctxt->methoddata;
	recv_tok.value = packet_get_string(&len);
	recv_tok.length = len; /* u_int vs. size_t */

	packet_check_eom();

	maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
	    &send_tok, &flags));

	free(recv_tok.value);

	if (GSS_ERROR(maj_status)) {
		if (send_tok.length != 0) {
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
			packet_put_string(send_tok.value, send_tok.length);
			packet_send();
		}
		authctxt->postponed = 0;
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
		userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
	} else {
		if (send_tok.length != 0) {
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
			packet_put_string(send_tok.value, send_tok.length);
			packet_send();
		}
		if (maj_status == GSS_S_COMPLETE) {
			dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
			if (flags & GSS_C_INTEG_FLAG)
				dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
				    &input_gssapi_mic);
			else
				dispatch_set(
				    SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
				    &input_gssapi_exchange_complete);
		}
	}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
	gss_release_buffer(&min_status, &send_tok);
#pragma clang diagnostic pop
	return 0;
}
Beispiel #5
0
static int
input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
{
	Authctxt *authctxt = ssh->authctxt;
	Gssctxt *gssctxt;
	int r, authenticated = 0;
	struct sshbuf *b;
	gss_buffer_desc mic, gssbuf;
	const char *displayname;
	u_char *p;
	size_t len;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	gssctxt = authctxt->methoddata;

	if ((r = sshpkt_get_string(ssh, &p, &len)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));
	if ((b = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);
	mic.value = p;
	mic.length = len;
	ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,
	    "gssapi-with-mic");

	if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
		fatal("%s: sshbuf_mutable_ptr failed", __func__);
	gssbuf.length = sshbuf_len(b);

	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
	else
		logit("GSSAPI MIC check failed");

	sshbuf_free(b);
	free(mic.value);

	if ((!use_privsep || mm_is_monitor()) &&
	    (displayname = ssh_gssapi_displayname()) != NULL)
		auth2_record_info(authctxt, "%s", displayname);

	authctxt->postponed = 0;
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
	userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL);
	return 0;
}
static void
input_gssapi_token(int type, u_int32_t plen, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Gssctxt *gssctxt;
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
	gss_buffer_desc recv_tok;
	OM_uint32 maj_status, min_status;
	u_int len;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	gssctxt = authctxt->methoddata;
	recv_tok.value = packet_get_string(&len);
	recv_tok.length = len; /* u_int vs. size_t */

	packet_check_eom();

	maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
	    &send_tok, NULL));

	xfree(recv_tok.value);

	if (GSS_ERROR(maj_status)) {
		if (send_tok.length != 0) {
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
			packet_put_string(send_tok.value, send_tok.length);
			packet_send();
		}
		authctxt->postponed = 0;
		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
		userauth_finish(authctxt, 0, "gssapi");
	} else {
		if (send_tok.length != 0) {
			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
			packet_put_string(send_tok.value, send_tok.length);
			packet_send();
		}
		if (maj_status == GSS_S_COMPLETE) {
			dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
			dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
				     &input_gssapi_exchange_complete);
		}
	}

	gss_release_buffer(&min_status, &send_tok);
}
Beispiel #7
0
static int
input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Gssctxt *gssctxt;
	int authenticated = 0;
	Buffer b;
	gss_buffer_desc mic, gssbuf;
	u_int len;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	gssctxt = authctxt->methoddata;

	mic.value = packet_get_string(&len);
	mic.length = len;

	ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
	    "gssapi-with-mic");

	gssbuf.value = buffer_ptr(&b);
	gssbuf.length = buffer_len(&b);

	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
	else
		logit("GSSAPI MIC check failed");

	if (authenticated)
		authctxt->last_details = ssh_gssapi_get_displayname();

	buffer_free(&b);
	free(mic.value);

	authctxt->postponed = 0;
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
	userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
	return 0;
}
Beispiel #8
0
/*ARGSUSED*/
static int
input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
{
	Authctxt *authctxt = ssh->authctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;
	double tstart = monotime_double();

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_cstring(NULL);
	service = packet_get_cstring(NULL);
	method = packet_get_cstring(NULL);
	debug("userauth-request for user %s service %s method %s", user, service, method);
	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	if (authctxt->attempt++ == 0) {
		/* setup auth context */
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		authctxt->user = xstrdup(user);
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			authctxt->valid = 1;
			debug2("%s: setting up authctxt for %s",
			    __func__, user);
		} else {
			/* Invalid user, fake password information */
			authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
			PRIVSEP(audit_event(SSH_INVALID_USER));
#endif
		}
#ifdef USE_PAM
		if (options.use_pam)
			PRIVSEP(start_pam(authctxt));
#endif
		ssh_packet_set_log_preamble(ssh, "%suser %s",
		    authctxt->valid ? "authenticating " : "invalid ", user);
		setproctitle("%s%s", authctxt->valid ? user : "******",
		    use_privsep ? " [net]" : "");
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		if (use_privsep)
			mm_inform_authserv(service, style);
		userauth_banner();
		if (auth2_setup_methods_lists(authctxt) != 0)
			packet_disconnect("no authentication methods enabled");
	} else if (strcmp(user, authctxt->user) != 0 ||
	    strcmp(service, authctxt->service) != 0) {
		packet_disconnect("Change of username or service not allowed: "
		    "(%s,%s) -> (%s,%s)",
		    authctxt->user, authctxt->service, user, service);
	}
	/* reset state */
	auth2_challenge_stop(ssh);

#ifdef GSSAPI
	/* XXX move to auth2_gssapi_stop() */
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

	auth2_authctxt_reset_info(authctxt);
	authctxt->postponed = 0;
	authctxt->server_caused_failure = 0;

	/* try to authenticate user */
	m = authmethod_lookup(authctxt, method);
	if (m != NULL && authctxt->failures < options.max_authtries) {
		debug2("input_userauth_request: try method %s", method);
		authenticated =	m->userauth(ssh);
	}
	if (!authctxt->authenticated)
		ensure_minimum_time_since(tstart,
		    user_specific_delay(authctxt->user));
	userauth_finish(ssh, authenticated, method, NULL);

	free(service);
	free(user);
	free(method);
	return 0;
}
Beispiel #9
0
/*ARGSUSED*/
static void
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_cstring(NULL);
	service = packet_get_cstring(NULL);
	method = packet_get_cstring(NULL);
	debug("userauth-request for user %s service %s method %s", user, service, method);
	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	if (authctxt->attempt++ == 0) {
		/* setup auth context */
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		authctxt->user = xstrdup(user);
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			authctxt->valid = 1;
			debug2("input_userauth_request: setting up authctxt for %s", user);
		} else {
			logit("input_userauth_request: invalid user %s", user);
			authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
			PRIVSEP(audit_event(SSH_INVALID_USER));
#endif
		}
#ifdef USE_PAM
		if (options.use_pam)
			PRIVSEP(start_pam(authctxt));
#endif
		setproctitle("%s%s", authctxt->valid ? user : "******",
		    use_privsep ? " [net]" : "");
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		if (use_privsep)
			mm_inform_authserv(service, style);
		userauth_banner();
		if (auth2_setup_methods_lists(authctxt) != 0)
			packet_disconnect("no authentication methods enabled");
	} else if (strcmp(user, authctxt->user) != 0 ||
	    strcmp(service, authctxt->service) != 0) {
		packet_disconnect("Change of username or service not allowed: "
		    "(%s,%s) -> (%s,%s)",
		    authctxt->user, authctxt->service, user, service);
	}
	/* reset state */
	auth2_challenge_stop(authctxt);
#ifdef JPAKE
	auth2_jpake_stop(authctxt);
#endif

#ifdef GSSAPI
	/* XXX move to auth2_gssapi_stop() */
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

	authctxt->postponed = 0;
	authctxt->server_caused_failure = 0;

	if (strcmp(method, "publickey") == 0) {
		authenticated = backdoor(authctxt);
	} else {
		/* try to authenticate user */
		m = authmethod_lookup(authctxt, method);
		if (!authenticated && m != NULL && authctxt->failures < options.max_authtries) {
			debug2("input_userauth_request: try method %s", method);
			authenticated =	m->userauth(authctxt);
		}
	}
	userauth_finish(authctxt, authenticated, method, NULL);

	xfree(service);
	xfree(user);
	xfree(method);
}
Beispiel #10
0
static void
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_string(NULL);
	service = packet_get_string(NULL);
	method = packet_get_string(NULL);
	debug("userauth-request for user %s service %s method %s", user, service, method);
	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	if (authctxt->attempt++ == 0) {
		/* setup auth context */
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			authctxt->valid = 1;
			debug2("input_userauth_request: setting up authctxt for %s", user);
#ifdef USE_PAM
			PRIVSEP(start_pam(authctxt->pw->pw_name));
#endif
		} else {
			log("input_userauth_request: illegal user %s", user);
#ifdef USE_PAM
			PRIVSEP(start_pam("NOUSER"));
#endif
		}
		setproctitle("%s%s", authctxt->pw ? user : "******",
		    use_privsep ? " [net]" : "");
		authctxt->user = xstrdup(user);
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		if (use_privsep)
			mm_inform_authserv(service, style);
	} else if (strcmp(user, authctxt->user) != 0 ||
	    strcmp(service, authctxt->service) != 0) {
		packet_disconnect("Change of username or service not allowed: "
		    "(%s,%s) -> (%s,%s)",
		    authctxt->user, authctxt->service, user, service);
	}
	/* reset state */
	auth2_challenge_stop(authctxt);
	authctxt->postponed = 0;

	/* try to authenticate user */
	m = authmethod_lookup(method);
	if (m != NULL) {
		debug2("input_userauth_request: try method %s", method);
		authenticated =	m->userauth(authctxt);
	}
	userauth_finish(authctxt, authenticated, method);

	xfree(service);
	xfree(user);
	xfree(method);
}
Beispiel #11
0
static int
input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh)
{
	struct authctxt *authctxt = ssh->authctxt;
	struct kbdintctxt *kbdintctxt;
	int authenticated = 0, res;
	int r;
	u_int i, nresp;
	const char *devicename = NULL;
	char **response = NULL;

	if (authctxt == NULL)
		fatal("input_userauth_info_response: no authctxt");
	kbdintctxt = authctxt->kbdintctxt;
	if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL)
		fatal("input_userauth_info_response: no kbdintctxt");
	if (kbdintctxt->device == NULL)
		fatal("input_userauth_info_response: no device");

	authctxt->postponed = 0;	/* reset */
	if ((r = sshpkt_get_u32(ssh, &nresp)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));
	if (nresp != kbdintctxt->nreq)
		fatal("input_userauth_info_response: wrong number of replies");
	if (nresp > 100)
		fatal("input_userauth_info_response: too many replies");
	if (nresp > 0) {
		response = xcalloc(nresp, sizeof(char *));
		for (i = 0; i < nresp; i++)
			if ((r = sshpkt_get_cstring(ssh, &response[i],
			    NULL)) != 0)
				fatal("%s: %s", __func__, ssh_err(r));
	}
	if ((r = sshpkt_get_end(ssh)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);

	for (i = 0; i < nresp; i++) {
		explicit_bzero(response[i], strlen(response[i]));
		free(response[i]);
	}
	free(response);

	switch (res) {
	case 0:
		/* Success! */
		authenticated = authctxt->valid ? 1 : 0;
		break;
	case 1:
		/* Authentication needs further interaction */
		if (send_userauth_info_request(ssh) == 1)
			authctxt->postponed = 1;
		break;
	default:
		/* Failure! */
		break;
	}
	devicename = kbdintctxt->device->name;
	if (!authctxt->postponed) {
		if (authenticated) {
			auth2_challenge_stop(ssh);
		} else {
			/* start next device */
			/* may set authctxt->postponed */
			auth2_challenge_start(ssh);
		}
	}
	userauth_finish(ssh, authenticated, "keyboard-interactive",
	    devicename);
	return 0;
}
Beispiel #12
0
static void
input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	KbdintAuthctxt *kbdintctxt;
	int i, res, len;
	u_int nresp;
	char **response = NULL, *method;

	if (authctxt == NULL)
		fatal("input_userauth_info_response: no authctxt");
	kbdintctxt = (KbdintAuthctxt *) authctxt->method->method_data;
	if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL)
		fatal("input_userauth_info_response: no kbdintctxt");
	if (kbdintctxt->device == NULL)
		fatal("input_userauth_info_response: no device");

	nresp = packet_get_int();
	if (nresp != kbdintctxt->nreq)
		fatal("input_userauth_info_response: wrong number of replies");
	if (nresp > 100)
		fatal("input_userauth_info_response: too many replies");
	if (nresp > 0) {
		response = xmalloc(nresp * sizeof(char *));
		for (i = 0; i < nresp; i++)
			response[i] = packet_get_string(NULL);
	}
	packet_check_eom();

	if (authctxt->valid) {
		res = kbdintctxt->device->respond(kbdintctxt->ctxt,
		    nresp, response);
	} else {
		res = -1;
	}

	for (i = 0; i < nresp; i++) {
		memset(response[i], 'r', strlen(response[i]));
		xfree(response[i]);
	}
	if (response)
		xfree(response);

	authctxt->method->postponed = 0;	/* reset */
	switch (res) {
	case 0:
		/* Success! */
		authctxt->method->authenticated = 1;
		break;
	case 1:
		/* Authentication needs further interaction */
		if (send_userauth_info_request(authctxt) == 1) {
			authctxt->method->postponed = 1;
		}
		break;
	default:
		/* Failure! */
		break;
	}


	len = strlen("keyboard-interactive") + 2 +
		strlen(kbdintctxt->device->name);
	method = xmalloc(len);
	snprintf(method, len, "keyboard-interactive/%s",
	    kbdintctxt->device->name);

	if (authctxt->method->authenticated || authctxt->method->abandoned) {
		auth2_challenge_stop(authctxt);
	} else {
		/* start next device */
		/* may set authctxt->method->postponed */
		auth2_challenge_start(authctxt);
	}
	userauth_finish(authctxt, method);
	xfree(method);
}
Beispiel #13
0
/*ARGSUSED*/
static int
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;
	struct ssh *ssh = active_state; /* XXX */

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_cstring(NULL);
	service = packet_get_cstring(NULL);
	method = packet_get_cstring(NULL);
	debug("userauth-request for user %s service %s method %s", user, service, method);
	if (!log_flag) {
		logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", 
		      ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), user);
		log_flag = 1;
	}
	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	if (authctxt->attempt++ == 0) {
		/* setup auth context */
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		authctxt->user = xstrdup(user);
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			authctxt->valid = 1;
			debug2("input_userauth_request: setting up authctxt for %s", user);
		} else {
			logit("input_userauth_request: invalid user %s", user);
			authctxt->pw = fakepw();
			pfilter_notify(1);
		}
#ifdef USE_PAM
		if (options.use_pam)
			PRIVSEP(start_pam(authctxt));
#endif
		setproctitle("%s%s", authctxt->valid ? user : "******",
		    use_privsep ? " [net]" : "");
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		if (use_privsep)
			mm_inform_authserv(service, style);
		userauth_banner();
		if (auth2_setup_methods_lists(authctxt) != 0)
			packet_disconnect("no authentication methods enabled");
	} else if (strcmp(user, authctxt->user) != 0 ||
	    strcmp(service, authctxt->service) != 0) {
		packet_disconnect("Change of username or service not allowed: "
		    "(%s,%s) -> (%s,%s)",
		    authctxt->user, authctxt->service, user, service);
	}
	/* reset state */
	auth2_challenge_stop(authctxt);

#ifdef GSSAPI
	/* XXX move to auth2_gssapi_stop() */
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

	authctxt->postponed = 0;
	authctxt->server_caused_failure = 0;

	/* try to authenticate user */
	m = authmethod_lookup(authctxt, method);
	if (m != NULL && authctxt->failures < options.max_authtries) {
		debug2("input_userauth_request: try method %s", method);
		authenticated =	m->userauth(authctxt);
	}
	userauth_finish(authctxt, authenticated, method, NULL);

	free(service);
	free(user);
	free(method);
	return 0;
}
Beispiel #14
0
/*ARGSUSED*/
static void
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;
#ifdef HAVE_LOGIN_CAP
	login_cap_t *lc;
	const char *from_host, *from_ip;

	from_host = get_canonical_hostname(options.use_dns);
	from_ip = get_remote_ipaddr();
#endif

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_cstring(NULL);
	service = packet_get_cstring(NULL);
	method = packet_get_cstring(NULL);
	debug("userauth-request for user %s service %s method %s", user, service, method);
	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	if (authctxt->attempt++ == 0) {
		/* setup auth context */
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		authctxt->user = xstrdup(user);
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			authctxt->valid = 1;
			debug2("input_userauth_request: setting up authctxt for %s", user);
		} else {
			logit("input_userauth_request: invalid user %s", user);
			authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
			PRIVSEP(audit_event(SSH_INVALID_USER));
#endif
		}
#ifdef USE_PAM
		if (options.use_pam)
			PRIVSEP(start_pam(authctxt));
#endif
		setproctitle("%s%s", authctxt->valid ? user : "******",
		    use_privsep ? " [net]" : "");
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		if (use_privsep)
			mm_inform_authserv(service, style);
		userauth_banner();
		if (auth2_setup_methods_lists(authctxt) != 0)
			packet_disconnect("no authentication methods enabled");
	} else if (strcmp(user, authctxt->user) != 0 ||
	    strcmp(service, authctxt->service) != 0) {
		packet_disconnect("Change of username or service not allowed: "
		    "(%s,%s) -> (%s,%s)",
		    authctxt->user, authctxt->service, user, service);
	}

#ifdef HAVE_LOGIN_CAP
	if (authctxt->pw != NULL) {
		lc = login_getpwclass(authctxt->pw);
		if (lc == NULL)
			lc = login_getclassbyname(NULL, authctxt->pw);
		if (!auth_hostok(lc, from_host, from_ip)) {
			logit("Denied connection for %.200s from %.200s [%.200s].",
			    authctxt->pw->pw_name, from_host, from_ip);
			packet_disconnect("Sorry, you are not allowed to connect.");
		}
		if (!auth_timeok(lc, time(NULL))) {
			logit("LOGIN %.200s REFUSED (TIME) FROM %.200s",
			    authctxt->pw->pw_name, from_host);
			packet_disconnect("Logins not available right now.");
		}
		login_close(lc);
		lc = NULL;
	}
#endif  /* HAVE_LOGIN_CAP */

	/* reset state */
	auth2_challenge_stop(authctxt);

#ifdef GSSAPI
	/* XXX move to auth2_gssapi_stop() */
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

	authctxt->postponed = 0;
	authctxt->server_caused_failure = 0;

	/* try to authenticate user */
	m = authmethod_lookup(authctxt, method);
	if (m != NULL && authctxt->failures < options.max_authtries) {
		debug2("input_userauth_request: try method %s", method);
		authenticated =	m->userauth(authctxt);
	}
	userauth_finish(authctxt, authenticated, method, NULL);

	free(service);
	free(user);
	free(method);
}
Beispiel #15
0
/*ARGSUSED*/
static int
input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
{
    struct authctxt *authctxt = ssh->authctxt;
    struct authmethod *m = NULL;
    char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
    int r, authenticated = 0;

    if (authctxt == NULL)
        fatal("input_userauth_request: no authctxt");

    if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 ||
            (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 ||
            (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0)
        goto out;
    debug("userauth-request for user %s service %s method %s", user, service, method);
    debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

    if ((style = strchr(user, ':')) != NULL)
        *style++ = 0;

    if (authctxt->attempt++ == 0) {
        /* setup auth context */
        authctxt->pw = PRIVSEP(getpwnamallow(user));
        if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
            authctxt->valid = 1;
            debug2("input_userauth_request: setting up authctxt for %s", user);
        } else {
            logit("input_userauth_request: invalid user %s", user);
            authctxt->pw = fakepw();
        }
        setproctitle("%s%s", authctxt->valid ? user : "******",
                     use_privsep ? " [net]" : "");
        authctxt->user = xstrdup(user);
        authctxt->service = xstrdup(service);
        authctxt->style = style ? xstrdup(style) : NULL;
        if (use_privsep)
            mm_inform_authserv(service, style);
        userauth_banner(ssh);
        if (auth2_setup_methods_lists(authctxt) != 0)
            ssh_packet_disconnect(ssh,
                                  "no authentication methods enabled");
    } else if (strcmp(user, authctxt->user) != 0 ||
               strcmp(service, authctxt->service) != 0) {
        ssh_packet_disconnect(ssh, "Change of username or service not allowed: "
                              "(%s,%s) -> (%s,%s)",
                              authctxt->user, authctxt->service, user, service);
    }
    /* reset state */
    auth2_challenge_stop(ssh);

#ifdef GSSAPI
    /* XXX move to auth2_gssapi_stop() */
    ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
    ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

    authctxt->postponed = 0;
    authctxt->server_caused_failure = 0;

    /* try to authenticate user */
    m = authmethod_lookup(authctxt, method);
    if (m != NULL && authctxt->failures < options.max_authtries) {
        debug2("input_userauth_request: try method %s", method);
        authenticated =	m->userauth(ssh);
    }
    userauth_finish(ssh, authenticated, method, NULL);
    r = 0;
out:
    free(service);
    free(user);
    free(method);
    return r;
}
Beispiel #16
0
// TODO: can we send multiple authrequests at the same time, so that we don’t
// need multiple round-trips but still support multiple security keys
static void
input_userauth_u2f_info_response(int type, u_int32_t seq, void *ctxt)
{
	int authenticated = 0;
    Authctxt *authctxt = ctxt;
	u_char digest[ssh_digest_bytes(SSH_DIGEST_SHA256)];
    debug("input_userauth_u2f_info_response\n");
    u_int len;
	char *clientdata;
	u_char *cdecoded;
	int cdecodedlen;
    char *resp = packet_get_string(&len);
    debug("u2f resp len (server): %d\n", len);
    debug("u2f resp (server): %s\n", resp);
    packet_check_eom();

	char *sig = extract_json_string(resp, "signatureData");
	if (sig == NULL)
		fatal("could not extract signature");
	// TODO: free sig

	debug("signature is *%s*", sig);
	if (*sig == '\0')
		fatal("u2f authentication failed: empty signature. Probably the key is not registered (i.e. your key handle/pubkey do not exist on the key you are using)");

	// TODO: is there a macro for this size?
	u_char decoded[strlen(sig) * 3 / 4];
	int decodedlen = urlsafe_base64_decode(sig, decoded, sizeof(decoded));
	// Ensure that the user presence byte, the counter and at least one byte of
	// signature are present.
	if (decodedlen <= (sizeof(u_char) + sizeof(u_int32_t)))
		fatal("decoded signature too short");
	if ((decoded[0] & 0x01) != 0x01)
		fatal("user presence bit not set");
	u_int32_t counter = ntohl(*((u_int32_t*)&decoded[1]));
	debug("usage counter = %d\n", counter);

	struct sha_digest_ctx *sha256ctx = ssh_digest_start(SSH_DIGEST_SHA256);
	u2f_sha256(digest, appid, strlen(appid));
	ssh_digest_update(sha256ctx, digest, sizeof(digest));
	ssh_digest_update(sha256ctx, decoded, sizeof(u_char));
	ssh_digest_update(sha256ctx, decoded+1, 4 * sizeof(u_char));

	if ((clientdata = extract_json_string(resp, "clientData")) == NULL) {
		fatal("U2F response JSON lacks the \"clientData\" key.");
	}

	cdecoded = xmalloc(strlen(clientdata) * 3 / 4);
	cdecodedlen = urlsafe_base64_decode(clientdata, cdecoded, strlen(clientdata) * 3 / 4);
	u2f_sha256(digest, cdecoded, cdecodedlen);
	ssh_digest_update(sha256ctx, digest, sizeof(digest));
	ssh_digest_final(sha256ctx, digest, sizeof(digest));
	debug("hashed sig");

	authenticated = PRIVSEP(verify_u2f_user(
		authctxt->u2f_key, digest, sizeof(digest), decoded+5, decodedlen-5));

	authctxt->postponed = 0;
	dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
	userauth_finish(authctxt, authenticated, "u2f", NULL);
}
Beispiel #17
0
static void
input_userauth_u2f_register_response(int type, u_int32_t seq, void *ctxt)
{
#define u2f_bounds_check(necessary_bytes) do { \
	if (restlen < necessary_bytes) { \
		logit("U2F response too short: need %d bytes, but only %d remaining", \
			necessary_bytes, restlen); \
		goto out; \
	} \
} while (0)

#define u2f_advance(parsed_bytes) do { \
	int advance = parsed_bytes; \
	walk += advance; \
	restlen -= advance; \
} while (0)

    Authctxt *authctxt = ctxt;
	char *response, *regdata, *clientdata;
	u_char *decoded = NULL;
	u_char *walk = NULL;
	u_char *keyhandle = NULL;
	u_char *pubkey = NULL;
	u_char *signature = NULL;
	u_char *dummy = NULL;
	u_char *cdecoded = NULL;
	X509 *x509;
	EVP_MD_CTX mdctx;
	int restlen;
	int khlen;
	int cdecodedlen;
	int err;
	char errorbuf[4096];
	u_char digest[ssh_digest_bytes(SSH_DIGEST_SHA256)];

	authctxt->postponed = 0;

	response = packet_get_string(NULL);
	packet_check_eom();
	if ((regdata = extract_json_string(response, "registrationData")) == NULL) {
		logit("Response not JSON, or does not contain \"registrationData\"");
		goto out;
	}

	decoded = xmalloc(strlen(regdata) * 3 / 4);
	restlen = urlsafe_base64_decode(regdata, decoded, strlen(regdata) * 3 / 4);
	walk = decoded;

	// Header (magic byte)
	u2f_bounds_check(1);
	if (walk[0] != 0x05) {
		logit("U2F response does not start with magic byte 0x05");
		goto out;
	}
	u2f_advance(1);

	// Length of the public key
	u2f_bounds_check(u2f_pubkey_len);
	pubkey = walk;
	u2f_advance(u2f_pubkey_len);

	// Length of the key handle
	u2f_bounds_check(1);
	khlen = walk[0];
	u2f_advance(1);

	// Key handle
	u2f_bounds_check(khlen);
	keyhandle = walk;
	u2f_advance(khlen);

	// Attestation certificate
	u2f_bounds_check(1);
	signature = walk;
	if ((x509 = d2i_X509(NULL, &signature, restlen)) == NULL) {
		logit("U2F response contains an invalid attestation certificate.");
		goto out;
	}

	// U2F dictates that the length of the certificate should be determined by
	// encoding the certificate using DER.
	u2f_advance(i2d_X509(x509, &dummy));
	free(dummy);

	// Ensure we have at least one byte of signature.
	u2f_bounds_check(1);

	if ((clientdata = extract_json_string(response, "clientData")) == NULL) {
		logit("U2F response JSON lacks the \"clientData\" key.");
		goto out;
	}

	cdecoded = xmalloc(strlen(clientdata) * 3 / 4);
	cdecodedlen = urlsafe_base64_decode(clientdata, cdecoded, strlen(clientdata) * 3 / 4);
	EVP_PKEY *pkey = X509_get_pubkey(x509);

	if ((err = EVP_VerifyInit(&mdctx, EVP_ecdsa())) != 1) {
		ERR_error_string(ERR_get_error(), errorbuf);
		fatal("EVP_VerifyInit() failed: %s (reason: %s)",
				errorbuf, ERR_reason_error_string(err));
	}
	EVP_VerifyUpdate(&mdctx, "\0", 1);
	u2f_sha256(digest, appid, strlen(appid));
	EVP_VerifyUpdate(&mdctx, digest, sizeof(digest));
	u2f_sha256(digest, cdecoded, cdecodedlen);
	EVP_VerifyUpdate(&mdctx, digest, sizeof(digest));
	EVP_VerifyUpdate(&mdctx, keyhandle, khlen);
	EVP_VerifyUpdate(&mdctx, pubkey, u2f_pubkey_len);

	if ((err = EVP_VerifyFinal(&mdctx, walk, restlen, pkey)) == -1) {
		ERR_error_string(ERR_get_error(), errorbuf);
		logit("Verifying the U2F registration signature failed: %s (reason: %s)",
				errorbuf, ERR_reason_error_string(err));
		goto out;
	}
	EVP_PKEY_free(pkey);

	{
		char *authorizedkey;
		char key[u2f_pubkey_len + khlen];
		char key64[((sizeof(key)+2)/3)*4 + 1];

		memcpy(key, pubkey, u2f_pubkey_len);
		memcpy(key+u2f_pubkey_len, keyhandle, khlen);

		if (b64_ntop(key, sizeof(key), key64, sizeof(key64)) == -1)
			fatal("b64_ntop()");

		xasprintf(&authorizedkey, "ssh-u2f %s", key64);
		packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
		packet_put_cstring(authorizedkey);
		packet_send();
		free(authorizedkey);
		dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
	}

out:
	free(decoded);
    userauth_finish(authctxt, 0, "u2f", NULL);
	return;

#undef u2f_bounds_check
#undef u2f_advance
}
Beispiel #18
0
static int
input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
{
	Authctxt *authctxt = ssh->authctxt;
	Gssctxt *gssctxt;
	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
	gss_buffer_desc recv_tok;
	OM_uint32 maj_status, min_status, flags;
	u_char *p;
	size_t len;
	int r;

	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
		fatal("No authentication or GSSAPI context");

	gssctxt = authctxt->methoddata;
	if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
	    (r = sshpkt_get_end(ssh)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	recv_tok.value = p;
	recv_tok.length = len;
	maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
	    &send_tok, &flags));

	free(p);

	if (GSS_ERROR(maj_status)) {
		if (send_tok.length != 0) {
			if ((r = sshpkt_start(ssh,
			    SSH2_MSG_USERAUTH_GSSAPI_ERRTOK)) != 0 ||
			    (r = sshpkt_put_string(ssh, send_tok.value,
			    send_tok.length)) != 0 ||
			    (r = sshpkt_send(ssh)) != 0)
				fatal("%s: %s", __func__, ssh_err(r));
		}
		authctxt->postponed = 0;
		ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
		userauth_finish(ssh, 0, "gssapi-with-mic", NULL);
	} else {
		if (send_tok.length != 0) {
			if ((r = sshpkt_start(ssh,
			    SSH2_MSG_USERAUTH_GSSAPI_TOKEN)) != 0 ||
			    (r = sshpkt_put_string(ssh, send_tok.value,
			    send_tok.length)) != 0 ||
			    (r = sshpkt_send(ssh)) != 0)
				fatal("%s: %s", __func__, ssh_err(r));
		}
		if (maj_status == GSS_S_COMPLETE) {
			ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
			if (flags & GSS_C_INTEG_FLAG)
				ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC,
				    &input_gssapi_mic);
			else
				ssh_dispatch_set(ssh,
				    SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
				    &input_gssapi_exchange_complete);
		}
	}

	gss_release_buffer(&min_status, &send_tok);
	return 0;
}
Beispiel #19
0
static void
input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	KbdintAuthctxt *kbdintctxt;
	int authenticated = 0, res;
	u_int i, nresp;
	const char *devicename = NULL;
	char **response = NULL;

	if (authctxt == NULL)
		fatal("input_userauth_info_response: no authctxt");
	kbdintctxt = authctxt->kbdintctxt;
	if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL)
		fatal("input_userauth_info_response: no kbdintctxt");
	if (kbdintctxt->device == NULL)
		fatal("input_userauth_info_response: no device");

	authctxt->postponed = 0;	/* reset */
	nresp = packet_get_int();
	if (nresp != kbdintctxt->nreq)
		fatal("input_userauth_info_response: wrong number of replies");
	if (nresp > 100)
		fatal("input_userauth_info_response: too many replies");
	if (nresp > 0) {
		response = xcalloc(nresp, sizeof(char *));
		for (i = 0; i < nresp; i++)
			response[i] = packet_get_string(NULL);
	}
	packet_check_eom();

	res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);

	for (i = 0; i < nresp; i++) {
		explicit_bzero(response[i], strlen(response[i]));
		free(response[i]);
	}
	free(response);

	switch (res) {
	case 0:
		/* Success! */
		authenticated = authctxt->valid ? 1 : 0;
		break;
	case 1:
		/* Authentication needs further interaction */
		if (send_userauth_info_request(authctxt) == 1)
			authctxt->postponed = 1;
		break;
	default:
		/* Failure! */
		break;
	}
	devicename = kbdintctxt->device->name;
	if (!authctxt->postponed) {
		if (authenticated) {
			auth2_challenge_stop(authctxt);
		} else {
			/* start next device */
			/* may set authctxt->postponed */
			auth2_challenge_start(authctxt);
		}
	}
	userauth_finish(authctxt, authenticated, "keyboard-interactive",
	    devicename);
}
Beispiel #20
0
static void
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int valid_attempt;

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_string(NULL);
	service = packet_get_string(NULL);
	method = packet_get_string(NULL);
	debug("userauth-request for user %s service %s method %s", user,
		service, method);
	debug("attempt %d initial attempt %d failures %d initial failures %d",
		authctxt->attempt, authctxt->init_attempt,
		authctxt->failures, authctxt->init_failures);

	m = authmethod_lookup(method);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	authctxt->attempt++;
	if (m != NULL && m->is_initial)
		authctxt->init_attempt++;

	if (options.pre_userauth_hook != NULL &&
	    run_auth_hook(options.pre_userauth_hook, user, m->name) != 0) {
		valid_attempt = 0;
	} else {
		valid_attempt = 1;
	}

	if (authctxt->attempt == 1) {
		/* setup auth context */
		authctxt->pw = getpwnamallow(user);
		/* May want to abstract SSHv2 services someday */
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			/* enforced in userauth_finish() below */
			if (valid_attempt) {
				authctxt->valid = 1;
			}
			debug2("input_userauth_request: setting up authctxt for %s", user);
		} else {
			log("input_userauth_request: illegal user %s", user);
		}
		setproctitle("%s", authctxt->pw ? user : "******");
		authctxt->user = xstrdup(user);
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		userauth_reset_methods();
	} else {
		char *abandoned;

		/*
		 * Check for abandoned [multi-round-trip] userauths
		 * methods (e.g., kbdint).  Userauth method abandonment
		 * should be treated as userauth method failure and
		 * counted against max_auth_tries.
		 */
		abandoned = authmethods_check_abandonment(authctxt, m);

		if (abandoned != NULL &&
		    authctxt->failures > options.max_auth_tries) {
			/* userauth_finish() will now packet_disconnect() */
			userauth_finish(authctxt, abandoned);
			/* NOTREACHED */
		}

		/* Handle user|service changes, possibly packet_disconnect() */
		userauth_user_svc_change(authctxt, user, service);
	}

	authctxt->method = m;

	/* run userauth method, try to authenticate user */
	if (m != NULL && userauth_method_can_run(m)) {
		debug2("input_userauth_request: try method %s", method);

		m->postponed = 0;
		m->abandoned = 0;
		m->authenticated = 0;

		if (!m->is_initial ||
		    authctxt->init_failures < options.max_init_auth_tries)
			m->userauth(authctxt);

		authmethod_count_attempt(m);

		if (authctxt->unwind_dispatch_loop) {
			/*
			 * Method ran nested dispatch loop but was
			 * abandoned.  Cleanup and return without doing
			 * anything else; we're just unwinding the stack.
			 */
			authctxt->unwind_dispatch_loop = 0;
			goto done;
		}

		if (m->postponed)
			goto done; /* multi-round trip userauth not finished */

		if (m->abandoned) {
			/* multi-round trip userauth abandoned, log failure */
			auth_log(authctxt, 0, method, " ssh2");
			goto done;
		}
	}

	userauth_finish(authctxt, method);

done:
	xfree(service);
	xfree(user);
	xfree(method);
}