2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
Password and authentication handling
2009-02-13 14:02:49 +11:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2001 - 2009
2004-05-13 23:16:33 +00:00
Copyright ( C ) Gerald Carter 2003
2005-01-09 12:55:25 +00:00
Copyright ( C ) Stefan Metzmacher 2005
2003-08-13 01:53:07 +00: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-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 01:53:07 +00:00
( at your option ) 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
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 01:53:07 +00:00
*/
# include "includes.h"
2004-11-02 00:24:21 +00:00
# include "system/time.h"
2011-02-10 14:12:51 +11:00
# include <ldb.h>
2010-04-15 11:58:05 +10:00
# include "libcli/ldap/ldap_ndr.h"
# include "libcli/security/security.h"
2006-04-27 19:50:13 +00:00
# include "auth/auth.h"
2009-03-17 14:03:02 +11:00
# include "../libcli/auth/ntlm_check.h"
2008-05-05 15:23:57 +10:00
# include "auth/ntlm/auth_proto.h"
2006-04-27 19:50:13 +00:00
# include "auth/auth_sam.h"
2006-03-14 15:03:25 +00:00
# include "dsdb/samdb/samdb.h"
2010-02-16 15:40:44 +11:00
# include "dsdb/common/util.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2010-09-12 10:06:39 +10:00
# include "librpc/gen_ndr/ndr_irpc_c.h"
# include "lib/messaging/irpc.h"
2003-08-13 01:53:07 +00:00
2011-03-19 00:44:28 +01:00
NTSTATUS auth_sam_init ( void ) ;
2006-04-27 19:50:13 +00:00
extern const char * user_attrs [ ] ;
extern const char * domain_ref_attrs [ ] ;
2003-08-13 01:53:07 +00:00
/****************************************************************************
2004-10-25 04:25:29 +00:00
Look for the specified user in the sam , return ldb result structures
2003-08-13 01:53:07 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-05 13:41:32 +00:00
static NTSTATUS authsam_search_account ( TALLOC_CTX * mem_ctx , struct ldb_context * sam_ctx ,
2005-01-09 12:55:25 +00:00
const char * account_name ,
2009-05-26 12:31:39 +10:00
struct ldb_dn * domain_dn ,
2009-06-04 14:07:35 +10:00
struct ldb_message * * ret_msg )
2003-08-13 01:53:07 +00:00
{
2005-01-09 12:55:25 +00:00
int ret ;
2004-05-14 01:15:16 +00:00
/* pull the user attributes */
2010-02-16 15:40:44 +11:00
ret = dsdb_search_one ( sam_ctx , mem_ctx , ret_msg , domain_dn , LDB_SCOPE_SUBTREE ,
user_attrs ,
DSDB_SEARCH_SHOW_EXTENDED_DN ,
" (&(sAMAccountName=%s)(objectclass=user)) " ,
ldb_binary_encode_string ( mem_ctx , account_name ) ) ;
2009-06-04 14:07:35 +10:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
2009-05-26 12:31:39 +10:00
DEBUG ( 3 , ( " sam_search_user: Couldn't find user [%s] in samdb, under %s \n " ,
account_name , ldb_dn_get_linearized ( domain_dn ) ) ) ;
2009-06-04 14:07:35 +10:00
return NT_STATUS_NO_SUCH_USER ;
2003-08-13 01:53:07 +00:00
}
2009-06-04 14:07:35 +10:00
if ( ret ! = LDB_SUCCESS ) {
2004-05-14 01:15:16 +00:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-10-25 04:25:29 +00:00
return NT_STATUS_OK ;
}
2006-04-27 19:50:13 +00:00
/****************************************************************************
Do a specific test for an smb password being correct , given a smb_password and
the lanman and NT responses .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-05-07 08:14:06 +02:00
static NTSTATUS authsam_password_ok ( struct auth4_context * auth_context ,
2006-04-27 19:50:13 +00:00
TALLOC_CTX * mem_ctx ,
uint16_t acct_flags ,
const struct samr_Password * lm_pwd ,
const struct samr_Password * nt_pwd ,
const struct auth_usersupplied_info * user_info ,
DATA_BLOB * user_sess_key ,
DATA_BLOB * lm_sess_key )
{
NTSTATUS status ;
switch ( user_info - > password_state ) {
case AUTH_PASSWORD_PLAIN :
{
const struct auth_usersupplied_info * user_info_temp ;
status = encrypt_user_info ( mem_ctx , auth_context ,
AUTH_PASSWORD_HASH ,
user_info , & user_info_temp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Failed to convert plaintext password to password HASH: %s \n " , nt_errstr ( status ) ) ) ;
return status ;
}
user_info = user_info_temp ;
/*fall through*/
}
case AUTH_PASSWORD_HASH :
* lm_sess_key = data_blob ( NULL , 0 ) ;
* user_sess_key = data_blob ( NULL , 0 ) ;
status = hash_password_check ( mem_ctx ,
2010-07-16 14:32:42 +10:00
lpcfg_lanman_auth ( auth_context - > lp_ctx ) ,
2006-04-27 19:50:13 +00:00
user_info - > password . hash . lanman ,
user_info - > password . hash . nt ,
user_info - > mapped . account_name ,
lm_pwd , nt_pwd ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
break ;
case AUTH_PASSWORD_RESPONSE :
2007-12-02 17:56:09 +01:00
status = ntlm_password_check ( mem_ctx ,
2010-07-16 14:32:42 +10:00
lpcfg_lanman_auth ( auth_context - > lp_ctx ) ,
lpcfg_ntlm_auth ( auth_context - > lp_ctx ) ,
2007-12-02 17:56:09 +01:00
user_info - > logon_parameters ,
2006-04-27 19:50:13 +00:00
& auth_context - > challenge . data ,
& user_info - > password . response . lanman ,
& user_info - > password . response . nt ,
user_info - > mapped . account_name ,
user_info - > client . account_name ,
user_info - > client . domain_name ,
lm_pwd , nt_pwd ,
user_sess_key , lm_sess_key ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
break ;
}
if ( user_sess_key & & user_sess_key - > data ) {
talloc_steal ( auth_context , user_sess_key - > data ) ;
}
if ( lm_sess_key & & lm_sess_key - > data ) {
talloc_steal ( auth_context , lm_sess_key - > data ) ;
}
return NT_STATUS_OK ;
}
2010-09-12 10:06:39 +10:00
/*
send a message to the drepl server telling it to initiate a
REPL_SECRET getncchanges extended op to fetch the users secrets
*/
2011-05-07 08:14:06 +02:00
static void auth_sam_trigger_repl_secret ( TALLOC_CTX * mem_ctx , struct auth4_context * auth_context ,
2010-09-12 10:06:39 +10:00
struct ldb_dn * user_dn )
{
struct dcerpc_binding_handle * irpc_handle ;
struct drepl_trigger_repl_secret r ;
struct tevent_req * req ;
irpc_handle = irpc_binding_handle_by_name ( mem_ctx , auth_context - > msg_ctx ,
" dreplsrv " ,
& ndr_table_irpc ) ;
if ( irpc_handle = = NULL ) {
DEBUG ( 1 , ( __location__ " : Unable to get binding handle for dreplsrv \n " ) ) ;
return ;
}
r . in . user_dn = ldb_dn_get_linearized ( user_dn ) ;
req = dcerpc_drepl_trigger_repl_secret_r_send ( mem_ctx ,
auth_context - > event_ctx ,
irpc_handle ,
& r ) ;
/* we aren't interested in a reply */
talloc_free ( req ) ;
talloc_free ( irpc_handle ) ;
}
2006-04-27 19:50:13 +00:00
2011-05-07 08:14:06 +02:00
static NTSTATUS authsam_authenticate ( struct auth4_context * auth_context ,
2005-06-05 13:41:32 +00:00
TALLOC_CTX * mem_ctx , struct ldb_context * sam_ctx ,
2009-05-26 12:31:39 +10:00
struct ldb_dn * domain_dn ,
2009-06-04 14:07:35 +10:00
struct ldb_message * msg ,
2005-01-09 12:55:25 +00:00
const struct auth_usersupplied_info * user_info ,
DATA_BLOB * user_sess_key , DATA_BLOB * lm_sess_key )
2004-10-25 04:25:29 +00:00
{
struct samr_Password * lm_pwd , * nt_pwd ;
NTSTATUS nt_status ;
2008-02-28 08:50:00 +11:00
2010-04-13 12:00:06 +10:00
uint16_t acct_flags = samdb_result_acct_flags ( auth_context - > sam_ctx , mem_ctx , msg , domain_dn ) ;
2004-05-13 15:34:56 +00:00
2004-05-02 08:45:00 +00:00
/* Quit if the account was locked out. */
2004-05-13 15:34:56 +00:00
if ( acct_flags & ACB_AUTOLOCK ) {
DEBUG ( 3 , ( " check_sam_security: Account for user %s was locked out. \n " ,
2005-07-22 04:10:07 +00:00
user_info - > mapped . account_name ) ) ;
2004-05-02 08:45:00 +00:00
return NT_STATUS_ACCOUNT_LOCKED_OUT ;
}
2005-10-28 11:20:48 +00:00
/* You can only do an interactive login to normal accounts */
if ( user_info - > flags & USER_INFO_INTERACTIVE_LOGON ) {
if ( ! ( acct_flags & ACB_NORMAL ) ) {
return NT_STATUS_NO_SUCH_USER ;
}
}
2009-06-04 14:07:35 +10:00
nt_status = samdb_result_passwords ( mem_ctx , auth_context - > lp_ctx , msg , & lm_pwd , & nt_pwd ) ;
2005-01-09 12:55:25 +00:00
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-05-13 15:34:56 +00:00
2010-09-12 10:06:39 +10:00
if ( lm_pwd = = NULL & & nt_pwd = = NULL ) {
bool am_rodc ;
if ( samdb_rodc ( auth_context - > sam_ctx , & am_rodc ) = = LDB_SUCCESS & & am_rodc ) {
/* we don't have passwords for this
* account . We are an RODC , and this account
* may be one for which we either are denied
* REPL_SECRET replication or we haven ' t yet
* done the replication . We return
* NT_STATUS_NOT_IMPLEMENTED which tells the
* auth code to try the next authentication
* mechanism . We also send a message to our
* drepl server to tell it to try and
* replicate the secrets for this account .
*/
auth_sam_trigger_repl_secret ( mem_ctx , auth_context , msg - > dn ) ;
return NT_STATUS_NOT_IMPLEMENTED ;
}
}
2005-01-09 12:55:25 +00:00
nt_status = authsam_password_ok ( auth_context , mem_ctx ,
acct_flags , lm_pwd , nt_pwd ,
user_info , user_sess_key , lm_sess_key ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2003-08-13 01:53:07 +00:00
2010-04-13 12:00:06 +10:00
nt_status = authsam_account_ok ( mem_ctx , auth_context - > sam_ctx ,
2005-10-28 08:54:37 +00:00
user_info - > logon_parameters ,
2009-05-26 12:31:39 +10:00
domain_dn ,
2009-06-04 14:07:35 +10:00
msg ,
2005-11-06 14:16:34 +00:00
user_info - > workstation_name ,
2008-12-04 15:09:21 +01:00
user_info - > mapped . account_name ,
2009-06-18 11:08:46 +10:00
false , false ) ;
2003-08-13 01:53:07 +00:00
2004-10-25 04:25:29 +00:00
return nt_status ;
}
2005-11-05 21:26:28 +00:00
2004-10-25 04:25:29 +00:00
2005-01-09 12:55:25 +00:00
static NTSTATUS authsam_check_password_internals ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const struct auth_usersupplied_info * user_info ,
2011-02-08 16:53:13 +11:00
struct auth_user_info_dc * * user_info_dc )
2004-10-25 04:25:29 +00:00
{
2005-01-09 12:55:25 +00:00
NTSTATUS nt_status ;
2005-07-22 04:10:07 +00:00
const char * account_name = user_info - > mapped . account_name ;
2009-06-04 14:07:35 +10:00
struct ldb_message * msg ;
2009-05-26 12:31:39 +10:00
struct ldb_dn * domain_dn ;
2004-10-25 04:25:29 +00:00
DATA_BLOB user_sess_key , lm_sess_key ;
2006-01-31 03:15:16 +00:00
TALLOC_CTX * tmp_ctx ;
2004-10-25 04:25:29 +00:00
2010-04-13 12:00:06 +10:00
if ( ctx - > auth_ctx - > sam_ctx = = NULL ) {
DEBUG ( 0 , ( " No SAM available, cannot log in users \n " ) ) ;
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
2005-01-09 12:55:25 +00:00
if ( ! account_name | | ! * account_name ) {
/* 'not for me' */
return NT_STATUS_NOT_IMPLEMENTED ;
2004-12-23 03:00:55 +00:00
}
2006-01-31 03:15:16 +00:00
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( ! tmp_ctx ) {
return NT_STATUS_NO_MEMORY ;
}
2010-04-13 12:00:06 +10:00
domain_dn = ldb_get_default_basedn ( ctx - > auth_ctx - > sam_ctx ) ;
2009-05-26 12:31:39 +10:00
if ( domain_dn = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_SUCH_DOMAIN ;
}
2010-04-13 12:00:06 +10:00
nt_status = authsam_search_account ( tmp_ctx , ctx - > auth_ctx - > sam_ctx , account_name , domain_dn , & msg ) ;
2006-01-31 03:15:16 +00:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( tmp_ctx ) ;
return nt_status ;
}
2004-10-25 04:25:29 +00:00
2010-04-13 12:00:06 +10:00
nt_status = authsam_authenticate ( ctx - > auth_ctx , tmp_ctx , ctx - > auth_ctx - > sam_ctx , domain_dn , msg , user_info ,
2005-01-09 12:55:25 +00:00
& user_sess_key , & lm_sess_key ) ;
2006-01-31 03:15:16 +00:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( tmp_ctx ) ;
return nt_status ;
}
2004-10-25 04:25:29 +00:00
2011-02-08 16:53:13 +11:00
nt_status = authsam_make_user_info_dc ( tmp_ctx , ctx - > auth_ctx - > sam_ctx , lpcfg_netbios_name ( ctx - > auth_ctx - > lp_ctx ) ,
2010-07-16 14:32:42 +10:00
lpcfg_sam_name ( ctx - > auth_ctx - > lp_ctx ) ,
2009-05-26 12:31:39 +10:00
domain_dn ,
2009-06-04 14:07:35 +10:00
msg ,
2005-01-09 12:55:25 +00:00
user_sess_key , lm_sess_key ,
2011-02-08 16:53:13 +11:00
user_info_dc ) ;
2006-01-31 03:15:16 +00:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( tmp_ctx ) ;
return nt_status ;
}
2004-10-25 04:25:29 +00:00
2011-02-08 16:53:13 +11:00
talloc_steal ( mem_ctx , * user_info_dc ) ;
2006-01-31 03:15:16 +00:00
talloc_free ( tmp_ctx ) ;
2005-01-24 02:19:57 +00:00
2004-10-25 04:25:29 +00:00
return NT_STATUS_OK ;
}
2006-07-27 11:24:18 +00:00
static NTSTATUS authsam_ignoredomain_want_check ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const struct auth_usersupplied_info * user_info )
{
if ( ! user_info - > mapped . account_name | | ! * user_info - > mapped . account_name ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
return NT_STATUS_OK ;
}
2003-08-13 01:53:07 +00:00
/****************************************************************************
Check SAM security ( above ) but with a few extra checks .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-27 11:24:18 +00:00
static NTSTATUS authsam_want_check ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const struct auth_usersupplied_info * user_info )
2003-08-13 01:53:07 +00:00
{
2007-10-01 18:52:55 +00:00
bool is_local_name , is_my_domain ;
2003-08-13 01:53:07 +00:00
2006-07-27 11:24:18 +00:00
if ( ! user_info - > mapped . account_name | | ! * user_info - > mapped . account_name ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
2010-07-16 14:32:42 +10:00
is_local_name = lpcfg_is_myname ( ctx - > auth_ctx - > lp_ctx ,
2007-10-01 18:52:55 +00:00
user_info - > mapped . domain_name ) ;
2010-07-16 14:32:42 +10:00
is_my_domain = lpcfg_is_mydomain ( ctx - > auth_ctx - > lp_ctx ,
2007-10-01 18:52:55 +00:00
user_info - > mapped . domain_name ) ;
2004-10-25 04:25:29 +00:00
/* check whether or not we service this domain/workgroup name */
2010-07-16 14:32:42 +10:00
switch ( lpcfg_server_role ( ctx - > auth_ctx - > lp_ctx ) ) {
2004-10-25 04:25:29 +00:00
case ROLE_STANDALONE :
2006-07-27 11:24:18 +00:00
return NT_STATUS_OK ;
2004-10-25 04:25:29 +00:00
case ROLE_DOMAIN_MEMBER :
2005-01-09 12:55:25 +00:00
if ( ! is_local_name ) {
2006-07-27 11:24:18 +00:00
DEBUG ( 6 , ( " authsam_check_password: %s is not one of my local names (DOMAIN_MEMBER) \n " ,
user_info - > mapped . domain_name ) ) ;
2004-10-25 04:25:29 +00:00
return NT_STATUS_NOT_IMPLEMENTED ;
}
2006-07-27 11:24:18 +00:00
return NT_STATUS_OK ;
2006-12-13 11:19:51 +00:00
case ROLE_DOMAIN_CONTROLLER :
2005-01-09 12:55:25 +00:00
if ( ! is_local_name & & ! is_my_domain ) {
DEBUG ( 6 , ( " authsam_check_password: %s is not one of my local names or domain name (DC) \n " ,
2005-07-22 04:10:07 +00:00
user_info - > mapped . domain_name ) ) ;
2004-10-25 04:25:29 +00:00
return NT_STATUS_NOT_IMPLEMENTED ;
}
2006-07-27 11:24:18 +00:00
return NT_STATUS_OK ;
}
2010-07-16 14:32:42 +10:00
DEBUG ( 6 , ( " authsam_check_password: lpcfg_server_role() has an undefined value \n " ) ) ;
2006-07-27 11:24:18 +00:00
return NT_STATUS_NOT_IMPLEMENTED ;
}
2009-02-13 14:02:49 +11:00
2010-12-22 17:17:07 +11:00
/* Wrapper for the auth subsystem pointer */
2011-02-08 16:53:13 +11:00
static NTSTATUS authsam_get_user_info_dc_principal_wrapper ( TALLOC_CTX * mem_ctx ,
2011-05-07 08:14:06 +02:00
struct auth4_context * auth_context ,
2011-01-15 16:54:23 +01:00
const char * principal ,
struct ldb_dn * user_dn ,
2011-02-08 16:53:13 +11:00
struct auth_user_info_dc * * user_info_dc )
2009-02-13 14:02:49 +11:00
{
2011-02-08 16:53:13 +11:00
return authsam_get_user_info_dc_principal ( mem_ctx , auth_context - > lp_ctx , auth_context - > sam_ctx ,
principal , user_dn , user_info_dc ) ;
2009-02-13 14:02:49 +11:00
}
2005-01-09 12:55:25 +00:00
static const struct auth_operations sam_ignoredomain_ops = {
2009-02-13 14:02:49 +11:00
. name = " sam_ignoredomain " ,
. get_challenge = auth_get_challenge_not_implemented ,
. want_check = authsam_ignoredomain_want_check ,
2009-05-26 12:31:39 +10:00
. check_password = authsam_check_password_internals ,
2011-02-08 16:53:13 +11:00
. get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper
2005-01-09 12:55:25 +00:00
} ;
2003-08-13 01:53:07 +00:00
2005-01-09 12:55:25 +00:00
static const struct auth_operations sam_ops = {
2009-02-13 14:02:49 +11:00
. name = " sam " ,
. get_challenge = auth_get_challenge_not_implemented ,
. want_check = authsam_want_check ,
2009-05-26 12:31:39 +10:00
. check_password = authsam_check_password_internals ,
2011-02-08 16:53:13 +11:00
. get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper
2005-01-09 12:55:25 +00:00
} ;
2004-02-03 11:10:56 +00:00
2011-05-07 08:14:06 +02:00
_PUBLIC_ NTSTATUS auth4_sam_init ( void )
2004-02-03 11:10:56 +00:00
{
NTSTATUS ret ;
2005-01-09 12:55:25 +00:00
ret = auth_register ( & sam_ops ) ;
2004-02-03 11:10:56 +00:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2005-01-09 12:55:25 +00:00
DEBUG ( 0 , ( " Failed to register 'sam' auth backend! \n " ) ) ;
2004-02-03 11:10:56 +00:00
return ret ;
}
2005-01-09 12:55:25 +00:00
ret = auth_register ( & sam_ignoredomain_ops ) ;
2004-02-03 11:10:56 +00:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2005-01-09 12:55:25 +00:00
DEBUG ( 0 , ( " Failed to register 'sam_ignoredomain' auth backend! \n " ) ) ;
2004-02-03 11:10:56 +00:00
return ret ;
}
return ret ;
}