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