Esempio n. 1
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;
}
Esempio n. 2
0
File: auth2.c Progetto: jhbsz/netbsd
/*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);
    if (!log_flag) {
        logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s",
              get_remote_ipaddr(), get_remote_port(), 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();
        }
#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;

    /* 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);
}
int
mm_answer_pwnamallow(int socket, Buffer *m)
{
	char *login;
	struct passwd *pwent;
	int allowed = 0;

	debug3("%s", __func__);

	if (authctxt->attempt++ != 0)
		fatal("%s: multiple attempts for getpwnam", __func__);

	login = buffer_get_string(m, NULL);

	pwent = getpwnamallow(login);

	authctxt->user = xstrdup(login);
	setproctitle("%s [priv]", pwent ? login : "******");
	xfree(login);

	buffer_clear(m);

	if (pwent == NULL) {
		buffer_put_char(m, 0);
		goto out;
	}

	allowed = 1;
	authctxt->pw = pwent;
	authctxt->valid = 1;

	buffer_put_char(m, 1);
	buffer_put_string(m, pwent, sizeof(struct passwd));
	buffer_put_cstring(m, pwent->pw_name);
	buffer_put_cstring(m, "*");
	buffer_put_cstring(m, pwent->pw_gecos);
#ifdef HAVE_PW_CLASS_IN_PASSWD
	buffer_put_cstring(m, pwent->pw_class);
#endif
	buffer_put_cstring(m, pwent->pw_dir);
	buffer_put_cstring(m, pwent->pw_shell);

 out:
	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
	mm_request_send(socket, MONITOR_ANS_PWNAM, m);

	/* For SSHv1 allow authentication now */
	if (!compat20)
		monitor_permit_authentications(1);
	else {
		/* Allow service/style information on the auth context */
		monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
	}

#ifdef USE_PAM
	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
#endif

	return (0);
}
Esempio n. 4
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();
	} 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 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;

	/* try to authenticate user */
	m = authmethod_lookup(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);

	xfree(service);
	xfree(user);
	xfree(method);
}
Esempio n. 5
0
/*
 * Performs authentication of an incoming connection.  Session key has already
 * been exchanged and encryption is enabled.
 */
void
do_authentication(Authctxt *authctxt)
{
	u_int ulen;
	char *user, *style = NULL;

	/* 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_cstring(&ulen);
	packet_check_eom();

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

	authctxt->user = user;
	authctxt->style = style;

	/* Verify that the user is a valid user. */
	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
		authctxt->valid = 1;
	else {
		debug("do_authentication: invalid user %s", user);
		authctxt->pw = fakepw();
	}

	/* Configuration may have changed as a result of Match */
	if (options.num_auth_methods != 0)
		fatal("AuthenticationMethods is not supported with SSH "
		    "protocol 1");

	setproctitle("%s%s", authctxt->valid ? user : "******",
	    use_privsep ? " [net]" : "");

#ifdef USE_PAM
	if (options.use_pam)
		PRIVSEP(start_pam(authctxt));
#endif

	/*
	 * If we are not running as root, the user must have the same uid as
	 * the server.
	 */
#ifndef HAVE_CYGWIN
	if (!use_privsep && getuid() != 0 && authctxt->pw &&
	    authctxt->pw->pw_uid != getuid())
		packet_disconnect("Cannot change user when server not running as root.");
#endif

	/*
	 * Loop until the user has been authenticated or the connection is
	 * closed, do_authloop() returns only if authentication is successful
	 */
	do_authloop(authctxt);

	/* The user has been authenticated and accepted. */
	packet_start(SSH_SMSG_SUCCESS);
	packet_send();
	packet_write_wait();
}
Esempio n. 6
0
/*
 * Performs authentication of an incoming connection.  Session key has already
 * been exchanged and encryption is enabled.
 */
Authctxt *
do_authentication(void)
{
	Authctxt *authctxt;
	u_int ulen;
	char *user, *style = NULL;

	/* 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(&ulen);
	packet_check_eom();

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

#ifdef KRB5
	/* XXX - SSH.com Kerberos v5 braindeath. */
	if ((datafellows & SSH_BUG_K5USER) &&
	    options.kerberos_authentication) {
		char *p;
		if ((p = strchr(user, '@')) != NULL)
			*p = '\0';
	}
#endif

	authctxt = authctxt_new();
	authctxt->user = user;
	authctxt->style = style;

	/* Verify that the user is a valid user. */
	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
		authctxt->valid = 1;
	else
		debug("do_authentication: illegal user %s", user);

	setproctitle("%s%s", authctxt->pw ? user : "******",
	    use_privsep ? " [net]" : "");

#ifdef USE_PAM
	PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user));
#endif

	/*
	 * If we are not running as root, the user must have the same uid as
	 * the server. (Unless you are running Windows)
	 */
#ifndef HAVE_CYGWIN
	if (!use_privsep && getuid() != 0 && authctxt->pw &&
	    authctxt->pw->pw_uid != getuid())
		packet_disconnect("Cannot change user when server not running as root.");
#endif

	/*
	 * Loop until the user has been authenticated or the connection is
	 * closed, do_authloop() returns only if authentication is successful
	 */
	do_authloop(authctxt);

	/* The user has been authenticated and accepted. */
	packet_start(SSH_SMSG_SUCCESS);
	packet_send();
	packet_write_wait();

	return (authctxt);
}
Esempio n. 7
0
int
mm_answer_pwnamallow(int sock, struct sshbuf *m)
{
	char *username;
	struct passwd *pwent;
	int r, allowed = 0;
	u_int i;

	debug3("%s", __func__);

	if (authctxt->attempt++ != 0)
		fatal("%s: multiple attempts for getpwnam", __func__);

	if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));

	pwent = getpwnamallow(username);

	authctxt->user = xstrdup(username);
	setproctitle("%s [priv]", pwent ? username : "******");
	free(username);

	sshbuf_reset(m);

	if (pwent == NULL) {
		if ((r = sshbuf_put_u8(m, 0)) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
		authctxt->pw = fakepw();
		goto out;
	}

	allowed = 1;
	authctxt->pw = pwent;
	authctxt->valid = 1;

	if ((r = sshbuf_put_u8(m, 1)) != 0 ||
	    (r = sshbuf_put_string(m, pwent, sizeof(struct passwd))) != 0 ||
	    (r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 ||
	    (r = sshbuf_put_cstring(m, "*")) != 0 ||
	    (r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 ||
	    (r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 ||
	    (r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 ||
	    (r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));

 out:
	if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));

#define M_CP_STROPT(x) do { \
		if (options.x != NULL) \
			if ((r = sshbuf_put_cstring(m, options.x)) != 0) \
				fatal("%s: buffer error: %s", __func__, \
				    ssh_err(r)); \
	} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
		for (i = 0; i < options.nx; i++) \
			if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \
				fatal("%s: buffer error: %s", __func__, \
				    ssh_err(r)); \
	} while (0)
	/* See comment in servconf.h */
	COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT

	/* Create valid auth method lists */
	if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
		/*
		 * The monitor will continue long enough to let the child
		 * run to it's packet_disconnect(), but it must not allow any
		 * authentication to succeed.
		 */
		debug("%s: no valid authentication method lists", __func__);
	}

	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
	mm_request_send(sock, MONITOR_ANS_PWNAM, m);

	/* For SSHv1 allow authentication now */
	if (!compat20)
		monitor_permit_authentications(1);
	else {
		/* Allow service/style information on the auth context */
		monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
	}

	return (0);
}
Esempio n. 8
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);
}
Esempio n. 9
0
int
mm_answer_pwnamallow(int sock, Buffer *m)
{
	struct ssh *ssh = active_state;	/* XXX */
	char *username;
	struct passwd *pwent;
	int allowed = 0;
	u_int i;

	debug3("%s", __func__);

	if (authctxt->attempt++ != 0)
		fatal("%s: multiple attempts for getpwnam", __func__);

	username = buffer_get_string(m, NULL);

	pwent = getpwnamallow(username);

	authctxt->user = xstrdup(username);
	setproctitle("%s [priv]", pwent ? username : "******");
	free(username);

	buffer_clear(m);

	if (pwent == NULL) {
		buffer_put_char(m, 0);
		authctxt->pw = fakepw();
		goto out;
	}

	allowed = 1;
	authctxt->pw = pwent;
	authctxt->valid = 1;

	buffer_put_char(m, 1);
	buffer_put_string(m, pwent, sizeof(struct passwd));
	buffer_put_cstring(m, pwent->pw_name);
	buffer_put_cstring(m, "*");
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
	buffer_put_cstring(m, pwent->pw_gecos);
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
	buffer_put_cstring(m, pwent->pw_class);
#endif
	buffer_put_cstring(m, pwent->pw_dir);
	buffer_put_cstring(m, pwent->pw_shell);

 out:
	ssh_packet_set_log_preamble(ssh, "%suser %s",
	    authctxt->valid ? "authenticating" : "invalid ", authctxt->user);
	buffer_put_string(m, &options, sizeof(options));

#define M_CP_STROPT(x) do { \
		if (options.x != NULL) \
			buffer_put_cstring(m, options.x); \
	} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
		for (i = 0; i < options.nx; i++) \
			buffer_put_cstring(m, options.x[i]); \
	} while (0)
	/* See comment in servconf.h */
	COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT

	/* Create valid auth method lists */
	if (auth2_setup_methods_lists(authctxt) != 0) {
		/*
		 * The monitor will continue long enough to let the child
		 * run to it's packet_disconnect(), but it must not allow any
		 * authentication to succeed.
		 */
		debug("%s: no valid authentication method lists", __func__);
	}

	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
	mm_request_send(sock, MONITOR_ANS_PWNAM, m);

	/* Allow service/style information on the auth context */
	monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
	monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);

#ifdef USE_PAM
	if (options.use_pam)
		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
#endif

	return (0);
}
Esempio n. 10
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;
}