diff options
Diffstat (limited to 'crypto/openssh/auth-passwd.c')
| -rw-r--r-- | crypto/openssh/auth-passwd.c | 223 | 
1 files changed, 223 insertions, 0 deletions
| diff --git a/crypto/openssh/auth-passwd.c b/crypto/openssh/auth-passwd.c new file mode 100644 index 000000000000..347d91e25192 --- /dev/null +++ b/crypto/openssh/auth-passwd.c @@ -0,0 +1,223 @@ +/* $OpenBSD: auth-passwd.c,v 1.48 2020/10/18 11:32:01 djm Exp $ */ +/* + * Author: Tatu Ylonen <ylo@cs.hut.fi> + * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland + *                    All rights reserved + * Password authentication.  This file contains the functions to check whether + * the password is valid for the user. + * + * As far as I am concerned, the code I have written for this software + * can be used freely for any purpose.  Any derived versions of this + * software must be clearly marked as such, and if the derived work is + * incompatible with the protocol description in the RFC file, it must be + * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 1999 Dug Song.  All rights reserved. + * Copyright (c) 2000 Markus Friedl.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include <sys/types.h> + +#include <pwd.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#include "packet.h" +#include "sshbuf.h" +#include "ssherr.h" +#include "log.h" +#include "misc.h" +#include "servconf.h" +#include "sshkey.h" +#include "hostfile.h" +#include "auth.h" +#include "auth-options.h" + +extern struct sshbuf *loginmsg; +extern ServerOptions options; + +#ifdef HAVE_LOGIN_CAP +extern login_cap_t *lc; +#endif + + +#define DAY		(24L * 60 * 60) /* 1 day in seconds */ +#define TWO_WEEKS	(2L * 7 * DAY)	/* 2 weeks in seconds */ + +#define MAX_PASSWORD_LEN	1024 + +/* + * Tries to authenticate the user using password.  Returns true if + * authentication succeeds. + */ +int +auth_password(struct ssh *ssh, const char *password) +{ +	Authctxt *authctxt = ssh->authctxt; +	struct passwd *pw = authctxt->pw; +	int result, ok = authctxt->valid; +#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) +	static int expire_checked = 0; +#endif + +	if (strlen(password) > MAX_PASSWORD_LEN) +		return 0; + +#ifndef HAVE_CYGWIN +	if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) +		ok = 0; +#endif +	if (*password == '\0' && options.permit_empty_passwd == 0) +		return 0; + +#ifdef KRB5 +	if (options.kerberos_authentication == 1) { +		int ret = auth_krb5_password(authctxt, password); +		if (ret == 1 || ret == 0) +			return ret && ok; +		/* Fall back to ordinary passwd authentication. */ +	} +#endif +#ifdef HAVE_CYGWIN +	{ +		HANDLE hToken = cygwin_logon_user(pw, password); + +		if (hToken == INVALID_HANDLE_VALUE) +			return 0; +		cygwin_set_impersonation_token(hToken); +		return ok; +	} +#endif +#ifdef USE_PAM +	if (options.use_pam) +		return (sshpam_auth_passwd(authctxt, password) && ok); +#endif +#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) +	if (!expire_checked) { +		expire_checked = 1; +		if (auth_shadow_pwexpired(authctxt)) +			authctxt->force_pwchange = 1; +	} +#endif +	result = sys_auth_passwd(ssh, password); +	if (authctxt->force_pwchange) +		auth_restrict_session(ssh); +	return (result && ok); +} + +#ifdef BSD_AUTH +static void +warn_expiry(Authctxt *authctxt, auth_session_t *as) +{ +	int r; +	quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime; + +	pwwarntime = acwarntime = TWO_WEEKS; + +	pwtimeleft = auth_check_change(as); +	actimeleft = auth_check_expire(as); +#ifdef HAVE_LOGIN_CAP +	if (authctxt->valid) { +		pwwarntime = login_getcaptime(lc, "password-warn", TWO_WEEKS, +		    TWO_WEEKS); +		acwarntime = login_getcaptime(lc, "expire-warn", TWO_WEEKS, +		    TWO_WEEKS); +	} +#endif +	if (pwtimeleft != 0 && pwtimeleft < pwwarntime) { +		daysleft = pwtimeleft / DAY + 1; +		if ((r = sshbuf_putf(loginmsg, +		    "Your password will expire in %lld day%s.\n", +		    daysleft, daysleft == 1 ? "" : "s")) != 0) +			fatal_fr(r, "buffer error"); +	} +	if (actimeleft != 0 && actimeleft < acwarntime) { +		daysleft = actimeleft / DAY + 1; +		if ((r = sshbuf_putf(loginmsg, +		    "Your account will expire in %lld day%s.\n", +		    daysleft, daysleft == 1 ? "" : "s")) != 0) +			fatal_fr(r, "buffer error"); +	} +} + +int +sys_auth_passwd(struct ssh *ssh, const char *password) +{ +	Authctxt *authctxt = ssh->authctxt; +	auth_session_t *as; +	static int expire_checked = 0; + +	as = auth_usercheck(authctxt->pw->pw_name, authctxt->style, "auth-ssh", +	    (char *)password); +	if (as == NULL) +		return (0); +	if (auth_getstate(as) & AUTH_PWEXPIRED) { +		auth_close(as); +		auth_restrict_session(ssh); +		authctxt->force_pwchange = 1; +		return (1); +	} else { +		if (!expire_checked) { +			expire_checked = 1; +			warn_expiry(authctxt, as); +		} +		return (auth_close(as)); +	} +} +#elif !defined(CUSTOM_SYS_AUTH_PASSWD) +int +sys_auth_passwd(struct ssh *ssh, const char *password) +{ +	Authctxt *authctxt = ssh->authctxt; +	struct passwd *pw = authctxt->pw; +	char *encrypted_password, *salt = NULL; + +	/* Just use the supplied fake password if authctxt is invalid */ +	char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; + +	if (pw_password == NULL) +		return 0; + +	/* Check for users with no password. */ +	if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) +		return (1); + +	/* +	 * Encrypt the candidate password using the proper salt, or pass a +	 * NULL and let xcrypt pick one. +	 */ +	if (authctxt->valid && pw_password[0] && pw_password[1]) +		salt = pw_password; +	encrypted_password = xcrypt(password, salt); + +	/* +	 * Authentication is accepted if the encrypted passwords +	 * are identical. +	 */ +	return encrypted_password != NULL && +	    strcmp(encrypted_password, pw_password) == 0; +} +#endif | 
