~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/rpc_server/drsuapi/dcesrv_drsuapi.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 implementation.
 
3
 
 
4
   endpoint server for the drsuapi pipe
 
5
 
 
6
   Copyright (C) Stefan Metzmacher 2004
 
7
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
 
8
   
 
9
   This program is free software; you can redistribute it and/or modify
 
10
   it under the terms of the GNU General Public License as published by
 
11
   the Free Software Foundation; either version 3 of the License, or
 
12
   (at your option) any later version.
 
13
   
 
14
   This program is distributed in the hope that it will be useful,
 
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
   GNU General Public License for more details.
 
18
   
 
19
   You should have received a copy of the GNU General Public License
 
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
*/
 
22
 
 
23
#include "includes.h"
 
24
#include "librpc/gen_ndr/ndr_drsuapi.h"
 
25
#include "rpc_server/dcerpc_server.h"
 
26
#include "rpc_server/common/common.h"
 
27
#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
 
28
#include "dsdb/samdb/samdb.h"
 
29
#include "lib/ldb/include/ldb_errors.h"
 
30
#include "param/param.h"
 
31
 
 
32
/* 
 
33
  drsuapi_DsBind 
 
34
*/
 
35
static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
36
                       struct drsuapi_DsBind *r)
 
37
{
 
38
        struct drsuapi_bind_state *b_state;
 
39
        struct dcesrv_handle *handle;
 
40
        struct drsuapi_DsBindInfoCtr *bind_info;
 
41
        struct GUID site_guid;
 
42
        struct ldb_result *site_res;
 
43
        struct ldb_dn *server_site_dn;
 
44
        static const char *site_attrs[] = { "objectGUID", NULL };
 
45
        struct ldb_result *ntds_res;
 
46
        struct ldb_dn *ntds_dn;
 
47
        static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL };
 
48
        uint32_t pid;
 
49
        uint32_t repl_epoch;
 
50
        int ret;
 
51
 
 
52
        r->out.bind_info = NULL;
 
53
        ZERO_STRUCTP(r->out.bind_handle);
 
54
 
 
55
        b_state = talloc_zero(mem_ctx, struct drsuapi_bind_state);
 
56
        W_ERROR_HAVE_NO_MEMORY(b_state);
 
57
 
 
58
        /*
 
59
         * connect to the samdb
 
60
         */
 
61
        b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 
 
62
        if (!b_state->sam_ctx) {
 
63
                return WERR_FOOBAR;
 
64
        }
 
65
 
 
66
        /*
 
67
         * find out the guid of our own site
 
68
         */
 
69
        server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx);
 
70
        W_ERROR_HAVE_NO_MEMORY(server_site_dn);
 
71
 
 
72
        ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res,
 
73
                                 server_site_dn, LDB_SCOPE_BASE, site_attrs,
 
74
                                 "(objectClass=*)");
 
75
        if (ret != LDB_SUCCESS) {
 
76
                return WERR_DS_DRA_INTERNAL_ERROR;
 
77
        }
 
78
        if (site_res->count != 1) {
 
79
                return WERR_DS_DRA_INTERNAL_ERROR;
 
80
        }
 
81
        site_guid = samdb_result_guid(site_res->msgs[0], "objectGUID");
 
82
 
 
83
        /*
 
84
         * lookup the local servers Replication Epoch
 
85
         */
 
86
        ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx);
 
87
        W_ERROR_HAVE_NO_MEMORY(ntds_dn);
 
88
 
 
89
        ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res,
 
90
                                 ntds_dn, LDB_SCOPE_BASE, ntds_attrs,
 
91
                                 "(objectClass=*)");
 
92
        if (ret != LDB_SUCCESS) {
 
93
                return WERR_DS_DRA_INTERNAL_ERROR;
 
94
        }
 
95
        if (ntds_res->count != 1) {
 
96
                return WERR_DS_DRA_INTERNAL_ERROR;
 
97
        }
 
98
        repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0);
 
99
 
 
100
        /*
 
101
         * The "process identifier" of the client.
 
102
         * According to the WSPP docs, sectin 5.35, this is
 
103
         * for informational and debugging purposes only.
 
104
         * The assignment is implementation specific.
 
105
         */
 
106
        pid = 0;
 
107
 
 
108
        /*
 
109
         * store the clients bind_guid
 
110
         */
 
111
        if (r->in.bind_guid) {
 
112
                b_state->remote_bind_guid = *r->in.bind_guid;
 
113
        }
 
114
 
 
115
        /*
 
116
         * store the clients bind_info
 
117
         */
 
118
        if (r->in.bind_info) {
 
119
                switch (r->in.bind_info->length) {
 
120
                case 24: {
 
121
                        struct drsuapi_DsBindInfo24 *info24;
 
122
                        info24 = &r->in.bind_info->info.info24;
 
123
                        b_state->remote_info28.supported_extensions     = info24->supported_extensions;
 
124
                        b_state->remote_info28.site_guid                = info24->site_guid;
 
125
                        b_state->remote_info28.pid                      = info24->pid;
 
126
                        b_state->remote_info28.repl_epoch               = 0;
 
127
                        break;
 
128
                }
 
129
                case 28:
 
130
                        b_state->remote_info28 = r->in.bind_info->info.info28;
 
131
                        break;
 
132
                }
 
133
        }
 
134
 
 
135
        /*
 
136
         * fill in our local bind info 28
 
137
         */
 
138
        b_state->local_info28.supported_extensions      = 0;
 
139
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
 
140
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
 
141
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
 
142
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
 
143
#if 0 /* we don't support MSZIP compression (only decompression) */
 
144
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
 
145
#endif
 
146
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
 
147
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
 
148
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
 
149
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
 
150
        if (0 /*domain.behavior_version == 2*/) {
 
151
                /* TODO: find out how this is really triggered! */
 
152
                b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
 
153
        }
 
154
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
 
155
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
 
156
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
 
157
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
 
158
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
 
159
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
 
160
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
 
161
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
 
162
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
 
163
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_00100000;
 
164
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
 
165
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
 
166
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
 
167
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
 
168
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
 
169
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
 
170
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
 
171
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
 
172
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
 
173
#if 0 /* we don't support XPRESS compression yet */
 
174
        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
 
175
#endif
 
176
        b_state->local_info28.site_guid                 = site_guid;
 
177
        b_state->local_info28.pid                       = pid;
 
178
        b_state->local_info28.repl_epoch                = repl_epoch;
 
179
 
 
180
        /*
 
181
         * allocate the return bind_info
 
182
         */
 
183
        bind_info = talloc(mem_ctx, struct drsuapi_DsBindInfoCtr);
 
184
        W_ERROR_HAVE_NO_MEMORY(bind_info);
 
185
 
 
186
        bind_info->length       = 28;
 
187
        bind_info->info.info28  = b_state->local_info28;
 
188
 
 
189
        /*
 
190
         * allocate a bind handle
 
191
         */
 
192
        handle = dcesrv_handle_new(dce_call->context, DRSUAPI_BIND_HANDLE);
 
193
        W_ERROR_HAVE_NO_MEMORY(handle);
 
194
        handle->data = talloc_steal(handle, b_state);
 
195
 
 
196
        /*
 
197
         * prepare reply
 
198
         */
 
199
        r->out.bind_info = bind_info;
 
200
        *r->out.bind_handle = handle->wire_handle;
 
201
 
 
202
        return WERR_OK;
 
203
}
 
204
 
 
205
 
 
206
/* 
 
207
  drsuapi_DsUnbind 
 
208
*/
 
209
static WERROR dcesrv_drsuapi_DsUnbind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
210
                               struct drsuapi_DsUnbind *r)
 
211
{
 
212
        struct dcesrv_handle *h;
 
213
 
 
214
        *r->out.bind_handle = *r->in.bind_handle;
 
215
 
 
216
        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
 
217
 
 
218
        talloc_free(h);
 
219
 
 
220
        ZERO_STRUCTP(r->out.bind_handle);
 
221
 
 
222
        return WERR_OK;
 
223
}
 
224
 
 
225
 
 
226
/* 
 
227
  drsuapi_DsReplicaSync 
 
228
*/
 
229
static WERROR dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
230
                       struct drsuapi_DsReplicaSync *r)
 
231
{
 
232
        /* TODO: implement this call correct!
 
233
         *       for now we just say yes,
 
234
         *       because we have no output parameter
 
235
         */
 
236
        return WERR_OK;
 
237
}
 
238
 
 
239
 
 
240
/* 
 
241
  drsuapi_DsGetNCChanges
 
242
*/
 
243
static WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
244
                       struct drsuapi_DsGetNCChanges *r)
 
245
{
 
246
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
247
}
 
248
 
 
249
 
 
250
/* 
 
251
  drsuapi_DsReplicaUpdateRefs
 
252
*/
 
253
static WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
254
                       struct drsuapi_DsReplicaUpdateRefs *r)
 
255
{
 
256
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
257
}
 
258
 
 
259
 
 
260
/* 
 
261
  DRSUAPI_REPLICA_ADD 
 
262
*/
 
263
static WERROR dcesrv_DRSUAPI_REPLICA_ADD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
264
                       struct DRSUAPI_REPLICA_ADD *r)
 
265
{
 
266
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
267
}
 
268
 
 
269
 
 
270
/* 
 
271
  DRSUAPI_REPLICA_DEL 
 
272
*/
 
273
static WERROR dcesrv_DRSUAPI_REPLICA_DEL(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
274
                       struct DRSUAPI_REPLICA_DEL *r)
 
275
{
 
276
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
277
}
 
278
 
 
279
 
 
280
/* 
 
281
  DRSUAPI_REPLICA_MODIFY 
 
282
*/
 
283
static WERROR dcesrv_DRSUAPI_REPLICA_MODIFY(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
284
                       struct DRSUAPI_REPLICA_MODIFY *r)
 
285
{
 
286
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
287
}
 
288
 
 
289
 
 
290
/* 
 
291
  DRSUAPI_VERIFY_NAMES 
 
292
*/
 
293
static WERROR dcesrv_DRSUAPI_VERIFY_NAMES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
294
                       struct DRSUAPI_VERIFY_NAMES *r)
 
295
{
 
296
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
297
}
 
298
 
 
299
 
 
300
/* 
 
301
  drsuapi_DsGetMemberships 
 
302
*/
 
303
static WERROR dcesrv_drsuapi_DsGetMemberships(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
304
                       struct drsuapi_DsGetMemberships *r)
 
305
{
 
306
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
307
}
 
308
 
 
309
 
 
310
/* 
 
311
  DRSUAPI_INTER_DOMAIN_MOVE 
 
312
*/
 
313
static WERROR dcesrv_DRSUAPI_INTER_DOMAIN_MOVE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
314
                       struct DRSUAPI_INTER_DOMAIN_MOVE *r)
 
315
{
 
316
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
317
}
 
318
 
 
319
 
 
320
/* 
 
321
  drsuapi_DsGetNT4ChangeLog 
 
322
*/
 
323
static WERROR dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
324
                       struct drsuapi_DsGetNT4ChangeLog *r)
 
325
{
 
326
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
327
}
 
328
 
 
329
 
 
330
/* 
 
331
  drsuapi_DsCrackNames 
 
332
*/
 
333
static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
334
                            struct drsuapi_DsCrackNames *r)
 
335
{
 
336
        WERROR status;
 
337
        struct drsuapi_bind_state *b_state;
 
338
        struct dcesrv_handle *h;
 
339
 
 
340
        *r->out.level_out = r->in.level;
 
341
 
 
342
        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
 
343
        b_state = h->data;
 
344
 
 
345
        r->out.ctr = talloc_zero(mem_ctx, union drsuapi_DsNameCtr);
 
346
        W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
 
347
 
 
348
        switch (r->in.level) {
 
349
                case 1: {
 
350
                        struct drsuapi_DsNameCtr1 *ctr1;
 
351
                        struct drsuapi_DsNameInfo1 *names;
 
352
                        int count;
 
353
                        int i;
 
354
 
 
355
                        ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
 
356
                        W_ERROR_HAVE_NO_MEMORY(ctr1);
 
357
 
 
358
                        count = r->in.req->req1.count;
 
359
                        names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
 
360
                        W_ERROR_HAVE_NO_MEMORY(names);
 
361
 
 
362
                        for (i=0; i < count; i++) {
 
363
                                status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx,
 
364
                                                            r->in.req->req1.format_flags,
 
365
                                                            r->in.req->req1.format_offered,
 
366
                                                            r->in.req->req1.format_desired,
 
367
                                                            r->in.req->req1.names[i].str,
 
368
                                                            &names[i]);
 
369
                                if (!W_ERROR_IS_OK(status)) {
 
370
                                        return status;
 
371
                                }
 
372
                        }
 
373
 
 
374
                        ctr1->count = count;
 
375
                        ctr1->array = names;
 
376
                        r->out.ctr->ctr1 = ctr1;
 
377
 
 
378
                        return WERR_OK;
 
379
                }
 
380
        }
 
381
        
 
382
        return WERR_UNKNOWN_LEVEL;
 
383
}
 
384
 
 
385
/* 
 
386
  drsuapi_DsWriteAccountSpn 
 
387
*/
 
388
static WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
389
                       struct drsuapi_DsWriteAccountSpn *r)
 
390
{
 
391
        struct drsuapi_bind_state *b_state;
 
392
        struct dcesrv_handle *h;
 
393
 
 
394
        *r->out.level_out = r->in.level;
 
395
 
 
396
        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
 
397
        b_state = h->data;
 
398
 
 
399
        r->out.res = talloc(mem_ctx, union drsuapi_DsWriteAccountSpnResult);
 
400
        W_ERROR_HAVE_NO_MEMORY(r->out.res);
 
401
 
 
402
        switch (r->in.level) {
 
403
                case 1: {
 
404
                        struct drsuapi_DsWriteAccountSpnRequest1 *req;
 
405
                        struct ldb_message *msg;
 
406
                        int count, i, ret;
 
407
                        req = &r->in.req->req1;
 
408
                        count = req->count;
 
409
 
 
410
                        msg = ldb_msg_new(mem_ctx);
 
411
                        if (msg == NULL) {
 
412
                                return WERR_NOMEM;
 
413
                        }
 
414
 
 
415
                        msg->dn = ldb_dn_new(msg, b_state->sam_ctx, req->object_dn);
 
416
                        if ( ! ldb_dn_validate(msg->dn)) {
 
417
                                r->out.res->res1.status = WERR_OK;
 
418
                                return WERR_OK;
 
419
                        }
 
420
                        
 
421
                        /* construct mods */
 
422
                        for (i = 0; i < count; i++) {
 
423
                                samdb_msg_add_string(b_state->sam_ctx, 
 
424
                                                     msg, msg, "servicePrincipalName",
 
425
                                                     req->spn_names[i].str);
 
426
                        }
 
427
                        for (i=0;i<msg->num_elements;i++) {
 
428
                                switch (req->operation) {
 
429
                                case DRSUAPI_DS_SPN_OPERATION_ADD:
 
430
                                        msg->elements[i].flags = LDB_FLAG_MOD_ADD;
 
431
                                        break;
 
432
                                case DRSUAPI_DS_SPN_OPERATION_REPLACE:
 
433
                                        msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
 
434
                                        break;
 
435
                                case DRSUAPI_DS_SPN_OPERATION_DELETE:
 
436
                                        msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
 
437
                                        break;
 
438
                                }
 
439
                        }
 
440
   
 
441
                        /* Apply to database */
 
442
 
 
443
                        ret = ldb_modify(b_state->sam_ctx, msg);
 
444
                        if (ret != 0) {
 
445
                                DEBUG(0,("Failed to modify SPNs on %s: %s\n",
 
446
                                         ldb_dn_get_linearized(msg->dn), 
 
447
                                         ldb_errstring(b_state->sam_ctx)));
 
448
                                r->out.res->res1.status = WERR_ACCESS_DENIED;
 
449
                        } else {
 
450
                                r->out.res->res1.status = WERR_OK;
 
451
                        }
 
452
 
 
453
                        return WERR_OK;
 
454
                }
 
455
        }
 
456
        
 
457
        return WERR_UNKNOWN_LEVEL;
 
458
}
 
459
 
 
460
 
 
461
/* 
 
462
  drsuapi_DsRemoveDSServer
 
463
*/
 
464
static WERROR dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
465
                                       struct drsuapi_DsRemoveDSServer *r)
 
466
{
 
467
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
468
}
 
469
 
 
470
 
 
471
/* 
 
472
  DRSUAPI_REMOVE_DS_DOMAIN 
 
473
*/
 
474
static WERROR dcesrv_DRSUAPI_REMOVE_DS_DOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
475
                       struct DRSUAPI_REMOVE_DS_DOMAIN *r)
 
476
{
 
477
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
478
}
 
479
 
 
480
/* Obtain the site name from a server DN */
 
481
static const char *result_site_name(struct ldb_dn *site_dn)
 
482
{
 
483
        /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
 
484
        const struct ldb_val *val = ldb_dn_get_component_val(site_dn, 2);
 
485
        const char *name = ldb_dn_get_component_name(site_dn, 2);
 
486
 
 
487
        if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
 
488
                /* Ensure this matches the format.  This gives us a
 
489
                 * bit more confidence that a 'cn' value will be a
 
490
                 * ascii string */
 
491
                return NULL;
 
492
        }
 
493
        if (val) {
 
494
                return (char *)val->data;
 
495
        }
 
496
        return NULL;
 
497
}
 
498
 
 
499
/* 
 
500
  drsuapi_DsGetDomainControllerInfo 
 
501
*/
 
502
static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_state, 
 
503
                                                TALLOC_CTX *mem_ctx,
 
504
                                                struct drsuapi_DsGetDomainControllerInfo *r)
 
505
{
 
506
        struct ldb_dn *sites_dn;
 
507
        struct ldb_result *res;
 
508
 
 
509
        const char *attrs_account_1[] = { "cn", "dnsHostName", NULL };
 
510
        const char *attrs_account_2[] = { "cn", "dnsHostName", "objectGUID", NULL };
 
511
 
 
512
        const char *attrs_none[] = { NULL };
 
513
 
 
514
        const char *attrs_site[] = { "objectGUID", NULL };
 
515
 
 
516
        const char *attrs_ntds[] = { "options", "objectGUID", NULL };
 
517
 
 
518
        const char *attrs_1[] = { "serverReference", "cn", "dnsHostName", NULL };
 
519
        const char *attrs_2[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL };
 
520
        const char **attrs;
 
521
 
 
522
        struct drsuapi_DsGetDCInfoCtr1 *ctr1;
 
523
        struct drsuapi_DsGetDCInfoCtr2 *ctr2;
 
524
 
 
525
        int ret, i;
 
526
 
 
527
        *r->out.level_out = r->in.req->req1.level;
 
528
        r->out.ctr = talloc(mem_ctx, union drsuapi_DsGetDCInfoCtr);
 
529
        W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
 
530
 
 
531
        sites_dn = samdb_sites_dn(b_state->sam_ctx, mem_ctx);
 
532
        if (!sites_dn) {
 
533
                return WERR_DS_OBJ_NOT_FOUND;
 
534
        }
 
535
 
 
536
        switch (*r->out.level_out) {
 
537
        case -1:
 
538
                /* this level is not like the others */
 
539
                return WERR_UNKNOWN_LEVEL;
 
540
        case 1:
 
541
                attrs = attrs_1;
 
542
                break;
 
543
        case 2:
 
544
                attrs = attrs_2;
 
545
                break;
 
546
        default:
 
547
                return WERR_UNKNOWN_LEVEL;
 
548
        }
 
549
 
 
550
        ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
 
551
                                 "objectClass=server");
 
552
        
 
553
        if (ret) {
 
554
                DEBUG(1, ("searching for servers in sites DN %s failed: %s\n", 
 
555
                          ldb_dn_get_linearized(sites_dn), ldb_errstring(b_state->sam_ctx)));
 
556
                return WERR_GENERAL_FAILURE;
 
557
        }
 
558
 
 
559
        switch (*r->out.level_out) {
 
560
        case 1:
 
561
                ctr1 = &r->out.ctr->ctr1;
 
562
                ctr1->count = res->count;
 
563
                ctr1->array = talloc_zero_array(mem_ctx, 
 
564
                                                struct drsuapi_DsGetDCInfo1, 
 
565
                                                res->count);
 
566
                for (i=0; i < res->count; i++) {
 
567
                        struct ldb_dn *domain_dn;
 
568
                        struct ldb_result *res_domain;
 
569
                        struct ldb_result *res_account;
 
570
                        struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
 
571
                        
 
572
                        struct ldb_dn *ref_dn
 
573
                                = ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
 
574
                                                          mem_ctx, res->msgs[i], 
 
575
                                                          "serverReference");
 
576
 
 
577
                        if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
 
578
                                return WERR_NOMEM;
 
579
                        }
 
580
 
 
581
                        ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
 
582
                                                 LDB_SCOPE_BASE, attrs_account_1, "objectClass=computer");
 
583
                        if (ret == LDB_SUCCESS && res_account->count == 1) {
 
584
                                const char *errstr;
 
585
                                ctr1->array[i].dns_name
 
586
                                        = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
 
587
                                ctr1->array[i].netbios_name
 
588
                                        = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
 
589
                                ctr1->array[i].computer_dn
 
590
                                        = ldb_dn_get_linearized(res_account->msgs[0]->dn);
 
591
 
 
592
                                /* Determine if this is the PDC */
 
593
                                ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
 
594
                                                                     mem_ctx, res_account->msgs[0]->dn,
 
595
                                                                     &domain_dn, &errstr);
 
596
                                
 
597
                                if (ret == LDB_SUCCESS) {
 
598
                                        ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
 
599
                                                                 LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
 
600
                                                                 ldb_dn_get_linearized(ntds_dn));
 
601
                                        if (ret) {
 
602
                                                return WERR_GENERAL_FAILURE;
 
603
                                        }
 
604
                                        if (res_domain->count == 1) {
 
605
                                                ctr1->array[i].is_pdc = true;
 
606
                                        }
 
607
                                }
 
608
                        }
 
609
                        if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
 
610
                                DEBUG(5, ("warning: searching for computer DN %s failed: %s\n", 
 
611
                                          ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx)));
 
612
                        }
 
613
 
 
614
                        /* Look at server DN and extract site component */
 
615
                        ctr1->array[i].site_name = result_site_name(res->msgs[i]->dn);
 
616
                        ctr1->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
 
617
 
 
618
 
 
619
                        ctr1->array[i].is_enabled = true;
 
620
 
 
621
                }
 
622
                break;
 
623
        case 2:
 
624
                ctr2 = &r->out.ctr->ctr2;
 
625
                ctr2->count = res->count;
 
626
                ctr2->array = talloc_zero_array(mem_ctx, 
 
627
                                                 struct drsuapi_DsGetDCInfo2, 
 
628
                                                 res->count);
 
629
                for (i=0; i < res->count; i++) {
 
630
                        struct ldb_dn *domain_dn;
 
631
                        struct ldb_result *res_domain;
 
632
                        struct ldb_result *res_account;
 
633
                        struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
 
634
                        struct ldb_result *res_ntds;
 
635
                        struct ldb_dn *site_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
 
636
                        struct ldb_result *res_site;
 
637
                        struct ldb_dn *ref_dn
 
638
                                = ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
 
639
                                                          mem_ctx, res->msgs[i], 
 
640
                                                          "serverReference");
 
641
 
 
642
                        if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
 
643
                                return WERR_NOMEM;
 
644
                        }
 
645
 
 
646
                        /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
 
647
                        if (!site_dn || !ldb_dn_remove_child_components(site_dn, 2)) {
 
648
                                return WERR_NOMEM;
 
649
                        }
 
650
 
 
651
                        ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
 
652
                                                 LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA");
 
653
                        if (ret == LDB_SUCCESS && res_ntds->count == 1) {
 
654
                                ctr2->array[i].is_gc
 
655
                                        = (ldb_msg_find_attr_as_int(res_ntds->msgs[0], "options", 0) == 1);
 
656
                                ctr2->array[i].ntds_guid 
 
657
                                        = samdb_result_guid(res_ntds->msgs[0], "objectGUID");
 
658
                                ctr2->array[i].ntds_dn = ldb_dn_get_linearized(res_ntds->msgs[0]->dn);
 
659
                        }
 
660
                        if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
 
661
                                DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n", 
 
662
                                          ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx)));
 
663
                        }
 
664
 
 
665
                        ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
 
666
                                                 LDB_SCOPE_BASE, attrs_site, "objectClass=site");
 
667
                        if (ret == LDB_SUCCESS && res_site->count == 1) {
 
668
                                ctr2->array[i].site_guid 
 
669
                                        = samdb_result_guid(res_site->msgs[0], "objectGUID");
 
670
                                ctr2->array[i].site_dn = ldb_dn_get_linearized(res_site->msgs[0]->dn);
 
671
                        }
 
672
                        if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
 
673
                                DEBUG(5, ("warning: searching for site DN %s failed: %s\n", 
 
674
                                          ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx)));
 
675
                        }
 
676
 
 
677
                        ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
 
678
                                                 LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
 
679
                        if (ret == LDB_SUCCESS && res_account->count == 1) {
 
680
                                const char *errstr;
 
681
                                ctr2->array[i].dns_name
 
682
                                        = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
 
683
                                ctr2->array[i].netbios_name
 
684
                                        = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
 
685
                                ctr2->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn);
 
686
                                ctr2->array[i].computer_guid 
 
687
                                        = samdb_result_guid(res_account->msgs[0], "objectGUID");
 
688
 
 
689
                                /* Determine if this is the PDC */
 
690
                                ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
 
691
                                                                     mem_ctx, res_account->msgs[0]->dn,
 
692
                                                                     &domain_dn, &errstr);
 
693
                                
 
694
                                if (ret == LDB_SUCCESS) {
 
695
                                        ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
 
696
                                                                 LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
 
697
                                                                 ldb_dn_get_linearized(ntds_dn));
 
698
                                        if (ret == LDB_SUCCESS && res_domain->count == 1) {
 
699
                                                ctr2->array[i].is_pdc = true;
 
700
                                        }
 
701
                                        if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
 
702
                                                DEBUG(5, ("warning: searching for domain DN %s failed: %s\n", 
 
703
                                                          ldb_dn_get_linearized(domain_dn), ldb_errstring(b_state->sam_ctx)));
 
704
                                        }
 
705
                                }
 
706
                        }
 
707
                        if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
 
708
                                DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n", 
 
709
                                          ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx)));
 
710
                        }
 
711
 
 
712
                        /* Look at server DN and extract site component */
 
713
                        ctr2->array[i].site_name = result_site_name(res->msgs[i]->dn);
 
714
                        ctr2->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
 
715
                        ctr2->array[i].server_guid 
 
716
                                = samdb_result_guid(res->msgs[i], "objectGUID");
 
717
 
 
718
                        ctr2->array[i].is_enabled = true;
 
719
 
 
720
                }
 
721
                break;
 
722
        }
 
723
        return WERR_OK;
 
724
}
 
725
 
 
726
/* 
 
727
  drsuapi_DsGetDomainControllerInfo 
 
728
*/
 
729
static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
730
                                                struct drsuapi_DsGetDomainControllerInfo *r)
 
731
{
 
732
        struct dcesrv_handle *h;
 
733
        struct drsuapi_bind_state *b_state;     
 
734
        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
 
735
        b_state = h->data;
 
736
 
 
737
        switch (r->in.level) {
 
738
        case 1:
 
739
                return dcesrv_drsuapi_DsGetDomainControllerInfo_1(b_state, mem_ctx, r);
 
740
        }
 
741
 
 
742
        return WERR_UNKNOWN_LEVEL;
 
743
}
 
744
 
 
745
 
 
746
/* 
 
747
  drsuapi_DsAddEntry
 
748
*/
 
749
static WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
750
                       struct drsuapi_DsAddEntry *r)
 
751
{
 
752
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
753
}
 
754
 
 
755
 
 
756
/* 
 
757
  DRSUAPI_EXECUTE_KCC 
 
758
*/
 
759
static WERROR dcesrv_DRSUAPI_EXECUTE_KCC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
760
                       struct DRSUAPI_EXECUTE_KCC *r)
 
761
{
 
762
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
763
}
 
764
 
 
765
 
 
766
/* 
 
767
  drsuapi_DsReplicaGetInfo 
 
768
*/
 
769
static WERROR dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
770
                       struct drsuapi_DsReplicaGetInfo *r)
 
771
{
 
772
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
773
}
 
774
 
 
775
 
 
776
/* 
 
777
  DRSUAPI_ADD_SID_HISTORY 
 
778
*/
 
779
static WERROR dcesrv_DRSUAPI_ADD_SID_HISTORY(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
780
                       struct DRSUAPI_ADD_SID_HISTORY *r)
 
781
{
 
782
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
783
}
 
784
 
 
785
/* 
 
786
  drsuapi_DsGetMemberships2 
 
787
*/
 
788
static WERROR dcesrv_drsuapi_DsGetMemberships2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
789
                       struct drsuapi_DsGetMemberships2 *r)
 
790
{
 
791
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
792
}
 
793
 
 
794
/* 
 
795
  DRSUAPI_REPLICA_VERIFY_OBJECTS 
 
796
*/
 
797
static WERROR dcesrv_DRSUAPI_REPLICA_VERIFY_OBJECTS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
798
                       struct DRSUAPI_REPLICA_VERIFY_OBJECTS *r)
 
799
{
 
800
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
801
}
 
802
 
 
803
 
 
804
/* 
 
805
  DRSUAPI_GET_OBJECT_EXISTENCE 
 
806
*/
 
807
static WERROR dcesrv_DRSUAPI_GET_OBJECT_EXISTENCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
808
                       struct DRSUAPI_GET_OBJECT_EXISTENCE *r)
 
809
{
 
810
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
811
}
 
812
 
 
813
 
 
814
/* 
 
815
  drsuapi_QuerySitesByCost 
 
816
*/
 
817
static WERROR dcesrv_drsuapi_QuerySitesByCost(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
818
                       struct drsuapi_QuerySitesByCost *r)
 
819
{
 
820
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
821
}
 
822
 
 
823
 
 
824
/* include the generated boilerplate */
 
825
#include "librpc/gen_ndr/ndr_drsuapi_s.c"