2005-05-02 18:17:19 +04:00
/*
Unix SMB / CIFS implementation .
2008-04-09 06:02:11 +04:00
Extract the user / system database from a remote server
2005-05-21 10:31:02 +04:00
2008-04-09 06:02:11 +04:00
Copyright ( C ) Stefan Metzmacher 2004 - 2006
Copyright ( C ) Brad Henry 2005
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005 - 2008
2005-05-02 18:17:19 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-05-02 18:17:19 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-05-02 18:17:19 +04:00
*/
# include "includes.h"
# include "libnet/libnet.h"
2008-04-09 06:02:11 +04:00
# include "lib/events/events.h"
# include "dsdb/samdb/samdb.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2008-04-09 06:02:11 +04:00
# include "lib/ldb/include/ldb.h"
# include "lib/ldb/include/ldb_errors.h"
# include "librpc/ndr/libndr.h"
# include "librpc/gen_ndr/ndr_drsuapi.h"
# include "librpc/gen_ndr/ndr_drsblobs.h"
# include "librpc/gen_ndr/ndr_misc.h"
# include "system/time.h"
2010-06-16 15:43:38 +04:00
# include "ldb_wrap.h"
2008-04-09 06:02:11 +04:00
# include "auth/auth.h"
2010-04-29 02:51:01 +04:00
# include "auth/credentials/credentials.h"
2007-09-28 05:17:46 +04:00
# include "param/param.h"
2008-04-09 08:59:32 +04:00
# include "param/provision.h"
2009-09-24 21:33:36 +04:00
# include "libcli/security/dom_sid.h"
2010-08-02 17:47:38 +04:00
# include "dsdb/common/util.h"
2005-05-21 09:05:44 +04:00
2008-04-09 06:02:11 +04:00
/*
List of tasks vampire . py must perform :
- Domain Join
- but don ' t write the secrets . ldb
- results for this should be enough to handle the provision
- if vampire method is samsync
- Provision using these results
- do we still want to support this NT4 technology ?
- Start samsync with libnet code
- provision in the callback
- Write out the secrets database , using the code from libnet_Join
*/
2010-06-12 11:22:20 +04:00
struct libnet_vampire_cb_state {
2008-04-09 06:02:11 +04:00
const char * netbios_name ;
2010-06-12 11:22:20 +04:00
const char * domain_name ;
const char * realm ;
2008-04-09 06:02:11 +04:00
struct cli_credentials * machine_account ;
2010-06-12 05:05:47 +04:00
/* Schema loaded from local LDIF files */
2010-06-09 14:52:02 +04:00
struct dsdb_schema * provision_schema ;
2010-06-12 05:05:47 +04:00
/* 1st pass, with some OIDs/attribute names/class names not
* converted , because we may not know them yet */
struct dsdb_schema * self_made_schema ;
/* 2nd pass, with full ID->OID->name table */
struct dsdb_schema * self_corrected_schema ;
/* prefixMap in LDB format, from the remote DRS server */
2010-06-09 15:53:01 +04:00
DATA_BLOB prefixmap_blob ;
2008-04-09 06:02:11 +04:00
const struct dsdb_schema * schema ;
struct ldb_context * ldb ;
2005-05-21 09:05:44 +04:00
2008-04-09 06:02:11 +04:00
struct {
uint32_t object_count ;
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
struct drsuapi_DsReplicaObjectListItemEx * last_object ;
} schema_part ;
const char * targetdir ;
struct loadparm_context * lp_ctx ;
2008-12-29 22:24:57 +03:00
struct tevent_context * event_ctx ;
2009-09-03 12:31:45 +04:00
unsigned total_objects ;
char * last_partition ;
2010-08-02 17:47:38 +04:00
const char * server_dn_str ;
2008-04-09 06:02:11 +04:00
} ;
2010-08-24 09:40:42 +04:00
/* initialise a state structure ready for replication of chunks */
void * libnet_vampire_replicate_init ( TALLOC_CTX * mem_ctx ,
struct ldb_context * samdb ,
struct loadparm_context * lp_ctx )
{
struct libnet_vampire_cb_state * s = talloc_zero ( mem_ctx , struct libnet_vampire_cb_state ) ;
if ( ! s ) {
return NULL ;
}
s - > ldb = samdb ;
s - > lp_ctx = lp_ctx ;
s - > provision_schema = dsdb_get_schema ( s - > ldb , s ) ;
2010-09-07 09:25:45 +04:00
s - > schema = s - > provision_schema ;
2010-09-15 12:50:09 +04:00
s - > netbios_name = lpcfg_netbios_name ( lp_ctx ) ;
s - > domain_name = lpcfg_workgroup ( lp_ctx ) ;
s - > realm = lpcfg_realm ( lp_ctx ) ;
2010-08-24 09:40:42 +04:00
return s ;
}
2010-06-12 11:22:20 +04:00
/* Caller is expected to keep supplied pointers around for the lifetime of the structure */
void * libnet_vampire_cb_state_init ( TALLOC_CTX * mem_ctx ,
struct loadparm_context * lp_ctx , struct tevent_context * event_ctx ,
const char * netbios_name , const char * domain_name , const char * realm ,
const char * targetdir )
{
struct libnet_vampire_cb_state * s = talloc_zero ( mem_ctx , struct libnet_vampire_cb_state ) ;
if ( ! s ) {
return NULL ;
}
s - > lp_ctx = lp_ctx ;
s - > event_ctx = event_ctx ;
s - > netbios_name = netbios_name ;
s - > domain_name = domain_name ;
s - > realm = realm ;
s - > targetdir = targetdir ;
return s ;
}
struct ldb_context * libnet_vampire_cb_ldb ( struct libnet_vampire_cb_state * state )
{
state = talloc_get_type_abort ( state , struct libnet_vampire_cb_state ) ;
return state - > ldb ;
}
struct loadparm_context * libnet_vampire_cb_lp_ctx ( struct libnet_vampire_cb_state * state )
{
state = talloc_get_type_abort ( state , struct libnet_vampire_cb_state ) ;
return state - > lp_ctx ;
}
NTSTATUS libnet_vampire_cb_prepare_db ( void * private_data ,
const struct libnet_BecomeDC_PrepareDB * p )
2005-05-21 09:05:44 +04:00
{
2010-06-12 11:22:20 +04:00
struct libnet_vampire_cb_state * s = talloc_get_type ( private_data , struct libnet_vampire_cb_state ) ;
2008-04-09 06:02:11 +04:00
struct provision_settings settings ;
2008-04-11 13:15:24 +04:00
struct provision_result result ;
2008-04-09 06:02:11 +04:00
NTSTATUS status ;
2005-05-21 09:05:44 +04:00
2009-07-02 08:47:06 +04:00
ZERO_STRUCT ( settings ) ;
2008-04-09 06:02:11 +04:00
settings . site_name = p - > dest_dsa - > site_name ;
settings . root_dn_str = p - > forest - > root_dn_str ;
settings . domain_dn_str = p - > domain - > dn_str ;
settings . config_dn_str = p - > forest - > config_dn_str ;
settings . schema_dn_str = p - > forest - > schema_dn_str ;
settings . netbios_name = p - > dest_dsa - > netbios_name ;
2010-06-12 11:22:20 +04:00
settings . realm = s - > realm ;
settings . domain = s - > domain_name ;
2008-04-09 06:02:11 +04:00
settings . server_dn_str = p - > dest_dsa - > server_dn_str ;
2010-02-24 17:09:50 +03:00
settings . machine_password = generate_random_password ( s , 16 , 255 ) ;
2008-04-09 06:02:11 +04:00
settings . targetdir = s - > targetdir ;
2008-04-11 13:15:24 +04:00
status = provision_bare ( s , s - > lp_ctx , & settings , & result ) ;
2005-05-02 18:17:19 +04:00
2008-04-11 13:15:24 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2005-05-02 18:17:19 +04:00
}
2010-06-12 11:23:32 +04:00
s - > ldb = talloc_steal ( s , result . samdb ) ;
s - > lp_ctx = talloc_steal ( s , result . lp_ctx ) ;
2010-06-09 14:52:02 +04:00
s - > provision_schema = dsdb_get_schema ( s - > ldb , s ) ;
2010-08-02 17:47:38 +04:00
s - > server_dn_str = talloc_steal ( s , p - > dest_dsa - > server_dn_str ) ;
2008-04-09 06:02:11 +04:00
2009-09-02 10:57:25 +04:00
/* wrap the entire vapire operation in a transaction. This
isn ' t just cosmetic - we use this to ensure that linked
attribute back links are added at the end by relying on a
transaction commit hook in the linked attributes module . We
need to do this as the order of objects coming from the
server is not sufficiently deterministic to know that the
record that a backlink needs to be created in has itself
been created before the object containing the forward link
has come over the wire */
if ( ldb_transaction_start ( s - > ldb ) ! = LDB_SUCCESS ) {
return NT_STATUS_FOOBAR ;
}
2008-04-09 06:02:11 +04:00
return NT_STATUS_OK ;
}
2010-06-12 11:22:20 +04:00
NTSTATUS libnet_vampire_cb_check_options ( void * private_data ,
const struct libnet_BecomeDC_CheckOptions * o )
2008-04-09 06:02:11 +04:00
{
2010-06-12 11:22:20 +04:00
struct libnet_vampire_cb_state * s = talloc_get_type ( private_data , struct libnet_vampire_cb_state ) ;
2008-04-09 06:02:11 +04:00
DEBUG ( 0 , ( " Become DC [%s] of Domain[%s]/[%s] \n " ,
s - > netbios_name ,
o - > domain - > netbios_name , o - > domain - > dns_name ) ) ;
DEBUG ( 0 , ( " Promotion Partner is Server[%s] from Site[%s] \n " ,
o - > source_dsa - > dns_name , o - > source_dsa - > site_name ) ) ;
DEBUG ( 0 , ( " Options:crossRef behavior_version[%u] \n "
" \t schema object_version[%u] \n "
" \t domain behavior_version[%u] \n "
" \t domain w2k3_update_revision[%u] \n " ,
o - > forest - > crossref_behavior_version ,
o - > forest - > schema_object_version ,
o - > domain - > behavior_version ,
o - > domain - > w2k3_update_revision ) ) ;
return NT_STATUS_OK ;
}
2010-06-12 11:22:20 +04:00
static NTSTATUS libnet_vampire_cb_apply_schema ( struct libnet_vampire_cb_state * s ,
const struct libnet_BecomeDC_StoreChunk * c )
2008-04-09 06:02:11 +04:00
{
WERROR status ;
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ;
uint32_t object_count ;
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
2010-06-12 05:05:47 +04:00
const struct drsuapi_DsReplicaObjectListItemEx * cur ;
2008-04-09 06:02:11 +04:00
uint32_t linked_attributes_count ;
struct drsuapi_DsReplicaLinkedAttribute * linked_attributes ;
const struct drsuapi_DsReplicaCursor2CtrEx * uptodateness_vector ;
2010-06-12 05:05:47 +04:00
struct dsdb_extended_replicated_objects * schema_objs ;
2008-04-09 06:02:11 +04:00
struct repsFromTo1 * s_dsa ;
char * tmp_dns_name ;
2010-06-10 15:33:45 +04:00
struct ldb_context * schema_ldb ;
2008-04-09 06:02:11 +04:00
struct ldb_message * msg ;
struct ldb_message_element * prefixMap_el ;
uint32_t i ;
int ret ;
bool ok ;
2009-09-16 01:42:26 +04:00
uint64_t seq_num ;
2008-04-09 06:02:11 +04:00
DEBUG ( 0 , ( " Analyze and apply schema objects \n " ) ) ;
s_dsa = talloc_zero ( s , struct repsFromTo1 ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa ) ;
s_dsa - > other_info = talloc ( s_dsa , struct repsFromTo1OtherInfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa - > other_info ) ;
switch ( c - > ctr_level ) {
case 1 :
mapping_ctr = & c - > ctr1 - > mapping_ctr ;
object_count = s - > schema_part . object_count ;
first_object = s - > schema_part . first_object ;
linked_attributes_count = 0 ;
linked_attributes = NULL ;
s_dsa - > highwatermark = c - > ctr1 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr1 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr1 - > source_dsa_invocation_id ;
uptodateness_vector = NULL ; /* TODO: map it */
break ;
case 6 :
mapping_ctr = & c - > ctr6 - > mapping_ctr ;
object_count = s - > schema_part . object_count ;
first_object = s - > schema_part . first_object ;
2009-09-03 12:31:45 +04:00
linked_attributes_count = c - > ctr6 - > linked_attributes_count ;
linked_attributes = c - > ctr6 - > linked_attributes ;
2008-04-09 06:02:11 +04:00
s_dsa - > highwatermark = c - > ctr6 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr6 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr6 - > source_dsa_invocation_id ;
uptodateness_vector = c - > ctr6 - > uptodateness_vector ;
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
2010-01-17 13:59:56 +03:00
s_dsa - > replica_flags = DRSUAPI_DRS_WRIT_REP
| DRSUAPI_DRS_INIT_SYNC
| DRSUAPI_DRS_PER_SYNC ;
2008-04-09 06:02:11 +04:00
memset ( s_dsa - > schedule , 0x11 , sizeof ( s_dsa - > schedule ) ) ;
tmp_dns_name = GUID_string ( s_dsa - > other_info , & s_dsa - > source_dsa_obj_guid ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
tmp_dns_name = talloc_asprintf_append_buffer ( tmp_dns_name , " ._msdcs.%s " , c - > forest - > dns_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
s_dsa - > other_info - > dns_name = tmp_dns_name ;
2010-06-10 15:33:45 +04:00
schema_ldb = provision_get_schema ( s , s - > lp_ctx , & s - > prefixmap_blob ) ;
if ( ! schema_ldb ) {
DEBUG ( 0 , ( " Failed to re-load from local provision using remote prefixMap. Will continue with local prefixMap \n " ) ) ;
s - > provision_schema = dsdb_get_schema ( s - > ldb , s ) ;
} else {
s - > provision_schema = dsdb_get_schema ( schema_ldb , s ) ;
ret = dsdb_reference_schema ( s - > ldb , s - > provision_schema , false ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Failed to attach schema from local provision using remote prefixMap. " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
talloc_free ( schema_ldb ) ;
}
2010-06-09 14:52:02 +04:00
s - > provision_schema - > relax_OID_conversions = true ;
2010-06-12 05:05:47 +04:00
/* Now convert the schema elements, using the schema we loaded locally */
for ( i = 0 , cur = first_object ; cur ; cur = cur - > next_object , i + + ) {
struct dsdb_extended_replicated_object object ;
TALLOC_CTX * tmp_ctx = talloc_new ( s ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
/* Convert the objects into LDB messages using the
* provision schema , and either the provision or DRS
* prefix map - it should not matter , as these are
* just schema objects , so the critical parts . At
* most we would mix up the mayContain etc for new
* schema classes */
status = dsdb_convert_object_ex ( s - > ldb , s - > provision_schema ,
cur , c - > gensec_skey ,
tmp_ctx , & object ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Warning: Failed to convert schema object %s into ldb msg \n " , cur - > object . identifier - > dn ) ) ;
} else {
/* Convert the schema from ldb_message format
* ( OIDs as OID strings ) into schema , using
* the remote prefixMap */
status = dsdb_schema_set_el_from_ldb_msg ( s - > ldb , s - > self_made_schema , object . msg ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Warning: failed to convert object %s into a schema element: %s \n " ,
ldb_dn_get_linearized ( object . msg - > dn ) ,
win_errstr ( status ) ) ) ;
}
}
talloc_free ( tmp_ctx ) ;
2010-06-09 12:57:52 +04:00
}
2008-04-09 06:02:11 +04:00
2010-06-12 05:05:47 +04:00
/* attach the schema we just brought over DRS to the ldb, so we can use it in dsdb_convert_object_ex below */
ret = dsdb_set_schema ( s - > ldb , s - > self_made_schema ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Failed to attach 1st pass schema from DRS. \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
/* Now convert the schema elements again, using the schema we loaded over DRS */
for ( i = 0 , cur = first_object ; cur ; cur = cur - > next_object , i + + ) {
struct dsdb_extended_replicated_object object ;
TALLOC_CTX * tmp_ctx = talloc_new ( s ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
/* Convert the objects into LDB messages using the
* self_made_schema , and the DRS prefix map . We now
* know the full schema int - > OID - > name mapping , so we
* can get it right this time */
status = dsdb_convert_object_ex ( s - > ldb , s - > self_made_schema ,
cur , c - > gensec_skey ,
tmp_ctx , & object ) ;
2010-06-09 12:57:52 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2010-06-12 05:05:47 +04:00
DEBUG ( 0 , ( " ERROR: Failed to convert schema object %s into ldb msg \n " , cur - > object . identifier - > dn ) ) ;
} else {
/* Convert the schema from ldb_message format
* ( OIDs as OID strings ) into schema , using
* the remote prefixMap , now that we know
* names for all the schema elements ( from the
* first conversion ) */
status = dsdb_schema_set_el_from_ldb_msg ( s - > ldb , s - > self_corrected_schema , object . msg ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 0 , ( " ERROR: failed to convert object %s into a schema element: %s \n " ,
ldb_dn_get_linearized ( object . msg - > dn ) ,
win_errstr ( status ) ) ) ;
}
2007-11-03 13:21:04 +03:00
}
2010-06-12 05:05:47 +04:00
talloc_free ( tmp_ctx ) ;
2005-05-02 18:17:19 +04:00
}
2010-06-12 05:05:47 +04:00
/* We don't want to use the s->self_made_schema any more */
s - > self_made_schema = NULL ;
2005-05-02 18:17:19 +04:00
2010-06-09 12:57:52 +04:00
/* attach the schema we just brought over DRS to the ldb */
2010-06-12 05:05:47 +04:00
ret = dsdb_set_schema ( s - > ldb , s - > self_corrected_schema ) ;
2008-04-09 06:02:11 +04:00
if ( ret ! = LDB_SUCCESS ) {
2010-06-12 05:05:47 +04:00
DEBUG ( 0 , ( " Failed to attach 2nd pass (corrected) schema from DRS. \n " ) ) ;
2008-04-09 06:02:11 +04:00
return NT_STATUS_FOOBAR ;
}
2010-06-09 12:57:52 +04:00
2008-04-09 06:02:11 +04:00
/* we don't want to access the self made schema anymore */
2010-06-12 05:05:47 +04:00
s - > schema = s - > self_corrected_schema ;
s - > self_corrected_schema = NULL ;
2008-04-09 06:02:11 +04:00
2010-06-12 05:05:47 +04:00
/* Now convert the schema elements again, using the schema we finalised, ready to actually import */
status = dsdb_extended_replicated_objects_convert ( s - > ldb ,
2009-11-09 13:26:02 +03:00
c - > partition - > nc . dn ,
mapping_ctr ,
object_count ,
first_object ,
linked_attributes_count ,
linked_attributes ,
s_dsa ,
uptodateness_vector ,
c - > gensec_skey ,
2010-06-12 05:05:47 +04:00
s , & schema_objs ) ;
2008-04-09 06:02:11 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2010-06-09 15:53:01 +04:00
DEBUG ( 0 , ( " Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s \n " , win_errstr ( status ) ) ) ;
2008-04-09 06:02:11 +04:00
return werror_to_ntstatus ( status ) ;
}
2005-05-21 10:31:02 +04:00
2010-07-16 08:32:42 +04:00
if ( lpcfg_parm_bool ( s - > lp_ctx , NULL , " become dc " , " dump objects " , false ) ) {
2010-06-12 05:05:47 +04:00
for ( i = 0 ; i < schema_objs - > num_objects ; i + + ) {
2008-04-09 06:02:11 +04:00
struct ldb_ldif ldif ;
fprintf ( stdout , " # \n " ) ;
ldif . changetype = LDB_CHANGETYPE_NONE ;
2010-06-12 05:05:47 +04:00
ldif . msg = schema_objs - > objects [ i ] . msg ;
2008-04-09 06:02:11 +04:00
ldb_ldif_write_file ( s - > ldb , stdout , & ldif ) ;
2010-06-12 05:05:47 +04:00
NDR_PRINT_DEBUG ( replPropertyMetaDataBlob , schema_objs - > objects [ i ] . meta_data ) ;
2008-04-09 06:02:11 +04:00
}
}
2010-06-12 05:05:47 +04:00
status = dsdb_extended_replicated_objects_commit ( s - > ldb , schema_objs , & seq_num ) ;
2009-11-09 13:26:02 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to commit objects: %s \n " , win_errstr ( status ) ) ) ;
return werror_to_ntstatus ( status ) ;
}
2010-06-12 05:05:47 +04:00
msg = ldb_msg_new ( schema_objs ) ;
2008-04-09 06:02:11 +04:00
NT_STATUS_HAVE_NO_MEMORY ( msg ) ;
2010-06-12 05:05:47 +04:00
msg - > dn = schema_objs - > partition_dn ;
/* We must ensure a prefixMap has been written. Unlike other
* attributes ( including schemaInfo ) , it is not replicated in
* the normal replication stream . We can use the one from
* s - > prefixmap_blob because we operate with one , unchanging
* prefixMap for this entire operation . */
ret = ldb_msg_add_value ( msg , " prefixMap " , & s - > prefixmap_blob , & prefixMap_el ) ;
2008-04-09 06:02:11 +04:00
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_FOOBAR ;
}
2010-06-12 05:05:47 +04:00
/* We want to know if a prefixMap was written already, as it
* would mean that the above comment was not true , and we have
* somehow updated the prefixMap during this transaction */
prefixMap_el - > flags = LDB_FLAG_MOD_ADD ;
2008-04-09 06:02:11 +04:00
ret = ldb_modify ( s - > ldb , msg ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-06-12 05:05:47 +04:00
DEBUG ( 0 , ( " Failed to add prefixMap: %s \n " , ldb_errstring ( s - > ldb ) ) ) ;
2008-04-09 06:02:11 +04:00
return NT_STATUS_FOOBAR ;
}
talloc_free ( s_dsa ) ;
2010-06-12 05:05:47 +04:00
talloc_free ( schema_objs ) ;
2008-04-09 06:02:11 +04:00
2009-09-02 10:57:25 +04:00
/* We must set these up to ensure the replMetaData is written
* correctly , before our NTDS Settings entry is replicated */
2008-04-09 06:02:11 +04:00
ok = samdb_set_ntds_invocation_id ( s - > ldb , & c - > dest_dsa - > invocation_id ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to set cached ntds invocationId \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
ok = samdb_set_ntds_objectGUID ( s - > ldb , & c - > dest_dsa - > ntds_guid ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to set cached ntds objectGUID \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
2010-03-16 06:52:39 +03:00
s - > schema = dsdb_get_schema ( s - > ldb , s ) ;
2008-04-09 06:02:11 +04:00
if ( ! s - > schema ) {
DEBUG ( 0 , ( " Failed to get loaded dsdb_schema \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
2005-05-21 10:31:02 +04:00
return NT_STATUS_OK ;
}
2010-06-12 11:22:20 +04:00
NTSTATUS libnet_vampire_cb_schema_chunk ( void * private_data ,
const struct libnet_BecomeDC_StoreChunk * c )
2005-05-03 18:38:14 +04:00
{
2010-06-12 11:22:20 +04:00
struct libnet_vampire_cb_state * s = talloc_get_type ( private_data , struct libnet_vampire_cb_state ) ;
2008-04-09 06:02:11 +04:00
WERROR status ;
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ;
2008-07-15 18:59:09 +04:00
uint32_t nc_object_count ;
2008-04-09 06:02:11 +04:00
uint32_t object_count ;
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
struct drsuapi_DsReplicaObjectListItemEx * cur ;
2008-07-16 15:02:54 +04:00
uint32_t nc_linked_attributes_count ;
uint32_t linked_attributes_count ;
2009-09-03 12:31:45 +04:00
struct drsuapi_DsReplicaLinkedAttribute * linked_attributes ;
2008-04-09 06:02:11 +04:00
switch ( c - > ctr_level ) {
case 1 :
2008-07-16 15:02:54 +04:00
mapping_ctr = & c - > ctr1 - > mapping_ctr ;
nc_object_count = c - > ctr1 - > extended_ret ; /* maybe w2k send this unexpected? */
object_count = c - > ctr1 - > object_count ;
first_object = c - > ctr1 - > first_object ;
nc_linked_attributes_count = 0 ;
linked_attributes_count = 0 ;
2009-09-03 12:31:45 +04:00
linked_attributes = NULL ;
2005-05-03 18:38:14 +04:00
break ;
2008-04-09 06:02:11 +04:00
case 6 :
2008-07-16 15:02:54 +04:00
mapping_ctr = & c - > ctr6 - > mapping_ctr ;
nc_object_count = c - > ctr6 - > nc_object_count ;
object_count = c - > ctr6 - > object_count ;
first_object = c - > ctr6 - > first_object ;
nc_linked_attributes_count = c - > ctr6 - > nc_linked_attributes_count ;
linked_attributes_count = c - > ctr6 - > linked_attributes_count ;
2009-09-03 12:31:45 +04:00
linked_attributes = c - > ctr6 - > linked_attributes ;
2005-05-21 10:31:02 +04:00
break ;
2005-07-25 05:19:16 +04:00
default :
2008-04-09 06:02:11 +04:00
return NT_STATUS_INVALID_PARAMETER ;
2005-05-03 18:38:14 +04:00
}
2005-05-02 18:17:19 +04:00
2008-07-15 18:59:09 +04:00
if ( nc_object_count ) {
2008-07-16 15:02:54 +04:00
DEBUG ( 0 , ( " Schema-DN[%s] objects[%u/%u] linked_values[%u/%u] \n " ,
c - > partition - > nc . dn , object_count , nc_object_count ,
linked_attributes_count , nc_linked_attributes_count ) ) ;
2008-04-09 06:02:11 +04:00
} else {
2009-09-26 07:47:06 +04:00
DEBUG ( 0 , ( " Schema-DN[%s] objects[%u] linked_values[%u] \n " ,
2008-07-16 15:02:54 +04:00
c - > partition - > nc . dn , object_count , linked_attributes_count ) ) ;
2008-04-09 06:02:11 +04:00
}
2010-06-12 05:05:47 +04:00
if ( ! s - > self_made_schema ) {
2010-06-09 15:53:01 +04:00
WERROR werr ;
2010-06-10 15:33:45 +04:00
struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info ;
2010-06-09 15:53:01 +04:00
/* Put the DRS prefixmap aside for the schema we are
* about to load in the provision , and into the one we
* are making with the help of DRS */
2010-06-10 15:33:45 +04:00
mapping_ctr_without_schema_info = * mapping_ctr ;
/* This strips off the 0xFF schema info from the end,
* because we don ' t want it in the blob */
if ( mapping_ctr_without_schema_info . num_mappings > 0 ) {
mapping_ctr_without_schema_info . num_mappings - - ;
}
werr = dsdb_get_drsuapi_prefixmap_as_blob ( & mapping_ctr_without_schema_info , s , & s - > prefixmap_blob ) ;
2010-06-09 15:53:01 +04:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werror_to_ntstatus ( werr ) ;
}
2010-06-12 05:05:47 +04:00
/* Set up two manually-constructed schema - the local
* schema from the provision will be used to build
* one , which will then in turn be used to build the
* other . */
2010-05-09 19:20:01 +04:00
s - > self_made_schema = dsdb_new_schema ( s ) ;
2008-04-09 06:02:11 +04:00
NT_STATUS_HAVE_NO_MEMORY ( s - > self_made_schema ) ;
2010-06-12 05:05:47 +04:00
s - > self_corrected_schema = dsdb_new_schema ( s ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > self_corrected_schema ) ;
2008-04-09 06:02:11 +04:00
2009-11-03 11:05:51 +03:00
status = dsdb_load_prefixmap_from_drsuapi ( s - > self_made_schema , mapping_ctr ) ;
2008-04-09 06:02:11 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
2005-07-25 06:23:41 +04:00
}
2008-04-09 06:02:11 +04:00
2010-06-12 05:05:47 +04:00
status = dsdb_load_prefixmap_from_drsuapi ( s - > self_corrected_schema , mapping_ctr ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
2008-04-09 06:02:11 +04:00
} else {
2010-06-12 05:05:47 +04:00
status = dsdb_schema_pfm_contains_drsuapi_pfm ( s - > self_made_schema - > prefixmap , mapping_ctr ) ;
2008-04-09 06:02:11 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
2005-07-25 06:23:41 +04:00
}
2008-04-09 06:02:11 +04:00
}
if ( ! s - > schema_part . first_object ) {
s - > schema_part . object_count = object_count ;
s - > schema_part . first_object = talloc_steal ( s , first_object ) ;
2005-07-25 06:23:41 +04:00
} else {
2008-04-09 06:02:11 +04:00
s - > schema_part . object_count + = object_count ;
s - > schema_part . last_object - > next_object = talloc_steal ( s - > schema_part . last_object ,
first_object ) ;
2005-05-02 18:17:19 +04:00
}
2008-04-09 06:02:11 +04:00
for ( cur = first_object ; cur - > next_object ; cur = cur - > next_object ) { }
s - > schema_part . last_object = cur ;
2005-07-25 06:23:41 +04:00
2008-07-16 15:01:56 +04:00
if ( ! c - > partition - > more_data ) {
2010-06-12 11:22:20 +04:00
return libnet_vampire_cb_apply_schema ( s , c ) ;
2005-05-02 18:17:19 +04:00
}
2008-04-09 06:02:11 +04:00
return NT_STATUS_OK ;
}
2010-06-12 11:22:20 +04:00
NTSTATUS libnet_vampire_cb_store_chunk ( void * private_data ,
const struct libnet_BecomeDC_StoreChunk * c )
2008-04-09 06:02:11 +04:00
{
2010-06-12 11:22:20 +04:00
struct libnet_vampire_cb_state * s = talloc_get_type ( private_data , struct libnet_vampire_cb_state ) ;
2008-04-09 06:02:11 +04:00
WERROR status ;
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ;
2008-07-15 18:59:09 +04:00
uint32_t nc_object_count ;
2008-04-09 06:02:11 +04:00
uint32_t object_count ;
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
2008-07-16 15:02:54 +04:00
uint32_t nc_linked_attributes_count ;
2008-04-09 06:02:11 +04:00
uint32_t linked_attributes_count ;
struct drsuapi_DsReplicaLinkedAttribute * linked_attributes ;
const struct drsuapi_DsReplicaCursor2CtrEx * uptodateness_vector ;
struct dsdb_extended_replicated_objects * objs ;
struct repsFromTo1 * s_dsa ;
char * tmp_dns_name ;
uint32_t i ;
2009-09-16 01:42:26 +04:00
uint64_t seq_num ;
2008-04-09 06:02:11 +04:00
s_dsa = talloc_zero ( s , struct repsFromTo1 ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa ) ;
s_dsa - > other_info = talloc ( s_dsa , struct repsFromTo1OtherInfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa - > other_info ) ;
switch ( c - > ctr_level ) {
case 1 :
mapping_ctr = & c - > ctr1 - > mapping_ctr ;
2008-07-15 18:59:09 +04:00
nc_object_count = c - > ctr1 - > extended_ret ; /* maybe w2k send this unexpected? */
2008-04-09 06:02:11 +04:00
object_count = c - > ctr1 - > object_count ;
first_object = c - > ctr1 - > first_object ;
2008-07-16 15:02:54 +04:00
nc_linked_attributes_count = 0 ;
2008-04-09 06:02:11 +04:00
linked_attributes_count = 0 ;
linked_attributes = NULL ;
s_dsa - > highwatermark = c - > ctr1 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr1 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr1 - > source_dsa_invocation_id ;
uptodateness_vector = NULL ; /* TODO: map it */
break ;
case 6 :
mapping_ctr = & c - > ctr6 - > mapping_ctr ;
2008-07-15 18:59:09 +04:00
nc_object_count = c - > ctr6 - > nc_object_count ;
2008-04-09 06:02:11 +04:00
object_count = c - > ctr6 - > object_count ;
first_object = c - > ctr6 - > first_object ;
2008-07-16 15:02:54 +04:00
nc_linked_attributes_count = c - > ctr6 - > nc_linked_attributes_count ;
2008-04-09 06:02:11 +04:00
linked_attributes_count = c - > ctr6 - > linked_attributes_count ;
linked_attributes = c - > ctr6 - > linked_attributes ;
s_dsa - > highwatermark = c - > ctr6 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr6 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr6 - > source_dsa_invocation_id ;
uptodateness_vector = c - > ctr6 - > uptodateness_vector ;
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
2006-01-12 12:33:49 +03:00
}
2010-01-17 13:59:56 +03:00
s_dsa - > replica_flags = DRSUAPI_DRS_WRIT_REP
| DRSUAPI_DRS_INIT_SYNC
| DRSUAPI_DRS_PER_SYNC ;
2008-04-09 06:02:11 +04:00
memset ( s_dsa - > schedule , 0x11 , sizeof ( s_dsa - > schedule ) ) ;
tmp_dns_name = GUID_string ( s_dsa - > other_info , & s_dsa - > source_dsa_obj_guid ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
tmp_dns_name = talloc_asprintf_append_buffer ( tmp_dns_name , " ._msdcs.%s " , c - > forest - > dns_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
s_dsa - > other_info - > dns_name = tmp_dns_name ;
2009-09-03 12:31:45 +04:00
/* we want to show a count per partition */
if ( ! s - > last_partition | | strcmp ( s - > last_partition , c - > partition - > nc . dn ) ! = 0 ) {
s - > total_objects = 0 ;
talloc_free ( s - > last_partition ) ;
s - > last_partition = talloc_strdup ( s , c - > partition - > nc . dn ) ;
}
s - > total_objects + = object_count ;
2008-07-15 18:59:09 +04:00
if ( nc_object_count ) {
2008-07-16 15:02:54 +04:00
DEBUG ( 0 , ( " Partition[%s] objects[%u/%u] linked_values[%u/%u] \n " ,
2009-09-03 12:31:45 +04:00
c - > partition - > nc . dn , s - > total_objects , nc_object_count ,
2008-07-16 15:02:54 +04:00
linked_attributes_count , nc_linked_attributes_count ) ) ;
2006-01-12 12:33:49 +03:00
} else {
2009-09-26 07:47:06 +04:00
DEBUG ( 0 , ( " Partition[%s] objects[%u] linked_values[%u] \n " ,
2009-09-03 12:31:45 +04:00
c - > partition - > nc . dn , s - > total_objects , linked_attributes_count ) ) ;
2006-01-12 12:33:49 +03:00
}
2008-04-09 06:02:11 +04:00
2009-09-03 12:31:45 +04:00
2009-11-09 13:26:02 +03:00
status = dsdb_extended_replicated_objects_convert ( s - > ldb ,
c - > partition - > nc . dn ,
mapping_ctr ,
object_count ,
first_object ,
linked_attributes_count ,
linked_attributes ,
s_dsa ,
uptodateness_vector ,
c - > gensec_skey ,
s , & objs ) ;
2008-04-09 06:02:11 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2009-11-09 13:26:02 +03:00
DEBUG ( 0 , ( " Failed to convert objects: %s \n " , win_errstr ( status ) ) ) ;
2008-04-09 06:02:11 +04:00
return werror_to_ntstatus ( status ) ;
2006-01-12 12:33:49 +03:00
}
2008-04-09 06:02:11 +04:00
2010-07-16 08:32:42 +04:00
if ( lpcfg_parm_bool ( s - > lp_ctx , NULL , " become dc " , " dump objects " , false ) ) {
2008-04-09 06:02:11 +04:00
for ( i = 0 ; i < objs - > num_objects ; i + + ) {
struct ldb_ldif ldif ;
fprintf ( stdout , " # \n " ) ;
ldif . changetype = LDB_CHANGETYPE_NONE ;
ldif . msg = objs - > objects [ i ] . msg ;
ldb_ldif_write_file ( s - > ldb , stdout , & ldif ) ;
NDR_PRINT_DEBUG ( replPropertyMetaDataBlob , objs - > objects [ i ] . meta_data ) ;
2006-01-13 00:42:26 +03:00
}
2005-05-02 18:17:19 +04:00
}
2009-11-09 13:26:02 +03:00
status = dsdb_extended_replicated_objects_commit ( s - > ldb ,
objs , & seq_num ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to commit objects: %s \n " , win_errstr ( status ) ) ) ;
return werror_to_ntstatus ( status ) ;
}
2008-04-09 06:02:11 +04:00
talloc_free ( s_dsa ) ;
talloc_free ( objs ) ;
2005-05-02 18:17:19 +04:00
2008-04-09 06:02:11 +04:00
for ( i = 0 ; i < linked_attributes_count ; i + + ) {
const struct dsdb_attribute * sa ;
2006-01-12 12:33:49 +03:00
2008-04-09 06:02:11 +04:00
if ( ! linked_attributes [ i ] . identifier ) {
return NT_STATUS_FOOBAR ;
}
2006-01-12 12:33:49 +03:00
2008-04-09 06:02:11 +04:00
if ( ! linked_attributes [ i ] . value . blob ) {
return NT_STATUS_FOOBAR ;
}
2005-05-02 18:17:19 +04:00
2008-04-09 06:02:11 +04:00
sa = dsdb_attribute_by_attributeID_id ( s - > schema ,
linked_attributes [ i ] . attid ) ;
if ( ! sa ) {
return NT_STATUS_FOOBAR ;
}
2005-05-02 18:17:19 +04:00
2010-07-16 08:32:42 +04:00
if ( lpcfg_parm_bool ( s - > lp_ctx , NULL , " become dc " , " dump objects " , false ) ) {
2008-04-09 06:02:11 +04:00
DEBUG ( 0 , ( " # %s \n " , sa - > lDAPDisplayName ) ) ;
NDR_PRINT_DEBUG ( drsuapi_DsReplicaLinkedAttribute , & linked_attributes [ i ] ) ;
dump_data ( 0 ,
linked_attributes [ i ] . value . blob - > data ,
linked_attributes [ i ] . value . blob - > length ) ;
}
2005-05-02 18:17:19 +04:00
}
2008-04-09 06:02:11 +04:00
return NT_STATUS_OK ;
}
2010-08-02 17:47:38 +04:00
static NTSTATUS update_dnshostname_for_server ( TALLOC_CTX * mem_ctx ,
struct ldb_context * ldb ,
const char * server_dn_str ,
const char * netbios_name ,
const char * realm )
{
int ret ;
struct ldb_message * msg ;
struct ldb_message_element * el ;
struct ldb_dn * server_dn ;
const char * dNSHostName = strlower_talloc ( mem_ctx ,
talloc_asprintf ( mem_ctx ,
" %s.%s " ,
netbios_name ,
realm ) ) ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
server_dn = ldb_dn_new ( mem_ctx , ldb , server_dn_str ) ;
if ( ! server_dn ) {
return NT_STATUS_INTERNAL_ERROR ;
}
msg - > dn = server_dn ;
ret = ldb_msg_add_empty ( msg , " dNSHostName " , LDB_FLAG_MOD_ADD , & el ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_INTERNAL_ERROR ;
}
ret = ldb_msg_add_steal_string ( msg ,
" dNSHostName " ,
talloc_asprintf ( el - > values , " %s " , dNSHostName ) ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_INTERNAL_ERROR ;
}
ret = dsdb_modify ( ldb , msg , DSDB_MODIFY_PERMISSIVE ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " : Failed to add dnsHostName to the Server object: %s \n " ,
ldb_errstring ( ldb ) ) ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
return NT_STATUS_OK ;
}
2008-04-09 08:59:32 +04:00
NTSTATUS libnet_Vampire ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_Vampire * r )
2008-04-09 06:02:11 +04:00
{
struct libnet_JoinDomain * join ;
2010-08-23 05:13:22 +04:00
struct libnet_Replicate rep ;
2008-04-09 06:02:11 +04:00
NTSTATUS status ;
const char * account_name ;
const char * netbios_name ;
2006-01-13 15:52:56 +03:00
2008-04-09 06:02:11 +04:00
r - > out . error_string = NULL ;
2010-06-12 11:22:20 +04:00
join = talloc_zero ( mem_ctx , struct libnet_JoinDomain ) ;
2008-04-09 06:02:11 +04:00
if ( ! join ) {
return NT_STATUS_NO_MEMORY ;
}
if ( r - > in . netbios_name ! = NULL ) {
netbios_name = r - > in . netbios_name ;
} else {
2010-07-16 08:32:42 +04:00
netbios_name = talloc_reference ( join , lpcfg_netbios_name ( ctx - > lp_ctx ) ) ;
2008-04-09 06:02:11 +04:00
if ( ! netbios_name ) {
2010-06-12 11:22:20 +04:00
talloc_free ( join ) ;
2008-04-09 06:02:11 +04:00
r - > out . error_string = NULL ;
return NT_STATUS_NO_MEMORY ;
2006-01-13 15:52:56 +03:00
}
}
2008-04-09 06:02:11 +04:00
account_name = talloc_asprintf ( join , " %s$ " , netbios_name ) ;
if ( ! account_name ) {
2010-06-12 11:22:20 +04:00
talloc_free ( join ) ;
2008-04-09 06:02:11 +04:00
r - > out . error_string = NULL ;
return NT_STATUS_NO_MEMORY ;
}
2010-04-29 02:51:01 +04:00
/* Re-use the domain we are joining as the domain for the user
* to be authenticated with , unless they specified
* otherwise */
cli_credentials_set_domain ( ctx - > cred , r - > in . domain_name , CRED_GUESS_ENV ) ;
2008-04-09 06:02:11 +04:00
join - > in . domain_name = r - > in . domain_name ;
join - > in . account_name = account_name ;
join - > in . netbios_name = netbios_name ;
join - > in . level = LIBNET_JOINDOMAIN_AUTOMATIC ;
join - > in . acct_type = ACB_WSTRUST ;
join - > in . recreate_account = false ;
status = libnet_JoinDomain ( ctx , join , join ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
r - > out . error_string = talloc_steal ( mem_ctx , join - > out . error_string ) ;
2010-06-12 11:22:20 +04:00
talloc_free ( join ) ;
2008-04-09 06:02:11 +04:00
return status ;
}
2010-08-23 05:13:22 +04:00
rep . in . domain_name = join - > out . domain_name ;
rep . in . netbios_name = netbios_name ;
rep . in . targetdir = r - > in . targetdir ;
rep . in . domain_sid = join - > out . domain_sid ;
rep . in . realm = join - > out . realm ;
rep . in . server = join - > out . samr_binding - > host ;
rep . in . join_password = join - > out . join_password ;
rep . in . kvno = join - > out . kvno ;
status = libnet_Replicate ( ctx , mem_ctx , & rep ) ;
r - > out . domain_sid = join - > out . domain_sid ;
r - > out . domain_name = join - > out . domain_name ;
r - > out . error_string = rep . out . error_string ;
return status ;
}
NTSTATUS libnet_Replicate ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_Replicate * r )
{
struct provision_store_self_join_settings * set_secrets ;
struct libnet_BecomeDC b ;
struct libnet_vampire_cb_state * s ;
struct ldb_message * msg ;
const char * error_string ;
int ldb_ret ;
uint32_t i ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
const char * account_name ;
const char * netbios_name ;
r - > out . error_string = NULL ;
netbios_name = r - > in . netbios_name ;
account_name = talloc_asprintf ( tmp_ctx , " %s$ " , netbios_name ) ;
if ( ! account_name ) {
talloc_free ( tmp_ctx ) ;
r - > out . error_string = NULL ;
return NT_STATUS_NO_MEMORY ;
}
2008-04-09 06:02:11 +04:00
2010-08-23 05:13:22 +04:00
/* Re-use the domain we are joining as the domain for the user
* to be authenticated with , unless they specified
* otherwise */
cli_credentials_set_domain ( ctx - > cred , r - > in . domain_name , CRED_GUESS_ENV ) ;
2010-06-12 11:22:20 +04:00
s = libnet_vampire_cb_state_init ( mem_ctx , ctx - > lp_ctx , ctx - > event_ctx ,
2010-08-23 05:13:22 +04:00
netbios_name , r - > in . domain_name , r - > in . realm ,
2010-06-12 11:22:20 +04:00
r - > in . targetdir ) ;
if ( ! s ) {
return NT_STATUS_NO_MEMORY ;
}
2010-08-23 05:13:22 +04:00
talloc_steal ( s , tmp_ctx ) ;
2008-04-09 08:59:32 +04:00
2008-04-09 06:02:11 +04:00
ZERO_STRUCT ( b ) ;
2010-04-29 02:51:01 +04:00
/* Be more robust:
* We now know the domain and realm for sure - if they didn ' t
* put one on the command line , use this for the rest of the
* join */
2010-08-23 05:13:22 +04:00
cli_credentials_set_realm ( ctx - > cred , r - > in . realm , CRED_GUESS_ENV ) ;
cli_credentials_set_domain ( ctx - > cred , r - > in . domain_name , CRED_GUESS_ENV ) ;
2010-04-29 02:51:01 +04:00
/* Now set these values into the smb.conf - we probably had
* empty or useless defaults here from whatever smb . conf we
* started with */
2010-08-23 05:13:22 +04:00
lpcfg_set_cmdline ( s - > lp_ctx , " realm " , r - > in . realm ) ;
lpcfg_set_cmdline ( s - > lp_ctx , " workgroup " , r - > in . domain_name ) ;
2010-04-29 02:51:01 +04:00
2010-08-23 05:13:22 +04:00
b . in . domain_dns_name = r - > in . realm ;
b . in . domain_netbios_name = r - > in . domain_name ;
b . in . domain_sid = r - > in . domain_sid ;
b . in . source_dsa_address = r - > in . server ;
2008-04-09 06:02:11 +04:00
b . in . dest_dsa_netbios_name = netbios_name ;
b . in . callbacks . private_data = s ;
2010-06-12 11:22:20 +04:00
b . in . callbacks . check_options = libnet_vampire_cb_check_options ;
b . in . callbacks . prepare_db = libnet_vampire_cb_prepare_db ;
b . in . callbacks . schema_chunk = libnet_vampire_cb_schema_chunk ;
b . in . callbacks . config_chunk = libnet_vampire_cb_store_chunk ;
b . in . callbacks . domain_chunk = libnet_vampire_cb_store_chunk ;
2008-04-09 06:02:11 +04:00
2010-07-16 08:32:42 +04:00
b . in . rodc_join = lpcfg_parm_bool ( s - > lp_ctx , NULL , " repl " , " RODC " , false ) ;
2010-02-17 19:01:31 +03:00
2008-04-09 08:59:32 +04:00
status = libnet_BecomeDC ( ctx , s , & b ) ;
2008-04-09 06:02:11 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " libnet_BecomeDC() failed - %s \n " , nt_errstr ( status ) ) ;
talloc_free ( s ) ;
return status ;
}
2005-05-02 18:17:19 +04:00
2008-04-09 06:02:11 +04:00
msg = ldb_msg_new ( s ) ;
if ( ! msg ) {
printf ( " ldb_msg_new() failed \n " ) ;
talloc_free ( s ) ;
return NT_STATUS_NO_MEMORY ;
}
msg - > dn = ldb_dn_new ( msg , s - > ldb , " @ROOTDSE " ) ;
if ( ! msg - > dn ) {
printf ( " ldb_msg_new(@ROOTDSE) failed \n " ) ;
talloc_free ( s ) ;
return NT_STATUS_NO_MEMORY ;
2005-05-02 18:17:19 +04:00
}
2008-04-09 06:02:11 +04:00
ldb_ret = ldb_msg_add_string ( msg , " isSynchronized " , " TRUE " ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
printf ( " ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d \n " , ldb_ret ) ;
talloc_free ( s ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-05-02 18:17:19 +04:00
2008-04-09 06:02:11 +04:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
msg - > elements [ i ] . flags = LDB_FLAG_MOD_REPLACE ;
}
2006-01-12 12:33:49 +03:00
2008-04-09 06:02:11 +04:00
printf ( " mark ROOTDSE with isSynchronized=TRUE \n " ) ;
ldb_ret = ldb_modify ( s - > ldb , msg ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
2010-01-07 04:19:42 +03:00
printf ( " ldb_modify() failed: %d : %s \n " , ldb_ret , ldb_errstring ( s - > ldb ) ) ;
2008-04-09 06:02:11 +04:00
talloc_free ( s ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
2005-05-03 18:38:14 +04:00
}
2010-08-02 17:47:38 +04:00
/* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
* the attribute appears on the original DC after replication
*/
status = update_dnshostname_for_server ( s , s - > ldb , s - > server_dn_str , s - > netbios_name , s - > realm ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to update dNSHostName on Server object - %s \n " , nt_errstr ( status ) ) ;
talloc_free ( s ) ;
return status ;
}
2009-09-21 03:27:24 +04:00
/* prepare the transaction - this prepares to commit all the changes in
the ldb from the whole vampire . Note that this
2009-09-02 10:57:25 +04:00
triggers the writing of the linked attribute backlinks .
*/
2009-09-21 03:27:24 +04:00
if ( ldb_transaction_prepare_commit ( s - > ldb ) ! = LDB_SUCCESS ) {
2010-01-07 04:19:42 +03:00
printf ( " Failed to prepare_commit vampire transaction: %s \n " , ldb_errstring ( s - > ldb ) ) ;
2009-09-02 10:57:25 +04:00
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2009-09-21 03:27:24 +04:00
set_secrets = talloc ( s , struct provision_store_self_join_settings ) ;
2008-04-09 08:59:32 +04:00
if ( ! set_secrets ) {
2009-09-21 03:27:24 +04:00
r - > out . error_string = NULL ;
talloc_free ( s ) ;
2008-04-09 08:59:32 +04:00
return NT_STATUS_NO_MEMORY ;
}
2009-09-21 03:27:24 +04:00
ZERO_STRUCTP ( set_secrets ) ;
2010-08-23 05:13:22 +04:00
set_secrets - > domain_name = r - > in . domain_name ;
set_secrets - > realm = r - > in . realm ;
2009-09-21 03:27:24 +04:00
set_secrets - > netbios_name = netbios_name ;
set_secrets - > secure_channel_type = SEC_CHAN_BDC ;
2010-08-23 05:13:22 +04:00
set_secrets - > machine_password = r - > in . join_password ;
set_secrets - > key_version_number = r - > in . kvno ;
set_secrets - > domain_sid = r - > in . domain_sid ;
2009-09-21 03:27:24 +04:00
2010-05-21 19:33:05 +04:00
status = provision_store_self_join ( ctx , s - > lp_ctx , ctx - > event_ctx , set_secrets , & error_string ) ;
2008-04-09 08:59:32 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-09-21 03:27:24 +04:00
r - > out . error_string = talloc_steal ( mem_ctx , error_string ) ;
2008-04-09 08:59:32 +04:00
talloc_free ( s ) ;
return status ;
}
2009-09-21 03:27:24 +04:00
/* commit the transaction now we know the secrets were written
* out properly
*/
if ( ldb_transaction_commit ( s - > ldb ) ! = LDB_SUCCESS ) {
printf ( " Failed to commit vampire transaction \n " ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
talloc_free ( s ) ;
2008-04-09 08:59:32 +04:00
return NT_STATUS_OK ;
2005-05-03 18:38:14 +04:00
}