auth-passwd.c revision 106130
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 106130 2002-10-29 10:16:02Z 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#ifdef WITH_AIXAUTHENTICATE
93extern char *aixloginmsg;
94#endif
95
96/*
97 * Tries to authenticate the user using password.  Returns true if
98 * authentication succeeds.
99 */
100int
101auth_password(Authctxt *authctxt, const char *password)
102{
103#if defined(USE_PAM)
104	if (*password == '\0' && options.permit_empty_passwd == 0)
105		return 0;
106	return auth_pam_password(authctxt, password);
107#elif defined(HAVE_OSF_SIA)
108	if (*password == '\0' && options.permit_empty_passwd == 0)
109		return 0;
110	return auth_sia_password(authctxt, password);
111#else
112	struct passwd * pw = authctxt->pw;
113	char *encrypted_password;
114	char *pw_password;
115	char *salt;
116#if defined(__hpux) || defined(HAVE_SECUREWARE)
117	struct pr_passwd *spw;
118#endif /* __hpux || HAVE_SECUREWARE */
119#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
120	struct spwd *spw;
121#endif
122#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
123	struct passwd_adjunct *spw;
124#endif
125#ifdef WITH_AIXAUTHENTICATE
126	char *authmsg;
127	int authsuccess;
128	int reenter = 1;
129#endif
130
131	/* deny if no user. */
132	if (pw == NULL)
133		return 0;
134#ifndef HAVE_CYGWIN
135       if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
136		return 0;
137#endif
138	if (*password == '\0' && options.permit_empty_passwd == 0)
139		return 0;
140#ifdef KRB5
141	if (options.kerberos_authentication == 1) {
142		int ret = auth_krb5_password(authctxt, password);
143		if (ret == 1 || ret == 0)
144			return ret;
145		/* Fall back to ordinary passwd authentication. */
146	}
147#endif
148#ifdef HAVE_CYGWIN
149	if (is_winnt) {
150		HANDLE hToken = cygwin_logon_user(pw, password);
151
152		if (hToken == INVALID_HANDLE_VALUE)
153			return 0;
154		cygwin_set_impersonation_token(hToken);
155		return 1;
156	}
157#endif
158#ifdef WITH_AIXAUTHENTICATE
159	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
160
161	if (authsuccess)
162	        /* We don't have a pty yet, so just label the line as "ssh" */
163	        if (loginsuccess(authctxt->user,
164			get_canonical_hostname(options.verify_reverse_mapping),
165			"ssh", &aixloginmsg) < 0)
166				aixloginmsg = NULL;
167
168	return(authsuccess);
169#endif
170#ifdef KRB4
171	if (options.kerberos_authentication == 1) {
172		int ret = auth_krb4_password(authctxt, password);
173		if (ret == 1 || ret == 0)
174			return ret;
175		/* Fall back to ordinary passwd authentication. */
176	}
177#endif
178#ifdef BSD_AUTH
179	if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
180	    (char *)password) == 0)
181		return 0;
182	else
183		return 1;
184#endif
185	pw_password = pw->pw_passwd;
186
187	/*
188	 * Various interfaces to shadow or protected password data
189	 */
190#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
191	spw = getspnam(pw->pw_name);
192	if (spw != NULL)
193		pw_password = spw->sp_pwdp;
194#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
195
196#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
197	if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL)
198		pw_password = spw->pwa_passwd;
199#endif /* defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) */
200
201#ifdef HAVE_SECUREWARE
202	if ((spw = getprpwnam(pw->pw_name)) != NULL)
203		pw_password = spw->ufld.fd_encrypt;
204#endif /* HAVE_SECUREWARE */
205
206#if defined(__hpux) && !defined(HAVE_SECUREWARE)
207	if (iscomsec() && (spw = getprpwnam(pw->pw_name)) != NULL)
208		pw_password = spw->ufld.fd_encrypt;
209#endif /* defined(__hpux) && !defined(HAVE_SECUREWARE) */
210
211	/* Check for users with no password. */
212	if ((password[0] == '\0') && (pw_password[0] == '\0'))
213		return 1;
214
215	if (pw_password[0] != '\0')
216		salt = pw_password;
217	else
218		salt = "xx";
219
220#ifdef HAVE_MD5_PASSWORDS
221	if (is_md5_salt(salt))
222		encrypted_password = md5_crypt(password, salt);
223	else
224		encrypted_password = crypt(password, salt);
225#else /* HAVE_MD5_PASSWORDS */
226# if defined(__hpux) && !defined(HAVE_SECUREWARE)
227	if (iscomsec())
228		encrypted_password = bigcrypt(password, salt);
229	else
230		encrypted_password = crypt(password, salt);
231# else
232#  ifdef HAVE_SECUREWARE
233	encrypted_password = bigcrypt(password, salt);
234#  else
235	encrypted_password = crypt(password, salt);
236#  endif /* HAVE_SECUREWARE */
237# endif /* __hpux && !defined(HAVE_SECUREWARE) */
238#endif /* HAVE_MD5_PASSWORDS */
239
240	/* Authentication is accepted if the encrypted passwords are identical. */
241	return (strcmp(encrypted_password, pw_password) == 0);
242#endif /* !USE_PAM && !HAVE_OSF_SIA */
243}
244