Home | History | Annotate | Download | only in sshd
      1 /*
      2  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
      3  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      4  *                    All rights reserved
      5  * Password authentication.  This file contains the functions to check whether
      6  * the password is valid for the user.
      7  *
      8  * As far as I am concerned, the code I have written for this software
      9  * can be used freely for any purpose.  Any derived versions of this
     10  * software must be clearly marked as such, and if the derived work is
     11  * incompatible with the protocol description in the RFC file, it must be
     12  * called by a name other than "ssh" or "Secure Shell".
     13  *
     14  * Copyright (c) 1999 Dug Song.  All rights reserved.
     15  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
     16  *
     17  * Redistribution and use in source and binary forms, with or without
     18  * modification, are permitted provided that the following conditions
     19  * are met:
     20  * 1. Redistributions of source code must retain the above copyright
     21  *    notice, this list of conditions and the following disclaimer.
     22  * 2. Redistributions in binary form must reproduce the above copyright
     23  *    notice, this list of conditions and the following disclaimer in the
     24  *    documentation and/or other materials provided with the distribution.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 #include "includes.h"
     39 RCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $");
     40 
     41 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     42 
     43 #include "packet.h"
     44 #include "log.h"
     45 #include "servconf.h"
     46 #include "auth.h"
     47 
     48 #if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
     49 /* Don't need any of these headers for the PAM or SIA cases */
     50 # ifdef HAVE_CRYPT_H
     51 #  include <crypt.h>
     52 # endif
     53 # ifdef WITH_AIXAUTHENTICATE
     54 #  include <login.h>
     55 # endif
     56 # ifdef __hpux
     57 #  include <hpsecurity.h>
     58 #  include <prot.h>
     59 # endif
     60 # ifdef HAVE_SECUREWARE
     61 #  include <sys/security.h>
     62 #  include <sys/audit.h>
     63 #  include <prot.h>
     64 # endif /* HAVE_SECUREWARE */
     65 # if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
     66 #  include <shadow.h>
     67 # endif
     68 # if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
     69 #  include <sys/label.h>
     70 #  include <sys/audit.h>
     71 #  include <pwdadj.h>
     72 # endif
     73 # if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT)
     74 #  include "md5crypt.h"
     75 # endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */
     76 
     77 # ifdef HAVE_CYGWIN
     78 #  undef ERROR
     79 #  include <windows.h>
     80 #  include <sys/cygwin.h>
     81 #  define is_winnt       (GetVersion() < 0x80000000)
     82 # endif
     83 #endif /* !USE_PAM && !HAVE_OSF_SIA */
     84 
     85 extern ServerOptions options;
     86 #ifdef WITH_AIXAUTHENTICATE
     87 extern char *aixloginmsg;
     88 #endif
     89 
     90 /*
     91  * Tries to authenticate the user using password.  Returns true if
     92  * authentication succeeds.
     93  */
     94 int
     95 auth_password(Authctxt *authctxt, const char *password)
     96 {
     97 #if defined(USE_PAM)
     98 	if (*password == '\0' && options.permit_empty_passwd == 0)
     99 		return 0;
    100 	return auth_pam_password(authctxt, password);
    101 #elif defined(HAVE_OSF_SIA)
    102 	if (*password == '\0' && options.permit_empty_passwd == 0)
    103 		return 0;
    104 	return auth_sia_password(authctxt, password);
    105 #else
    106 	struct passwd * pw = authctxt->pw;
    107 	char *encrypted_password;
    108 	char *pw_password;
    109 	char *salt;
    110 #if defined(__hpux) || defined(HAVE_SECUREWARE)
    111 	struct pr_passwd *spw;
    112 #endif /* __hpux || HAVE_SECUREWARE */
    113 #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
    114 	struct spwd *spw;
    115 #endif
    116 #if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
    117 	struct passwd_adjunct *spw;
    118 #endif
    119 #ifdef WITH_AIXAUTHENTICATE
    120 	char *authmsg;
    121 	int authsuccess;
    122 	int reenter = 1;
    123 #endif
    124 
    125 	/* deny if no user. */
    126 	if (pw == NULL)
    127 		return 0;
    128 #ifndef HAVE_CYGWIN
    129        if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
    130 		return 0;
    131 #endif
    132 	if (*password == '\0' && options.permit_empty_passwd == 0)
    133 		return 0;
    134 #ifdef KRB5
    135 	if (options.kerberos_authentication == 1) {
    136 		int ret = auth_krb5_password(authctxt, password);
    137 		if (ret == 1 || ret == 0)
    138 			return ret;
    139 		/* Fall back to ordinary passwd authentication. */
    140 	}
    141 #endif
    142 #ifdef HAVE_CYGWIN
    143 	if (is_winnt) {
    144 		HANDLE hToken = cygwin_logon_user(pw, password);
    145 
    146 		if (hToken == INVALID_HANDLE_VALUE)
    147 			return 0;
    148 		cygwin_set_impersonation_token(hToken);
    149 		return 1;
    150 	}
    151 #endif
    152 #ifdef WITH_AIXAUTHENTICATE
    153 	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
    154 
    155 	if (authsuccess)
    156 	        /* We don't have a pty yet, so just label the line as "ssh" */
    157 	        if (loginsuccess(authctxt->user,
    158 			get_canonical_hostname(options.verify_reverse_mapping),
    159 			"ssh", &aixloginmsg) < 0)
    160 				aixloginmsg = NULL;
    161 
    162 	return(authsuccess);
    163 #endif
    164 #ifdef KRB4
    165 	if (options.kerberos_authentication == 1) {
    166 		int ret = auth_krb4_password(authctxt, password);
    167 		if (ret == 1 || ret == 0)
    168 			return ret;
    169 		/* Fall back to ordinary passwd authentication. */
    170 	}
    171 #endif
    172 #ifdef BSD_AUTH
    173 	if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
    174 	    (char *)password) == 0)
    175 		return 0;
    176 	else
    177 		return 1;
    178 #endif
    179 	pw_password = pw->pw_passwd;
    180 
    181 	/*
    182 	 * Various interfaces to shadow or protected password data
    183 	 */
    184 #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
    185 	spw = getspnam(pw->pw_name);
    186 	if (spw != NULL)
    187 		pw_password = spw->sp_pwdp;
    188 #endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
    189 
    190 #if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
    191 	if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL)
    192 		pw_password = spw->pwa_passwd;
    193 #endif /* defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) */
    194 
    195 #ifdef HAVE_SECUREWARE
    196 	if ((spw = getprpwnam(pw->pw_name)) != NULL)
    197 		pw_password = spw->ufld.fd_encrypt;
    198 #endif /* HAVE_SECUREWARE */
    199 
    200 #if defined(__hpux) && !defined(HAVE_SECUREWARE)
    201 	if (iscomsec() && (spw = getprpwnam(pw->pw_name)) != NULL)
    202 		pw_password = spw->ufld.fd_encrypt;
    203 #endif /* defined(__hpux) && !defined(HAVE_SECUREWARE) */
    204 
    205 	/* Check for users with no password. */
    206 	if ((password[0] == '\0') && (pw_password[0] == '\0'))
    207 		return 1;
    208 
    209 	if (pw_password[0] != '\0')
    210 		salt = pw_password;
    211 	else
    212 		salt = "xx";
    213 
    214 #ifdef HAVE_MD5_PASSWORDS
    215 	if (is_md5_salt(salt))
    216 		encrypted_password = md5_crypt(password, salt);
    217 	else
    218 		encrypted_password = crypt(password, salt);
    219 #else /* HAVE_MD5_PASSWORDS */
    220 # if defined(__hpux) && !defined(HAVE_SECUREWARE)
    221 	if (iscomsec())
    222 		encrypted_password = bigcrypt(password, salt);
    223 	else
    224 		encrypted_password = crypt(password, salt);
    225 # else
    226 #  ifdef HAVE_SECUREWARE
    227 	encrypted_password = bigcrypt(password, salt);
    228 #  else
    229 	encrypted_password = crypt(password, salt);
    230 #  endif /* HAVE_SECUREWARE */
    231 # endif /* __hpux && !defined(HAVE_SECUREWARE) */
    232 #endif /* HAVE_MD5_PASSWORDS */
    233 
    234 	/* Authentication is accepted if the encrypted passwords are identical. */
    235 	return (strcmp(encrypted_password, pw_password) == 0);
    236 #endif /* !USE_PAM && !HAVE_OSF_SIA */
    237 }
    238