2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
Password and authentication handling
2004-05-14 03:16:33 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2001 - 2004
Copyright ( C ) Gerald Carter 2003
2005-01-09 15:55:25 +03:00
Copyright ( C ) Stefan Metzmacher 2005
2003-08-13 05:53:07 +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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-01 13:30:34 +03:00
# include "librpc/gen_ndr/ndr_samr.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2004-11-02 05:57:18 +03:00
# include "auth/auth.h"
2004-11-16 12:00:52 +03:00
# include "lib/ldb/include/ldb.h"
2005-02-10 08:09:35 +03:00
# include "pstring.h"
2003-08-13 05:53:07 +04:00
/****************************************************************************
Do a specific test for an smb password being correct , given a smb_password and
the lanman and NT responses .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_password_ok ( const struct auth_context * auth_context ,
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 )
2003-08-13 05:53:07 +04:00
{
2004-09-26 10:44:08 +04:00
NTSTATUS status ;
2004-05-13 19:34:56 +04:00
if ( acct_flags & ACB_PWNOTREQ ) {
2004-05-02 12:45:00 +04:00
if ( lp_null_passwords ( ) ) {
2004-05-14 05:15:16 +04:00
DEBUG ( 3 , ( " Account for user '%s' has no password and null passwords are allowed. \n " ,
2005-01-09 15:55:25 +03:00
user_info - > account_name ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
} else {
2004-05-14 05:15:16 +04:00
DEBUG ( 3 , ( " Account for user '%s' has no password and null passwords are NOT allowed. \n " ,
2005-01-09 15:55:25 +03:00
user_info - > account_name ) ) ;
2004-05-02 12:45:00 +04:00
return NT_STATUS_LOGON_FAILURE ;
}
2003-08-13 05:53:07 +04:00
}
2005-01-09 15:55:25 +03:00
status = ntlm_password_check ( mem_ctx , & auth_context - > challenge . data ,
& user_info - > lm_resp , & user_info - > nt_resp ,
& user_info - > lm_interactive_password ,
& user_info - > nt_interactive_password ,
user_info - > account_name ,
user_info - > client . account_name ,
user_info - > client . domain_name ,
lm_pwd - > hash , nt_pwd - > hash ,
user_sess_key , lm_sess_key ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
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 ) ;
2004-09-26 10:44:08 +04:00
}
2005-01-09 15:55:25 +03:00
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
2004-05-02 12:45:00 +04:00
2003-08-13 05:53:07 +04:00
/****************************************************************************
Do a specific test for a SAM_ACCOUNT being vaild for this connection
( ie not disabled , expired and the like ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_account_ok ( TALLOC_CTX * mem_ctx ,
uint16_t acct_flags ,
NTTIME acct_expiry ,
NTTIME must_change_time ,
NTTIME last_set_time ,
const char * workstation_list ,
const struct auth_usersupplied_info * user_info )
2003-08-13 05:53:07 +04:00
{
2005-01-09 15:55:25 +03:00
DEBUG ( 4 , ( " authsam_account_ok: Checking SMB password for user %s \n " , user_info - > account_name ) ) ;
2003-08-13 05:53:07 +04:00
/* Quit if the account was disabled. */
2004-05-13 19:34:56 +04:00
if ( acct_flags & ACB_DISABLED ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 1 , ( " authsam_account_ok: Account for user '%s' was disabled. \n " , user_info - > account_name ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_ACCOUNT_DISABLED ;
}
2004-05-02 12:45:00 +04:00
/* Quit if the account was locked out. */
2004-05-13 19:34:56 +04:00
if ( acct_flags & ACB_AUTOLOCK ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 1 , ( " authsam_account_ok: Account for user %s was locked out. \n " , user_info - > account_name ) ) ;
2004-05-02 12:45:00 +04:00
return NT_STATUS_ACCOUNT_LOCKED_OUT ;
}
2003-08-13 05:53:07 +04:00
/* Test account expire time */
2005-01-09 15:55:25 +03:00
if ( ( acct_expiry ) ! = - 1 & & time ( NULL ) > nt_time_to_unix ( acct_expiry ) ) {
DEBUG ( 1 , ( " authsam_account_ok: Account for user '%s' has expired. \n " , user_info - > account_name ) ) ;
DEBUG ( 3 , ( " authsam_account_ok: Account expired at '%s'. \n " ,
nt_time_string ( mem_ctx , acct_expiry ) ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_ACCOUNT_EXPIRED ;
}
2004-05-13 19:34:56 +04:00
if ( ! ( acct_flags & ACB_PWNOEXP ) ) {
2003-08-13 05:53:07 +04:00
/* check for immediate expiry "must change at next logon" */
2005-01-09 15:55:25 +03:00
if ( must_change_time = = 0 & & last_set_time ! = 0 ) {
2004-05-14 05:15:16 +04:00
DEBUG ( 1 , ( " sam_account_ok: Account for user '%s' password must change!. \n " ,
2005-01-09 15:55:25 +03:00
user_info - > account_name ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_PASSWORD_MUST_CHANGE ;
}
/* check for expired password */
2005-01-09 15:55:25 +03:00
if ( ( must_change_time ) ! = 0 & & nt_time_to_unix ( must_change_time ) < time ( NULL ) ) {
2004-05-14 05:15:16 +04:00
DEBUG ( 1 , ( " sam_account_ok: Account for user '%s' password expired!. \n " ,
2005-01-09 15:55:25 +03:00
user_info - > account_name ) ) ;
2004-05-14 05:15:16 +04:00
DEBUG ( 1 , ( " sam_account_ok: Password expired at '%s' unix time. \n " ,
2005-01-09 15:55:25 +03:00
nt_time_string ( mem_ctx , must_change_time ) ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_PASSWORD_EXPIRED ;
}
}
/* Test workstation. Workstation list is comma separated. */
2004-05-14 05:15:16 +04:00
if ( workstation_list & & * workstation_list ) {
2003-08-13 05:53:07 +04:00
BOOL invalid_ws = True ;
const char * s = workstation_list ;
fstring tok ;
while ( next_token ( & s , tok , " , " , sizeof ( tok ) ) ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 10 , ( " sam_account_ok: checking for workstation match '%s' and '%s' \n " ,
tok , user_info - > workstation_name ) ) ;
if ( strequal ( tok , user_info - > workstation_name ) ) {
2003-08-13 05:53:07 +04:00
invalid_ws = False ;
2004-10-25 08:25:29 +04:00
2003-08-13 05:53:07 +04:00
break ;
}
}
2005-01-09 15:55:25 +03:00
if ( invalid_ws ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_WORKSTATION ;
2005-01-09 15:55:25 +03:00
}
2003-08-13 05:53:07 +04:00
}
2004-05-14 05:15:16 +04:00
2004-05-13 19:34:56 +04:00
if ( acct_flags & ACB_DOMTRUST ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 2 , ( " sam_account_ok: Domain trust account %s denied by server \n " , user_info - > account_name ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ;
}
2005-01-09 15:55:25 +03:00
2004-05-13 19:34:56 +04:00
if ( acct_flags & ACB_SVRTRUST ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 2 , ( " sam_account_ok: Server trust account %s denied by server \n " , user_info - > account_name ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ;
}
2005-01-09 15:55:25 +03:00
2004-05-13 19:34:56 +04:00
if ( acct_flags & ACB_WSTRUST ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 4 , ( " sam_account_ok: Wksta trust account %s denied by server \n " , user_info - > account_name ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ;
}
2005-01-09 15:55:25 +03:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
/****************************************************************************
2004-10-25 08:25:29 +04:00
Look for the specified user in the sam , return ldb result structures
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_search_account ( TALLOC_CTX * mem_ctx , void * sam_ctx ,
const char * account_name ,
const char * domain_name ,
struct ldb_message * * * ret_msgs ,
struct ldb_message * * * ret_msgs_domain )
2003-08-13 05:53:07 +04:00
{
2005-05-18 18:19:17 +04:00
struct ldb_message * * msgs_tmp ;
2004-05-13 19:34:56 +04:00
struct ldb_message * * msgs ;
2004-05-14 05:15:16 +04:00
struct ldb_message * * msgs_domain ;
2005-01-09 15:55:25 +03:00
int ret ;
int ret_domain ;
2004-05-14 05:15:16 +04:00
2004-10-25 08:25:29 +04:00
const char * domain_dn = NULL ;
2004-05-14 05:15:16 +04:00
2005-01-09 15:55:25 +03:00
const char * attrs [ ] = { " unicodePwd " , " lmPwdHash " , " ntPwdHash " ,
2004-05-15 11:51:38 +04:00
" userAccountControl " ,
2004-05-14 05:15:16 +04:00
" pwdLastSet " ,
" accountExpires " ,
" objectSid " ,
" userWorkstations " ,
2004-06-07 07:46:32 +04:00
/* required for server_info, not access control: */
2004-06-14 17:20:33 +04:00
" sAMAccountName " ,
2004-06-07 07:46:32 +04:00
" displayName " ,
" scriptPath " ,
" profilePath " ,
" homeDirectory " ,
" homeDrive " ,
" lastLogon " ,
" lastLogoff " ,
" accountExpires " ,
" badPwdCount " ,
" logonCount " ,
2004-10-03 10:40:40 +04:00
" primaryGroupID " ,
2004-05-14 05:15:16 +04:00
NULL ,
} ;
2005-05-18 18:19:17 +04:00
const char * domain_attrs [ ] = { " nETBIOSName " , " nCName " } ;
2004-10-25 08:25:29 +04:00
2005-01-09 15:55:25 +03:00
if ( domain_name ) {
2004-10-25 08:25:29 +04:00
/* find the domain's DN */
2005-03-23 04:30:43 +03:00
ret_domain = gendb_search ( sam_ctx , mem_ctx , NULL , & msgs_domain , domain_attrs ,
2005-05-18 18:19:17 +04:00
" (&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*)) " ,
2005-01-09 15:55:25 +03:00
domain_name , domain_name ) ;
if ( ret_domain = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-10-25 08:25:29 +04:00
if ( ret_domain = = 0 ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 3 , ( " sam_search_user: Couldn't find domain [%s] in samdb. \n " ,
domain_name ) ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_NO_SUCH_USER ;
}
2005-01-09 15:55:25 +03:00
2004-10-25 08:25:29 +04:00
if ( ret_domain > 1 ) {
DEBUG ( 0 , ( " Found %d records matching domain [%s] \n " ,
2005-01-09 15:55:25 +03:00
ret_domain , domain_name ) ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-05-18 18:19:17 +04:00
domain_dn = samdb_result_string ( msgs_domain [ 0 ] , " nCName " , NULL ) ;
2003-08-13 05:53:07 +04:00
}
2005-01-09 15:55:25 +03:00
2004-05-14 05:15:16 +04:00
/* pull the user attributes */
2005-03-23 04:30:43 +03:00
ret = gendb_search ( sam_ctx , mem_ctx , domain_dn , & msgs , attrs ,
2004-05-13 19:34:56 +04:00
" (&(sAMAccountName=%s)(objectclass=user)) " ,
2005-01-09 15:55:25 +03:00
account_name ) ;
if ( ret = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-05-13 19:34:56 +04:00
if ( ret = = 0 ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 3 , ( " sam_search_user: Couldn't find user [%s] in samdb. \n " ,
account_name ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_NO_SUCH_USER ;
}
2004-05-13 19:34:56 +04:00
if ( ret > 1 ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 0 , ( " Found %d records matching user [%s] \n " , ret , account_name ) ) ;
2004-05-14 05:15:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-09 15:55:25 +03:00
if ( ! domain_name ) {
const char * domain_sid ;
2004-10-25 08:25:29 +04:00
domain_sid = samdb_result_sid_prefix ( mem_ctx , msgs [ 0 ] , " objectSid " ) ;
if ( ! domain_sid ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-05-14 05:15:16 +04:00
2004-10-25 08:25:29 +04:00
/* find the domain's DN */
2005-05-18 18:19:17 +04:00
ret = gendb_search ( sam_ctx , mem_ctx , NULL , & msgs_tmp , NULL ,
" (&(objectSid=%s)(objectclass=domain)) " ,
domain_sid ) ;
if ( ret = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( ret = = 0 ) {
DEBUG ( 3 , ( " check_sam_security: Couldn't find domain_sid [%s] in passdb file. \n " ,
domain_sid ) ) ;
return NT_STATUS_NO_SUCH_USER ;
}
if ( ret > 1 ) {
DEBUG ( 0 , ( " Found %d records matching domain_sid [%s] \n " ,
ret , domain_sid ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-03-23 04:30:43 +03:00
ret_domain = gendb_search ( sam_ctx , mem_ctx , NULL , & msgs_domain , domain_attrs ,
2005-05-18 18:19:17 +04:00
" (nCName=%s) " , msgs_tmp [ 0 ] - > dn ) ;
2005-01-09 15:55:25 +03:00
if ( ret_domain = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-10-25 08:25:29 +04:00
if ( ret_domain = = 0 ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 3 , ( " check_sam_security: Couldn't find domain [%s] in passdb file. \n " ,
2005-05-18 18:19:17 +04:00
msgs_tmp [ 0 ] - > dn ) ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_NO_SUCH_USER ;
}
if ( ret_domain > 1 ) {
DEBUG ( 0 , ( " Found %d records matching domain [%s] \n " ,
2005-05-18 18:19:17 +04:00
ret_domain , msgs_tmp [ 0 ] - > dn ) ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-05-18 18:19:17 +04:00
2004-05-14 05:15:16 +04:00
}
2005-01-09 15:55:25 +03:00
2004-10-25 08:25:29 +04:00
* ret_msgs = msgs ;
* ret_msgs_domain = msgs_domain ;
return NT_STATUS_OK ;
}
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_authenticate ( const struct auth_context * auth_context ,
TALLOC_CTX * mem_ctx , void * sam_ctx ,
struct ldb_message * * msgs ,
struct ldb_message * * msgs_domain ,
const struct auth_usersupplied_info * user_info ,
DATA_BLOB * user_sess_key , DATA_BLOB * lm_sess_key )
2004-10-25 08:25:29 +04:00
{
uint16_t acct_flags ;
const char * workstation_list ;
NTTIME acct_expiry ;
NTTIME must_change_time ;
NTTIME last_set_time ;
struct samr_Password * lm_pwd , * nt_pwd ;
NTSTATUS nt_status ;
2005-05-18 18:19:17 +04:00
const char * domain_dn = samdb_result_string ( msgs_domain [ 0 ] , " nCName " , " " ) ;
2004-05-14 05:15:16 +04:00
2004-05-13 19:34:56 +04:00
acct_flags = samdb_result_acct_flags ( msgs [ 0 ] , " sAMAcctFlags " ) ;
2004-05-02 12:45:00 +04:00
/* Quit if the account was locked out. */
2004-05-13 19:34:56 +04:00
if ( acct_flags & ACB_AUTOLOCK ) {
DEBUG ( 3 , ( " check_sam_security: Account for user %s was locked out. \n " ,
2005-01-09 15:55:25 +03:00
user_info - > account_name ) ) ;
2004-05-02 12:45:00 +04:00
return NT_STATUS_ACCOUNT_LOCKED_OUT ;
}
2005-01-09 15:55:25 +03:00
nt_status = samdb_result_passwords ( mem_ctx , msgs [ 0 ] , & lm_pwd , & nt_pwd ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-05-13 19:34:56 +04:00
2005-01-09 15:55:25 +03: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 05:53:07 +04:00
2004-05-14 05:15:16 +04:00
acct_expiry = samdb_result_nttime ( msgs [ 0 ] , " accountExpires " , 0 ) ;
2004-06-05 07:22:10 +04:00
must_change_time = samdb_result_force_password_change ( sam_ctx , mem_ctx ,
domain_dn , msgs [ 0 ] ,
" pwdLastSet " ) ;
2004-05-14 05:15:16 +04:00
last_set_time = samdb_result_nttime ( msgs [ 0 ] , " pwdLastSet " , 0 ) ;
workstation_list = samdb_result_string ( msgs [ 0 ] , " userWorkstations " , NULL ) ;
2005-01-09 15:55:25 +03:00
nt_status = authsam_account_ok ( mem_ctx , acct_flags ,
acct_expiry ,
must_change_time ,
last_set_time ,
workstation_list ,
user_info ) ;
2003-08-13 05:53:07 +04:00
2004-10-25 08:25:29 +04:00
return nt_status ;
}
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_make_server_info ( TALLOC_CTX * mem_ctx , void * sam_ctx ,
struct ldb_message * * msgs ,
struct ldb_message * * msgs_domain ,
DATA_BLOB user_sess_key , DATA_BLOB lm_sess_key ,
struct auth_serversupplied_info * * _server_info )
2004-10-25 08:25:29 +04:00
{
2005-01-09 15:55:25 +03:00
struct auth_serversupplied_info * server_info ;
2004-10-25 08:25:29 +04:00
struct ldb_message * * group_msgs ;
int group_ret ;
const char * group_attrs [ 3 ] = { " sAMAccountType " , " objectSid " , NULL } ;
/* find list of sids */
struct dom_sid * * groupSIDs = NULL ;
2005-01-09 15:55:25 +03:00
struct dom_sid * account_sid ;
2004-10-25 08:25:29 +04:00
struct dom_sid * primary_group_sid ;
2005-05-18 18:19:17 +04:00
const char * str , * ncname ;
2004-10-25 08:25:29 +04:00
int i ;
uint_t rid ;
2005-01-24 05:19:57 +03:00
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
2003-08-13 05:53:07 +04:00
2005-03-23 04:30:43 +03:00
group_ret = gendb_search ( sam_ctx ,
2005-01-24 05:19:57 +03:00
tmp_ctx , NULL , & group_msgs , group_attrs ,
2004-10-25 08:25:29 +04:00
" (&(member=%s)(sAMAccountType=*)) " ,
msgs [ 0 ] - > dn ) ;
if ( group_ret = = - 1 ) {
2005-01-24 05:19:57 +03:00
talloc_free ( tmp_ctx ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-09 15:55:25 +03:00
server_info = talloc ( mem_ctx , struct auth_serversupplied_info ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info ) ;
2004-10-25 08:25:29 +04:00
2005-01-09 15:55:25 +03:00
if ( group_ret > 0 ) {
groupSIDs = talloc_array ( server_info , struct dom_sid * , group_ret ) ;
NT_STATUS_HAVE_NO_MEMORY ( groupSIDs ) ;
2004-10-25 08:25:29 +04:00
}
2005-01-09 15:55:25 +03:00
2004-10-25 08:25:29 +04:00
/* Need to unroll some nested groups, but not aliases */
for ( i = 0 ; i < group_ret ; i + + ) {
2005-01-09 15:55:25 +03:00
str = ldb_msg_find_string ( group_msgs [ i ] , " objectSid " , NULL ) ;
groupSIDs [ i ] = dom_sid_parse_talloc ( groupSIDs , str ) ;
NT_STATUS_HAVE_NO_MEMORY ( groupSIDs [ i ] ) ;
2004-10-25 08:25:29 +04:00
}
2005-01-09 15:55:25 +03:00
2005-01-24 05:19:57 +03:00
talloc_free ( tmp_ctx ) ;
2005-01-09 15:55:25 +03:00
str = ldb_msg_find_string ( msgs [ 0 ] , " objectSid " , NULL ) ;
account_sid = dom_sid_parse_talloc ( server_info , str ) ;
NT_STATUS_HAVE_NO_MEMORY ( account_sid ) ;
primary_group_sid = dom_sid_dup ( server_info , account_sid ) ;
NT_STATUS_HAVE_NO_MEMORY ( primary_group_sid ) ;
2004-10-25 08:25:29 +04:00
rid = samdb_result_uint ( msgs [ 0 ] , " primaryGroupID " , ~ 0 ) ;
if ( rid = = ~ 0 ) {
if ( group_ret > 0 ) {
primary_group_sid = groupSIDs [ 0 ] ;
2004-10-03 10:40:40 +04:00
} else {
2004-10-25 08:25:29 +04:00
primary_group_sid = NULL ;
2004-10-03 10:40:40 +04:00
}
2004-10-25 08:25:29 +04:00
} else {
primary_group_sid - > sub_auths [ primary_group_sid - > num_auths - 1 ] = rid ;
2004-05-13 19:34:56 +04:00
}
2005-01-09 15:55:25 +03:00
server_info - > account_sid = account_sid ;
server_info - > primary_group_sid = primary_group_sid ;
2004-10-25 08:25:29 +04:00
2005-01-09 15:55:25 +03:00
server_info - > n_domain_groups = group_ret ;
server_info - > domain_groups = groupSIDs ;
2004-06-07 07:46:32 +04:00
2005-06-04 15:10:57 +04:00
server_info - > account_name = talloc_steal ( server_info , samdb_result_string ( msgs [ 0 ] , " sAMAccountName " , NULL ) ) ;
2005-01-09 15:55:25 +03:00
2005-06-04 15:10:57 +04:00
server_info - > domain_name = talloc_steal ( server_info , samdb_result_string ( msgs_domain [ 0 ] , " nETBIOSName " , NULL ) ) ;
2005-01-09 15:55:25 +03:00
str = samdb_result_string ( msgs [ 0 ] , " displayName " , " " ) ;
server_info - > full_name = talloc_strdup ( server_info , str ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > full_name ) ;
str = samdb_result_string ( msgs [ 0 ] , " scriptPath " , " " ) ;
server_info - > logon_script = talloc_strdup ( server_info , str ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > logon_script ) ;
str = samdb_result_string ( msgs [ 0 ] , " profilePath " , " " ) ;
server_info - > profile_path = talloc_strdup ( server_info , str ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > profile_path ) ;
str = samdb_result_string ( msgs [ 0 ] , " homeDirectory " , " " ) ;
server_info - > home_directory = talloc_strdup ( server_info , str ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > home_directory ) ;
str = samdb_result_string ( msgs [ 0 ] , " homeDrive " , " " ) ;
server_info - > home_drive = talloc_strdup ( server_info , str ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > home_drive ) ;
server_info - > last_logon = samdb_result_nttime ( msgs [ 0 ] , " lastLogon " , 0 ) ;
server_info - > last_logoff = samdb_result_nttime ( msgs [ 0 ] , " lastLogoff " , 0 ) ;
server_info - > acct_expiry = samdb_result_nttime ( msgs [ 0 ] , " accountExpires " , 0 ) ;
server_info - > last_password_change = samdb_result_nttime ( msgs [ 0 ] , " pwdLastSet " , 0 ) ;
2005-05-18 18:19:17 +04:00
ncname = samdb_result_string ( msgs_domain [ 0 ] , " nCName " , " " ) ;
2005-01-09 15:55:25 +03:00
server_info - > allow_password_change = samdb_result_allow_password_change ( sam_ctx , mem_ctx ,
2005-05-18 18:19:17 +04:00
ncname , msgs [ 0 ] , " pwdLastSet " ) ;
2005-01-09 15:55:25 +03:00
server_info - > force_password_change = samdb_result_force_password_change ( sam_ctx , mem_ctx ,
2005-05-18 18:19:17 +04:00
ncname , msgs [ 0 ] , " pwdLastSet " ) ;
2005-01-09 15:55:25 +03:00
server_info - > logon_count = samdb_result_uint ( msgs [ 0 ] , " logonCount " , 0 ) ;
server_info - > bad_password_count = samdb_result_uint ( msgs [ 0 ] , " badPwdCount " , 0 ) ;
server_info - > acct_flags = samdb_result_acct_flags ( msgs [ 0 ] , " userAccountControl " ) ;
server_info - > user_session_key = user_sess_key ;
server_info - > lm_session_key = lm_sess_key ;
server_info - > authenticated = True ;
* _server_info = server_info ;
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
2005-01-09 15:55:25 +03:00
NTSTATUS sam_get_server_info ( TALLOC_CTX * mem_ctx , const char * account_name , const char * domain_name ,
DATA_BLOB user_sess_key , DATA_BLOB lm_sess_key ,
2004-10-25 08:25:29 +04:00
struct auth_serversupplied_info * * server_info )
{
NTSTATUS nt_status ;
struct ldb_message * * msgs ;
struct ldb_message * * domain_msgs ;
void * sam_ctx ;
sam_ctx = samdb_connect ( mem_ctx ) ;
if ( sam_ctx = = NULL ) {
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
2005-01-09 15:55:25 +03:00
nt_status = authsam_search_account ( mem_ctx , sam_ctx , account_name , domain_name , & msgs , & domain_msgs ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-10-25 08:25:29 +04:00
2005-01-09 15:55:25 +03:00
nt_status = authsam_make_server_info ( mem_ctx , sam_ctx , msgs , domain_msgs ,
user_sess_key , lm_sess_key ,
server_info ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-10-25 08:25:29 +04:00
2005-01-24 05:19:57 +03:00
talloc_free ( msgs ) ;
talloc_free ( domain_msgs ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_OK ;
}
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_check_password_internals ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const char * domain ,
const struct auth_usersupplied_info * user_info ,
struct auth_serversupplied_info * * server_info )
2004-10-25 08:25:29 +04:00
{
2005-01-09 15:55:25 +03:00
NTSTATUS nt_status ;
const char * account_name = user_info - > account_name ;
2004-10-25 08:25:29 +04:00
struct ldb_message * * msgs ;
struct ldb_message * * domain_msgs ;
void * sam_ctx ;
DATA_BLOB user_sess_key , lm_sess_key ;
2005-01-09 15:55:25 +03:00
if ( ! account_name | | ! * account_name ) {
/* 'not for me' */
return NT_STATUS_NOT_IMPLEMENTED ;
2004-12-23 06:00:55 +03:00
}
2004-10-25 08:25:29 +04:00
sam_ctx = samdb_connect ( mem_ctx ) ;
if ( sam_ctx = = NULL ) {
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
2005-01-09 15:55:25 +03:00
nt_status = authsam_search_account ( mem_ctx , sam_ctx , account_name , domain , & msgs , & domain_msgs ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-10-25 08:25:29 +04:00
2005-01-09 15:55:25 +03:00
nt_status = authsam_authenticate ( ctx - > auth_ctx , mem_ctx , sam_ctx , msgs , domain_msgs , user_info ,
& user_sess_key , & lm_sess_key ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-10-25 08:25:29 +04:00
2005-01-09 15:55:25 +03:00
nt_status = authsam_make_server_info ( mem_ctx , sam_ctx , msgs , domain_msgs ,
user_sess_key , lm_sess_key ,
server_info ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-10-25 08:25:29 +04:00
2005-01-24 05:19:57 +03:00
talloc_free ( msgs ) ;
talloc_free ( domain_msgs ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_OK ;
}
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_ignoredomain_check_password ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const struct auth_usersupplied_info * user_info ,
struct auth_serversupplied_info * * server_info )
2004-10-25 08:25:29 +04:00
{
2005-01-09 15:55:25 +03:00
return authsam_check_password_internals ( ctx , mem_ctx , NULL , user_info , server_info ) ;
2004-10-25 08:25:29 +04:00
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
Check SAM security ( above ) but with a few extra checks .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-09 15:55:25 +03:00
static NTSTATUS authsam_check_password ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const struct auth_usersupplied_info * user_info ,
struct auth_serversupplied_info * * server_info )
2003-08-13 05:53:07 +04:00
{
2004-10-25 08:25:29 +04:00
const char * domain ;
BOOL is_local_name , is_my_domain ;
2003-08-13 05:53:07 +04:00
2005-01-09 15:55:25 +03:00
is_local_name = is_myname ( user_info - > domain_name ) ;
is_my_domain = strequal ( user_info - > domain_name , lp_workgroup ( ) ) ;
2004-10-25 08:25:29 +04:00
/* check whether or not we service this domain/workgroup name */
2005-01-09 15:55:25 +03:00
switch ( lp_server_role ( ) ) {
2004-10-25 08:25:29 +04:00
case ROLE_STANDALONE :
2005-01-09 15:55:25 +03:00
domain = lp_netbios_name ( ) ;
break ;
2004-10-25 08:25:29 +04:00
case ROLE_DOMAIN_MEMBER :
2005-01-09 15:55:25 +03:00
if ( ! is_local_name ) {
DEBUG ( 6 , ( " authsam_check_password: %s is not one of my local names (%s) \n " ,
user_info - > domain_name , ( lp_server_role ( ) = = ROLE_DOMAIN_MEMBER
2004-10-25 08:25:29 +04:00
? " ROLE_DOMAIN_MEMBER " : " ROLE_STANDALONE " ) ) ) ;
return NT_STATUS_NOT_IMPLEMENTED ;
}
domain = lp_netbios_name ( ) ;
break ;
case ROLE_DOMAIN_PDC :
case ROLE_DOMAIN_BDC :
2005-01-09 15:55:25 +03: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 " ,
user_info - > domain_name ) ) ;
2004-10-25 08:25:29 +04:00
return NT_STATUS_NOT_IMPLEMENTED ;
}
domain = lp_workgroup ( ) ;
break ;
2005-01-09 15:55:25 +03:00
default :
DEBUG ( 6 , ( " authsam_check_password: lp_server_role() has an undefined value \n " ) ) ;
return NT_STATUS_NOT_IMPLEMENTED ;
2003-08-13 05:53:07 +04:00
}
2005-01-09 15:55:25 +03:00
return authsam_check_password_internals ( ctx , mem_ctx , domain , user_info , server_info ) ;
2003-08-13 05:53:07 +04:00
}
2005-01-09 15:55:25 +03:00
static const struct auth_operations sam_ignoredomain_ops = {
. name = " sam_ignoredomain " ,
. get_challenge = auth_get_challenge_not_implemented ,
. check_password = authsam_ignoredomain_check_password
} ;
2003-08-13 05:53:07 +04:00
2005-01-09 15:55:25 +03:00
static const struct auth_operations sam_ops = {
. name = " sam " ,
. get_challenge = auth_get_challenge_not_implemented ,
. check_password = authsam_check_password
} ;
2004-02-03 14:10:56 +03:00
NTSTATUS auth_sam_init ( void )
{
NTSTATUS ret ;
2005-01-09 15:55:25 +03:00
ret = auth_register ( & sam_ops ) ;
2004-02-03 14:10:56 +03:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 0 , ( " Failed to register 'sam' auth backend! \n " ) ) ;
2004-02-03 14:10:56 +03:00
return ret ;
}
2005-01-09 15:55:25 +03:00
ret = auth_register ( & sam_ignoredomain_ops ) ;
2004-02-03 14:10:56 +03:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 0 , ( " Failed to register 'sam_ignoredomain' auth backend! \n " ) ) ;
2004-02-03 14:10:56 +03:00
return ret ;
}
return ret ;
}