auth-passwd.c revision 147005
11539Srgrimes/* 21539Srgrimes * Author: Tatu Ylonen <ylo@cs.hut.fi> 31539Srgrimes * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 41539Srgrimes * All rights reserved 51539Srgrimes * Password authentication. This file contains the functions to check whether 61539Srgrimes * the password is valid for the user. 71539Srgrimes * 81539Srgrimes * As far as I am concerned, the code I have written for this software 91539Srgrimes * can be used freely for any purpose. Any derived versions of this 101539Srgrimes * software must be clearly marked as such, and if the derived work is 111539Srgrimes * incompatible with the protocol description in the RFC file, it must be 121539Srgrimes * called by a name other than "ssh" or "Secure Shell". 131539Srgrimes * 141539Srgrimes * Copyright (c) 1999 Dug Song. All rights reserved. 151539Srgrimes * Copyright (c) 2000 Markus Friedl. All rights reserved. 161539Srgrimes * 171539Srgrimes * Redistribution and use in source and binary forms, with or without 181539Srgrimes * modification, are permitted provided that the following conditions 191539Srgrimes * are met: 201539Srgrimes * 1. Redistributions of source code must retain the above copyright 211539Srgrimes * notice, this list of conditions and the following disclaimer. 221539Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 231539Srgrimes * notice, this list of conditions and the following disclaimer in the 241539Srgrimes * documentation and/or other materials provided with the distribution. 251539Srgrimes * 261539Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 271539Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 281539Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 291539Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 301539Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 311539Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 321539Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 331539Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 341539Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 358858Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 361539Srgrimes */ 371539Srgrimes 381539Srgrimes#include "includes.h" 391539SrgrimesRCSID("$OpenBSD: auth-passwd.c,v 1.33 2005/01/24 11:47:13 dtucker Exp $"); 401539SrgrimesRCSID("$FreeBSD: head/crypto/openssh/auth-passwd.c 147005 2005-06-05 15:46:09Z des $"); 411539Srgrimes 428858Srgrimes#include "packet.h" 431539Srgrimes#include "buffer.h" 441539Srgrimes#include "log.h" 451539Srgrimes#include "servconf.h" 461539Srgrimes#include "auth.h" 471539Srgrimes#include "auth-options.h" 481539Srgrimes 491539Srgrimesextern Buffer loginmsg; 501539Srgrimesextern ServerOptions options; 511539Srgrimes 521539Srgrimes#ifdef HAVE_LOGIN_CAP 531539Srgrimesextern login_cap_t *lc; 541539Srgrimes#endif 5536888Speter 5636888Speter 5736888Speter#define DAY (24L * 60 * 60) /* 1 day in seconds */ 5850473Speter#define TWO_WEEKS (2L * 7 * DAY) /* 2 weeks in seconds */ 5936888Speter 6036888Spetervoid 611539Srgrimesdisable_forwarding(void) 621539Srgrimes{ 631539Srgrimes no_port_forwarding_flag = 1; 6484463Sbde no_agent_forwarding_flag = 1; 65102227Smike no_x11_forwarding_flag = 1; 66146244Sume} 67146244Sume 6821055Speter/* 69102227Smike * Tries to authenticate the user using password. Returns true if 70102227Smike * authentication succeeds. 71102227Smike */ 7272510Sumeint 7372510Sumeauth_password(Authctxt *authctxt, const char *password) 74102227Smike{ 75102227Smike struct passwd * pw = authctxt->pw; 76102227Smike int result, ok = authctxt->valid; 7784463Sbde#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) 7884463Sbde static int expire_checked = 0; 79146244Sume#endif 80146244Sume 81146244Sume#ifndef HAVE_CYGWIN 82146244Sume if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) 83146244Sume ok = 0; 8436888Speter#endif 8536888Speter if (*password == '\0' && options.permit_empty_passwd == 0) 8636888Speter return 0; 871539Srgrimes 881539Srgrimes#ifdef KRB5 891539Srgrimes if (options.kerberos_authentication == 1) { 901539Srgrimes int ret = auth_krb5_password(authctxt, password); 911539Srgrimes if (ret == 1 || ret == 0) 92126243Sgreen return ret && ok; 9310132Speter /* Fall back to ordinary passwd authentication. */ 941539Srgrimes } 951539Srgrimes#endif 961539Srgrimes#ifdef HAVE_CYGWIN 971539Srgrimes if (is_winnt) { 981539Srgrimes HANDLE hToken = cygwin_logon_user(pw, password); 9983047Sobrien 1001539Srgrimes if (hToken == INVALID_HANDLE_VALUE) 1011539Srgrimes return 0; 1021539Srgrimes cygwin_set_impersonation_token(hToken); 1031539Srgrimes return ok; 1041539Srgrimes } 10513771Smpp#endif 1061539Srgrimes#ifdef USE_PAM 1071539Srgrimes if (options.use_pam) 1081539Srgrimes return (sshpam_auth_passwd(authctxt, password) && ok); 109146244Sume#endif 110146244Sume#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) 111146244Sume if (!expire_checked) { 112146244Sume expire_checked = 1; 113146244Sume if (auth_shadow_pwexpired(authctxt)) 114146244Sume authctxt->force_pwchange = 1; 115146244Sume } 116146244Sume#endif 117146244Sume result = sys_auth_passwd(authctxt, password); 1181539Srgrimes if (authctxt->force_pwchange) 11983047Sobrien disable_forwarding(); 1201539Srgrimes return (result && ok); 1211539Srgrimes} 1221539Srgrimes 123146244Sume#ifdef BSD_AUTH 124146244Sumestatic void 125146244Sumewarn_expiry(Authctxt *authctxt, auth_session_t *as) 126146244Sume{ 127146244Sume char buf[256]; 128146244Sume quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime; 129146244Sume 1301539Srgrimes pwwarntime = acwarntime = TWO_WEEKS; 1311539Srgrimes 13283047Sobrien pwtimeleft = auth_check_change(as); 1331539Srgrimes actimeleft = auth_check_expire(as); 1341539Srgrimes#ifdef HAVE_LOGIN_CAP 1351539Srgrimes if (authctxt->valid) { 1361539Srgrimes pwwarntime = login_getcaptime(lc, "password-warn", TWO_WEEKS, 1371539Srgrimes TWO_WEEKS); 1381539Srgrimes acwarntime = login_getcaptime(lc, "expire-warn", TWO_WEEKS, 13983047Sobrien TWO_WEEKS); 1401539Srgrimes } 1411539Srgrimes#endif 1421539Srgrimes if (pwtimeleft != 0 && pwtimeleft < pwwarntime) { 1431539Srgrimes daysleft = pwtimeleft / DAY + 1; 1441539Srgrimes snprintf(buf, sizeof(buf), 145146244Sume "Your password will expire in %lld day%s.\n", 146146244Sume daysleft, daysleft == 1 ? "" : "s"); 147146244Sume buffer_append(&loginmsg, buf, strlen(buf)); 148146244Sume } 149146244Sume if (actimeleft != 0 && actimeleft < acwarntime) { 150146244Sume daysleft = actimeleft / DAY + 1; 151146244Sume snprintf(buf, sizeof(buf), 152146244Sume "Your account will expire in %lld day%s.\n", 153146244Sume daysleft, daysleft == 1 ? "" : "s"); 154146244Sume buffer_append(&loginmsg, buf, strlen(buf)); 155146244Sume } 15655163Sshin} 15755163Sshin 15855163Sshinint 15955163Sshinsys_auth_passwd(Authctxt *authctxt, const char *password) 16055163Sshin{ 161146244Sume struct passwd *pw = authctxt->pw; 162146244Sume auth_session_t *as; 163146244Sume static int expire_checked = 0; 164146244Sume 165146244Sume as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh", 166146244Sume (char *)password); 167146244Sume if (auth_getstate(as) & AUTH_PWEXPIRED) { 16855163Sshin auth_close(as); 16955163Sshin disable_forwarding(); 17055163Sshin authctxt->force_pwchange = 1; 17155163Sshin return (1); 17255163Sshin } else { 1731539Srgrimes if (!expire_checked) { 1741539Srgrimes expire_checked = 1; 175126243Sgreen warn_expiry(authctxt, as); 1761539Srgrimes } 1771539Srgrimes return (auth_close(as)); 17810132Speter } 17910132Speter} 1801539Srgrimes#elif !defined(CUSTOM_SYS_AUTH_PASSWD) 18113771Smppint 1821539Srgrimessys_auth_passwd(Authctxt *authctxt, const char *password) 1831539Srgrimes{ 1841539Srgrimes struct passwd *pw = authctxt->pw; 1851539Srgrimes char *encrypted_password; 18655163Sshin 18755163Sshin /* Just use the supplied fake password if authctxt is invalid */ 18855163Sshin char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; 189121430Sume 190121430Sume /* Check for users with no password. */ 19155163Sshin if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) 192121430Sume return (1); 19355163Sshin 19455163Sshin /* Encrypt the candidate password using the proper salt. */ 19555163Sshin encrypted_password = xcrypt(password, 19655163Sshin (pw_password[0] && pw_password[1]) ? pw_password : "xx"); 19755163Sshin 198121430Sume /* 199121430Sume * Authentication is accepted if the encrypted passwords 20055163Sshin * are identical. 201121430Sume */ 20255163Sshin return (strcmp(encrypted_password, pw_password) == 0); 20355163Sshin} 20455163Sshin#endif 20555163Sshin