415e8db084e66733bc75ffaeb36a87ee00c5cc7e
[samba.git] / source4 / rpc_server / drsuapi / dcesrv_drsuapi.c
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 "dsdb/samdb/samdb.h"
28 #include "dsdb/common/util.h"
29 #include "libcli/security/security.h"
30 #include "libcli/security/session.h"
31 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
32 #include "auth/auth.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35
36 #undef DBGC_CLASS
37 #define DBGC_CLASS            DBGC_DRS_REPL
38
39 #define DRSUAPI_UNSUPPORTED(fname) do { \
40         DEBUG(1,(__location__ ": Unsupported DRS call %s\n", #fname)); \
41         if (DEBUGLVL(2)) NDR_PRINT_IN_DEBUG(fname, r); \
42         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); \
43 } while (0)
44
45 #define DCESRV_INTERFACE_DRSUAPI_BIND(call, iface) \
46         dcesrv_interface_drsuapi_bind(call, iface)
47 static NTSTATUS dcesrv_interface_drsuapi_bind(struct dcesrv_call_state *dce_call,
48                                               const struct dcesrv_interface *iface)
49 {
50         return dcesrv_interface_bind_require_privacy(dce_call, iface);
51 }
52
53 /* 
54   drsuapi_DsBind 
55 */
56 static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
57                        struct drsuapi_DsBind *r)
58 {
59         struct drsuapi_bind_state *b_state;
60         struct dcesrv_handle *handle;
61         struct drsuapi_DsBindInfoCtr *bind_info;
62         struct drsuapi_DsBindInfoCtr *local_info;
63         struct GUID site_guid, config_guid;
64         struct ldb_result *site_res, *config_res;
65         struct ldb_dn *server_site_dn, *config_dn;
66         static const char *site_attrs[] = { "objectGUID", NULL };
67         static const char *config_attrs[] = { "objectGUID", NULL };
68         struct ldb_result *ntds_res;
69         struct ldb_dn *ntds_dn;
70         static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL };
71         uint32_t pid;
72         uint32_t repl_epoch;
73         uint32_t supported_extensions;
74         uint32_t req_length;
75         int ret;
76         struct auth_session_info *auth_info;
77         WERROR werr;
78         bool connected_as_system = false;
79
80         r->out.bind_info = NULL;
81         ZERO_STRUCTP(r->out.bind_handle);
82
83         b_state = talloc_zero(mem_ctx, struct drsuapi_bind_state);
84         W_ERROR_HAVE_NO_MEMORY(b_state);
85
86         /* if this is a DC connecting, give them system level access */
87         werr = drs_security_level_check(dce_call, NULL, SECURITY_DOMAIN_CONTROLLER, NULL);
88         if (W_ERROR_IS_OK(werr)) {
89                 DEBUG(3,(__location__ ": doing DsBind with system_session\n"));
90                 auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx);
91                 connected_as_system = true;
92         } else {
93                 auth_info = dcesrv_call_session_info(dce_call);
94         }
95
96         /*
97          * connect to the samdb
98          */
99         b_state->sam_ctx = samdb_connect(
100                 b_state,
101                 dce_call->event_ctx,
102                 dce_call->conn->dce_ctx->lp_ctx,
103                 auth_info,
104                 dce_call->conn->remote_address,
105                 0);
106         if (!b_state->sam_ctx) {
107                 return WERR_FOOBAR;
108         }
109
110         if (connected_as_system) {
111                 b_state->sam_ctx_system = b_state->sam_ctx;
112         } else {
113                 /* an RODC also needs system samdb access for secret
114                    attribute replication */
115                 werr = drs_security_level_check(dce_call, NULL, SECURITY_RO_DOMAIN_CONTROLLER,
116                                                 samdb_domain_sid(b_state->sam_ctx));
117                 if (W_ERROR_IS_OK(werr)) {
118                         b_state->sam_ctx_system
119                         = samdb_connect(
120                                 b_state,
121                                 dce_call->event_ctx,
122                                 dce_call->conn->dce_ctx->lp_ctx,
123                                 system_session(dce_call->conn->dce_ctx->lp_ctx),
124                                 dce_call->conn->remote_address,
125                                 0);
126                         if (!b_state->sam_ctx_system) {
127                                 return WERR_FOOBAR;
128                         }
129                 }
130         }
131
132         /*
133          * find out the guid of our own site
134          */
135         server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx);
136         W_ERROR_HAVE_NO_MEMORY(server_site_dn);
137
138         ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res,
139                                  server_site_dn, LDB_SCOPE_BASE, site_attrs,
140                                  "(objectClass=*)");
141         if (ret != LDB_SUCCESS) {
142                 return WERR_DS_DRA_INTERNAL_ERROR;
143         }
144         if (site_res->count != 1) {
145                 return WERR_DS_DRA_INTERNAL_ERROR;
146         }
147         site_guid = samdb_result_guid(site_res->msgs[0], "objectGUID");
148
149         /*
150          * lookup the local servers Replication Epoch
151          */
152         ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx, mem_ctx);
153         W_ERROR_HAVE_NO_MEMORY(ntds_dn);
154
155         ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res,
156                                  ntds_dn, LDB_SCOPE_BASE, ntds_attrs,
157                                  "(objectClass=*)");
158         if (ret != LDB_SUCCESS) {
159                 return WERR_DS_DRA_INTERNAL_ERROR;
160         }
161         if (ntds_res->count != 1) {
162                 return WERR_DS_DRA_INTERNAL_ERROR;
163         }
164         repl_epoch = ldb_msg_find_attr_as_uint(ntds_res->msgs[0],
165                                                "ms-DS-ReplicationEpoch", 0);
166
167         /*
168          * The "process identifier" of the client.
169          * According to the WSPP docs, sectin 5.35, this is
170          * for informational and debugging purposes only.
171          * The assignment is implementation specific.
172          */
173         pid = 0;
174
175         /*
176          * store the clients bind_guid
177          */
178         if (r->in.bind_guid) {
179                 b_state->remote_bind_guid = *r->in.bind_guid;
180         }
181
182         /*
183          * store the clients bind_info
184          */
185         if (r->in.bind_info) {
186                 b_state->remote_info = r->in.bind_info;
187         }
188
189         /*
190          * fill in our local bind info
191          */
192         local_info = talloc_zero(mem_ctx, struct drsuapi_DsBindInfoCtr);
193         W_ERROR_HAVE_NO_MEMORY(local_info);
194
195         /*
196          * Fill in supported extensions
197          */
198         supported_extensions = 0;
199         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
200         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
201         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
202         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
203 #if 0 /* we don't support MSZIP compression (only decompression) */
204         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
205 #endif
206         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
207         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
208         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
209         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
210         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
211         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
212         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
213         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
214         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
215         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
216         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
217         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
218         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
219         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
220         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5;
221         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
222         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
223         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
224         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
225         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
226         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
227         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
228         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
229         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
230 #if 0 /* we don't support XPRESS compression yet */
231         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
232 #endif
233         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10;
234
235         /*
236          * There is a chance for r->in.bind_info == NULL
237          * Currently we don't care, since it seems to be used nowhere else.
238          * But we need a request length. So use 28 as default.
239          */
240         req_length = 28;
241         if (r->in.bind_info) {
242                 req_length = r->in.bind_info->length;
243         }
244
245         /*
246          * fill 28 or 48 info, depends on request
247          */
248         if (req_length < 48) {
249                 local_info->length = 28;
250                 local_info->info.info28.supported_extensions = supported_extensions;
251                 local_info->info.info28.site_guid = site_guid;
252                 local_info->info.info28.pid = pid;
253                 local_info->info.info28.repl_epoch = repl_epoch;
254         } else {
255                 local_info->length = 48;
256                 local_info->info.info48.supported_extensions = supported_extensions;
257                 local_info->info.info48.site_guid = site_guid;
258                 local_info->info.info48.pid = pid;
259                 local_info->info.info48.repl_epoch = repl_epoch;
260
261                 local_info->info.info48.supported_extensions_ext = 0;
262                 local_info->info.info48.supported_extensions_ext |= DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2;
263
264                 /*
265                  * find out the guid of our own site
266                  */
267                 config_dn = ldb_get_config_basedn(b_state->sam_ctx);
268                 W_ERROR_HAVE_NO_MEMORY(config_dn);
269
270                 ret = ldb_search(b_state->sam_ctx, mem_ctx, &config_res,
271                              config_dn, LDB_SCOPE_BASE, config_attrs,
272                              "(objectClass=*)");
273                 if (ret != LDB_SUCCESS) {
274                         return WERR_DS_DRA_INTERNAL_ERROR;
275                 }
276                 if (config_res->count != 1) {
277                         return WERR_DS_DRA_INTERNAL_ERROR;
278                 }
279                 config_guid = samdb_result_guid(config_res->msgs[0], "objectGUID");
280                 local_info->info.info48.config_dn_guid = config_guid;
281         }
282
283         /*
284          * set local_info
285          */
286         b_state->local_info = local_info;
287
288         /*
289          * set bind_info
290          */
291         bind_info = local_info;
292
293         /*
294          * allocate a bind handle
295          */
296         handle = dcesrv_handle_create(dce_call, DRSUAPI_BIND_HANDLE);
297         W_ERROR_HAVE_NO_MEMORY(handle);
298         handle->data = talloc_steal(handle, b_state);
299
300         /*
301          * prepare reply
302          */
303         r->out.bind_info = bind_info;
304         *r->out.bind_handle = handle->wire_handle;
305
306         return WERR_OK;
307 }
308
309
310 /* 
311   drsuapi_DsUnbind 
312 */
313 static WERROR dcesrv_drsuapi_DsUnbind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
314                                struct drsuapi_DsUnbind *r)
315 {
316         struct dcesrv_handle *h;
317
318         *r->out.bind_handle = *r->in.bind_handle;
319
320         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
321
322         talloc_free(h);
323
324         ZERO_STRUCTP(r->out.bind_handle);
325
326         return WERR_OK;
327 }
328
329
330 /* 
331   drsuapi_DsReplicaSync 
332 */
333 static WERROR dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
334                                            struct drsuapi_DsReplicaSync *r)
335 {
336         WERROR status;
337         uint32_t timeout;
338
339         status = drs_security_level_check(dce_call, "DsReplicaSync", SECURITY_DOMAIN_CONTROLLER, NULL);
340         if (!W_ERROR_IS_OK(status)) {
341                 return status;
342         }
343
344         if (r->in.level != 1) {
345                 DEBUG(0,("DsReplicaSync called with unsupported level %d\n", r->in.level));
346                 return WERR_DS_DRA_INVALID_PARAMETER;
347         }
348
349         if (r->in.req->req1.options & DRSUAPI_DRS_ASYNC_OP) {
350                 timeout = IRPC_CALL_TIMEOUT;
351         } else {
352                 /*
353                  * use Infinite time for timeout in case
354                  * the caller made a sync call
355                  */
356                 timeout = IRPC_CALL_TIMEOUT_INF;
357         }
358
359         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
360                                      r, NDR_DRSUAPI_DSREPLICASYNC,
361                                      &ndr_table_drsuapi,
362                                      "dreplsrv", "DsReplicaSync",
363                                      timeout);
364
365         return WERR_OK;
366 }
367
368
369 /* 
370   drsuapi_DsReplicaAdd 
371 */
372 static WERROR dcesrv_drsuapi_DsReplicaAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
373                                           struct drsuapi_DsReplicaAdd *r)
374 {
375         WERROR status;
376
377         status = drs_security_level_check(dce_call, "DsReplicaAdd", SECURITY_DOMAIN_CONTROLLER, NULL);
378         if (!W_ERROR_IS_OK(status)) {
379                 return status;
380         }
381
382         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
383                                      r, NDR_DRSUAPI_DSREPLICAADD,
384                                      &ndr_table_drsuapi,
385                                      "dreplsrv", "DsReplicaAdd",
386                                      IRPC_CALL_TIMEOUT);
387
388         return WERR_OK;
389 }
390
391
392 /* 
393   drsuapi_DsReplicaDel 
394 */
395 static WERROR dcesrv_drsuapi_DsReplicaDel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
396                                           struct drsuapi_DsReplicaDel *r)
397 {
398         WERROR status;
399
400         status = drs_security_level_check(dce_call, "DsReplicaDel", SECURITY_DOMAIN_CONTROLLER, NULL);
401         if (!W_ERROR_IS_OK(status)) {
402                 return status;
403         }
404
405         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
406                                      r, NDR_DRSUAPI_DSREPLICADEL,
407                                      &ndr_table_drsuapi,
408                                      "dreplsrv", "DsReplicaDel",
409                                      IRPC_CALL_TIMEOUT);
410
411         return WERR_OK;
412 }
413
414
415 /* 
416   drsuapi_DsReplicaModify 
417 */
418 static WERROR dcesrv_drsuapi_DsReplicaMod(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
419                                           struct drsuapi_DsReplicaMod *r)
420 {
421         WERROR status;
422
423         status = drs_security_level_check(dce_call, "DsReplicaMod", SECURITY_DOMAIN_CONTROLLER, NULL);
424         if (!W_ERROR_IS_OK(status)) {
425                 return status;
426         }
427
428         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
429                                      r, NDR_DRSUAPI_DSREPLICAMOD,
430                                      &ndr_table_drsuapi,
431                                      "dreplsrv", "DsReplicaMod",
432                                      IRPC_CALL_TIMEOUT);
433
434         return WERR_OK;
435 }
436
437
438 /* 
439   DRSUAPI_VERIFY_NAMES 
440 */
441 static WERROR dcesrv_DRSUAPI_VERIFY_NAMES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
442                        struct DRSUAPI_VERIFY_NAMES *r)
443 {
444         DRSUAPI_UNSUPPORTED(DRSUAPI_VERIFY_NAMES);
445 }
446
447
448 /* 
449   drsuapi_DsGetMemberships 
450 */
451 static WERROR dcesrv_drsuapi_DsGetMemberships(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
452                        struct drsuapi_DsGetMemberships *r)
453 {
454         DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships);
455 }
456
457
458 /* 
459   DRSUAPI_INTER_DOMAIN_MOVE 
460 */
461 static WERROR dcesrv_DRSUAPI_INTER_DOMAIN_MOVE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
462                        struct DRSUAPI_INTER_DOMAIN_MOVE *r)
463 {
464         DRSUAPI_UNSUPPORTED(DRSUAPI_INTER_DOMAIN_MOVE);
465 }
466
467
468 /* 
469   drsuapi_DsGetNT4ChangeLog 
470 */
471 static WERROR dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
472                        struct drsuapi_DsGetNT4ChangeLog *r)
473 {
474         DRSUAPI_UNSUPPORTED(drsuapi_DsGetNT4ChangeLog);
475 }
476
477 /* 
478   drsuapi_DsCrackNames 
479 */
480 static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
481                             struct drsuapi_DsCrackNames *r)
482 {
483         struct drsuapi_bind_state *b_state;
484         struct dcesrv_handle *h;
485
486         *r->out.level_out = r->in.level;
487
488         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
489         b_state = h->data;
490
491         r->out.ctr = talloc_zero(mem_ctx, union drsuapi_DsNameCtr);
492         W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
493
494         switch (r->in.level) {
495                 case 1: {
496                         switch(r->in.req->req1.format_offered){
497                         case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX:
498                         case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN:
499                         case DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME:
500                         case DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME:
501                         case DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID:
502                         case DRSUAPI_DS_NAME_FORMAT_LIST_NCS:
503                         case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS:
504                         case DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS:
505                         case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE:
506                         case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE:
507                         case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE:
508                         case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE:
509                         case DRSUAPI_DS_NAME_FORMAT_LIST_SITES:
510                         case DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID:
511                         case DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON:
512                                 DEBUG(0, ("DsCrackNames: Unsupported operation requested: %X",
513                                           r->in.req->req1.format_offered));
514                                 return WERR_OK;
515                         case DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER:
516                                 return dcesrv_drsuapi_ListInfoServer(b_state->sam_ctx, mem_ctx, &r->in.req->req1, &r->out.ctr->ctr1);
517                         case DRSUAPI_DS_NAME_FORMAT_LIST_ROLES:
518                                 return dcesrv_drsuapi_ListRoles(b_state->sam_ctx, mem_ctx,
519                                                                 &r->in.req->req1, &r->out.ctr->ctr1);
520                         default:/* format_offered is in the enum drsuapi_DsNameFormat*/
521                                 return dcesrv_drsuapi_CrackNamesByNameFormat(b_state->sam_ctx, mem_ctx,
522                                                                              &r->in.req->req1, &r->out.ctr->ctr1);
523                         }
524                 }
525         }
526         return WERR_INVALID_LEVEL;
527 }
528
529
530 /* 
531   drsuapi_DsRemoveDSServer
532 */
533 static WERROR dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
534                                        struct drsuapi_DsRemoveDSServer *r)
535 {
536         struct drsuapi_bind_state *b_state;
537         struct dcesrv_handle *h;
538         struct ldb_dn *ntds_dn;
539         int ret;
540         bool ok;
541         WERROR status;
542
543         *r->out.level_out = 1;
544
545         status = drs_security_level_check(dce_call, "DsRemoveDSServer", SECURITY_DOMAIN_CONTROLLER, NULL);
546         if (!W_ERROR_IS_OK(status)) {
547                 return status;
548         }
549
550         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
551         b_state = h->data;
552
553         switch (r->in.level) {
554         case 1:
555                 ntds_dn = ldb_dn_new(mem_ctx, b_state->sam_ctx, r->in.req->req1.server_dn);
556                 W_ERROR_HAVE_NO_MEMORY(ntds_dn);
557
558                 ok = ldb_dn_validate(ntds_dn);
559                 if (!ok) {
560                         return WERR_FOOBAR;
561                 }
562
563                 /* TODO: it's likely that we need more checks here */
564
565                 ok = ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings");
566                 if (!ok) {
567                         return WERR_FOOBAR;
568                 }
569
570                 if (r->in.req->req1.commit) {
571                         ret = dsdb_delete(b_state->sam_ctx, ntds_dn, DSDB_TREE_DELETE);
572                         if (ret != LDB_SUCCESS) {
573                                 return WERR_FOOBAR;
574                         }
575                 }
576
577                 return WERR_OK;
578         default:
579                 break;
580         }
581
582         return WERR_FOOBAR;
583 }
584
585
586 /* 
587   DRSUAPI_REMOVE_DS_DOMAIN 
588 */
589 static WERROR dcesrv_DRSUAPI_REMOVE_DS_DOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
590                        struct DRSUAPI_REMOVE_DS_DOMAIN *r)
591 {
592         DRSUAPI_UNSUPPORTED(DRSUAPI_REMOVE_DS_DOMAIN);
593 }
594
595 /* Obtain the site name from a server DN */
596 static const char *result_site_name(struct ldb_dn *server_dn)
597 {
598         /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
599         const struct ldb_val *val = ldb_dn_get_component_val(server_dn, 2);
600         const char *name = ldb_dn_get_component_name(server_dn, 2);
601
602         if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
603                 /* Ensure this matches the format.  This gives us a
604                  * bit more confidence that a 'cn' value will be a
605                  * ascii string */
606                 return NULL;
607         }
608         if (val) {
609                 return (char *)val->data;
610         }
611         return NULL;
612 }
613
614 /* 
615   drsuapi_DsGetDomainControllerInfo 
616 */
617 static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_state, 
618                                                 TALLOC_CTX *mem_ctx,
619                                                 struct drsuapi_DsGetDomainControllerInfo *r)
620 {
621         struct ldb_dn *sites_dn;
622         struct ldb_result *res;
623
624         const char *attrs_account_1[] = { "cn", "dnsHostName", NULL };
625         const char *attrs_account_2[] = { "cn", "dnsHostName", "objectGUID", NULL };
626
627         const char *attrs_none[] = { NULL };
628
629         const char *attrs_site[] = { "objectGUID", NULL };
630
631         const char *attrs_ntds[] = { "options", "objectGUID", NULL };
632
633         const char *attrs_1[] = { "serverReference", "cn", "dnsHostName", NULL };
634         const char *attrs_2[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL };
635         const char **attrs;
636
637         struct drsuapi_DsGetDCInfoCtr1 *ctr1;
638         struct drsuapi_DsGetDCInfoCtr2 *ctr2;
639         struct drsuapi_DsGetDCInfoCtr3 *ctr3;
640
641         int ret;
642         unsigned int i;
643
644         *r->out.level_out = r->in.req->req1.level;
645         r->out.ctr = talloc_zero(mem_ctx, union drsuapi_DsGetDCInfoCtr);
646         W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
647
648         switch (*r->out.level_out) {
649         case -1:
650                 /* this level is not like the others */
651                 return WERR_INVALID_LEVEL;
652         case 1:
653                 attrs = attrs_1;
654                 break;
655         case 2:
656         case 3:
657                 attrs = attrs_2;
658                 break;
659         default:
660                 return WERR_INVALID_LEVEL;
661         }
662
663         sites_dn = samdb_sites_dn(b_state->sam_ctx, mem_ctx);
664         if (!sites_dn) {
665                 return WERR_DS_OBJ_NOT_FOUND;
666         }
667
668         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
669                                  "(&(objectClass=server)(serverReference=*))");
670         
671         if (ret) {
672                 DEBUG(1, ("searching for servers in sites DN %s failed: %s\n", 
673                           ldb_dn_get_linearized(sites_dn), ldb_errstring(b_state->sam_ctx)));
674                 return WERR_GEN_FAILURE;
675         }
676
677         switch (*r->out.level_out) {
678         case 1:
679                 ctr1 = &r->out.ctr->ctr1;
680                 ctr1->count = res->count;
681                 ctr1->array = talloc_zero_array(mem_ctx, 
682                                                 struct drsuapi_DsGetDCInfo1, 
683                                                 res->count);
684                 for (i=0; i < res->count; i++) {
685                         struct ldb_dn *domain_dn;
686                         struct ldb_result *res_domain;
687                         struct ldb_result *res_account;
688                         struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
689                         
690                         struct ldb_dn *ref_dn
691                                 = ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
692                                                           mem_ctx, res->msgs[i], 
693                                                           "serverReference");
694
695                         if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
696                                 return WERR_NOT_ENOUGH_MEMORY;
697                         }
698
699                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
700                                                  LDB_SCOPE_BASE, attrs_account_1,
701                                                 "(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
702                                                 UF_SERVER_TRUST_ACCOUNT);
703                         if (ret == LDB_SUCCESS && res_account->count == 1) {
704                                 const char *errstr;
705                                 ctr1->array[i].dns_name
706                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
707                                 ctr1->array[i].netbios_name
708                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
709                                 ctr1->array[i].computer_dn
710                                         = ldb_dn_get_linearized(res_account->msgs[0]->dn);
711
712                                 /* Determine if this is the PDC */
713                                 ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
714                                                                      mem_ctx, res_account->msgs[0]->dn,
715                                                                      &domain_dn, &errstr);
716                                 
717                                 if (ret == LDB_SUCCESS) {
718                                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
719                                                                  LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
720                                                                  ldb_dn_get_linearized(ntds_dn));
721                                         if (ret) {
722                                                 return WERR_GEN_FAILURE;
723                                         }
724                                         if (res_domain->count == 1) {
725                                                 ctr1->array[i].is_pdc = true;
726                                         }
727                                 }
728                         }
729                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
730                                 DEBUG(5, ("warning: searching for computer DN %s failed: %s\n", 
731                                           ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx)));
732                         }
733
734                         /* Look at server DN and extract site component */
735                         ctr1->array[i].site_name = result_site_name(res->msgs[i]->dn);
736                         ctr1->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
737
738
739                         ctr1->array[i].is_enabled = true;
740
741                 }
742                 break;
743         case 2:
744                 ctr2 = &r->out.ctr->ctr2;
745                 ctr2->count = res->count;
746                 ctr2->array = talloc_zero_array(mem_ctx, 
747                                                  struct drsuapi_DsGetDCInfo2, 
748                                                  res->count);
749                 for (i=0; i < res->count; i++) {
750                         struct ldb_dn *domain_dn;
751                         struct ldb_result *res_domain;
752                         struct ldb_result *res_account;
753                         struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
754                         struct ldb_result *res_ntds;
755                         struct ldb_dn *site_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
756                         struct ldb_result *res_site;
757                         struct ldb_dn *ref_dn
758                                 = ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
759                                                           mem_ctx, res->msgs[i], 
760                                                           "serverReference");
761
762                         if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
763                                 return WERR_NOT_ENOUGH_MEMORY;
764                         }
765
766                         /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
767                         if (!site_dn || !ldb_dn_remove_child_components(site_dn, 2)) {
768                                 return WERR_NOT_ENOUGH_MEMORY;
769                         }
770
771                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
772                                                  LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA");
773                         if (ret == LDB_SUCCESS && res_ntds->count == 1) {
774                                 ctr2->array[i].is_gc
775                                         = (ldb_msg_find_attr_as_uint(res_ntds->msgs[0], "options", 0) & DS_NTDSDSA_OPT_IS_GC);
776                                 ctr2->array[i].ntds_guid 
777                                         = samdb_result_guid(res_ntds->msgs[0], "objectGUID");
778                                 ctr2->array[i].ntds_dn = ldb_dn_get_linearized(res_ntds->msgs[0]->dn);
779                         }
780                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
781                                 DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n", 
782                                           ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx)));
783                         }
784
785                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
786                                                  LDB_SCOPE_BASE, attrs_site, "objectClass=site");
787                         if (ret == LDB_SUCCESS && res_site->count == 1) {
788                                 ctr2->array[i].site_guid 
789                                         = samdb_result_guid(res_site->msgs[0], "objectGUID");
790                                 ctr2->array[i].site_dn = ldb_dn_get_linearized(res_site->msgs[0]->dn);
791                         }
792                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
793                                 DEBUG(5, ("warning: searching for site DN %s failed: %s\n", 
794                                           ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx)));
795                         }
796
797                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
798                                                  LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
799                         if (ret == LDB_SUCCESS && res_account->count == 1) {
800                                 const char *errstr;
801                                 ctr2->array[i].dns_name
802                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
803                                 ctr2->array[i].netbios_name
804                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
805                                 ctr2->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn);
806                                 ctr2->array[i].computer_guid 
807                                         = samdb_result_guid(res_account->msgs[0], "objectGUID");
808
809                                 /* Determine if this is the PDC */
810                                 ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
811                                                                      mem_ctx, res_account->msgs[0]->dn,
812                                                                      &domain_dn, &errstr);
813                                 
814                                 if (ret == LDB_SUCCESS) {
815                                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
816                                                                  LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
817                                                                  ldb_dn_get_linearized(ntds_dn));
818                                         if (ret == LDB_SUCCESS && res_domain->count == 1) {
819                                                 ctr2->array[i].is_pdc = true;
820                                         }
821                                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
822                                                 DEBUG(5, ("warning: searching for domain DN %s failed: %s\n", 
823                                                           ldb_dn_get_linearized(domain_dn), ldb_errstring(b_state->sam_ctx)));
824                                         }
825                                 }
826                         }
827                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
828                                 DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n", 
829                                           ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx)));
830                         }
831
832                         /* Look at server DN and extract site component */
833                         ctr2->array[i].site_name = result_site_name(res->msgs[i]->dn);
834                         ctr2->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
835                         ctr2->array[i].server_guid 
836                                 = samdb_result_guid(res->msgs[i], "objectGUID");
837
838                         ctr2->array[i].is_enabled = true;
839
840                 }
841                 break;
842         case 3:
843                 ctr3 = &r->out.ctr->ctr3;
844                 ctr3->count = res->count;
845                 ctr3->array = talloc_zero_array(mem_ctx,
846                                                  struct drsuapi_DsGetDCInfo3,
847                                                  res->count);
848                 for (i=0; i<res->count; i++) {
849                         struct ldb_dn *domain_dn;
850                         struct ldb_result *res_domain;
851                         struct ldb_result *res_account;
852                         struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
853                         struct ldb_result *res_ntds;
854                         struct ldb_dn *site_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
855                         struct ldb_result *res_site;
856                         bool is_rodc;
857                         struct ldb_dn *ref_dn
858                                 = ldb_msg_find_attr_as_dn(b_state->sam_ctx,
859                                                           mem_ctx, res->msgs[i],
860                                                           "serverReference");
861
862                         if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
863                                 return WERR_NOT_ENOUGH_MEMORY;
864                         }
865
866                         /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
867                         if (!site_dn || !ldb_dn_remove_child_components(site_dn, 2)) {
868                                 return WERR_NOT_ENOUGH_MEMORY;
869                         }
870
871                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
872                                                  LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA");
873                         if (ret == LDB_SUCCESS && res_ntds->count == 1) {
874                                 ctr3->array[i].is_gc
875                                         = (ldb_msg_find_attr_as_uint(res_ntds->msgs[0], "options", 0) & DS_NTDSDSA_OPT_IS_GC);
876                                 ctr3->array[i].ntds_guid
877                                         = samdb_result_guid(res_ntds->msgs[0], "objectGUID");
878                                 ctr3->array[i].ntds_dn = ldb_dn_get_linearized(res_ntds->msgs[0]->dn);
879                         }
880                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
881                                 DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n",
882                                           ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx)));
883                         }
884
885                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
886                                                  LDB_SCOPE_BASE, attrs_site, "objectClass=site");
887                         if (ret == LDB_SUCCESS && res_site->count == 1) {
888                                 ctr3->array[i].site_guid
889                                         = samdb_result_guid(res_site->msgs[0], "objectGUID");
890                                 ctr3->array[i].site_dn = ldb_dn_get_linearized(res_site->msgs[0]->dn);
891                         }
892                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
893                                 DEBUG(5, ("warning: searching for site DN %s failed: %s\n",
894                                           ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx)));
895                         }
896
897                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
898                                                  LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
899                         if (ret == LDB_SUCCESS && res_account->count == 1) {
900                                 const char *errstr;
901                                 ctr3->array[i].dns_name
902                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
903                                 ctr3->array[i].netbios_name
904                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
905                                 ctr3->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn);
906                                 ctr3->array[i].computer_guid
907                                         = samdb_result_guid(res_account->msgs[0], "objectGUID");
908
909                                 /* Determine if this is the PDC */
910                                 ret = samdb_search_for_parent_domain(b_state->sam_ctx,
911                                                                      mem_ctx, res_account->msgs[0]->dn,
912                                                                      &domain_dn, &errstr);
913
914                                 if (ret == LDB_SUCCESS) {
915                                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
916                                                                  LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
917                                                                  ldb_dn_get_linearized(ntds_dn));
918                                         if (ret == LDB_SUCCESS && res_domain->count == 1) {
919                                                 ctr3->array[i].is_pdc = true;
920                                         }
921                                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
922                                                 DEBUG(5, ("warning: searching for domain DN %s failed: %s\n",
923                                                           ldb_dn_get_linearized(domain_dn), ldb_errstring(b_state->sam_ctx)));
924                                         }
925                                 }
926                         }
927                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
928                                 DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n",
929                                           ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx)));
930                         }
931
932                         /* Look at server DN and extract site component */
933                         ctr3->array[i].site_name = result_site_name(res->msgs[i]->dn);
934                         ctr3->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
935                         ctr3->array[i].server_guid
936                                 = samdb_result_guid(res->msgs[i], "objectGUID");
937
938                         ctr3->array[i].is_enabled = true;
939
940                         /* rodc? */
941                         ret = samdb_is_rodc(b_state->sam_ctx, &ctr3->array[i].server_guid, &is_rodc);
942                         if (ret == LDB_SUCCESS && is_rodc) {
943                                 ctr3->array[i].is_rodc = true;
944                         }
945                 }
946                 break;
947         default:
948                 return WERR_INVALID_LEVEL;
949         }
950         return WERR_OK;
951 }
952
953 /* 
954   drsuapi_DsGetDomainControllerInfo 
955 */
956 static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
957                                                 struct drsuapi_DsGetDomainControllerInfo *r)
958 {
959         struct dcesrv_handle *h;
960         struct drsuapi_bind_state *b_state;     
961         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
962         b_state = h->data;
963
964         switch (r->in.level) {
965         case 1:
966                 return dcesrv_drsuapi_DsGetDomainControllerInfo_1(b_state, mem_ctx, r);
967         }
968
969         return WERR_INVALID_LEVEL;
970 }
971
972
973
974 /* 
975   drsuapi_DsExecuteKCC 
976 */
977 static WERROR dcesrv_drsuapi_DsExecuteKCC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
978                                   struct drsuapi_DsExecuteKCC *r)
979 {
980         WERROR status;
981         uint32_t timeout;
982         status = drs_security_level_check(dce_call, "DsExecuteKCC", SECURITY_DOMAIN_CONTROLLER, NULL);
983
984         if (!W_ERROR_IS_OK(status)) {
985                 return status;
986         }
987         if (r->in.req->ctr1.taskID != 0) {
988                 return WERR_INVALID_PARAMETER;
989         }
990         if (r->in.req->ctr1.flags & DRSUAPI_DS_EXECUTE_KCC_ASYNCHRONOUS_OPERATION) {
991                 timeout = IRPC_CALL_TIMEOUT;
992         } else {
993                 /*
994                  * use Infinite time for timeout in case
995                  * the caller made a sync call
996                  */
997                 timeout = IRPC_CALL_TIMEOUT_INF;
998         }
999
1000         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSEXECUTEKCC,
1001                                      &ndr_table_drsuapi, "kccsrv", "DsExecuteKCC",
1002                                      timeout);
1003         DEBUG(10, ("Forwarded the call to execute the KCC\n"));
1004         return WERR_OK;
1005 }
1006
1007
1008 /* 
1009   drsuapi_DsReplicaGetInfo 
1010 */
1011 static WERROR dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1012                        struct drsuapi_DsReplicaGetInfo *r)
1013 {
1014         struct auth_session_info *session_info =
1015                 dcesrv_call_session_info(dce_call);
1016         enum security_user_level level;
1017
1018         if (!lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL,
1019                          "drs", "disable_sec_check", false)) {
1020                 level = security_session_user_level(session_info, NULL);
1021                 if (level < SECURITY_DOMAIN_CONTROLLER) {
1022                         DEBUG(1,(__location__ ": Administrator access required for DsReplicaGetInfo\n"));
1023                         security_token_debug(DBGC_DRS_REPL, 2,
1024                                              session_info->security_token);
1025                         return WERR_DS_DRA_ACCESS_DENIED;
1026                 }
1027         }
1028
1029         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICAGETINFO,
1030                                      &ndr_table_drsuapi, "kccsrv", "DsReplicaGetInfo",
1031                                      IRPC_CALL_TIMEOUT);
1032
1033         return WERR_OK;
1034 }
1035
1036
1037 /* 
1038   DRSUAPI_ADD_SID_HISTORY 
1039 */
1040 static WERROR dcesrv_DRSUAPI_ADD_SID_HISTORY(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1041                        struct DRSUAPI_ADD_SID_HISTORY *r)
1042 {
1043         DRSUAPI_UNSUPPORTED(DRSUAPI_ADD_SID_HISTORY);
1044 }
1045
1046 /* 
1047   drsuapi_DsGetMemberships2 
1048 */
1049 static WERROR dcesrv_drsuapi_DsGetMemberships2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1050                        struct drsuapi_DsGetMemberships2 *r)
1051 {
1052         DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships2);
1053 }
1054
1055 /* 
1056   DRSUAPI_REPLICA_VERIFY_OBJECTS 
1057 */
1058 static WERROR dcesrv_DRSUAPI_REPLICA_VERIFY_OBJECTS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1059                        struct DRSUAPI_REPLICA_VERIFY_OBJECTS *r)
1060 {
1061         DRSUAPI_UNSUPPORTED(DRSUAPI_REPLICA_VERIFY_OBJECTS);
1062 }
1063
1064
1065 /* 
1066   DRSUAPI_GET_OBJECT_EXISTENCE 
1067 */
1068 static WERROR dcesrv_DRSUAPI_GET_OBJECT_EXISTENCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1069                        struct DRSUAPI_GET_OBJECT_EXISTENCE *r)
1070 {
1071         DRSUAPI_UNSUPPORTED(DRSUAPI_GET_OBJECT_EXISTENCE);
1072 }
1073
1074
1075 /* 
1076   drsuapi_QuerySitesByCost 
1077 */
1078 static WERROR dcesrv_drsuapi_QuerySitesByCost(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1079                        struct drsuapi_QuerySitesByCost *r)
1080 {
1081         DRSUAPI_UNSUPPORTED(drsuapi_QuerySitesByCost);
1082 }
1083
1084
1085 /* include the generated boilerplate */
1086 #include "librpc/gen_ndr/ndr_drsuapi_s.c"