2005-07-25 10:33:51 +04:00
/*
Unix SMB / CIFS implementation .
Extract the user / system database from a remote SamSync server
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2005
Copyright ( C ) Andrew Tridgell 2004
2005-07-27 04:23:09 +04:00
Copyright ( C ) Volker Lendecke 2004
2005-07-25 10:33:51 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-07-25 10:33:51 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-07-25 10:33:51 +04:00
*/
# include "includes.h"
# include "libnet/libnet.h"
2005-12-28 18:38:36 +03:00
# include "libcli/ldap/ldap.h"
# include "dsdb/samdb/samdb.h"
# include "auth/auth.h"
2006-01-14 04:29:38 +03:00
# include "librpc/gen_ndr/ndr_misc.h"
2006-03-07 14:07:23 +03:00
# include "db_wrap.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2006-03-18 18:42:57 +03:00
# include "librpc/rpc/dcerpc.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2005-07-25 10:33:51 +04:00
struct samsync_ldb_secret {
struct samsync_ldb_secret * prev , * next ;
DATA_BLOB secret ;
char * name ;
NTTIME mtime ;
} ;
struct samsync_ldb_trusted_domain {
struct samsync_ldb_trusted_domain * prev , * next ;
struct dom_sid * sid ;
char * name ;
} ;
struct samsync_ldb_state {
2006-01-13 15:52:56 +03:00
/* Values from the LSA lookup */
2006-01-14 04:29:38 +03:00
const struct libnet_SamSync_state * samsync_state ;
2006-01-13 15:52:56 +03:00
2005-07-25 10:33:51 +04:00
struct dom_sid * dom_sid [ 3 ] ;
2006-01-13 15:52:56 +03:00
struct ldb_context * sam_ldb , * remote_ldb ;
2005-08-18 19:02:01 +04:00
struct ldb_dn * base_dn [ 3 ] ;
2005-07-25 10:33:51 +04:00
struct samsync_ldb_secret * secrets ;
struct samsync_ldb_trusted_domain * trusted_domains ;
} ;
2005-07-27 04:23:09 +04:00
static NTSTATUS samsync_ldb_add_foreignSecurityPrincipal ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
struct dom_sid * sid ,
2006-01-13 07:30:18 +03:00
struct ldb_dn * * fsp_dn ,
char * * error_string )
2005-07-27 04:23:09 +04:00
{
const char * sidstr = dom_sid_string ( mem_ctx , sid ) ;
/* We assume that ForeignSecurityPrincipals are under the BASEDN of the main domain */
2005-08-26 20:12:25 +04:00
struct ldb_dn * basedn = samdb_search_dn ( state - > sam_ldb , mem_ctx ,
state - > base_dn [ SAM_DATABASE_DOMAIN ] ,
" (&(objectClass=container)(cn=ForeignSecurityPrincipals)) " ) ;
2005-07-27 04:23:09 +04:00
struct ldb_message * msg ;
int ret ;
if ( ! sidstr ) {
return NT_STATUS_NO_MEMORY ;
}
if ( basedn = = NULL ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx ,
" Failed to find DN for "
" ForeignSecurityPrincipal container under %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( state - > base_dn [ SAM_DATABASE_DOMAIN ] ) ) ;
2005-07-27 04:23:09 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* add core elements to the ldb_message for the alias */
2006-11-22 03:59:34 +03:00
msg - > dn = basedn ;
if ( ! ldb_dn_add_child_fmt ( msg - > dn , " CN=%s " , sidstr ) )
return NT_STATUS_UNSUCCESSFUL ;
2005-07-27 04:23:09 +04:00
samdb_msg_add_string ( state - > sam_ldb , mem_ctx , msg ,
" objectClass " ,
" foreignSecurityPrincipal " ) ;
* fsp_dn = msg - > dn ;
/* create the alias */
ret = samdb_add ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to create foreignSecurityPrincipal "
" record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-27 04:23:09 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
return NT_STATUS_OK ;
}
2005-07-25 10:33:51 +04:00
static NTSTATUS samsync_ldb_handle_domain ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
2006-01-13 07:30:18 +03:00
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-25 10:33:51 +04:00
{
struct netr_DELTA_DOMAIN * domain = delta - > delta_union . domain ;
const char * domain_name = domain - > domain_name . string ;
struct ldb_message * msg ;
int ret ;
2006-01-14 04:29:38 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-07-25 10:33:51 +04:00
if ( database = = SAM_DATABASE_DOMAIN ) {
2006-11-22 03:59:34 +03:00
struct ldb_dn * partitions_basedn ;
2005-07-25 10:33:51 +04:00
const char * domain_attrs [ ] = { " nETBIOSName " , " nCName " , NULL } ;
struct ldb_message * * msgs_domain ;
int ret_domain ;
2005-08-26 15:36:28 +04:00
2006-10-16 05:19:01 +04:00
partitions_basedn = samdb_partitions_dn ( state - > sam_ldb , mem_ctx ) ;
ret_domain = gendb_search ( state - > sam_ldb , mem_ctx , partitions_basedn , & msgs_domain , domain_attrs ,
2005-07-25 10:33:51 +04:00
" (&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*)) " ,
domain_name ) ;
if ( ret_domain = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search for domain failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-25 10:33:51 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( ret_domain ! = 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to find existing domain record for %s: %d results " , domain_name ,
ret_domain ) ;
2005-07-25 10:33:51 +04:00
return NT_STATUS_NO_SUCH_DOMAIN ;
}
2006-11-22 03:59:34 +03:00
state - > base_dn [ database ] = samdb_result_dn ( state - > sam_ldb , state , msgs_domain [ 0 ] , " nCName " , NULL ) ;
2005-08-26 15:36:28 +04:00
2006-01-14 04:29:38 +03:00
if ( state - > dom_sid [ database ] ) {
/* Update the domain sid with the incoming
* domain ( found on LSA pipe , database sid may
* be random ) */
samdb_msg_add_dom_sid ( state - > sam_ldb , mem_ctx ,
msg , " objectSid " , state - > dom_sid [ database ] ) ;
2006-01-13 15:52:56 +03:00
} else {
2006-01-14 04:29:38 +03:00
/* Well, we will have to use the one from the database */
2006-01-13 15:52:56 +03:00
state - > dom_sid [ database ] = samdb_search_dom_sid ( state - > sam_ldb , state ,
state - > base_dn [ database ] ,
" objectSid " , NULL ) ;
}
2006-01-14 04:29:38 +03:00
if ( state - > samsync_state - > domain_guid ) {
NTSTATUS nt_status ;
struct ldb_val v ;
nt_status = ndr_push_struct_blob ( & v , msg , state - > samsync_state - > domain_guid ,
( ndr_push_flags_fn_t ) ndr_push_GUID ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
* error_string = talloc_asprintf ( mem_ctx , " ndr_push of domain GUID failed! " ) ;
return nt_status ;
}
2006-10-25 05:42:59 +04:00
ldb_msg_add_value ( msg , " objectGUID " , & v , NULL ) ;
2006-01-14 04:29:38 +03:00
}
2005-07-25 10:33:51 +04:00
} else if ( database = = SAM_DATABASE_BUILTIN ) {
2005-08-26 15:36:28 +04:00
/* work out the builtin_dn - useful for so many calls its worth
fetching here */
const char * dnstring = samdb_search_string ( state - > sam_ldb , mem_ctx , NULL ,
2005-10-11 15:00:16 +04:00
" distinguishedName " , " objectClass=builtinDomain " ) ;
2006-11-22 03:59:34 +03:00
state - > base_dn [ database ] = ldb_dn_new ( state , state - > sam_ldb , dnstring ) ;
if ( ! ldb_dn_validate ( state - > base_dn [ database ] ) ) {
return NT_STATUS_INTERNAL_ERROR ;
}
2005-07-25 10:33:51 +04:00
} else {
/* PRIVs DB */
return NT_STATUS_INVALID_PARAMETER ;
}
msg - > dn = talloc_reference ( mem_ctx , state - > base_dn [ database ] ) ;
if ( ! msg - > dn ) {
return NT_STATUS_NO_MEMORY ;
}
samdb_msg_add_string ( state - > sam_ldb , mem_ctx ,
msg , " oEMInformation " , domain - > comment . string ) ;
2005-08-03 09:24:13 +04:00
samdb_msg_add_int64 ( state - > sam_ldb , mem_ctx ,
2006-01-13 07:30:18 +03:00
msg , " forceLogoff " , domain - > force_logoff_time ) ;
2005-07-25 10:33:51 +04:00
samdb_msg_add_uint ( state - > sam_ldb , mem_ctx ,
2006-01-13 07:30:18 +03:00
msg , " minPwdLen " , domain - > min_password_length ) ;
2005-07-25 10:33:51 +04:00
samdb_msg_add_int64 ( state - > sam_ldb , mem_ctx ,
2006-01-13 07:30:18 +03:00
msg , " maxPwdAge " , domain - > max_password_age ) ;
2005-07-25 10:33:51 +04:00
samdb_msg_add_int64 ( state - > sam_ldb , mem_ctx ,
2006-01-13 07:30:18 +03:00
msg , " minPwdAge " , domain - > min_password_age ) ;
2005-07-25 10:33:51 +04:00
samdb_msg_add_uint ( state - > sam_ldb , mem_ctx ,
2006-01-13 07:30:18 +03:00
msg , " pwdHistoryLength " , domain - > password_history_length ) ;
2005-07-25 10:33:51 +04:00
samdb_msg_add_uint64 ( state - > sam_ldb , mem_ctx ,
2005-08-03 09:24:13 +04:00
msg , " modifiedCount " ,
2005-07-25 10:33:51 +04:00
domain - > sequence_num ) ;
samdb_msg_add_uint64 ( state - > sam_ldb , mem_ctx ,
msg , " creationTime " , domain - > domain_create_time ) ;
/* TODO: Account lockout, password properties */
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ) {
return NT_STATUS_INTERNAL_ERROR ;
}
return NT_STATUS_OK ;
}
static NTSTATUS samsync_ldb_handle_user ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
2006-01-13 07:30:18 +03:00
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-25 10:33:51 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct netr_DELTA_USER * user = delta - > delta_union . user ;
const char * container , * obj_class ;
char * cn_name ;
int cn_name_len ;
2006-01-13 15:52:56 +03:00
const struct dom_sid * user_sid ;
2005-07-25 10:33:51 +04:00
struct ldb_message * msg ;
struct ldb_message * * msgs ;
2006-04-08 07:00:12 +04:00
struct ldb_message * * remote_msgs = NULL ;
2006-01-13 15:52:56 +03:00
int ret , i ;
2005-07-25 10:33:51 +04:00
uint32_t acb ;
BOOL add = False ;
const char * attrs [ ] = { NULL } ;
2006-01-13 15:52:56 +03:00
/* we may change this to a global search, then fill in only the things not in ldap later */
const char * remote_attrs [ ] = { " userPrincipalName " , " servicePrincipalName " ,
2006-01-14 04:29:38 +03:00
" msDS-KeyVersionNumber " , " objectGUID " , NULL } ;
2006-01-13 15:52:56 +03:00
user_sid = dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ;
if ( ! user_sid ) {
return NT_STATUS_NO_MEMORY ;
}
2005-07-25 10:33:51 +04:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2006-01-14 04:29:38 +03:00
msg - > dn = NULL ;
2005-07-25 10:33:51 +04:00
/* search for the user, by rid */
2005-08-18 19:02:01 +04:00
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] ,
& msgs , attrs , " (&(objectClass=user)(objectSid=%s)) " ,
2006-01-13 15:52:56 +03:00
ldap_encode_ndr_dom_sid ( mem_ctx , user_sid ) ) ;
2005-07-25 10:33:51 +04:00
if ( ret = = - 1 ) {
2006-01-13 15:52:56 +03:00
* error_string = talloc_asprintf ( mem_ctx , " LDB for user %s failed: %s " ,
dom_sid_string ( mem_ctx , user_sid ) ,
2006-01-13 07:36:58 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-25 10:33:51 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
add = True ;
} else if ( ret > 1 ) {
2006-01-13 15:52:56 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one user with SID: %s in local LDB " ,
dom_sid_string ( mem_ctx , user_sid ) ) ;
2005-07-25 10:33:51 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
2006-01-13 15:52:56 +03:00
msg - > dn = msgs [ 0 ] - > dn ;
talloc_steal ( msg , msgs [ 0 ] - > dn ) ;
2005-07-25 10:33:51 +04:00
}
2006-01-13 15:52:56 +03:00
/* and do the same on the remote database */
2006-01-14 04:29:38 +03:00
if ( state - > remote_ldb ) {
ret = gendb_search ( state - > remote_ldb , mem_ctx , state - > base_dn [ database ] ,
& remote_msgs , remote_attrs , " (&(objectClass=user)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , user_sid ) ) ;
if ( ret = = - 1 ) {
* error_string = talloc_asprintf ( mem_ctx , " remote LDAP for user %s failed: %s " ,
dom_sid_string ( mem_ctx , user_sid ) ,
ldb_errstring ( state - > remote_ldb ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
* error_string = talloc_asprintf ( mem_ctx , " User exists in samsync but not in remote LDAP domain! (base: %s, SID: %s) " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( state - > base_dn [ database ] ) ,
2006-01-14 04:29:38 +03:00
dom_sid_string ( mem_ctx , user_sid ) ) ;
return NT_STATUS_NO_SUCH_USER ;
} else if ( ret > 1 ) {
* error_string = talloc_asprintf ( mem_ctx , " More than one user in remote LDAP domain with SID: %s " ,
dom_sid_string ( mem_ctx , user_sid ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
/* Try to put things in the same location as the remote server */
} else if ( add ) {
msg - > dn = remote_msgs [ 0 ] - > dn ;
talloc_steal ( msg , remote_msgs [ 0 ] - > dn ) ;
}
2006-01-13 15:52:56 +03:00
}
2005-07-25 10:33:51 +04:00
cn_name = talloc_strdup ( mem_ctx , user - > account_name . string ) ;
NT_STATUS_HAVE_NO_MEMORY ( cn_name ) ;
cn_name_len = strlen ( cn_name ) ;
2006-01-13 07:30:18 +03:00
# define ADD_OR_DEL(type, attrib, field) do { \
if ( user - > field ) { \
samdb_msg_add_ # # type ( state - > sam_ldb , mem_ctx , msg , \
attrib , user - > field ) ; \
} else if ( ! add ) { \
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg , \
attrib ) ; \
} \
2005-07-25 10:33:51 +04:00
} while ( 0 ) ;
ADD_OR_DEL ( string , " samAccountName " , account_name . string ) ;
ADD_OR_DEL ( string , " displayName " , full_name . string ) ;
if ( samdb_msg_add_dom_sid ( state - > sam_ldb , mem_ctx , msg ,
" objectSid " , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
ADD_OR_DEL ( uint , " primaryGroupID " , primary_gid ) ;
ADD_OR_DEL ( string , " homeDirectory " , home_directory . string ) ;
ADD_OR_DEL ( string , " homeDrive " , home_drive . string ) ;
ADD_OR_DEL ( string , " scriptPath " , logon_script . string ) ;
ADD_OR_DEL ( string , " description " , description . string ) ;
ADD_OR_DEL ( string , " userWorkstations " , workstations . string ) ;
ADD_OR_DEL ( uint64 , " lastLogon " , last_logon ) ;
ADD_OR_DEL ( uint64 , " lastLogoff " , last_logoff ) ;
2005-07-26 10:37:20 +04:00
if ( samdb_msg_add_logon_hours ( state - > sam_ldb , mem_ctx , msg , " logonHours " , & user - > logon_hours ) ! = 0 ) {
return NT_STATUS_NO_MEMORY ;
}
2005-07-25 10:33:51 +04:00
ADD_OR_DEL ( uint , " badPwdCount " , bad_password_count ) ;
ADD_OR_DEL ( uint , " logonCount " , logon_count ) ;
ADD_OR_DEL ( uint64 , " pwdLastSet " , last_password_change ) ;
ADD_OR_DEL ( uint64 , " accountExpires " , acct_expiry ) ;
if ( samdb_msg_add_acct_flags ( state - > sam_ldb , mem_ctx , msg ,
2005-08-03 09:24:13 +04:00
" userAccountControl " , user - > acct_flags ) ! = 0 ) {
2005-07-25 10:33:51 +04:00
return NT_STATUS_NO_MEMORY ;
}
2006-10-16 05:19:01 +04:00
if ( ! add ) {
/* Passwords. Ensure there is no plaintext stored against
* this entry , as we only have hashes */
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg ,
" sambaPassword " ) ;
}
2005-07-25 10:33:51 +04:00
if ( user - > lm_password_present ) {
samdb_msg_add_hash ( state - > sam_ldb , mem_ctx , msg ,
2007-02-15 15:54:58 +03:00
" dBCSPwd " , & user - > lmpassword ) ;
2006-10-16 05:19:01 +04:00
} else if ( ! add ) {
2005-07-25 10:33:51 +04:00
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg ,
2007-02-15 15:54:58 +03:00
" dBCSPwd " ) ;
2005-07-25 10:33:51 +04:00
}
if ( user - > nt_password_present ) {
samdb_msg_add_hash ( state - > sam_ldb , mem_ctx , msg ,
2007-02-15 15:54:58 +03:00
" unicodePwd " , & user - > ntpassword ) ;
2006-10-16 05:19:01 +04:00
} else if ( ! add ) {
2005-07-25 10:33:51 +04:00
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg ,
2007-02-15 15:54:58 +03:00
" unicodePwd " ) ;
2005-07-25 10:33:51 +04:00
}
ADD_OR_DEL ( string , " comment " , comment . string ) ;
ADD_OR_DEL ( string , " userParameters " , parameters . string ) ;
ADD_OR_DEL ( uint , " countryCode " , country_code ) ;
ADD_OR_DEL ( uint , " codePage " , code_page ) ;
ADD_OR_DEL ( string , " profilePath " , profile_path . string ) ;
2005-07-26 07:11:16 +04:00
# undef ADD_OR_DEL
2006-01-13 15:52:56 +03:00
for ( i = 0 ; remote_attrs [ i ] ; i + + ) {
struct ldb_message_element * el = ldb_msg_find_element ( remote_msgs [ 0 ] , remote_attrs [ i ] ) ;
if ( ! el ) {
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg ,
remote_attrs [ i ] ) ;
} else {
ldb_msg_add ( msg , el , LDB_FLAG_MOD_REPLACE ) ;
}
}
2005-07-25 10:33:51 +04:00
acb = user - > acct_flags ;
if ( acb & ( ACB_WSTRUST ) ) {
cn_name [ cn_name_len - 1 ] = ' \0 ' ;
container = " Computers " ;
obj_class = " computer " ;
} else if ( acb & ACB_SVRTRUST ) {
if ( cn_name [ cn_name_len - 1 ] ! = ' $ ' ) {
return NT_STATUS_FOOBAR ;
}
cn_name [ cn_name_len - 1 ] = ' \0 ' ;
container = " Domain Controllers " ;
obj_class = " computer " ;
} else {
container = " Users " ;
obj_class = " user " ;
}
if ( add ) {
samdb_msg_add_string ( state - > sam_ldb , mem_ctx , msg ,
" objectClass " , obj_class ) ;
if ( ! msg - > dn ) {
2006-11-22 03:59:34 +03:00
msg - > dn = ldb_dn_copy ( mem_ctx , state - > base_dn [ database ] ) ;
ldb_dn_add_child_fmt ( msg - > dn , " CN=%s,CN=%s " , cn_name , container ) ;
2006-01-14 04:29:38 +03:00
if ( ! msg - > dn ) {
return NT_STATUS_NO_MEMORY ;
}
2005-07-25 10:33:51 +04:00
}
ret = samdb_add ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 15:52:56 +03:00
struct ldb_dn * first_try_dn = msg - > dn ;
/* Try again with the default DN */
2007-09-10 05:39:20 +04:00
if ( ! remote_msgs ) {
* error_string = talloc_asprintf ( mem_ctx , " Failed to create user record. Tried %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( first_try_dn ) ,
2006-01-13 15:52:56 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2007-09-10 05:39:20 +04:00
} else {
msg - > dn = talloc_steal ( msg , remote_msgs [ 0 ] - > dn ) ;
ret = samdb_add ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
* error_string = talloc_asprintf ( mem_ctx , " Failed to create user record. Tried both %s and %s: %s " ,
ldb_dn_get_linearized ( first_try_dn ) ,
ldb_dn_get_linearized ( msg - > dn ) ,
ldb_errstring ( state - > sam_ldb ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2006-01-13 15:52:56 +03:00
}
2005-07-25 10:33:51 +04:00
}
} else {
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:36:58 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to modify user record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:36:58 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-25 10:33:51 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
}
return NT_STATUS_OK ;
}
2005-07-26 07:11:16 +04:00
static NTSTATUS samsync_ldb_delete_user ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
2006-01-13 07:30:18 +03:00
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 07:11:16 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct ldb_message * * msgs ;
int ret ;
const char * attrs [ ] = { NULL } ;
/* search for the user, by rid */
2005-08-18 19:02:01 +04:00
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] ,
& msgs , attrs , " (&(objectClass=user)(objectSid=%s)) " ,
2005-07-26 07:11:16 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_USER ;
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one user with SID: %s " ,
dom_sid_string ( mem_ctx ,
dom_sid_add_rid ( mem_ctx ,
state - > dom_sid [ database ] ,
rid ) ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
ret = samdb_delete ( state - > sam_ldb , mem_ctx , msgs [ 0 ] - > dn ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to delete user record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msgs [ 0 ] - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
return NT_STATUS_OK ;
}
2005-07-25 10:33:51 +04:00
static NTSTATUS samsync_ldb_handle_group ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
2006-01-13 07:30:18 +03:00
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-25 10:33:51 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct netr_DELTA_GROUP * group = delta - > delta_union . group ;
2005-07-26 07:11:16 +04:00
const char * container , * obj_class ;
const char * cn_name ;
struct ldb_message * msg ;
struct ldb_message * * msgs ;
int ret ;
BOOL add = False ;
const char * attrs [ ] = { NULL } ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* search for the group, by rid */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] , & msgs , attrs ,
" (&(objectClass=group)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
add = True ;
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one group/alias with SID: %s " ,
dom_sid_string ( mem_ctx ,
dom_sid_add_rid ( mem_ctx ,
state - > dom_sid [ database ] ,
rid ) ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
2005-07-26 10:37:20 +04:00
msg - > dn = talloc_steal ( msg , msgs [ 0 ] - > dn ) ;
2005-07-26 07:11:16 +04:00
}
cn_name = group - > group_name . string ;
2006-01-13 07:30:18 +03:00
# define ADD_OR_DEL(type, attrib, field) do { \
if ( group - > field ) { \
samdb_msg_add_ # # type ( state - > sam_ldb , mem_ctx , msg , \
attrib , group - > field ) ; \
} else if ( ! add ) { \
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg , \
attrib ) ; \
} \
2005-07-26 07:11:16 +04:00
} while ( 0 ) ;
ADD_OR_DEL ( string , " samAccountName " , group_name . string ) ;
if ( samdb_msg_add_dom_sid ( state - > sam_ldb , mem_ctx , msg ,
" objectSid " , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
ADD_OR_DEL ( string , " description " , description . string ) ;
# undef ADD_OR_DEL
container = " Users " ;
obj_class = " group " ;
if ( add ) {
samdb_msg_add_string ( state - > sam_ldb , mem_ctx , msg ,
" objectClass " , obj_class ) ;
2006-11-22 03:59:34 +03:00
msg - > dn = ldb_dn_copy ( mem_ctx , state - > base_dn [ database ] ) ;
ldb_dn_add_child_fmt ( msg - > dn , " CN=%s,CN=%s " , cn_name , container ) ;
2005-07-26 07:11:16 +04:00
if ( ! msg - > dn ) {
return NT_STATUS_NO_MEMORY ;
}
ret = samdb_add ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to create group record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
} else {
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to modify group record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
}
return NT_STATUS_OK ;
}
static NTSTATUS samsync_ldb_delete_group ( TALLOC_CTX * mem_ctx ,
2006-01-13 07:30:18 +03:00
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 07:11:16 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct ldb_message * * msgs ;
int ret ;
const char * attrs [ ] = { NULL } ;
/* search for the group, by rid */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] , & msgs , attrs ,
" (&(objectClass=group)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_GROUP ;
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one group/alias with SID: %s " ,
dom_sid_string ( mem_ctx ,
dom_sid_add_rid ( mem_ctx ,
state - > dom_sid [ database ] ,
rid ) ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-07-26 10:37:20 +04:00
2005-07-26 07:11:16 +04:00
ret = samdb_delete ( state - > sam_ldb , mem_ctx , msgs [ 0 ] - > dn ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to delete group record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msgs [ 0 ] - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
return NT_STATUS_OK ;
}
2005-07-26 10:37:20 +04:00
static NTSTATUS samsync_ldb_handle_group_member ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
2006-01-13 07:30:18 +03:00
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 10:37:20 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct netr_DELTA_GROUP_MEMBER * group_member = delta - > delta_union . group_member ;
struct ldb_message * msg ;
struct ldb_message * * msgs ;
int ret ;
const char * attrs [ ] = { NULL } ;
int i ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* search for the group, by rid */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] , & msgs , attrs ,
" (&(objectClass=group)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_GROUP ;
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one group/alias with SID: %s " ,
dom_sid_string ( mem_ctx ,
dom_sid_add_rid ( mem_ctx ,
state - > dom_sid [ database ] ,
rid ) ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
msg - > dn = talloc_steal ( msg , msgs [ 0 ] - > dn ) ;
}
talloc_free ( msgs ) ;
for ( i = 0 ; i < group_member - > num_rids ; i + + ) {
/* search for the group, by rid */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] , & msgs , attrs ,
" (&(objectClass=user)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , group_member - > rids [ i ] ) ) ) ;
2006-01-13 07:30:18 +03:00
2005-07-26 10:37:20 +04:00
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_USER ;
} else if ( ret > 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
2006-11-22 05:05:19 +03:00
samdb_msg_add_string ( state - > sam_ldb , mem_ctx , msg , " member " , ldb_dn_alloc_linearized ( mem_ctx , msgs [ 0 ] - > dn ) ) ;
2005-07-26 10:37:20 +04:00
}
2006-01-13 07:30:18 +03:00
2005-07-26 10:37:20 +04:00
talloc_free ( msgs ) ;
}
2006-01-13 07:30:18 +03:00
2005-07-26 10:37:20 +04:00
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to modify group record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
return NT_STATUS_OK ;
}
2005-07-26 07:11:16 +04:00
static NTSTATUS samsync_ldb_handle_alias ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
2006-01-13 07:30:18 +03:00
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 07:11:16 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct netr_DELTA_ALIAS * alias = delta - > delta_union . alias ;
const char * container , * obj_class ;
const char * cn_name ;
struct ldb_message * msg ;
struct ldb_message * * msgs ;
int ret ;
BOOL add = False ;
const char * attrs [ ] = { NULL } ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* search for the alias, by rid */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] , & msgs , attrs ,
" (&(objectClass=group)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
add = True ;
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one group/alias with SID: %s " ,
dom_sid_string ( mem_ctx ,
dom_sid_add_rid ( mem_ctx ,
state - > dom_sid [ database ] ,
rid ) ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
msg - > dn = talloc_steal ( mem_ctx , msgs [ 0 ] - > dn ) ;
}
cn_name = alias - > alias_name . string ;
2006-01-13 07:30:18 +03:00
# define ADD_OR_DEL(type, attrib, field) do { \
if ( alias - > field ) { \
samdb_msg_add_ # # type ( state - > sam_ldb , mem_ctx , msg , \
attrib , alias - > field ) ; \
} else if ( ! add ) { \
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg , \
attrib ) ; \
} \
} while ( 0 ) ;
2005-07-26 07:11:16 +04:00
2006-01-13 07:30:18 +03:00
ADD_OR_DEL ( string , " samAccountName " , alias_name . string ) ;
2005-07-26 07:11:16 +04:00
if ( samdb_msg_add_dom_sid ( state - > sam_ldb , mem_ctx , msg ,
" objectSid " , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
ADD_OR_DEL ( string , " description " , description . string ) ;
# undef ADD_OR_DEL
2005-07-26 10:37:20 +04:00
samdb_msg_add_uint ( state - > sam_ldb , mem_ctx , msg , " groupType " , 0x80000004 ) ;
2005-07-26 07:11:16 +04:00
container = " Users " ;
obj_class = " group " ;
if ( add ) {
samdb_msg_add_string ( state - > sam_ldb , mem_ctx , msg ,
" objectClass " , obj_class ) ;
2006-11-22 03:59:34 +03:00
msg - > dn = ldb_dn_copy ( mem_ctx , state - > base_dn [ database ] ) ;
ldb_dn_add_child_fmt ( msg - > dn , " CN=%s,CN=%s " , cn_name , container ) ;
2005-07-26 07:11:16 +04:00
if ( ! msg - > dn ) {
return NT_STATUS_NO_MEMORY ;
}
ret = samdb_add ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to create alias record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
} else {
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to modify alias record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
}
return NT_STATUS_OK ;
}
static NTSTATUS samsync_ldb_delete_alias ( TALLOC_CTX * mem_ctx ,
2006-01-13 07:30:18 +03:00
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 07:11:16 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct ldb_message * * msgs ;
int ret ;
const char * attrs [ ] = { NULL } ;
/* search for the alias, by rid */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] , & msgs , attrs ,
" (&(objectClass=group)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_ALIAS ;
} else if ( ret > 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
ret = samdb_delete ( state - > sam_ldb , mem_ctx , msgs [ 0 ] - > dn ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to delete alias record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msgs [ 0 ] - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 07:11:16 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-07-25 10:33:51 +04:00
return NT_STATUS_OK ;
}
2005-07-26 10:37:20 +04:00
static NTSTATUS samsync_ldb_handle_alias_member ( TALLOC_CTX * mem_ctx ,
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
2006-01-13 07:30:18 +03:00
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 10:37:20 +04:00
{
uint32_t rid = delta - > delta_id_union . rid ;
struct netr_DELTA_ALIAS_MEMBER * alias_member = delta - > delta_union . alias_member ;
struct ldb_message * msg ;
struct ldb_message * * msgs ;
int ret ;
const char * attrs [ ] = { NULL } ;
int i ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* search for the alias, by rid */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ database ] , & msgs , attrs ,
" (&(objectClass=group)(objectSid=%s)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid_add_rid ( mem_ctx , state - > dom_sid [ database ] , rid ) ) ) ;
2006-01-13 07:30:18 +03:00
2005-07-26 10:37:20 +04:00
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_GROUP ;
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one group/alias with SID: %s " ,
dom_sid_string ( mem_ctx ,
dom_sid_add_rid ( mem_ctx ,
state - > dom_sid [ database ] ,
rid ) ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
msg - > dn = talloc_steal ( msg , msgs [ 0 ] - > dn ) ;
}
talloc_free ( msgs ) ;
for ( i = 0 ; i < alias_member - > sids . num_sids ; i + + ) {
2005-08-18 19:02:01 +04:00
struct ldb_dn * alias_member_dn ;
2005-07-27 04:23:09 +04:00
/* search for members, in the top basedn (normal users are builtin aliases) */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ SAM_DATABASE_DOMAIN ] , & msgs , attrs ,
2005-07-26 10:37:20 +04:00
" (objectSid=%s) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , alias_member - > sids . sids [ i ] . sid ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
2005-07-27 04:23:09 +04:00
NTSTATUS nt_status ;
nt_status = samsync_ldb_add_foreignSecurityPrincipal ( mem_ctx , state ,
alias_member - > sids . sids [ i ] . sid ,
2006-01-13 07:30:18 +03:00
& alias_member_dn ,
error_string ) ;
2005-07-27 04:23:09 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
}
2006-01-13 07:30:18 +03:00
} else if ( ret > 1 ) {
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
2005-07-27 04:23:09 +04:00
alias_member_dn = msgs [ 0 ] - > dn ;
2005-07-26 10:37:20 +04:00
}
2006-11-22 05:05:19 +03:00
samdb_msg_add_string ( state - > sam_ldb , mem_ctx , msg , " member " , ldb_dn_alloc_linearized ( mem_ctx , alias_member_dn ) ) ;
2005-07-26 10:37:20 +04:00
talloc_free ( msgs ) ;
}
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to modify group record %s: %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-01-13 07:30:18 +03:00
ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
return NT_STATUS_OK ;
}
static NTSTATUS samsync_ldb_handle_account ( TALLOC_CTX * mem_ctx ,
2006-01-13 07:30:18 +03:00
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 10:37:20 +04:00
{
struct dom_sid * sid = delta - > delta_id_union . sid ;
struct netr_DELTA_ACCOUNT * account = delta - > delta_union . account ;
struct ldb_message * msg ;
struct ldb_message * * msgs ;
2005-08-18 19:02:01 +04:00
struct ldb_dn * privilege_dn ;
2005-07-26 10:37:20 +04:00
int ret ;
const char * attrs [ ] = { NULL } ;
int i ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-07-27 04:23:09 +04:00
/* search for the account, by sid, in the top basedn */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ SAM_DATABASE_DOMAIN ] , & msgs , attrs ,
2005-07-26 10:37:20 +04:00
" (objectSid=%s) " , ldap_encode_ndr_dom_sid ( mem_ctx , sid ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
2005-07-27 04:23:09 +04:00
NTSTATUS nt_status ;
nt_status = samsync_ldb_add_foreignSecurityPrincipal ( mem_ctx , state ,
sid ,
2006-01-13 07:30:18 +03:00
& privilege_dn ,
error_string ) ;
2005-08-18 19:02:01 +04:00
privilege_dn = talloc_steal ( msg , privilege_dn ) ;
2005-07-27 04:23:09 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
}
2005-07-26 10:37:20 +04:00
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one account with SID: %s " ,
dom_sid_string ( mem_ctx , sid ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
2005-08-18 19:02:01 +04:00
privilege_dn = talloc_steal ( msg , msgs [ 0 ] - > dn ) ;
2005-07-26 10:37:20 +04:00
}
2005-08-18 19:02:01 +04:00
msg - > dn = privilege_dn ;
2005-07-27 04:23:09 +04:00
2005-07-26 10:37:20 +04:00
for ( i = 0 ; i < account - > privilege_entries ; i + + ) {
2005-08-18 19:02:01 +04:00
samdb_msg_add_string ( state - > sam_ldb , mem_ctx , msg , " privilege " ,
2005-07-26 10:37:20 +04:00
account - > privilege_name [ i ] . string ) ;
}
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to modify privilege record %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
return NT_STATUS_OK ;
}
static NTSTATUS samsync_ldb_delete_account ( TALLOC_CTX * mem_ctx ,
2006-01-13 07:30:18 +03:00
struct samsync_ldb_state * state ,
enum netr_SamDatabaseID database ,
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-26 10:37:20 +04:00
{
struct dom_sid * sid = delta - > delta_id_union . sid ;
struct ldb_message * msg ;
struct ldb_message * * msgs ;
int ret ;
const char * attrs [ ] = { NULL } ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-07-27 04:23:09 +04:00
/* search for the account, by sid, in the top basedn */
ret = gendb_search ( state - > sam_ldb , mem_ctx , state - > base_dn [ SAM_DATABASE_DOMAIN ] , & msgs , attrs ,
2005-07-26 10:37:20 +04:00
" (objectSid=%s) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , sid ) ) ;
if ( ret = = - 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " gendb_search failed: %s " , ldb_errstring ( state - > sam_ldb ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_USER ;
} else if ( ret > 1 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " More than one account with SID: %s " ,
dom_sid_string ( mem_ctx , sid ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else {
msg - > dn = talloc_steal ( msg , msgs [ 0 ] - > dn ) ;
}
samdb_msg_add_delete ( state - > sam_ldb , mem_ctx , msg ,
" privilage " ) ;
ret = samdb_replace ( state - > sam_ldb , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2006-01-13 07:30:18 +03:00
* error_string = talloc_asprintf ( mem_ctx , " Failed to modify privilege record %s " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ) ;
2005-07-26 10:37:20 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
return NT_STATUS_OK ;
}
2005-07-25 10:33:51 +04:00
static NTSTATUS libnet_samsync_ldb_fn ( TALLOC_CTX * mem_ctx ,
2006-01-13 07:30:18 +03:00
void * private ,
enum netr_SamDatabaseID database ,
struct netr_DELTA_ENUM * delta ,
char * * error_string )
2005-07-25 10:33:51 +04:00
{
NTSTATUS nt_status = NT_STATUS_OK ;
2006-01-13 15:52:56 +03:00
struct samsync_ldb_state * state = talloc_get_type ( private , struct samsync_ldb_state ) ;
2005-07-25 10:33:51 +04:00
* error_string = NULL ;
switch ( delta - > delta_type ) {
case NETR_DELTA_DOMAIN :
{
nt_status = samsync_ldb_handle_domain ( mem_ctx ,
state ,
database ,
2006-01-13 07:30:18 +03:00
delta ,
error_string ) ;
2005-07-25 10:33:51 +04:00
break ;
}
case NETR_DELTA_USER :
{
nt_status = samsync_ldb_handle_user ( mem_ctx ,
state ,
database ,
2006-01-13 07:30:18 +03:00
delta ,
error_string ) ;
2005-07-25 10:33:51 +04:00
break ;
}
2005-07-26 07:11:16 +04:00
case NETR_DELTA_DELETE_USER :
{
nt_status = samsync_ldb_delete_user ( mem_ctx ,
state ,
database ,
2006-01-13 07:30:18 +03:00
delta ,
error_string ) ;
2005-07-26 07:11:16 +04:00
break ;
}
2005-07-25 10:33:51 +04:00
case NETR_DELTA_GROUP :
{
nt_status = samsync_ldb_handle_group ( mem_ctx ,
state ,
database ,
2006-01-13 07:30:18 +03:00
delta ,
error_string ) ;
2005-07-25 10:33:51 +04:00
break ;
}
2005-07-26 07:11:16 +04:00
case NETR_DELTA_DELETE_GROUP :
{
nt_status = samsync_ldb_delete_group ( mem_ctx ,
2006-01-13 07:30:18 +03:00
state ,
database ,
delta ,
error_string ) ;
2005-07-26 07:11:16 +04:00
break ;
}
2005-07-26 10:37:20 +04:00
case NETR_DELTA_GROUP_MEMBER :
{
nt_status = samsync_ldb_handle_group_member ( mem_ctx ,
state ,
database ,
2006-01-13 07:30:18 +03:00
delta ,
error_string ) ;
2005-07-26 10:37:20 +04:00
break ;
}
2005-07-26 07:11:16 +04:00
case NETR_DELTA_ALIAS :
{
nt_status = samsync_ldb_handle_alias ( mem_ctx ,
state ,
database ,
2006-01-13 07:30:18 +03:00
delta ,
error_string ) ;
2005-07-26 07:11:16 +04:00
break ;
}
case NETR_DELTA_DELETE_ALIAS :
{
nt_status = samsync_ldb_delete_alias ( mem_ctx ,
2006-01-13 07:30:18 +03:00
state ,
database ,
delta ,
error_string ) ;
2005-07-26 07:11:16 +04:00
break ;
}
2005-07-26 10:37:20 +04:00
case NETR_DELTA_ALIAS_MEMBER :
{
nt_status = samsync_ldb_handle_alias_member ( mem_ctx ,
state ,
database ,
2006-01-13 07:30:18 +03:00
delta ,
error_string ) ;
2005-07-26 10:37:20 +04:00
break ;
}
case NETR_DELTA_ACCOUNT :
{
nt_status = samsync_ldb_handle_account ( mem_ctx ,
2006-01-13 07:30:18 +03:00
state ,
database ,
delta ,
error_string ) ;
2005-07-26 10:37:20 +04:00
break ;
}
case NETR_DELTA_DELETE_ACCOUNT :
{
nt_status = samsync_ldb_delete_account ( mem_ctx ,
2006-01-13 07:30:18 +03:00
state ,
database ,
delta ,
error_string ) ;
2005-07-26 10:37:20 +04:00
break ;
}
2005-07-25 10:33:51 +04:00
default :
/* Can't dump them all right now */
break ;
}
2006-01-13 07:30:18 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) & & ! * error_string ) {
* error_string = talloc_asprintf ( mem_ctx , " Failed to handle samsync delta: %s " , nt_errstr ( nt_status ) ) ;
}
2005-07-25 10:33:51 +04:00
return nt_status ;
}
2006-01-13 15:52:56 +03:00
static NTSTATUS libnet_samsync_ldb_init ( TALLOC_CTX * mem_ctx ,
void * private ,
2006-01-14 04:29:38 +03:00
struct libnet_SamSync_state * samsync_state ,
2006-01-13 15:52:56 +03:00
char * * error_string )
{
struct samsync_ldb_state * state = talloc_get_type ( private , struct samsync_ldb_state ) ;
2006-01-14 04:29:38 +03:00
const char * server = dcerpc_server_name ( samsync_state - > netlogon_pipe ) ;
2006-01-13 15:52:56 +03:00
char * ldap_url ;
2006-01-14 04:29:38 +03:00
state - > samsync_state = samsync_state ;
2006-01-13 15:52:56 +03:00
2006-01-14 04:29:38 +03:00
ZERO_STRUCT ( state - > dom_sid ) ;
if ( state - > samsync_state - > domain_sid ) {
state - > dom_sid [ SAM_DATABASE_DOMAIN ] = dom_sid_dup ( state , state - > samsync_state - > domain_sid ) ;
}
state - > dom_sid [ SAM_DATABASE_BUILTIN ] = dom_sid_parse_talloc ( state , SID_BUILTIN ) ;
if ( state - > samsync_state - > realm ) {
2006-01-13 15:52:56 +03:00
if ( ! server | | ! * server ) {
/* huh? how do we not have a server name? */
* error_string = talloc_strdup ( mem_ctx , " No DCE/RPC server name available. How did we connect? " ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2006-01-14 04:29:38 +03:00
ldap_url = talloc_asprintf ( state , " ldap://%s " , server ) ;
2006-01-13 15:52:56 +03:00
state - > remote_ldb = ldb_wrap_connect ( mem_ctx , ldap_url ,
2006-01-14 04:29:38 +03:00
NULL , state - > samsync_state - > machine_net_ctx - > cred ,
2006-01-13 15:52:56 +03:00
0 , NULL ) ;
2006-01-14 04:29:38 +03:00
if ( ! state - > remote_ldb ) {
* error_string = talloc_asprintf ( mem_ctx , " Failed to connect to remote LDAP server at %s (used to extract additional data in SamSync replication) " , ldap_url ) ;
return NT_STATUS_NO_LOGON_SERVERS ;
}
} else {
state - > remote_ldb = NULL ;
2006-01-13 15:52:56 +03:00
}
return NT_STATUS_OK ;
}
2006-01-12 12:33:49 +03:00
NTSTATUS libnet_samsync_ldb ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx , struct libnet_samsync_ldb * r )
2005-07-25 10:33:51 +04:00
{
NTSTATUS nt_status ;
struct libnet_SamSync r2 ;
struct samsync_ldb_state * state = talloc ( mem_ctx , struct samsync_ldb_state ) ;
if ( ! state ) {
return NT_STATUS_NO_MEMORY ;
}
2006-01-12 12:33:49 +03:00
state - > secrets = NULL ;
2005-07-25 10:33:51 +04:00
state - > trusted_domains = NULL ;
2007-09-28 05:17:46 +04:00
state - > sam_ldb = ldb_wrap_connect ( mem_ctx , lp_sam_url ( global_loadparm ) ,
2007-09-07 19:35:18 +04:00
r - > in . session_info ,
2006-01-14 09:17:24 +03:00
ctx - > cred , 0 , NULL ) ;
2005-07-25 10:33:51 +04:00
2006-01-12 12:33:49 +03:00
r2 . out . error_string = NULL ;
r2 . in . binding_string = r - > in . binding_string ;
2007-02-12 16:34:04 +03:00
r2 . in . rid_crypt = true ;
2006-01-13 15:52:56 +03:00
r2 . in . init_fn = libnet_samsync_ldb_init ;
2006-01-12 12:33:49 +03:00
r2 . in . delta_fn = libnet_samsync_ldb_fn ;
r2 . in . fn_ctx = state ;
r2 . in . machine_account = NULL ; /* TODO: Create a machine account, fill this in, and the delete it */
nt_status = libnet_SamSync_netlogon ( ctx , state , & r2 ) ;
r - > out . error_string = r2 . out . error_string ;
2006-01-13 15:52:56 +03:00
talloc_steal ( mem_ctx , r - > out . error_string ) ;
2005-07-25 10:33:51 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( state ) ;
return nt_status ;
}
talloc_free ( state ) ;
return nt_status ;
}