2011-05-06 18:50:04 +04:00
/*
Unix SMB / CIFS implementation .
2012-09-04 04:27:50 +04:00
pdb glue module for direct access to the dsdb via LDB APIs
2011-05-06 18:50:04 +04:00
Copyright ( C ) Volker Lendecke 2009 - 2011
2012-09-04 04:27:50 +04:00
Copyright ( C ) Andrew Bartlett 2010 - 2012
2011-05-06 18:50:04 +04:00
Copyright ( C ) Matthias Dieter Wallnöfer 2009
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
/* This module, is a port of Volker's pdb_ads to ldb and DSDB APIs */
# include "includes.h"
# include "source3/include/passdb.h"
# include "source4/dsdb/samdb/samdb.h"
# include "ldb_errors.h"
# include "libcli/security/dom_sid.h"
# include "source4/winbind/idmap.h"
# include "librpc/gen_ndr/ndr_security.h"
2014-08-15 07:01:31 +04:00
# include "librpc/gen_ndr/ndr_drsblobs.h"
# include "librpc/gen_ndr/ndr_lsa.h"
2011-05-06 18:50:04 +04:00
# include "libds/common/flag_mapping.h"
# include "source4/lib/events/events.h"
# include "source4/auth/session.h"
# include "source4/auth/system_session_proto.h"
2011-10-06 12:34:50 +04:00
# include "lib/param/param.h"
2011-08-11 10:19:24 +04:00
# include "source4/dsdb/common/util.h"
2012-01-27 00:33:02 +04:00
# include "source3/include/secrets.h"
2014-08-15 07:01:31 +04:00
# include "source4/auth/auth_sam.h"
2014-12-16 18:06:56 +03:00
# include "auth/credentials/credentials.h"
2011-05-06 18:50:04 +04:00
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state {
2011-05-06 18:50:04 +04:00
struct tevent_context * ev ;
struct ldb_context * ldb ;
struct idmap_context * idmap_ctx ;
struct loadparm_context * lp_ctx ;
} ;
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getsampwsid ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * sam_acct ,
const struct dom_sid * sid ) ;
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getsamupriv ( struct pdb_samba_dsdb_state * state ,
2011-05-06 18:50:04 +04:00
const char * filter ,
TALLOC_CTX * mem_ctx ,
struct ldb_message * * pmsg ) ;
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_sid_to_id ( struct pdb_methods * m , const struct dom_sid * sid ,
2012-03-16 02:16:23 +04:00
struct unixid * id ) ;
2011-05-06 18:50:04 +04:00
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_pull_time ( struct ldb_message * msg , const char * attr ,
2011-05-06 18:50:04 +04:00
time_t * ptime )
{
uint64_t tmp ;
if ( ! ldb_msg_find_element ( msg , attr ) ) {
return false ;
}
tmp = ldb_msg_find_attr_as_uint64 ( msg , attr , 0 ) ;
2012-06-27 08:56:04 +04:00
* ptime = nt_time_to_unix ( tmp ) ;
2011-05-06 18:50:04 +04:00
return true ;
}
2012-09-04 04:27:50 +04:00
static struct pdb_domain_info * pdb_samba_dsdb_get_domain_info (
2011-05-06 18:50:04 +04:00
struct pdb_methods * m , TALLOC_CTX * mem_ctx )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct pdb_domain_info * info ;
struct dom_sid * domain_sid ;
struct ldb_dn * forest_dn , * domain_dn ;
struct ldb_result * dom_res = NULL ;
const char * dom_attrs [ ] = {
2012-09-04 04:27:50 +04:00
" objectSid " ,
" objectGUID " ,
2011-05-06 18:50:04 +04:00
" fSMORoleOwner " ,
NULL
} ;
char * p ;
int ret ;
info = talloc ( mem_ctx , struct pdb_domain_info ) ;
if ( info = = NULL ) {
return NULL ;
}
2012-09-04 04:27:50 +04:00
domain_dn = ldb_get_default_basedn ( state - > ldb ) ;
2011-05-06 18:50:04 +04:00
ret = ldb_search ( state - > ldb , info , & dom_res ,
domain_dn , LDB_SCOPE_BASE , dom_attrs , NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
goto fail ;
}
if ( dom_res - > count ! = 1 ) {
goto fail ;
}
info - > guid = samdb_result_guid ( dom_res - > msgs [ 0 ] , " objectGUID " ) ;
domain_sid = samdb_result_dom_sid ( state , dom_res - > msgs [ 0 ] , " objectSid " ) ;
if ( ! domain_sid ) {
goto fail ;
}
info - > sid = * domain_sid ;
TALLOC_FREE ( dom_res ) ;
info - > name = talloc_strdup ( info , lpcfg_sam_name ( state - > lp_ctx ) ) ;
info - > dns_domain = ldb_dn_canonical_string ( info , domain_dn ) ;
if ( ! info - > dns_domain ) {
goto fail ;
}
p = strchr ( info - > dns_domain , ' / ' ) ;
if ( p ) {
* p = ' \0 ' ;
}
forest_dn = ldb_get_root_basedn ( state - > ldb ) ;
if ( ! forest_dn ) {
goto fail ;
}
info - > dns_forest = ldb_dn_canonical_string ( info , forest_dn ) ;
if ( ! info - > dns_forest ) {
goto fail ;
}
p = strchr ( info - > dns_forest , ' / ' ) ;
if ( p ) {
* p = ' \0 ' ;
}
return info ;
fail :
TALLOC_FREE ( dom_res ) ;
TALLOC_FREE ( info ) ;
return NULL ;
}
2012-09-04 04:27:50 +04:00
static struct ldb_message * pdb_samba_dsdb_get_samu_private (
2011-05-06 18:50:04 +04:00
struct pdb_methods * m , struct samu * sam )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct ldb_message * msg ;
char * sidstr , * filter ;
NTSTATUS status ;
msg = ( struct ldb_message * )
pdb_get_backend_private_data ( sam , m ) ;
if ( msg ! = NULL ) {
return talloc_get_type_abort ( msg , struct ldb_message ) ;
}
sidstr = dom_sid_string ( talloc_tos ( ) , pdb_get_user_sid ( sam ) ) ;
if ( sidstr = = NULL ) {
return NULL ;
}
filter = talloc_asprintf (
talloc_tos ( ) , " (&(objectsid=%s)(objectclass=user)) " , sidstr ) ;
TALLOC_FREE ( sidstr ) ;
if ( filter = = NULL ) {
return NULL ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_getsamupriv ( state , filter , sam , & msg ) ;
2011-05-06 18:50:04 +04:00
TALLOC_FREE ( filter ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return NULL ;
}
return msg ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_init_sam_from_priv ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * sam ,
struct ldb_message * msg )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
const char * str ;
time_t tmp_time ;
struct dom_sid * sid , group_sid ;
uint64_t n ;
const DATA_BLOB * blob ;
str = ldb_msg_find_attr_as_string ( msg , " samAccountName " , NULL ) ;
if ( str = = NULL ) {
DEBUG ( 10 , ( " no samAccountName \n " ) ) ;
goto fail ;
}
pdb_set_username ( sam , str , PDB_SET ) ;
2012-09-04 04:27:50 +04:00
if ( pdb_samba_dsdb_pull_time ( msg , " lastLogon " , & tmp_time ) ) {
2011-05-06 18:50:04 +04:00
pdb_set_logon_time ( sam , tmp_time , PDB_SET ) ;
}
2012-09-04 04:27:50 +04:00
if ( pdb_samba_dsdb_pull_time ( msg , " lastLogoff " , & tmp_time ) ) {
2011-05-06 18:50:04 +04:00
pdb_set_logoff_time ( sam , tmp_time , PDB_SET ) ;
}
2012-09-04 04:27:50 +04:00
if ( pdb_samba_dsdb_pull_time ( msg , " pwdLastSet " , & tmp_time ) ) {
2011-05-06 18:50:04 +04:00
pdb_set_pass_last_set_time ( sam , tmp_time , PDB_SET ) ;
}
2012-09-04 04:27:50 +04:00
if ( pdb_samba_dsdb_pull_time ( msg , " accountExpires " , & tmp_time ) ) {
2011-05-06 18:50:04 +04:00
pdb_set_kickoff_time ( sam , tmp_time , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " displayName " ,
NULL ) ;
if ( str ! = NULL ) {
pdb_set_fullname ( sam , str , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " homeDirectory " ,
NULL ) ;
if ( str ! = NULL ) {
pdb_set_homedir ( sam , str , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " homeDrive " , NULL ) ;
if ( str ! = NULL ) {
pdb_set_dir_drive ( sam , str , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " scriptPath " , NULL ) ;
if ( str ! = NULL ) {
pdb_set_logon_script ( sam , str , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " profilePath " ,
NULL ) ;
if ( str ! = NULL ) {
pdb_set_profile_path ( sam , str , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " comment " ,
NULL ) ;
if ( str ! = NULL ) {
pdb_set_comment ( sam , str , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " description " ,
NULL ) ;
if ( str ! = NULL ) {
pdb_set_acct_desc ( sam , str , PDB_SET ) ;
}
str = ldb_msg_find_attr_as_string ( msg , " userWorkstations " ,
NULL ) ;
if ( str ! = NULL ) {
pdb_set_workstations ( sam , str , PDB_SET ) ;
}
2014-06-17 08:03:22 +04:00
blob = ldb_msg_find_ldb_val ( msg , " userParameters " ) ;
if ( blob ! = NULL ) {
str = base64_encode_data_blob ( frame , * blob ) ;
if ( str = = NULL ) {
DEBUG ( 0 , ( " base64_encode_data_blob() failed \n " ) ) ;
goto fail ;
}
2011-05-06 18:50:04 +04:00
pdb_set_munged_dial ( sam , str , PDB_SET ) ;
}
sid = samdb_result_dom_sid ( talloc_tos ( ) , msg , " objectSid " ) ;
if ( ! sid ) {
DEBUG ( 10 , ( " Could not pull SID \n " ) ) ;
goto fail ;
}
pdb_set_user_sid ( sam , sid , PDB_SET ) ;
2013-10-29 08:30:18 +04:00
n = samdb_result_acct_flags ( msg , " msDS-User-Account-Control-Computed " ) ;
2011-05-06 18:50:04 +04:00
if ( n = = 0 ) {
DEBUG ( 10 , ( " Could not pull userAccountControl \n " ) ) ;
goto fail ;
}
2013-10-29 08:30:18 +04:00
pdb_set_acct_ctrl ( sam , n , PDB_SET ) ;
2011-05-06 18:50:04 +04:00
blob = ldb_msg_find_ldb_val ( msg , " unicodePwd " ) ;
if ( blob ) {
if ( blob - > length ! = NT_HASH_LEN ) {
DEBUG ( 0 , ( " Got NT hash of length %d, expected %d \n " ,
( int ) blob - > length , NT_HASH_LEN ) ) ;
goto fail ;
}
pdb_set_nt_passwd ( sam , blob - > data , PDB_SET ) ;
}
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
blob = ldb_msg_find_ldb_val ( msg , " dBCSPwd " ) ;
if ( blob ) {
if ( blob - > length ! = LM_HASH_LEN ) {
DEBUG ( 0 , ( " Got LM hash of length %d, expected %d \n " ,
( int ) blob - > length , LM_HASH_LEN ) ) ;
goto fail ;
}
pdb_set_lanman_passwd ( sam , blob - > data , PDB_SET ) ;
}
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
n = ldb_msg_find_attr_as_uint ( msg , " primaryGroupID " , 0 ) ;
if ( n = = 0 ) {
DEBUG ( 10 , ( " Could not pull primaryGroupID \n " ) ) ;
goto fail ;
}
sid_compose ( & group_sid , samdb_domain_sid ( state - > ldb ) , n ) ;
pdb_set_group_sid ( sam , & group_sid , PDB_SET ) ;
status = NT_STATUS_OK ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_add_time ( struct ldb_message * msg ,
2011-05-06 18:50:04 +04:00
const char * attrib , time_t t )
{
uint64_t nt_time ;
unix_to_nt_time ( & nt_time , t ) ;
2011-06-07 00:34:00 +04:00
return ldb_msg_add_fmt ( msg , attrib , " %llu " , ( unsigned long long ) nt_time ) ;
2011-05-06 18:50:04 +04:00
}
2012-09-04 04:27:50 +04:00
static int pdb_samba_dsdb_replace_by_sam ( struct pdb_samba_dsdb_state * state ,
2011-08-11 09:47:01 +04:00
bool ( * need_update ) ( const struct samu * ,
enum pdb_elements ) ,
struct ldb_dn * dn ,
struct samu * sam )
2011-05-06 18:50:04 +04:00
{
2012-06-26 14:51:17 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2011-05-06 18:50:04 +04:00
int ret = LDB_SUCCESS ;
const char * pw ;
struct ldb_message * msg ;
2011-08-11 09:47:01 +04:00
struct ldb_request * req ;
2011-08-11 10:19:24 +04:00
uint32_t dsdb_flags = 0 ;
2011-05-06 18:50:04 +04:00
/* TODO: All fields :-) */
2012-06-26 14:51:17 +04:00
msg = ldb_msg_new ( frame ) ;
2011-05-06 18:50:04 +04:00
if ( ! msg ) {
2014-05-28 19:57:31 +04:00
talloc_free ( frame ) ;
2011-05-06 18:50:04 +04:00
return false ;
}
2011-08-11 09:47:01 +04:00
msg - > dn = dn ;
/* build modify request */
2012-06-26 14:51:17 +04:00
ret = ldb_build_mod_req ( & req , state - > ldb , frame , msg , NULL , NULL ,
2011-08-11 10:19:24 +04:00
ldb_op_default_callback ,
NULL ) ;
2011-08-11 09:47:01 +04:00
if ( ret ! = LDB_SUCCESS ) {
2012-06-26 14:51:17 +04:00
talloc_free ( frame ) ;
2011-08-11 09:47:01 +04:00
return ret ;
}
2011-05-06 18:50:04 +04:00
2012-01-24 11:37:24 +04:00
/* If we set a plaintext password, the system will
* force the pwdLastSet to now ( ) */
if ( need_update ( sam , PDB_PASSLASTSET ) ) {
dsdb_flags = DSDB_PASSWORD_BYPASS_LAST_SET ;
2012-09-04 04:27:50 +04:00
ret | = pdb_samba_dsdb_add_time ( msg , " pwdLastSet " ,
2012-01-24 11:37:24 +04:00
pdb_get_pass_last_set_time ( sam ) ) ;
}
2011-05-06 18:50:04 +04:00
pw = pdb_get_plaintext_passwd ( sam ) ;
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_PLAINTEXT_PW ) ) {
2012-01-24 11:38:09 +04:00
struct ldb_val pw_utf16 ;
2011-05-06 18:50:04 +04:00
if ( pw = = NULL ) {
2012-06-26 14:51:17 +04:00
talloc_free ( frame ) ;
2011-08-11 09:47:01 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
2011-05-06 18:50:04 +04:00
}
2012-09-04 04:27:50 +04:00
2012-01-24 11:38:09 +04:00
if ( ! convert_string_talloc ( msg ,
CH_UNIX , CH_UTF16 ,
pw , strlen ( pw ) ,
( void * ) & pw_utf16 . data ,
& pw_utf16 . length ) ) {
2014-05-28 19:57:31 +04:00
talloc_free ( frame ) ;
2012-01-24 11:38:09 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
ret | = ldb_msg_add_value ( msg , " clearTextPassword " , & pw_utf16 , NULL ) ;
2011-08-11 09:47:01 +04:00
} else {
bool changed_lm_pw = false ;
bool changed_nt_pw = false ;
bool changed_history = false ;
if ( need_update ( sam , PDB_LMPASSWD ) ) {
struct ldb_val val ;
2012-12-13 03:33:04 +04:00
val . data = discard_const_p ( uint8_t , pdb_get_lanman_passwd ( sam ) ) ;
2011-08-11 09:47:01 +04:00
if ( ! val . data ) {
samdb_msg_add_delete ( state - > ldb , msg , msg ,
" dBCSPwd " ) ;
} else {
val . length = LM_HASH_LEN ;
ret | = ldb_msg_add_value ( msg , " dBCSPwd " , & val , NULL ) ;
}
changed_lm_pw = true ;
}
if ( need_update ( sam , PDB_NTPASSWD ) ) {
struct ldb_val val ;
2012-12-13 03:33:04 +04:00
val . data = discard_const_p ( uint8_t , pdb_get_nt_passwd ( sam ) ) ;
2011-08-11 09:47:01 +04:00
if ( ! val . data ) {
samdb_msg_add_delete ( state - > ldb , msg , msg ,
" unicodePwd " ) ;
} else {
val . length = NT_HASH_LEN ;
ret | = ldb_msg_add_value ( msg , " unicodePwd " , & val , NULL ) ;
}
changed_nt_pw = true ;
}
/* Try to ensure we don't get out of sync */
if ( changed_lm_pw & & ! changed_nt_pw ) {
samdb_msg_add_delete ( state - > ldb , msg , msg ,
" unicodePwd " ) ;
} else if ( changed_nt_pw & & ! changed_lm_pw ) {
samdb_msg_add_delete ( state - > ldb , msg , msg ,
" dBCSPwd " ) ;
}
if ( changed_lm_pw | | changed_nt_pw ) {
samdb_msg_add_delete ( state - > ldb , msg , msg ,
" supplementalCredentials " ) ;
}
if ( need_update ( sam , PDB_PWHISTORY ) ) {
uint32_t current_hist_len ;
const uint8_t * history = pdb_get_pw_history ( sam , & current_hist_len ) ;
bool invalid_history = false ;
struct samr_Password * history_hashes = talloc_array ( talloc_tos ( ) , struct samr_Password ,
current_hist_len ) ;
if ( ! history ) {
invalid_history = true ;
} else {
unsigned int i ;
static const uint8_t zeros [ 16 ] ;
/* Parse the history into the correct format */
for ( i = 0 ; i < current_hist_len ; i + + ) {
if ( memcmp ( & history [ i * PW_HISTORY_ENTRY_LEN ] , zeros , 16 ) ! = 0 ) {
/* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
invalid_history = true ;
break ;
}
/* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
memcpy ( history_hashes [ i ] . hash ,
& history [ ( i * PW_HISTORY_ENTRY_LEN ) + PW_HISTORY_SALT_LEN ] ,
sizeof ( history_hashes [ i ] . hash ) ) ;
}
}
if ( invalid_history ) {
ret | = samdb_msg_add_delete ( state - > ldb , msg , msg ,
" ntPwdHistory " ) ;
ret | = samdb_msg_add_delete ( state - > ldb , msg , msg ,
" lmPwdHistory " ) ;
} else {
ret | = samdb_msg_add_hashes ( state - > ldb , msg , msg ,
" ntPwdHistory " ,
history_hashes ,
current_hist_len ) ;
}
changed_history = true ;
}
if ( changed_lm_pw | | changed_nt_pw | | changed_history ) {
2011-08-11 10:19:24 +04:00
/* These attributes can only be modified directly by using a special control */
dsdb_flags = DSDB_BYPASS_PASSWORD_HASH ;
2011-08-11 09:47:01 +04:00
}
2011-05-06 18:50:04 +04:00
}
2011-08-11 09:47:01 +04:00
/* PDB_USERSID is only allowed on ADD, handled in caller */
if ( need_update ( sam , PDB_GROUPSID ) ) {
const struct dom_sid * sid = pdb_get_group_sid ( sam ) ;
uint32_t rid ;
NTSTATUS status = dom_sid_split_rid ( NULL , sid , NULL , & rid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-06-26 14:51:17 +04:00
talloc_free ( frame ) ;
2011-08-11 09:47:01 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
if ( ! dom_sid_in_domain ( samdb_domain_sid ( state - > ldb ) , sid ) ) {
2012-06-26 14:51:17 +04:00
talloc_free ( frame ) ;
2011-08-11 09:47:01 +04:00
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX ;
}
ret | = samdb_msg_add_uint ( state - > ldb , msg , msg , " primaryGroupID " , rid ) ;
}
if ( need_update ( sam , PDB_FULLNAME ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " displayName " , pdb_get_fullname ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_SMBHOME ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " homeDirectory " ,
pdb_get_homedir ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_PROFILE ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " profilePath " ,
pdb_get_profile_path ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_DRIVE ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " homeDrive " ,
pdb_get_dir_drive ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_LOGONSCRIPT ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " scriptPath " ,
pdb_get_logon_script ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_KICKOFFTIME ) ) {
2012-09-04 04:27:50 +04:00
ret | = pdb_samba_dsdb_add_time ( msg , " accountExpires " ,
2011-05-06 18:50:04 +04:00
pdb_get_kickoff_time ( sam ) ) ;
}
2012-06-27 08:34:47 +04:00
if ( need_update ( sam , PDB_LOGONTIME ) ) {
2012-09-04 04:27:50 +04:00
ret | = pdb_samba_dsdb_add_time ( msg , " lastLogon " ,
2012-06-27 08:34:47 +04:00
pdb_get_logon_time ( sam ) ) ;
}
if ( need_update ( sam , PDB_LOGOFFTIME ) ) {
2012-09-04 04:27:50 +04:00
ret | = pdb_samba_dsdb_add_time ( msg , " lastLogoff " ,
2012-06-27 08:34:47 +04:00
pdb_get_logoff_time ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_USERNAME ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " samAccountName " ,
pdb_get_username ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_HOURSLEN ) | | need_update ( sam , PDB_HOURS ) ) {
2011-05-06 18:50:04 +04:00
struct ldb_val hours = data_blob_const ( pdb_get_hours ( sam ) , pdb_get_hours_len ( sam ) ) ;
ret | = ldb_msg_add_value ( msg , " logonHours " ,
& hours , NULL ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_ACCTCTRL ) ) {
ret | = samdb_msg_add_acct_flags ( state - > ldb , msg , msg ,
" userAccountControl " , pdb_get_acct_ctrl ( sam ) ) ;
2011-05-06 18:50:04 +04:00
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_COMMENT ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " comment " ,
pdb_get_comment ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_ACCTDESC ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " description " ,
pdb_get_acct_desc ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_WORKSTATIONS ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_string ( msg , " userWorkstations " ,
pdb_get_workstations ( sam ) ) ;
}
/* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_MUNGEDDIAL ) ) {
2014-06-17 08:03:22 +04:00
const char * base64_munged_dial = NULL ;
base64_munged_dial = pdb_get_munged_dial ( sam ) ;
if ( base64_munged_dial ! = NULL & & strlen ( base64_munged_dial ) > 0 ) {
struct ldb_val blob ;
blob = base64_decode_data_blob_talloc ( msg ,
base64_munged_dial ) ;
if ( blob . data = = NULL ) {
DEBUG ( 0 , ( " Failed to decode userParameters from "
" munged dialback string[%s] for %s \n " ,
base64_munged_dial ,
ldb_dn_get_linearized ( msg - > dn ) ) ) ;
talloc_free ( frame ) ;
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX ;
}
ret | = ldb_msg_add_steal_value ( msg , " userParameters " ,
& blob ) ;
}
2011-05-06 18:50:04 +04:00
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_COUNTRY_CODE ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_fmt ( msg , " countryCode " ,
" %i " , ( int ) pdb_get_country_code ( sam ) ) ;
}
2011-08-11 09:47:01 +04:00
if ( need_update ( sam , PDB_CODE_PAGE ) ) {
2011-05-06 18:50:04 +04:00
ret | = ldb_msg_add_fmt ( msg , " codePage " ,
" %i " , ( int ) pdb_get_code_page ( sam ) ) ;
}
2012-09-04 04:27:50 +04:00
/* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
2011-05-06 18:50:04 +04:00
PDB_BAD_PASSWORD_TIME ,
2011-08-11 09:47:01 +04:00
PDB_CANCHANGETIME , - these are calculated per policy , not stored
2011-05-06 18:50:04 +04:00
PDB_DOMAIN ,
2011-08-11 09:47:01 +04:00
PDB_NTUSERNAME , - this makes no sense , and never really did
2011-05-06 18:50:04 +04:00
PDB_LOGONDIVS ,
2012-09-04 04:27:50 +04:00
PDB_USERSID , - Handled in pdb_samba_dsdb_add_sam_account ( )
2011-05-06 18:50:04 +04:00
PDB_FIELDS_PRESENT ,
PDB_BAD_PASSWORD_COUNT ,
PDB_LOGON_COUNT ,
PDB_UNKNOWN6 ,
PDB_BACKEND_PRIVATE_DATA ,
*/
2011-08-11 09:47:01 +04:00
if ( ret ! = LDB_SUCCESS ) {
2012-06-26 14:51:17 +04:00
talloc_free ( frame ) ;
2011-08-11 09:47:01 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2011-05-06 18:50:04 +04:00
2011-08-11 09:47:01 +04:00
if ( msg - > num_elements = = 0 ) {
2012-06-26 14:51:17 +04:00
talloc_free ( frame ) ;
2011-08-11 09:47:01 +04:00
/* Nothing to do, just return success */
return LDB_SUCCESS ;
}
2011-08-11 10:19:24 +04:00
ret = dsdb_replace ( state - > ldb , msg , dsdb_flags ) ;
2011-08-11 09:47:01 +04:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Failed to modify account record %s to set user attributes: %s \n " ,
ldb_dn_get_linearized ( msg - > dn ) ,
ldb_errstring ( state - > ldb ) ) ) ;
}
2012-06-26 14:51:17 +04:00
talloc_free ( frame ) ;
2011-08-11 09:47:01 +04:00
return ret ;
2011-05-06 18:50:04 +04:00
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getsamupriv ( struct pdb_samba_dsdb_state * state ,
2011-05-06 18:50:04 +04:00
const char * filter ,
TALLOC_CTX * mem_ctx ,
struct ldb_message * * msg )
{
const char * attrs [ ] = {
" lastLogon " , " lastLogoff " , " pwdLastSet " , " accountExpires " ,
" sAMAccountName " , " displayName " , " homeDirectory " ,
" homeDrive " , " scriptPath " , " profilePath " , " description " ,
" userWorkstations " , " comment " , " userParameters " , " objectSid " ,
2013-10-29 08:30:18 +04:00
" primaryGroupID " , " userAccountControl " ,
" msDS-User-Account-Control-Computed " , " logonHours " ,
2011-05-06 18:50:04 +04:00
" badPwdCount " , " logonCount " , " countryCode " , " codePage " ,
" unicodePwd " , " dBCSPwd " , NULL } ;
2011-08-19 11:27:14 +04:00
int rc = dsdb_search_one ( state - > ldb , mem_ctx , msg , ldb_get_default_basedn ( state - > ldb ) , LDB_SCOPE_SUBTREE , attrs , 0 , " %s " , filter ) ;
2011-05-06 18:50:04 +04:00
if ( rc ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " ldap_search failed %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
return NT_STATUS_LDAP ( rc ) ;
}
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getsampwfilter ( struct pdb_methods * m ,
struct pdb_samba_dsdb_state * state ,
2011-05-06 18:50:04 +04:00
struct samu * sam_acct ,
const char * exp_fmt , . . . ) _PRINTF_ATTRIBUTE ( 4 , 5 )
{
struct ldb_message * priv ;
NTSTATUS status ;
va_list ap ;
char * expression = NULL ;
TALLOC_CTX * tmp_ctx = talloc_new ( state ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
va_start ( ap , exp_fmt ) ;
expression = talloc_vasprintf ( tmp_ctx , exp_fmt , ap ) ;
va_end ( ap ) ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
if ( ! expression ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_getsamupriv ( state , expression , sam_acct , & priv ) ;
2011-05-06 18:50:04 +04:00
talloc_free ( tmp_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-09-04 04:27:50 +04:00
DEBUG ( 10 , ( " pdb_samba_dsdb_getsamupriv failed: %s \n " ,
2011-05-06 18:50:04 +04:00
nt_errstr ( status ) ) ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_init_sam_from_priv ( m , sam_acct , priv ) ;
2011-05-06 18:50:04 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-09-04 04:27:50 +04:00
DEBUG ( 10 , ( " pdb_samba_dsdb_init_sam_from_priv failed: %s \n " ,
2011-05-06 18:50:04 +04:00
nt_errstr ( status ) ) ) ;
TALLOC_FREE ( priv ) ;
return status ;
}
pdb_set_backend_private_data ( sam_acct , priv , NULL , m , PDB_SET ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getsampwnam ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * sam_acct ,
const char * username )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
2012-09-04 04:27:50 +04:00
return pdb_samba_dsdb_getsampwfilter ( m , state , sam_acct ,
2011-05-06 18:50:04 +04:00
" (&(samaccountname=%s)(objectclass=user)) " ,
username ) ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getsampwsid ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * sam_acct ,
const struct dom_sid * sid )
{
NTSTATUS status ;
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
char * sidstr ;
sidstr = dom_sid_string ( talloc_tos ( ) , sid ) ;
NT_STATUS_HAVE_NO_MEMORY ( sidstr ) ;
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_getsampwfilter ( m , state , sam_acct ,
" (&(objectsid=%s)(objectclass=user)) " ,
2011-05-06 18:50:04 +04:00
sidstr ) ;
talloc_free ( sidstr ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_create_user ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
const char * name , uint32 acct_flags ,
uint32 * rid )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct dom_sid * sid ;
struct ldb_dn * dn ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
/* Internally this uses transactions to ensure all the steps
* happen or fail as one */
2011-08-11 09:46:26 +04:00
status = dsdb_add_user ( state - > ldb , tmp_ctx , name , acct_flags , NULL ,
& sid , & dn ) ;
2011-05-06 18:50:04 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
sid_peek_rid ( sid , rid ) ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_delete_user ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
struct samu * sam )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct ldb_dn * dn ;
int rc ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
dn = ldb_dn_new_fmt ( tmp_ctx , state - > ldb , " <SID=%s> " , dom_sid_string ( tmp_ctx , pdb_get_user_sid ( sam ) ) ) ;
if ( ! dn | | ! ldb_dn_validate ( dn ) ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
rc = ldb_delete ( state - > ldb , dn ) ;
if ( rc ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " ldb_delete for %s failed: %s \n " , ldb_dn_get_linearized ( dn ) ,
ldb_errstring ( state - > ldb ) ) ) ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_LDAP ( rc ) ;
}
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
/* This interface takes a fully populated struct samu and places it in
* the database . This is not implemented at this time as we need to
* be careful around the creation of arbitary SIDs ( ie , we must ensrue
* they are not left in a RID pool */
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_add_sam_account ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * sampass )
{
2011-08-11 09:47:01 +04:00
int ret ;
NTSTATUS status ;
struct ldb_dn * dn ;
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-08-11 09:47:01 +04:00
uint32_t acb_flags = pdb_get_acct_ctrl ( sampass ) ;
const char * username = pdb_get_username ( sampass ) ;
const struct dom_sid * user_sid = pdb_get_user_sid ( sampass ) ;
TALLOC_CTX * tframe = talloc_stackframe ( ) ;
acb_flags & = ( ACB_NORMAL | ACB_WSTRUST | ACB_SVRTRUST | ACB_DOMTRUST ) ;
ret = ldb_transaction_start ( state - > ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tframe ) ;
return NT_STATUS_LOCK_NOT_GRANTED ;
}
status = dsdb_add_user ( state - > ldb , talloc_tos ( ) , username ,
acb_flags , user_sid , NULL , & dn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ldb_transaction_cancel ( state - > ldb ) ;
talloc_free ( tframe ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
ret = pdb_samba_dsdb_replace_by_sam ( state , pdb_element_is_set_or_changed ,
2011-08-11 09:47:01 +04:00
dn , sampass ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_transaction_cancel ( state - > ldb ) ;
talloc_free ( tframe ) ;
return dsdb_ldb_err_to_ntstatus ( ret ) ;
}
ret = ldb_transaction_commit ( state - > ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Failed to commit transaction to add and modify account record %s: %s \n " ,
ldb_dn_get_linearized ( dn ) ,
ldb_errstring ( state - > ldb ) ) ) ;
talloc_free ( tframe ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
talloc_free ( tframe ) ;
return NT_STATUS_OK ;
2011-05-06 18:50:04 +04:00
}
/*
2012-09-04 04:27:50 +04:00
* Update the Samba_Dsdb LDB with the changes from a struct samu .
2011-05-06 18:50:04 +04:00
*
* This takes care not to update elements that have not been changed
* by the caller
*/
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_update_sam_account ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * sam )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
struct ldb_message * msg = pdb_samba_dsdb_get_samu_private (
2011-05-06 18:50:04 +04:00
m , sam ) ;
2011-08-11 09:47:01 +04:00
int ret ;
2011-05-06 18:50:04 +04:00
2012-09-04 04:27:50 +04:00
ret = pdb_samba_dsdb_replace_by_sam ( state , pdb_element_is_changed , msg - > dn ,
2011-08-11 09:47:01 +04:00
sam ) ;
return dsdb_ldb_err_to_ntstatus ( ret ) ;
2011-05-06 18:50:04 +04:00
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_delete_sam_account ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * username )
{
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_new ( NULL ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_delete_user ( m , tmp_ctx , username ) ;
2011-05-06 18:50:04 +04:00
talloc_free ( tmp_ctx ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_rename_sam_account ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * oldname ,
const char * newname )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
/* This is not implemented, as this module is exptected to be used
2012-09-04 04:27:50 +04:00
* with auth_samba_dsdb , and this is responible for login counters etc
2011-05-06 18:50:04 +04:00
*
*/
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_update_login_attempts ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct samu * sam_acct ,
bool success )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getgrfilter ( struct pdb_methods * m , GROUP_MAP * map ,
2011-05-06 18:50:04 +04:00
const char * exp_fmt , . . . ) _PRINTF_ATTRIBUTE ( 4 , 5 )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2013-01-17 19:44:28 +04:00
const char * attrs [ ] = { " objectClass " , " objectSid " , " description " , " samAccountName " , " groupType " ,
2011-05-06 18:50:04 +04:00
NULL } ;
struct ldb_message * msg ;
va_list ap ;
char * expression = NULL ;
struct dom_sid * sid ;
const char * str ;
int rc ;
2012-03-16 02:16:23 +04:00
struct id_map id_map ;
struct id_map * id_maps [ 2 ] ;
2011-05-06 18:50:04 +04:00
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
va_start ( ap , exp_fmt ) ;
expression = talloc_vasprintf ( tmp_ctx , exp_fmt , ap ) ;
va_end ( ap ) ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
if ( ! expression ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-08-19 11:27:14 +04:00
rc = dsdb_search_one ( state - > ldb , tmp_ctx , & msg , ldb_get_default_basedn ( state - > ldb ) , LDB_SCOPE_SUBTREE , attrs , 0 , " %s " , expression ) ;
2011-05-06 18:50:04 +04:00
if ( rc = = LDB_ERR_NO_SUCH_OBJECT ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_SUCH_GROUP ;
} else if ( rc ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
DEBUG ( 10 , ( " dsdb_search_one failed %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
return NT_STATUS_LDAP ( rc ) ;
}
sid = samdb_result_dom_sid ( tmp_ctx , msg , " objectSid " ) ;
if ( ! sid ) {
talloc_free ( tmp_ctx ) ;
DEBUG ( 10 , ( " Could not pull SID \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
map - > sid = * sid ;
2012-09-04 04:27:50 +04:00
2012-03-16 02:16:23 +04:00
if ( samdb_find_attribute ( state - > ldb , msg , " objectClass " , " group " ) ) {
NTSTATUS status ;
uint32_t grouptype = ldb_msg_find_attr_as_uint ( msg , " groupType " , 0 ) ;
switch ( grouptype ) {
case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP :
case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP :
map - > sid_name_use = SID_NAME_ALIAS ;
break ;
case GTYPE_SECURITY_GLOBAL_GROUP :
map - > sid_name_use = SID_NAME_DOM_GRP ;
break ;
default :
talloc_free ( tmp_ctx ) ;
DEBUG ( 10 , ( " Could not pull groupType \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
ZERO_STRUCT ( id_map ) ;
id_map . sid = sid ;
id_maps [ 0 ] = & id_map ;
id_maps [ 1 ] = NULL ;
status = idmap_sids_to_xids ( state - > idmap_ctx , tmp_ctx , id_maps ) ;
2013-01-17 19:44:28 +04:00
2012-03-16 02:16:23 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
if ( id_map . xid . type = = ID_TYPE_GID | | id_map . xid . type = = ID_TYPE_BOTH ) {
map - > gid = id_map . xid . id ;
} else {
DEBUG ( 1 , ( __location__ " Did not get GUID when mapping SID for %s " , expression ) ) ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
} else if ( samdb_find_attribute ( state - > ldb , msg , " objectClass " , " user " ) ) {
2011-05-06 18:50:04 +04:00
DEBUG ( 1 , ( __location__ " Got SID_NAME_USER when searching for a group with %s " , expression ) ) ;
2012-03-16 02:16:23 +04:00
talloc_free ( tmp_ctx ) ;
2011-05-06 18:50:04 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
str = ldb_msg_find_attr_as_string ( msg , " samAccountName " ,
NULL ) ;
if ( str = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2011-09-27 01:55:47 +04:00
map - > nt_name = talloc_strdup ( map , str ) ;
if ( ! map - > nt_name ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-05-06 18:50:04 +04:00
str = ldb_msg_find_attr_as_string ( msg , " description " ,
NULL ) ;
if ( str ! = NULL ) {
2011-09-27 01:55:47 +04:00
map - > comment = talloc_strdup ( map , str ) ;
2011-05-06 18:50:04 +04:00
} else {
2011-09-27 01:55:47 +04:00
map - > comment = talloc_strdup ( map , " " ) ;
}
if ( ! map - > comment ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
2011-05-06 18:50:04 +04:00
}
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getgrsid ( struct pdb_methods * m , GROUP_MAP * map ,
2011-05-06 18:50:04 +04:00
struct dom_sid sid )
{
char * filter ;
NTSTATUS status ;
filter = talloc_asprintf ( talloc_tos ( ) ,
" (&(objectsid=%s)(objectclass=group)) " ,
sid_string_talloc ( talloc_tos ( ) , & sid ) ) ;
if ( filter = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_getgrfilter ( m , map , filter ) ;
2011-05-06 18:50:04 +04:00
TALLOC_FREE ( filter ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getgrgid ( struct pdb_methods * m , GROUP_MAP * map ,
2011-05-06 18:50:04 +04:00
gid_t gid )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
NTSTATUS status ;
struct id_map id_map ;
struct id_map * id_maps [ 2 ] ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
id_map . xid . id = gid ;
id_map . xid . type = ID_TYPE_GID ;
id_maps [ 0 ] = & id_map ;
id_maps [ 1 ] = NULL ;
status = idmap_xids_to_sids ( state - > idmap_ctx , tmp_ctx , id_maps ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-05-28 19:57:31 +04:00
talloc_free ( tmp_ctx ) ;
2011-05-06 18:50:04 +04:00
return status ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_getgrsid ( m , map , * id_map . sid ) ;
2011-05-06 18:50:04 +04:00
talloc_free ( tmp_ctx ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_getgrnam ( struct pdb_methods * m , GROUP_MAP * map ,
2011-05-06 18:50:04 +04:00
const char * name )
{
char * filter ;
NTSTATUS status ;
filter = talloc_asprintf ( talloc_tos ( ) ,
" (&(samaccountname=%s)(objectclass=group)) " ,
name ) ;
if ( filter = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_getgrfilter ( m , map , filter ) ;
2011-05-06 18:50:04 +04:00
TALLOC_FREE ( filter ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_create_dom_group ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx , const char * name ,
uint32 * rid )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
NTSTATUS status ;
struct dom_sid * sid ;
struct ldb_dn * dn ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
status = dsdb_add_domain_group ( state - > ldb , tmp_ctx , name , & sid , & dn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
sid_peek_rid ( sid , rid ) ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_delete_dom_group ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx , uint32 rid )
{
const char * attrs [ ] = { NULL } ;
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct dom_sid sid ;
struct ldb_message * msg ;
struct ldb_dn * dn ;
int rc ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
sid_compose ( & sid , samdb_domain_sid ( state - > ldb ) , rid ) ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
if ( ldb_transaction_start ( state - > ldb ) ! = LDB_SUCCESS ) {
2012-09-04 04:27:50 +04:00
DEBUG ( 0 , ( " Unable to start transaction in pdb_samba_dsdb_delete_dom_group() \n " ) ) ;
2011-05-06 18:50:04 +04:00
return NT_STATUS_INTERNAL_ERROR ;
}
dn = ldb_dn_new_fmt ( tmp_ctx , state - > ldb , " <SID=%s> " , dom_sid_string ( tmp_ctx , & sid ) ) ;
if ( ! dn | | ! ldb_dn_validate ( dn ) ) {
talloc_free ( tmp_ctx ) ;
ldb_transaction_cancel ( state - > ldb ) ;
return NT_STATUS_NO_MEMORY ;
}
rc = dsdb_search_one ( state - > ldb , tmp_ctx , & msg , dn , LDB_SCOPE_BASE , attrs , 0 , " objectclass=group " ) ;
if ( rc = = LDB_ERR_NO_SUCH_OBJECT ) {
talloc_free ( tmp_ctx ) ;
ldb_transaction_cancel ( state - > ldb ) ;
return NT_STATUS_NO_SUCH_GROUP ;
}
rc = ldb_delete ( state - > ldb , dn ) ;
if ( rc = = LDB_ERR_NO_SUCH_OBJECT ) {
talloc_free ( tmp_ctx ) ;
ldb_transaction_cancel ( state - > ldb ) ;
return NT_STATUS_NO_SUCH_GROUP ;
} else if ( rc ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " ldb_delete failed %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
ldb_transaction_cancel ( state - > ldb ) ;
return NT_STATUS_LDAP ( rc ) ;
}
if ( ldb_transaction_commit ( state - > ldb ) ! = LDB_SUCCESS ) {
2012-09-04 04:27:50 +04:00
DEBUG ( 0 , ( " Unable to commit transaction in pdb_samba_dsdb_delete_dom_group() \n " ) ) ;
2011-05-06 18:50:04 +04:00
return NT_STATUS_INTERNAL_ERROR ;
}
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
GROUP_MAP * map )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
GROUP_MAP * map )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct dom_sid sid )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_enum_group_mapping ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * sid ,
enum lsa_SidType sid_name_use ,
2011-09-27 01:55:47 +04:00
GROUP_MAP * * * pp_rmap ,
2011-05-06 18:50:04 +04:00
size_t * p_num_entries ,
bool unix_only )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_enum_group_members ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
const struct dom_sid * group ,
uint32_t * * pmembers ,
size_t * pnum_members )
{
unsigned int i , num_sids , num_members ;
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct dom_sid * members_as_sids ;
struct dom_sid * dom_sid ;
uint32_t * members ;
struct ldb_dn * dn ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
dn = ldb_dn_new_fmt ( tmp_ctx , state - > ldb , " <SID=%s> " , dom_sid_string ( tmp_ctx , group ) ) ;
if ( ! dn | | ! ldb_dn_validate ( dn ) ) {
return NT_STATUS_NO_MEMORY ;
}
status = dsdb_enum_group_mem ( state - > ldb , tmp_ctx , dn , & members_as_sids , & num_sids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
status = dom_sid_split_rid ( tmp_ctx , group , & dom_sid , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
* pmembers = members = talloc_array ( mem_ctx , uint32_t , num_sids ) ;
2014-02-13 08:51:11 +04:00
if ( * pmembers = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-05-06 18:50:04 +04:00
num_members = 0 ;
for ( i = 0 ; i < num_sids ; i + + ) {
if ( ! dom_sid_in_domain ( dom_sid , & members_as_sids [ i ] ) ) {
continue ;
}
2012-09-04 04:27:50 +04:00
status = dom_sid_split_rid ( NULL , & members_as_sids [ i ] ,
2011-05-06 18:50:04 +04:00
NULL , & members [ num_members ] ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
num_members + + ;
}
* pnum_members = num_members ;
return NT_STATUS_OK ;
}
/* Just convert the primary group SID into a group */
2012-09-04 04:27:50 +04:00
static NTSTATUS fake_enum_group_memberships ( struct pdb_samba_dsdb_state * state ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
struct samu * user ,
struct dom_sid * * pp_sids ,
gid_t * * pp_gids ,
uint32_t * p_num_groups )
{
NTSTATUS status ;
size_t num_groups = 0 ;
2013-05-27 15:28:47 +04:00
struct dom_sid * group_sids = NULL ;
gid_t * gids = NULL ;
2011-05-06 18:50:04 +04:00
TALLOC_CTX * tmp_ctx ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
if ( user - > group_sid ) {
struct id_map * id_maps [ 2 ] ;
struct id_map id_map ;
num_groups = 1 ;
group_sids = talloc_array ( tmp_ctx , struct dom_sid , num_groups ) ;
if ( group_sids = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
gids = talloc_array ( tmp_ctx , gid_t , num_groups ) ;
if ( gids = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
group_sids [ 0 ] = * user - > group_sid ;
ZERO_STRUCT ( id_map ) ;
id_map . sid = & group_sids [ 0 ] ;
id_maps [ 0 ] = & id_map ;
id_maps [ 1 ] = NULL ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
status = idmap_sids_to_xids ( state - > idmap_ctx , tmp_ctx , id_maps ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
if ( id_map . xid . type = = ID_TYPE_GID | | id_map . xid . type = = ID_TYPE_BOTH ) {
gids [ 0 ] = id_map . xid . id ;
} else {
2012-09-04 04:27:50 +04:00
DEBUG ( 1 , ( __location__
2011-05-06 18:50:04 +04:00
" Group %s, of which %s is a member, could not be converted to a GID \n " ,
dom_sid_string ( tmp_ctx , & group_sids [ 0 ] ) ,
dom_sid_string ( tmp_ctx , & user - > user_sid ) ) ) ;
talloc_free ( tmp_ctx ) ;
/* We must error out, otherwise a user might
* avoid a DENY acl based on a group they
* missed out on */
return NT_STATUS_NO_SUCH_GROUP ;
}
}
* pp_sids = talloc_steal ( mem_ctx , group_sids ) ;
* pp_gids = talloc_steal ( mem_ctx , gids ) ;
* p_num_groups = num_groups ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_enum_group_memberships ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
struct samu * user ,
struct dom_sid * * pp_sids ,
gid_t * * pp_gids ,
uint32_t * p_num_groups )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
struct ldb_message * msg = pdb_samba_dsdb_get_samu_private (
2011-05-06 18:50:04 +04:00
m , user ) ;
const char * attrs [ ] = { " tokenGroups " , NULL } ;
struct ldb_message * tokengroups_msg ;
struct ldb_message_element * tokengroups ;
int i , rc ;
NTSTATUS status ;
unsigned int count = 0 ;
size_t num_groups ;
struct dom_sid * group_sids ;
gid_t * gids ;
TALLOC_CTX * tmp_ctx ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
if ( msg = = NULL ) {
/* Fake up some things here */
2012-09-04 04:27:50 +04:00
return fake_enum_group_memberships ( state ,
mem_ctx ,
2011-05-06 18:50:04 +04:00
user , pp_sids ,
pp_gids , p_num_groups ) ;
}
tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
rc = dsdb_search_one ( state - > ldb , tmp_ctx , & tokengroups_msg , msg - > dn , LDB_SCOPE_BASE , attrs , 0 , NULL ) ;
if ( rc = = LDB_ERR_NO_SUCH_OBJECT ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_SUCH_USER ;
} else if ( rc ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " dsdb_search_one failed %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_LDAP ( rc ) ;
}
tokengroups = ldb_msg_find_element ( tokengroups_msg , " tokenGroups " ) ;
if ( tokengroups ) {
count = tokengroups - > num_values ;
}
group_sids = talloc_array ( tmp_ctx , struct dom_sid , count ) ;
if ( group_sids = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
gids = talloc_array ( tmp_ctx , gid_t , count ) ;
if ( gids = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
num_groups = 0 ;
for ( i = 0 ; i < count ; i + + ) {
struct id_map * id_maps [ 2 ] ;
struct id_map id_map ;
struct ldb_val * v = & tokengroups - > values [ i ] ;
enum ndr_err_code ndr_err
= ndr_pull_struct_blob ( v , group_sids , & group_sids [ num_groups ] ,
( ndr_pull_flags_fn_t ) ndr_pull_dom_sid ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
ZERO_STRUCT ( id_map ) ;
id_map . sid = & group_sids [ num_groups ] ;
id_maps [ 0 ] = & id_map ;
id_maps [ 1 ] = NULL ;
status = idmap_sids_to_xids ( state - > idmap_ctx , tmp_ctx , id_maps ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
if ( id_map . xid . type = = ID_TYPE_GID | | id_map . xid . type = = ID_TYPE_BOTH ) {
gids [ num_groups ] = id_map . xid . id ;
} else {
2012-09-04 04:27:50 +04:00
DEBUG ( 1 , ( __location__
2011-05-06 18:50:04 +04:00
" Group %s, of which %s is a member, could not be converted to a GID \n " ,
dom_sid_string ( tmp_ctx , & group_sids [ num_groups ] ) ,
ldb_dn_get_linearized ( msg - > dn ) ) ) ;
talloc_free ( tmp_ctx ) ;
/* We must error out, otherwise a user might
* avoid a DENY acl based on a group they
* missed out on */
return NT_STATUS_NO_SUCH_GROUP ;
}
num_groups + = 1 ;
if ( num_groups = = count ) {
break ;
}
}
* pp_sids = talloc_steal ( mem_ctx , group_sids ) ;
* pp_gids = talloc_steal ( mem_ctx , gids ) ;
* p_num_groups = num_groups ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_set_unix_primary_group ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
struct samu * user )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
2012-09-04 04:27:50 +04:00
const struct dom_sid * groupsid ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * membersid ,
int mod_op )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct ldb_message * msg ;
int ret ;
struct ldb_message_element * el ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
msg = ldb_msg_new ( tmp_ctx ) ;
2014-02-13 08:51:11 +04:00
if ( msg = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-05-06 18:50:04 +04:00
msg - > dn = ldb_dn_new_fmt ( msg , state - > ldb , " <SID=%s> " , dom_sid_string ( tmp_ctx , groupsid ) ) ;
if ( ! msg - > dn | | ! ldb_dn_validate ( msg - > dn ) ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
ret = ldb_msg_add_fmt ( msg , " member " , " <SID=%s> " , dom_sid_string ( tmp_ctx , membersid ) ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
el = ldb_msg_find_element ( msg , " member " ) ;
el - > flags = mod_op ;
/* No need for transactions here, the ldb auto-transaction
* code will handle things for the single operation */
ret = ldb_modify ( state - > ldb , msg ) ;
talloc_free ( tmp_ctx ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " ldb_modify failed: %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
if ( ret = = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS ) {
return NT_STATUS_MEMBER_IN_GROUP ;
}
if ( ret = = LDB_ERR_NO_SUCH_ATTRIBUTE ) {
return NT_STATUS_MEMBER_NOT_IN_GROUP ;
}
return NT_STATUS_LDAP ( ret ) ;
}
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_mod_groupmem ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
uint32 grouprid , uint32 memberrid ,
int mod_op )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
const struct dom_sid * dom_sid , * groupsid , * membersid ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
dom_sid = samdb_domain_sid ( state - > ldb ) ;
groupsid = dom_sid_add_rid ( tmp_ctx , dom_sid , grouprid ) ;
2014-02-13 08:51:11 +04:00
if ( groupsid = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-05-06 18:50:04 +04:00
membersid = dom_sid_add_rid ( tmp_ctx , dom_sid , memberrid ) ;
2014-02-13 08:51:11 +04:00
if ( membersid = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_mod_groupmem_by_sid ( m , tmp_ctx , groupsid , membersid , mod_op ) ;
2011-05-06 18:50:04 +04:00
talloc_free ( tmp_ctx ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_add_groupmem ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
uint32 group_rid , uint32 member_rid )
{
2012-09-04 04:27:50 +04:00
return pdb_samba_dsdb_mod_groupmem ( m , mem_ctx , group_rid , member_rid ,
2011-05-06 18:50:04 +04:00
LDB_FLAG_MOD_ADD ) ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_del_groupmem ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
uint32 group_rid , uint32 member_rid )
{
2012-09-04 04:27:50 +04:00
return pdb_samba_dsdb_mod_groupmem ( m , mem_ctx , group_rid , member_rid ,
2011-05-06 18:50:04 +04:00
LDB_FLAG_MOD_DELETE ) ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_create_alias ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const char * name , uint32 * rid )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct dom_sid * sid ;
struct ldb_dn * dn ;
NTSTATUS status ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
/* Internally this uses transactions to ensure all the steps
* happen or fail as one */
status = dsdb_add_domain_alias ( state - > ldb , frame , name , & sid , & dn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
}
sid_peek_rid ( sid , rid ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_delete_alias ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * sid )
{
const char * attrs [ ] = { NULL } ;
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct ldb_message * msg ;
struct ldb_dn * dn ;
int rc ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
dn = ldb_dn_new_fmt ( tmp_ctx , state - > ldb , " <SID=%s> " , dom_sid_string ( tmp_ctx , sid ) ) ;
if ( ! dn | | ! ldb_dn_validate ( dn ) ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( ldb_transaction_start ( state - > ldb ) ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Failed to start transaction in dsdb_add_domain_alias(): %s \n " , ldb_errstring ( state - > ldb ) ) ) ;
2014-05-28 19:57:31 +04:00
talloc_free ( tmp_ctx ) ;
2011-05-06 18:50:04 +04:00
return NT_STATUS_INTERNAL_ERROR ;
}
rc = dsdb_search_one ( state - > ldb , tmp_ctx , & msg , dn , LDB_SCOPE_BASE , attrs , 0 , " (objectclass=group) "
" (|(grouptype=%d)(grouptype=%d))) " ,
GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ,
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
if ( rc = = LDB_ERR_NO_SUCH_OBJECT ) {
talloc_free ( tmp_ctx ) ;
ldb_transaction_cancel ( state - > ldb ) ;
return NT_STATUS_NO_SUCH_ALIAS ;
}
rc = ldb_delete ( state - > ldb , dn ) ;
if ( rc = = LDB_ERR_NO_SUCH_OBJECT ) {
talloc_free ( tmp_ctx ) ;
ldb_transaction_cancel ( state - > ldb ) ;
return NT_STATUS_NO_SUCH_ALIAS ;
} else if ( rc ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " ldb_delete failed %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
ldb_transaction_cancel ( state - > ldb ) ;
2014-05-28 19:57:31 +04:00
talloc_free ( tmp_ctx ) ;
2011-05-06 18:50:04 +04:00
return NT_STATUS_LDAP ( rc ) ;
}
if ( ldb_transaction_commit ( state - > ldb ) ! = LDB_SUCCESS ) {
2012-09-04 04:27:50 +04:00
DEBUG ( 0 , ( " Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s \n " ,
2011-05-06 18:50:04 +04:00
ldb_errstring ( state - > ldb ) ) ) ;
2014-05-28 19:57:31 +04:00
talloc_free ( tmp_ctx ) ;
2011-05-06 18:50:04 +04:00
return NT_STATUS_INTERNAL_ERROR ;
}
2014-05-28 19:57:31 +04:00
talloc_free ( tmp_ctx ) ;
2011-05-06 18:50:04 +04:00
return NT_STATUS_OK ;
}
#if 0
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_set_aliasinfo ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * sid ,
struct acct_info * info )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct tldap_context * ld ;
const char * attrs [ 3 ] = { " objectSid " , " description " ,
" samAccountName " } ;
struct ldb_message * * msg ;
char * sidstr , * dn ;
int rc ;
struct tldap_mod * mods ;
int num_mods ;
bool ok ;
2012-09-04 04:27:50 +04:00
ld = pdb_samba_dsdb_ld ( state ) ;
2011-05-06 18:50:04 +04:00
if ( ld = = NULL ) {
return NT_STATUS_LDAP ( TLDAP_SERVER_DOWN ) ;
}
sidstr = sid_binstring ( talloc_tos ( ) , sid ) ;
NT_STATUS_HAVE_NO_MEMORY ( sidstr ) ;
2012-09-04 04:27:50 +04:00
rc = pdb_samba_dsdb_search_fmt ( state , state - > domaindn , TLDAP_SCOPE_SUB ,
2011-05-06 18:50:04 +04:00
attrs , ARRAY_SIZE ( attrs ) , 0 , talloc_tos ( ) ,
& msg , " (&(objectSid=%s)(objectclass=group) "
" (|(grouptype=%d)(grouptype=%d))) " ,
sidstr , GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ,
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
TALLOC_FREE ( sidstr )
if ( rc ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " ldap_search failed %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
return NT_STATUS_LDAP ( rc ) ;
}
switch talloc_array_length ( msg ) {
case 0 :
return NT_STATUS_NO_SUCH_ALIAS ;
case 1 :
break ;
default :
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( ! tldap_entry_dn ( msg [ 0 ] , & dn ) ) {
TALLOC_FREE ( msg ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
mods = NULL ;
num_mods = 0 ;
ok = true ;
ok & = tldap_make_mod_fmt (
msg [ 0 ] , msg , & num_mods , & mods , " description " ,
" %s " , info - > acct_desc ) ;
ok & = tldap_make_mod_fmt (
msg [ 0 ] , msg , & num_mods , & mods , " samAccountName " ,
" %s " , info - > acct_name ) ;
if ( ! ok ) {
TALLOC_FREE ( msg ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( num_mods = = 0 ) {
/* no change */
TALLOC_FREE ( msg ) ;
return NT_STATUS_OK ;
}
rc = tldap_modify ( ld , dn , num_mods , mods , NULL , 0 , NULL , 0 ) ;
TALLOC_FREE ( msg ) ;
if ( rc ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " ldap_modify failed: %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
return NT_STATUS_LDAP ( rc ) ;
}
return NT_STATUS_OK ;
}
# endif
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_add_aliasmem ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * alias ,
const struct dom_sid * member )
{
NTSTATUS status ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_mod_groupmem_by_sid ( m , frame , alias , member , LDB_FLAG_MOD_ADD ) ;
2011-05-06 18:50:04 +04:00
talloc_free ( frame ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_del_aliasmem ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * alias ,
const struct dom_sid * member )
{
NTSTATUS status ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_mod_groupmem_by_sid ( m , frame , alias , member , LDB_FLAG_MOD_DELETE ) ;
2011-05-06 18:50:04 +04:00
talloc_free ( frame ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_enum_aliasmem ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * alias ,
TALLOC_CTX * mem_ctx ,
struct dom_sid * * pmembers ,
size_t * pnum_members )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct ldb_dn * dn ;
unsigned int num_members ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
dn = ldb_dn_new_fmt ( tmp_ctx , state - > ldb , " <SID=%s> " , dom_sid_string ( tmp_ctx , alias ) ) ;
if ( ! dn | | ! ldb_dn_validate ( dn ) ) {
return NT_STATUS_NO_MEMORY ;
}
status = dsdb_enum_group_mem ( state - > ldb , mem_ctx , dn , pmembers , & num_members ) ;
* pnum_members = num_members ;
if ( NT_STATUS_IS_OK ( status ) ) {
talloc_steal ( mem_ctx , pmembers ) ;
}
talloc_free ( tmp_ctx ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_enum_alias_memberships ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
const struct dom_sid * domain_sid ,
const struct dom_sid * members ,
size_t num_members ,
uint32_t * * palias_rids ,
size_t * pnum_alias_rids )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
uint32_t * alias_rids = NULL ;
size_t num_alias_rids = 0 ;
int i ;
struct dom_sid * groupSIDs = NULL ;
unsigned int num_groupSIDs = 0 ;
char * filter ;
NTSTATUS status ;
const char * sid_string ;
const char * sid_dn ;
DATA_BLOB sid_blob ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
/*
* TODO : Get the filter right so that we only get the aliases from
* either the SAM or BUILTIN
*/
filter = talloc_asprintf ( tmp_ctx , " (&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u)) " ,
GROUP_TYPE_BUILTIN_LOCAL_GROUP ) ;
if ( filter = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < num_members ; i + + ) {
sid_string = dom_sid_string ( tmp_ctx , & members [ i ] ) ;
2014-02-13 08:51:11 +04:00
if ( sid_string = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-05-06 18:50:04 +04:00
sid_dn = talloc_asprintf ( tmp_ctx , " <SID=%s> " , sid_string ) ;
2014-02-13 08:51:11 +04:00
if ( sid_dn = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
sid_blob = data_blob_string_const ( sid_dn ) ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
status = dsdb_expand_nested_groups ( state - > ldb , & sid_blob , true , filter ,
tmp_ctx , & groupSIDs , & num_groupSIDs ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
}
alias_rids = talloc_array ( mem_ctx , uint32_t , num_groupSIDs ) ;
if ( alias_rids = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < num_groupSIDs ; i + + ) {
if ( sid_peek_check_rid ( domain_sid , & groupSIDs [ i ] ,
& alias_rids [ num_alias_rids ] ) ) {
num_alias_rids + + ; ;
}
}
* palias_rids = alias_rids ;
* pnum_alias_rids = num_alias_rids ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_lookup_rids ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * domain_sid ,
int num_rids ,
uint32 * rids ,
const char * * names ,
enum lsa_SidType * lsa_attrs )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
NTSTATUS status ;
TALLOC_CTX * tmp_ctx ;
if ( num_rids = = 0 ) {
return NT_STATUS_NONE_MAPPED ;
}
tmp_ctx = talloc_stackframe ( ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
status = dsdb_lookup_rids ( state - > ldb , tmp_ctx , domain_sid , num_rids , rids , names , lsa_attrs ) ;
talloc_free ( tmp_ctx ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_lookup_names ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const struct dom_sid * domain_sid ,
int num_names ,
const char * * pp_names ,
uint32 * rids ,
enum lsa_SidType * attrs )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_get_account_policy ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
enum pdb_policy_type type ,
uint32_t * value )
{
return account_policy_get ( type , value )
? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_set_account_policy ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
enum pdb_policy_type type ,
uint32_t value )
{
return account_policy_set ( type , value )
? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_get_seq_num ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
time_t * seq_num_out )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
uint64_t seq_num ;
int ret = ldb_sequence_number ( state - > ldb , LDB_SEQ_HIGHEST_SEQ , & seq_num ) ;
if ( ret = = LDB_SUCCESS ) {
* seq_num_out = seq_num ;
return NT_STATUS_OK ;
} else {
return NT_STATUS_UNSUCCESSFUL ;
}
}
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_search_state {
2011-05-06 18:50:04 +04:00
uint32_t acct_flags ;
struct samr_displayentry * entries ;
uint32_t num_entries ;
ssize_t array_size ;
uint32_t current ;
} ;
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_next_entry ( struct pdb_search * search ,
2011-05-06 18:50:04 +04:00
struct samr_displayentry * entry )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_search_state * state = talloc_get_type_abort (
search - > private_data , struct pdb_samba_dsdb_search_state ) ;
2011-05-06 18:50:04 +04:00
if ( state - > current = = state - > num_entries ) {
return false ;
}
entry - > idx = state - > entries [ state - > current ] . idx ;
entry - > rid = state - > entries [ state - > current ] . rid ;
entry - > acct_flags = state - > entries [ state - > current ] . acct_flags ;
entry - > account_name = talloc_strdup (
search , state - > entries [ state - > current ] . account_name ) ;
entry - > fullname = talloc_strdup (
search , state - > entries [ state - > current ] . fullname ) ;
entry - > description = talloc_strdup (
search , state - > entries [ state - > current ] . description ) ;
state - > current + = 1 ;
return true ;
}
2012-09-04 04:27:50 +04:00
static void pdb_samba_dsdb_search_end ( struct pdb_search * search )
2011-05-06 18:50:04 +04:00
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_search_state * state = talloc_get_type_abort (
search - > private_data , struct pdb_samba_dsdb_search_state ) ;
2011-05-06 18:50:04 +04:00
talloc_free ( state ) ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_search_filter ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct pdb_search * search ,
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_search_state * * pstate ,
2011-05-06 18:50:04 +04:00
const char * exp_fmt , . . . ) _PRINTF_ATTRIBUTE ( 4 , 5 )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
struct pdb_samba_dsdb_search_state * sstate ;
2011-05-06 18:50:04 +04:00
const char * attrs [ ] = { " objectSid " , " sAMAccountName " , " displayName " ,
" userAccountControl " , " description " , NULL } ;
struct ldb_result * res ;
int i , rc , num_users ;
va_list ap ;
char * expression = NULL ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
if ( ! tmp_ctx ) {
return false ;
}
va_start ( ap , exp_fmt ) ;
expression = talloc_vasprintf ( tmp_ctx , exp_fmt , ap ) ;
va_end ( ap ) ;
2012-09-04 04:27:50 +04:00
2011-05-06 18:50:04 +04:00
if ( ! expression ) {
talloc_free ( tmp_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2012-09-04 04:27:50 +04:00
sstate = talloc_zero ( tmp_ctx , struct pdb_samba_dsdb_search_state ) ;
2011-05-06 18:50:04 +04:00
if ( sstate = = NULL ) {
talloc_free ( tmp_ctx ) ;
return false ;
}
2011-08-19 11:27:14 +04:00
rc = dsdb_search ( state - > ldb , tmp_ctx , & res , ldb_get_default_basedn ( state - > ldb ) , LDB_SCOPE_SUBTREE , attrs , 0 , " %s " , expression ) ;
2011-05-06 18:50:04 +04:00
if ( rc ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
DEBUG ( 10 , ( " dsdb_search failed: %s \n " ,
ldb_errstring ( state - > ldb ) ) ) ;
return false ;
}
num_users = res - > count ;
sstate - > entries = talloc_array ( sstate , struct samr_displayentry ,
num_users ) ;
if ( sstate - > entries = = NULL ) {
talloc_free ( tmp_ctx ) ;
DEBUG ( 10 , ( " talloc failed \n " ) ) ;
return false ;
}
sstate - > num_entries = 0 ;
for ( i = 0 ; i < num_users ; i + + ) {
struct samr_displayentry * e ;
struct dom_sid * sid ;
e = & sstate - > entries [ sstate - > num_entries ] ;
e - > idx = sstate - > num_entries ;
sid = samdb_result_dom_sid ( tmp_ctx , res - > msgs [ i ] , " objectSid " ) ;
if ( ! sid ) {
talloc_free ( tmp_ctx ) ;
DEBUG ( 10 , ( " Could not pull SID \n " ) ) ;
return false ;
}
sid_peek_rid ( sid , & e - > rid ) ;
2012-09-04 04:27:50 +04:00
2013-10-29 08:30:18 +04:00
e - > acct_flags = samdb_result_acct_flags ( res - > msgs [ i ] , " userAccountControl " ) ;
2011-05-06 18:50:04 +04:00
e - > account_name = ldb_msg_find_attr_as_string (
res - > msgs [ i ] , " samAccountName " , NULL ) ;
if ( e - > account_name = = NULL ) {
talloc_free ( tmp_ctx ) ;
return false ;
}
e - > fullname = ldb_msg_find_attr_as_string (
res - > msgs [ i ] , " displayName " , " " ) ;
e - > description = ldb_msg_find_attr_as_string (
res - > msgs [ i ] , " description " , " " ) ;
sstate - > num_entries + = 1 ;
if ( sstate - > num_entries > = num_users ) {
break ;
}
}
talloc_steal ( sstate - > entries , res - > msgs ) ;
search - > private_data = talloc_steal ( search , sstate ) ;
2012-09-04 04:27:50 +04:00
search - > next_entry = pdb_samba_dsdb_next_entry ;
search - > search_end = pdb_samba_dsdb_search_end ;
2011-05-06 18:50:04 +04:00
* pstate = sstate ;
talloc_free ( tmp_ctx ) ;
return true ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_search_users ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct pdb_search * search ,
uint32 acct_flags )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_search_state * sstate ;
2011-05-06 18:50:04 +04:00
bool ret ;
2012-09-04 04:27:50 +04:00
ret = pdb_samba_dsdb_search_filter ( m , search , & sstate , " (objectclass=user) " ) ;
2011-05-06 18:50:04 +04:00
if ( ! ret ) {
return false ;
}
sstate - > acct_flags = acct_flags ;
return true ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_search_groups ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct pdb_search * search )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_search_state * sstate ;
2011-05-06 18:50:04 +04:00
bool ret ;
2012-09-04 04:27:50 +04:00
ret = pdb_samba_dsdb_search_filter ( m , search , & sstate ,
2011-05-06 18:50:04 +04:00
" (&(grouptype=%d)(objectclass=group)) " ,
GTYPE_SECURITY_GLOBAL_GROUP ) ;
if ( ! ret ) {
return false ;
}
sstate - > acct_flags = 0 ;
return true ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_search_aliases ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
struct pdb_search * search ,
const struct dom_sid * sid )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_search_state * sstate ;
2011-05-06 18:50:04 +04:00
bool ret ;
2012-09-04 04:27:50 +04:00
ret = pdb_samba_dsdb_search_filter ( m , search , & sstate ,
2011-05-06 18:50:04 +04:00
" (&(grouptype=%d)(objectclass=group)) " ,
sid_check_is_builtin ( sid )
? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
: GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
if ( ! ret ) {
return false ;
}
sstate - > acct_flags = 0 ;
return true ;
}
2014-11-25 04:45:26 +03:00
/*
* Instead of taking a gid or uid , this function takes a pointer to a
* unixid .
*
* This acts as an in - out variable so that the idmap functions can correctly
* receive ID_TYPE_BOTH , and this function ensures cache details are filled
* correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID .
*/
static bool pdb_samba_dsdb_id_to_sid ( struct pdb_methods * m , struct unixid * id ,
struct dom_sid * sid )
2011-05-06 18:50:04 +04:00
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
NTSTATUS status ;
struct id_map id_map ;
struct id_map * id_maps [ 2 ] ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
if ( ! tmp_ctx ) {
return false ;
}
2014-11-25 04:45:26 +03:00
id_map . xid = * id ;
2011-05-06 18:50:04 +04:00
id_maps [ 0 ] = & id_map ;
id_maps [ 1 ] = NULL ;
status = idmap_xids_to_sids ( state - > idmap_ctx , tmp_ctx , id_maps ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return false ;
}
2014-11-25 04:45:26 +03:00
if ( id_map . xid . type ! = ID_TYPE_NOT_SPECIFIED ) {
id - > type = id_map . xid . type ;
2011-05-06 18:50:04 +04:00
}
* sid = * id_map . sid ;
talloc_free ( tmp_ctx ) ;
return true ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_sid_to_id ( struct pdb_methods * m , const struct dom_sid * sid ,
2012-03-16 02:16:23 +04:00
struct unixid * id )
2011-05-06 18:50:04 +04:00
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
struct id_map id_map ;
struct id_map * id_maps [ 2 ] ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
if ( ! tmp_ctx ) {
return false ;
}
ZERO_STRUCT ( id_map ) ;
2013-05-27 15:33:24 +04:00
id_map . sid = discard_const_p ( struct dom_sid , sid ) ;
2012-08-07 08:17:09 +04:00
id_maps [ 0 ] = & id_map ;
id_maps [ 1 ] = NULL ;
2011-05-06 18:50:04 +04:00
2012-08-07 08:17:09 +04:00
status = idmap_sids_to_xids ( state - > idmap_ctx , tmp_ctx , id_maps ) ;
talloc_free ( tmp_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-05-06 18:50:04 +04:00
return false ;
}
2012-08-07 08:17:09 +04:00
if ( id_map . xid . type ! = ID_TYPE_NOT_SPECIFIED ) {
* id = id_map . xid ;
return true ;
2011-05-06 18:50:04 +04:00
}
return false ;
}
2012-09-04 04:27:50 +04:00
static uint32_t pdb_samba_dsdb_capabilities ( struct pdb_methods * m )
2011-05-06 18:50:04 +04:00
{
return PDB_CAP_STORE_RIDS | PDB_CAP_ADS ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_new_rid ( struct pdb_methods * m , uint32 * rid )
2011-05-06 18:50:04 +04:00
{
return false ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_get_trusteddom_pw ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const char * domain , char * * pwd ,
struct dom_sid * sid ,
time_t * pass_last_set_time )
{
2014-08-15 07:01:31 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
const char * const attrs [ ] = {
" securityIdentifier " ,
2014-12-16 18:06:56 +03:00
" flatName " ,
2014-08-15 07:01:31 +04:00
" trustPartner " ,
" trustAuthOutgoing " ,
" whenCreated " ,
" msDS-SupportedEncryptionTypes " ,
" trustAttributes " ,
" trustDirection " ,
" trustType " ,
NULL
} ;
struct ldb_message * msg ;
const struct ldb_val * password_val ;
int trust_direction_flags ;
int trust_type ;
int i ;
DATA_BLOB password_utf16 ;
struct trustAuthInOutBlob password_blob ;
struct AuthenticationInformationArray * auth_array ;
char * password_talloc ;
size_t password_len ;
enum ndr_err_code ndr_err ;
NTSTATUS status ;
2014-12-16 18:06:56 +03:00
const char * netbios_domain = NULL ;
2014-08-15 07:01:31 +04:00
status = sam_get_results_trust ( state - > ldb , tmp_ctx , domain ,
NULL , attrs , & msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/*
* This can be called to work out of a domain is
* trusted , rather than just to get the password
*/
DEBUG ( 2 , ( " Failed to get trusted domain password for %s. "
" It may not be a trusted domain. \n " , domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
2014-12-16 18:06:56 +03:00
netbios_domain = ldb_msg_find_attr_as_string ( msg , " flatName " , NULL ) ;
if ( netbios_domain = = NULL ) {
DEBUG ( 2 , ( " Trusted domain %s has to flatName defined. \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
2014-08-15 07:01:31 +04:00
trust_direction_flags = ldb_msg_find_attr_as_int ( msg , " trustDirection " , 0 ) ;
if ( ! ( trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND ) ) {
DEBUG ( 2 , ( " Trusted domain %s is is not an outbound trust. \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
trust_type = ldb_msg_find_attr_as_int ( msg , " trustType " , 0 ) ;
if ( trust_type = = LSA_TRUST_TYPE_MIT ) {
DEBUG ( 1 , ( " Trusted domain %s is is not an AD trust "
" (trustType == LSA_TRUST_TYPE_MIT). \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
password_val = ldb_msg_find_ldb_val ( msg , " trustAuthOutgoing " ) ;
if ( password_val = = NULL ) {
DEBUG ( 2 , ( " Failed to get trusted domain password for %s, "
" attribute trustAuthOutgoing not returned. \n " , domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
ndr_err = ndr_pull_struct_blob ( password_val , tmp_ctx , & password_blob ,
( ndr_pull_flags_fn_t ) ndr_pull_trustAuthInOutBlob ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " Failed to get trusted domain password for %s, "
" attribute trustAuthOutgoing coult not be parsed %s. \n " ,
domain ,
ndr_map_error2string ( ndr_err ) ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
auth_array = & password_blob . current ;
for ( i = 0 ; i < auth_array - > count ; i + + ) {
if ( auth_array - > array [ i ] . AuthType = = TRUST_AUTH_TYPE_CLEAR ) {
break ;
}
}
if ( i = = auth_array - > count ) {
DEBUG ( 0 , ( " Trusted domain %s does not have a "
" clear-text password stored \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
password_utf16 = data_blob_const ( auth_array - > array [ i ] . AuthInfo . clear . password ,
auth_array - > array [ i ] . AuthInfo . clear . size ) ;
/*
* In the future , make this function return a
* cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash ( )
* but for now convert to UTF8 and fail if the string can not be converted .
*
* We can ' t safely convert the random strings windows uses into
* utf8 .
*/
if ( ! convert_string_talloc ( tmp_ctx ,
2014-12-16 18:06:56 +03:00
CH_UTF16MUNGED , CH_UTF8 ,
2014-08-15 07:01:31 +04:00
password_utf16 . data , password_utf16 . length ,
( void * ) & password_talloc ,
& password_len ) ) {
DEBUG ( 0 , ( " FIXME: Could not convert password for trusted domain %s "
" to UTF8. This may be a password set from Windows. \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return false ;
}
* pwd = SMB_STRNDUP ( password_talloc , password_len ) ;
if ( pass_last_set_time ) {
* pass_last_set_time = nt_time_to_unix ( auth_array - > array [ i ] . LastUpdateTime ) ;
}
TALLOC_FREE ( tmp_ctx ) ;
return true ;
2011-05-06 18:50:04 +04:00
}
2014-12-16 18:06:56 +03:00
static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds ( struct pdb_methods * m ,
const char * domain ,
TALLOC_CTX * mem_ctx ,
struct cli_credentials * * _creds )
{
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
m - > private_data , struct pdb_samba_dsdb_state ) ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
const char * const attrs [ ] = {
" securityIdentifier " ,
" flatName " ,
" trustPartner " ,
" trustAuthOutgoing " ,
" whenCreated " ,
" msDS-SupportedEncryptionTypes " ,
" trustAttributes " ,
" trustDirection " ,
" trustType " ,
NULL
} ;
struct ldb_message * msg ;
const struct ldb_val * password_val ;
int trust_direction_flags ;
int trust_type ;
int i ;
DATA_BLOB password_utf16 = { } ;
DATA_BLOB password_nt = { } ;
struct trustAuthInOutBlob password_blob ;
struct AuthenticationInformationArray * auth_array = NULL ;
enum ndr_err_code ndr_err ;
NTSTATUS status ;
time_t last_set_time = 0 ;
struct cli_credentials * creds = NULL ;
bool ok ;
const char * my_netbios_name = NULL ;
const char * my_netbios_domain = NULL ;
2014-12-16 18:57:49 +03:00
const char * my_dns_domain = NULL ;
2014-12-16 18:06:56 +03:00
const char * netbios_domain = NULL ;
char * account_name = NULL ;
2014-12-16 18:57:49 +03:00
char * principal_name = NULL ;
2014-12-16 18:06:56 +03:00
const char * dns_domain = NULL ;
status = sam_get_results_trust ( state - > ldb , tmp_ctx , domain ,
NULL , attrs , & msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/*
* This can be called to work out of a domain is
* trusted , rather than just to get the password
*/
DEBUG ( 2 , ( " Failed to get trusted domain password for %s. "
" It may not be a trusted domain. \n " , domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return status ;
}
netbios_domain = ldb_msg_find_attr_as_string ( msg , " flatName " , NULL ) ;
if ( netbios_domain = = NULL ) {
DEBUG ( 2 , ( " Trusted domain %s has to flatName defined. \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
dns_domain = ldb_msg_find_attr_as_string ( msg , " trustPartner " , NULL ) ;
trust_direction_flags = ldb_msg_find_attr_as_int ( msg , " trustDirection " , 0 ) ;
if ( ! ( trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND ) ) {
DEBUG ( 2 , ( " Trusted domain %s is is not an outbound trust. \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
trust_type = ldb_msg_find_attr_as_int ( msg , " trustType " , 0 ) ;
if ( trust_type = = LSA_TRUST_TYPE_MIT ) {
DEBUG ( 1 , ( " Trusted domain %s is is not an AD trust "
" (trustType == LSA_TRUST_TYPE_MIT). \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
password_val = ldb_msg_find_ldb_val ( msg , " trustAuthOutgoing " ) ;
if ( password_val = = NULL ) {
DEBUG ( 2 , ( " Failed to get trusted domain password for %s, "
" attribute trustAuthOutgoing not returned. \n " , domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
ndr_err = ndr_pull_struct_blob ( password_val , tmp_ctx , & password_blob ,
( ndr_pull_flags_fn_t ) ndr_pull_trustAuthInOutBlob ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " Failed to get trusted domain password for %s, "
" attribute trustAuthOutgoing coult not be parsed %s. \n " ,
domain ,
ndr_map_error2string ( ndr_err ) ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
auth_array = & password_blob . current ;
for ( i = 0 ; i < auth_array - > count ; i + + ) {
if ( auth_array - > array [ i ] . AuthType = = TRUST_AUTH_TYPE_CLEAR ) {
last_set_time = nt_time_to_unix ( auth_array - > array [ i ] . LastUpdateTime ) ;
password_utf16 = data_blob_const ( auth_array - > array [ i ] . AuthInfo . clear . password ,
auth_array - > array [ i ] . AuthInfo . clear . size ) ;
password_nt = data_blob_null ;
break ;
}
if ( auth_array - > array [ i ] . AuthType = = TRUST_AUTH_TYPE_NT4OWF ) {
last_set_time = nt_time_to_unix ( auth_array - > array [ i ] . LastUpdateTime ) ;
password_nt = data_blob_const ( auth_array - > array [ i ] . AuthInfo . clear . password ,
auth_array - > array [ i ] . AuthInfo . clear . size ) ;
}
}
if ( password_utf16 . length = = 0 & & password_nt . length = = 0 ) {
DEBUG ( 0 , ( " Trusted domain %s does not have a "
" clear-text nor nt password stored \n " ,
domain ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
my_netbios_name = lpcfg_netbios_name ( state - > lp_ctx ) ;
my_netbios_domain = lpcfg_workgroup ( state - > lp_ctx ) ;
2014-12-16 18:57:49 +03:00
my_dns_domain = lpcfg_dnsdomain ( state - > lp_ctx ) ;
2014-12-16 18:06:56 +03:00
creds = cli_credentials_init ( tmp_ctx ) ;
if ( creds = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
ok = cli_credentials_set_workstation ( creds , my_netbios_name , CRED_SPECIFIED ) ;
if ( ! ok ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
ok = cli_credentials_set_domain ( creds , netbios_domain , CRED_SPECIFIED ) ;
if ( ! ok ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
ok = cli_credentials_set_realm ( creds , dns_domain , CRED_SPECIFIED ) ;
if ( ! ok ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2014-12-16 18:57:49 +03:00
if ( my_dns_domain ! = NULL & & dns_domain ! = NULL ) {
cli_credentials_set_secure_channel_type ( creds , SEC_CHAN_DNS_DOMAIN ) ;
account_name = talloc_asprintf ( tmp_ctx , " %s. " , my_dns_domain ) ;
if ( account_name = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
principal_name = talloc_asprintf ( tmp_ctx , " %s$@%s " , my_netbios_domain ,
cli_credentials_get_realm ( creds ) ) ;
if ( principal_name = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
} else {
cli_credentials_set_secure_channel_type ( creds , SEC_CHAN_DOMAIN ) ;
account_name = talloc_asprintf ( tmp_ctx , " %s$ " , my_netbios_domain ) ;
if ( account_name = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
principal_name = NULL ;
2014-12-16 18:06:56 +03:00
}
ok = cli_credentials_set_username ( creds , account_name , CRED_SPECIFIED ) ;
if ( ! ok ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2014-12-16 18:57:49 +03:00
if ( principal_name ! = NULL ) {
ok = cli_credentials_set_principal ( creds , principal_name ,
CRED_SPECIFIED ) ;
if ( ! ok ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
}
2014-12-16 18:06:56 +03:00
if ( password_nt . length = = 16 ) {
struct samr_Password nt_hash ;
memcpy ( nt_hash . hash , password_nt . data , 16 ) ;
ok = cli_credentials_set_nt_hash ( creds , & nt_hash ,
CRED_SPECIFIED ) ;
ZERO_STRUCT ( nt_hash ) ;
if ( ! ok ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
}
if ( password_utf16 . length > 0 ) {
ok = cli_credentials_set_utf16_password ( creds ,
& password_utf16 ,
CRED_SPECIFIED ) ;
if ( ! ok ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
}
cli_credentials_set_password_last_changed_time ( creds , last_set_time ) ;
if ( password_utf16 . length > 0 & & dns_domain ! = NULL ) {
/*
* Force kerberos if this is an active directory domain
*/
cli_credentials_set_kerberos_state ( creds ,
CRED_MUST_USE_KERBEROS ) ;
} else {
/*
* TODO : we should allow krb5 with the raw nt hash .
*/
cli_credentials_set_kerberos_state ( creds ,
CRED_DONT_USE_KERBEROS ) ;
}
* _creds = talloc_move ( mem_ctx , & creds ) ;
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_set_trusteddom_pw ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const char * domain , const char * pwd ,
const struct dom_sid * sid )
{
return false ;
}
2012-09-04 04:27:50 +04:00
static bool pdb_samba_dsdb_del_trusteddom_pw ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
const char * domain )
{
return false ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_enum_trusteddoms ( struct pdb_methods * m ,
2011-05-06 18:50:04 +04:00
TALLOC_CTX * mem_ctx ,
uint32 * num_domains ,
struct trustdom_info * * * domains )
{
* num_domains = 0 ;
* domains = NULL ;
return NT_STATUS_OK ;
}
2013-06-18 12:43:38 +04:00
static bool pdb_samba_dsdb_is_responsible_for_wellknown ( struct pdb_methods * m )
{
return true ;
}
2014-03-28 06:36:22 +04:00
static bool pdb_samba_dsdb_is_responsible_for_everything_else ( struct pdb_methods * m )
{
return true ;
}
2012-09-04 04:27:50 +04:00
static void pdb_samba_dsdb_init_methods ( struct pdb_methods * m )
{
m - > name = " samba_dsdb " ;
m - > get_domain_info = pdb_samba_dsdb_get_domain_info ;
m - > getsampwnam = pdb_samba_dsdb_getsampwnam ;
m - > getsampwsid = pdb_samba_dsdb_getsampwsid ;
m - > create_user = pdb_samba_dsdb_create_user ;
m - > delete_user = pdb_samba_dsdb_delete_user ;
m - > add_sam_account = pdb_samba_dsdb_add_sam_account ;
m - > update_sam_account = pdb_samba_dsdb_update_sam_account ;
m - > delete_sam_account = pdb_samba_dsdb_delete_sam_account ;
m - > rename_sam_account = pdb_samba_dsdb_rename_sam_account ;
m - > update_login_attempts = pdb_samba_dsdb_update_login_attempts ;
m - > getgrsid = pdb_samba_dsdb_getgrsid ;
m - > getgrgid = pdb_samba_dsdb_getgrgid ;
m - > getgrnam = pdb_samba_dsdb_getgrnam ;
m - > create_dom_group = pdb_samba_dsdb_create_dom_group ;
m - > delete_dom_group = pdb_samba_dsdb_delete_dom_group ;
m - > add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry ;
m - > update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry ;
m - > delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry ;
m - > enum_group_mapping = pdb_samba_dsdb_enum_group_mapping ;
m - > enum_group_members = pdb_samba_dsdb_enum_group_members ;
m - > enum_group_memberships = pdb_samba_dsdb_enum_group_memberships ;
m - > set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group ;
m - > add_groupmem = pdb_samba_dsdb_add_groupmem ;
m - > del_groupmem = pdb_samba_dsdb_del_groupmem ;
m - > create_alias = pdb_samba_dsdb_create_alias ;
m - > delete_alias = pdb_samba_dsdb_delete_alias ;
2011-05-06 18:50:04 +04:00
m - > get_aliasinfo = pdb_default_get_aliasinfo ;
2012-09-04 04:27:50 +04:00
m - > add_aliasmem = pdb_samba_dsdb_add_aliasmem ;
m - > del_aliasmem = pdb_samba_dsdb_del_aliasmem ;
m - > enum_aliasmem = pdb_samba_dsdb_enum_aliasmem ;
m - > enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships ;
m - > lookup_rids = pdb_samba_dsdb_lookup_rids ;
m - > lookup_names = pdb_samba_dsdb_lookup_names ;
m - > get_account_policy = pdb_samba_dsdb_get_account_policy ;
m - > set_account_policy = pdb_samba_dsdb_set_account_policy ;
m - > get_seq_num = pdb_samba_dsdb_get_seq_num ;
m - > search_users = pdb_samba_dsdb_search_users ;
m - > search_groups = pdb_samba_dsdb_search_groups ;
m - > search_aliases = pdb_samba_dsdb_search_aliases ;
2014-11-25 04:45:26 +03:00
m - > id_to_sid = pdb_samba_dsdb_id_to_sid ;
2012-09-04 04:27:50 +04:00
m - > sid_to_id = pdb_samba_dsdb_sid_to_id ;
m - > capabilities = pdb_samba_dsdb_capabilities ;
m - > new_rid = pdb_samba_dsdb_new_rid ;
m - > get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw ;
2014-12-16 18:06:56 +03:00
m - > get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds ;
2012-09-04 04:27:50 +04:00
m - > set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw ;
m - > del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw ;
m - > enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms ;
2013-06-18 12:43:38 +04:00
m - > is_responsible_for_wellknown =
pdb_samba_dsdb_is_responsible_for_wellknown ;
2014-03-28 06:36:22 +04:00
m - > is_responsible_for_everything_else =
pdb_samba_dsdb_is_responsible_for_everything_else ;
2011-05-06 18:50:04 +04:00
}
static void free_private_data ( void * * vp )
{
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state = talloc_get_type_abort (
* vp , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
talloc_unlink ( state , state - > ldb ) ;
return ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_samba_dsdb_init_secrets ( struct pdb_methods * m )
2012-01-27 00:33:02 +04:00
{
struct pdb_domain_info * dom_info ;
2014-05-13 09:47:03 +04:00
struct dom_sid stored_sid ;
struct GUID stored_guid ;
bool sid_exists_and_matches = false ;
bool guid_exists_and_matches = false ;
2012-01-27 00:33:02 +04:00
bool ret ;
2012-09-04 04:27:50 +04:00
dom_info = pdb_samba_dsdb_get_domain_info ( m , m ) ;
2012-01-27 00:33:02 +04:00
if ( ! dom_info ) {
return NT_STATUS_UNSUCCESSFUL ;
}
2014-05-13 09:47:03 +04:00
ret = secrets_fetch_domain_sid ( dom_info - > name , & stored_sid ) ;
if ( ret ) {
if ( dom_sid_equal ( & stored_sid , & dom_info - > sid ) ) {
sid_exists_and_matches = true ;
}
2012-01-27 00:33:02 +04:00
}
2014-05-13 09:47:03 +04:00
if ( sid_exists_and_matches = = false ) {
secrets_clear_domain_protection ( dom_info - > name ) ;
ret = secrets_store_domain_sid ( dom_info - > name ,
& dom_info - > sid ) ;
ret & = secrets_mark_domain_protected ( dom_info - > name ) ;
if ( ! ret ) {
goto done ;
}
2012-01-27 00:33:02 +04:00
}
2014-05-13 09:47:03 +04:00
ret = secrets_fetch_domain_guid ( dom_info - > name , & stored_guid ) ;
if ( ret ) {
if ( GUID_equal ( & stored_guid , & dom_info - > guid ) ) {
guid_exists_and_matches = true ;
}
}
if ( guid_exists_and_matches = = false ) {
secrets_clear_domain_protection ( dom_info - > name ) ;
ret = secrets_store_domain_guid ( dom_info - > name ,
& dom_info - > guid ) ;
ret & = secrets_mark_domain_protected ( dom_info - > name ) ;
if ( ! ret ) {
goto done ;
}
2012-01-27 00:33:02 +04:00
}
done :
TALLOC_FREE ( dom_info ) ;
if ( ! ret ) {
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
}
2012-09-04 04:27:50 +04:00
static NTSTATUS pdb_init_samba_dsdb ( struct pdb_methods * * pdb_method ,
2011-05-06 18:50:04 +04:00
const char * location )
{
struct pdb_methods * m ;
2012-09-04 04:27:50 +04:00
struct pdb_samba_dsdb_state * state ;
2011-05-06 18:50:04 +04:00
NTSTATUS status ;
if ( ! NT_STATUS_IS_OK ( status = make_pdb_method ( & m ) ) ) {
return status ;
}
2012-09-04 04:27:50 +04:00
state = talloc_zero ( m , struct pdb_samba_dsdb_state ) ;
2011-05-06 18:50:04 +04:00
if ( state = = NULL ) {
goto nomem ;
}
m - > private_data = state ;
m - > free_private_data = free_private_data ;
2012-09-04 04:27:50 +04:00
pdb_samba_dsdb_init_methods ( m ) ;
2011-05-06 18:50:04 +04:00
state - > ev = s4_event_context_init ( state ) ;
if ( ! state - > ev ) {
2011-08-12 09:44:39 +04:00
DEBUG ( 0 , ( " s4_event_context_init failed \n " ) ) ;
goto nomem ;
2011-05-06 18:50:04 +04:00
}
2012-06-27 17:24:39 +04:00
state - > lp_ctx = loadparm_init_s3 ( state , loadparm_s3_helpers ( ) ) ;
2011-05-06 18:50:04 +04:00
if ( state - > lp_ctx = = NULL ) {
2011-08-12 09:44:39 +04:00
DEBUG ( 0 , ( " loadparm_init_s3 failed \n " ) ) ;
goto nomem ;
2011-05-06 18:50:04 +04:00
}
2011-08-12 09:45:43 +04:00
if ( location ) {
state - > ldb = samdb_connect_url ( state ,
state - > ev ,
state - > lp_ctx ,
system_session ( state - > lp_ctx ) ,
0 , location ) ;
} else {
state - > ldb = samdb_connect ( state ,
2011-05-06 18:50:04 +04:00
state - > ev ,
state - > lp_ctx ,
system_session ( state - > lp_ctx ) , 0 ) ;
2011-08-12 09:45:43 +04:00
}
2011-05-06 18:50:04 +04:00
if ( ! state - > ldb ) {
2011-08-12 09:44:39 +04:00
DEBUG ( 0 , ( " samdb_connect failed \n " ) ) ;
status = NT_STATUS_INTERNAL_ERROR ;
2011-05-06 18:50:04 +04:00
goto fail ;
}
state - > idmap_ctx = idmap_init ( state , state - > ev ,
state - > lp_ctx ) ;
if ( ! state - > idmap_ctx ) {
2011-08-12 09:44:39 +04:00
DEBUG ( 0 , ( " idmap failed \n " ) ) ;
status = NT_STATUS_INTERNAL_ERROR ;
2011-05-06 18:50:04 +04:00
goto fail ;
}
2012-09-04 04:27:50 +04:00
status = pdb_samba_dsdb_init_secrets ( m ) ;
2012-01-27 00:33:02 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-09-04 04:27:50 +04:00
DEBUG ( 10 , ( " pdb_samba_dsdb_init_secrets failed! \n " ) ) ;
2012-01-27 00:33:02 +04:00
goto fail ;
}
2011-05-06 18:50:04 +04:00
* pdb_method = m ;
return NT_STATUS_OK ;
nomem :
status = NT_STATUS_NO_MEMORY ;
fail :
TALLOC_FREE ( m ) ;
return status ;
}
2012-09-04 04:27:50 +04:00
NTSTATUS pdb_samba_dsdb_init ( void ) ;
NTSTATUS pdb_samba_dsdb_init ( void )
2011-05-06 18:50:04 +04:00
{
2012-09-04 04:27:50 +04:00
NTSTATUS status = smb_register_passdb ( PASSDB_INTERFACE_VERSION , " samba_dsdb " ,
pdb_init_samba_dsdb ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-05-06 18:50:04 +04:00
return smb_register_passdb ( PASSDB_INTERFACE_VERSION , " samba4 " ,
2012-09-04 04:27:50 +04:00
pdb_init_samba_dsdb ) ;
2011-05-06 18:50:04 +04:00
}