2010-08-21 16:42:24 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-08-10 11:04:53 +04:00
Password checking
Copyright ( C ) Andrew Tridgell 1992 - 1998
2010-08-21 16:42:24 +04:00
1998-08-10 11:04:53 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-08-10 11:04:53 +04:00
( at your option ) any later version .
2010-08-21 16:42:24 +04:00
1998-08-10 11:04:53 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2010-08-21 16:42:24 +04:00
1998-08-10 11:04:53 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-08-10 11:04:53 +04:00
*/
/* this module is for checking a username/password against a system
password database . The SMB encrypted password support is elsewhere */
# include "includes.h"
2011-03-30 12:50:10 +04:00
# include "system/passwd.h"
2011-03-25 04:28:05 +03:00
# include "auth.h"
1998-08-10 11:04:53 +04:00
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_AUTH
2007-12-18 04:02:48 +03:00
# if !defined(WITH_PAM)
static char * ths_salt ;
/* This must be writable. */
2007-12-18 04:13:31 +03:00
static char * get_this_salt ( void )
2007-12-18 04:02:48 +03:00
{
return ths_salt ;
}
/* We may be setting a modified version of the same
* string , so don ' t free before use . */
static const char * set_this_salt ( const char * newsalt )
{
char * orig_salt = ths_salt ;
ths_salt = SMB_STRDUP ( newsalt ) ;
SAFE_FREE ( orig_salt ) ;
return ths_salt ;
}
static char * ths_crypted ;
2007-12-18 04:13:31 +03:00
static const char * get_this_crypted ( void )
2007-12-18 04:02:48 +03:00
{
if ( ! ths_crypted ) {
return " " ;
}
return ths_crypted ;
}
static const char * set_this_crypted ( const char * newcrypted )
{
char * orig_crypted = ths_crypted ;
ths_crypted = SMB_STRDUP ( newcrypted ) ;
SAFE_FREE ( orig_crypted ) ;
return ths_crypted ;
}
2001-09-20 17:15:35 +04:00
# endif
1998-08-10 11:04:53 +04:00
/****************************************************************************
core of password checking routine
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-01-22 01:40:11 +04:00
static NTSTATUS password_check ( const char * user , const char * password , const void * private_data )
1998-08-10 11:04:53 +04:00
{
1999-12-13 16:27:58 +03:00
# ifdef WITH_PAM
2010-08-21 16:52:16 +04:00
const char * rhost = ( const char * ) private_data ;
2014-01-22 01:40:11 +04:00
return smb_pam_passcheck ( user , rhost , password ) ;
2001-09-20 17:15:35 +04:00
# else
2007-10-19 04:40:25 +04:00
bool ret ;
2000-03-22 00:08:07 +03:00
1998-08-10 11:04:53 +04:00
2010-08-21 16:42:24 +04:00
1998-08-10 11:04:53 +04:00
# ifdef ULTRIX_AUTH
2007-12-18 04:02:48 +03:00
ret = ( strcmp ( ( char * ) crypt16 ( password , get_this_salt ( ) ) , get_this_crypted ( ) ) = = 0 ) ;
2001-09-20 17:15:35 +04:00
if ( ret ) {
return NT_STATUS_OK ;
} else {
return NT_STATUS_WRONG_PASSWORD ;
}
2010-08-21 16:42:24 +04:00
1999-12-13 16:27:58 +03:00
# endif /* ULTRIX_AUTH */
2010-08-21 16:42:24 +04:00
1998-08-10 11:04:53 +04:00
# ifdef HAVE_BIGCRYPT
2007-12-18 04:02:48 +03:00
ret = ( strcmp ( bigcrypt ( password , get_this_salt ( ) ) , get_this_crypted ( ) ) = = 0 ) ;
2001-09-20 17:15:35 +04:00
if ( ret ) {
return NT_STATUS_OK ;
} else {
return NT_STATUS_WRONG_PASSWORD ;
}
1999-12-13 16:27:58 +03:00
# endif /* HAVE_BIGCRYPT */
2010-08-21 16:42:24 +04:00
1998-08-10 11:04:53 +04:00
# ifndef HAVE_CRYPT
2000-03-22 00:08:07 +03:00
DEBUG ( 1 , ( " Warning - no crypt available \n " ) ) ;
2001-09-20 17:15:35 +04:00
return NT_STATUS_LOGON_FAILURE ;
1999-12-13 16:27:58 +03:00
# else /* HAVE_CRYPT */
2007-12-18 04:02:48 +03:00
ret = ( strcmp ( ( char * ) crypt ( password , get_this_salt ( ) ) , get_this_crypted ( ) ) = = 0 ) ;
2001-09-20 17:15:35 +04:00
if ( ret ) {
return NT_STATUS_OK ;
} else {
return NT_STATUS_WRONG_PASSWORD ;
}
1999-12-13 16:27:58 +03:00
# endif /* HAVE_CRYPT */
2003-02-10 14:47:21 +03:00
# endif /* WITH_PAM */
1998-08-10 11:04:53 +04:00
}
/****************************************************************************
2001-09-20 17:15:35 +04:00
CHECK if a username / password is OK
1998-08-10 11:04:53 +04:00
the function pointer fn ( ) points to a function to call when a successful
match is found and is used to update the encrypted password file
2001-09-20 17:15:35 +04:00
return NT_STATUS_OK on correct match , appropriate error otherwise
1998-08-10 11:04:53 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-04-22 11:20:24 +04:00
2010-07-29 15:16:09 +04:00
NTSTATUS pass_check ( const struct passwd * pass ,
const char * user ,
2010-08-21 16:57:16 +04:00
const char * rhost ,
2010-07-29 15:16:09 +04:00
const char * password ,
bool run_cracker )
1998-08-10 11:04:53 +04:00
{
2007-11-14 21:37:18 +03:00
char * pass2 = NULL ;
1998-08-10 11:04:53 +04:00
2001-09-20 17:15:35 +04:00
NTSTATUS nt_status ;
1998-08-10 11:04:53 +04:00
2004-10-11 04:32:31 +04:00
# ifdef DEBUG_PASSWORD
2000-03-22 00:08:07 +03:00
DEBUG ( 100 , ( " checking user=[%s] pass=[%s] \n " , user , password ) ) ;
1998-08-10 11:04:53 +04:00
# endif
2000-03-22 00:08:07 +03:00
if ( ! password )
2001-09-20 17:15:35 +04:00
return NT_STATUS_LOGON_FAILURE ;
1998-08-10 11:04:53 +04:00
2010-06-01 15:52:01 +04:00
if ( ( ! * password ) & & ! lp_null_passwords ( ) )
2001-09-20 17:15:35 +04:00
return NT_STATUS_LOGON_FAILURE ;
1998-08-10 11:04:53 +04:00
2001-11-11 13:42:07 +03:00
# if defined(WITH_PAM)
2001-04-22 11:20:24 +04:00
/*
* If we ' re using PAM we want to short - circuit all the
* checks below and dive straight into the PAM code .
*/
2010-06-01 15:52:01 +04:00
DEBUG ( 4 , ( " pass_check: Checking (PAM) password for user %s \n " , user ) ) ;
2001-04-22 11:20:24 +04:00
2002-01-17 11:45:58 +03:00
# else /* Not using PAM */
1998-08-10 11:04:53 +04:00
2010-06-01 15:52:01 +04:00
DEBUG ( 4 , ( " pass_check: Checking password for user %s \n " , user ) ) ;
1998-08-10 11:04:53 +04:00
2002-07-15 14:35:28 +04:00
if ( ! pass ) {
2000-03-22 00:08:07 +03:00
DEBUG ( 3 , ( " Couldn't find user %s \n " , user ) ) ;
2001-09-20 17:15:35 +04:00
return NT_STATUS_NO_SUCH_USER ;
1998-08-10 11:04:53 +04:00
}
2002-07-15 14:35:28 +04:00
/* Copy into global for the convenience of looping code */
/* Also the place to keep the 'password' no matter what
crazy struct it started in . . . */
2007-12-18 04:02:48 +03:00
if ( set_this_crypted ( pass - > pw_passwd ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( set_this_salt ( pass - > pw_passwd ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2002-01-17 11:45:58 +03:00
1999-12-13 16:27:58 +03:00
# ifdef HAVE_GETSPNAM
{
struct spwd * spass ;
/* many shadow systems require you to be root to get
the password , in most cases this should already be
the case when this function is called , except
perhaps for IPC password changing requests */
spass = getspnam ( pass - > pw_name ) ;
2002-10-01 17:10:57 +04:00
if ( spass & & spass - > sp_pwdp ) {
2007-12-18 04:02:48 +03:00
if ( set_this_crypted ( spass - > sp_pwdp ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( set_this_salt ( spass - > sp_pwdp ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2002-10-01 17:10:57 +04:00
}
1999-12-13 16:27:58 +03:00
}
# elif defined(IA_UINFO)
{
/* Need to get password with SVR4.2's ia_ functions
instead of get { sp , pw } ent functions . Required by
UnixWare 2. x , tested on version
2.1 . ( tangent @ cyberport . com ) */
uinfo_t uinfo ;
2000-03-22 00:08:07 +03:00
if ( ia_openinfo ( pass - > pw_name , & uinfo ) ! = - 1 )
1999-12-13 16:27:58 +03:00
ia_get_logpwd ( uinfo , & ( pass - > pw_passwd ) ) ;
}
# endif
2002-01-17 11:45:58 +03:00
# ifdef HAVE_GETPWANAM
{
struct passwd_adjunct * pwret ;
pwret = getpwanam ( s ) ;
2007-12-18 04:02:48 +03:00
if ( pwret & & pwret - > pwa_passwd ) {
if ( set_this_crypted ( pwret - > pwa_passwd ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
2002-01-17 11:45:58 +03:00
}
# endif
1999-12-13 16:27:58 +03:00
# ifdef ULTRIX_AUTH
{
AUTHORIZATION * ap = getauthuid ( pass - > pw_uid ) ;
2001-04-10 23:43:14 +04:00
if ( ap ) {
2007-12-18 04:02:48 +03:00
if ( set_this_crypted ( ap - > a_password ) = = NULL ) {
endauthent ( ) ;
return NT_STATUS_NO_MEMORY ;
}
1999-12-13 16:27:58 +03:00
endauthent ( ) ;
}
}
# endif
2000-03-22 00:08:07 +03:00
2007-12-18 04:02:48 +03:00
if ( ! get_this_crypted ( ) | | ! * get_this_crypted ( ) ) {
2001-04-10 22:10:38 +04:00
if ( ! lp_null_passwords ( ) ) {
2000-03-22 00:08:07 +03:00
DEBUG ( 2 , ( " Disallowing %s with null password \n " ,
2014-01-22 01:40:11 +04:00
user ) ) ;
2001-09-20 17:15:35 +04:00
return NT_STATUS_LOGON_FAILURE ;
1998-08-10 11:04:53 +04:00
}
2001-04-10 22:10:38 +04:00
if ( ! * password ) {
2000-03-22 00:08:07 +03:00
DEBUG ( 3 ,
( " Allowing access to %s with null password \n " ,
2014-01-22 01:40:11 +04:00
user ) ) ;
2001-09-20 17:15:35 +04:00
return NT_STATUS_OK ;
1998-08-10 11:04:53 +04:00
}
}
2001-11-11 13:42:07 +03:00
# endif /* defined(WITH_PAM) */
2001-04-22 11:20:24 +04:00
1998-08-10 11:04:53 +04:00
/* try it as it came to us */
2014-01-22 01:40:11 +04:00
nt_status = password_check ( user , password , ( const void * ) rhost ) ;
2001-09-20 17:15:35 +04:00
if NT_STATUS_IS_OK ( nt_status ) {
return ( nt_status ) ;
} else if ( ! NT_STATUS_EQUAL ( nt_status , NT_STATUS_WRONG_PASSWORD ) ) {
2023-06-30 13:06:01 +03:00
/* No point continuing if its not the password that's to blame (ie PAM disabled). */
2001-09-20 17:15:35 +04:00
return ( nt_status ) ;
}
1998-08-10 11:04:53 +04:00
2001-09-19 09:26:11 +04:00
if ( ! run_cracker ) {
2001-09-20 17:15:35 +04:00
return ( nt_status ) ;
2001-09-19 09:26:11 +04:00
}
1998-08-10 11:04:53 +04:00
/* if the password was given to us with mixed case then we don't
2001-09-20 17:15:35 +04:00
* need to proceed as we know it hasn ' t been case modified by the
* client */
2001-04-10 23:43:14 +04:00
if ( strhasupper ( password ) & & strhaslower ( password ) ) {
2001-09-20 17:15:35 +04:00
return nt_status ;
1998-08-10 11:04:53 +04:00
}
/* make a copy of it */
2007-11-14 21:37:18 +03:00
pass2 = talloc_strdup ( talloc_tos ( ) , password ) ;
if ( ! pass2 ) {
return NT_STATUS_NO_MEMORY ;
}
2000-03-22 00:08:07 +03:00
2001-04-10 23:43:14 +04:00
/* try all lowercase if it's currently all uppercase */
2002-07-15 14:35:28 +04:00
if ( strhasupper ( pass2 ) ) {
2012-08-09 04:01:00 +04:00
if ( ! strlower_m ( pass2 ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2014-01-22 01:40:11 +04:00
nt_status = password_check ( user , pass2 , ( const void * ) rhost ) ;
2010-08-21 16:52:16 +04:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
2001-09-20 17:15:35 +04:00
return ( nt_status ) ;
2001-04-10 23:43:14 +04:00
}
1998-08-10 11:04:53 +04:00
}
2001-09-20 17:15:35 +04:00
return NT_STATUS_WRONG_PASSWORD ;
1998-08-10 11:04:53 +04:00
}