2008-06-24 01:13:21 +04:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Stefan ( metze ) Metzmacher 2005
Copyright ( C ) Guenther Deschner 2008
2008-08-01 16:26:46 +04:00
Copyright ( C ) Michael Adam 2008
2008-06-24 01:13:21 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 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"
2010-07-02 02:14:04 +04:00
# include "libnet/libnet_dssync.h"
2011-02-28 12:19:44 +03:00
# include "rpc_client/cli_pipe.h"
2009-03-16 07:20:28 +03:00
# include "../libcli/drsuapi/drsuapi.h"
2011-01-11 19:46:11 +03:00
# include "../librpc/gen_ndr/ndr_drsuapi_c.h"
2008-06-24 01:13:21 +04:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int libnet_dssync_free_context ( struct dssync_context * ctx )
{
2011-01-11 19:46:11 +03:00
WERROR result ;
struct dcerpc_binding_handle * b ;
2008-06-24 01:13:21 +04:00
if ( ! ctx ) {
return 0 ;
}
if ( is_valid_policy_hnd ( & ctx - > bind_handle ) & & ctx - > cli ) {
2011-01-11 19:46:11 +03:00
b = ctx - > cli - > binding_handle ;
dcerpc_drsuapi_DsUnbind ( b , ctx , & ctx - > bind_handle , & result ) ;
2008-06-24 01:13:21 +04:00
}
return 0 ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS libnet_dssync_init_context ( TALLOC_CTX * mem_ctx ,
struct dssync_context * * ctx_p )
{
struct dssync_context * ctx ;
2011-06-07 05:44:43 +04:00
ctx = talloc_zero ( mem_ctx , struct dssync_context ) ;
2008-06-24 01:13:21 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
talloc_set_destructor ( ctx , libnet_dssync_free_context ) ;
2008-08-01 02:09:28 +04:00
ctx - > clean_old_entries = false ;
2008-06-24 01:13:21 +04:00
* ctx_p = ctx ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-06-26 17:06:58 +04:00
static void parse_obj_identifier ( struct drsuapi_DsReplicaObjectIdentifier * id ,
uint32_t * rid )
{
if ( ! id | | ! rid ) {
return ;
}
* rid = 0 ;
if ( id - > sid . num_auths > 0 ) {
* rid = id - > sid . sub_auths [ id - > sid . num_auths - 1 ] ;
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void libnet_dssync_decrypt_attributes ( TALLOC_CTX * mem_ctx ,
DATA_BLOB * session_key ,
struct drsuapi_DsReplicaObjectListItemEx * cur )
{
for ( ; cur ; cur = cur - > next_object ) {
uint32_t i ;
uint32_t rid = 0 ;
parse_obj_identifier ( cur - > object . identifier , & rid ) ;
for ( i = 0 ; i < cur - > object . attribute_ctr . num_attributes ; i + + ) {
struct drsuapi_DsReplicaAttribute * attr ;
attr = & cur - > object . attribute_ctr . attributes [ i ] ;
if ( attr - > value_ctr . num_values < 1 ) {
continue ;
}
if ( ! attr - > value_ctr . values [ 0 ] . blob ) {
continue ;
}
2009-03-16 07:20:28 +03:00
drsuapi_decrypt_attribute ( mem_ctx ,
session_key ,
rid ,
attr ) ;
2008-06-26 17:06:58 +04:00
}
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-06-24 01:13:21 +04:00
static NTSTATUS libnet_dssync_bind ( TALLOC_CTX * mem_ctx ,
struct dssync_context * ctx )
{
NTSTATUS status ;
WERROR werr ;
struct GUID bind_guid ;
struct drsuapi_DsBindInfoCtr bind_info ;
struct drsuapi_DsBindInfo28 info28 ;
2011-01-11 19:46:11 +03:00
struct dcerpc_binding_handle * b = ctx - > cli - > binding_handle ;
2008-06-24 01:13:21 +04:00
ZERO_STRUCT ( info28 ) ;
GUID_from_string ( DRSUAPI_DS_BIND_GUID , & bind_guid ) ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_BASE ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7 ;
info28 . supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT ;
info28 . site_guid = GUID_zero ( ) ;
2008-07-22 18:18:03 +04:00
info28 . pid = 508 ;
2008-06-24 01:13:21 +04:00
info28 . repl_epoch = 0 ;
bind_info . length = 28 ;
bind_info . info . info28 = info28 ;
2011-01-11 19:46:11 +03:00
status = dcerpc_drsuapi_DsBind ( b , mem_ctx ,
2008-06-24 01:13:21 +04:00
& bind_guid ,
& bind_info ,
& ctx - > bind_handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werror_to_ntstatus ( werr ) ;
}
2008-07-17 15:04:04 +04:00
ZERO_STRUCT ( ctx - > remote_info28 ) ;
switch ( bind_info . length ) {
case 24 : {
struct drsuapi_DsBindInfo24 * info24 ;
info24 = & bind_info . info . info24 ;
ctx - > remote_info28 . site_guid = info24 - > site_guid ;
ctx - > remote_info28 . supported_extensions = info24 - > supported_extensions ;
ctx - > remote_info28 . pid = info24 - > pid ;
ctx - > remote_info28 . repl_epoch = 0 ;
break ;
}
2014-07-04 14:45:59 +04:00
case 28 : {
2008-07-17 15:04:04 +04:00
ctx - > remote_info28 = bind_info . info . info28 ;
break ;
2014-07-04 14:45:59 +04:00
}
case 32 : {
struct drsuapi_DsBindInfo32 * info32 ;
info32 = & bind_info . info . info32 ;
ctx - > remote_info28 . site_guid = info32 - > site_guid ;
ctx - > remote_info28 . supported_extensions = info32 - > supported_extensions ;
ctx - > remote_info28 . pid = info32 - > pid ;
ctx - > remote_info28 . repl_epoch = info32 - > repl_epoch ;
break ;
}
2008-07-17 15:04:04 +04:00
case 48 : {
struct drsuapi_DsBindInfo48 * info48 ;
info48 = & bind_info . info . info48 ;
ctx - > remote_info28 . site_guid = info48 - > site_guid ;
ctx - > remote_info28 . supported_extensions = info48 - > supported_extensions ;
ctx - > remote_info28 . pid = info48 - > pid ;
ctx - > remote_info28 . repl_epoch = info48 - > repl_epoch ;
break ;
}
2014-07-04 14:45:59 +04:00
case 52 : {
struct drsuapi_DsBindInfo52 * info52 ;
info52 = & bind_info . info . info52 ;
ctx - > remote_info28 . site_guid = info52 - > site_guid ;
ctx - > remote_info28 . supported_extensions = info52 - > supported_extensions ;
ctx - > remote_info28 . pid = info52 - > pid ;
ctx - > remote_info28 . repl_epoch = info52 - > repl_epoch ;
break ;
}
2008-07-17 15:04:04 +04:00
default :
DEBUG ( 1 , ( " Warning: invalid info length in bind info: %d \n " ,
bind_info . length ) ) ;
break ;
}
2008-06-24 01:13:21 +04:00
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS libnet_dssync_lookup_nc ( TALLOC_CTX * mem_ctx ,
struct dssync_context * ctx )
{
NTSTATUS status ;
WERROR werr ;
2010-03-05 23:50:57 +03:00
uint32_t level = 1 ;
2008-06-24 01:13:21 +04:00
union drsuapi_DsNameRequest req ;
2010-03-05 23:50:57 +03:00
uint32_t level_out ;
2008-06-24 01:13:21 +04:00
struct drsuapi_DsNameString names [ 1 ] ;
union drsuapi_DsNameCtr ctr ;
2011-01-11 19:46:11 +03:00
struct dcerpc_binding_handle * b = ctx - > cli - > binding_handle ;
2008-06-24 01:13:21 +04:00
names [ 0 ] . str = talloc_asprintf ( mem_ctx , " %s \\ " , ctx - > domain_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( names [ 0 ] . str ) ;
req . req1 . codepage = 1252 ; /* german */
req . req1 . language = 0x00000407 ; /* german */
req . req1 . count = 1 ;
req . req1 . names = names ;
req . req1 . format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS ;
2008-10-17 12:50:28 +04:00
req . req1 . format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN ;
2008-06-24 01:13:21 +04:00
req . req1 . format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ;
2011-01-11 19:46:11 +03:00
status = dcerpc_drsuapi_DsCrackNames ( b , mem_ctx ,
2008-06-24 01:13:21 +04:00
& ctx - > bind_handle ,
level ,
& req ,
& level_out ,
& ctr ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-08-01 19:10:59 +04:00
ctx - > error_message = talloc_asprintf ( ctx ,
2008-06-26 12:22:40 +04:00
" Failed to lookup DN for domain name: %s " ,
2011-01-12 15:41:16 +03:00
get_friendly_nt_error_msg ( status ) ) ;
2008-06-24 01:13:21 +04:00
return status ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
2011-01-12 15:41:16 +03:00
ctx - > error_message = talloc_asprintf ( ctx ,
" Failed to lookup DN for domain name: %s " ,
get_friendly_werror_msg ( werr ) ) ;
2008-06-24 01:13:21 +04:00
return werror_to_ntstatus ( werr ) ;
}
if ( ctr . ctr1 - > count ! = 1 ) {
return NT_STATUS_UNSUCCESSFUL ;
}
if ( ctr . ctr1 - > array [ 0 ] . status ! = DRSUAPI_DS_NAME_STATUS_OK ) {
return NT_STATUS_UNSUCCESSFUL ;
}
ctx - > nc_dn = talloc_strdup ( mem_ctx , ctr . ctr1 - > array [ 0 ] . result_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( ctx - > nc_dn ) ;
2008-06-27 01:24:25 +04:00
if ( ! ctx - > dns_domain_name ) {
ctx - > dns_domain_name = talloc_strdup_upper ( mem_ctx ,
ctr . ctr1 - > array [ 0 ] . dns_domain_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( ctx - > dns_domain_name ) ;
}
2008-06-24 01:13:21 +04:00
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS libnet_dssync_init ( TALLOC_CTX * mem_ctx ,
struct dssync_context * ctx )
{
NTSTATUS status ;
status = libnet_dssync_bind ( mem_ctx , ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! ctx - > nc_dn ) {
status = libnet_dssync_lookup_nc ( mem_ctx , ctx ) ;
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-07-30 12:27:00 +04:00
static NTSTATUS libnet_dssync_build_request ( TALLOC_CTX * mem_ctx ,
struct dssync_context * ctx ,
const char * dn ,
struct replUpToDateVectorBlob * utdv ,
2010-03-05 22:58:01 +03:00
uint32_t * plevel ,
2008-07-30 12:27:00 +04:00
union drsuapi_DsGetNCChangesRequest * preq )
2008-06-24 01:13:21 +04:00
{
NTSTATUS status ;
2008-07-30 12:27:00 +04:00
uint32_t count ;
2010-03-05 22:58:01 +03:00
uint32_t level ;
2008-06-24 01:13:21 +04:00
union drsuapi_DsGetNCChangesRequest req ;
struct dom_sid null_sid ;
2008-07-30 12:27:00 +04:00
enum drsuapi_DsExtendedOperation extended_op ;
struct drsuapi_DsReplicaObjectIdentifier * nc = NULL ;
struct drsuapi_DsReplicaCursorCtrEx * cursors = NULL ;
2008-06-24 01:13:21 +04:00
2010-01-17 13:59:56 +03:00
uint32_t replica_flags = DRSUAPI_DRS_WRIT_REP |
DRSUAPI_DRS_INIT_SYNC |
DRSUAPI_DRS_PER_SYNC |
DRSUAPI_DRS_GET_ANC |
DRSUAPI_DRS_NEVER_SYNCED ;
2008-06-24 01:13:21 +04:00
ZERO_STRUCT ( null_sid ) ;
ZERO_STRUCT ( req ) ;
2008-07-30 14:35:45 +04:00
if ( ctx - > remote_info28 . supported_extensions
& DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8 )
{
level = 8 ;
} else {
level = 5 ;
}
2011-06-07 05:44:43 +04:00
nc = talloc_zero ( mem_ctx , struct drsuapi_DsReplicaObjectIdentifier ) ;
2008-07-30 12:27:00 +04:00
if ( ! nc ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
nc - > dn = dn ;
nc - > guid = GUID_zero ( ) ;
nc - > sid = null_sid ;
2008-07-30 19:53:28 +04:00
if ( ! ctx - > single_object_replication & &
! ctx - > force_full_replication & & utdv )
{
2011-06-07 05:44:43 +04:00
cursors = talloc_zero ( mem_ctx ,
2008-07-30 12:27:00 +04:00
struct drsuapi_DsReplicaCursorCtrEx ) ;
if ( ! cursors ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
switch ( utdv - > version ) {
case 1 :
cursors - > count = utdv - > ctr . ctr1 . count ;
cursors - > cursors = utdv - > ctr . ctr1 . cursors ;
break ;
case 2 :
cursors - > count = utdv - > ctr . ctr2 . count ;
cursors - > cursors = talloc_array ( cursors ,
struct drsuapi_DsReplicaCursor ,
cursors - > count ) ;
if ( ! cursors - > cursors ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
for ( count = 0 ; count < cursors - > count ; count + + ) {
cursors - > cursors [ count ] . source_dsa_invocation_id =
utdv - > ctr . ctr2 . cursors [ count ] . source_dsa_invocation_id ;
cursors - > cursors [ count ] . highest_usn =
utdv - > ctr . ctr2 . cursors [ count ] . highest_usn ;
}
break ;
}
}
2008-07-30 19:53:28 +04:00
if ( ctx - > single_object_replication ) {
2008-07-30 12:27:00 +04:00
extended_op = DRSUAPI_EXOP_REPL_OBJ ;
2008-07-18 02:18:40 +04:00
} else {
2008-07-30 12:27:00 +04:00
extended_op = DRSUAPI_EXOP_NONE ;
2008-07-18 02:18:40 +04:00
}
2008-06-24 01:13:21 +04:00
2008-07-30 12:27:00 +04:00
if ( level = = 8 ) {
req . req8 . naming_context = nc ;
req . req8 . replica_flags = replica_flags ;
req . req8 . max_object_count = 402 ;
req . req8 . max_ndr_size = 402116 ;
req . req8 . uptodateness_vector = cursors ;
req . req8 . extended_op = extended_op ;
} else if ( level = = 5 ) {
req . req5 . naming_context = nc ;
req . req5 . replica_flags = replica_flags ;
req . req5 . max_object_count = 402 ;
req . req5 . max_ndr_size = 402116 ;
req . req5 . uptodateness_vector = cursors ;
req . req5 . extended_op = extended_op ;
} else {
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2008-07-18 02:18:40 +04:00
}
2008-07-30 14:35:45 +04:00
if ( plevel ) {
* plevel = level ;
}
2008-07-30 12:27:00 +04:00
if ( preq ) {
* preq = req ;
}
return NT_STATUS_OK ;
fail :
TALLOC_FREE ( nc ) ;
TALLOC_FREE ( cursors ) ;
return status ;
}
2008-07-30 14:32:30 +04:00
static NTSTATUS libnet_dssync_getncchanges ( TALLOC_CTX * mem_ctx ,
struct dssync_context * ctx ,
2010-03-05 22:58:01 +03:00
uint32_t level ,
2008-07-30 14:32:30 +04:00
union drsuapi_DsGetNCChangesRequest * req ,
struct replUpToDateVectorBlob * * pnew_utdv )
2008-07-30 12:27:00 +04:00
{
NTSTATUS status ;
WERROR werr ;
union drsuapi_DsGetNCChangesCtr ctr ;
struct drsuapi_DsGetNCChangesCtr1 * ctr1 = NULL ;
struct drsuapi_DsGetNCChangesCtr6 * ctr6 = NULL ;
2008-07-30 14:32:30 +04:00
struct replUpToDateVectorBlob * new_utdv = NULL ;
2010-03-05 22:58:01 +03:00
uint32_t level_out = 0 ;
uint32_t out_level = 0 ;
2008-07-30 12:27:00 +04:00
int y ;
2008-07-30 14:00:49 +04:00
bool last_query ;
2011-01-11 19:46:11 +03:00
struct dcerpc_binding_handle * b = ctx - > cli - > binding_handle ;
2008-07-30 12:27:00 +04:00
2008-07-30 19:53:28 +04:00
if ( ! ctx - > single_object_replication ) {
2011-06-07 05:44:43 +04:00
new_utdv = talloc_zero ( mem_ctx , struct replUpToDateVectorBlob ) ;
2008-07-30 14:32:30 +04:00
if ( ! new_utdv ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2008-07-30 12:27:00 +04:00
}
2008-07-30 14:00:49 +04:00
for ( y = 0 , last_query = false ; ! last_query ; y + + ) {
2008-08-08 04:49:19 +04:00
struct drsuapi_DsReplicaObjectListItemEx * first_object = NULL ;
struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr = NULL ;
2011-01-13 19:18:24 +03:00
uint32_t linked_attributes_count = 0 ;
struct drsuapi_DsReplicaLinkedAttribute * linked_attributes = NULL ;
2008-06-27 03:41:26 +04:00
2008-06-24 01:13:21 +04:00
if ( level = = 8 ) {
DEBUG ( 1 , ( " start[%d] tmp_higest_usn: %llu , highest_usn: %llu \n " , y ,
2008-07-30 14:32:30 +04:00
( long long ) req - > req8 . highwatermark . tmp_highest_usn ,
( long long ) req - > req8 . highwatermark . highest_usn ) ) ;
2008-07-17 15:05:43 +04:00
} else if ( level = = 5 ) {
DEBUG ( 1 , ( " start[%d] tmp_higest_usn: %llu , highest_usn: %llu \n " , y ,
2008-07-30 14:32:30 +04:00
( long long ) req - > req5 . highwatermark . tmp_highest_usn ,
( long long ) req - > req5 . highwatermark . highest_usn ) ) ;
2008-06-24 01:13:21 +04:00
}
2011-01-11 19:46:11 +03:00
status = dcerpc_drsuapi_DsGetNCChanges ( b , mem_ctx ,
2008-06-24 01:13:21 +04:00
& ctx - > bind_handle ,
level ,
2008-07-30 14:32:30 +04:00
req ,
2008-06-24 01:13:21 +04:00
& level_out ,
& ctr ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-08-01 19:10:59 +04:00
ctx - > error_message = talloc_asprintf ( ctx ,
2008-06-26 12:22:40 +04:00
" Failed to get NC Changes: %s " ,
2011-01-12 15:41:16 +03:00
get_friendly_nt_error_msg ( status ) ) ;
2008-06-24 01:13:21 +04:00
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
2008-06-26 12:22:40 +04:00
status = werror_to_ntstatus ( werr ) ;
2011-01-11 19:46:11 +03:00
ctx - > error_message = talloc_asprintf ( ctx ,
" Failed to get NC Changes: %s " ,
get_friendly_werror_msg ( werr ) ) ;
2008-06-24 01:13:21 +04:00
goto out ;
}
if ( level_out = = 1 ) {
out_level = 1 ;
ctr1 = & ctr . ctr1 ;
2008-10-16 16:03:10 +04:00
} else if ( level_out = = 2 & & ctr . ctr2 . mszip1 . ts ) {
2008-06-24 01:13:21 +04:00
out_level = 1 ;
2008-10-16 16:03:10 +04:00
ctr1 = & ctr . ctr2 . mszip1 . ts - > ctr1 ;
2008-07-30 14:00:49 +04:00
} else if ( level_out = = 6 ) {
out_level = 6 ;
ctr6 = & ctr . ctr6 ;
} else if ( level_out = = 7
& & ctr . ctr7 . level = = 6
2008-10-16 16:03:10 +04:00
& & ctr . ctr7 . type = = DRSUAPI_COMPRESSION_TYPE_MSZIP
& & ctr . ctr7 . ctr . mszip6 . ts ) {
2008-07-30 14:00:49 +04:00
out_level = 6 ;
2008-10-16 16:03:10 +04:00
ctr6 = & ctr . ctr7 . ctr . mszip6 . ts - > ctr6 ;
} else if ( level_out = = 7
& & ctr . ctr7 . level = = 6
& & ctr . ctr7 . type = = DRSUAPI_COMPRESSION_TYPE_XPRESS
& & ctr . ctr7 . ctr . xpress6 . ts ) {
out_level = 6 ;
ctr6 = & ctr . ctr7 . ctr . xpress6 . ts - > ctr6 ;
2008-06-24 01:13:21 +04:00
}
if ( out_level = = 1 ) {
DEBUG ( 1 , ( " end[%d] tmp_highest_usn: %llu , highest_usn: %llu \n " , y ,
( long long ) ctr1 - > new_highwatermark . tmp_highest_usn ,
( long long ) ctr1 - > new_highwatermark . highest_usn ) ) ;
2008-07-30 14:00:49 +04:00
first_object = ctr1 - > first_object ;
mapping_ctr = & ctr1 - > mapping_ctr ;
2008-06-26 17:06:58 +04:00
2008-07-16 17:30:03 +04:00
if ( ctr1 - > more_data ) {
2008-07-30 14:32:30 +04:00
req - > req5 . highwatermark = ctr1 - > new_highwatermark ;
2008-07-30 14:00:49 +04:00
} else {
last_query = true ;
2008-07-30 19:53:28 +04:00
if ( ctr1 - > uptodateness_vector & &
! ctx - > single_object_replication )
{
2008-07-30 14:32:30 +04:00
new_utdv - > version = 1 ;
new_utdv - > ctr . ctr1 . count =
2008-07-30 14:00:49 +04:00
ctr1 - > uptodateness_vector - > count ;
2008-07-30 14:32:30 +04:00
new_utdv - > ctr . ctr1 . cursors =
2008-07-30 14:00:49 +04:00
ctr1 - > uptodateness_vector - > cursors ;
2008-06-24 01:13:21 +04:00
}
}
2008-07-30 14:00:49 +04:00
} else if ( out_level = = 6 ) {
2008-06-24 01:13:21 +04:00
DEBUG ( 1 , ( " end[%d] tmp_highest_usn: %llu , highest_usn: %llu \n " , y ,
( long long ) ctr6 - > new_highwatermark . tmp_highest_usn ,
( long long ) ctr6 - > new_highwatermark . highest_usn ) ) ;
2008-07-30 14:00:49 +04:00
first_object = ctr6 - > first_object ;
mapping_ctr = & ctr6 - > mapping_ctr ;
2008-06-26 17:06:58 +04:00
2011-01-13 19:18:24 +03:00
linked_attributes = ctr6 - > linked_attributes ;
linked_attributes_count = ctr6 - > linked_attributes_count ;
2008-07-16 17:30:03 +04:00
if ( ctr6 - > more_data ) {
2008-07-30 14:32:30 +04:00
req - > req8 . highwatermark = ctr6 - > new_highwatermark ;
2008-07-30 14:00:49 +04:00
} else {
last_query = true ;
2008-07-30 19:53:28 +04:00
if ( ctr6 - > uptodateness_vector & &
! ctx - > single_object_replication )
{
2008-07-30 14:32:30 +04:00
new_utdv - > version = 2 ;
new_utdv - > ctr . ctr2 . count =
2008-07-30 14:00:49 +04:00
ctr6 - > uptodateness_vector - > count ;
2008-07-30 14:32:30 +04:00
new_utdv - > ctr . ctr2 . cursors =
2008-07-30 14:00:49 +04:00
ctr6 - > uptodateness_vector - > cursors ;
2008-06-24 01:13:21 +04:00
}
}
}
2008-07-30 14:00:49 +04:00
status = cli_get_session_key ( mem_ctx , ctx - > cli , & ctx - > session_key ) ;
2008-07-16 19:12:04 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-08-01 19:10:59 +04:00
ctx - > error_message = talloc_asprintf ( ctx ,
2008-07-30 14:00:49 +04:00
" Failed to get Session Key: %s " ,
2008-07-16 19:12:04 +04:00
nt_errstr ( status ) ) ;
goto out ;
}
2008-07-30 14:00:49 +04:00
libnet_dssync_decrypt_attributes ( mem_ctx ,
& ctx - > session_key ,
first_object ) ;
if ( ctx - > ops - > process_objects ) {
status = ctx - > ops - > process_objects ( ctx , mem_ctx ,
first_object ,
mapping_ctr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-08-01 19:10:59 +04:00
ctx - > error_message = talloc_asprintf ( ctx ,
2008-07-30 14:00:49 +04:00
" Failed to call processing function: %s " ,
nt_errstr ( status ) ) ;
goto out ;
}
}
2011-01-13 19:18:24 +03:00
if ( linked_attributes_count = = 0 ) {
continue ;
}
if ( ctx - > ops - > process_links ) {
status = ctx - > ops - > process_links ( ctx , mem_ctx ,
linked_attributes_count ,
linked_attributes ,
mapping_ctr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ctx - > error_message = talloc_asprintf ( ctx ,
" Failed to call processing function: %s " ,
nt_errstr ( status ) ) ;
goto out ;
}
}
2008-07-30 14:00:49 +04:00
}
2008-07-30 14:32:30 +04:00
* pnew_utdv = new_utdv ;
out :
return status ;
}
static NTSTATUS libnet_dssync_process ( TALLOC_CTX * mem_ctx ,
struct dssync_context * ctx )
{
NTSTATUS status ;
2010-03-05 22:58:01 +03:00
uint32_t level = 0 ;
2008-07-30 14:32:30 +04:00
union drsuapi_DsGetNCChangesRequest req ;
struct replUpToDateVectorBlob * old_utdv = NULL ;
struct replUpToDateVectorBlob * pnew_utdv = NULL ;
2008-07-30 15:02:36 +04:00
const char * * dns ;
uint32_t dn_count ;
uint32_t count ;
2008-07-30 14:32:30 +04:00
2009-04-01 18:55:53 +04:00
if ( ctx - > ops - > startup ) {
status = ctx - > ops - > startup ( ctx , mem_ctx , & old_utdv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ctx - > error_message = talloc_asprintf ( ctx ,
" Failed to call startup operation: %s " ,
nt_errstr ( status ) ) ;
goto out ;
}
2008-07-30 14:32:30 +04:00
}
2008-07-30 19:53:28 +04:00
if ( ctx - > single_object_replication & & ctx - > object_dns ) {
2008-07-30 15:02:36 +04:00
dns = ctx - > object_dns ;
dn_count = ctx - > object_count ;
2008-07-30 14:32:30 +04:00
} else {
2008-07-30 15:02:36 +04:00
dns = & ctx - > nc_dn ;
dn_count = 1 ;
2008-07-30 14:32:30 +04:00
}
2009-04-23 16:23:23 +04:00
status = NT_STATUS_OK ;
2008-07-30 15:02:36 +04:00
for ( count = 0 ; count < dn_count ; count + + ) {
status = libnet_dssync_build_request ( mem_ctx , ctx ,
dns [ count ] ,
old_utdv , & level ,
& req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
2008-07-30 14:32:30 +04:00
2008-07-30 15:02:36 +04:00
status = libnet_dssync_getncchanges ( mem_ctx , ctx , level , & req ,
& pnew_utdv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-03-04 09:20:59 +04:00
if ( ! ctx - > error_message ) {
ctx - > error_message = talloc_asprintf ( ctx ,
" Failed to call DsGetNCCHanges: %s " ,
nt_errstr ( status ) ) ;
}
2008-07-30 15:02:36 +04:00
goto out ;
}
2008-07-30 14:00:49 +04:00
}
2009-04-01 18:55:53 +04:00
if ( ctx - > ops - > finish ) {
status = ctx - > ops - > finish ( ctx , mem_ctx , pnew_utdv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ctx - > error_message = talloc_asprintf ( ctx ,
" Failed to call finishing operation: %s " ,
nt_errstr ( status ) ) ;
goto out ;
}
2008-06-24 01:13:21 +04:00
}
out :
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS libnet_dssync ( TALLOC_CTX * mem_ctx ,
struct dssync_context * ctx )
{
NTSTATUS status ;
2008-08-01 19:13:42 +04:00
TALLOC_CTX * tmp_ctx ;
2008-06-24 01:13:21 +04:00
2008-08-01 19:13:42 +04:00
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( ! tmp_ctx ) {
return NT_STATUS_NO_MEMORY ;
}
status = libnet_dssync_init ( tmp_ctx , ctx ) ;
2008-06-24 01:13:21 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
2008-08-01 19:13:42 +04:00
status = libnet_dssync_process ( tmp_ctx , ctx ) ;
2008-06-24 01:13:21 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
out :
2008-08-01 19:13:42 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2008-06-24 01:13:21 +04:00
return status ;
}
2008-07-18 02:18:40 +04:00