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

Generated by: LCOV version 1.14