Imported Upstream version 4.0.0+dfsg1
[abartlet/samba-debian.git] / source4 / libnet / libnet_become_dc.c
index 29ee069dd3d444135e14e7da2481659de0724fae..3e4c7f871cc69eb74bb0c79ca39cbff68dfe061d 100644 (file)
@@ -735,6 +735,7 @@ struct libnet_BecomeDC_state {
        struct libnet_BecomeDC_Callbacks callbacks;
 
        bool rodc_join;
+       bool critical_only;
 };
 
 static int32_t get_dc_function_level(struct loadparm_context *lp_ctx)
@@ -769,15 +770,15 @@ static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
                                                lpcfg_cldap_port(s->libnet->lp_ctx),
                                                &dest_address);
        if (ret != 0) {
-               c->status = map_nt_error_from_unix(errno);
+               c->status = map_nt_error_from_unix_common(errno);
                if (!composite_is_ok(c)) return;
        }
 
-       c->status = cldap_socket_init(s, s->libnet->event_ctx,
-                                     NULL, dest_address, &s->cldap.sock);
+       c->status = cldap_socket_init(s, NULL, dest_address, &s->cldap.sock);
        if (!composite_is_ok(c)) return;
 
-       req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io);
+       req = cldap_netlogon_send(s, s->libnet->event_ctx,
+                                 s->cldap.sock, &s->cldap.io);
        if (composite_nomem(req, c)) return;
        tevent_req_set_callback(req, becomeDC_recv_cldap, s);
 }
@@ -1046,11 +1047,17 @@ static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state
                                DS_GUID_INFRASTRUCTURE_CONTAINER,
                                &basedn);
        if (ret != LDB_SUCCESS) {
+               DEBUG(0,("Failed to get well known DN for DS_GUID_INFRASTRUCTURE_CONTAINER on %s: %s\n", 
+                        ldb_dn_get_linearized(ldb_get_default_basedn(s->ldap1.ldb)), 
+                        ldb_errstring(s->ldap1.ldb)));
                return NT_STATUS_LDAP(ret);
        }
 
        ret = samdb_reference_dn(s->ldap1.ldb, s, basedn, "fSMORoleOwner", &ntds_dn);
        if (ret != LDB_SUCCESS) {
+               DEBUG(0,("Failed to get reference DN from fsmoRoleOwner on %s: %s\n", 
+                        ldb_dn_get_linearized(basedn), 
+                        ldb_errstring(s->ldap1.ldb)));
                talloc_free(basedn);
                return NT_STATUS_LDAP(ret);
        }
@@ -1067,6 +1074,9 @@ static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state
        ret = ldb_search(s->ldap1.ldb, s, &r, server_dn, LDB_SCOPE_BASE,
                         dns_attrs, "(objectClass=*)");
        if (ret != LDB_SUCCESS) {
+               DEBUG(0,("Failed to get server DN %s: %s\n", 
+                        ldb_dn_get_linearized(server_dn), 
+                        ldb_errstring(s->ldap1.ldb)));
                return NT_STATUS_LDAP(ret);
        } else if (r->count != 1) {
                talloc_free(r);
@@ -1079,9 +1089,13 @@ static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state
 
        talloc_free(r);
 
+       ldb_dn_remove_extended_components(ntds_dn);
        ret = ldb_search(s->ldap1.ldb, s, &r, ntds_dn, LDB_SCOPE_BASE,
                         guid_attrs, "(objectClass=*)");
        if (ret != LDB_SUCCESS) {
+               DEBUG(0,("Failed to get NTDS Settings DN %s: %s\n", 
+                        ldb_dn_get_linearized(ntds_dn), 
+                        ldb_errstring(s->ldap1.ldb)));
                return NT_STATUS_LDAP(ret);
        } else if (r->count != 1) {
                talloc_free(r);
@@ -1568,6 +1582,10 @@ static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
                if (!composite_is_ok(c)) return;
        }
 
+       if (DEBUGLEVEL >= 10) {
+               drsuapi->binding->flags |= DCERPC_DEBUG_PRINT_BOTH;
+       }
+
        creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &ndr_table_drsuapi,
                                          s->libnet->cred, s->libnet->event_ctx,
                                          s->libnet->lp_ctx);
@@ -1591,6 +1609,7 @@ static void becomeDC_drsuapi1_connect_recv(struct composite_context *req)
        s->drsuapi1.drsuapi_handle = s->drsuapi1.pipe->binding_handle;
 
        c->status = gensec_session_key(s->drsuapi1.pipe->conn->security_state.generic_state,
+                                      s,
                                       &s->drsuapi1.gensec_skey);
        if (!composite_is_ok(c)) return;
 
@@ -2389,6 +2408,7 @@ static void becomeDC_drsuapi1_add_entry_recv(struct tevent_req *subreq)
                                 "method succeeded but objects returned are %d (expected 1).\n",
                                 r->out.ctr->ctr3.count));
                        composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
+                       return;
                }
 
                s->dest_dsa.ntds_guid   = r->out.ctr->ctr3.objects[0].guid;
@@ -2410,6 +2430,7 @@ static void becomeDC_drsuapi1_add_entry_recv(struct tevent_req *subreq)
                                 r->out.ctr->ctr2.dir_err,
                                 win_errstr(r->out.ctr->ctr2.extended_err)));
                        composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
+                       return;
                }
 
                s->dest_dsa.ntds_guid   = r->out.ctr->ctr2.objects[0].guid;
@@ -2435,6 +2456,10 @@ static void becomeDC_drsuapi1_add_entry_recv(struct tevent_req *subreq)
        talloc_free(binding_str);
        if (!composite_is_ok(c)) return;
 
+       if (DEBUGLEVEL >= 10) {
+               s->drsuapi2.binding->flags |= DCERPC_DEBUG_PRINT_BOTH;
+       }
+
        /* w2k3 uses the same assoc_group_id as on the first connection, so we do */
        s->drsuapi2.binding->assoc_group_id     = s->drsuapi1.pipe->assoc_group_id;
 
@@ -2467,6 +2492,7 @@ static void becomeDC_drsuapi2_connect_recv(struct composite_context *req)
        s->drsuapi2.drsuapi_handle = s->drsuapi2.pipe->binding_handle;
 
        c->status = gensec_session_key(s->drsuapi2.pipe->conn->security_state.generic_state,
+                                      s,
                                       &s->drsuapi2.gensec_skey);
        if (!composite_is_ok(c)) return;
 
@@ -2501,6 +2527,10 @@ static void becomeDC_drsuapi2_bind_recv(struct tevent_req *subreq)
        talloc_free(binding_str);
        if (!composite_is_ok(c)) return;
 
+       if (DEBUGLEVEL >= 10) {
+               s->drsuapi3.binding->flags |= DCERPC_DEBUG_PRINT_BOTH;
+       }
+
        /* w2k3 uses the same assoc_group_id as on the first connection, so we do */
        s->drsuapi3.binding->assoc_group_id     = s->drsuapi1.pipe->assoc_group_id;
        /* w2k3 uses the concurrent multiplex feature on the 3rd connection, so we do */
@@ -2523,6 +2553,7 @@ static void becomeDC_drsuapi3_connect_recv(struct composite_context *req)
        s->drsuapi3.drsuapi_handle = s->drsuapi3.pipe->binding_handle;
 
        c->status = gensec_session_key(s->drsuapi3.pipe->conn->security_state.generic_state,
+                                      s,
                                       &s->drsuapi3.gensec_skey);
        if (!composite_is_ok(c)) return;
 
@@ -2600,6 +2631,10 @@ static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state
                                                   struct libnet_BecomeDC_Partition *partition,
                                                   struct drsuapi_DsGetNCChanges *r)
 {
+       uint32_t req_level = 0;
+       struct drsuapi_DsGetNCChangesRequest5 *req5 = NULL;
+       struct drsuapi_DsGetNCChangesRequest8 *req8 = NULL;
+       struct drsuapi_DsGetNCChangesRequest10 *req10 = NULL;
        uint32_t ctr_level = 0;
        struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
        struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
@@ -2613,6 +2648,23 @@ static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state
                return r->out.result;
        }
 
+       switch (r->in.level) {
+       case 0:
+               /* none */
+               break;
+       case 5:
+               req5 = &r->in.req->req5;
+               break;
+       case 8:
+               req8 = &r->in.req->req8;
+               break;
+       case 10:
+               req10 = &r->in.req->req10;
+               break;
+       default:
+               return WERR_INVALID_PARAMETER;
+       }
+
        if (*r->out.level_out == 1) {
                ctr_level = 1;
                ctr1 = &r->out.ctr->ctr1;
@@ -2676,6 +2728,10 @@ static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state
        s->_sc.source_dsa       = &s->source_dsa;
        s->_sc.dest_dsa         = &s->dest_dsa;
        s->_sc.partition        = partition;
+       s->_sc.req_level        = req_level;
+       s->_sc.req5             = req5;
+       s->_sc.req8             = req8;
+       s->_sc.req10            = req10;
        s->_sc.ctr_level        = ctr_level;
        s->_sc.ctr1             = ctr1;
        s->_sc.ctr6             = ctr6;
@@ -2827,6 +2883,9 @@ static void becomeDC_drsuapi3_pull_domain_send(struct libnet_BecomeDC_state *s)
                                        | DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
                                        | DRSUAPI_DRS_NEVER_SYNCED
                                        | DRSUAPI_DRS_USE_COMPRESSION;
+       if (s->critical_only) {
+               s->domain_part.replica_flags |= DRSUAPI_DRS_CRITICAL_ONLY | DRSUAPI_DRS_GET_ANC;
+       }
        if (s->rodc_join) {
            s->schema_part.replica_flags &= ~DRSUAPI_DRS_WRIT_REP;
        }
@@ -2872,6 +2931,14 @@ static void becomeDC_drsuapi3_pull_domain_recv(struct tevent_req *subreq)
                return;
        }
 
+       if (s->critical_only) {
+               /* Remove the critical and ANC */
+               s->domain_part.replica_flags ^= DRSUAPI_DRS_CRITICAL_ONLY | DRSUAPI_DRS_GET_ANC;
+               s->critical_only = false;
+               becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
+                                                    becomeDC_drsuapi3_pull_domain_recv);
+               return;
+       }
        becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->schema_part,
                                          becomeDC_drsuapi2_update_refs_schema_recv);
 }
@@ -2895,7 +2962,7 @@ static void becomeDC_drsuapi_update_refs_send(struct libnet_BecomeDC_state *s,
 
        ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
                                        ntds_guid_str,
-                                       s->domain.dns_name);
+                                       s->forest.dns_name);
        if (composite_nomem(ntds_dns_name, c)) return;
 
        r->in.bind_handle               = &drsuapi->bind_handle;
@@ -3095,6 +3162,7 @@ static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
        c->status = becomeDC_ldap2_move_computer(s);
        if (!composite_is_ok(c)) return;
 
+       s->critical_only = true;
        becomeDC_drsuapi3_pull_domain_send(s);
 }