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"
31 #include "librpc/gen_ndr/ndr_drsblobs.h"
36 static WERROR
dcesrv_drsuapi_DsBind(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
37 struct drsuapi_DsBind
*r
)
39 struct drsuapi_bind_state
*b_state
;
40 struct dcesrv_handle
*handle
;
41 struct drsuapi_DsBindInfoCtr
*bind_info
;
42 struct GUID site_guid
;
43 struct ldb_result
*site_res
;
44 struct ldb_dn
*server_site_dn
;
45 static const char *site_attrs
[] = { "objectGUID", NULL
};
46 struct ldb_result
*ntds_res
;
47 struct ldb_dn
*ntds_dn
;
48 static const char *ntds_attrs
[] = { "ms-DS-ReplicationEpoch", NULL
};
53 r
->out
.bind_info
= NULL
;
54 ZERO_STRUCTP(r
->out
.bind_handle
);
56 b_state
= talloc_zero(mem_ctx
, struct drsuapi_bind_state
);
57 W_ERROR_HAVE_NO_MEMORY(b_state
);
60 * connect to the samdb
62 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
);
63 if (!b_state
->sam_ctx
) {
68 * find out the guid of our own site
70 server_site_dn
= samdb_server_site_dn(b_state
->sam_ctx
, mem_ctx
);
71 W_ERROR_HAVE_NO_MEMORY(server_site_dn
);
73 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &site_res
,
74 server_site_dn
, LDB_SCOPE_BASE
, site_attrs
,
76 if (ret
!= LDB_SUCCESS
) {
77 return WERR_DS_DRA_INTERNAL_ERROR
;
79 if (site_res
->count
!= 1) {
80 return WERR_DS_DRA_INTERNAL_ERROR
;
82 site_guid
= samdb_result_guid(site_res
->msgs
[0], "objectGUID");
85 * lookup the local servers Replication Epoch
87 ntds_dn
= samdb_ntds_settings_dn(b_state
->sam_ctx
);
88 W_ERROR_HAVE_NO_MEMORY(ntds_dn
);
90 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &ntds_res
,
91 ntds_dn
, LDB_SCOPE_BASE
, ntds_attrs
,
93 if (ret
!= LDB_SUCCESS
) {
94 return WERR_DS_DRA_INTERNAL_ERROR
;
96 if (ntds_res
->count
!= 1) {
97 return WERR_DS_DRA_INTERNAL_ERROR
;
99 repl_epoch
= samdb_result_uint(ntds_res
->msgs
[0], "ms-DS-ReplicationEpoch", 0);
102 * The "process identifier" of the client.
103 * According to the WSPP docs, sectin 5.35, this is
104 * for informational and debugging purposes only.
105 * The assignment is implementation specific.
110 * store the clients bind_guid
112 if (r
->in
.bind_guid
) {
113 b_state
->remote_bind_guid
= *r
->in
.bind_guid
;
117 * store the clients bind_info
119 if (r
->in
.bind_info
) {
120 switch (r
->in
.bind_info
->length
) {
122 struct drsuapi_DsBindInfo24
*info24
;
123 info24
= &r
->in
.bind_info
->info
.info24
;
124 b_state
->remote_info28
.supported_extensions
= info24
->supported_extensions
;
125 b_state
->remote_info28
.site_guid
= info24
->site_guid
;
126 b_state
->remote_info28
.pid
= info24
->pid
;
127 b_state
->remote_info28
.repl_epoch
= 0;
131 b_state
->remote_info28
= r
->in
.bind_info
->info
.info28
;
137 * fill in our local bind info 28
139 b_state
->local_info28
.supported_extensions
= 0;
140 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_BASE
;
141 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION
;
142 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI
;
143 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2
;
144 #if 0 /* we don't support MSZIP compression (only decompression) */
145 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS
;
147 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1
;
148 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION
;
149 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE
;
150 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2
;
151 if (0 /*domain.behavior_version == 2*/) {
152 /* TODO: find out how this is really triggered! */
153 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION
;
155 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2
;
156 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD
;
157 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND
;
158 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO
;
159 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION
;
160 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01
;
161 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP
;
162 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY
;
163 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
;
164 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_00100000
;
165 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2
;
166 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6
;
167 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS
;
168 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8
;
169 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5
;
170 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6
;
171 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3
;
172 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7
;
173 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT
;
174 #if 0 /* we don't support XPRESS compression yet */
175 b_state
->local_info28
.supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS
;
177 b_state
->local_info28
.site_guid
= site_guid
;
178 b_state
->local_info28
.pid
= pid
;
179 b_state
->local_info28
.repl_epoch
= repl_epoch
;
182 * allocate the return bind_info
184 bind_info
= talloc(mem_ctx
, struct drsuapi_DsBindInfoCtr
);
185 W_ERROR_HAVE_NO_MEMORY(bind_info
);
187 bind_info
->length
= 28;
188 bind_info
->info
.info28
= b_state
->local_info28
;
191 * allocate a bind handle
193 handle
= dcesrv_handle_new(dce_call
->context
, DRSUAPI_BIND_HANDLE
);
194 W_ERROR_HAVE_NO_MEMORY(handle
);
195 handle
->data
= talloc_steal(handle
, b_state
);
200 r
->out
.bind_info
= bind_info
;
201 *r
->out
.bind_handle
= handle
->wire_handle
;
210 static WERROR
dcesrv_drsuapi_DsUnbind(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
211 struct drsuapi_DsUnbind
*r
)
213 struct dcesrv_handle
*h
;
215 *r
->out
.bind_handle
= *r
->in
.bind_handle
;
217 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
221 ZERO_STRUCTP(r
->out
.bind_handle
);
228 drsuapi_DsReplicaSync
230 static WERROR
dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
231 struct drsuapi_DsReplicaSync
*r
)
233 /* TODO: implement this call correct!
234 * for now we just say yes,
235 * because we have no output parameter
240 int drsuapi_search_with_extended_dn(struct ldb_context
*ldb
,
242 struct ldb_result
**_res
,
243 struct ldb_dn
*basedn
,
244 enum ldb_scope scope
,
245 const char * const *attrs
,
246 const char *format
, ...)
250 struct ldb_request
*req
;
253 struct ldb_result
*res
;
255 tmp_ctx
= talloc_new(mem_ctx
);
257 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
259 return LDB_ERR_OPERATIONS_ERROR
;
262 va_start(ap
, format
);
263 filter
= talloc_vasprintf(tmp_ctx
, format
, ap
);
266 if (filter
== NULL
) {
267 talloc_free(tmp_ctx
);
268 return LDB_ERR_OPERATIONS_ERROR
;
271 ret
= ldb_build_search_req(&req
, ldb
, tmp_ctx
,
278 ldb_search_default_callback
,
280 if (ret
!= LDB_SUCCESS
) {
281 talloc_free(tmp_ctx
);
285 ret
= ldb_request_add_control(req
, LDB_CONTROL_EXTENDED_DN_OID
, true, NULL
);
286 if (ret
!= LDB_SUCCESS
) {
290 ret
= ldb_request(ldb
, req
);
291 if (ret
== LDB_SUCCESS
) {
292 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
302 drsuapi_DsGetNCChanges
304 static WERROR
dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
305 struct drsuapi_DsGetNCChanges
*r
)
307 struct ldb_result
*site_res
;
308 struct drsuapi_DsReplicaObjectIdentifier
*ncRoot
;
309 struct drsuapi_bind_state
*b_state
;
310 struct ldb_dn
*ncRoot_dn
;
315 struct dsdb_schema
*schema
;
316 struct drsuapi_DsReplicaOIDMapping_Ctr
*ctr
;
317 time_t t
= time(NULL
);
319 struct drsuapi_DsReplicaObjectListItemEx
*currentObject
;
320 struct dom_sid
*zero_sid
;
321 struct ldb_dn
*obj_dn
;
322 enum ndr_err_code ndr_err
;
323 const struct ldb_val
*md_value
;
324 struct replPropertyMetaDataBlob md
;
327 b_state
= talloc_zero(mem_ctx
, struct drsuapi_bind_state
);
328 W_ERROR_HAVE_NO_MEMORY(b_state
);
329 zero_sid
= talloc_zero(mem_ctx
, struct dom_sid
);
331 * connect to the samdb
333 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
);
334 if (!b_state
->sam_ctx
) {
338 /* Check request revision. */
339 if (r
->in
.level
!= 8) {
340 return WERR_REVISION_MISMATCH
;
343 /* Perform access checks. */
344 if (r
->in
.req
->req8
.naming_context
== NULL
) {
345 return WERR_DS_DRA_INVALID_PARAMETER
;
348 ncRoot
= r
->in
.req
->req8
.naming_context
;
349 if (ncRoot
== NULL
) {
350 return WERR_DS_DRA_BAD_NC
;
353 DEBUG(4,("DsGetNSChanges with uSHChanged >= %llu\n",
354 (unsigned long long)r
->in
.req
->req8
.highwatermark
.highest_usn
));
356 /* Construct response. */
357 ncRoot_dn
= ldb_dn_new(mem_ctx
, b_state
->sam_ctx
, ncRoot
->dn
);
358 ret
= drsuapi_search_with_extended_dn(b_state
->sam_ctx
, mem_ctx
, &site_res
,
359 ncRoot_dn
, LDB_SCOPE_SUBTREE
, NULL
,
360 "(&(uSNChanged>=%lld)(objectClass=*))", r
->in
.req
->req8
.highwatermark
.highest_usn
);
361 if (ret
!= LDB_SUCCESS
) {
362 return WERR_DS_DRA_INTERNAL_ERROR
;
365 *r
->out
.level_out
= 6;
366 r
->out
.ctr
->ctr6
.naming_context
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectIdentifier
);
367 *r
->out
.ctr
->ctr6
.naming_context
= *ncRoot
;
368 /* TODO: linked attributes*/
369 r
->out
.ctr
->ctr6
.linked_attributes_count
= 0;
370 r
->out
.ctr
->ctr6
.linked_attributes
= NULL
;
372 r
->out
.ctr
->ctr6
.object_count
= 0;
373 r
->out
.ctr
->ctr6
.more_data
= false;
374 r
->out
.ctr
->ctr6
.uptodateness_vector
= NULL
;
377 schema
= dsdb_get_schema(b_state
->sam_ctx
);
379 DEBUG(0,("No schema in b_state->sam_ctx"));
382 dsdb_get_oid_mappings_drsuapi(schema
, true, mem_ctx
, &ctr
);
383 r
->out
.ctr
->ctr6
.mapping_ctr
= *ctr
;
385 r
->out
.ctr
->ctr6
.source_dsa_guid
= *(samdb_ntds_objectGUID(b_state
->sam_ctx
));
386 r
->out
.ctr
->ctr6
.source_dsa_invocation_id
= *(samdb_ntds_invocation_id(b_state
->sam_ctx
));
388 r
->out
.ctr
->ctr6
.old_highwatermark
= r
->in
.req
->req8
.highwatermark
;
389 r
->out
.ctr
->ctr6
.new_highwatermark
= r
->in
.req
->req8
.highwatermark
;
391 r
->out
.ctr
->ctr6
.first_object
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectListItemEx
);
392 currentObject
= r
->out
.ctr
->ctr6
.first_object
;
394 for(i
=0; i
<site_res
->count
; i
++) {
395 uSN
= ldb_msg_find_attr_as_int(site_res
->msgs
[i
],"uSNChanged", -1);
396 r
->out
.ctr
->ctr6
.object_count
++;
397 if (uSN
> r
->out
.ctr
->ctr6
.new_highwatermark
.highest_usn
) {
398 r
->out
.ctr
->ctr6
.new_highwatermark
.highest_usn
= uSN
;
401 if (ldb_dn_compare(ncRoot_dn
, site_res
->msgs
[i
]->dn
) == 0) {
402 currentObject
->is_nc_prefix
= true;
403 currentObject
->parent_object_guid
= NULL
;
405 currentObject
->is_nc_prefix
= false;
406 currentObject
->parent_object_guid
= talloc(mem_ctx
, struct GUID
);
407 *currentObject
->parent_object_guid
= samdb_result_guid(site_res
->msgs
[i
], "parentGUID");
409 currentObject
->next_object
= NULL
;
411 currentObject
->meta_data_ctr
= talloc(mem_ctx
, struct drsuapi_DsReplicaMetaDataCtr
);
412 md_value
= ldb_msg_find_ldb_val(site_res
->msgs
[i
], "replPropertyMetaData");
414 ndr_err
= ndr_pull_struct_blob(md_value
, mem_ctx
,
415 lp_iconv_convenience(ldb_get_opaque(b_state
->sam_ctx
, "loadparm")), &md
,
416 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
);
417 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
418 return WERR_DS_DRA_INTERNAL_ERROR
;
421 if (md
.version
!= 1) {
422 return WERR_DS_DRA_INTERNAL_ERROR
;
425 currentObject
->meta_data_ctr
->count
= md
.ctr
.ctr1
.count
;
426 currentObject
->meta_data_ctr
->meta_data
= talloc_array(mem_ctx
, struct drsuapi_DsReplicaMetaData
, md
.ctr
.ctr1
.count
);
427 for (j
=0; j
<md
.ctr
.ctr1
.count
; j
++) {
428 currentObject
->meta_data_ctr
->meta_data
[j
].originating_change_time
= md
.ctr
.ctr1
.array
[j
].originating_change_time
;
429 currentObject
->meta_data_ctr
->meta_data
[j
].version
= md
.ctr
.ctr1
.array
[j
].version
;
430 currentObject
->meta_data_ctr
->meta_data
[j
].originating_invocation_id
= md
.ctr
.ctr1
.array
[j
].originating_invocation_id
;
431 currentObject
->meta_data_ctr
->meta_data
[j
].originating_usn
= md
.ctr
.ctr1
.array
[j
].originating_usn
;
434 currentObject
->meta_data_ctr
->meta_data
= talloc(mem_ctx
, struct drsuapi_DsReplicaMetaData
);
435 currentObject
->meta_data_ctr
->count
= 0;
437 currentObject
->object
.identifier
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectIdentifier
);
438 obj_dn
= ldb_msg_find_attr_as_dn(b_state
->sam_ctx
, mem_ctx
, site_res
->msgs
[i
], "distinguishedName");
439 currentObject
->object
.identifier
->dn
= ldb_dn_get_linearized(obj_dn
);
440 currentObject
->object
.identifier
->guid
= GUID_zero();
441 currentObject
->object
.identifier
->sid
= *zero_sid
;
443 currentObject
->object
.attribute_ctr
.num_attributes
= site_res
->msgs
[i
]->num_elements
;
444 /* Exclude non-replicate attributes from the responce.*/
445 for (j
=0; j
<site_res
->msgs
[i
]->num_elements
; j
++) {
446 const struct dsdb_attribute
*sa
;
447 sa
= dsdb_attribute_by_lDAPDisplayName(schema
, site_res
->msgs
[i
]->elements
[j
].name
);
448 if (sa
&& sa
->systemFlags
& 0x00000001) {
449 ldb_msg_remove_attr(site_res
->msgs
[i
], site_res
->msgs
[i
]->elements
[j
].name
);
450 currentObject
->object
.attribute_ctr
.num_attributes
--;
453 currentObject
->object
.attribute_ctr
.attributes
= talloc_array(mem_ctx
, struct drsuapi_DsReplicaAttribute
,
454 currentObject
->object
.attribute_ctr
.num_attributes
);
455 for (j
=0; j
<currentObject
->object
.attribute_ctr
.num_attributes
; j
++) {
456 dsdb_attribute_ldb_to_drsuapi(b_state
->sam_ctx
, schema
,&site_res
->msgs
[i
]->elements
[j
], mem_ctx
,
457 ¤tObject
->object
.attribute_ctr
.attributes
[j
]);
460 if (i
== (site_res
->count
-1)) {
463 currentObject
->next_object
= talloc(mem_ctx
, struct drsuapi_DsReplicaObjectListItemEx
);
464 currentObject
= currentObject
->next_object
;
467 r
->out
.ctr
->ctr6
.uptodateness_vector
= talloc(mem_ctx
, struct drsuapi_DsReplicaCursor2CtrEx
);
469 r
->out
.ctr
->ctr6
.uptodateness_vector
->version
= 2;
470 r
->out
.ctr
->ctr6
.uptodateness_vector
->count
= 1;
471 r
->out
.ctr
->ctr6
.uptodateness_vector
->reserved1
= 0;
472 r
->out
.ctr
->ctr6
.uptodateness_vector
->reserved2
= 0;
473 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
= talloc(mem_ctx
, struct drsuapi_DsReplicaCursor2
);
475 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
[0].source_dsa_invocation_id
= *(samdb_ntds_invocation_id(b_state
->sam_ctx
));
476 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
[0].highest_usn
= r
->out
.ctr
->ctr6
.new_highwatermark
.highest_usn
;
477 unix_to_nt_time(&now
, t
);
478 r
->out
.ctr
->ctr6
.uptodateness_vector
->cursors
[0].last_sync_success
= now
;
487 static WERROR
dcesrv_DRSUAPI_REPLICA_ADD(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
488 struct DRSUAPI_REPLICA_ADD
*r
)
490 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
497 static WERROR
dcesrv_DRSUAPI_REPLICA_DEL(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
498 struct DRSUAPI_REPLICA_DEL
*r
)
500 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
505 DRSUAPI_REPLICA_MODIFY
507 static WERROR
dcesrv_DRSUAPI_REPLICA_MODIFY(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
508 struct DRSUAPI_REPLICA_MODIFY
*r
)
510 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
517 static WERROR
dcesrv_DRSUAPI_VERIFY_NAMES(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
518 struct DRSUAPI_VERIFY_NAMES
*r
)
520 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
525 drsuapi_DsGetMemberships
527 static WERROR
dcesrv_drsuapi_DsGetMemberships(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
528 struct drsuapi_DsGetMemberships
*r
)
530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
535 DRSUAPI_INTER_DOMAIN_MOVE
537 static WERROR
dcesrv_DRSUAPI_INTER_DOMAIN_MOVE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
538 struct DRSUAPI_INTER_DOMAIN_MOVE
*r
)
540 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
545 drsuapi_DsGetNT4ChangeLog
547 static WERROR
dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
548 struct drsuapi_DsGetNT4ChangeLog
*r
)
550 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
557 static WERROR
dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
558 struct drsuapi_DsCrackNames
*r
)
561 struct drsuapi_bind_state
*b_state
;
562 struct dcesrv_handle
*h
;
564 *r
->out
.level_out
= r
->in
.level
;
566 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
569 r
->out
.ctr
= talloc_zero(mem_ctx
, union drsuapi_DsNameCtr
);
570 W_ERROR_HAVE_NO_MEMORY(r
->out
.ctr
);
572 switch (r
->in
.level
) {
574 struct drsuapi_DsNameCtr1
*ctr1
;
575 struct drsuapi_DsNameInfo1
*names
;
579 ctr1
= talloc(mem_ctx
, struct drsuapi_DsNameCtr1
);
580 W_ERROR_HAVE_NO_MEMORY(ctr1
);
582 count
= r
->in
.req
->req1
.count
;
583 names
= talloc_array(mem_ctx
, struct drsuapi_DsNameInfo1
, count
);
584 W_ERROR_HAVE_NO_MEMORY(names
);
586 for (i
=0; i
< count
; i
++) {
587 status
= DsCrackNameOneName(b_state
->sam_ctx
, mem_ctx
,
588 r
->in
.req
->req1
.format_flags
,
589 r
->in
.req
->req1
.format_offered
,
590 r
->in
.req
->req1
.format_desired
,
591 r
->in
.req
->req1
.names
[i
].str
,
593 if (!W_ERROR_IS_OK(status
)) {
600 r
->out
.ctr
->ctr1
= ctr1
;
606 return WERR_UNKNOWN_LEVEL
;
610 drsuapi_DsWriteAccountSpn
612 static WERROR
dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
613 struct drsuapi_DsWriteAccountSpn
*r
)
615 struct drsuapi_bind_state
*b_state
;
616 struct dcesrv_handle
*h
;
618 *r
->out
.level_out
= r
->in
.level
;
620 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
623 r
->out
.res
= talloc(mem_ctx
, union drsuapi_DsWriteAccountSpnResult
);
624 W_ERROR_HAVE_NO_MEMORY(r
->out
.res
);
626 switch (r
->in
.level
) {
628 struct drsuapi_DsWriteAccountSpnRequest1
*req
;
629 struct ldb_message
*msg
;
631 req
= &r
->in
.req
->req1
;
634 msg
= ldb_msg_new(mem_ctx
);
639 msg
->dn
= ldb_dn_new(msg
, b_state
->sam_ctx
, req
->object_dn
);
640 if ( ! ldb_dn_validate(msg
->dn
)) {
641 r
->out
.res
->res1
.status
= WERR_OK
;
646 for (i
= 0; i
< count
; i
++) {
647 samdb_msg_add_string(b_state
->sam_ctx
,
648 msg
, msg
, "servicePrincipalName",
649 req
->spn_names
[i
].str
);
651 for (i
=0;i
<msg
->num_elements
;i
++) {
652 switch (req
->operation
) {
653 case DRSUAPI_DS_SPN_OPERATION_ADD
:
654 msg
->elements
[i
].flags
= LDB_FLAG_MOD_ADD
;
656 case DRSUAPI_DS_SPN_OPERATION_REPLACE
:
657 msg
->elements
[i
].flags
= LDB_FLAG_MOD_REPLACE
;
659 case DRSUAPI_DS_SPN_OPERATION_DELETE
:
660 msg
->elements
[i
].flags
= LDB_FLAG_MOD_DELETE
;
665 /* Apply to database */
667 ret
= ldb_modify(b_state
->sam_ctx
, msg
);
669 DEBUG(0,("Failed to modify SPNs on %s: %s\n",
670 ldb_dn_get_linearized(msg
->dn
),
671 ldb_errstring(b_state
->sam_ctx
)));
672 r
->out
.res
->res1
.status
= WERR_ACCESS_DENIED
;
674 r
->out
.res
->res1
.status
= WERR_OK
;
681 return WERR_UNKNOWN_LEVEL
;
686 drsuapi_DsRemoveDSServer
688 static WERROR
dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
689 struct drsuapi_DsRemoveDSServer
*r
)
691 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
696 DRSUAPI_REMOVE_DS_DOMAIN
698 static WERROR
dcesrv_DRSUAPI_REMOVE_DS_DOMAIN(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
699 struct DRSUAPI_REMOVE_DS_DOMAIN
*r
)
701 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
704 /* Obtain the site name from a server DN */
705 static const char *result_site_name(struct ldb_dn
*site_dn
)
707 /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
708 const struct ldb_val
*val
= ldb_dn_get_component_val(site_dn
, 2);
709 const char *name
= ldb_dn_get_component_name(site_dn
, 2);
711 if (!name
|| (ldb_attr_cmp(name
, "cn") != 0)) {
712 /* Ensure this matches the format. This gives us a
713 * bit more confidence that a 'cn' value will be a
718 return (char *)val
->data
;
724 drsuapi_DsGetDomainControllerInfo
726 static WERROR
dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state
*b_state
,
728 struct drsuapi_DsGetDomainControllerInfo
*r
)
730 struct ldb_dn
*sites_dn
;
731 struct ldb_result
*res
;
733 const char *attrs_account_1
[] = { "cn", "dnsHostName", NULL
};
734 const char *attrs_account_2
[] = { "cn", "dnsHostName", "objectGUID", NULL
};
736 const char *attrs_none
[] = { NULL
};
738 const char *attrs_site
[] = { "objectGUID", NULL
};
740 const char *attrs_ntds
[] = { "options", "objectGUID", NULL
};
742 const char *attrs_1
[] = { "serverReference", "cn", "dnsHostName", NULL
};
743 const char *attrs_2
[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL
};
746 struct drsuapi_DsGetDCInfoCtr1
*ctr1
;
747 struct drsuapi_DsGetDCInfoCtr2
*ctr2
;
751 *r
->out
.level_out
= r
->in
.req
->req1
.level
;
752 r
->out
.ctr
= talloc(mem_ctx
, union drsuapi_DsGetDCInfoCtr
);
753 W_ERROR_HAVE_NO_MEMORY(r
->out
.ctr
);
755 sites_dn
= samdb_sites_dn(b_state
->sam_ctx
, mem_ctx
);
757 return WERR_DS_OBJ_NOT_FOUND
;
760 switch (*r
->out
.level_out
) {
762 /* this level is not like the others */
763 return WERR_UNKNOWN_LEVEL
;
771 return WERR_UNKNOWN_LEVEL
;
774 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res
, sites_dn
, LDB_SCOPE_SUBTREE
, attrs
,
775 "objectClass=server");
778 DEBUG(1, ("searching for servers in sites DN %s failed: %s\n",
779 ldb_dn_get_linearized(sites_dn
), ldb_errstring(b_state
->sam_ctx
)));
780 return WERR_GENERAL_FAILURE
;
783 switch (*r
->out
.level_out
) {
785 ctr1
= &r
->out
.ctr
->ctr1
;
786 ctr1
->count
= res
->count
;
787 ctr1
->array
= talloc_zero_array(mem_ctx
,
788 struct drsuapi_DsGetDCInfo1
,
790 for (i
=0; i
< res
->count
; i
++) {
791 struct ldb_dn
*domain_dn
;
792 struct ldb_result
*res_domain
;
793 struct ldb_result
*res_account
;
794 struct ldb_dn
*ntds_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
796 struct ldb_dn
*ref_dn
797 = ldb_msg_find_attr_as_dn(b_state
->sam_ctx
,
798 mem_ctx
, res
->msgs
[i
],
801 if (!ntds_dn
|| !ldb_dn_add_child_fmt(ntds_dn
, "CN=NTDS Settings")) {
805 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_account
, ref_dn
,
806 LDB_SCOPE_BASE
, attrs_account_1
, "objectClass=computer");
807 if (ret
== LDB_SUCCESS
&& res_account
->count
== 1) {
809 ctr1
->array
[i
].dns_name
810 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "dNSHostName", NULL
);
811 ctr1
->array
[i
].netbios_name
812 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "cn", NULL
);
813 ctr1
->array
[i
].computer_dn
814 = ldb_dn_get_linearized(res_account
->msgs
[0]->dn
);
816 /* Determine if this is the PDC */
817 ret
= samdb_search_for_parent_domain(b_state
->sam_ctx
,
818 mem_ctx
, res_account
->msgs
[0]->dn
,
819 &domain_dn
, &errstr
);
821 if (ret
== LDB_SUCCESS
) {
822 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_domain
, domain_dn
,
823 LDB_SCOPE_BASE
, attrs_none
, "fSMORoleOwner=%s",
824 ldb_dn_get_linearized(ntds_dn
));
826 return WERR_GENERAL_FAILURE
;
828 if (res_domain
->count
== 1) {
829 ctr1
->array
[i
].is_pdc
= true;
833 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
834 DEBUG(5, ("warning: searching for computer DN %s failed: %s\n",
835 ldb_dn_get_linearized(ref_dn
), ldb_errstring(b_state
->sam_ctx
)));
838 /* Look at server DN and extract site component */
839 ctr1
->array
[i
].site_name
= result_site_name(res
->msgs
[i
]->dn
);
840 ctr1
->array
[i
].server_dn
= ldb_dn_get_linearized(res
->msgs
[i
]->dn
);
843 ctr1
->array
[i
].is_enabled
= true;
848 ctr2
= &r
->out
.ctr
->ctr2
;
849 ctr2
->count
= res
->count
;
850 ctr2
->array
= talloc_zero_array(mem_ctx
,
851 struct drsuapi_DsGetDCInfo2
,
853 for (i
=0; i
< res
->count
; i
++) {
854 struct ldb_dn
*domain_dn
;
855 struct ldb_result
*res_domain
;
856 struct ldb_result
*res_account
;
857 struct ldb_dn
*ntds_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
858 struct ldb_result
*res_ntds
;
859 struct ldb_dn
*site_dn
= ldb_dn_copy(mem_ctx
, res
->msgs
[i
]->dn
);
860 struct ldb_result
*res_site
;
861 struct ldb_dn
*ref_dn
862 = ldb_msg_find_attr_as_dn(b_state
->sam_ctx
,
863 mem_ctx
, res
->msgs
[i
],
866 if (!ntds_dn
|| !ldb_dn_add_child_fmt(ntds_dn
, "CN=NTDS Settings")) {
870 /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
871 if (!site_dn
|| !ldb_dn_remove_child_components(site_dn
, 2)) {
875 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_ntds
, ntds_dn
,
876 LDB_SCOPE_BASE
, attrs_ntds
, "objectClass=nTDSDSA");
877 if (ret
== LDB_SUCCESS
&& res_ntds
->count
== 1) {
879 = (ldb_msg_find_attr_as_int(res_ntds
->msgs
[0], "options", 0) == 1);
880 ctr2
->array
[i
].ntds_guid
881 = samdb_result_guid(res_ntds
->msgs
[0], "objectGUID");
882 ctr2
->array
[i
].ntds_dn
= ldb_dn_get_linearized(res_ntds
->msgs
[0]->dn
);
884 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
885 DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n",
886 ldb_dn_get_linearized(ntds_dn
), ldb_errstring(b_state
->sam_ctx
)));
889 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_site
, site_dn
,
890 LDB_SCOPE_BASE
, attrs_site
, "objectClass=site");
891 if (ret
== LDB_SUCCESS
&& res_site
->count
== 1) {
892 ctr2
->array
[i
].site_guid
893 = samdb_result_guid(res_site
->msgs
[0], "objectGUID");
894 ctr2
->array
[i
].site_dn
= ldb_dn_get_linearized(res_site
->msgs
[0]->dn
);
896 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
897 DEBUG(5, ("warning: searching for site DN %s failed: %s\n",
898 ldb_dn_get_linearized(site_dn
), ldb_errstring(b_state
->sam_ctx
)));
901 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_account
, ref_dn
,
902 LDB_SCOPE_BASE
, attrs_account_2
, "objectClass=computer");
903 if (ret
== LDB_SUCCESS
&& res_account
->count
== 1) {
905 ctr2
->array
[i
].dns_name
906 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "dNSHostName", NULL
);
907 ctr2
->array
[i
].netbios_name
908 = ldb_msg_find_attr_as_string(res_account
->msgs
[0], "cn", NULL
);
909 ctr2
->array
[i
].computer_dn
= ldb_dn_get_linearized(res_account
->msgs
[0]->dn
);
910 ctr2
->array
[i
].computer_guid
911 = samdb_result_guid(res_account
->msgs
[0], "objectGUID");
913 /* Determine if this is the PDC */
914 ret
= samdb_search_for_parent_domain(b_state
->sam_ctx
,
915 mem_ctx
, res_account
->msgs
[0]->dn
,
916 &domain_dn
, &errstr
);
918 if (ret
== LDB_SUCCESS
) {
919 ret
= ldb_search(b_state
->sam_ctx
, mem_ctx
, &res_domain
, domain_dn
,
920 LDB_SCOPE_BASE
, attrs_none
, "fSMORoleOwner=%s",
921 ldb_dn_get_linearized(ntds_dn
));
922 if (ret
== LDB_SUCCESS
&& res_domain
->count
== 1) {
923 ctr2
->array
[i
].is_pdc
= true;
925 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
926 DEBUG(5, ("warning: searching for domain DN %s failed: %s\n",
927 ldb_dn_get_linearized(domain_dn
), ldb_errstring(b_state
->sam_ctx
)));
931 if ((ret
!= LDB_SUCCESS
) && (ret
!= LDB_ERR_NO_SUCH_OBJECT
)) {
932 DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n",
933 ldb_dn_get_linearized(ref_dn
), ldb_errstring(b_state
->sam_ctx
)));
936 /* Look at server DN and extract site component */
937 ctr2
->array
[i
].site_name
= result_site_name(res
->msgs
[i
]->dn
);
938 ctr2
->array
[i
].server_dn
= ldb_dn_get_linearized(res
->msgs
[i
]->dn
);
939 ctr2
->array
[i
].server_guid
940 = samdb_result_guid(res
->msgs
[i
], "objectGUID");
942 ctr2
->array
[i
].is_enabled
= true;
951 drsuapi_DsGetDomainControllerInfo
953 static WERROR
dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
954 struct drsuapi_DsGetDomainControllerInfo
*r
)
956 struct dcesrv_handle
*h
;
957 struct drsuapi_bind_state
*b_state
;
958 DCESRV_PULL_HANDLE_WERR(h
, r
->in
.bind_handle
, DRSUAPI_BIND_HANDLE
);
961 switch (r
->in
.level
) {
963 return dcesrv_drsuapi_DsGetDomainControllerInfo_1(b_state
, mem_ctx
, r
);
966 return WERR_UNKNOWN_LEVEL
;
973 static WERROR
dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
974 struct drsuapi_DsAddEntry
*r
)
976 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
983 static WERROR
dcesrv_DRSUAPI_EXECUTE_KCC(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
984 struct DRSUAPI_EXECUTE_KCC
*r
)
986 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
991 drsuapi_DsReplicaGetInfo
993 static WERROR
dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
994 struct drsuapi_DsReplicaGetInfo
*r
)
996 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1001 DRSUAPI_ADD_SID_HISTORY
1003 static WERROR
dcesrv_DRSUAPI_ADD_SID_HISTORY(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1004 struct DRSUAPI_ADD_SID_HISTORY
*r
)
1006 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1010 drsuapi_DsGetMemberships2
1012 static WERROR
dcesrv_drsuapi_DsGetMemberships2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1013 struct drsuapi_DsGetMemberships2
*r
)
1015 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1019 DRSUAPI_REPLICA_VERIFY_OBJECTS
1021 static WERROR
dcesrv_DRSUAPI_REPLICA_VERIFY_OBJECTS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1022 struct DRSUAPI_REPLICA_VERIFY_OBJECTS
*r
)
1024 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1029 DRSUAPI_GET_OBJECT_EXISTENCE
1031 static WERROR
dcesrv_DRSUAPI_GET_OBJECT_EXISTENCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1032 struct DRSUAPI_GET_OBJECT_EXISTENCE
*r
)
1034 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1039 drsuapi_QuerySitesByCost
1041 static WERROR
dcesrv_drsuapi_QuerySitesByCost(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1042 struct drsuapi_QuerySitesByCost
*r
)
1044 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1048 /* include the generated boilerplate */
1049 #include "librpc/gen_ndr/ndr_drsuapi_s.c"