2 Unix SMB/CIFS implementation.
4 endpoint server for the drsuapi pipe
6 Copyright (C) Stefan Metzmacher 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
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.
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.
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/>.
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 #include "auth/auth.h"
31 #include "param/param.h"
32 #include "lib/messaging/irpc.h"
34 #define DRSUAPI_UNSUPPORTED(fname) do { \
35 DEBUG(1,(__location__ ": Unsupported DRS call %s\n", #fname)); \
36 if (DEBUGLVL(2)) NDR_PRINT_IN_DEBUG(fname, r); \
37 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); \
43 static WERROR
dcesrv_drsuapi_DsBind(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
44 struct drsuapi_DsBind
*r
)
46 struct drsuapi_bind_state
*b_state
;
47 struct dcesrv_handle
*handle
;
48 struct drsuapi_DsBindInfoCtr
*bind_info
;
49 struct GUID site_guid
;
50 struct ldb_result
*site_res
;
51 struct ldb_dn
*server_site_dn
;
52 static const char *site_attrs
[] = { "objectGUID", NULL
};
53 struct ldb_result
*ntds_res
;
54 struct ldb_dn
*ntds_dn
;
55 static const char *ntds_attrs
[] = { "ms-DS-ReplicationEpoch", NULL
};
59 struct auth_session_info
*auth_info
;
61 bool connected_as_system
= false;
63 r
->out
.bind_info
= NULL
;
64 ZERO_STRUCTP(r
->out
.bind_handle
);
66 b_state
= talloc_zero(mem_ctx
, struct drsuapi_bind_state
);
67 W_ERROR_HAVE_NO_MEMORY(b_state
);
69 /* if this is a DC connecting, give them system level access */
70 werr
= drs_security_level_check(dce_call
, NULL
, SECURITY_DOMAIN_CONTROLLER
, NULL
);
71 if (W_ERROR_IS_OK(werr
)) {
72 DEBUG(3,(__location__
": doing DsBind with system_session\n"));
73 auth_info
= system_session(dce_call
->conn
->dce_ctx
->lp_ctx
);
74 connected_as_system
= true;
76 auth_info
= dce_call
->conn
->auth_state
.session_info
;
80 * connect to the samdb
82 b_state
->sam_ctx
= samdb_connect(b_state
, dce_call
->event_ctx
,
83 dce_call
->conn
->dce_ctx
->lp_ctx
, auth_info
);
84 if (!b_state
->sam_ctx
) {
88 if (connected_as_system
) {
89 b_state
->sam_ctx_system
= b_state
->sam_ctx
;
91 /* an RODC also needs system samdb access for secret
92 attribute replication */
93 werr
= drs_security_level_check(dce_call
, NULL
, SECURITY_RO_DOMAIN_CONTROLLER
,
94 samdb_domain_sid(b_state
->sam_ctx
));
95 if (W_ERROR_IS_OK(werr
)) {
96 b_state
->sam_ctx_system
= samdb_connect(b_state
, dce_call
->event_ctx
,
97 dce_call
->conn
->dce_ctx
->lp_ctx
,
98 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
));
99 if (!b_state
->sam_ctx_system
) {
106 * find out the guid of our own site
108 server_site_dn
= samdb_server_site_dn(b_state
->sam_ctx
, mem_ctx
);
109 W_ERROR_HAVE_NO_MEMORY(server_site_dn
);
111 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &site_res
,
112 server_site_dn
, LDB_SCOPE_BASE
, site_attrs
,
114 if (ret
!= LDB_SUCCESS
) {
115 return WERR_DS_DRA_INTERNAL_ERROR
;
117 if (site_res
->count
!= 1) {
118 return WERR_DS_DRA_INTERNAL_ERROR
;
120 site_guid
= samdb_result_guid(site_res
->msgs
[0], "objectGUID");
123 * lookup the local servers Replication Epoch
125 ntds_dn
= samdb_ntds_settings_dn(b_state
->sam_ctx
);
126 W_ERROR_HAVE_NO_MEMORY(ntds_dn
);
128 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &ntds_res
,
129 ntds_dn
, LDB_SCOPE_BASE
, ntds_attrs
,
131 if (ret
!= LDB_SUCCESS
) {
132 return WERR_DS_DRA_INTERNAL_ERROR
;
134 if (ntds_res
->count
!= 1) {
135 return WERR_DS_DRA_INTERNAL_ERROR
;
137 repl_epoch
= samdb_result_uint(ntds_res
->msgs
[0], "ms-DS-ReplicationEpoch", 0);
140 * The "process identifier" of the client.
141 * According to the WSPP docs, sectin 5.35, this is
142 * for informational and debugging purposes only.
143 * The assignment is implementation specific.
148 * store the clients bind_guid
150 if (r
->in
.bind_guid
) {
151 b_state
->remote_bind_guid
= *r
->in
.bind_guid
;
155 * store the clients bind_info
157 if (r
->in
.bind_info
) {
158 switch (r
->in
.bind_info
->length
) {
160 struct drsuapi_DsBindInfo24
*info24
;
161 info24
= &r
->in
.bind_info
->info
.info24
;
162 b_state
->remote_info28
.supported_extensions
= info24
->supported_extensions
;
163 b_state
->remote_info28
.site_guid
= info24
->site_guid
;
164 b_state
->remote_info28
.pid
= info24
->pid
;
165 b_state
->remote_info28
.repl_epoch
= 0;
169 b_state
->remote_info28
= r
->in
.bind_info
->info
.info28
;
175 * fill in our local bind info 28
177 b_state
->local_info28
.supported_extensions
= 0;
178 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_BASE
;
179 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION
;
180 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI
;
181 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2
;
182 #if 0 /* we don't support MSZIP compression (only decompression) */
183 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS
;
185 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1
;
186 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION
;
187 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE
;
188 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2
;
189 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION
;
190 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2
;
191 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD
;
192 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND
;
193 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO
;
194 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION
;
195 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01
;
196 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP
;
197 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY
;
198 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
;
199 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5
;
200 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2
;
201 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6
;
202 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS
;
203 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8
;
204 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5
;
205 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6
;
206 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3
;
207 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7
;
208 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT
;
209 #if 0 /* we don't support XPRESS compression yet */
210 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS
;
212 b_state
->local_info28
.site_guid
= site_guid
;
213 b_state
->local_info28
.pid
= pid
;
214 b_state
->local_info28
.repl_epoch
= repl_epoch
;
217 * allocate the return bind_info
219 bind_info
= talloc(mem_ctx
, struct drsuapi_DsBindInfoCtr
);
220 W_ERROR_HAVE_NO_MEMORY(bind_info
);
222 bind_info
->length
= 28;
223 bind_info
->info
.info28
= b_state
->local_info28
;
226 * allocate a bind handle
228 handle
= dcesrv_handle_new(dce_call
->context
, DRSUAPI_BIND_HANDLE
);
229 W_ERROR_HAVE_NO_MEMORY(handle
);
230 handle
->data
= talloc_steal(handle
, b_state
);
235 r
->out
.bind_info
= bind_info
;
236 *r
->out
.bind_handle
= handle
->wire_handle
;
245 static WERROR
dcesrv_drsuapi_DsUnbind(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
246 struct drsuapi_DsUnbind
*r
)
248 struct dcesrv_handle
*h
;
250 *r
->out
.bind_handle
= *r
->in
.bind_handle
;
252 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
256 ZERO_STRUCTP(r
->out
.bind_handle
);
263 drsuapi_DsReplicaSync
265 static WERROR
dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
266 struct drsuapi_DsReplicaSync
*r
)
271 status
= drs_security_level_check(dce_call
, "DsReplicaSync", SECURITY_DOMAIN_CONTROLLER
, NULL
);
272 if (!W_ERROR_IS_OK(status
)) {
276 if (r
->in
.level
!= 1) {
277 DEBUG(0,("DsReplicaSync called with unsupported level %d\n", r
->in
.level
));
278 return WERR_DS_DRA_INVALID_PARAMETER
;
281 if (r
->in
.req
->req1
.options
& DRSUAPI_DRS_ASYNC_OP
) {
282 timeout
= IRPC_CALL_TIMEOUT
;
285 * use Infinite time for timeout in case
286 * the caller made a sync call
288 timeout
= IRPC_CALL_TIMEOUT_INF
;
291 dcesrv_irpc_forward_rpc_call(dce_call
, mem_ctx
,
292 r
, NDR_DRSUAPI_DSREPLICASYNC
,
294 "dreplsrv", "DsReplicaSync",
304 static WERROR
dcesrv_drsuapi_DsReplicaAdd(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
305 struct drsuapi_DsReplicaAdd
*r
)
307 DRSUAPI_UNSUPPORTED(drsuapi_DsReplicaAdd
);
314 static WERROR
dcesrv_drsuapi_DsReplicaDel(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
315 struct drsuapi_DsReplicaDel
*r
)
317 DRSUAPI_UNSUPPORTED(drsuapi_DsReplicaDel
);
322 drsuapi_DsReplicaModify
324 static WERROR
dcesrv_drsuapi_DsReplicaMod(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
325 struct drsuapi_DsReplicaMod
*r
)
327 DRSUAPI_UNSUPPORTED(drsuapi_DsReplicaMod
);
334 static WERROR
dcesrv_DRSUAPI_VERIFY_NAMES(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
335 struct DRSUAPI_VERIFY_NAMES
*r
)
337 DRSUAPI_UNSUPPORTED(DRSUAPI_VERIFY_NAMES
);
342 drsuapi_DsGetMemberships
344 static WERROR
dcesrv_drsuapi_DsGetMemberships(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
345 struct drsuapi_DsGetMemberships
*r
)
347 DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships
);
352 DRSUAPI_INTER_DOMAIN_MOVE
354 static WERROR
dcesrv_DRSUAPI_INTER_DOMAIN_MOVE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
355 struct DRSUAPI_INTER_DOMAIN_MOVE
*r
)
357 DRSUAPI_UNSUPPORTED(DRSUAPI_INTER_DOMAIN_MOVE
);
362 drsuapi_DsGetNT4ChangeLog
364 static WERROR
dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
365 struct drsuapi_DsGetNT4ChangeLog
*r
)
367 DRSUAPI_UNSUPPORTED(drsuapi_DsGetNT4ChangeLog
);
374 static WERROR
dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
375 struct drsuapi_DsCrackNames
*r
)
378 struct drsuapi_bind_state
*b_state
;
379 struct dcesrv_handle
*h
;
381 *r
->out
.level_out
= r
->in
.level
;
383 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
386 r
->out
.ctr
= talloc_zero(mem_ctx
, union drsuapi_DsNameCtr
);
387 W_ERROR_HAVE_NO_MEMORY(r
->out
.ctr
);
389 switch (r
->in
.level
) {
391 struct drsuapi_DsNameCtr1
*ctr1
;
392 struct drsuapi_DsNameInfo1
*names
;
395 ctr1
= talloc(mem_ctx
, struct drsuapi_DsNameCtr1
);
396 W_ERROR_HAVE_NO_MEMORY(ctr1
);
398 count
= r
->in
.req
->req1
.count
;
399 names
= talloc_array(mem_ctx
, struct drsuapi_DsNameInfo1
, count
);
400 W_ERROR_HAVE_NO_MEMORY(names
);
402 for (i
=0; i
< count
; i
++) {
403 status
= DsCrackNameOneName(b_state
->sam_ctx
, mem_ctx
,
404 r
->in
.req
->req1
.format_flags
,
405 r
->in
.req
->req1
.format_offered
,
406 r
->in
.req
->req1
.format_desired
,
407 r
->in
.req
->req1
.names
[i
].str
,
409 if (!W_ERROR_IS_OK(status
)) {
416 r
->out
.ctr
->ctr1
= ctr1
;
422 return WERR_UNKNOWN_LEVEL
;
427 drsuapi_DsRemoveDSServer
429 static WERROR
dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
430 struct drsuapi_DsRemoveDSServer
*r
)
432 struct drsuapi_bind_state
*b_state
;
433 struct dcesrv_handle
*h
;
434 struct ldb_dn
*ntds_dn
;
439 *r
->out
.level_out
= 1;
441 status
= drs_security_level_check(dce_call
, "DsRemoveDSServer", SECURITY_DOMAIN_CONTROLLER
, NULL
);
442 if (!W_ERROR_IS_OK(status
)) {
446 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
449 switch (r
->in
.level
) {
451 ntds_dn
= ldb_dn_new(mem_ctx
, b_state
->sam_ctx
, r
->in
.req
->req1
.server_dn
);
452 W_ERROR_HAVE_NO_MEMORY(ntds_dn
);
454 ok
= ldb_dn_validate(ntds_dn
);
459 /* TODO: it's likely that we need more checks here */
461 ok
= ldb_dn_add_child_fmt(ntds_dn
, "CN=NTDS Settings");
466 if (r
->in
.req
->req1
.commit
) {
467 ret
= ldb_delete(b_state
->sam_ctx
, ntds_dn
);
468 if (ret
!= LDB_SUCCESS
) {
483 DRSUAPI_REMOVE_DS_DOMAIN
485 static WERROR
dcesrv_DRSUAPI_REMOVE_DS_DOMAIN(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
486 struct DRSUAPI_REMOVE_DS_DOMAIN
*r
)
488 DRSUAPI_UNSUPPORTED(DRSUAPI_REMOVE_DS_DOMAIN
);
491 /* Obtain the site name from a server DN */
492 static const char *result_site_name(struct ldb_dn
*server_dn
)
494 /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
495 const struct ldb_val
*val
= ldb_dn_get_component_val(server_dn
, 2);
496 const char *name
= ldb_dn_get_component_name(server_dn
, 2);
498 if (!name
|| (ldb_attr_cmp(name
, "cn") != 0)) {
499 /* Ensure this matches the format. This gives us a
500 * bit more confidence that a 'cn' value will be a
505 return (char *)val
->data
;
511 drsuapi_DsGetDomainControllerInfo
513 static WERROR
dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state
*b_state
,
515 struct drsuapi_DsGetDomainControllerInfo
*r
)
517 struct ldb_dn
*sites_dn
;
518 struct ldb_result
*res
;
520 const char *attrs_account_1
[] = { "cn", "dnsHostName", NULL
};
521 const char *attrs_account_2
[] = { "cn", "dnsHostName", "objectGUID", NULL
};
523 const char *attrs_none
[] = { NULL
};
525 const char *attrs_site
[] = { "objectGUID", NULL
};
527 const char *attrs_ntds
[] = { "options", "objectGUID", NULL
};
529 const char *attrs_1
[] = { "serverReference", "cn", "dnsHostName", NULL
};
530 const char *attrs_2
[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL
};
533 struct drsuapi_DsGetDCInfoCtr1
*ctr1
;
534 struct drsuapi_DsGetDCInfoCtr2
*ctr2
;
539 *r
->out
.level_out
= r
->in
.req
->req1
.level
;
540 r
->out
.ctr
= talloc(mem_ctx
, union drsuapi_DsGetDCInfoCtr
);
541 W_ERROR_HAVE_NO_MEMORY(r
->out
.ctr
);
543 sites_dn
= samdb_sites_dn(b_state
->sam_ctx
, mem_ctx
);
545 return WERR_DS_OBJ_NOT_FOUND
;
548 switch (*r
->out
.level_out
) {
550 /* this level is not like the others */
551 return WERR_UNKNOWN_LEVEL
;
559 return WERR_UNKNOWN_LEVEL
;
562 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res
, sites_dn
, LDB_SCOPE_SUBTREE
, attrs
,
563 "objectClass=server");
566 DEBUG(1, ("searching for servers in sites DN %s failed: %s\n",
567 ldb_dn_get_linearized(sites_dn
), ldb_errstring(b_state
->sam_ctx
)));
568 return WERR_GENERAL_FAILURE
;
571 switch (*r
->out
.level_out
) {
573 ctr1
= &r
->out
.ctr
->ctr1
;
574 ctr1
->count
= res
->count
;
575 ctr1
->array
= talloc_zero_array(mem_ctx
,
576 struct drsuapi_DsGetDCInfo1
,
578 for (i
=0; i
< res
->count
; i
++) {
579 struct ldb_dn
*domain_dn
;
580 struct ldb_result
*res_domain
;
581 struct ldb_result
*res_account
;
582 struct ldb_dn
*ntds_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
584 struct ldb_dn
*ref_dn
585 = ldb_msg_find_attr_as_dn(b_state
->sam_ctx
,
586 mem_ctx
, res
->msgs
[i
],
589 if (!ntds_dn
|| !ldb_dn_add_child_fmt(ntds_dn
, "CN=NTDS Settings")) {
593 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_account
, ref_dn
,
594 LDB_SCOPE_BASE
, attrs_account_1
, "objectClass=computer");
595 if (ret
== LDB_SUCCESS
&& res_account
->count
== 1) {
597 ctr1
->array
[i
].dns_name
598 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "dNSHostName", NULL
);
599 ctr1
->array
[i
].netbios_name
600 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "cn", NULL
);
601 ctr1
->array
[i
].computer_dn
602 = ldb_dn_get_linearized(res_account
->msgs
[0]->dn
);
604 /* Determine if this is the PDC */
605 ret
= samdb_search_for_parent_domain(b_state
->sam_ctx
,
606 mem_ctx
, res_account
->msgs
[0]->dn
,
607 &domain_dn
, &errstr
);
609 if (ret
== LDB_SUCCESS
) {
610 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_domain
, domain_dn
,
611 LDB_SCOPE_BASE
, attrs_none
, "fSMORoleOwner=%s",
612 ldb_dn_get_linearized(ntds_dn
));
614 return WERR_GENERAL_FAILURE
;
616 if (res_domain
->count
== 1) {
617 ctr1
->array
[i
].is_pdc
= true;
621 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
622 DEBUG(5, ("warning: searching for computer DN %s failed: %s\n",
623 ldb_dn_get_linearized(ref_dn
), ldb_errstring(b_state
->sam_ctx
)));
626 /* Look at server DN and extract site component */
627 ctr1
->array
[i
].site_name
= result_site_name(res
->msgs
[i
]->dn
);
628 ctr1
->array
[i
].server_dn
= ldb_dn_get_linearized(res
->msgs
[i
]->dn
);
631 ctr1
->array
[i
].is_enabled
= true;
636 ctr2
= &r
->out
.ctr
->ctr2
;
637 ctr2
->count
= res
->count
;
638 ctr2
->array
= talloc_zero_array(mem_ctx
,
639 struct drsuapi_DsGetDCInfo2
,
641 for (i
=0; i
< res
->count
; i
++) {
642 struct ldb_dn
*domain_dn
;
643 struct ldb_result
*res_domain
;
644 struct ldb_result
*res_account
;
645 struct ldb_dn
*ntds_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
646 struct ldb_result
*res_ntds
;
647 struct ldb_dn
*site_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
648 struct ldb_result
*res_site
;
649 struct ldb_dn
*ref_dn
650 = ldb_msg_find_attr_as_dn(b_state
->sam_ctx
,
651 mem_ctx
, res
->msgs
[i
],
654 if (!ntds_dn
|| !ldb_dn_add_child_fmt(ntds_dn
, "CN=NTDS Settings")) {
658 /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
659 if (!site_dn
|| !ldb_dn_remove_child_components(site_dn
, 2)) {
663 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_ntds
, ntds_dn
,
664 LDB_SCOPE_BASE
, attrs_ntds
, "objectClass=nTDSDSA");
665 if (ret
== LDB_SUCCESS
&& res_ntds
->count
== 1) {
667 = (ldb_msg_find_attr_as_int(res_ntds
->msgs
[0], "options", 0) == 1);
668 ctr2
->array
[i
].ntds_guid
669 = samdb_result_guid(res_ntds
->msgs
[0], "objectGUID");
670 ctr2
->array
[i
].ntds_dn
= ldb_dn_get_linearized(res_ntds
->msgs
[0]->dn
);
672 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
673 DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n",
674 ldb_dn_get_linearized(ntds_dn
), ldb_errstring(b_state
->sam_ctx
)));
677 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_site
, site_dn
,
678 LDB_SCOPE_BASE
, attrs_site
, "objectClass=site");
679 if (ret
== LDB_SUCCESS
&& res_site
->count
== 1) {
680 ctr2
->array
[i
].site_guid
681 = samdb_result_guid(res_site
->msgs
[0], "objectGUID");
682 ctr2
->array
[i
].site_dn
= ldb_dn_get_linearized(res_site
->msgs
[0]->dn
);
684 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
685 DEBUG(5, ("warning: searching for site DN %s failed: %s\n",
686 ldb_dn_get_linearized(site_dn
), ldb_errstring(b_state
->sam_ctx
)));
689 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_account
, ref_dn
,
690 LDB_SCOPE_BASE
, attrs_account_2
, "objectClass=computer");
691 if (ret
== LDB_SUCCESS
&& res_account
->count
== 1) {
693 ctr2
->array
[i
].dns_name
694 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "dNSHostName", NULL
);
695 ctr2
->array
[i
].netbios_name
696 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "cn", NULL
);
697 ctr2
->array
[i
].computer_dn
= ldb_dn_get_linearized(res_account
->msgs
[0]->dn
);
698 ctr2
->array
[i
].computer_guid
699 = samdb_result_guid(res_account
->msgs
[0], "objectGUID");
701 /* Determine if this is the PDC */
702 ret
= samdb_search_for_parent_domain(b_state
->sam_ctx
,
703 mem_ctx
, res_account
->msgs
[0]->dn
,
704 &domain_dn
, &errstr
);
706 if (ret
== LDB_SUCCESS
) {
707 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_domain
, domain_dn
,
708 LDB_SCOPE_BASE
, attrs_none
, "fSMORoleOwner=%s",
709 ldb_dn_get_linearized(ntds_dn
));
710 if (ret
== LDB_SUCCESS
&& res_domain
->count
== 1) {
711 ctr2
->array
[i
].is_pdc
= true;
713 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
714 DEBUG(5, ("warning: searching for domain DN %s failed: %s\n",
715 ldb_dn_get_linearized(domain_dn
), ldb_errstring(b_state
->sam_ctx
)));
719 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
720 DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n",
721 ldb_dn_get_linearized(ref_dn
), ldb_errstring(b_state
->sam_ctx
)));
724 /* Look at server DN and extract site component */
725 ctr2
->array
[i
].site_name
= result_site_name(res
->msgs
[i
]->dn
);
726 ctr2
->array
[i
].server_dn
= ldb_dn_get_linearized(res
->msgs
[i
]->dn
);
727 ctr2
->array
[i
].server_guid
728 = samdb_result_guid(res
->msgs
[i
], "objectGUID");
730 ctr2
->array
[i
].is_enabled
= true;
739 drsuapi_DsGetDomainControllerInfo
741 static WERROR
dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
742 struct drsuapi_DsGetDomainControllerInfo
*r
)
744 struct dcesrv_handle
*h
;
745 struct drsuapi_bind_state
*b_state
;
746 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
749 switch (r
->in
.level
) {
751 return dcesrv_drsuapi_DsGetDomainControllerInfo_1(b_state
, mem_ctx
, r
);
754 return WERR_UNKNOWN_LEVEL
;
762 static WERROR
dcesrv_drsuapi_DsExecuteKCC(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
763 struct drsuapi_DsExecuteKCC
*r
)
766 status
= drs_security_level_check(dce_call
, "DsExecuteKCC", SECURITY_DOMAIN_CONTROLLER
, NULL
);
768 if (!W_ERROR_IS_OK(status
)) {
772 dcesrv_irpc_forward_rpc_call(dce_call
, mem_ctx
, r
, NDR_DRSUAPI_DSEXECUTEKCC
,
773 &ndr_table_drsuapi
, "kccsrv", "DsExecuteKCC",
780 drsuapi_DsReplicaGetInfo
782 static WERROR
dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
783 struct drsuapi_DsReplicaGetInfo
*r
)
785 enum security_user_level level
;
787 if (!lpcfg_parm_bool(dce_call
->conn
->dce_ctx
->lp_ctx
, NULL
,
788 "drs", "disable_sec_check", false)) {
789 level
= security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
);
790 if (level
< SECURITY_ADMINISTRATOR
) {
791 DEBUG(1,(__location__
": Administrator access required for DsReplicaGetInfo\n"));
792 security_token_debug(2, dce_call
->conn
->auth_state
.session_info
->security_token
);
793 return WERR_DS_DRA_ACCESS_DENIED
;
797 dcesrv_irpc_forward_rpc_call(dce_call
, mem_ctx
, r
, NDR_DRSUAPI_DSREPLICAGETINFO
,
798 &ndr_table_drsuapi
, "kccsrv", "DsReplicaGetInfo",
806 DRSUAPI_ADD_SID_HISTORY
808 static WERROR
dcesrv_DRSUAPI_ADD_SID_HISTORY(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
809 struct DRSUAPI_ADD_SID_HISTORY
*r
)
811 DRSUAPI_UNSUPPORTED(DRSUAPI_ADD_SID_HISTORY
);
815 drsuapi_DsGetMemberships2
817 static WERROR
dcesrv_drsuapi_DsGetMemberships2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
818 struct drsuapi_DsGetMemberships2
*r
)
820 DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships2
);
824 DRSUAPI_REPLICA_VERIFY_OBJECTS
826 static WERROR
dcesrv_DRSUAPI_REPLICA_VERIFY_OBJECTS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
827 struct DRSUAPI_REPLICA_VERIFY_OBJECTS
*r
)
829 DRSUAPI_UNSUPPORTED(DRSUAPI_REPLICA_VERIFY_OBJECTS
);
834 DRSUAPI_GET_OBJECT_EXISTENCE
836 static WERROR
dcesrv_DRSUAPI_GET_OBJECT_EXISTENCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
837 struct DRSUAPI_GET_OBJECT_EXISTENCE
*r
)
839 DRSUAPI_UNSUPPORTED(DRSUAPI_GET_OBJECT_EXISTENCE
);
844 drsuapi_QuerySitesByCost
846 static WERROR
dcesrv_drsuapi_QuerySitesByCost(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
847 struct drsuapi_QuerySitesByCost
*r
)
849 DRSUAPI_UNSUPPORTED(drsuapi_QuerySitesByCost
);
853 /* include the generated boilerplate */
854 #include "librpc/gen_ndr/ndr_drsuapi_s.c"