LCOV - code coverage report
Current view: top level - source4/libnet - libnet_vampire.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 314 441 71.2 %
Date: 2024-06-10 12:05:21 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Extract the user/system database from a remote server
       5             : 
       6             :    Copyright (C) Stefan Metzmacher      2004-2006
       7             :    Copyright (C) Brad Henry 2005
       8             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : 
      25             : #include "includes.h"
      26             : #include "libnet/libnet.h"
      27             : #include "libnet/libnet_join_proto.h"
      28             : #include "lib/events/events.h"
      29             : #include "dsdb/samdb/samdb.h"
      30             : #include "../lib/util/dlinklist.h"
      31             : #include <ldb.h>
      32             : #include <ldb_errors.h>
      33             : #include "librpc/ndr/libndr.h"
      34             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      35             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      36             : #include "librpc/gen_ndr/ndr_misc.h"
      37             : #include "system/time.h"
      38             : #include "ldb_wrap.h"
      39             : #include "auth/auth.h"
      40             : #include "auth/credentials/credentials.h"
      41             : #include "param/param.h"
      42             : #include "param/provision.h"
      43             : #include "libcli/security/security.h"
      44             : #include "dsdb/common/util.h"
      45             : 
      46             : #undef DBGC_CLASS
      47             : #define DBGC_CLASS            DBGC_DRS_REPL
      48             : 
      49             : /*
      50             : List of tasks vampire.py must perform:
      51             : - Domain Join
      52             :  - but don't write the secrets.ldb
      53             :  - results for this should be enough to handle the provision
      54             : - if vampire method is samsync
      55             :  - Provision using these results
      56             :   - do we still want to support this NT4 technology?
      57             : - Start samsync with libnet code
      58             :  - provision in the callback
      59             : - Write out the secrets database, using the code from libnet_Join
      60             : 
      61             : */
      62             : struct libnet_vampire_cb_state {
      63             :         const char *netbios_name;
      64             :         const char *domain_name;
      65             :         const char *realm;
      66             :         struct cli_credentials *machine_account;
      67             : 
      68             :         /* Schema loaded from local LDIF files */
      69             :         struct dsdb_schema *provision_schema;
      70             : 
      71             :         /* 1st pass, with some OIDs/attribute names/class names not
      72             :          * converted, because we may not know them yet */
      73             :         struct dsdb_schema *self_made_schema;
      74             : 
      75             :         /* prefixMap in LDB format, from the remote DRS server */
      76             :         DATA_BLOB prefixmap_blob;
      77             :         const struct dsdb_schema *schema;
      78             : 
      79             :         struct ldb_context *ldb;
      80             : 
      81             :         struct {
      82             :                 uint32_t object_count;
      83             :                 struct drsuapi_DsReplicaObjectListItemEx *first_object;
      84             :                 struct drsuapi_DsReplicaObjectListItemEx *last_object;
      85             :         } schema_part;
      86             : 
      87             :         const char *targetdir;
      88             : 
      89             :         struct loadparm_context *lp_ctx;
      90             :         struct tevent_context *event_ctx;
      91             :         unsigned total_objects;
      92             :         unsigned total_links;
      93             :         char *last_partition;
      94             :         const char *server_dn_str;
      95             : };
      96             : 
      97             : /* initialise a state structure ready for replication of chunks */
      98         130 : void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
      99             :                                     struct ldb_context *samdb,
     100             :                                     struct loadparm_context *lp_ctx)
     101             : {
     102         130 :         struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
     103         130 :         if (!s) {
     104           0 :                 return NULL;
     105             :         }
     106             : 
     107         130 :         s->ldb              = samdb;
     108         130 :         s->lp_ctx           = lp_ctx;
     109         130 :         s->provision_schema = dsdb_get_schema(s->ldb, s);
     110         130 :         s->schema           = s->provision_schema;
     111         130 :         s->netbios_name     = lpcfg_netbios_name(lp_ctx);
     112         130 :         s->domain_name      = lpcfg_workgroup(lp_ctx);
     113         130 :         s->realm            = lpcfg_realm(lp_ctx);
     114             : 
     115         130 :         return s;
     116             : }
     117             : 
     118             : /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
     119           4 : void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
     120             :                                    struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
     121             :                                    const char *netbios_name, const char *domain_name, const char *realm,
     122             :                                    const char *targetdir)
     123             : {
     124           4 :         struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
     125           4 :         if (!s) {
     126           0 :                 return NULL;
     127             :         }
     128             : 
     129           4 :         s->lp_ctx = lp_ctx;
     130           4 :         s->event_ctx = event_ctx;
     131           4 :         s->netbios_name = netbios_name;
     132           4 :         s->domain_name = domain_name;
     133           4 :         s->realm = realm;
     134           4 :         s->targetdir = targetdir;
     135           4 :         return s;
     136             : }
     137             : 
     138           8 : struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
     139             : {
     140           8 :         state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
     141           8 :         return state->ldb;
     142             : }
     143             : 
     144           4 : struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
     145             : {
     146           4 :         state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
     147           4 :         return state->lp_ctx;
     148             : }
     149             : 
     150           4 : NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
     151             :                                       const struct libnet_BecomeDC_PrepareDB *p)
     152             : {
     153           4 :         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
     154           2 :         struct provision_settings settings;
     155           2 :         struct provision_result result;
     156           2 :         NTSTATUS status;
     157             : 
     158           4 :         ZERO_STRUCT(settings);
     159           4 :         settings.site_name = p->dest_dsa->site_name;
     160           4 :         settings.root_dn_str = p->forest->root_dn_str;
     161           4 :         settings.domain_dn_str = p->domain->dn_str;
     162           4 :         settings.config_dn_str = p->forest->config_dn_str;
     163           4 :         settings.schema_dn_str = p->forest->schema_dn_str;
     164           4 :         settings.netbios_name = p->dest_dsa->netbios_name;
     165           4 :         settings.realm = s->realm;
     166           4 :         settings.domain = s->domain_name;
     167           4 :         settings.server_dn_str = p->dest_dsa->server_dn_str;
     168           4 :         settings.machine_password = generate_random_machine_password(s, 120, 120);
     169           4 :         settings.targetdir = s->targetdir;
     170           4 :         settings.use_ntvfs = true;
     171           4 :         status = provision_bare(s, s->lp_ctx, &settings, &result);
     172             : 
     173           4 :         if (!NT_STATUS_IS_OK(status)) {
     174           2 :                 return status;
     175             :         }
     176             : 
     177           4 :         s->ldb = talloc_steal(s, result.samdb);
     178           4 :         s->lp_ctx = talloc_reparent(talloc_parent(result.lp_ctx), s, result.lp_ctx);
     179           4 :         s->provision_schema = dsdb_get_schema(s->ldb, s);
     180           4 :         s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
     181             : 
     182             :         /* wrap the entire vapire operation in a transaction.  This
     183             :            isn't just cosmetic - we use this to ensure that linked
     184             :            attribute back links are added at the end by relying on a
     185             :            transaction commit hook in the linked attributes module. We
     186             :            need to do this as the order of objects coming from the
     187             :            server is not sufficiently deterministic to know that the
     188             :            record that a backlink needs to be created in has itself
     189             :            been created before the object containing the forward link
     190             :            has come over the wire */
     191           4 :         if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
     192           0 :                 return NT_STATUS_FOOBAR;
     193             :         }
     194             : 
     195           4 :         return NT_STATUS_OK;
     196             : 
     197             : 
     198             : }
     199             : 
     200           4 : NTSTATUS libnet_vampire_cb_check_options(void *private_data,
     201             :                                          const struct libnet_BecomeDC_CheckOptions *o)
     202             : {
     203           4 :         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
     204             : 
     205           4 :         DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
     206             :                 s->netbios_name,
     207             :                 o->domain->netbios_name, o->domain->dns_name));
     208             : 
     209           4 :         DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
     210             :                 o->source_dsa->dns_name, o->source_dsa->site_name));
     211             : 
     212           4 :         DEBUG(0,("Options:crossRef behavior_version[%u]\n"
     213             :                        "\tschema object_version[%u]\n"
     214             :                        "\tdomain behavior_version[%u]\n"
     215             :                        "\tdomain w2k3_update_revision[%u]\n",
     216             :                 o->forest->crossref_behavior_version,
     217             :                 o->forest->schema_object_version,
     218             :                 o->domain->behavior_version,
     219             :                 o->domain->w2k3_update_revision));
     220             : 
     221           4 :         return NT_STATUS_OK;
     222             : }
     223             : 
     224          76 : static WERROR libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
     225             :                                              const struct libnet_BecomeDC_StoreChunk *c)
     226             : {
     227          71 :         WERROR status;
     228          71 :         struct dsdb_schema_prefixmap *pfm_remote;
     229          71 :         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
     230          71 :         struct dsdb_schema *provision_schema;
     231          76 :         uint32_t object_count = 0;
     232          71 :         struct drsuapi_DsReplicaObjectListItemEx *first_object;
     233          71 :         uint32_t linked_attributes_count;
     234          71 :         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
     235          71 :         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
     236          71 :         struct dsdb_extended_replicated_objects *schema_objs;
     237          71 :         struct repsFromTo1 *s_dsa;
     238          71 :         char *tmp_dns_name;
     239          71 :         struct ldb_context *schema_ldb;
     240          71 :         struct ldb_dn *partition_dn;
     241          71 :         struct ldb_message *msg;
     242          71 :         struct ldb_message_element *prefixMap_el;
     243          71 :         uint32_t i;
     244          71 :         int ret;
     245          71 :         bool ok;
     246          76 :         uint64_t seq_num = 0;
     247          71 :         uint32_t cycle_before_switching;
     248             : 
     249          76 :         DEBUG(0,("Analyze and apply schema objects\n"));
     250             : 
     251          76 :         s_dsa                   = talloc_zero(s, struct repsFromTo1);
     252          76 :         if (s_dsa == NULL) {
     253           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     254             :         }
     255          76 :         s_dsa->other_info    = talloc(s_dsa, struct repsFromTo1OtherInfo);
     256          76 :         if (s_dsa->other_info == NULL) {
     257           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     258             :         }
     259             : 
     260          76 :         switch (c->ctr_level) {
     261           0 :         case 1:
     262           0 :                 mapping_ctr                     = &c->ctr1->mapping_ctr;
     263           0 :                 object_count                    = s->schema_part.object_count;
     264           0 :                 first_object                    = s->schema_part.first_object;
     265           0 :                 linked_attributes_count         = 0;
     266           0 :                 linked_attributes               = NULL;
     267           0 :                 s_dsa->highwatermark         = c->ctr1->new_highwatermark;
     268           0 :                 s_dsa->source_dsa_obj_guid   = c->ctr1->source_dsa_guid;
     269           0 :                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
     270           0 :                 uptodateness_vector             = NULL; /* TODO: map it */
     271           0 :                 break;
     272          76 :         case 6:
     273          76 :                 mapping_ctr                     = &c->ctr6->mapping_ctr;
     274          76 :                 object_count                    = s->schema_part.object_count;
     275          76 :                 first_object                    = s->schema_part.first_object;
     276          76 :                 linked_attributes_count         = c->ctr6->linked_attributes_count;
     277          76 :                 linked_attributes               = c->ctr6->linked_attributes;
     278          76 :                 s_dsa->highwatermark         = c->ctr6->new_highwatermark;
     279          76 :                 s_dsa->source_dsa_obj_guid   = c->ctr6->source_dsa_guid;
     280          76 :                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
     281          76 :                 uptodateness_vector             = c->ctr6->uptodateness_vector;
     282          76 :                 break;
     283           0 :         default:
     284           0 :                 return WERR_INVALID_PARAMETER;
     285             :         }
     286             :         /* We must set these up to ensure the replMetaData is written
     287             :          * correctly, before our NTDS Settings entry is replicated */
     288          76 :         ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
     289          76 :         if (!ok) {
     290           0 :                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
     291           0 :                 return WERR_INTERNAL_ERROR;
     292             :         }
     293          76 :         ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
     294          76 :         if (!ok) {
     295           0 :                 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
     296           0 :                 return WERR_INTERNAL_ERROR;
     297             :         }
     298             : 
     299          76 :         status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
     300             :                                                   s, &pfm_remote, NULL);
     301          76 :         if (!W_ERROR_IS_OK(status)) {
     302           0 :                 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s\n",
     303             :                          win_errstr(status)));
     304           0 :                 return status;
     305             :         }
     306             : 
     307          76 :         s_dsa->replica_flags         = DRSUAPI_DRS_WRIT_REP
     308             :                                         | DRSUAPI_DRS_INIT_SYNC
     309             :                                         | DRSUAPI_DRS_PER_SYNC;
     310          76 :         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
     311             : 
     312          76 :         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
     313          76 :         if (tmp_dns_name == NULL) {
     314           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     315             :         }
     316          76 :         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
     317          76 :         if (tmp_dns_name == NULL) {
     318           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     319             :         }
     320          76 :         s_dsa->other_info->dns_name = tmp_dns_name;
     321             : 
     322          76 :         if (s->self_made_schema == NULL) {
     323           0 :                 DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
     324           0 :                 return WERR_INTERNAL_ERROR;
     325             :         }
     326             : 
     327         152 :         schema_ldb = provision_get_schema(s, s->lp_ctx,
     328          76 :                                           c->forest->schema_dn_str,
     329             :                                           &s->prefixmap_blob);
     330          76 :         if (!schema_ldb) {
     331           0 :                 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
     332             :                          "Will continue with local prefixMap\n"));
     333           0 :                 provision_schema = dsdb_get_schema(s->ldb, s);
     334             :         } else {
     335          76 :                 provision_schema = dsdb_get_schema(schema_ldb, s);
     336          76 :                 ret = dsdb_reference_schema(s->ldb, provision_schema, SCHEMA_MEMORY_ONLY);
     337          76 :                 if (ret != LDB_SUCCESS) {
     338           0 :                         DEBUG(0,("Failed to attach schema from local provision using remote prefixMap.\n"));
     339           0 :                         return WERR_INTERNAL_ERROR;
     340             :                 }
     341          76 :                 talloc_unlink(s, schema_ldb);
     342             :         }
     343             : 
     344          76 :         cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
     345             :                                                  "become dc",
     346             :                                                  "schema convert retrial", 1);
     347             : 
     348          76 :         provision_schema->resolving_in_progress = true;
     349          76 :         s->self_made_schema->resolving_in_progress = true;
     350             : 
     351          76 :         status = dsdb_repl_resolve_working_schema(s->ldb,
     352             :                                                   pfm_remote,
     353             :                                                   cycle_before_switching,
     354             :                                                   provision_schema,
     355             :                                                   s->self_made_schema,
     356             :                                                   object_count,
     357             :                                                   first_object);
     358          76 :         if (!W_ERROR_IS_OK(status)) {
     359           0 :                 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s\n",
     360             :                           __location__, win_errstr(status)));
     361           0 :                 return status;
     362             :         }
     363             : 
     364             :         /* free temp objects for 1st conversion phase */
     365          76 :         talloc_unlink(s, provision_schema);
     366             : 
     367          76 :         s->self_made_schema->resolving_in_progress = false;
     368             : 
     369             :         /*
     370             :          * attach the schema we just brought over DRS to the ldb,
     371             :          * so we can use it in dsdb_convert_object_ex below
     372             :          */
     373          76 :         ret = dsdb_set_schema(s->ldb, s->self_made_schema, SCHEMA_WRITE);
     374          76 :         if (ret != LDB_SUCCESS) {
     375           0 :                 DEBUG(0,("Failed to attach working schema from DRS.\n"));
     376           0 :                 return WERR_INTERNAL_ERROR;
     377             :         }
     378             : 
     379             :         /* we don't want to access the self made schema anymore */
     380          76 :         s->schema = s->self_made_schema;
     381          76 :         s->self_made_schema = NULL;
     382             : 
     383          76 :         partition_dn = ldb_dn_new(s, s->ldb, c->partition->nc.dn);
     384          76 :         if (partition_dn == NULL) {
     385           0 :                 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
     386           0 :                 return WERR_INVALID_PARAMETER;
     387             :         }
     388             : 
     389             :         /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
     390         147 :         status = dsdb_replicated_objects_convert(s->ldb,
     391             :                                                  s->schema,
     392             :                                                  partition_dn,
     393             :                                                  mapping_ctr,
     394             :                                                  object_count,
     395             :                                                  first_object,
     396             :                                                  linked_attributes_count,
     397             :                                                  linked_attributes,
     398             :                                                  s_dsa,
     399             :                                                  uptodateness_vector,
     400          76 :                                                  c->gensec_skey,
     401             :                                                  0,
     402             :                                                  s, &schema_objs);
     403          76 :         if (!W_ERROR_IS_OK(status)) {
     404           0 :                 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
     405           0 :                 return status;
     406             :         }
     407             : 
     408          76 :         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
     409           0 :                 for (i=0; i < schema_objs->num_objects; i++) {
     410           0 :                         struct ldb_ldif ldif;
     411           0 :                         fprintf(stdout, "#\n");
     412           0 :                         ldif.changetype = LDB_CHANGETYPE_NONE;
     413           0 :                         ldif.msg = schema_objs->objects[i].msg;
     414           0 :                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
     415           0 :                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
     416             :                 }
     417             :         }
     418             : 
     419          76 :         status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
     420          76 :         if (!W_ERROR_IS_OK(status)) {
     421           0 :                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
     422           0 :                 return status;
     423             :         }
     424             : 
     425          76 :         msg = ldb_msg_new(schema_objs);
     426          76 :         if (msg == NULL) {
     427           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     428             :         }
     429          76 :         msg->dn = schema_objs->partition_dn;
     430             : 
     431             :         /* We must ensure a prefixMap has been written.  Unlike other
     432             :          * attributes (including schemaInfo), it is not replicated in
     433             :          * the normal replication stream.  We can use the one from
     434             :          * s->prefixmap_blob because we operate with one, unchanging
     435             :          * prefixMap for this entire operation.  */
     436          76 :         ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
     437          76 :         if (ret != LDB_SUCCESS) {
     438           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     439             :         }
     440             :         /* We want to know if a prefixMap was written already, as it
     441             :          * would mean that the above comment was not true, and we have
     442             :          * somehow updated the prefixMap during this transaction */
     443          76 :         prefixMap_el->flags = LDB_FLAG_MOD_ADD;
     444             : 
     445          76 :         ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
     446          76 :         if (ret != LDB_SUCCESS) {
     447           0 :                 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
     448           0 :                 return WERR_INTERNAL_ERROR;
     449             :         }
     450             : 
     451          76 :         talloc_free(s_dsa);
     452          76 :         talloc_free(schema_objs);
     453             : 
     454          76 :         s->schema = dsdb_get_schema(s->ldb, s);
     455          76 :         if (!s->schema) {
     456           0 :                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
     457           0 :                 return WERR_INTERNAL_ERROR;
     458             :         }
     459             : 
     460          76 :         return WERR_OK;
     461             : }
     462             : 
     463         392 : WERROR libnet_vampire_cb_schema_chunk(void *private_data,
     464             :                                       const struct libnet_BecomeDC_StoreChunk *c)
     465             : {
     466         392 :         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
     467         354 :         WERROR werr;
     468         354 :         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
     469         354 :         uint32_t nc_object_count;
     470         392 :         uint32_t nc_total_received = 0;
     471         354 :         uint32_t object_count;
     472         354 :         struct drsuapi_DsReplicaObjectListItemEx *first_object;
     473         354 :         struct drsuapi_DsReplicaObjectListItemEx *cur;
     474         354 :         uint32_t nc_linked_attributes_count;
     475         354 :         uint32_t linked_attributes_count;
     476             : 
     477         392 :         switch (c->ctr_level) {
     478           0 :         case 1:
     479           0 :                 mapping_ctr                     = &c->ctr1->mapping_ctr;
     480           0 :                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
     481           0 :                 object_count                    = c->ctr1->object_count;
     482           0 :                 first_object                    = c->ctr1->first_object;
     483           0 :                 nc_linked_attributes_count      = 0;
     484           0 :                 linked_attributes_count         = 0;
     485           0 :                 break;
     486         392 :         case 6:
     487         392 :                 mapping_ctr                     = &c->ctr6->mapping_ctr;
     488         392 :                 nc_object_count                 = c->ctr6->nc_object_count;
     489         392 :                 object_count                    = c->ctr6->object_count;
     490         392 :                 first_object                    = c->ctr6->first_object;
     491         392 :                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
     492         392 :                 linked_attributes_count         = c->ctr6->linked_attributes_count;
     493         392 :                 break;
     494           0 :         default:
     495           0 :                 return WERR_INVALID_PARAMETER;
     496             :         }
     497             : 
     498         392 :         if (!s->schema_part.first_object) {
     499           5 :                 nc_total_received = object_count;
     500             :         } else {
     501         316 :                 nc_total_received = s->schema_part.object_count + object_count;
     502             :         }
     503         392 :         if (nc_object_count) {
     504         344 :                 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
     505             :                         c->partition->nc.dn, nc_total_received, nc_object_count,
     506             :                         linked_attributes_count, nc_linked_attributes_count));
     507             :         } else {
     508          48 :                 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
     509             :                 c->partition->nc.dn, nc_total_received, linked_attributes_count));
     510             :         }
     511             : 
     512         392 :         if (!s->self_made_schema) {
     513          71 :                 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
     514             :                 /* Put the DRS prefixmap aside for the schema we are
     515             :                  * about to load in the provision, and into the one we
     516             :                  * are making with the help of DRS */
     517             : 
     518          76 :                 mapping_ctr_without_schema_info = *mapping_ctr;
     519             : 
     520             :                 /* This strips off the 0xFF schema info from the end,
     521             :                  * because we don't want it in the blob */
     522          76 :                 if (mapping_ctr_without_schema_info.num_mappings > 0) {
     523          76 :                         mapping_ctr_without_schema_info.num_mappings--;
     524             :                 }
     525          76 :                 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
     526          76 :                 if (!W_ERROR_IS_OK(werr)) {
     527           0 :                         return werr;
     528             :                 }
     529             : 
     530             :                 /* Set up two manually-constructed schema - the local
     531             :                  * schema from the provision will be used to build
     532             :                  * one, which will then in turn be used to build the
     533             :                  * other. */
     534          76 :                 s->self_made_schema = dsdb_new_schema(s);
     535          76 :                 if (s->self_made_schema == NULL) {
     536           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     537             :                 }
     538             : 
     539          76 :                 werr = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
     540          76 :                 if (!W_ERROR_IS_OK(werr)) {
     541           0 :                         return werr;
     542             :                 }
     543             :         } else {
     544         316 :                 werr = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
     545         316 :                 if (!W_ERROR_IS_OK(werr)) {
     546           0 :                         return werr;
     547             :                 }
     548             :         }
     549             : 
     550         392 :         if (!s->schema_part.first_object) {
     551          76 :                 s->schema_part.object_count = object_count;
     552          76 :                 s->schema_part.first_object = talloc_steal(s, first_object);
     553             :         } else {
     554         316 :                 s->schema_part.object_count          += object_count;
     555         316 :                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
     556             :                                                                        first_object);
     557             :         }
     558         392 :         if (first_object != NULL) {
     559      130860 :                 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
     560             :         } else {
     561           0 :                 cur = first_object;
     562             :         }
     563             : 
     564         392 :         s->schema_part.last_object = cur;
     565             : 
     566         392 :         if (!c->partition->more_data) {
     567          76 :                 return libnet_vampire_cb_apply_schema(s, c);
     568             :         }
     569             : 
     570         316 :         return WERR_OK;
     571             : }
     572             : 
     573        1418 : WERROR libnet_vampire_cb_store_chunk(void *private_data,
     574             :                                      const struct libnet_BecomeDC_StoreChunk *c)
     575             : {
     576        1418 :         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
     577        1338 :         WERROR status;
     578        1338 :         struct dsdb_schema *schema;
     579        1338 :         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
     580        1338 :         uint32_t nc_object_count;
     581        1338 :         uint32_t object_count;
     582        1338 :         struct drsuapi_DsReplicaObjectListItemEx *first_object;
     583        1338 :         uint32_t nc_linked_attributes_count;
     584        1338 :         uint32_t linked_attributes_count;
     585        1338 :         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
     586        1338 :         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
     587        1338 :         struct dsdb_extended_replicated_objects *objs;
     588        1338 :         uint32_t req_replica_flags;
     589        1418 :         uint32_t dsdb_repl_flags = 0;
     590        1338 :         struct repsFromTo1 *s_dsa;
     591        1338 :         char *tmp_dns_name;
     592        1338 :         uint32_t i;
     593        1418 :         uint64_t seq_num = 0;
     594        1418 :         bool is_exop = false;
     595        1418 :         struct ldb_dn *partition_dn = NULL;
     596        1418 :         struct ldb_dn *nc_root = NULL;
     597             : 
     598        1418 :         s_dsa                   = talloc_zero(s, struct repsFromTo1);
     599        1418 :         if (s_dsa == NULL) {
     600           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     601             :         }
     602        1418 :         s_dsa->other_info    = talloc(s_dsa, struct repsFromTo1OtherInfo);
     603        1418 :         if (s_dsa->other_info == NULL) {
     604           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     605             :         }
     606             : 
     607        1418 :         switch (c->ctr_level) {
     608           0 :         case 1:
     609           0 :                 mapping_ctr                     = &c->ctr1->mapping_ctr;
     610           0 :                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
     611           0 :                 object_count                    = c->ctr1->object_count;
     612           0 :                 first_object                    = c->ctr1->first_object;
     613           0 :                 nc_linked_attributes_count      = 0;
     614           0 :                 linked_attributes_count         = 0;
     615           0 :                 linked_attributes               = NULL;
     616           0 :                 s_dsa->highwatermark         = c->ctr1->new_highwatermark;
     617           0 :                 s_dsa->source_dsa_obj_guid   = c->ctr1->source_dsa_guid;
     618           0 :                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
     619           0 :                 uptodateness_vector             = NULL; /* TODO: map it */
     620           0 :                 break;
     621        1418 :         case 6:
     622        1418 :                 mapping_ctr                     = &c->ctr6->mapping_ctr;
     623        1418 :                 nc_object_count                 = c->ctr6->nc_object_count;
     624        1418 :                 object_count                    = c->ctr6->object_count;
     625        1418 :                 first_object                    = c->ctr6->first_object;
     626        1418 :                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
     627        1418 :                 linked_attributes_count         = c->ctr6->linked_attributes_count;
     628        1418 :                 linked_attributes               = c->ctr6->linked_attributes;
     629        1418 :                 s_dsa->highwatermark         = c->ctr6->new_highwatermark;
     630        1418 :                 s_dsa->source_dsa_obj_guid   = c->ctr6->source_dsa_guid;
     631        1418 :                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
     632        1418 :                 uptodateness_vector             = c->ctr6->uptodateness_vector;
     633        1418 :                 break;
     634           0 :         default:
     635           0 :                 return WERR_INVALID_PARAMETER;
     636             :         }
     637             : 
     638        1418 :         switch (c->req_level) {
     639           0 :         case 0:
     640             :                 /* none */
     641           0 :                 req_replica_flags = 0;
     642           0 :                 break;
     643           0 :         case 5:
     644           0 :                 if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
     645           0 :                         is_exop = true;
     646             :                 }
     647           0 :                 req_replica_flags = c->req5->replica_flags;
     648           0 :                 break;
     649          60 :         case 8:
     650          60 :                 if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
     651           0 :                         is_exop = true;
     652             :                 }
     653          60 :                 req_replica_flags = c->req8->replica_flags;
     654          60 :                 break;
     655        1358 :         case 10:
     656        1358 :                 if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
     657          70 :                         is_exop = true;
     658             :                 }
     659        1358 :                 req_replica_flags = c->req10->replica_flags;
     660             : 
     661        1358 :                 if (c->req10->more_flags & DRSUAPI_DRS_GET_TGT) {
     662         280 :                         dsdb_repl_flags |= DSDB_REPL_FLAG_TARGETS_UPTODATE;
     663             :                 }
     664          50 :                 break;
     665           0 :         default:
     666           0 :                 return WERR_INVALID_PARAMETER;
     667             :         }
     668             : 
     669             :         /*
     670             :          * If the peer DC doesn't support GET_TGT (req v10), then the link
     671             :          * targets are as up-to-date as they're ever gonna be. (Without this,
     672             :          * cases where we'd normally retry with GET_TGT cause the join to fail)
     673             :          */
     674        1418 :         if (c->req_level < 10) {
     675          60 :                 dsdb_repl_flags |= DSDB_REPL_FLAG_TARGETS_UPTODATE;
     676             :         }
     677             : 
     678        1418 :         if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY || is_exop) {
     679             :                 /*
     680             :                  * If we only replicate the critical objects, or this
     681             :                  * is an exop we should not remember what we already
     682             :                  * got, as it is incomplete.
     683             :                  */
     684         206 :                 ZERO_STRUCT(s_dsa->highwatermark);
     685         206 :                 uptodateness_vector = NULL;
     686         206 :                 dsdb_repl_flags |= DSDB_REPL_FLAG_OBJECT_SUBSET;
     687             :         }
     688             : 
     689             :         /* TODO: avoid hardcoded flags */
     690        1418 :         s_dsa->replica_flags         = DRSUAPI_DRS_WRIT_REP
     691             :                                         | DRSUAPI_DRS_INIT_SYNC
     692             :                                         | DRSUAPI_DRS_PER_SYNC;
     693        1418 :         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
     694             : 
     695        1418 :         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
     696        1418 :         if (tmp_dns_name == NULL) {
     697           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     698             :         }
     699        1418 :         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
     700        1418 :         if (tmp_dns_name == NULL) {
     701           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     702             :         }
     703        1418 :         s_dsa->other_info->dns_name = tmp_dns_name;
     704             : 
     705             :         /* we want to show a count per partition */
     706        1418 :         if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
     707         459 :                 s->total_objects = 0;
     708         459 :                 s->total_links = 0;
     709         459 :                 talloc_free(s->last_partition);
     710         459 :                 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
     711             :         }
     712        1418 :         s->total_objects += object_count;
     713        1418 :         s->total_links += linked_attributes_count;
     714             : 
     715        1418 :         partition_dn = ldb_dn_new(s_dsa, s->ldb, c->partition->nc.dn);
     716        1418 :         if (partition_dn == NULL) {
     717           0 :                 DEBUG(0,("Failed to parse partition DN from DRS.\n"));
     718           0 :                 return WERR_INVALID_PARAMETER;
     719             :         }
     720             : 
     721        1418 :         if (is_exop) {
     722          67 :                 int ret;
     723          70 :                 if (nc_object_count) {
     724           0 :                         DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
     725             :                                 c->partition->nc.dn, s->total_objects, nc_object_count,
     726             :                                 s->total_links, nc_linked_attributes_count));
     727             :                 } else {
     728          70 :                         DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
     729             :                         c->partition->nc.dn, s->total_objects, linked_attributes_count));
     730             :                 }
     731          70 :                 ret = dsdb_find_nc_root(s->ldb, s_dsa,
     732             :                                         partition_dn, &nc_root);
     733          70 :                 if (ret != LDB_SUCCESS) {
     734           0 :                         DEBUG(0,(__location__ ": Failed to find nc_root for %s\n",
     735             :                                  ldb_dn_get_linearized(partition_dn)));
     736           0 :                         return WERR_INTERNAL_ERROR;
     737             :                 }
     738             :         } else {
     739        1348 :                 if (nc_object_count) {
     740        1186 :                         DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
     741             :                                 c->partition->nc.dn, s->total_objects, nc_object_count,
     742             :                                 s->total_links, nc_linked_attributes_count));
     743             :                 } else {
     744         162 :                         DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
     745             :                         c->partition->nc.dn, s->total_objects, s->total_links));
     746             :                 }
     747        1348 :                 nc_root = partition_dn;
     748             :         }
     749             : 
     750             : 
     751        1418 :         schema = dsdb_get_schema(s->ldb, NULL);
     752        1418 :         if (!schema) {
     753           0 :                 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
     754           0 :                 return WERR_INTERNAL_ERROR;
     755             :         }
     756             : 
     757        1418 :         if (req_replica_flags & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS) {
     758        1167 :                 dsdb_repl_flags |= DSDB_REPL_FLAG_PRIORITISE_INCOMING;
     759             :         }
     760             : 
     761        1418 :         if (req_replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
     762         301 :                 dsdb_repl_flags |= DSDB_REPL_FLAG_EXPECT_NO_SECRETS;
     763             :         }
     764             : 
     765        2756 :         status = dsdb_replicated_objects_convert(s->ldb,
     766             :                                                  schema,
     767             :                                                  nc_root,
     768             :                                                  mapping_ctr,
     769             :                                                  object_count,
     770             :                                                  first_object,
     771             :                                                  linked_attributes_count,
     772             :                                                  linked_attributes,
     773             :                                                  s_dsa,
     774             :                                                  uptodateness_vector,
     775        1418 :                                                  c->gensec_skey,
     776             :                                                  dsdb_repl_flags,
     777             :                                                  s, &objs);
     778        1418 :         if (!W_ERROR_IS_OK(status)) {
     779           0 :                 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
     780           0 :                 return status;
     781             :         }
     782             : 
     783        1418 :         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
     784           0 :                 for (i=0; i < objs->num_objects; i++) {
     785           0 :                         struct ldb_ldif ldif;
     786           0 :                         fprintf(stdout, "#\n");
     787           0 :                         ldif.changetype = LDB_CHANGETYPE_NONE;
     788           0 :                         ldif.msg = objs->objects[i].msg;
     789           0 :                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
     790           0 :                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
     791             :                 }
     792             :         }
     793        1418 :         status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
     794        1418 :         if (!W_ERROR_IS_OK(status)) {
     795          29 :                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
     796          29 :                 return status;
     797             :         }
     798             : 
     799             :         /* reset debug counters once we've finished replicating the partition */
     800        1389 :         if (!c->partition->more_data) {
     801         529 :                 s->total_objects = 0;
     802         529 :                 s->total_links = 0;
     803             :         }
     804             : 
     805        1389 :         talloc_free(s_dsa);
     806        1389 :         talloc_free(objs);
     807             : 
     808       11584 :         for (i=0; i < linked_attributes_count; i++) {
     809        8542 :                 const struct dsdb_attribute *sa;
     810             : 
     811        8885 :                 if (!linked_attributes[i].identifier) {
     812           0 :                         DEBUG(0, ("No linked attribute identifier\n"));
     813           0 :                         return WERR_INTERNAL_ERROR;
     814             :                 }
     815             : 
     816        8885 :                 if (!linked_attributes[i].value.blob) {
     817           0 :                         DEBUG(0, ("No linked attribute value\n"));
     818           0 :                         return WERR_INTERNAL_ERROR;
     819             :                 }
     820             : 
     821       17770 :                 sa = dsdb_attribute_by_attributeID_id(s->schema,
     822        8885 :                                                       linked_attributes[i].attid);
     823        8885 :                 if (!sa) {
     824           0 :                         DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes[i].attid));
     825           0 :                         return WERR_INTERNAL_ERROR;
     826             :                 }
     827             : 
     828        8885 :                 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
     829           0 :                         DEBUG(0,("# %s\n", sa->lDAPDisplayName));
     830           0 :                         NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
     831           0 :                         dump_data(0,
     832           0 :                                 linked_attributes[i].value.blob->data,
     833           0 :                                 linked_attributes[i].value.blob->length);
     834             :                 }
     835             :         }
     836             : 
     837        1389 :         return WERR_OK;
     838             : }
     839             : 

Generated by: LCOV version 1.14