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 "rpc_server/drsuapi/dcesrv_drsuapi.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "lib/ldb/include/ldb_errors.h"
30 #include "param/param.h"
35 static WERROR
dcesrv_drsuapi_DsBind(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
36 struct drsuapi_DsBind
*r
)
38 struct drsuapi_bind_state
*b_state
;
39 struct dcesrv_handle
*handle
;
40 struct drsuapi_DsBindInfoCtr
*bind_info
;
41 struct GUID site_guid
;
42 struct ldb_result
*site_res
;
43 struct ldb_dn
*server_site_dn
;
44 static const char *site_attrs
[] = { "objectGUID", NULL
};
45 struct ldb_result
*ntds_res
;
46 struct ldb_dn
*ntds_dn
;
47 static const char *ntds_attrs
[] = { "ms-DS-ReplicationEpoch", NULL
};
52 r
->out
.bind_info
= NULL
;
53 ZERO_STRUCTP(r
->out
.bind_handle
);
55 b_state
= talloc_zero(mem_ctx
, struct drsuapi_bind_state
);
56 W_ERROR_HAVE_NO_MEMORY(b_state
);
59 * connect to the samdb
61 b_state
->sam_ctx
= samdb_connect(b_state
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
, dce_call
->conn
->auth_state
.session_info
);
62 if (!b_state
->sam_ctx
) {
67 * find out the guid of our own site
69 server_site_dn
= samdb_server_site_dn(b_state
->sam_ctx
, mem_ctx
);
70 W_ERROR_HAVE_NO_MEMORY(server_site_dn
);
72 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &site_res
,
73 server_site_dn
, LDB_SCOPE_BASE
, site_attrs
,
75 if (ret
!= LDB_SUCCESS
) {
76 return WERR_DS_DRA_INTERNAL_ERROR
;
78 if (site_res
->count
!= 1) {
79 return WERR_DS_DRA_INTERNAL_ERROR
;
81 site_guid
= samdb_result_guid(site_res
->msgs
[0], "objectGUID");
84 * lookup the local servers Replication Epoch
86 ntds_dn
= samdb_ntds_settings_dn(b_state
->sam_ctx
);
87 W_ERROR_HAVE_NO_MEMORY(ntds_dn
);
89 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &ntds_res
,
90 ntds_dn
, LDB_SCOPE_BASE
, ntds_attrs
,
92 if (ret
!= LDB_SUCCESS
) {
93 return WERR_DS_DRA_INTERNAL_ERROR
;
95 if (ntds_res
->count
!= 1) {
96 return WERR_DS_DRA_INTERNAL_ERROR
;
98 repl_epoch
= samdb_result_uint(ntds_res
->msgs
[0], "ms-DS-ReplicationEpoch", 0);
101 * The "process identifier" of the client.
102 * According to the WSPP docs, sectin 5.35, this is
103 * for informational and debugging purposes only.
104 * The assignment is implementation specific.
109 * store the clients bind_guid
111 if (r
->in
.bind_guid
) {
112 b_state
->remote_bind_guid
= *r
->in
.bind_guid
;
116 * store the clients bind_info
118 if (r
->in
.bind_info
) {
119 switch (r
->in
.bind_info
->length
) {
121 struct drsuapi_DsBindInfo24
*info24
;
122 info24
= &r
->in
.bind_info
->info
.info24
;
123 b_state
->remote_info28
.supported_extensions
= info24
->supported_extensions
;
124 b_state
->remote_info28
.site_guid
= info24
->site_guid
;
125 b_state
->remote_info28
.pid
= info24
->pid
;
126 b_state
->remote_info28
.repl_epoch
= 0;
130 b_state
->remote_info28
= r
->in
.bind_info
->info
.info28
;
136 * fill in our local bind info 28
138 b_state
->local_info28
.supported_extensions
= 0;
139 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_BASE
;
140 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION
;
141 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI
;
142 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2
;
143 #if 0 /* we don't support MSZIP compression (only decompression) */
144 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS
;
146 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1
;
147 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION
;
148 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE
;
149 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2
;
150 if (0 /*domain.behavior_version == 2*/) {
151 /* TODO: find out how this is really triggered! */
152 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION
;
154 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2
;
155 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD
;
156 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND
;
157 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO
;
158 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION
;
159 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01
;
160 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP
;
161 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY
;
162 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
;
163 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_00100000
;
164 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2
;
165 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6
;
166 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS
;
167 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8
;
168 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5
;
169 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6
;
170 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3
;
171 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7
;
172 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT
;
173 #if 0 /* we don't support XPRESS compression yet */
174 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS
;
176 b_state
->local_info28
.site_guid
= site_guid
;
177 b_state
->local_info28
.pid
= pid
;
178 b_state
->local_info28
.repl_epoch
= repl_epoch
;
181 * allocate the return bind_info
183 bind_info
= talloc(mem_ctx
, struct drsuapi_DsBindInfoCtr
);
184 W_ERROR_HAVE_NO_MEMORY(bind_info
);
186 bind_info
->length
= 28;
187 bind_info
->info
.info28
= b_state
->local_info28
;
190 * allocate a bind handle
192 handle
= dcesrv_handle_new(dce_call
->context
, DRSUAPI_BIND_HANDLE
);
193 W_ERROR_HAVE_NO_MEMORY(handle
);
194 handle
->data
= talloc_steal(handle
, b_state
);
199 r
->out
.bind_info
= bind_info
;
200 *r
->out
.bind_handle
= handle
->wire_handle
;
209 static WERROR
dcesrv_drsuapi_DsUnbind(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
210 struct drsuapi_DsUnbind
*r
)
212 struct dcesrv_handle
*h
;
214 *r
->out
.bind_handle
= *r
->in
.bind_handle
;
216 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
220 ZERO_STRUCTP(r
->out
.bind_handle
);
227 drsuapi_DsReplicaSync
229 static WERROR
dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
230 struct drsuapi_DsReplicaSync
*r
)
232 /* TODO: implement this call correct!
233 * for now we just say yes,
234 * because we have no output parameter
239 int drsuapi_search_with_extended_dn(struct ldb_context
*ldb
,
241 struct ldb_result
**_res
,
242 struct ldb_dn
*basedn
,
243 enum ldb_scope scope
,
244 const char * const *attrs
,
245 const char *format
, ...)
249 struct ldb_request
*req
;
252 struct ldb_result
*res
;
254 tmp_ctx
= talloc_new(mem_ctx
);
256 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
258 return LDB_ERR_OPERATIONS_ERROR
;
261 va_start(ap
, format
);
262 filter
= talloc_vasprintf(tmp_ctx
, format
, ap
);
265 if (filter
== NULL
) {
266 talloc_free(tmp_ctx
);
267 return LDB_ERR_OPERATIONS_ERROR
;
270 ret
= ldb_build_search_req(&req
, ldb
, tmp_ctx
,
277 ldb_search_default_callback
,
279 if (ret
!= LDB_SUCCESS
) {
280 talloc_free(tmp_ctx
);
284 ret
= ldb_request_add_control(req
, LDB_CONTROL_EXTENDED_DN_OID
, true, NULL
);
285 if (ret
!= LDB_SUCCESS
) {
289 ret
= ldb_request(ldb
, req
);
290 if (ret
== LDB_SUCCESS
) {
291 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
301 drsuapi_DsGetNCChanges
303 static WERROR
dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
304 struct drsuapi_DsGetNCChanges
*r
)
306 struct ldb_result
*site_res
;
307 struct drsuapi_DsReplicaObjectIdentifier
*ncRoot
;
308 struct drsuapi_bind_state
*b_state
;
309 struct ldb_dn
*ncRoot_dn
;
314 struct dsdb_schema
*schema
;
315 struct drsuapi_DsReplicaOIDMapping_Ctr
*ctr
;
316 time_t t
= time(NULL
);
318 struct drsuapi_DsReplicaObjectListItemEx
*currentObject
;
319 struct dom_sid
*zero_sid
;
320 struct ldb_dn
*obj_dn
;
322 b_state
= talloc_zero(mem_ctx
, struct drsuapi_bind_state
);
323 W_ERROR_HAVE_NO_MEMORY(b_state
);
324 zero_sid
= talloc_zero(mem_ctx
, struct dom_sid
);
326 * connect to the samdb
328 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
);
329 if (!b_state
->sam_ctx
) {
333 /* Check request revision. */
334 if (r
->in
.level
!= 8) {
335 return WERR_REVISION_MISMATCH
;
338 /* Perform access checks. */
339 if (r
->in
.req
->req8
.naming_context
== NULL
) {
340 return WERR_DS_DRA_INVALID_PARAMETER
;
343 ncRoot
= r
->in
.req
->req8
.naming_context
;
344 if (ncRoot
== NULL
) {
345 return WERR_DS_DRA_BAD_NC
;
348 /* Construct response. */
349 ncRoot_dn
= ldb_dn_new(mem_ctx
, b_state
->sam_ctx
, ncRoot
->dn
);
350 ret
= drsuapi_search_with_extended_dn(b_state
->sam_ctx
, mem_ctx
, &site_res
,
351 ncRoot_dn
, LDB_SCOPE_SUBTREE
, NULL
,
352 "(&(uSNChanged>=%lld)(objectClass=*))", r
->in
.req
->req8
.highwatermark
.highest_usn
);
353 if (ret
!= LDB_SUCCESS
) {
354 return WERR_DS_DRA_INTERNAL_ERROR
;
357 *r
->out
.level_out
= 6;
358 r
->out
.ctr
->ctr6
.naming_context
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectIdentifier
);
359 *r
->out
.ctr
->ctr6
.naming_context
= *ncRoot
;
360 /* TODO: linked attributes*/
361 r
->out
.ctr
->ctr6
.linked_attributes_count
= 0;
362 r
->out
.ctr
->ctr6
.linked_attributes
= NULL
;
364 r
->out
.ctr
->ctr6
.object_count
= 0;
365 r
->out
.ctr
->ctr6
.more_data
= false;
366 r
->out
.ctr
->ctr6
.uptodateness_vector
= NULL
;
369 schema
= dsdb_get_schema(b_state
->sam_ctx
);
371 DEBUG(0,("No schema in b_state->sam_ctx"));
374 dsdb_get_oid_mappings_drsuapi(schema
, true, mem_ctx
, &ctr
);
375 r
->out
.ctr
->ctr6
.mapping_ctr
= *ctr
;
377 r
->out
.ctr
->ctr6
.source_dsa_guid
= *(samdb_ntds_objectGUID(b_state
->sam_ctx
));
378 r
->out
.ctr
->ctr6
.source_dsa_invocation_id
= *(samdb_ntds_invocation_id(b_state
->sam_ctx
));
380 r
->out
.ctr
->ctr6
.old_highwatermark
= r
->in
.req
->req8
.highwatermark
;
381 r
->out
.ctr
->ctr6
.new_highwatermark
= r
->in
.req
->req8
.highwatermark
;
383 r
->out
.ctr
->ctr6
.first_object
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectListItemEx
);
384 currentObject
= r
->out
.ctr
->ctr6
.first_object
;
386 for(i
=0; i
<site_res
->count
; i
++) {
387 uSN
= ldb_msg_find_attr_as_int(site_res
->msgs
[i
],"uSNChanged", -1);
388 r
->out
.ctr
->ctr6
.object_count
++;
389 if (uSN
> r
->out
.ctr
->ctr6
.new_highwatermark
.highest_usn
) {
390 r
->out
.ctr
->ctr6
.new_highwatermark
.highest_usn
= uSN
;
393 if (ldb_dn_compare(ncRoot_dn
, site_res
->msgs
[i
]->dn
) == 0) {
394 currentObject
->is_nc_prefix
= true;
395 currentObject
->parent_object_guid
= NULL
;
397 currentObject
->is_nc_prefix
= false;
398 currentObject
->parent_object_guid
= talloc(mem_ctx
, struct GUID
);
399 *currentObject
->parent_object_guid
= samdb_result_guid(site_res
->msgs
[i
], "parentGUID");
401 currentObject
->next_object
= NULL
;
402 /* TODO: MetaData vector*/
403 currentObject
->meta_data_ctr
= talloc(mem_ctx
, struct drsuapi_DsReplicaMetaDataCtr
);
404 currentObject
->meta_data_ctr
->meta_data
= talloc(mem_ctx
, struct drsuapi_DsReplicaMetaData
);
405 currentObject
->meta_data_ctr
->count
= 0;
406 currentObject
->object
.identifier
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectIdentifier
);
407 obj_dn
= ldb_msg_find_attr_as_dn(b_state
->sam_ctx
, mem_ctx
, site_res
->msgs
[i
], "distinguishedName");
408 currentObject
->object
.identifier
->dn
= ldb_dn_get_linearized(obj_dn
);
409 currentObject
->object
.identifier
->guid
= GUID_zero();
410 currentObject
->object
.identifier
->sid
= *zero_sid
;
412 currentObject
->object
.attribute_ctr
.num_attributes
= site_res
->msgs
[i
]->num_elements
;
413 /* Exclude non-replicate attributes from the responce.*/
414 for (j
=0; j
<site_res
->msgs
[i
]->num_elements
; j
++) {
415 const struct dsdb_attribute
*sa
;
416 sa
= dsdb_attribute_by_lDAPDisplayName(schema
, site_res
->msgs
[i
]->elements
[j
].name
);
417 if (sa
&& sa
->systemFlags
& 0x00000001) {
418 ldb_msg_remove_attr(site_res
->msgs
[i
], site_res
->msgs
[i
]->elements
[j
].name
);
419 currentObject
->object
.attribute_ctr
.num_attributes
--;
422 currentObject
->object
.attribute_ctr
.attributes
= talloc_array(mem_ctx
, struct drsuapi_DsReplicaAttribute
,
423 currentObject
->object
.attribute_ctr
.num_attributes
);
424 for (j
=0; j
<currentObject
->object
.attribute_ctr
.num_attributes
; j
++) {
425 dsdb_attribute_ldb_to_drsuapi(b_state
->sam_ctx
, schema
,&site_res
->msgs
[i
]->elements
[j
], mem_ctx
,
426 ¤tObject
->object
.attribute_ctr
.attributes
[j
]);
429 if (i
== (site_res
->count
-1)) {
432 currentObject
->next_object
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectListItemEx
);
433 currentObject
= currentObject
->next_object
;
436 r
->out
.ctr
->ctr6
.uptodateness_vector
= talloc(mem_ctx
, struct drsuapi_DsReplicaCursor2CtrEx
);
438 r
->out
.ctr
->ctr6
.uptodateness_vector
->version
= 2;
439 r
->out
.ctr
->ctr6
.uptodateness_vector
->count
= 1;
440 r
->out
.ctr
->ctr6
.uptodateness_vector
->reserved1
= 0;
441 r
->out
.ctr
->ctr6
.uptodateness_vector
->reserved2
= 0;
442 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
= talloc(mem_ctx
, struct drsuapi_DsReplicaCursor2
);
444 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
[0].source_dsa_invocation_id
= *(samdb_ntds_invocation_id(b_state
->sam_ctx
));
445 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
[0].highest_usn
= r
->out
.ctr
->ctr6
.new_highwatermark
.highest_usn
;
446 unix_to_nt_time(&now
, t
);
447 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
[0].last_sync_success
= now
;
454 drsuapi_DsReplicaUpdateRefs
456 static WERROR
dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
457 struct drsuapi_DsReplicaUpdateRefs
*r
)
459 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
466 static WERROR
dcesrv_DRSUAPI_REPLICA_ADD(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
467 struct DRSUAPI_REPLICA_ADD
*r
)
469 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
476 static WERROR
dcesrv_DRSUAPI_REPLICA_DEL(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
477 struct DRSUAPI_REPLICA_DEL
*r
)
479 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
484 DRSUAPI_REPLICA_MODIFY
486 static WERROR
dcesrv_DRSUAPI_REPLICA_MODIFY(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
487 struct DRSUAPI_REPLICA_MODIFY
*r
)
489 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
496 static WERROR
dcesrv_DRSUAPI_VERIFY_NAMES(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
497 struct DRSUAPI_VERIFY_NAMES
*r
)
499 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
504 drsuapi_DsGetMemberships
506 static WERROR
dcesrv_drsuapi_DsGetMemberships(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
507 struct drsuapi_DsGetMemberships
*r
)
509 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
514 DRSUAPI_INTER_DOMAIN_MOVE
516 static WERROR
dcesrv_DRSUAPI_INTER_DOMAIN_MOVE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
517 struct DRSUAPI_INTER_DOMAIN_MOVE
*r
)
519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
524 drsuapi_DsGetNT4ChangeLog
526 static WERROR
dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
527 struct drsuapi_DsGetNT4ChangeLog
*r
)
529 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
536 static WERROR
dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
537 struct drsuapi_DsCrackNames
*r
)
540 struct drsuapi_bind_state
*b_state
;
541 struct dcesrv_handle
*h
;
543 *r
->out
.level_out
= r
->in
.level
;
545 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
548 r
->out
.ctr
= talloc_zero(mem_ctx
, union drsuapi_DsNameCtr
);
549 W_ERROR_HAVE_NO_MEMORY(r
->out
.ctr
);
551 switch (r
->in
.level
) {
553 struct drsuapi_DsNameCtr1
*ctr1
;
554 struct drsuapi_DsNameInfo1
*names
;
558 ctr1
= talloc(mem_ctx
, struct drsuapi_DsNameCtr1
);
559 W_ERROR_HAVE_NO_MEMORY(ctr1
);
561 count
= r
->in
.req
->req1
.count
;
562 names
= talloc_array(mem_ctx
, struct drsuapi_DsNameInfo1
, count
);
563 W_ERROR_HAVE_NO_MEMORY(names
);
565 for (i
=0; i
< count
; i
++) {
566 status
= DsCrackNameOneName(b_state
->sam_ctx
, mem_ctx
,
567 r
->in
.req
->req1
.format_flags
,
568 r
->in
.req
->req1
.format_offered
,
569 r
->in
.req
->req1
.format_desired
,
570 r
->in
.req
->req1
.names
[i
].str
,
572 if (!W_ERROR_IS_OK(status
)) {
579 r
->out
.ctr
->ctr1
= ctr1
;
585 return WERR_UNKNOWN_LEVEL
;
589 drsuapi_DsWriteAccountSpn
591 static WERROR
dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
592 struct drsuapi_DsWriteAccountSpn
*r
)
594 struct drsuapi_bind_state
*b_state
;
595 struct dcesrv_handle
*h
;
597 *r
->out
.level_out
= r
->in
.level
;
599 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
602 r
->out
.res
= talloc(mem_ctx
, union drsuapi_DsWriteAccountSpnResult
);
603 W_ERROR_HAVE_NO_MEMORY(r
->out
.res
);
605 switch (r
->in
.level
) {
607 struct drsuapi_DsWriteAccountSpnRequest1
*req
;
608 struct ldb_message
*msg
;
610 req
= &r
->in
.req
->req1
;
613 msg
= ldb_msg_new(mem_ctx
);
618 msg
->dn
= ldb_dn_new(msg
, b_state
->sam_ctx
, req
->object_dn
);
619 if ( ! ldb_dn_validate(msg
->dn
)) {
620 r
->out
.res
->res1
.status
= WERR_OK
;
625 for (i
= 0; i
< count
; i
++) {
626 samdb_msg_add_string(b_state
->sam_ctx
,
627 msg
, msg
, "servicePrincipalName",
628 req
->spn_names
[i
].str
);
630 for (i
=0;i
<msg
->num_elements
;i
++) {
631 switch (req
->operation
) {
632 case DRSUAPI_DS_SPN_OPERATION_ADD
:
633 msg
->elements
[i
].flags
= LDB_FLAG_MOD_ADD
;
635 case DRSUAPI_DS_SPN_OPERATION_REPLACE
:
636 msg
->elements
[i
].flags
= LDB_FLAG_MOD_REPLACE
;
638 case DRSUAPI_DS_SPN_OPERATION_DELETE
:
639 msg
->elements
[i
].flags
= LDB_FLAG_MOD_DELETE
;
644 /* Apply to database */
646 ret
= ldb_modify(b_state
->sam_ctx
, msg
);
648 DEBUG(0,("Failed to modify SPNs on %s: %s\n",
649 ldb_dn_get_linearized(msg
->dn
),
650 ldb_errstring(b_state
->sam_ctx
)));
651 r
->out
.res
->res1
.status
= WERR_ACCESS_DENIED
;
653 r
->out
.res
->res1
.status
= WERR_OK
;
660 return WERR_UNKNOWN_LEVEL
;
665 drsuapi_DsRemoveDSServer
667 static WERROR
dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
668 struct drsuapi_DsRemoveDSServer
*r
)
670 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
675 DRSUAPI_REMOVE_DS_DOMAIN
677 static WERROR
dcesrv_DRSUAPI_REMOVE_DS_DOMAIN(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
678 struct DRSUAPI_REMOVE_DS_DOMAIN
*r
)
680 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
683 /* Obtain the site name from a server DN */
684 static const char *result_site_name(struct ldb_dn
*site_dn
)
686 /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
687 const struct ldb_val
*val
= ldb_dn_get_component_val(site_dn
, 2);
688 const char *name
= ldb_dn_get_component_name(site_dn
, 2);
690 if (!name
|| (ldb_attr_cmp(name
, "cn") != 0)) {
691 /* Ensure this matches the format. This gives us a
692 * bit more confidence that a 'cn' value will be a
697 return (char *)val
->data
;
703 drsuapi_DsGetDomainControllerInfo
705 static WERROR
dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state
*b_state
,
707 struct drsuapi_DsGetDomainControllerInfo
*r
)
709 struct ldb_dn
*sites_dn
;
710 struct ldb_result
*res
;
712 const char *attrs_account_1
[] = { "cn", "dnsHostName", NULL
};
713 const char *attrs_account_2
[] = { "cn", "dnsHostName", "objectGUID", NULL
};
715 const char *attrs_none
[] = { NULL
};
717 const char *attrs_site
[] = { "objectGUID", NULL
};
719 const char *attrs_ntds
[] = { "options", "objectGUID", NULL
};
721 const char *attrs_1
[] = { "serverReference", "cn", "dnsHostName", NULL
};
722 const char *attrs_2
[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL
};
725 struct drsuapi_DsGetDCInfoCtr1
*ctr1
;
726 struct drsuapi_DsGetDCInfoCtr2
*ctr2
;
730 *r
->out
.level_out
= r
->in
.req
->req1
.level
;
731 r
->out
.ctr
= talloc(mem_ctx
, union drsuapi_DsGetDCInfoCtr
);
732 W_ERROR_HAVE_NO_MEMORY(r
->out
.ctr
);
734 sites_dn
= samdb_sites_dn(b_state
->sam_ctx
, mem_ctx
);
736 return WERR_DS_OBJ_NOT_FOUND
;
739 switch (*r
->out
.level_out
) {
741 /* this level is not like the others */
742 return WERR_UNKNOWN_LEVEL
;
750 return WERR_UNKNOWN_LEVEL
;
753 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res
, sites_dn
, LDB_SCOPE_SUBTREE
, attrs
,
754 "objectClass=server");
757 DEBUG(1, ("searching for servers in sites DN %s failed: %s\n",
758 ldb_dn_get_linearized(sites_dn
), ldb_errstring(b_state
->sam_ctx
)));
759 return WERR_GENERAL_FAILURE
;
762 switch (*r
->out
.level_out
) {
764 ctr1
= &r
->out
.ctr
->ctr1
;
765 ctr1
->count
= res
->count
;
766 ctr1
->array
= talloc_zero_array(mem_ctx
,
767 struct drsuapi_DsGetDCInfo1
,
769 for (i
=0; i
< res
->count
; i
++) {
770 struct ldb_dn
*domain_dn
;
771 struct ldb_result
*res_domain
;
772 struct ldb_result
*res_account
;
773 struct ldb_dn
*ntds_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
775 struct ldb_dn
*ref_dn
776 = ldb_msg_find_attr_as_dn(b_state
->sam_ctx
,
777 mem_ctx
, res
->msgs
[i
],
780 if (!ntds_dn
|| !ldb_dn_add_child_fmt(ntds_dn
, "CN=NTDS Settings")) {
784 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_account
, ref_dn
,
785 LDB_SCOPE_BASE
, attrs_account_1
, "objectClass=computer");
786 if (ret
== LDB_SUCCESS
&& res_account
->count
== 1) {
788 ctr1
->array
[i
].dns_name
789 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "dNSHostName", NULL
);
790 ctr1
->array
[i
].netbios_name
791 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "cn", NULL
);
792 ctr1
->array
[i
].computer_dn
793 = ldb_dn_get_linearized(res_account
->msgs
[0]->dn
);
795 /* Determine if this is the PDC */
796 ret
= samdb_search_for_parent_domain(b_state
->sam_ctx
,
797 mem_ctx
, res_account
->msgs
[0]->dn
,
798 &domain_dn
, &errstr
);
800 if (ret
== LDB_SUCCESS
) {
801 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_domain
, domain_dn
,
802 LDB_SCOPE_BASE
, attrs_none
, "fSMORoleOwner=%s",
803 ldb_dn_get_linearized(ntds_dn
));
805 return WERR_GENERAL_FAILURE
;
807 if (res_domain
->count
== 1) {
808 ctr1
->array
[i
].is_pdc
= true;
812 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
813 DEBUG(5, ("warning: searching for computer DN %s failed: %s\n",
814 ldb_dn_get_linearized(ref_dn
), ldb_errstring(b_state
->sam_ctx
)));
817 /* Look at server DN and extract site component */
818 ctr1
->array
[i
].site_name
= result_site_name(res
->msgs
[i
]->dn
);
819 ctr1
->array
[i
].server_dn
= ldb_dn_get_linearized(res
->msgs
[i
]->dn
);
822 ctr1
->array
[i
].is_enabled
= true;
827 ctr2
= &r
->out
.ctr
->ctr2
;
828 ctr2
->count
= res
->count
;
829 ctr2
->array
= talloc_zero_array(mem_ctx
,
830 struct drsuapi_DsGetDCInfo2
,
832 for (i
=0; i
< res
->count
; i
++) {
833 struct ldb_dn
*domain_dn
;
834 struct ldb_result
*res_domain
;
835 struct ldb_result
*res_account
;
836 struct ldb_dn
*ntds_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
837 struct ldb_result
*res_ntds
;
838 struct ldb_dn
*site_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
839 struct ldb_result
*res_site
;
840 struct ldb_dn
*ref_dn
841 = ldb_msg_find_attr_as_dn(b_state
->sam_ctx
,
842 mem_ctx
, res
->msgs
[i
],
845 if (!ntds_dn
|| !ldb_dn_add_child_fmt(ntds_dn
, "CN=NTDS Settings")) {
849 /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
850 if (!site_dn
|| !ldb_dn_remove_child_components(site_dn
, 2)) {
854 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_ntds
, ntds_dn
,
855 LDB_SCOPE_BASE
, attrs_ntds
, "objectClass=nTDSDSA");
856 if (ret
== LDB_SUCCESS
&& res_ntds
->count
== 1) {
858 = (ldb_msg_find_attr_as_int(res_ntds
->msgs
[0], "options", 0) == 1);
859 ctr2
->array
[i
].ntds_guid
860 = samdb_result_guid(res_ntds
->msgs
[0], "objectGUID");
861 ctr2
->array
[i
].ntds_dn
= ldb_dn_get_linearized(res_ntds
->msgs
[0]->dn
);
863 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
864 DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n",
865 ldb_dn_get_linearized(ntds_dn
), ldb_errstring(b_state
->sam_ctx
)));
868 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_site
, site_dn
,
869 LDB_SCOPE_BASE
, attrs_site
, "objectClass=site");
870 if (ret
== LDB_SUCCESS
&& res_site
->count
== 1) {
871 ctr2
->array
[i
].site_guid
872 = samdb_result_guid(res_site
->msgs
[0], "objectGUID");
873 ctr2
->array
[i
].site_dn
= ldb_dn_get_linearized(res_site
->msgs
[0]->dn
);
875 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
876 DEBUG(5, ("warning: searching for site DN %s failed: %s\n",
877 ldb_dn_get_linearized(site_dn
), ldb_errstring(b_state
->sam_ctx
)));
880 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_account
, ref_dn
,
881 LDB_SCOPE_BASE
, attrs_account_2
, "objectClass=computer");
882 if (ret
== LDB_SUCCESS
&& res_account
->count
== 1) {
884 ctr2
->array
[i
].dns_name
885 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "dNSHostName", NULL
);
886 ctr2
->array
[i
].netbios_name
887 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "cn", NULL
);
888 ctr2
->array
[i
].computer_dn
= ldb_dn_get_linearized(res_account
->msgs
[0]->dn
);
889 ctr2
->array
[i
].computer_guid
890 = samdb_result_guid(res_account
->msgs
[0], "objectGUID");
892 /* Determine if this is the PDC */
893 ret
= samdb_search_for_parent_domain(b_state
->sam_ctx
,
894 mem_ctx
, res_account
->msgs
[0]->dn
,
895 &domain_dn
, &errstr
);
897 if (ret
== LDB_SUCCESS
) {
898 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_domain
, domain_dn
,
899 LDB_SCOPE_BASE
, attrs_none
, "fSMORoleOwner=%s",
900 ldb_dn_get_linearized(ntds_dn
));
901 if (ret
== LDB_SUCCESS
&& res_domain
->count
== 1) {
902 ctr2
->array
[i
].is_pdc
= true;
904 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
905 DEBUG(5, ("warning: searching for domain DN %s failed: %s\n",
906 ldb_dn_get_linearized(domain_dn
), ldb_errstring(b_state
->sam_ctx
)));
910 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
911 DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n",
912 ldb_dn_get_linearized(ref_dn
), ldb_errstring(b_state
->sam_ctx
)));
915 /* Look at server DN and extract site component */
916 ctr2
->array
[i
].site_name
= result_site_name(res
->msgs
[i
]->dn
);
917 ctr2
->array
[i
].server_dn
= ldb_dn_get_linearized(res
->msgs
[i
]->dn
);
918 ctr2
->array
[i
].server_guid
919 = samdb_result_guid(res
->msgs
[i
], "objectGUID");
921 ctr2
->array
[i
].is_enabled
= true;
930 drsuapi_DsGetDomainControllerInfo
932 static WERROR
dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
933 struct drsuapi_DsGetDomainControllerInfo
*r
)
935 struct dcesrv_handle
*h
;
936 struct drsuapi_bind_state
*b_state
;
937 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
940 switch (r
->in
.level
) {
942 return dcesrv_drsuapi_DsGetDomainControllerInfo_1(b_state
, mem_ctx
, r
);
945 return WERR_UNKNOWN_LEVEL
;
952 static WERROR
dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
953 struct drsuapi_DsAddEntry
*r
)
955 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
962 static WERROR
dcesrv_DRSUAPI_EXECUTE_KCC(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
963 struct DRSUAPI_EXECUTE_KCC
*r
)
965 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
970 drsuapi_DsReplicaGetInfo
972 static WERROR
dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
973 struct drsuapi_DsReplicaGetInfo
*r
)
975 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
980 DRSUAPI_ADD_SID_HISTORY
982 static WERROR
dcesrv_DRSUAPI_ADD_SID_HISTORY(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
983 struct DRSUAPI_ADD_SID_HISTORY
*r
)
985 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
989 drsuapi_DsGetMemberships2
991 static WERROR
dcesrv_drsuapi_DsGetMemberships2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
992 struct drsuapi_DsGetMemberships2
*r
)
994 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
998 DRSUAPI_REPLICA_VERIFY_OBJECTS
1000 static WERROR
dcesrv_DRSUAPI_REPLICA_VERIFY_OBJECTS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1001 struct DRSUAPI_REPLICA_VERIFY_OBJECTS
*r
)
1003 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1008 DRSUAPI_GET_OBJECT_EXISTENCE
1010 static WERROR
dcesrv_DRSUAPI_GET_OBJECT_EXISTENCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1011 struct DRSUAPI_GET_OBJECT_EXISTENCE
*r
)
1013 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1018 drsuapi_QuerySitesByCost
1020 static WERROR
dcesrv_drsuapi_QuerySitesByCost(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1021 struct drsuapi_QuerySitesByCost
*r
)
1023 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1027 /* include the generated boilerplate */
1028 #include "librpc/gen_ndr/ndr_drsuapi_s.c"