auth-passwd.c revision 113911
1244543Sbrooks/*
2244543Sbrooks * Author: Tatu Ylonen <ylo@cs.hut.fi>
3244543Sbrooks * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4244543Sbrooks *                    All rights reserved
5244543Sbrooks * Password authentication.  This file contains the functions to check whether
6244543Sbrooks * the password is valid for the user.
7244543Sbrooks *
8244543Sbrooks * As far as I am concerned, the code I have written for this software
9244543Sbrooks * can be used freely for any purpose.  Any derived versions of this
10244543Sbrooks * software must be clearly marked as such, and if the derived work is
11244543Sbrooks * incompatible with the protocol description in the RFC file, it must be
12244543Sbrooks * called by a name other than "ssh" or "Secure Shell".
13244543Sbrooks *
14244543Sbrooks * Copyright (c) 1999 Dug Song.  All rights reserved.
15244543Sbrooks * Copyright (c) 2000 Markus Friedl.  All rights reserved.
16244543Sbrooks *
17244543Sbrooks * Redistribution and use in source and binary forms, with or without
18244543Sbrooks * modification, are permitted provided that the following conditions
19244543Sbrooks * are met:
20244543Sbrooks * 1. Redistributions of source code must retain the above copyright
21244543Sbrooks *    notice, this list of conditions and the following disclaimer.
22244543Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
23244543Sbrooks *    notice, this list of conditions and the following disclaimer in the
24244543Sbrooks *    documentation and/or other materials provided with the distribution.
25244543Sbrooks *
26244543Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27244543Sbrooks * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28244543Sbrooks * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29244543Sbrooks * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30244543Sbrooks * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31244543Sbrooks * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32244543Sbrooks * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33244543Sbrooks * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34244543Sbrooks * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35244543Sbrooks * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36244543Sbrooks */
37244543Sbrooks
38244543Sbrooks#include "includes.h"
39244543SbrooksRCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $");
40244543SbrooksRCSID("$FreeBSD: head/crypto/openssh/auth-passwd.c 113911 2003-04-23 17:13:13Z des $");
41244543Sbrooks
42244543Sbrooks#include "packet.h"
43244543Sbrooks#include "log.h"
44244543Sbrooks#include "servconf.h"
45244543Sbrooks#include "auth.h"
46244543Sbrooks
47244543Sbrooks/*
48244543Sbrooks * Do not try to use PAM for password authentication, as it is
49244543Sbrooks * already (and far better) supported by the challenge/response
50244543Sbrooks * authentication mechanism.
51244543Sbrooks */
52244543Sbrooks#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	struct passwd * pw = authctxt->pw;
104#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
105	char *encrypted_password;
106	char *pw_password;
107	char *salt;
108# if defined(__hpux) || defined(HAVE_SECUREWARE)
109	struct pr_passwd *spw;
110# endif /* __hpux || HAVE_SECUREWARE */
111# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
112	struct spwd *spw;
113# endif
114# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
115	struct passwd_adjunct *spw;
116# endif
117# ifdef WITH_AIXAUTHENTICATE
118	char *authmsg;
119	int authsuccess;
120	int reenter = 1;
121# endif
122#endif /* !defined(USE_PAM) && !defined(HAVE_OSF_SIA) */
123
124	/* deny if no user. */
125	if (pw == NULL)
126		return 0;
127#ifndef HAVE_CYGWIN
128       if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
129		return 0;
130#endif
131	if (*password == '\0' && options.permit_empty_passwd == 0)
132		return 0;
133
134#if defined(USE_PAM)
135	return auth_pam_password(authctxt, password);
136#elif defined(HAVE_OSF_SIA)
137	return auth_sia_password(authctxt, password);
138#else
139# ifdef KRB5
140	if (options.kerberos_authentication == 1) {
141		int ret = auth_krb5_password(authctxt, password);
142		if (ret == 1 || ret == 0)
143			return ret;
144		/* Fall back to ordinary passwd authentication. */
145	}
146# endif
147# ifdef HAVE_CYGWIN
148	if (is_winnt) {
149		HANDLE hToken = cygwin_logon_user(pw, password);
150
151		if (hToken == INVALID_HANDLE_VALUE)
152			return 0;
153		cygwin_set_impersonation_token(hToken);
154		return 1;
155	}
156# endif
157# ifdef WITH_AIXAUTHENTICATE
158	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
159
160	if (authsuccess)
161	        /* We don't have a pty yet, so just label the line as "ssh" */
162	        if (loginsuccess(authctxt->user,
163			get_canonical_hostname(options.verify_reverse_mapping),
164			"ssh", &aixloginmsg) < 0)
165				aixloginmsg = NULL;
166
167	return(authsuccess);
168# endif
169# ifdef KRB4
170	if (options.kerberos_authentication == 1) {
171		int ret = auth_krb4_password(authctxt, password);
172		if (ret == 1 || ret == 0)
173			return ret;
174		/* Fall back to ordinary passwd authentication. */
175	}
176# endif
177# ifdef BSD_AUTH
178	if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
179	    (char *)password) == 0)
180		return 0;
181	else
182		return 1;
183# endif
184	pw_password = pw->pw_passwd;
185
186	/*
187	 * Various interfaces to shadow or protected password data
188	 */
189# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
190	spw = getspnam(pw->pw_name);
191	if (spw != NULL)
192		pw_password = spw->sp_pwdp;
193# endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
194
195# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
196	if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL)
197		pw_password = spw->pwa_passwd;
198# endif /* defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) */
199
200# ifdef HAVE_SECUREWARE
201	if ((spw = getprpwnam(pw->pw_name)) != NULL)
202		pw_password = spw->ufld.fd_encrypt;
203# endif /* HAVE_SECUREWARE */
204
205# if defined(__hpux) && !defined(HAVE_SECUREWARE)
206	if (iscomsec() && (spw = getprpwnam(pw->pw_name)) != NULL)
207		pw_password = spw->ufld.fd_encrypt;
208# endif /* defined(__hpux) && !defined(HAVE_SECUREWARE) */
209
210	/* Check for users with no password. */
211	if ((password[0] == '\0') && (pw_password[0] == '\0'))
212		return 1;
213
214	if (pw_password[0] != '\0')
215		salt = pw_password;
216	else
217		salt = "xx";
218
219# ifdef HAVE_MD5_PASSWORDS
220	if (is_md5_salt(salt))
221		encrypted_password = md5_crypt(password, salt);
222	else
223		encrypted_password = crypt(password, salt);
224# else /* HAVE_MD5_PASSWORDS */
225#  if defined(__hpux) && !defined(HAVE_SECUREWARE)
226	if (iscomsec())
227		encrypted_password = bigcrypt(password, salt);
228	else
229		encrypted_password = crypt(password, salt);
230#  else
231#   ifdef HAVE_SECUREWARE
232	encrypted_password = bigcrypt(password, salt);
233#   else
234	encrypted_password = crypt(password, salt);
235#   endif /* HAVE_SECUREWARE */
236#  endif /* __hpux && !defined(HAVE_SECUREWARE) */
237# endif /* HAVE_MD5_PASSWORDS */
238
239	/* Authentication is accepted if the encrypted passwords are identical. */
240	return (strcmp(encrypted_password, pw_password) == 0);
241#endif /* !USE_PAM && !HAVE_OSF_SIA */
242}
243