~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source4/dsdb/repl/drepl_out_helpers.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include "auth/auth.h"
25
25
#include "smbd/service.h"
26
26
#include "lib/events/events.h"
27
 
#include "lib/messaging/irpc.h"
28
27
#include "dsdb/repl/drepl_service.h"
29
 
#include "lib/ldb/include/ldb_errors.h"
 
28
#include <ldb_errors.h>
30
29
#include "../lib/util/dlinklist.h"
31
30
#include "librpc/gen_ndr/ndr_misc.h"
32
31
#include "librpc/gen_ndr/ndr_drsuapi.h"
34
33
#include "libcli/composite/composite.h"
35
34
#include "auth/gensec/gensec.h"
36
35
#include "param/param.h"
 
36
#include "../lib/util/tevent_ntstatus.h"
 
37
#include "libcli/security/security.h"
37
38
 
38
39
struct dreplsrv_out_drsuapi_state {
39
 
        struct composite_context *creq;
 
40
        struct tevent_context *ev;
40
41
 
41
42
        struct dreplsrv_out_connection *conn;
42
43
 
46
47
        struct drsuapi_DsBind bind_r;
47
48
};
48
49
 
49
 
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq);
 
50
static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq);
50
51
 
51
 
struct composite_context *dreplsrv_out_drsuapi_send(struct dreplsrv_out_connection *conn)
 
52
struct tevent_req *dreplsrv_out_drsuapi_send(TALLOC_CTX *mem_ctx,
 
53
                                             struct tevent_context *ev,
 
54
                                             struct dreplsrv_out_connection *conn)
52
55
{
53
 
        struct composite_context *c;
 
56
        struct tevent_req *req;
 
57
        struct dreplsrv_out_drsuapi_state *state;
54
58
        struct composite_context *creq;
55
 
        struct dreplsrv_out_drsuapi_state *st;
56
 
 
57
 
        c = composite_create(conn, conn->service->task->event_ctx);
58
 
        if (c == NULL) return NULL;
59
 
 
60
 
        st = talloc_zero(c, struct dreplsrv_out_drsuapi_state);
61
 
        if (composite_nomem(st, c)) return c;
62
 
 
63
 
        c->private_data = st;
64
 
 
65
 
        st->creq        = c;
66
 
        st->conn        = conn;
67
 
        st->drsuapi     = conn->drsuapi;
68
 
 
69
 
        if (st->drsuapi && !st->drsuapi->pipe->conn->dead) {
70
 
                composite_done(c);
71
 
                return c;
72
 
        } else if (st->drsuapi && st->drsuapi->pipe->conn->dead) {
73
 
                talloc_free(st->drsuapi);
 
59
 
 
60
        req = tevent_req_create(mem_ctx, &state,
 
61
                                struct dreplsrv_out_drsuapi_state);
 
62
        if (req == NULL) {
 
63
                return NULL;
 
64
        }
 
65
 
 
66
        state->ev       = ev;
 
67
        state->conn     = conn;
 
68
        state->drsuapi  = conn->drsuapi;
 
69
 
 
70
        if (state->drsuapi && !state->drsuapi->pipe->conn->dead) {
 
71
                tevent_req_done(req);
 
72
                return tevent_req_post(req, ev);
 
73
        }
 
74
 
 
75
        if (state->drsuapi && state->drsuapi->pipe->conn->dead) {
 
76
                talloc_free(state->drsuapi);
74
77
                conn->drsuapi = NULL;
75
78
        }
76
79
 
77
 
        st->drsuapi     = talloc_zero(st, struct dreplsrv_drsuapi_connection);
78
 
        if (composite_nomem(st->drsuapi, c)) return c;
 
80
        state->drsuapi = talloc_zero(state, struct dreplsrv_drsuapi_connection);
 
81
        if (tevent_req_nomem(state->drsuapi, req)) {
 
82
                return tevent_req_post(req, ev);
 
83
        }
79
84
 
80
 
        creq = dcerpc_pipe_connect_b_send(st, conn->binding, &ndr_table_drsuapi,
 
85
        creq = dcerpc_pipe_connect_b_send(state, conn->binding, &ndr_table_drsuapi,
81
86
                                          conn->service->system_session_info->credentials,
82
 
                                          c->event_ctx, conn->service->task->lp_ctx);
83
 
        composite_continue(c, creq, dreplsrv_out_drsuapi_connect_recv, st);
84
 
 
85
 
        return c;
86
 
}
87
 
 
88
 
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st);
89
 
 
90
 
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq)
91
 
{
92
 
        struct dreplsrv_out_drsuapi_state *st = talloc_get_type(creq->async.private_data,
93
 
                                                struct dreplsrv_out_drsuapi_state);
94
 
        struct composite_context *c = st->creq;
95
 
 
96
 
        c->status = dcerpc_pipe_connect_b_recv(creq, st->drsuapi, &st->drsuapi->pipe);
97
 
        if (!composite_is_ok(c)) return;
98
 
 
99
 
        c->status = gensec_session_key(st->drsuapi->pipe->conn->security_state.generic_state,
100
 
                                       &st->drsuapi->gensec_skey);
101
 
        if (!composite_is_ok(c)) return;
102
 
 
103
 
        dreplsrv_out_drsuapi_bind_send(st);
104
 
}
105
 
 
106
 
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req);
107
 
 
108
 
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st)
109
 
{
110
 
        struct composite_context *c = st->creq;
111
 
        struct rpc_request *req;
112
 
 
113
 
        st->bind_info_ctr.length        = 28;
114
 
        st->bind_info_ctr.info.info28   = st->conn->service->bind_info28;
115
 
 
116
 
        st->bind_r.in.bind_guid = &st->conn->service->ntds_guid;
117
 
        st->bind_r.in.bind_info = &st->bind_info_ctr;
118
 
        st->bind_r.out.bind_handle = &st->drsuapi->bind_handle;
119
 
 
120
 
        req = dcerpc_drsuapi_DsBind_send(st->drsuapi->pipe, st, &st->bind_r);
121
 
        composite_continue_rpc(c, req, dreplsrv_out_drsuapi_bind_recv, st);
122
 
}
123
 
 
124
 
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req)
125
 
{
126
 
        struct dreplsrv_out_drsuapi_state *st = talloc_get_type(req->async.private_data,
127
 
                                                struct dreplsrv_out_drsuapi_state);
128
 
        struct composite_context *c = st->creq;
129
 
 
130
 
        c->status = dcerpc_ndr_request_recv(req);
131
 
        if (!composite_is_ok(c)) return;
132
 
 
133
 
        if (!W_ERROR_IS_OK(st->bind_r.out.result)) {
134
 
                composite_error(c, werror_to_ntstatus(st->bind_r.out.result));
135
 
                return;
136
 
        }
137
 
 
138
 
        ZERO_STRUCT(st->drsuapi->remote_info28);
139
 
        if (st->bind_r.out.bind_info) {
140
 
                switch (st->bind_r.out.bind_info->length) {
 
87
                                          ev, conn->service->task->lp_ctx);
 
88
        if (tevent_req_nomem(creq, req)) {
 
89
                return tevent_req_post(req, ev);
 
90
        }
 
91
        composite_continue(NULL, creq, dreplsrv_out_drsuapi_connect_done, req);
 
92
 
 
93
        return req;
 
94
}
 
95
 
 
96
static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq);
 
97
 
 
98
static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq)
 
99
{
 
100
        struct tevent_req *req = talloc_get_type(creq->async.private_data,
 
101
                                                 struct tevent_req);
 
102
        struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
 
103
                                                   struct dreplsrv_out_drsuapi_state);
 
104
        NTSTATUS status;
 
105
        struct tevent_req *subreq;
 
106
 
 
107
        status = dcerpc_pipe_connect_b_recv(creq,
 
108
                                            state->drsuapi,
 
109
                                            &state->drsuapi->pipe);
 
110
        if (tevent_req_nterror(req, status)) {
 
111
                return;
 
112
        }
 
113
 
 
114
        state->drsuapi->drsuapi_handle = state->drsuapi->pipe->binding_handle;
 
115
 
 
116
        status = gensec_session_key(state->drsuapi->pipe->conn->security_state.generic_state,
 
117
                                    &state->drsuapi->gensec_skey);
 
118
        if (tevent_req_nterror(req, status)) {
 
119
                return;
 
120
        }
 
121
 
 
122
        state->bind_info_ctr.length             = 28;
 
123
        state->bind_info_ctr.info.info28        = state->conn->service->bind_info28;
 
124
 
 
125
        state->bind_r.in.bind_guid = &state->conn->service->ntds_guid;
 
126
        state->bind_r.in.bind_info = &state->bind_info_ctr;
 
127
        state->bind_r.out.bind_handle = &state->drsuapi->bind_handle;
 
128
 
 
129
        subreq = dcerpc_drsuapi_DsBind_r_send(state,
 
130
                                              state->ev,
 
131
                                              state->drsuapi->drsuapi_handle,
 
132
                                              &state->bind_r);
 
133
        if (tevent_req_nomem(subreq, req)) {
 
134
                return;
 
135
        }
 
136
        tevent_req_set_callback(subreq, dreplsrv_out_drsuapi_bind_done, req);
 
137
}
 
138
 
 
139
static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq)
 
140
{
 
141
        struct tevent_req *req = tevent_req_callback_data(subreq,
 
142
                                 struct tevent_req);
 
143
        struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
 
144
                                                   struct dreplsrv_out_drsuapi_state);
 
145
        NTSTATUS status;
 
146
 
 
147
        status = dcerpc_drsuapi_DsBind_r_recv(subreq, state);
 
148
        TALLOC_FREE(subreq);
 
149
        if (tevent_req_nterror(req, status)) {
 
150
                return;
 
151
        }
 
152
 
 
153
        if (!W_ERROR_IS_OK(state->bind_r.out.result)) {
 
154
                status = werror_to_ntstatus(state->bind_r.out.result);
 
155
                tevent_req_nterror(req, status);
 
156
                return;
 
157
        }
 
158
 
 
159
        ZERO_STRUCT(state->drsuapi->remote_info28);
 
160
        if (state->bind_r.out.bind_info) {
 
161
                struct drsuapi_DsBindInfo28 *info28;
 
162
                info28 = &state->drsuapi->remote_info28;
 
163
 
 
164
                switch (state->bind_r.out.bind_info->length) {
141
165
                case 24: {
142
166
                        struct drsuapi_DsBindInfo24 *info24;
143
 
                        info24 = &st->bind_r.out.bind_info->info.info24;
144
 
                        st->drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
145
 
                        st->drsuapi->remote_info28.site_guid            = info24->site_guid;
146
 
                        st->drsuapi->remote_info28.pid                  = info24->pid;
147
 
                        st->drsuapi->remote_info28.repl_epoch           = 0;
 
167
                        info24 = &state->bind_r.out.bind_info->info.info24;
 
168
 
 
169
                        info28->supported_extensions    = info24->supported_extensions;
 
170
                        info28->site_guid               = info24->site_guid;
 
171
                        info28->pid                     = info24->pid;
 
172
                        info28->repl_epoch              = 0;
148
173
                        break;
149
174
                }
150
175
                case 48: {
151
176
                        struct drsuapi_DsBindInfo48 *info48;
152
 
                        info48 = &st->bind_r.out.bind_info->info.info48;
153
 
                        st->drsuapi->remote_info28.supported_extensions = info48->supported_extensions;
154
 
                        st->drsuapi->remote_info28.site_guid            = info48->site_guid;
155
 
                        st->drsuapi->remote_info28.pid                  = info48->pid;
156
 
                        st->drsuapi->remote_info28.repl_epoch           = info48->repl_epoch;
 
177
                        info48 = &state->bind_r.out.bind_info->info.info48;
 
178
 
 
179
                        info28->supported_extensions    = info48->supported_extensions;
 
180
                        info28->site_guid               = info48->site_guid;
 
181
                        info28->pid                     = info48->pid;
 
182
                        info28->repl_epoch              = info48->repl_epoch;
157
183
                        break;
158
184
                }
159
185
                case 28:
160
 
                        st->drsuapi->remote_info28 = st->bind_r.out.bind_info->info.info28;
 
186
                        *info28 = state->bind_r.out.bind_info->info.info28;
161
187
                        break;
162
188
                }
163
189
        }
164
190
 
165
 
        composite_done(c);
 
191
        tevent_req_done(req);
166
192
}
167
193
 
168
 
NTSTATUS dreplsrv_out_drsuapi_recv(struct composite_context *c)
 
194
NTSTATUS dreplsrv_out_drsuapi_recv(struct tevent_req *req)
169
195
{
 
196
        struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
 
197
                                                   struct dreplsrv_out_drsuapi_state);
170
198
        NTSTATUS status;
171
 
        struct dreplsrv_out_drsuapi_state *st = talloc_get_type(c->private_data,
172
 
                                                struct dreplsrv_out_drsuapi_state);
173
 
 
174
 
        status = composite_wait(c);
175
 
 
176
 
        if (NT_STATUS_IS_OK(status)) {
177
 
                st->conn->drsuapi = talloc_steal(st->conn, st->drsuapi);
 
199
 
 
200
        if (tevent_req_is_nterror(req, &status)) {
 
201
                tevent_req_received(req);
 
202
                return status;
178
203
        }
179
204
 
180
 
        talloc_free(c);
181
 
        return status;
 
205
        state->conn->drsuapi = talloc_move(state->conn, &state->drsuapi);
 
206
 
 
207
        tevent_req_received(req);
 
208
        return NT_STATUS_OK;
182
209
}
183
210
 
184
211
struct dreplsrv_op_pull_source_state {
185
 
        struct composite_context *creq;
186
 
 
 
212
        struct tevent_context *ev;
187
213
        struct dreplsrv_out_operation *op;
188
 
 
189
 
        struct dreplsrv_drsuapi_connection *drsuapi;
190
 
 
191
 
        bool have_all;
192
 
 
193
 
        uint32_t ctr_level;
194
 
        struct drsuapi_DsGetNCChangesCtr1 *ctr1;
195
 
        struct drsuapi_DsGetNCChangesCtr6 *ctr6;
 
214
        void *ndr_struct_ptr;
196
215
};
197
216
 
198
 
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq);
199
 
 
200
 
struct composite_context *dreplsrv_op_pull_source_send(struct dreplsrv_out_operation *op)
201
 
{
202
 
        struct composite_context *c;
203
 
        struct composite_context *creq;
204
 
        struct dreplsrv_op_pull_source_state *st;
205
 
 
206
 
        c = composite_create(op, op->service->task->event_ctx);
207
 
        if (c == NULL) return NULL;
208
 
 
209
 
        st = talloc_zero(c, struct dreplsrv_op_pull_source_state);
210
 
        if (composite_nomem(st, c)) return c;
211
 
 
212
 
        st->creq        = c;
213
 
        st->op          = op;
214
 
 
215
 
        creq = dreplsrv_out_drsuapi_send(op->source_dsa->conn);
216
 
        composite_continue(c, creq, dreplsrv_op_pull_source_connect_recv, st);
217
 
 
218
 
        return c;
219
 
}
220
 
 
221
 
static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st);
222
 
 
223
 
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq)
224
 
{
225
 
        struct dreplsrv_op_pull_source_state *st = talloc_get_type(creq->async.private_data,
226
 
                                                   struct dreplsrv_op_pull_source_state);
227
 
        struct composite_context *c = st->creq;
228
 
 
229
 
        c->status = dreplsrv_out_drsuapi_recv(creq);
230
 
        if (!composite_is_ok(c)) return;
231
 
 
232
 
        dreplsrv_op_pull_source_get_changes_send(st);
233
 
}
234
 
 
235
 
static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req);
236
 
 
237
 
static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st)
238
 
{
239
 
        struct composite_context *c = st->creq;
240
 
        struct repsFromTo1 *rf1 = st->op->source_dsa->repsFrom1;
241
 
        struct dreplsrv_service *service = st->op->service;
242
 
        struct dreplsrv_partition *partition = st->op->source_dsa->partition;
243
 
        struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
244
 
        struct rpc_request *req;
 
217
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq);
 
218
 
 
219
struct tevent_req *dreplsrv_op_pull_source_send(TALLOC_CTX *mem_ctx,
 
220
                                                struct tevent_context *ev,
 
221
                                                struct dreplsrv_out_operation *op)
 
222
{
 
223
        struct tevent_req *req;
 
224
        struct dreplsrv_op_pull_source_state *state;
 
225
        struct tevent_req *subreq;
 
226
 
 
227
        req = tevent_req_create(mem_ctx, &state,
 
228
                                struct dreplsrv_op_pull_source_state);
 
229
        if (req == NULL) {
 
230
                return NULL;
 
231
        }
 
232
        state->ev = ev;
 
233
        state->op = op;
 
234
 
 
235
        subreq = dreplsrv_out_drsuapi_send(state, ev, op->source_dsa->conn);
 
236
        if (tevent_req_nomem(subreq, req)) {
 
237
                return tevent_req_post(req, ev);
 
238
        }
 
239
        tevent_req_set_callback(subreq, dreplsrv_op_pull_source_connect_done, req);
 
240
 
 
241
        return req;
 
242
}
 
243
 
 
244
static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req);
 
245
 
 
246
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq)
 
247
{
 
248
        struct tevent_req *req = tevent_req_callback_data(subreq,
 
249
                                 struct tevent_req);
 
250
        NTSTATUS status;
 
251
 
 
252
        status = dreplsrv_out_drsuapi_recv(subreq);
 
253
        TALLOC_FREE(subreq);
 
254
        if (tevent_req_nterror(req, status)) {
 
255
                return;
 
256
        }
 
257
 
 
258
        dreplsrv_op_pull_source_get_changes_trigger(req);
 
259
}
 
260
 
 
261
static void dreplsrv_op_pull_source_get_changes_done(struct tevent_req *subreq);
 
262
 
 
263
/*
 
264
  get a partial attribute set for a replication call
 
265
 */
 
266
static NTSTATUS dreplsrv_get_rodc_partial_attribute_set(struct dreplsrv_service *service,
 
267
                                                        TALLOC_CTX *mem_ctx,
 
268
                                                        struct drsuapi_DsPartialAttributeSet **_pas,
 
269
                                                        bool for_schema)
 
270
{
 
271
        struct drsuapi_DsPartialAttributeSet *pas;
 
272
        struct dsdb_schema *schema;
 
273
        uint32_t i;
 
274
 
 
275
        pas = talloc_zero(mem_ctx, struct drsuapi_DsPartialAttributeSet);
 
276
        NT_STATUS_HAVE_NO_MEMORY(pas);
 
277
 
 
278
        schema = dsdb_get_schema(service->samdb, NULL);
 
279
 
 
280
        pas->version = 1;
 
281
        pas->attids = talloc_array(pas, enum drsuapi_DsAttributeId, schema->num_attributes);
 
282
        NT_STATUS_HAVE_NO_MEMORY_AND_FREE(pas->attids, pas);
 
283
 
 
284
        for (i=0; i<schema->num_attributes; i++) {
 
285
                struct dsdb_attribute *a;
 
286
                a = schema->attributes_by_attributeID_id[i];
 
287
                if (a->systemFlags & (DS_FLAG_ATTR_NOT_REPLICATED | DS_FLAG_ATTR_IS_CONSTRUCTED)) {
 
288
                        continue;
 
289
                }
 
290
                if (a->searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE) {
 
291
                        continue;
 
292
                }
 
293
                pas->attids[pas->num_attids] = dsdb_attribute_get_attid(a, for_schema);
 
294
                pas->num_attids++;
 
295
        }
 
296
        *_pas = pas;
 
297
        return NT_STATUS_OK;
 
298
}
 
299
 
 
300
/*
 
301
  convert from one udv format to the other
 
302
 */
 
303
static WERROR udv_convert(TALLOC_CTX *mem_ctx,
 
304
                          const struct replUpToDateVectorCtr2 *udv,
 
305
                          struct drsuapi_DsReplicaCursorCtrEx *udv_ex)
 
306
{
 
307
        uint32_t i;
 
308
 
 
309
        udv_ex->version = 2;
 
310
        udv_ex->reserved1 = 0;
 
311
        udv_ex->reserved2 = 0;
 
312
        udv_ex->count = udv->count;
 
313
        udv_ex->cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, udv->count);
 
314
        W_ERROR_HAVE_NO_MEMORY(udv_ex->cursors);
 
315
 
 
316
        for (i=0; i<udv->count; i++) {
 
317
                udv_ex->cursors[i].source_dsa_invocation_id = udv->cursors[i].source_dsa_invocation_id;
 
318
                udv_ex->cursors[i].highest_usn = udv->cursors[i].highest_usn;
 
319
        }
 
320
 
 
321
        return WERR_OK;
 
322
}
 
323
 
 
324
 
 
325
static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req)
 
326
{
 
327
        struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
 
328
                                                      struct dreplsrv_op_pull_source_state);
 
329
        struct repsFromTo1 *rf1 = state->op->source_dsa->repsFrom1;
 
330
        struct dreplsrv_service *service = state->op->service;
 
331
        struct dreplsrv_partition *partition = state->op->source_dsa->partition;
 
332
        struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
245
333
        struct drsuapi_DsGetNCChanges *r;
246
 
 
247
 
        r = talloc(st, struct drsuapi_DsGetNCChanges);
248
 
        if (composite_nomem(r, c)) return;
249
 
 
250
 
        r->out.level_out = talloc(r, int32_t);
251
 
        if (composite_nomem(r->out.level_out, c)) return;
 
334
        struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector;
 
335
        struct tevent_req *subreq;
 
336
        struct drsuapi_DsPartialAttributeSet *pas = NULL;
 
337
        NTSTATUS status;
 
338
        uint32_t replica_flags;
 
339
 
 
340
        r = talloc(state, struct drsuapi_DsGetNCChanges);
 
341
        if (tevent_req_nomem(r, req)) {
 
342
                return;
 
343
        }
 
344
 
 
345
        r->out.level_out = talloc(r, uint32_t);
 
346
        if (tevent_req_nomem(r->out.level_out, req)) {
 
347
                return;
 
348
        }
252
349
        r->in.req = talloc(r, union drsuapi_DsGetNCChangesRequest);
253
 
        if (composite_nomem(r->in.req, c)) return;
 
350
        if (tevent_req_nomem(r->in.req, req)) {
 
351
                return;
 
352
        }
254
353
        r->out.ctr = talloc(r, union drsuapi_DsGetNCChangesCtr);
255
 
        if (composite_nomem(r->out.ctr, c)) return;
 
354
        if (tevent_req_nomem(r->out.ctr, req)) {
 
355
                return;
 
356
        }
 
357
 
 
358
        if (partition->uptodatevector.count != 0 &&
 
359
            partition->uptodatevector_ex.count == 0) {
 
360
                WERROR werr;
 
361
                werr = udv_convert(partition, &partition->uptodatevector, &partition->uptodatevector_ex);
 
362
                if (!W_ERROR_IS_OK(werr)) {
 
363
                        DEBUG(0,(__location__ ": Failed to convert UDV for %s : %s\n",
 
364
                                 ldb_dn_get_linearized(partition->dn), win_errstr(werr)));
 
365
                }
 
366
        }
 
367
 
 
368
        if (partition->uptodatevector_ex.count == 0) {
 
369
                uptodateness_vector = NULL;
 
370
        } else {
 
371
                uptodateness_vector = &partition->uptodatevector_ex;
 
372
        }
 
373
 
 
374
        replica_flags = rf1->replica_flags;
 
375
 
 
376
        if (service->am_rodc) {
 
377
                bool for_schema = false;
 
378
                if (ldb_dn_compare_base(ldb_get_schema_basedn(service->samdb), partition->dn) == 0) {
 
379
                        for_schema = true;
 
380
                }
 
381
 
 
382
                status = dreplsrv_get_rodc_partial_attribute_set(service, r, &pas, for_schema);
 
383
                if (!NT_STATUS_IS_OK(status)) {
 
384
                        DEBUG(0,(__location__ ": Failed to construct partial attribute set : %s\n", nt_errstr(status)));
 
385
                        return;
 
386
                }
 
387
                if (state->op->extended_op == DRSUAPI_EXOP_REPL_SECRET) {
 
388
                        replica_flags &= ~DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING;
 
389
                }
 
390
        }
256
391
 
257
392
        r->in.bind_handle       = &drsuapi->bind_handle;
258
393
        if (drsuapi->remote_info28.supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
261
396
                r->in.req->req8.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
262
397
                r->in.req->req8.naming_context          = &partition->nc;
263
398
                r->in.req->req8.highwatermark           = rf1->highwatermark;
264
 
                r->in.req->req8.uptodateness_vector     = NULL;/*&partition->uptodatevector_ex;*/
265
 
                r->in.req->req8.replica_flags           = rf1->replica_flags;
 
399
                r->in.req->req8.uptodateness_vector     = uptodateness_vector;
 
400
                r->in.req->req8.replica_flags           = replica_flags;
266
401
                r->in.req->req8.max_object_count        = 133;
267
402
                r->in.req->req8.max_ndr_size            = 1336811;
268
 
                r->in.req->req8.extended_op             = DRSUAPI_EXOP_NONE;
269
 
                r->in.req->req8.fsmo_info               = 0;
270
 
                r->in.req->req8.partial_attribute_set   = NULL;
 
403
                r->in.req->req8.extended_op             = state->op->extended_op;
 
404
                r->in.req->req8.fsmo_info               = state->op->fsmo_info;
 
405
                r->in.req->req8.partial_attribute_set   = pas;
271
406
                r->in.req->req8.partial_attribute_set_ex= NULL;
272
407
                r->in.req->req8.mapping_ctr.num_mappings= 0;
273
408
                r->in.req->req8.mapping_ctr.mappings    = NULL;
277
412
                r->in.req->req5.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
278
413
                r->in.req->req5.naming_context          = &partition->nc;
279
414
                r->in.req->req5.highwatermark           = rf1->highwatermark;
280
 
                r->in.req->req5.uptodateness_vector     = NULL;/*&partition->uptodatevector_ex;*/
281
 
                r->in.req->req5.replica_flags           = rf1->replica_flags;
 
415
                r->in.req->req5.uptodateness_vector     = uptodateness_vector;
 
416
                r->in.req->req5.replica_flags           = replica_flags;
282
417
                r->in.req->req5.max_object_count        = 133;
283
418
                r->in.req->req5.max_ndr_size            = 1336770;
284
 
                r->in.req->req5.extended_op             = DRSUAPI_EXOP_NONE;
285
 
                r->in.req->req5.fsmo_info               = 0;
286
 
        }
287
 
 
288
 
        req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi->pipe, r, r);
289
 
        composite_continue_rpc(c, req, dreplsrv_op_pull_source_get_changes_recv, st);
 
419
                r->in.req->req5.extended_op             = state->op->extended_op;
 
420
                r->in.req->req5.fsmo_info               = state->op->fsmo_info;
 
421
        }
 
422
 
 
423
#if 0
 
424
        NDR_PRINT_IN_DEBUG(drsuapi_DsGetNCChanges, r);
 
425
#endif
 
426
 
 
427
        state->ndr_struct_ptr = r;
 
428
        subreq = dcerpc_drsuapi_DsGetNCChanges_r_send(state,
 
429
                                                      state->ev,
 
430
                                                      drsuapi->drsuapi_handle,
 
431
                                                      r);
 
432
        if (tevent_req_nomem(subreq, req)) {
 
433
                return;
 
434
        }
 
435
        tevent_req_set_callback(subreq, dreplsrv_op_pull_source_get_changes_done, req);
290
436
}
291
437
 
292
 
static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st,
293
 
                                                       struct drsuapi_DsGetNCChanges *r,
294
 
                                                       uint32_t ctr_level,
295
 
                                                       struct drsuapi_DsGetNCChangesCtr1 *ctr1,
296
 
                                                       struct drsuapi_DsGetNCChangesCtr6 *ctr6);
 
438
static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req,
 
439
                                                          struct drsuapi_DsGetNCChanges *r,
 
440
                                                          uint32_t ctr_level,
 
441
                                                          struct drsuapi_DsGetNCChangesCtr1 *ctr1,
 
442
                                                          struct drsuapi_DsGetNCChangesCtr6 *ctr6);
297
443
 
298
 
static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req)
 
444
static void dreplsrv_op_pull_source_get_changes_done(struct tevent_req *subreq)
299
445
{
300
 
        struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data,
301
 
                                                   struct dreplsrv_op_pull_source_state);
302
 
        struct composite_context *c = st->creq;
303
 
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
 
446
        struct tevent_req *req = tevent_req_callback_data(subreq,
 
447
                                 struct tevent_req);
 
448
        struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
 
449
                                                      struct dreplsrv_op_pull_source_state);
 
450
        NTSTATUS status;
 
451
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(state->ndr_struct_ptr,
304
452
                                           struct drsuapi_DsGetNCChanges);
305
453
        uint32_t ctr_level = 0;
306
454
        struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
307
455
        struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
 
456
        enum drsuapi_DsExtendedError extended_ret;
 
457
        state->ndr_struct_ptr = NULL;
308
458
 
309
 
        c->status = dcerpc_ndr_request_recv(req);
310
 
        if (!composite_is_ok(c)) return;
 
459
        status = dcerpc_drsuapi_DsGetNCChanges_r_recv(subreq, r);
 
460
        TALLOC_FREE(subreq);
 
461
        if (tevent_req_nterror(req, status)) {
 
462
                return;
 
463
        }
311
464
 
312
465
        if (!W_ERROR_IS_OK(r->out.result)) {
313
 
                composite_error(c, werror_to_ntstatus(r->out.result));
 
466
                status = werror_to_ntstatus(r->out.result);
 
467
                tevent_req_nterror(req, status);
314
468
                return;
315
469
        }
316
470
 
337
491
                ctr_level = 6;
338
492
                ctr6 = &r->out.ctr->ctr7.ctr.xpress6.ts->ctr6;
339
493
        } else {
340
 
                composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
 
494
                status = werror_to_ntstatus(WERR_BAD_NET_RESP);
 
495
                tevent_req_nterror(req, status);
341
496
                return;
342
497
        }
343
498
 
344
499
        if (!ctr1 && !ctr6) {
345
 
                composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
 
500
                status = werror_to_ntstatus(WERR_BAD_NET_RESP);
 
501
                tevent_req_nterror(req, status);
346
502
                return;
347
503
        }
348
504
 
349
505
        if (ctr_level == 6) {
350
506
                if (!W_ERROR_IS_OK(ctr6->drs_error)) {
351
 
                        composite_error(c, werror_to_ntstatus(ctr6->drs_error));
352
 
                        return;
353
 
                }
354
 
        }
355
 
 
356
 
        dreplsrv_op_pull_source_apply_changes_send(st, r, ctr_level, ctr1, ctr6);
 
507
                        status = werror_to_ntstatus(ctr6->drs_error);
 
508
                        tevent_req_nterror(req, status);
 
509
                        return;
 
510
                }
 
511
                extended_ret = ctr6->extended_ret;
 
512
        }
 
513
 
 
514
        if (ctr_level == 1) {
 
515
                extended_ret = ctr1->extended_ret;
 
516
        }
 
517
 
 
518
        if (state->op->extended_op != DRSUAPI_EXOP_NONE) {
 
519
                state->op->extended_ret = extended_ret;
 
520
 
 
521
                if (extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) {
 
522
                        status = NT_STATUS_UNSUCCESSFUL;
 
523
                        tevent_req_nterror(req, status);
 
524
                        return;
 
525
                }
 
526
        }
 
527
 
 
528
        dreplsrv_op_pull_source_apply_changes_trigger(req, r, ctr_level, ctr1, ctr6);
357
529
}
358
530
 
359
 
static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st);
 
531
static void dreplsrv_update_refs_trigger(struct tevent_req *req);
360
532
 
361
 
static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st,
362
 
                                                       struct drsuapi_DsGetNCChanges *r,
363
 
                                                       uint32_t ctr_level,
364
 
                                                       struct drsuapi_DsGetNCChangesCtr1 *ctr1,
365
 
                                                       struct drsuapi_DsGetNCChangesCtr6 *ctr6)
 
533
static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req,
 
534
                                                          struct drsuapi_DsGetNCChanges *r,
 
535
                                                          uint32_t ctr_level,
 
536
                                                          struct drsuapi_DsGetNCChangesCtr1 *ctr1,
 
537
                                                           struct drsuapi_DsGetNCChangesCtr6 *ctr6)
366
538
{
367
 
        struct composite_context *c = st->creq;
368
 
        struct repsFromTo1 rf1 = *st->op->source_dsa->repsFrom1;
369
 
        struct dreplsrv_service *service = st->op->service;
370
 
        struct dreplsrv_partition *partition = st->op->source_dsa->partition;
371
 
        struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
 
539
        struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
 
540
                                                      struct dreplsrv_op_pull_source_state);
 
541
        struct repsFromTo1 rf1 = *state->op->source_dsa->repsFrom1;
 
542
        struct dreplsrv_service *service = state->op->service;
 
543
        struct dreplsrv_partition *partition = state->op->source_dsa->partition;
 
544
        struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
 
545
        struct dsdb_schema *schema;
 
546
        struct dsdb_schema *working_schema = NULL;
372
547
        const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
373
548
        uint32_t object_count;
374
549
        struct drsuapi_DsReplicaObjectListItemEx *first_object;
375
550
        uint32_t linked_attributes_count;
376
551
        struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
377
552
        const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
 
553
        struct dsdb_extended_replicated_objects *objects;
378
554
        bool more_data = false;
379
555
        WERROR status;
 
556
        NTSTATUS nt_status;
380
557
 
381
558
        switch (ctr_level) {
382
559
        case 1:
400
577
                more_data                       = ctr6->more_data;
401
578
                break;
402
579
        default:
403
 
                composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
404
 
                return;
405
 
        }
406
 
 
407
 
        status = dsdb_extended_replicated_objects_commit(service->samdb,
408
 
                                                         partition->nc.dn,
409
 
                                                         mapping_ctr,
410
 
                                                         object_count,
411
 
                                                         first_object,
412
 
                                                         linked_attributes_count,
413
 
                                                         linked_attributes,
414
 
                                                         &rf1,
415
 
                                                         uptodateness_vector,
416
 
                                                         &drsuapi->gensec_skey,
417
 
                                                         st, NULL, 
418
 
                                                         &st->op->source_dsa->notify_uSN);
419
 
        if (!W_ERROR_IS_OK(status)) {
420
 
                DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
421
 
                composite_error(c, werror_to_ntstatus(status));
422
 
                return;
423
 
        }
424
 
 
425
 
        /* if it applied fine, we need to update the highwatermark */
426
 
        *st->op->source_dsa->repsFrom1 = rf1;
427
 
 
 
580
                nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
 
581
                tevent_req_nterror(req, nt_status);
 
582
                return;
 
583
        }
 
584
 
 
585
        schema = dsdb_get_schema(service->samdb, NULL);
 
586
        if (!schema) {
 
587
                DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
 
588
                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
 
589
                return;
 
590
        }
 
591
 
 
592
        /*
 
593
         * Decide what working schema to use for object conversion.
 
594
         * We won't need a working schema for empty replicas sent.
 
595
         */
 
596
        if (first_object && ldb_dn_compare(partition->dn, schema->base_dn) == 0) {
 
597
                /* create working schema to convert objects with */
 
598
                status = dsdb_repl_make_working_schema(service->samdb,
 
599
                                                       schema,
 
600
                                                       mapping_ctr,
 
601
                                                       object_count,
 
602
                                                       first_object,
 
603
                                                       &drsuapi->gensec_skey,
 
604
                                                       state, &working_schema);
 
605
                if (!W_ERROR_IS_OK(status)) {
 
606
                        DEBUG(0,("Failed to create working schema: %s\n",
 
607
                                 win_errstr(status)));
 
608
                        tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
 
609
                        return;
 
610
                }
 
611
        }
 
612
 
 
613
        status = dsdb_replicated_objects_convert(service->samdb,
 
614
                                                 working_schema ? working_schema : schema,
 
615
                                                 partition->nc.dn,
 
616
                                                 mapping_ctr,
 
617
                                                 object_count,
 
618
                                                 first_object,
 
619
                                                 linked_attributes_count,
 
620
                                                 linked_attributes,
 
621
                                                 &rf1,
 
622
                                                 uptodateness_vector,
 
623
                                                 &drsuapi->gensec_skey,
 
624
                                                 state, &objects);
 
625
        if (!W_ERROR_IS_OK(status)) {
 
626
                nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
 
627
                DEBUG(0,("Failed to convert objects: %s/%s\n",
 
628
                          win_errstr(status), nt_errstr(nt_status)));
 
629
                tevent_req_nterror(req, nt_status);
 
630
                return;
 
631
        }
 
632
 
 
633
        status = dsdb_replicated_objects_commit(service->samdb,
 
634
                                                working_schema,
 
635
                                                objects,
 
636
                                                &state->op->source_dsa->notify_uSN);
 
637
        talloc_free(objects);
 
638
        if (!W_ERROR_IS_OK(status)) {
 
639
                nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
 
640
                DEBUG(0,("Failed to commit objects: %s/%s\n",
 
641
                          win_errstr(status), nt_errstr(nt_status)));
 
642
                tevent_req_nterror(req, nt_status);
 
643
                return;
 
644
        }
 
645
 
 
646
        if (state->op->extended_op == DRSUAPI_EXOP_NONE) {
 
647
                /* if it applied fine, we need to update the highwatermark */
 
648
                *state->op->source_dsa->repsFrom1 = rf1;
 
649
        }
428
650
        /*
429
651
         * TODO: update our uptodatevector!
430
652
         */
431
653
 
 
654
        /* we don't need this maybe very large structure anymore */
 
655
        TALLOC_FREE(r);
 
656
 
432
657
        if (more_data) {
433
 
                dreplsrv_op_pull_source_get_changes_send(st);
 
658
                dreplsrv_op_pull_source_get_changes_trigger(req);
 
659
                return;
 
660
        }
 
661
 
 
662
        if (state->op->extended_op != DRSUAPI_EXOP_NONE ||
 
663
            state->op->service->am_rodc) {
 
664
                /*
 
665
                  we don't do the UpdateRefs for extended ops or if we
 
666
                  are a RODC
 
667
                 */
 
668
                tevent_req_done(req);
434
669
                return;
435
670
        }
436
671
 
439
674
           we join the domain, but they quickly expire.  We do it here
440
675
           so we can use the already established DRSUAPI pipe
441
676
        */
442
 
        dreplsrv_update_refs_send(st);
443
 
}
444
 
 
445
 
WERROR dreplsrv_op_pull_source_recv(struct composite_context *c)
446
 
{
447
 
        NTSTATUS status;
448
 
 
449
 
        status = composite_wait(c);
450
 
 
451
 
        talloc_free(c);
452
 
        return ntstatus_to_werror(status);
453
 
}
454
 
 
455
 
/*
456
 
  receive a UpdateRefs reply
457
 
 */
458
 
static void dreplsrv_update_refs_recv(struct rpc_request *req)
459
 
{
460
 
        struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data,
461
 
                                                   struct dreplsrv_op_pull_source_state);
462
 
        struct composite_context *c = st->creq;
463
 
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
464
 
                                                                struct drsuapi_DsReplicaUpdateRefs);
465
 
 
466
 
        c->status = dcerpc_ndr_request_recv(req);
467
 
        if (!composite_is_ok(c)) {
468
 
                DEBUG(0,("UpdateRefs failed with %s\n", 
469
 
                         nt_errstr(c->status)));
470
 
                return;
471
 
        }
472
 
 
473
 
        if (!W_ERROR_IS_OK(r->out.result)) {
474
 
                DEBUG(0,("UpdateRefs failed with %s for %s %s\n", 
475
 
                         win_errstr(r->out.result),
476
 
                         r->in.req.req1.dest_dsa_dns_name,
477
 
                         r->in.req.req1.naming_context->dn));
478
 
                composite_error(c, werror_to_ntstatus(r->out.result));
479
 
                return;
480
 
        }
481
 
 
482
 
        DEBUG(4,("UpdateRefs OK for %s %s\n", 
483
 
                 r->in.req.req1.dest_dsa_dns_name,
484
 
                 r->in.req.req1.naming_context->dn));
485
 
 
486
 
        composite_done(c);
487
 
}
 
677
        dreplsrv_update_refs_trigger(req);
 
678
}
 
679
 
 
680
static void dreplsrv_update_refs_done(struct tevent_req *subreq);
488
681
 
489
682
/*
490
683
  send a UpdateRefs request to refresh our repsTo record on the server
491
684
 */
492
 
static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st)
 
685
static void dreplsrv_update_refs_trigger(struct tevent_req *req)
493
686
{
494
 
        struct composite_context *c = st->creq;
495
 
        struct dreplsrv_service *service = st->op->service;
496
 
        struct dreplsrv_partition *partition = st->op->source_dsa->partition;
497
 
        struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
498
 
        struct rpc_request *req;
 
687
        struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
 
688
                                                      struct dreplsrv_op_pull_source_state);
 
689
        struct dreplsrv_service *service = state->op->service;
 
690
        struct dreplsrv_partition *partition = state->op->source_dsa->partition;
 
691
        struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
499
692
        struct drsuapi_DsReplicaUpdateRefs *r;
500
693
        char *ntds_guid_str;
501
694
        char *ntds_dns_name;
 
695
        struct tevent_req *subreq;
502
696
 
503
 
        r = talloc(st, struct drsuapi_DsReplicaUpdateRefs);
504
 
        if (composite_nomem(r, c)) return;
 
697
        r = talloc(state, struct drsuapi_DsReplicaUpdateRefs);
 
698
        if (tevent_req_nomem(r, req)) {
 
699
                return;
 
700
        }
505
701
 
506
702
        ntds_guid_str = GUID_string(r, &service->ntds_guid);
507
 
        if (composite_nomem(ntds_guid_str, c)) return;
 
703
        if (tevent_req_nomem(ntds_guid_str, req)) {
 
704
                return;
 
705
        }
508
706
 
509
 
        /* lp_realm() is not really right here */
510
707
        ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
511
708
                                        ntds_guid_str,
512
 
                                        lp_realm(service->task->lp_ctx));
513
 
        if (composite_nomem(ntds_dns_name, c)) return;
 
709
                                        lpcfg_dnsdomain(service->task->lp_ctx));
 
710
        if (tevent_req_nomem(ntds_dns_name, req)) {
 
711
                return;
 
712
        }
514
713
 
515
714
        r->in.bind_handle       = &drsuapi->bind_handle;
516
715
        r->in.level             = 1;
517
716
        r->in.req.req1.naming_context     = &partition->nc;
518
717
        r->in.req.req1.dest_dsa_dns_name  = ntds_dns_name;
519
718
        r->in.req.req1.dest_dsa_guid      = service->ntds_guid;
520
 
        r->in.req.req1.options            = 
521
 
                DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE |
522
 
                DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE;
523
 
        if (!lp_parm_bool(service->task->lp_ctx, NULL, "repl", "RODC", false)) {
524
 
                r->in.req.req1.options |= DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE;
525
 
        }
526
 
 
527
 
        req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
528
 
        composite_continue_rpc(c, req, dreplsrv_update_refs_recv, st);
529
 
}
 
719
        r->in.req.req1.options            = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF;
 
720
        if (!service->am_rodc) {
 
721
                r->in.req.req1.options |= DRSUAPI_DRS_WRIT_REP;
 
722
        }
 
723
 
 
724
        state->ndr_struct_ptr = r;
 
725
        subreq = dcerpc_drsuapi_DsReplicaUpdateRefs_r_send(state,
 
726
                                                           state->ev,
 
727
                                                           drsuapi->drsuapi_handle,
 
728
                                                           r);
 
729
        if (tevent_req_nomem(subreq, req)) {
 
730
                return;
 
731
        }
 
732
        tevent_req_set_callback(subreq, dreplsrv_update_refs_done, req);
 
733
}
 
734
 
 
735
/*
 
736
  receive a UpdateRefs reply
 
737
 */
 
738
static void dreplsrv_update_refs_done(struct tevent_req *subreq)
 
739
{
 
740
        struct tevent_req *req = tevent_req_callback_data(subreq,
 
741
                                 struct tevent_req);
 
742
        struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
 
743
                                                      struct dreplsrv_op_pull_source_state);
 
744
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(state->ndr_struct_ptr,
 
745
                                                                struct drsuapi_DsReplicaUpdateRefs);
 
746
        NTSTATUS status;
 
747
 
 
748
        state->ndr_struct_ptr = NULL;
 
749
 
 
750
        status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv(subreq, r);
 
751
        TALLOC_FREE(subreq);
 
752
        if (!NT_STATUS_IS_OK(status)) {
 
753
                DEBUG(0,("UpdateRefs failed with %s\n", 
 
754
                         nt_errstr(status)));
 
755
                tevent_req_nterror(req, status);
 
756
                return;
 
757
        }
 
758
 
 
759
        if (!W_ERROR_IS_OK(r->out.result)) {
 
760
                status = werror_to_ntstatus(r->out.result);
 
761
                DEBUG(0,("UpdateRefs failed with %s/%s for %s %s\n",
 
762
                         win_errstr(r->out.result),
 
763
                         nt_errstr(status),
 
764
                         r->in.req.req1.dest_dsa_dns_name,
 
765
                         r->in.req.req1.naming_context->dn));
 
766
                tevent_req_nterror(req, status);
 
767
                return;
 
768
        }
 
769
 
 
770
        DEBUG(4,("UpdateRefs OK for %s %s\n", 
 
771
                 r->in.req.req1.dest_dsa_dns_name,
 
772
                 r->in.req.req1.naming_context->dn));
 
773
 
 
774
        tevent_req_done(req);
 
775
}
 
776
 
 
777
WERROR dreplsrv_op_pull_source_recv(struct tevent_req *req)
 
778
{
 
779
        NTSTATUS status;
 
780
 
 
781
        if (tevent_req_is_nterror(req, &status)) {
 
782
                tevent_req_received(req);
 
783
                return ntstatus_to_werror(status);
 
784
        }
 
785
 
 
786
        tevent_req_received(req);
 
787
        return WERR_OK;
 
788
}
 
789