2001-04-25 00:00:12 +04:00
/* Unix NT password database implementation, version 0.7.5.
*
* 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 the Free
2007-07-09 23:25:36 +04:00
* Software Foundation ; either version 3 of the License , or ( at your option )
2001-04-25 00:00:12 +04:00
* any later version .
*
* 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 .
*
* You should have received a copy of the GNU General Public License along with
2007-07-10 09:23:25 +04:00
* this program ; if not , see < http : //www.gnu.org/licenses/>.
2001-04-25 00:00:12 +04:00
*/
/* indicate the following groups are defined */
# define PAM_SM_AUTH
# include "includes.h"
# include "debug.h"
# ifndef LINUX
/* This is only used in the Sun implementation. */
2007-05-24 00:31:28 +04:00
# if defined(HAVE_SECURITY_PAM_APPL_H)
2001-04-25 00:00:12 +04:00
# include <security/pam_appl.h>
2007-05-24 00:31:28 +04:00
# elif defined(HAVE_PAM_PAM_APPL_H)
# include <pam/pam_appl.h>
# endif
2001-04-25 00:00:12 +04:00
# endif /* LINUX */
2007-05-24 00:31:28 +04:00
# if defined(HAVE_SECURITY_PAM_MODULES_H)
2001-04-25 00:00:12 +04:00
# include <security/pam_modules.h>
2007-05-24 00:31:28 +04:00
# elif defined(HAVE_PAM_PAM_MODULES_H)
# include <pam/pam_modules.h>
# endif
2001-04-25 00:00:12 +04:00
# include "general.h"
# include "support.h"
# define AUTH_RETURN \
do { \
2003-04-08 08:42:44 +04:00
/* Restore application signal handler */ \
CatchSignal ( SIGPIPE , SIGNAL_CAST oldsig_handler ) ; \
2001-04-25 00:00:12 +04:00
if ( ret_data ) { \
* ret_data = retval ; \
pam_set_data ( pamh , " smb_setcred_return " \
, ( void * ) ret_data , NULL ) ; \
} \
return retval ; \
} while ( 0 )
static int _smb_add_user ( pam_handle_t * pamh , unsigned int ctrl ,
2007-10-19 04:40:25 +04:00
const char * name , struct samu * sampass , bool exist ) ;
2001-04-25 00:00:12 +04:00
2002-07-15 14:35:28 +04:00
2001-04-25 00:00:12 +04:00
/*
* pam_sm_authenticate ( ) authenticates users against the samba password file .
*
* First , obtain the password from the user . Then use a
* routine in ' support . c ' to authenticate the user .
*/
# define _SMB_AUTHTOK "-SMB-PASS"
int pam_sm_authenticate ( pam_handle_t * pamh , int flags ,
int argc , const char * * argv )
{
2006-06-15 05:54:09 +04:00
unsigned int ctrl ;
int retval , * ret_data = NULL ;
struct samu * sampass = NULL ;
const char * name ;
void ( * oldsig_handler ) ( int ) = NULL ;
2007-10-19 04:40:25 +04:00
bool found ;
2006-06-15 05:54:09 +04:00
/* Points to memory managed by the PAM library. Do not free. */
char * p = NULL ;
/* Samba initialization. */
load_case_tables ( ) ;
2008-03-06 18:41:42 +03:00
lp_set_in_client ( True ) ;
2006-06-15 05:54:09 +04:00
2009-05-26 17:40:21 +04:00
ctrl = set_ctrl ( pamh , flags , argc , argv ) ;
2006-06-15 05:54:09 +04:00
/* Get a few bytes so we can pass our return value to
pam_sm_setcred ( ) . */
ret_data = SMB_MALLOC_P ( int ) ;
/* we need to do this before we call AUTH_RETURN */
/* Getting into places that might use LDAP -- protect the app
from a SIGPIPE it ' s not expecting */
oldsig_handler = CatchSignal ( SIGPIPE , SIGNAL_CAST SIG_IGN ) ;
/* get the username */
retval = pam_get_user ( pamh , & name , " Username: " ) ;
if ( retval ! = PAM_SUCCESS ) {
if ( on ( SMB_DEBUG , ctrl ) ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_DEBUG , " auth: could not identify user " ) ;
2006-06-15 05:54:09 +04:00
}
AUTH_RETURN ;
}
if ( on ( SMB_DEBUG , ctrl ) ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_DEBUG , " username [%s] obtained " , name ) ;
2006-06-15 05:54:09 +04:00
}
2001-04-25 00:00:12 +04:00
2007-12-13 04:26:49 +03:00
if ( geteuid ( ) ! = 0 ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_DEBUG , " Cannot access samba password database, not running as root. " ) ;
2007-12-13 04:26:49 +03:00
retval = PAM_AUTHINFO_UNAVAIL ;
AUTH_RETURN ;
}
2007-05-25 00:26:07 +04:00
if ( ! initialize_password_db ( True , NULL ) ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_ALERT , " Cannot access samba password database " ) ;
2006-06-15 05:54:09 +04:00
retval = PAM_AUTHINFO_UNAVAIL ;
AUTH_RETURN ;
}
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
sampass = samu_new ( NULL ) ;
if ( ! sampass ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_ALERT , " Cannot talloc a samu struct " ) ;
2006-06-15 05:54:09 +04:00
retval = nt_status_to_pam ( NT_STATUS_NO_MEMORY ) ;
AUTH_RETURN ;
}
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
found = pdb_getsampwnam ( sampass , name ) ;
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
if ( on ( SMB_MIGRATE , ctrl ) ) {
retval = _smb_add_user ( pamh , ctrl , name , sampass , found ) ;
TALLOC_FREE ( sampass ) ;
AUTH_RETURN ;
}
if ( ! found ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_ALERT , " Failed to find entry for user %s. " , name ) ;
2006-06-15 05:54:09 +04:00
retval = PAM_USER_UNKNOWN ;
TALLOC_FREE ( sampass ) ;
sampass = NULL ;
AUTH_RETURN ;
}
2007-12-13 04:26:49 +03:00
2006-06-15 05:54:09 +04:00
/* if this user does not have a password... */
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
if ( _smb_blankpasswd ( ctrl , sampass ) ) {
TALLOC_FREE ( sampass ) ;
retval = PAM_SUCCESS ;
AUTH_RETURN ;
}
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
/* get this user's authentication token */
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
retval = _smb_read_password ( pamh , ctrl , NULL , " Password: " , NULL , _SMB_AUTHTOK , & p ) ;
if ( retval ! = PAM_SUCCESS ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_CRIT , " auth: no password provided for [%s] " , name ) ;
2006-06-15 05:54:09 +04:00
TALLOC_FREE ( sampass ) ;
AUTH_RETURN ;
}
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
/* verify the password of this user */
2001-04-25 00:00:12 +04:00
2006-06-15 05:54:09 +04:00
retval = _smb_verify_password ( pamh , sampass , p , ctrl ) ;
TALLOC_FREE ( sampass ) ;
p = NULL ;
AUTH_RETURN ;
2001-04-25 00:00:12 +04:00
}
/*
* This function is for setting samba credentials . If anyone comes up
* with any credentials they think should be set , let me know .
*/
int pam_sm_setcred ( pam_handle_t * pamh , int flags ,
int argc , const char * * argv )
{
2007-11-22 04:42:52 +03:00
int retval , * pretval = NULL ;
2001-04-25 00:00:12 +04:00
2007-11-22 04:42:52 +03:00
retval = PAM_SUCCESS ;
2001-04-25 00:00:12 +04:00
2009-05-22 19:56:37 +04:00
_pam_get_data ( pamh , " smb_setcred_return " , & pretval ) ;
2007-11-22 04:42:52 +03:00
if ( pretval ) {
retval = * pretval ;
SAFE_FREE ( pretval ) ;
}
pam_set_data ( pamh , " smb_setcred_return " , NULL , NULL ) ;
2001-04-25 00:00:12 +04:00
2007-11-22 04:42:52 +03:00
return retval ;
2001-04-25 00:00:12 +04:00
}
/* Helper function for adding a user to the db. */
static int _smb_add_user ( pam_handle_t * pamh , unsigned int ctrl ,
2007-10-19 04:40:25 +04:00
const char * name , struct samu * sampass , bool exist )
2001-04-25 00:00:12 +04:00
{
2007-11-22 04:42:52 +03:00
char * err_str = NULL ;
char * msg_str = NULL ;
const char * pass = NULL ;
int retval ;
/* Get the authtok; if we don't have one, silently fail. */
2009-05-22 19:56:37 +04:00
retval = _pam_get_item ( pamh , PAM_AUTHTOK , & pass ) ;
2007-11-22 04:42:52 +03:00
if ( retval ! = PAM_SUCCESS ) {
2009-05-26 17:40:21 +04:00
_log_err ( pamh , LOG_ALERT
2007-11-22 04:42:52 +03:00
, " pam_get_item returned error to pam_sm_authenticate " ) ;
return PAM_AUTHTOK_RECOVER_ERR ;
} else if ( pass = = NULL ) {
return PAM_AUTHTOK_RECOVER_ERR ;
2001-04-25 00:00:12 +04:00
}
2007-11-22 04:42:52 +03:00
/* Add the user to the db if they aren't already there. */
if ( ! exist ) {
retval = NT_STATUS_IS_OK ( local_password_change ( name , LOCAL_ADD_USER | LOCAL_SET_PASSWORD ,
pass , & err_str , & msg_str ) ) ;
if ( ! retval & & err_str ) {
make_remark ( pamh , ctrl , PAM_ERROR_MSG , err_str ) ;
} else if ( msg_str ) {
make_remark ( pamh , ctrl , PAM_TEXT_INFO , msg_str ) ;
}
pass = NULL ;
SAFE_FREE ( err_str ) ;
SAFE_FREE ( msg_str ) ;
return PAM_IGNORE ;
} else {
/* mimick 'update encrypted' as long as the 'no pw req' flag is not set */
if ( pdb_get_acct_ctrl ( sampass ) & ~ ACB_PWNOTREQ ) {
retval = NT_STATUS_IS_OK ( local_password_change ( name , LOCAL_SET_PASSWORD ,
pass , & err_str , & msg_str ) ) ;
if ( ! retval & & err_str ) {
make_remark ( pamh , ctrl , PAM_ERROR_MSG , err_str ) ;
} else if ( msg_str ) {
make_remark ( pamh , ctrl , PAM_TEXT_INFO , msg_str ) ;
}
}
2001-04-25 00:00:12 +04:00
}
2002-01-13 02:12:13 +03:00
2007-11-22 04:42:52 +03:00
SAFE_FREE ( err_str ) ;
SAFE_FREE ( msg_str ) ;
pass = NULL ;
return PAM_IGNORE ;
2001-04-25 00:00:12 +04:00
}
/* static module data */
# ifdef PAM_STATIC
struct pam_module _pam_smbpass_auth_modstruct = {
2007-11-22 04:42:52 +03:00
" pam_smbpass " ,
pam_sm_authenticate ,
pam_sm_setcred ,
NULL ,
NULL ,
NULL ,
NULL
2001-04-25 00:00:12 +04:00
} ;
# endif