Branch data Line data Source code
1 : : /* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */
2 : : /*
3 : : * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 : : * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 : : * All rights reserved
6 : : * Password authentication. This file contains the functions to check whether
7 : : * the password is valid for the user.
8 : : *
9 : : * As far as I am concerned, the code I have written for this software
10 : : * can be used freely for any purpose. Any derived versions of this
11 : : * software must be clearly marked as such, and if the derived work is
12 : : * incompatible with the protocol description in the RFC file, it must be
13 : : * called by a name other than "ssh" or "Secure Shell".
14 : : *
15 : : * Copyright (c) 1999 Dug Song. All rights reserved.
16 : : * Copyright (c) 2000 Markus Friedl. All rights reserved.
17 : : *
18 : : * Redistribution and use in source and binary forms, with or without
19 : : * modification, are permitted provided that the following conditions
20 : : * are met:
21 : : * 1. Redistributions of source code must retain the above copyright
22 : : * notice, this list of conditions and the following disclaimer.
23 : : * 2. Redistributions in binary form must reproduce the above copyright
24 : : * notice, this list of conditions and the following disclaimer in the
25 : : * documentation and/or other materials provided with the distribution.
26 : : *
27 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 : : */
38 : :
39 : : #include "includes.h"
40 : :
41 : : #include <sys/types.h>
42 : :
43 : : #include <pwd.h>
44 : : #include <stdio.h>
45 : : #include <string.h>
46 : : #include <stdarg.h>
47 : :
48 : : #include "packet.h"
49 : : #include "buffer.h"
50 : : #include "log.h"
51 : : #include "servconf.h"
52 : : #include "key.h"
53 : : #include "hostfile.h"
54 : : #include "auth.h"
55 : : #include "auth-options.h"
56 : :
57 : : extern Buffer loginmsg;
58 : : extern ServerOptions options;
59 : :
60 : : #ifdef HAVE_LOGIN_CAP
61 : : extern login_cap_t *lc;
62 : : #endif
63 : :
64 : :
65 : : #define DAY (24L * 60 * 60) /* 1 day in seconds */
66 : : #define TWO_WEEKS (2L * 7 * DAY) /* 2 weeks in seconds */
67 : :
68 : : void
69 : 0 : disable_forwarding(void)
70 : : {
71 : 0 : no_port_forwarding_flag = 1;
72 : 0 : no_agent_forwarding_flag = 1;
73 : 0 : no_x11_forwarding_flag = 1;
74 : 0 : }
75 : :
76 : : /*
77 : : * Tries to authenticate the user using password. Returns true if
78 : : * authentication succeeds.
79 : : */
80 : : int
81 : 0 : auth_password(Authctxt *authctxt, const char *password)
82 : : {
83 : 0 : struct passwd * pw = authctxt->pw;
84 : 0 : int result, ok = authctxt->valid;
85 : : #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
86 : : static int expire_checked = 0;
87 : : #endif
88 : :
89 : : #ifndef HAVE_CYGWIN
90 [ # # ][ # # ]: 0 : if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
91 : 0 : ok = 0;
92 : : #endif
93 [ # # ][ # # ]: 0 : if (*password == '\0' && options.permit_empty_passwd == 0)
94 : : return 0;
95 : :
96 : : #ifdef KRB5
97 : : if (options.kerberos_authentication == 1) {
98 : : int ret = auth_krb5_password(authctxt, password);
99 : : if (ret == 1 || ret == 0)
100 : : return ret && ok;
101 : : /* Fall back to ordinary passwd authentication. */
102 : : }
103 : : #endif
104 : : #ifdef HAVE_CYGWIN
105 : : {
106 : : HANDLE hToken = cygwin_logon_user(pw, password);
107 : :
108 : : if (hToken == INVALID_HANDLE_VALUE)
109 : : return 0;
110 : : cygwin_set_impersonation_token(hToken);
111 : : return ok;
112 : : }
113 : : #endif
114 : : #ifdef USE_PAM
115 : : if (options.use_pam)
116 : : return (sshpam_auth_passwd(authctxt, password) && ok);
117 : : #endif
118 : : #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
119 [ # # ]: 0 : if (!expire_checked) {
120 : 0 : expire_checked = 1;
121 [ # # ]: 0 : if (auth_shadow_pwexpired(authctxt))
122 : 0 : authctxt->force_pwchange = 1;
123 : : }
124 : : #endif
125 : 0 : result = sys_auth_passwd(authctxt, password);
126 [ # # ]: 0 : if (authctxt->force_pwchange)
127 : : disable_forwarding();
128 : 0 : return (result && ok);
129 : : }
130 : :
131 : : #ifdef BSD_AUTH
132 : : static void
133 : : warn_expiry(Authctxt *authctxt, auth_session_t *as)
134 : : {
135 : : char buf[256];
136 : : quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime;
137 : :
138 : : pwwarntime = acwarntime = TWO_WEEKS;
139 : :
140 : : pwtimeleft = auth_check_change(as);
141 : : actimeleft = auth_check_expire(as);
142 : : #ifdef HAVE_LOGIN_CAP
143 : : if (authctxt->valid) {
144 : : pwwarntime = login_getcaptime(lc, "password-warn", TWO_WEEKS,
145 : : TWO_WEEKS);
146 : : acwarntime = login_getcaptime(lc, "expire-warn", TWO_WEEKS,
147 : : TWO_WEEKS);
148 : : }
149 : : #endif
150 : : if (pwtimeleft != 0 && pwtimeleft < pwwarntime) {
151 : : daysleft = pwtimeleft / DAY + 1;
152 : : snprintf(buf, sizeof(buf),
153 : : "Your password will expire in %lld day%s.\n",
154 : : daysleft, daysleft == 1 ? "" : "s");
155 : : buffer_append(&loginmsg, buf, strlen(buf));
156 : : }
157 : : if (actimeleft != 0 && actimeleft < acwarntime) {
158 : : daysleft = actimeleft / DAY + 1;
159 : : snprintf(buf, sizeof(buf),
160 : : "Your account will expire in %lld day%s.\n",
161 : : daysleft, daysleft == 1 ? "" : "s");
162 : : buffer_append(&loginmsg, buf, strlen(buf));
163 : : }
164 : : }
165 : :
166 : : int
167 : : sys_auth_passwd(Authctxt *authctxt, const char *password)
168 : : {
169 : : struct passwd *pw = authctxt->pw;
170 : : auth_session_t *as;
171 : : static int expire_checked = 0;
172 : :
173 : : as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh",
174 : : (char *)password);
175 : : if (as == NULL)
176 : : return (0);
177 : : if (auth_getstate(as) & AUTH_PWEXPIRED) {
178 : : auth_close(as);
179 : : disable_forwarding();
180 : : authctxt->force_pwchange = 1;
181 : : return (1);
182 : : } else {
183 : : if (!expire_checked) {
184 : : expire_checked = 1;
185 : : warn_expiry(authctxt, as);
186 : : }
187 : : return (auth_close(as));
188 : : }
189 : : }
190 : : #elif !defined(CUSTOM_SYS_AUTH_PASSWD)
191 : : int
192 : 0 : sys_auth_passwd(Authctxt *authctxt, const char *password)
193 : : {
194 : 0 : struct passwd *pw = authctxt->pw;
195 : : char *encrypted_password;
196 : :
197 : : /* Just use the supplied fake password if authctxt is invalid */
198 [ # # ]: 0 : char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
199 : :
200 : : /* Check for users with no password. */
201 [ # # ][ # # ]: 0 : if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
202 : : return (1);
203 : :
204 : : /* Encrypt the candidate password using the proper salt. */
205 [ # # ]: 0 : encrypted_password = xcrypt(password,
206 [ # # ]: 0 : (pw_password[0] && pw_password[1]) ? pw_password : "xx");
207 : :
208 : : /*
209 : : * Authentication is accepted if the encrypted passwords
210 : : * are identical.
211 : : */
212 [ # # ][ # # ]: 0 : return encrypted_password != NULL &&
213 : 0 : strcmp(encrypted_password, pw_password) == 0;
214 : : }
215 : : #endif
|