~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

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

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS mplementation.
 
3
   DSDB replication service helper function for outgoing traffic
 
4
   
 
5
   Copyright (C) Stefan Metzmacher 2007
 
6
    
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 3 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
   
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
   
 
20
*/
 
21
 
 
22
#include "includes.h"
 
23
#include "dsdb/samdb/samdb.h"
 
24
#include "auth/auth.h"
 
25
#include "smbd/service.h"
 
26
#include "lib/events/events.h"
 
27
#include "lib/messaging/irpc.h"
 
28
#include "dsdb/repl/drepl_service.h"
 
29
#include "lib/ldb/include/ldb_errors.h"
 
30
#include "../lib/util/dlinklist.h"
 
31
#include "librpc/gen_ndr/ndr_misc.h"
 
32
#include "librpc/gen_ndr/ndr_drsuapi.h"
 
33
#include "librpc/gen_ndr/ndr_drsblobs.h"
 
34
#include "libcli/composite/composite.h"
 
35
#include "auth/gensec/gensec.h"
 
36
 
 
37
struct dreplsrv_out_drsuapi_state {
 
38
        struct composite_context *creq;
 
39
 
 
40
        struct dreplsrv_out_connection *conn;
 
41
 
 
42
        struct dreplsrv_drsuapi_connection *drsuapi;
 
43
 
 
44
        struct drsuapi_DsBindInfoCtr bind_info_ctr;
 
45
        struct drsuapi_DsBind bind_r;
 
46
};
 
47
 
 
48
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq);
 
49
 
 
50
static struct composite_context *dreplsrv_out_drsuapi_send(struct dreplsrv_out_connection *conn)
 
51
{
 
52
        struct composite_context *c;
 
53
        struct composite_context *creq;
 
54
        struct dreplsrv_out_drsuapi_state *st;
 
55
 
 
56
        c = composite_create(conn, conn->service->task->event_ctx);
 
57
        if (c == NULL) return NULL;
 
58
 
 
59
        st = talloc_zero(c, struct dreplsrv_out_drsuapi_state);
 
60
        if (composite_nomem(st, c)) return c;
 
61
 
 
62
        c->private_data = st;
 
63
 
 
64
        st->creq        = c;
 
65
        st->conn        = conn;
 
66
        st->drsuapi     = conn->drsuapi;
 
67
 
 
68
        if (st->drsuapi && !st->drsuapi->pipe->conn->dead) {
 
69
                composite_done(c);
 
70
                return c;
 
71
        } else if (st->drsuapi && st->drsuapi->pipe->conn->dead) {
 
72
                talloc_free(st->drsuapi);
 
73
                conn->drsuapi = NULL;
 
74
        }
 
75
 
 
76
        st->drsuapi     = talloc_zero(st, struct dreplsrv_drsuapi_connection);
 
77
        if (composite_nomem(st->drsuapi, c)) return c;
 
78
 
 
79
        creq = dcerpc_pipe_connect_b_send(st, conn->binding, &ndr_table_drsuapi,
 
80
                                          conn->service->system_session_info->credentials,
 
81
                                          c->event_ctx, conn->service->task->lp_ctx);
 
82
        composite_continue(c, creq, dreplsrv_out_drsuapi_connect_recv, st);
 
83
 
 
84
        return c;
 
85
}
 
86
 
 
87
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st);
 
88
 
 
89
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq)
 
90
{
 
91
        struct dreplsrv_out_drsuapi_state *st = talloc_get_type(creq->async.private_data,
 
92
                                                struct dreplsrv_out_drsuapi_state);
 
93
        struct composite_context *c = st->creq;
 
94
 
 
95
        c->status = dcerpc_pipe_connect_b_recv(creq, st->drsuapi, &st->drsuapi->pipe);
 
96
        if (!composite_is_ok(c)) return;
 
97
 
 
98
        c->status = gensec_session_key(st->drsuapi->pipe->conn->security_state.generic_state,
 
99
                                       &st->drsuapi->gensec_skey);
 
100
        if (!composite_is_ok(c)) return;
 
101
 
 
102
        dreplsrv_out_drsuapi_bind_send(st);
 
103
}
 
104
 
 
105
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req);
 
106
 
 
107
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st)
 
108
{
 
109
        struct composite_context *c = st->creq;
 
110
        struct rpc_request *req;
 
111
 
 
112
        st->bind_info_ctr.length        = 28;
 
113
        st->bind_info_ctr.info.info28   = st->conn->service->bind_info28;
 
114
 
 
115
        st->bind_r.in.bind_guid = &st->conn->service->ntds_guid;
 
116
        st->bind_r.in.bind_info = &st->bind_info_ctr;
 
117
        st->bind_r.out.bind_handle = &st->drsuapi->bind_handle;
 
118
 
 
119
        req = dcerpc_drsuapi_DsBind_send(st->drsuapi->pipe, st, &st->bind_r);
 
120
        composite_continue_rpc(c, req, dreplsrv_out_drsuapi_bind_recv, st);
 
121
}
 
122
 
 
123
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req)
 
124
{
 
125
        struct dreplsrv_out_drsuapi_state *st = talloc_get_type(req->async.private_data,
 
126
                                                struct dreplsrv_out_drsuapi_state);
 
127
        struct composite_context *c = st->creq;
 
128
 
 
129
        c->status = dcerpc_ndr_request_recv(req);
 
130
        if (!composite_is_ok(c)) return;
 
131
 
 
132
        if (!W_ERROR_IS_OK(st->bind_r.out.result)) {
 
133
                composite_error(c, werror_to_ntstatus(st->bind_r.out.result));
 
134
                return;
 
135
        }
 
136
 
 
137
        ZERO_STRUCT(st->drsuapi->remote_info28);
 
138
        if (st->bind_r.out.bind_info) {
 
139
                switch (st->bind_r.out.bind_info->length) {
 
140
                case 24: {
 
141
                        struct drsuapi_DsBindInfo24 *info24;
 
142
                        info24 = &st->bind_r.out.bind_info->info.info24;
 
143
                        st->drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
 
144
                        st->drsuapi->remote_info28.site_guid            = info24->site_guid;
 
145
                        st->drsuapi->remote_info28.pid                  = info24->pid;
 
146
                        st->drsuapi->remote_info28.repl_epoch           = 0;
 
147
                        break;
 
148
                }
 
149
                case 48: {
 
150
                        struct drsuapi_DsBindInfo48 *info48;
 
151
                        info48 = &st->bind_r.out.bind_info->info.info48;
 
152
                        st->drsuapi->remote_info28.supported_extensions = info48->supported_extensions;
 
153
                        st->drsuapi->remote_info28.site_guid            = info48->site_guid;
 
154
                        st->drsuapi->remote_info28.pid                  = info48->pid;
 
155
                        st->drsuapi->remote_info28.repl_epoch           = info48->repl_epoch;
 
156
                        break;
 
157
                }
 
158
                case 28:
 
159
                        st->drsuapi->remote_info28 = st->bind_r.out.bind_info->info.info28;
 
160
                        break;
 
161
                }
 
162
        }
 
163
 
 
164
        composite_done(c);
 
165
}
 
166
 
 
167
static NTSTATUS dreplsrv_out_drsuapi_recv(struct composite_context *c)
 
168
{
 
169
        NTSTATUS status;
 
170
        struct dreplsrv_out_drsuapi_state *st = talloc_get_type(c->private_data,
 
171
                                                struct dreplsrv_out_drsuapi_state);
 
172
 
 
173
        status = composite_wait(c);
 
174
 
 
175
        if (NT_STATUS_IS_OK(status)) {
 
176
                st->conn->drsuapi = talloc_steal(st->conn, st->drsuapi);
 
177
        }
 
178
 
 
179
        talloc_free(c);
 
180
        return status;
 
181
}
 
182
 
 
183
struct dreplsrv_op_pull_source_state {
 
184
        struct composite_context *creq;
 
185
 
 
186
        struct dreplsrv_out_operation *op;
 
187
 
 
188
        struct dreplsrv_drsuapi_connection *drsuapi;
 
189
 
 
190
        bool have_all;
 
191
 
 
192
        uint32_t ctr_level;
 
193
        struct drsuapi_DsGetNCChangesCtr1 *ctr1;
 
194
        struct drsuapi_DsGetNCChangesCtr6 *ctr6;
 
195
};
 
196
 
 
197
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq);
 
198
 
 
199
struct composite_context *dreplsrv_op_pull_source_send(struct dreplsrv_out_operation *op)
 
200
{
 
201
        struct composite_context *c;
 
202
        struct composite_context *creq;
 
203
        struct dreplsrv_op_pull_source_state *st;
 
204
 
 
205
        c = composite_create(op, op->service->task->event_ctx);
 
206
        if (c == NULL) return NULL;
 
207
 
 
208
        st = talloc_zero(c, struct dreplsrv_op_pull_source_state);
 
209
        if (composite_nomem(st, c)) return c;
 
210
 
 
211
        st->creq        = c;
 
212
        st->op          = op;
 
213
 
 
214
        creq = dreplsrv_out_drsuapi_send(op->source_dsa->conn);
 
215
        composite_continue(c, creq, dreplsrv_op_pull_source_connect_recv, st);
 
216
 
 
217
        return c;
 
218
}
 
219
 
 
220
static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st);
 
221
 
 
222
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq)
 
223
{
 
224
        struct dreplsrv_op_pull_source_state *st = talloc_get_type(creq->async.private_data,
 
225
                                                   struct dreplsrv_op_pull_source_state);
 
226
        struct composite_context *c = st->creq;
 
227
 
 
228
        c->status = dreplsrv_out_drsuapi_recv(creq);
 
229
        if (!composite_is_ok(c)) return;
 
230
 
 
231
        dreplsrv_op_pull_source_get_changes_send(st);
 
232
}
 
233
 
 
234
static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req);
 
235
 
 
236
static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st)
 
237
{
 
238
        struct composite_context *c = st->creq;
 
239
        struct repsFromTo1 *rf1 = st->op->source_dsa->repsFrom1;
 
240
        struct dreplsrv_service *service = st->op->service;
 
241
        struct dreplsrv_partition *partition = st->op->source_dsa->partition;
 
242
        struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
 
243
        struct rpc_request *req;
 
244
        struct drsuapi_DsGetNCChanges *r;
 
245
 
 
246
        r = talloc(st, struct drsuapi_DsGetNCChanges);
 
247
        if (composite_nomem(r, c)) return;
 
248
 
 
249
        r->out.level_out = talloc(r, int32_t);
 
250
        if (composite_nomem(r->out.level_out, c)) return;
 
251
        r->in.req = talloc(r, union drsuapi_DsGetNCChangesRequest);
 
252
        if (composite_nomem(r->in.req, c)) return;
 
253
        r->out.ctr = talloc(r, union drsuapi_DsGetNCChangesCtr);
 
254
        if (composite_nomem(r->out.ctr, c)) return;
 
255
 
 
256
        r->in.bind_handle       = &drsuapi->bind_handle;
 
257
        if (drsuapi->remote_info28.supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
 
258
                r->in.level                             = 8;
 
259
                r->in.req->req8.destination_dsa_guid    = service->ntds_guid;
 
260
                r->in.req->req8.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
 
261
                r->in.req->req8.naming_context          = &partition->nc;
 
262
                r->in.req->req8.highwatermark           = rf1->highwatermark;
 
263
                r->in.req->req8.uptodateness_vector     = NULL;/*&partition->uptodatevector_ex;*/
 
264
                r->in.req->req8.replica_flags           = rf1->replica_flags;
 
265
                r->in.req->req8.max_object_count        = 133;
 
266
                r->in.req->req8.max_ndr_size            = 1336811;
 
267
                r->in.req->req8.extended_op             = DRSUAPI_EXOP_NONE;
 
268
                r->in.req->req8.fsmo_info               = 0;
 
269
                r->in.req->req8.partial_attribute_set   = NULL;
 
270
                r->in.req->req8.partial_attribute_set_ex= NULL;
 
271
                r->in.req->req8.mapping_ctr.num_mappings= 0;
 
272
                r->in.req->req8.mapping_ctr.mappings    = NULL;
 
273
        } else {
 
274
                r->in.level                             = 5;
 
275
                r->in.req->req5.destination_dsa_guid    = service->ntds_guid;
 
276
                r->in.req->req5.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
 
277
                r->in.req->req5.naming_context          = &partition->nc;
 
278
                r->in.req->req5.highwatermark           = rf1->highwatermark;
 
279
                r->in.req->req5.uptodateness_vector     = NULL;/*&partition->uptodatevector_ex;*/
 
280
                r->in.req->req5.replica_flags           = rf1->replica_flags;
 
281
                r->in.req->req5.max_object_count        = 133;
 
282
                r->in.req->req5.max_ndr_size            = 1336770;
 
283
                r->in.req->req5.extended_op             = DRSUAPI_EXOP_NONE;
 
284
                r->in.req->req5.fsmo_info               = 0;
 
285
        }
 
286
 
 
287
        req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi->pipe, r, r);
 
288
        composite_continue_rpc(c, req, dreplsrv_op_pull_source_get_changes_recv, st);
 
289
}
 
290
 
 
291
static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st,
 
292
                                                       struct drsuapi_DsGetNCChanges *r,
 
293
                                                       uint32_t ctr_level,
 
294
                                                       struct drsuapi_DsGetNCChangesCtr1 *ctr1,
 
295
                                                       struct drsuapi_DsGetNCChangesCtr6 *ctr6);
 
296
 
 
297
static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req)
 
298
{
 
299
        struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data,
 
300
                                                   struct dreplsrv_op_pull_source_state);
 
301
        struct composite_context *c = st->creq;
 
302
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
 
303
                                           struct drsuapi_DsGetNCChanges);
 
304
        uint32_t ctr_level = 0;
 
305
        struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
 
306
        struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
 
307
 
 
308
        c->status = dcerpc_ndr_request_recv(req);
 
309
        if (!composite_is_ok(c)) return;
 
310
 
 
311
        if (!W_ERROR_IS_OK(r->out.result)) {
 
312
                composite_error(c, werror_to_ntstatus(r->out.result));
 
313
                return;
 
314
        }
 
315
 
 
316
        if (*r->out.level_out == 1) {
 
317
                ctr_level = 1;
 
318
                ctr1 = &r->out.ctr->ctr1;
 
319
        } else if (*r->out.level_out == 2 &&
 
320
                   r->out.ctr->ctr2.mszip1.ts) {
 
321
                ctr_level = 1;
 
322
                ctr1 = &r->out.ctr->ctr2.mszip1.ts->ctr1;
 
323
        } else if (*r->out.level_out == 6) {
 
324
                ctr_level = 6;
 
325
                ctr6 = &r->out.ctr->ctr6;
 
326
        } else if (*r->out.level_out == 7 &&
 
327
                   r->out.ctr->ctr7.level == 6 &&
 
328
                   r->out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP &&
 
329
                   r->out.ctr->ctr7.ctr.mszip6.ts) {
 
330
                ctr_level = 6;
 
331
                ctr6 = &r->out.ctr->ctr7.ctr.mszip6.ts->ctr6;
 
332
        } else if (*r->out.level_out == 7 &&
 
333
                   r->out.ctr->ctr7.level == 6 &&
 
334
                   r->out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS &&
 
335
                   r->out.ctr->ctr7.ctr.xpress6.ts) {
 
336
                ctr_level = 6;
 
337
                ctr6 = &r->out.ctr->ctr7.ctr.xpress6.ts->ctr6;
 
338
        } else {
 
339
                composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
 
340
                return;
 
341
        }
 
342
 
 
343
        if (!ctr1 && !ctr6) {
 
344
                composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
 
345
                return;
 
346
        }
 
347
 
 
348
        if (ctr_level == 6) {
 
349
                if (!W_ERROR_IS_OK(ctr6->drs_error)) {
 
350
                        composite_error(c, werror_to_ntstatus(ctr6->drs_error));
 
351
                        return;
 
352
                }
 
353
        }
 
354
 
 
355
        dreplsrv_op_pull_source_apply_changes_send(st, r, ctr_level, ctr1, ctr6);
 
356
}
 
357
 
 
358
static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st,
 
359
                                                       struct drsuapi_DsGetNCChanges *r,
 
360
                                                       uint32_t ctr_level,
 
361
                                                       struct drsuapi_DsGetNCChangesCtr1 *ctr1,
 
362
                                                       struct drsuapi_DsGetNCChangesCtr6 *ctr6)
 
363
{
 
364
        struct composite_context *c = st->creq;
 
365
        struct repsFromTo1 rf1 = *st->op->source_dsa->repsFrom1;
 
366
        struct dreplsrv_service *service = st->op->service;
 
367
        struct dreplsrv_partition *partition = st->op->source_dsa->partition;
 
368
        struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
 
369
        const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
 
370
        uint32_t object_count;
 
371
        struct drsuapi_DsReplicaObjectListItemEx *first_object;
 
372
        uint32_t linked_attributes_count;
 
373
        struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
 
374
        const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
 
375
        bool more_data = false;
 
376
        WERROR status;
 
377
 
 
378
        switch (ctr_level) {
 
379
        case 1:
 
380
                mapping_ctr                     = &ctr1->mapping_ctr;
 
381
                object_count                    = ctr1->object_count;
 
382
                first_object                    = ctr1->first_object;
 
383
                linked_attributes_count         = 0;
 
384
                linked_attributes               = NULL;
 
385
                rf1.highwatermark               = ctr1->new_highwatermark;
 
386
                uptodateness_vector             = NULL; /* TODO: map it */
 
387
                more_data                       = ctr1->more_data;
 
388
                break;
 
389
        case 6:
 
390
                mapping_ctr                     = &ctr6->mapping_ctr;
 
391
                object_count                    = ctr6->object_count;
 
392
                first_object                    = ctr6->first_object;
 
393
                linked_attributes_count         = ctr6->linked_attributes_count;
 
394
                linked_attributes               = ctr6->linked_attributes;
 
395
                rf1.highwatermark               = ctr6->new_highwatermark;
 
396
                uptodateness_vector             = ctr6->uptodateness_vector;
 
397
                more_data                       = ctr6->more_data;
 
398
                break;
 
399
        default:
 
400
                composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
 
401
                return;
 
402
        }
 
403
 
 
404
        status = dsdb_extended_replicated_objects_commit(service->samdb,
 
405
                                                         partition->nc.dn,
 
406
                                                         mapping_ctr,
 
407
                                                         object_count,
 
408
                                                         first_object,
 
409
                                                         linked_attributes_count,
 
410
                                                         linked_attributes,
 
411
                                                         &rf1,
 
412
                                                         uptodateness_vector,
 
413
                                                         &drsuapi->gensec_skey,
 
414
                                                         st, NULL);
 
415
        if (!W_ERROR_IS_OK(status)) {
 
416
                DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
 
417
                composite_error(c, werror_to_ntstatus(status));
 
418
                return;
 
419
        }
 
420
 
 
421
        /* if it applied fine, we need to update the highwatermark */
 
422
        *st->op->source_dsa->repsFrom1 = rf1;
 
423
 
 
424
        /*
 
425
         * TODO: update our uptodatevector!
 
426
         */
 
427
 
 
428
        if (more_data) {
 
429
                dreplsrv_op_pull_source_get_changes_send(st);
 
430
                return;
 
431
        }
 
432
 
 
433
        composite_done(c);
 
434
}
 
435
 
 
436
WERROR dreplsrv_op_pull_source_recv(struct composite_context *c)
 
437
{
 
438
        NTSTATUS status;
 
439
 
 
440
        status = composite_wait(c);
 
441
 
 
442
        talloc_free(c);
 
443
        return ntstatus_to_werror(status);
 
444
}