2009-09-09 15:00:01 +04:00
/*
Unix SMB / CIFS implementation .
implement the DRSUpdateRefs call
Copyright ( C ) Anatoliy Atanasov 2009
Copyright ( C ) Andrew Tridgell 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/>.
*/
# include "includes.h"
# include "rpc_server/dcerpc_server.h"
# include "dsdb/samdb/samdb.h"
# include "param/param.h"
# include "librpc/gen_ndr/ndr_drsblobs.h"
2009-12-19 16:12:35 +03:00
# include "librpc/gen_ndr/ndr_drsuapi.h"
2009-09-09 15:00:01 +04:00
# include "rpc_server/drsuapi/dcesrv_drsuapi.h"
2009-09-10 11:46:30 +04:00
# include "rpc_server/dcerpc_server_proto.h"
# include "../libcli/drsuapi/drsuapi.h"
2009-09-16 06:26:33 +04:00
# include "libcli/security/security.h"
2009-09-09 15:00:01 +04:00
2009-12-19 04:25:09 +03:00
/*
build a DsReplicaObjectIdentifier from a ldb msg
*/
static struct drsuapi_DsReplicaObjectIdentifier * get_object_identifier ( TALLOC_CTX * mem_ctx ,
struct ldb_message * msg )
{
struct drsuapi_DsReplicaObjectIdentifier * identifier ;
struct dom_sid * sid ;
identifier = talloc ( mem_ctx , struct drsuapi_DsReplicaObjectIdentifier ) ;
if ( identifier = = NULL ) {
return NULL ;
}
identifier - > dn = ldb_dn_alloc_linearized ( identifier , msg - > dn ) ;
identifier - > guid = samdb_result_guid ( msg , " objectGUID " ) ;
sid = samdb_result_dom_sid ( identifier , msg , " objectSid " ) ;
if ( sid ) {
identifier - > sid = * sid ;
} else {
ZERO_STRUCT ( identifier - > sid ) ;
}
return identifier ;
}
2009-09-09 15:26:17 +04:00
/*
2009-09-10 11:46:30 +04:00
drsuapi_DsGetNCChanges for one object
2009-09-09 15:26:17 +04:00
*/
static WERROR get_nc_changes_build_object ( struct drsuapi_DsReplicaObjectListItemEx * obj ,
struct ldb_message * msg ,
struct ldb_context * sam_ctx ,
struct ldb_dn * ncRoot_dn ,
2009-09-10 11:46:30 +04:00
struct dsdb_schema * schema ,
2009-09-12 05:14:29 +04:00
DATA_BLOB * session_key ,
s4: Handle DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING in getncchanges
When this flag is specified in the request these attributes are treated as
secret: currentValue, dBCSPwd, initialAuthIncoming, initialAuthOutgoing,
lmPwdHistory, ntPwdHistory, priorValue, supplementalCredentials,
trustAuthIncoming, trustAuthOutgoing, unicodePwd
Their value is changed to NULL and the meta_data.originating_change_time to 0
2009-09-24 03:51:55 +04:00
uint64_t highest_usn ,
uint32_t replica_flags )
2009-09-09 15:26:17 +04:00
{
const struct ldb_val * md_value ;
2009-09-12 05:14:29 +04:00
int i , n ;
2009-09-09 17:38:51 +04:00
struct replPropertyMetaDataBlob md ;
2009-09-10 11:46:30 +04:00
uint32_t rid = 0 ;
2009-09-12 05:14:29 +04:00
enum ndr_err_code ndr_err ;
uint32_t * attids ;
2009-09-24 00:56:10 +04:00
const char * rdn ;
const struct dsdb_attribute * rdn_sa ;
2009-09-09 15:26:17 +04:00
if ( ldb_dn_compare ( ncRoot_dn , msg - > dn ) = = 0 ) {
obj - > is_nc_prefix = true ;
obj - > parent_object_guid = NULL ;
} else {
2009-09-26 02:17:44 +04:00
obj - > is_nc_prefix = false ;
obj - > parent_object_guid = talloc ( obj , struct GUID ) ;
2009-12-09 06:38:25 +03:00
if ( obj - > parent_object_guid = = NULL ) {
2009-09-26 02:17:44 +04:00
return WERR_DS_DRA_INTERNAL_ERROR ;
2009-09-24 00:56:10 +04:00
}
2009-12-09 06:38:25 +03:00
* obj - > parent_object_guid = samdb_result_guid ( msg , " parentGUID " ) ;
if ( GUID_all_zero ( obj - > parent_object_guid ) ) {
DEBUG ( 0 , ( __location__ " : missing parentGUID for %s \n " ,
ldb_dn_get_linearized ( msg - > dn ) ) ) ;
2009-09-26 02:17:44 +04:00
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2009-09-09 15:26:17 +04:00
}
obj - > next_object = NULL ;
md_value = ldb_msg_find_ldb_val ( msg , " replPropertyMetaData " ) ;
2009-09-12 05:14:29 +04:00
if ( ! md_value ) {
/* nothing to send */
return WERR_OK ;
}
ndr_err = ndr_pull_struct_blob ( md_value , obj ,
lp_iconv_convenience ( ldb_get_opaque ( sam_ctx , " loadparm " ) ) , & md ,
( ndr_pull_flags_fn_t ) ndr_pull_replPropertyMetaDataBlob ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
if ( md . version ! = 1 ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
2009-09-09 15:26:17 +04:00
}
2009-09-12 05:14:29 +04:00
2009-09-24 00:56:10 +04:00
rdn = ldb_dn_get_rdn_name ( msg - > dn ) ;
if ( rdn = = NULL ) {
DEBUG ( 0 , ( __location__ " : No rDN for %s \n " , ldb_dn_get_linearized ( msg - > dn ) ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
rdn_sa = dsdb_attribute_by_lDAPDisplayName ( schema , rdn ) ;
if ( rdn_sa = = NULL ) {
DEBUG ( 0 , ( __location__ " : Can't find dsds_attribute for rDN %s in %s \n " ,
rdn , ldb_dn_get_linearized ( msg - > dn ) ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2009-09-12 05:14:29 +04:00
obj - > meta_data_ctr = talloc ( obj , struct drsuapi_DsReplicaMetaDataCtr ) ;
attids = talloc_array ( obj , uint32_t , md . ctr . ctr1 . count ) ;
2009-12-03 01:19:55 +03:00
2009-12-19 04:25:09 +03:00
obj - > object . identifier = get_object_identifier ( obj , msg ) ;
if ( obj - > object . identifier = = NULL ) {
return WERR_NOMEM ;
2009-12-03 01:19:55 +03:00
}
2009-12-19 04:25:09 +03:00
dom_sid_split_rid ( NULL , & obj - > object . identifier - > sid , NULL , & rid ) ;
2009-09-12 05:14:29 +04:00
obj - > meta_data_ctr - > meta_data = talloc_array ( obj , struct drsuapi_DsReplicaMetaData , md . ctr . ctr1 . count ) ;
for ( n = i = 0 ; i < md . ctr . ctr1 . count ; i + + ) {
2009-12-19 12:59:04 +03:00
const struct dsdb_attribute * sa ;
2009-09-24 00:56:10 +04:00
/* if the attribute has not changed, and it is not the
instanceType then don ' t include it */
if ( md . ctr . ctr1 . array [ i ] . local_usn < highest_usn & &
md . ctr . ctr1 . array [ i ] . attid ! = DRSUAPI_ATTRIBUTE_instanceType ) continue ;
2009-10-14 13:29:39 +04:00
2009-09-24 00:56:10 +04:00
/* don't include the rDN */
if ( md . ctr . ctr1 . array [ i ] . attid = = rdn_sa - > attributeID_id ) continue ;
2009-10-14 13:29:39 +04:00
2009-12-19 12:59:04 +03:00
sa = dsdb_attribute_by_attributeID_id ( schema , md . ctr . ctr1 . array [ i ] . attid ) ;
if ( sa - > linkID ) {
struct ldb_message_element * el ;
el = ldb_msg_find_element ( msg , sa - > lDAPDisplayName ) ;
if ( el & & el - > num_values & & dsdb_dn_is_upgraded_link_val ( & el - > values [ 0 ] ) ) {
/* don't send upgraded links inline */
continue ;
}
}
2009-09-12 05:14:29 +04:00
obj - > meta_data_ctr - > meta_data [ n ] . originating_change_time = md . ctr . ctr1 . array [ i ] . originating_change_time ;
obj - > meta_data_ctr - > meta_data [ n ] . version = md . ctr . ctr1 . array [ i ] . version ;
obj - > meta_data_ctr - > meta_data [ n ] . originating_invocation_id = md . ctr . ctr1 . array [ i ] . originating_invocation_id ;
obj - > meta_data_ctr - > meta_data [ n ] . originating_usn = md . ctr . ctr1 . array [ i ] . originating_usn ;
attids [ n ] = md . ctr . ctr1 . array [ i ] . attid ;
n + + ;
}
2009-09-15 00:12:32 +04:00
/*
note that if n = = 0 we still need to send the change , as it
could be a rename , which changes the uSNChanged , but not any
of the replicated attributes
*/
2009-09-12 05:14:29 +04:00
obj - > meta_data_ctr - > count = n ;
2009-09-24 00:56:10 +04:00
obj - > object . flags = DRSUAPI_DS_REPLICA_OBJECT_FROM_MASTER ;
2009-09-09 17:38:51 +04:00
obj - > object . attribute_ctr . num_attributes = obj - > meta_data_ctr - > count ;
obj - > object . attribute_ctr . attributes = talloc_array ( obj , struct drsuapi_DsReplicaAttribute ,
obj - > object . attribute_ctr . num_attributes ) ;
/*
* Note that the meta_data array and the attributes array must
* be the same size and in the same order
*/
for ( i = 0 ; i < obj - > object . attribute_ctr . num_attributes ; i + + ) {
struct ldb_message_element * el ;
WERROR werr ;
2009-09-24 00:56:10 +04:00
const struct dsdb_attribute * sa ;
2009-09-12 05:14:29 +04:00
sa = dsdb_attribute_by_attributeID_id ( schema , attids [ i ] ) ;
2009-09-09 17:38:51 +04:00
if ( ! sa ) {
2009-09-12 05:14:29 +04:00
DEBUG ( 0 , ( " Unable to find attributeID %u in schema \n " , attids [ i ] ) ) ;
2009-09-09 17:38:51 +04:00
return WERR_DS_DRA_INTERNAL_ERROR ;
}
el = ldb_msg_find_element ( msg , sa - > lDAPDisplayName ) ;
if ( el = = NULL ) {
2009-12-03 01:19:55 +03:00
/* this happens for attributes that have been removed */
DEBUG ( 5 , ( " No element '%s' for attributeID %u in message \n " ,
2009-09-12 05:14:29 +04:00
sa - > lDAPDisplayName , attids [ i ] ) ) ;
2009-09-09 19:27:12 +04:00
ZERO_STRUCT ( obj - > object . attribute_ctr . attributes [ i ] ) ;
2009-09-12 05:14:29 +04:00
obj - > object . attribute_ctr . attributes [ i ] . attid = attids [ i ] ;
2009-09-09 19:27:12 +04:00
} else {
werr = dsdb_attribute_ldb_to_drsuapi ( sam_ctx , schema , el , obj ,
& obj - > object . attribute_ctr . attributes [ i ] ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " Unable to convert %s to DRS object - %s \n " ,
sa - > lDAPDisplayName , win_errstr ( werr ) ) ) ;
return werr ;
}
2009-10-14 13:29:39 +04:00
/* if DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING is set
s4: Handle DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING in getncchanges
When this flag is specified in the request these attributes are treated as
secret: currentValue, dBCSPwd, initialAuthIncoming, initialAuthOutgoing,
lmPwdHistory, ntPwdHistory, priorValue, supplementalCredentials,
trustAuthIncoming, trustAuthOutgoing, unicodePwd
Their value is changed to NULL and the meta_data.originating_change_time to 0
2009-09-24 03:51:55 +04:00
* check if attribute is secret and send a null value
*/
2009-10-14 13:29:39 +04:00
if ( replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING ) {
s4: Handle DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING in getncchanges
When this flag is specified in the request these attributes are treated as
secret: currentValue, dBCSPwd, initialAuthIncoming, initialAuthOutgoing,
lmPwdHistory, ntPwdHistory, priorValue, supplementalCredentials,
trustAuthIncoming, trustAuthOutgoing, unicodePwd
Their value is changed to NULL and the meta_data.originating_change_time to 0
2009-09-24 03:51:55 +04:00
drsuapi_process_secret_attribute ( & obj - > object . attribute_ctr . attributes [ i ] ,
& obj - > meta_data_ctr - > meta_data [ i ] ) ;
}
2009-09-10 11:46:30 +04:00
/* some attributes needs to be encrypted
before being sent */
werr = drsuapi_encrypt_attribute ( obj , session_key , rid ,
& obj - > object . attribute_ctr . attributes [ i ] ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " Unable to encrypt %s in DRS object - %s \n " ,
sa - > lDAPDisplayName , win_errstr ( werr ) ) ) ;
return werr ;
}
2009-09-09 15:26:17 +04:00
}
}
return WERR_OK ;
}
2009-12-19 04:25:09 +03:00
/*
add one linked attribute from an object to the list of linked
attributes in a getncchanges request
*/
static WERROR get_nc_changes_add_la ( TALLOC_CTX * mem_ctx ,
struct ldb_context * sam_ctx ,
const struct dsdb_schema * schema ,
const struct dsdb_attribute * sa ,
struct ldb_message * msg ,
struct dsdb_dn * dsdb_dn ,
struct drsuapi_DsReplicaLinkedAttribute * * la_list ,
uint32_t * la_count )
{
struct drsuapi_DsReplicaLinkedAttribute * la ;
bool active ;
NTSTATUS status ;
WERROR werr ;
( * la_list ) = talloc_realloc ( mem_ctx , * la_list , struct drsuapi_DsReplicaLinkedAttribute , ( * la_count ) + 1 ) ;
W_ERROR_HAVE_NO_MEMORY ( * la_list ) ;
la = & ( * la_list ) [ * la_count ] ;
la - > identifier = get_object_identifier ( * la_list , msg ) ;
W_ERROR_HAVE_NO_MEMORY ( la - > identifier ) ;
2010-01-02 00:14:52 +03:00
active = ( dsdb_dn_rmd_flags ( dsdb_dn - > dn ) & DSDB_RMD_FLAG_DELETED ) = = 0 ;
2009-12-19 04:25:09 +03:00
la - > attid = sa - > attributeID_id ;
la - > flags = active ? DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE : 0 ;
status = dsdb_get_extended_dn_nttime ( dsdb_dn - > dn , & la - > originating_add_time , " RMD_ADDTIME " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
status = dsdb_get_extended_dn_uint32 ( dsdb_dn - > dn , & la - > meta_data . version , " RMD_VERSION " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
status = dsdb_get_extended_dn_nttime ( dsdb_dn - > dn , & la - > meta_data . originating_change_time , " RMD_CHANGETIME " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
status = dsdb_get_extended_dn_guid ( dsdb_dn - > dn , & la - > meta_data . originating_invocation_id , " RMD_INVOCID " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
status = dsdb_get_extended_dn_uint64 ( dsdb_dn - > dn , & la - > meta_data . originating_usn , " RMD_ORIGINATING_USN " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
2009-12-28 09:19:29 +03:00
werr = dsdb_dn_la_to_blob ( sam_ctx , sa , schema , * la_list , dsdb_dn , & la - > value . blob ) ;
2009-12-19 04:25:09 +03:00
W_ERROR_NOT_OK_RETURN ( werr ) ;
( * la_count ) + + ;
return WERR_OK ;
}
/*
add linked attributes from an object to the list of linked
attributes in a getncchanges request
*/
static WERROR get_nc_changes_add_links ( struct ldb_context * sam_ctx ,
TALLOC_CTX * mem_ctx ,
struct ldb_dn * ncRoot_dn ,
struct dsdb_schema * schema ,
uint64_t highest_usn ,
uint32_t replica_flags ,
struct ldb_message * msg ,
struct drsuapi_DsReplicaLinkedAttribute * * la_list ,
uint32_t * la_count )
{
int i ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
2009-12-19 16:12:35 +03:00
uint64_t uSNChanged = ldb_msg_find_attr_as_int ( msg , " uSNChanged " , - 1 ) ;
2009-12-19 04:25:09 +03:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
struct ldb_message_element * el = & msg - > elements [ i ] ;
const struct dsdb_attribute * sa ;
int j ;
sa = dsdb_attribute_by_lDAPDisplayName ( schema , el - > name ) ;
if ( ! sa | | sa - > linkID = = 0 | | ( sa - > linkID & 1 ) ) {
/* we only want forward links */
continue ;
}
2009-12-19 12:59:04 +03:00
if ( el - > num_values & & ! dsdb_dn_is_upgraded_link_val ( & el - > values [ 0 ] ) ) {
/* its an old style link, it will have been
* sent in the main replication data */
continue ;
}
2009-12-19 04:25:09 +03:00
for ( j = 0 ; j < el - > num_values ; j + + ) {
struct dsdb_dn * dsdb_dn ;
uint64_t local_usn ;
NTSTATUS status ;
WERROR werr ;
dsdb_dn = dsdb_dn_parse ( tmp_ctx , sam_ctx , & el - > values [ j ] , sa - > syntax - > ldap_oid ) ;
if ( dsdb_dn = = NULL ) {
DEBUG ( 1 , ( __location__ " : Failed to parse DN for %s in %s \n " ,
el - > name , ldb_dn_get_linearized ( msg - > dn ) ) ) ;
talloc_free ( tmp_ctx ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
status = dsdb_get_extended_dn_uint64 ( dsdb_dn - > dn , & local_usn , " RMD_LOCAL_USN " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* this can happen for attributes
given to us with old style meta
data */
continue ;
}
2009-12-19 16:12:35 +03:00
if ( local_usn > uSNChanged ) {
DEBUG ( 1 , ( __location__ " : uSNChanged less than RMD_LOCAL_USN for %s on %s \n " ,
el - > name , ldb_dn_get_linearized ( msg - > dn ) ) ) ;
talloc_free ( tmp_ctx ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2009-12-19 04:25:09 +03:00
if ( local_usn < highest_usn ) {
continue ;
}
werr = get_nc_changes_add_la ( mem_ctx , sam_ctx , schema , sa , msg ,
2009-12-21 13:12:19 +03:00
dsdb_dn , la_list , la_count ) ;
2009-12-19 04:25:09 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
talloc_free ( tmp_ctx ) ;
return werr ;
}
}
}
talloc_free ( tmp_ctx ) ;
return WERR_OK ;
}
2009-09-12 05:14:29 +04:00
/*
load replUpToDateVector from a DN
*/
static WERROR load_udv ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
struct ldb_dn * dn , struct replUpToDateVectorBlob * ouv )
2009-09-10 13:41:48 +04:00
{
2009-09-12 05:14:29 +04:00
const char * attrs [ ] = { " replUpToDateVector " , NULL } ;
struct ldb_result * res = NULL ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
struct ldb_message_element * el ;
enum ndr_err_code ndr_err ;
ZERO_STRUCTP ( ouv ) ;
if ( ldb_search ( sam_ctx , tmp_ctx , & res , dn , LDB_SCOPE_BASE , attrs , NULL ) ! = LDB_SUCCESS | |
res - > count < 1 ) {
DEBUG ( 0 , ( " load_udv: failed to read partition object \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2009-09-10 13:41:48 +04:00
2009-09-12 05:14:29 +04:00
el = ldb_msg_find_element ( res - > msgs [ 0 ] , " replUpToDateVector " ) ;
if ( el = = NULL | | el - > num_values < 1 ) {
talloc_free ( tmp_ctx ) ;
ouv - > version = 2 ;
return WERR_OK ;
}
2009-09-10 13:41:48 +04:00
2009-09-12 05:14:29 +04:00
ndr_err = ndr_pull_struct_blob ( & el - > values [ 0 ] ,
mem_ctx , lp_iconv_convenience ( ldb_get_opaque ( sam_ctx , " loadparm " ) ) ,
ouv ,
( ndr_pull_flags_fn_t ) ndr_pull_replUpToDateVectorBlob ) ;
talloc_free ( tmp_ctx ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( __location__ " : Failed to parse replUpToDateVector for %s \n " ,
ldb_dn_get_linearized ( dn ) ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
return WERR_OK ;
}
/*
fill in the cursors return based on the replUpToDateVector for the ncRoot_dn
*/
static WERROR get_nc_changes_udv ( struct ldb_context * sam_ctx ,
struct ldb_dn * ncRoot_dn ,
2009-12-03 01:19:55 +03:00
struct drsuapi_DsReplicaCursor2CtrEx * udv ,
uint64_t highestUSN )
2009-09-12 05:14:29 +04:00
{
WERROR werr ;
struct drsuapi_DsReplicaCursor2 * tmp_cursor ;
NTTIME now ;
time_t t = time ( NULL ) ;
struct replUpToDateVectorBlob ouv ;
2009-12-20 02:27:03 +03:00
int i ;
2009-09-12 05:14:29 +04:00
werr = load_udv ( sam_ctx , udv , ncRoot_dn , & ouv ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
tmp_cursor = talloc ( udv , struct drsuapi_DsReplicaCursor2 ) ;
tmp_cursor - > source_dsa_invocation_id = * ( samdb_ntds_invocation_id ( sam_ctx ) ) ;
2009-12-03 01:19:55 +03:00
tmp_cursor - > highest_usn = highestUSN ;
2009-09-12 05:14:29 +04:00
unix_to_nt_time ( & now , t ) ;
tmp_cursor - > last_sync_success = now ;
2009-12-20 02:27:03 +03:00
udv - > count = ouv . ctr . ctr2 . count ;
2009-09-12 05:14:29 +04:00
udv - > cursors = talloc_steal ( udv , ouv . ctr . ctr2 . cursors ) ;
2009-12-20 02:27:03 +03:00
for ( i = 0 ; i < udv - > count ; i + + ) {
if ( GUID_equal ( & tmp_cursor - > source_dsa_invocation_id ,
& udv - > cursors [ i ] . source_dsa_invocation_id ) ) {
udv - > cursors [ i ] = * tmp_cursor ;
break ;
}
}
if ( i = = udv - > count ) {
udv - > cursors = talloc_realloc ( udv , udv - > cursors , struct drsuapi_DsReplicaCursor2 , udv - > count + 1 ) ;
if ( ! udv - > cursors ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
udv - > cursors [ udv - > count ] = * tmp_cursor ;
udv - > count + + ;
2009-09-12 05:14:29 +04:00
}
qsort ( udv - > cursors , udv - > count ,
sizeof ( struct drsuapi_DsReplicaCursor2 ) ,
2009-09-14 22:46:59 +04:00
( comparison_fn_t ) drsuapi_DsReplicaCursor2_compare ) ;
2009-09-12 05:14:29 +04:00
2009-09-10 13:41:48 +04:00
return WERR_OK ;
}
2009-12-28 09:22:40 +03:00
/* comparison function for linked attributes - see CompareLinks() in
* MS - DRSR section 4.1 .10 .5 .17 */
static int linked_attribute_compare ( const struct drsuapi_DsReplicaLinkedAttribute * la1 ,
const struct drsuapi_DsReplicaLinkedAttribute * la2 ,
struct ldb_context * sam_ctx )
{
int c ;
WERROR werr ;
TALLOC_CTX * tmp_ctx ;
const struct dsdb_schema * schema ;
const struct dsdb_attribute * schema_attrib ;
struct dsdb_dn * dn1 , * dn2 ;
struct GUID guid1 , guid2 ;
NTSTATUS status ;
c = GUID_compare ( & la1 - > identifier - > guid ,
& la2 - > identifier - > guid ) ;
if ( c ! = 0 ) return c ;
if ( la1 - > attid ! = la2 - > attid ) {
return la1 - > attid < la2 - > attid ? - 1 : 1 ;
}
if ( ( la1 - > flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE ) ! =
( la2 - > flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE ) ) {
return ( la1 - > flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE ) ? 1 : - 1 ;
}
/* we need to get the target GUIDs to compare */
tmp_ctx = talloc_new ( sam_ctx ) ;
schema = dsdb_get_schema ( sam_ctx ) ;
schema_attrib = dsdb_attribute_by_attributeID_id ( schema , la1 - > attid ) ;
werr = dsdb_dn_la_from_blob ( sam_ctx , schema_attrib , schema , tmp_ctx , la1 - > value . blob , & dn1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( __location__ " : Bad la1 blob in sort \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return 0 ;
}
werr = dsdb_dn_la_from_blob ( sam_ctx , schema_attrib , schema , tmp_ctx , la2 - > value . blob , & dn2 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( __location__ " : Bad la2 blob in sort \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return 0 ;
}
status = dsdb_get_extended_dn_guid ( dn1 - > dn , & guid1 , " GUID " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( __location__ " : Bad la1 guid in sort \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return 0 ;
}
status = dsdb_get_extended_dn_guid ( dn2 - > dn , & guid2 , " GUID " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( __location__ " : Bad la2 guid in sort \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return 0 ;
}
talloc_free ( tmp_ctx ) ;
return GUID_compare ( & guid1 , & guid2 ) ;
}
2009-12-21 13:10:41 +03:00
/*
sort the objects we send by tree order
*/
static int site_res_cmp_parent_order ( const struct ldb_message * * m1 , const struct ldb_message * * m2 )
{
return ldb_dn_compare ( ( * m2 ) - > dn , ( * m1 ) - > dn ) ;
}
/*
sort the objects we send first by uSNChanged
*/
static int site_res_cmp_usn_order ( const struct ldb_message * * m1 , const struct ldb_message * * m2 )
{
unsigned usnchanged1 , usnchanged2 ;
unsigned cn1 , cn2 ;
cn1 = ldb_dn_get_comp_num ( ( * m1 ) - > dn ) ;
cn2 = ldb_dn_get_comp_num ( ( * m2 ) - > dn ) ;
if ( cn1 ! = cn2 ) {
return cn1 > cn2 ? 1 : - 1 ;
}
usnchanged1 = ldb_msg_find_attr_as_uint ( * m1 , " uSNChanged " , 0 ) ;
usnchanged2 = ldb_msg_find_attr_as_uint ( * m2 , " uSNChanged " , 0 ) ;
if ( usnchanged1 = = usnchanged2 ) {
return 0 ;
}
return usnchanged1 > usnchanged2 ? 1 : - 1 ;
}
2010-01-06 11:35:05 +03:00
/*
handle a DRSUAPI_EXOP_FSMO_RID_ALLOC call
*/
static WERROR getncchanges_rid_alloc ( struct drsuapi_bind_state * b_state ,
TALLOC_CTX * mem_ctx ,
struct drsuapi_DsGetNCChangesRequest8 * req8 ,
struct drsuapi_DsGetNCChangesCtr6 * ctr6 )
{
struct ldb_dn * rid_manager_dn , * fsmo_role_dn , * req_dn ;
int ret ;
struct ldb_context * ldb = b_state - > sam_ctx ;
struct ldb_result * ext_res ;
struct ldb_dn * base_dn ;
struct dsdb_fsmo_extended_op * exop ;
/*
steps :
- verify that the DN being asked for is the RID Manager DN
- verify that we are the RID Manager
*/
/* work out who is the RID Manager */
ret = samdb_rid_manager_dn ( ldb , mem_ctx , & rid_manager_dn ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-01-07 10:38:39 +03:00
DEBUG ( 0 , ( __location__ " : Failed to find RID Manager object - %s \n " , ldb_errstring ( ldb ) ) ) ;
2010-01-06 11:35:05 +03:00
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2010-01-09 01:03:45 +03:00
req_dn = ldb_dn_new ( mem_ctx , ldb , req8 - > naming_context - > dn ) ;
2010-01-06 11:35:05 +03:00
if ( ! req_dn | |
! ldb_dn_validate ( req_dn ) | |
2010-01-07 10:38:39 +03:00
ldb_dn_compare ( req_dn , rid_manager_dn ) ! = 0 ) {
2010-01-06 11:35:05 +03:00
/* that isn't the RID Manager DN */
2010-01-07 10:38:39 +03:00
DEBUG ( 0 , ( __location__ " : RID Alloc request for wrong DN %s \n " ,
2010-01-06 12:56:19 +03:00
req8 - > naming_context - > dn ) ) ;
2010-01-06 11:35:05 +03:00
ctr6 - > extended_ret = DRSUAPI_EXOP_ERR_MISMATCH ;
return WERR_OK ;
}
/* find the DN of the RID Manager */
ret = samdb_reference_dn ( ldb , mem_ctx , rid_manager_dn , " fSMORoleOwner " , & fsmo_role_dn ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-01-07 10:38:39 +03:00
DEBUG ( 0 , ( __location__ " : Failed to find fSMORoleOwner in RID Manager object - %s \n " ,
2010-01-06 11:35:05 +03:00
ldb_errstring ( ldb ) ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
if ( ldb_dn_compare ( samdb_ntds_settings_dn ( ldb ) , fsmo_role_dn ) ! = 0 ) {
/* we're not the RID Manager - go away */
2010-01-07 10:38:39 +03:00
DEBUG ( 0 , ( __location__ " : RID Alloc request when not RID Manager \n " ) ) ;
2010-01-06 11:35:05 +03:00
ctr6 - > extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER ;
return WERR_OK ;
}
exop = talloc ( mem_ctx , struct dsdb_fsmo_extended_op ) ;
W_ERROR_HAVE_NO_MEMORY ( exop ) ;
exop - > fsmo_info = req8 - > fsmo_info ;
exop - > destination_dsa_guid = req8 - > destination_dsa_guid ;
2010-01-07 10:38:39 +03:00
ret = ldb_transaction_start ( ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " : Failed transaction start - %s \n " ,
ldb_errstring ( ldb ) ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2010-01-06 11:35:05 +03:00
ret = ldb_extended ( ldb , DSDB_EXTENDED_ALLOCATE_RID_POOL , exop , & ext_res ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " : Failed extended allocation RID pool operation - %s \n " ,
ldb_errstring ( ldb ) ) ) ;
2010-01-07 10:38:39 +03:00
ldb_transaction_cancel ( ldb ) ;
2010-01-06 11:35:05 +03:00
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2010-01-07 10:38:39 +03:00
ret = ldb_transaction_commit ( ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " : Failed transaction commit - %s \n " ,
ldb_errstring ( ldb ) ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2010-01-06 11:35:05 +03:00
talloc_free ( ext_res ) ;
base_dn = samdb_base_dn ( ldb ) ;
2010-01-06 12:56:19 +03:00
DEBUG ( 2 , ( " Allocated RID pool for server %s \n " ,
GUID_string ( mem_ctx , & req8 - > destination_dsa_guid ) ) ) ;
2010-01-06 11:35:05 +03:00
/* to complete the rest of the operation we need to point
getncchanges at the base DN for the domain */
req8 - > naming_context - > dn = ldb_dn_get_linearized ( base_dn ) ;
ret = dsdb_find_guid_by_dn ( ldb , base_dn , & req8 - > naming_context - > guid ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " : Failed to find base DN GUID - %s \n " ,
ldb_errstring ( ldb ) ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
return WERR_OK ;
}
2009-09-26 02:17:44 +04:00
/* state of a partially completed getncchanges call */
struct drsuapi_getncchanges_state {
struct ldb_result * site_res ;
uint32_t num_sent ;
struct ldb_dn * ncRoot_dn ;
2009-12-03 01:19:55 +03:00
uint64_t min_usn ;
uint64_t highest_usn ;
2009-12-19 16:12:35 +03:00
struct ldb_dn * last_dn ;
2009-12-21 13:13:59 +03:00
struct drsuapi_DsReplicaLinkedAttribute * la_list ;
uint32_t la_count ;
2009-09-26 02:17:44 +04:00
} ;
2009-09-09 15:00:01 +04:00
/*
drsuapi_DsGetNCChanges
2009-10-13 12:49:08 +04:00
see MS - DRSR 4.1 .10 .5 .2 for basic logic of this function
2009-09-09 15:00:01 +04:00
*/
WERROR dcesrv_drsuapi_DsGetNCChanges ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct drsuapi_DsGetNCChanges * r )
{
struct drsuapi_DsReplicaObjectIdentifier * ncRoot ;
int ret ;
int i ;
struct dsdb_schema * schema ;
struct drsuapi_DsReplicaOIDMapping_Ctr * ctr ;
2009-09-12 05:14:29 +04:00
struct drsuapi_DsReplicaObjectListItemEx * * currentObject ;
2009-09-10 11:46:30 +04:00
NTSTATUS status ;
DATA_BLOB session_key ;
2009-12-16 11:45:22 +03:00
const char * attrs [ ] = { " * " , " distinguishedName " ,
" nTSecurityDescriptor " ,
2009-12-09 06:38:25 +03:00
" parentGUID " ,
2009-12-16 11:45:22 +03:00
" replPropertyMetaData " ,
" unicodePwd " ,
" dBCSPwd " ,
" ntPwdHistory " ,
" lmPwdHistory " ,
" supplementalCredentials " ,
2009-11-20 07:19:35 +03:00
NULL } ;
2009-09-12 05:14:29 +04:00
WERROR werr ;
2009-09-26 02:17:44 +04:00
struct dcesrv_handle * h ;
struct drsuapi_bind_state * b_state ;
struct drsuapi_getncchanges_state * getnc_state ;
2009-10-13 12:49:08 +04:00
struct drsuapi_DsGetNCChangesRequest8 * req8 ;
uint32_t options ;
2009-12-19 16:12:35 +03:00
uint32_t max_objects ;
2009-09-26 02:17:44 +04:00
DCESRV_PULL_HANDLE_WERR ( h , r - > in . bind_handle , DRSUAPI_BIND_HANDLE ) ;
b_state = h - > data ;
2009-09-24 02:47:14 +04:00
2009-09-16 06:26:33 +04:00
* r - > out . level_out = 6 ;
/* TODO: linked attributes*/
r - > out . ctr - > ctr6 . linked_attributes_count = 0 ;
r - > out . ctr - > ctr6 . linked_attributes = NULL ;
2009-09-09 15:26:17 +04:00
2009-09-16 06:26:33 +04:00
r - > out . ctr - > ctr6 . object_count = 0 ;
2009-09-26 02:17:44 +04:00
r - > out . ctr - > ctr6 . nc_object_count = 0 ;
2009-09-16 06:26:33 +04:00
r - > out . ctr - > ctr6 . more_data = false ;
r - > out . ctr - > ctr6 . uptodateness_vector = NULL ;
2009-09-09 15:00:01 +04:00
2009-10-13 12:49:08 +04:00
/* a RODC doesn't allow for any replication */
if ( samdb_rodc ( ldb_get_opaque ( b_state - > sam_ctx , " loadparm " ) ) ) {
DEBUG ( 0 , ( __location__ " : DsGetNCChanges attempt on RODC \n " ) ) ;
return WERR_DS_DRA_SOURCE_DISABLED ;
}
/* Check request revision.
TODO : Adding mappings to req8 from the other levels
*/
2009-09-09 15:00:01 +04:00
if ( r - > in . level ! = 8 ) {
2009-10-13 12:49:08 +04:00
DEBUG ( 0 , ( __location__ " : Request for DsGetNCChanges with unsupported level %u \n " ,
r - > in . level ) ) ;
2009-09-09 15:00:01 +04:00
return WERR_REVISION_MISMATCH ;
}
2009-10-13 12:49:08 +04:00
req8 = & r - > in . req - > req8 ;
2009-09-09 15:00:01 +04:00
/* Perform access checks. */
2009-12-03 01:19:55 +03:00
/* TODO: we need to support a sync on a specific non-root
* DN . We ' ll need to find the real partition root here */
2009-10-13 12:49:08 +04:00
ncRoot = req8 - > naming_context ;
if ( ncRoot = = NULL ) {
DEBUG ( 0 , ( __location__ " : Request for DsGetNCChanges with no NC \n " ) ) ;
2009-09-09 15:00:01 +04:00
return WERR_DS_DRA_INVALID_PARAMETER ;
}
2009-10-13 12:49:08 +04:00
if ( samdb_ntds_options ( b_state - > sam_ctx , & options ) ! = LDB_SUCCESS ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
if ( ( options & DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL ) & &
! ( req8 - > replica_flags & DRSUAPI_DRS_SYNC_FORCED ) ) {
return WERR_DS_DRA_SOURCE_DISABLED ;
2009-09-09 15:00:01 +04:00
}
2009-10-13 12:49:08 +04:00
if ( req8 - > replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_SYNC_PACKET ) {
2009-09-24 03:58:58 +04:00
/* Ignore the _in_ uptpdateness vector*/
2009-10-13 12:49:08 +04:00
req8 - > uptodateness_vector = NULL ;
2009-09-24 03:58:58 +04:00
}
2009-09-20 02:08:19 +04:00
werr = drs_security_level_check ( dce_call , " DsGetNCChanges " ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
2009-09-16 06:26:33 +04:00
}
2010-01-06 11:35:05 +03:00
/* we don't yet support extended operations */
switch ( req8 - > extended_op ) {
case DRSUAPI_EXOP_NONE :
break ;
case DRSUAPI_EXOP_FSMO_RID_ALLOC :
werr = getncchanges_rid_alloc ( b_state , mem_ctx , req8 , & r - > out . ctr - > ctr6 ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
break ;
case DRSUAPI_EXOP_FSMO_REQ_ROLE :
case DRSUAPI_EXOP_FSMO_RID_REQ_ROLE :
case DRSUAPI_EXOP_FSMO_REQ_PDC :
case DRSUAPI_EXOP_FSMO_ABANDON_ROLE :
case DRSUAPI_EXOP_REPL_OBJ :
case DRSUAPI_EXOP_REPL_SECRET :
DEBUG ( 0 , ( __location__ " : Request for DsGetNCChanges unsupported extended op 0x%x \n " ,
( unsigned ) req8 - > extended_op ) ) ;
return WERR_DS_DRA_NOT_SUPPORTED ;
}
2009-09-26 02:17:44 +04:00
getnc_state = b_state - > getncchanges_state ;
2009-12-03 01:19:55 +03:00
/* see if a previous replication has been abandoned */
if ( getnc_state ) {
struct ldb_dn * new_dn = ldb_dn_new ( getnc_state , b_state - > sam_ctx , ncRoot - > dn ) ;
if ( ldb_dn_compare ( new_dn , getnc_state - > ncRoot_dn ) ! = 0 ) {
2009-12-19 16:12:35 +03:00
DEBUG ( 0 , ( __location__ " : DsGetNCChanges 2nd replication on different DN %s %s (last_dn %s) \n " ,
2009-12-03 01:19:55 +03:00
ldb_dn_get_linearized ( new_dn ) ,
2009-12-19 16:12:35 +03:00
ldb_dn_get_linearized ( getnc_state - > ncRoot_dn ) ,
ldb_dn_get_linearized ( getnc_state - > last_dn ) ) ) ;
2009-12-03 01:19:55 +03:00
talloc_free ( getnc_state ) ;
getnc_state = NULL ;
}
}
2009-09-26 02:17:44 +04:00
if ( getnc_state = = NULL ) {
getnc_state = talloc_zero ( b_state , struct drsuapi_getncchanges_state ) ;
if ( getnc_state = = NULL ) {
return WERR_NOMEM ;
}
b_state - > getncchanges_state = getnc_state ;
2009-12-09 06:39:05 +03:00
getnc_state - > ncRoot_dn = ldb_dn_new ( getnc_state , b_state - > sam_ctx , ncRoot - > dn ) ;
}
if ( ! ldb_dn_validate ( getnc_state - > ncRoot_dn ) | |
ldb_dn_is_null ( getnc_state - > ncRoot_dn ) ) {
DEBUG ( 0 , ( __location__ " : Bad DN '%s' \n " , ncRoot - > dn ) ) ;
return WERR_DS_DRA_INVALID_PARAMETER ;
2009-09-16 06:26:33 +04:00
}
2009-09-10 11:46:30 +04:00
/* we need the session key for encrypting password attributes */
status = dcesrv_inherited_session_key ( dce_call - > conn , & session_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( __location__ " : Failed to get session key \n " ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2009-10-13 12:49:08 +04:00
/*
TODO : MS - DRSR section 4.1 .10 .1 .1
Work out if this is the start of a new cycle */
2009-09-26 02:17:44 +04:00
if ( getnc_state - > site_res = = NULL ) {
char * search_filter ;
enum ldb_scope scope = LDB_SCOPE_SUBTREE ;
2009-12-19 16:12:35 +03:00
const char * extra_filter ;
extra_filter = lp_parm_string ( dce_call - > conn - > dce_ctx - > lp_ctx , NULL , " drs " , " object filter " ) ;
2009-09-24 02:47:14 +04:00
2009-10-13 12:49:08 +04:00
getnc_state - > min_usn = req8 - > highwatermark . highest_usn ;
2009-09-24 03:52:34 +04:00
2009-09-26 02:17:44 +04:00
/* Construct response. */
search_filter = talloc_asprintf ( mem_ctx ,
" (uSNChanged>=%llu) " ,
( unsigned long long ) ( getnc_state - > min_usn + 1 ) ) ;
2009-10-13 06:09:07 +04:00
2009-12-19 16:12:35 +03:00
if ( extra_filter ) {
search_filter = talloc_asprintf ( mem_ctx , " (&%s(%s)) " , search_filter , extra_filter ) ;
}
2009-10-13 12:49:08 +04:00
if ( req8 - > replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_CRITICAL_ONLY ) {
2009-09-26 02:17:44 +04:00
search_filter = talloc_asprintf ( mem_ctx ,
" (&%s(isCriticalSystemObject=TRUE)) " ,
search_filter ) ;
}
2009-10-13 12:49:08 +04:00
if ( req8 - > replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_ASYNC_REP ) {
2009-09-26 02:17:44 +04:00
scope = LDB_SCOPE_BASE ;
}
2009-12-21 13:10:41 +03:00
DEBUG ( 1 , ( __location__ " : getncchanges on %s using filter %s \n " ,
2009-09-26 02:17:44 +04:00
ldb_dn_get_linearized ( getnc_state - > ncRoot_dn ) , search_filter ) ) ;
2009-10-06 11:59:30 +04:00
ret = drsuapi_search_with_extended_dn ( b_state - > sam_ctx , getnc_state , & getnc_state - > site_res ,
2009-09-26 02:17:44 +04:00
getnc_state - > ncRoot_dn , scope , attrs ,
search_filter ) ;
if ( ret ! = LDB_SUCCESS ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2009-12-21 13:10:41 +03:00
if ( req8 - > replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS ) {
qsort ( getnc_state - > site_res - > msgs ,
getnc_state - > site_res - > count ,
sizeof ( getnc_state - > site_res - > msgs [ 0 ] ) ,
( comparison_fn_t ) site_res_cmp_parent_order ) ;
} else {
qsort ( getnc_state - > site_res - > msgs ,
getnc_state - > site_res - > count ,
sizeof ( getnc_state - > site_res - > msgs [ 0 ] ) ,
( comparison_fn_t ) site_res_cmp_usn_order ) ;
}
2009-09-09 15:00:01 +04:00
}
/* Prefix mapping */
2009-10-06 11:59:30 +04:00
schema = dsdb_get_schema ( b_state - > sam_ctx ) ;
2009-09-09 15:00:01 +04:00
if ( ! schema ) {
2009-09-09 15:26:17 +04:00
DEBUG ( 0 , ( " No schema in sam_ctx \n " ) ) ;
return WERR_DS_DRA_INTERNAL_ERROR ;
2009-09-09 15:00:01 +04:00
}
2009-09-16 06:26:33 +04:00
r - > out . ctr - > ctr6 . naming_context = talloc ( mem_ctx , struct drsuapi_DsReplicaObjectIdentifier ) ;
* r - > out . ctr - > ctr6 . naming_context = * ncRoot ;
2009-10-06 11:59:30 +04:00
if ( dsdb_find_guid_by_dn ( b_state - > sam_ctx , getnc_state - > ncRoot_dn ,
2009-09-26 02:17:44 +04:00
& r - > out . ctr - > ctr6 . naming_context - > guid ) ! = LDB_SUCCESS ) {
2009-09-24 00:56:10 +04:00
DEBUG ( 0 , ( __location__ " : Failed to find GUID of ncRoot_dn %s \n " ,
2009-09-26 02:17:44 +04:00
ldb_dn_get_linearized ( getnc_state - > ncRoot_dn ) ) ) ;
2009-09-24 00:56:10 +04:00
return WERR_DS_DRA_INTERNAL_ERROR ;
}
/* find the SID if there is one */
2009-10-06 11:59:30 +04:00
dsdb_find_sid_by_dn ( b_state - > sam_ctx , getnc_state - > ncRoot_dn , & r - > out . ctr - > ctr6 . naming_context - > sid ) ;
2009-09-24 00:56:10 +04:00
2009-09-09 15:00:01 +04:00
dsdb_get_oid_mappings_drsuapi ( schema , true , mem_ctx , & ctr ) ;
r - > out . ctr - > ctr6 . mapping_ctr = * ctr ;
2009-10-06 11:59:30 +04:00
r - > out . ctr - > ctr6 . source_dsa_guid = * ( samdb_ntds_objectGUID ( b_state - > sam_ctx ) ) ;
r - > out . ctr - > ctr6 . source_dsa_invocation_id = * ( samdb_ntds_invocation_id ( b_state - > sam_ctx ) ) ;
2009-09-09 15:00:01 +04:00
2009-10-13 12:49:08 +04:00
r - > out . ctr - > ctr6 . old_highwatermark = req8 - > highwatermark ;
r - > out . ctr - > ctr6 . new_highwatermark = req8 - > highwatermark ;
2009-09-09 15:00:01 +04:00
2009-09-12 05:14:29 +04:00
r - > out . ctr - > ctr6 . first_object = NULL ;
currentObject = & r - > out . ctr - > ctr6 . first_object ;
2009-09-09 15:00:01 +04:00
2009-12-19 04:25:09 +03:00
/* use this to force single objects at a time, which is useful
* for working out what object is giving problems
*/
2009-12-19 16:12:35 +03:00
max_objects = lp_parm_int ( dce_call - > conn - > dce_ctx - > lp_ctx , NULL , " drs " , " max object sync " , 1000 ) ;
if ( req8 - > max_object_count < max_objects ) {
max_objects = req8 - > max_object_count ;
}
2009-12-19 04:25:09 +03:00
2009-09-26 02:17:44 +04:00
for ( i = getnc_state - > num_sent ;
i < getnc_state - > site_res - > count & &
2009-12-19 16:12:35 +03:00
( r - > out . ctr - > ctr6 . object_count < max_objects ) ;
2009-09-26 02:17:44 +04:00
i + + ) {
2009-09-09 15:26:17 +04:00
int uSN ;
2009-09-12 05:14:29 +04:00
struct drsuapi_DsReplicaObjectListItemEx * obj ;
2009-12-19 04:25:09 +03:00
struct ldb_message * msg = getnc_state - > site_res - > msgs [ i ] ;
2009-09-12 05:14:29 +04:00
obj = talloc_zero ( mem_ctx , struct drsuapi_DsReplicaObjectListItemEx ) ;
2009-09-09 15:26:17 +04:00
2009-12-19 04:25:09 +03:00
werr = get_nc_changes_build_object ( obj , msg ,
2009-10-06 11:59:30 +04:00
b_state - > sam_ctx , getnc_state - > ncRoot_dn ,
2009-09-26 02:17:44 +04:00
schema , & session_key , getnc_state - > min_usn ,
2009-10-13 12:49:08 +04:00
req8 - > replica_flags ) ;
2009-09-09 15:26:17 +04:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
2009-09-09 15:00:01 +04:00
}
2009-09-10 13:41:48 +04:00
2009-12-21 13:13:59 +03:00
werr = get_nc_changes_add_links ( b_state - > sam_ctx , getnc_state ,
2009-12-19 04:25:09 +03:00
getnc_state - > ncRoot_dn ,
schema , getnc_state - > min_usn ,
req8 - > replica_flags ,
msg ,
2009-12-21 13:13:59 +03:00
& getnc_state - > la_list ,
& getnc_state - > la_count ) ;
2009-12-19 04:25:09 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
2009-12-21 13:16:35 +03:00
uSN = ldb_msg_find_attr_as_int ( msg , " uSNChanged " , - 1 ) ;
if ( uSN > r - > out . ctr - > ctr6 . new_highwatermark . tmp_highest_usn ) {
r - > out . ctr - > ctr6 . new_highwatermark . tmp_highest_usn = uSN ;
}
if ( uSN > getnc_state - > highest_usn ) {
getnc_state - > highest_usn = uSN ;
}
2009-09-12 05:14:29 +04:00
if ( obj - > meta_data_ctr = = NULL ) {
2009-09-26 02:17:44 +04:00
DEBUG ( 0 , ( __location__ " : getncchanges skipping send of object %s \n " ,
2009-12-19 04:25:09 +03:00
ldb_dn_get_linearized ( msg - > dn ) ) ) ;
2009-09-12 05:14:29 +04:00
/* no attributes to send */
talloc_free ( obj ) ;
continue ;
2009-09-10 13:41:48 +04:00
}
2009-09-12 05:14:29 +04:00
r - > out . ctr - > ctr6 . object_count + + ;
* currentObject = obj ;
currentObject = & obj - > next_object ;
2009-12-19 04:25:09 +03:00
2009-12-19 16:12:35 +03:00
talloc_free ( getnc_state - > last_dn ) ;
getnc_state - > last_dn = ldb_dn_copy ( getnc_state , msg - > dn ) ;
2009-12-19 04:25:09 +03:00
DEBUG ( 8 , ( __location__ " : replicating object %s \n " , ldb_dn_get_linearized ( msg - > dn ) ) ) ;
2009-09-09 15:00:01 +04:00
}
2009-09-26 02:17:44 +04:00
getnc_state - > num_sent + = r - > out . ctr - > ctr6 . object_count ;
2009-09-12 05:14:29 +04:00
2009-09-26 02:17:44 +04:00
r - > out . ctr - > ctr6 . nc_object_count = getnc_state - > site_res - > count ;
2009-10-14 13:29:39 +04:00
/* the client can us to call UpdateRefs on its behalf to
re - establish monitoring of the NC */
if ( ( req8 - > replica_flags & DRSUAPI_DRS_ADD_REF ) & &
! GUID_all_zero ( & req8 - > destination_dsa_guid ) ) {
struct drsuapi_DsReplicaUpdateRefsRequest1 ureq ;
ureq . naming_context = ncRoot ;
ureq . dest_dsa_dns_name = talloc_asprintf ( mem_ctx , " %s._msdcs.%s " ,
GUID_string ( mem_ctx , & req8 - > destination_dsa_guid ) ,
lp_realm ( dce_call - > conn - > dce_ctx - > lp_ctx ) ) ;
if ( ! ureq . dest_dsa_dns_name ) {
return WERR_NOMEM ;
}
ureq . dest_dsa_guid = req8 - > destination_dsa_guid ;
ureq . options = DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE |
DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION |
DRSUAPI_DS_REPLICA_UPDATE_GETCHG_CHECK ;
werr = drsuapi_UpdateRefs ( b_state , mem_ctx , & ureq ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( __location__ " : Failed UpdateRefs in DsGetNCChanges - %s \n " ,
win_errstr ( werr ) ) ) ;
}
}
2009-09-26 02:17:44 +04:00
if ( i < getnc_state - > site_res - > count ) {
r - > out . ctr - > ctr6 . more_data = true ;
} else {
2009-12-21 13:13:59 +03:00
r - > out . ctr - > ctr6 . linked_attributes_count = getnc_state - > la_count ;
r - > out . ctr - > ctr6 . linked_attributes = talloc_steal ( mem_ctx , getnc_state - > la_list ) ;
2009-12-28 09:22:40 +03:00
ldb_qsort ( r - > out . ctr - > ctr6 . linked_attributes , r - > out . ctr - > ctr6 . linked_attributes_count ,
sizeof ( r - > out . ctr - > ctr6 . linked_attributes [ 0 ] ) ,
b_state - > sam_ctx , ( ldb_qsort_cmp_fn_t ) linked_attribute_compare ) ;
2009-09-26 02:17:44 +04:00
r - > out . ctr - > ctr6 . uptodateness_vector = talloc ( mem_ctx , struct drsuapi_DsReplicaCursor2CtrEx ) ;
r - > out . ctr - > ctr6 . uptodateness_vector - > version = 2 ;
r - > out . ctr - > ctr6 . uptodateness_vector - > reserved1 = 0 ;
r - > out . ctr - > ctr6 . uptodateness_vector - > reserved2 = 0 ;
r - > out . ctr - > ctr6 . new_highwatermark . highest_usn = r - > out . ctr - > ctr6 . new_highwatermark . tmp_highest_usn ;
2009-10-06 11:59:30 +04:00
werr = get_nc_changes_udv ( b_state - > sam_ctx , getnc_state - > ncRoot_dn ,
2009-12-03 01:19:55 +03:00
r - > out . ctr - > ctr6 . uptodateness_vector ,
getnc_state - > highest_usn ) ;
2009-09-26 02:17:44 +04:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
talloc_free ( getnc_state ) ;
b_state - > getncchanges_state = NULL ;
}
2009-09-12 05:14:29 +04:00
2009-12-19 16:12:35 +03:00
DEBUG ( r - > out . ctr - > ctr6 . more_data ? 2 : 1 ,
( " DsGetNCChanges with uSNChanged >= %llu flags 0x%08x on %s gave %u objects (done %d/%d la=%d) \n " ,
( unsigned long long ) ( req8 - > highwatermark . highest_usn + 1 ) ,
req8 - > replica_flags ,
ncRoot - > dn , r - > out . ctr - > ctr6 . object_count ,
i , r - > out . ctr - > ctr6 . more_data ? getnc_state - > site_res - > count : i ,
r - > out . ctr - > ctr6 . linked_attributes_count ) ) ;
#if 0
if ( ! r - > out . ctr - > ctr6 . more_data ) {
NDR_PRINT_FUNCTION_DEBUG ( drsuapi_DsGetNCChanges , NDR_BOTH , r ) ;
}
# endif
2009-09-12 05:14:29 +04:00
2009-09-09 15:00:01 +04:00
return WERR_OK ;
}