2007-01-09 14:15:56 +03:00
/*
Unix SMB / CIFS mplementation .
Helper functions for applying replicated objects
2007-03-14 22:10:21 +03:00
Copyright ( C ) Stefan Metzmacher < metze @ samba . org > 2007
2007-01-09 14:15:56 +03: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
2007-01-09 14:15:56 +03: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/>.
2007-01-09 14:15:56 +03:00
*/
# include "includes.h"
# include "dsdb/samdb/samdb.h"
# include "lib/ldb/include/ldb_errors.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2007-01-09 14:15:56 +03:00
# include "librpc/gen_ndr/ndr_misc.h"
# include "librpc/gen_ndr/ndr_drsuapi.h"
# include "librpc/gen_ndr/ndr_drsblobs.h"
2008-09-24 17:30:23 +04:00
# include "../lib/crypto/crypto.h"
2009-03-16 07:20:28 +03:00
# include "../libcli/drsuapi/drsuapi.h"
2007-02-15 15:40:13 +03:00
# include "libcli/auth/libcli_auth.h"
2008-01-02 07:05:05 +03:00
# include "param/param.h"
2007-02-12 14:46:35 +03:00
2010-11-29 15:00:42 +03:00
/**
* Multi - pass working schema creation
* Function will :
* - shallow copy initial schema supplied
* - create a working schema in multiple passes
* until all objects are resolved
* Working schema is a schema with Attributes , Classes
* and indexes , but w / o subClassOf , possibleSupperiors etc .
* It is to be used just us cache for converting attribute values .
*/
WERROR dsdb_repl_make_working_schema ( struct ldb_context * ldb ,
const struct dsdb_schema * initial_schema ,
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ,
uint32_t object_count ,
const struct drsuapi_DsReplicaObjectListItemEx * first_object ,
const DATA_BLOB * gensec_skey ,
TALLOC_CTX * mem_ctx ,
struct dsdb_schema * * _schema_out )
{
struct schema_list {
struct schema_list * next , * prev ;
const struct drsuapi_DsReplicaObjectListItemEx * obj ;
} ;
WERROR werr ;
struct dsdb_schema_prefixmap * pfm_remote ;
struct schema_list * schema_list = NULL , * schema_list_item , * schema_list_next_item ;
struct dsdb_schema * working_schema ;
const struct drsuapi_DsReplicaObjectListItemEx * cur ;
int ret , pass_no ;
/* make a copy of the iniatial_scheam so we don't mess with it */
working_schema = dsdb_schema_copy_shallow ( mem_ctx , ldb , initial_schema ) ;
if ( ! working_schema ) {
DEBUG ( 0 , ( __location__ " : schema copy failed! \n " ) ) ;
return WERR_NOMEM ;
}
/* we are going to need remote prefixMap for decoding */
werr = dsdb_schema_pfm_from_drsuapi_pfm ( mapping_ctr , true ,
mem_ctx , & pfm_remote , NULL ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( __location__ " : Failed to decode remote prefixMap: %s " ,
win_errstr ( werr ) ) ) ;
return werr ;
}
/* create a list of objects yet to be converted */
for ( cur = first_object ; cur ; cur = cur - > next_object ) {
schema_list_item = talloc ( mem_ctx , struct schema_list ) ;
schema_list_item - > obj = cur ;
DLIST_ADD_END ( schema_list , schema_list_item , struct schema_list ) ;
}
/* resolve objects until all are resolved and in local schema */
pass_no = 1 ;
while ( schema_list ) {
uint32_t converted_obj_count = 0 ;
uint32_t failed_obj_count = 0 ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
W_ERROR_HAVE_NO_MEMORY ( tmp_ctx ) ;
for ( schema_list_item = schema_list ; schema_list_item ; schema_list_item = schema_list_next_item ) {
struct dsdb_extended_replicated_object object ;
cur = schema_list_item - > obj ;
/* Save the next item, now we have saved out
* the current one , so we can DLIST_REMOVE it
* safely */
schema_list_next_item = schema_list_item - > next ;
/*
* Convert the objects into LDB messages using the
* schema we have so far . It ' s ok if we fail to convert
* an object . We should convert more objects on next pass .
*/
werr = dsdb_convert_object_ex ( ldb , working_schema , pfm_remote ,
cur , gensec_skey ,
tmp_ctx , & object ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 1 , ( " Warning: Failed to convert schema object %s into ldb msg \n " ,
cur - > object . identifier - > dn ) ) ;
failed_obj_count + + ;
} else {
/*
* Convert the schema from ldb_message format
* ( OIDs as OID strings ) into schema , using
* the remote prefixMap
*/
werr = dsdb_schema_set_el_from_ldb_msg ( ldb ,
working_schema ,
object . msg ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 1 , ( " Warning: failed to convert object %s into a schema element: %s \n " ,
ldb_dn_get_linearized ( object . msg - > dn ) ,
win_errstr ( werr ) ) ) ;
failed_obj_count + + ;
} else {
DLIST_REMOVE ( schema_list , schema_list_item ) ;
talloc_free ( schema_list_item ) ;
converted_obj_count + + ;
}
}
}
talloc_free ( tmp_ctx ) ;
DEBUG ( 4 , ( " Schema load pass %d: %d/%d of %d objects left to be converted. \n " ,
pass_no , failed_obj_count , converted_obj_count , object_count ) ) ;
pass_no + + ;
/* check if we converted any objects in this pass */
if ( converted_obj_count = = 0 ) {
DEBUG ( 0 , ( " Can't continue Schema load: didn't manage to convert any objects: all %d remaining of %d objects failed to convert \n " , failed_obj_count , object_count ) ) ;
return WERR_INTERNAL_ERROR ;
}
/* rebuild indexes */
ret = dsdb_setup_sorted_accessors ( ldb , working_schema ) ;
if ( LDB_SUCCESS ! = ret ) {
DEBUG ( 0 , ( " Failed to create schema-cache indexes! \n " ) ) ;
return WERR_INTERNAL_ERROR ;
}
} ;
* _schema_out = working_schema ;
return WERR_OK ;
}
2010-06-12 05:03:36 +04:00
WERROR dsdb_convert_object_ex ( struct ldb_context * ldb ,
const struct dsdb_schema * schema ,
2010-11-10 04:45:22 +03:00
const struct dsdb_schema_prefixmap * pfm_remote ,
2010-06-12 05:03:36 +04:00
const struct drsuapi_DsReplicaObjectListItemEx * in ,
const DATA_BLOB * gensec_skey ,
TALLOC_CTX * mem_ctx ,
struct dsdb_extended_replicated_object * out )
2007-01-09 14:15:56 +03:00
{
NTSTATUS nt_status ;
WERROR status ;
uint32_t i ;
struct ldb_message * msg ;
2007-01-11 12:45:30 +03:00
struct replPropertyMetaDataBlob * md ;
2007-01-09 14:15:56 +03:00
struct ldb_val guid_value ;
NTTIME whenChanged = 0 ;
time_t whenChanged_t ;
const char * whenChanged_s ;
2007-01-13 13:53:12 +03:00
const char * rdn_name = NULL ;
const struct ldb_val * rdn_value = NULL ;
const struct dsdb_attribute * rdn_attr = NULL ;
2007-01-09 14:15:56 +03:00
uint32_t rdn_attid ;
2007-01-13 13:53:12 +03:00
struct drsuapi_DsReplicaAttribute * name_a = NULL ;
struct drsuapi_DsReplicaMetaData * name_d = NULL ;
struct replPropertyMetaData1 * rdn_m = NULL ;
2007-02-15 15:40:13 +03:00
struct dom_sid * sid = NULL ;
uint32_t rid = 0 ;
2007-01-09 14:15:56 +03:00
int ret ;
if ( ! in - > object . identifier ) {
return WERR_FOOBAR ;
}
if ( ! in - > object . identifier - > dn | | ! in - > object . identifier - > dn [ 0 ] ) {
return WERR_FOOBAR ;
}
2007-02-11 20:36:33 +03:00
if ( in - > object . attribute_ctr . num_attributes ! = 0 & & ! in - > meta_data_ctr ) {
return WERR_FOOBAR ;
}
if ( in - > object . attribute_ctr . num_attributes ! = in - > meta_data_ctr - > count ) {
return WERR_FOOBAR ;
}
2007-02-15 15:40:13 +03:00
sid = & in - > object . identifier - > sid ;
if ( sid - > num_auths > 0 ) {
rid = sid - > sub_auths [ sid - > num_auths - 1 ] ;
}
2007-01-09 14:15:56 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
W_ERROR_HAVE_NO_MEMORY ( msg ) ;
msg - > dn = ldb_dn_new ( msg , ldb , in - > object . identifier - > dn ) ;
W_ERROR_HAVE_NO_MEMORY ( msg - > dn ) ;
rdn_name = ldb_dn_get_rdn_name ( msg - > dn ) ;
rdn_attr = dsdb_attribute_by_lDAPDisplayName ( schema , rdn_name ) ;
if ( ! rdn_attr ) {
return WERR_FOOBAR ;
}
rdn_attid = rdn_attr - > attributeID_id ;
rdn_value = ldb_dn_get_rdn_val ( msg - > dn ) ;
msg - > num_elements = in - > object . attribute_ctr . num_attributes ;
msg - > elements = talloc_array ( msg , struct ldb_message_element ,
msg - > num_elements ) ;
W_ERROR_HAVE_NO_MEMORY ( msg - > elements ) ;
2007-01-11 12:45:30 +03:00
md = talloc ( mem_ctx , struct replPropertyMetaDataBlob ) ;
W_ERROR_HAVE_NO_MEMORY ( md ) ;
2007-01-09 14:15:56 +03:00
2007-01-11 12:45:30 +03:00
md - > version = 1 ;
md - > reserved = 0 ;
md - > ctr . ctr1 . count = in - > meta_data_ctr - > count ;
md - > ctr . ctr1 . reserved = 0 ;
md - > ctr . ctr1 . array = talloc_array ( mem_ctx ,
struct replPropertyMetaData1 ,
md - > ctr . ctr1 . count + 1 ) ; /* +1 because of the RDN attribute */
W_ERROR_HAVE_NO_MEMORY ( md - > ctr . ctr1 . array ) ;
2007-01-09 14:15:56 +03:00
for ( i = 0 ; i < in - > meta_data_ctr - > count ; i + + ) {
struct drsuapi_DsReplicaAttribute * a ;
struct drsuapi_DsReplicaMetaData * d ;
struct replPropertyMetaData1 * m ;
2007-02-11 20:51:38 +03:00
struct ldb_message_element * e ;
2009-11-06 22:14:41 +03:00
uint32_t j ;
2007-01-09 14:15:56 +03:00
a = & in - > object . attribute_ctr . attributes [ i ] ;
d = & in - > meta_data_ctr - > meta_data [ i ] ;
2007-01-11 12:45:30 +03:00
m = & md - > ctr . ctr1 . array [ i ] ;
2007-02-11 20:51:38 +03:00
e = & msg - > elements [ i ] ;
2009-07-02 09:33:01 +04:00
for ( j = 0 ; j < a - > value_ctr . num_values ; j + + ) {
status = drsuapi_decrypt_attribute ( a - > value_ctr . values [ j ] . blob , gensec_skey , rid , a ) ;
W_ERROR_NOT_OK_RETURN ( status ) ;
}
2007-02-12 14:46:35 +03:00
2010-11-10 04:45:22 +03:00
status = dsdb_attribute_drsuapi_to_ldb ( ldb , schema , pfm_remote ,
a , msg - > elements , e ) ;
2007-02-11 20:51:38 +03:00
W_ERROR_NOT_OK_RETURN ( status ) ;
2007-01-09 14:15:56 +03:00
m - > attid = a - > attid ;
m - > version = d - > version ;
2007-03-09 13:09:37 +03:00
m - > originating_change_time = d - > originating_change_time ;
m - > originating_invocation_id = d - > originating_invocation_id ;
m - > originating_usn = d - > originating_usn ;
2007-01-09 14:15:56 +03:00
m - > local_usn = 0 ;
2007-03-09 13:09:37 +03:00
if ( d - > originating_change_time > whenChanged ) {
whenChanged = d - > originating_change_time ;
2007-01-09 14:15:56 +03:00
}
2010-10-29 03:22:35 +04:00
if ( a - > attid = = DRSUAPI_ATTID_name ) {
2007-01-09 14:15:56 +03:00
name_a = a ;
name_d = d ;
2007-01-11 12:45:30 +03:00
rdn_m = & md - > ctr . ctr1 . array [ md - > ctr . ctr1 . count ] ;
2007-01-09 14:15:56 +03:00
}
}
2007-01-13 13:53:12 +03:00
if ( rdn_m ) {
2009-09-11 12:01:27 +04:00
struct ldb_message_element * el ;
el = ldb_msg_find_element ( msg , rdn_attr - > lDAPDisplayName ) ;
if ( ! el ) {
2009-11-16 19:01:43 +03:00
ret = ldb_msg_add_value ( msg , rdn_attr - > lDAPDisplayName , rdn_value , NULL ) ;
2009-09-11 12:01:27 +04:00
if ( ret ! = LDB_SUCCESS ) {
return WERR_FOOBAR ;
}
} else {
if ( el - > num_values ! = 1 ) {
DEBUG ( 0 , ( __location__ " : Unexpected num_values=%u \n " ,
el - > num_values ) ) ;
return WERR_FOOBAR ;
}
if ( ! ldb_val_equal_exact ( & el - > values [ 0 ] , rdn_value ) ) {
DEBUG ( 0 , ( __location__ " : RDN value changed? '%*.*s' '%*.*s' \n " ,
( int ) el - > values [ 0 ] . length , ( int ) el - > values [ 0 ] . length , el - > values [ 0 ] . data ,
( int ) rdn_value - > length , ( int ) rdn_value - > length , rdn_value - > data ) ) ;
return WERR_FOOBAR ;
}
2007-01-13 13:53:12 +03:00
}
2007-01-09 14:15:56 +03:00
2007-01-13 13:53:12 +03:00
rdn_m - > attid = rdn_attid ;
rdn_m - > version = name_d - > version ;
2007-03-09 13:09:37 +03:00
rdn_m - > originating_change_time = name_d - > originating_change_time ;
rdn_m - > originating_invocation_id = name_d - > originating_invocation_id ;
rdn_m - > originating_usn = name_d - > originating_usn ;
2007-01-13 13:53:12 +03:00
rdn_m - > local_usn = 0 ;
md - > ctr . ctr1 . count + + ;
2007-01-09 14:15:56 +03:00
}
whenChanged_t = nt_time_to_unix ( whenChanged ) ;
whenChanged_s = ldb_timestring ( msg , whenChanged_t ) ;
W_ERROR_HAVE_NO_MEMORY ( whenChanged_s ) ;
2007-01-13 13:53:12 +03:00
2009-12-10 06:33:13 +03:00
nt_status = GUID_to_ndr_blob ( & in - > object . identifier - > guid , msg , & guid_value ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2007-01-13 13:53:12 +03:00
return ntstatus_to_werror ( nt_status ) ;
2007-01-09 14:15:56 +03:00
}
2007-01-13 13:53:12 +03:00
out - > msg = msg ;
out - > guid_value = guid_value ;
out - > when_changed = whenChanged_s ;
out - > meta_data = md ;
2007-01-09 14:15:56 +03:00
return WERR_OK ;
}
2010-11-08 00:04:33 +03:00
WERROR dsdb_replicated_objects_convert ( struct ldb_context * ldb ,
2010-11-26 03:38:39 +03:00
const struct dsdb_schema * schema ,
2010-11-08 00:04:33 +03:00
const char * partition_dn_str ,
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ,
uint32_t object_count ,
const struct drsuapi_DsReplicaObjectListItemEx * first_object ,
uint32_t linked_attributes_count ,
const struct drsuapi_DsReplicaLinkedAttribute * linked_attributes ,
const struct repsFromTo1 * source_dsa ,
const struct drsuapi_DsReplicaCursor2CtrEx * uptodateness_vector ,
const DATA_BLOB * gensec_skey ,
TALLOC_CTX * mem_ctx ,
struct dsdb_extended_replicated_objects * * objects )
2007-01-09 14:15:56 +03:00
{
WERROR status ;
2010-09-18 16:09:22 +04:00
struct ldb_dn * partition_dn ;
2010-11-10 04:45:22 +03:00
struct dsdb_schema_prefixmap * pfm_remote ;
2007-01-09 14:15:56 +03:00
struct dsdb_extended_replicated_objects * out ;
2007-01-11 13:21:38 +03:00
const struct drsuapi_DsReplicaObjectListItemEx * cur ;
2007-01-09 14:15:56 +03:00
uint32_t i ;
2010-03-16 06:52:39 +03:00
out = talloc_zero ( mem_ctx , struct dsdb_extended_replicated_objects ) ;
W_ERROR_HAVE_NO_MEMORY ( out ) ;
out - > version = DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION ;
2010-11-26 03:38:39 +03:00
/*
* Ensure schema is kept valid for as long as ' out '
* which may contain pointers to it
*/
2010-12-01 18:28:57 +03:00
schema = talloc_reference ( out , schema ) ;
W_ERROR_HAVE_NO_MEMORY ( schema ) ;
2007-01-14 18:35:10 +03:00
2010-09-18 16:09:22 +04:00
partition_dn = ldb_dn_new ( out , ldb , partition_dn_str ) ;
W_ERROR_HAVE_NO_MEMORY_AND_FREE ( partition_dn , out ) ;
2010-11-10 04:45:22 +03:00
status = dsdb_schema_pfm_from_drsuapi_pfm ( mapping_ctr , true ,
out , & pfm_remote , NULL ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 0 , ( __location__ " : Failed to decode remote prefixMap: %s " ,
win_errstr ( status ) ) ) ;
talloc_free ( out ) ;
return status ;
}
2010-09-18 16:09:22 +04:00
if ( ldb_dn_compare ( partition_dn , ldb_get_schema_basedn ( ldb ) ) ! = 0 ) {
/*
* check for schema changes in case
* we are not replicating Schema NC
*/
status = dsdb_schema_info_cmp ( schema , mapping_ctr ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Remote schema has changed while replicating %s \n " ,
partition_dn_str ) ) ;
talloc_free ( out ) ;
return status ;
}
2010-03-16 06:52:39 +03:00
}
2007-01-09 14:15:56 +03:00
2010-09-18 16:09:22 +04:00
out - > partition_dn = partition_dn ;
2007-01-09 14:15:56 +03:00
2007-01-12 19:02:10 +03:00
out - > source_dsa = source_dsa ;
out - > uptodateness_vector = uptodateness_vector ;
2007-01-12 16:17:25 +03:00
2007-01-09 14:15:56 +03:00
out - > num_objects = object_count ;
out - > objects = talloc_array ( out ,
struct dsdb_extended_replicated_object ,
out - > num_objects ) ;
2010-09-18 16:09:22 +04:00
W_ERROR_HAVE_NO_MEMORY_AND_FREE ( out - > objects , out ) ;
2007-01-09 14:15:56 +03:00
2009-09-03 06:52:31 +04:00
/* pass the linked attributes down to the repl_meta_data
module */
out - > linked_attributes_count = linked_attributes_count ;
out - > linked_attributes = linked_attributes ;
2007-01-09 14:15:56 +03:00
for ( i = 0 , cur = first_object ; cur ; cur = cur - > next_object , i + + ) {
if ( i = = out - > num_objects ) {
2010-03-16 06:52:39 +03:00
talloc_free ( out ) ;
2007-01-09 14:15:56 +03:00
return WERR_FOOBAR ;
}
2010-11-10 04:45:22 +03:00
status = dsdb_convert_object_ex ( ldb , schema , pfm_remote ,
2008-10-01 08:28:32 +04:00
cur , gensec_skey ,
out - > objects , & out - > objects [ i ] ) ;
2009-09-10 11:42:36 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2010-03-16 06:52:39 +03:00
talloc_free ( out ) ;
2010-09-24 01:47:37 +04:00
DEBUG ( 0 , ( " Failed to convert object %s: %s \n " ,
cur - > object . identifier - > dn ,
win_errstr ( status ) ) ) ;
2009-09-10 11:42:36 +04:00
return status ;
}
2007-01-09 14:15:56 +03:00
}
if ( i ! = out - > num_objects ) {
2010-03-16 06:52:39 +03:00
talloc_free ( out ) ;
2007-01-09 14:15:56 +03:00
return WERR_FOOBAR ;
}
2010-11-10 04:45:22 +03:00
/* free pfm_remote, we won't need it anymore */
talloc_free ( pfm_remote ) ;
2009-11-09 13:26:02 +03:00
* objects = out ;
return WERR_OK ;
}
2010-12-10 03:55:30 +03:00
/**
* Commits a list of replicated objects .
*
* @ param working_schema dsdb_schema to be used for resolving
* Classes / Attributes during Schema replication . If not NULL ,
* it will be set on ldb and used while committing replicated objects
*/
2010-11-07 23:51:11 +03:00
WERROR dsdb_replicated_objects_commit ( struct ldb_context * ldb ,
2010-12-10 03:55:30 +03:00
struct dsdb_schema * working_schema ,
2010-11-07 23:51:11 +03:00
struct dsdb_extended_replicated_objects * objects ,
uint64_t * notify_uSN )
2009-11-09 13:26:02 +03:00
{
struct ldb_result * ext_res ;
2010-12-10 03:55:30 +03:00
struct dsdb_schema * cur_schema = NULL ;
2009-11-09 13:26:02 +03:00
int ret ;
uint64_t seq_num1 , seq_num2 ;
2007-01-09 14:15:56 +03:00
/* TODO: handle linked attributes */
2009-09-02 05:17:43 +04:00
/* wrap the extended operation in a transaction
See [ MS - DRSR ] 3.3 .2 Transactions
*/
ret = ldb_transaction_start ( ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " Failed to start transaction \n " ) ) ;
return WERR_FOOBAR ;
}
2010-01-07 21:30:05 +03:00
ret = dsdb_load_partition_usn ( ldb , objects - > partition_dn , & seq_num1 , NULL ) ;
2009-09-16 01:06:07 +04:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " Failed to load partition uSN \n " ) ) ;
ldb_transaction_cancel ( ldb ) ;
return WERR_FOOBAR ;
}
2010-12-10 03:55:30 +03:00
/*
* Set working_schema for ldb in case we are replicating from Schema NC .
* Schema won ' t be reloaded during Replicated Objects commit , as it is
* done in a transaction . So we need some way to search for newly
* added Classes and Attributes
*/
if ( working_schema ) {
/* store current schema so we can fall back in case of failure */
2010-12-17 23:26:03 +03:00
cur_schema = dsdb_get_schema ( ldb , working_schema ) ;
2010-12-10 03:55:30 +03:00
ret = dsdb_reference_schema ( ldb , working_schema , false ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " Failed to reference working schema - %s \n " ,
ldb_strerror ( ret ) ) ) ;
/* TODO: Map LDB Error to NTSTATUS? */
ldb_transaction_cancel ( ldb ) ;
return WERR_INTERNAL_ERROR ;
}
}
2009-11-09 13:26:02 +03:00
ret = ldb_extended ( ldb , DSDB_EXTENDED_REPLICATED_OBJECTS_OID , objects , & ext_res ) ;
2007-01-09 14:15:56 +03:00
if ( ret ! = LDB_SUCCESS ) {
2010-12-10 03:55:30 +03:00
/* restore previous schema */
if ( cur_schema ) {
dsdb_reference_schema ( ldb , cur_schema , false ) ;
2010-12-16 23:31:28 +03:00
dsdb_make_schema_global ( ldb , cur_schema ) ;
2010-12-10 03:55:30 +03:00
}
2008-01-23 07:44:02 +03:00
DEBUG ( 0 , ( " Failed to apply records: %s: %s \n " ,
ldb_errstring ( ldb ) , ldb_strerror ( ret ) ) ) ;
2009-09-02 05:17:43 +04:00
ldb_transaction_cancel ( ldb ) ;
2007-01-09 14:15:56 +03:00
return WERR_FOOBAR ;
}
talloc_free ( ext_res ) ;
2009-09-16 01:06:07 +04:00
ret = ldb_transaction_prepare_commit ( ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-12-10 03:55:30 +03:00
/* restore previous schema */
if ( cur_schema ) {
dsdb_reference_schema ( ldb , cur_schema , false ) ;
2010-12-16 23:31:28 +03:00
dsdb_make_schema_global ( ldb , cur_schema ) ;
2010-12-10 03:55:30 +03:00
}
2009-12-21 12:58:09 +03:00
DEBUG ( 0 , ( __location__ " Failed to prepare commit of transaction: %s \n " ,
ldb_errstring ( ldb ) ) ) ;
2009-09-16 01:06:07 +04:00
return WERR_FOOBAR ;
}
2010-01-07 21:30:05 +03:00
ret = dsdb_load_partition_usn ( ldb , objects - > partition_dn , & seq_num2 , NULL ) ;
2009-09-16 01:06:07 +04:00
if ( ret ! = LDB_SUCCESS ) {
2010-12-10 03:55:30 +03:00
/* restore previous schema */
if ( cur_schema ) {
dsdb_reference_schema ( ldb , cur_schema , false ) ;
2010-12-16 23:31:28 +03:00
dsdb_make_schema_global ( ldb , cur_schema ) ;
2010-12-10 03:55:30 +03:00
}
2009-09-16 01:06:07 +04:00
DEBUG ( 0 , ( __location__ " Failed to load partition uSN \n " ) ) ;
ldb_transaction_cancel ( ldb ) ;
return WERR_FOOBAR ;
}
/* if this replication partner didn't need to be notified
before this transaction then it still doesn ' t need to be
notified , as the changes came from this server */
if ( seq_num2 > seq_num1 & & seq_num1 < = * notify_uSN ) {
* notify_uSN = seq_num2 ;
}
2009-09-02 05:17:43 +04:00
ret = ldb_transaction_commit ( ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-12-10 03:55:30 +03:00
/* restore previous schema */
if ( cur_schema ) {
dsdb_reference_schema ( ldb , cur_schema , false ) ;
2010-12-16 23:31:28 +03:00
dsdb_make_schema_global ( ldb , cur_schema ) ;
2010-12-10 03:55:30 +03:00
}
2009-09-02 05:17:43 +04:00
DEBUG ( 0 , ( __location__ " Failed to commit transaction \n " ) ) ;
return WERR_FOOBAR ;
}
2010-12-10 03:55:30 +03:00
/*
* Reset the Schema used by ldb . This will lead to
* a schema cache being refreshed from database .
*/
if ( working_schema ) {
cur_schema = dsdb_get_schema ( ldb , NULL ) ;
/* TODO: What we do in case dsdb_get_schema() fail?
* We can ' t fallback at this point anymore */
2010-12-16 23:31:28 +03:00
if ( cur_schema ) {
dsdb_make_schema_global ( ldb , cur_schema ) ;
}
2010-12-10 03:55:30 +03:00
}
2009-09-16 01:06:07 +04:00
2009-09-15 20:23:14 +04:00
DEBUG ( 2 , ( " Replicated %u objects (%u linked attributes) for %s \n " ,
2009-11-09 13:26:02 +03:00
objects - > num_objects , objects - > linked_attributes_count ,
ldb_dn_get_linearized ( objects - > partition_dn ) ) ) ;
2009-09-15 20:23:14 +04:00
2007-01-09 14:15:56 +03:00
return WERR_OK ;
}
2008-10-01 08:28:32 +04:00
2010-11-07 22:47:39 +03:00
static WERROR dsdb_origin_object_convert ( struct ldb_context * ldb ,
const struct dsdb_schema * schema ,
const struct drsuapi_DsReplicaObjectListItem * in ,
TALLOC_CTX * mem_ctx ,
struct ldb_message * * _msg )
2008-10-01 08:28:32 +04:00
{
WERROR status ;
2009-11-06 22:14:41 +03:00
unsigned int i ;
2008-10-01 08:28:32 +04:00
struct ldb_message * msg ;
if ( ! in - > object . identifier ) {
return WERR_FOOBAR ;
}
if ( ! in - > object . identifier - > dn | | ! in - > object . identifier - > dn [ 0 ] ) {
return WERR_FOOBAR ;
}
msg = ldb_msg_new ( mem_ctx ) ;
W_ERROR_HAVE_NO_MEMORY ( msg ) ;
msg - > dn = ldb_dn_new ( msg , ldb , in - > object . identifier - > dn ) ;
W_ERROR_HAVE_NO_MEMORY ( msg - > dn ) ;
msg - > num_elements = in - > object . attribute_ctr . num_attributes ;
msg - > elements = talloc_array ( msg , struct ldb_message_element ,
msg - > num_elements ) ;
W_ERROR_HAVE_NO_MEMORY ( msg - > elements ) ;
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
struct drsuapi_DsReplicaAttribute * a ;
struct ldb_message_element * e ;
a = & in - > object . attribute_ctr . attributes [ i ] ;
e = & msg - > elements [ i ] ;
2010-11-10 04:45:22 +03:00
status = dsdb_attribute_drsuapi_to_ldb ( ldb , schema , schema - > prefixmap ,
a , msg - > elements , e ) ;
2008-10-01 08:28:32 +04:00
W_ERROR_NOT_OK_RETURN ( status ) ;
}
2009-09-11 09:15:39 +04:00
2008-10-01 08:28:32 +04:00
* _msg = msg ;
2009-09-11 09:15:39 +04:00
2008-10-01 08:28:32 +04:00
return WERR_OK ;
}
WERROR dsdb_origin_objects_commit ( struct ldb_context * ldb ,
TALLOC_CTX * mem_ctx ,
const struct drsuapi_DsReplicaObjectListItem * first_object ,
uint32_t * _num ,
struct drsuapi_DsReplicaObjectIdentifier2 * * _ids )
{
WERROR status ;
const struct dsdb_schema * schema ;
const struct drsuapi_DsReplicaObjectListItem * cur ;
struct ldb_message * * objects ;
struct drsuapi_DsReplicaObjectIdentifier2 * ids ;
uint32_t i ;
uint32_t num_objects = 0 ;
const char * const attrs [ ] = {
" objectGUID " ,
" objectSid " ,
NULL
} ;
struct ldb_result * res ;
int ret ;
for ( cur = first_object ; cur ; cur = cur - > next_object ) {
num_objects + + ;
}
if ( num_objects = = 0 ) {
return WERR_OK ;
}
2009-10-06 11:55:14 +04:00
ret = ldb_transaction_start ( ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
return WERR_DS_INTERNAL_FAILURE ;
}
2008-10-01 08:28:32 +04:00
objects = talloc_array ( mem_ctx , struct ldb_message * ,
num_objects ) ;
2009-10-06 11:55:14 +04:00
if ( objects = = NULL ) {
status = WERR_NOMEM ;
goto cancel ;
}
2008-10-01 08:28:32 +04:00
2010-03-16 06:52:39 +03:00
schema = dsdb_get_schema ( ldb , objects ) ;
if ( ! schema ) {
return WERR_DS_SCHEMA_NOT_LOADED ;
}
2008-10-01 08:28:32 +04:00
for ( i = 0 , cur = first_object ; cur ; cur = cur - > next_object , i + + ) {
2010-11-07 22:47:39 +03:00
status = dsdb_origin_object_convert ( ldb , schema , cur ,
objects , & objects [ i ] ) ;
2009-10-06 11:55:14 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
goto cancel ;
}
2008-10-01 08:28:32 +04:00
}
2009-10-07 09:20:16 +04:00
ids = talloc_array ( mem_ctx ,
2008-10-01 08:28:32 +04:00
struct drsuapi_DsReplicaObjectIdentifier2 ,
num_objects ) ;
2009-10-06 11:55:14 +04:00
if ( ids = = NULL ) {
status = WERR_NOMEM ;
goto cancel ;
}
2008-10-01 08:28:32 +04:00
for ( i = 0 ; i < num_objects ; i + + ) {
struct dom_sid * sid = NULL ;
2009-10-06 11:55:14 +04:00
struct ldb_request * add_req ;
2009-09-23 01:26:59 +04:00
DEBUG ( 6 , ( __location__ " : adding %s \n " ,
ldb_dn_get_linearized ( objects [ i ] - > dn ) ) ) ;
2009-10-06 11:55:14 +04:00
ret = ldb_build_add_req ( & add_req ,
ldb ,
objects ,
objects [ i ] ,
NULL ,
NULL ,
ldb_op_default_callback ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
status = WERR_DS_INTERNAL_FAILURE ;
goto cancel ;
}
ret = ldb_request_add_control ( add_req , LDB_CONTROL_RELAX_OID , true , NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
status = WERR_DS_INTERNAL_FAILURE ;
goto cancel ;
}
2009-09-23 01:26:59 +04:00
2009-10-06 11:55:14 +04:00
ret = ldb_request ( ldb , add_req ) ;
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( add_req - > handle , LDB_WAIT_ALL ) ;
}
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " : Failed add of %s - %s \n " ,
ldb_dn_get_linearized ( objects [ i ] - > dn ) , ldb_errstring ( ldb ) ) ) ;
status = WERR_DS_INTERNAL_FAILURE ;
2008-10-01 08:28:32 +04:00
goto cancel ;
}
2009-10-06 11:55:14 +04:00
talloc_free ( add_req ) ;
2008-10-01 08:28:32 +04:00
ret = ldb_search ( ldb , objects , & res , objects [ i ] - > dn ,
LDB_SCOPE_BASE , attrs ,
" (objectClass=*) " ) ;
2009-10-06 11:55:14 +04:00
if ( ret ! = LDB_SUCCESS ) {
status = WERR_DS_INTERNAL_FAILURE ;
2008-10-01 08:28:32 +04:00
goto cancel ;
}
ids [ i ] . guid = samdb_result_guid ( res - > msgs [ 0 ] , " objectGUID " ) ;
sid = samdb_result_dom_sid ( objects , res - > msgs [ 0 ] , " objectSid " ) ;
if ( sid ) {
ids [ i ] . sid = * sid ;
} else {
ZERO_STRUCT ( ids [ i ] . sid ) ;
}
}
2009-10-06 11:55:14 +04:00
ret = ldb_transaction_commit ( ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
return WERR_DS_INTERNAL_FAILURE ;
}
2008-10-01 08:28:32 +04:00
talloc_free ( objects ) ;
* _num = num_objects ;
* _ids = ids ;
return WERR_OK ;
2009-10-06 11:55:14 +04:00
2008-10-01 08:28:32 +04:00
cancel :
talloc_free ( objects ) ;
ldb_transaction_cancel ( ldb ) ;
2009-10-06 11:55:14 +04:00
return status ;
2008-10-01 08:28:32 +04:00
}