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