auth-passwd.c revision 147005
1169689Skan/* 2169689Skan * Author: Tatu Ylonen <ylo@cs.hut.fi> 3169689Skan * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4169689Skan * All rights reserved 5169689Skan * Password authentication. This file contains the functions to check whether 6169689Skan * the password is valid for the user. 7169689Skan * 8169689Skan * As far as I am concerned, the code I have written for this software 9169689Skan * can be used freely for any purpose. Any derived versions of this 10169689Skan * software must be clearly marked as such, and if the derived work is 11169689Skan * incompatible with the protocol description in the RFC file, it must be 12169689Skan * called by a name other than "ssh" or "Secure Shell". 13169689Skan * 14169689Skan * Copyright (c) 1999 Dug Song. All rights reserved. 15169689Skan * Copyright (c) 2000 Markus Friedl. All rights reserved. 16169689Skan * 17169689Skan * Redistribution and use in source and binary forms, with or without 18169689Skan * modification, are permitted provided that the following conditions 19169689Skan * are met: 20169689Skan * 1. Redistributions of source code must retain the above copyright 21169689Skan * notice, this list of conditions and the following disclaimer. 22169689Skan * 2. Redistributions in binary form must reproduce the above copyright 23169689Skan * notice, this list of conditions and the following disclaimer in the 24169689Skan * documentation and/or other materials provided with the distribution. 25169689Skan * 26169689Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27169689Skan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28169689Skan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29169689Skan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30169689Skan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31169689Skan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32169689Skan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33169689Skan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34169689Skan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35169689Skan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36169689Skan */ 37169689Skan 38169689Skan#include "includes.h" 39169689SkanRCSID("$OpenBSD: auth-passwd.c,v 1.33 2005/01/24 11:47:13 dtucker Exp $"); 40169689SkanRCSID("$FreeBSD: head/crypto/openssh/auth-passwd.c 147005 2005-06-05 15:46:09Z des $"); 41169689Skan 42169689Skan#include "packet.h" 43169689Skan#include "buffer.h" 44169689Skan#include "log.h" 45169689Skan#include "servconf.h" 46169689Skan#include "auth.h" 47169689Skan#include "auth-options.h" 48169689Skan 49169689Skanextern Buffer loginmsg; 50169689Skanextern ServerOptions options; 51169689Skan 52169689Skan#ifdef HAVE_LOGIN_CAP 53169689Skanextern login_cap_t *lc; 54169689Skan#endif 55169689Skan 56169689Skan 57169689Skan#define DAY (24L * 60 * 60) /* 1 day in seconds */ 58169689Skan#define TWO_WEEKS (2L * 7 * DAY) /* 2 weeks in seconds */ 59169689Skan 60169689Skanvoid 61169689Skandisable_forwarding(void) 62169689Skan{ 63169689Skan no_port_forwarding_flag = 1; 64169689Skan no_agent_forwarding_flag = 1; 65169689Skan no_x11_forwarding_flag = 1; 66169689Skan} 67169689Skan 68169689Skan/* 69169689Skan * Tries to authenticate the user using password. Returns true if 70169689Skan * authentication succeeds. 71169689Skan */ 72169689Skanint 73169689Skanauth_password(Authctxt *authctxt, const char *password) 74169689Skan{ 75169689Skan struct passwd * pw = authctxt->pw; 76169689Skan int result, ok = authctxt->valid; 77169689Skan#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) 78169689Skan static int expire_checked = 0; 79169689Skan#endif 80169689Skan 81169689Skan#ifndef HAVE_CYGWIN 82169689Skan if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) 83169689Skan ok = 0; 84#endif 85 if (*password == '\0' && options.permit_empty_passwd == 0) 86 return 0; 87 88#ifdef KRB5 89 if (options.kerberos_authentication == 1) { 90 int ret = auth_krb5_password(authctxt, password); 91 if (ret == 1 || ret == 0) 92 return ret && ok; 93 /* Fall back to ordinary passwd authentication. */ 94 } 95#endif 96#ifdef HAVE_CYGWIN 97 if (is_winnt) { 98 HANDLE hToken = cygwin_logon_user(pw, password); 99 100 if (hToken == INVALID_HANDLE_VALUE) 101 return 0; 102 cygwin_set_impersonation_token(hToken); 103 return ok; 104 } 105#endif 106#ifdef USE_PAM 107 if (options.use_pam) 108 return (sshpam_auth_passwd(authctxt, password) && ok); 109#endif 110#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) 111 if (!expire_checked) { 112 expire_checked = 1; 113 if (auth_shadow_pwexpired(authctxt)) 114 authctxt->force_pwchange = 1; 115 } 116#endif 117 result = sys_auth_passwd(authctxt, password); 118 if (authctxt->force_pwchange) 119 disable_forwarding(); 120 return (result && ok); 121} 122 123#ifdef BSD_AUTH 124static void 125warn_expiry(Authctxt *authctxt, auth_session_t *as) 126{ 127 char buf[256]; 128 quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime; 129 130 pwwarntime = acwarntime = TWO_WEEKS; 131 132 pwtimeleft = auth_check_change(as); 133 actimeleft = auth_check_expire(as); 134#ifdef HAVE_LOGIN_CAP 135 if (authctxt->valid) { 136 pwwarntime = login_getcaptime(lc, "password-warn", TWO_WEEKS, 137 TWO_WEEKS); 138 acwarntime = login_getcaptime(lc, "expire-warn", TWO_WEEKS, 139 TWO_WEEKS); 140 } 141#endif 142 if (pwtimeleft != 0 && pwtimeleft < pwwarntime) { 143 daysleft = pwtimeleft / DAY + 1; 144 snprintf(buf, sizeof(buf), 145 "Your password will expire in %lld day%s.\n", 146 daysleft, daysleft == 1 ? "" : "s"); 147 buffer_append(&loginmsg, buf, strlen(buf)); 148 } 149 if (actimeleft != 0 && actimeleft < acwarntime) { 150 daysleft = actimeleft / DAY + 1; 151 snprintf(buf, sizeof(buf), 152 "Your account will expire in %lld day%s.\n", 153 daysleft, daysleft == 1 ? "" : "s"); 154 buffer_append(&loginmsg, buf, strlen(buf)); 155 } 156} 157 158int 159sys_auth_passwd(Authctxt *authctxt, const char *password) 160{ 161 struct passwd *pw = authctxt->pw; 162 auth_session_t *as; 163 static int expire_checked = 0; 164 165 as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh", 166 (char *)password); 167 if (auth_getstate(as) & AUTH_PWEXPIRED) { 168 auth_close(as); 169 disable_forwarding(); 170 authctxt->force_pwchange = 1; 171 return (1); 172 } else { 173 if (!expire_checked) { 174 expire_checked = 1; 175 warn_expiry(authctxt, as); 176 } 177 return (auth_close(as)); 178 } 179} 180#elif !defined(CUSTOM_SYS_AUTH_PASSWD) 181int 182sys_auth_passwd(Authctxt *authctxt, const char *password) 183{ 184 struct passwd *pw = authctxt->pw; 185 char *encrypted_password; 186 187 /* Just use the supplied fake password if authctxt is invalid */ 188 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; 189 190 /* Check for users with no password. */ 191 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) 192 return (1); 193 194 /* Encrypt the candidate password using the proper salt. */ 195 encrypted_password = xcrypt(password, 196 (pw_password[0] && pw_password[1]) ? pw_password : "xx"); 197 198 /* 199 * Authentication is accepted if the encrypted passwords 200 * are identical. 201 */ 202 return (strcmp(encrypted_password, pw_password) == 0); 203} 204#endif 205