auth-passwd.c revision 99748
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@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"
39RCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $");
40RCSID("$FreeBSD: head/crypto/openssh/auth-passwd.c 99748 2002-07-10 23:05:13Z des $");
41
42#include "packet.h"
43#include "log.h"
44#include "servconf.h"
45#include "auth.h"
46
47/*
48 * Do not try to use PAM for password authentication, as it is
49 * already (and far better) supported by the challenge/response
50 * authentication mechanism.
51 */
52#undef USE_PAM
53
54#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
55/* Don't need any of these headers for the PAM or SIA cases */
56# ifdef HAVE_CRYPT_H
57#  include <crypt.h>
58# endif
59# ifdef WITH_AIXAUTHENTICATE
60#  include <login.h>
61# endif
62# ifdef __hpux
63#  include <hpsecurity.h>
64#  include <prot.h>
65# endif
66# ifdef HAVE_SECUREWARE
67#  include <sys/security.h>
68#  include <sys/audit.h>
69#  include <prot.h>
70# endif /* HAVE_SECUREWARE */
71# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
72#  include <shadow.h>
73# endif
74# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
75#  include <sys/label.h>
76#  include <sys/audit.h>
77#  include <pwdadj.h>
78# endif
79# if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT)
80#  include "md5crypt.h"
81# endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */
82
83# ifdef HAVE_CYGWIN
84#  undef ERROR
85#  include <windows.h>
86#  include <sys/cygwin.h>
87#  define is_winnt       (GetVersion() < 0x80000000)
88# endif
89#endif /* !USE_PAM && !HAVE_OSF_SIA */
90
91extern ServerOptions options;
92
93/*
94 * Tries to authenticate the user using password.  Returns true if
95 * authentication succeeds.
96 */
97int
98auth_password(Authctxt *authctxt, const char *password)
99{
100#if defined(USE_PAM)
101	if (*password == '\0' && options.permit_empty_passwd == 0)
102		return 0;
103	return auth_pam_password(authctxt, password);
104#elif defined(HAVE_OSF_SIA)
105	if (*password == '\0' && options.permit_empty_passwd == 0)
106		return 0;
107	return auth_sia_password(authctxt, password);
108#else
109	struct passwd * pw = authctxt->pw;
110	char *encrypted_password;
111	char *pw_password;
112	char *salt;
113#if defined(__hpux) || defined(HAVE_SECUREWARE)
114	struct pr_passwd *spw;
115#endif /* __hpux || HAVE_SECUREWARE */
116#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
117	struct spwd *spw;
118#endif
119#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
120	struct passwd_adjunct *spw;
121#endif
122#ifdef WITH_AIXAUTHENTICATE
123	char *authmsg;
124	char *loginmsg;
125	int reenter = 1;
126#endif
127
128	/* deny if no user. */
129	if (pw == NULL)
130		return 0;
131#ifndef HAVE_CYGWIN
132       if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
133		return 0;
134#endif
135	if (*password == '\0' && options.permit_empty_passwd == 0)
136		return 0;
137#ifdef KRB5
138	if (options.kerberos_authentication == 1) {
139		int ret = auth_krb5_password(authctxt, password);
140		if (ret == 1 || ret == 0)
141			return ret;
142		/* Fall back to ordinary passwd authentication. */
143	}
144#endif
145#ifdef HAVE_CYGWIN
146	if (is_winnt) {
147		HANDLE hToken = cygwin_logon_user(pw, password);
148
149		if (hToken == INVALID_HANDLE_VALUE)
150			return 0;
151		cygwin_set_impersonation_token(hToken);
152		return 1;
153	}
154#endif
155#ifdef WITH_AIXAUTHENTICATE
156	return (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
157#endif
158#ifdef KRB4
159	if (options.kerberos_authentication == 1) {
160		int ret = auth_krb4_password(authctxt, password);
161		if (ret == 1 || ret == 0)
162			return ret;
163		/* Fall back to ordinary passwd authentication. */
164	}
165#endif
166#ifdef BSD_AUTH
167	if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
168	    (char *)password) == 0)
169		return 0;
170	else
171		return 1;
172#endif
173	pw_password = pw->pw_passwd;
174
175	/*
176	 * Various interfaces to shadow or protected password data
177	 */
178#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
179	spw = getspnam(pw->pw_name);
180	if (spw != NULL)
181		pw_password = spw->sp_pwdp;
182#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
183
184#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
185	if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL)
186		pw_password = spw->pwa_passwd;
187#endif /* defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) */
188
189#ifdef HAVE_SECUREWARE
190	if ((spw = getprpwnam(pw->pw_name)) != NULL)
191		pw_password = spw->ufld.fd_encrypt;
192#endif /* HAVE_SECUREWARE */
193
194#if defined(__hpux) && !defined(HAVE_SECUREWARE)
195	if (iscomsec() && (spw = getprpwnam(pw->pw_name)) != NULL)
196		pw_password = spw->ufld.fd_encrypt;
197#endif /* defined(__hpux) && !defined(HAVE_SECUREWARE) */
198
199	/* Check for users with no password. */
200	if ((password[0] == '\0') && (pw_password[0] == '\0'))
201		return 1;
202
203	if (pw_password[0] != '\0')
204		salt = pw_password;
205	else
206		salt = "xx";
207
208#ifdef HAVE_MD5_PASSWORDS
209	if (is_md5_salt(salt))
210		encrypted_password = md5_crypt(password, salt);
211	else
212		encrypted_password = crypt(password, salt);
213#else /* HAVE_MD5_PASSWORDS */
214# if defined(__hpux) && !defined(HAVE_SECUREWARE)
215	if (iscomsec())
216		encrypted_password = bigcrypt(password, salt);
217	else
218		encrypted_password = crypt(password, salt);
219# else
220#  ifdef HAVE_SECUREWARE
221	encrypted_password = bigcrypt(password, salt);
222#  else
223	encrypted_password = crypt(password, salt);
224#  endif /* HAVE_SECUREWARE */
225# endif /* __hpux && !defined(HAVE_SECUREWARE) */
226#endif /* HAVE_MD5_PASSWORDS */
227
228	/* Authentication is accepted if the encrypted passwords are identical. */
229	return (strcmp(encrypted_password, pw_password) == 0);
230#endif /* !USE_PAM && !HAVE_OSF_SIA */
231}
232