Esempio n. 1
0
void
userauth_finish(Authctxt *authctxt, int authenticated, 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 USE_PAM
	if (!use_privsep && authenticated && authctxt->user && 
	    !do_pam_account(authctxt->user, NULL))
		authenticated = 0;
#endif /* USE_PAM */

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

	/* 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 {
		if (authctxt->failures++ > AUTH_FAIL_MAX) {
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
		}
#ifdef _UNICOS
		if (strcmp(method, "password") == 0)
			cray_login_failure(authctxt->user, IA_UDBERR);
#endif /* _UNICOS */
		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);
	}
}
Esempio n. 2
0
Authctxt *
monitor_child_preauth(struct monitor *pmonitor)
{
	struct mon_table *ent;
	int authenticated = 0;

	debug3("preauth child monitor started");

	if (compat20) {
		mon_dispatch = mon_dispatch_proto20;

		/* Permit requests for moduli and signatures */
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
	} else {
		mon_dispatch = mon_dispatch_proto15;

		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
	}

	authctxt = authctxt_new();

	/* The first few requests do not require asynchronous access */
	while (!authenticated) {
		authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
		if (authenticated) {
			if (!(ent->flags & MON_AUTHDECIDE))
				fatal("%s: unexpected authentication from %d",
				    __func__, ent->type);
			if (authctxt->pw->pw_uid == 0 &&
			    !auth_root_allowed(auth_method))
				authenticated = 0;
#ifdef USE_PAM
			if (!do_pam_account(authctxt->pw->pw_name, NULL))
				authenticated = 0;
#endif
		}

		if (ent->flags & MON_AUTHDECIDE) {
			auth_log(authctxt, authenticated, auth_method,
			    compat20 ? " ssh2" : "");
			if (!authenticated)
				authctxt->failures++;
		}
	}

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

	debug("%s: %s has been authenticated by privileged process",
	    __func__, authctxt->user);

	mm_get_keystate(pmonitor);

	return (authctxt);
}
Esempio n. 3
0
void
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
{
	struct mon_table *ent;
	int authenticated = 0;

	debug3("preauth child monitor started");

	authctxt = _authctxt;
	memset(authctxt, 0, sizeof(*authctxt));

	authctxt->loginmsg = &loginmsg;

	if (compat20) {
		mon_dispatch = mon_dispatch_proto20;

		/* Permit requests for moduli and signatures */
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
	} else {
		mon_dispatch = mon_dispatch_proto15;

		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
	}

	/* The first few requests do not require asynchronous access */
	while (!authenticated) {
		authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
		if (authenticated) {
			if (!(ent->flags & MON_AUTHDECIDE))
				fatal("%s: unexpected authentication from %d",
				    __func__, ent->type);
			if (authctxt->pw->pw_uid == 0 &&
			    !auth_root_allowed(auth_method))
				authenticated = 0;
#ifdef USE_PAM
			/* PAM needs to perform account checks after auth */
			if (options.use_pam && authenticated) {
				Buffer m;

				buffer_init(&m);
				mm_request_receive_expect(pmonitor->m_sendfd,
				    MONITOR_REQ_PAM_ACCOUNT, &m);
				authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
				buffer_free(&m);
			}
#endif
		}

		if (ent->flags & MON_AUTHDECIDE) {
			auth_log(authctxt, authenticated, auth_method,
			    compat20 ? " ssh2" : "");
			if (!authenticated)
				authctxt->failures++;
		}
	}

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

	debug("%s: %s has been authenticated by privileged process",
	    __func__, authctxt->user);

	mm_get_keystate(pmonitor);
}
Esempio n. 4
0
/*
 * read packets, try to authenticate the user and
 * return only if authentication is successful
 */
static void
do_authloop(Authctxt *authctxt)
{
	int authenticated = 0;
	int prev = 0, type = 0;
	const struct AuthMethod1 *meth;

	debug("Attempting authentication for %s%.100s.",
	    authctxt->valid ? "" : "invalid user ", authctxt->user);

	/* If the user has no password, accept authentication immediately. */
	if (options.permit_empty_passwd && options.password_authentication &&
#ifdef KRB5
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
	    PRIVSEP(auth_password(authctxt, ""))) {
#ifdef USE_PAM
		if (options.use_pam && (PRIVSEP(do_pam_account())))
#endif
		{
			auth_log(authctxt, 1, 0, "without authentication",
			    NULL);
			return;
		}
	}

	/* Indicate that authentication is needed. */
	packet_start(SSH_SMSG_FAILURE);
	packet_send();
	packet_write_wait();

	for (;;) {
		/* default to fail */
		authenticated = 0;


		/* Get a packet from the client. */
		prev = type;
		type = packet_read();

		/*
		 * If we started challenge-response authentication but the
		 * next packet is not a response to our challenge, release
		 * the resources allocated by get_challenge() (which would
		 * normally have been released by verify_response() had we
		 * received such a response)
		 */
		if (prev == SSH_CMSG_AUTH_TIS &&
		    type != SSH_CMSG_AUTH_TIS_RESPONSE)
			abandon_challenge_response(authctxt);

		if (authctxt->failures >= options.max_authtries)
			goto skip;
		if ((meth = lookup_authmethod1(type)) == NULL) {
			logit("Unknown message during authentication: "
			    "type %d", type);
			goto skip;
		}

		if (!*(meth->enabled)) {
			verbose("%s authentication disabled.", meth->name);
			goto skip;
		}

		authenticated = meth->method(authctxt);
		if (authenticated == -1)
			continue; /* "postponed" */

#ifdef BSD_AUTH
		if (authctxt->as) {
			auth_close(authctxt->as);
			authctxt->as = NULL;
		}
#endif
		if (!authctxt->valid && authenticated)
			fatal("INTERNAL ERROR: authenticated invalid user %s",
			    authctxt->user);

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

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

#ifdef USE_PAM
		if (options.use_pam && authenticated &&
		    !PRIVSEP(do_pam_account())) {
			char *msg;
			size_t len;

			error("Access denied for user %s by PAM account "
			    "configuration", authctxt->user);
			len = buffer_len(&loginmsg);
			buffer_append(&loginmsg, "\0", 1);
			msg = buffer_ptr(&loginmsg);
			/* strip trailing newlines */
			if (len > 0)
				while (len > 0 && msg[--len] == '\n')
					msg[len] = '\0';
			else
				msg = "Access denied.";
			packet_disconnect("%s", msg);
		}
#endif

 skip:
		/* Log before sending the reply */
		auth_log(authctxt, authenticated, 0, get_authname(type), NULL);

		free(client_user);
		client_user = NULL;

		if (authenticated)
			return;

		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);
		}

		packet_start(SSH_SMSG_FAILURE);
		packet_send();
		packet_write_wait();
	}
}
Esempio n. 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);
	}
}
Esempio n. 6
0
/*
 * read packets, try to authenticate the user and
 * return only if authentication is successful
 */
static void
do_authloop(Authctxt *authctxt)
{
	int authenticated = 0;
	int type = 0;
	const struct AuthMethod1 *meth;

	debug("Attempting authentication for %s%.100s.",
	    authctxt->valid ? "" : "invalid user ", authctxt->user);

	/* If the user has no password, accept authentication immediately. */
	if (options.permit_empty_passwd && options.password_authentication &&
#if defined(KRB4) || defined(KRB5)
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
	    PRIVSEP(auth_password(authctxt, __UNCONST("")))) {
#ifdef USE_PAM
 		if (options.use_pam && PRIVSEP(do_pam_account()))
#endif
		{
			auth_log(authctxt, 1, 0, "without authentication",
			    NULL);
			return;
		}
		return;
	}

	/* Indicate that authentication is needed. */
	packet_start(SSH_SMSG_FAILURE);
	packet_send();
	packet_write_wait();

	for (;;) {
		/* default to fail */
		authenticated = 0;


		/* Get a packet from the client. */
		type = packet_read();
		if (authctxt->failures >= options.max_authtries)
			goto skip;
		if ((meth = lookup_authmethod1(type)) == NULL) {
			logit("Unknown message during authentication: "
			    "type %d", type);
			goto skip;
		}

		if (!*(meth->enabled)) {
			verbose("%s authentication disabled.", meth->name);
			goto skip;
		}

		authenticated = meth->method(authctxt);
		if (authenticated == -1)
			continue; /* "postponed" */

#ifdef BSD_AUTH
		if (authctxt->as) {
			auth_close(authctxt->as);
			authctxt->as = NULL;
		}
#endif
		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(meth->name))
			authenticated = 0;

#ifdef USE_PAM
		if (options.use_pam && authenticated &&
		    !PRIVSEP(do_pam_account())) {
			char *msg;
			size_t len;

			error("Access denied for user %s by PAM account "
			    "configuration", authctxt->user);
			len = buffer_len(&loginmsg);
			buffer_append(&loginmsg, "\0", 1);
			msg = (char *)buffer_ptr(&loginmsg);
			/* strip trailing newlines */
			if (len > 0)
				while (len > 0 && msg[--len] == '\n')
					msg[len] = '\0';
			else
				msg = __UNCONST("Access denied.");
			packet_disconnect("%s", msg);
		}
#endif

 skip:
		/* Log before sending the reply */
		auth_log(authctxt, authenticated, 0, get_authname(type), NULL);

		if (authenticated)
			return;

		if (++authctxt->failures >= options.max_authtries)
			auth_maxtries_exceeded(authctxt);

		packet_start(SSH_SMSG_FAILURE);
		packet_send();
		packet_write_wait();
	}
}
Esempio n. 7
0
void
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
{
	struct mon_table *ent;
	int authenticated = 0;

	debug3("preauth child monitor started");

	authctxt = _authctxt;
	memset(authctxt, 0, sizeof(*authctxt));

	if (compat20) {
		mon_dispatch = mon_dispatch_proto20;

		/* Permit requests for moduli and signatures */
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
	} else {
		mon_dispatch = mon_dispatch_proto15;

		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
	}

	/* The first few requests do not require asynchronous access */
	while (!authenticated) {
		auth_method = "unknown";
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
		if (authenticated) {
			if (!(ent->flags & MON_AUTHDECIDE))
				fatal("%s: unexpected authentication from %d",
				    __func__, ent->type);
			if (authctxt->pw->pw_uid == 0 &&
			    !auth_root_allowed(auth_method))
				authenticated = 0;
		}

		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
			auth_log(authctxt, authenticated, auth_method,
			    compat20 ? " ssh2" : "");
			if (!authenticated)
				authctxt->failures++;
		}
#ifdef JPAKE
		/* Cleanup JPAKE context after authentication */
		if (ent->flags & MON_AUTHDECIDE) {
			if (authctxt->jpake_ctx != NULL) {
				jpake_free(authctxt->jpake_ctx);
				authctxt->jpake_ctx = NULL;
			}
		}
#endif
	}

	if (!authctxt->valid)
		fatal("%s: authenticated invalid user", __func__);
	if (strcmp(auth_method, "unknown") == 0)
		fatal("%s: authentication method name unknown", __func__);

	debug("%s: %s has been authenticated by privileged process",
	    __func__, authctxt->user);

	mm_get_keystate(pmonitor);
}
Esempio n. 8
0
/*
 * read packets, try to authenticate the user and
 * return only if authentication is successful
 */
static void
do_authloop(Authctxt *authctxt)
{
	int authenticated = 0;
	u_int bits;
	Key *client_host_key;
	BIGNUM *n;
	char *client_user, *password;
	char info[1024];
	u_int dlen;
	u_int ulen;
	int type = 0;
	struct passwd *pw = authctxt->pw;

	debug("Attempting authentication for %s%.100s.",
	    authctxt->valid ? "" : "illegal user ", authctxt->user);

	/* If the user has no password, accept authentication immediately. */
	if (options.password_authentication &&
#if defined(KRB4) || defined(KRB5)
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
	    PRIVSEP(auth_password(authctxt, ""))) {
		auth_log(authctxt, 1, "without authentication", "");
		return;
	}

	/* Indicate that authentication is needed. */
	packet_start(SSH_SMSG_FAILURE);
	packet_send();
	packet_write_wait();

	client_user = NULL;

	for ( ;; ) {
		/* default to fail */
		authenticated = 0;

		info[0] = '\0';

		/* Get a packet from the client. */
		authctxt->v1_auth_type = type = packet_read();
		authctxt->v1_auth_name = get_authname(type);

		authctxt->attempt++;

		/* Process the packet. */
		switch (type) {

#if defined(KRB4) || defined(KRB5)
		case SSH_CMSG_AUTH_KERBEROS:
			if (!options.kerberos_authentication) {
				verbose("Kerberos authentication disabled.");
			} else {
				char *kdata = packet_get_string(&dlen);
				packet_check_eom();

				if (kdata[0] == 4) { /* KRB_PROT_VERSION */
#ifdef KRB4
					KTEXT_ST tkt, reply;
					tkt.length = dlen;
					if (tkt.length < MAX_KTXT_LEN)
						memcpy(tkt.dat, kdata, tkt.length);

					if (PRIVSEP(auth_krb4(authctxt, &tkt,
					    &client_user, &reply))) {
						authenticated = 1;
						snprintf(info, sizeof(info),
						    " tktuser %.100s",
						    client_user);

						packet_start(
						    SSH_SMSG_AUTH_KERBEROS_RESPONSE);
						packet_put_string((char *)
						    reply.dat, reply.length);
						packet_send();
						packet_write_wait();
					}
#endif /* KRB4 */
				} else {
#ifdef KRB5
					krb5_data tkt, reply;
					tkt.length = dlen;
					tkt.data = kdata;

					if (PRIVSEP(auth_krb5(authctxt, &tkt,
					    &client_user, &reply))) {
						authenticated = 1;
						snprintf(info, sizeof(info),
						    " tktuser %.100s",
						    client_user);
 
 						/* Send response to client */
 						packet_start(
						    SSH_SMSG_AUTH_KERBEROS_RESPONSE);
 						packet_put_string((char *)
						    reply.data, reply.length);
 						packet_send();
 						packet_write_wait();

 						if (reply.length)
 							xfree(reply.data);
					}
#endif /* KRB5 */
				}
				xfree(kdata);
			}
			break;
#endif /* KRB4 || KRB5 */

#if defined(AFS) || defined(KRB5)
			/* XXX - punt on backward compatibility here. */
		case SSH_CMSG_HAVE_KERBEROS_TGT:
			packet_send_debug("Kerberos TGT passing disabled before authentication.");
			break;
#ifdef AFS
		case SSH_CMSG_HAVE_AFS_TOKEN:
			packet_send_debug("AFS token passing disabled before authentication.");
			break;
#endif /* AFS */
#endif /* AFS || KRB5 */

		case SSH_CMSG_AUTH_RHOSTS:
			if (!options.rhosts_authentication) {
				verbose("Rhosts authentication disabled.");
				break;
			}
			/*
			 * Get client user name.  Note that we just have to
			 * trust the client; this is one reason why rhosts
			 * authentication is insecure. (Another is
			 * IP-spoofing on a local network.)
			 */
			client_user = packet_get_string(&ulen);
			packet_check_eom();

			/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
			authenticated = auth_rhosts(pw, client_user);

			snprintf(info, sizeof info, " ruser %.100s", client_user);
			break;

		case SSH_CMSG_AUTH_RHOSTS_RSA:
			if (!options.rhosts_rsa_authentication) {
				verbose("Rhosts with RSA authentication disabled.");
				break;
			}
			/*
			 * Get client user name.  Note that we just have to
			 * trust the client; root on the client machine can
			 * claim to be any user.
			 */
			client_user = packet_get_string(&ulen);

			/* Get the client host key. */
			client_host_key = key_new(KEY_RSA1);
			bits = packet_get_int();
			packet_get_bignum(client_host_key->rsa->e);
			packet_get_bignum(client_host_key->rsa->n);

			if (bits != BN_num_bits(client_host_key->rsa->n))
				verbose("Warning: keysize mismatch for client_host_key: "
				    "actual %d, announced %d",
				    BN_num_bits(client_host_key->rsa->n), bits);
			packet_check_eom();

			authenticated = auth_rhosts_rsa(pw, client_user,
			    client_host_key);
			key_free(client_host_key);

			snprintf(info, sizeof info, " ruser %.100s", client_user);
			break;

		case SSH_CMSG_AUTH_RSA:
			if (!options.rsa_authentication) {
				verbose("RSA authentication disabled.");
				break;
			}
			/* RSA authentication requested. */
			if ((n = BN_new()) == NULL)
				fatal("do_authloop: BN_new failed");
			packet_get_bignum(n);
			packet_check_eom();
			authenticated = auth_rsa(pw, n);
			BN_clear_free(n);
			break;

		case SSH_CMSG_AUTH_PASSWORD:
			authctxt->init_attempt++;

			if (!options.password_authentication) {
				verbose("Password authentication disabled.");
				break;
			}
			/*
			 * Read user password.  It is in plain text, but was
			 * transmitted over the encrypted channel so it is
			 * not visible to an outside observer.
			 */
			password = packet_get_string(&dlen);
			packet_check_eom();

			/* Try authentication with the password. */
			if (authctxt->init_failures <
				options.max_init_auth_tries)
				authenticated =
				    PRIVSEP(auth_password(authctxt,
						password));

			memset(password, 0, strlen(password));
			xfree(password);
			break;

		case SSH_CMSG_AUTH_TIS:
			debug("rcvd SSH_CMSG_AUTH_TIS");
			if (options.challenge_response_authentication == 1) {
				char *challenge = get_challenge(authctxt);
				if (challenge != NULL) {
					debug("sending challenge '%s'", challenge);
					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
					packet_put_cstring(challenge);
					xfree(challenge);
					packet_send();
					packet_write_wait();
					continue;
				}
			}
			break;
		case SSH_CMSG_AUTH_TIS_RESPONSE:
			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
			if (options.challenge_response_authentication == 1) {
				char *response = packet_get_string(&dlen);
				debug("got response '%s'", response);
				packet_check_eom();
				authenticated = verify_response(authctxt, response);
				memset(response, 'r', dlen);
				xfree(response);
			}
			break;

		default:
			/*
			 * Any unknown messages will be ignored (and failure
			 * returned) during authentication.
			 */
			log("Unknown message during authentication: type %d", type);
			break;
		}
#ifdef BSD_AUTH
		if (authctxt->as) {
			auth_close(authctxt->as);
			authctxt->as = NULL;
		}
#endif
		if (!authctxt->valid && authenticated) {
			authenticated = 0;
			log("Ignoring authenticated invalid user %s",
			    authctxt->user);
		}

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

#ifdef HAVE_CYGWIN
		if (authenticated &&
		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) {
			packet_disconnect("Authentication rejected for uid %d.",
			pw == NULL ? -1 : pw->pw_uid);
			authenticated = 0;
		}
#else
		/* Special handling for root */
		if (!use_privsep &&
		    authenticated && authctxt->pw->pw_uid == 0 &&
		    !auth_root_allowed(get_authname(type)))
			authenticated = 0;
#endif
#ifdef USE_PAM
		/* XXX PAM and PRIVSEP don't mix */
		if (use_privsep && authenticated)
			fatal("Privsep is not supported");

		if (authenticated && type != SSH_CMSG_AUTH_PASSWORD)
			authenticated = do_pam_non_initial_userauth(authctxt);
		else if (authenticated && !AUTHPAM_DONE(authctxt))
			authenticated = 0;

		if (!authenticated)
			authctxt->pam_retval = AUTHPAM_ERROR(authctxt,
				PAM_PERM_DENIED);
#endif /* USE_PAM */

		/* Log before sending the reply */
		auth_log(authctxt, authenticated, get_authname(type), info);

		if (client_user != NULL) {
			xfree(client_user);
			client_user = NULL;
		}

		if (authenticated)
			return;

		if (type == SSH_CMSG_AUTH_PASSWORD)
			authctxt->init_failures++;

		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);
#endif /* HAVE_BSM */
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
		}

		packet_start(SSH_SMSG_FAILURE);
		packet_send();
		packet_write_wait();
	}
}
Esempio n. 9
0
void
userauth_finish(struct ssh *ssh, int authenticated, const char *method,
                const char *submethod)
{
    struct authctxt *authctxt = ssh->authctxt;
    char *methods;
    int r, 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;

    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;

    if (authenticated == 1) {
        /* turn off userauth */
        ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST,
                         &dispatch_protocol_ignore);
        if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 ||
                (r = sshpkt_send(ssh)) != 0)
            fatal("%s: %s", __func__, ssh_err(r));
        ssh_packet_write_wait(ssh);
        /* now we can break out */
        authctxt->success = 1;
    } else {
        /* Allow initial try of "none" auth without failure penalty */
        if (!partial && !authctxt->server_caused_failure &&
                (authctxt->attempt > 1 || strcmp(method, "none") != 0))
            authctxt->failures++;
        if (authctxt->failures >= options.max_authtries)
            auth_maxtries_exceeded(ssh, authctxt);
        methods = authmethods_get(authctxt);
        debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
               partial, methods);
        if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 ||
                (r = sshpkt_put_cstring(ssh, methods)) != 0 ||
                (r = sshpkt_put_u8(ssh, partial)) != 0 ||
                (r = sshpkt_send(ssh)) != 0)
            fatal("%s: %s", __func__, ssh_err(r));
        ssh_packet_write_wait(ssh);
        free(methods);
    }
}
Esempio n. 10
0
/*
 * read packets, try to authenticate the user and
 * return only if authentication is successful
 */
static void
do_authloop(Authctxt *authctxt)
{
	int authenticated = 0;
	u_int bits;
	Key *client_host_key;
	BIGNUM *n;
	char *client_user, *password;
	char info[1024];
	u_int dlen;
	u_int ulen;
	int prev, type = 0;
	struct passwd *pw = authctxt->pw;

	debug("Attempting authentication for %s%.100s.",
	    authctxt->valid ? "" : "illegal user ", authctxt->user);

	/* If the user has no password, accept authentication immediately. */
	if (options.password_authentication &&
#ifdef KRB5
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
	    PRIVSEP(auth_password(authctxt, ""))) {
		auth_log(authctxt, 1, "without authentication", "");
		return;
	}

	/* Indicate that authentication is needed. */
	packet_start(SSH_SMSG_FAILURE);
	packet_send();
	packet_write_wait();

	client_user = NULL;

	for (;;) {
		/* default to fail */
		authenticated = 0;

		info[0] = '\0';

		/* Get a packet from the client. */
		prev = type;
		type = packet_read();

		/*
		 * If we started challenge-response authentication but the
		 * next packet is not a response to our challenge, release
		 * the resources allocated by get_challenge() (which would
		 * normally have been released by verify_response() had we
		 * received such a response)
		 */
		if (prev == SSH_CMSG_AUTH_TIS &&
		    type != SSH_CMSG_AUTH_TIS_RESPONSE)
			abandon_challenge_response(authctxt);

		/* Process the packet. */
		switch (type) {
		case SSH_CMSG_AUTH_RHOSTS_RSA:
			if (!options.rhosts_rsa_authentication) {
				verbose("Rhosts with RSA authentication disabled.");
				break;
			}
			/*
			 * Get client user name.  Note that we just have to
			 * trust the client; root on the client machine can
			 * claim to be any user.
			 */
			client_user = packet_get_string(&ulen);

			/* Get the client host key. */
			client_host_key = key_new(KEY_RSA1);
			bits = packet_get_int();
			packet_get_bignum(client_host_key->rsa->e);
			packet_get_bignum(client_host_key->rsa->n);

			if (bits != BN_num_bits(client_host_key->rsa->n))
				verbose("Warning: keysize mismatch for client_host_key: "
				    "actual %d, announced %d",
				    BN_num_bits(client_host_key->rsa->n), bits);
			packet_check_eom();

			authenticated = auth_rhosts_rsa(authctxt, client_user,
			    client_host_key);
			key_free(client_host_key);

			snprintf(info, sizeof info, " ruser %.100s", client_user);
			break;

		case SSH_CMSG_AUTH_RSA:
			if (!options.rsa_authentication) {
				verbose("RSA authentication disabled.");
				break;
			}
			/* RSA authentication requested. */
			if ((n = BN_new()) == NULL)
				fatal("do_authloop: BN_new failed");
			packet_get_bignum(n);
			packet_check_eom();
			authenticated = auth_rsa(authctxt, n);
			BN_clear_free(n);
			break;

		case SSH_CMSG_AUTH_PASSWORD:
			if (!options.password_authentication) {
				verbose("Password authentication disabled.");
				break;
			}
			/*
			 * Read user password.  It is in plain text, but was
			 * transmitted over the encrypted channel so it is
			 * not visible to an outside observer.
			 */
			password = packet_get_string(&dlen);
			packet_check_eom();

			/* Try authentication with the password. */
			authenticated = PRIVSEP(auth_password(authctxt, password));

			memset(password, 0, strlen(password));
			xfree(password);
			break;

		case SSH_CMSG_AUTH_TIS:
			debug("rcvd SSH_CMSG_AUTH_TIS");
			if (options.challenge_response_authentication == 1) {
				char *challenge = get_challenge(authctxt);
				if (challenge != NULL) {
					debug("sending challenge '%s'", challenge);
					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
					packet_put_cstring(challenge);
					xfree(challenge);
					packet_send();
					packet_write_wait();
					continue;
				}
			}
			break;
		case SSH_CMSG_AUTH_TIS_RESPONSE:
			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
			if (options.challenge_response_authentication == 1) {
				char *response = packet_get_string(&dlen);
				packet_check_eom();
				authenticated = verify_response(authctxt, response);
				memset(response, 'r', dlen);
				xfree(response);
			}
			break;

		default:
			/*
			 * Any unknown messages will be ignored (and failure
			 * returned) during authentication.
			 */
			logit("Unknown message during authentication: type %d", type);
			break;
		}
#ifdef BSD_AUTH
		if (authctxt->as) {
			auth_close(authctxt->as);
			authctxt->as = NULL;
		}
#endif
		if (!authctxt->valid && authenticated)
			fatal("INTERNAL ERROR: authenticated invalid user %s",
			    authctxt->user);

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

#ifdef HAVE_CYGWIN
		if (authenticated &&
		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) {
			packet_disconnect("Authentication rejected for uid %d.",
			    pw == NULL ? -1 : pw->pw_uid);
			authenticated = 0;
		}
#else
		/* Special handling for root */
		if (authenticated && authctxt->pw->pw_uid == 0 &&
		    !auth_root_allowed(get_authname(type))) {
			authenticated = 0;
#if defined(HAVE_BSM_AUDIT_H) && defined(HAVE_LIBBSM)
			PRIVSEP(solaris_audit_not_console());
#endif /* BSM */
		}
#endif

#ifdef USE_PAM
		if (options.use_pam && authenticated &&
		    !PRIVSEP(do_pam_account()))
			authenticated = 0;
#endif

		/* Log before sending the reply */
		auth_log(authctxt, authenticated, get_authname(type), info);

		if (client_user != NULL) {
			xfree(client_user);
			client_user = NULL;
		}

		if (authenticated)
			return;

		if (authctxt->failures++ > AUTH_FAIL_MAX) {
#if defined(HAVE_BSM_AUDIT_H) && defined(HAVE_LIBBSM)
			PRIVSEP(solaris_audit_maxtrys());
#endif /* BSM */
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
		}
#if defined(HAVE_BSM_AUDIT_H) && defined(HAVE_LIBBSM)
		PRIVSEP(solaris_audit_bad_pw("authorization"));
#endif /* BSM */

		packet_start(SSH_SMSG_FAILURE);
		packet_send();
		packet_write_wait();
	}
}
Esempio n. 11
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);
	}
}
Esempio n. 12
0
void
monitor_child_preauth(struct authctxt *_authctxt, struct monitor *pmonitor)
{
	struct mon_table *ent;
	int authenticated = 0, partial = 0;

	debug3("preauth child monitor started");

	close(pmonitor->m_recvfd);
	close(pmonitor->m_log_sendfd);
	pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;

	authctxt = _authctxt;
	memset(authctxt, 0, sizeof(*authctxt));

	if (compat20) {
		mon_dispatch = mon_dispatch_proto20;

		/* Permit requests for moduli and signatures */
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
	} else {
		mon_dispatch = mon_dispatch_proto15;

		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
	}

	/* The first few requests do not require asynchronous access */
	while (!authenticated) {
		partial = 0;
		auth_method = "unknown";
		auth_submethod = NULL;
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);

		/* Special handling for multiple required authentications */
		if (options.num_auth_methods != 0) {
			if (!compat20)
				fatal("AuthenticationMethods is not supported"
				    "with SSH protocol 1");
			if (authenticated &&
			    !auth2_update_methods_lists(authctxt,
			    auth_method, auth_submethod)) {
				debug3("%s: method %s: partial", __func__,
				    auth_method);
				authenticated = 0;
				partial = 1;
			}
		}

		if (authenticated) {
			if (!(ent->flags & MON_AUTHDECIDE))
				fatal("%s: unexpected authentication from %d",
				    __func__, ent->type);
			if (authctxt->pw->pw_uid == 0 &&
			    !auth_root_allowed(auth_method))
				authenticated = 0;
		}
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
			auth_log(authctxt, authenticated, partial,
			    auth_method, auth_submethod);
			if (!authenticated)
				authctxt->failures++;
		}
	}

	if (!authctxt->valid)
		fatal("%s: authenticated invalid user", __func__);
	if (strcmp(auth_method, "unknown") == 0)
		fatal("%s: authentication method name unknown", __func__);

	debug("%s: %s has been authenticated by privileged process",
	    __func__, authctxt->user);

	mm_get_keystate(pmonitor);

	/* Drain any buffered messages from the child */
	while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
		;

	close(pmonitor->m_sendfd);
	close(pmonitor->m_log_recvfd);
	pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
}
Esempio n. 13
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();
	}
}
Esempio n. 14
0
/*
 * read packets, try to authenticate the user and
 * return only if authentication is successful
 */
static void
do_authloop(Authctxt *authctxt)
{
	int authenticated = 0;
	char info[1024];
	int type = 0;
	const struct AuthMethod1 *meth;

	debug("Attempting authentication for %s%.100s.",
	    authctxt->valid ? "" : "invalid user ", authctxt->user);

	/* If the user has no password, accept authentication immediately. */
	if (options.password_authentication &&
#ifdef KRB5
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
	    PRIVSEP(auth_password(authctxt, ""))) {
		auth_log(authctxt, 1, "without authentication", "");
		return;
	}

	/* Indicate that authentication is needed. */
	packet_start(SSH_SMSG_FAILURE);
	packet_send();
	packet_write_wait();

	for (;;) {
		/* default to fail */
		authenticated = 0;

		info[0] = '\0';

		/* Get a packet from the client. */
		type = packet_read();
		if (authctxt->failures >= options.max_authtries)
			goto skip;
		if ((meth = lookup_authmethod1(type)) == NULL) {
			logit("Unknown message during authentication: "
			    "type %d", type);
			goto skip;
		}

		if (!*(meth->enabled)) {
			verbose("%s authentication disabled.", meth->name);
			goto skip;
		}

		authenticated = meth->method(authctxt, info, sizeof(info));
		if (authenticated == -1)
			continue; /* "postponed" */

		if (authctxt->as) {
			auth_close(authctxt->as);
			authctxt->as = NULL;
		}
		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(meth->name))
			authenticated = 0;

 skip:
		/* Log before sending the reply */
		auth_log(authctxt, authenticated, get_authname(type), info);

		if (authenticated)
			return;

		if (++authctxt->failures >= options.max_authtries)
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);

		packet_start(SSH_SMSG_FAILURE);
		packet_send();
		packet_write_wait();
	}
}
Esempio n. 15
0
void
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
{
	struct ssh *ssh = active_state;	/* XXX */
	struct mon_table *ent;
	int authenticated = 0, partial = 0;

	debug3("preauth child monitor started");

	close(pmonitor->m_recvfd);
	close(pmonitor->m_log_sendfd);
	pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;

	authctxt = _authctxt;
	memset(authctxt, 0, sizeof(*authctxt));

	authctxt->loginmsg = &loginmsg;

	mon_dispatch = mon_dispatch_proto20;
	/* Permit requests for moduli and signatures */
	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);

	/* The first few requests do not require asynchronous access */
	while (!authenticated) {
		partial = 0;
		auth_method = "unknown";
		auth_submethod = NULL;
		auth2_authctxt_reset_info(authctxt);

		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);

		/* Special handling for multiple required authentications */
		if (options.num_auth_methods != 0) {
			if (authenticated &&
			    !auth2_update_methods_lists(authctxt,
			    auth_method, auth_submethod)) {
				debug3("%s: method %s: partial", __func__,
				    auth_method);
				authenticated = 0;
				partial = 1;
			}
		}

		if (authenticated) {
			if (!(ent->flags & MON_AUTHDECIDE))
				fatal("%s: unexpected authentication from %d",
				    __func__, ent->type);
			if (authctxt->pw->pw_uid == 0 &&
			    !auth_root_allowed(auth_method))
				authenticated = 0;
#ifdef USE_PAM
			/* PAM needs to perform account checks after auth */
			if (options.use_pam && authenticated) {
				Buffer m;

				buffer_init(&m);
				mm_request_receive_expect(pmonitor->m_sendfd,
				    MONITOR_REQ_PAM_ACCOUNT, &m);
				authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
				buffer_free(&m);
			}
#endif
		}
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
			auth_log(authctxt, authenticated, partial,
			    auth_method, auth_submethod);
			if (!partial && !authenticated)
				authctxt->failures++;
			if (authenticated || partial) {
				auth2_update_session_info(authctxt,
				    auth_method, auth_submethod);
			}
		}
	}

	if (!authctxt->valid)
		fatal("%s: authenticated invalid user", __func__);
	if (strcmp(auth_method, "unknown") == 0)
		fatal("%s: authentication method name unknown", __func__);

	debug("%s: %s has been authenticated by privileged process",
	    __func__, authctxt->user);
	ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);

	mm_get_keystate(pmonitor);

	/* Drain any buffered messages from the child */
	while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
		;

	close(pmonitor->m_sendfd);
	close(pmonitor->m_log_recvfd);
	pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
}
Esempio n. 16
0
/*
 * To be called from userauth methods, directly (as in keyboard-interactive) or
 * indirectly (from auth_pam_password() or from do_pam_non_initial_userauth().
 *
 * The caller is responsible for calling new_start_pam() first.
 *
 * PAM state is not cleaned up here on error.  This is left to subsequent calls
 * to new_start_pam() or to the cleanup function upon authentication error.
 */
int
finish_userauth_do_pam(Authctxt *authctxt)
{
	int retval;
	char *user, *method;

	/* Various checks; fail gracefully */
	if (authctxt == NULL || authctxt->pam == NULL)
		return PAM_SYSTEM_ERR;	/* shouldn't happen */

	if (compat20) {
		if (authctxt->method == NULL || authctxt->method->name == NULL)
			return PAM_SYSTEM_ERR;	/* shouldn't happen */
		method = authctxt->method->name;
	} else if ((method = authctxt->v1_auth_name) == NULL)
		return PAM_SYSTEM_ERR;	/* shouldn't happen */

	if (AUTHPAM_DONE(authctxt))
		return PAM_SYSTEM_ERR;	/* shouldn't happen */

	if (!(authctxt->pam->state & PAM_S_DONE_ACCT_MGMT)) {
		retval = pam_acct_mgmt(authctxt->pam->h, 0);
		authctxt->pam->last_pam_retval = retval;
		if (retval == PAM_NEW_AUTHTOK_REQD) {
			userauth_force_kbdint();
			return retval;
		}
		if (retval != PAM_SUCCESS)
			return retval;
		authctxt->pam->state |= PAM_S_DONE_ACCT_MGMT;
	}

	/*
	 * Handle PAM_USER change, if any.
	 *
	 * We do this before pam_open_session() because we need the PAM_USER's
	 * UID for:
	 *
	 * a) PermitRootLogin checking
	 * b) to get at the lastlog entry before pam_open_session() updates it.
	 */
	retval = pam_get_item(authctxt->pam->h, PAM_USER, (void **) &user);
	if (retval != PAM_SUCCESS) {
		fatal("PAM failure: pam_get_item(PAM_USER) "
		      "returned %d: %.200s", retval,
		      PAM_STRERROR(authctxt->pam->h, retval));
	}

	if (user == NULL || *user == '\0') {
		debug("PAM set NULL PAM_USER");
		return PAM_PERM_DENIED;
	}

	if (strcmp(user, authctxt->user) != 0) {
		log("PAM changed the SSH username");
		pwfree(&authctxt->pw);
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		authctxt->valid = (authctxt->pw != NULL);
		xfree(authctxt->user);
		authctxt->user = xstrdup(user);
	}

	if (!authctxt->valid) {
		debug2("PAM set PAM_USER to unknown user");
		/*
		 * Return success, userauth_finish() will catch
		 * this and send back a failure message.
		 */
		return PAM_SUCCESS;
	}

	/* Check PermitRootLogin semantics */
	if (authctxt->pw->pw_uid == 0 && !auth_root_allowed(method))
		return PAM_PERM_DENIED;

	if (!(authctxt->pam->state & PAM_S_DONE_SETCRED)) {
		retval = pam_setcred(authctxt->pam->h,
				     PAM_ESTABLISH_CRED);
		authctxt->pam->last_pam_retval = retval;
		if (retval != PAM_SUCCESS)
			return retval;
		authctxt->pam->state |= PAM_S_DONE_SETCRED;

#ifdef GSSAPI
		/*
		 * Store GSS-API delegated creds after pam_setcred(), which may
		 * have set the current credential store.
		 */
		ssh_gssapi_storecreds(NULL, authctxt);
#endif /* GSSAPI */
	}

	/*
	 * On Solaris pam_unix_session.so updates the lastlog, but does
	 * not converse a PAM_TEXT_INFO message about it.  So we need to
	 * fetch the lastlog entry here and save it for use later.
	 */
	authctxt->last_login_time =
		get_last_login_time(authctxt->pw->pw_uid,
			authctxt->pw->pw_name,
			authctxt->last_login_host,
			sizeof(authctxt->last_login_host));

	if (!(authctxt->pam->state & PAM_S_DONE_OPEN_SESSION)) {
		retval = pam_open_session(authctxt->pam->h, 0);
		authctxt->pam->last_pam_retval = retval;
		if (retval != PAM_SUCCESS)
			return retval;
		authctxt->pam->state |= PAM_S_DONE_OPEN_SESSION;
	}

	/*
	 * All PAM work done successfully.
	 *
	 * PAM handle stays around so we can call pam_close_session() on
	 * it later.
	 */
	return PAM_SUCCESS;
}